blob: 7b62970e17ee22283cd0a6fd0e18d36005638e3a [file] [log] [blame]
// 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 <stddef.h>
#include <stdint.h>
#include <memory>
#include "base/callback.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<NfcAdapter> 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<NfcAdapter> adapter_;
};
} // namespace
class NfcChromeOSTest : public testing::Test {
public:
void SetUp() override {
DBusThreadManager::Initialize();
fake_nfc_adapter_client_ = static_cast<FakeNfcAdapterClient*>(
DBusThreadManager::Get()->GetNfcAdapterClient());
fake_nfc_device_client_ = static_cast<FakeNfcDeviceClient*>(
DBusThreadManager::Get()->GetNfcDeviceClient());
fake_nfc_record_client_ = static_cast<FakeNfcRecordClient*>(
DBusThreadManager::Get()->GetNfcRecordClient());
fake_nfc_tag_client_ = static_cast<FakeNfcTagClient*>(
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<NfcAdapter> 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<size_t>(1), peers.size());
NfcPeer* peer = peers[0];
const NfcNdefMessage& message = peer->GetNdefMessage();
EXPECT_EQ(static_cast<size_t>(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<size_t>(1), tags.size());
NfcTag* tag = tags[0];
const NfcNdefMessage& message = tag->GetNdefTagTechnology()->GetNdefMessage();
EXPECT_EQ(static_cast<size_t>(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<size_t>(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<size_t>(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);
std::unique_ptr<NfcNdefRecord> 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_t 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);
std::unique_ptr<NfcNdefRecord> 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<size_t>(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