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
CheckEphemeralKey(ThreadApiDBus * aApi)264 void CheckEphemeralKey(ThreadApiDBus *aApi)
265 {
266 bool enabled;
267
268 TEST_ASSERT(aApi->SetEphemeralKeyEnabled(false) == OTBR_ERROR_NONE);
269 TEST_ASSERT(aApi->GetEphemeralKeyEnabled(enabled) == OTBR_ERROR_NONE);
270 TEST_ASSERT(enabled == false);
271 TEST_ASSERT(aApi->SetEphemeralKeyEnabled(true) == OTBR_ERROR_NONE);
272 TEST_ASSERT(aApi->GetEphemeralKeyEnabled(enabled) == OTBR_ERROR_NONE);
273 TEST_ASSERT(enabled == true);
274 }
275
CheckBorderAgentInfo(const threadnetwork::TelemetryData_BorderAgentInfo & aBorderAgentInfo)276 void CheckBorderAgentInfo(const threadnetwork::TelemetryData_BorderAgentInfo &aBorderAgentInfo)
277 {
278 TEST_ASSERT(aBorderAgentInfo.border_agent_counters().epskc_activations() == 0);
279 TEST_ASSERT(aBorderAgentInfo.border_agent_counters().epskc_deactivation_clears() == 0);
280 TEST_ASSERT(aBorderAgentInfo.border_agent_counters().epskc_deactivation_timeouts() == 0);
281 TEST_ASSERT(aBorderAgentInfo.border_agent_counters().epskc_deactivation_max_attempts() == 0);
282 TEST_ASSERT(aBorderAgentInfo.border_agent_counters().epskc_deactivation_disconnects() == 0);
283 TEST_ASSERT(aBorderAgentInfo.border_agent_counters().epskc_invalid_ba_state_errors() == 0);
284 TEST_ASSERT(aBorderAgentInfo.border_agent_counters().epskc_invalid_args_errors() == 0);
285 TEST_ASSERT(aBorderAgentInfo.border_agent_counters().epskc_start_secure_session_errors() == 0);
286 TEST_ASSERT(aBorderAgentInfo.border_agent_counters().epskc_secure_session_successes() == 0);
287 TEST_ASSERT(aBorderAgentInfo.border_agent_counters().epskc_secure_session_failures() == 0);
288 TEST_ASSERT(aBorderAgentInfo.border_agent_counters().epskc_commissioner_petitions() == 0);
289 TEST_ASSERT(aBorderAgentInfo.border_agent_counters().pskc_secure_session_successes() == 0);
290 TEST_ASSERT(aBorderAgentInfo.border_agent_counters().pskc_secure_session_failures() == 0);
291 TEST_ASSERT(aBorderAgentInfo.border_agent_counters().pskc_commissioner_petitions() == 0);
292 TEST_ASSERT(aBorderAgentInfo.border_agent_counters().mgmt_active_get_reqs() == 0);
293 TEST_ASSERT(aBorderAgentInfo.border_agent_counters().mgmt_pending_get_reqs() == 0);
294 }
295
296 #if OTBR_ENABLE_TELEMETRY_DATA_API
CheckTelemetryData(ThreadApiDBus * aApi)297 void CheckTelemetryData(ThreadApiDBus *aApi)
298 {
299 std::vector<uint8_t> responseTelemetryDataBytes;
300 threadnetwork::TelemetryData telemetryData;
301
302 TEST_ASSERT(aApi->GetTelemetryData(responseTelemetryDataBytes) == OTBR_ERROR_NONE);
303 // Print TelemetryData proto in hex format.
304 printf("TelemetryData bytes in hex: ");
305 for (uint8_t byte : responseTelemetryDataBytes)
306 {
307 printf("%02x ", byte);
308 }
309 printf("\n");
310
311 TEST_ASSERT(telemetryData.ParseFromString(
312 std::string(responseTelemetryDataBytes.begin(), responseTelemetryDataBytes.end())));
313 TEST_ASSERT(telemetryData.wpan_stats().node_type() == threadnetwork::TelemetryData::NODE_TYPE_LEADER);
314 TEST_ASSERT(telemetryData.wpan_stats().channel() == 11);
315 TEST_ASSERT(telemetryData.wpan_stats().radio_tx_power() == 0);
316 TEST_ASSERT(telemetryData.wpan_stats().mac_cca_fail_rate() < 1e-6);
317 TEST_ASSERT(telemetryData.wpan_stats().phy_tx() > 0);
318 TEST_ASSERT(telemetryData.wpan_stats().phy_rx() > 0);
319 TEST_ASSERT(telemetryData.wpan_stats().ip_tx_success() > 0);
320 TEST_ASSERT(telemetryData.wpan_topo_full().rloc16() < 0xffff);
321 TEST_ASSERT(telemetryData.wpan_topo_full().network_data().size() > 0);
322 TEST_ASSERT(telemetryData.wpan_topo_full().partition_id() > 0);
323 TEST_ASSERT(telemetryData.wpan_topo_full().extended_pan_id() > 0);
324 TEST_ASSERT(telemetryData.wpan_topo_full().peer_br_count() == 0);
325 TEST_ASSERT(telemetryData.topo_entries_size() == 1);
326 TEST_ASSERT(telemetryData.topo_entries(0).rloc16() < 0xffff);
327 TEST_ASSERT(telemetryData.wpan_border_router().border_routing_counters().rs_tx_failure() == 0);
328 #if OTBR_ENABLE_SRP_ADVERTISING_PROXY
329 TEST_ASSERT(telemetryData.wpan_border_router().srp_server().state() ==
330 threadnetwork::TelemetryData::SRP_SERVER_STATE_RUNNING);
331 #endif
332 #if OTBR_ENABLE_DNSSD_DISCOVERY_PROXY
333 TEST_ASSERT(telemetryData.wpan_border_router().dns_server().response_counters().server_failure_count() == 0);
334 #endif
335 #if OTBR_ENABLE_TREL
336 TEST_ASSERT(telemetryData.wpan_border_router().trel_info().is_trel_enabled());
337 TEST_ASSERT(telemetryData.wpan_border_router().trel_info().has_counters());
338 TEST_ASSERT(telemetryData.wpan_border_router().trel_info().counters().trel_tx_packets() == 0);
339 TEST_ASSERT(telemetryData.wpan_border_router().trel_info().counters().trel_tx_bytes() == 0);
340 #endif
341 #if OTBR_ENABLE_BORDER_ROUTING
342 TEST_ASSERT(telemetryData.wpan_border_router().infra_link_info().name() == "lo");
343 TEST_ASSERT(telemetryData.wpan_border_router().infra_link_info().is_up());
344 TEST_ASSERT(telemetryData.wpan_border_router().infra_link_info().is_running());
345 TEST_ASSERT(!telemetryData.wpan_border_router().infra_link_info().is_multicast());
346 TEST_ASSERT(telemetryData.wpan_border_router().infra_link_info().link_local_address_count() == 0);
347 TEST_ASSERT(telemetryData.wpan_border_router().infra_link_info().unique_local_address_count() == 0);
348 TEST_ASSERT(telemetryData.wpan_border_router().infra_link_info().global_unicast_address_count() == 0);
349 TEST_ASSERT(telemetryData.wpan_border_router().infra_link_info().peer_br_count() == 0);
350 TEST_ASSERT(telemetryData.wpan_border_router().external_route_info().has_default_route_added() == false);
351 TEST_ASSERT(telemetryData.wpan_border_router().external_route_info().has_ula_route_added() == false);
352 TEST_ASSERT(telemetryData.wpan_border_router().external_route_info().has_others_route_added() == false);
353 #endif
354 TEST_ASSERT(telemetryData.wpan_border_router().mdns().service_registration_responses().success_count() > 0);
355 #if OTBR_ENABLE_NAT64
356 TEST_ASSERT(telemetryData.wpan_border_router().nat64_state().prefix_manager_state() ==
357 threadnetwork::TelemetryData::NAT64_STATE_NOT_RUNNING);
358 #endif
359 #if OTBR_ENABLE_DHCP6_PD
360 TEST_ASSERT(telemetryData.wpan_border_router().dhcp6_pd_state() ==
361 threadnetwork::TelemetryData::DHCP6_PD_STATE_DISABLED);
362 TEST_ASSERT(telemetryData.wpan_border_router().hashed_pd_prefix().empty());
363 TEST_ASSERT(telemetryData.wpan_border_router().pd_processed_ra_info().num_platform_ra_received() == 0);
364 TEST_ASSERT(telemetryData.wpan_border_router().pd_processed_ra_info().num_platform_pio_processed() == 0);
365 TEST_ASSERT(telemetryData.wpan_border_router().pd_processed_ra_info().last_platform_ra_msec() == 0);
366 #endif
367 TEST_ASSERT(telemetryData.wpan_rcp().rcp_interface_statistics().transferred_frames_count() > 0);
368 TEST_ASSERT(telemetryData.coex_metrics().count_tx_request() > 0);
369 #if OTBR_ENABLE_LINK_METRICS_TELEMETRY
370 TEST_ASSERT(telemetryData.low_power_metrics().link_metrics_entries_size() >= 0);
371 #endif
372 #if OTBR_ENABLE_BORDER_AGENT
373 CheckBorderAgentInfo(telemetryData.wpan_border_router().border_agent_info());
374 #endif
375 }
376 #endif
377
CheckCapabilities(ThreadApiDBus * aApi)378 void CheckCapabilities(ThreadApiDBus *aApi)
379 {
380 std::vector<uint8_t> responseCapabilitiesBytes;
381 otbr::Capabilities capabilities;
382
383 TEST_ASSERT(aApi->GetCapabilities(responseCapabilitiesBytes) == OTBR_ERROR_NONE);
384 // Print TelemetryData proto in hex format.
385 printf("TelemetryData bytes in hex: ");
386 for (uint8_t byte : responseCapabilitiesBytes)
387 {
388 printf("%02x ", byte);
389 }
390 printf("\n");
391
392 TEST_ASSERT(
393 capabilities.ParseFromString(std::string(responseCapabilitiesBytes.begin(), responseCapabilitiesBytes.end())));
394 TEST_ASSERT(capabilities.nat64() == OTBR_ENABLE_NAT64);
395 }
396
main()397 int main()
398 {
399 DBusError error;
400 UniqueDBusConnection connection;
401 std::unique_ptr<ThreadApiDBus> api;
402 uint64_t extpanid = 0xdead00beaf00cafe;
403 std::string region;
404 uint32_t scanDuration = 1000; // 1s for each channel
405 bool stepDone = false;
406 uint32_t preferredChannelMask = 0;
407
408 dbus_error_init(&error);
409 connection = UniqueDBusConnection(dbus_bus_get(DBUS_BUS_SYSTEM, &error));
410
411 VerifyOrExit(connection != nullptr);
412
413 VerifyOrExit(dbus_bus_register(connection.get(), &error) == true);
414
415 api = std::unique_ptr<ThreadApiDBus>(new ThreadApiDBus(connection.get()));
416
417 api->AddDeviceRoleHandler(
418 [](DeviceRole aRole) { printf("Device role changed to %d\n", static_cast<uint8_t>(aRole)); });
419
420 TEST_ASSERT(api->SetRadioRegion("US") == ClientError::ERROR_NONE);
421 TEST_ASSERT(api->GetRadioRegion(region) == ClientError::ERROR_NONE);
422 TEST_ASSERT(region == "US");
423
424 TEST_ASSERT(api->GetPreferredChannelMask(preferredChannelMask) == ClientError::ERROR_NONE);
425
426 api->EnergyScan(scanDuration, [&stepDone](const std::vector<EnergyScanResult> &aResult) {
427 TEST_ASSERT(!aResult.empty());
428 printf("Energy Scan:\n");
429 for (auto &result : aResult)
430 {
431 printf("channel %d rssi %d\n", result.mChannel, result.mMaxRssi);
432 }
433
434 stepDone = true;
435 });
436
437 CheckFeatureFlagUpdate(api.get());
438
439 while (!stepDone)
440 {
441 dbus_connection_read_write_dispatch(connection.get(), 0);
442 }
443
444 stepDone = false;
445
446 api->Scan([&api, extpanid, &stepDone](const std::vector<ActiveScanResult> &aResult) {
447 LinkModeConfig cfg = {true, false, true};
448 std::vector<uint8_t> networkKey = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
449 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
450 uint16_t channel = 11;
451
452 for (auto &&result : aResult)
453 {
454 printf("channel %d rssi %d\n", result.mChannel, result.mRssi);
455 }
456
457 api->SetLinkMode(cfg);
458 api->GetLinkMode(cfg);
459 printf("LinkMode %d %d %d\n", cfg.mRxOnWhenIdle, cfg.mDeviceType, cfg.mNetworkData);
460
461 cfg.mDeviceType = true;
462 api->SetLinkMode(cfg);
463
464 api->Attach("Test", 0x3456, extpanid, networkKey, {}, 1 << channel,
465 [&api, channel, extpanid, &stepDone](ClientError aError) {
466 printf("Attach result %d\n", static_cast<int>(aError));
467 sleep(20);
468 uint64_t extpanidCheck;
469 std::vector<uint8_t> activeDataset;
470
471 if (aError == OTBR_ERROR_NONE)
472 {
473 std::string name;
474 uint64_t extAddress = 0;
475 uint16_t rloc16 = 0xffff;
476 std::vector<uint8_t> networkData;
477 std::vector<uint8_t> stableNetworkData;
478 int8_t rssi;
479 int8_t txPower;
480 std::vector<otbr::DBus::ChildInfo> childTable;
481 std::vector<otbr::DBus::NeighborInfo> neighborTable;
482 uint32_t partitionId;
483 uint16_t channelResult;
484
485 TEST_ASSERT(api->GetChannel(channelResult) == OTBR_ERROR_NONE);
486 TEST_ASSERT(channelResult == channel);
487 TEST_ASSERT(api->GetNetworkName(name) == OTBR_ERROR_NONE);
488 TEST_ASSERT(api->GetExtPanId(extpanidCheck) == OTBR_ERROR_NONE);
489 TEST_ASSERT(api->GetRloc16(rloc16) == OTBR_ERROR_NONE);
490 TEST_ASSERT(api->GetExtendedAddress(extAddress) == OTBR_ERROR_NONE);
491 TEST_ASSERT(api->GetNetworkData(networkData) == OTBR_ERROR_NONE);
492 TEST_ASSERT(api->GetStableNetworkData(stableNetworkData) == OTBR_ERROR_NONE);
493 TEST_ASSERT(api->GetChildTable(childTable) == OTBR_ERROR_NONE);
494 TEST_ASSERT(api->GetNeighborTable(neighborTable) == OTBR_ERROR_NONE);
495 printf("neighborTable size %zu\n", neighborTable.size());
496 printf("childTable size %zu\n", childTable.size());
497 TEST_ASSERT(neighborTable.size() == 1);
498 TEST_ASSERT(childTable.size() == 1);
499 TEST_ASSERT(api->GetPartitionId(partitionId) == OTBR_ERROR_NONE);
500 TEST_ASSERT(api->GetInstantRssi(rssi) == OTBR_ERROR_NONE);
501 TEST_ASSERT(api->GetRadioTxPower(txPower) == OTBR_ERROR_NONE);
502 TEST_ASSERT(api->GetActiveDatasetTlvs(activeDataset) == OTBR_ERROR_NONE);
503 CheckSrpServerInfo(api.get());
504 CheckTrelInfo(api.get());
505 CheckMdnsInfo(api.get());
506 CheckDnssdCounters(api.get());
507 CheckNat64(api.get());
508 CheckEphemeralKey(api.get());
509 #if OTBR_ENABLE_TELEMETRY_DATA_API
510 CheckTelemetryData(api.get());
511 #endif
512 CheckCapabilities(api.get());
513 api->FactoryReset(nullptr);
514 TEST_ASSERT(api->GetNetworkName(name) == OTBR_ERROR_NONE);
515 TEST_ASSERT(rloc16 != 0xffff);
516 TEST_ASSERT(extAddress != 0);
517 TEST_ASSERT(!networkData.empty());
518 TEST_ASSERT(api->GetNeighborTable(neighborTable) == OTBR_ERROR_NONE);
519 TEST_ASSERT(neighborTable.empty());
520 }
521 if (aError != OTBR_ERROR_NONE || extpanidCheck != extpanid)
522 {
523 exit(-1);
524 }
525 TEST_ASSERT(api->SetActiveDatasetTlvs(activeDataset) == OTBR_ERROR_NONE);
526 api->Attach([&api, channel, extpanid, &stepDone](ClientError aErr) {
527 uint8_t routerId;
528 otbr::DBus::LeaderData leaderData;
529 uint8_t leaderWeight;
530 uint16_t channelResult;
531 uint64_t extpanidCheck;
532 Ip6Prefix prefix;
533 std::vector<TxtEntry> updatedTxtEntries{TxtEntry{"B", {97, 98, 99}}};
534
535 prefix.mPrefix = {0xfd, 0xcd, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
536 prefix.mLength = 64;
537
538 TEST_ASSERT(aErr == ClientError::ERROR_NONE);
539 TEST_ASSERT(api->GetChannel(channelResult) == OTBR_ERROR_NONE);
540 TEST_ASSERT(channelResult == channel);
541 TEST_ASSERT(api->GetExtPanId(extpanidCheck) == OTBR_ERROR_NONE);
542 TEST_ASSERT(extpanidCheck == extpanid);
543
544 TEST_ASSERT(api->GetLocalLeaderWeight(leaderWeight) == OTBR_ERROR_NONE);
545 TEST_ASSERT(api->GetLeaderData(leaderData) == OTBR_ERROR_NONE);
546 TEST_ASSERT(api->GetRouterId(routerId) == OTBR_ERROR_NONE);
547 TEST_ASSERT(routerId == leaderData.mLeaderRouterId);
548
549 TEST_ASSERT(api->UpdateVendorMeshCopTxtEntries(updatedTxtEntries) == OTBR_ERROR_NONE);
550
551 CheckExternalRoute(api.get(), prefix);
552 CheckOnMeshPrefix(api.get());
553
554 api->FactoryReset(nullptr);
555 TEST_ASSERT(api->JoinerStart("ABCDEF", "", "", "", "", "", nullptr) ==
556 ClientError::OT_ERROR_NOT_FOUND);
557 TEST_ASSERT(api->JoinerStart(
558 "ABCDEF", "", "", "", "", "", [&api, &stepDone](ClientError aJoinError) {
559 DeviceRole deviceRole;
560
561 TEST_ASSERT(aJoinError == ClientError::OT_ERROR_NOT_FOUND);
562
563 api->FactoryReset(nullptr);
564 api->GetDeviceRole(deviceRole);
565 TEST_ASSERT(deviceRole == otbr::DBus::OTBR_DEVICE_ROLE_DISABLED);
566
567 stepDone = true;
568 }) == ClientError::ERROR_NONE);
569 });
570 });
571 });
572
573 while (!stepDone)
574 {
575 dbus_connection_read_write_dispatch(connection.get(), 0);
576 }
577
578 exit:
579 dbus_error_free(&error);
580 return 0;
581 };
582