test_scripts.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. import tempfile
  2. from datetime import date, datetime, timezone
  3. from django.core.files.uploadedfile import SimpleUploadedFile
  4. from django.test import TestCase
  5. from netaddr import IPAddress, IPNetwork
  6. from dcim.models import DeviceRole
  7. from extras.scripts import *
  8. CHOICES = (
  9. ('ff0000', 'Red'),
  10. ('00ff00', 'Green'),
  11. ('0000ff', 'Blue')
  12. )
  13. YAML_DATA = """
  14. Foo: 123
  15. Bar: 456
  16. Baz:
  17. - A
  18. - B
  19. - C
  20. """
  21. JSON_DATA = """
  22. {
  23. "Foo": 123,
  24. "Bar": 456,
  25. "Baz": ["A", "B", "C"]
  26. }
  27. """
  28. class ScriptTest(TestCase):
  29. def test_load_yaml(self):
  30. datafile = tempfile.NamedTemporaryFile()
  31. datafile.write(bytes(YAML_DATA, 'UTF-8'))
  32. datafile.seek(0)
  33. data = Script().load_yaml(datafile.name)
  34. self.assertEqual(data, {
  35. 'Foo': 123,
  36. 'Bar': 456,
  37. 'Baz': ['A', 'B', 'C'],
  38. })
  39. def test_load_json(self):
  40. datafile = tempfile.NamedTemporaryFile()
  41. datafile.write(bytes(JSON_DATA, 'UTF-8'))
  42. datafile.seek(0)
  43. data = Script().load_json(datafile.name)
  44. self.assertEqual(data, {
  45. 'Foo': 123,
  46. 'Bar': 456,
  47. 'Baz': ['A', 'B', 'C'],
  48. })
  49. class ScriptVariablesTest(TestCase):
  50. def test_stringvar(self):
  51. class TestScript(Script):
  52. var1 = StringVar(
  53. min_length=3,
  54. max_length=3,
  55. regex=r'[a-z]+'
  56. )
  57. # Validate min_length enforcement
  58. data = {'var1': 'xx'}
  59. form = TestScript().as_form(data, None)
  60. self.assertFalse(form.is_valid())
  61. self.assertIn('var1', form.errors)
  62. # Validate max_length enforcement
  63. data = {'var1': 'xxxx'}
  64. form = TestScript().as_form(data, None)
  65. self.assertFalse(form.is_valid())
  66. self.assertIn('var1', form.errors)
  67. # Validate regex enforcement
  68. data = {'var1': 'ABC'}
  69. form = TestScript().as_form(data, None)
  70. self.assertFalse(form.is_valid())
  71. self.assertIn('var1', form.errors)
  72. # Validate valid data
  73. data = {'var1': 'abc'}
  74. form = TestScript().as_form(data, None)
  75. self.assertTrue(form.is_valid())
  76. self.assertEqual(form.cleaned_data['var1'], data['var1'])
  77. def test_textvar(self):
  78. class TestScript(Script):
  79. var1 = TextVar()
  80. # Validate valid data
  81. data = {'var1': 'This is a test string'}
  82. form = TestScript().as_form(data, None)
  83. self.assertTrue(form.is_valid())
  84. self.assertEqual(form.cleaned_data['var1'], data['var1'])
  85. def test_integervar(self):
  86. class TestScript(Script):
  87. var1 = IntegerVar(
  88. min_value=5,
  89. max_value=10
  90. )
  91. # Validate min_value enforcement
  92. data = {'var1': 4}
  93. form = TestScript().as_form(data, None)
  94. self.assertFalse(form.is_valid())
  95. self.assertIn('var1', form.errors)
  96. # Validate max_value enforcement
  97. data = {'var1': 11}
  98. form = TestScript().as_form(data, None)
  99. self.assertFalse(form.is_valid())
  100. self.assertIn('var1', form.errors)
  101. # Validate valid data
  102. data = {'var1': 7}
  103. form = TestScript().as_form(data, None)
  104. self.assertTrue(form.is_valid())
  105. self.assertEqual(form.cleaned_data['var1'], data['var1'])
  106. def test_booleanvar(self):
  107. class TestScript(Script):
  108. var1 = BooleanVar()
  109. # Validate True
  110. data = {'var1': True}
  111. form = TestScript().as_form(data, None)
  112. self.assertTrue(form.is_valid())
  113. self.assertEqual(form.cleaned_data['var1'], True)
  114. # Validate False
  115. data = {'var1': False}
  116. form = TestScript().as_form(data, None)
  117. self.assertTrue(form.is_valid())
  118. self.assertEqual(form.cleaned_data['var1'], False)
  119. def test_choicevar(self):
  120. class TestScript(Script):
  121. var1 = ChoiceVar(
  122. choices=CHOICES
  123. )
  124. # Validate valid choice
  125. data = {'var1': 'ff0000'}
  126. form = TestScript().as_form(data)
  127. self.assertTrue(form.is_valid())
  128. self.assertEqual(form.cleaned_data['var1'], 'ff0000')
  129. # Validate invalid choice
  130. data = {'var1': 'taupe'}
  131. form = TestScript().as_form(data)
  132. self.assertFalse(form.is_valid())
  133. def test_multichoicevar(self):
  134. class TestScript(Script):
  135. var1 = MultiChoiceVar(
  136. choices=CHOICES
  137. )
  138. # Validate single choice
  139. data = {'var1': ['ff0000']}
  140. form = TestScript().as_form(data)
  141. self.assertTrue(form.is_valid())
  142. self.assertEqual(form.cleaned_data['var1'], ['ff0000'])
  143. # Validate multiple choices
  144. data = {'var1': ('ff0000', '00ff00')}
  145. form = TestScript().as_form(data)
  146. self.assertTrue(form.is_valid())
  147. self.assertEqual(form.cleaned_data['var1'], ['ff0000', '00ff00'])
  148. # Validate invalid choice
  149. data = {'var1': 'taupe'}
  150. form = TestScript().as_form(data)
  151. self.assertFalse(form.is_valid())
  152. def test_objectvar(self):
  153. class TestScript(Script):
  154. var1 = ObjectVar(model=DeviceRole)
  155. # Populate some objects
  156. for i in range(1, 6):
  157. DeviceRole(
  158. name='Device Role {}'.format(i),
  159. slug='device-role-{}'.format(i)
  160. ).save()
  161. # Validate valid data
  162. data = {'var1': DeviceRole.objects.first().pk}
  163. form = TestScript().as_form(data, None)
  164. self.assertTrue(form.is_valid())
  165. self.assertEqual(form.cleaned_data['var1'].pk, data['var1'])
  166. def test_multiobjectvar(self):
  167. class TestScript(Script):
  168. var1 = MultiObjectVar(model=DeviceRole)
  169. # Populate some objects
  170. for i in range(1, 6):
  171. DeviceRole(
  172. name='Device Role {}'.format(i),
  173. slug='device-role-{}'.format(i)
  174. ).save()
  175. # Validate valid data
  176. data = {'var1': [role.pk for role in DeviceRole.objects.all()[:3]]}
  177. form = TestScript().as_form(data, None)
  178. self.assertTrue(form.is_valid())
  179. self.assertEqual(form.cleaned_data['var1'][0].pk, data['var1'][0])
  180. self.assertEqual(form.cleaned_data['var1'][1].pk, data['var1'][1])
  181. self.assertEqual(form.cleaned_data['var1'][2].pk, data['var1'][2])
  182. def test_filevar(self):
  183. class TestScript(Script):
  184. var1 = FileVar()
  185. # Dummy file
  186. testfile = SimpleUploadedFile(
  187. name='test_file.txt',
  188. content=b'This is a dummy file for testing'
  189. )
  190. # Validate valid data
  191. file_data = {'var1': testfile}
  192. form = TestScript().as_form(None, file_data)
  193. self.assertTrue(form.is_valid())
  194. self.assertEqual(form.cleaned_data['var1'], testfile)
  195. def test_ipaddressvar(self):
  196. class TestScript(Script):
  197. var1 = IPAddressVar()
  198. # Validate IP network enforcement
  199. data = {'var1': '1.2.3'}
  200. form = TestScript().as_form(data, None)
  201. self.assertFalse(form.is_valid())
  202. self.assertIn('var1', form.errors)
  203. # Validate IP mask exclusion
  204. data = {'var1': '192.0.2.0/24'}
  205. form = TestScript().as_form(data, None)
  206. self.assertFalse(form.is_valid())
  207. self.assertIn('var1', form.errors)
  208. # Validate valid data
  209. data = {'var1': '192.0.2.1'}
  210. form = TestScript().as_form(data, None)
  211. self.assertTrue(form.is_valid())
  212. self.assertEqual(form.cleaned_data['var1'], IPAddress(data['var1']))
  213. def test_ipaddresswithmaskvar(self):
  214. class TestScript(Script):
  215. var1 = IPAddressWithMaskVar()
  216. # Validate IP network enforcement
  217. data = {'var1': '1.2.3'}
  218. form = TestScript().as_form(data, None)
  219. self.assertFalse(form.is_valid())
  220. self.assertIn('var1', form.errors)
  221. # Validate IP mask requirement
  222. data = {'var1': '192.0.2.0'}
  223. form = TestScript().as_form(data, None)
  224. self.assertFalse(form.is_valid())
  225. self.assertIn('var1', form.errors)
  226. # Validate valid data
  227. data = {'var1': '192.0.2.0/24'}
  228. form = TestScript().as_form(data, None)
  229. self.assertTrue(form.is_valid())
  230. self.assertEqual(form.cleaned_data['var1'], IPNetwork(data['var1']))
  231. def test_ipnetworkvar(self):
  232. class TestScript(Script):
  233. var1 = IPNetworkVar()
  234. # Validate IP network enforcement
  235. data = {'var1': '1.2.3'}
  236. form = TestScript().as_form(data, None)
  237. self.assertFalse(form.is_valid())
  238. self.assertIn('var1', form.errors)
  239. # Validate host IP check
  240. data = {'var1': '192.0.2.1/24'}
  241. form = TestScript().as_form(data, None)
  242. self.assertFalse(form.is_valid())
  243. self.assertIn('var1', form.errors)
  244. # Validate valid data
  245. data = {'var1': '192.0.2.0/24'}
  246. form = TestScript().as_form(data, None)
  247. self.assertTrue(form.is_valid())
  248. self.assertEqual(form.cleaned_data['var1'], IPNetwork(data['var1']))
  249. def test_datevar(self):
  250. class TestScript(Script):
  251. var1 = DateVar()
  252. var2 = DateVar(required=False)
  253. # Test date validation
  254. data = {'var1': 'not a date'}
  255. form = TestScript().as_form(data, None)
  256. self.assertFalse(form.is_valid())
  257. self.assertIn('var1', form.errors)
  258. # Validate valid data
  259. input_date = date(2024, 4, 1)
  260. data = {'var1': input_date}
  261. form = TestScript().as_form(data, None)
  262. self.assertTrue(form.is_valid())
  263. self.assertEqual(form.cleaned_data['var1'], input_date)
  264. # Validate required=False works for this Var type
  265. self.assertEqual(form.cleaned_data['var2'], None)
  266. def test_datetimevar(self):
  267. class TestScript(Script):
  268. var1 = DateTimeVar()
  269. var2 = DateTimeVar(required=False)
  270. # Test datetime validation
  271. data = {'var1': 'not a datetime'}
  272. form = TestScript().as_form(data, None)
  273. self.assertFalse(form.is_valid())
  274. self.assertIn('var1', form.errors)
  275. # Validate valid data
  276. input_datetime = datetime(2024, 4, 1, 8, 0, 0, 0, timezone.utc)
  277. data = {'var1': input_datetime}
  278. form = TestScript().as_form(data, None)
  279. self.assertTrue(form.is_valid())
  280. self.assertEqual(form.cleaned_data['var1'], input_datetime)
  281. # Validate required=False works for this Var type
  282. self.assertEqual(form.cleaned_data['var2'], None)