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)
Example #2
0
    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"], [])
    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)
 def setUp(self):
     self.id = 'R1'
     self.engine = PathEngine(self)
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)
 def setUp(self):
     self.id = 'R1'
     self.engine = PathEngine(self)
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)
Example #8
0
 def setUp(self):
     self.id = "R1"
     self.engine = PathEngine(self)
Example #9
0
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"], [])
Example #10
0
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'])