Skip to content

Commit 06e68c7

Browse files
michael-koellermroethke
authored andcommitted
Add unit tests
1 parent a4117ae commit 06e68c7

File tree

3 files changed

+154
-0
lines changed

3 files changed

+154
-0
lines changed

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@
4242
"six",
4343
'enum34; python_version < "3.4.0"'
4444
],
45+
test_suite="tests.suite"
4546
)

tests/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import unittest
2+
from .test_pfx_table import PfxTableTest
3+
4+
5+
def suite():
6+
loader = unittest.TestLoader()
7+
s = loader.loadTestsFromTestCase(PfxTableTest)
8+
return s
9+
10+
11+
if __name__ == '__main__':
12+
runner = unittest.TextTestRunner()
13+
runner.run(suite())

tests/test_pfx_table.py

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# -*- coding: utf8 -*-
2+
"""
3+
tests.pfx_table_test
4+
------------------
5+
"""
6+
7+
import os, sys
8+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
9+
10+
import unittest
11+
12+
from rtrlib import PfxTable
13+
14+
# flag constants for asserting the validation result
15+
VALID = 1 << 0
16+
INVALID = 1 << 1
17+
UNKNOWN = 1 << 2
18+
LENGTH_INVALID = 1 << 3
19+
AS_INVALID = 1 << 4
20+
21+
22+
class PfxTableTest(unittest.TestCase):
23+
24+
DEFAULT_RECORDS = [
25+
(10010, '110.1.0.0', 20, 24),
26+
(10020, '120.1.0.0', 20, 32),
27+
(10030, '130::', 64, 64)
28+
]
29+
30+
def setUp(self):
31+
"""
32+
Create a new prefix table instance for any test method
33+
"""
34+
self.pfx_table = PfxTable()
35+
36+
def tearDown(self):
37+
"""
38+
Close and remove the current prefix table instance
39+
"""
40+
self.pfx_table.close()
41+
42+
def test_v4(self):
43+
"""
44+
- Test IPV4 record in prefix table
45+
"""
46+
self._fill_table(self.DEFAULT_RECORDS)
47+
48+
self._assert(10010, '110.1.0.0', 20, VALID)
49+
self._assert(10010, '110.1.0.0', 24, VALID)
50+
self._assert(10010, '110.1.8.0', 23, VALID)
51+
self._assert(10010, '110.1.0.0', 18, UNKNOWN)
52+
self._assert(10010, '110.1.0.0', 30, INVALID)
53+
self._assert(10011, '110.1.0.0', 20, INVALID)
54+
55+
self._assert_r(10010, '110.1.0.0', 20, VALID)
56+
self._assert_r(10010, '110.1.0.0', 24, VALID)
57+
self._assert_r(10010, '110.1.8.0', 23, VALID)
58+
self._assert_r(10010, '110.1.0.0', 18, UNKNOWN)
59+
self._assert_r(10010, '110.1.0.0', 30, INVALID | LENGTH_INVALID)
60+
self._assert_r(10011, '110.1.0.0', 20, INVALID | AS_INVALID)
61+
62+
def test_v6(self):
63+
"""
64+
- Test IPV6 record in prefix table
65+
"""
66+
self._fill_table(self.DEFAULT_RECORDS)
67+
68+
self._assert(10030, '130::', 64, VALID)
69+
self._assert(10030, '130::', 66, INVALID)
70+
self._assert(10030, '130::', 62, UNKNOWN)
71+
72+
self._assert_r(10030, '130::', 64, VALID)
73+
self._assert_r(10030, '130::', 66, INVALID | LENGTH_INVALID)
74+
self._assert_r(10030, '130::', 62, UNKNOWN)
75+
76+
def test_duplicate(self):
77+
"""
78+
- Add duplicate record into prefix table (same prefix range, other AS number)
79+
"""
80+
self._fill_table(self.DEFAULT_RECORDS)
81+
self._fill_table([(10020, '110.1.0.0', 22, 24)])
82+
83+
self._assert(10010, '110.1.0.0', 20, VALID)
84+
self._assert(10010, '110.1.0.0', 24, VALID)
85+
self._assert(10020, '110.1.0.0', 22, VALID)
86+
self._assert(10020, '110.1.0.0', 24, VALID)
87+
88+
def test_remove(self):
89+
"""
90+
- Remove record from prefix table
91+
"""
92+
self._fill_table(self.DEFAULT_RECORDS)
93+
self.pfx_table.remove_record(10010, '110.1.0.0', 20, 24)
94+
95+
self._assert(10010, '110.1.0.0', 20, UNKNOWN)
96+
97+
def _fill_table(self, records):
98+
"""
99+
Adds a list of record tuples to the prefix talbe.
100+
Each tuple must contain these four elements:
101+
* as number (int)
102+
* ip address (str)
103+
* min range length (int)
104+
* max range length (int)
105+
:param records: List of records to be added to the prefix table
106+
:type records: list
107+
"""
108+
for record in records:
109+
self.pfx_table.add_record(*record)
110+
111+
def _assert(self, asn, ip, mask, exp_flags):
112+
"""
113+
Let the prefix table validate the given IP prefix
114+
and check the returned validation result
115+
"""
116+
r = self.pfx_table.validate(asn, ip, mask)
117+
record = "AS{0}:{1}/{2}".format(asn, ip, mask)
118+
self._assert_flag(r.is_valid, bool(exp_flags & VALID), record, "is invalid", "is valid")
119+
self._assert_flag(r.is_invalid, bool(exp_flags & INVALID), record, "is valid", "is invalid")
120+
self._assert_flag(r.not_found, bool(exp_flags & UNKNOWN), record, "was found", "not found")
121+
122+
def _assert_r(self, asn, ip, mask, exp_flags):
123+
"""
124+
Let the prefix table validate the given IP prefix
125+
and check the returned validation result
126+
"""
127+
r = self.pfx_table.validate_r(asn, ip, mask)
128+
record = "AS{0}:{1}/{2}".format(asn, ip, mask)
129+
self._assert_flag(r.is_valid, bool(exp_flags & VALID), record, "is invalid", "is valid")
130+
self._assert_flag(r.is_invalid, bool(exp_flags & INVALID), record, "is valid", "is invalid")
131+
self._assert_flag(r.not_found, bool(exp_flags & UNKNOWN), record, "was found", "not found")
132+
self._assert_flag(r.length_invalid, bool(exp_flags & LENGTH_INVALID), record, "has invalid length", "has valid length")
133+
self._assert_flag(r.as_invalid, bool(exp_flags & AS_INVALID), record, "has invalid AS", "has valid AS")
134+
135+
def _assert_flag(self, act_flag, exp_val, record, msg_exp_true, msg_exp_false):
136+
self.assertEqual(act_flag, exp_val, "{0} {1}".format(record, msg_exp_true if exp_val else msg_exp_false))
137+
138+
139+
if __name__ == '__main__':
140+
unittest.main()

0 commit comments

Comments
 (0)