nfc_client_unittest.cc revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
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
18using ::testing::_;
19using ::testing::Invoke;
20using ::testing::Mock;
21using ::testing::Return;
22
23namespace chromeos {
24
25namespace {
26
27// D-Bus service name used by the test.
28const char kTestServiceName[] = "test.service.name";
29
30// Object paths that are used for testing.
31const char kTestManagerPath[] = "/test/nfc/manager";
32const char kTestAdapterPath0[] = "/test/nfc/adapter0";
33const char kTestAdapterPath1[] = "/test/nfc/adapter1";
34const char kTestDevicePath0[] = "/test/nfc/device0";
35const char kTestDevicePath1[] = "/test/nfc/device1";
36const char kTestTagPath0[] = "/test/nfc/tag0";
37const char kTestTagPath1[] = "/test/nfc/tag1";
38
39class 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
46class 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
54class 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
62class 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
72class 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.
306TEST_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.
422TEST_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.
550TEST_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
676