1 /*
2 * Copyright (c) 2023, 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 <openthread/config.h>
30
31 #include "test_platform.h"
32 #include "test_util.hpp"
33
34 #include "common/num_utils.hpp"
35 #include "thread/mle_types.hpp"
36
37 namespace ot {
38
39 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
40
TestDefaultDeviceProperties(void)41 void TestDefaultDeviceProperties(void)
42 {
43 Instance *instance;
44 const otDeviceProperties *props;
45 uint8_t weight;
46
47 instance = static_cast<Instance *>(testInitInstance());
48 VerifyOrQuit(instance != nullptr);
49
50 props = otThreadGetDeviceProperties(instance);
51
52 VerifyOrQuit(props->mPowerSupply == OPENTHREAD_CONFIG_DEVICE_POWER_SUPPLY);
53 VerifyOrQuit(!props->mSupportsCcm);
54 VerifyOrQuit(!props->mIsUnstable);
55 VerifyOrQuit(props->mLeaderWeightAdjustment == OPENTHREAD_CONFIG_MLE_DEFAULT_LEADER_WEIGHT_ADJUSTMENT);
56 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
57 VerifyOrQuit(props->mIsBorderRouter);
58 #else
59 VerifyOrQuit(!props->mIsBorderRouter);
60 #endif
61
62 weight = 64;
63
64 switch (props->mPowerSupply)
65 {
66 case OT_POWER_SUPPLY_BATTERY:
67 weight -= 8;
68 break;
69 case OT_POWER_SUPPLY_EXTERNAL:
70 break;
71 case OT_POWER_SUPPLY_EXTERNAL_STABLE:
72 weight += 4;
73 break;
74 case OT_POWER_SUPPLY_EXTERNAL_UNSTABLE:
75 weight -= 4;
76 break;
77 }
78
79 weight += props->mIsBorderRouter ? 1 : 0;
80
81 VerifyOrQuit(otThreadGetLocalLeaderWeight(instance) == weight);
82
83 printf("TestDefaultDeviceProperties passed\n");
84 }
85
CompareDevicePropertiess(const otDeviceProperties & aFirst,const otDeviceProperties & aSecond)86 void CompareDevicePropertiess(const otDeviceProperties &aFirst, const otDeviceProperties &aSecond)
87 {
88 static constexpr int8_t kMinAdjustment = -16;
89 static constexpr int8_t kMaxAdjustment = +16;
90
91 VerifyOrQuit(aFirst.mPowerSupply == aSecond.mPowerSupply);
92 VerifyOrQuit(aFirst.mIsBorderRouter == aSecond.mIsBorderRouter);
93 VerifyOrQuit(aFirst.mSupportsCcm == aSecond.mSupportsCcm);
94 VerifyOrQuit(aFirst.mIsUnstable == aSecond.mIsUnstable);
95 VerifyOrQuit(Clamp(aFirst.mLeaderWeightAdjustment, kMinAdjustment, kMaxAdjustment) ==
96 Clamp(aSecond.mLeaderWeightAdjustment, kMinAdjustment, kMaxAdjustment));
97 }
98
TestLeaderWeightCalculation(void)99 void TestLeaderWeightCalculation(void)
100 {
101 struct TestCase
102 {
103 otDeviceProperties mDeviceProperties;
104 uint8_t mExpectedLeaderWeight;
105 };
106
107 static const TestCase kTestCases[] = {
108 {{OT_POWER_SUPPLY_BATTERY, false, false, false, 0}, 56},
109 {{OT_POWER_SUPPLY_EXTERNAL, false, false, false, 0}, 64},
110 {{OT_POWER_SUPPLY_EXTERNAL_STABLE, false, false, false, 0}, 68},
111 {{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, false, false, false, 0}, 60},
112
113 {{OT_POWER_SUPPLY_BATTERY, true, false, false, 0}, 57},
114 {{OT_POWER_SUPPLY_EXTERNAL, true, false, false, 0}, 65},
115 {{OT_POWER_SUPPLY_EXTERNAL_STABLE, true, false, false, 0}, 69},
116 {{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, true, false, false, 0}, 61},
117
118 {{OT_POWER_SUPPLY_BATTERY, true, true, false, 0}, 64},
119 {{OT_POWER_SUPPLY_EXTERNAL, true, true, false, 0}, 72},
120 {{OT_POWER_SUPPLY_EXTERNAL_STABLE, true, true, false, 0}, 76},
121 {{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, true, true, false, 0}, 68},
122
123 // Check when `mIsUnstable` is set.
124 {{OT_POWER_SUPPLY_BATTERY, false, false, true, 0}, 56},
125 {{OT_POWER_SUPPLY_EXTERNAL, false, false, true, 0}, 60},
126 {{OT_POWER_SUPPLY_EXTERNAL_STABLE, false, false, true, 0}, 64},
127 {{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, false, false, true, 0}, 60},
128
129 {{OT_POWER_SUPPLY_BATTERY, true, false, true, 0}, 57},
130 {{OT_POWER_SUPPLY_EXTERNAL, true, false, true, 0}, 61},
131 {{OT_POWER_SUPPLY_EXTERNAL_STABLE, true, false, true, 0}, 65},
132 {{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, true, false, true, 0}, 61},
133
134 // Include non-zero `mLeaderWeightAdjustment`.
135 {{OT_POWER_SUPPLY_BATTERY, true, false, false, 10}, 67},
136 {{OT_POWER_SUPPLY_EXTERNAL, true, false, false, 10}, 75},
137 {{OT_POWER_SUPPLY_EXTERNAL_STABLE, true, false, false, 10}, 79},
138 {{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, true, false, false, 10}, 71},
139
140 {{OT_POWER_SUPPLY_BATTERY, false, false, false, -10}, 46},
141 {{OT_POWER_SUPPLY_EXTERNAL, false, false, false, -10}, 54},
142 {{OT_POWER_SUPPLY_EXTERNAL_STABLE, false, false, false, -10}, 58},
143 {{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, false, false, false, -10}, 50},
144
145 // Use `mLeaderWeightAdjustment` larger than valid range
146 // Make sure it clamps to -16 and +16.
147 {{OT_POWER_SUPPLY_BATTERY, false, false, false, 20}, 72},
148 {{OT_POWER_SUPPLY_EXTERNAL, false, false, false, 20}, 80},
149 {{OT_POWER_SUPPLY_EXTERNAL_STABLE, false, false, false, 20}, 84},
150 {{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, false, false, false, 20}, 76},
151
152 {{OT_POWER_SUPPLY_BATTERY, true, false, false, -20}, 41},
153 {{OT_POWER_SUPPLY_EXTERNAL, true, false, false, -20}, 49},
154 {{OT_POWER_SUPPLY_EXTERNAL_STABLE, true, false, false, -20}, 53},
155 {{OT_POWER_SUPPLY_EXTERNAL_UNSTABLE, true, false, false, -20}, 45},
156 };
157
158 Instance *instance;
159
160 instance = static_cast<Instance *>(testInitInstance());
161 VerifyOrQuit(instance != nullptr);
162
163 for (const TestCase &testCase : kTestCases)
164 {
165 otThreadSetDeviceProperties(instance, &testCase.mDeviceProperties);
166 CompareDevicePropertiess(testCase.mDeviceProperties, *otThreadGetDeviceProperties(instance));
167 VerifyOrQuit(otThreadGetLocalLeaderWeight(instance) == testCase.mExpectedLeaderWeight);
168 }
169
170 printf("TestLeaderWeightCalculation passed\n");
171 }
172
173 #endif // #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
174
175 } // namespace ot
176
main(void)177 int main(void)
178 {
179 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE
180 ot::TestDefaultDeviceProperties();
181 ot::TestLeaderWeightCalculation();
182 #endif
183
184 printf("All tests passed\n");
185 return 0;
186 }
187