xref: /aosp_15_r20/external/openthread/tests/unit/test_link_quality.cpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1*cfb92d14SAndroid Build Coastguard Worker /*
2*cfb92d14SAndroid Build Coastguard Worker  *  Copyright (c) 2016, The OpenThread Authors.
3*cfb92d14SAndroid Build Coastguard Worker  *  All rights reserved.
4*cfb92d14SAndroid Build Coastguard Worker  *
5*cfb92d14SAndroid Build Coastguard Worker  *  Redistribution and use in source and binary forms, with or without
6*cfb92d14SAndroid Build Coastguard Worker  *  modification, are permitted provided that the following conditions are met:
7*cfb92d14SAndroid Build Coastguard Worker  *  1. Redistributions of source code must retain the above copyright
8*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer.
9*cfb92d14SAndroid Build Coastguard Worker  *  2. Redistributions in binary form must reproduce the above copyright
10*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer in the
11*cfb92d14SAndroid Build Coastguard Worker  *     documentation and/or other materials provided with the distribution.
12*cfb92d14SAndroid Build Coastguard Worker  *  3. Neither the name of the copyright holder nor the
13*cfb92d14SAndroid Build Coastguard Worker  *     names of its contributors may be used to endorse or promote products
14*cfb92d14SAndroid Build Coastguard Worker  *     derived from this software without specific prior written permission.
15*cfb92d14SAndroid Build Coastguard Worker  *
16*cfb92d14SAndroid Build Coastguard Worker  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*cfb92d14SAndroid Build Coastguard Worker  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*cfb92d14SAndroid Build Coastguard Worker  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*cfb92d14SAndroid Build Coastguard Worker  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20*cfb92d14SAndroid Build Coastguard Worker  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*cfb92d14SAndroid Build Coastguard Worker  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*cfb92d14SAndroid Build Coastguard Worker  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*cfb92d14SAndroid Build Coastguard Worker  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*cfb92d14SAndroid Build Coastguard Worker  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*cfb92d14SAndroid Build Coastguard Worker  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*cfb92d14SAndroid Build Coastguard Worker  *  POSSIBILITY OF SUCH DAMAGE.
27*cfb92d14SAndroid Build Coastguard Worker  */
28*cfb92d14SAndroid Build Coastguard Worker 
29*cfb92d14SAndroid Build Coastguard Worker #include "test_platform.h"
30*cfb92d14SAndroid Build Coastguard Worker #include "test_util.h"
31*cfb92d14SAndroid Build Coastguard Worker 
32*cfb92d14SAndroid Build Coastguard Worker #include "common/array.hpp"
33*cfb92d14SAndroid Build Coastguard Worker #include "common/code_utils.hpp"
34*cfb92d14SAndroid Build Coastguard Worker #include "thread/link_metrics.hpp"
35*cfb92d14SAndroid Build Coastguard Worker #include "thread/link_quality.hpp"
36*cfb92d14SAndroid Build Coastguard Worker 
37*cfb92d14SAndroid Build Coastguard Worker namespace ot {
38*cfb92d14SAndroid Build Coastguard Worker 
39*cfb92d14SAndroid Build Coastguard Worker static Instance *sInstance;
40*cfb92d14SAndroid Build Coastguard Worker 
41*cfb92d14SAndroid Build Coastguard Worker enum
42*cfb92d14SAndroid Build Coastguard Worker {
43*cfb92d14SAndroid Build Coastguard Worker     kMaxRssValue = 0,
44*cfb92d14SAndroid Build Coastguard Worker     kMinRssValue = -128,
45*cfb92d14SAndroid Build Coastguard Worker 
46*cfb92d14SAndroid Build Coastguard Worker     kStringBuffferSize = 80,
47*cfb92d14SAndroid Build Coastguard Worker 
48*cfb92d14SAndroid Build Coastguard Worker     kRssAverageMaxDiff = 16,
49*cfb92d14SAndroid Build Coastguard Worker     kNumRssAdds        = 300,
50*cfb92d14SAndroid Build Coastguard Worker 
51*cfb92d14SAndroid Build Coastguard Worker     kRawAverageBitShift = 3,
52*cfb92d14SAndroid Build Coastguard Worker     kRawAverageMultiple = (1 << kRawAverageBitShift),
53*cfb92d14SAndroid Build Coastguard Worker     kRawAverageBitMask  = (1 << kRawAverageBitShift) - 1,
54*cfb92d14SAndroid Build Coastguard Worker };
55*cfb92d14SAndroid Build Coastguard Worker 
56*cfb92d14SAndroid Build Coastguard Worker #define MIN_RSS(_rss1, _rss2) (((_rss1) < (_rss2)) ? (_rss1) : (_rss2))
57*cfb92d14SAndroid Build Coastguard Worker #define MAX_RSS(_rss1, _rss2) (((_rss1) < (_rss2)) ? (_rss2) : (_rss1))
58*cfb92d14SAndroid Build Coastguard Worker #define ABS(value) (((value) >= 0) ? (value) : -(value))
59*cfb92d14SAndroid Build Coastguard Worker 
60*cfb92d14SAndroid Build Coastguard Worker // This struct contains RSS values and test data for checking link quality info class.
61*cfb92d14SAndroid Build Coastguard Worker struct RssTestData
62*cfb92d14SAndroid Build Coastguard Worker {
63*cfb92d14SAndroid Build Coastguard Worker     const int8_t *mRssList;             // Array of RSS values.
64*cfb92d14SAndroid Build Coastguard Worker     size_t        mRssListSize;         // Size of RSS list.
65*cfb92d14SAndroid Build Coastguard Worker     uint8_t       mExpectedLinkQuality; // Expected final link quality value.
66*cfb92d14SAndroid Build Coastguard Worker };
67*cfb92d14SAndroid Build Coastguard Worker 
68*cfb92d14SAndroid Build Coastguard Worker int8_t sNoiseFloor = -100; // dBm
69*cfb92d14SAndroid Build Coastguard Worker 
70*cfb92d14SAndroid Build Coastguard Worker // Check and verify the raw average RSS value to match the value from GetAverage().
VerifyRawRssValue(int8_t aAverage,uint16_t aRawValue)71*cfb92d14SAndroid Build Coastguard Worker void VerifyRawRssValue(int8_t aAverage, uint16_t aRawValue)
72*cfb92d14SAndroid Build Coastguard Worker {
73*cfb92d14SAndroid Build Coastguard Worker     if (aAverage != Radio::kInvalidRssi)
74*cfb92d14SAndroid Build Coastguard Worker     {
75*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(aAverage == -static_cast<int16_t>((aRawValue + (kRawAverageMultiple / 2)) >> kRawAverageBitShift),
76*cfb92d14SAndroid Build Coastguard Worker                      "Raw value does not match the average.");
77*cfb92d14SAndroid Build Coastguard Worker     }
78*cfb92d14SAndroid Build Coastguard Worker     else
79*cfb92d14SAndroid Build Coastguard Worker     {
80*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(aRawValue == 0, "Raw value does not match the average.");
81*cfb92d14SAndroid Build Coastguard Worker     }
82*cfb92d14SAndroid Build Coastguard Worker }
83*cfb92d14SAndroid Build Coastguard Worker 
84*cfb92d14SAndroid Build Coastguard Worker // This function prints the values in the passed in link info instance. It is invoked as the final step in test-case.
PrintOutcome(LinkQualityInfo & aLinkInfo)85*cfb92d14SAndroid Build Coastguard Worker void PrintOutcome(LinkQualityInfo &aLinkInfo) { printf("%s -> PASS \n", aLinkInfo.ToInfoString().AsCString()); }
86*cfb92d14SAndroid Build Coastguard Worker 
TestLinkQualityData(RssTestData aRssData)87*cfb92d14SAndroid Build Coastguard Worker void TestLinkQualityData(RssTestData aRssData)
88*cfb92d14SAndroid Build Coastguard Worker {
89*cfb92d14SAndroid Build Coastguard Worker     LinkQualityInfo linkInfo;
90*cfb92d14SAndroid Build Coastguard Worker     int8_t          rss, ave, min, max;
91*cfb92d14SAndroid Build Coastguard Worker     size_t          i;
92*cfb92d14SAndroid Build Coastguard Worker 
93*cfb92d14SAndroid Build Coastguard Worker     sInstance = testInitInstance();
94*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(sInstance != nullptr);
95*cfb92d14SAndroid Build Coastguard Worker     linkInfo.Init(*sInstance);
96*cfb92d14SAndroid Build Coastguard Worker 
97*cfb92d14SAndroid Build Coastguard Worker     printf("- - - - - - - - - - - - - - - - - -\n");
98*cfb92d14SAndroid Build Coastguard Worker     linkInfo.Clear();
99*cfb92d14SAndroid Build Coastguard Worker     min = kMinRssValue;
100*cfb92d14SAndroid Build Coastguard Worker     max = kMaxRssValue;
101*cfb92d14SAndroid Build Coastguard Worker 
102*cfb92d14SAndroid Build Coastguard Worker     for (i = 0; i < aRssData.mRssListSize; i++)
103*cfb92d14SAndroid Build Coastguard Worker     {
104*cfb92d14SAndroid Build Coastguard Worker         rss = aRssData.mRssList[i];
105*cfb92d14SAndroid Build Coastguard Worker         min = MIN_RSS(rss, min);
106*cfb92d14SAndroid Build Coastguard Worker         max = MAX_RSS(rss, max);
107*cfb92d14SAndroid Build Coastguard Worker         linkInfo.AddRss(rss);
108*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(linkInfo.GetLastRss() == rss);
109*cfb92d14SAndroid Build Coastguard Worker         ave = linkInfo.GetAverageRss();
110*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(ave >= min, "GetAverageRss() is smaller than min value.");
111*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(ave <= max, "GetAverageRss() is larger than min value");
112*cfb92d14SAndroid Build Coastguard Worker         VerifyRawRssValue(linkInfo.GetAverageRss(), linkInfo.GetAverageRssRaw());
113*cfb92d14SAndroid Build Coastguard Worker         printf("%02u) AddRss(%4d): ", static_cast<unsigned int>(i), rss);
114*cfb92d14SAndroid Build Coastguard Worker         PrintOutcome(linkInfo);
115*cfb92d14SAndroid Build Coastguard Worker     }
116*cfb92d14SAndroid Build Coastguard Worker 
117*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(linkInfo.GetLinkQuality() == aRssData.mExpectedLinkQuality);
118*cfb92d14SAndroid Build Coastguard Worker }
119*cfb92d14SAndroid Build Coastguard Worker 
120*cfb92d14SAndroid Build Coastguard Worker // Check and verify the raw average RSS value to match the value from GetAverage().
VerifyRawRssValue(RssAverager & aRssAverager)121*cfb92d14SAndroid Build Coastguard Worker void VerifyRawRssValue(RssAverager &aRssAverager)
122*cfb92d14SAndroid Build Coastguard Worker {
123*cfb92d14SAndroid Build Coastguard Worker     int8_t   average  = aRssAverager.GetAverage();
124*cfb92d14SAndroid Build Coastguard Worker     uint16_t rawValue = aRssAverager.GetRaw();
125*cfb92d14SAndroid Build Coastguard Worker 
126*cfb92d14SAndroid Build Coastguard Worker     if (average != Radio::kInvalidRssi)
127*cfb92d14SAndroid Build Coastguard Worker     {
128*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(average == -static_cast<int16_t>((rawValue + (kRawAverageMultiple / 2)) >> kRawAverageBitShift),
129*cfb92d14SAndroid Build Coastguard Worker                      "Raw value does not match the average.");
130*cfb92d14SAndroid Build Coastguard Worker     }
131*cfb92d14SAndroid Build Coastguard Worker     else
132*cfb92d14SAndroid Build Coastguard Worker     {
133*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(rawValue == 0, "Raw value does not match the average.");
134*cfb92d14SAndroid Build Coastguard Worker     }
135*cfb92d14SAndroid Build Coastguard Worker }
136*cfb92d14SAndroid Build Coastguard Worker 
137*cfb92d14SAndroid Build Coastguard Worker // This function prints the values in the passed link info instance. It is invoked as the final step in test-case.
PrintOutcome(RssAverager & aRssAverager)138*cfb92d14SAndroid Build Coastguard Worker void PrintOutcome(RssAverager &aRssAverager) { printf("%s -> PASS\n", aRssAverager.ToString().AsCString()); }
139*cfb92d14SAndroid Build Coastguard Worker 
GetRandomRss(void)140*cfb92d14SAndroid Build Coastguard Worker int8_t GetRandomRss(void)
141*cfb92d14SAndroid Build Coastguard Worker {
142*cfb92d14SAndroid Build Coastguard Worker     uint32_t value;
143*cfb92d14SAndroid Build Coastguard Worker 
144*cfb92d14SAndroid Build Coastguard Worker     value = rand() % 128;
145*cfb92d14SAndroid Build Coastguard Worker     return -static_cast<int8_t>(value);
146*cfb92d14SAndroid Build Coastguard Worker }
147*cfb92d14SAndroid Build Coastguard Worker 
TestRssAveraging(void)148*cfb92d14SAndroid Build Coastguard Worker void TestRssAveraging(void)
149*cfb92d14SAndroid Build Coastguard Worker {
150*cfb92d14SAndroid Build Coastguard Worker     RssAverager  rssAverager;
151*cfb92d14SAndroid Build Coastguard Worker     int8_t       rss, rss2, ave;
152*cfb92d14SAndroid Build Coastguard Worker     int16_t      diff;
153*cfb92d14SAndroid Build Coastguard Worker     size_t       i, j, k;
154*cfb92d14SAndroid Build Coastguard Worker     const int8_t rssValues[] = {kMinRssValue, -70, -40, -41, -10, kMaxRssValue};
155*cfb92d14SAndroid Build Coastguard Worker     int16_t      sum;
156*cfb92d14SAndroid Build Coastguard Worker 
157*cfb92d14SAndroid Build Coastguard Worker     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
158*cfb92d14SAndroid Build Coastguard Worker     // Values after initialization/reset.
159*cfb92d14SAndroid Build Coastguard Worker 
160*cfb92d14SAndroid Build Coastguard Worker     rssAverager.Clear();
161*cfb92d14SAndroid Build Coastguard Worker 
162*cfb92d14SAndroid Build Coastguard Worker     printf("\nAfter Clear: ");
163*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(rssAverager.GetAverage() == Radio::kInvalidRssi, "Initial value from GetAverage() is incorrect.");
164*cfb92d14SAndroid Build Coastguard Worker     VerifyRawRssValue(rssAverager);
165*cfb92d14SAndroid Build Coastguard Worker     PrintOutcome(rssAverager);
166*cfb92d14SAndroid Build Coastguard Worker 
167*cfb92d14SAndroid Build Coastguard Worker     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
168*cfb92d14SAndroid Build Coastguard Worker     // Adding a single value
169*cfb92d14SAndroid Build Coastguard Worker     rss = -70;
170*cfb92d14SAndroid Build Coastguard Worker     printf("AddRss(%d): ", rss);
171*cfb92d14SAndroid Build Coastguard Worker     IgnoreError(rssAverager.Add(rss));
172*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(rssAverager.GetAverage() == rss, "GetAverage() failed after a single AddRss().");
173*cfb92d14SAndroid Build Coastguard Worker     VerifyRawRssValue(rssAverager);
174*cfb92d14SAndroid Build Coastguard Worker     PrintOutcome(rssAverager);
175*cfb92d14SAndroid Build Coastguard Worker 
176*cfb92d14SAndroid Build Coastguard Worker     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
177*cfb92d14SAndroid Build Coastguard Worker     // Clear
178*cfb92d14SAndroid Build Coastguard Worker 
179*cfb92d14SAndroid Build Coastguard Worker     printf("Clear(): ");
180*cfb92d14SAndroid Build Coastguard Worker     rssAverager.Clear();
181*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(rssAverager.GetAverage() == Radio::kInvalidRssi, "GetAverage() after Clear() is incorrect.");
182*cfb92d14SAndroid Build Coastguard Worker     VerifyRawRssValue(rssAverager);
183*cfb92d14SAndroid Build Coastguard Worker     PrintOutcome(rssAverager);
184*cfb92d14SAndroid Build Coastguard Worker 
185*cfb92d14SAndroid Build Coastguard Worker     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
186*cfb92d14SAndroid Build Coastguard Worker     // Adding the same value many times.
187*cfb92d14SAndroid Build Coastguard Worker 
188*cfb92d14SAndroid Build Coastguard Worker     printf("- - - - - - - - - - - - - - - - - -\n");
189*cfb92d14SAndroid Build Coastguard Worker 
190*cfb92d14SAndroid Build Coastguard Worker     for (j = 0; j < sizeof(rssValues); j++)
191*cfb92d14SAndroid Build Coastguard Worker     {
192*cfb92d14SAndroid Build Coastguard Worker         rssAverager.Clear();
193*cfb92d14SAndroid Build Coastguard Worker         rss = rssValues[j];
194*cfb92d14SAndroid Build Coastguard Worker         printf("AddRss(%4d) %d times: ", rss, kNumRssAdds);
195*cfb92d14SAndroid Build Coastguard Worker 
196*cfb92d14SAndroid Build Coastguard Worker         for (i = 0; i < kNumRssAdds; i++)
197*cfb92d14SAndroid Build Coastguard Worker         {
198*cfb92d14SAndroid Build Coastguard Worker             IgnoreError(rssAverager.Add(rss));
199*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(rssAverager.GetAverage() == rss, "GetAverage() returned incorrect value.");
200*cfb92d14SAndroid Build Coastguard Worker             VerifyRawRssValue(rssAverager);
201*cfb92d14SAndroid Build Coastguard Worker         }
202*cfb92d14SAndroid Build Coastguard Worker 
203*cfb92d14SAndroid Build Coastguard Worker         PrintOutcome(rssAverager);
204*cfb92d14SAndroid Build Coastguard Worker     }
205*cfb92d14SAndroid Build Coastguard Worker 
206*cfb92d14SAndroid Build Coastguard Worker     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
207*cfb92d14SAndroid Build Coastguard Worker     // Adding two RSS values:
208*cfb92d14SAndroid Build Coastguard Worker 
209*cfb92d14SAndroid Build Coastguard Worker     printf("- - - - - - - - - - - - - - - - - -\n");
210*cfb92d14SAndroid Build Coastguard Worker 
211*cfb92d14SAndroid Build Coastguard Worker     for (j = 0; j < sizeof(rssValues); j++)
212*cfb92d14SAndroid Build Coastguard Worker     {
213*cfb92d14SAndroid Build Coastguard Worker         rss = rssValues[j];
214*cfb92d14SAndroid Build Coastguard Worker 
215*cfb92d14SAndroid Build Coastguard Worker         for (k = 0; k < sizeof(rssValues); k++)
216*cfb92d14SAndroid Build Coastguard Worker         {
217*cfb92d14SAndroid Build Coastguard Worker             if (k == j)
218*cfb92d14SAndroid Build Coastguard Worker             {
219*cfb92d14SAndroid Build Coastguard Worker                 continue;
220*cfb92d14SAndroid Build Coastguard Worker             }
221*cfb92d14SAndroid Build Coastguard Worker 
222*cfb92d14SAndroid Build Coastguard Worker             rss2 = rssValues[k];
223*cfb92d14SAndroid Build Coastguard Worker             rssAverager.Clear();
224*cfb92d14SAndroid Build Coastguard Worker             IgnoreError(rssAverager.Add(rss));
225*cfb92d14SAndroid Build Coastguard Worker             IgnoreError(rssAverager.Add(rss2));
226*cfb92d14SAndroid Build Coastguard Worker             printf("AddRss(%4d), AddRss(%4d): ", rss, rss2);
227*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(rssAverager.GetAverage() == ((rss + rss2) >> 1), "GetAverage() returned incorrect value.");
228*cfb92d14SAndroid Build Coastguard Worker             VerifyRawRssValue(rssAverager);
229*cfb92d14SAndroid Build Coastguard Worker             PrintOutcome(rssAverager);
230*cfb92d14SAndroid Build Coastguard Worker         }
231*cfb92d14SAndroid Build Coastguard Worker     }
232*cfb92d14SAndroid Build Coastguard Worker 
233*cfb92d14SAndroid Build Coastguard Worker     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
234*cfb92d14SAndroid Build Coastguard Worker     // Adding one value many times and a different value once:
235*cfb92d14SAndroid Build Coastguard Worker 
236*cfb92d14SAndroid Build Coastguard Worker     printf("- - - - - - - - - - - - - - - - - -\n");
237*cfb92d14SAndroid Build Coastguard Worker 
238*cfb92d14SAndroid Build Coastguard Worker     for (j = 0; j < sizeof(rssValues); j++)
239*cfb92d14SAndroid Build Coastguard Worker     {
240*cfb92d14SAndroid Build Coastguard Worker         rss = rssValues[j];
241*cfb92d14SAndroid Build Coastguard Worker 
242*cfb92d14SAndroid Build Coastguard Worker         for (k = 0; k < sizeof(rssValues); k++)
243*cfb92d14SAndroid Build Coastguard Worker         {
244*cfb92d14SAndroid Build Coastguard Worker             if (k == j)
245*cfb92d14SAndroid Build Coastguard Worker             {
246*cfb92d14SAndroid Build Coastguard Worker                 continue;
247*cfb92d14SAndroid Build Coastguard Worker             }
248*cfb92d14SAndroid Build Coastguard Worker 
249*cfb92d14SAndroid Build Coastguard Worker             rss2 = rssValues[k];
250*cfb92d14SAndroid Build Coastguard Worker             rssAverager.Clear();
251*cfb92d14SAndroid Build Coastguard Worker 
252*cfb92d14SAndroid Build Coastguard Worker             for (i = 0; i < kNumRssAdds; i++)
253*cfb92d14SAndroid Build Coastguard Worker             {
254*cfb92d14SAndroid Build Coastguard Worker                 IgnoreError(rssAverager.Add(rss));
255*cfb92d14SAndroid Build Coastguard Worker             }
256*cfb92d14SAndroid Build Coastguard Worker 
257*cfb92d14SAndroid Build Coastguard Worker             IgnoreError(rssAverager.Add(rss2));
258*cfb92d14SAndroid Build Coastguard Worker             printf("AddRss(%4d) %d times, AddRss(%4d): ", rss, kNumRssAdds, rss2);
259*cfb92d14SAndroid Build Coastguard Worker             ave = rssAverager.GetAverage();
260*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(ave >= MIN_RSS(rss, rss2), "GetAverage() returned incorrect value.");
261*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(ave <= MAX_RSS(rss, rss2), "GetAverage() returned incorrect value.");
262*cfb92d14SAndroid Build Coastguard Worker             VerifyRawRssValue(rssAverager);
263*cfb92d14SAndroid Build Coastguard Worker             PrintOutcome(rssAverager);
264*cfb92d14SAndroid Build Coastguard Worker         }
265*cfb92d14SAndroid Build Coastguard Worker     }
266*cfb92d14SAndroid Build Coastguard Worker 
267*cfb92d14SAndroid Build Coastguard Worker     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
268*cfb92d14SAndroid Build Coastguard Worker     // Adding two alternating values many times:
269*cfb92d14SAndroid Build Coastguard Worker 
270*cfb92d14SAndroid Build Coastguard Worker     printf("- - - - - - - - - - - - - - - - - -\n");
271*cfb92d14SAndroid Build Coastguard Worker 
272*cfb92d14SAndroid Build Coastguard Worker     for (j = 0; j < sizeof(rssValues); j++)
273*cfb92d14SAndroid Build Coastguard Worker     {
274*cfb92d14SAndroid Build Coastguard Worker         rss = rssValues[j];
275*cfb92d14SAndroid Build Coastguard Worker 
276*cfb92d14SAndroid Build Coastguard Worker         for (k = 0; k < sizeof(rssValues); k++)
277*cfb92d14SAndroid Build Coastguard Worker         {
278*cfb92d14SAndroid Build Coastguard Worker             if (k == j)
279*cfb92d14SAndroid Build Coastguard Worker             {
280*cfb92d14SAndroid Build Coastguard Worker                 continue;
281*cfb92d14SAndroid Build Coastguard Worker             }
282*cfb92d14SAndroid Build Coastguard Worker 
283*cfb92d14SAndroid Build Coastguard Worker             rss2 = rssValues[k];
284*cfb92d14SAndroid Build Coastguard Worker             rssAverager.Clear();
285*cfb92d14SAndroid Build Coastguard Worker 
286*cfb92d14SAndroid Build Coastguard Worker             for (i = 0; i < kNumRssAdds; i++)
287*cfb92d14SAndroid Build Coastguard Worker             {
288*cfb92d14SAndroid Build Coastguard Worker                 IgnoreError(rssAverager.Add(rss));
289*cfb92d14SAndroid Build Coastguard Worker                 IgnoreError(rssAverager.Add(rss2));
290*cfb92d14SAndroid Build Coastguard Worker                 ave = rssAverager.GetAverage();
291*cfb92d14SAndroid Build Coastguard Worker                 VerifyOrQuit(ave >= MIN_RSS(rss, rss2), "GetAverage() is smaller than min value.");
292*cfb92d14SAndroid Build Coastguard Worker                 VerifyOrQuit(ave <= MAX_RSS(rss, rss2), "GetAverage() is larger than min value.");
293*cfb92d14SAndroid Build Coastguard Worker                 diff = ave;
294*cfb92d14SAndroid Build Coastguard Worker                 diff -= (rss + rss2) >> 1;
295*cfb92d14SAndroid Build Coastguard Worker                 VerifyOrQuit(ABS(diff) <= kRssAverageMaxDiff, "GetAverage() is incorrect");
296*cfb92d14SAndroid Build Coastguard Worker                 VerifyRawRssValue(rssAverager);
297*cfb92d14SAndroid Build Coastguard Worker             }
298*cfb92d14SAndroid Build Coastguard Worker 
299*cfb92d14SAndroid Build Coastguard Worker             printf("[AddRss(%4d),  AddRss(%4d)] %d times: ", rss, rss2, kNumRssAdds);
300*cfb92d14SAndroid Build Coastguard Worker             PrintOutcome(rssAverager);
301*cfb92d14SAndroid Build Coastguard Worker         }
302*cfb92d14SAndroid Build Coastguard Worker     }
303*cfb92d14SAndroid Build Coastguard Worker 
304*cfb92d14SAndroid Build Coastguard Worker     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
305*cfb92d14SAndroid Build Coastguard Worker     // For the first 8 values the average should be the arithmetic mean.
306*cfb92d14SAndroid Build Coastguard Worker 
307*cfb92d14SAndroid Build Coastguard Worker     printf("- - - - - - - - - - - - - - - - - -\n");
308*cfb92d14SAndroid Build Coastguard Worker 
309*cfb92d14SAndroid Build Coastguard Worker     for (i = 0; i < 1000; i++)
310*cfb92d14SAndroid Build Coastguard Worker     {
311*cfb92d14SAndroid Build Coastguard Worker         double mean;
312*cfb92d14SAndroid Build Coastguard Worker 
313*cfb92d14SAndroid Build Coastguard Worker         rssAverager.Clear();
314*cfb92d14SAndroid Build Coastguard Worker         sum = 0;
315*cfb92d14SAndroid Build Coastguard Worker 
316*cfb92d14SAndroid Build Coastguard Worker         printf("\n");
317*cfb92d14SAndroid Build Coastguard Worker 
318*cfb92d14SAndroid Build Coastguard Worker         for (j = 1; j <= 8; j++)
319*cfb92d14SAndroid Build Coastguard Worker         {
320*cfb92d14SAndroid Build Coastguard Worker             rss = GetRandomRss();
321*cfb92d14SAndroid Build Coastguard Worker             IgnoreError(rssAverager.Add(rss));
322*cfb92d14SAndroid Build Coastguard Worker             sum += rss;
323*cfb92d14SAndroid Build Coastguard Worker             mean = static_cast<double>(sum) / static_cast<double>(j);
324*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(ABS(rssAverager.GetAverage() - mean) < 1, "Average does not match the arithmetic mean!");
325*cfb92d14SAndroid Build Coastguard Worker             VerifyRawRssValue(rssAverager);
326*cfb92d14SAndroid Build Coastguard Worker             printf("AddRss(%4d) sum=%-5d, mean=%-8.2f RssAverager=", rss, sum, mean);
327*cfb92d14SAndroid Build Coastguard Worker             PrintOutcome(rssAverager);
328*cfb92d14SAndroid Build Coastguard Worker         }
329*cfb92d14SAndroid Build Coastguard Worker     }
330*cfb92d14SAndroid Build Coastguard Worker }
331*cfb92d14SAndroid Build Coastguard Worker 
TestLinkQualityCalculations(void)332*cfb92d14SAndroid Build Coastguard Worker void TestLinkQualityCalculations(void)
333*cfb92d14SAndroid Build Coastguard Worker {
334*cfb92d14SAndroid Build Coastguard Worker     const int8_t      rssList1[] = {-81, -80, -79, -78, -76, -80, -77, -75, -77, -76, -77, -74};
335*cfb92d14SAndroid Build Coastguard Worker     const RssTestData rssData1   = {
336*cfb92d14SAndroid Build Coastguard Worker           rssList1,         // mRssList
337*cfb92d14SAndroid Build Coastguard Worker           sizeof(rssList1), // mRssListSize
338*cfb92d14SAndroid Build Coastguard Worker           3                 // mExpectedLinkQuality
339*cfb92d14SAndroid Build Coastguard Worker     };
340*cfb92d14SAndroid Build Coastguard Worker 
341*cfb92d14SAndroid Build Coastguard Worker     const int8_t      rssList2[] = {-90, -80, -85};
342*cfb92d14SAndroid Build Coastguard Worker     const RssTestData rssData2   = {
343*cfb92d14SAndroid Build Coastguard Worker           rssList2,         // mRssList
344*cfb92d14SAndroid Build Coastguard Worker           sizeof(rssList2), // mRssListSize
345*cfb92d14SAndroid Build Coastguard Worker           2                 // mExpectedLinkQuality
346*cfb92d14SAndroid Build Coastguard Worker     };
347*cfb92d14SAndroid Build Coastguard Worker 
348*cfb92d14SAndroid Build Coastguard Worker     const int8_t      rssList3[] = {-95, -96, -98, -99, -100, -100, -98, -99, -100, -100, -100, -100, -100};
349*cfb92d14SAndroid Build Coastguard Worker     const RssTestData rssData3   = {
350*cfb92d14SAndroid Build Coastguard Worker           rssList3,         // mRssList
351*cfb92d14SAndroid Build Coastguard Worker           sizeof(rssList3), // mRssListSize
352*cfb92d14SAndroid Build Coastguard Worker           0                 // mExpectedLinkQuality
353*cfb92d14SAndroid Build Coastguard Worker     };
354*cfb92d14SAndroid Build Coastguard Worker 
355*cfb92d14SAndroid Build Coastguard Worker     const int8_t      rssList4[] = {-75, -100, -100, -100, -100, -100, -95, -92, -93, -94, -93, -93};
356*cfb92d14SAndroid Build Coastguard Worker     const RssTestData rssData4   = {
357*cfb92d14SAndroid Build Coastguard Worker           rssList4,         // mRssList
358*cfb92d14SAndroid Build Coastguard Worker           sizeof(rssList4), // mRssListSize
359*cfb92d14SAndroid Build Coastguard Worker           1                 // mExpectedLinkQuality
360*cfb92d14SAndroid Build Coastguard Worker     };
361*cfb92d14SAndroid Build Coastguard Worker 
362*cfb92d14SAndroid Build Coastguard Worker     TestLinkQualityData(rssData1);
363*cfb92d14SAndroid Build Coastguard Worker     TestLinkQualityData(rssData2);
364*cfb92d14SAndroid Build Coastguard Worker     TestLinkQualityData(rssData3);
365*cfb92d14SAndroid Build Coastguard Worker     TestLinkQualityData(rssData4);
366*cfb92d14SAndroid Build Coastguard Worker }
367*cfb92d14SAndroid Build Coastguard Worker 
TestSuccessRateTracker(void)368*cfb92d14SAndroid Build Coastguard Worker void TestSuccessRateTracker(void)
369*cfb92d14SAndroid Build Coastguard Worker {
370*cfb92d14SAndroid Build Coastguard Worker     SuccessRateTracker rateTracker;
371*cfb92d14SAndroid Build Coastguard Worker     uint16_t           sampleCount;
372*cfb92d14SAndroid Build Coastguard Worker 
373*cfb92d14SAndroid Build Coastguard Worker     const uint16_t kMaxSamples = 5000;
374*cfb92d14SAndroid Build Coastguard Worker 
375*cfb92d14SAndroid Build Coastguard Worker     const uint16_t kMaxRate       = SuccessRateTracker::kMaxRateValue;
376*cfb92d14SAndroid Build Coastguard Worker     const double   kMaxError      = 1.0; // Max permitted error in percentage
377*cfb92d14SAndroid Build Coastguard Worker     const uint16_t kWeightLimit[] = {64, 128, 256, 300, 512, 810, 900};
378*cfb92d14SAndroid Build Coastguard Worker 
379*cfb92d14SAndroid Build Coastguard Worker     printf("\nTesting SuccessRateTracker\n");
380*cfb92d14SAndroid Build Coastguard Worker 
381*cfb92d14SAndroid Build Coastguard Worker     rateTracker.Clear();
382*cfb92d14SAndroid Build Coastguard Worker 
383*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(rateTracker.GetSuccessRate() == kMaxRate, "SuccessRateTracker: Initial value incorrect");
384*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(rateTracker.GetFailureRate() == 0, "SuccessRateTracker: Initial value incorrect");
385*cfb92d14SAndroid Build Coastguard Worker 
386*cfb92d14SAndroid Build Coastguard Worker     // Adding all success
387*cfb92d14SAndroid Build Coastguard Worker     for (sampleCount = 1; sampleCount < kMaxSamples; sampleCount++)
388*cfb92d14SAndroid Build Coastguard Worker     {
389*cfb92d14SAndroid Build Coastguard Worker         rateTracker.AddSample(true, sampleCount);
390*cfb92d14SAndroid Build Coastguard Worker 
391*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(rateTracker.GetSuccessRate() == kMaxRate, "SuccessRateTracker: incorrect rate all success case");
392*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(rateTracker.GetFailureRate() == 0, "SuccessRateTracker: incorrect rate in all success case");
393*cfb92d14SAndroid Build Coastguard Worker     }
394*cfb92d14SAndroid Build Coastguard Worker 
395*cfb92d14SAndroid Build Coastguard Worker     rateTracker.Clear();
396*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(rateTracker.GetSuccessRate() == kMaxRate, "SuccessRateTracker: Rate incorrect after reset");
397*cfb92d14SAndroid Build Coastguard Worker     VerifyOrQuit(rateTracker.GetFailureRate() == 0, "SuccessRateTracker: Rate incorrect after reset");
398*cfb92d14SAndroid Build Coastguard Worker 
399*cfb92d14SAndroid Build Coastguard Worker     // Adding all failures
400*cfb92d14SAndroid Build Coastguard Worker     for (sampleCount = 1; sampleCount < kMaxRate; sampleCount++)
401*cfb92d14SAndroid Build Coastguard Worker     {
402*cfb92d14SAndroid Build Coastguard Worker         rateTracker.AddSample(false, sampleCount);
403*cfb92d14SAndroid Build Coastguard Worker 
404*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(rateTracker.GetSuccessRate() == 0, "SuccessRateTracker: rate incorrect all failure case");
405*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(rateTracker.GetFailureRate() == kMaxRate,
406*cfb92d14SAndroid Build Coastguard Worker                      "SuccessRateTracker: rate incorrect in all failure case");
407*cfb92d14SAndroid Build Coastguard Worker     }
408*cfb92d14SAndroid Build Coastguard Worker 
409*cfb92d14SAndroid Build Coastguard Worker     // Adding success/failure at different rates and checking the RateTracker rate for every sample
410*cfb92d14SAndroid Build Coastguard Worker 
411*cfb92d14SAndroid Build Coastguard Worker     for (uint16_t testRound = 0; testRound < GetArrayLength(kWeightLimit) * 2; testRound++)
412*cfb92d14SAndroid Build Coastguard Worker     {
413*cfb92d14SAndroid Build Coastguard Worker         uint16_t weightLimit;
414*cfb92d14SAndroid Build Coastguard Worker         bool     reverseLogic;
415*cfb92d14SAndroid Build Coastguard Worker         double   maxDiff = 0;
416*cfb92d14SAndroid Build Coastguard Worker 
417*cfb92d14SAndroid Build Coastguard Worker         // Reverse the logic (add success instead of failure) on even test rounds
418*cfb92d14SAndroid Build Coastguard Worker         reverseLogic = ((testRound % 2) == 0);
419*cfb92d14SAndroid Build Coastguard Worker 
420*cfb92d14SAndroid Build Coastguard Worker         // Select a different weight limit based on the current test round
421*cfb92d14SAndroid Build Coastguard Worker         weightLimit = kWeightLimit[testRound / 2];
422*cfb92d14SAndroid Build Coastguard Worker 
423*cfb92d14SAndroid Build Coastguard Worker         printf("TestRound %02d, weightLimit %3d, reverseLogic %d ", testRound, weightLimit, reverseLogic);
424*cfb92d14SAndroid Build Coastguard Worker 
425*cfb92d14SAndroid Build Coastguard Worker         for (uint16_t period = 1; period < 101; period++)
426*cfb92d14SAndroid Build Coastguard Worker         {
427*cfb92d14SAndroid Build Coastguard Worker             uint16_t failureCount = 0;
428*cfb92d14SAndroid Build Coastguard Worker 
429*cfb92d14SAndroid Build Coastguard Worker             rateTracker.Clear();
430*cfb92d14SAndroid Build Coastguard Worker 
431*cfb92d14SAndroid Build Coastguard Worker             for (sampleCount = 1; sampleCount < kMaxSamples; sampleCount++)
432*cfb92d14SAndroid Build Coastguard Worker             {
433*cfb92d14SAndroid Build Coastguard Worker                 double   expectedRate;
434*cfb92d14SAndroid Build Coastguard Worker                 double   failureRate;
435*cfb92d14SAndroid Build Coastguard Worker                 double   diff;
436*cfb92d14SAndroid Build Coastguard Worker                 bool     isSuccess = ((sampleCount % period) == 0);
437*cfb92d14SAndroid Build Coastguard Worker                 uint16_t weight;
438*cfb92d14SAndroid Build Coastguard Worker 
439*cfb92d14SAndroid Build Coastguard Worker                 if (reverseLogic)
440*cfb92d14SAndroid Build Coastguard Worker                 {
441*cfb92d14SAndroid Build Coastguard Worker                     isSuccess = !isSuccess;
442*cfb92d14SAndroid Build Coastguard Worker                 }
443*cfb92d14SAndroid Build Coastguard Worker 
444*cfb92d14SAndroid Build Coastguard Worker                 weight = sampleCount;
445*cfb92d14SAndroid Build Coastguard Worker 
446*cfb92d14SAndroid Build Coastguard Worker                 if (weight > weightLimit)
447*cfb92d14SAndroid Build Coastguard Worker                 {
448*cfb92d14SAndroid Build Coastguard Worker                     weight = weightLimit;
449*cfb92d14SAndroid Build Coastguard Worker                 }
450*cfb92d14SAndroid Build Coastguard Worker 
451*cfb92d14SAndroid Build Coastguard Worker                 rateTracker.AddSample(isSuccess, weight);
452*cfb92d14SAndroid Build Coastguard Worker 
453*cfb92d14SAndroid Build Coastguard Worker                 if (!isSuccess)
454*cfb92d14SAndroid Build Coastguard Worker                 {
455*cfb92d14SAndroid Build Coastguard Worker                     failureCount++;
456*cfb92d14SAndroid Build Coastguard Worker                 }
457*cfb92d14SAndroid Build Coastguard Worker 
458*cfb92d14SAndroid Build Coastguard Worker                 // Calculate the failure rate from rateTracker and expected rate.
459*cfb92d14SAndroid Build Coastguard Worker 
460*cfb92d14SAndroid Build Coastguard Worker                 failureRate  = static_cast<double>(rateTracker.GetFailureRate()) * 100.0 / kMaxRate; // in percent
461*cfb92d14SAndroid Build Coastguard Worker                 expectedRate = static_cast<double>(failureCount) * 100.0 / sampleCount;              // in percent
462*cfb92d14SAndroid Build Coastguard Worker 
463*cfb92d14SAndroid Build Coastguard Worker                 diff = failureRate - expectedRate;
464*cfb92d14SAndroid Build Coastguard Worker                 diff = ABS(diff);
465*cfb92d14SAndroid Build Coastguard Worker 
466*cfb92d14SAndroid Build Coastguard Worker                 VerifyOrQuit(diff <= kMaxError, "SuccessRateTracker: rate does not match expected value");
467*cfb92d14SAndroid Build Coastguard Worker 
468*cfb92d14SAndroid Build Coastguard Worker                 if (diff > maxDiff)
469*cfb92d14SAndroid Build Coastguard Worker                 {
470*cfb92d14SAndroid Build Coastguard Worker                     maxDiff = diff;
471*cfb92d14SAndroid Build Coastguard Worker                 }
472*cfb92d14SAndroid Build Coastguard Worker             }
473*cfb92d14SAndroid Build Coastguard Worker         }
474*cfb92d14SAndroid Build Coastguard Worker 
475*cfb92d14SAndroid Build Coastguard Worker         printf(" MaxDiff = %.3f%%-> PASS\n", maxDiff);
476*cfb92d14SAndroid Build Coastguard Worker     }
477*cfb92d14SAndroid Build Coastguard Worker }
478*cfb92d14SAndroid Build Coastguard Worker 
479*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
480*cfb92d14SAndroid Build Coastguard Worker 
481*cfb92d14SAndroid Build Coastguard Worker class UnitTester
482*cfb92d14SAndroid Build Coastguard Worker {
483*cfb92d14SAndroid Build Coastguard Worker public:
TestLinkMetricsScaling(void)484*cfb92d14SAndroid Build Coastguard Worker     static void TestLinkMetricsScaling(void)
485*cfb92d14SAndroid Build Coastguard Worker     {
486*cfb92d14SAndroid Build Coastguard Worker         printf("\nTestLinkMetricsScaling\n");
487*cfb92d14SAndroid Build Coastguard Worker 
488*cfb92d14SAndroid Build Coastguard Worker         // Test Link Margin scaling from [0,130] -> [0, 255]
489*cfb92d14SAndroid Build Coastguard Worker 
490*cfb92d14SAndroid Build Coastguard Worker         for (uint8_t linkMargin = 0; linkMargin <= 130; linkMargin++)
491*cfb92d14SAndroid Build Coastguard Worker         {
492*cfb92d14SAndroid Build Coastguard Worker             double  scaled     = 255.0 / 130.0 * linkMargin;
493*cfb92d14SAndroid Build Coastguard Worker             uint8_t scaledAsU8 = static_cast<uint8_t>(scaled + 0.5);
494*cfb92d14SAndroid Build Coastguard Worker 
495*cfb92d14SAndroid Build Coastguard Worker             printf("\nLinkMargin : %-3u -> Scaled : %.1f (rounded:%u)", linkMargin, scaled, scaledAsU8);
496*cfb92d14SAndroid Build Coastguard Worker 
497*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(LinkMetrics::ScaleLinkMarginToRawValue(linkMargin) == scaledAsU8);
498*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(LinkMetrics::ScaleRawValueToLinkMargin(scaledAsU8) == linkMargin);
499*cfb92d14SAndroid Build Coastguard Worker         }
500*cfb92d14SAndroid Build Coastguard Worker 
501*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(LinkMetrics::ScaleLinkMarginToRawValue(131) == 255);
502*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(LinkMetrics::ScaleLinkMarginToRawValue(150) == 255);
503*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(LinkMetrics::ScaleLinkMarginToRawValue(255) == 255);
504*cfb92d14SAndroid Build Coastguard Worker 
505*cfb92d14SAndroid Build Coastguard Worker         // Test RSSI scaling from [-130, 0] -> [0, 255]
506*cfb92d14SAndroid Build Coastguard Worker 
507*cfb92d14SAndroid Build Coastguard Worker         for (int8_t rssi = -128; rssi <= 0; rssi++)
508*cfb92d14SAndroid Build Coastguard Worker         {
509*cfb92d14SAndroid Build Coastguard Worker             double  scaled     = 255.0 / 130.0 * (rssi + 130.0);
510*cfb92d14SAndroid Build Coastguard Worker             uint8_t scaledAsU8 = static_cast<uint8_t>(scaled + 0.5);
511*cfb92d14SAndroid Build Coastguard Worker 
512*cfb92d14SAndroid Build Coastguard Worker             printf("\nRSSI : %-3d -> Scaled :%.1f (rounded:%u)", rssi, scaled, scaledAsU8);
513*cfb92d14SAndroid Build Coastguard Worker 
514*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(LinkMetrics::ScaleRssiToRawValue(rssi) == scaledAsU8);
515*cfb92d14SAndroid Build Coastguard Worker             VerifyOrQuit(LinkMetrics::ScaleRawValueToRssi(scaledAsU8) == rssi);
516*cfb92d14SAndroid Build Coastguard Worker         }
517*cfb92d14SAndroid Build Coastguard Worker 
518*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(LinkMetrics::ScaleRssiToRawValue(1) == 255);
519*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(LinkMetrics::ScaleRssiToRawValue(10) == 255);
520*cfb92d14SAndroid Build Coastguard Worker         VerifyOrQuit(LinkMetrics::ScaleRssiToRawValue(127) == 255);
521*cfb92d14SAndroid Build Coastguard Worker 
522*cfb92d14SAndroid Build Coastguard Worker         // Test corner case of ScaleRawValueToRssi
523*cfb92d14SAndroid Build Coastguard Worker         for (uint8_t rawValue = 0; rawValue < 2; rawValue++)
524*cfb92d14SAndroid Build Coastguard Worker         {
525*cfb92d14SAndroid Build Coastguard Worker             int8_t rssi = LinkMetrics::ScaleRawValueToRssi(rawValue);
526*cfb92d14SAndroid Build Coastguard Worker             printf("\nRaw Value: %u -> RSSI : %-3d", rawValue, rssi);
527*cfb92d14SAndroid Build Coastguard Worker         }
528*cfb92d14SAndroid Build Coastguard Worker     }
529*cfb92d14SAndroid Build Coastguard Worker };
530*cfb92d14SAndroid Build Coastguard Worker 
531*cfb92d14SAndroid Build Coastguard Worker #endif
532*cfb92d14SAndroid Build Coastguard Worker 
533*cfb92d14SAndroid Build Coastguard Worker } // namespace ot
534*cfb92d14SAndroid Build Coastguard Worker 
main(void)535*cfb92d14SAndroid Build Coastguard Worker int main(void)
536*cfb92d14SAndroid Build Coastguard Worker {
537*cfb92d14SAndroid Build Coastguard Worker     ot::TestRssAveraging();
538*cfb92d14SAndroid Build Coastguard Worker     ot::TestLinkQualityCalculations();
539*cfb92d14SAndroid Build Coastguard Worker     ot::TestSuccessRateTracker();
540*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
541*cfb92d14SAndroid Build Coastguard Worker     ot::UnitTester::TestLinkMetricsScaling();
542*cfb92d14SAndroid Build Coastguard Worker #endif
543*cfb92d14SAndroid Build Coastguard Worker 
544*cfb92d14SAndroid Build Coastguard Worker     printf("\nAll tests passed\n");
545*cfb92d14SAndroid Build Coastguard Worker     return 0;
546*cfb92d14SAndroid Build Coastguard Worker }
547