test_genericipaddressfield.py 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. from django.core.exceptions import ValidationError
  2. from django.forms import GenericIPAddressField
  3. from django.test import SimpleTestCase
  4. from django.utils.ipv6 import MAX_IPV6_ADDRESS_LENGTH
  5. class GenericIPAddressFieldTest(SimpleTestCase):
  6. def test_generic_ipaddress_invalid_arguments(self):
  7. with self.assertRaises(ValueError):
  8. GenericIPAddressField(protocol="hamster")
  9. with self.assertRaises(ValueError):
  10. GenericIPAddressField(protocol="ipv4", unpack_ipv4=True)
  11. def test_generic_ipaddress_as_generic(self):
  12. # The edge cases of the IPv6 validation code are not deeply tested
  13. # here, they are covered in the tests for django.utils.ipv6
  14. f = GenericIPAddressField()
  15. with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
  16. f.clean("")
  17. with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
  18. f.clean(None)
  19. self.assertEqual(f.clean(" 127.0.0.1 "), "127.0.0.1")
  20. with self.assertRaisesMessage(
  21. ValidationError, "'Enter a valid IPv4 or IPv6 address.'"
  22. ):
  23. f.clean("foo")
  24. with self.assertRaisesMessage(
  25. ValidationError, "'Enter a valid IPv4 or IPv6 address.'"
  26. ):
  27. f.clean("127.0.0.")
  28. with self.assertRaisesMessage(
  29. ValidationError, "'Enter a valid IPv4 or IPv6 address.'"
  30. ):
  31. f.clean("1.2.3.4.5")
  32. with self.assertRaisesMessage(
  33. ValidationError, "'Enter a valid IPv4 or IPv6 address.'"
  34. ):
  35. f.clean("256.125.1.5")
  36. self.assertEqual(
  37. f.clean(" fe80::223:6cff:fe8a:2e8a "), "fe80::223:6cff:fe8a:2e8a"
  38. )
  39. self.assertEqual(
  40. f.clean(" 2a02::223:6cff:fe8a:2e8a "), "2a02::223:6cff:fe8a:2e8a"
  41. )
  42. with self.assertRaisesMessage(
  43. ValidationError, "'This is not a valid IPv6 address.'"
  44. ):
  45. f.clean("12345:2:3:4")
  46. with self.assertRaisesMessage(
  47. ValidationError, "'This is not a valid IPv6 address.'"
  48. ):
  49. f.clean("1::2:3::4")
  50. with self.assertRaisesMessage(
  51. ValidationError, "'This is not a valid IPv6 address.'"
  52. ):
  53. f.clean("foo::223:6cff:fe8a:2e8a")
  54. with self.assertRaisesMessage(
  55. ValidationError, "'This is not a valid IPv6 address.'"
  56. ):
  57. f.clean("1::2:3:4:5:6:7:8")
  58. with self.assertRaisesMessage(
  59. ValidationError, "'This is not a valid IPv6 address.'"
  60. ):
  61. f.clean("1:2")
  62. def test_generic_ipaddress_as_ipv4_only(self):
  63. f = GenericIPAddressField(protocol="IPv4")
  64. with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
  65. f.clean("")
  66. with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
  67. f.clean(None)
  68. self.assertEqual(f.clean(" 127.0.0.1 "), "127.0.0.1")
  69. with self.assertRaisesMessage(ValidationError, "'Enter a valid IPv4 address.'"):
  70. f.clean("foo")
  71. with self.assertRaisesMessage(ValidationError, "'Enter a valid IPv4 address.'"):
  72. f.clean("127.0.0.")
  73. with self.assertRaisesMessage(ValidationError, "'Enter a valid IPv4 address.'"):
  74. f.clean("1.2.3.4.5")
  75. with self.assertRaisesMessage(ValidationError, "'Enter a valid IPv4 address.'"):
  76. f.clean("256.125.1.5")
  77. with self.assertRaisesMessage(ValidationError, "'Enter a valid IPv4 address.'"):
  78. f.clean("fe80::223:6cff:fe8a:2e8a")
  79. with self.assertRaisesMessage(ValidationError, "'Enter a valid IPv4 address.'"):
  80. f.clean("2a02::223:6cff:fe8a:2e8a")
  81. def test_generic_ipaddress_as_ipv6_only(self):
  82. f = GenericIPAddressField(protocol="IPv6")
  83. with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
  84. f.clean("")
  85. with self.assertRaisesMessage(ValidationError, "'This field is required.'"):
  86. f.clean(None)
  87. with self.assertRaisesMessage(ValidationError, "'Enter a valid IPv6 address.'"):
  88. f.clean("127.0.0.1")
  89. with self.assertRaisesMessage(ValidationError, "'Enter a valid IPv6 address.'"):
  90. f.clean("foo")
  91. with self.assertRaisesMessage(ValidationError, "'Enter a valid IPv6 address.'"):
  92. f.clean("127.0.0.")
  93. with self.assertRaisesMessage(ValidationError, "'Enter a valid IPv6 address.'"):
  94. f.clean("1.2.3.4.5")
  95. with self.assertRaisesMessage(ValidationError, "'Enter a valid IPv6 address.'"):
  96. f.clean("256.125.1.5")
  97. self.assertEqual(
  98. f.clean(" fe80::223:6cff:fe8a:2e8a "), "fe80::223:6cff:fe8a:2e8a"
  99. )
  100. self.assertEqual(
  101. f.clean(" 2a02::223:6cff:fe8a:2e8a "), "2a02::223:6cff:fe8a:2e8a"
  102. )
  103. with self.assertRaisesMessage(
  104. ValidationError, "'This is not a valid IPv6 address.'"
  105. ):
  106. f.clean("12345:2:3:4")
  107. with self.assertRaisesMessage(
  108. ValidationError, "'This is not a valid IPv6 address.'"
  109. ):
  110. f.clean("1::2:3::4")
  111. with self.assertRaisesMessage(
  112. ValidationError, "'This is not a valid IPv6 address.'"
  113. ):
  114. f.clean("foo::223:6cff:fe8a:2e8a")
  115. with self.assertRaisesMessage(
  116. ValidationError, "'This is not a valid IPv6 address.'"
  117. ):
  118. f.clean("1::2:3:4:5:6:7:8")
  119. with self.assertRaisesMessage(
  120. ValidationError, "'This is not a valid IPv6 address.'"
  121. ):
  122. f.clean("1:2")
  123. def test_generic_ipaddress_max_length_custom(self):
  124. # Valid IPv4-mapped IPv6 address, len 45.
  125. addr = "0000:0000:0000:0000:0000:ffff:192.168.100.228"
  126. f = GenericIPAddressField(max_length=len(addr))
  127. f.clean(addr)
  128. def test_generic_ipaddress_max_length_validation_error(self):
  129. # Valid IPv4-mapped IPv6 address, len 45.
  130. addr = "0000:0000:0000:0000:0000:ffff:192.168.100.228"
  131. cases = [
  132. ({}, MAX_IPV6_ADDRESS_LENGTH), # Default value.
  133. ({"max_length": len(addr) - 1}, len(addr) - 1),
  134. ]
  135. for kwargs, max_length in cases:
  136. max_length_plus_one = max_length + 1
  137. msg = (
  138. f"Ensure this value has at most {max_length} characters (it has "
  139. f"{max_length_plus_one}).'"
  140. )
  141. with self.subTest(max_length=max_length):
  142. f = GenericIPAddressField(**kwargs)
  143. with self.assertRaisesMessage(ValidationError, msg):
  144. f.clean("x" * max_length_plus_one)
  145. with self.assertRaisesMessage(
  146. ValidationError, "This is not a valid IPv6 address."
  147. ):
  148. f.clean(addr)
  149. def test_generic_ipaddress_as_generic_not_required(self):
  150. f = GenericIPAddressField(required=False)
  151. self.assertEqual(f.clean(""), "")
  152. self.assertEqual(f.clean(None), "")
  153. self.assertEqual(f.clean("127.0.0.1"), "127.0.0.1")
  154. with self.assertRaisesMessage(
  155. ValidationError, "'Enter a valid IPv4 or IPv6 address.'"
  156. ):
  157. f.clean("foo")
  158. with self.assertRaisesMessage(
  159. ValidationError, "'Enter a valid IPv4 or IPv6 address.'"
  160. ):
  161. f.clean("127.0.0.")
  162. with self.assertRaisesMessage(
  163. ValidationError, "'Enter a valid IPv4 or IPv6 address.'"
  164. ):
  165. f.clean("1.2.3.4.5")
  166. with self.assertRaisesMessage(
  167. ValidationError, "'Enter a valid IPv4 or IPv6 address.'"
  168. ):
  169. f.clean("256.125.1.5")
  170. self.assertEqual(
  171. f.clean(" fe80::223:6cff:fe8a:2e8a "), "fe80::223:6cff:fe8a:2e8a"
  172. )
  173. self.assertEqual(
  174. f.clean(" " * MAX_IPV6_ADDRESS_LENGTH + " 2a02::223:6cff:fe8a:2e8a "),
  175. "2a02::223:6cff:fe8a:2e8a",
  176. )
  177. with self.assertRaisesMessage(
  178. ValidationError, "'This is not a valid IPv6 address.'"
  179. ):
  180. f.clean("12345:2:3:4")
  181. with self.assertRaisesMessage(
  182. ValidationError, "'This is not a valid IPv6 address.'"
  183. ):
  184. f.clean("1::2:3::4")
  185. with self.assertRaisesMessage(
  186. ValidationError, "'This is not a valid IPv6 address.'"
  187. ):
  188. f.clean("foo::223:6cff:fe8a:2e8a")
  189. with self.assertRaisesMessage(
  190. ValidationError, "'This is not a valid IPv6 address.'"
  191. ):
  192. f.clean("1::2:3:4:5:6:7:8")
  193. with self.assertRaisesMessage(
  194. ValidationError, "'This is not a valid IPv6 address.'"
  195. ):
  196. f.clean("1:2")
  197. def test_generic_ipaddress_normalization(self):
  198. # Test the normalizing code
  199. f = GenericIPAddressField()
  200. self.assertEqual(f.clean(" ::ffff:0a0a:0a0a "), "::ffff:10.10.10.10")
  201. self.assertEqual(f.clean(" ::ffff:10.10.10.10 "), "::ffff:10.10.10.10")
  202. self.assertEqual(
  203. f.clean(" 2001:000:a:0000:0:fe:fe:beef "), "2001:0:a::fe:fe:beef"
  204. )
  205. self.assertEqual(
  206. f.clean(" 2001::a:0000:0:fe:fe:beef "), "2001:0:a::fe:fe:beef"
  207. )
  208. f = GenericIPAddressField(unpack_ipv4=True)
  209. self.assertEqual(f.clean(" ::ffff:0a0a:0a0a"), "10.10.10.10")