| OLD | NEW |
| (Empty) |
| 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 <stddef.h> | |
| 6 #include <stdint.h> | |
| 7 | |
| 8 #include <memory> | |
| 9 | |
| 10 #include "base/callback.h" | |
| 11 #include "base/message_loop/message_loop.h" | |
| 12 #include "base/run_loop.h" | |
| 13 #include "base/values.h" | |
| 14 #include "chromeos/dbus/dbus_thread_manager.h" | |
| 15 #include "chromeos/dbus/fake_nfc_adapter_client.h" | |
| 16 #include "chromeos/dbus/fake_nfc_device_client.h" | |
| 17 #include "chromeos/dbus/fake_nfc_record_client.h" | |
| 18 #include "chromeos/dbus/fake_nfc_tag_client.h" | |
| 19 #include "device/nfc/nfc_adapter_chromeos.h" | |
| 20 #include "device/nfc/nfc_ndef_record.h" | |
| 21 #include "device/nfc/nfc_ndef_record_utils_chromeos.h" | |
| 22 #include "device/nfc/nfc_peer.h" | |
| 23 #include "device/nfc/nfc_tag.h" | |
| 24 #include "device/nfc/nfc_tag_technology.h" | |
| 25 #include "testing/gtest/include/gtest/gtest.h" | |
| 26 #include "third_party/cros_system_api/dbus/service_constants.h" | |
| 27 | |
| 28 using device::NfcAdapter; | |
| 29 using device::NfcNdefMessage; | |
| 30 using device::NfcNdefRecord; | |
| 31 using device::NfcNdefTagTechnology; | |
| 32 using device::NfcPeer; | |
| 33 using device::NfcTag; | |
| 34 | |
| 35 namespace chromeos { | |
| 36 | |
| 37 namespace { | |
| 38 | |
| 39 // Callback passed to property structures. | |
| 40 void OnPropertyChangedCallback(const std::string& property_name) { | |
| 41 } | |
| 42 | |
| 43 // Callback passed to dbus::PropertyBase::Set. | |
| 44 void OnSet(bool success) { | |
| 45 } | |
| 46 | |
| 47 class TestObserver : public NfcAdapter::Observer, | |
| 48 public NfcPeer::Observer, | |
| 49 public NfcTag::Observer, | |
| 50 public NfcNdefTagTechnology::Observer { | |
| 51 public: | |
| 52 TestObserver(scoped_refptr<NfcAdapter> adapter) | |
| 53 : present_changed_count_(0), | |
| 54 powered_changed_count_(0), | |
| 55 polling_changed_count_(0), | |
| 56 peer_records_received_count_(0), | |
| 57 tag_records_received_count_(0), | |
| 58 peer_count_(0), | |
| 59 tag_count_(0), | |
| 60 adapter_(adapter) { | |
| 61 } | |
| 62 | |
| 63 ~TestObserver() override {} | |
| 64 | |
| 65 // NfcAdapter::Observer override. | |
| 66 void AdapterPresentChanged(NfcAdapter* adapter, bool present) override { | |
| 67 EXPECT_EQ(adapter_.get(), adapter); | |
| 68 present_changed_count_++; | |
| 69 } | |
| 70 | |
| 71 // NfcAdapter::Observer override. | |
| 72 void AdapterPoweredChanged(NfcAdapter* adapter, bool powered) override { | |
| 73 EXPECT_EQ(adapter_.get(), adapter); | |
| 74 powered_changed_count_++; | |
| 75 } | |
| 76 | |
| 77 // NfcAdapter::Observer override. | |
| 78 void AdapterPollingChanged(NfcAdapter* adapter, bool powered) override { | |
| 79 EXPECT_EQ(adapter_.get(), adapter); | |
| 80 polling_changed_count_++; | |
| 81 } | |
| 82 | |
| 83 // NfcAdapter::Observer override. | |
| 84 void PeerFound(NfcAdapter* adapter, NfcPeer* peer) override { | |
| 85 EXPECT_EQ(adapter_.get(), adapter); | |
| 86 peer_count_++; | |
| 87 peer_identifier_ = peer->GetIdentifier(); | |
| 88 } | |
| 89 | |
| 90 // NfcAdapter::Observer override. | |
| 91 void PeerLost(NfcAdapter* adapter, NfcPeer* peer) override { | |
| 92 EXPECT_EQ(adapter_.get(), adapter); | |
| 93 EXPECT_EQ(peer_identifier_, peer->GetIdentifier()); | |
| 94 peer_count_--; | |
| 95 peer_identifier_.clear(); | |
| 96 } | |
| 97 | |
| 98 // NfcAdapter::Observer override. | |
| 99 void TagFound(NfcAdapter* adapter, NfcTag* tag) override { | |
| 100 EXPECT_EQ(adapter_.get(), adapter); | |
| 101 tag_count_++; | |
| 102 tag_identifier_ = tag->GetIdentifier(); | |
| 103 } | |
| 104 | |
| 105 // NfcAdapter::Observer override. | |
| 106 void TagLost(NfcAdapter* adapter, NfcTag* tag) override { | |
| 107 EXPECT_EQ(adapter_.get(), adapter); | |
| 108 EXPECT_EQ(tag_identifier_, tag->GetIdentifier()); | |
| 109 tag_count_--; | |
| 110 tag_identifier_.clear(); | |
| 111 } | |
| 112 | |
| 113 // NfcPeer::Observer override. | |
| 114 void RecordReceived(NfcPeer* peer, const NfcNdefRecord* record) override { | |
| 115 EXPECT_EQ(peer, adapter_->GetPeer(peer_identifier_)); | |
| 116 EXPECT_EQ(peer_identifier_, peer->GetIdentifier()); | |
| 117 peer_records_received_count_++; | |
| 118 } | |
| 119 | |
| 120 // NfcNdefTagTechnology::Observer override. | |
| 121 void RecordReceived(NfcTag* tag, const NfcNdefRecord* record) override { | |
| 122 EXPECT_EQ(tag, adapter_->GetTag(tag_identifier_)); | |
| 123 EXPECT_EQ(tag_identifier_, tag->GetIdentifier()); | |
| 124 tag_records_received_count_++; | |
| 125 } | |
| 126 | |
| 127 int present_changed_count_; | |
| 128 int powered_changed_count_; | |
| 129 int polling_changed_count_; | |
| 130 int peer_records_received_count_; | |
| 131 int tag_records_received_count_; | |
| 132 int peer_count_; | |
| 133 int tag_count_; | |
| 134 std::string peer_identifier_; | |
| 135 std::string tag_identifier_; | |
| 136 scoped_refptr<NfcAdapter> adapter_; | |
| 137 }; | |
| 138 | |
| 139 } // namespace | |
| 140 | |
| 141 class NfcChromeOSTest : public testing::Test { | |
| 142 public: | |
| 143 void SetUp() override { | |
| 144 DBusThreadManager::Initialize(); | |
| 145 fake_nfc_adapter_client_ = static_cast<FakeNfcAdapterClient*>( | |
| 146 DBusThreadManager::Get()->GetNfcAdapterClient()); | |
| 147 fake_nfc_device_client_ = static_cast<FakeNfcDeviceClient*>( | |
| 148 DBusThreadManager::Get()->GetNfcDeviceClient()); | |
| 149 fake_nfc_record_client_ = static_cast<FakeNfcRecordClient*>( | |
| 150 DBusThreadManager::Get()->GetNfcRecordClient()); | |
| 151 fake_nfc_tag_client_ = static_cast<FakeNfcTagClient*>( | |
| 152 DBusThreadManager::Get()->GetNfcTagClient()); | |
| 153 | |
| 154 fake_nfc_adapter_client_->EnablePairingOnPoll(false); | |
| 155 fake_nfc_device_client_->DisableSimulationTimeout(); | |
| 156 fake_nfc_tag_client_->DisableSimulationTimeout(); | |
| 157 success_callback_count_ = 0; | |
| 158 error_callback_count_ = 0; | |
| 159 } | |
| 160 | |
| 161 void TearDown() override { | |
| 162 adapter_ = NULL; | |
| 163 DBusThreadManager::Shutdown(); | |
| 164 } | |
| 165 | |
| 166 // Assigns a new instance of NfcAdapterChromeOS to |adapter_|. | |
| 167 void SetAdapter() { | |
| 168 adapter_ = new NfcAdapterChromeOS(); | |
| 169 ASSERT_TRUE(adapter_.get() != NULL); | |
| 170 ASSERT_TRUE(adapter_->IsInitialized()); | |
| 171 base::RunLoop().RunUntilIdle(); | |
| 172 } | |
| 173 | |
| 174 // Generic callbacks for success and error. | |
| 175 void SuccessCallback() { | |
| 176 success_callback_count_++; | |
| 177 } | |
| 178 | |
| 179 void ErrorCallback() { | |
| 180 error_callback_count_++; | |
| 181 } | |
| 182 | |
| 183 void ErrorCallbackWithParameters(const std::string& error_name, | |
| 184 const std::string& error_message) { | |
| 185 LOG(INFO) << "Error callback called: " << error_name << ", " | |
| 186 << error_message; | |
| 187 error_callback_count_++; | |
| 188 } | |
| 189 | |
| 190 protected: | |
| 191 // MessageLoop instance, used to simulate asynchronous behavior. | |
| 192 base::MessageLoop message_loop_; | |
| 193 | |
| 194 // Fields for storing the number of times SuccessCallback and ErrorCallback | |
| 195 // have been called. | |
| 196 int success_callback_count_; | |
| 197 int error_callback_count_; | |
| 198 | |
| 199 // The NfcAdapter instance under test. | |
| 200 scoped_refptr<NfcAdapter> adapter_; | |
| 201 | |
| 202 // The fake D-Bus client instances used for testing. | |
| 203 FakeNfcAdapterClient* fake_nfc_adapter_client_; | |
| 204 FakeNfcDeviceClient* fake_nfc_device_client_; | |
| 205 FakeNfcRecordClient* fake_nfc_record_client_; | |
| 206 FakeNfcTagClient* fake_nfc_tag_client_; | |
| 207 }; | |
| 208 | |
| 209 // Tests that the adapter updates correctly to reflect the current "default" | |
| 210 // adapter, when multiple adapters appear and disappear. | |
| 211 TEST_F(NfcChromeOSTest, PresentChanged) { | |
| 212 SetAdapter(); | |
| 213 EXPECT_TRUE(adapter_->IsPresent()); | |
| 214 | |
| 215 TestObserver observer(adapter_); | |
| 216 adapter_->AddObserver(&observer); | |
| 217 | |
| 218 // Remove all adapters. | |
| 219 fake_nfc_adapter_client_->SetAdapterPresent(false); | |
| 220 EXPECT_EQ(1, observer.present_changed_count_); | |
| 221 EXPECT_FALSE(adapter_->IsPresent()); | |
| 222 | |
| 223 // Add two adapters. | |
| 224 fake_nfc_adapter_client_->SetAdapterPresent(true); | |
| 225 fake_nfc_adapter_client_->SetSecondAdapterPresent(true); | |
| 226 EXPECT_EQ(2, observer.present_changed_count_); | |
| 227 EXPECT_TRUE(adapter_->IsPresent()); | |
| 228 | |
| 229 // Remove the first adapter. Adapter should update to the second one. | |
| 230 fake_nfc_adapter_client_->SetAdapterPresent(false); | |
| 231 EXPECT_EQ(4, observer.present_changed_count_); | |
| 232 EXPECT_TRUE(adapter_->IsPresent()); | |
| 233 | |
| 234 fake_nfc_adapter_client_->SetSecondAdapterPresent(false); | |
| 235 EXPECT_EQ(5, observer.present_changed_count_); | |
| 236 EXPECT_FALSE(adapter_->IsPresent()); | |
| 237 } | |
| 238 | |
| 239 // Tests that the adapter correctly reflects the power state. | |
| 240 TEST_F(NfcChromeOSTest, SetPowered) { | |
| 241 SetAdapter(); | |
| 242 TestObserver observer(adapter_); | |
| 243 adapter_->AddObserver(&observer); | |
| 244 | |
| 245 EXPECT_FALSE(adapter_->IsPowered()); | |
| 246 | |
| 247 // SetPowered(false), while not powered. | |
| 248 adapter_->SetPowered( | |
| 249 false, | |
| 250 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 251 base::Unretained(this)), | |
| 252 base::Bind(&NfcChromeOSTest::ErrorCallback, | |
| 253 base::Unretained(this))); | |
| 254 EXPECT_FALSE(adapter_->IsPowered()); | |
| 255 EXPECT_EQ(0, observer.powered_changed_count_); | |
| 256 EXPECT_EQ(0, success_callback_count_); | |
| 257 EXPECT_EQ(1, error_callback_count_); | |
| 258 | |
| 259 // SetPowered(true). | |
| 260 adapter_->SetPowered( | |
| 261 true, | |
| 262 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 263 base::Unretained(this)), | |
| 264 base::Bind(&NfcChromeOSTest::ErrorCallback, | |
| 265 base::Unretained(this))); | |
| 266 EXPECT_TRUE(adapter_->IsPowered()); | |
| 267 EXPECT_EQ(1, observer.powered_changed_count_); | |
| 268 EXPECT_EQ(1, success_callback_count_); | |
| 269 EXPECT_EQ(1, error_callback_count_); | |
| 270 | |
| 271 // SetPowered(true), while powered. | |
| 272 adapter_->SetPowered( | |
| 273 true, | |
| 274 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 275 base::Unretained(this)), | |
| 276 base::Bind(&NfcChromeOSTest::ErrorCallback, | |
| 277 base::Unretained(this))); | |
| 278 EXPECT_TRUE(adapter_->IsPowered()); | |
| 279 EXPECT_EQ(1, observer.powered_changed_count_); | |
| 280 EXPECT_EQ(1, success_callback_count_); | |
| 281 EXPECT_EQ(2, error_callback_count_); | |
| 282 | |
| 283 // SetPowered(false). | |
| 284 adapter_->SetPowered( | |
| 285 false, | |
| 286 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 287 base::Unretained(this)), | |
| 288 base::Bind(&NfcChromeOSTest::ErrorCallback, | |
| 289 base::Unretained(this))); | |
| 290 EXPECT_FALSE(adapter_->IsPowered()); | |
| 291 EXPECT_EQ(2, observer.powered_changed_count_); | |
| 292 EXPECT_EQ(2, success_callback_count_); | |
| 293 EXPECT_EQ(2, error_callback_count_); | |
| 294 } | |
| 295 | |
| 296 // Tests that the power state updates correctly when the adapter disappears. | |
| 297 TEST_F(NfcChromeOSTest, PresentChangedWhilePowered) { | |
| 298 SetAdapter(); | |
| 299 TestObserver observer(adapter_); | |
| 300 adapter_->AddObserver(&observer); | |
| 301 | |
| 302 EXPECT_FALSE(adapter_->IsPowered()); | |
| 303 EXPECT_TRUE(adapter_->IsPresent()); | |
| 304 | |
| 305 adapter_->SetPowered( | |
| 306 true, | |
| 307 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 308 base::Unretained(this)), | |
| 309 base::Bind(&NfcChromeOSTest::ErrorCallback, | |
| 310 base::Unretained(this))); | |
| 311 EXPECT_TRUE(adapter_->IsPowered()); | |
| 312 | |
| 313 fake_nfc_adapter_client_->SetAdapterPresent(false); | |
| 314 EXPECT_EQ(1, observer.present_changed_count_); | |
| 315 EXPECT_EQ(2, observer.powered_changed_count_); | |
| 316 EXPECT_FALSE(adapter_->IsPowered()); | |
| 317 EXPECT_FALSE(adapter_->IsPresent()); | |
| 318 } | |
| 319 | |
| 320 // Tests that peer and record objects are created for all peers and records | |
| 321 // that already exist when the adapter is created. | |
| 322 TEST_F(NfcChromeOSTest, PeersInitializedWhenAdapterCreated) { | |
| 323 // Set up the adapter client. | |
| 324 NfcAdapterClient::Properties* properties = | |
| 325 fake_nfc_adapter_client_->GetProperties( | |
| 326 dbus::ObjectPath(FakeNfcAdapterClient::kAdapterPath0)); | |
| 327 properties->powered.Set(true, base::Bind(&OnSet)); | |
| 328 | |
| 329 fake_nfc_adapter_client_->StartPollLoop( | |
| 330 dbus::ObjectPath(FakeNfcAdapterClient::kAdapterPath0), | |
| 331 nfc_adapter::kModeInitiator, | |
| 332 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 333 base::Unretained(this)), | |
| 334 base::Bind(&NfcChromeOSTest::ErrorCallbackWithParameters, | |
| 335 base::Unretained(this))); | |
| 336 EXPECT_EQ(1, success_callback_count_); | |
| 337 EXPECT_TRUE(properties->powered.value()); | |
| 338 EXPECT_TRUE(properties->polling.value()); | |
| 339 | |
| 340 // Start pairing simulation, which will add a fake device and fake records. | |
| 341 fake_nfc_device_client_->BeginPairingSimulation(0, 0); | |
| 342 base::RunLoop().RunUntilIdle(); | |
| 343 | |
| 344 // Create the adapter. | |
| 345 SetAdapter(); | |
| 346 TestObserver observer(adapter_); | |
| 347 adapter_->AddObserver(&observer); | |
| 348 | |
| 349 // Observer shouldn't have received any calls, as it got created AFTER the | |
| 350 // notifications were sent. | |
| 351 EXPECT_EQ(0, observer.present_changed_count_); | |
| 352 EXPECT_EQ(0, observer.powered_changed_count_); | |
| 353 EXPECT_EQ(0, observer.polling_changed_count_); | |
| 354 EXPECT_EQ(0, observer.peer_count_); | |
| 355 | |
| 356 EXPECT_TRUE(adapter_->IsPresent()); | |
| 357 EXPECT_TRUE(adapter_->IsPowered()); | |
| 358 EXPECT_FALSE(adapter_->IsPolling()); | |
| 359 | |
| 360 NfcAdapter::PeerList peers; | |
| 361 adapter_->GetPeers(&peers); | |
| 362 EXPECT_EQ(static_cast<size_t>(1), peers.size()); | |
| 363 | |
| 364 NfcPeer* peer = peers[0]; | |
| 365 const NfcNdefMessage& message = peer->GetNdefMessage(); | |
| 366 EXPECT_EQ(static_cast<size_t>(3), message.records().size()); | |
| 367 } | |
| 368 | |
| 369 // Tests that tag and record objects are created for all tags and records that | |
| 370 // already exist when the adapter is created. | |
| 371 TEST_F(NfcChromeOSTest, TagsInitializedWhenAdapterCreated) { | |
| 372 const char kTestURI[] = "fake://path/for/testing"; | |
| 373 | |
| 374 // Set up the adapter client. | |
| 375 NfcAdapterClient::Properties* properties = | |
| 376 fake_nfc_adapter_client_->GetProperties( | |
| 377 dbus::ObjectPath(FakeNfcAdapterClient::kAdapterPath0)); | |
| 378 properties->powered.Set(true, base::Bind(&OnSet)); | |
| 379 | |
| 380 fake_nfc_adapter_client_->StartPollLoop( | |
| 381 dbus::ObjectPath(FakeNfcAdapterClient::kAdapterPath0), | |
| 382 nfc_adapter::kModeInitiator, | |
| 383 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 384 base::Unretained(this)), | |
| 385 base::Bind(&NfcChromeOSTest::ErrorCallbackWithParameters, | |
| 386 base::Unretained(this))); | |
| 387 EXPECT_EQ(1, success_callback_count_); | |
| 388 EXPECT_TRUE(properties->powered.value()); | |
| 389 EXPECT_TRUE(properties->polling.value()); | |
| 390 | |
| 391 // Add the fake tag. | |
| 392 fake_nfc_tag_client_->BeginPairingSimulation(0); | |
| 393 base::RunLoop().RunUntilIdle(); | |
| 394 | |
| 395 // Create a fake record. | |
| 396 base::DictionaryValue test_record_data; | |
| 397 test_record_data.SetString(nfc_record::kTypeProperty, nfc_record::kTypeUri); | |
| 398 test_record_data.SetString(nfc_record::kUriProperty, kTestURI); | |
| 399 fake_nfc_tag_client_->Write( | |
| 400 dbus::ObjectPath(FakeNfcTagClient::kTagPath), | |
| 401 test_record_data, | |
| 402 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 403 base::Unretained(this)), | |
| 404 base::Bind(&NfcChromeOSTest::ErrorCallbackWithParameters, | |
| 405 base::Unretained(this))); | |
| 406 EXPECT_EQ(2, success_callback_count_); | |
| 407 | |
| 408 // Create the adapter. | |
| 409 SetAdapter(); | |
| 410 TestObserver observer(adapter_); | |
| 411 adapter_->AddObserver(&observer); | |
| 412 | |
| 413 // Observer shouldn't have received any calls, as it got created AFTER the | |
| 414 // notifications were sent. | |
| 415 EXPECT_EQ(0, observer.present_changed_count_); | |
| 416 EXPECT_EQ(0, observer.powered_changed_count_); | |
| 417 EXPECT_EQ(0, observer.polling_changed_count_); | |
| 418 EXPECT_EQ(0, observer.peer_count_); | |
| 419 | |
| 420 EXPECT_TRUE(adapter_->IsPresent()); | |
| 421 EXPECT_TRUE(adapter_->IsPowered()); | |
| 422 EXPECT_FALSE(adapter_->IsPolling()); | |
| 423 | |
| 424 NfcAdapter::TagList tags; | |
| 425 adapter_->GetTags(&tags); | |
| 426 EXPECT_EQ(static_cast<size_t>(1), tags.size()); | |
| 427 | |
| 428 NfcTag* tag = tags[0]; | |
| 429 const NfcNdefMessage& message = tag->GetNdefTagTechnology()->GetNdefMessage(); | |
| 430 EXPECT_EQ(static_cast<size_t>(1), message.records().size()); | |
| 431 | |
| 432 const NfcNdefRecord* record = message.records()[0]; | |
| 433 std::string uri; | |
| 434 EXPECT_TRUE(record->data().GetString(NfcNdefRecord::kFieldURI, &uri)); | |
| 435 EXPECT_EQ(kTestURI, uri); | |
| 436 } | |
| 437 | |
| 438 // Tests that the adapter correctly updates its state when polling is started | |
| 439 // and stopped. | |
| 440 TEST_F(NfcChromeOSTest, StartAndStopPolling) { | |
| 441 SetAdapter(); | |
| 442 EXPECT_TRUE(adapter_->IsPresent()); | |
| 443 | |
| 444 TestObserver observer(adapter_); | |
| 445 adapter_->AddObserver(&observer); | |
| 446 | |
| 447 // Start polling while not powered. Should fail. | |
| 448 EXPECT_FALSE(adapter_->IsPowered()); | |
| 449 adapter_->StartPolling( | |
| 450 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 451 base::Unretained(this)), | |
| 452 base::Bind(&NfcChromeOSTest::ErrorCallback, | |
| 453 base::Unretained(this))); | |
| 454 EXPECT_EQ(0, success_callback_count_); | |
| 455 EXPECT_EQ(1, error_callback_count_); | |
| 456 EXPECT_FALSE(adapter_->IsPolling()); | |
| 457 | |
| 458 // Start polling while powered. Should succeed. | |
| 459 adapter_->SetPowered( | |
| 460 true, | |
| 461 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 462 base::Unretained(this)), | |
| 463 base::Bind(&NfcChromeOSTest::ErrorCallback, | |
| 464 base::Unretained(this))); | |
| 465 EXPECT_EQ(1, success_callback_count_); | |
| 466 EXPECT_EQ(1, error_callback_count_); | |
| 467 EXPECT_TRUE(adapter_->IsPowered()); | |
| 468 | |
| 469 adapter_->StartPolling( | |
| 470 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 471 base::Unretained(this)), | |
| 472 base::Bind(&NfcChromeOSTest::ErrorCallback, | |
| 473 base::Unretained(this))); | |
| 474 EXPECT_EQ(2, success_callback_count_); | |
| 475 EXPECT_EQ(1, error_callback_count_); | |
| 476 EXPECT_TRUE(adapter_->IsPolling()); | |
| 477 | |
| 478 // Start polling while already polling. Should fail. | |
| 479 adapter_->StartPolling( | |
| 480 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 481 base::Unretained(this)), | |
| 482 base::Bind(&NfcChromeOSTest::ErrorCallback, | |
| 483 base::Unretained(this))); | |
| 484 EXPECT_EQ(2, success_callback_count_); | |
| 485 EXPECT_EQ(2, error_callback_count_); | |
| 486 EXPECT_TRUE(adapter_->IsPolling()); | |
| 487 | |
| 488 // Stop polling. Should succeed. | |
| 489 adapter_->StopPolling( | |
| 490 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 491 base::Unretained(this)), | |
| 492 base::Bind(&NfcChromeOSTest::ErrorCallback, | |
| 493 base::Unretained(this))); | |
| 494 EXPECT_EQ(3, success_callback_count_); | |
| 495 EXPECT_EQ(2, error_callback_count_); | |
| 496 EXPECT_FALSE(adapter_->IsPolling()); | |
| 497 | |
| 498 // Stop polling while not polling. Should fail. | |
| 499 adapter_->StopPolling( | |
| 500 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 501 base::Unretained(this)), | |
| 502 base::Bind(&NfcChromeOSTest::ErrorCallback, | |
| 503 base::Unretained(this))); | |
| 504 EXPECT_EQ(3, success_callback_count_); | |
| 505 EXPECT_EQ(3, error_callback_count_); | |
| 506 EXPECT_FALSE(adapter_->IsPolling()); | |
| 507 } | |
| 508 | |
| 509 // Tests a simple peer pairing simulation. | |
| 510 TEST_F(NfcChromeOSTest, PeerTest) { | |
| 511 SetAdapter(); | |
| 512 TestObserver observer(adapter_); | |
| 513 adapter_->AddObserver(&observer); | |
| 514 | |
| 515 adapter_->SetPowered( | |
| 516 true, | |
| 517 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 518 base::Unretained(this)), | |
| 519 base::Bind(&NfcChromeOSTest::ErrorCallback, | |
| 520 base::Unretained(this))); | |
| 521 adapter_->StartPolling( | |
| 522 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 523 base::Unretained(this)), | |
| 524 base::Bind(&NfcChromeOSTest::ErrorCallback, | |
| 525 base::Unretained(this))); | |
| 526 EXPECT_EQ(2, success_callback_count_); | |
| 527 | |
| 528 EXPECT_TRUE(adapter_->IsPowered()); | |
| 529 EXPECT_TRUE(adapter_->IsPolling()); | |
| 530 EXPECT_EQ(0, observer.peer_count_); | |
| 531 | |
| 532 // Add the fake device. | |
| 533 fake_nfc_device_client_->BeginPairingSimulation(0, -1); | |
| 534 base::RunLoop().RunUntilIdle(); | |
| 535 | |
| 536 EXPECT_EQ(1, observer.peer_count_); | |
| 537 EXPECT_EQ(FakeNfcDeviceClient::kDevicePath, observer.peer_identifier_); | |
| 538 | |
| 539 NfcPeer* peer = adapter_->GetPeer(observer.peer_identifier_); | |
| 540 CHECK(peer); | |
| 541 peer->AddObserver(&observer); | |
| 542 | |
| 543 // Peer should have no records on it. | |
| 544 EXPECT_TRUE(peer->GetNdefMessage().records().empty()); | |
| 545 EXPECT_EQ(0, observer.peer_records_received_count_); | |
| 546 | |
| 547 // Make records visible. | |
| 548 fake_nfc_record_client_->SetDeviceRecordsVisible(true); | |
| 549 EXPECT_EQ(3, observer.peer_records_received_count_); | |
| 550 EXPECT_EQ(static_cast<size_t>(3), peer->GetNdefMessage().records().size()); | |
| 551 | |
| 552 // End the simulation. Peer should get removed. | |
| 553 fake_nfc_device_client_->EndPairingSimulation(); | |
| 554 EXPECT_EQ(0, observer.peer_count_); | |
| 555 EXPECT_TRUE(observer.peer_identifier_.empty()); | |
| 556 | |
| 557 peer = adapter_->GetPeer(observer.peer_identifier_); | |
| 558 EXPECT_FALSE(peer); | |
| 559 | |
| 560 // No record related notifications will be sent when a peer gets removed. | |
| 561 EXPECT_EQ(3, observer.peer_records_received_count_); | |
| 562 } | |
| 563 | |
| 564 // Tests a simple tag pairing simulation. | |
| 565 TEST_F(NfcChromeOSTest, TagTest) { | |
| 566 const char kTestURI[] = "fake://path/for/testing"; | |
| 567 | |
| 568 SetAdapter(); | |
| 569 TestObserver observer(adapter_); | |
| 570 adapter_->AddObserver(&observer); | |
| 571 | |
| 572 adapter_->SetPowered( | |
| 573 true, | |
| 574 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 575 base::Unretained(this)), | |
| 576 base::Bind(&NfcChromeOSTest::ErrorCallback, | |
| 577 base::Unretained(this))); | |
| 578 adapter_->StartPolling( | |
| 579 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 580 base::Unretained(this)), | |
| 581 base::Bind(&NfcChromeOSTest::ErrorCallback, | |
| 582 base::Unretained(this))); | |
| 583 EXPECT_EQ(2, success_callback_count_); | |
| 584 | |
| 585 EXPECT_TRUE(adapter_->IsPowered()); | |
| 586 EXPECT_TRUE(adapter_->IsPolling()); | |
| 587 EXPECT_EQ(0, observer.tag_count_); | |
| 588 | |
| 589 // Add the fake tag. | |
| 590 fake_nfc_tag_client_->BeginPairingSimulation(0); | |
| 591 base::RunLoop().RunUntilIdle(); | |
| 592 | |
| 593 EXPECT_EQ(1, observer.tag_count_); | |
| 594 EXPECT_EQ(FakeNfcTagClient::kTagPath, observer.tag_identifier_); | |
| 595 | |
| 596 NfcTag* tag = adapter_->GetTag(observer.tag_identifier_); | |
| 597 CHECK(tag); | |
| 598 tag->AddObserver(&observer); | |
| 599 EXPECT_TRUE(tag->IsReady()); | |
| 600 CHECK(tag->GetNdefTagTechnology()); | |
| 601 tag->GetNdefTagTechnology()->AddObserver(&observer); | |
| 602 | |
| 603 NfcNdefTagTechnology* tag_technology = tag->GetNdefTagTechnology(); | |
| 604 EXPECT_TRUE(tag_technology->IsSupportedByTag()); | |
| 605 | |
| 606 // Tag should have no records on it. | |
| 607 EXPECT_TRUE(tag_technology->GetNdefMessage().records().empty()); | |
| 608 EXPECT_EQ(0, observer.tag_records_received_count_); | |
| 609 | |
| 610 // Set the tag record visible. By default the record has no content, so no | |
| 611 // NfcNdefMessage should be received. | |
| 612 fake_nfc_record_client_->SetTagRecordsVisible(true); | |
| 613 EXPECT_TRUE(tag_technology->GetNdefMessage().records().empty()); | |
| 614 EXPECT_EQ(0, observer.tag_records_received_count_); | |
| 615 fake_nfc_record_client_->SetTagRecordsVisible(false); | |
| 616 | |
| 617 // Write an NDEF record to the tag. | |
| 618 EXPECT_EQ(2, success_callback_count_); // 2 for SetPowered and StartPolling. | |
| 619 EXPECT_EQ(0, error_callback_count_); | |
| 620 | |
| 621 base::DictionaryValue record_data; | |
| 622 record_data.SetString(NfcNdefRecord::kFieldURI, kTestURI); | |
| 623 NfcNdefRecord written_record; | |
| 624 written_record.Populate(NfcNdefRecord::kTypeURI, &record_data); | |
| 625 NfcNdefMessage written_message; | |
| 626 written_message.AddRecord(&written_record); | |
| 627 | |
| 628 tag_technology->WriteNdef( | |
| 629 written_message, | |
| 630 base::Bind(&NfcChromeOSTest::SuccessCallback, | |
| 631 base::Unretained(this)), | |
| 632 base::Bind(&NfcChromeOSTest::ErrorCallback, | |
| 633 base::Unretained(this))); | |
| 634 EXPECT_EQ(3, success_callback_count_); | |
| 635 EXPECT_EQ(0, error_callback_count_); | |
| 636 | |
| 637 EXPECT_EQ(static_cast<size_t>(1), | |
| 638 tag_technology->GetNdefMessage().records().size()); | |
| 639 EXPECT_EQ(1, observer.tag_records_received_count_); | |
| 640 | |
| 641 NfcNdefRecord* received_record = | |
| 642 tag_technology->GetNdefMessage().records()[0]; | |
| 643 EXPECT_EQ(NfcNdefRecord::kTypeURI, received_record->type()); | |
| 644 std::string uri; | |
| 645 EXPECT_TRUE(received_record->data().GetString( | |
| 646 NfcNdefRecord::kFieldURI, &uri)); | |
| 647 EXPECT_EQ(kTestURI, uri); | |
| 648 | |
| 649 // End the simulation. Tag should get removed. | |
| 650 fake_nfc_tag_client_->EndPairingSimulation(); | |
| 651 EXPECT_EQ(0, observer.tag_count_); | |
| 652 EXPECT_TRUE(observer.tag_identifier_.empty()); | |
| 653 | |
| 654 tag = adapter_->GetTag(observer.tag_identifier_); | |
| 655 EXPECT_FALSE(tag); | |
| 656 | |
| 657 // No record related notifications will be sent when a tag gets removed. | |
| 658 EXPECT_EQ(1, observer.tag_records_received_count_); | |
| 659 } | |
| 660 | |
| 661 // Unit tests for nfc_ndef_record_utils methods. | |
| 662 TEST_F(NfcChromeOSTest, NfcNdefRecordToDBusAttributes) { | |
| 663 const char kText[] = "text"; | |
| 664 const char kURI[] = "test://uri"; | |
| 665 const char kEncoding[] = "encoding"; | |
| 666 const char kLanguageCode[] = "en"; | |
| 667 const char kMimeType[] = "mime-type"; | |
| 668 const double kSize = 5; | |
| 669 | |
| 670 // Text record. | |
| 671 base::DictionaryValue data; | |
| 672 data.SetString(NfcNdefRecord::kFieldText, kText); | |
| 673 data.SetString(NfcNdefRecord::kFieldLanguageCode, kLanguageCode); | |
| 674 data.SetString(NfcNdefRecord::kFieldEncoding, kEncoding); | |
| 675 | |
| 676 std::unique_ptr<NfcNdefRecord> record(new NfcNdefRecord()); | |
| 677 ASSERT_TRUE(record->Populate(NfcNdefRecord::kTypeText, &data)); | |
| 678 | |
| 679 base::DictionaryValue result; | |
| 680 EXPECT_TRUE(nfc_ndef_record_utils::NfcNdefRecordToDBusAttributes( | |
| 681 record.get(), &result)); | |
| 682 | |
| 683 std::string string_value; | |
| 684 EXPECT_TRUE(result.GetString( | |
| 685 nfc_record::kTypeProperty, &string_value)); | |
| 686 EXPECT_EQ(nfc_record::kTypeText, string_value); | |
| 687 EXPECT_TRUE(result.GetString( | |
| 688 nfc_record::kRepresentationProperty, &string_value)); | |
| 689 EXPECT_EQ(kText, string_value); | |
| 690 EXPECT_TRUE(result.GetString( | |
| 691 nfc_record::kLanguageProperty, &string_value)); | |
| 692 EXPECT_EQ(kLanguageCode, string_value); | |
| 693 EXPECT_TRUE(result.GetString( | |
| 694 nfc_record::kEncodingProperty, &string_value)); | |
| 695 EXPECT_EQ(kEncoding, string_value); | |
| 696 | |
| 697 // URI record. | |
| 698 data.Clear(); | |
| 699 data.SetString(NfcNdefRecord::kFieldURI, kURI); | |
| 700 data.SetString(NfcNdefRecord::kFieldMimeType, kMimeType); | |
| 701 data.SetDouble(NfcNdefRecord::kFieldTargetSize, kSize); | |
| 702 | |
| 703 record.reset(new NfcNdefRecord()); | |
| 704 ASSERT_TRUE(record->Populate(NfcNdefRecord::kTypeURI, &data)); | |
| 705 | |
| 706 result.Clear(); | |
| 707 EXPECT_TRUE(nfc_ndef_record_utils::NfcNdefRecordToDBusAttributes( | |
| 708 record.get(), &result)); | |
| 709 | |
| 710 EXPECT_TRUE(result.GetString(nfc_record::kTypeProperty, &string_value)); | |
| 711 EXPECT_EQ(nfc_record::kTypeUri, string_value); | |
| 712 EXPECT_TRUE(result.GetString(nfc_record::kUriProperty, &string_value)); | |
| 713 EXPECT_EQ(kURI, string_value); | |
| 714 EXPECT_TRUE(result.GetString(nfc_record::kMimeTypeProperty, &string_value)); | |
| 715 EXPECT_EQ(kMimeType, string_value); | |
| 716 double double_value; | |
| 717 EXPECT_TRUE(result.GetDouble(nfc_record::kSizeProperty, &double_value)); | |
| 718 EXPECT_EQ(kSize, double_value); | |
| 719 | |
| 720 // SmartPoster record. | |
| 721 base::DictionaryValue* title = new base::DictionaryValue(); | |
| 722 title->SetString(NfcNdefRecord::kFieldText, kText); | |
| 723 title->SetString(NfcNdefRecord::kFieldLanguageCode, kLanguageCode); | |
| 724 title->SetString(NfcNdefRecord::kFieldEncoding, kEncoding); | |
| 725 | |
| 726 base::ListValue* titles = new base::ListValue(); | |
| 727 titles->Append(title); | |
| 728 data.Set(NfcNdefRecord::kFieldTitles, titles); | |
| 729 | |
| 730 record.reset(new NfcNdefRecord()); | |
| 731 ASSERT_TRUE(record->Populate(NfcNdefRecord::kTypeSmartPoster, &data)); | |
| 732 | |
| 733 result.Clear(); | |
| 734 EXPECT_TRUE(nfc_ndef_record_utils::NfcNdefRecordToDBusAttributes( | |
| 735 record.get(), &result)); | |
| 736 | |
| 737 EXPECT_TRUE(result.GetString( | |
| 738 nfc_record::kTypeProperty, &string_value)); | |
| 739 EXPECT_EQ(nfc_record::kTypeSmartPoster, string_value); | |
| 740 EXPECT_TRUE(result.GetString( | |
| 741 nfc_record::kRepresentationProperty, &string_value)); | |
| 742 EXPECT_EQ(kText, string_value); | |
| 743 EXPECT_TRUE(result.GetString( | |
| 744 nfc_record::kLanguageProperty, &string_value)); | |
| 745 EXPECT_EQ(kLanguageCode, string_value); | |
| 746 EXPECT_TRUE(result.GetString( | |
| 747 nfc_record::kEncodingProperty, &string_value)); | |
| 748 EXPECT_EQ(kEncoding, string_value); | |
| 749 EXPECT_TRUE(result.GetString(nfc_record::kUriProperty, &string_value)); | |
| 750 EXPECT_EQ(kURI, string_value); | |
| 751 EXPECT_TRUE(result.GetString(nfc_record::kMimeTypeProperty, &string_value)); | |
| 752 EXPECT_EQ(kMimeType, string_value); | |
| 753 EXPECT_TRUE(result.GetDouble(nfc_record::kSizeProperty, &double_value)); | |
| 754 EXPECT_EQ(kSize, double_value); | |
| 755 } | |
| 756 | |
| 757 TEST_F(NfcChromeOSTest, RecordPropertiesToNfcNdefRecord) { | |
| 758 const char kText[] = "text"; | |
| 759 const char kURI[] = "test://uri"; | |
| 760 const char kEncoding[] = "encoding"; | |
| 761 const char kLanguageCode[] = "en"; | |
| 762 const char kMimeType[] = "mime-type"; | |
| 763 const uint32_t kSize = 5; | |
| 764 | |
| 765 FakeNfcRecordClient::Properties record_properties( | |
| 766 base::Bind(&OnPropertyChangedCallback)); | |
| 767 | |
| 768 // Text record. | |
| 769 record_properties.type.ReplaceValue(nfc_record::kTypeText); | |
| 770 record_properties.representation.ReplaceValue(kText); | |
| 771 record_properties.language.ReplaceValue(kLanguageCode); | |
| 772 record_properties.encoding.ReplaceValue(kEncoding); | |
| 773 | |
| 774 std::unique_ptr<NfcNdefRecord> record(new NfcNdefRecord()); | |
| 775 EXPECT_TRUE(nfc_ndef_record_utils::RecordPropertiesToNfcNdefRecord( | |
| 776 &record_properties, record.get())); | |
| 777 EXPECT_TRUE(record->IsPopulated()); | |
| 778 | |
| 779 std::string string_value; | |
| 780 EXPECT_EQ(NfcNdefRecord::kTypeText, record->type()); | |
| 781 EXPECT_TRUE(record->data().GetString( | |
| 782 NfcNdefRecord::kFieldText, &string_value)); | |
| 783 EXPECT_EQ(kText, string_value); | |
| 784 EXPECT_TRUE(record->data().GetString( | |
| 785 NfcNdefRecord::kFieldLanguageCode, &string_value)); | |
| 786 EXPECT_EQ(kLanguageCode, string_value); | |
| 787 EXPECT_TRUE(record->data().GetString( | |
| 788 NfcNdefRecord::kFieldEncoding, &string_value)); | |
| 789 EXPECT_EQ(kEncoding, string_value); | |
| 790 | |
| 791 // URI record. | |
| 792 record_properties.representation.ReplaceValue(""); | |
| 793 record_properties.language.ReplaceValue(""); | |
| 794 record_properties.encoding.ReplaceValue(""); | |
| 795 | |
| 796 record_properties.type.ReplaceValue(nfc_record::kTypeUri); | |
| 797 record_properties.uri.ReplaceValue(kURI); | |
| 798 record_properties.mime_type.ReplaceValue(kMimeType); | |
| 799 record_properties.size.ReplaceValue(kSize); | |
| 800 | |
| 801 record.reset(new NfcNdefRecord()); | |
| 802 EXPECT_TRUE(nfc_ndef_record_utils::RecordPropertiesToNfcNdefRecord( | |
| 803 &record_properties, record.get())); | |
| 804 EXPECT_TRUE(record->IsPopulated()); | |
| 805 | |
| 806 EXPECT_EQ(NfcNdefRecord::kTypeURI, record->type()); | |
| 807 EXPECT_TRUE(record->data().GetString( | |
| 808 NfcNdefRecord::kFieldURI, &string_value)); | |
| 809 EXPECT_EQ(kURI, string_value); | |
| 810 EXPECT_TRUE(record->data().GetString( | |
| 811 NfcNdefRecord::kFieldMimeType, &string_value)); | |
| 812 EXPECT_EQ(kMimeType, string_value); | |
| 813 double double_value; | |
| 814 EXPECT_TRUE(record->data().GetDouble( | |
| 815 NfcNdefRecord::kFieldTargetSize, &double_value)); | |
| 816 EXPECT_EQ(kSize, double_value); | |
| 817 | |
| 818 // Contents not matching type. | |
| 819 record_properties.representation.ReplaceValue(kText); | |
| 820 record_properties.language.ReplaceValue(kLanguageCode); | |
| 821 record_properties.encoding.ReplaceValue(kEncoding); | |
| 822 | |
| 823 record.reset(new NfcNdefRecord()); | |
| 824 EXPECT_FALSE(nfc_ndef_record_utils::RecordPropertiesToNfcNdefRecord( | |
| 825 &record_properties, record.get())); | |
| 826 EXPECT_FALSE(record->IsPopulated()); | |
| 827 | |
| 828 // SmartPoster record. | |
| 829 record_properties.type.ReplaceValue(nfc_record::kTypeSmartPoster); | |
| 830 EXPECT_TRUE(nfc_ndef_record_utils::RecordPropertiesToNfcNdefRecord( | |
| 831 &record_properties, record.get())); | |
| 832 EXPECT_TRUE(record->IsPopulated()); | |
| 833 | |
| 834 EXPECT_EQ(NfcNdefRecord::kTypeSmartPoster, record->type()); | |
| 835 EXPECT_TRUE(record->data().GetString( | |
| 836 NfcNdefRecord::kFieldURI, &string_value)); | |
| 837 EXPECT_EQ(kURI, string_value); | |
| 838 EXPECT_TRUE(record->data().GetString( | |
| 839 NfcNdefRecord::kFieldMimeType, &string_value)); | |
| 840 EXPECT_EQ(kMimeType, string_value); | |
| 841 EXPECT_TRUE(record->data().GetDouble( | |
| 842 NfcNdefRecord::kFieldTargetSize, &double_value)); | |
| 843 EXPECT_EQ(kSize, double_value); | |
| 844 | |
| 845 const base::ListValue* titles = NULL; | |
| 846 EXPECT_TRUE(record->data().GetList(NfcNdefRecord::kFieldTitles, &titles)); | |
| 847 EXPECT_EQ(static_cast<size_t>(1), titles->GetSize()); | |
| 848 ASSERT_TRUE(titles); | |
| 849 const base::DictionaryValue* title = NULL; | |
| 850 EXPECT_TRUE(titles->GetDictionary(0, &title)); | |
| 851 CHECK(title); | |
| 852 | |
| 853 EXPECT_TRUE(title->GetString(NfcNdefRecord::kFieldText, &string_value)); | |
| 854 EXPECT_EQ(kText, string_value); | |
| 855 EXPECT_TRUE(title->GetString( | |
| 856 NfcNdefRecord::kFieldLanguageCode, &string_value)); | |
| 857 EXPECT_EQ(kLanguageCode, string_value); | |
| 858 EXPECT_TRUE(title->GetString(NfcNdefRecord::kFieldEncoding, &string_value)); | |
| 859 EXPECT_EQ(kEncoding, string_value); | |
| 860 } | |
| 861 | |
| 862 } // namespace chromeos | |
| OLD | NEW |