Example #1
0
    def testAddAutoLayoutDevices(self):
        """Test adding auto layout nodes.
        """
        ns = self.ns
        manager = self.manager

        layout_center_x = random.randint(100, 200)
        layout_center_y = random.randint(100, 200)
        layout_radius = random.randint(50, 100)

        device_1 = MockThreadDevBoard(1)
        device_2 = MockThreadDevBoard(2)
        device_3 = MockThreadDevBoard(3)
        device_4 = MockThreadDevBoard(4)

        for device in [device_1, device_2, device_3, device_4]:
            device.device.set_otns_layout_parameter(layout_center_x,
                                                    layout_center_y,
                                                    layout_radius)

        manager.add_node(device_1)
        ns.go(0.1)

        nodes_info = ns.nodes()
        self.assertEqual(len(nodes_info), 1)
        # placing the first node alone
        expected_coords = {
            device_1.id: (layout_center_x + layout_radius, layout_center_y)
        }
        nodes_info = ns.nodes()
        self.assert_device_positions(nodes_info, expected_coords)

        manager.add_node(device_2)
        ns.go(0.1)

        nodes_info = ns.nodes()
        self.assertEqual(len(nodes_info), 2)
        # forming a horizontal line
        expected_coords = {
            device_1.id: (layout_center_x - layout_radius, layout_center_y),
            device_2.id: (layout_center_x + layout_radius, layout_center_y)
        }
        self.assert_device_positions(nodes_info, expected_coords)

        manager.add_node(device_3)
        manager.add_node(device_4)
        ns.go(0.1)

        nodes_info = ns.nodes()
        self.assertEqual(len(nodes_info), 4)
        # forming a cross shape
        expected_coords = {
            device_1.id: (layout_center_x, layout_center_y + layout_radius),
            device_2.id: (layout_center_x - layout_radius, layout_center_y),
            device_3.id: (layout_center_x, layout_center_y - layout_radius),
            device_4.id: (layout_center_x + layout_radius, layout_center_y)
        }
        self.assert_device_positions(nodes_info, expected_coords)
Example #2
0
    def testUpdateExtaddr(self):
        """Test updating node extended address.

        Also tests updating before the OTNS manager subscribes to the node.
        """
        ns = self.ns
        manager = self.manager

        device_extaddr = random.getrandbits(64)
        device = MockThreadDevBoard(random.randint(1, 10))

        manager.add_node(device)
        ns.go(0.1)

        self.assertEqual(ns.nodes()[device.id]["extaddr"], device.id)

        device.wpantund_process.emit_status(f"extaddr={device_extaddr:016x}")
        ns.go(0.1)

        self.assertEqual(ns.nodes()[device.id]["extaddr"], device.id)

        manager.subscribe_to_node(device)
        device.wpantund_process.emit_status(f"extaddr={device_extaddr:016x}")
        ns.go(0.1)

        self.assertEqual(ns.nodes()[device.id]["extaddr"], device_extaddr)
Example #3
0
    def testUpdateRLOC16(self):
        """Test updating node RLOC16.

        Also tests updating before the OTNS manager subscribes to the node.
        """
        ns = self.ns
        manager = self.manager

        device_rloc16 = random.getrandbits(16)
        device = MockThreadDevBoard(random.randint(1, 10))

        manager.add_node(device)
        ns.go(0.1)

        original_rloc16 = ns.nodes()[device.id]["rloc16"]

        device.wpantund_process.emit_status(f"rloc16={device_rloc16}")
        ns.go(0.1)

        self.assertEqual(ns.nodes()[device.id]["rloc16"], original_rloc16)

        manager.subscribe_to_node(device)
        device.wpantund_process.emit_status(f"rloc16={device_rloc16}")
        ns.go(0.1)

        self.assertEqual(ns.nodes()[device.id]["rloc16"], device_rloc16)
