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