Skip to content
This repository was archived by the owner on Jun 27, 2020. It is now read-only.

Commit 466e0da

Browse files
authored
Merge pull request #79 from acoul/master
merge issue/58 branch to upstream master tree
2 parents a05e2ad + bc10c14 commit 466e0da

File tree

7 files changed

+128
-22
lines changed

7 files changed

+128
-22
lines changed

django_netjsongraph/base/link.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ def get_from_nodes(cls, source, target, topology):
103103
:param topology: Topology instance
104104
:returns: Link object or None
105105
"""
106-
source = '{0};'.format(source)
107-
target = '{0};'.format(target)
106+
source = ';{0};'.format(source)
107+
target = ';{0};'.format(target)
108108
q = (Q(source__addresses__contains=source,
109109
target__addresses__contains=target) |
110110
Q(source__addresses__contains=target,

django_netjsongraph/base/node.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ def save(self, *args, **kwargs):
4141

4242
def _format_addresses(self):
4343
"""
44-
Ensure address format is correct:
45-
addr1; addr2; addr3;
44+
Ensure address format is correct: ";addr1;addr2;addr3;"
4645
"""
4746
self.addresses = self.addresses.replace(',', ';')\
4847
.replace(' ', '')\
49-
.replace(';', '; ')
50-
if not self.addresses.endswith('; '):
51-
self.addresses += '; '
52-
self.addresses = self.addresses[0:-1]
48+
.replace(';', ';')
49+
if not self.addresses.startswith(';'):
50+
self.addresses = ';' + self.addresses
51+
if not self.addresses.endswith(';'):
52+
self.addresses += ';'
5353

5454
def truncate_addresses(self):
5555
"""
@@ -60,13 +60,16 @@ def truncate_addresses(self):
6060
return
6161
addresses = self.address_list
6262
# +1 stands for the character added in self._format_address()
63-
while len('; '.join(addresses))+1 > max_length:
63+
while len(';'.join(addresses)) + 2 > max_length:
6464
addresses.pop()
65-
self.addresses = '; '.join(addresses)
65+
self.addresses = ';'.join(addresses)
6666

6767
@cached_property
6868
def address_list(self):
69-
return self.addresses.replace(' ', '')[0:-1].split(';')
69+
addresses = self.addresses.replace(' ', '')
70+
if addresses.startswith(';'):
71+
addresses = addresses[1:]
72+
return addresses[0:-1].split(';')
7073

7174
@property
7275
def netjson_id(self):
@@ -107,7 +110,7 @@ def get_from_address(cls, address, topology):
107110
:param topology: Topology instance
108111
:returns: Node object or None
109112
"""
110-
address = '{0};'.format(address)
113+
address = ';{0};'.format(address)
111114
return cls.objects.filter(topology=topology,
112115
addresses__contains=address).first()
113116

@@ -119,6 +122,6 @@ def count_address(cls, address, topology):
119122
:param topology: Topology instance
120123
:returns: int
121124
"""
122-
address = '{0};'.format(address)
125+
address = ';{0};'.format(address)
123126
return cls.objects.filter(topology=topology,
124127
addresses__contains=address).count()

django_netjsongraph/tests/base/test_node.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def test_node_address_list_single(self):
2121
properties=None)
2222
n.full_clean()
2323
n.save()
24-
self.assertEqual(n.addresses, '192.168.0.1;')
24+
self.assertEqual(n.addresses, ';192.168.0.1;')
2525
self.assertEqual(n.address_list, ['192.168.0.1'])
2626

2727
def test_node_address_list_semicolon(self):
@@ -30,7 +30,7 @@ def test_node_address_list_semicolon(self):
3030
addresses='192.168.0.1;')
3131
n.full_clean()
3232
n.save()
33-
self.assertEqual(n.addresses, '192.168.0.1;')
33+
self.assertEqual(n.addresses, ';192.168.0.1;')
3434
self.assertEqual(n.address_list, ['192.168.0.1'])
3535

