Skip to content

Commit 419decf

Browse files
authored
[nexus] migrate test_reset to Nexus (openthread#12971)
Migrate legacy Python test `test_reset.py` to Nexus C++ test `test_reset.cpp`. The test verifies that OpenThread correctly recovers network state, specifically frame counters and datasets, after sequential resets of nodes in a multi-hop topology (Leader <-> Router <-> ED). The test sequence: - Establish multi-hop topology: Leader <-> Router <-> ED. - Send 1010 pings from ED to Leader to advance the frame counter beyond the default storage threshold (1000). - Reset Leader, Router, and ED sequentially. - Verify end-to-end connectivity after resets, confirming that frame counters were correctly recovered from non-volatile storage. Legacy `tests/scripts/thread-cert/test_reset.py` is removed as its functionality is now fully covered by the Nexus test.
1 parent e74aebb commit 419decf

3 files changed

Lines changed: 155 additions & 94 deletions

File tree

tests/nexus/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ ot_nexus_test(mle_msg_key_seq_jump "core;nexus")
407407
ot_nexus_test(nat64_translator "core;nexus")
408408
ot_nexus_test(netdata_publisher "core;nexus")
409409
ot_nexus_test(reed_address_solicit_rejected "core;nexus")
410+
ot_nexus_test(reset "core;nexus")
410411
ot_nexus_test(router_downgrade_on_sec_policy_change "core;nexus")
411412
ot_nexus_test(router_reattach "core;nexus")
412413
ot_nexus_test(router_reboot_multiple_link_request "core;nexus")

tests/nexus/test_reset.cpp

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
* Copyright (c) 2026, The OpenThread Authors.
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
* 1. Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* 2. Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
* 3. Neither the name of the copyright holder nor the
13+
* names of its contributors may be used to endorse or promote products
14+
* derived from this software without specific prior written permission.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
*/
28+
29+
#include <stdio.h>
30+
31+
#include "platform/nexus_core.hpp"
32+
#include "platform/nexus_node.hpp"
33+
34+
namespace ot {
35+
namespace Nexus {
36+
37+
/**
38+
* Time to advance for a node to form a network and become leader, in milliseconds.
39+
*/
40+
static constexpr uint32_t kFormNetworkTime = 13 * 1000;
41+
42+
/**
43+
* Time to advance for a node to join as a child and upgrade to a router, in milliseconds.
44+
*/
45+
static constexpr uint32_t kAttachToRouterTime = 200 * 1000;
46+
47+
/**
48+
* Time to advance for a node to join as a child.
49+
*/
50+
static constexpr uint32_t kAttachAsChildTime = 5 * 1000;
51+
52+
/**
53+
* The number of pings to send to advance the frame counter beyond the storage threshold.
54+
*/
55+
static constexpr uint16_t kNumPings = 1010;
56+
57+
void TestReset(void)
58+
{
59+
Core nexus;
60+
61+
Node &leader = nexus.CreateNode();
62+
Node &router = nexus.CreateNode();
63+
Node &ed = nexus.CreateNode();
64+
65+
leader.SetName("Leader");
66+
router.SetName("Router");
67+
ed.SetName("ED");
68+
69+
nexus.AdvanceTime(0);
70+
71+
// Set up allowlists to enforce Leader <-> Router <-> ED topology
72+
AllowLinkBetween(leader, router);
73+
AllowLinkBetween(router, ed);
74+
75+
SuccessOrQuit(Instance::SetGlobalLogLevel(kLogLevelInfo));
76+
77+
Log("---------------------------------------------------------------------------------------");
78+
Log("Forming network");
79+
80+
leader.Form();
81+
nexus.AdvanceTime(kFormNetworkTime);
82+
VerifyOrQuit(leader.Get<Mle::Mle>().IsLeader());
83+
84+
router.Join(leader);
85+
nexus.AdvanceTime(kAttachToRouterTime);
86+
VerifyOrQuit(router.Get<Mle::Mle>().IsRouter());
87+
88+
ed.Join(router, Node::kAsMed);
89+
nexus.AdvanceTime(kAttachAsChildTime);
90+
VerifyOrQuit(ed.Get<Mle::Mle>().IsChild());
91+
92+
nexus.AdvanceTime(10 * 1000); // Extra time to stabilize
93+
94+
const Ip6::Address &leaderRloc = leader.Get<Mle::Mle>().GetMeshLocalRloc();
95+
96+
Log("---------------------------------------------------------------------------------------");
97+
Log("Sending %u pings from ED to Leader", kNumPings);
98+
99+
for (uint16_t i = 0; i < kNumPings; i++)
100+
{
101+
// Use a 500ms timeout for each ping to ensure it has enough time in a multi-hop setup
102+
nexus.SendAndVerifyEchoRequest(ed, leaderRloc, 0, Ip6::kDefaultHopLimit, 500);
103+
}
104+
105+
Log("---------------------------------------------------------------------------------------");
106+
Log("Resetting nodes sequentially");
107+
108+
Log("Resetting Leader");
109+
leader.Reset();
110+
AllowLinkBetween(leader, router);
111+
leader.Get<ThreadNetif>().Up();
112+
SuccessOrQuit(leader.Get<Mle::Mle>().Start());
113+
nexus.AdvanceTime(kFormNetworkTime);
114+
VerifyOrQuit(leader.Get<Mle::Mle>().IsLeader());
115+
116+
Log("Resetting Router");
117+
router.Reset();
118+
AllowLinkBetween(router, leader);
119+
AllowLinkBetween(router, ed);
120+
router.Get<ThreadNetif>().Up();
121+
SuccessOrQuit(router.Get<Mle::Mle>().Start());
122+
nexus.AdvanceTime(kAttachToRouterTime);
123+
VerifyOrQuit(router.Get<Mle::Mle>().IsRouter());
124+
125+
Log("Resetting ED");
126+
ed.Reset();
127+
AllowLinkBetween(ed, router);
128+
ed.Get<ThreadNetif>().Up();
129+
SuccessOrQuit(ed.Get<Mle::Mle>().Start());
130+
nexus.AdvanceTime(kAttachAsChildTime);
131+
VerifyOrQuit(ed.Get<Mle::Mle>().IsChild());
132+
133+
nexus.AdvanceTime(10 * 1000); // Extra time to stabilize
134+
135+
Log("---------------------------------------------------------------------------------------");
136+
Log("Verifying connectivity after resets");
137+
138+
// The success of this ping after resets is critical.
139+
// Since we sent 1010 pings before resets, the frame counters on all nodes
140+
// have advanced significantly. If a node fails to recover its frame counter
141+
// from settings after reset, it would start at 0, and its packets would be
142+
// rejected by its neighbors.
143+
nexus.SendAndVerifyEchoRequest(ed, leaderRloc);
144+
}
145+
146+
} // namespace Nexus
147+
} // namespace ot
148+
149+
int main(void)
150+
{
151+
ot::Nexus::TestReset();
152+
printf("All tests passed\n");
153+
return 0;
154+
}

tests/scripts/thread-cert/test_reset.py

Lines changed: 0 additions & 94 deletions
This file was deleted.

0 commit comments

Comments
 (0)