1 /*
2 * Copyright (c) 2019, 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 <gtest/gtest.h>
30 #include <string.h>
31
32 #include "dbus/common/dbus_message_helper.hpp"
33
34 using std::array;
35 using std::string;
36 using std::tuple;
37 using std::vector;
38
39 using otbr::DBus::DBusMessageEncode;
40 using otbr::DBus::DBusMessageExtract;
41 using otbr::DBus::DBusMessageToTuple;
42 using otbr::DBus::TupleToDBusMessage;
43
44 struct TestStruct
45 {
46 uint8_t tag;
47 uint32_t val;
48 std::string name;
49 };
50
51 namespace otbr {
52 namespace DBus {
53 template <> struct DBusTypeTrait<TestStruct>
54 {
55 static constexpr const char *TYPE_AS_STRING =
56 //{uint8, uint32, string}
57 "(yus)";
58 };
59 } // namespace DBus
60 } // namespace otbr
61
operator ==(const TestStruct & aLhs,const TestStruct & aRhs)62 bool operator==(const TestStruct &aLhs, const TestStruct &aRhs)
63 {
64 return aLhs.tag == aRhs.tag && aLhs.val == aRhs.val && aLhs.name == aRhs.name;
65 }
66
operator ==(const otbr::DBus::ChannelQuality & aLhs,const otbr::DBus::ChannelQuality & aRhs)67 bool operator==(const otbr::DBus::ChannelQuality &aLhs, const otbr::DBus::ChannelQuality &aRhs)
68 {
69 return aLhs.mChannel == aRhs.mChannel && aLhs.mOccupancy == aRhs.mOccupancy;
70 }
71
operator ==(const otbr::DBus::ChildInfo & aLhs,const otbr::DBus::ChildInfo & aRhs)72 bool operator==(const otbr::DBus::ChildInfo &aLhs, const otbr::DBus::ChildInfo &aRhs)
73 {
74 return aLhs.mExtAddress == aRhs.mExtAddress && aLhs.mTimeout == aRhs.mTimeout && aLhs.mAge == aRhs.mAge &&
75 aLhs.mRloc16 == aRhs.mRloc16 && aLhs.mChildId == aRhs.mChildId &&
76 aLhs.mNetworkDataVersion == aRhs.mNetworkDataVersion && aLhs.mLinkQualityIn == aRhs.mLinkQualityIn &&
77 aLhs.mAverageRssi == aRhs.mAverageRssi && aLhs.mLastRssi == aRhs.mLastRssi &&
78 aLhs.mFrameErrorRate == aRhs.mFrameErrorRate && aLhs.mMessageErrorRate == aRhs.mMessageErrorRate &&
79 aLhs.mRxOnWhenIdle == aRhs.mRxOnWhenIdle && aLhs.mFullThreadDevice == aRhs.mFullThreadDevice &&
80 aLhs.mFullNetworkData == aRhs.mFullNetworkData && aLhs.mIsStateRestoring == aRhs.mIsStateRestoring;
81 }
82
operator ==(const otbr::DBus::NeighborInfo & aLhs,const otbr::DBus::NeighborInfo & aRhs)83 bool operator==(const otbr::DBus::NeighborInfo &aLhs, const otbr::DBus::NeighborInfo &aRhs)
84 {
85 return aLhs.mExtAddress == aRhs.mExtAddress && aLhs.mAge == aRhs.mAge && aLhs.mRloc16 == aRhs.mRloc16 &&
86 aLhs.mLinkFrameCounter == aRhs.mLinkFrameCounter && aLhs.mMleFrameCounter == aRhs.mMleFrameCounter &&
87 aLhs.mLinkQualityIn == aRhs.mLinkQualityIn && aLhs.mAverageRssi == aRhs.mAverageRssi &&
88 aLhs.mLastRssi == aRhs.mLastRssi && aLhs.mFrameErrorRate == aRhs.mFrameErrorRate &&
89 aLhs.mMessageErrorRate == aRhs.mMessageErrorRate && aLhs.mRxOnWhenIdle == aRhs.mRxOnWhenIdle &&
90 aLhs.mFullThreadDevice == aRhs.mFullThreadDevice && aLhs.mFullNetworkData == aRhs.mFullNetworkData &&
91 aLhs.mIsChild == aRhs.mIsChild;
92 }
93
operator ==(const otbr::DBus::LeaderData & aLhs,const otbr::DBus::LeaderData & aRhs)94 bool operator==(const otbr::DBus::LeaderData &aLhs, const otbr::DBus::LeaderData &aRhs)
95 {
96 return aLhs.mPartitionId == aRhs.mPartitionId && aLhs.mWeighting == aRhs.mWeighting &&
97 aLhs.mDataVersion == aRhs.mDataVersion && aLhs.mStableDataVersion == aRhs.mStableDataVersion &&
98 aLhs.mLeaderRouterId == aRhs.mLeaderRouterId;
99 }
100
operator ==(const otbr::DBus::ActiveScanResult & aLhs,const otbr::DBus::ActiveScanResult & aRhs)101 bool operator==(const otbr::DBus::ActiveScanResult &aLhs, const otbr::DBus::ActiveScanResult &aRhs)
102 {
103 return aLhs.mExtAddress == aRhs.mExtAddress && aLhs.mNetworkName == aRhs.mNetworkName &&
104 aLhs.mExtendedPanId == aRhs.mExtendedPanId && aLhs.mSteeringData == aRhs.mSteeringData &&
105 aLhs.mPanId == aRhs.mPanId && aLhs.mJoinerUdpPort == aRhs.mJoinerUdpPort && aLhs.mChannel == aRhs.mChannel &&
106 aLhs.mRssi == aRhs.mRssi && aLhs.mLqi == aRhs.mLqi && aLhs.mVersion == aRhs.mVersion &&
107 aLhs.mIsNative == aRhs.mIsNative;
108 }
109
operator ==(const otbr::DBus::Ip6Prefix & aLhs,const otbr::DBus::Ip6Prefix & aRhs)110 bool operator==(const otbr::DBus::Ip6Prefix &aLhs, const otbr::DBus::Ip6Prefix &aRhs)
111 {
112 bool prefixDataEquality = (aLhs.mPrefix.size() == aRhs.mPrefix.size()) &&
113 (memcmp(&aLhs.mPrefix[0], &aRhs.mPrefix[0], aLhs.mPrefix.size()) == 0);
114
115 return prefixDataEquality && aLhs.mLength == aRhs.mLength;
116 }
117
operator ==(const otbr::DBus::ExternalRoute & aLhs,const otbr::DBus::ExternalRoute & aRhs)118 bool operator==(const otbr::DBus::ExternalRoute &aLhs, const otbr::DBus::ExternalRoute &aRhs)
119 {
120 return aLhs.mPrefix == aRhs.mPrefix && aLhs.mRloc16 == aRhs.mRloc16 && aLhs.mPreference == aRhs.mPreference &&
121 aLhs.mStable == aRhs.mStable && aLhs.mNextHopIsThisDevice == aRhs.mNextHopIsThisDevice;
122 }
123
DBusMessageEncode(DBusMessageIter * aIter,const TestStruct & aValue)124 inline otbrError DBusMessageEncode(DBusMessageIter *aIter, const TestStruct &aValue)
125 {
126 otbrError error = OTBR_ERROR_DBUS;
127 DBusMessageIter sub;
128 VerifyOrExit(dbus_message_iter_open_container(aIter, DBUS_TYPE_STRUCT, nullptr, &sub), error = OTBR_ERROR_DBUS);
129
130 SuccessOrExit(DBusMessageEncode(&sub, aValue.tag));
131 SuccessOrExit(DBusMessageEncode(&sub, aValue.val));
132 SuccessOrExit(DBusMessageEncode(&sub, aValue.name));
133 VerifyOrExit(dbus_message_iter_close_container(aIter, &sub), error = OTBR_ERROR_DBUS);
134 error = OTBR_ERROR_NONE;
135
136 exit:
137 return error;
138 }
139
DBusMessageExtract(DBusMessageIter * aIter,TestStruct & aValue)140 inline otbrError DBusMessageExtract(DBusMessageIter *aIter, TestStruct &aValue)
141 {
142 otbrError error = OTBR_ERROR_DBUS;
143 DBusMessageIter sub;
144
145 VerifyOrExit(dbus_message_iter_get_arg_type(aIter) == DBUS_TYPE_STRUCT, error = OTBR_ERROR_DBUS);
146 dbus_message_iter_recurse(aIter, &sub);
147 SuccessOrExit(DBusMessageExtract(&sub, aValue.tag));
148 SuccessOrExit(DBusMessageExtract(&sub, aValue.val));
149 SuccessOrExit(DBusMessageExtract(&sub, aValue.name));
150
151 dbus_message_iter_next(aIter);
152 error = OTBR_ERROR_NONE;
153
154 exit:
155 return error;
156 }
157
TEST_GROUP(DBusMessage)158 TEST_GROUP(DBusMessage){};
159
TEST(DBusMessage,TestVectorMessage)160 TEST(DBusMessage, TestVectorMessage)
161 {
162 DBusMessage *msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
163 tuple<vector<uint8_t>, vector<uint16_t>, vector<uint32_t>, vector<uint64_t>, vector<int16_t>, vector<int32_t>,
164 vector<int64_t>>
165 setVals({0, 1}, {2, 3}, {4, 5}, {6, 7, 8}, {}, {9, 10}, {11, 12});
166
167 tuple<vector<uint8_t>, vector<uint16_t>, vector<uint32_t>, vector<uint64_t>, vector<int16_t>, vector<int32_t>,
168 vector<int64_t>>
169 getVals({}, {}, {}, {}, {}, {}, {});
170 EXPECT_NE(msg, nullptr);
171
172 EXPECT_EQ(TupleToDBusMessage(*msg, setVals), OTBR_ERROR_NONE);
173 EXPECT_EQ(DBusMessageToTuple(*msg, getVals), OTBR_ERROR_NONE);
174
175 EXPECT_EQ(setVals, getVals);
176
177 dbus_message_unref(msg);
178 }
179
TEST(DBusMessage,TestArrayMessage)180 TEST(DBusMessage, TestArrayMessage)
181 {
182 DBusMessage *msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
183 tuple<array<uint8_t, 4>> setVals({1, 2, 3, 4});
184 tuple<array<uint8_t, 4>> getVals({0, 0, 0, 0});
185
186 EXPECT_NE(msg, nullptr);
187
188 EXPECT_EQ(TupleToDBusMessage(*msg, setVals), OTBR_ERROR_NONE);
189 EXPECT_EQ(DBusMessageToTuple(*msg, getVals), OTBR_ERROR_NONE);
190
191 EXPECT_EQ(setVals, getVals);
192
193 dbus_message_unref(msg);
194 }
195
TEST(DBusMessage,TestNumberMessage)196 TEST(DBusMessage, TestNumberMessage)
197 {
198 DBusMessage *msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
199 tuple<uint8_t, uint16_t, uint32_t, uint64_t, bool, int16_t, int32_t, int64_t> setVals =
200 std::make_tuple<uint8_t, uint16_t, uint32_t, uint64_t, bool, int16_t, int32_t, int64_t>(1, 2, 3, 4, true, 5, 6,
201 7);
202 tuple<uint8_t, uint16_t, uint32_t, uint64_t, bool, int16_t, int32_t, int64_t> getVals =
203 std::make_tuple<uint8_t, uint16_t, uint32_t, uint64_t, bool, int16_t, int32_t, int64_t>(0, 0, 0, 0, false, 0, 0,
204 0);
205
206 EXPECT_NE(msg, nullptr);
207
208 EXPECT_EQ(TupleToDBusMessage(*msg, setVals), OTBR_ERROR_NONE);
209 EXPECT_EQ(DBusMessageToTuple(*msg, getVals), OTBR_ERROR_NONE);
210
211 EXPECT_EQ(setVals, getVals);
212
213 dbus_message_unref(msg);
214 }
215
TEST(DBusMessage,TestStructMessage)216 TEST(DBusMessage, TestStructMessage)
217 {
218 DBusMessage *msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
219 tuple<uint8_t, vector<int32_t>, vector<string>, vector<TestStruct>> setVals(
220 0x03, {0x04, 0x05}, {"hello", "world"}, {{1, 0xf0a, "test1"}, {2, 0xf0b, "test2"}});
221 tuple<uint8_t, vector<int32_t>, vector<string>, vector<TestStruct>> getVals(0, {}, {}, {});
222
223 EXPECT_NE(msg, nullptr);
224
225 EXPECT_EQ(TupleToDBusMessage(*msg, setVals), OTBR_ERROR_NONE);
226 EXPECT_EQ(DBusMessageToTuple(*msg, getVals), OTBR_ERROR_NONE);
227
228 EXPECT_EQ(setVals, getVals);
229
230 dbus_message_unref(msg);
231 }
232
TEST(DBusMessage,TestOtbrChannelQuality)233 TEST(DBusMessage, TestOtbrChannelQuality)
234 {
235 DBusMessage *msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
236 tuple<std::vector<otbr::DBus::ChannelQuality>> setVals({{1, 2}});
237 tuple<std::vector<otbr::DBus::ChannelQuality>> getVals;
238
239 EXPECT_NE(msg, nullptr);
240
241 EXPECT_EQ(TupleToDBusMessage(*msg, setVals), OTBR_ERROR_NONE);
242 EXPECT_EQ(DBusMessageToTuple(*msg, getVals), OTBR_ERROR_NONE);
243
244 EXPECT_EQ(std::get<0>(setVals)[0], std::get<0>(getVals)[0]);
245
246 dbus_message_unref(msg);
247 }
248
TEST(DBusMessage,TestOtbrChildInfo)249 TEST(DBusMessage, TestOtbrChildInfo)
250 {
251 DBusMessage *msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
252 tuple<std::vector<otbr::DBus::ChildInfo>> setVals({{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, true, false, true, false}});
253 tuple<std::vector<otbr::DBus::ChildInfo>> getVals;
254
255 EXPECT_NE(msg, nullptr);
256
257 EXPECT_EQ(TupleToDBusMessage(*msg, setVals), OTBR_ERROR_NONE);
258 EXPECT_EQ(DBusMessageToTuple(*msg, getVals), OTBR_ERROR_NONE);
259
260 EXPECT_EQ(std::get<0>(setVals)[0], std::get<0>(getVals)[0]);
261
262 dbus_message_unref(msg);
263 }
264
TEST(DBusMessage,TestOtbrNeighborInfo)265 TEST(DBusMessage, TestOtbrNeighborInfo)
266 {
267 DBusMessage *msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
268 tuple<std::vector<otbr::DBus::NeighborInfo>> setVals(
269 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, true, false, true, false}});
270 tuple<std::vector<otbr::DBus::NeighborInfo>> getVals;
271
272 EXPECT_NE(msg, nullptr);
273
274 EXPECT_EQ(TupleToDBusMessage(*msg, setVals), OTBR_ERROR_NONE);
275 EXPECT_EQ(DBusMessageToTuple(*msg, getVals), OTBR_ERROR_NONE);
276
277 EXPECT_EQ(std::get<0>(setVals)[0], std::get<0>(getVals)[0]);
278
279 dbus_message_unref(msg);
280 }
281
TEST(DBusMessage,TestOtbrLeaderData)282 TEST(DBusMessage, TestOtbrLeaderData)
283 {
284 DBusMessage *msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
285 tuple<std::vector<otbr::DBus::LeaderData>> setVals({{1, 2, 3, 4, 5}});
286 tuple<std::vector<otbr::DBus::LeaderData>> getVals;
287
288 EXPECT_NE(msg, nullptr);
289
290 EXPECT_EQ(TupleToDBusMessage(*msg, setVals), OTBR_ERROR_NONE);
291 EXPECT_EQ(DBusMessageToTuple(*msg, getVals), OTBR_ERROR_NONE);
292
293 EXPECT_EQ(std::get<0>(setVals)[0], std::get<0>(getVals)[0]);
294
295 dbus_message_unref(msg);
296 }
297
TEST(DBusMessage,TestOtbrActiveScanResults)298 TEST(DBusMessage, TestOtbrActiveScanResults)
299 {
300 DBusMessage *msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
301 tuple<std::vector<otbr::DBus::ActiveScanResult>> setVals({{1, "a", 2, {3}, 4, 5, 6, 7, 8, 9, true, false}});
302 tuple<std::vector<otbr::DBus::ActiveScanResult>> getVals;
303
304 EXPECT_NE(msg, nullptr);
305
306 EXPECT_EQ(TupleToDBusMessage(*msg, setVals), OTBR_ERROR_NONE);
307 EXPECT_EQ(DBusMessageToTuple(*msg, getVals), OTBR_ERROR_NONE);
308
309 EXPECT_EQ(std::get<0>(setVals)[0], std::get<0>(getVals)[0]);
310
311 dbus_message_unref(msg);
312 }
313
TEST(DBusMessage,TestOtbrExternalRoute)314 TEST(DBusMessage, TestOtbrExternalRoute)
315 {
316 DBusMessage *msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
317 tuple<std::vector<otbr::DBus::ExternalRoute>> setVals(
318 {{otbr::DBus::Ip6Prefix({{0xfa, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}, 64}), uint16_t(0xfc00), 1, true,
319 true}});
320 tuple<std::vector<otbr::DBus::ExternalRoute>> getVals;
321
322 EXPECT_NE(msg, nullptr);
323
324 EXPECT_EQ(TupleToDBusMessage(*msg, setVals), OTBR_ERROR_NONE);
325 EXPECT_EQ(DBusMessageToTuple(*msg, getVals), OTBR_ERROR_NONE);
326
327 EXPECT_EQ(std::get<0>(setVals)[0], std::get<0>(getVals)[0]);
328
329 dbus_message_unref(msg);
330 }
331