module_spec_test.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. # Copyright (C) 2009 Internet Systems Consortium.
  2. #
  3. # Permission to use, copy, modify, and distribute this software for any
  4. # purpose with or without fee is hereby granted, provided that the above
  5. # copyright notice and this permission notice appear in all copies.
  6. #
  7. # THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
  8. # DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
  9. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
  10. # INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
  11. # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
  12. # FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  13. # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  14. # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. #
  16. # Tests for the module_spec module
  17. #
  18. import unittest
  19. import os
  20. from isc.config import ModuleSpec, ModuleSpecError
  21. import isc.cc.data
  22. class TestModuleSpec(unittest.TestCase):
  23. def setUp(self):
  24. if 'CONFIG_TESTDATA_PATH' in os.environ:
  25. self.data_path = os.environ['CONFIG_TESTDATA_PATH']
  26. else:
  27. self.data_path = "../../../testdata"
  28. def spec_file(self, filename):
  29. return(self.data_path + os.sep + filename)
  30. def read_spec_file(self, filename):
  31. return isc.config.module_spec_from_file(self.spec_file(filename))
  32. def spec1(self, dd):
  33. module_spec = dd.get_full_spec()
  34. self.assert_('module_name' in module_spec)
  35. self.assertEqual(module_spec['module_name'], "Spec1")
  36. def test_open_file_name(self):
  37. dd = self.read_spec_file("spec1.spec")
  38. self.spec1(dd)
  39. def test_open_file_obj(self):
  40. file1 = open(self.spec_file("spec1.spec"))
  41. dd = isc.config.module_spec_from_file(file1)
  42. self.spec1(dd)
  43. def test_open_bad_file_obj(self):
  44. self.assertRaises(ModuleSpecError, isc.config.module_spec_from_file, 1)
  45. # contains single quotes which json parser does not accept
  46. self.assertRaises(ModuleSpecError, isc.config.module_spec_from_file, self.spec_file("spec28.spec"), False)
  47. my_spec_file = open(self.spec_file("spec28.spec"))
  48. self.assertRaises(ModuleSpecError, isc.config.module_spec_from_file, my_spec_file, False)
  49. self.assertRaises(ModuleSpecError, isc.config.module_spec_from_file, self.spec_file("does_not_exist"), False)
  50. def test_bad_specfiles(self):
  51. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec3.spec")
  52. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec4.spec")
  53. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec5.spec")
  54. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec6.spec")
  55. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec7.spec")
  56. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec8.spec")
  57. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec9.spec")
  58. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec10.spec")
  59. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec11.spec")
  60. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec12.spec")
  61. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec13.spec")
  62. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec14.spec")
  63. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec15.spec")
  64. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec16.spec")
  65. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec17.spec")
  66. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec18.spec")
  67. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec19.spec")
  68. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec20.spec")
  69. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec21.spec")
  70. self.assertRaises(ModuleSpecError, self.read_spec_file, "spec26.spec")
  71. def validate_data(self, specfile_name, datafile_name):
  72. dd = self.read_spec_file(specfile_name);
  73. data_file = open(self.spec_file(datafile_name))
  74. data_str = data_file.read()
  75. data = isc.cc.data.parse_value_str(data_str)
  76. return dd.validate_config(True, data)
  77. def test_data_validation(self):
  78. self.assertEqual(True, self.validate_data("spec22.spec", "data22_1.data"))
  79. self.assertEqual(False, self.validate_data("spec22.spec", "data22_2.data"))
  80. self.assertEqual(False, self.validate_data("spec22.spec", "data22_3.data"))
  81. self.assertEqual(False, self.validate_data("spec22.spec", "data22_4.data"))
  82. self.assertEqual(False, self.validate_data("spec22.spec", "data22_5.data"))
  83. self.assertEqual(True, self.validate_data("spec22.spec", "data22_6.data"))
  84. self.assertEqual(True, self.validate_data("spec22.spec", "data22_7.data"))
  85. self.assertEqual(False, self.validate_data("spec22.spec", "data22_8.data"))
  86. self.assertEqual(True, self.validate_data("spec32.spec", "data32_1.data"))
  87. self.assertEqual(False, self.validate_data("spec32.spec", "data32_2.data"))
  88. self.assertEqual(False, self.validate_data("spec32.spec", "data32_3.data"))
  89. def validate_command_params(self, specfile_name, datafile_name, cmd_name):
  90. dd = self.read_spec_file(specfile_name);
  91. data_file = open(self.spec_file(datafile_name))
  92. data_str = data_file.read()
  93. params = isc.cc.data.parse_value_str(data_str)
  94. return dd.validate_command(cmd_name, params)
  95. def test_command_validation(self):
  96. # tests for a command that doesn't take an argument
  97. self.assertEqual(True, self.read_spec_file("spec2.spec").validate_command("shutdown", None));
  98. self.assertEqual(False, self.read_spec_file("spec2.spec").validate_command("shutdown", '{"val": 1}'));
  99. self.assertEqual(True, self.validate_command_params("spec27.spec", "data22_1.data", 'cmd1'))
  100. self.assertEqual(False, self.validate_command_params("spec27.spec", "data22_2.data",'cmd1'))
  101. self.assertEqual(False, self.validate_command_params("spec27.spec", "data22_3.data", 'cmd1'))
  102. self.assertEqual(False, self.validate_command_params("spec27.spec", "data22_4.data", 'cmd1'))
  103. self.assertEqual(False, self.validate_command_params("spec27.spec", "data22_5.data", 'cmd1'))
  104. self.assertEqual(True, self.validate_command_params("spec27.spec", "data22_6.data", 'cmd1'))
  105. self.assertEqual(True, self.validate_command_params("spec27.spec", "data22_7.data", 'cmd1'))
  106. self.assertEqual(False, self.validate_command_params("spec27.spec", "data22_8.data", 'cmd1'))
  107. self.assertEqual(False, self.validate_command_params("spec27.spec", "data22_8.data", 'cmd2'))
  108. def test_init(self):
  109. self.assertRaises(ModuleSpecError, ModuleSpec, 1)
  110. module_spec = isc.config.module_spec_from_file(self.spec_file("spec1.spec"), False)
  111. self.spec1(module_spec)
  112. module_spec = isc.config.module_spec_from_file(self.spec_file("spec25.spec"), True)
  113. self.assertEqual("Spec25", module_spec.get_module_name())
  114. self.assertEqual("Just an empty module", module_spec.get_module_description())
  115. def test_str(self):
  116. module_spec = isc.config.module_spec_from_file(self.spec_file("spec1.spec"), False)
  117. self.assertEqual(module_spec.__str__(), "{'module_name': 'Spec1'}")
  118. def test_check_module_spec(self):
  119. self.assertRaises(ModuleSpecError, isc.config.module_spec._check, 1)
  120. def test_check_command_spec(self):
  121. self.assertRaises(ModuleSpecError, isc.config.module_spec._check_command_spec, 1 )
  122. self.assertRaises(ModuleSpecError, isc.config.module_spec._check_command_spec, [ 1 ] )
  123. self.assertRaises(ModuleSpecError, isc.config.module_spec._check_command_spec,
  124. [ { 'command_name': 1,
  125. 'command_description': 'just for testing',
  126. 'command_args': [
  127. { 'item_name': 'arg1',
  128. 'item_type': 'string',
  129. 'item_optional': True
  130. }
  131. ]
  132. }
  133. ]
  134. )
  135. self.assertRaises(ModuleSpecError, isc.config.module_spec._check_command_spec,
  136. [ { 'command_name': 'test_command',
  137. 'command_description': 1,
  138. 'command_args': [
  139. { 'item_name': 'arg1',
  140. 'item_type': 'string',
  141. 'item_optional': True
  142. }
  143. ]
  144. }
  145. ]
  146. )
  147. self.assertRaises(ModuleSpecError, isc.config.module_spec._check_command_spec,
  148. [ { 'command_name': 'test_command',
  149. 'command_args': [ 1 ]
  150. }
  151. ]
  152. )
  153. def test_check_item_spec(self):
  154. self.assertRaises(ModuleSpecError, isc.config.module_spec._check_item_spec, 1 )
  155. self.assertRaises(ModuleSpecError, isc.config.module_spec._check_item_spec,
  156. { 'item_name': 1,
  157. 'item_type': "string",
  158. 'item_optional': False,
  159. 'item_default': "asdf"
  160. }
  161. )
  162. self.assertRaises(ModuleSpecError, isc.config.module_spec._check_item_spec,
  163. { 'item_name': "an_item",
  164. 'item_type': "bad_type",
  165. 'item_optional': False,
  166. 'item_default': "asdf"
  167. }
  168. )
  169. self.assertRaises(ModuleSpecError, isc.config.module_spec._check_item_spec,
  170. { 'item_name': "an_item",
  171. 'item_type': 1,
  172. 'item_optional': False,
  173. 'item_default': "asdf"
  174. }
  175. )
  176. self.assertRaises(ModuleSpecError, isc.config.module_spec._check_item_spec,
  177. { 'item_name': "an_item",
  178. 'item_type': "string",
  179. 'item_optional': False,
  180. }
  181. )
  182. self.assertRaises(ModuleSpecError, isc.config.module_spec._check_item_spec,
  183. { 'item_name': "an_item",
  184. 'item_type': "string",
  185. 'item_optional': 1,
  186. }
  187. )
  188. self.assertRaises(ModuleSpecError, isc.config.module_spec._check_item_spec,
  189. { 'item_name': "an_item",
  190. 'item_type': "string",
  191. 'item_optional': False,
  192. 'item_default': 1
  193. }
  194. )
  195. self.assertRaises(ModuleSpecError, isc.config.module_spec._check_item_spec,
  196. { 'item_name': "an_item",
  197. 'item_type': "list",
  198. 'item_optional': False,
  199. 'item_default': []
  200. }
  201. )
  202. self.assertRaises(ModuleSpecError, isc.config.module_spec._check_item_spec,
  203. { 'item_name': "an_item",
  204. 'item_type': "list",
  205. 'item_optional': False,
  206. 'item_default': [],
  207. 'list_item_spec': 1
  208. }
  209. )
  210. self.assertRaises(ModuleSpecError, isc.config.module_spec._check_item_spec,
  211. { 'item_name': "an_item",
  212. 'item_type': "map",
  213. 'item_optional': False,
  214. 'item_default': {}
  215. }
  216. )
  217. self.assertRaises(ModuleSpecError, isc.config.module_spec._check_item_spec,
  218. { 'item_name': "an_item",
  219. 'item_type': "map",
  220. 'item_optional': False,
  221. 'item_default': {},
  222. 'map_item_spec': 1
  223. }
  224. )
  225. self.assertRaises(ModuleSpecError, isc.config.module_spec._check_item_spec,
  226. { 'item_name': "an_item",
  227. 'item_type': "map",
  228. 'item_optional': False,
  229. 'item_default': {},
  230. 'map_item_spec': [ 1 ]
  231. }
  232. )
  233. def test_validate_type(self):
  234. errors = []
  235. self.assertEqual(True, isc.config.module_spec._validate_type({ 'item_type': 'integer' }, 1, errors))
  236. self.assertEqual(False, isc.config.module_spec._validate_type({ 'item_type': 'integer' }, "a", None))
  237. self.assertEqual(False, isc.config.module_spec._validate_type({ 'item_type': 'integer' }, "a", errors))
  238. self.assertEqual(['a should be an integer'], errors)
  239. errors = []
  240. self.assertEqual(True, isc.config.module_spec._validate_type({ 'item_type': 'real' }, 1.1, errors))
  241. self.assertEqual(False, isc.config.module_spec._validate_type({ 'item_type': 'real' }, "a", None))
  242. self.assertEqual(False, isc.config.module_spec._validate_type({ 'item_type': 'real' }, "a", errors))
  243. self.assertEqual(['a should be a real'], errors)
  244. errors = []
  245. self.assertEqual(True, isc.config.module_spec._validate_type({ 'item_type': 'boolean' }, True, errors))
  246. self.assertEqual(False, isc.config.module_spec._validate_type({ 'item_type': 'boolean' }, "a", None))
  247. self.assertEqual(False, isc.config.module_spec._validate_type({ 'item_type': 'boolean' }, "a", errors))
  248. self.assertEqual(['a should be a boolean'], errors)
  249. errors = []
  250. self.assertEqual(True, isc.config.module_spec._validate_type({ 'item_type': 'string' }, "a", errors))
  251. self.assertEqual(False, isc.config.module_spec._validate_type({ 'item_type': 'string' }, 1, None))
  252. self.assertEqual(False, isc.config.module_spec._validate_type({ 'item_type': 'string' }, 1, errors))
  253. self.assertEqual(['1 should be a string'], errors)
  254. errors = []
  255. self.assertEqual(True, isc.config.module_spec._validate_type({ 'item_type': 'list' }, [ 1, 1], errors))
  256. self.assertEqual(False, isc.config.module_spec._validate_type({ 'item_type': 'list' }, 1, None))
  257. self.assertEqual(False, isc.config.module_spec._validate_type({ 'item_type': 'list' }, 1, errors))
  258. self.assertEqual(['1 should be a list'], errors)
  259. errors = []
  260. self.assertEqual(True, isc.config.module_spec._validate_type({ 'item_type': 'map' }, {"a": 1}, errors))
  261. self.assertEqual(False, isc.config.module_spec._validate_type({ 'item_type': 'map' }, 1, None))
  262. self.assertEqual(False, isc.config.module_spec._validate_type({ 'item_type': 'map' }, 1, errors))
  263. self.assertEqual(['1 should be a map'], errors)
  264. def test_validate_spec(self):
  265. spec = { 'item_name': "an_item",
  266. 'item_type': "string",
  267. 'item_optional': False,
  268. 'item_default': "asdf"
  269. }
  270. errors = []
  271. self.assertEqual(False, isc.config.module_spec._validate_spec(spec, True, {}, None))
  272. self.assertEqual(False, isc.config.module_spec._validate_spec(spec, True, {}, errors))
  273. self.assertEqual(['non-optional item an_item missing'], errors)
  274. def test_validate_unknown_items(self):
  275. spec = [{ 'item_name': "an_item",
  276. 'item_type': "string",
  277. 'item_optional': True,
  278. 'item_default': "asdf"
  279. }]
  280. errors = []
  281. self.assertEqual(True, isc.config.module_spec._validate_spec_list(spec, True, None, None))
  282. self.assertEqual(False, isc.config.module_spec._validate_spec_list(spec, True, { 'does_not_exist': 1 }, None))
  283. self.assertEqual(False, isc.config.module_spec._validate_spec_list(spec, True, { 'does_not_exist': 1 }, errors))
  284. self.assertEqual(['unknown item does_not_exist'], errors)
  285. if __name__ == '__main__':
  286. unittest.main()