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 19 using ::testing::_; 20 using ::testing::Invoke; 21 using ::testing::Mock; 22 using ::testing::Return; 23 24 using chromeos::nfc_client_helpers::ObjectPathVector; 25 26 namespace chromeos { 27 28 namespace { 29 30 // D-Bus service name used by the test. 31 const char kTestServiceName[] = "test.service.name"; 32 33 // Object paths that are used for testing. 34 const char kTestManagerPath[] = "/test/nfc/manager"; 35 const char kTestAdapterPath0[] = "/test/nfc/adapter0"; 36 const char kTestAdapterPath1[] = "/test/nfc/adapter1"; 37 const char kTestDevicePath0[] = "/test/nfc/device0"; 38 const char kTestDevicePath1[] = "/test/nfc/device1"; 39 const char kTestRecordPath0[] = "/test/nfc/record0"; 40 const char kTestRecordPath1[] = "/test/nfc/record1"; 41 const char kTestRecordPath2[] = "/test/nfc/record2"; 42 const char kTestRecordPath3[] = "/test/nfc/record3"; 43 const char kTestTagPath0[] = "/test/nfc/tag0"; 44 const char kTestTagPath1[] = "/test/nfc/tag1"; 45 46 class 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 53 class 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 61 class 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 69 class 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 78 class 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 88 class 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. 391 TEST_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. 507 TEST_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. 636 TEST_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 761 TEST_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