test_forms.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. from django import forms
  2. from django.test import TestCase
  3. from ipam.forms import IPAddressCSVForm
  4. from ipam.models import VRF
  5. from utilities.forms import *
  6. class ExpandIPAddress(TestCase):
  7. """
  8. Validate the operation of expand_ipaddress_pattern().
  9. """
  10. def test_ipv4_range(self):
  11. input = '1.2.3.[9-10]/32'
  12. output = sorted([
  13. '1.2.3.9/32',
  14. '1.2.3.10/32',
  15. ])
  16. self.assertEqual(sorted(expand_ipaddress_pattern(input, 4)), output)
  17. def test_ipv4_set(self):
  18. input = '1.2.3.[4,44]/32'
  19. output = sorted([
  20. '1.2.3.4/32',
  21. '1.2.3.44/32',
  22. ])
  23. self.assertEqual(sorted(expand_ipaddress_pattern(input, 4)), output)
  24. def test_ipv4_multiple_ranges(self):
  25. input = '1.[9-10].3.[9-11]/32'
  26. output = sorted([
  27. '1.9.3.9/32',
  28. '1.9.3.10/32',
  29. '1.9.3.11/32',
  30. '1.10.3.9/32',
  31. '1.10.3.10/32',
  32. '1.10.3.11/32',
  33. ])
  34. self.assertEqual(sorted(expand_ipaddress_pattern(input, 4)), output)
  35. def test_ipv4_multiple_sets(self):
  36. input = '1.[2,22].3.[4,44]/32'
  37. output = sorted([
  38. '1.2.3.4/32',
  39. '1.2.3.44/32',
  40. '1.22.3.4/32',
  41. '1.22.3.44/32',
  42. ])
  43. self.assertEqual(sorted(expand_ipaddress_pattern(input, 4)), output)
  44. def test_ipv4_set_and_range(self):
  45. input = '1.[2,22].3.[9-11]/32'
  46. output = sorted([
  47. '1.2.3.9/32',
  48. '1.2.3.10/32',
  49. '1.2.3.11/32',
  50. '1.22.3.9/32',
  51. '1.22.3.10/32',
  52. '1.22.3.11/32',
  53. ])
  54. self.assertEqual(sorted(expand_ipaddress_pattern(input, 4)), output)
  55. def test_ipv6_range(self):
  56. input = 'fec::abcd:[9-b]/64'
  57. output = sorted([
  58. 'fec::abcd:9/64',
  59. 'fec::abcd:a/64',
  60. 'fec::abcd:b/64',
  61. ])
  62. self.assertEqual(sorted(expand_ipaddress_pattern(input, 6)), output)
  63. def test_ipv6_range_multichar_field(self):
  64. input = 'fec::abcd:[f-11]/64'
  65. output = sorted([
  66. 'fec::abcd:f/64',
  67. 'fec::abcd:10/64',
  68. 'fec::abcd:11/64',
  69. ])
  70. self.assertEqual(sorted(expand_ipaddress_pattern(input, 6)), output)
  71. def test_ipv6_set(self):
  72. input = 'fec::abcd:[9,ab]/64'
  73. output = sorted([
  74. 'fec::abcd:9/64',
  75. 'fec::abcd:ab/64',
  76. ])
  77. self.assertEqual(sorted(expand_ipaddress_pattern(input, 6)), output)
  78. def test_ipv6_multiple_ranges(self):
  79. input = 'fec::[1-2]bcd:[9-b]/64'
  80. output = sorted([
  81. 'fec::1bcd:9/64',
  82. 'fec::1bcd:a/64',
  83. 'fec::1bcd:b/64',
  84. 'fec::2bcd:9/64',
  85. 'fec::2bcd:a/64',
  86. 'fec::2bcd:b/64',
  87. ])
  88. self.assertEqual(sorted(expand_ipaddress_pattern(input, 6)), output)
  89. def test_ipv6_multiple_sets(self):
  90. input = 'fec::[a,f]bcd:[9,ab]/64'
  91. output = sorted([
  92. 'fec::abcd:9/64',
  93. 'fec::abcd:ab/64',
  94. 'fec::fbcd:9/64',
  95. 'fec::fbcd:ab/64',
  96. ])
  97. self.assertEqual(sorted(expand_ipaddress_pattern(input, 6)), output)
  98. def test_ipv6_set_and_range(self):
  99. input = 'fec::[dead,beaf]:[9-b]/64'
  100. output = sorted([
  101. 'fec::dead:9/64',
  102. 'fec::dead:a/64',
  103. 'fec::dead:b/64',
  104. 'fec::beaf:9/64',
  105. 'fec::beaf:a/64',
  106. 'fec::beaf:b/64',
  107. ])
  108. self.assertEqual(sorted(expand_ipaddress_pattern(input, 6)), output)
  109. def test_invalid_address_family(self):
  110. with self.assertRaisesRegex(Exception, 'Invalid IP address family: 5'):
  111. sorted(expand_ipaddress_pattern(None, 5))
  112. def test_invalid_non_pattern(self):
  113. with self.assertRaises(ValueError):
  114. sorted(expand_ipaddress_pattern('1.2.3.4/32', 4))
  115. def test_invalid_range(self):
  116. with self.assertRaises(ValueError):
  117. sorted(expand_ipaddress_pattern('1.2.3.[4-]/32', 4))
  118. with self.assertRaises(ValueError):
  119. sorted(expand_ipaddress_pattern('1.2.3.[-4]/32', 4))
  120. with self.assertRaises(ValueError):
  121. sorted(expand_ipaddress_pattern('1.2.3.[4--5]/32', 4))
  122. def test_invalid_range_bounds(self):
  123. self.assertEqual(sorted(expand_ipaddress_pattern('1.2.3.[4-3]/32', 6)), [])
  124. def test_invalid_set(self):
  125. with self.assertRaises(ValueError):
  126. sorted(expand_ipaddress_pattern('1.2.3.[4]/32', 4))
  127. with self.assertRaises(ValueError):
  128. sorted(expand_ipaddress_pattern('1.2.3.[4,]/32', 4))
  129. with self.assertRaises(ValueError):
  130. sorted(expand_ipaddress_pattern('1.2.3.[,4]/32', 4))
  131. with self.assertRaises(ValueError):
  132. sorted(expand_ipaddress_pattern('1.2.3.[4,,5]/32', 4))
  133. class ExpandAlphanumeric(TestCase):
  134. """
  135. Validate the operation of expand_alphanumeric_pattern().
  136. """
  137. def test_range_numberic(self):
  138. input = 'r[9-11]a'
  139. output = sorted([
  140. 'r9a',
  141. 'r10a',
  142. 'r11a',
  143. ])
  144. self.assertEqual(sorted(expand_alphanumeric_pattern(input)), output)
  145. def test_range_alpha(self):
  146. input = '[r-t]1a'
  147. output = sorted([
  148. 'r1a',
  149. 's1a',
  150. 't1a',
  151. ])
  152. self.assertEqual(sorted(expand_alphanumeric_pattern(input)), output)
  153. def test_set(self):
  154. input = '[r,t]1a'
  155. output = sorted([
  156. 'r1a',
  157. 't1a',
  158. ])
  159. self.assertEqual(sorted(expand_alphanumeric_pattern(input)), output)
  160. def test_set_multichar(self):
  161. input = '[ra,tb]1a'
  162. output = sorted([
  163. 'ra1a',
  164. 'tb1a',
  165. ])
  166. self.assertEqual(sorted(expand_alphanumeric_pattern(input)), output)
  167. def test_multiple_ranges(self):
  168. input = '[r-t]1[a-b]'
  169. output = sorted([
  170. 'r1a',
  171. 'r1b',
  172. 's1a',
  173. 's1b',
  174. 't1a',
  175. 't1b',
  176. ])
  177. self.assertEqual(sorted(expand_alphanumeric_pattern(input)), output)
  178. def test_multiple_sets(self):
  179. input = '[ra,tb]1[ax,by]'
  180. output = sorted([
  181. 'ra1ax',
  182. 'ra1by',
  183. 'tb1ax',
  184. 'tb1by',
  185. ])
  186. self.assertEqual(sorted(expand_alphanumeric_pattern(input)), output)
  187. def test_set_and_range(self):
  188. input = '[ra,tb]1[a-c]'
  189. output = sorted([
  190. 'ra1a',
  191. 'ra1b',
  192. 'ra1c',
  193. 'tb1a',
  194. 'tb1b',
  195. 'tb1c',
  196. ])
  197. self.assertEqual(sorted(expand_alphanumeric_pattern(input)), output)
  198. def test_invalid_non_pattern(self):
  199. with self.assertRaises(ValueError):
  200. sorted(expand_alphanumeric_pattern('r9a'))
  201. def test_invalid_range(self):
  202. with self.assertRaises(ValueError):
  203. sorted(expand_alphanumeric_pattern('r[8-]a'))
  204. with self.assertRaises(ValueError):
  205. sorted(expand_alphanumeric_pattern('r[-8]a'))
  206. with self.assertRaises(ValueError):
  207. sorted(expand_alphanumeric_pattern('r[8--9]a'))
  208. def test_invalid_range_alphanumeric(self):
  209. self.assertEqual(sorted(expand_alphanumeric_pattern('r[9-a]a')), [])
  210. self.assertEqual(sorted(expand_alphanumeric_pattern('r[a-9]a')), [])
  211. def test_invalid_range_bounds(self):
  212. self.assertEqual(sorted(expand_alphanumeric_pattern('r[9-8]a')), [])
  213. self.assertEqual(sorted(expand_alphanumeric_pattern('r[b-a]a')), [])
  214. def test_invalid_range_len(self):
  215. with self.assertRaises(forms.ValidationError):
  216. sorted(expand_alphanumeric_pattern('r[a-bb]a'))
  217. def test_invalid_set(self):
  218. with self.assertRaises(ValueError):
  219. sorted(expand_alphanumeric_pattern('r[a]a'))
  220. with self.assertRaises(ValueError):
  221. sorted(expand_alphanumeric_pattern('r[a,]a'))
  222. with self.assertRaises(ValueError):
  223. sorted(expand_alphanumeric_pattern('r[,a]a'))
  224. with self.assertRaises(ValueError):
  225. sorted(expand_alphanumeric_pattern('r[a,,b]a'))
  226. class CSVDataFieldTest(TestCase):
  227. def setUp(self):
  228. self.field = CSVDataField(from_form=IPAddressCSVForm)
  229. def test_clean(self):
  230. input = """
  231. address,status,vrf
  232. 192.0.2.1/32,Active,Test VRF
  233. """
  234. output = (
  235. {'address': None, 'status': None, 'vrf': None},
  236. [{'address': '192.0.2.1/32', 'status': 'Active', 'vrf': 'Test VRF'}]
  237. )
  238. self.assertEqual(self.field.clean(input), output)
  239. def test_clean_invalid_header(self):
  240. input = """
  241. address,status,vrf,xxx
  242. 192.0.2.1/32,Active,Test VRF,123
  243. """
  244. with self.assertRaises(forms.ValidationError):
  245. self.field.clean(input)
  246. def test_clean_missing_required_header(self):
  247. input = """
  248. status,vrf
  249. Active,Test VRF
  250. """
  251. with self.assertRaises(forms.ValidationError):
  252. self.field.clean(input)
  253. def test_clean_default_to_field(self):
  254. input = """
  255. address,status,vrf.name
  256. 192.0.2.1/32,Active,Test VRF
  257. """
  258. output = (
  259. {'address': None, 'status': None, 'vrf': 'name'},
  260. [{'address': '192.0.2.1/32', 'status': 'Active', 'vrf': 'Test VRF'}]
  261. )
  262. self.assertEqual(self.field.clean(input), output)
  263. def test_clean_pk_to_field(self):
  264. input = """
  265. address,status,vrf.pk
  266. 192.0.2.1/32,Active,123
  267. """
  268. output = (
  269. {'address': None, 'status': None, 'vrf': 'pk'},
  270. [{'address': '192.0.2.1/32', 'status': 'Active', 'vrf': '123'}]
  271. )
  272. self.assertEqual(self.field.clean(input), output)
  273. def test_clean_custom_to_field(self):
  274. input = """
  275. address,status,vrf.rd
  276. 192.0.2.1/32,Active,123:456
  277. """
  278. output = (
  279. {'address': None, 'status': None, 'vrf': 'rd'},
  280. [{'address': '192.0.2.1/32', 'status': 'Active', 'vrf': '123:456'}]
  281. )
  282. self.assertEqual(self.field.clean(input), output)
  283. def test_clean_invalid_to_field(self):
  284. input = """
  285. address,status,vrf.xxx
  286. 192.0.2.1/32,Active,123:456
  287. """
  288. with self.assertRaises(forms.ValidationError):
  289. self.field.clean(input)
  290. def test_clean_to_field_on_non_object(self):
  291. input = """
  292. address,status.foo,vrf
  293. 192.0.2.1/32,Bar,Test VRF
  294. """
  295. with self.assertRaises(forms.ValidationError):
  296. self.field.clean(input)