Example #4
0
    def testFormPartition(self):
        """Test forming a partition.
        """
        ns = self.ns
        manager = self.manager

        device_1_parid = random.getrandbits(16)
        device_1 = MockThreadDevBoard(random.randint(1, 10))

        device_2_parid = random.getrandbits(16)
        device_2 = MockThreadDevBoard(random.randint(11, 20))

        manager.add_node(device_1)
        manager.add_node(device_2)

        manager.subscribe_to_node(device_1)
        manager.subscribe_to_node(device_2)

        device_1.wpantund_process.emit_status(f"parid={device_1_parid:08x}")
        device_2.wpantund_process.emit_status(f"parid={device_2_parid:08x}")
        ns.go(0.1)

        partitions_info = ns.partitions()
        self.assertEqual(len(partitions_info), 2)
        self.assertEqual(len(partitions_info[device_1_parid]), 1)
        self.assertEqual(len(partitions_info[device_2_parid]), 1)
        self.assertEqual(partitions_info[device_1_parid][0], device_1.id)
        self.assertEqual(partitions_info[device_2_parid][0], device_2.id)

        device_2.wpantund_process.emit_status(f"parid={device_1_parid:08x}")
        ns.go(0.1)

        partitions_info = ns.partitions()
        self.assertEqual(len(partitions_info), 1)
        self.assertEqual(len(partitions_info[device_1_parid]), 2)
        self.assertIn(device_1.id, partitions_info[device_1_parid])
        self.assertIn(device_2.id, partitions_info[device_1_parid])

        device_2.wpantund_process.emit_status(f"parid={device_2_parid:08x}")
        ns.go(0.1)

        partitions_info = ns.partitions()
        self.assertEqual(len(partitions_info), 2)
        self.assertEqual(len(partitions_info[device_1_parid]), 1)
        self.assertEqual(len(partitions_info[device_2_parid]), 1)
        self.assertEqual(partitions_info[device_1_parid][0], device_1.id)
        self.assertEqual(partitions_info[device_2_parid][0], device_2.id)
Example #5
0
    def testRemoveDevice(self):
        """Test removing device.
        """
        device = MockThreadDevBoard(random.randint(1, 10))

        self.manager.add_node(device)

        expect_thread = self.expect_grpc_commands([f"del {device.id}"])
        self.manager.remove_node(device)
        self.wait_for_expect(expect_thread)
Example #6
0
    def testAddDevice(self):
        """Test adding device.
        """
        ns = self.ns
        manager = self.manager

        device = MockThreadDevBoard(1)
        manager.add_node(device)
        ns.go(0.1)
        self.assertEqual(len(ns.nodes()), 1)
Example #7
0
    def testFixedPosition(self):
        """Test OTNS manager fixed position feature.
        """
        device_1_id, device_2_id = random.randint(1, 10), random.randint(11, 20)
        device_1 = MockThreadDevBoard(device_1_id)
        device_2 = MockThreadDevBoard(device_2_id)

        device_1_x, device_1_y = random.randint(100, 200), random.randint(100, 200)
        device_2_x, device_2_y = random.randint(100, 200), random.randint(100, 200)
        device_1.device.set_otns_vis_position(device_1_x, device_1_y)
        device_2.device.set_otns_vis_position(device_2_x, device_2_y)

        expect_thread = self.expect_grpc_commands([
            f"add router x {device_1_x} y {device_1_y} id {device_1_id}",
            f"add router x {device_2_x} y {device_2_y} id {device_2_id}"
        ])
        self.manager.add_node(device_1)
        self.manager.add_node(device_2)
        self.wait_for_expect(expect_thread)
Example #8
0
    def testAddDevice(self):
        """Test adding device.
        """
        device = MockThreadDevBoard(random.randint(1, 10))
        device_x, device_y = random.randint(100, 200), random.randint(100, 200)
        device.device.set_otns_vis_position(device_x, device_y)

        expect_thread = self.expect_grpc_commands([f"add router x {device_x} y {device_y} id {device.id}"])
        self.manager.add_node(device)
        self.wait_for_expect(expect_thread)
Example #9
0
    def testUpdateRoleMultipleNodes(self):
        """Test updating role for multiple nodes.
        """
        device_1 = MockThreadDevBoard(random.randint(1, 10))
        device_2 = MockThreadDevBoard(random.randint(11, 20))

        self.manager.add_node(device_1)
        self.manager.add_node(device_2)
        self.manager.subscribe_to_node(device_1)
        self.manager.subscribe_to_node(device_2)

        device_1.wpantund_process.emit_status(f"role={RoleType.LEADER.value:1d}")
        device_2.wpantund_process.emit_status(f"role={RoleType.LEADER.value:1d}")

        for role in RoleType:
            for device in [device_1, device_2]:
                expect_thread = self.expect_udp_messages([(f"role={role.value:1d}", device.id)])
                device.wpantund_process.emit_status(f"role={role.value:1d}")
                self.wait_for_expect(expect_thread)
                self.assertEqual(self.manager.otns_node_map[device].role, role)
