test_mysql_database.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. # -*- coding: utf-8 -*-
  2. """
  3. Tests for the MySQL states
  4. """
  5. from __future__ import absolute_import, print_function, unicode_literals
  6. import pytest
  7. import salt.utils.path
  8. from salt.ext import six
  9. from tests.support.case import ModuleCase
  10. from tests.support.mixins import SaltReturnAssertsMixin
  11. from tests.support.unit import skipIf
  12. NO_MYSQL = False
  13. try:
  14. import MySQLdb # pylint: disable=import-error,unused-import
  15. except ImportError:
  16. NO_MYSQL = True
  17. if not salt.utils.path.which("mysqladmin"):
  18. NO_MYSQL = True
  19. @skipIf(
  20. NO_MYSQL,
  21. "Please install MySQL bindings and a MySQL Server before running"
  22. "MySQL integration tests.",
  23. )
  24. class MysqlDatabaseStateTest(ModuleCase, SaltReturnAssertsMixin):
  25. """
  26. Validate the mysql_database state
  27. """
  28. user = "root"
  29. password = "poney"
  30. @pytest.mark.destructive_test
  31. def setUp(self):
  32. """
  33. Test presence of MySQL server, enforce a root password
  34. """
  35. super(MysqlDatabaseStateTest, self).setUp()
  36. NO_MYSQL_SERVER = True
  37. # now ensure we know the mysql root password
  38. # one of theses two at least should work
  39. ret1 = self.run_state(
  40. "cmd.run",
  41. name='mysqladmin --host="localhost" -u '
  42. + self.user
  43. + ' flush-privileges password "'
  44. + self.password
  45. + '"',
  46. )
  47. ret2 = self.run_state(
  48. "cmd.run",
  49. name='mysqladmin --host="localhost" -u '
  50. + self.user
  51. + ' --password="'
  52. + self.password
  53. + '" flush-privileges password "'
  54. + self.password
  55. + '"',
  56. )
  57. key, value = ret2.popitem()
  58. if value["result"]:
  59. NO_MYSQL_SERVER = False
  60. else:
  61. self.skipTest("No MySQL Server running, or no root access on it.")
  62. def _test_database(self, db_name, second_db_name, test_conn, **kwargs):
  63. """
  64. Create db two times, test conn, remove it two times
  65. """
  66. # In case of...
  67. ret = self.run_state("mysql_database.absent", name=db_name, **kwargs)
  68. ret = self.run_state("mysql_database.present", name=db_name, **kwargs)
  69. self.assertSaltTrueReturn(ret)
  70. self.assertInSaltComment("The database " + db_name + " has been created", ret)
  71. # 2nd run
  72. ret = self.run_state("mysql_database.present", name=second_db_name, **kwargs)
  73. self.assertSaltTrueReturn(ret)
  74. self.assertInSaltComment("Database " + db_name + " is already present", ret)
  75. if test_conn:
  76. # test root connection
  77. ret = self.run_function(
  78. "mysql.query", database=db_name, query="SELECT 1", **kwargs
  79. )
  80. if not isinstance(ret, dict) or "results" not in ret:
  81. raise AssertionError(
  82. (
  83. "Unexpected result while testing connection" " on db '{0}': {1}"
  84. ).format(db_name, repr(ret))
  85. )
  86. self.assertEqual([["1"]], ret["results"])
  87. # Now removing databases
  88. kwargs.pop("character_set")
  89. kwargs.pop("collate")
  90. ret = self.run_state("mysql_database.absent", name=db_name, **kwargs)
  91. self.assertSaltTrueReturn(ret)
  92. self.assertInSaltComment("Database " + db_name + " has been removed", ret)
  93. # 2nd run
  94. ret = self.run_state("mysql_database.absent", name=second_db_name, **kwargs)
  95. self.assertSaltTrueReturn(ret)
  96. self.assertInSaltComment(
  97. "Database " + db_name + " is not present, so it cannot be removed", ret
  98. )
  99. self.assertSaltStateChangesEqual(ret, {})
  100. @pytest.mark.destructive_test
  101. def test_present_absent(self):
  102. """
  103. mysql_database.present
  104. """
  105. self._test_database(
  106. "testdb1",
  107. "testdb1",
  108. test_conn=True,
  109. character_set="utf8",
  110. collate="utf8_general_ci",
  111. connection_user=self.user,
  112. connection_pass=self.password,
  113. connection_charset="utf8",
  114. )
  115. # TODO: test with variations on collate and charset, check for db alter
  116. # once it will be done in mysql_database.present state
  117. @pytest.mark.destructive_test
  118. def test_present_absent_fuzzy(self):
  119. """
  120. mysql_database.present with utf-8 andf fuzzy db name
  121. """
  122. # this is : ":() ;,?@=`&'\
  123. dbname_fuzzy = "\":() ;,?@=`&/'\\"
  124. # \xe6\xa8\x99\ = \u6a19 = 標
  125. # this is : "();,?:@=`&/標'\
  126. dbname_utf8 = "\"();,?@=`&//\xe6\xa8\x99'\\"
  127. dbname_unicode = "\"();,?@=`&//\u6a19'\\"
  128. self._test_database(
  129. dbname_fuzzy,
  130. dbname_fuzzy,
  131. test_conn=True,
  132. character_set="utf8",
  133. collate="utf8_general_ci",
  134. connection_user=self.user,
  135. connection_pass=self.password,
  136. connection_charset="utf8",
  137. )
  138. # FIXME: MySQLdb bugs on dbnames with utf-8?
  139. self._test_database(
  140. dbname_utf8,
  141. dbname_unicode,
  142. test_conn=False,
  143. character_set="utf8",
  144. collate="utf8_general_ci",
  145. connection_user=self.user,
  146. connection_pass=self.password,
  147. connection_charset="utf8",
  148. # saltenv={"LC_ALL": "en_US.utf8"}
  149. )
  150. @pytest.mark.destructive_test
  151. @skipIf(True, "This tests needs issue #8947 to be fixed first")
  152. def test_utf8_from_sls_file(self):
  153. """
  154. Try to create/destroy an utf-8 database name from an sls file #8947
  155. """
  156. expected_result = {
  157. "mysql_database_|-A_|-foo \xe6\xba\x96`bar_|-present": {
  158. "__run_num__": 0,
  159. "comment": "The database foo \xe6\xba\x96`bar has been created",
  160. "result": True,
  161. },
  162. "mysql_database_|-B_|-foo \xe6\xba\x96`bar_|-absent": {
  163. "__run_num__": 1,
  164. "comment": "Database foo \xe6\xba\x96`bar has been removed",
  165. "result": True,
  166. },
  167. }
  168. result = {}
  169. ret = self.run_function("state.sls", mods="mysql_utf8")
  170. if not isinstance(ret, dict):
  171. raise AssertionError(
  172. (
  173. "Unexpected result while testing external mysql utf8 sls" ": {0}"
  174. ).format(repr(ret))
  175. )
  176. for item, descr in six.iteritems(ret):
  177. result[item] = {
  178. "__run_num__": descr["__run_num__"],
  179. "comment": descr["comment"],
  180. "result": descr["result"],
  181. }
  182. self.assertEqual(expected_result, result)