class PathTest(unittest.TestCase): def setUp(self): self.id = 'R1' self.engine = PathEngine(self) def log(self, level, text): pass def test_topology1(self): """ +====+ +----+ +----+ | R1 |------| R2 |------| R3 | +====+ +----+ +----+ """ collection = { 'R1': LinkState(None, 'R1', 1, {'R2':1}), 'R2': LinkState(None, 'R2', 1, {'R1':1, 'R3':1}), 'R3': LinkState(None, 'R3', 1, {'R2':1}) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 2) self.assertEqual(next_hops['R2'], 'R2') self.assertEqual(next_hops['R3'], 'R2') valid_origins['R2'].sort() valid_origins['R3'].sort() self.assertEqual(valid_origins['R2'], []) self.assertEqual(valid_origins['R3'], []) self.assertEqual(radius, 2) def test_topology2(self): """ +====+ +----+ +----+ | R1 |------| R2 |------| R4 | +====+ +----+ +----+ | | +----+ +----+ +----+ | R3 |------| R5 |------| R6 | +----+ +----+ +----+ """ collection = { 'R1': LinkState(None, 'R1', 1, {'R2':1}), 'R2': LinkState(None, 'R2', 1, {'R1':1, 'R3':1, 'R4':1}), 'R3': LinkState(None, 'R3', 1, {'R2':1, 'R5':1}), 'R4': LinkState(None, 'R4', 1, {'R2':1, 'R5':1}), 'R5': LinkState(None, 'R5', 1, {'R3':1, 'R4':1, 'R6':1}), 'R6': LinkState(None, 'R6', 1, {'R5':1}) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 5) self.assertEqual(next_hops['R2'], 'R2') self.assertEqual(next_hops['R3'], 'R2') self.assertEqual(next_hops['R4'], 'R2') self.assertEqual(next_hops['R5'], 'R2') self.assertEqual(next_hops['R6'], 'R2') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() self.assertEqual(valid_origins['R2'], []) self.assertEqual(valid_origins['R3'], []) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], []) self.assertEqual(valid_origins['R6'], []) self.assertEqual(radius, 4) def test_topology3(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ | | +====+ +----+ +----+ | R1 |------| R5 |------| R6 | +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, {'R3':1}), 'R3': LinkState(None, 'R3', 1, {'R1':1, 'R2':1, 'R4':1}), 'R4': LinkState(None, 'R4', 1, {'R3':1, 'R5':1}), 'R1': LinkState(None, 'R1', 1, {'R3':1, 'R5':1}), 'R5': LinkState(None, 'R5', 1, {'R1':1, 'R4':1, 'R6':1}), 'R6': LinkState(None, 'R6', 1, {'R5':1}) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 5) self.assertEqual(next_hops['R2'], 'R3') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() self.assertEqual(valid_origins['R2'], ['R5', 'R6']) self.assertEqual(valid_origins['R3'], ['R5', 'R6']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3']) self.assertEqual(valid_origins['R6'], ['R2', 'R3']) self.assertEqual(radius, 2) def test_topology4(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ | | +====+ +----+ +----+ | R1 |------| R5 |------| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, {'R3':1}), 'R3': LinkState(None, 'R3', 1, {'R1':1, 'R2':1, 'R4':1}), 'R4': LinkState(None, 'R4', 1, {'R3':1, 'R5':1}), 'R1': LinkState(None, 'R1', 1, {'R3':1, 'R5':1}), 'R5': LinkState(None, 'R5', 1, {'R1':1, 'R4':1, 'R6':1}), 'R6': LinkState(None, 'R6', 1, {'R5':1, 'R7':1}) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R3') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') self.assertEqual(next_hops['R7'], 'R5') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() valid_origins['R7'].sort() self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3']) self.assertEqual(valid_origins['R6'], ['R2', 'R3']) self.assertEqual(valid_origins['R7'], ['R2', 'R3']) self.assertEqual(radius, 3) def test_topology5(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ | | | | +====+ +----+ +----+ +--------| R1 |------| R5 |------| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, {'R3':1, 'R1':1}), 'R3': LinkState(None, 'R3', 1, {'R1':1, 'R2':1, 'R4':1}), 'R4': LinkState(None, 'R4', 1, {'R3':1, 'R5':1}), 'R1': LinkState(None, 'R1', 1, {'R3':1, 'R5':1, 'R2':1}), 'R5': LinkState(None, 'R5', 1, {'R1':1, 'R4':1, 'R6':1}), 'R6': LinkState(None, 'R6', 1, {'R5':1, 'R7':1}) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R2') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') self.assertEqual(next_hops['R7'], 'R5') self.assertEqual(costs['R2'], 1) self.assertEqual(costs['R3'], 1) self.assertEqual(costs['R4'], 2) self.assertEqual(costs['R5'], 1) self.assertEqual(costs['R6'], 2) self.assertEqual(costs['R7'], 3) valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() valid_origins['R7'].sort() self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3']) self.assertEqual(valid_origins['R6'], ['R2', 'R3']) self.assertEqual(valid_origins['R7'], ['R2', 'R3']) self.assertEqual(radius, 3) def test_topology5_with_asymmetry1(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ ^ | | ^ +====+ +----+ +----+ +-<-<-<--| R1 |------| R5 |------| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, {'R3':1}), 'R3': LinkState(None, 'R3', 1, {'R1':1, 'R2':1, 'R4':1}), 'R4': LinkState(None, 'R4', 1, {'R3':1, 'R5':1}), 'R1': LinkState(None, 'R1', 1, {'R3':1, 'R5':1, 'R2':1}), 'R5': LinkState(None, 'R5', 1, {'R1':1, 'R4':1, 'R6':1}), 'R6': LinkState(None, 'R6', 1, {'R5':1, 'R7':1}) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R2') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') self.assertEqual(next_hops['R7'], 'R5') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() valid_origins['R7'].sort() self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3']) self.assertEqual(valid_origins['R6'], ['R2', 'R3']) self.assertEqual(valid_origins['R7'], ['R2', 'R3']) self.assertEqual(radius, 3) def test_topology5_with_asymmetry2(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ v | | v +====+ +----+ +----+ +->->->->| R1 |------| R5 |------| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, {'R3':1, 'R1':1}), 'R3': LinkState(None, 'R3', 1, {'R1':1, 'R2':1, 'R4':1}), 'R4': LinkState(None, 'R4', 1, {'R3':1, 'R5':1}), 'R1': LinkState(None, 'R1', 1, {'R3':1, 'R5':1}), 'R5': LinkState(None, 'R5', 1, {'R1':1, 'R4':1, 'R6':1}), 'R6': LinkState(None, 'R6', 1, {'R5':1, 'R7':1}) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R3') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') self.assertEqual(next_hops['R7'], 'R5') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() valid_origins['R7'].sort() self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3']) self.assertEqual(valid_origins['R6'], ['R2', 'R3']) self.assertEqual(valid_origins['R7'], ['R2', 'R3']) self.assertEqual(radius, 3) def test_topology5_with_asymmetry3(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ v | | v +====+ +----+ +----+ +->->->->| R1 |------| R5 |<-<-<-| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, {'R3':1, 'R1':1}), 'R3': LinkState(None, 'R3', 1, {'R1':1, 'R2':1, 'R4':1}), 'R4': LinkState(None, 'R4', 1, {'R3':1, 'R5':1}), 'R1': LinkState(None, 'R1', 1, {'R3':1, 'R5':1}), 'R5': LinkState(None, 'R5', 1, {'R1':1, 'R4':1}), 'R6': LinkState(None, 'R6', 1, {'R5':1, 'R7':1}) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 4) self.assertEqual(next_hops['R2'], 'R3') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() self.assertEqual(valid_origins['R2'], ['R5']) self.assertEqual(valid_origins['R3'], ['R5']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3']) self.assertEqual(radius, 2) def test_topology5_with_costs1(self): """ +----+ +----+ +----+ | R2 |--4---| R3 |---4--| R4 | +----+ +----+ +----+ | | | | 3 5 | | | | +====+ +----+ +----+ +--20----| R1 |--10--| R5 |--2---| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, {'R3':4, 'R1':20}), 'R3': LinkState(None, 'R3', 1, {'R1':3, 'R2':4, 'R4':4}), 'R4': LinkState(None, 'R4', 1, {'R3':4, 'R5':5}), 'R1': LinkState(None, 'R1', 1, {'R3':3, 'R5':10, 'R2':20}), 'R5': LinkState(None, 'R5', 1, {'R1':10, 'R4':5, 'R6':2}), 'R6': LinkState(None, 'R6', 1, {'R5':2, 'R7':1}) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R3') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') self.assertEqual(next_hops['R7'], 'R5') self.assertEqual(costs['R2'], 7) self.assertEqual(costs['R3'], 3) self.assertEqual(costs['R4'], 7) self.assertEqual(costs['R5'], 10) self.assertEqual(costs['R6'], 12) self.assertEqual(costs['R7'], 13) valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() valid_origins['R7'].sort() self.assertEqual(valid_origins['R2'], []) self.assertEqual(valid_origins['R3'], []) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], []) self.assertEqual(valid_origins['R6'], []) self.assertEqual(valid_origins['R7'], []) self.assertEqual(radius, 3) def test_topology5_with_costs2(self): """ +----+ +----+ +----+ | R2 |--4---| R3 |---4--| R4 | +----+ +----+ +----+ | | | | 100 100 | | | | +====+ +----+ +----+ +---5----| R1 |--10--| R5 |--2---| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, {'R3':4, 'R1':5}), 'R3': LinkState(None, 'R3', 1, {'R1':100, 'R2':4, 'R4':4}), 'R4': LinkState(None, 'R4', 1, {'R3':4, 'R5':100}), 'R1': LinkState(None, 'R1', 1, {'R3':100, 'R5':10, 'R2':5}), 'R5': LinkState(None, 'R5', 1, {'R1':10, 'R4':100, 'R6':2}), 'R6': LinkState(None, 'R6', 1, {'R5':2, 'R7':1}) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R2') self.assertEqual(next_hops['R3'], 'R2') self.assertEqual(next_hops['R4'], 'R2') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') self.assertEqual(next_hops['R7'], 'R5') self.assertEqual(costs['R2'], 5) self.assertEqual(costs['R3'], 9) self.assertEqual(costs['R4'], 13) self.assertEqual(costs['R5'], 10) self.assertEqual(costs['R6'], 12) self.assertEqual(costs['R7'], 13) valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() valid_origins['R7'].sort() self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R4'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R5'], ['R2', 'R3', 'R4']) self.assertEqual(valid_origins['R6'], ['R2', 'R3', 'R4']) self.assertEqual(valid_origins['R7'], ['R2', 'R3', 'R4']) self.assertEqual(radius, 3) def test_topology6_path_vs_valid_origin(self): """ +====+ +====+ +----+ | R1 |--10--| R3 |--10--| R5 | +====+ +====+ +----+ | | | 1 10 1 | | | +----+ +----+ +----+ | R2 |--10--| R4 |--10--| R6 | +----+ +----+ +----+ """ collection = { 'R1': LinkState(None, 'R1', 1, {'R2':1, 'R3':10}), 'R2': LinkState(None, 'R2', 1, {'R1':1, 'R4':10}), 'R3': LinkState(None, 'R3', 1, {'R1':10, 'R4':10, 'R5':10}), 'R4': LinkState(None, 'R4', 1, {'R2':10, 'R3':10, 'R6':10}), 'R5': LinkState(None, 'R5', 1, {'R3':10, 'R6':1}), 'R6': LinkState(None, 'R6', 1, {'R4':10, 'R5':1}) } self.id = 'R3' self.engine = PathEngine(self) r3_next_hops, r3_costs, r3_valid_origins, r3_radius = self.engine.calculate_routes(collection) self.id = 'R1' self.engine = PathEngine(self) r1_next_hops, r1_costs, r1_valid_origins, r1_radius = self.engine.calculate_routes(collection) self.assertEqual(r1_next_hops['R6'], 'R2') self.assertEqual(r3_valid_origins['R6'], []) self.assertEqual(r1_radius, 3) self.assertEqual(r3_radius, 2)
class PathTest(unittest.TestCase): def setUp(self): self.id = "R1" self.engine = PathEngine(self) def log(self, level, text): pass def test_topology1(self): """ +====+ +----+ +----+ | R1 |------| R2 |------| R3 | +====+ +----+ +----+ """ collection = { "R1": LinkState(None, "R1", 1, {"R2": 1}), "R2": LinkState(None, "R2", 1, {"R1": 1, "R3": 1}), "R3": LinkState(None, "R3", 1, {"R2": 1}), } next_hops, costs, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 2) self.assertEqual(next_hops["R2"], "R2") self.assertEqual(next_hops["R3"], "R2") valid_origins["R2"].sort() valid_origins["R3"].sort() self.assertEqual(valid_origins["R2"], []) self.assertEqual(valid_origins["R3"], []) def test_topology2(self): """ +====+ +----+ +----+ | R1 |------| R2 |------| R4 | +====+ +----+ +----+ | | +----+ +----+ +----+ | R3 |------| R5 |------| R6 | +----+ +----+ +----+ """ collection = { "R1": LinkState(None, "R1", 1, {"R2": 1}), "R2": LinkState(None, "R2", 1, {"R1": 1, "R3": 1, "R4": 1}), "R3": LinkState(None, "R3", 1, {"R2": 1, "R5": 1}), "R4": LinkState(None, "R4", 1, {"R2": 1, "R5": 1}), "R5": LinkState(None, "R5", 1, {"R3": 1, "R4": 1, "R6": 1}), "R6": LinkState(None, "R6", 1, {"R5": 1}), } next_hops, costs, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 5) self.assertEqual(next_hops["R2"], "R2") self.assertEqual(next_hops["R3"], "R2") self.assertEqual(next_hops["R4"], "R2") self.assertEqual(next_hops["R5"], "R2") self.assertEqual(next_hops["R6"], "R2") valid_origins["R2"].sort() valid_origins["R3"].sort() valid_origins["R4"].sort() valid_origins["R5"].sort() valid_origins["R6"].sort() self.assertEqual(valid_origins["R2"], []) self.assertEqual(valid_origins["R3"], []) self.assertEqual(valid_origins["R4"], []) self.assertEqual(valid_origins["R5"], []) self.assertEqual(valid_origins["R6"], []) def test_topology3(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ | | +====+ +----+ +----+ | R1 |------| R5 |------| R6 | +====+ +----+ +----+ """ collection = { "R2": LinkState(None, "R2", 1, {"R3": 1}), "R3": LinkState(None, "R3", 1, {"R1": 1, "R2": 1, "R4": 1}), "R4": LinkState(None, "R4", 1, {"R3": 1, "R5": 1}), "R1": LinkState(None, "R1", 1, {"R3": 1, "R5": 1}), "R5": LinkState(None, "R5", 1, {"R1": 1, "R4": 1, "R6": 1}), "R6": LinkState(None, "R6", 1, {"R5": 1}), } next_hops, costs, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 5) self.assertEqual(next_hops["R2"], "R3") self.assertEqual(next_hops["R3"], "R3") self.assertEqual(next_hops["R4"], "R3") self.assertEqual(next_hops["R5"], "R5") self.assertEqual(next_hops["R6"], "R5") valid_origins["R2"].sort() valid_origins["R3"].sort() valid_origins["R4"].sort() valid_origins["R5"].sort() valid_origins["R6"].sort() self.assertEqual(valid_origins["R2"], ["R5", "R6"]) self.assertEqual(valid_origins["R3"], ["R5", "R6"]) self.assertEqual(valid_origins["R4"], []) self.assertEqual(valid_origins["R5"], ["R2", "R3"]) self.assertEqual(valid_origins["R6"], ["R2", "R3"]) def test_topology4(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ | | +====+ +----+ +----+ | R1 |------| R5 |------| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { "R2": LinkState(None, "R2", 1, {"R3": 1}), "R3": LinkState(None, "R3", 1, {"R1": 1, "R2": 1, "R4": 1}), "R4": LinkState(None, "R4", 1, {"R3": 1, "R5": 1}), "R1": LinkState(None, "R1", 1, {"R3": 1, "R5": 1}), "R5": LinkState(None, "R5", 1, {"R1": 1, "R4": 1, "R6": 1}), "R6": LinkState(None, "R6", 1, {"R5": 1, "R7": 1}), } next_hops, costs, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops["R2"], "R3") self.assertEqual(next_hops["R3"], "R3") self.assertEqual(next_hops["R4"], "R3") self.assertEqual(next_hops["R5"], "R5") self.assertEqual(next_hops["R6"], "R5") self.assertEqual(next_hops["R7"], "R5") valid_origins["R2"].sort() valid_origins["R3"].sort() valid_origins["R4"].sort() valid_origins["R5"].sort() valid_origins["R6"].sort() valid_origins["R7"].sort() self.assertEqual(valid_origins["R2"], ["R5", "R6", "R7"]) self.assertEqual(valid_origins["R3"], ["R5", "R6", "R7"]) self.assertEqual(valid_origins["R4"], []) self.assertEqual(valid_origins["R5"], ["R2", "R3"]) self.assertEqual(valid_origins["R6"], ["R2", "R3"]) self.assertEqual(valid_origins["R7"], ["R2", "R3"]) def test_topology5(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ | | | | +====+ +----+ +----+ +--------| R1 |------| R5 |------| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { "R2": LinkState(None, "R2", 1, {"R3": 1, "R1": 1}), "R3": LinkState(None, "R3", 1, {"R1": 1, "R2": 1, "R4": 1}), "R4": LinkState(None, "R4", 1, {"R3": 1, "R5": 1}), "R1": LinkState(None, "R1", 1, {"R3": 1, "R5": 1, "R2": 1}), "R5": LinkState(None, "R5", 1, {"R1": 1, "R4": 1, "R6": 1}), "R6": LinkState(None, "R6", 1, {"R5": 1, "R7": 1}), } next_hops, costs, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops["R2"], "R2") self.assertEqual(next_hops["R3"], "R3") self.assertEqual(next_hops["R4"], "R3") self.assertEqual(next_hops["R5"], "R5") self.assertEqual(next_hops["R6"], "R5") self.assertEqual(next_hops["R7"], "R5") self.assertEqual(costs["R2"], 1) self.assertEqual(costs["R3"], 1) self.assertEqual(costs["R4"], 2) self.assertEqual(costs["R5"], 1) self.assertEqual(costs["R6"], 2) self.assertEqual(costs["R7"], 3) valid_origins["R2"].sort() valid_origins["R3"].sort() valid_origins["R4"].sort() valid_origins["R5"].sort() valid_origins["R6"].sort() valid_origins["R7"].sort() self.assertEqual(valid_origins["R2"], ["R5", "R6", "R7"]) self.assertEqual(valid_origins["R3"], ["R5", "R6", "R7"]) self.assertEqual(valid_origins["R4"], []) self.assertEqual(valid_origins["R5"], ["R2", "R3"]) self.assertEqual(valid_origins["R6"], ["R2", "R3"]) self.assertEqual(valid_origins["R7"], ["R2", "R3"]) def test_topology5_with_asymmetry1(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ ^ | | ^ +====+ +----+ +----+ +-<-<-<--| R1 |------| R5 |------| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { "R2": LinkState(None, "R2", 1, {"R3": 1}), "R3": LinkState(None, "R3", 1, {"R1": 1, "R2": 1, "R4": 1}), "R4": LinkState(None, "R4", 1, {"R3": 1, "R5": 1}), "R1": LinkState(None, "R1", 1, {"R3": 1, "R5": 1, "R2": 1}), "R5": LinkState(None, "R5", 1, {"R1": 1, "R4": 1, "R6": 1}), "R6": LinkState(None, "R6", 1, {"R5": 1, "R7": 1}), } next_hops, costs, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops["R2"], "R2") self.assertEqual(next_hops["R3"], "R3") self.assertEqual(next_hops["R4"], "R3") self.assertEqual(next_hops["R5"], "R5") self.assertEqual(next_hops["R6"], "R5") self.assertEqual(next_hops["R7"], "R5") valid_origins["R2"].sort() valid_origins["R3"].sort() valid_origins["R4"].sort() valid_origins["R5"].sort() valid_origins["R6"].sort() valid_origins["R7"].sort() self.assertEqual(valid_origins["R2"], ["R5", "R6", "R7"]) self.assertEqual(valid_origins["R3"], ["R5", "R6", "R7"]) self.assertEqual(valid_origins["R4"], []) self.assertEqual(valid_origins["R5"], ["R2", "R3"]) self.assertEqual(valid_origins["R6"], ["R2", "R3"]) self.assertEqual(valid_origins["R7"], ["R2", "R3"]) def test_topology5_with_asymmetry2(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ v | | v +====+ +----+ +----+ +->->->->| R1 |------| R5 |------| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { "R2": LinkState(None, "R2", 1, {"R3": 1, "R1": 1}), "R3": LinkState(None, "R3", 1, {"R1": 1, "R2": 1, "R4": 1}), "R4": LinkState(None, "R4", 1, {"R3": 1, "R5": 1}), "R1": LinkState(None, "R1", 1, {"R3": 1, "R5": 1}), "R5": LinkState(None, "R5", 1, {"R1": 1, "R4": 1, "R6": 1}), "R6": LinkState(None, "R6", 1, {"R5": 1, "R7": 1}), } next_hops, costs, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops["R2"], "R3") self.assertEqual(next_hops["R3"], "R3") self.assertEqual(next_hops["R4"], "R3") self.assertEqual(next_hops["R5"], "R5") self.assertEqual(next_hops["R6"], "R5") self.assertEqual(next_hops["R7"], "R5") valid_origins["R2"].sort() valid_origins["R3"].sort() valid_origins["R4"].sort() valid_origins["R5"].sort() valid_origins["R6"].sort() valid_origins["R7"].sort() self.assertEqual(valid_origins["R2"], ["R5", "R6", "R7"]) self.assertEqual(valid_origins["R3"], ["R5", "R6", "R7"]) self.assertEqual(valid_origins["R4"], []) self.assertEqual(valid_origins["R5"], ["R2", "R3"]) self.assertEqual(valid_origins["R6"], ["R2", "R3"]) self.assertEqual(valid_origins["R7"], ["R2", "R3"]) def test_topology5_with_asymmetry3(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ v | | v +====+ +----+ +----+ +->->->->| R1 |------| R5 |<-<-<-| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { "R2": LinkState(None, "R2", 1, {"R3": 1, "R1": 1}), "R3": LinkState(None, "R3", 1, {"R1": 1, "R2": 1, "R4": 1}), "R4": LinkState(None, "R4", 1, {"R3": 1, "R5": 1}), "R1": LinkState(None, "R1", 1, {"R3": 1, "R5": 1}), "R5": LinkState(None, "R5", 1, {"R1": 1, "R4": 1}), "R6": LinkState(None, "R6", 1, {"R5": 1, "R7": 1}), } next_hops, costs, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 4) self.assertEqual(next_hops["R2"], "R3") self.assertEqual(next_hops["R3"], "R3") self.assertEqual(next_hops["R4"], "R3") self.assertEqual(next_hops["R5"], "R5") valid_origins["R2"].sort() valid_origins["R3"].sort() valid_origins["R4"].sort() valid_origins["R5"].sort() self.assertEqual(valid_origins["R2"], ["R5"]) self.assertEqual(valid_origins["R3"], ["R5"]) self.assertEqual(valid_origins["R4"], []) self.assertEqual(valid_origins["R5"], ["R2", "R3"]) def test_topology5_with_costs1(self): """ +----+ +----+ +----+ | R2 |--4---| R3 |---4--| R4 | +----+ +----+ +----+ | | | | 3 5 | | | | +====+ +----+ +----+ +--20----| R1 |--10--| R5 |--2---| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { "R2": LinkState(None, "R2", 1, {"R3": 4, "R1": 20}), "R3": LinkState(None, "R3", 1, {"R1": 3, "R2": 4, "R4": 4}), "R4": LinkState(None, "R4", 1, {"R3": 4, "R5": 5}), "R1": LinkState(None, "R1", 1, {"R3": 3, "R5": 10, "R2": 20}), "R5": LinkState(None, "R5", 1, {"R1": 10, "R4": 5, "R6": 2}), "R6": LinkState(None, "R6", 1, {"R5": 2, "R7": 1}), } next_hops, costs, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops["R2"], "R3") self.assertEqual(next_hops["R3"], "R3") self.assertEqual(next_hops["R4"], "R3") self.assertEqual(next_hops["R5"], "R5") self.assertEqual(next_hops["R6"], "R5") self.assertEqual(next_hops["R7"], "R5") self.assertEqual(costs["R2"], 7) self.assertEqual(costs["R3"], 3) self.assertEqual(costs["R4"], 7) self.assertEqual(costs["R5"], 10) self.assertEqual(costs["R6"], 12) self.assertEqual(costs["R7"], 13) valid_origins["R2"].sort() valid_origins["R3"].sort() valid_origins["R4"].sort() valid_origins["R5"].sort() valid_origins["R6"].sort() valid_origins["R7"].sort() self.assertEqual(valid_origins["R2"], []) self.assertEqual(valid_origins["R3"], []) self.assertEqual(valid_origins["R4"], []) self.assertEqual(valid_origins["R5"], []) self.assertEqual(valid_origins["R6"], []) self.assertEqual(valid_origins["R7"], []) def test_topology5_with_costs2(self): """ +----+ +----+ +----+ | R2 |--4---| R3 |---4--| R4 | +----+ +----+ +----+ | | | | 100 100 | | | | +====+ +----+ +----+ +---5----| R1 |--10--| R5 |--2---| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { "R2": LinkState(None, "R2", 1, {"R3": 4, "R1": 5}), "R3": LinkState(None, "R3", 1, {"R1": 100, "R2": 4, "R4": 4}), "R4": LinkState(None, "R4", 1, {"R3": 4, "R5": 100}), "R1": LinkState(None, "R1", 1, {"R3": 100, "R5": 10, "R2": 5}), "R5": LinkState(None, "R5", 1, {"R1": 10, "R4": 100, "R6": 2}), "R6": LinkState(None, "R6", 1, {"R5": 2, "R7": 1}), } next_hops, costs, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops["R2"], "R2") self.assertEqual(next_hops["R3"], "R2") self.assertEqual(next_hops["R4"], "R2") self.assertEqual(next_hops["R5"], "R5") self.assertEqual(next_hops["R6"], "R5") self.assertEqual(next_hops["R7"], "R5") self.assertEqual(costs["R2"], 5) self.assertEqual(costs["R3"], 9) self.assertEqual(costs["R4"], 13) self.assertEqual(costs["R5"], 10) self.assertEqual(costs["R6"], 12) self.assertEqual(costs["R7"], 13) valid_origins["R2"].sort() valid_origins["R3"].sort() valid_origins["R4"].sort() valid_origins["R5"].sort() valid_origins["R6"].sort() valid_origins["R7"].sort() self.assertEqual(valid_origins["R2"], ["R5", "R6", "R7"]) self.assertEqual(valid_origins["R3"], ["R5", "R6", "R7"]) self.assertEqual(valid_origins["R4"], ["R5", "R6", "R7"]) self.assertEqual(valid_origins["R5"], ["R2", "R3", "R4"]) self.assertEqual(valid_origins["R6"], ["R2", "R3", "R4"]) self.assertEqual(valid_origins["R7"], ["R2", "R3", "R4"]) def test_topology6_path_vs_valid_origin(self): """ +====+ +====+ +----+ | R1 |--10--| R3 |--10--| R5 | +====+ +====+ +----+ | | | 1 10 1 | | | +----+ +----+ +----+ | R2 |--10--| R4 |--10--| R6 | +----+ +----+ +----+ """ collection = { "R1": LinkState(None, "R1", 1, {"R2": 1, "R3": 10}), "R2": LinkState(None, "R2", 1, {"R1": 1, "R4": 10}), "R3": LinkState(None, "R3", 1, {"R1": 10, "R4": 10, "R5": 10}), "R4": LinkState(None, "R4", 1, {"R2": 10, "R3": 10, "R6": 10}), "R5": LinkState(None, "R5", 1, {"R3": 10, "R6": 1}), "R6": LinkState(None, "R6", 1, {"R4": 10, "R5": 1}), } self.id = "R3" self.engine = PathEngine(self) r3_next_hops, r3_costs, r3_valid_origins = self.engine.calculate_routes(collection) self.id = "R1" self.engine = PathEngine(self) r1_next_hops, r1_costs, r1_valid_origins = self.engine.calculate_routes(collection) self.assertEqual(r1_next_hops["R6"], "R2") self.assertEqual(r3_valid_origins["R6"], [])
class PathTest(unittest.TestCase): def setUp(self): self.id = 'R1' self.engine = PathEngine(self) def log(self, level, text): pass def test_topology1(self): """ +====+ +----+ +----+ | R1 |------| R2 |------| R3 | +====+ +----+ +----+ """ collection = { 'R1': LinkState(None, 'R1', 1, {'R2': 1}), 'R2': LinkState(None, 'R2', 1, { 'R1': 1, 'R3': 1 }), 'R3': LinkState(None, 'R3', 1, {'R2': 1}) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes( collection) self.assertEqual(len(next_hops), 2) self.assertEqual(next_hops['R2'], 'R2') self.assertEqual(next_hops['R3'], 'R2') valid_origins['R2'].sort() valid_origins['R3'].sort() self.assertEqual(valid_origins['R2'], []) self.assertEqual(valid_origins['R3'], []) self.assertEqual(radius, 2) def test_topology2(self): """ +====+ +----+ +----+ | R1 |------| R2 |------| R4 | +====+ +----+ +----+ | | +----+ +----+ +----+ | R3 |------| R5 |------| R6 | +----+ +----+ +----+ """ collection = { 'R1': LinkState(None, 'R1', 1, {'R2': 1}), 'R2': LinkState(None, 'R2', 1, { 'R1': 1, 'R3': 1, 'R4': 1 }), 'R3': LinkState(None, 'R3', 1, { 'R2': 1, 'R5': 1 }), 'R4': LinkState(None, 'R4', 1, { 'R2': 1, 'R5': 1 }), 'R5': LinkState(None, 'R5', 1, { 'R3': 1, 'R4': 1, 'R6': 1 }), 'R6': LinkState(None, 'R6', 1, {'R5': 1}) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes( collection) self.assertEqual(len(next_hops), 5) self.assertEqual(next_hops['R2'], 'R2') self.assertEqual(next_hops['R3'], 'R2') self.assertEqual(next_hops['R4'], 'R2') self.assertEqual(next_hops['R5'], 'R2') self.assertEqual(next_hops['R6'], 'R2') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() self.assertEqual(valid_origins['R2'], []) self.assertEqual(valid_origins['R3'], []) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], []) self.assertEqual(valid_origins['R6'], []) self.assertEqual(radius, 4) def test_topology3(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ | | +====+ +----+ +----+ | R1 |------| R5 |------| R6 | +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, {'R3': 1}), 'R3': LinkState(None, 'R3', 1, { 'R1': 1, 'R2': 1, 'R4': 1 }), 'R4': LinkState(None, 'R4', 1, { 'R3': 1, 'R5': 1 }), 'R1': LinkState(None, 'R1', 1, { 'R3': 1, 'R5': 1 }), 'R5': LinkState(None, 'R5', 1, { 'R1': 1, 'R4': 1, 'R6': 1 }), 'R6': LinkState(None, 'R6', 1, {'R5': 1}) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes( collection) self.assertEqual(len(next_hops), 5) self.assertEqual(next_hops['R2'], 'R3') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() self.assertEqual(valid_origins['R2'], ['R5', 'R6']) self.assertEqual(valid_origins['R3'], ['R5', 'R6']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3']) self.assertEqual(valid_origins['R6'], ['R2', 'R3']) self.assertEqual(radius, 2) def test_topology4(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ | | +====+ +----+ +----+ | R1 |------| R5 |------| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, {'R3': 1}), 'R3': LinkState(None, 'R3', 1, { 'R1': 1, 'R2': 1, 'R4': 1 }), 'R4': LinkState(None, 'R4', 1, { 'R3': 1, 'R5': 1 }), 'R1': LinkState(None, 'R1', 1, { 'R3': 1, 'R5': 1 }), 'R5': LinkState(None, 'R5', 1, { 'R1': 1, 'R4': 1, 'R6': 1 }), 'R6': LinkState(None, 'R6', 1, { 'R5': 1, 'R7': 1 }) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes( collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R3') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') self.assertEqual(next_hops['R7'], 'R5') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() valid_origins['R7'].sort() self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3']) self.assertEqual(valid_origins['R6'], ['R2', 'R3']) self.assertEqual(valid_origins['R7'], ['R2', 'R3']) self.assertEqual(radius, 3) def test_topology5(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ | | | | +====+ +----+ +----+ +--------| R1 |------| R5 |------| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, { 'R3': 1, 'R1': 1 }), 'R3': LinkState(None, 'R3', 1, { 'R1': 1, 'R2': 1, 'R4': 1 }), 'R4': LinkState(None, 'R4', 1, { 'R3': 1, 'R5': 1 }), 'R1': LinkState(None, 'R1', 1, { 'R3': 1, 'R5': 1, 'R2': 1 }), 'R5': LinkState(None, 'R5', 1, { 'R1': 1, 'R4': 1, 'R6': 1 }), 'R6': LinkState(None, 'R6', 1, { 'R5': 1, 'R7': 1 }) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes( collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R2') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') self.assertEqual(next_hops['R7'], 'R5') self.assertEqual(costs['R2'], 1) self.assertEqual(costs['R3'], 1) self.assertEqual(costs['R4'], 2) self.assertEqual(costs['R5'], 1) self.assertEqual(costs['R6'], 2) self.assertEqual(costs['R7'], 3) valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() valid_origins['R7'].sort() self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3']) self.assertEqual(valid_origins['R6'], ['R2', 'R3']) self.assertEqual(valid_origins['R7'], ['R2', 'R3']) self.assertEqual(radius, 3) def test_topology5_with_asymmetry1(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ ^ | | ^ +====+ +----+ +----+ +-<-<-<--| R1 |------| R5 |------| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, {'R3': 1}), 'R3': LinkState(None, 'R3', 1, { 'R1': 1, 'R2': 1, 'R4': 1 }), 'R4': LinkState(None, 'R4', 1, { 'R3': 1, 'R5': 1 }), 'R1': LinkState(None, 'R1', 1, { 'R3': 1, 'R5': 1, 'R2': 1 }), 'R5': LinkState(None, 'R5', 1, { 'R1': 1, 'R4': 1, 'R6': 1 }), 'R6': LinkState(None, 'R6', 1, { 'R5': 1, 'R7': 1 }) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes( collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R2') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') self.assertEqual(next_hops['R7'], 'R5') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() valid_origins['R7'].sort() self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3']) self.assertEqual(valid_origins['R6'], ['R2', 'R3']) self.assertEqual(valid_origins['R7'], ['R2', 'R3']) self.assertEqual(radius, 3) def test_topology5_with_asymmetry2(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ v | | v +====+ +----+ +----+ +->->->->| R1 |------| R5 |------| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, { 'R3': 1, 'R1': 1 }), 'R3': LinkState(None, 'R3', 1, { 'R1': 1, 'R2': 1, 'R4': 1 }), 'R4': LinkState(None, 'R4', 1, { 'R3': 1, 'R5': 1 }), 'R1': LinkState(None, 'R1', 1, { 'R3': 1, 'R5': 1 }), 'R5': LinkState(None, 'R5', 1, { 'R1': 1, 'R4': 1, 'R6': 1 }), 'R6': LinkState(None, 'R6', 1, { 'R5': 1, 'R7': 1 }) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes( collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R3') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') self.assertEqual(next_hops['R7'], 'R5') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() valid_origins['R7'].sort() self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3']) self.assertEqual(valid_origins['R6'], ['R2', 'R3']) self.assertEqual(valid_origins['R7'], ['R2', 'R3']) self.assertEqual(radius, 3) def test_topology5_with_asymmetry3(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ v | | v +====+ +----+ +----+ +->->->->| R1 |------| R5 |<-<-<-| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, { 'R3': 1, 'R1': 1 }), 'R3': LinkState(None, 'R3', 1, { 'R1': 1, 'R2': 1, 'R4': 1 }), 'R4': LinkState(None, 'R4', 1, { 'R3': 1, 'R5': 1 }), 'R1': LinkState(None, 'R1', 1, { 'R3': 1, 'R5': 1 }), 'R5': LinkState(None, 'R5', 1, { 'R1': 1, 'R4': 1 }), 'R6': LinkState(None, 'R6', 1, { 'R5': 1, 'R7': 1 }) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes( collection) self.assertEqual(len(next_hops), 4) self.assertEqual(next_hops['R2'], 'R3') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() self.assertEqual(valid_origins['R2'], ['R5']) self.assertEqual(valid_origins['R3'], ['R5']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3']) self.assertEqual(radius, 2) def test_topology5_with_costs1(self): """ +----+ +----+ +----+ | R2 |--4---| R3 |---4--| R4 | +----+ +----+ +----+ | | | | 3 5 | | | | +====+ +----+ +----+ +--20----| R1 |--10--| R5 |--2---| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, { 'R3': 4, 'R1': 20 }), 'R3': LinkState(None, 'R3', 1, { 'R1': 3, 'R2': 4, 'R4': 4 }), 'R4': LinkState(None, 'R4', 1, { 'R3': 4, 'R5': 5 }), 'R1': LinkState(None, 'R1', 1, { 'R3': 3, 'R5': 10, 'R2': 20 }), 'R5': LinkState(None, 'R5', 1, { 'R1': 10, 'R4': 5, 'R6': 2 }), 'R6': LinkState(None, 'R6', 1, { 'R5': 2, 'R7': 1 }) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes( collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R3') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') self.assertEqual(next_hops['R7'], 'R5') self.assertEqual(costs['R2'], 7) self.assertEqual(costs['R3'], 3) self.assertEqual(costs['R4'], 7) self.assertEqual(costs['R5'], 10) self.assertEqual(costs['R6'], 12) self.assertEqual(costs['R7'], 13) valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() valid_origins['R7'].sort() self.assertEqual(valid_origins['R2'], []) self.assertEqual(valid_origins['R3'], []) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], []) self.assertEqual(valid_origins['R6'], []) self.assertEqual(valid_origins['R7'], []) self.assertEqual(radius, 3) def test_topology5_with_costs2(self): """ +----+ +----+ +----+ | R2 |--4---| R3 |---4--| R4 | +----+ +----+ +----+ | | | | 100 100 | | | | +====+ +----+ +----+ +---5----| R1 |--10--| R5 |--2---| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, { 'R3': 4, 'R1': 5 }), 'R3': LinkState(None, 'R3', 1, { 'R1': 100, 'R2': 4, 'R4': 4 }), 'R4': LinkState(None, 'R4', 1, { 'R3': 4, 'R5': 100 }), 'R1': LinkState(None, 'R1', 1, { 'R3': 100, 'R5': 10, 'R2': 5 }), 'R5': LinkState(None, 'R5', 1, { 'R1': 10, 'R4': 100, 'R6': 2 }), 'R6': LinkState(None, 'R6', 1, { 'R5': 2, 'R7': 1 }) } next_hops, costs, valid_origins, radius = self.engine.calculate_routes( collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R2') self.assertEqual(next_hops['R3'], 'R2') self.assertEqual(next_hops['R4'], 'R2') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') self.assertEqual(next_hops['R7'], 'R5') self.assertEqual(costs['R2'], 5) self.assertEqual(costs['R3'], 9) self.assertEqual(costs['R4'], 13) self.assertEqual(costs['R5'], 10) self.assertEqual(costs['R6'], 12) self.assertEqual(costs['R7'], 13) valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() valid_origins['R7'].sort() self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R4'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R5'], ['R2', 'R3', 'R4']) self.assertEqual(valid_origins['R6'], ['R2', 'R3', 'R4']) self.assertEqual(valid_origins['R7'], ['R2', 'R3', 'R4']) self.assertEqual(radius, 3) def test_topology6_path_vs_valid_origin(self): """ +====+ +====+ +----+ | R1 |--10--| R3 |--10--| R5 | +====+ +====+ +----+ | | | 1 10 1 | | | +----+ +----+ +----+ | R2 |--10--| R4 |--10--| R6 | +----+ +----+ +----+ """ collection = { 'R1': LinkState(None, 'R1', 1, { 'R2': 1, 'R3': 10 }), 'R2': LinkState(None, 'R2', 1, { 'R1': 1, 'R4': 10 }), 'R3': LinkState(None, 'R3', 1, { 'R1': 10, 'R4': 10, 'R5': 10 }), 'R4': LinkState(None, 'R4', 1, { 'R2': 10, 'R3': 10, 'R6': 10 }), 'R5': LinkState(None, 'R5', 1, { 'R3': 10, 'R6': 1 }), 'R6': LinkState(None, 'R6', 1, { 'R4': 10, 'R5': 1 }) } self.id = 'R3' self.engine = PathEngine(self) r3_next_hops, r3_costs, r3_valid_origins, r3_radius = self.engine.calculate_routes( collection) self.id = 'R1' self.engine = PathEngine(self) r1_next_hops, r1_costs, r1_valid_origins, r1_radius = self.engine.calculate_routes( collection) self.assertEqual(r1_next_hops['R6'], 'R2') self.assertEqual(r3_valid_origins['R6'], []) self.assertEqual(r1_radius, 3) self.assertEqual(r3_radius, 2)
class PathTest(unittest.TestCase): def setUp(self): self.id = 'R1' self.engine = PathEngine(self) def log(self, level, text): pass def test_topology1(self): """ +====+ +----+ +----+ | R1 |------| R2 |------| R3 | +====+ +----+ +----+ """ collection = { 'R1': LinkState(None, 'R1', 1, ['R2']), 'R2': LinkState(None, 'R2', 1, ['R1', 'R3']), 'R3': LinkState(None, 'R3', 1, ['R2']) } next_hops, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 2) self.assertEqual(next_hops['R2'], 'R2') self.assertEqual(next_hops['R3'], 'R2') valid_origins['R2'].sort() valid_origins['R3'].sort() self.assertEqual(valid_origins['R2'], []) self.assertEqual(valid_origins['R3'], []) def test_topology2(self): """ +====+ +----+ +----+ | R1 |------| R2 |------| R4 | +====+ +----+ +----+ | | +----+ +----+ +----+ | R3 |------| R5 |------| R6 | +----+ +----+ +----+ """ collection = { 'R1': LinkState(None, 'R1', 1, ['R2']), 'R2': LinkState(None, 'R2', 1, ['R1', 'R3', 'R4']), 'R3': LinkState(None, 'R3', 1, ['R2', 'R5']), 'R4': LinkState(None, 'R4', 1, ['R2', 'R5']), 'R5': LinkState(None, 'R5', 1, ['R3', 'R4', 'R6']), 'R6': LinkState(None, 'R6', 1, ['R5']) } next_hops, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 5) self.assertEqual(next_hops['R2'], 'R2') self.assertEqual(next_hops['R3'], 'R2') self.assertEqual(next_hops['R4'], 'R2') self.assertEqual(next_hops['R5'], 'R2') self.assertEqual(next_hops['R6'], 'R2') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() self.assertEqual(valid_origins['R2'], []) self.assertEqual(valid_origins['R3'], []) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], []) self.assertEqual(valid_origins['R6'], []) def test_topology3(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ | | +====+ +----+ +----+ | R1 |------| R5 |------| R6 | +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, ['R3']), 'R3': LinkState(None, 'R3', 1, ['R1', 'R2', 'R4']), 'R4': LinkState(None, 'R4', 1, ['R3', 'R5']), 'R1': LinkState(None, 'R1', 1, ['R3', 'R5']), 'R5': LinkState(None, 'R5', 1, ['R1', 'R4', 'R6']), 'R6': LinkState(None, 'R6', 1, ['R5']) } next_hops, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 5) self.assertEqual(next_hops['R2'], 'R3') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() self.assertEqual(valid_origins['R2'], ['R5', 'R6']) self.assertEqual(valid_origins['R3'], ['R5', 'R6']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3']) self.assertEqual(valid_origins['R6'], ['R2', 'R3']) def test_topology4(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ | | +====+ +----+ +----+ | R1 |------| R5 |------| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, ['R3']), 'R3': LinkState(None, 'R3', 1, ['R1', 'R2', 'R4']), 'R4': LinkState(None, 'R4', 1, ['R3', 'R5']), 'R1': LinkState(None, 'R1', 1, ['R3', 'R5']), 'R5': LinkState(None, 'R5', 1, ['R1', 'R4', 'R6']), 'R6': LinkState(None, 'R6', 1, ['R5', 'R7']) } next_hops, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R3') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') self.assertEqual(next_hops['R7'], 'R5') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() valid_origins['R7'].sort() self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3']) self.assertEqual(valid_origins['R6'], ['R2', 'R3']) self.assertEqual(valid_origins['R7'], ['R2', 'R3']) def test_topology5(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ | | | | +====+ +----+ +----+ +--------| R1 |------| R5 |------| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, ['R3', 'R1']), 'R3': LinkState(None, 'R3', 1, ['R1', 'R2', 'R4']), 'R4': LinkState(None, 'R4', 1, ['R3', 'R5']), 'R1': LinkState(None, 'R1', 1, ['R3', 'R5', 'R2']), 'R5': LinkState(None, 'R5', 1, ['R1', 'R4', 'R6']), 'R6': LinkState(None, 'R6', 1, ['R5', 'R7']) } next_hops, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R2') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') self.assertEqual(next_hops['R7'], 'R5') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() valid_origins['R7'].sort() self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3']) self.assertEqual(valid_origins['R6'], ['R2', 'R3']) self.assertEqual(valid_origins['R7'], ['R2', 'R3']) def test_topology5_with_asymmetry1(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ ^ | | ^ +====+ +----+ +----+ +-<-<-<--| R1 |------| R5 |------| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, ['R3']), 'R3': LinkState(None, 'R3', 1, ['R1', 'R2', 'R4']), 'R4': LinkState(None, 'R4', 1, ['R3', 'R5']), 'R1': LinkState(None, 'R1', 1, ['R3', 'R5', 'R2']), 'R5': LinkState(None, 'R5', 1, ['R1', 'R4', 'R6']), 'R6': LinkState(None, 'R6', 1, ['R5', 'R7']) } next_hops, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R2') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') self.assertEqual(next_hops['R7'], 'R5') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() valid_origins['R7'].sort() self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3']) self.assertEqual(valid_origins['R6'], ['R2', 'R3']) self.assertEqual(valid_origins['R7'], ['R2', 'R3']) def test_topology5_with_asymmetry2(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ v | | v +====+ +----+ +----+ +->->->->| R1 |------| R5 |------| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, ['R3', 'R1']), 'R3': LinkState(None, 'R3', 1, ['R1', 'R2', 'R4']), 'R4': LinkState(None, 'R4', 1, ['R3', 'R5']), 'R1': LinkState(None, 'R1', 1, ['R3', 'R5']), 'R5': LinkState(None, 'R5', 1, ['R1', 'R4', 'R6']), 'R6': LinkState(None, 'R6', 1, ['R5', 'R7']) } next_hops, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 6) self.assertEqual(next_hops['R2'], 'R3') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') self.assertEqual(next_hops['R6'], 'R5') self.assertEqual(next_hops['R7'], 'R5') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() valid_origins['R6'].sort() valid_origins['R7'].sort() self.assertEqual(valid_origins['R2'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R3'], ['R5', 'R6', 'R7']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3']) self.assertEqual(valid_origins['R6'], ['R2', 'R3']) self.assertEqual(valid_origins['R7'], ['R2', 'R3']) def test_topology5_with_asymmetry3(self): """ +----+ +----+ +----+ | R2 |------| R3 |------| R4 | +----+ +----+ +----+ v | | v +====+ +----+ +----+ +->->->->| R1 |------| R5 |<-<-<-| R6 |------ R7 (no ls from R7) +====+ +----+ +----+ """ collection = { 'R2': LinkState(None, 'R2', 1, ['R3', 'R1']), 'R3': LinkState(None, 'R3', 1, ['R1', 'R2', 'R4']), 'R4': LinkState(None, 'R4', 1, ['R3', 'R5']), 'R1': LinkState(None, 'R1', 1, ['R3', 'R5']), 'R5': LinkState(None, 'R5', 1, ['R1', 'R4']), 'R6': LinkState(None, 'R6', 1, ['R5', 'R7']) } next_hops, valid_origins = self.engine.calculate_routes(collection) self.assertEqual(len(next_hops), 4) self.assertEqual(next_hops['R2'], 'R3') self.assertEqual(next_hops['R3'], 'R3') self.assertEqual(next_hops['R4'], 'R3') self.assertEqual(next_hops['R5'], 'R5') valid_origins['R2'].sort() valid_origins['R3'].sort() valid_origins['R4'].sort() valid_origins['R5'].sort() self.assertEqual(valid_origins['R2'], ['R5']) self.assertEqual(valid_origins['R3'], ['R5']) self.assertEqual(valid_origins['R4'], []) self.assertEqual(valid_origins['R5'], ['R2', 'R3'])