- add sources.
[platform/framework/web/crosswalk.git] / src / chromeos / dbus / nfc_client_unittest.cc
1 // Copyright 2013 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 "base/bind.h"
6 #include "base/message_loop/message_loop.h"
7 #include "chromeos/dbus/nfc_adapter_client.h"
8 #include "chromeos/dbus/nfc_client_helpers.h"
9 #include "chromeos/dbus/nfc_device_client.h"
10 #include "chromeos/dbus/nfc_manager_client.h"
11 #include "chromeos/dbus/nfc_tag_client.h"
12 #include "dbus/mock_bus.h"
13 #include "dbus/mock_object_proxy.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/cros_system_api/dbus/service_constants.h"
17
18 using ::testing::_;
19 using ::testing::Invoke;
20 using ::testing::Mock;
21 using ::testing::Return;
22
23 namespace chromeos {
24
25 namespace {
26
27 // D-Bus service name used by the test.
28 const char kTestServiceName[] = "test.service.name";
29
30 // Object paths that are used for testing.
31 const char kTestManagerPath[] = "/test/nfc/manager";
32 const char kTestAdapterPath0[] = "/test/nfc/adapter0";
33 const char kTestAdapterPath1[] = "/test/nfc/adapter1";
34 const char kTestDevicePath0[] = "/test/nfc/device0";
35 const char kTestDevicePath1[] = "/test/nfc/device1";
36 const char kTestTagPath0[] = "/test/nfc/tag0";
37 const char kTestTagPath1[] = "/test/nfc/tag1";
38
39 class MockNfcManagerObserver : public NfcManagerClient::Observer {
40  public:
41   MOCK_METHOD1(AdapterAdded, void(const dbus::ObjectPath&));
42   MOCK_METHOD1(AdapterRemoved, void(const dbus::ObjectPath&));
43   MOCK_METHOD1(ManagerPropertyChanged, void(const std::string&));
44 };
45
46 class MockNfcAdapterObserver : public NfcAdapterClient::Observer {
47  public:
48   MOCK_METHOD1(AdapterAdded, void(const dbus::ObjectPath&));
49   MOCK_METHOD1(AdapterRemoved, void(const dbus::ObjectPath&));
50   MOCK_METHOD2(AdapterPropertyChanged, void(const dbus::ObjectPath&,
51                                             const std::string&));
52 };
53
54 class MockNfcDeviceObserver : public NfcDeviceClient::Observer {
55  public:
56   MOCK_METHOD1(DeviceFound, void(const dbus::ObjectPath&));
57   MOCK_METHOD1(DeviceLost, void(const dbus::ObjectPath&));
58   MOCK_METHOD2(DevicePropertyChanged, void(const dbus::ObjectPath&,
59                                            const std::string&));
60 };
61
62 class MockNfcTagObserver : public NfcTagClient::Observer {
63  public:
64   MOCK_METHOD1(TagFound, void(const dbus::ObjectPath&));
65   MOCK_METHOD1(TagLost, void(const dbus::ObjectPath&));
66   MOCK_METHOD2(TagPropertyChanged, void(const dbus::ObjectPath&,
67                                         const std::string&));
68 };
69
70 }  // namespace
71
72 class NfcClientTest : public testing::Test {
73  public:
74   NfcClientTest() : response_(NULL) {}
75   virtual ~NfcClientTest() {}
76
77   virtual void SetUp() OVERRIDE {
78     // Create the mock bus.
79     dbus::Bus::Options options;
80     options.bus_type = dbus::Bus::SYSTEM;
81     mock_bus_ = new dbus::MockBus(options);
82
83     // Create the mock proxies.
84     mock_manager_proxy_ = new dbus::MockObjectProxy(
85         mock_bus_.get(),
86         kTestServiceName,
87         dbus::ObjectPath(kTestManagerPath));
88     mock_adapter0_proxy_ = new dbus::MockObjectProxy(
89         mock_bus_.get(),
90         kTestServiceName,
91         dbus::ObjectPath(kTestAdapterPath0));
92     mock_adapter1_proxy_ = new dbus::MockObjectProxy(
93         mock_bus_.get(),
94         kTestServiceName,
95         dbus::ObjectPath(kTestAdapterPath1));
96     mock_device0_proxy_ = new dbus::MockObjectProxy(
97         mock_bus_.get(),
98         kTestServiceName,
99         dbus::ObjectPath(kTestDevicePath0));
100     mock_device1_proxy_ = new dbus::MockObjectProxy(
101         mock_bus_.get(),
102         kTestServiceName,
103         dbus::ObjectPath(kTestDevicePath1));
104     mock_tag0_proxy_ = new dbus::MockObjectProxy(
105         mock_bus_.get(),
106         kTestServiceName,
107         dbus::ObjectPath(kTestTagPath0));
108     mock_tag1_proxy_ = new dbus::MockObjectProxy(
109         mock_bus_.get(),
110         kTestServiceName,
111         dbus::ObjectPath(kTestTagPath1));
112
113     // Set expectations that use NfcClientTest::OnConnectToSignal when the
114     // client connect signals on the mock proxies.
115     EXPECT_CALL(*mock_manager_proxy_.get(), ConnectToSignal(_, _, _, _))
116         .WillRepeatedly(Invoke(this, &NfcClientTest::OnConnectToSignal));
117     EXPECT_CALL(*mock_adapter0_proxy_.get(), ConnectToSignal(_, _, _, _))
118         .WillRepeatedly(Invoke(this, &NfcClientTest::OnConnectToSignal));
119     EXPECT_CALL(*mock_adapter1_proxy_.get(), ConnectToSignal(_, _, _, _))
120         .WillRepeatedly(Invoke(this, &NfcClientTest::OnConnectToSignal));
121
122     // Set expectations that return our mock proxies on demand.
123     EXPECT_CALL(
124         *mock_bus_.get(),
125         GetObjectProxy(nfc_manager::kNfcManagerServiceName,
126                        dbus::ObjectPath(nfc_manager::kNfcManagerServicePath)))
127         .WillRepeatedly(Return(mock_manager_proxy_.get()));
128     EXPECT_CALL(*mock_bus_.get(),
129                 GetObjectProxy(nfc_adapter::kNfcAdapterServiceName,
130                                dbus::ObjectPath(kTestAdapterPath0)))
131         .WillRepeatedly(Return(mock_adapter0_proxy_.get()));
132     EXPECT_CALL(*mock_bus_.get(),
133                 GetObjectProxy(nfc_adapter::kNfcAdapterServiceName,
134                                dbus::ObjectPath(kTestAdapterPath1)))
135         .WillRepeatedly(Return(mock_adapter1_proxy_.get()));
136     EXPECT_CALL(*mock_bus_.get(),
137                 GetObjectProxy(nfc_device::kNfcDeviceServiceName,
138                                dbus::ObjectPath(kTestDevicePath0)))
139         .WillRepeatedly(Return(mock_device0_proxy_.get()));
140     EXPECT_CALL(*mock_bus_.get(),
141                 GetObjectProxy(nfc_device::kNfcDeviceServiceName,
142                                dbus::ObjectPath(kTestDevicePath1)))
143         .WillRepeatedly(Return(mock_device1_proxy_.get()));
144     EXPECT_CALL(*mock_bus_.get(),
145                 GetObjectProxy(nfc_tag::kNfcTagServiceName,
146                                dbus::ObjectPath(kTestTagPath0)))
147         .WillRepeatedly(Return(mock_tag0_proxy_.get()));
148     EXPECT_CALL(*mock_bus_.get(),
149                 GetObjectProxy(nfc_tag::kNfcTagServiceName,
150                                dbus::ObjectPath(kTestTagPath1)))
151         .WillRepeatedly(Return(mock_tag1_proxy_.get()));
152
153     // ShutdownAndBlock will be called in TearDown.
154     EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()).WillOnce(Return());
155
156     // Create the clients.
157     manager_client_.reset(
158         NfcManagerClient::Create(REAL_DBUS_CLIENT_IMPLEMENTATION));
159     adapter_client_.reset(
160         NfcAdapterClient::Create(REAL_DBUS_CLIENT_IMPLEMENTATION,
161                                  manager_client_.get()));
162     device_client_.reset(
163         NfcDeviceClient::Create(REAL_DBUS_CLIENT_IMPLEMENTATION,
164                                 adapter_client_.get()));
165     tag_client_.reset(
166         NfcTagClient::Create(REAL_DBUS_CLIENT_IMPLEMENTATION,
167                              adapter_client_.get()));
168     manager_client_->Init(mock_bus_.get());
169     adapter_client_->Init(mock_bus_.get());
170     device_client_->Init(mock_bus_.get());
171     tag_client_->Init(mock_bus_.get());
172     manager_client_->AddObserver(&mock_manager_observer_);
173     adapter_client_->AddObserver(&mock_adapter_observer_);
174     device_client_->AddObserver(&mock_device_observer_);
175     tag_client_->AddObserver(&mock_tag_observer_);
176
177     message_loop_.RunUntilIdle();
178   }
179
180   virtual void TearDown() OVERRIDE {
181     tag_client_->RemoveObserver(&mock_tag_observer_);
182     device_client_->RemoveObserver(&mock_device_observer_);
183     adapter_client_->RemoveObserver(&mock_adapter_observer_);
184     manager_client_->RemoveObserver(&mock_manager_observer_);
185     mock_bus_->ShutdownAndBlock();
186   }
187
188   void SimulateAdaptersChanged(
189       const std::vector<dbus::ObjectPath>& adapter_paths) {
190     NfcManagerClient::Properties* properties =
191         manager_client_->GetProperties();
192     ASSERT_TRUE(properties);
193     EXPECT_CALL(mock_manager_observer_,
194                 ManagerPropertyChanged(nfc_manager::kAdaptersProperty));
195     SendArrayPropertyChangedSignal(
196         properties,
197         nfc_manager::kNfcManagerInterface,
198         nfc_manager::kAdaptersProperty,
199         adapter_paths);
200     Mock::VerifyAndClearExpectations(&mock_manager_observer_);
201   }
202
203   void SimulateTagsChanged(const std::vector<dbus::ObjectPath>& tag_paths,
204                            const dbus::ObjectPath& adapter_path) {
205     NfcAdapterClient::Properties* properties =
206         adapter_client_->GetProperties(adapter_path);
207     ASSERT_TRUE(properties);
208     EXPECT_CALL(mock_adapter_observer_,
209                 AdapterPropertyChanged(adapter_path,
210                                        nfc_adapter::kTagsProperty));
211     SendArrayPropertyChangedSignal(
212         properties,
213         nfc_adapter::kNfcAdapterInterface,
214         nfc_adapter::kTagsProperty,
215         tag_paths);
216     Mock::VerifyAndClearExpectations(&mock_adapter_observer_);
217   }
218
219   void SimulateDevicesChanged(const std::vector<dbus::ObjectPath>& device_paths,
220                               const dbus::ObjectPath& adapter_path) {
221     NfcAdapterClient::Properties* properties =
222         adapter_client_->GetProperties(adapter_path);
223     ASSERT_TRUE(properties);
224     EXPECT_CALL(mock_adapter_observer_,
225                 AdapterPropertyChanged(adapter_path,
226                                        nfc_adapter::kDevicesProperty));
227     SendArrayPropertyChangedSignal(
228         properties,
229         nfc_adapter::kNfcAdapterInterface,
230         nfc_adapter::kDevicesProperty,
231         device_paths);
232     Mock::VerifyAndClearExpectations(&mock_adapter_observer_);
233   }
234
235   void SendArrayPropertyChangedSignal(
236       dbus::PropertySet* properties,
237       const std::string& interface,
238       const std::string& property_name,
239       std::vector<dbus::ObjectPath> object_paths) {
240     dbus::Signal signal(interface, nfc_common::kPropertyChangedSignal);
241     dbus::MessageWriter writer(&signal);
242     writer.AppendString(property_name);
243     dbus::MessageWriter variant_writer(NULL);
244     writer.OpenVariant("ao", &variant_writer);
245     variant_writer.AppendArrayOfObjectPaths(object_paths);
246     writer.CloseContainer(&variant_writer);
247     properties->ChangedReceived(&signal);
248   }
249
250   MOCK_METHOD0(SuccessCallback, void(void));
251   MOCK_METHOD2(ErrorCallback, void(const std::string& error_name,
252                                    const std::string& error_message));
253
254  protected:
255   // The mock object proxies.
256   scoped_refptr<dbus::MockObjectProxy> mock_manager_proxy_;
257   scoped_refptr<dbus::MockObjectProxy> mock_adapter0_proxy_;
258   scoped_refptr<dbus::MockObjectProxy> mock_adapter1_proxy_;
259   scoped_refptr<dbus::MockObjectProxy> mock_device0_proxy_;
260   scoped_refptr<dbus::MockObjectProxy> mock_device1_proxy_;
261   scoped_refptr<dbus::MockObjectProxy> mock_tag0_proxy_;
262   scoped_refptr<dbus::MockObjectProxy> mock_tag1_proxy_;
263   // The mock bus.
264   scoped_refptr<dbus::MockBus> mock_bus_;
265   // A message loop to emulate asynchronous behavior.
266   base::MessageLoop message_loop_;
267   // Response returned by mock methods.
268   dbus::Response* response_;
269   // The D-Bus client objects under test.
270   scoped_ptr<NfcManagerClient> manager_client_;
271   scoped_ptr<NfcAdapterClient> adapter_client_;
272   scoped_ptr<NfcDeviceClient> device_client_;
273   scoped_ptr<NfcTagClient> tag_client_;
274   // Mock observers.
275   MockNfcManagerObserver mock_manager_observer_;
276   MockNfcAdapterObserver mock_adapter_observer_;
277   MockNfcDeviceObserver mock_device_observer_;
278   MockNfcTagObserver mock_tag_observer_;
279   // The signal callbacks used to simulate asychronous signals.
280   dbus::ObjectProxy::SignalCallback manager_adapter_added_signal_callback_;
281   dbus::ObjectProxy::SignalCallback manager_adapter_removed_signal_callback_;
282
283  private:
284   // Used to implement the mock proxy.
285   void OnConnectToSignal(
286       const std::string& interface_name,
287       const std::string& signal_name,
288       const dbus::ObjectProxy::SignalCallback& signal_callback,
289       const dbus::ObjectProxy::OnConnectedCallback& on_connected_callback) {
290     if (interface_name == nfc_manager::kNfcManagerInterface) {
291       if (signal_name == nfc_manager::kAdapterAddedSignal)
292         manager_adapter_added_signal_callback_ = signal_callback;
293       else if (signal_name == nfc_manager::kAdapterRemovedSignal)
294         manager_adapter_removed_signal_callback_ = signal_callback;
295     }
296     message_loop_.PostTask(FROM_HERE, base::Bind(on_connected_callback,
297                                                  interface_name,
298                                                  signal_name,
299                                                  true));
300   }
301 };
302
303 // Tests that when adapters are added and removed through the manager, all
304 // observers are notified and the proxies are created and removed
305 // accordingly.
306 TEST_F(NfcClientTest, AdaptersAddedAndRemoved) {
307   // Invoking methods on adapters that haven't been added should fail.
308   EXPECT_CALL(*this,
309               ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
310   adapter_client_->StartPollLoop(
311       dbus::ObjectPath(kTestAdapterPath0),
312       nfc_adapter::kModeInitiator,
313       base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
314       base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
315   Mock::VerifyAndClearExpectations(this);
316
317   // Add adapter 0.
318   std::vector<dbus::ObjectPath> adapter_paths;
319   adapter_paths.push_back(dbus::ObjectPath(kTestAdapterPath0));
320   EXPECT_CALL(mock_adapter_observer_,
321               AdapterAdded(dbus::ObjectPath(kTestAdapterPath0)));
322   SimulateAdaptersChanged(adapter_paths);
323
324   // Invoking methods should succeed on adapter 0 but fail on adapter 1.
325   EXPECT_CALL(*mock_adapter0_proxy_, CallMethodWithErrorCallback(_, _, _, _));
326   adapter_client_->StartPollLoop(
327       dbus::ObjectPath(kTestAdapterPath0),
328       nfc_adapter::kModeInitiator,
329       base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
330       base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
331   Mock::VerifyAndClearExpectations(&mock_adapter0_proxy_);
332   EXPECT_CALL(*this,
333               ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
334   EXPECT_CALL(*mock_adapter1_proxy_, CallMethodWithErrorCallback(_, _, _, _))
335       .Times(0);
336   adapter_client_->StartPollLoop(
337       dbus::ObjectPath(kTestAdapterPath1),
338       nfc_adapter::kModeInitiator,
339       base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
340       base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
341   Mock::VerifyAndClearExpectations(this);
342   Mock::VerifyAndClearExpectations(&mock_adapter1_proxy_);
343
344   // Add adapter 1.
345   adapter_paths.push_back(dbus::ObjectPath(kTestAdapterPath1));
346   EXPECT_CALL(mock_adapter_observer_,
347               AdapterAdded(dbus::ObjectPath(kTestAdapterPath1)));
348   SimulateAdaptersChanged(adapter_paths);
349
350   // Invoking methods should succeed on both adapters.
351   EXPECT_CALL(*mock_adapter0_proxy_, CallMethodWithErrorCallback(_, _, _, _));
352   EXPECT_CALL(*mock_adapter1_proxy_, CallMethodWithErrorCallback(_, _, _, _));
353   adapter_client_->StartPollLoop(
354       dbus::ObjectPath(kTestAdapterPath0),
355       nfc_adapter::kModeInitiator,
356       base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
357       base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
358   adapter_client_->StartPollLoop(
359       dbus::ObjectPath(kTestAdapterPath1),
360       nfc_adapter::kModeInitiator,
361       base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
362       base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
363   Mock::VerifyAndClearExpectations(&mock_adapter0_proxy_);
364   Mock::VerifyAndClearExpectations(&mock_adapter1_proxy_);
365
366   // Remove adapter 0.
367   adapter_paths.erase(adapter_paths.begin());
368   EXPECT_CALL(mock_adapter_observer_,
369               AdapterRemoved(dbus::ObjectPath(kTestAdapterPath0)));
370   SimulateAdaptersChanged(adapter_paths);
371
372   // Invoking methods should succeed on adapter 1 but fail on adapter 0.
373   EXPECT_CALL(*this,
374               ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
375   EXPECT_CALL(*mock_adapter0_proxy_, CallMethodWithErrorCallback(_, _, _, _))
376       .Times(0);
377   adapter_client_->StartPollLoop(
378       dbus::ObjectPath(kTestAdapterPath0),
379       nfc_adapter::kModeInitiator,
380       base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
381       base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
382   Mock::VerifyAndClearExpectations(this);
383
384   EXPECT_CALL(*mock_adapter1_proxy_, CallMethodWithErrorCallback(_, _, _, _));
385   adapter_client_->StartPollLoop(
386       dbus::ObjectPath(kTestAdapterPath1),
387       nfc_adapter::kModeInitiator,
388       base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
389       base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
390   Mock::VerifyAndClearExpectations(&mock_adapter0_proxy_);
391   Mock::VerifyAndClearExpectations(&mock_adapter1_proxy_);
392
393   // Remove adapter 1.
394   adapter_paths.clear();
395   EXPECT_CALL(mock_adapter_observer_,
396               AdapterRemoved(dbus::ObjectPath(kTestAdapterPath1)));
397   SimulateAdaptersChanged(adapter_paths);
398
399   // Invoking methods should fail on both adapters.
400   EXPECT_CALL(*this,
401               ErrorCallback(nfc_client_helpers::kUnknownObjectError, _))
402       .Times(2);
403   EXPECT_CALL(*mock_adapter0_proxy_, CallMethodWithErrorCallback(_, _, _, _))
404       .Times(0);
405   EXPECT_CALL(*mock_adapter1_proxy_, CallMethodWithErrorCallback(_, _, _, _))
406       .Times(0);;
407   adapter_client_->StartPollLoop(
408       dbus::ObjectPath(kTestAdapterPath0),
409       nfc_adapter::kModeInitiator,
410       base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
411       base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
412   adapter_client_->StartPollLoop(
413       dbus::ObjectPath(kTestAdapterPath1),
414       nfc_adapter::kModeInitiator,
415       base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
416       base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
417 }
418
419 // Tests that when tags are added and removed through an adapter, all
420 // observers are notified and the proxies are created and removed
421 // accordingly.
422 TEST_F(NfcClientTest, TagsAddedAndRemoved) {
423   // Invoking methods on tags that haven't been added should fail.
424   EXPECT_CALL(*this,
425               ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
426   NfcTagClient::RecordAttributes write_data;
427   write_data[nfc_record::kTypeProperty] = nfc_record::kTypeText;
428   tag_client_->Write(dbus::ObjectPath(kTestTagPath0), write_data,
429                      base::Bind(&NfcClientTest::SuccessCallback,
430                                 base::Unretained(this)),
431                      base::Bind(&NfcClientTest::ErrorCallback,
432                                 base::Unretained(this)));
433   Mock::VerifyAndClearExpectations(this);
434
435   // Add adapter 0.
436   std::vector<dbus::ObjectPath> adapter_paths;
437   adapter_paths.push_back(dbus::ObjectPath(kTestAdapterPath0));
438   EXPECT_CALL(mock_adapter_observer_,
439               AdapterAdded(dbus::ObjectPath(kTestAdapterPath0)));
440   SimulateAdaptersChanged(adapter_paths);
441
442   // Add tag 0.
443   std::vector<dbus::ObjectPath> tag_paths;
444   tag_paths.push_back(dbus::ObjectPath(kTestTagPath0));
445   EXPECT_CALL(mock_tag_observer_,
446               TagFound(dbus::ObjectPath(kTestTagPath0)));
447   SimulateTagsChanged(tag_paths, dbus::ObjectPath(kTestAdapterPath0));
448   Mock::VerifyAndClearExpectations(&mock_tag_observer_);
449
450   // Invoking methods should succeed on tag 0 but fail on tag 1.
451   EXPECT_CALL(*mock_tag0_proxy_, CallMethodWithErrorCallback(_, _, _, _));
452   tag_client_->Write(dbus::ObjectPath(kTestTagPath0), write_data,
453                      base::Bind(&NfcClientTest::SuccessCallback,
454                                 base::Unretained(this)),
455                      base::Bind(&NfcClientTest::ErrorCallback,
456                                 base::Unretained(this)));
457   Mock::VerifyAndClearExpectations(&mock_tag0_proxy_);
458   EXPECT_CALL(*this,
459               ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
460   EXPECT_CALL(*mock_tag1_proxy_, CallMethodWithErrorCallback(_, _, _, _))
461       .Times(0);
462   tag_client_->Write(dbus::ObjectPath(kTestTagPath1), write_data,
463                      base::Bind(&NfcClientTest::SuccessCallback,
464                                 base::Unretained(this)),
465                      base::Bind(&NfcClientTest::ErrorCallback,
466                                 base::Unretained(this)));
467   Mock::VerifyAndClearExpectations(this);
468   Mock::VerifyAndClearExpectations(&mock_tag1_proxy_);
469
470   // Add tag 1.
471   tag_paths.push_back(dbus::ObjectPath(kTestTagPath1));
472   EXPECT_CALL(mock_tag_observer_,
473               TagFound(dbus::ObjectPath(kTestTagPath1)));
474   SimulateTagsChanged(tag_paths, dbus::ObjectPath(kTestAdapterPath0));
475   Mock::VerifyAndClearExpectations(&mock_tag_observer_);
476
477   // Invoking methods should succeed on both tags.
478   EXPECT_CALL(*mock_tag0_proxy_, CallMethodWithErrorCallback(_, _, _, _));
479   EXPECT_CALL(*mock_tag1_proxy_, CallMethodWithErrorCallback(_, _, _, _));
480   tag_client_->Write(dbus::ObjectPath(kTestTagPath0), write_data,
481                      base::Bind(&NfcClientTest::SuccessCallback,
482                                 base::Unretained(this)),
483                      base::Bind(&NfcClientTest::ErrorCallback,
484                                 base::Unretained(this)));
485   tag_client_->Write(dbus::ObjectPath(kTestTagPath1), write_data,
486                      base::Bind(&NfcClientTest::SuccessCallback,
487                                 base::Unretained(this)),
488                      base::Bind(&NfcClientTest::ErrorCallback,
489                                 base::Unretained(this)));
490   Mock::VerifyAndClearExpectations(&mock_tag0_proxy_);
491   Mock::VerifyAndClearExpectations(&mock_tag1_proxy_);
492
493   // Remove tag 0.
494   tag_paths.erase(tag_paths.begin());
495   EXPECT_CALL(mock_tag_observer_,
496               TagLost(dbus::ObjectPath(kTestTagPath0)));
497   SimulateTagsChanged(tag_paths, dbus::ObjectPath(kTestAdapterPath0));
498   Mock::VerifyAndClearExpectations(&mock_tag_observer_);
499
500   // Invoking methods should succeed on tag 1 but fail on tag 0.
501   EXPECT_CALL(*this,
502               ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
503   EXPECT_CALL(*mock_tag0_proxy_, CallMethodWithErrorCallback(_, _, _, _))
504       .Times(0);
505   tag_client_->Write(dbus::ObjectPath(kTestTagPath0), write_data,
506                      base::Bind(&NfcClientTest::SuccessCallback,
507                                 base::Unretained(this)),
508                      base::Bind(&NfcClientTest::ErrorCallback,
509                                 base::Unretained(this)));
510   Mock::VerifyAndClearExpectations(this);
511   Mock::VerifyAndClearExpectations(&mock_tag0_proxy_);
512   EXPECT_CALL(*mock_tag1_proxy_, CallMethodWithErrorCallback(_, _, _, _));
513   tag_client_->Write(dbus::ObjectPath(kTestTagPath1), write_data,
514                      base::Bind(&NfcClientTest::SuccessCallback,
515                                 base::Unretained(this)),
516                      base::Bind(&NfcClientTest::ErrorCallback,
517                                 base::Unretained(this)));
518   Mock::VerifyAndClearExpectations(&mock_tag1_proxy_);
519
520   // Remove tag 1.
521   tag_paths.clear();
522   EXPECT_CALL(mock_tag_observer_,
523               TagLost(dbus::ObjectPath(kTestTagPath1)));
524   SimulateTagsChanged(tag_paths, dbus::ObjectPath(kTestAdapterPath0));
525   Mock::VerifyAndClearExpectations(&mock_tag_observer_);
526
527   // Invoking methods should fail on both tags.
528   EXPECT_CALL(*this,
529               ErrorCallback(nfc_client_helpers::kUnknownObjectError, _))
530       .Times(2);
531   EXPECT_CALL(*mock_tag0_proxy_, CallMethodWithErrorCallback(_, _, _, _))
532       .Times(0);
533   EXPECT_CALL(*mock_tag1_proxy_, CallMethodWithErrorCallback(_, _, _, _))
534       .Times(0);
535   tag_client_->Write(dbus::ObjectPath(kTestTagPath0), write_data,
536                      base::Bind(&NfcClientTest::SuccessCallback,
537                                 base::Unretained(this)),
538                      base::Bind(&NfcClientTest::ErrorCallback,
539                                 base::Unretained(this)));
540   tag_client_->Write(dbus::ObjectPath(kTestTagPath1), write_data,
541                      base::Bind(&NfcClientTest::SuccessCallback,
542                                 base::Unretained(this)),
543                      base::Bind(&NfcClientTest::ErrorCallback,
544                                 base::Unretained(this)));
545 }
546
547 // Tests that when devices are added and removed through an adapter, all
548 // observers are notified and the proxies are created and removed
549 // accordingly.
550 TEST_F(NfcClientTest, DevicesAddedAndRemoved) {
551   // Invoking methods on devices that haven't been added should fail.
552   EXPECT_CALL(*this,
553               ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
554   NfcDeviceClient::RecordAttributes write_data;
555   write_data[nfc_record::kTypeProperty] = nfc_record::kTypeText;
556   device_client_->Push(dbus::ObjectPath(kTestDevicePath0), write_data,
557                        base::Bind(&NfcClientTest::SuccessCallback,
558                                   base::Unretained(this)),
559                        base::Bind(&NfcClientTest::ErrorCallback,
560                                   base::Unretained(this)));
561   Mock::VerifyAndClearExpectations(this);
562
563   // Add adapter 0.
564   std::vector<dbus::ObjectPath> adapter_paths;
565   adapter_paths.push_back(dbus::ObjectPath(kTestAdapterPath0));
566   EXPECT_CALL(mock_adapter_observer_,
567               AdapterAdded(dbus::ObjectPath(kTestAdapterPath0)));
568   SimulateAdaptersChanged(adapter_paths);
569
570   // Add device 0.
571   std::vector<dbus::ObjectPath> device_paths;
572   device_paths.push_back(dbus::ObjectPath(kTestDevicePath0));
573   EXPECT_CALL(mock_device_observer_,
574               DeviceFound(dbus::ObjectPath(kTestDevicePath0)));
575   SimulateDevicesChanged(device_paths, dbus::ObjectPath(kTestAdapterPath0));
576   Mock::VerifyAndClearExpectations(&mock_device_observer_);
577
578   // Invoking methods should succeed on device 0 but fail on device 1.
579   EXPECT_CALL(*mock_device0_proxy_, CallMethodWithErrorCallback(_, _, _, _));
580   device_client_->Push(dbus::ObjectPath(kTestDevicePath0), write_data,
581                        base::Bind(&NfcClientTest::SuccessCallback,
582                                   base::Unretained(this)),
583                        base::Bind(&NfcClientTest::ErrorCallback,
584                                   base::Unretained(this)));
585   Mock::VerifyAndClearExpectations(&mock_device0_proxy_);
586   EXPECT_CALL(*this,
587               ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
588   EXPECT_CALL(*mock_device1_proxy_, CallMethodWithErrorCallback(_, _, _, _))
589       .Times(0);
590   device_client_->Push(dbus::ObjectPath(kTestDevicePath1), write_data,
591                        base::Bind(&NfcClientTest::SuccessCallback,
592                                   base::Unretained(this)),
593                        base::Bind(&NfcClientTest::ErrorCallback,
594                                   base::Unretained(this)));
595   Mock::VerifyAndClearExpectations(this);
596   Mock::VerifyAndClearExpectations(&mock_device1_proxy_);
597
598   // Add device 1.
599   device_paths.push_back(dbus::ObjectPath(kTestDevicePath1));
600   EXPECT_CALL(mock_device_observer_,
601               DeviceFound(dbus::ObjectPath(kTestDevicePath1)));
602   SimulateDevicesChanged(device_paths, dbus::ObjectPath(kTestAdapterPath0));
603   Mock::VerifyAndClearExpectations(&mock_device_observer_);
604
605   // Invoking methods should succeed on both devices.
606   EXPECT_CALL(*mock_device0_proxy_, CallMethodWithErrorCallback(_, _, _, _));
607   EXPECT_CALL(*mock_device1_proxy_, CallMethodWithErrorCallback(_, _, _, _));
608   device_client_->Push(dbus::ObjectPath(kTestDevicePath0), write_data,
609                        base::Bind(&NfcClientTest::SuccessCallback,
610                                   base::Unretained(this)),
611                        base::Bind(&NfcClientTest::ErrorCallback,
612                                   base::Unretained(this)));
613   device_client_->Push(dbus::ObjectPath(kTestDevicePath1), write_data,
614                        base::Bind(&NfcClientTest::SuccessCallback,
615                                   base::Unretained(this)),
616                        base::Bind(&NfcClientTest::ErrorCallback,
617                                   base::Unretained(this)));
618   Mock::VerifyAndClearExpectations(&mock_device0_proxy_);
619   Mock::VerifyAndClearExpectations(&mock_device1_proxy_);
620
621   // Remove device 0.
622   device_paths.erase(device_paths.begin());
623   EXPECT_CALL(mock_device_observer_,
624               DeviceLost(dbus::ObjectPath(kTestDevicePath0)));
625   SimulateDevicesChanged(device_paths, dbus::ObjectPath(kTestAdapterPath0));
626   Mock::VerifyAndClearExpectations(&mock_device_observer_);
627
628   // Invoking methods should succeed on device 1 but fail on device 0.
629   EXPECT_CALL(*this,
630               ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
631   EXPECT_CALL(*mock_device0_proxy_, CallMethodWithErrorCallback(_, _, _, _))
632       .Times(0);
633   device_client_->Push(dbus::ObjectPath(kTestDevicePath0), write_data,
634                        base::Bind(&NfcClientTest::SuccessCallback,
635                                   base::Unretained(this)),
636                        base::Bind(&NfcClientTest::ErrorCallback,
637                                   base::Unretained(this)));
638   Mock::VerifyAndClearExpectations(this);
639   Mock::VerifyAndClearExpectations(&mock_device0_proxy_);
640   EXPECT_CALL(*mock_device1_proxy_, CallMethodWithErrorCallback(_, _, _, _));
641   device_client_->Push(dbus::ObjectPath(kTestDevicePath1), write_data,
642                        base::Bind(&NfcClientTest::SuccessCallback,
643                                   base::Unretained(this)),
644                        base::Bind(&NfcClientTest::ErrorCallback,
645                                   base::Unretained(this)));
646   Mock::VerifyAndClearExpectations(&mock_device1_proxy_);
647
648   // Remove device 1.
649   device_paths.clear();
650   EXPECT_CALL(mock_device_observer_,
651               DeviceLost(dbus::ObjectPath(kTestDevicePath1)));
652   SimulateDevicesChanged(device_paths, dbus::ObjectPath(kTestAdapterPath0));
653   Mock::VerifyAndClearExpectations(&mock_device_observer_);
654
655   // Invoking methods should fail on both devices.
656   EXPECT_CALL(*this,
657               ErrorCallback(nfc_client_helpers::kUnknownObjectError, _))
658       .Times(2);
659   EXPECT_CALL(*mock_device0_proxy_, CallMethodWithErrorCallback(_, _, _, _))
660       .Times(0);
661   EXPECT_CALL(*mock_device1_proxy_, CallMethodWithErrorCallback(_, _, _, _))
662       .Times(0);
663   device_client_->Push(dbus::ObjectPath(kTestDevicePath0), write_data,
664                        base::Bind(&NfcClientTest::SuccessCallback,
665                                   base::Unretained(this)),
666                        base::Bind(&NfcClientTest::ErrorCallback,
667                                   base::Unretained(this)));
668   device_client_->Push(dbus::ObjectPath(kTestDevicePath1), write_data,
669                        base::Bind(&NfcClientTest::SuccessCallback,
670                                   base::Unretained(this)),
671                        base::Bind(&NfcClientTest::ErrorCallback,
672                                   base::Unretained(this)));
673 }
674
675 }  // namespace chromeos