2 * Copyright (c) 2020, The OpenThread Authors.
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.
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.
36 #include <dbus/dbus.h>
39 #include "common/code_utils.hpp"
40 #include "dbus/client/thread_api_dbus.hpp"
41 #include "dbus/common/constants.hpp"
43 using otbr::DBus::ActiveScanResult;
44 using otbr::DBus::ClientError;
45 using otbr::DBus::DeviceRole;
46 using otbr::DBus::ExternalRoute;
47 using otbr::DBus::Ip6Prefix;
48 using otbr::DBus::LinkModeConfig;
49 using otbr::DBus::OnMeshPrefix;
50 using otbr::DBus::ThreadApiDBus;
52 #define TEST_ASSERT(x) \
57 printf("Assert failed at %s:%d\n", __FILE__, __LINE__); \
62 struct DBusConnectionDeleter
64 void operator()(DBusConnection *aConnection) { dbus_connection_unref(aConnection); }
67 using UniqueDBusConnection = std::unique_ptr<DBusConnection, DBusConnectionDeleter>;
69 static bool operator==(const otbr::DBus::Ip6Prefix &aLhs, const otbr::DBus::Ip6Prefix &aRhs)
71 bool prefixDataEquality = (aLhs.mPrefix.size() == aRhs.mPrefix.size()) &&
72 (memcmp(&aLhs.mPrefix[0], &aRhs.mPrefix[0], aLhs.mPrefix.size()) == 0);
74 return prefixDataEquality && aLhs.mLength == aRhs.mLength;
77 static void CheckExternalRoute(ThreadApiDBus *aApi, const Ip6Prefix &aPrefix)
80 std::vector<ExternalRoute> externalRouteTable;
82 route.mPrefix = aPrefix;
84 route.mPreference = 0;
86 TEST_ASSERT(aApi->AddExternalRoute(route) == OTBR_ERROR_NONE);
87 TEST_ASSERT(aApi->GetExternalRoutes(externalRouteTable) == OTBR_ERROR_NONE);
88 TEST_ASSERT(externalRouteTable.size() == 1);
89 TEST_ASSERT(externalRouteTable[0].mPrefix == aPrefix);
90 TEST_ASSERT(externalRouteTable[0].mPreference == 0);
91 TEST_ASSERT(externalRouteTable[0].mStable);
92 TEST_ASSERT(externalRouteTable[0].mNextHopIsThisDevice);
93 TEST_ASSERT(aApi->RemoveExternalRoute(aPrefix) == OTBR_ERROR_NONE);
99 UniqueDBusConnection connection;
100 std::unique_ptr<ThreadApiDBus> api;
101 uint64_t extpanid = 0xdead00beaf00cafe;
104 dbus_error_init(&error);
105 connection = UniqueDBusConnection(dbus_bus_get(DBUS_BUS_SYSTEM, &error));
107 VerifyOrExit(connection != nullptr);
109 VerifyOrExit(dbus_bus_register(connection.get(), &error) == true);
111 api = std::unique_ptr<ThreadApiDBus>(new ThreadApiDBus(connection.get()));
113 api->AddDeviceRoleHandler(
114 [](DeviceRole aRole) { printf("Device role changed to %d\n", static_cast<uint8_t>(aRole)); });
116 TEST_ASSERT(api->SetRadioRegion("US") == ClientError::ERROR_NONE);
117 TEST_ASSERT(api->GetRadioRegion(region) == ClientError::ERROR_NONE);
118 TEST_ASSERT(region == "US");
120 api->Scan([&api, extpanid](const std::vector<ActiveScanResult> &aResult) {
121 LinkModeConfig cfg = {true, false, true};
122 std::vector<uint8_t> masterKey = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
123 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
124 uint16_t channel = 11;
126 for (auto &&result : aResult)
128 printf("%s channel %d rssi %d\n", result.mNetworkName.c_str(), result.mChannel, result.mRssi);
131 api->SetLinkMode(cfg);
132 api->GetLinkMode(cfg);
133 printf("LinkMode %d %d %d\n", cfg.mRxOnWhenIdle, cfg.mDeviceType, cfg.mNetworkData);
135 cfg.mDeviceType = true;
136 api->SetLinkMode(cfg);
138 api->Attach("Test", 0x3456, extpanid, masterKey, {}, 1 << channel,
139 [&api, channel, extpanid](ClientError aError) {
140 printf("Attach result %d\n", static_cast<int>(aError));
142 uint64_t extpanidCheck;
143 std::vector<uint8_t> activeDataset;
145 if (aError == OTBR_ERROR_NONE)
148 uint64_t extAddress = 0;
149 uint16_t rloc16 = 0xffff;
150 std::vector<uint8_t> networkData;
151 std::vector<uint8_t> stableNetworkData;
154 std::vector<otbr::DBus::ChildInfo> childTable;
155 std::vector<otbr::DBus::NeighborInfo> neighborTable;
156 uint32_t partitionId;
157 uint16_t channelResult;
159 TEST_ASSERT(api->GetChannel(channelResult) == OTBR_ERROR_NONE);
160 TEST_ASSERT(channelResult == channel);
161 TEST_ASSERT(api->GetNetworkName(name) == OTBR_ERROR_NONE);
162 TEST_ASSERT(api->GetExtPanId(extpanidCheck) == OTBR_ERROR_NONE);
163 TEST_ASSERT(api->GetRloc16(rloc16) == OTBR_ERROR_NONE);
164 TEST_ASSERT(api->GetExtendedAddress(extAddress) == OTBR_ERROR_NONE);
165 TEST_ASSERT(api->GetNetworkData(networkData) == OTBR_ERROR_NONE);
166 TEST_ASSERT(api->GetStableNetworkData(stableNetworkData) == OTBR_ERROR_NONE);
167 TEST_ASSERT(api->GetChildTable(childTable) == OTBR_ERROR_NONE);
168 TEST_ASSERT(api->GetNeighborTable(neighborTable) == OTBR_ERROR_NONE);
169 printf("neighborTable size %zu\n", neighborTable.size());
170 printf("childTable size %zu\n", childTable.size());
171 TEST_ASSERT(neighborTable.size() == 1);
172 TEST_ASSERT(childTable.size() == 1);
173 TEST_ASSERT(api->GetPartitionId(partitionId) == OTBR_ERROR_NONE);
174 TEST_ASSERT(api->GetInstantRssi(rssi) == OTBR_ERROR_NONE);
175 TEST_ASSERT(api->GetRadioTxPower(txPower) == OTBR_ERROR_NONE);
176 TEST_ASSERT(api->GetActiveDatasetTlvs(activeDataset) == OTBR_ERROR_NONE);
177 api->FactoryReset(nullptr);
179 TEST_ASSERT(api->GetNetworkName(name) == OTBR_ERROR_NONE);
180 TEST_ASSERT(rloc16 != 0xffff);
181 TEST_ASSERT(extAddress != 0);
182 TEST_ASSERT(!networkData.empty());
183 TEST_ASSERT(api->GetNeighborTable(neighborTable) == OTBR_ERROR_NONE);
184 TEST_ASSERT(neighborTable.empty());
186 if (aError != OTBR_ERROR_NONE || extpanidCheck != extpanid)
190 TEST_ASSERT(api->SetActiveDatasetTlvs(activeDataset) == OTBR_ERROR_NONE);
191 api->Attach([&api, channel, extpanid](ClientError aErr) {
193 otbr::DBus::LeaderData leaderData;
194 uint8_t leaderWeight;
195 uint16_t channelResult;
196 uint64_t extpanidCheck;
198 OnMeshPrefix onMeshPrefix = {};
200 prefix.mPrefix = {0xfd, 0xcd, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
203 onMeshPrefix.mPrefix = prefix;
204 onMeshPrefix.mPreference = 0;
205 onMeshPrefix.mStable = true;
207 TEST_ASSERT(aErr == ClientError::ERROR_NONE);
208 TEST_ASSERT(api->GetChannel(channelResult) == OTBR_ERROR_NONE);
209 TEST_ASSERT(channelResult == channel);
210 TEST_ASSERT(api->GetExtPanId(extpanidCheck) == OTBR_ERROR_NONE);
211 TEST_ASSERT(extpanidCheck == extpanid);
213 TEST_ASSERT(api->GetLocalLeaderWeight(leaderWeight) == OTBR_ERROR_NONE);
214 TEST_ASSERT(api->GetLeaderData(leaderData) == OTBR_ERROR_NONE);
215 TEST_ASSERT(api->GetRouterId(routerId) == OTBR_ERROR_NONE);
216 TEST_ASSERT(routerId == leaderData.mLeaderRouterId);
218 CheckExternalRoute(api.get(), prefix);
219 TEST_ASSERT(api->AddOnMeshPrefix(onMeshPrefix) == OTBR_ERROR_NONE);
220 TEST_ASSERT(api->RemoveOnMeshPrefix(onMeshPrefix.mPrefix) == OTBR_ERROR_NONE);
222 api->FactoryReset(nullptr);
224 TEST_ASSERT(api->JoinerStart("ABCDEF", "", "", "", "", "", nullptr) ==
225 ClientError::OT_ERROR_NOT_FOUND);
226 TEST_ASSERT(api->JoinerStart("ABCDEF", "", "", "", "", "", [](ClientError aJoinError) {
227 TEST_ASSERT(aJoinError == ClientError::OT_ERROR_NOT_FOUND);
229 }) == ClientError::ERROR_NONE);
236 dbus_connection_read_write_dispatch(connection.get(), 0);
240 dbus_error_free(&error);