Example #10
0
    def testAddRemoveNeighbors(self):
        """Test adding and removing neighbors.
        """
        device_1 = MockThreadDevBoard(random.randint(1, 10))
        device_2 = MockThreadDevBoard(random.randint(11, 20))
        device_3 = MockThreadDevBoard(random.randint(21, 30))
        devices = [device_1, device_2, device_3]

        for device in devices:
            self.manager.add_node(device)
            self.manager.subscribe_to_node(device)
            device.wpantund_process.emit_status(f"extaddr={device.mock_extaddr:016x}")

        device_1_otns_node = self.manager.otns_node_map[device_1]
        expect_thread = self.expect_udp_messages([(f"router_added={device_2.mock_extaddr:016x}", device_1.id)])
        device_1.wpantund_process.emit_status(f"router_added={device_2.mock_extaddr:016x}")
        self.wait_for_expect(expect_thread)
        self.assertEqual(len(device_1_otns_node.neighbors), 1)
        self.assertIn(device_2.mock_extaddr, device_1_otns_node.neighbors)
        self.assertNotIn(device_3.mock_extaddr, device_1_otns_node.neighbors)

        expect_thread = self.expect_udp_messages([(f"router_added={device_3.mock_extaddr:016x}", device_1.id)])
        device_1.wpantund_process.emit_status(f"router_added={device_3.mock_extaddr:016x}")
        self.wait_for_expect(expect_thread)
        self.assertEqual(len(device_1_otns_node.neighbors), 2)
        self.assertIn(device_2.mock_extaddr, device_1_otns_node.neighbors)
        self.assertIn(device_3.mock_extaddr, device_1_otns_node.neighbors)

        expect_thread = self.expect_udp_messages([(f"router_removed={device_3.mock_extaddr:016x}", device_1.id)])
        device_1.wpantund_process.emit_status(f"router_removed={device_3.mock_extaddr:016x}")
        self.wait_for_expect(expect_thread)
        self.assertEqual(len(device_1_otns_node.neighbors), 1)
        self.assertIn(device_2.mock_extaddr, device_1_otns_node.neighbors)
        self.assertNotIn(device_3.mock_extaddr, device_1_otns_node.neighbors)

        expect_thread = self.expect_udp_messages([(f"router_removed={device_2.mock_extaddr:016x}", device_1.id)])
        device_1.wpantund_process.emit_status(f"router_removed={device_2.mock_extaddr:016x}")
        self.wait_for_expect(expect_thread)
        self.assertEqual(len(device_1_otns_node.neighbors), 0)
        self.assertNotIn(device_2.mock_extaddr, device_1_otns_node.neighbors)
        self.assertNotIn(device_3.mock_extaddr, device_1_otns_node.neighbors)
Example #11
0
    def testUpdateMode(self):
        """Test updating node mode, one of the properties OTNS manager does not track.
        """
        device = MockThreadDevBoard(random.randint(1, 10))

        self.manager.add_node(device)
        self.manager.subscribe_to_node(device)

        mode = "sn"
        expect_thread = self.expect_udp_messages([(f"mode={mode}", device.id)])
        device.wpantund_process.emit_status(f"mode={mode}")
        self.wait_for_expect(expect_thread)
Example #12
0
    def testUpdateRLOC16(self):
        """Test updating node RLOC16.
        """
        device = MockThreadDevBoard(random.randint(1, 10))

        self.manager.add_node(device)
        self.manager.subscribe_to_node(device)

        for _ in range(3):
            rloc16 = random.getrandbits(16)
            expect_thread = self.expect_udp_messages([(f"rloc16={rloc16}", device.id)])
            device.wpantund_process.emit_status(f"rloc16={rloc16}")
            self.wait_for_expect(expect_thread)
