blob: 5922554f23d425074d0df17302b019ba63f2a23e [file] [log] [blame]
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "dbus/property.h"
6
avi0ad0ce02015-12-23 03:12:45 +09007#include <stddef.h>
8#include <stdint.h>
9
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090010#include <string>
11#include <vector>
12
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090013#include "base/bind.h"
14#include "base/logging.h"
avi0ad0ce02015-12-23 03:12:45 +090015#include "base/macros.h"
avi@chromium.orga29af562013-07-18 08:00:30 +090016#include "base/message_loop/message_loop.h"
earthdok64401d72014-09-03 19:32:36 +090017#include "base/run_loop.h"
dtapuska95f71722015-02-10 01:02:55 +090018#include "base/strings/string_number_conversions.h"
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090019#include "base/threading/thread.h"
20#include "base/threading/thread_restrictions.h"
21#include "dbus/bus.h"
22#include "dbus/object_path.h"
23#include "dbus/object_proxy.h"
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090024#include "dbus/test_service.h"
25#include "testing/gtest/include/gtest/gtest.h"
26
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090027namespace dbus {
28
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090029// The property test exerises the asynchronous APIs in PropertySet and
30// Property<>.
31class PropertyTest : public testing::Test {
32 public:
jpawlowski77e73fc2015-05-11 20:07:04 +090033 PropertyTest() {}
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090034
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090035 struct Properties : public PropertySet {
36 Property<std::string> name;
avi0ad0ce02015-12-23 03:12:45 +090037 Property<int16_t> version;
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090038 Property<std::vector<std::string> > methods;
39 Property<std::vector<ObjectPath> > objects;
avi0ad0ce02015-12-23 03:12:45 +090040 Property<std::vector<uint8_t>> bytes;
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090041
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090042 Properties(ObjectProxy* object_proxy,
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090043 PropertyChangedCallback property_changed_callback)
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090044 : PropertySet(object_proxy,
45 "org.chromium.TestInterface",
46 property_changed_callback) {
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090047 RegisterProperty("Name", &name);
48 RegisterProperty("Version", &version);
49 RegisterProperty("Methods", &methods);
50 RegisterProperty("Objects", &objects);
armansito@chromium.org11e12742014-03-15 16:40:49 +090051 RegisterProperty("Bytes", &bytes);
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090052 }
53 };
54
dcheng7f5750d2014-12-30 03:30:17 +090055 void SetUp() override {
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090056 // Make the main thread not to allow IO.
57 base::ThreadRestrictions::SetIOAllowed(false);
58
59 // Start the D-Bus thread.
60 dbus_thread_.reset(new base::Thread("D-Bus Thread"));
61 base::Thread::Options thread_options;
xhwang@chromium.orgdff6b132013-05-02 01:10:30 +090062 thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090063 ASSERT_TRUE(dbus_thread_->StartWithOptions(thread_options));
64
65 // Start the test service, using the D-Bus thread.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090066 TestService::Options options;
skyostile5a8dc42015-06-18 00:46:04 +090067 options.dbus_task_runner = dbus_thread_->task_runner();
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090068 test_service_.reset(new TestService(options));
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090069 ASSERT_TRUE(test_service_->StartService());
70 ASSERT_TRUE(test_service_->WaitUntilServiceIsStarted());
71 ASSERT_TRUE(test_service_->HasDBusThread());
72
73 // Create the client, using the D-Bus thread.
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090074 Bus::Options bus_options;
75 bus_options.bus_type = Bus::SESSION;
76 bus_options.connection_type = Bus::PRIVATE;
skyostile5a8dc42015-06-18 00:46:04 +090077 bus_options.dbus_task_runner = dbus_thread_->task_runner();
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090078 bus_ = new Bus(bus_options);
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090079 object_proxy_ = bus_->GetObjectProxy(
hashimotof4a4c0d2016-01-05 17:48:03 +090080 test_service_->service_name(),
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +090081 ObjectPath("/org/chromium/TestObject"));
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090082 ASSERT_TRUE(bus_->HasDBusThread());
83
84 // Create the properties structure
satorux@chromium.org5e612da2012-05-31 15:55:53 +090085 properties_.reset(new Properties(
86 object_proxy_,
87 base::Bind(&PropertyTest::OnPropertyChanged,
88 base::Unretained(this))));
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090089 properties_->ConnectSignals();
90 properties_->GetAll();
91 }
92
dcheng7f5750d2014-12-30 03:30:17 +090093 void TearDown() override {
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090094 bus_->ShutdownOnDBusThreadAndBlock();
95
96 // Shut down the service.
97 test_service_->ShutdownAndBlock();
98
99 // Reset to the default.
100 base::ThreadRestrictions::SetIOAllowed(true);
101
102 // Stopping a thread is considered an IO operation, so do this after
103 // allowing IO.
104 test_service_->Stop();
105 }
106
107 // Generic callback, bind with a string |id| for passing to
108 // WaitForCallback() to ensure the callback for the right method is
109 // waited for.
110 void PropertyCallback(const std::string& id, bool success) {
111 last_callback_ = id;
earthdok64401d72014-09-03 19:32:36 +0900112 run_loop_->Quit();
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900113 }
114
jpawlowski77e73fc2015-05-11 20:07:04 +0900115 // Generic method callback, that might be used together with
116 // WaitForMethodCallback to test wether method was succesfully called.
117 void MethodCallback(Response* response) { run_loop_->Quit(); }
118
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900119 protected:
120 // Called when a property value is updated.
121 void OnPropertyChanged(const std::string& name) {
122 updated_properties_.push_back(name);
earthdok64401d72014-09-03 19:32:36 +0900123 run_loop_->Quit();
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900124 }
125
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900126 // Waits for the given number of updates.
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900127 void WaitForUpdates(size_t num_updates) {
earthdok64401d72014-09-03 19:32:36 +0900128 while (updated_properties_.size() < num_updates) {
129 run_loop_.reset(new base::RunLoop);
130 run_loop_->Run();
131 }
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900132 for (size_t i = 0; i < num_updates; ++i)
133 updated_properties_.erase(updated_properties_.begin());
134 }
135
136 // Name, Version, Methods, Objects
armansito@chromium.org11e12742014-03-15 16:40:49 +0900137 static const int kExpectedSignalUpdates = 5;
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900138
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900139 // Waits for initial values to be set.
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900140 void WaitForGetAll() {
141 WaitForUpdates(kExpectedSignalUpdates);
142 }
143
jpawlowski77e73fc2015-05-11 20:07:04 +0900144 // Waits until MethodCallback is called.
145 void WaitForMethodCallback() {
146 run_loop_.reset(new base::RunLoop);
147 run_loop_->Run();
148 }
149
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900150 // Waits for the callback. |id| is the string bound to the callback when
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900151 // the method call is made that identifies it and distinguishes from any
152 // other; you can set this to whatever you wish.
153 void WaitForCallback(const std::string& id) {
154 while (last_callback_ != id) {
earthdok64401d72014-09-03 19:32:36 +0900155 run_loop_.reset(new base::RunLoop);
156 run_loop_->Run();
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900157 }
158 }
159
xhwang@chromium.orgdff6b132013-05-02 01:10:30 +0900160 base::MessageLoop message_loop_;
dcheng30c5a172016-04-09 07:55:04 +0900161 std::unique_ptr<base::RunLoop> run_loop_;
162 std::unique_ptr<base::Thread> dbus_thread_;
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900163 scoped_refptr<Bus> bus_;
164 ObjectProxy* object_proxy_;
dcheng30c5a172016-04-09 07:55:04 +0900165 std::unique_ptr<Properties> properties_;
166 std::unique_ptr<TestService> test_service_;
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900167 // Properties updated.
168 std::vector<std::string> updated_properties_;
169 // Last callback received.
170 std::string last_callback_;
171};
172
173TEST_F(PropertyTest, InitialValues) {
jpawlowski77e73fc2015-05-11 20:07:04 +0900174 EXPECT_FALSE(properties_->name.is_valid());
175 EXPECT_FALSE(properties_->version.is_valid());
176
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900177 WaitForGetAll();
178
jpawlowski77e73fc2015-05-11 20:07:04 +0900179 EXPECT_TRUE(properties_->name.is_valid());
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900180 EXPECT_EQ("TestService", properties_->name.value());
jpawlowski77e73fc2015-05-11 20:07:04 +0900181 EXPECT_TRUE(properties_->version.is_valid());
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900182 EXPECT_EQ(10, properties_->version.value());
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900183
184 std::vector<std::string> methods = properties_->methods.value();
185 ASSERT_EQ(4U, methods.size());
186 EXPECT_EQ("Echo", methods[0]);
187 EXPECT_EQ("SlowEcho", methods[1]);
188 EXPECT_EQ("AsyncEcho", methods[2]);
189 EXPECT_EQ("BrokenMethod", methods[3]);
190
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900191 std::vector<ObjectPath> objects = properties_->objects.value();
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900192 ASSERT_EQ(1U, objects.size());
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900193 EXPECT_EQ(ObjectPath("/TestObjectPath"), objects[0]);
armansito@chromium.org11e12742014-03-15 16:40:49 +0900194
avi0ad0ce02015-12-23 03:12:45 +0900195 std::vector<uint8_t> bytes = properties_->bytes.value();
armansito@chromium.org11e12742014-03-15 16:40:49 +0900196 ASSERT_EQ(4U, bytes.size());
197 EXPECT_EQ('T', bytes[0]);
198 EXPECT_EQ('e', bytes[1]);
199 EXPECT_EQ('s', bytes[2]);
200 EXPECT_EQ('t', bytes[3]);
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900201}
202
keybuk@google.comf056b962012-03-22 08:43:45 +0900203TEST_F(PropertyTest, UpdatedValues) {
204 WaitForGetAll();
205
206 // Update the value of the "Name" property, this value should not change.
207 properties_->name.Get(base::Bind(&PropertyTest::PropertyCallback,
208 base::Unretained(this),
209 "Name"));
210 WaitForCallback("Name");
211 WaitForUpdates(1);
212
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900213 EXPECT_EQ("TestService", properties_->name.value());
keybuk@google.comf056b962012-03-22 08:43:45 +0900214
215 // Update the value of the "Version" property, this value should be changed.
216 properties_->version.Get(base::Bind(&PropertyTest::PropertyCallback,
217 base::Unretained(this),
218 "Version"));
219 WaitForCallback("Version");
220 WaitForUpdates(1);
221
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900222 EXPECT_EQ(20, properties_->version.value());
keybuk@google.comf056b962012-03-22 08:43:45 +0900223
224 // Update the value of the "Methods" property, this value should not change
225 // and should not grow to contain duplicate entries.
226 properties_->methods.Get(base::Bind(&PropertyTest::PropertyCallback,
227 base::Unretained(this),
228 "Methods"));
229 WaitForCallback("Methods");
230 WaitForUpdates(1);
231
232 std::vector<std::string> methods = properties_->methods.value();
233 ASSERT_EQ(4U, methods.size());
234 EXPECT_EQ("Echo", methods[0]);
235 EXPECT_EQ("SlowEcho", methods[1]);
236 EXPECT_EQ("AsyncEcho", methods[2]);
237 EXPECT_EQ("BrokenMethod", methods[3]);
238
239 // Update the value of the "Objects" property, this value should not change
240 // and should not grow to contain duplicate entries.
241 properties_->objects.Get(base::Bind(&PropertyTest::PropertyCallback,
242 base::Unretained(this),
243 "Objects"));
244 WaitForCallback("Objects");
245 WaitForUpdates(1);
246
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900247 std::vector<ObjectPath> objects = properties_->objects.value();
keybuk@google.comf056b962012-03-22 08:43:45 +0900248 ASSERT_EQ(1U, objects.size());
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900249 EXPECT_EQ(ObjectPath("/TestObjectPath"), objects[0]);
armansito@chromium.org11e12742014-03-15 16:40:49 +0900250
251 // Update the value of the "Bytes" property, this value should not change
252 // and should not grow to contain duplicate entries.
253 properties_->bytes.Get(base::Bind(&PropertyTest::PropertyCallback,
254 base::Unretained(this),
255 "Bytes"));
256 WaitForCallback("Bytes");
257 WaitForUpdates(1);
258
avi0ad0ce02015-12-23 03:12:45 +0900259 std::vector<uint8_t> bytes = properties_->bytes.value();
armansito@chromium.org11e12742014-03-15 16:40:49 +0900260 ASSERT_EQ(4U, bytes.size());
261 EXPECT_EQ('T', bytes[0]);
262 EXPECT_EQ('e', bytes[1]);
263 EXPECT_EQ('s', bytes[2]);
264 EXPECT_EQ('t', bytes[3]);
keybuk@google.comf056b962012-03-22 08:43:45 +0900265}
266
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900267TEST_F(PropertyTest, Get) {
268 WaitForGetAll();
269
270 // Ask for the new Version property.
271 properties_->version.Get(base::Bind(&PropertyTest::PropertyCallback,
272 base::Unretained(this),
273 "Get"));
274 WaitForCallback("Get");
275
276 // Make sure we got a property update too.
277 WaitForUpdates(1);
278
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900279 EXPECT_EQ(20, properties_->version.value());
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900280}
281
282TEST_F(PropertyTest, Set) {
283 WaitForGetAll();
284
285 // Set a new name.
286 properties_->name.Set("NewService",
287 base::Bind(&PropertyTest::PropertyCallback,
288 base::Unretained(this),
289 "Set"));
290 WaitForCallback("Set");
291
292 // TestService sends a property update.
293 WaitForUpdates(1);
294
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900295 EXPECT_EQ("NewService", properties_->name.value());
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900296}
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900297
jpawlowski77e73fc2015-05-11 20:07:04 +0900298TEST_F(PropertyTest, Invalidate) {
299 WaitForGetAll();
300
301 EXPECT_TRUE(properties_->name.is_valid());
302
303 // Invalidate name.
304 MethodCall method_call("org.chromium.TestInterface", "PerformAction");
305 MessageWriter writer(&method_call);
306 writer.AppendString("InvalidateProperty");
307 writer.AppendObjectPath(ObjectPath("/org/chromium/TestService"));
308 object_proxy_->CallMethod(
309 &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT,
310 base::Bind(&PropertyTest::MethodCallback, base::Unretained(this)));
311 WaitForMethodCallback();
312
313 // TestService sends a property update.
314 WaitForUpdates(1);
315
316 EXPECT_FALSE(properties_->name.is_valid());
317
318 // Set name to something valid.
319 properties_->name.Set("NewService",
320 base::Bind(&PropertyTest::PropertyCallback,
321 base::Unretained(this), "Set"));
322 WaitForCallback("Set");
323
324 // TestService sends a property update.
325 WaitForUpdates(1);
326
327 EXPECT_TRUE(properties_->name.is_valid());
328}
329
dtapuska95f71722015-02-10 01:02:55 +0900330TEST(PropertyTestStatic, ReadWriteStringMap) {
dcheng30c5a172016-04-09 07:55:04 +0900331 std::unique_ptr<Response> message(Response::CreateEmpty());
dtapuska95f71722015-02-10 01:02:55 +0900332 MessageWriter writer(message.get());
333 MessageWriter variant_writer(NULL);
334 MessageWriter variant_array_writer(NULL);
335 MessageWriter struct_entry_writer(NULL);
336
337 writer.OpenVariant("a{ss}", &variant_writer);
338 variant_writer.OpenArray("{ss}", &variant_array_writer);
339 const char* items[] = {"One", "Two", "Three", "Four"};
340 for (unsigned i = 0; i < arraysize(items); ++i) {
341 variant_array_writer.OpenDictEntry(&struct_entry_writer);
342 struct_entry_writer.AppendString(items[i]);
343 struct_entry_writer.AppendString(base::UintToString(i + 1));
344 variant_array_writer.CloseContainer(&struct_entry_writer);
345 }
346 variant_writer.CloseContainer(&variant_array_writer);
347 writer.CloseContainer(&variant_writer);
348
349 MessageReader reader(message.get());
350 Property<std::map<std::string, std::string>> string_map;
351 EXPECT_TRUE(string_map.PopValueFromReader(&reader));
352 ASSERT_EQ(4U, string_map.value().size());
353 EXPECT_EQ("1", string_map.value().at("One"));
354 EXPECT_EQ("2", string_map.value().at("Two"));
355 EXPECT_EQ("3", string_map.value().at("Three"));
356 EXPECT_EQ("4", string_map.value().at("Four"));
357}
358
359TEST(PropertyTestStatic, SerializeStringMap) {
360 std::map<std::string, std::string> test_map;
361 test_map["Hi"] = "There";
362 test_map["Map"] = "Test";
363 test_map["Random"] = "Text";
364
dcheng30c5a172016-04-09 07:55:04 +0900365 std::unique_ptr<Response> message(Response::CreateEmpty());
dtapuska95f71722015-02-10 01:02:55 +0900366 MessageWriter writer(message.get());
367
368 Property<std::map<std::string, std::string>> string_map;
369 string_map.ReplaceSetValueForTesting(test_map);
370 string_map.AppendSetValueToWriter(&writer);
371
372 MessageReader reader(message.get());
373 EXPECT_TRUE(string_map.PopValueFromReader(&reader));
374 EXPECT_EQ(test_map, string_map.value());
375}
376
377TEST(PropertyTestStatic, ReadWriteNetAddressArray) {
dcheng30c5a172016-04-09 07:55:04 +0900378 std::unique_ptr<Response> message(Response::CreateEmpty());
dtapuska95f71722015-02-10 01:02:55 +0900379 MessageWriter writer(message.get());
380 MessageWriter variant_writer(NULL);
381 MessageWriter variant_array_writer(NULL);
382 MessageWriter struct_entry_writer(NULL);
383
384 writer.OpenVariant("a(ayq)", &variant_writer);
385 variant_writer.OpenArray("(ayq)", &variant_array_writer);
avi0ad0ce02015-12-23 03:12:45 +0900386 uint8_t ip_bytes[] = {0x54, 0x65, 0x73, 0x74, 0x30};
387 for (uint16_t i = 0; i < 5; ++i) {
dtapuska95f71722015-02-10 01:02:55 +0900388 variant_array_writer.OpenStruct(&struct_entry_writer);
389 ip_bytes[4] = 0x30 + i;
390 struct_entry_writer.AppendArrayOfBytes(ip_bytes, arraysize(ip_bytes));
391 struct_entry_writer.AppendUint16(i);
392 variant_array_writer.CloseContainer(&struct_entry_writer);
393 }
394 variant_writer.CloseContainer(&variant_array_writer);
395 writer.CloseContainer(&variant_writer);
396
397 MessageReader reader(message.get());
avi0ad0ce02015-12-23 03:12:45 +0900398 Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>> ip_list;
dtapuska95f71722015-02-10 01:02:55 +0900399 EXPECT_TRUE(ip_list.PopValueFromReader(&reader));
400
401 ASSERT_EQ(5U, ip_list.value().size());
402 size_t item_index = 0;
403 for (auto& item : ip_list.value()) {
404 ASSERT_EQ(5U, item.first.size());
405 ip_bytes[4] = 0x30 + item_index;
406 EXPECT_EQ(0, memcmp(ip_bytes, item.first.data(), 5U));
407 EXPECT_EQ(item_index, item.second);
408 ++item_index;
409 }
410}
411
412TEST(PropertyTestStatic, SerializeNetAddressArray) {
avi0ad0ce02015-12-23 03:12:45 +0900413 std::vector<std::pair<std::vector<uint8_t>, uint16_t>> test_list;
dtapuska95f71722015-02-10 01:02:55 +0900414
avi0ad0ce02015-12-23 03:12:45 +0900415 uint8_t ip_bytes[] = {0x54, 0x65, 0x73, 0x74, 0x30};
416 for (uint16_t i = 0; i < 5; ++i) {
dtapuska95f71722015-02-10 01:02:55 +0900417 ip_bytes[4] = 0x30 + i;
avi0ad0ce02015-12-23 03:12:45 +0900418 std::vector<uint8_t> bytes(ip_bytes, ip_bytes + arraysize(ip_bytes));
dtapuska95f71722015-02-10 01:02:55 +0900419 test_list.push_back(make_pair(bytes, 16));
420 }
421
dcheng30c5a172016-04-09 07:55:04 +0900422 std::unique_ptr<Response> message(Response::CreateEmpty());
dtapuska95f71722015-02-10 01:02:55 +0900423 MessageWriter writer(message.get());
424
avi0ad0ce02015-12-23 03:12:45 +0900425 Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>> ip_list;
dtapuska95f71722015-02-10 01:02:55 +0900426 ip_list.ReplaceSetValueForTesting(test_list);
427 ip_list.AppendSetValueToWriter(&writer);
428
429 MessageReader reader(message.get());
430 EXPECT_TRUE(ip_list.PopValueFromReader(&reader));
431 EXPECT_EQ(test_list, ip_list.value());
432}
433
thestig@chromium.orgf0b7eac2013-06-13 15:37:19 +0900434} // namespace dbus