A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
sixlowpan-nd-binding-table-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2025
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Boh Jie Qi <jieqiboh5836@gmail.com>
7 */
8
9#include "ns3/ipv6-address.h"
10#include "ns3/log.h"
11#include "ns3/simple-net-device.h"
12#include "ns3/simulator.h"
13#include "ns3/sixlowpan-nd-binding-table.h"
14#include "ns3/test.h"
15
16using namespace ns3;
17
18NS_LOG_COMPONENT_DEFINE("SixLowPanNdBindingTableTest");
19
20/**
21 * @ingroup sixlowpan-nd-binding-table-tests
22 *
23 * @brief 6LoWPAN-ND binding table test case for basic entry creation and manipulation
24 */
26{
27 public:
29 : TestCase("SixLowPanNdBindingTable Basic Operations Test")
30 {
31 }
32
33 void DoRun() override
34 {
35 // Create a binding table
37
38 // Test IPv6 addresses
39 Ipv6Address addr1("2001:db8::1");
40 Ipv6Address addr2("2001:db8::2");
41 Ipv6Address addr3("2001:db8::3");
42
43 // Test 1: Add entries
44 auto entry1 = bindingTable->Add(addr1);
45 auto entry2 = bindingTable->Add(addr2);
46
47 NS_TEST_ASSERT_MSG_NE(entry1, nullptr, "Failed to create first entry");
48 NS_TEST_ASSERT_MSG_NE(entry2, nullptr, "Failed to create second entry");
49
50 // Simple ROVR sanity check: set a canonical 16-byte ROVR and verify it is stored
51 std::vector<uint8_t> rovr(16);
52 for (uint8_t i = 0; i < 16; ++i)
53 {
54 rovr[i] = i;
55 }
56 entry1->SetRovr(rovr);
57 auto gotRovr = entry1->GetRovr();
58 NS_TEST_ASSERT_MSG_EQ(gotRovr.size(), rovr.size(), "ROVR size mismatch");
59 NS_TEST_ASSERT_MSG_EQ(std::equal(gotRovr.begin(), gotRovr.end(), rovr.begin()),
60 true,
61 "ROVR content mismatch");
62
63 // Test 2: Lookup entries
64 auto foundEntry1 = bindingTable->Lookup(addr1);
65 auto foundEntry2 = bindingTable->Lookup(addr2);
66 auto notFoundEntry = bindingTable->Lookup(addr3);
67
68 NS_TEST_ASSERT_MSG_EQ(foundEntry1, entry1, "Lookup should return the same entry1");
69 NS_TEST_ASSERT_MSG_EQ(foundEntry2, entry2, "Lookup should return the same entry2");
70 NS_TEST_ASSERT_MSG_EQ(notFoundEntry,
71 nullptr,
72 "Lookup for non-existent entry should return nullptr");
73
74 // Test 3: Try to add duplicate entry (should return existing entry)
75 auto duplicateEntry = bindingTable->Add(addr1);
76 NS_TEST_ASSERT_MSG_EQ(duplicateEntry,
77 entry1,
78 "Adding duplicate should return existing entry");
79
80 // Test 4: Mark entry as REACHABLE
81 entry1->MarkReachable(10); // 10 minutes lifetime
82 NS_TEST_ASSERT_MSG_EQ(entry1->IsReachable(), true, "Entry1 should be REACHABLE");
83 NS_TEST_ASSERT_MSG_EQ(entry1->IsStale(), false, "Entry1 should not be STALE");
84
85 // Test 5: Mark entry as STALE
86 entry2->MarkStale();
87 NS_TEST_ASSERT_MSG_EQ(entry2->IsStale(), true, "Entry2 should be STALE");
88 NS_TEST_ASSERT_MSG_EQ(entry2->IsReachable(), false, "Entry2 should not be REACHABLE");
89
90 // Cleanup
92 }
93};
94
95/**
96 * @ingroup sixlowpan-nd-binding-table-tests
97 *
98 * @brief Test REACHABLE to STALE state transition after timer expiry
99 */
101{
102 public:
104 : TestCase("SixLowPanNdBindingTable REACHABLE to STALE Transition Test"),
105 m_entryBecameStale(false)
106 {
107 }
108
109 void DoRun() override
110 {
111 // Create a binding table with a mock device
114
115 Ipv6Address testAddr("2001:db8::1");
116 auto entry = bindingTable->Add(testAddr);
117
118 // Mark as REACHABLE with 1 minute lifetime (for faster testing)
119 entry->MarkReachable(1); // 1 minute
120 NS_TEST_ASSERT_MSG_EQ(entry->IsReachable(), true, "Entry should be REACHABLE");
121
122 // Schedule check at 70 seconds (after 1 minute timer should expire)
125 this,
126 bindingTable,
127 testAddr);
128
129 // Run simulation
133
134 NS_TEST_ASSERT_MSG_EQ(m_entryBecameStale, true, "Entry should be STALE after timer expiry");
135 }
136
137 private:
138 /**
139 * @brief Verify that the binding table entry for addr is in STALE state.
140 * @param bindingTable the binding table to query
141 * @param addr the IPv6 address to look up
142 */
144 {
145 // Safely look up the entry (it should still exist but be STALE)
146 auto entry = bindingTable->Lookup(addr);
147
148 if (entry != nullptr)
149 {
150 m_entryBecameStale = entry->IsStale();
151
152 NS_TEST_ASSERT_MSG_EQ(entry->IsStale(),
153 true,
154 "Entry should be STALE after timer expiry");
155 NS_TEST_ASSERT_MSG_EQ(entry->IsReachable(),
156 false,
157 "Entry should not be REACHABLE after timer expiry");
158
159 // Print Binding Table State for debugging
160 NS_LOG_DEBUG("Entry found and is STALE: " << entry->IsStale());
161 }
162 else
163 {
164 NS_TEST_ASSERT_MSG_NE(entry, nullptr, "Entry should still exist at 70 seconds");
165 }
166 }
167
168 bool m_entryBecameStale; //!< True if the entry transitioned to STALE during the test.
169};
170
171/**
172 * @ingroup sixlowpan-nd-binding-table-tests
173 *
174 * @brief Test STALE entry removal after stale duration
175 */
177{
178 public:
180 : TestCase("SixLowPanNdBindingTable STALE Entry Removal Test")
181 {
182 }
183
184 void DoRun() override
185 {
186 // Create a binding table
188
189 // Set a short stale duration for testing (2 seconds instead of 24 hours)
190 bindingTable->SetAttribute("StaleDuration", TimeValue(Seconds(2)));
191
192 Ipv6Address testAddr("2001:db8::1");
193 auto entry = bindingTable->Add(testAddr);
194
195 // Mark as STALE immediately (this starts the stale timer with the short duration)
196 entry->MarkStale();
197 NS_TEST_ASSERT_MSG_EQ(entry->IsStale(), true, "Entry should be STALE");
198
199 // Verify entry exists before timer expiry
200 auto foundEntry = bindingTable->Lookup(testAddr);
201 NS_TEST_ASSERT_MSG_EQ(foundEntry, entry, "Entry should exist before stale timer expiry");
202
203 // Schedule a check just before the timer expires to ensure entry still exists
206 this,
207 bindingTable,
208 testAddr);
209
210 // Schedule a check after the timer expires to ensure entry is removed
213 this,
214 bindingTable,
215 testAddr);
216
220
221 NS_TEST_ASSERT_MSG_EQ(m_entryStillExisted, true, "Entry should exist before timeout");
222 NS_TEST_ASSERT_MSG_EQ(m_entryWasRemoved, true, "Entry should be removed after timeout");
223 }
224
225 private:
226 /**
227 * @brief Verify that the binding table entry for addr still exists.
228 * @param bindingTable the binding table to query
229 * @param addr the IPv6 address to look up
230 */
232 {
233 auto entry = bindingTable->Lookup(addr);
234 m_entryStillExisted = (entry != nullptr);
235 NS_TEST_ASSERT_MSG_NE(entry, nullptr, "Entry should still exist before timer expiry");
236 }
237
238 /**
239 * @brief Verify that the binding table entry for addr has been removed.
240 * @param bindingTable the binding table to query
241 * @param addr the IPv6 address to look up
242 */
244 {
245 auto entry = bindingTable->Lookup(addr);
246 m_entryWasRemoved = (entry == nullptr);
247 NS_TEST_ASSERT_MSG_EQ(entry, nullptr, "Entry should be removed after timer expiry");
248 }
249
250 bool m_entryStillExisted; //!< True if the entry was present before the stale timer expired.
251 bool m_entryWasRemoved; //!< True if the entry was removed after the stale timer expired.
252};
253
254/**
255 * @ingroup sixlowpan-nd-binding-table-tests
256 *
257 * @brief Test state transitions and timer cancellations
258 */
260{
261 public:
263 : TestCase("SixLowPanNdBindingTable State Transition Test")
264 {
265 }
266
267 void DoRun() override
268 {
270 Ipv6Address testAddr("2001:db8::1");
271 auto entry = bindingTable->Add(testAddr);
272
273 // Test 1: Mark REACHABLE
274 entry->MarkReachable(5); // 5 minutes
275 NS_TEST_ASSERT_MSG_EQ(entry->IsReachable(), true, "Entry should be REACHABLE");
276 NS_TEST_ASSERT_MSG_EQ(entry->IsStale(), false, "Entry should not be STALE");
277
278 // Test 2: REACHABLE -> STALE
279 entry->MarkStale();
280 NS_TEST_ASSERT_MSG_EQ(entry->IsStale(), true, "Entry should be STALE");
281 NS_TEST_ASSERT_MSG_EQ(entry->IsReachable(), false, "Entry should no longer be REACHABLE");
282
283 // Test 3: STALE -> REACHABLE (stale timer should be cancelled)
284 entry->MarkReachable(10);
285 NS_TEST_ASSERT_MSG_EQ(entry->IsReachable(), true, "Entry should be REACHABLE again");
286 NS_TEST_ASSERT_MSG_EQ(entry->IsStale(), false, "Entry should no longer be STALE");
287
289 }
290};
291
292/**
293 * @ingroup sixlowpan-nd-binding-table-tests
294 *
295 * @brief 6LoWPAN-ND binding table test suite
296 */
309
310/**
311 * @brief Static variable for registering the 6LoWPAN-ND binding table test suite
312 */
6LoWPAN-ND binding table test case for basic entry creation and manipulation
void DoRun() override
Implementation to actually run this TestCase.
Test REACHABLE to STALE state transition after timer expiry.
bool m_entryBecameStale
True if the entry transitioned to STALE during the test.
void DoRun() override
Implementation to actually run this TestCase.
void CheckStaleState(Ptr< SixLowPanNdBindingTable > bindingTable, Ipv6Address addr)
Verify that the binding table entry for addr is in STALE state.
Test STALE entry removal after stale duration.
bool m_entryStillExisted
True if the entry was present before the stale timer expired.
void CheckEntryRemoved(Ptr< SixLowPanNdBindingTable > bindingTable, Ipv6Address addr)
Verify that the binding table entry for addr has been removed.
void CheckEntryExists(Ptr< SixLowPanNdBindingTable > bindingTable, Ipv6Address addr)
Verify that the binding table entry for addr still exists.
bool m_entryWasRemoved
True if the entry was removed after the stale timer expired.
void DoRun() override
Implementation to actually run this TestCase.
Test state transitions and timer cancellations.
void DoRun() override
Implementation to actually run this TestCase.
Describes an IPv6 address.
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:580
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:125
static void Run()
Run the simulation.
Definition simulator.cc:161
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:169
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:296
@ QUICK
Fast test.
Definition test.h:1057
TestCase(const TestCase &)=delete
Caller graph was not generated because of its size.
Type
Type of test.
Definition test.h:1271
@ UNIT
This test suite implements a Unit Test.
Definition test.h:1273
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
Definition test.cc:494
AttributeValue implementation for Time.
Definition nstime.h:1375
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:260
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition test.h:133
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not.
Definition test.h:553
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1273
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static SixLowPanNdBindingTableTestSuite g_sixlowpanNdBindingTableTestSuite
Static variable for registering the 6LoWPAN-ND binding table test suite.