// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/callback.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/values.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_nfc_adapter_client.h" #include "chromeos/dbus/fake_nfc_device_client.h" #include "chromeos/dbus/fake_nfc_record_client.h" #include "chromeos/dbus/fake_nfc_tag_client.h" #include "device/nfc/nfc_adapter_chromeos.h" #include "device/nfc/nfc_ndef_record.h" #include "device/nfc/nfc_ndef_record_utils_chromeos.h" #include "device/nfc/nfc_peer.h" #include "device/nfc/nfc_tag.h" #include "device/nfc/nfc_tag_technology.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/cros_system_api/dbus/service_constants.h" using device::NfcAdapter; using device::NfcNdefMessage; using device::NfcNdefRecord; using device::NfcNdefTagTechnology; using device::NfcPeer; using device::NfcTag; namespace chromeos { namespace { // Callback passed to property structures. void OnPropertyChangedCallback(const std::string& property_name) { } // Callback passed to dbus::PropertyBase::Set. void OnSet(bool success) { } class TestObserver : public NfcAdapter::Observer, public NfcPeer::Observer, public NfcTag::Observer, public NfcNdefTagTechnology::Observer { public: TestObserver(scoped_refptr adapter) : present_changed_count_(0), powered_changed_count_(0), polling_changed_count_(0), peer_records_received_count_(0), tag_records_received_count_(0), peer_count_(0), tag_count_(0), adapter_(adapter) { } ~TestObserver() override {} // NfcAdapter::Observer override. void AdapterPresentChanged(NfcAdapter* adapter, bool present) override { EXPECT_EQ(adapter_.get(), adapter); present_changed_count_++; } // NfcAdapter::Observer override. void AdapterPoweredChanged(NfcAdapter* adapter, bool powered) override { EXPECT_EQ(adapter_.get(), adapter); powered_changed_count_++; } // NfcAdapter::Observer override. void AdapterPollingChanged(NfcAdapter* adapter, bool powered) override { EXPECT_EQ(adapter_.get(), adapter); polling_changed_count_++; } // NfcAdapter::Observer override. void PeerFound(NfcAdapter* adapter, NfcPeer* peer) override { EXPECT_EQ(adapter_.get(), adapter); peer_count_++; peer_identifier_ = peer->GetIdentifier(); } // NfcAdapter::Observer override. void PeerLost(NfcAdapter* adapter, NfcPeer* peer) override { EXPECT_EQ(adapter_.get(), adapter); EXPECT_EQ(peer_identifier_, peer->GetIdentifier()); peer_count_--; peer_identifier_.clear(); } // NfcAdapter::Observer override. void TagFound(NfcAdapter* adapter, NfcTag* tag) override { EXPECT_EQ(adapter_.get(), adapter); tag_count_++; tag_identifier_ = tag->GetIdentifier(); } // NfcAdapter::Observer override. void TagLost(NfcAdapter* adapter, NfcTag* tag) override { EXPECT_EQ(adapter_.get(), adapter); EXPECT_EQ(tag_identifier_, tag->GetIdentifier()); tag_count_--; tag_identifier_.clear(); } // NfcPeer::Observer override. void RecordReceived(NfcPeer* peer, const NfcNdefRecord* record) override { EXPECT_EQ(peer, adapter_->GetPeer(peer_identifier_)); EXPECT_EQ(peer_identifier_, peer->GetIdentifier()); peer_records_received_count_++; } // NfcNdefTagTechnology::Observer override. void RecordReceived(NfcTag* tag, const NfcNdefRecord* record) override { EXPECT_EQ(tag, adapter_->GetTag(tag_identifier_)); EXPECT_EQ(tag_identifier_, tag->GetIdentifier()); tag_records_received_count_++; } int present_changed_count_; int powered_changed_count_; int polling_changed_count_; int peer_records_received_count_; int tag_records_received_count_; int peer_count_; int tag_count_; std::string peer_identifier_; std::string tag_identifier_; scoped_refptr adapter_; }; } // namespace class NfcChromeOSTest : public testing::Test { public: void SetUp() override { DBusThreadManager::Initialize(); fake_nfc_adapter_client_ = static_cast( DBusThreadManager::Get()->GetNfcAdapterClient()); fake_nfc_device_client_ = static_cast( DBusThreadManager::Get()->GetNfcDeviceClient()); fake_nfc_record_client_ = static_cast( DBusThreadManager::Get()->GetNfcRecordClient()); fake_nfc_tag_client_ = static_cast( DBusThreadManager::Get()->GetNfcTagClient()); fake_nfc_adapter_client_->EnablePairingOnPoll(false); fake_nfc_device_client_->DisableSimulationTimeout(); fake_nfc_tag_client_->DisableSimulationTimeout(); success_callback_count_ = 0; error_callback_count_ = 0; } void TearDown() override { adapter_ = NULL; DBusThreadManager::Shutdown(); } // Assigns a new instance of NfcAdapterChromeOS to |adapter_|. void SetAdapter() { adapter_ = new NfcAdapterChromeOS(); ASSERT_TRUE(adapter_.get() != NULL); ASSERT_TRUE(adapter_->IsInitialized()); base::RunLoop().RunUntilIdle(); } // Generic callbacks for success and error. void SuccessCallback() { success_callback_count_++; } void ErrorCallback() { error_callback_count_++; } void ErrorCallbackWithParameters(const std::string& error_name, const std::string& error_message) { LOG(INFO) << "Error callback called: " << error_name << ", " << error_message; error_callback_count_++; } protected: // MessageLoop instance, used to simulate asynchronous behavior. base::MessageLoop message_loop_; // Fields for storing the number of times SuccessCallback and ErrorCallback // have been called. int success_callback_count_; int error_callback_count_; // The NfcAdapter instance under test. scoped_refptr adapter_; // The fake D-Bus client instances used for testing. FakeNfcAdapterClient* fake_nfc_adapter_client_; FakeNfcDeviceClient* fake_nfc_device_client_; FakeNfcRecordClient* fake_nfc_record_client_; FakeNfcTagClient* fake_nfc_tag_client_; }; // Tests that the adapter updates correctly to reflect the current "default" // adapter, when multiple adapters appear and disappear. TEST_F(NfcChromeOSTest, PresentChanged) { SetAdapter(); EXPECT_TRUE(adapter_->IsPresent()); TestObserver observer(adapter_); adapter_->AddObserver(&observer); // Remove all adapters. fake_nfc_adapter_client_->SetAdapterPresent(false); EXPECT_EQ(1, observer.present_changed_count_); EXPECT_FALSE(adapter_->IsPresent()); // Add two adapters. fake_nfc_adapter_client_->SetAdapterPresent(true); fake_nfc_adapter_client_->SetSecondAdapterPresent(true); EXPECT_EQ(2, observer.present_changed_count_); EXPECT_TRUE(adapter_->IsPresent()); // Remove the first adapter. Adapter should update to the second one. fake_nfc_adapter_client_->SetAdapterPresent(false); EXPECT_EQ(4, observer.present_changed_count_); EXPECT_TRUE(adapter_->IsPresent()); fake_nfc_adapter_client_->SetSecondAdapterPresent(false); EXPECT_EQ(5, observer.present_changed_count_); EXPECT_FALSE(adapter_->IsPresent()); } // Tests that the adapter correctly reflects the power state. TEST_F(NfcChromeOSTest, SetPowered) { SetAdapter(); TestObserver observer(adapter_); adapter_->AddObserver(&observer); EXPECT_FALSE(adapter_->IsPowered()); // SetPowered(false), while not powered. adapter_->SetPowered( false, base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallback, base::Unretained(this))); EXPECT_FALSE(adapter_->IsPowered()); EXPECT_EQ(0, observer.powered_changed_count_); EXPECT_EQ(0, success_callback_count_); EXPECT_EQ(1, error_callback_count_); // SetPowered(true). adapter_->SetPowered( true, base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallback, base::Unretained(this))); EXPECT_TRUE(adapter_->IsPowered()); EXPECT_EQ(1, observer.powered_changed_count_); EXPECT_EQ(1, success_callback_count_); EXPECT_EQ(1, error_callback_count_); // SetPowered(true), while powered. adapter_->SetPowered( true, base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallback, base::Unretained(this))); EXPECT_TRUE(adapter_->IsPowered()); EXPECT_EQ(1, observer.powered_changed_count_); EXPECT_EQ(1, success_callback_count_); EXPECT_EQ(2, error_callback_count_); // SetPowered(false). adapter_->SetPowered( false, base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallback, base::Unretained(this))); EXPECT_FALSE(adapter_->IsPowered()); EXPECT_EQ(2, observer.powered_changed_count_); EXPECT_EQ(2, success_callback_count_); EXPECT_EQ(2, error_callback_count_); } // Tests that the power state updates correctly when the adapter disappears. TEST_F(NfcChromeOSTest, PresentChangedWhilePowered) { SetAdapter(); TestObserver observer(adapter_); adapter_->AddObserver(&observer); EXPECT_FALSE(adapter_->IsPowered()); EXPECT_TRUE(adapter_->IsPresent()); adapter_->SetPowered( true, base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallback, base::Unretained(this))); EXPECT_TRUE(adapter_->IsPowered()); fake_nfc_adapter_client_->SetAdapterPresent(false); EXPECT_EQ(1, observer.present_changed_count_); EXPECT_EQ(2, observer.powered_changed_count_); EXPECT_FALSE(adapter_->IsPowered()); EXPECT_FALSE(adapter_->IsPresent()); } // Tests that peer and record objects are created for all peers and records // that already exist when the adapter is created. TEST_F(NfcChromeOSTest, PeersInitializedWhenAdapterCreated) { // Set up the adapter client. NfcAdapterClient::Properties* properties = fake_nfc_adapter_client_->GetProperties( dbus::ObjectPath(FakeNfcAdapterClient::kAdapterPath0)); properties->powered.Set(true, base::Bind(&OnSet)); fake_nfc_adapter_client_->StartPollLoop( dbus::ObjectPath(FakeNfcAdapterClient::kAdapterPath0), nfc_adapter::kModeInitiator, base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallbackWithParameters, base::Unretained(this))); EXPECT_EQ(1, success_callback_count_); EXPECT_TRUE(properties->powered.value()); EXPECT_TRUE(properties->polling.value()); // Start pairing simulation, which will add a fake device and fake records. fake_nfc_device_client_->BeginPairingSimulation(0, 0); base::RunLoop().RunUntilIdle(); // Create the adapter. SetAdapter(); TestObserver observer(adapter_); adapter_->AddObserver(&observer); // Observer shouldn't have received any calls, as it got created AFTER the // notifications were sent. EXPECT_EQ(0, observer.present_changed_count_); EXPECT_EQ(0, observer.powered_changed_count_); EXPECT_EQ(0, observer.polling_changed_count_); EXPECT_EQ(0, observer.peer_count_); EXPECT_TRUE(adapter_->IsPresent()); EXPECT_TRUE(adapter_->IsPowered()); EXPECT_FALSE(adapter_->IsPolling()); NfcAdapter::PeerList peers; adapter_->GetPeers(&peers); EXPECT_EQ(static_cast(1), peers.size()); NfcPeer* peer = peers[0]; const NfcNdefMessage& message = peer->GetNdefMessage(); EXPECT_EQ(static_cast(3), message.records().size()); } // Tests that tag and record objects are created for all tags and records that // already exist when the adapter is created. TEST_F(NfcChromeOSTest, TagsInitializedWhenAdapterCreated) { const char kTestURI[] = "fake://path/for/testing"; // Set up the adapter client. NfcAdapterClient::Properties* properties = fake_nfc_adapter_client_->GetProperties( dbus::ObjectPath(FakeNfcAdapterClient::kAdapterPath0)); properties->powered.Set(true, base::Bind(&OnSet)); fake_nfc_adapter_client_->StartPollLoop( dbus::ObjectPath(FakeNfcAdapterClient::kAdapterPath0), nfc_adapter::kModeInitiator, base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallbackWithParameters, base::Unretained(this))); EXPECT_EQ(1, success_callback_count_); EXPECT_TRUE(properties->powered.value()); EXPECT_TRUE(properties->polling.value()); // Add the fake tag. fake_nfc_tag_client_->BeginPairingSimulation(0); base::RunLoop().RunUntilIdle(); // Create a fake record. base::DictionaryValue test_record_data; test_record_data.SetString(nfc_record::kTypeProperty, nfc_record::kTypeUri); test_record_data.SetString(nfc_record::kUriProperty, kTestURI); fake_nfc_tag_client_->Write( dbus::ObjectPath(FakeNfcTagClient::kTagPath), test_record_data, base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallbackWithParameters, base::Unretained(this))); EXPECT_EQ(2, success_callback_count_); // Create the adapter. SetAdapter(); TestObserver observer(adapter_); adapter_->AddObserver(&observer); // Observer shouldn't have received any calls, as it got created AFTER the // notifications were sent. EXPECT_EQ(0, observer.present_changed_count_); EXPECT_EQ(0, observer.powered_changed_count_); EXPECT_EQ(0, observer.polling_changed_count_); EXPECT_EQ(0, observer.peer_count_); EXPECT_TRUE(adapter_->IsPresent()); EXPECT_TRUE(adapter_->IsPowered()); EXPECT_FALSE(adapter_->IsPolling()); NfcAdapter::TagList tags; adapter_->GetTags(&tags); EXPECT_EQ(static_cast(1), tags.size()); NfcTag* tag = tags[0]; const NfcNdefMessage& message = tag->GetNdefTagTechnology()->GetNdefMessage(); EXPECT_EQ(static_cast(1), message.records().size()); const NfcNdefRecord* record = message.records()[0]; std::string uri; EXPECT_TRUE(record->data().GetString(NfcNdefRecord::kFieldURI, &uri)); EXPECT_EQ(kTestURI, uri); } // Tests that the adapter correctly updates its state when polling is started // and stopped. TEST_F(NfcChromeOSTest, StartAndStopPolling) { SetAdapter(); EXPECT_TRUE(adapter_->IsPresent()); TestObserver observer(adapter_); adapter_->AddObserver(&observer); // Start polling while not powered. Should fail. EXPECT_FALSE(adapter_->IsPowered()); adapter_->StartPolling( base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallback, base::Unretained(this))); EXPECT_EQ(0, success_callback_count_); EXPECT_EQ(1, error_callback_count_); EXPECT_FALSE(adapter_->IsPolling()); // Start polling while powered. Should succeed. adapter_->SetPowered( true, base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallback, base::Unretained(this))); EXPECT_EQ(1, success_callback_count_); EXPECT_EQ(1, error_callback_count_); EXPECT_TRUE(adapter_->IsPowered()); adapter_->StartPolling( base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallback, base::Unretained(this))); EXPECT_EQ(2, success_callback_count_); EXPECT_EQ(1, error_callback_count_); EXPECT_TRUE(adapter_->IsPolling()); // Start polling while already polling. Should fail. adapter_->StartPolling( base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallback, base::Unretained(this))); EXPECT_EQ(2, success_callback_count_); EXPECT_EQ(2, error_callback_count_); EXPECT_TRUE(adapter_->IsPolling()); // Stop polling. Should succeed. adapter_->StopPolling( base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallback, base::Unretained(this))); EXPECT_EQ(3, success_callback_count_); EXPECT_EQ(2, error_callback_count_); EXPECT_FALSE(adapter_->IsPolling()); // Stop polling while not polling. Should fail. adapter_->StopPolling( base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallback, base::Unretained(this))); EXPECT_EQ(3, success_callback_count_); EXPECT_EQ(3, error_callback_count_); EXPECT_FALSE(adapter_->IsPolling()); } // Tests a simple peer pairing simulation. TEST_F(NfcChromeOSTest, PeerTest) { SetAdapter(); TestObserver observer(adapter_); adapter_->AddObserver(&observer); adapter_->SetPowered( true, base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallback, base::Unretained(this))); adapter_->StartPolling( base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallback, base::Unretained(this))); EXPECT_EQ(2, success_callback_count_); EXPECT_TRUE(adapter_->IsPowered()); EXPECT_TRUE(adapter_->IsPolling()); EXPECT_EQ(0, observer.peer_count_); // Add the fake device. fake_nfc_device_client_->BeginPairingSimulation(0, -1); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, observer.peer_count_); EXPECT_EQ(FakeNfcDeviceClient::kDevicePath, observer.peer_identifier_); NfcPeer* peer = adapter_->GetPeer(observer.peer_identifier_); CHECK(peer); peer->AddObserver(&observer); // Peer should have no records on it. EXPECT_TRUE(peer->GetNdefMessage().records().empty()); EXPECT_EQ(0, observer.peer_records_received_count_); // Make records visible. fake_nfc_record_client_->SetDeviceRecordsVisible(true); EXPECT_EQ(3, observer.peer_records_received_count_); EXPECT_EQ(static_cast(3), peer->GetNdefMessage().records().size()); // End the simulation. Peer should get removed. fake_nfc_device_client_->EndPairingSimulation(); EXPECT_EQ(0, observer.peer_count_); EXPECT_TRUE(observer.peer_identifier_.empty()); peer = adapter_->GetPeer(observer.peer_identifier_); EXPECT_FALSE(peer); // No record related notifications will be sent when a peer gets removed. EXPECT_EQ(3, observer.peer_records_received_count_); } // Tests a simple tag pairing simulation. TEST_F(NfcChromeOSTest, TagTest) { const char kTestURI[] = "fake://path/for/testing"; SetAdapter(); TestObserver observer(adapter_); adapter_->AddObserver(&observer); adapter_->SetPowered( true, base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallback, base::Unretained(this))); adapter_->StartPolling( base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallback, base::Unretained(this))); EXPECT_EQ(2, success_callback_count_); EXPECT_TRUE(adapter_->IsPowered()); EXPECT_TRUE(adapter_->IsPolling()); EXPECT_EQ(0, observer.tag_count_); // Add the fake tag. fake_nfc_tag_client_->BeginPairingSimulation(0); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, observer.tag_count_); EXPECT_EQ(FakeNfcTagClient::kTagPath, observer.tag_identifier_); NfcTag* tag = adapter_->GetTag(observer.tag_identifier_); CHECK(tag); tag->AddObserver(&observer); EXPECT_TRUE(tag->IsReady()); CHECK(tag->GetNdefTagTechnology()); tag->GetNdefTagTechnology()->AddObserver(&observer); NfcNdefTagTechnology* tag_technology = tag->GetNdefTagTechnology(); EXPECT_TRUE(tag_technology->IsSupportedByTag()); // Tag should have no records on it. EXPECT_TRUE(tag_technology->GetNdefMessage().records().empty()); EXPECT_EQ(0, observer.tag_records_received_count_); // Set the tag record visible. By default the record has no content, so no // NfcNdefMessage should be received. fake_nfc_record_client_->SetTagRecordsVisible(true); EXPECT_TRUE(tag_technology->GetNdefMessage().records().empty()); EXPECT_EQ(0, observer.tag_records_received_count_); fake_nfc_record_client_->SetTagRecordsVisible(false); // Write an NDEF record to the tag. EXPECT_EQ(2, success_callback_count_); // 2 for SetPowered and StartPolling. EXPECT_EQ(0, error_callback_count_); base::DictionaryValue record_data; record_data.SetString(NfcNdefRecord::kFieldURI, kTestURI); NfcNdefRecord written_record; written_record.Populate(NfcNdefRecord::kTypeURI, &record_data); NfcNdefMessage written_message; written_message.AddRecord(&written_record); tag_technology->WriteNdef( written_message, base::Bind(&NfcChromeOSTest::SuccessCallback, base::Unretained(this)), base::Bind(&NfcChromeOSTest::ErrorCallback, base::Unretained(this))); EXPECT_EQ(3, success_callback_count_); EXPECT_EQ(0, error_callback_count_); EXPECT_EQ(static_cast(1), tag_technology->GetNdefMessage().records().size()); EXPECT_EQ(1, observer.tag_records_received_count_); NfcNdefRecord* received_record = tag_technology->GetNdefMessage().records()[0]; EXPECT_EQ(NfcNdefRecord::kTypeURI, received_record->type()); std::string uri; EXPECT_TRUE(received_record->data().GetString( NfcNdefRecord::kFieldURI, &uri)); EXPECT_EQ(kTestURI, uri); // End the simulation. Tag should get removed. fake_nfc_tag_client_->EndPairingSimulation(); EXPECT_EQ(0, observer.tag_count_); EXPECT_TRUE(observer.tag_identifier_.empty()); tag = adapter_->GetTag(observer.tag_identifier_); EXPECT_FALSE(tag); // No record related notifications will be sent when a tag gets removed. EXPECT_EQ(1, observer.tag_records_received_count_); } // Unit tests for nfc_ndef_record_utils methods. TEST_F(NfcChromeOSTest, NfcNdefRecordToDBusAttributes) { const char kText[] = "text"; const char kURI[] = "test://uri"; const char kEncoding[] = "encoding"; const char kLanguageCode[] = "en"; const char kMimeType[] = "mime-type"; const double kSize = 5; // Text record. base::DictionaryValue data; data.SetString(NfcNdefRecord::kFieldText, kText); data.SetString(NfcNdefRecord::kFieldLanguageCode, kLanguageCode); data.SetString(NfcNdefRecord::kFieldEncoding, kEncoding); scoped_ptr record(new NfcNdefRecord()); ASSERT_TRUE(record->Populate(NfcNdefRecord::kTypeText, &data)); base::DictionaryValue result; EXPECT_TRUE(nfc_ndef_record_utils::NfcNdefRecordToDBusAttributes( record.get(), &result)); std::string string_value; EXPECT_TRUE(result.GetString( nfc_record::kTypeProperty, &string_value)); EXPECT_EQ(nfc_record::kTypeText, string_value); EXPECT_TRUE(result.GetString( nfc_record::kRepresentationProperty, &string_value)); EXPECT_EQ(kText, string_value); EXPECT_TRUE(result.GetString( nfc_record::kLanguageProperty, &string_value)); EXPECT_EQ(kLanguageCode, string_value); EXPECT_TRUE(result.GetString( nfc_record::kEncodingProperty, &string_value)); EXPECT_EQ(kEncoding, string_value); // URI record. data.Clear(); data.SetString(NfcNdefRecord::kFieldURI, kURI); data.SetString(NfcNdefRecord::kFieldMimeType, kMimeType); data.SetDouble(NfcNdefRecord::kFieldTargetSize, kSize); record.reset(new NfcNdefRecord()); ASSERT_TRUE(record->Populate(NfcNdefRecord::kTypeURI, &data)); result.Clear(); EXPECT_TRUE(nfc_ndef_record_utils::NfcNdefRecordToDBusAttributes( record.get(), &result)); EXPECT_TRUE(result.GetString(nfc_record::kTypeProperty, &string_value)); EXPECT_EQ(nfc_record::kTypeUri, string_value); EXPECT_TRUE(result.GetString(nfc_record::kUriProperty, &string_value)); EXPECT_EQ(kURI, string_value); EXPECT_TRUE(result.GetString(nfc_record::kMimeTypeProperty, &string_value)); EXPECT_EQ(kMimeType, string_value); double double_value; EXPECT_TRUE(result.GetDouble(nfc_record::kSizeProperty, &double_value)); EXPECT_EQ(kSize, double_value); // SmartPoster record. base::DictionaryValue* title = new base::DictionaryValue(); title->SetString(NfcNdefRecord::kFieldText, kText); title->SetString(NfcNdefRecord::kFieldLanguageCode, kLanguageCode); title->SetString(NfcNdefRecord::kFieldEncoding, kEncoding); base::ListValue* titles = new base::ListValue(); titles->Append(title); data.Set(NfcNdefRecord::kFieldTitles, titles); record.reset(new NfcNdefRecord()); ASSERT_TRUE(record->Populate(NfcNdefRecord::kTypeSmartPoster, &data)); result.Clear(); EXPECT_TRUE(nfc_ndef_record_utils::NfcNdefRecordToDBusAttributes( record.get(), &result)); EXPECT_TRUE(result.GetString( nfc_record::kTypeProperty, &string_value)); EXPECT_EQ(nfc_record::kTypeSmartPoster, string_value); EXPECT_TRUE(result.GetString( nfc_record::kRepresentationProperty, &string_value)); EXPECT_EQ(kText, string_value); EXPECT_TRUE(result.GetString( nfc_record::kLanguageProperty, &string_value)); EXPECT_EQ(kLanguageCode, string_value); EXPECT_TRUE(result.GetString( nfc_record::kEncodingProperty, &string_value)); EXPECT_EQ(kEncoding, string_value); EXPECT_TRUE(result.GetString(nfc_record::kUriProperty, &string_value)); EXPECT_EQ(kURI, string_value); EXPECT_TRUE(result.GetString(nfc_record::kMimeTypeProperty, &string_value)); EXPECT_EQ(kMimeType, string_value); EXPECT_TRUE(result.GetDouble(nfc_record::kSizeProperty, &double_value)); EXPECT_EQ(kSize, double_value); } TEST_F(NfcChromeOSTest, RecordPropertiesToNfcNdefRecord) { const char kText[] = "text"; const char kURI[] = "test://uri"; const char kEncoding[] = "encoding"; const char kLanguageCode[] = "en"; const char kMimeType[] = "mime-type"; const uint32 kSize = 5; FakeNfcRecordClient::Properties record_properties( base::Bind(&OnPropertyChangedCallback)); // Text record. record_properties.type.ReplaceValue(nfc_record::kTypeText); record_properties.representation.ReplaceValue(kText); record_properties.language.ReplaceValue(kLanguageCode); record_properties.encoding.ReplaceValue(kEncoding); scoped_ptr record(new NfcNdefRecord()); EXPECT_TRUE(nfc_ndef_record_utils::RecordPropertiesToNfcNdefRecord( &record_properties, record.get())); EXPECT_TRUE(record->IsPopulated()); std::string string_value; EXPECT_EQ(NfcNdefRecord::kTypeText, record->type()); EXPECT_TRUE(record->data().GetString( NfcNdefRecord::kFieldText, &string_value)); EXPECT_EQ(kText, string_value); EXPECT_TRUE(record->data().GetString( NfcNdefRecord::kFieldLanguageCode, &string_value)); EXPECT_EQ(kLanguageCode, string_value); EXPECT_TRUE(record->data().GetString( NfcNdefRecord::kFieldEncoding, &string_value)); EXPECT_EQ(kEncoding, string_value); // URI record. record_properties.representation.ReplaceValue(""); record_properties.language.ReplaceValue(""); record_properties.encoding.ReplaceValue(""); record_properties.type.ReplaceValue(nfc_record::kTypeUri); record_properties.uri.ReplaceValue(kURI); record_properties.mime_type.ReplaceValue(kMimeType); record_properties.size.ReplaceValue(kSize); record.reset(new NfcNdefRecord()); EXPECT_TRUE(nfc_ndef_record_utils::RecordPropertiesToNfcNdefRecord( &record_properties, record.get())); EXPECT_TRUE(record->IsPopulated()); EXPECT_EQ(NfcNdefRecord::kTypeURI, record->type()); EXPECT_TRUE(record->data().GetString( NfcNdefRecord::kFieldURI, &string_value)); EXPECT_EQ(kURI, string_value); EXPECT_TRUE(record->data().GetString( NfcNdefRecord::kFieldMimeType, &string_value)); EXPECT_EQ(kMimeType, string_value); double double_value; EXPECT_TRUE(record->data().GetDouble( NfcNdefRecord::kFieldTargetSize, &double_value)); EXPECT_EQ(kSize, double_value); // Contents not matching type. record_properties.representation.ReplaceValue(kText); record_properties.language.ReplaceValue(kLanguageCode); record_properties.encoding.ReplaceValue(kEncoding); record.reset(new NfcNdefRecord()); EXPECT_FALSE(nfc_ndef_record_utils::RecordPropertiesToNfcNdefRecord( &record_properties, record.get())); EXPECT_FALSE(record->IsPopulated()); // SmartPoster record. record_properties.type.ReplaceValue(nfc_record::kTypeSmartPoster); EXPECT_TRUE(nfc_ndef_record_utils::RecordPropertiesToNfcNdefRecord( &record_properties, record.get())); EXPECT_TRUE(record->IsPopulated()); EXPECT_EQ(NfcNdefRecord::kTypeSmartPoster, record->type()); EXPECT_TRUE(record->data().GetString( NfcNdefRecord::kFieldURI, &string_value)); EXPECT_EQ(kURI, string_value); EXPECT_TRUE(record->data().GetString( NfcNdefRecord::kFieldMimeType, &string_value)); EXPECT_EQ(kMimeType, string_value); EXPECT_TRUE(record->data().GetDouble( NfcNdefRecord::kFieldTargetSize, &double_value)); EXPECT_EQ(kSize, double_value); const base::ListValue* titles = NULL; EXPECT_TRUE(record->data().GetList(NfcNdefRecord::kFieldTitles, &titles)); EXPECT_EQ(static_cast(1), titles->GetSize()); ASSERT_TRUE(titles); const base::DictionaryValue* title = NULL; EXPECT_TRUE(titles->GetDictionary(0, &title)); CHECK(title); EXPECT_TRUE(title->GetString(NfcNdefRecord::kFieldText, &string_value)); EXPECT_EQ(kText, string_value); EXPECT_TRUE(title->GetString( NfcNdefRecord::kFieldLanguageCode, &string_value)); EXPECT_EQ(kLanguageCode, string_value); EXPECT_TRUE(title->GetString(NfcNdefRecord::kFieldEncoding, &string_value)); EXPECT_EQ(kEncoding, string_value); } } // namespace chromeos