salt/tests/integration/modules/mysql.py

507 lines
16 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
# Import python libs
import os
import logging
from mock import patch, MagicMock
# Import Salt Testing libs
from salttesting import skipIf
from salttesting.helpers import (
destructiveTest,
ensure_in_syspath,
requires_system_grains
)
ensure_in_syspath('../../')
# Import salt libs
import integration
import salt.utils
from salt.modules import mysql as mysqlmod
log = logging.getLogger(__name__)
NO_MYSQL = False
try:
import MySQLdb
except Exception:
NO_MYSQL = True
2013-12-01 01:34:05 +00:00
@skipIf(NO_MYSQL, 'Install MySQL bindings and a MySQL Server before running MySQL integration tests.')
class MysqlModuleTest(integration.ModuleCase,
integration.SaltReturnAssertsMixIn):
2013-12-01 01:34:05 +00:00
user = 'root'
password = 'poney'
@destructiveTest
def setUp(self):
'''
Test presence of MySQL server, enforce a root password
2013-12-01 01:34:05 +00:00
'''
super(MysqlModuleTest, self).setUp()
NO_MYSQL_SERVER = True
# now ensure we know the mysql root password
# one of theses two at least should work
ret1 = self.run_state(
2013-12-01 01:34:05 +00:00
'cmd.run',
name='mysqladmin -u '
+ self.user
+ ' flush-privileges password "'
+ self.password
+ '"'
)
ret2 = self.run_state(
2013-12-01 01:34:05 +00:00
'cmd.run',
name='mysqladmin -u '
+ self.user
+ ' --password="'
+ self.password
+ '" flush-privileges password "'
+ self.password
+ '"'
)
key, value = ret2.popitem()
if value['result']:
NO_MYSQL_SERVER = False
else:
self.skipTest('No MySQL Server running, or no root access on it.')
@destructiveTest
def test_database_creation_level1(self):
'''
Create database, test it exists and remove it
'''
# create
ret = self.run_function(
'mysql.db_create',
name='foo 1',
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(True, ret)
# test db exists
ret = self.run_function(
'mysql.db_exists',
name='foo 1',
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(True, ret)
# redoing the same should fail
ret = self.run_function(
'mysql.db_create',
name='foo 1',
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(False, ret)
# Now remove database
ret = self.run_function(
'mysql.db_remove',
name='foo 1',
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(True, ret)
@destructiveTest
def test_database_creation_level2(self):
'''
Same as level1 with strange names and with character set and collate keywords
'''
# ```````
# create
# also with character_set and collate only
ret = self.run_function(
'mysql.db_create',
name='foo`2',
character_set='utf8',
collate='utf8_general_ci',
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(True, ret)
# test db exists
ret = self.run_function(
'mysql.db_exists',
name='foo`2',
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(True, ret)
# redoing the same should fail
# even with other character sets or collations
ret = self.run_function(
'mysql.db_create',
name='foo`2',
character_set='utf8',
collate='utf8_general_ci',
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(False, ret)
# redoing the same should fail
ret = self.run_function(
'mysql.db_create',
name='foo`2',
character_set='utf8',
collate='utf8_general_ci',
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(False, ret)
# Now remove database
ret = self.run_function(
'mysql.db_remove',
name='foo`2',
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(True, ret)
# '''''''
# create
# also with character_set only
ret = self.run_function(
'mysql.db_create',
name="foo'3",
character_set='utf8',
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(True, ret)
# test db exists
ret = self.run_function(
'mysql.db_exists',
name="foo'3",
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(True, ret)
# Now remove database
ret = self.run_function(
'mysql.db_remove',
name="foo'3",
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(True, ret)
# """"""""
# also with collate only
ret = self.run_function(
'mysql.db_create',
name='foo"4',
collate='utf8_general_ci',
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(True, ret)
# test db exists
ret = self.run_function(
'mysql.db_exists',
name='foo"4',
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(True, ret)
# Now remove database
ret = self.run_function(
'mysql.db_remove',
name='foo"4',
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(True, ret)
# TODO: Simple accents :
#db_name=u'notamérican'
#ret = self.run_function(
# 'mysql.db_create',
# name=db_name,
# connection_user=self.user,
# connection_pass=self.password
#)
2013-12-02 10:33:13 +00:00
#self.assertEqual(True, ret)
# test db exists
#ret = self.run_function(
# 'mysql.db_exists',
# name=db_name,
# connection_user=self.user,
# connection_pass=self.password
#)
2013-12-02 10:33:13 +00:00
#self.assertEqual(True, ret)
# Now remove database
#ret = self.run_function(
# 'mysql.db_remove',
# name=db_name,
# connection_user=self.user,
# connection_pass=self.password
#)
2013-12-02 10:33:13 +00:00
#self.assertEqual(True, ret)
# TODO: Unicode, currently Failing on :
# UnicodeDecodeError: \'ascii\' codec can\'t decode byte 0xe6 in position 1: ordinal not in range(128)
# something like: '標準語'
#unicode_str=u'\u6a19\u6e96\u8a9e'
#db_name=unicode_str.encode('utf8')
#ret = self.run_function(
# 'mysql.db_create',
# name=db_name,
# connection_user=self.user,
# connection_pass=self.password
#)
2013-12-02 10:33:13 +00:00
#self.assertEqual(True, ret)
# test db exists
#ret = self.run_function(
# 'mysql.db_exists',
# name=db_name,
# connection_user=self.user,
# connection_pass=self.password
#)
2013-12-02 10:33:13 +00:00
#self.assertEqual(True, ret)
# Now remove database
#ret = self.run_function(
# 'mysql.db_remove',
# name=db_name,
# connection_user=self.user,
# connection_pass=self.password
#)
2013-12-02 10:33:13 +00:00
#self.assertEqual(True, ret)
@destructiveTest
def test_database_maintenance(self):
'''
Test maintenance operations on a created database
'''
dbname = u"foo'-- `\"'"
# create database
# but first silently try to remove it
# in case of previous tests failures
ret = self.run_function(
'mysql.db_remove',
name=dbname,
connection_user=self.user,
connection_pass=self.password
)
ret = self.run_function(
'mysql.db_create',
name=dbname,
character_set='utf8',
collate='utf8_general_ci',
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(True, ret)
# test db exists
ret = self.run_function(
'mysql.db_exists',
name=dbname,
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(True, ret)
# Create 3 tables
tablenames = {'Atable "`1': 'MYISAM', 'Btable \'`2': 'InnoDB', 'Ctable --`3': 'MEMORY'}
2013-12-02 10:33:13 +00:00
for tablename, engine in iter(sorted(tablenames.iteritems())):
# prepare queries
create_query = ('CREATE TABLE %(tblname)s ('
' id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,'
' data VARCHAR(100)) ENGINE=%(engine)s;') % dict(
tblname=mysqlmod.quoteIdentifier(tablename),
engine=engine,
)
insert_query = ('INSERT INTO %(tblname)s (data)'
' VALUES ') % dict(tblname=mysqlmod.quoteIdentifier(tablename))
delete_query = ('DELETE from %(tblname)s'
' order by rand() limit 50;') % dict(tblname=mysqlmod.quoteIdentifier(tablename))
for x in range(100):
insert_query += "('foo"+str(x)+"'),"
insert_query += "('bar');"
# populate database
log.info('Adding table{0!r}'.format(tablename,))
ret = self.run_function(
'mysql.query',
database=dbname,
query=create_query,
connection_user=self.user,
connection_pass=self.password
)
if not isinstance(ret, dict) or 'rows affected' not in ret:
raise AssertionError(
'Unexpected query result while populating test table {0!r} : {1!r}'.format(
tablename,
ret,
)
)
2013-12-02 10:33:13 +00:00
self.assertEqual(ret['rows affected'], 0)
log.info('Populating table{0!r}'.format(tablename,))
ret = self.run_function(
'mysql.query',
database=dbname,
query=insert_query,
connection_user=self.user,
connection_pass=self.password
)
if not isinstance(ret, dict) or 'rows affected' not in ret:
raise AssertionError(
'Unexpected query result while populating test table {0!r} : {1!r}'.format(
tablename,
ret,
)
)
2013-12-02 10:33:13 +00:00
self.assertEqual(ret['rows affected'], 101)
log.info('Removing some rows on table{0!r}'.format(tablename,))
ret = self.run_function(
'mysql.query',
database=dbname,
query=delete_query,
connection_user=self.user,
connection_pass=self.password
)
if not isinstance(ret, dict) or 'rows affected' not in ret:
raise AssertionError(
('Unexpected query result while removing rows on test table'
' {0!r} : {1!r}').format(
tablename,
ret,
)
)
2013-12-02 10:33:13 +00:00
self.assertEqual(ret['rows affected'], 50)
# test check/repair/opimize on 1 table
2013-12-02 10:33:13 +00:00
tablename = 'Atable "`1'
ret = self.run_function(
'mysql.db_check',
name=dbname,
table=tablename,
connection_user=self.user,
connection_pass=self.password
)
# Note that returned result does not quoteIdentifier of table and db
2013-12-02 10:33:13 +00:00
self.assertEqual(ret, [{'Table': dbname+'.'+tablename, 'Msg_text': 'OK', 'Msg_type': 'status', 'Op': 'check'}])
ret = self.run_function(
'mysql.db_repair',
name=dbname,
table=tablename,
connection_user=self.user,
connection_pass=self.password
)
# Note that returned result does not quoteIdentifier of table and db
2013-12-02 10:33:13 +00:00
self.assertEqual(ret, [{'Table': dbname+'.'+tablename, 'Msg_text': 'OK', 'Msg_type': 'status', 'Op': 'repair'}])
ret = self.run_function(
'mysql.db_optimize',
name=dbname,
table=tablename,
connection_user=self.user,
connection_pass=self.password
)
# Note that returned result does not quoteIdentifier of table and db
2013-12-02 10:33:13 +00:00
self.assertEqual(ret, [{'Table': dbname+'.'+tablename, 'Msg_text': 'OK', 'Msg_type': 'status', 'Op': 'optimize'}])
# test check/repair/opimize on all tables
ret = self.run_function(
'mysql.db_check',
name=dbname,
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
expected = []
for tablename, engine in iter(sorted(tablenames.iteritems())):
if engine is 'MEMORY':
expected.append([{
'Table': dbname+'.'+tablename,
'Msg_text': "The storage engine for the table doesn't support check",
'Msg_type': 'note',
'Op': 'check'
}])
else:
expected.append([{
'Table': dbname+'.'+tablename,
'Msg_text': 'OK',
'Msg_type': 'status',
'Op': 'check'
}])
2013-12-02 10:33:13 +00:00
self.assertEqual(ret, expected)
ret = self.run_function(
'mysql.db_repair',
name=dbname,
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
expected = []
for tablename, engine in iter(sorted(tablenames.iteritems())):
if engine is 'MYISAM':
expected.append([{
'Table': dbname+'.'+tablename,
'Msg_text': 'OK',
'Msg_type': 'status',
'Op': 'repair'
}])
else:
expected.append([{
'Table': dbname+'.'+tablename,
'Msg_text': "The storage engine for the table doesn't support repair",
'Msg_type': 'note',
'Op': 'repair'
}])
2013-12-02 10:33:13 +00:00
self.assertEqual(ret, expected)
ret = self.run_function(
'mysql.db_optimize',
name=dbname,
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
expected = []
for tablename, engine in iter(sorted(tablenames.iteritems())):
if engine is 'MYISAM':
expected.append([{
'Table': dbname+'.'+tablename,
'Msg_text': 'OK',
'Msg_type': 'status',
'Op': 'optimize'
}])
elif engine is 'InnoDB':
expected.append([{
'Table': dbname+'.'+tablename,
'Msg_text': ("Table does not support optimize, "
"doing recreate + analyze instead"),
'Msg_type': 'note',
'Op': 'optimize'
},
{
'Table': dbname+'.'+tablename,
'Msg_text': 'OK',
'Msg_type': 'status',
'Op': 'optimize'
}])
elif engine is 'MEMORY':
expected.append([{
'Table': dbname+'.'+tablename,
'Msg_text': "The storage engine for the table doesn't support optimize",
'Msg_type': 'note',
'Op': 'optimize'
}])
2013-12-02 10:33:13 +00:00
self.assertEqual(ret, expected)
# Teardown, remove database
ret = self.run_function(
'mysql.db_remove',
name=dbname,
connection_user=self.user,
connection_pass=self.password
)
2013-12-02 10:33:13 +00:00
self.assertEqual(True, ret)
if __name__ == '__main__':
from integration import run_tests
run_tests(MysqlModuleTest)