Example #13
0
    def testAddFixedPositionDevices(self):
        """Test adding fixed position nodes.
        """
        def assert_device_fixed_positions(devices: List[MockThreadDevBoard]):
            """Helper method to assert fixed position devices coordinates.

            Args:
                devices (List[MockThreadDevBoard]): list of devices to check.
            """
            for a_device in devices:
                self.assertEqual(nodes_info[a_device.id]["x"], a_device.x)
                self.assertEqual(nodes_info[a_device.id]["y"], a_device.y)

        ns = self.ns
        manager = self.manager

        device_1 = MockThreadDevBoard(random.randint(1, 10))
        device_2 = MockThreadDevBoard(random.randint(11, 20))
        device_3 = MockThreadDevBoard(random.randint(21, 30))

        for device in [device_1, device_2, device_3]:
            device.device.set_otns_vis_position(random.randint(100, 200),
                                                random.randint(100, 200))

        manager.add_node(device_1)
        manager.add_node(device_2)
        ns.go(0.1)

        nodes_info = ns.nodes()
        self.assertEqual(len(nodes_info), 2)
        assert_device_fixed_positions([device_1, device_2])

        manager.add_node(device_3)
        ns.go(0.1)

        nodes_info = ns.nodes()
        self.assertEqual(len(nodes_info), 3)
        assert_device_fixed_positions([device_1, device_2, device_3])
Example #14
0
    def testUpdateExtaddr(self):
        """Test updating node extaddr.
        """
        device = MockThreadDevBoard(random.randint(1, 10))

        self.manager.add_node(device)
        self.manager.subscribe_to_node(device)

        for _ in range(3):
            extaddr = random.getrandbits(64)
            expect_thread = self.expect_udp_messages([(f"extaddr={extaddr:016x}", device.id)])
            device.wpantund_process.emit_status(f"extaddr={extaddr:016x}")
            self.wait_for_expect(expect_thread)
            self.assertEqual(self.manager.otns_node_map[device].extaddr, extaddr)
Example #15
0
    def testUpdateRole(self):
        """Test updating node role.
        """
        device = MockThreadDevBoard(random.randint(1, 10))

        self.manager.add_node(device)
        self.manager.subscribe_to_node(device)

        device.wpantund_process.emit_status(f"role={RoleType.LEADER.value:1d}")

        for role in RoleType:
            expect_thread = self.expect_udp_messages([(f"role={role.value:1d}", device.id)])
            device.wpantund_process.emit_status(f"role={role.value:1d}")
            self.wait_for_expect(expect_thread)
            self.assertEqual(self.manager.otns_node_map[device].role, role)
Example #16
0
    def testAutoLayout(self):
        """Test OTNS manager auto layout feature.
        """

        def expect_grpc_move_commands(coords: Dict[int, Tuple[int, int]]):
            commands = [f"move {node_id} {x} {y}" for node_id, (x, y) in coords.items()]
            return self.expect_grpc_commands(commands)

        def expect_node_vis_positions(nodes: List[MockThreadDevBoard], coords: Dict[int, Tuple[int, int]]):
            for node in nodes:
                if node.id in coords:
                    otns_node = self.manager.otns_node_map[node]
                    self.assertAlmostEqual(coords[node.id][0], otns_node.vis_x, delta=1)
                    self.assertAlmostEqual(coords[node.id][1], otns_node.vis_y, delta=1)

        layout_center_x = random.randint(100, 200)
        layout_center_y = random.randint(100, 200)
        layout_radius = random.randint(50, 100)

        device_1 = MockThreadDevBoard(1)
        device_2 = MockThreadDevBoard(2)
        device_3 = MockThreadDevBoard(3)
        device_4 = MockThreadDevBoard(4)

        devices = [device_1, device_2, device_3, device_4]

        for device in devices:
            device.device.set_otns_layout_parameter(layout_center_x, layout_center_y, layout_radius)

        self.manager.add_node(device_1)

        expected_coords = {
            device_1.id: (layout_center_x - layout_radius, layout_center_y),
            device_2.id: (layout_center_x + layout_radius, layout_center_y)
        }
        expect_thread = expect_grpc_move_commands(expected_coords)
        self.manager.add_node(device_2)
        self.wait_for_expect(expect_thread)
        expect_node_vis_positions(devices, expected_coords)

        expected_coords = {
            device_1.id: (layout_center_x, layout_center_y + layout_radius),
            device_2.id: (layout_center_x - layout_radius, layout_center_y),
            device_3.id: (layout_center_x, layout_center_y - layout_radius),
            device_4.id: (layout_center_x + layout_radius, layout_center_y)
        }
        expect_thread = expect_grpc_move_commands(expected_coords)
        self.manager.add_node(device_3)
        self.manager.add_node(device_4)
        self.wait_for_expect(expect_thread)
        expect_node_vis_positions(devices, expected_coords)

        expected_coords = {
            device_1.id: (layout_center_x, layout_center_y + layout_radius),
            device_2.id: (layout_center_x - layout_radius, layout_center_y),
            device_3.id: (layout_center_x, layout_center_y - layout_radius)
        }
        self.manager.remove_node(device_4)
        expect_node_vis_positions(devices, expected_coords)

        expected_coords = {
            device_1.id: (layout_center_x, layout_center_y + layout_radius),
            device_2.id: (layout_center_x - layout_radius, layout_center_y)
        }
        self.manager.remove_node(device_3)
        expect_node_vis_positions(devices, expected_coords)
