xref: /aosp_15_r20/external/openthread/tests/unit/test_dataset.cpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1 /*
2  *  Copyright (c) 2024, 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 "meshcop/dataset.hpp"
35 
36 namespace ot {
37 namespace MeshCoP {
38 
TestDataset(void)39 void TestDataset(void)
40 {
41     static const uint8_t kTlvBytes[] = {
42         0x0e, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x35, 0x06, 0x00,
43         0x04, 0x00, 0x1f, 0xff, 0xe0, 0x02, 0x08, 0x1d, 0xe5, 0xbf, 0xec, 0xd5, 0x16, 0x5b, 0x8f, 0x07, 0x08, 0xfd,
44         0xe2, 0x1f, 0x0c, 0x8a, 0x13, 0xe8, 0xe7, 0x05, 0x10, 0xea, 0xf9, 0x14, 0x9f, 0xdc, 0x73, 0x78, 0x77, 0x06,
45         0x98, 0xd5, 0x91, 0x80, 0x22, 0x19, 0x58, 0x03, 0x0f, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61,
46         0x64, 0x2d, 0x61, 0x61, 0x63, 0x33, 0x01, 0x02, 0xfa, 0xce, 0x04, 0x10, 0x2e, 0xaa, 0xe2, 0x94, 0x84, 0x38,
47         0x8e, 0x31, 0x19, 0x58, 0x1a, 0x7b, 0x5a, 0x94, 0x8c, 0x07, 0x0c, 0x04, 0x02, 0xa0, 0xf7, 0xf8,
48     };
49 
50     static const otNetworkKey kNetworkKey = {
51         {0xea, 0xf9, 0x14, 0x9f, 0xdc, 0x73, 0x78, 0x77, 0x06, 0x98, 0xd5, 0x91, 0x80, 0x22, 0x19, 0x58}};
52 
53     static const otNetworkKey kNewNetworkKey = {
54         {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}};
55 
56     static const uint8_t kDuplicateChannels[] = {
57         0x00, 0x03, 0x00, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x00, 0x1a,
58     };
59 
60     static const Tlv::Type kDatasetTlvTypes[] = {
61         Tlv::kChannel,    Tlv::kPanId,           Tlv::kExtendedPanId,  Tlv::kNetworkName,     Tlv::kPskc,
62         Tlv::kNetworkKey, Tlv::kMeshLocalPrefix, Tlv::kSecurityPolicy, Tlv::kActiveTimestamp,
63     };
64 
65     Dataset       dataset;
66     Dataset       dataset2;
67     Dataset::Tlvs datasetTlvs;
68     Dataset::Info datasetInfo;
69     uint16_t      panId;
70     NetworkKey    networkKey;
71 
72     SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes)));
73 
74     VerifyOrQuit(dataset.GetLength() == sizeof(kTlvBytes));
75 
76     SuccessOrQuit(dataset.ValidateTlvs());
77 
78     for (Tlv::Type tlvType : kDatasetTlvTypes)
79     {
80         VerifyOrQuit(dataset.ContainsTlv(tlvType));
81     }
82 
83     // Converting to `Dataset::Tlvs`
84 
85     dataset.ConvertTo(datasetTlvs);
86     VerifyOrQuit(datasetTlvs.mLength == sizeof(kTlvBytes));
87     VerifyOrQuit(memcmp(datasetTlvs.mTlvs, kTlvBytes, sizeof(kTlvBytes)) == 0);
88 
89     // Converting to `Dataset::Info`
90 
91     dataset.ConvertTo(datasetInfo);
92 
93     VerifyOrQuit(datasetInfo.mComponents.mIsActiveTimestampPresent);
94     VerifyOrQuit(datasetInfo.mComponents.mIsNetworkKeyPresent);
95     VerifyOrQuit(datasetInfo.mComponents.mIsNetworkNamePresent);
96     VerifyOrQuit(datasetInfo.mComponents.mIsExtendedPanIdPresent);
97     VerifyOrQuit(datasetInfo.mComponents.mIsMeshLocalPrefixPresent);
98     VerifyOrQuit(datasetInfo.mComponents.mIsPanIdPresent);
99     VerifyOrQuit(datasetInfo.mComponents.mIsChannelPresent);
100     VerifyOrQuit(datasetInfo.mComponents.mIsPskcPresent);
101     VerifyOrQuit(datasetInfo.mComponents.mIsSecurityPolicyPresent);
102     VerifyOrQuit(datasetInfo.mComponents.mIsChannelMaskPresent);
103     VerifyOrQuit(!datasetInfo.mComponents.mIsPendingTimestampPresent);
104     VerifyOrQuit(!datasetInfo.mComponents.mIsDelayPresent);
105 
106     VerifyOrQuit(datasetInfo.mPanId == 0xface);
107     VerifyOrQuit(AsCoreType(&datasetInfo.mNetworkKey) == AsCoreType(&kNetworkKey));
108 
109     // Finding, reading TLVs
110 
111     VerifyOrQuit(dataset.Contains<PanIdTlv>());
112     VerifyOrQuit(dataset.FindTlv(Tlv::kPanId) != nullptr);
113     SuccessOrQuit(dataset.Read<PanIdTlv>(panId));
114     VerifyOrQuit(panId == 0xface);
115 
116     VerifyOrQuit(dataset.Contains<NetworkKeyTlv>());
117     VerifyOrQuit(dataset.FindTlv(Tlv::kNetworkKey) != nullptr);
118     SuccessOrQuit(dataset.Read<NetworkKeyTlv>(networkKey));
119     VerifyOrQuit(networkKey == AsCoreType(&kNetworkKey));
120 
121     // Change PAN ID TLV
122 
123     SuccessOrQuit(dataset.Write<PanIdTlv>(0xcafe));
124 
125     SuccessOrQuit(dataset.ValidateTlvs());
126 
127     VerifyOrQuit(dataset.Contains<PanIdTlv>());
128     VerifyOrQuit(dataset.FindTlv(Tlv::kPanId) != nullptr);
129     SuccessOrQuit(dataset.Read<PanIdTlv>(panId));
130     VerifyOrQuit(panId == 0xcafe);
131 
132     for (Tlv::Type tlvType : kDatasetTlvTypes)
133     {
134         VerifyOrQuit(dataset.ContainsTlv(tlvType));
135     }
136 
137     // Change Network Key TLV
138 
139     SuccessOrQuit(dataset.Write<NetworkKeyTlv>(AsCoreType(&kNewNetworkKey)));
140     VerifyOrQuit(dataset.Contains<NetworkKeyTlv>());
141     VerifyOrQuit(dataset.FindTlv(Tlv::kNetworkKey) != nullptr);
142     SuccessOrQuit(dataset.Read<NetworkKeyTlv>(networkKey));
143     VerifyOrQuit(networkKey == AsCoreType(&kNewNetworkKey));
144 
145     for (Tlv::Type tlvType : kDatasetTlvTypes)
146     {
147         VerifyOrQuit(dataset.ContainsTlv(tlvType));
148     }
149 
150     // Remove PAN ID TLV
151 
152     dataset.RemoveTlv(Tlv::kPanId);
153     VerifyOrQuit(!dataset.Contains<PanIdTlv>());
154     VerifyOrQuit(dataset.FindTlv(Tlv::kPanId) == nullptr);
155     VerifyOrQuit(dataset.Read<PanIdTlv>(panId) == kErrorNotFound);
156 
157     SuccessOrQuit(dataset.ValidateTlvs());
158 
159     // Invalid datasets
160 
161     SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes) - 1));
162     VerifyOrQuit(dataset.ValidateTlvs() == kErrorParse);
163 
164     SuccessOrQuit(dataset.SetFrom(kDuplicateChannels, sizeof(kDuplicateChannels)));
165     VerifyOrQuit(dataset.ValidateTlvs() == kErrorParse);
166 
167     SuccessOrQuit(dataset.SetFrom(kDuplicateChannels, sizeof(kDuplicateChannels) / 2));
168     SuccessOrQuit(dataset.ValidateTlvs());
169 
170     // Combining/Merging TLVs from two Datasets.
171 
172     SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes)));
173 
174     datasetInfo.Clear();
175     datasetInfo.mComponents.mIsPanIdPresent      = true;
176     datasetInfo.mComponents.mIsNetworkKeyPresent = true;
177     datasetInfo.mPanId                           = 0xcafe;
178     datasetInfo.mNetworkKey                      = kNewNetworkKey;
179 
180     dataset2.SetFrom(datasetInfo);
181     SuccessOrQuit(dataset2.ValidateTlvs());
182 
183     SuccessOrQuit(dataset.WriteTlvsFrom(dataset2));
184 
185     SuccessOrQuit(dataset.ValidateTlvs());
186 
187     VerifyOrQuit(dataset.Contains<PanIdTlv>());
188     VerifyOrQuit(dataset.FindTlv(Tlv::kPanId) != nullptr);
189     SuccessOrQuit(dataset.Read<PanIdTlv>(panId));
190     VerifyOrQuit(panId == 0xcafe);
191 
192     VerifyOrQuit(dataset.Contains<NetworkKeyTlv>());
193     VerifyOrQuit(dataset.FindTlv(Tlv::kNetworkKey) != nullptr);
194     SuccessOrQuit(dataset.Read<NetworkKeyTlv>(networkKey));
195     VerifyOrQuit(networkKey == AsCoreType(&kNewNetworkKey));
196 
197     // Combining/Merging TLVs from two Datasets (using `Dataset::Info`).
198 
199     SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes)));
200 
201     SuccessOrQuit(dataset.WriteTlvsFrom(datasetInfo));
202 
203     SuccessOrQuit(dataset.ValidateTlvs());
204 
205     VerifyOrQuit(dataset.Contains<PanIdTlv>());
206     VerifyOrQuit(dataset.FindTlv(Tlv::kPanId) != nullptr);
207     SuccessOrQuit(dataset.Read<PanIdTlv>(panId));
208     VerifyOrQuit(panId == 0xcafe);
209 
210     VerifyOrQuit(dataset.Contains<NetworkKeyTlv>());
211     VerifyOrQuit(dataset.FindTlv(Tlv::kNetworkKey) != nullptr);
212     SuccessOrQuit(dataset.Read<NetworkKeyTlv>(networkKey));
213     VerifyOrQuit(networkKey == AsCoreType(&kNewNetworkKey));
214 
215     // Append TLVs
216 
217     SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes)));
218     VerifyOrQuit(dataset.GetLength() == sizeof(kTlvBytes));
219     VerifyOrQuit(memcmp(dataset.GetBytes(), kTlvBytes, sizeof(kTlvBytes)) == 0);
220 
221     SuccessOrQuit(dataset.AppendTlvsFrom(kTlvBytes, sizeof(kTlvBytes)));
222     VerifyOrQuit(dataset.GetLength() == 2 * sizeof(kTlvBytes));
223     VerifyOrQuit(memcmp(dataset.GetBytes(), kTlvBytes, sizeof(kTlvBytes)) == 0);
224     VerifyOrQuit(memcmp(dataset.GetBytes() + sizeof(kTlvBytes), kTlvBytes, sizeof(kTlvBytes)) == 0);
225 
226     VerifyOrQuit(dataset.ValidateTlvs() == kErrorParse);
227 
228     // Validate `IsSubsetOf()`
229 
230     SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes)));
231 
232     datasetInfo.Clear();
233     datasetInfo.mComponents.mIsPanIdPresent      = true;
234     datasetInfo.mComponents.mIsNetworkKeyPresent = true;
235     datasetInfo.mPanId                           = 0xface;
236     datasetInfo.mNetworkKey                      = kNetworkKey;
237 
238     dataset2.SetFrom(datasetInfo);
239 
240     SuccessOrQuit(dataset2.ValidateTlvs());
241     SuccessOrQuit(dataset.ValidateTlvs());
242 
243     VerifyOrQuit(dataset2.IsSubsetOf(dataset));
244     VerifyOrQuit(!dataset.IsSubsetOf(dataset2));
245 
246     datasetInfo.mComponents.mIsActiveTimestampPresent  = true;
247     datasetInfo.mComponents.mIsPendingTimestampPresent = true;
248     datasetInfo.mComponents.mIsDelayPresent            = true;
249     datasetInfo.mActiveTimestamp.mSeconds              = 0xffff;
250     datasetInfo.mPendingTimestamp.mSeconds             = 0x1000;
251     datasetInfo.mDelay                                 = 5000;
252     dataset2.SetFrom(datasetInfo);
253 
254     VerifyOrQuit(dataset2.IsSubsetOf(dataset));
255     VerifyOrQuit(!dataset.IsSubsetOf(dataset2));
256 
257     datasetInfo.mPanId = 0xcafe;
258     dataset2.SetFrom(datasetInfo);
259 
260     VerifyOrQuit(!dataset2.IsSubsetOf(dataset));
261     VerifyOrQuit(!dataset.IsSubsetOf(dataset2));
262 }
263 
264 } // namespace MeshCoP
265 } // namespace ot
266 
main(void)267 int main(void)
268 {
269     ot::MeshCoP::TestDataset();
270 
271     printf("All tests passed\n");
272     return 0;
273 }
274