nfc_client_unittest.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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_record_client.h"
12#include "chromeos/dbus/nfc_tag_client.h"
13#include "dbus/mock_bus.h"
14#include "dbus/mock_object_proxy.h"
15#include "testing/gmock/include/gmock/gmock.h"
16#include "testing/gtest/include/gtest/gtest.h"
17#include "third_party/cros_system_api/dbus/service_constants.h"
18
19using ::testing::_;
20using ::testing::Invoke;
21using ::testing::Mock;
22using ::testing::Return;
23
24using chromeos::nfc_client_helpers::ObjectPathVector;
25
26namespace chromeos {
27
28namespace {
29
30// D-Bus service name used by the test.
31const char kTestServiceName[] = "test.service.name";
32
33// Object paths that are used for testing.
34const char kTestManagerPath[] = "/test/nfc/manager";
35const char kTestAdapterPath0[] = "/test/nfc/adapter0";
36const char kTestAdapterPath1[] = "/test/nfc/adapter1";
37const char kTestDevicePath0[] = "/test/nfc/device0";
38const char kTestDevicePath1[] = "/test/nfc/device1";
39const char kTestRecordPath0[] = "/test/nfc/record0";
40const char kTestRecordPath1[] = "/test/nfc/record1";
41const char kTestRecordPath2[] = "/test/nfc/record2";
42const char kTestRecordPath3[] = "/test/nfc/record3";
43const char kTestTagPath0[] = "/test/nfc/tag0";
44const char kTestTagPath1[] = "/test/nfc/tag1";
45
46class MockNfcManagerObserver : public NfcManagerClient::Observer {
47 public:
48  MOCK_METHOD1(AdapterAdded, void(const dbus::ObjectPath&));
49  MOCK_METHOD1(AdapterRemoved, void(const dbus::ObjectPath&));
50  MOCK_METHOD1(ManagerPropertyChanged, void(const std::string&));
51};
52
53class MockNfcAdapterObserver : public NfcAdapterClient::Observer {
54 public:
55  MOCK_METHOD1(AdapterAdded, void(const dbus::ObjectPath&));
56  MOCK_METHOD1(AdapterRemoved, void(const dbus::ObjectPath&));
57  MOCK_METHOD2(AdapterPropertyChanged, void(const dbus::ObjectPath&,
58                                            const std::string&));
59};
60
61class MockNfcDeviceObserver : public NfcDeviceClient::Observer {
62 public:
63  MOCK_METHOD1(DeviceAdded, void(const dbus::ObjectPath&));
64  MOCK_METHOD1(DeviceRemoved, void(const dbus::ObjectPath&));
65  MOCK_METHOD2(DevicePropertyChanged, void(const dbus::ObjectPath&,
66                                           const std::string&));
67};
68
69class MockNfcRecordObserver : public NfcRecordClient::Observer {
70 public:
71  MOCK_METHOD1(RecordAdded, void(const dbus::ObjectPath&));
72  MOCK_METHOD1(RecordRemoved, void(const dbus::ObjectPath&));
73  MOCK_METHOD2(RecordPropertyChanged, void(const dbus::ObjectPath&,
74                                           const std::string&));
75  MOCK_METHOD1(RecordPropertiesReceived, void(const dbus::ObjectPath&));
76};
77
78class MockNfcTagObserver : public NfcTagClient::Observer {
79 public:
80  MOCK_METHOD1(TagAdded, void(const dbus::ObjectPath&));
81  MOCK_METHOD1(TagRemoved, void(const dbus::ObjectPath&));
82  MOCK_METHOD2(TagPropertyChanged, void(const dbus::ObjectPath&,
83                                        const std::string&));
84};
85
86}  // namespace
87
88class NfcClientTest : public testing::Test {
89 public:
90  NfcClientTest() : response_(NULL) {}
91  virtual ~NfcClientTest() {}
92
93  virtual void SetUp() OVERRIDE {
94    // Create the mock bus.
95    dbus::Bus::Options options;
96    options.bus_type = dbus::Bus::SYSTEM;
97    mock_bus_ = new dbus::MockBus(options);
98
99    // Create the mock proxies.
100    mock_manager_proxy_ = new dbus::MockObjectProxy(
101        mock_bus_.get(),
102        kTestServiceName,
103        dbus::ObjectPath(kTestManagerPath));
104    mock_adapter0_proxy_ = new dbus::MockObjectProxy(
105        mock_bus_.get(),
106        kTestServiceName,
107        dbus::ObjectPath(kTestAdapterPath0));
108    mock_adapter1_proxy_ = new dbus::MockObjectProxy(
109        mock_bus_.get(),
110        kTestServiceName,
111        dbus::ObjectPath(kTestAdapterPath1));
112    mock_device0_proxy_ = new dbus::MockObjectProxy(
113        mock_bus_.get(),
114        kTestServiceName,
115        dbus::ObjectPath(kTestDevicePath0));
116    mock_device1_proxy_ = new dbus::MockObjectProxy(
117        mock_bus_.get(),
118        kTestServiceName,
119        dbus::ObjectPath(kTestDevicePath1));
120    mock_record0_proxy_ = new dbus::MockObjectProxy(
121        mock_bus_.get(),
122        kTestServiceName,
123        dbus::ObjectPath(kTestRecordPath0));
124    mock_record1_proxy_ = new dbus::MockObjectProxy(
125        mock_bus_.get(),
126        kTestServiceName,
127        dbus::ObjectPath(kTestRecordPath1));
128    mock_record2_proxy_ = new dbus::MockObjectProxy(
129        mock_bus_.get(),
130        kTestServiceName,
131        dbus::ObjectPath(kTestRecordPath2));
132    mock_record3_proxy_ = new dbus::MockObjectProxy(
133        mock_bus_.get(),
134        kTestServiceName,
135        dbus::ObjectPath(kTestRecordPath3));
136    mock_tag0_proxy_ = new dbus::MockObjectProxy(
137        mock_bus_.get(),
138        kTestServiceName,
139        dbus::ObjectPath(kTestTagPath0));
140    mock_tag1_proxy_ = new dbus::MockObjectProxy(
141        mock_bus_.get(),
142        kTestServiceName,
143        dbus::ObjectPath(kTestTagPath1));
144
145    // Set expectations that use NfcClientTest::OnConnectToSignal when the
146    // client connect signals on the mock proxies.
147    EXPECT_CALL(*mock_manager_proxy_.get(), ConnectToSignal(_, _, _, _))
148        .WillRepeatedly(Invoke(this, &NfcClientTest::OnConnectToSignal));
149    EXPECT_CALL(*mock_adapter0_proxy_.get(), ConnectToSignal(_, _, _, _))
150        .WillRepeatedly(Invoke(this, &NfcClientTest::OnConnectToSignal));
151    EXPECT_CALL(*mock_adapter1_proxy_.get(), ConnectToSignal(_, _, _, _))
152        .WillRepeatedly(Invoke(this, &NfcClientTest::OnConnectToSignal));
153
154    // Set expectations that return our mock proxies on demand.
155    EXPECT_CALL(
156        *mock_bus_.get(),
157        GetObjectProxy(nfc_manager::kNfcManagerServiceName,
158                       dbus::ObjectPath(nfc_manager::kNfcManagerServicePath)))
159        .WillRepeatedly(Return(mock_manager_proxy_.get()));
160    EXPECT_CALL(*mock_bus_.get(),
161                GetObjectProxy(nfc_adapter::kNfcAdapterServiceName,
162                               dbus::ObjectPath(kTestAdapterPath0)))
163        .WillRepeatedly(Return(mock_adapter0_proxy_.get()));
164    EXPECT_CALL(*mock_bus_.get(),
165                GetObjectProxy(nfc_adapter::kNfcAdapterServiceName,
166                               dbus::ObjectPath(kTestAdapterPath1)))
167        .WillRepeatedly(Return(mock_adapter1_proxy_.get()));
168    EXPECT_CALL(*mock_bus_.get(),
169                GetObjectProxy(nfc_device::kNfcDeviceServiceName,
170                               dbus::ObjectPath(kTestDevicePath0)))
171        .WillRepeatedly(Return(mock_device0_proxy_.get()));
172    EXPECT_CALL(*mock_bus_.get(),
173                GetObjectProxy(nfc_device::kNfcDeviceServiceName,
174                               dbus::ObjectPath(kTestDevicePath1)))
175        .WillRepeatedly(Return(mock_device1_proxy_.get()));
176    EXPECT_CALL(*mock_bus_.get(),
177                GetObjectProxy(nfc_record::kNfcRecordServiceName,
178                               dbus::ObjectPath(kTestRecordPath0)))
179        .WillRepeatedly(Return(mock_record0_proxy_.get()));
180    EXPECT_CALL(*mock_bus_.get(),
181                GetObjectProxy(nfc_record::kNfcRecordServiceName,
182                               dbus::ObjectPath(kTestRecordPath1)))
183        .WillRepeatedly(Return(mock_record1_proxy_.get()));
184    EXPECT_CALL(*mock_bus_.get(),
185                GetObjectProxy(nfc_record::kNfcRecordServiceName,
186                               dbus::ObjectPath(kTestRecordPath2)))
187        .WillRepeatedly(Return(mock_record2_proxy_.get()));
188    EXPECT_CALL(*mock_bus_.get(),
189                GetObjectProxy(nfc_record::kNfcRecordServiceName,
190                               dbus::ObjectPath(kTestRecordPath3)))
191        .WillRepeatedly(Return(mock_record3_proxy_.get()));
192    EXPECT_CALL(*mock_bus_.get(),
193                GetObjectProxy(nfc_tag::kNfcTagServiceName,
194                               dbus::ObjectPath(kTestTagPath0)))
195        .WillRepeatedly(Return(mock_tag0_proxy_.get()));
196    EXPECT_CALL(*mock_bus_.get(),
197                GetObjectProxy(nfc_tag::kNfcTagServiceName,
198                               dbus::ObjectPath(kTestTagPath1)))
199        .WillRepeatedly(Return(mock_tag1_proxy_.get()));
200
201    // ShutdownAndBlock will be called in TearDown.
202    EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()).WillOnce(Return());
203
204    // Create the clients.
205    manager_client_.reset(NfcManagerClient::Create());
206    adapter_client_.reset(NfcAdapterClient::Create(manager_client_.get()));
207    device_client_.reset(NfcDeviceClient::Create(adapter_client_.get()));
208    tag_client_.reset(NfcTagClient::Create(adapter_client_.get()));
209    record_client_.reset(
210        NfcRecordClient::Create(device_client_.get(), tag_client_.get()));
211    manager_client_->Init(mock_bus_.get());
212    adapter_client_->Init(mock_bus_.get());
213    device_client_->Init(mock_bus_.get());
214    tag_client_->Init(mock_bus_.get());
215    record_client_->Init(mock_bus_.get());
216    manager_client_->AddObserver(&mock_manager_observer_);
217    adapter_client_->AddObserver(&mock_adapter_observer_);
218    device_client_->AddObserver(&mock_device_observer_);
219    tag_client_->AddObserver(&mock_tag_observer_);
220    record_client_->AddObserver(&mock_record_observer_);
221
222    message_loop_.RunUntilIdle();
223  }
224
225  virtual void TearDown() OVERRIDE {
226    tag_client_->RemoveObserver(&mock_tag_observer_);
227    device_client_->RemoveObserver(&mock_device_observer_);
228    adapter_client_->RemoveObserver(&mock_adapter_observer_);
229    manager_client_->RemoveObserver(&mock_manager_observer_);
230    mock_bus_->ShutdownAndBlock();
231  }
232
233  void SimulateAdaptersChanged(
234      const ObjectPathVector& adapter_paths) {
235    NfcManagerClient::Properties* properties =
236        manager_client_->GetProperties();
237    ASSERT_TRUE(properties);
238    EXPECT_CALL(mock_manager_observer_,
239                ManagerPropertyChanged(nfc_manager::kAdaptersProperty));
240    SendArrayPropertyChangedSignal(
241        properties,
242        nfc_manager::kNfcManagerInterface,
243        nfc_manager::kAdaptersProperty,
244        adapter_paths);
245    Mock::VerifyAndClearExpectations(&mock_manager_observer_);
246  }
247
248  void SimulateTagsChanged(const ObjectPathVector& tag_paths,
249                           const dbus::ObjectPath& adapter_path) {
250    NfcAdapterClient::Properties* properties =
251        adapter_client_->GetProperties(adapter_path);
252    ASSERT_TRUE(properties);
253    EXPECT_CALL(mock_adapter_observer_,
254                AdapterPropertyChanged(adapter_path,
255                                       nfc_adapter::kTagsProperty));
256    SendArrayPropertyChangedSignal(
257        properties,
258        nfc_adapter::kNfcAdapterInterface,
259        nfc_adapter::kTagsProperty,
260        tag_paths);
261    Mock::VerifyAndClearExpectations(&mock_adapter_observer_);
262  }
263
264  void SimulateDevicesChanged(const ObjectPathVector& device_paths,
265                              const dbus::ObjectPath& adapter_path) {
266    NfcAdapterClient::Properties* properties =
267        adapter_client_->GetProperties(adapter_path);
268    ASSERT_TRUE(properties);
269    EXPECT_CALL(mock_adapter_observer_,
270                AdapterPropertyChanged(adapter_path,
271                                       nfc_adapter::kDevicesProperty));
272    SendArrayPropertyChangedSignal(
273        properties,
274        nfc_adapter::kNfcAdapterInterface,
275        nfc_adapter::kDevicesProperty,
276        device_paths);
277    Mock::VerifyAndClearExpectations(&mock_adapter_observer_);
278  }
279
280  void SimulateDeviceRecordsChanged(
281      const ObjectPathVector& record_paths,
282      const dbus::ObjectPath& device_path) {
283    NfcDeviceClient::Properties* properties =
284        device_client_->GetProperties(device_path);
285    ASSERT_TRUE(properties);
286    EXPECT_CALL(mock_device_observer_,
287                DevicePropertyChanged(device_path,
288                                      nfc_device::kRecordsProperty));
289    SendArrayPropertyChangedSignal(
290        properties,
291        nfc_device::kNfcDeviceInterface,
292        nfc_device::kRecordsProperty,
293        record_paths);
294    Mock::VerifyAndClearExpectations(&mock_device_observer_);
295  }
296
297  void SimulateTagRecordsChanged(
298      const ObjectPathVector& record_paths,
299      const dbus::ObjectPath& tag_path) {
300    NfcTagClient::Properties* properties =
301        tag_client_->GetProperties(tag_path);
302    ASSERT_TRUE(properties);
303    EXPECT_CALL(mock_tag_observer_,
304                TagPropertyChanged(tag_path,
305                                   nfc_tag::kRecordsProperty));
306    SendArrayPropertyChangedSignal(
307        properties,
308        nfc_tag::kNfcTagInterface,
309        nfc_tag::kRecordsProperty,
310        record_paths);
311    Mock::VerifyAndClearExpectations(&mock_tag_observer_);
312  }
313
314  void SendArrayPropertyChangedSignal(
315      dbus::PropertySet* properties,
316      const std::string& interface,
317      const std::string& property_name,
318      ObjectPathVector object_paths) {
319    dbus::Signal signal(interface, nfc_common::kPropertyChangedSignal);
320    dbus::MessageWriter writer(&signal);
321    writer.AppendString(property_name);
322    dbus::MessageWriter variant_writer(NULL);
323    writer.OpenVariant("ao", &variant_writer);
324    variant_writer.AppendArrayOfObjectPaths(object_paths);
325    writer.CloseContainer(&variant_writer);
326    properties->ChangedReceived(&signal);
327  }
328
329  MOCK_METHOD0(SuccessCallback, void(void));
330  MOCK_METHOD2(ErrorCallback, void(const std::string& error_name,
331                                   const std::string& error_message));
332
333 protected:
334  // The mock object proxies.
335  scoped_refptr<dbus::MockObjectProxy> mock_manager_proxy_;
336  scoped_refptr<dbus::MockObjectProxy> mock_adapter0_proxy_;
337  scoped_refptr<dbus::MockObjectProxy> mock_adapter1_proxy_;
338  scoped_refptr<dbus::MockObjectProxy> mock_device0_proxy_;
339  scoped_refptr<dbus::MockObjectProxy> mock_device1_proxy_;
340  scoped_refptr<dbus::MockObjectProxy> mock_record0_proxy_;
341  scoped_refptr<dbus::MockObjectProxy> mock_record1_proxy_;
342  scoped_refptr<dbus::MockObjectProxy> mock_record2_proxy_;
343  scoped_refptr<dbus::MockObjectProxy> mock_record3_proxy_;
344  scoped_refptr<dbus::MockObjectProxy> mock_tag0_proxy_;
345  scoped_refptr<dbus::MockObjectProxy> mock_tag1_proxy_;
346  // The mock bus.
347  scoped_refptr<dbus::MockBus> mock_bus_;
348  // A message loop to emulate asynchronous behavior.
349  base::MessageLoop message_loop_;
350  // Response returned by mock methods.
351  dbus::Response* response_;
352  // The D-Bus client objects under test.
353  scoped_ptr<NfcManagerClient> manager_client_;
354  scoped_ptr<NfcAdapterClient> adapter_client_;
355  scoped_ptr<NfcDeviceClient> device_client_;
356  scoped_ptr<NfcTagClient> tag_client_;
357  scoped_ptr<NfcRecordClient> record_client_;
358  // Mock observers.
359  MockNfcManagerObserver mock_manager_observer_;
360  MockNfcAdapterObserver mock_adapter_observer_;
361  MockNfcDeviceObserver mock_device_observer_;
362  MockNfcTagObserver mock_tag_observer_;
363  MockNfcRecordObserver mock_record_observer_;
364  // The signal callbacks used to simulate asychronous signals.
365  dbus::ObjectProxy::SignalCallback manager_adapter_added_signal_callback_;
366  dbus::ObjectProxy::SignalCallback manager_adapter_removed_signal_callback_;
367
368 private:
369  // Used to implement the mock proxy.
370  void OnConnectToSignal(
371      const std::string& interface_name,
372      const std::string& signal_name,
373      const dbus::ObjectProxy::SignalCallback& signal_callback,
374      const dbus::ObjectProxy::OnConnectedCallback& on_connected_callback) {
375    if (interface_name == nfc_manager::kNfcManagerInterface) {
376      if (signal_name == nfc_manager::kAdapterAddedSignal)
377        manager_adapter_added_signal_callback_ = signal_callback;
378      else if (signal_name == nfc_manager::kAdapterRemovedSignal)
379        manager_adapter_removed_signal_callback_ = signal_callback;
380    }
381    message_loop_.PostTask(FROM_HERE, base::Bind(on_connected_callback,
382                                                 interface_name,
383                                                 signal_name,
384                                                 true));
385  }
386};
387
388// Tests that when adapters are added and removed through the manager, all
389// observers are notified and the proxies are created and removed
390// accordingly.
391TEST_F(NfcClientTest, AdaptersAddedAndRemoved) {
392  // Invoking methods on adapters that haven't been added should fail.
393  EXPECT_CALL(*this,
394              ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
395  adapter_client_->StartPollLoop(
396      dbus::ObjectPath(kTestAdapterPath0),
397      nfc_adapter::kModeInitiator,
398      base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
399      base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
400  Mock::VerifyAndClearExpectations(this);
401
402  // Add adapter 0.
403  ObjectPathVector adapter_paths;
404  adapter_paths.push_back(dbus::ObjectPath(kTestAdapterPath0));
405  EXPECT_CALL(mock_adapter_observer_,
406              AdapterAdded(dbus::ObjectPath(kTestAdapterPath0)));
407  SimulateAdaptersChanged(adapter_paths);
408
409  // Invoking methods should succeed on adapter 0 but fail on adapter 1.
410  EXPECT_CALL(*mock_adapter0_proxy_, CallMethodWithErrorCallback(_, _, _, _));
411  adapter_client_->StartPollLoop(
412      dbus::ObjectPath(kTestAdapterPath0),
413      nfc_adapter::kModeInitiator,
414      base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
415      base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
416  Mock::VerifyAndClearExpectations(&mock_adapter0_proxy_);
417  EXPECT_CALL(*this,
418              ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
419  EXPECT_CALL(*mock_adapter1_proxy_, CallMethodWithErrorCallback(_, _, _, _))
420      .Times(0);
421  adapter_client_->StartPollLoop(
422      dbus::ObjectPath(kTestAdapterPath1),
423      nfc_adapter::kModeInitiator,
424      base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
425      base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
426  Mock::VerifyAndClearExpectations(this);
427  Mock::VerifyAndClearExpectations(&mock_adapter1_proxy_);
428
429  // Add adapter 1.
430  adapter_paths.push_back(dbus::ObjectPath(kTestAdapterPath1));
431  EXPECT_CALL(mock_adapter_observer_,
432              AdapterAdded(dbus::ObjectPath(kTestAdapterPath1)));
433  SimulateAdaptersChanged(adapter_paths);
434
435  // Invoking methods should succeed on both adapters.
436  EXPECT_CALL(*mock_adapter0_proxy_, CallMethodWithErrorCallback(_, _, _, _));
437  EXPECT_CALL(*mock_adapter1_proxy_, CallMethodWithErrorCallback(_, _, _, _));
438  adapter_client_->StartPollLoop(
439      dbus::ObjectPath(kTestAdapterPath0),
440      nfc_adapter::kModeInitiator,
441      base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
442      base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
443  adapter_client_->StartPollLoop(
444      dbus::ObjectPath(kTestAdapterPath1),
445      nfc_adapter::kModeInitiator,
446      base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
447      base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
448  Mock::VerifyAndClearExpectations(&mock_adapter0_proxy_);
449  Mock::VerifyAndClearExpectations(&mock_adapter1_proxy_);
450
451  // Remove adapter 0.
452  adapter_paths.erase(adapter_paths.begin());
453  EXPECT_CALL(mock_adapter_observer_,
454              AdapterRemoved(dbus::ObjectPath(kTestAdapterPath0)));
455  SimulateAdaptersChanged(adapter_paths);
456
457  // Invoking methods should succeed on adapter 1 but fail on adapter 0.
458  EXPECT_CALL(*this,
459              ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
460  EXPECT_CALL(*mock_adapter0_proxy_, CallMethodWithErrorCallback(_, _, _, _))
461      .Times(0);
462  adapter_client_->StartPollLoop(
463      dbus::ObjectPath(kTestAdapterPath0),
464      nfc_adapter::kModeInitiator,
465      base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
466      base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
467  Mock::VerifyAndClearExpectations(this);
468
469  EXPECT_CALL(*mock_adapter1_proxy_, CallMethodWithErrorCallback(_, _, _, _));
470  adapter_client_->StartPollLoop(
471      dbus::ObjectPath(kTestAdapterPath1),
472      nfc_adapter::kModeInitiator,
473      base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
474      base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
475  Mock::VerifyAndClearExpectations(&mock_adapter0_proxy_);
476  Mock::VerifyAndClearExpectations(&mock_adapter1_proxy_);
477
478  // Remove adapter 1.
479  adapter_paths.clear();
480  EXPECT_CALL(mock_adapter_observer_,
481              AdapterRemoved(dbus::ObjectPath(kTestAdapterPath1)));
482  SimulateAdaptersChanged(adapter_paths);
483
484  // Invoking methods should fail on both adapters.
485  EXPECT_CALL(*this,
486              ErrorCallback(nfc_client_helpers::kUnknownObjectError, _))
487      .Times(2);
488  EXPECT_CALL(*mock_adapter0_proxy_, CallMethodWithErrorCallback(_, _, _, _))
489      .Times(0);
490  EXPECT_CALL(*mock_adapter1_proxy_, CallMethodWithErrorCallback(_, _, _, _))
491      .Times(0);
492  adapter_client_->StartPollLoop(
493      dbus::ObjectPath(kTestAdapterPath0),
494      nfc_adapter::kModeInitiator,
495      base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
496      base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
497  adapter_client_->StartPollLoop(
498      dbus::ObjectPath(kTestAdapterPath1),
499      nfc_adapter::kModeInitiator,
500      base::Bind(&NfcClientTest::SuccessCallback, base::Unretained(this)),
501      base::Bind(&NfcClientTest::ErrorCallback, base::Unretained(this)));
502}
503
504// Tests that when tags are added and removed through an adapter, all
505// observers are notified and the proxies are created and removed
506// accordingly.
507TEST_F(NfcClientTest, TagsAddedAndRemoved) {
508  // Invoking methods on tags that haven't been added should fail.
509  EXPECT_CALL(*this,
510              ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
511  base::DictionaryValue write_data;
512  write_data.SetString(nfc_record::kTypeProperty, nfc_record::kTypeText);
513  tag_client_->Write(dbus::ObjectPath(kTestTagPath0), write_data,
514                     base::Bind(&NfcClientTest::SuccessCallback,
515                                base::Unretained(this)),
516                     base::Bind(&NfcClientTest::ErrorCallback,
517                                base::Unretained(this)));
518  Mock::VerifyAndClearExpectations(this);
519
520  // Add adapter 0.
521  ObjectPathVector adapter_paths;
522  adapter_paths.push_back(dbus::ObjectPath(kTestAdapterPath0));
523  EXPECT_CALL(mock_adapter_observer_,
524              AdapterAdded(dbus::ObjectPath(kTestAdapterPath0)));
525  SimulateAdaptersChanged(adapter_paths);
526  Mock::VerifyAndClearExpectations(&mock_adapter_observer_);
527
528  // Add tag 0.
529  ObjectPathVector tag_paths;
530  tag_paths.push_back(dbus::ObjectPath(kTestTagPath0));
531  EXPECT_CALL(mock_tag_observer_,
532              TagAdded(dbus::ObjectPath(kTestTagPath0)));
533  SimulateTagsChanged(tag_paths, dbus::ObjectPath(kTestAdapterPath0));
534  Mock::VerifyAndClearExpectations(&mock_tag_observer_);
535
536  // Invoking methods should succeed on tag 0 but fail on tag 1.
537  EXPECT_CALL(*mock_tag0_proxy_, CallMethodWithErrorCallback(_, _, _, _));
538  tag_client_->Write(dbus::ObjectPath(kTestTagPath0), write_data,
539                     base::Bind(&NfcClientTest::SuccessCallback,
540                                base::Unretained(this)),
541                     base::Bind(&NfcClientTest::ErrorCallback,
542                                base::Unretained(this)));
543  Mock::VerifyAndClearExpectations(&mock_tag0_proxy_);
544  EXPECT_CALL(*this,
545              ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
546  EXPECT_CALL(*mock_tag1_proxy_, CallMethodWithErrorCallback(_, _, _, _))
547      .Times(0);
548  tag_client_->Write(dbus::ObjectPath(kTestTagPath1), write_data,
549                     base::Bind(&NfcClientTest::SuccessCallback,
550                                base::Unretained(this)),
551                     base::Bind(&NfcClientTest::ErrorCallback,
552                                base::Unretained(this)));
553  Mock::VerifyAndClearExpectations(this);
554  Mock::VerifyAndClearExpectations(&mock_tag1_proxy_);
555
556  // Add tag 1.
557  tag_paths.push_back(dbus::ObjectPath(kTestTagPath1));
558  EXPECT_CALL(mock_tag_observer_,
559              TagAdded(dbus::ObjectPath(kTestTagPath1)));
560  SimulateTagsChanged(tag_paths, dbus::ObjectPath(kTestAdapterPath0));
561  Mock::VerifyAndClearExpectations(&mock_tag_observer_);
562
563  // Invoking methods should succeed on both tags.
564  EXPECT_CALL(*mock_tag0_proxy_, CallMethodWithErrorCallback(_, _, _, _));
565  EXPECT_CALL(*mock_tag1_proxy_, CallMethodWithErrorCallback(_, _, _, _));
566  tag_client_->Write(dbus::ObjectPath(kTestTagPath0), write_data,
567                     base::Bind(&NfcClientTest::SuccessCallback,
568                                base::Unretained(this)),
569                     base::Bind(&NfcClientTest::ErrorCallback,
570                                base::Unretained(this)));
571  tag_client_->Write(dbus::ObjectPath(kTestTagPath1), write_data,
572                     base::Bind(&NfcClientTest::SuccessCallback,
573                                base::Unretained(this)),
574                     base::Bind(&NfcClientTest::ErrorCallback,
575                                base::Unretained(this)));
576  Mock::VerifyAndClearExpectations(&mock_tag0_proxy_);
577  Mock::VerifyAndClearExpectations(&mock_tag1_proxy_);
578
579  // Remove tag 0.
580  tag_paths.erase(tag_paths.begin());
581  EXPECT_CALL(mock_tag_observer_,
582              TagRemoved(dbus::ObjectPath(kTestTagPath0)));
583  SimulateTagsChanged(tag_paths, dbus::ObjectPath(kTestAdapterPath0));
584  Mock::VerifyAndClearExpectations(&mock_tag_observer_);
585
586  // Invoking methods should succeed on tag 1 but fail on tag 0.
587  EXPECT_CALL(*this,
588              ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
589  EXPECT_CALL(*mock_tag0_proxy_, CallMethodWithErrorCallback(_, _, _, _))
590      .Times(0);
591  tag_client_->Write(dbus::ObjectPath(kTestTagPath0), write_data,
592                     base::Bind(&NfcClientTest::SuccessCallback,
593                                base::Unretained(this)),
594                     base::Bind(&NfcClientTest::ErrorCallback,
595                                base::Unretained(this)));
596  Mock::VerifyAndClearExpectations(this);
597  Mock::VerifyAndClearExpectations(&mock_tag0_proxy_);
598  EXPECT_CALL(*mock_tag1_proxy_, CallMethodWithErrorCallback(_, _, _, _));
599  tag_client_->Write(dbus::ObjectPath(kTestTagPath1), write_data,
600                     base::Bind(&NfcClientTest::SuccessCallback,
601                                base::Unretained(this)),
602                     base::Bind(&NfcClientTest::ErrorCallback,
603                                base::Unretained(this)));
604  Mock::VerifyAndClearExpectations(&mock_tag1_proxy_);
605
606  // Remove tag 1.
607  tag_paths.clear();
608  EXPECT_CALL(mock_tag_observer_,
609              TagRemoved(dbus::ObjectPath(kTestTagPath1)));
610  SimulateTagsChanged(tag_paths, dbus::ObjectPath(kTestAdapterPath0));
611  Mock::VerifyAndClearExpectations(&mock_tag_observer_);
612
613  // Invoking methods should fail on both tags.
614  EXPECT_CALL(*this,
615              ErrorCallback(nfc_client_helpers::kUnknownObjectError, _))
616      .Times(2);
617  EXPECT_CALL(*mock_tag0_proxy_, CallMethodWithErrorCallback(_, _, _, _))
618      .Times(0);
619  EXPECT_CALL(*mock_tag1_proxy_, CallMethodWithErrorCallback(_, _, _, _))
620      .Times(0);
621  tag_client_->Write(dbus::ObjectPath(kTestTagPath0), write_data,
622                     base::Bind(&NfcClientTest::SuccessCallback,
623                                base::Unretained(this)),
624                     base::Bind(&NfcClientTest::ErrorCallback,
625                                base::Unretained(this)));
626  tag_client_->Write(dbus::ObjectPath(kTestTagPath1), write_data,
627                     base::Bind(&NfcClientTest::SuccessCallback,
628                                base::Unretained(this)),
629                     base::Bind(&NfcClientTest::ErrorCallback,
630                                base::Unretained(this)));
631}
632
633// Tests that when devices are added and removed through an adapter, all
634// observers are notified and the proxies are created and removed
635// accordingly.
636TEST_F(NfcClientTest, DevicesAddedAndRemoved) {
637  // Invoking methods on devices that haven't been added should fail.
638  EXPECT_CALL(*this,
639              ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
640  base::DictionaryValue write_data;
641  write_data.SetString(nfc_record::kTypeProperty, nfc_record::kTypeText);
642  device_client_->Push(dbus::ObjectPath(kTestDevicePath0), write_data,
643                       base::Bind(&NfcClientTest::SuccessCallback,
644                                  base::Unretained(this)),
645                       base::Bind(&NfcClientTest::ErrorCallback,
646                                  base::Unretained(this)));
647  Mock::VerifyAndClearExpectations(this);
648
649  // Add adapter 0.
650  ObjectPathVector adapter_paths;
651  adapter_paths.push_back(dbus::ObjectPath(kTestAdapterPath0));
652  EXPECT_CALL(mock_adapter_observer_,
653              AdapterAdded(dbus::ObjectPath(kTestAdapterPath0)));
654  SimulateAdaptersChanged(adapter_paths);
655
656  // Add device 0.
657  ObjectPathVector device_paths;
658  device_paths.push_back(dbus::ObjectPath(kTestDevicePath0));
659  EXPECT_CALL(mock_device_observer_,
660              DeviceAdded(dbus::ObjectPath(kTestDevicePath0)));
661  SimulateDevicesChanged(device_paths, dbus::ObjectPath(kTestAdapterPath0));
662  Mock::VerifyAndClearExpectations(&mock_device_observer_);
663
664  // Invoking methods should succeed on device 0 but fail on device 1.
665  EXPECT_CALL(*mock_device0_proxy_, CallMethodWithErrorCallback(_, _, _, _));
666  device_client_->Push(dbus::ObjectPath(kTestDevicePath0), write_data,
667                       base::Bind(&NfcClientTest::SuccessCallback,
668                                  base::Unretained(this)),
669                       base::Bind(&NfcClientTest::ErrorCallback,
670                                  base::Unretained(this)));
671  Mock::VerifyAndClearExpectations(&mock_device0_proxy_);
672  EXPECT_CALL(*this,
673              ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
674  EXPECT_CALL(*mock_device1_proxy_, CallMethodWithErrorCallback(_, _, _, _))
675      .Times(0);
676  device_client_->Push(dbus::ObjectPath(kTestDevicePath1), write_data,
677                       base::Bind(&NfcClientTest::SuccessCallback,
678                                  base::Unretained(this)),
679                       base::Bind(&NfcClientTest::ErrorCallback,
680                                  base::Unretained(this)));
681  Mock::VerifyAndClearExpectations(this);
682  Mock::VerifyAndClearExpectations(&mock_device1_proxy_);
683
684  // Add device 1.
685  device_paths.push_back(dbus::ObjectPath(kTestDevicePath1));
686  EXPECT_CALL(mock_device_observer_,
687              DeviceAdded(dbus::ObjectPath(kTestDevicePath1)));
688  SimulateDevicesChanged(device_paths, dbus::ObjectPath(kTestAdapterPath0));
689  Mock::VerifyAndClearExpectations(&mock_device_observer_);
690
691  // Invoking methods should succeed on both devices.
692  EXPECT_CALL(*mock_device0_proxy_, CallMethodWithErrorCallback(_, _, _, _));
693  EXPECT_CALL(*mock_device1_proxy_, CallMethodWithErrorCallback(_, _, _, _));
694  device_client_->Push(dbus::ObjectPath(kTestDevicePath0), write_data,
695                       base::Bind(&NfcClientTest::SuccessCallback,
696                                  base::Unretained(this)),
697                       base::Bind(&NfcClientTest::ErrorCallback,
698                                  base::Unretained(this)));
699  device_client_->Push(dbus::ObjectPath(kTestDevicePath1), write_data,
700                       base::Bind(&NfcClientTest::SuccessCallback,
701                                  base::Unretained(this)),
702                       base::Bind(&NfcClientTest::ErrorCallback,
703                                  base::Unretained(this)));
704  Mock::VerifyAndClearExpectations(&mock_device0_proxy_);
705  Mock::VerifyAndClearExpectations(&mock_device1_proxy_);
706
707  // Remove device 0.
708  device_paths.erase(device_paths.begin());
709  EXPECT_CALL(mock_device_observer_,
710              DeviceRemoved(dbus::ObjectPath(kTestDevicePath0)));
711  SimulateDevicesChanged(device_paths, dbus::ObjectPath(kTestAdapterPath0));
712  Mock::VerifyAndClearExpectations(&mock_device_observer_);
713
714  // Invoking methods should succeed on device 1 but fail on device 0.
715  EXPECT_CALL(*this,
716              ErrorCallback(nfc_client_helpers::kUnknownObjectError, _));
717  EXPECT_CALL(*mock_device0_proxy_, CallMethodWithErrorCallback(_, _, _, _))
718      .Times(0);
719  device_client_->Push(dbus::ObjectPath(kTestDevicePath0), write_data,
720                       base::Bind(&NfcClientTest::SuccessCallback,
721                                  base::Unretained(this)),
722                       base::Bind(&NfcClientTest::ErrorCallback,
723                                  base::Unretained(this)));
724  Mock::VerifyAndClearExpectations(this);
725  Mock::VerifyAndClearExpectations(&mock_device0_proxy_);
726  EXPECT_CALL(*mock_device1_proxy_, CallMethodWithErrorCallback(_, _, _, _));
727  device_client_->Push(dbus::ObjectPath(kTestDevicePath1), write_data,
728                       base::Bind(&NfcClientTest::SuccessCallback,
729                                  base::Unretained(this)),
730                       base::Bind(&NfcClientTest::ErrorCallback,
731                                  base::Unretained(this)));
732  Mock::VerifyAndClearExpectations(&mock_device1_proxy_);
733
734  // Remove device 1.
735  device_paths.clear();
736  EXPECT_CALL(mock_device_observer_,
737              DeviceRemoved(dbus::ObjectPath(kTestDevicePath1)));
738  SimulateDevicesChanged(device_paths, dbus::ObjectPath(kTestAdapterPath0));
739  Mock::VerifyAndClearExpectations(&mock_device_observer_);
740
741  // Invoking methods should fail on both devices.
742  EXPECT_CALL(*this,
743              ErrorCallback(nfc_client_helpers::kUnknownObjectError, _))
744      .Times(2);
745  EXPECT_CALL(*mock_device0_proxy_, CallMethodWithErrorCallback(_, _, _, _))
746      .Times(0);
747  EXPECT_CALL(*mock_device1_proxy_, CallMethodWithErrorCallback(_, _, _, _))
748      .Times(0);
749  device_client_->Push(dbus::ObjectPath(kTestDevicePath0), write_data,
750                       base::Bind(&NfcClientTest::SuccessCallback,
751                                  base::Unretained(this)),
752                       base::Bind(&NfcClientTest::ErrorCallback,
753                                  base::Unretained(this)));
754  device_client_->Push(dbus::ObjectPath(kTestDevicePath1), write_data,
755                       base::Bind(&NfcClientTest::SuccessCallback,
756                                  base::Unretained(this)),
757                       base::Bind(&NfcClientTest::ErrorCallback,
758                                  base::Unretained(this)));
759}
760
761TEST_F(NfcClientTest, ObjectCleanup) {
762  // Tests that when an adapter gets removed, proxies that belong to the
763  // adapter, device, tag, and record hierarchy get cleaned up properly.
764  ObjectPathVector object_paths;
765
766  // Add adapters.
767  EXPECT_CALL(mock_adapter_observer_,
768              AdapterAdded(dbus::ObjectPath(kTestAdapterPath0)));
769  EXPECT_CALL(mock_adapter_observer_,
770              AdapterAdded(dbus::ObjectPath(kTestAdapterPath1)));
771  object_paths.push_back(dbus::ObjectPath(kTestAdapterPath0));
772  object_paths.push_back(dbus::ObjectPath(kTestAdapterPath1));
773  SimulateAdaptersChanged(object_paths);
774  Mock::VerifyAndClearExpectations(&mock_adapter_observer_);
775
776  // Add devices and a tags. Assign them like the following:
777  //  - device 0 -> adapter 0
778  //  - tag 0 -> adapter 0
779  //  - device 1 -> adapter 1
780  //  - tag 1 -> adapter 1
781  EXPECT_CALL(mock_device_observer_,
782              DeviceAdded(dbus::ObjectPath(kTestDevicePath0)));
783  EXPECT_CALL(mock_device_observer_,
784              DeviceAdded(dbus::ObjectPath(kTestDevicePath1)));
785  EXPECT_CALL(mock_tag_observer_,
786              TagAdded(dbus::ObjectPath(kTestTagPath0)));
787  EXPECT_CALL(mock_tag_observer_,
788              TagAdded(dbus::ObjectPath(kTestTagPath1)));
789  object_paths.clear();
790  object_paths.push_back(dbus::ObjectPath(kTestDevicePath0));
791  SimulateDevicesChanged(object_paths, dbus::ObjectPath(kTestAdapterPath0));
792  object_paths.clear();
793  object_paths.push_back(dbus::ObjectPath(kTestTagPath0));
794  SimulateTagsChanged(object_paths, dbus::ObjectPath(kTestAdapterPath0));
795  object_paths.clear();
796  object_paths.push_back(dbus::ObjectPath(kTestDevicePath1));
797  SimulateDevicesChanged(object_paths, dbus::ObjectPath(kTestAdapterPath1));
798  object_paths.clear();
799  object_paths.push_back(dbus::ObjectPath(kTestTagPath1));
800  SimulateTagsChanged(object_paths, dbus::ObjectPath(kTestAdapterPath1));
801  Mock::VerifyAndClearExpectations(&mock_device_observer_);
802  Mock::VerifyAndClearExpectations(&mock_tag_observer_);
803
804  // Add records. Assign them like the following:
805  //  - record 0 -> device 0
806  //  - record 1 -> tag 0
807  //  - record 2 -> device 1
808  //  - record 3 -> tag 1
809  EXPECT_CALL(mock_record_observer_,
810              RecordAdded(dbus::ObjectPath(kTestRecordPath0)));
811  EXPECT_CALL(mock_record_observer_,
812              RecordAdded(dbus::ObjectPath(kTestRecordPath1)));
813  EXPECT_CALL(mock_record_observer_,
814              RecordAdded(dbus::ObjectPath(kTestRecordPath2)));
815  EXPECT_CALL(mock_record_observer_,
816              RecordAdded(dbus::ObjectPath(kTestRecordPath3)));
817  object_paths.clear();
818  object_paths.push_back(dbus::ObjectPath(kTestRecordPath0));
819  SimulateDeviceRecordsChanged(object_paths,
820                               dbus::ObjectPath(kTestDevicePath0));
821  object_paths.clear();
822  object_paths.push_back(dbus::ObjectPath(kTestRecordPath1));
823  SimulateTagRecordsChanged(object_paths,
824                            dbus::ObjectPath(kTestTagPath0));
825  object_paths.clear();
826  object_paths.push_back(dbus::ObjectPath(kTestRecordPath2));
827  SimulateDeviceRecordsChanged(object_paths,
828                               dbus::ObjectPath(kTestDevicePath1));
829  object_paths.clear();
830  object_paths.push_back(dbus::ObjectPath(kTestRecordPath3));
831  SimulateTagRecordsChanged(object_paths,
832                            dbus::ObjectPath(kTestTagPath1));
833  Mock::VerifyAndClearExpectations(&mock_record_observer_);
834
835  // Check that the records have been assigned to the correct device or tag.
836  NfcTagClient::Properties* tag_properties =
837      tag_client_->GetProperties(dbus::ObjectPath(kTestTagPath0));
838  EXPECT_EQ((size_t)1, tag_properties->records.value().size());
839  EXPECT_EQ(dbus::ObjectPath(kTestRecordPath1),
840            tag_properties->records.value()[0]);
841  NfcDeviceClient::Properties* device_properties =
842      device_client_->GetProperties(dbus::ObjectPath(kTestDevicePath0));
843  EXPECT_EQ((size_t)1, device_properties->records.value().size());
844  EXPECT_EQ(dbus::ObjectPath(kTestRecordPath0),
845            device_properties->records.value()[0]);
846
847  // Remove adapter 0. Make sure that all of the tag, device, and records that
848  // are in the adapter 0 hierarchy are removed.
849  object_paths.clear();
850  object_paths.push_back(dbus::ObjectPath(kTestAdapterPath1));
851  EXPECT_CALL(mock_adapter_observer_,
852              AdapterRemoved(dbus::ObjectPath(kTestAdapterPath0)));
853  EXPECT_CALL(mock_device_observer_,
854              DeviceRemoved(dbus::ObjectPath(kTestDevicePath0)));
855  EXPECT_CALL(mock_tag_observer_,
856              TagRemoved(dbus::ObjectPath(kTestTagPath0)));
857  EXPECT_CALL(mock_record_observer_,
858              RecordRemoved(dbus::ObjectPath(kTestRecordPath0)));
859  EXPECT_CALL(mock_record_observer_,
860              RecordRemoved(dbus::ObjectPath(kTestRecordPath1)));
861  SimulateAdaptersChanged(object_paths);
862  Mock::VerifyAndClearExpectations(&mock_adapter_observer_);
863  Mock::VerifyAndClearExpectations(&mock_device_observer_);
864  Mock::VerifyAndClearExpectations(&mock_tag_observer_);
865  Mock::VerifyAndClearExpectations(&mock_record_observer_);
866
867  // Remove adapter 1.
868  object_paths.clear();
869  EXPECT_CALL(mock_adapter_observer_,
870              AdapterRemoved(dbus::ObjectPath(kTestAdapterPath1)));
871  EXPECT_CALL(mock_device_observer_,
872              DeviceRemoved(dbus::ObjectPath(kTestDevicePath1)));
873  EXPECT_CALL(mock_tag_observer_,
874              TagRemoved(dbus::ObjectPath(kTestTagPath1)));
875  EXPECT_CALL(mock_record_observer_,
876              RecordRemoved(dbus::ObjectPath(kTestRecordPath2)));
877  EXPECT_CALL(mock_record_observer_,
878              RecordRemoved(dbus::ObjectPath(kTestRecordPath3)));
879  SimulateAdaptersChanged(object_paths);
880}
881
882}  // namespace chromeos
883