Example #17
0
    def testRemoveAutoLayoutDevices(self):
        """Test that removing nodes keeps other nodes stationary with auto layout.
        """
        ns = self.ns
        manager = self.manager

        layout_center_x = random.randint(100, 200)
        layout_center_y = random.randint(100, 200)
        layout_radius = random.randint(50, 100)

        device_1 = MockThreadDevBoard(1)
        device_2 = MockThreadDevBoard(2)
        device_3 = MockThreadDevBoard(3)
        device_4 = MockThreadDevBoard(4)

        for device in [device_1, device_2, device_3, device_4]:
            device.device.set_otns_layout_parameter(layout_center_x,
                                                    layout_center_y,
                                                    layout_radius)
            manager.add_node(device)

        ns.go(0.1)

        nodes_info = ns.nodes()
        self.assertEqual(len(nodes_info), 4)
        expected_coords = {
            device_1.id: (layout_center_x, layout_center_y + layout_radius),
            device_2.id: (layout_center_x - layout_radius, layout_center_y),
            device_3.id: (layout_center_x, layout_center_y - layout_radius),
            device_4.id: (layout_center_x + layout_radius, layout_center_y)
        }
        self.assert_device_positions(nodes_info, expected_coords)

        manager.remove_node(device_4)
        ns.go(0.1)
        nodes_info = ns.nodes()
        self.assertEqual(len(nodes_info), 3)
        expected_coords = {
            device_1.id: (layout_center_x, layout_center_y + layout_radius),
            device_2.id: (layout_center_x - layout_radius, layout_center_y),
            device_3.id: (layout_center_x, layout_center_y - layout_radius)
        }
        self.assert_device_positions(nodes_info, expected_coords)

        manager.remove_node(device_3)
        ns.go(0.1)
        nodes_info = ns.nodes()
        self.assertEqual(len(nodes_info), 2)
        expected_coords = {
            device_1.id: (layout_center_x, layout_center_y + layout_radius),
            device_2.id: (layout_center_x - layout_radius, layout_center_y)
        }
        self.assert_device_positions(nodes_info, expected_coords)

        manager.remove_node(device_2)
        ns.go(0.1)
        nodes_info = ns.nodes()
        self.assertEqual(len(nodes_info), 1)
        expected_coords = {
            device_1.id: (layout_center_x, layout_center_y + layout_radius)
        }
        self.assert_device_positions(nodes_info, expected_coords)

        manager.add_node(device_2)
        manager.remove_node(device_1)
        ns.go(0.1)
        nodes_info = ns.nodes()
        self.assertEqual(len(nodes_info), 1)
        expected_coords = {
            device_2.id: (layout_center_x - layout_radius, layout_center_y)
        }
        self.assert_device_positions(nodes_info, expected_coords)

        manager.add_node(device_3)
        manager.remove_node(device_2)
        ns.go(0.1)
        nodes_info = ns.nodes()
        self.assertEqual(len(nodes_info), 1)
        expected_coords = {
            device_3.id: (layout_center_x, layout_center_y - layout_radius)
        }
        self.assert_device_positions(nodes_info, expected_coords)

        manager.add_node(device_4)
        manager.remove_node(device_3)
        ns.go(0.1)
        nodes_info = ns.nodes()
        self.assertEqual(len(nodes_info), 1)
        expected_coords = {
            device_4.id: (layout_center_x + layout_radius, layout_center_y)
        }
        self.assert_device_positions(nodes_info, expected_coords)
