1 /*
2 * Copyright (c) 2020, 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 <assert.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include <memory>
35
36 #include <dbus/dbus.h>
37 #include <unistd.h>
38
39 #include "common/code_utils.hpp"
40 #include "dbus/client/thread_api_dbus.hpp"
41 #include "dbus/common/constants.hpp"
42 #if OTBR_ENABLE_TELEMETRY_DATA_API
43 #include "proto/thread_telemetry.pb.h"
44 #endif
45 #include "proto/capabilities.pb.h"
46
47 using otbr::DBus::ActiveScanResult;
48 using otbr::DBus::ClientError;
49 using otbr::DBus::DeviceRole;
50 using otbr::DBus::EnergyScanResult;
51 using otbr::DBus::ExternalRoute;
52 using otbr::DBus::Ip6Prefix;
53 using otbr::DBus::LinkModeConfig;
54 using otbr::DBus::OnMeshPrefix;
55 using otbr::DBus::SrpServerInfo;
56 using otbr::DBus::ThreadApiDBus;
57 using otbr::DBus::TxtEntry;
58
59 #if OTBR_ENABLE_DNSSD_DISCOVERY_PROXY
60 using otbr::DBus::DnssdCounters;
61 #endif
62
63 #if OTBR_ENABLE_NAT64
64 using otbr::DBus::Nat64AddressMapping;
65 using otbr::DBus::Nat64ComponentState;
66 using otbr::DBus::Nat64ErrorCounters;
67 using otbr::DBus::Nat64ProtocolCounters;
68 #endif
69
70 #define TEST_ASSERT(x) \
71 do \
72 { \
73 if (!(x)) \
74 { \
75 printf("Assert failed at %s:%d\n", __FILE__, __LINE__); \
76 exit(EXIT_FAILURE); \
77 } \
78 } while (false)
79
80 struct DBusConnectionDeleter
81 {
operator ()DBusConnectionDeleter82 void operator()(DBusConnection *aConnection) { dbus_connection_unref(aConnection); }
83 };
84
85 using UniqueDBusConnection = std::unique_ptr<DBusConnection, DBusConnectionDeleter>;
86
operator ==(const otbr::DBus::Ip6Prefix & aLhs,const otbr::DBus::Ip6Prefix & aRhs)87 static bool operator==(const otbr::DBus::Ip6Prefix &aLhs, const otbr::DBus::Ip6Prefix &aRhs)
88 {
89 bool prefixDataEquality = (aLhs.mPrefix.size() == aRhs.mPrefix.size()) &&
90 (memcmp(&aLhs.mPrefix[0], &aRhs.mPrefix[0], aLhs.mPrefix.size()) == 0);
91
92 return prefixDataEquality && aLhs.mLength == aRhs.mLength;
93 }
94
CheckExternalRoute(ThreadApiDBus * aApi,const Ip6Prefix & aPrefix)95 static void CheckExternalRoute(ThreadApiDBus *aApi, const Ip6Prefix &aPrefix)
96 {
97 ExternalRoute route = {};
98 std::vector<ExternalRoute> externalRouteTable;
99
100 route.mPrefix = aPrefix;
101 route.mStable = true;
102 route.mPreference = 0;
103
104 TEST_ASSERT(aApi->AddExternalRoute(route) == OTBR_ERROR_NONE);
105 sleep(10);
106 TEST_ASSERT(aApi->GetExternalRoutes(externalRouteTable) == OTBR_ERROR_NONE);
107 TEST_ASSERT(externalRouteTable.size() == 1);
108 TEST_ASSERT(externalRouteTable[0].mPrefix == aPrefix);
109 TEST_ASSERT(externalRouteTable[0].mPreference == 0);
110 TEST_ASSERT(externalRouteTable[0].mStable);
111 TEST_ASSERT(externalRouteTable[0].mNextHopIsThisDevice);
112
113 TEST_ASSERT(aApi->RemoveExternalRoute(aPrefix) == OTBR_ERROR_NONE);
114 sleep(10);
115 TEST_ASSERT(aApi->GetExternalRoutes(externalRouteTable) == OTBR_ERROR_NONE);
116 TEST_ASSERT(externalRouteTable.empty());
117 }
118
CheckOnMeshPrefix(ThreadApiDBus * aApi)119 static void CheckOnMeshPrefix(ThreadApiDBus *aApi)
120 {
121 OnMeshPrefix prefix = {};
122 std::vector<OnMeshPrefix> onMeshPrefixes;
123
124 prefix.mPrefix.mPrefix = {0xfd, 0xee, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
125 prefix.mPrefix.mLength = 64;
126
127 prefix.mPreference = 0;
128 prefix.mStable = true;
129
130 TEST_ASSERT(aApi->AddOnMeshPrefix(prefix) == OTBR_ERROR_NONE);
131 sleep(10);
132 TEST_ASSERT(aApi->GetOnMeshPrefixes(onMeshPrefixes) == OTBR_ERROR_NONE);
133 TEST_ASSERT(onMeshPrefixes.size() == 1);
134 TEST_ASSERT(onMeshPrefixes[0].mPrefix == prefix.mPrefix);
135 TEST_ASSERT(onMeshPrefixes[0].mPreference == 0);
136 TEST_ASSERT(onMeshPrefixes[0].mStable);
137
138 TEST_ASSERT(aApi->RemoveOnMeshPrefix(prefix.mPrefix) == OTBR_ERROR_NONE);
139 sleep(10);
140 TEST_ASSERT(aApi->GetOnMeshPrefixes(onMeshPrefixes) == OTBR_ERROR_NONE);
141 TEST_ASSERT(onMeshPrefixes.empty());
142 }
143
CheckFeatureFlagUpdate(ThreadApiDBus * aApi)144 static void CheckFeatureFlagUpdate(ThreadApiDBus *aApi)
145 {
146 OTBR_UNUSED_VARIABLE(aApi);
147 #if OTBR_ENABLE_FEATURE_FLAGS
148 std::vector<uint8_t> responseFeatureFlagBytes;
149 // Serialized bytes of feature_flag proto, with enable_nat64=true.
150 uint8_t requestRawBytes[] = {0x08, 0x01};
151 unsigned byteArraySize = sizeof(requestRawBytes) / sizeof(uint8_t);
152 std::vector<uint8_t> requestFeatureFlagBytes(&requestRawBytes[0], &requestRawBytes[byteArraySize]);
153 TEST_ASSERT(aApi->SetFeatureFlagListData(requestFeatureFlagBytes) == OTBR_ERROR_NONE);
154 TEST_ASSERT(aApi->GetFeatureFlagListData(responseFeatureFlagBytes) == OTBR_ERROR_NONE);
155 #endif
156 }
157
CheckSrpServerInfo(ThreadApiDBus * aApi)158 void CheckSrpServerInfo(ThreadApiDBus *aApi)
159 {
160 SrpServerInfo srpServerInfo;
161
162 TEST_ASSERT(aApi->GetSrpServerInfo(srpServerInfo) == OTBR_ERROR_NONE);
163 TEST_ASSERT(srpServerInfo.mState == otbr::DBus::OTBR_SRP_SERVER_STATE_RUNNING);
164 TEST_ASSERT(srpServerInfo.mPort != 0);
165 TEST_ASSERT(srpServerInfo.mHosts.mFreshCount == 0);
166 TEST_ASSERT(srpServerInfo.mHosts.mDeletedCount == 0);
167 TEST_ASSERT(srpServerInfo.mHosts.mLeaseTimeTotal == 0);
168 TEST_ASSERT(srpServerInfo.mHosts.mKeyLeaseTimeTotal == 0);
169 TEST_ASSERT(srpServerInfo.mHosts.mRemainingLeaseTimeTotal == 0);
170 TEST_ASSERT(srpServerInfo.mHosts.mRemainingKeyLeaseTimeTotal == 0);
171 TEST_ASSERT(srpServerInfo.mServices.mFreshCount == 0);
172 TEST_ASSERT(srpServerInfo.mServices.mDeletedCount == 0);
173 TEST_ASSERT(srpServerInfo.mServices.mLeaseTimeTotal == 0);
174 TEST_ASSERT(srpServerInfo.mServices.mKeyLeaseTimeTotal == 0);
175 TEST_ASSERT(srpServerInfo.mServices.mRemainingLeaseTimeTotal == 0);
176 TEST_ASSERT(srpServerInfo.mServices.mRemainingKeyLeaseTimeTotal == 0);
177 TEST_ASSERT(srpServerInfo.mResponseCounters.mSuccess == 0);
178 TEST_ASSERT(srpServerInfo.mResponseCounters.mServerFailure == 0);
179 TEST_ASSERT(srpServerInfo.mResponseCounters.mFormatError == 0);
180 TEST_ASSERT(srpServerInfo.mResponseCounters.mNameExists == 0);
181 TEST_ASSERT(srpServerInfo.mResponseCounters.mRefused == 0);
182 TEST_ASSERT(srpServerInfo.mResponseCounters.mOther == 0);
183 }
184
CheckTrelInfo(ThreadApiDBus * aApi)185 void CheckTrelInfo(ThreadApiDBus *aApi)
186 {
187 OTBR_UNUSED_VARIABLE(aApi);
188
189 #if OTBR_ENABLE_TREL
190 otbr::DBus::TrelInfo trelInfo;
191
192 TEST_ASSERT(aApi->GetTrelInfo(trelInfo) == OTBR_ERROR_NONE);
193 TEST_ASSERT(trelInfo.mEnabled);
194 TEST_ASSERT(trelInfo.mNumTrelPeers == 0);
195 TEST_ASSERT(trelInfo.mTrelCounters.mTxPackets == 0);
196 TEST_ASSERT(trelInfo.mTrelCounters.mTxBytes == 0);
197 TEST_ASSERT(trelInfo.mTrelCounters.mTxFailure == 0);
198 TEST_ASSERT(trelInfo.mTrelCounters.mRxPackets == 0);
199 TEST_ASSERT(trelInfo.mTrelCounters.mRxBytes == 0);
200 #endif
201 }
202
CheckDnssdCounters(ThreadApiDBus * aApi)203 void CheckDnssdCounters(ThreadApiDBus *aApi)
204 {
205 OTBR_UNUSED_VARIABLE(aApi);
206 #if OTBR_ENABLE_DNSSD_DISCOVERY_PROXY
207 otbr::DBus::DnssdCounters dnssdCounters;
208
209 TEST_ASSERT(aApi->GetDnssdCounters(dnssdCounters) == OTBR_ERROR_NONE);
210 TEST_ASSERT(dnssdCounters.mSuccessResponse == 0);
211 TEST_ASSERT(dnssdCounters.mServerFailureResponse == 0);
212 TEST_ASSERT(dnssdCounters.mFormatErrorResponse == 0);
213 TEST_ASSERT(dnssdCounters.mNameErrorResponse == 0);
214 TEST_ASSERT(dnssdCounters.mNotImplementedResponse == 0);
215 TEST_ASSERT(dnssdCounters.mOtherResponse == 0);
216 TEST_ASSERT(dnssdCounters.mResolvedBySrp == 0);
217 #endif
218 }
219
CheckMdnsInfo(ThreadApiDBus * aApi)220 void CheckMdnsInfo(ThreadApiDBus *aApi)
221 {
222 otbr::MdnsTelemetryInfo mdnsInfo;
223
224 TEST_ASSERT(aApi->GetMdnsTelemetryInfo(mdnsInfo) == OTBR_ERROR_NONE);
225
226 TEST_ASSERT(mdnsInfo.mServiceRegistrations.mSuccess > 0);
227 TEST_ASSERT(mdnsInfo.mServiceRegistrationEmaLatency > 0);
228 }
229
CheckNat64(ThreadApiDBus * aApi)230 void CheckNat64(ThreadApiDBus *aApi)
231 {
232 OTBR_UNUSED_VARIABLE(aApi);
233 #if OTBR_ENABLE_NAT64
234 {
235 Nat64ComponentState aState;
236 TEST_ASSERT(aApi->SetNat64Enabled(false) == OTBR_ERROR_NONE);
237 TEST_ASSERT(aApi->GetNat64State(aState) == OTBR_ERROR_NONE);
238 TEST_ASSERT(aState.mPrefixManagerState == OTBR_NAT64_STATE_NAME_DISABLED);
239 TEST_ASSERT(aState.mTranslatorState == OTBR_NAT64_STATE_NAME_DISABLED);
240
241 TEST_ASSERT(aApi->SetNat64Enabled(true) == OTBR_ERROR_NONE);
242 TEST_ASSERT(aApi->GetNat64State(aState) == OTBR_ERROR_NONE);
243 TEST_ASSERT(aState.mPrefixManagerState != OTBR_NAT64_STATE_NAME_DISABLED);
244 TEST_ASSERT(aState.mTranslatorState != OTBR_NAT64_STATE_NAME_DISABLED);
245 }
246
247 {
248 std::vector<Nat64AddressMapping> aMappings;
249 TEST_ASSERT(aApi->GetNat64Mappings(aMappings) == OTBR_ERROR_NONE);
250 }
251
252 {
253 Nat64ProtocolCounters aCounters;
254 TEST_ASSERT(aApi->GetNat64ProtocolCounters(aCounters) == OTBR_ERROR_NONE);
255 }
256
257 {
258 Nat64ErrorCounters aCounters;
259 TEST_ASSERT(aApi->GetNat64ErrorCounters(aCounters) == OTBR_ERROR_NONE);
260 }
261 #endif
262 }
263
264 #if OTBR_ENABLE_TELEMETRY_DATA_API
CheckTelemetryData(ThreadApiDBus * aApi)265 void CheckTelemetryData(ThreadApiDBus *aApi)
266 {
267 std::vector<uint8_t> responseTelemetryDataBytes;
268 threadnetwork::TelemetryData telemetryData;
269
270 TEST_ASSERT(aApi->GetTelemetryData(responseTelemetryDataBytes) == OTBR_ERROR_NONE);
271 // Print TelemetryData proto in hex format.
272 printf("TelemetryData bytes in hex: ");
273 for (uint8_t byte : responseTelemetryDataBytes)
274 {
275 printf("%02x ", byte);
276 }
277 printf("\n");
278
279 TEST_ASSERT(telemetryData.ParseFromString(
280 std::string(responseTelemetryDataBytes.begin(), responseTelemetryDataBytes.end())));
281 TEST_ASSERT(telemetryData.wpan_stats().node_type() == threadnetwork::TelemetryData::NODE_TYPE_LEADER);
282 TEST_ASSERT(telemetryData.wpan_stats().channel() == 11);
283 TEST_ASSERT(telemetryData.wpan_stats().radio_tx_power() == 0);
284 TEST_ASSERT(telemetryData.wpan_stats().mac_cca_fail_rate() < 1e-6);
285 TEST_ASSERT(telemetryData.wpan_stats().phy_tx() > 0);
286 TEST_ASSERT(telemetryData.wpan_stats().phy_rx() > 0);
287 TEST_ASSERT(telemetryData.wpan_stats().ip_tx_success() > 0);
288 TEST_ASSERT(telemetryData.wpan_topo_full().rloc16() > 0);
289 TEST_ASSERT(telemetryData.wpan_topo_full().network_data().size() > 0);
290 TEST_ASSERT(telemetryData.wpan_topo_full().partition_id() > 0);
291 TEST_ASSERT(telemetryData.wpan_topo_full().extended_pan_id() > 0);
292 TEST_ASSERT(telemetryData.topo_entries_size() == 1);
293 TEST_ASSERT(telemetryData.topo_entries(0).rloc16() > 0);
294 TEST_ASSERT(telemetryData.wpan_border_router().border_routing_counters().rs_tx_failure() == 0);
295 #if OTBR_ENABLE_SRP_ADVERTISING_PROXY
296 TEST_ASSERT(telemetryData.wpan_border_router().srp_server().state() ==
297 threadnetwork::TelemetryData::SRP_SERVER_STATE_RUNNING);
298 #endif
299 #if OTBR_ENABLE_DNSSD_DISCOVERY_PROXY
300 TEST_ASSERT(telemetryData.wpan_border_router().dns_server().response_counters().server_failure_count() == 0);
301 #endif
302 #if OTBR_ENABLE_TREL
303 TEST_ASSERT(telemetryData.wpan_border_router().trel_info().is_trel_enabled());
304 TEST_ASSERT(telemetryData.wpan_border_router().trel_info().has_counters());
305 TEST_ASSERT(telemetryData.wpan_border_router().trel_info().counters().trel_tx_packets() == 0);
306 TEST_ASSERT(telemetryData.wpan_border_router().trel_info().counters().trel_tx_bytes() == 0);
307 #endif
308 TEST_ASSERT(telemetryData.wpan_border_router().mdns().service_registration_responses().success_count() > 0);
309 #if OTBR_ENABLE_NAT64
310 TEST_ASSERT(telemetryData.wpan_border_router().nat64_state().prefix_manager_state() ==
311 threadnetwork::TelemetryData::NAT64_STATE_NOT_RUNNING);
312 #endif
313 #if OTBR_ENABLE_DHCP6_PD
314 TEST_ASSERT(!telemetryData.wpan_border_router().hashed_pd_prefix().empty());
315 #endif
316 TEST_ASSERT(telemetryData.wpan_rcp().rcp_interface_statistics().transferred_frames_count() > 0);
317 TEST_ASSERT(telemetryData.coex_metrics().count_tx_request() > 0);
318 #if OTBR_ENABLE_LINK_METRICS_TELEMETRY
319 TEST_ASSERT(telemetryData.low_power_metrics().link_metrics_entries_size() >= 0);
320 #endif
321 }
322 #endif
323
CheckCapabilities(ThreadApiDBus * aApi)324 void CheckCapabilities(ThreadApiDBus *aApi)
325 {
326 std::vector<uint8_t> responseCapabilitiesBytes;
327 otbr::Capabilities capabilities;
328
329 TEST_ASSERT(aApi->GetCapabilities(responseCapabilitiesBytes) == OTBR_ERROR_NONE);
330 // Print TelemetryData proto in hex format.
331 printf("TelemetryData bytes in hex: ");
332 for (uint8_t byte : responseCapabilitiesBytes)
333 {
334 printf("%02x ", byte);
335 }
336 printf("\n");
337
338 TEST_ASSERT(
339 capabilities.ParseFromString(std::string(responseCapabilitiesBytes.begin(), responseCapabilitiesBytes.end())));
340 TEST_ASSERT(capabilities.nat64() == OTBR_ENABLE_NAT64);
341 }
342
main()343 int main()
344 {
345 DBusError error;
346 UniqueDBusConnection connection;
347 std::unique_ptr<ThreadApiDBus> api;
348 uint64_t extpanid = 0xdead00beaf00cafe;
349 std::string region;
350 uint32_t scanDuration = 1000; // 1s for each channel
351 bool stepDone = false;
352 uint32_t preferredChannelMask = 0;
353
354 dbus_error_init(&error);
355 connection = UniqueDBusConnection(dbus_bus_get(DBUS_BUS_SYSTEM, &error));
356
357 VerifyOrExit(connection != nullptr);
358
359 VerifyOrExit(dbus_bus_register(connection.get(), &error) == true);
360
361 api = std::unique_ptr<ThreadApiDBus>(new ThreadApiDBus(connection.get()));
362
363 api->AddDeviceRoleHandler(
364 [](DeviceRole aRole) { printf("Device role changed to %d\n", static_cast<uint8_t>(aRole)); });
365
366 TEST_ASSERT(api->SetRadioRegion("US") == ClientError::ERROR_NONE);
367 TEST_ASSERT(api->GetRadioRegion(region) == ClientError::ERROR_NONE);
368 TEST_ASSERT(region == "US");
369
370 TEST_ASSERT(api->GetPreferredChannelMask(preferredChannelMask) == ClientError::ERROR_NONE);
371
372 api->EnergyScan(scanDuration, [&stepDone](const std::vector<EnergyScanResult> &aResult) {
373 TEST_ASSERT(!aResult.empty());
374 printf("Energy Scan:\n");
375 for (auto &result : aResult)
376 {
377 printf("channel %d rssi %d\n", result.mChannel, result.mMaxRssi);
378 }
379
380 stepDone = true;
381 });
382
383 CheckFeatureFlagUpdate(api.get());
384
385 while (!stepDone)
386 {
387 dbus_connection_read_write_dispatch(connection.get(), 0);
388 }
389
390 stepDone = false;
391
392 api->Scan([&api, extpanid, &stepDone](const std::vector<ActiveScanResult> &aResult) {
393 LinkModeConfig cfg = {true, false, true};
394 std::vector<uint8_t> networkKey = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
395 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
396 uint16_t channel = 11;
397
398 for (auto &&result : aResult)
399 {
400 printf("channel %d rssi %d\n", result.mChannel, result.mRssi);
401 }
402
403 api->SetLinkMode(cfg);
404 api->GetLinkMode(cfg);
405 printf("LinkMode %d %d %d\n", cfg.mRxOnWhenIdle, cfg.mDeviceType, cfg.mNetworkData);
406
407 cfg.mDeviceType = true;
408 api->SetLinkMode(cfg);
409
410 api->Attach("Test", 0x3456, extpanid, networkKey, {}, 1 << channel,
411 [&api, channel, extpanid, &stepDone](ClientError aError) {
412 printf("Attach result %d\n", static_cast<int>(aError));
413 sleep(20);
414 uint64_t extpanidCheck;
415 std::vector<uint8_t> activeDataset;
416
417 if (aError == OTBR_ERROR_NONE)
418 {
419 std::string name;
420 uint64_t extAddress = 0;
421 uint16_t rloc16 = 0xffff;
422 std::vector<uint8_t> networkData;
423 std::vector<uint8_t> stableNetworkData;
424 int8_t rssi;
425 int8_t txPower;
426 std::vector<otbr::DBus::ChildInfo> childTable;
427 std::vector<otbr::DBus::NeighborInfo> neighborTable;
428 uint32_t partitionId;
429 uint16_t channelResult;
430
431 TEST_ASSERT(api->GetChannel(channelResult) == OTBR_ERROR_NONE);
432 TEST_ASSERT(channelResult == channel);
433 TEST_ASSERT(api->GetNetworkName(name) == OTBR_ERROR_NONE);
434 TEST_ASSERT(api->GetExtPanId(extpanidCheck) == OTBR_ERROR_NONE);
435 TEST_ASSERT(api->GetRloc16(rloc16) == OTBR_ERROR_NONE);
436 TEST_ASSERT(api->GetExtendedAddress(extAddress) == OTBR_ERROR_NONE);
437 TEST_ASSERT(api->GetNetworkData(networkData) == OTBR_ERROR_NONE);
438 TEST_ASSERT(api->GetStableNetworkData(stableNetworkData) == OTBR_ERROR_NONE);
439 TEST_ASSERT(api->GetChildTable(childTable) == OTBR_ERROR_NONE);
440 TEST_ASSERT(api->GetNeighborTable(neighborTable) == OTBR_ERROR_NONE);
441 printf("neighborTable size %zu\n", neighborTable.size());
442 printf("childTable size %zu\n", childTable.size());
443 TEST_ASSERT(neighborTable.size() == 1);
444 TEST_ASSERT(childTable.size() == 1);
445 TEST_ASSERT(api->GetPartitionId(partitionId) == OTBR_ERROR_NONE);
446 TEST_ASSERT(api->GetInstantRssi(rssi) == OTBR_ERROR_NONE);
447 TEST_ASSERT(api->GetRadioTxPower(txPower) == OTBR_ERROR_NONE);
448 TEST_ASSERT(api->GetActiveDatasetTlvs(activeDataset) == OTBR_ERROR_NONE);
449 CheckSrpServerInfo(api.get());
450 CheckTrelInfo(api.get());
451 CheckMdnsInfo(api.get());
452 CheckDnssdCounters(api.get());
453 CheckNat64(api.get());
454 #if OTBR_ENABLE_TELEMETRY_DATA_API
455 CheckTelemetryData(api.get());
456 #endif
457 CheckCapabilities(api.get());
458 api->FactoryReset(nullptr);
459 TEST_ASSERT(api->GetNetworkName(name) == OTBR_ERROR_NONE);
460 TEST_ASSERT(rloc16 != 0xffff);
461 TEST_ASSERT(extAddress != 0);
462 TEST_ASSERT(!networkData.empty());
463 TEST_ASSERT(api->GetNeighborTable(neighborTable) == OTBR_ERROR_NONE);
464 TEST_ASSERT(neighborTable.empty());
465 }
466 if (aError != OTBR_ERROR_NONE || extpanidCheck != extpanid)
467 {
468 exit(-1);
469 }
470 TEST_ASSERT(api->SetActiveDatasetTlvs(activeDataset) == OTBR_ERROR_NONE);
471 api->Attach([&api, channel, extpanid, &stepDone](ClientError aErr) {
472 uint8_t routerId;
473 otbr::DBus::LeaderData leaderData;
474 uint8_t leaderWeight;
475 uint16_t channelResult;
476 uint64_t extpanidCheck;
477 Ip6Prefix prefix;
478 std::vector<TxtEntry> updatedTxtEntries{TxtEntry{"B", {97, 98, 99}}};
479
480 prefix.mPrefix = {0xfd, 0xcd, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
481 prefix.mLength = 64;
482
483 TEST_ASSERT(aErr == ClientError::ERROR_NONE);
484 TEST_ASSERT(api->GetChannel(channelResult) == OTBR_ERROR_NONE);
485 TEST_ASSERT(channelResult == channel);
486 TEST_ASSERT(api->GetExtPanId(extpanidCheck) == OTBR_ERROR_NONE);
487 TEST_ASSERT(extpanidCheck == extpanid);
488
489 TEST_ASSERT(api->GetLocalLeaderWeight(leaderWeight) == OTBR_ERROR_NONE);
490 TEST_ASSERT(api->GetLeaderData(leaderData) == OTBR_ERROR_NONE);
491 TEST_ASSERT(api->GetRouterId(routerId) == OTBR_ERROR_NONE);
492 TEST_ASSERT(routerId == leaderData.mLeaderRouterId);
493
494 TEST_ASSERT(api->UpdateVendorMeshCopTxtEntries(updatedTxtEntries) == OTBR_ERROR_NONE);
495
496 CheckExternalRoute(api.get(), prefix);
497 CheckOnMeshPrefix(api.get());
498
499 api->FactoryReset(nullptr);
500 TEST_ASSERT(api->JoinerStart("ABCDEF", "", "", "", "", "", nullptr) ==
501 ClientError::OT_ERROR_NOT_FOUND);
502 TEST_ASSERT(api->JoinerStart(
503 "ABCDEF", "", "", "", "", "", [&api, &stepDone](ClientError aJoinError) {
504 DeviceRole deviceRole;
505
506 TEST_ASSERT(aJoinError == ClientError::OT_ERROR_NOT_FOUND);
507
508 api->FactoryReset(nullptr);
509 api->GetDeviceRole(deviceRole);
510 TEST_ASSERT(deviceRole == otbr::DBus::OTBR_DEVICE_ROLE_DISABLED);
511
512 stepDone = true;
513 }) == ClientError::ERROR_NONE);
514 });
515 });
516 });
517
518 while (!stepDone)
519 {
520 dbus_connection_read_write_dispatch(connection.get(), 0);
521 }
522
523 exit:
524 dbus_error_free(&error);
525 return 0;
526 };
527