From 6618c5564dcab2e2cb8fe508cdaa9dd2ede70794 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Fri, 14 Sep 2018 13:58:26 -0700 Subject: [PATCH] [toranj] new test to check partition formation and merging (#3066) --- tests/toranj/start.sh | 1 + tests/toranj/test-024-partition-merge.py | 182 +++++++++++++++++++++++ 2 files changed, 183 insertions(+) create mode 100644 tests/toranj/test-024-partition-merge.py diff --git a/tests/toranj/start.sh b/tests/toranj/start.sh index e9643c488..ffb29a55b 100755 --- a/tests/toranj/start.sh +++ b/tests/toranj/start.sh @@ -138,6 +138,7 @@ run test-020-router-table.py run test-021-address-cache-table.py run test-022-multicast-ip6-address.py run test-023-multicast-traffic.py +run test-024-partition-merge.py run test-100-mcu-power-state.py run test-600-channel-manager-properties.py run test-601-channel-manager-channel-change.py diff --git a/tests/toranj/test-024-partition-merge.py b/tests/toranj/test-024-partition-merge.py new file mode 100644 index 000000000..5fc53ac86 --- /dev/null +++ b/tests/toranj/test-024-partition-merge.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python +# +# Copyright (c) 2018, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import time +import wpan +from wpan import verify + +#----------------------------------------------------------------------------------------------------------------------- +# Test description: Partition formation and merge +# +# Network Topology: +# +# r1 ---- / ---- r2 +# | \ | +# | / | +# c1 \ c2 +# +# +# Test covers the following situations: +# +# - r2 forming its own partition when it can no longer hear r1 +# - Partitions merging into one once r1 and r2 can talk again +# - Adding on-mesh prefixes on each partition and ensuring after +# merge the info in combined. +# + + +test_name = __file__[:-3] if __file__.endswith('.py') else __file__ +print '-' * 120 +print 'Starting \'{}\''.format(test_name) + +#----------------------------------------------------------------------------------------------------------------------- +# Utility functions + +def verify_prefix(node_list, prefix, prefix_len=64, stable=True, priority='med', on_mesh=False, slaac=False, dhcp=False, + configure=False, default_route=False, preferred=False): + """ + This function verifies that the `prefix` is present on all the nodes in the `node_list`. + """ + for node in node_list: + prefixes = wpan.parse_on_mesh_prefix_result(node.get(wpan.WPAN_THREAD_ON_MESH_PREFIXES)) + for p in prefixes: + if p.prefix == prefix: + verify(int(p.prefix_len) == prefix_len) + verify(p.is_stable() == stable) + verify(p.is_on_mesh() == on_mesh) + verify(p.is_def_route() == default_route) + verify(p.is_slaac() == slaac) + verify(p.is_dhcp() == dhcp) + verify(p.is_config() == configure) + verify(p.is_preferred() == preferred) + verify(p.priority == priority) + break + else: + raise wpan.VerifyError("Did not find prefix {} on node {}".format(prefix, node)) + +#----------------------------------------------------------------------------------------------------------------------- +# Creating `wpan.Nodes` instances + +speedup = 25 +wpan.Node.set_time_speedup_factor(speedup) + +r1 = wpan.Node() +r2 = wpan.Node() +c1 = wpan.Node() +c2 = wpan.Node() + +#----------------------------------------------------------------------------------------------------------------------- +# Init all nodes + +wpan.Node.init_all_nodes() + +#----------------------------------------------------------------------------------------------------------------------- +# Build network topology +# + +r1.form("partition") + +r1.whitelist_node(r2) +r2.whitelist_node(r1) +r2.join_node(r1, wpan.JOIN_TYPE_ROUTER) + +c1.whitelist_node(r1) +r1.whitelist_node(c1) +c1.join_node(r1, wpan.JOIN_TYPE_END_DEVICE) + +c2.whitelist_node(r2) +r2.whitelist_node(c2) +c2.join_node(r2, wpan.JOIN_TYPE_END_DEVICE) + +#----------------------------------------------------------------------------------------------------------------------- +# Test implementation + +short_wait = 6 +long_wait = 15 # With speedup of 25, this emulates 375s (~6 min). + +prefix1 = "fd00:1234::" +prefix2 = "fd00:abcd::" + +time.sleep(1) + +verify(r1.get(wpan.WPAN_NODE_TYPE) == wpan.NODE_TYPE_LEADER) +verify(r2.get(wpan.WPAN_NODE_TYPE) == wpan.NODE_TYPE_ROUTER) + +# Now force the two routers to form their own partition +# by removing them from each other's whitelist table +r1.un_whitelist_node(r2) +r2.un_whitelist_node(r1) + +# Add a prefix before r2 releaizes it can not longer talk +# to leader (r1). +r2.add_prefix(prefix2) + +# Check that r2 forms its own partition +def check_r2_become_leader(): + verify(r2.get(wpan.WPAN_NODE_TYPE) == wpan.NODE_TYPE_LEADER) + +wpan.verify_within(check_r2_become_leader, long_wait) + +# While we have two partition, add a prefix on r1 +r1.add_prefix(prefix1) + +# Update white list and wait for partitions to merge. +r1.whitelist_node(r2) +r2.whitelist_node(r1) + +def check_paritition_id_macth(): + verify(r1.get(wpan.WPAN_PARTITION_ID) == r2.get(wpan.WPAN_PARTITION_ID)) + +wpan.verify_within(check_paritition_id_macth, long_wait) + +# Check that partitions merged successfully +def check_r1_r2_roles(): + r1_type = r1.get(wpan.WPAN_NODE_TYPE) + r2_type = r2.get(wpan.WPAN_NODE_TYPE) + verify((r1_type == wpan.NODE_TYPE_LEADER and r2_type == wpan.NODE_TYPE_ROUTER) or + (r2_type == wpan.NODE_TYPE_LEADER and r1_type == wpan.NODE_TYPE_ROUTER)) + +wpan.verify_within(check_r1_r2_roles, short_wait) + +# Verify all nodes have both prefixes +def check_prefixes(): + verify_prefix([r1, r2, c1, c2], prefix1) + verify_prefix([r1, r2, c1, c2], prefix2) + +wpan.verify_within(check_prefixes, short_wait) + +# Verify that the children stayed with their parents +verify(len(wpan.parse_list(r1.get(wpan.WPAN_THREAD_CHILD_TABLE))) == 1) +verify(len(wpan.parse_list(r2.get(wpan.WPAN_THREAD_CHILD_TABLE))) == 1) + +#----------------------------------------------------------------------------------------------------------------------- +# Test finished + +wpan.Node.finalize_all_nodes() + +print '\'{}\' passed.'.format(test_name)