Example #18
0
    def testSummary(self):
        """Verify generated summary by OTNS manager.
        """
        device_1 = MockThreadDevBoard(random.randint(1, 10))
        device_2 = MockThreadDevBoard(random.randint(11, 20))
        device_3 = MockThreadDevBoard(random.randint(21, 30))
        device_4 = MockThreadDevBoard(random.randint(31, 40))
        devices = [device_1, device_2, device_3, device_4]

        for device in devices:
            self.manager.add_node(device)
            self.manager.subscribe_to_node(device)
            device.wpantund_process.emit_status(f"extaddr={device.mock_extaddr:016x}")

        # make device_1 a leader, device_2 a router and device_3 and 4 children of device_2
        device_1.wpantund_process.emit_status(f"role={RoleType.LEADER.value}")
        device_2.wpantund_process.emit_status(f"role={RoleType.ROUTER.value}")
        device_3.wpantund_process.emit_status(f"role={RoleType.CHILD.value}")
        device_4.wpantund_process.emit_status(f"role={RoleType.CHILD.value}")

        parid = random.getrandbits(16)
        for device in devices:
            device.wpantund_process.emit_status(f"parid={parid:08x}")

        device_1.wpantund_process.emit_status(f"router_added={device_2.mock_extaddr:016x}")
        device_2.wpantund_process.emit_status(f"router_added={device_1.mock_extaddr:016x}")

        device_2.wpantund_process.emit_status(f"child_added={device_3.mock_extaddr:016x}")
        device_2.wpantund_process.emit_status(f"child_added={device_4.mock_extaddr:016x}")

        # detach the network and disable all nodes
        device_2.wpantund_process.emit_status(f"child_removed={device_3.mock_extaddr:016x}")
        device_2.wpantund_process.emit_status(f"child_removed={device_4.mock_extaddr:016x}")

        device_1.wpantund_process.emit_status(f"router_removed={device_2.mock_extaddr:016x}")
        device_2.wpantund_process.emit_status(f"router_removed={device_1.mock_extaddr:016x}")

        for device in devices:
            device.wpantund_process.emit_status(f"role={RoleType.DISABLED.value}")

        # Verify summaries. Elements at index 0 in the summary entries are history timestamps. For extaddr and role
        # histories, entry[1] is the value; for children and neighbors histories, entry[1] is bool (is_added) and
        # entry[2] is the extended address of the corresponding event.
        for device in devices:
            self.assertIn(device.mock_extaddr,
                          [entry[1] for entry in self.manager.node_summaries[device.id].extaddr_history])

        device_1_summary = self.manager.node_summaries[device_1.id]
        self.assertEqual([entry[1] for entry in device_1_summary.role_history], [RoleType.LEADER, RoleType.DISABLED])
        self.assertFalse(device_1_summary.children_history)
        self.assertEqual([(entry[1], entry[2]) for entry in device_1_summary.neighbors_history],
                         [(True, device_2.mock_extaddr), (False, device_2.mock_extaddr)])

        device_2_summary = self.manager.node_summaries[device_2.id]
        self.assertEqual([entry[1] for entry in device_2_summary.role_history], [RoleType.ROUTER, RoleType.DISABLED])
        self.assertEqual([(entry[1], entry[2]) for entry in device_2_summary.children_history],
                         [(True, device_3.mock_extaddr), (True, device_4.mock_extaddr), (False, device_3.mock_extaddr),
                          (False, device_4.mock_extaddr)])
        self.assertEqual([(entry[1], entry[2]) for entry in device_2_summary.neighbors_history],
                         [(True, device_1.mock_extaddr), (False, device_1.mock_extaddr)])

        device_3_summary = self.manager.node_summaries[device_3.id]
        self.assertEqual([entry[1] for entry in device_3_summary.role_history], [RoleType.CHILD, RoleType.DISABLED])
        self.assertFalse(device_3_summary.children_history)
        self.assertFalse(device_3_summary.neighbors_history)

        device_4_summary = self.manager.node_summaries[device_4.id]
        self.assertEqual([entry[1] for entry in device_4_summary.role_history], [RoleType.CHILD, RoleType.DISABLED])
        self.assertFalse(device_4_summary.children_history)
        self.assertFalse(device_4_summary.neighbors_history)