3636
def test_node_address_list_multiple(self):
@@ -39,8 +39,10 @@ def test_node_address_list_multiple(self):
3939
addresses='192.168.0.1; 10.0.0.1,10.0.0.2;10.0.0.3')
4040
n.full_clean()
4141
n.save()
42-
self.assertEqual(n.addresses, '192.168.0.1; 10.0.0.1; '
43-
'10.0.0.2; 10.0.0.3;')
42+
# repeat _format_addresses() to ensure idempotency
43+
n._format_addresses()
44+
self.assertEqual(n.addresses, ';192.168.0.1;10.0.0.1;'
45+
'10.0.0.2;10.0.0.3;')
4446
self.assertEqual(n.address_list, ['192.168.0.1',
4547
'10.0.0.1',
4648
'10.0.0.2',
@@ -63,7 +65,7 @@ def test_node_name(self):
6365
def test_json(self):
6466
t = self.topology_model.objects.first()
6567
n = t._create_node(label='test node',
66-
addresses='192.168.0.1;10.0.0.1;',
68+
addresses=';192.168.0.1;10.0.0.1;',
6769
properties='{"gateway": true}')
6870
self.assertEqual(dict(n.json(dict=True)), {
6971
'id': '192.168.0.1',
@@ -80,13 +82,24 @@ def test_json(self):
8082
def test_get_from_address(self):
8183
t = self.topology_model.objects.first()
8284
n = t._create_node(addresses='192.168.0.1,10.0.0.1')
85+
n.full_clean()
8386
n.save()
8487
self.assertIsInstance(self.node_model.get_from_address('192.168.0.1', t), self.node_model)
8588
self.assertIsInstance(self.node_model.get_from_address('10.0.0.1', t), self.node_model)
8689
self.assertIsNone(self.node_model.get_from_address('wrong', t))
8790

8891
def test_count_address(self):
8992
t = self.topology_model.objects.first()
90-
t._create_node(addresses='192.168.0.1,10.0.0.1')
9193
self.assertEqual(self.node_model.count_address('192.168.0.1', t), 1)
9294
self.assertEqual(self.node_model.count_address('0.0.0.0', t), 0)
95+
96+
def test_count_address_issue_58(self):
97+
t = self.topology_model.objects.first()
98+
n1 = t._create_node(addresses='Benz_Kalloni')
99+
n1.full_clean()
100+
n1.save()
101+
n2 = t._create_node(addresses='Kalloni')
102+
n2.full_clean()
103+
n2.save()
104+
self.assertEqual(self.node_model.count_address('Benz_Kalloni', t), 1)
105+
self.assertEqual(self.node_model.count_address('Kalloni', t), 1)

django_netjsongraph/tests/base/test_topology.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ def test_very_long_addresses(self):
378378
data = self._load('static/very-long-addresses.json')
379379
t.receive(data)
380380
n = self.node_model.get_from_address('2001:4e12:452a:1:172::10', t)
381-
self.assertEqual(len(n.addresses), 485)
381+
self.assertEqual(len(n.addresses), 493)
382382

383383
def test_save_snapshot(self):
384384
t = self._set_receive()
@@ -403,3 +403,12 @@ def test_label_addition(self):
403403
self.assertIn('Syskrack', labels)
404404
self.assertIn('Kali-Matera', labels)
405405
self.assertIn('pomezia', labels)
406+
407+
def test_issue_58(self):
408+
self.node_model.objects.all().delete()
409+
self.link_model.objects.all().delete()
410+
t = self._set_receive()
411+
data = self._load('static/issue-58.json')
412+
t.receive(data)
413+
self.assertEqual(t.node_set.all().count(), 13)
414+
self.assertEqual(t.link_set.all().count(), 11)
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
{
2+
"router_id": "Own AS not provided",
3+
"version": "",
4+
"protocol": "BGP",
5+
"links": [
6+
{
7+
"source": "sv1gsd",
8+
"cost": 1.0,
9+
"target": "downlots3"
10+
},
11+
{
12+
"source": "sv1gsd",
13+
"cost": 1.0,
14+
"target": "SV1CIM-SOFIKO-SV1GSD"
15+
},
16+
{
17+
"source": "sofiko_WNK",
18+
"cost": 1.0,
19+
"target": "Geolos"
20+
},
21+
{
22+
"source": "Kalloni",
23+
"cost": 1.0,
24+
"target": "Benz_Kalloni_2"
25+
},
26+
{
27+
"source": "sv1gsd",
28+
"cost": 1.0,
29+
"target": "SV1EGD"
30+
},
31+
{
32+
"source": "sv1gsd_2",
33+
"cost": 1.0,
34+
"target": "SV1CIM-SOFIKO-SV1GSD"
35+
},
36+
{
37+
"source": "Kalloni",
38+
"cost": 1.0,
39+
"target": "Metamorfosi"
40+
},
41+
{
42+
"source": "Kalloni",
43+
"cost": 1.0,
44+
"target": "Benz_Kalloni"
45+
},
46+
{
47+
"source": "sofiko_WNK",
48+
"cost": 1.0,
49+
"target": "Sv1gyk-Sofiko"
50+
},
51+
{
52+
"source": "Kalloni",
53+
"cost": 1.0,
54+
"target": "Taktikoupoli"
55+
},
56+
{
57+
"source": "sofiko_WNK",
58+
"cost": 1.0,
59+
"target": "SV1CIM-SOFIKO-SV1GSD"
60+
}
61+
],
62+
"metric": "eBGP",
63+
"type": "NetworkGraph",
64+
"nodes": [
65+
{"id": "Sv1gyk-Sofiko"},
66+
{"id": "Kalloni"},
67+
{"id": "sv1gsd"},
68+
{"id": "Benz_Kalloni_2"},
69+
{"id": "Metamorfosi"},
70+
{"id": "Taktikoupoli"},
71+
{"id": "SV1EGD"},
72+
{"id": "downlots3"},
73+
{"id": "Geolos"},
74+
{"id": "SV1CIM-SOFIKO-SV1GSD"},
75+
{"id": "sv1gsd_2"},
76+
{"id": "sofiko_WNK"},
77+
{"id": "Benz_Kalloni"}
78+
]
79+
}

django_netjsongraph/tests/static/very-long-addresses.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"nodes": [
77
{
88
"id": "2001:4e12:452a:1:172::10",
9+
"label": "very-long-test-node1",
910
"local_addresses": [
1011
"2001:4e12:452a:1:177::4",
1112
"2001:4e12:452a:1:177::3",
@@ -33,7 +34,8 @@
3334
]
3435
},
3536
{
36-
"id": "2001:4e12:452a:1:172::11"
37+
"id": "2001:4e12:452a:1:172::11",
38+
"label": "very-long-test-node1"
3739
}
3840
],
3941
"links": [

django_netjsongraph/tests/test_node.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
class TestNode(TestNodeMixin, CreateGraphObjectsMixin, TestCase):
99
topology_model = Topology
1010
node_model = Node
11-
maxDiff = 0
11+
maxDiff = None
1212

1313
def setUp(self):
1414
t = self._create_topology()

0 commit comments

Comments
 (0)