def send_mcast(self, src_node, src_addr, mcast_addr, recving_nodes, non_recving_nodes=[], msg_len=30, mcast_hops=5,): """ Send a multicast message with given `len` from `src_node` using `src_addr` to the multicast address `mcast_addr`. Verify that the message is received on all nodes in `recving_nodes` list and that it is not received on all nodes in `non_recving_nodes` list. """ timeout = 10 delay = 1 message = random_string(msg_len) if src_addr == src_node.ip6_lla: src_addr = f"{src_addr}%{src_node.netns}" for receiver in recving_nodes: receiver.receive_udp_data(port, message, timeout) for listener in non_recving_nodes: listener.receive_udp_data(port, "", timeout) time.sleep(delay) src_node.send_udp_data(target=mcast_addr, port=port, message=message, source=src_addr, hop_limit=mcast_hops) time.sleep(timeout - delay)
def test04_transmit_receive(self): # Traffic from `sed2` to `OFF_MESH_ADDR_1` (verify that it is received on`r1`). # Traffic from `r1` to `OFF_MESH_ADDR_2` (verify that it is received on `r2`), # Traffic from `r2` to `OFF_MESH_ADDR_3` (verify that it is received on `fed1`) class AddressType(enum.Enum): Prefix = 0 addresses = [ (self.sed2, self.r1, AddressType.Prefix, OFF_MESH_ADDR_1), (self.r1, self.r2, AddressType.Prefix, OFF_MESH_ADDR_2), (self.r2, self.fed1, AddressType.Prefix, OFF_MESH_ADDR_3), ] timeout = 5 delay = 1 for i, (src, dst, src_type, dst_address) in enumerate(addresses): port = random.randint(10000 + i * 100, 10099 + i * 100) message = random_string(10) src_address = "" if src_type == AddressType.Prefix: src_address = src.find_ip6_address_with_prefix(ON_MESH_PREFIX) self.wait_for_completion(self.device_list) dst.receive_udp_data(port, message, timeout) time.sleep(delay) src.send_udp_data(dst_address, port, message, src_address) time.sleep(timeout - delay)
def test03_Transmit_Receive(self): # Send from the first router in the chain to the last one. # Send from the SED child of the last router to the SED child of the first # router. # Send from the FED child of the first router to the FED child of the last # router. class AddressType(enum.Enum): MLA = 0 addresses = [ (self.routers[0], self.routers[-1], AddressType.MLA, AddressType.MLA), (self.sed_children[-1], self.sed_children[0], AddressType.MLA, AddressType.MLA), (self.fed_children[0], self.fed_children[-1], AddressType.MLA, AddressType.MLA), ] timeout = 5 delay = 1 for i, (src, dst, src_address, dst_address) in enumerate(addresses): port = random.randint(10000 + i * 100, 10099 + i * 100) for msg_length in MSG_LENS: message = random_string(msg_length) src_address = src.ip6_mla dst_address = dst.ip6_mla dst.receive_udp_data(port, message, timeout) time.sleep(delay) src.send_udp_data(dst_address, port, message, src_address) time.sleep(timeout - delay)
def test_signal(self): """Test signal publisher and subscriber. """ class TestSubscriber(signal.Subscriber): """Subscriber for simple unit test. """ def __init__(self, test_class: SilkTestCase, expect: str): """Initialize a test subscriber. """ super().__init__() self.test_class = test_class self.expect = expect self.received = False def subscribe_handle(self, sender, **kwargs): """Checks for expected signal. """ line = kwargs["line"] if line == self.expect: self.received = True string = random_string(10) publisher = signal.Publisher() subscriber = TestSubscriber(self, string) subscriber.subscribe(publisher) publisher.emit(line=string) self.assertTrue(subscriber.received)
def test08_verify_behavior_when_cache_table_is_full(self): # Check behavior when cache table is full. for num in range(NUM_QUERY_ADDRS): self.r1.send_udp_data(PREFIX + "900:" + str(num), PORT, random_string(10), self.r1_address, timeout=0.05) cache_table = self.r1.wpanctl( "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2) cache_table = wpan_table_parser.parse_address_cache_table_result( cache_table) verify(len(cache_table) == MAX_CACHE_ENTRIES) # Send from c2 to r1 and verify that snoop optimization uses at most`MAX_SNOOPED_NON_EVICTABLE` entries. for num in range(NUM_ADDRESSES): self.transmit_receive_udp_message(self.c2, self.r1, PREFIX + "c2:" + str(num), self.r1_address, PORT) cache_table = self.r1.wpanctl( "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2) cache_table = wpan_table_parser.parse_address_cache_table_result( cache_table) verify(len(cache_table) == MAX_CACHE_ENTRIES) snooped_entries = [ entry for entry in cache_table if entry.state == wpan.ADDRESS_CACHE_ENTRY_STATE_SNOOPED ] verify(len(snooped_entries) == MAX_SNOOPED_NON_EVICTABLE) for entry in snooped_entries: verify(entry.rloc16 == self.c2_rloc) verify(entry.state == wpan.ADDRESS_CACHE_ENTRY_STATE_SNOOPED) verify(entry.can_evict() == False) verify(entry.timeout > 0) # Now send from r1 to c2, some of the snooped entries would be used, others would go through full address query. for num in range(NUM_ADDRESSES): self.transmit_receive_udp_message(self.r1, self.c2, self.r1_address, PREFIX + "c2:" + str(num), PORT) cache_table = self.r1.wpanctl( "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2) cache_table = wpan_table_parser.parse_address_cache_table_result( cache_table) verify(len(cache_table) == MAX_CACHE_ENTRIES) # Verify that c2 entries are now at the top of cache list. for index in range(NUM_ADDRESSES): verify(cache_table[index].address == PREFIX + "c2:" + str(NUM_ADDRESSES - index - 1)) verify(cache_table[index].rloc16 == self.c2_rloc) verify(cache_table[index].state == wpan.ADDRESS_CACHE_ENTRY_STATE_CACHED)
def testSetOTNSProperties(self): """Test setting OTNS properties. """ # speed speed = random.randint(2, 20) expect_thread = self.expect_grpc_commands([f"speed {speed}"]) self.manager.set_replay_speed(speed) self.wait_for_expect(expect_thread) # OT NCP version version = random_string(10) expect_thread = self.expect_grpc_commands([f"netinfo version \"{version}\" real y"]) self.manager.set_ncp_version(version) self.wait_for_expect(expect_thread) # test title title = random_string(10) expect_thread = self.expect_grpc_commands([f"title \"{title}\" x 0 y 20 fs 20"]) self.manager.set_test_title(title) self.wait_for_expect(expect_thread)
def transmit_receive_udp_message(self, src, dst, src_address, dst_address, port, src_port): timeout = 5 delay = 1 message = random_string(10) if src_address == src.ip6_lla: src_address = f"{src_address}%{src.netns}" dst.receive_udp_data(port, message, timeout) time.sleep(delay) src.send_udp_data(target=dst_address, port=port, message=message, source=src_address, src_port=src_port) time.sleep(timeout - delay)
def transmit_receive_udp_message(self, addresses: list): timeout = 5 delay = 1 for i, (src, dst, src_address, dst_address) in enumerate(addresses): port = random.randint(10000 + i * 100, 10099 + i * 100) message = random_string(10) dst.receive_udp_data(port, message, timeout) time.sleep(delay) src.send_udp_data(dst_address, port, message, src_address) time.sleep(timeout - delay)
def testEventEncodeDecode(self): """Test encoding and decoding an OTNS status event. """ message = random_string(10) encoded_event = Event.status_event(message) self.assertEqual(encoded_event.event, EventType.OTNS_STATUS_PUSH.value) event_bytes = encoded_event.to_bytes() self.assertEqual(len(event_bytes), 11 + len(message)) decoded_event = Event.from_bytes(event_bytes) self.assertEqual(encoded_event.data, decoded_event.data) self.assertEqual(message, decoded_event.message)
def __init__(self, node_id: int): """Initialize a mock ThreadDevBoard. Args: node_id (int): ID of the node. """ mock_device = MockHwModule(random_string(10), node_id) FifteenFourDevBoardNode.__init__(self, virtual=True, device=mock_device, device_path=mock_device.port()) if self.logger: self.logger.setLevel(logging.WARN) self.mock_extaddr = random.getrandbits(64) self.wpantund_process = MockWpantundProcess()
def transmit_receive_udp_message(self, src, dst, src_address: str, dst_address: str, port: int, message: str = random_string(10), timeout: float = 0.05): dst.receive_udp_data(port, message, timeout) time.sleep(timeout) src.send_udp_data(dst_address, port, message, src_address, timeout=timeout) time.sleep(timeout)
def test03_Transmit_Receive(self): class AddressType(enum.Enum): LLA = 0 MLA = 1 addresses = [(self.router, self.sleepy_end_device, AddressType.LLA, AddressType.LLA), (self.router, self.sleepy_end_device, AddressType.LLA, AddressType.MLA), (self.router, self.sleepy_end_device, AddressType.MLA, AddressType.MLA), (self.sleepy_end_device, self.router, AddressType.LLA, AddressType.LLA), (self.sleepy_end_device, self.router, AddressType.LLA, AddressType.MLA), (self.sleepy_end_device, self.router, AddressType.MLA, AddressType.MLA)] timeout = 5 delay = 1 for poll_interval in POLL_INTERVALS: self.sleepy_end_device.setprop(wpan.WPAN_POLL_INTERVAL, str(poll_interval)) interval = self.sleepy_end_device.getprop(wpan.WPAN_POLL_INTERVAL) self.assertEqual(int(interval), poll_interval) for i, (src, dst, src_type, dst_type) in enumerate(addresses): port = random.randint(10000 + i * 100, 10099 + i * 100) for msg_len in MSG_LENS: message = random_string(msg_len) src_address = f"{src.ip6_lla}%{src.netns}" if src_type == AddressType.LLA else None dst_address = dst.ip6_lla if dst_type == AddressType.LLA else dst.ip6_mla dst.receive_udp_data(port, message, timeout) time.sleep(delay) src.send_udp_data(dst_address, port, message, src_address) time.sleep(timeout - delay)
def test04_verify_cache_table_entries_in_query_state(self): # From r1 send msg to a group of addresses (not provided by any nodes in network). for num in range(NUM_QUERY_ADDRS): self.r1.send_udp_data(PREFIX + "800:" + str(num), PORT, random_string(10), self.r1_address, timeout=0.05) # Wait before next tx to stagger the address queries request ensuring different timeouts time.sleep(MAX_STAGGER_INTERVAL / NUM_QUERY_ADDRS) # Verify that we do see entries in cache table for all the addresses and all are in "query" state addr_cache_table = self.r1.wpanctl( "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2) addr_cache_table = wpan_table_parser.parse_address_cache_table_result( addr_cache_table) verify(len(addr_cache_table) == NUM_QUERY_ADDRS) for entry in addr_cache_table: verify(entry.state == wpan.ADDRESS_CACHE_ENTRY_STATE_QUERY) verify(not entry.can_evict()) verify(entry.timeout > 0) verify(entry.retry_delay >= INITIAL_RETRY_DELAY)
def test05_verify_retry_query_behavior(self): # Wait till all the address queries time out and verify they enter "retry-query" state. def check_cache_entry_switch_to_retry_state(): cache_table = self.r1.wpanctl( "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2) cache_table = wpan_table_parser.parse_address_cache_table_result( cache_table) for index in range(NUM_QUERY_ADDRS): self.logger.info( f"{cache_table[index].state}, {wpan.ADDRESS_CACHE_ENTRY_STATE_RETRY_QUERY}" ) verify(cache_table[index].state == wpan.ADDRESS_CACHE_ENTRY_STATE_RETRY_QUERY) verify( cache_table[index].retry_delay >= 2 * INITIAL_RETRY_DELAY) verify_within(check_cache_entry_switch_to_retry_state, WAIT_TIME) # Try sending again to same addresses which are in "retry-delay" state. for num in range(NUM_QUERY_ADDRS): self.r1.send_udp_data(PREFIX + "800:" + str(num), PORT, random_string(10), self.r1_address, timeout=0.05) # Make sure the entries stayed in retry-delay as before. verify_within(check_cache_entry_switch_to_retry_state, WAIT_TIME) # Now wait for them to get to zero timeout. cache_table = self.r1.wpanctl( "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2) cache_table = wpan_table_parser.parse_address_cache_table_result( cache_table) def check_cache_entry_in_retry_state_to_get_to_zero_timeout(): cache_table = self.r1.wpanctl( "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2) cache_table = wpan_table_parser.parse_address_cache_table_result( cache_table) for index in range(NUM_QUERY_ADDRS): verify(cache_table[index].state == wpan.ADDRESS_CACHE_ENTRY_STATE_RETRY_QUERY) verify(cache_table[index].timeout == 0) verify_within(check_cache_entry_in_retry_state_to_get_to_zero_timeout, WAIT_TIME) # Now try again using the same addresses. for num in range(NUM_QUERY_ADDRS): self.r1.send_udp_data(PREFIX + "800:" + str(num), PORT, random_string(10), self.r1_address, timeout=0.05) # We expect now after the delay to see retries for same addresses. def check_cache_entry_switch_to_query_state(): cache_table = self.r1.wpanctl( "get", "get " + wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE, 2) cache_table = wpan_table_parser.parse_address_cache_table_result( cache_table) for index in range(NUM_QUERY_ADDRS): verify(cache_table[index].state == wpan.ADDRESS_CACHE_ENTRY_STATE_QUERY) verify(cache_table[index].can_evict() == True) verify_within(check_cache_entry_switch_to_query_state, WAIT_TIME)
def test_process(self): """Test process runner. """ string = random_string(10) process = Process(f"echo '{string}'") self.assertEqual(string, process.get_process_result().rstrip())