xref: /aosp_15_r20/external/openthread/tests/toranj/cli/test-603-channel-announce-recovery.py (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1#!/usr/bin/env python3
2#
3#  Copyright (c) 2022, The OpenThread Authors.
4#  All rights reserved.
5#
6#  Redistribution and use in source and binary forms, with or without
7#  modification, are permitted provided that the following conditions are met:
8#  1. Redistributions of source code must retain the above copyright
9#     notice, this list of conditions and the following disclaimer.
10#  2. Redistributions in binary form must reproduce the above copyright
11#     notice, this list of conditions and the following disclaimer in the
12#     documentation and/or other materials provided with the distribution.
13#  3. Neither the name of the copyright holder nor the
14#     names of its contributors may be used to endorse or promote products
15#     derived from this software without specific prior written permission.
16#
17#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27#  POSSIBILITY OF SUCH DAMAGE.
28
29from cli import verify
30from cli import verify_within
31import cli
32import time
33
34# -----------------------------------------------------------------------------------------------------------------------
35# Test description:
36#
37# Orphaned node attach through MLE Announcement after channel change.
38
39test_name = __file__[:-3] if __file__.endswith('.py') else __file__
40print('-' * 120)
41print('Starting \'{}\''.format(test_name))
42
43# -----------------------------------------------------------------------------------------------------------------------
44# Creating `cli.Node` instances
45
46speedup = 40
47cli.Node.set_time_speedup_factor(speedup)
48
49r1 = cli.Node()
50r2 = cli.Node()
51c1 = cli.Node()
52c2 = cli.Node()
53
54# -----------------------------------------------------------------------------------------------------------------------
55# Form topology
56
57r1.form('announce-tst', channel=11)
58
59r2.join(r1, cli.JOIN_TYPE_ROUTER)
60c1.join(r1, cli.JOIN_TYPE_SLEEPY_END_DEVICE)
61c2.join(r1, cli.JOIN_TYPE_SLEEPY_END_DEVICE)
62c1.set_pollperiod(500)
63c2.set_pollperiod(500)
64
65verify(r1.get_state() == 'leader')
66verify(r2.get_state() == 'router')
67verify(c1.get_state() == 'child')
68verify(c2.get_state() == 'child')
69
70# -----------------------------------------------------------------------------------------------------------------------
71# Test Implementation
72
73# Stop c2 and r2
74
75r2.thread_stop()
76c2.thread_stop()
77
78# Switch the rest of network to channel 26
79r1.cli('channel manager change 26')
80
81
82def check_channel_changed_to_26_on_r1_c1():
83    for node in [r1, c1]:
84        verify(int(node.get_channel()) == 26)
85
86
87verify_within(check_channel_changed_to_26_on_r1_c1, 10)
88
89# Now re-enable c2 and verify that it does attach to r1 and is on
90# channel 26. c2 would go through the ML Announce recovery.
91
92c2.thread_start()
93verify(int(c2.get_channel()) == 11)
94
95# wait for 20s for c2 to be attached/associated
96
97
98def check_c2_is_attched():
99    verify(c2.get_state() == 'child')
100
101
102verify_within(check_c2_is_attched, 20)
103
104# Check that c2 is now on channel 26.
105verify(int(c2.get_channel()) == 26)
106
107# Now re-enable r2, and verify that it switches to channel 26
108# after processing announce from r1.
109
110r2.thread_start()
111verify(int(r2.get_channel()) == 11)
112
113
114def check_r2_switches_to_channel_26():
115    verify(r2.get_state() != 'detached')
116    verify(int(r2.get_channel()) == 26)
117
118
119verify_within(check_r2_switches_to_channel_26, 60)
120
121# -----------------------------------------------------------------------------------------------------------------------
122# Test finished
123
124cli.Node.finalize_all_nodes()
125
126print('\'{}\' passed.'.format(test_name))
127