1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

417 lines
12 KiB
Python

from django import forms
from django.test import TestCase
from ipam.forms import IPAddressImportForm
from utilities.choices import ImportFormatChoices
from utilities.forms import ImportForm
from utilities.forms.fields import CSVDataField
from utilities.forms.utils import expand_alphanumeric_pattern, expand_ipaddress_pattern
class ExpandIPAddress(TestCase):
"""
Validate the operation of expand_ipaddress_pattern().
"""
def test_ipv4_range(self):
input = '1.2.3.[9-10]/32'
output = sorted([
'1.2.3.9/32',
'1.2.3.10/32',
])
self.assertEqual(sorted(expand_ipaddress_pattern(input, 4)), output)
def test_ipv4_set(self):
input = '1.2.3.[4,44]/32'
output = sorted([
'1.2.3.4/32',
'1.2.3.44/32',
])
self.assertEqual(sorted(expand_ipaddress_pattern(input, 4)), output)
def test_ipv4_multiple_ranges(self):
input = '1.[9-10].3.[9-11]/32'
output = sorted([
'1.9.3.9/32',
'1.9.3.10/32',
'1.9.3.11/32',
'1.10.3.9/32',
'1.10.3.10/32',
'1.10.3.11/32',
])
self.assertEqual(sorted(expand_ipaddress_pattern(input, 4)), output)
def test_ipv4_multiple_sets(self):
input = '1.[2,22].3.[4,44]/32'
output = sorted([
'1.2.3.4/32',
'1.2.3.44/32',
'1.22.3.4/32',
'1.22.3.44/32',
])
self.assertEqual(sorted(expand_ipaddress_pattern(input, 4)), output)
def test_ipv4_set_and_range(self):
input = '1.[2,22].3.[9-11]/32'
output = sorted([
'1.2.3.9/32',
'1.2.3.10/32',
'1.2.3.11/32',
'1.22.3.9/32',
'1.22.3.10/32',
'1.22.3.11/32',
])
self.assertEqual(sorted(expand_ipaddress_pattern(input, 4)), output)
def test_ipv6_range(self):
input = 'fec::abcd:[9-b]/64'
output = sorted([
'fec::abcd:9/64',
'fec::abcd:a/64',
'fec::abcd:b/64',
])
self.assertEqual(sorted(expand_ipaddress_pattern(input, 6)), output)
def test_ipv6_range_multichar_field(self):
input = 'fec::abcd:[f-11]/64'
output = sorted([
'fec::abcd:f/64',
'fec::abcd:10/64',
'fec::abcd:11/64',
])
self.assertEqual(sorted(expand_ipaddress_pattern(input, 6)), output)
def test_ipv6_set(self):
input = 'fec::abcd:[9,ab]/64'
output = sorted([
'fec::abcd:9/64',
'fec::abcd:ab/64',
])
self.assertEqual(sorted(expand_ipaddress_pattern(input, 6)), output)
def test_ipv6_multiple_ranges(self):
input = 'fec::[1-2]bcd:[9-b]/64'
output = sorted([
'fec::1bcd:9/64',
'fec::1bcd:a/64',
'fec::1bcd:b/64',
'fec::2bcd:9/64',
'fec::2bcd:a/64',
'fec::2bcd:b/64',
])
self.assertEqual(sorted(expand_ipaddress_pattern(input, 6)), output)
def test_ipv6_multiple_sets(self):
input = 'fec::[a,f]bcd:[9,ab]/64'
output = sorted([
'fec::abcd:9/64',
'fec::abcd:ab/64',
'fec::fbcd:9/64',
'fec::fbcd:ab/64',
])
self.assertEqual(sorted(expand_ipaddress_pattern(input, 6)), output)
def test_ipv6_set_and_range(self):
input = 'fec::[dead,beaf]:[9-b]/64'
output = sorted([
'fec::dead:9/64',
'fec::dead:a/64',
'fec::dead:b/64',
'fec::beaf:9/64',
'fec::beaf:a/64',
'fec::beaf:b/64',
])
self.assertEqual(sorted(expand_ipaddress_pattern(input, 6)), output)
def test_invalid_address_family(self):
with self.assertRaisesRegex(Exception, 'Invalid IP address family: 5'):
sorted(expand_ipaddress_pattern(None, 5))
def test_invalid_non_pattern(self):
with self.assertRaises(ValueError):
sorted(expand_ipaddress_pattern('1.2.3.4/32', 4))
def test_invalid_range(self):
with self.assertRaises(ValueError):
sorted(expand_ipaddress_pattern('1.2.3.[4-]/32', 4))
with self.assertRaises(ValueError):
sorted(expand_ipaddress_pattern('1.2.3.[-4]/32', 4))
with self.assertRaises(ValueError):
sorted(expand_ipaddress_pattern('1.2.3.[4--5]/32', 4))
def test_invalid_range_bounds(self):
self.assertEqual(sorted(expand_ipaddress_pattern('1.2.3.[4-3]/32', 6)), [])
def test_invalid_set(self):
with self.assertRaises(ValueError):
sorted(expand_ipaddress_pattern('1.2.3.[4]/32', 4))
with self.assertRaises(ValueError):
sorted(expand_ipaddress_pattern('1.2.3.[4,]/32', 4))
with self.assertRaises(ValueError):
sorted(expand_ipaddress_pattern('1.2.3.[,4]/32', 4))
with self.assertRaises(ValueError):
sorted(expand_ipaddress_pattern('1.2.3.[4,,5]/32', 4))
class ExpandAlphanumeric(TestCase):
"""
Validate the operation of expand_alphanumeric_pattern().
"""
def test_range_numberic(self):
input = 'r[9-11]a'
output = sorted([
'r9a',
'r10a',
'r11a',
])
self.assertEqual(sorted(expand_alphanumeric_pattern(input)), output)
def test_range_alpha(self):
input = '[r-t]1a'
output = sorted([
'r1a',
's1a',
't1a',
])
self.assertEqual(sorted(expand_alphanumeric_pattern(input)), output)
def test_set(self):
input = '[r,t]1a'
output = sorted([
'r1a',
't1a',
])
self.assertEqual(sorted(expand_alphanumeric_pattern(input)), output)
def test_set_multichar(self):
input = '[ra,tb]1a'
output = sorted([
'ra1a',
'tb1a',
])
self.assertEqual(sorted(expand_alphanumeric_pattern(input)), output)
def test_multiple_ranges(self):
input = '[r-t]1[a-b]'
output = sorted([
'r1a',
'r1b',
's1a',
's1b',
't1a',
't1b',
])
self.assertEqual(sorted(expand_alphanumeric_pattern(input)), output)
def test_multiple_sets(self):
input = '[ra,tb]1[ax,by]'
output = sorted([
'ra1ax',
'ra1by',
'tb1ax',
'tb1by',
])
self.assertEqual(sorted(expand_alphanumeric_pattern(input)), output)
def test_set_and_range(self):
input = '[ra,tb]1[a-c]'
output = sorted([
'ra1a',
'ra1b',
'ra1c',
'tb1a',
'tb1b',
'tb1c',
])
self.assertEqual(sorted(expand_alphanumeric_pattern(input)), output)
def test_invalid_non_pattern(self):
with self.assertRaises(ValueError):
sorted(expand_alphanumeric_pattern('r9a'))
def test_invalid_range(self):
with self.assertRaises(ValueError):
sorted(expand_alphanumeric_pattern('r[8-]a'))
with self.assertRaises(ValueError):
sorted(expand_alphanumeric_pattern('r[-8]a'))
with self.assertRaises(ValueError):
sorted(expand_alphanumeric_pattern('r[8--9]a'))
def test_invalid_range_alphanumeric(self):
self.assertEqual(sorted(expand_alphanumeric_pattern('r[9-a]a')), [])
self.assertEqual(sorted(expand_alphanumeric_pattern('r[a-9]a')), [])
def test_invalid_range_bounds(self):
self.assertEqual(sorted(expand_alphanumeric_pattern('r[9-8]a')), [])
self.assertEqual(sorted(expand_alphanumeric_pattern('r[b-a]a')), [])
def test_invalid_range_len(self):
with self.assertRaises(forms.ValidationError):
sorted(expand_alphanumeric_pattern('r[a-bb]a'))
def test_invalid_set(self):
with self.assertRaises(ValueError):
sorted(expand_alphanumeric_pattern('r[a]a'))
with self.assertRaises(ValueError):
sorted(expand_alphanumeric_pattern('r[a,]a'))
with self.assertRaises(ValueError):
sorted(expand_alphanumeric_pattern('r[,a]a'))
with self.assertRaises(ValueError):
sorted(expand_alphanumeric_pattern('r[a,,b]a'))
class CSVDataFieldTest(TestCase):
def setUp(self):
self.field = CSVDataField(from_form=IPAddressImportForm)
def test_clean(self):
input = """
address,status,vrf
192.0.2.1/32,Active,Test VRF
"""
output = (
{'address': None, 'status': None, 'vrf': None},
[{'address': '192.0.2.1/32', 'status': 'Active', 'vrf': 'Test VRF'}]
)
self.assertEqual(self.field.clean(input), output)
def test_clean_invalid_header(self):
input = """
address,status,vrf,xxx
192.0.2.1/32,Active,Test VRF,123
"""
with self.assertRaises(forms.ValidationError):
self.field.clean(input)
def test_clean_missing_required_header(self):
input = """
status,vrf
Active,Test VRF
"""
with self.assertRaises(forms.ValidationError):
self.field.clean(input)
def test_clean_default_to_field(self):
input = """
address,status,vrf.name
192.0.2.1/32,Active,Test VRF
"""
output = (
{'address': None, 'status': None, 'vrf': 'name'},
[{'address': '192.0.2.1/32', 'status': 'Active', 'vrf': 'Test VRF'}]
)
self.assertEqual(self.field.clean(input), output)
def test_clean_pk_to_field(self):
input = """
address,status,vrf.pk
192.0.2.1/32,Active,123
"""
output = (
{'address': None, 'status': None, 'vrf': 'pk'},
[{'address': '192.0.2.1/32', 'status': 'Active', 'vrf': '123'}]
)
self.assertEqual(self.field.clean(input), output)
def test_clean_custom_to_field(self):
input = """
address,status,vrf.rd
192.0.2.1/32,Active,123:456
"""
output = (
{'address': None, 'status': None, 'vrf': 'rd'},
[{'address': '192.0.2.1/32', 'status': 'Active', 'vrf': '123:456'}]
)
self.assertEqual(self.field.clean(input), output)
def test_clean_invalid_to_field(self):
input = """
address,status,vrf.xxx
192.0.2.1/32,Active,123:456
"""
with self.assertRaises(forms.ValidationError):
self.field.clean(input)
def test_clean_to_field_on_non_object(self):
input = """
address,status.foo,vrf
192.0.2.1/32,Bar,Test VRF
"""
with self.assertRaises(forms.ValidationError):
self.field.clean(input)
class ImportFormTest(TestCase):
def test_format_detection(self):
form = ImportForm()
data = (
"a,b,c\n"
"1,2,3\n"
"4,5,6\n"
)
self.assertEqual(form._detect_format(data), ImportFormatChoices.CSV)
data = '{"a": 1, "b": 2, "c": 3"}'
self.assertEqual(form._detect_format(data), ImportFormatChoices.JSON)
data = '[{"a": 1, "b": 2, "c": 3"}, {"a": 4, "b": 5, "c": 6"}]'
self.assertEqual(form._detect_format(data), ImportFormatChoices.JSON)
data = (
"- a: 1\n"
" b: 2\n"
" c: 3\n"
"- a: 4\n"
" b: 5\n"
" c: 6\n"
)
self.assertEqual(form._detect_format(data), ImportFormatChoices.YAML)
data = (
"---\n"
"a: 1\n"
"b: 2\n"
"c: 3\n"
"---\n"
"a: 4\n"
"b: 5\n"
"c: 6\n"
)
self.assertEqual(form._detect_format(data), ImportFormatChoices.YAML)
# Invalid data
with self.assertRaises(forms.ValidationError):
form._detect_format('')
with self.assertRaises(forms.ValidationError):
form._detect_format('?')