blob: 8f142295f95cf6f0f9b65ce72c80b067a53115af [file] [log] [blame]
// Copyright 2020 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 "chrome/browser/nearby_sharing/certificates/nearby_share_certificate_manager_impl.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "chrome/browser/nearby_sharing/certificates/constants.h"
#include "chrome/browser/nearby_sharing/certificates/fake_nearby_share_certificate_storage.h"
#include "chrome/browser/nearby_sharing/certificates/nearby_share_certificate_manager.h"
#include "chrome/browser/nearby_sharing/certificates/test_util.h"
#include "chrome/browser/nearby_sharing/client/fake_nearby_share_client.h"
#include "chrome/browser/nearby_sharing/common/nearby_share_prefs.h"
#include "chrome/browser/nearby_sharing/contacts/fake_nearby_share_contact_manager.h"
#include "chrome/browser/nearby_sharing/local_device_data/fake_nearby_share_local_device_data_manager.h"
#include "chrome/browser/nearby_sharing/scheduling/fake_nearby_share_scheduler_factory.h"
#include "chrome/browser/ui/webui/nearby_share/public/mojom/nearby_share_settings.mojom.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
const base::Time t0 =
base::Time::UnixEpoch() + base::TimeDelta::FromDays(365 * 50);
// Copied from nearby_share_certificate_manager_impl.cc.
constexpr base::TimeDelta kListPublicCertificatesTimeout =
base::TimeDelta::FromSeconds(30);
const char kPageTokenPrefix[] = "page_token_";
const char kSecretIdPrefix[] = "secret_id_";
const char kDeviceIdPrefix[] = "users/me/devices/";
const char kDeviceId[] = "123456789A";
const std::vector<std::string> kPublicCertificateIds = {"id1", "id2", "id3"};
void CaptureDecryptedPublicCertificateCallback(
base::Optional<NearbyShareDecryptedPublicCertificate>* dest,
base::Optional<NearbyShareDecryptedPublicCertificate> src) {
*dest = std::move(src);
}
} // namespace
class NearbyShareCertificateManagerImplTest
: public ::testing::Test,
public NearbyShareCertificateManager::Observer {
public:
NearbyShareCertificateManagerImplTest() {
// Set time to t0.
FastForward(t0 - base::Time::UnixEpoch());
local_device_data_manager_ =
std::make_unique<FakeNearbyShareLocalDeviceDataManager>();
local_device_data_manager_->SetId(kDeviceId);
contact_manager_ = std::make_unique<FakeNearbyShareContactManager>();
pref_service_ = std::make_unique<TestingPrefServiceSimple>();
pref_service_->registry()->RegisterDictionaryPref(
prefs::kNearbySharingSchedulerDownloadPublicCertificatesPrefName);
NearbyShareSchedulerFactory::SetFactoryForTesting(&scheduler_factory_);
NearbyShareCertificateStorageImpl::Factory::SetFactoryForTesting(
&cert_store_factory_);
// Set default device data.
local_device_data_manager_->SetDeviceName(
GetNearbyShareTestMetadata().device_name());
local_device_data_manager_->SetFullName(
GetNearbyShareTestMetadata().full_name());
local_device_data_manager_->SetIconUrl(
GetNearbyShareTestMetadata().icon_url());
SetBluetoothMacAddress(kTestUnparsedBluetoothMacAddress);
cert_manager_ = NearbyShareCertificateManagerImpl::Factory::Create(
local_device_data_manager_.get(), contact_manager_.get(),
pref_service_.get(),
/*proto_database_provider=*/nullptr, base::FilePath(), &client_factory_,
task_environment_.GetMockClock());
cert_manager_->AddObserver(this);
cert_store_ = cert_store_factory_.instances().back();
private_cert_exp_scheduler_ =
scheduler_factory_.pref_name_to_expiration_instance()
.find(
prefs::
kNearbySharingSchedulerPrivateCertificateExpirationPrefName)
->second.fake_scheduler;
public_cert_exp_scheduler_ =
scheduler_factory_.pref_name_to_expiration_instance()
.find(
prefs::
kNearbySharingSchedulerPublicCertificateExpirationPrefName)
->second.fake_scheduler;
upload_scheduler_ =
scheduler_factory_.pref_name_to_on_demand_instance()
.find(
prefs::
kNearbySharingSchedulerUploadLocalDeviceCertificatesPrefName)
->second.fake_scheduler;
download_scheduler_ =
scheduler_factory_.pref_name_to_periodic_instance()
.find(prefs::
kNearbySharingSchedulerDownloadPublicCertificatesPrefName)
->second.fake_scheduler;
PopulatePrivateCertificates();
PopulatePublicCertificates();
mock_adapter_ =
base::MakeRefCounted<testing::NiceMock<device::MockBluetoothAdapter>>();
ON_CALL(*mock_adapter_, GetAddress()).WillByDefault([this] {
return bluetooth_mac_address_;
});
device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter_);
}
~NearbyShareCertificateManagerImplTest() override = default;
void TearDown() override {
cert_manager_->RemoveObserver(this);
NearbyShareSchedulerFactory::SetFactoryForTesting(nullptr);
NearbyShareCertificateStorageImpl::Factory::SetFactoryForTesting(nullptr);
}
void SetBluetoothMacAddress(const std::string& bluetooth_mac_address) {
bluetooth_mac_address_ = bluetooth_mac_address;
}
// NearbyShareCertificateManager::Observer:
void OnPublicCertificatesDownloaded() override {
++num_public_certs_downloaded_notifications_;
}
void OnPrivateCertificatesChanged() override {
++num_private_certs_changed_notifications_;
}
protected:
enum class DownloadPublicCertificatesResult {
kSuccess,
kTimeout,
kHttpError,
kStorageError
};
base::Time Now() const { return task_environment_.GetMockClock()->Now(); }
// Fast-forwards mock time by |delta| and fires relevant timers.
void FastForward(base::TimeDelta delta) {
task_environment_.FastForwardBy(delta);
}
void GetPublicCertificatesCallback(
bool success,
const std::vector<nearbyshare::proto::PublicCertificate>& certs) {
auto& callbacks = cert_store_->get_public_certificates_callbacks();
auto callback = std::move(callbacks.back());
callbacks.pop_back();
auto pub_certs =
std::make_unique<std::vector<nearbyshare::proto::PublicCertificate>>(
certs.begin(), certs.end());
std::move(callback).Run(success, std::move(pub_certs));
}
void HandlePrivateCertificateRefresh(bool expect_private_cert_refresh,
bool expected_success) {
if (expect_private_cert_refresh)
private_cert_exp_scheduler_->InvokeRequestCallback();
EXPECT_EQ(expect_private_cert_refresh ? 1u : 0u,
private_cert_exp_scheduler_->handled_results().size());
if (expect_private_cert_refresh) {
EXPECT_EQ(expected_success,
private_cert_exp_scheduler_->handled_results().back());
}
EXPECT_EQ(expect_private_cert_refresh && expected_success ? 1u : 0u,
num_private_certs_changed_notifications_);
EXPECT_EQ(expect_private_cert_refresh && expected_success ? 1u : 0u,
upload_scheduler_->num_immediate_requests());
}
void VerifyPrivateCertificates(
const nearbyshare::proto::EncryptedMetadata& expected_metadata) {
// Expect a full set of certificates for both all-contacts and
// selected-contacts
std::vector<NearbySharePrivateCertificate> certs =
*cert_store_->GetPrivateCertificates();
EXPECT_EQ(2 * kNearbyShareNumPrivateCertificates, certs.size());
base::Time min_not_before_all_contacts = base::Time::Max();
base::Time min_not_before_selected_contacts = base::Time::Max();
base::Time max_not_after_all_contacts = base::Time::Min();
base::Time max_not_after_selected_contacts = base::Time::Min();
for (const auto& cert : certs) {
EXPECT_EQ(cert.not_after() - cert.not_before(),
kNearbyShareCertificateValidityPeriod);
switch (cert.visibility()) {
case nearby_share::mojom::Visibility::kAllContacts:
min_not_before_all_contacts =
std::min(min_not_before_all_contacts, cert.not_before());
max_not_after_all_contacts =
std::max(max_not_after_all_contacts, cert.not_after());
break;
case nearby_share::mojom::Visibility::kSelectedContacts:
min_not_before_selected_contacts =
std::min(min_not_before_selected_contacts, cert.not_before());
max_not_after_selected_contacts =
std::max(max_not_after_selected_contacts, cert.not_after());
break;
default:
NOTREACHED();
break;
}
// Verify metadata.
EXPECT_EQ(expected_metadata.SerializeAsString(),
cert.unencrypted_metadata().SerializeAsString());
}
// Verify contiguous validity periods
EXPECT_EQ(kNearbyShareNumPrivateCertificates *
kNearbyShareCertificateValidityPeriod,
max_not_after_all_contacts - min_not_before_all_contacts);
EXPECT_EQ(
kNearbyShareNumPrivateCertificates *
kNearbyShareCertificateValidityPeriod,
max_not_after_selected_contacts - min_not_before_selected_contacts);
}
void RunUpload(bool success) {
size_t initial_num_upload_calls =
local_device_data_manager_->upload_certificates_calls().size();
upload_scheduler_->InvokeRequestCallback();
EXPECT_EQ(initial_num_upload_calls + 1,
local_device_data_manager_->upload_certificates_calls().size());
EXPECT_EQ(2 * kNearbyShareNumPrivateCertificates,
local_device_data_manager_->upload_certificates_calls()
.back()
.certificates.size());
size_t initial_num_handled_results =
upload_scheduler_->handled_results().size();
std::move(
local_device_data_manager_->upload_certificates_calls().back().callback)
.Run(success);
EXPECT_EQ(initial_num_handled_results + 1,
upload_scheduler_->handled_results().size());
EXPECT_EQ(success, upload_scheduler_->handled_results().back());
}
// Test downloading public certificates with or without errors. The RPC is
// paginated, and |num_pages| will be simulated. Any failures, as indicated by
// |result|, will be simulated on the last page.
void DownloadPublicCertificatesFlow(size_t num_pages,
DownloadPublicCertificatesResult result) {
size_t prev_num_results = download_scheduler_->handled_results().size();
cert_store_->SetPublicCertificateIds(kPublicCertificateIds);
cert_manager_->Start();
download_scheduler_->InvokeRequestCallback();
cert_manager_->Stop();
size_t initial_num_notifications =
num_public_certs_downloaded_notifications_;
size_t initial_num_public_cert_exp_reschedules =
public_cert_exp_scheduler_->num_reschedule_calls();
std::string page_token;
for (size_t page_number = 0; page_number < num_pages; ++page_number) {
bool last_page = page_number == num_pages - 1;
auto& request = client_factory_.instances()
.back()
->list_public_certificates_requests()
.back();
CheckRpcRequest(request.request, page_token);
if (last_page) {
if (result == DownloadPublicCertificatesResult::kTimeout) {
FastForward(kListPublicCertificatesTimeout);
break;
} else if (result == DownloadPublicCertificatesResult::kHttpError) {
std::move(request.error_callback)
.Run(NearbyShareHttpError::kResponseMalformed);
break;
}
}
page_token = last_page
? std::string()
: kPageTokenPrefix + base::NumberToString(page_number);
std::move(request.callback)
.Run(BuildRpcResponse(page_number, page_token));
auto& add_cert_call = cert_store_->add_public_certificates_calls().back();
CheckStorageAddCertificates(add_cert_call);
std::move(add_cert_call.callback)
.Run(/*success=*/!last_page ||
result != DownloadPublicCertificatesResult::kStorageError);
}
ASSERT_EQ(download_scheduler_->handled_results().size(),
prev_num_results + 1);
bool success = result == DownloadPublicCertificatesResult::kSuccess;
EXPECT_EQ(download_scheduler_->handled_results().back(), success);
EXPECT_EQ(initial_num_notifications + (success ? 1u : 0u),
num_public_certs_downloaded_notifications_);
EXPECT_EQ(initial_num_public_cert_exp_reschedules + (success ? 1u : 0u),
public_cert_exp_scheduler_->num_reschedule_calls());
}
void CheckRpcRequest(
const nearbyshare::proto::ListPublicCertificatesRequest& request,
const std::string& page_token) {
EXPECT_EQ(request.parent(), std::string(kDeviceIdPrefix) + kDeviceId);
ASSERT_EQ(request.secret_ids_size(),
static_cast<int>(kPublicCertificateIds.size()));
for (size_t i = 0; i < kPublicCertificateIds.size(); ++i) {
EXPECT_EQ(request.secret_ids(i), kPublicCertificateIds[i]);
}
EXPECT_EQ(request.page_token(), page_token);
}
nearbyshare::proto::ListPublicCertificatesResponse BuildRpcResponse(
size_t page_number,
const std::string& page_token) {
nearbyshare::proto::ListPublicCertificatesResponse response;
for (size_t i = 0; i < public_certificates_.size(); ++i) {
public_certificates_[i].set_secret_id(kSecretIdPrefix +
base::NumberToString(page_number) +
"_" + base::NumberToString(i));
response.add_public_certificates();
*response.mutable_public_certificates(i) = public_certificates_[i];
}
response.set_next_page_token(page_token);
return response;
}
void CheckStorageAddCertificates(
const FakeNearbyShareCertificateStorage::AddPublicCertificatesCall&
add_cert_call) {
ASSERT_EQ(add_cert_call.public_certificates.size(),
public_certificates_.size());
for (size_t i = 0; i < public_certificates_.size(); ++i) {
EXPECT_EQ(add_cert_call.public_certificates[i].secret_id(),
public_certificates_[i].secret_id());
}
}
void PopulatePrivateCertificates() {
private_certificates_.clear();
const auto& metadata = GetNearbyShareTestMetadata();
for (auto visibility :
{nearby_share::mojom::Visibility::kAllContacts,
nearby_share::mojom::Visibility::kSelectedContacts}) {
private_certificates_.emplace_back(visibility, t0, metadata);
private_certificates_.emplace_back(
visibility, t0 + kNearbyShareCertificateValidityPeriod, metadata);
private_certificates_.emplace_back(
visibility, t0 + kNearbyShareCertificateValidityPeriod * 2, metadata);
}
}
void PopulatePublicCertificates() {
public_certificates_.clear();
metadata_encryption_keys_.clear();
auto& metadata1 = GetNearbyShareTestMetadata();
nearbyshare::proto::EncryptedMetadata metadata2;
metadata2.set_device_name("device_name2");
metadata2.set_full_name("full_name2");
metadata2.set_icon_url("icon_url2");
metadata2.set_bluetooth_mac_address("bluetooth_mac_address2");
for (auto metadata : {metadata1, metadata2}) {
auto private_cert = NearbySharePrivateCertificate(
nearby_share::mojom::Visibility::kAllContacts, t0, metadata);
public_certificates_.push_back(*private_cert.ToPublicCertificate());
metadata_encryption_keys_.push_back(*private_cert.EncryptMetadataKey());
}
}
FakeNearbyShareCertificateStorage* cert_store_;
FakeNearbyShareScheduler* private_cert_exp_scheduler_;
FakeNearbyShareScheduler* public_cert_exp_scheduler_;
FakeNearbyShareScheduler* upload_scheduler_;
FakeNearbyShareScheduler* download_scheduler_;
std::string bluetooth_mac_address_ = kTestUnparsedBluetoothMacAddress;
scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>> mock_adapter_;
size_t num_public_certs_downloaded_notifications_ = 0;
size_t num_private_certs_changed_notifications_ = 0;
std::vector<NearbySharePrivateCertificate> private_certificates_;
std::vector<nearbyshare::proto::PublicCertificate> public_certificates_;
std::vector<NearbyShareEncryptedMetadataKey> metadata_encryption_keys_;
base::test::SingleThreadTaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
FakeNearbyShareClientFactory client_factory_;
FakeNearbyShareSchedulerFactory scheduler_factory_;
FakeNearbyShareCertificateStorage::Factory cert_store_factory_;
std::unique_ptr<FakeNearbyShareLocalDeviceDataManager>
local_device_data_manager_;
std::unique_ptr<FakeNearbyShareContactManager> contact_manager_;
std::unique_ptr<TestingPrefServiceSimple> pref_service_;
std::unique_ptr<NearbyShareCertificateManager> cert_manager_;
};
TEST_F(NearbyShareCertificateManagerImplTest, GetValidPrivateCertificate) {
cert_store_->ReplacePrivateCertificates(private_certificates_);
FastForward(kNearbyShareCertificateValidityPeriod * 1.5);
auto cert = cert_manager_->GetValidPrivateCertificate(
nearby_share::mojom::Visibility::kAllContacts);
EXPECT_EQ(nearby_share::mojom::Visibility::kAllContacts, cert.visibility());
EXPECT_LE(cert.not_before(), Now());
EXPECT_LT(Now(), cert.not_after());
}
TEST_F(NearbyShareCertificateManagerImplTest,
GetDecryptedPublicCertificateSuccess) {
base::Optional<NearbyShareDecryptedPublicCertificate> decrypted_pub_cert;
cert_manager_->GetDecryptedPublicCertificate(
metadata_encryption_keys_[0],
base::BindOnce(&CaptureDecryptedPublicCertificateCallback,
&decrypted_pub_cert));
GetPublicCertificatesCallback(true, public_certificates_);
ASSERT_TRUE(decrypted_pub_cert);
std::vector<uint8_t> id(public_certificates_[0].secret_id().begin(),
public_certificates_[0].secret_id().end());
EXPECT_EQ(decrypted_pub_cert->id(), id);
EXPECT_EQ(decrypted_pub_cert->unencrypted_metadata().SerializeAsString(),
GetNearbyShareTestMetadata().SerializeAsString());
}
TEST_F(NearbyShareCertificateManagerImplTest,
GetDecryptedPublicCertificateCertNotFound) {
auto private_cert = NearbySharePrivateCertificate(
nearby_share::mojom::Visibility::kAllContacts, t0,
GetNearbyShareTestMetadata());
auto metadata_key = private_cert.EncryptMetadataKey();
ASSERT_TRUE(metadata_key);
base::Optional<NearbyShareDecryptedPublicCertificate> decrypted_pub_cert;
cert_manager_->GetDecryptedPublicCertificate(
*metadata_key, base::BindOnce(&CaptureDecryptedPublicCertificateCallback,
&decrypted_pub_cert));
GetPublicCertificatesCallback(true, public_certificates_);
EXPECT_FALSE(decrypted_pub_cert);
}
TEST_F(NearbyShareCertificateManagerImplTest,
GetDecryptedPublicCertificateGetPublicCertificatesFailure) {
base::Optional<NearbyShareDecryptedPublicCertificate> decrypted_pub_cert;
cert_manager_->GetDecryptedPublicCertificate(
metadata_encryption_keys_[0],
base::BindOnce(&CaptureDecryptedPublicCertificateCallback,
&decrypted_pub_cert));
GetPublicCertificatesCallback(false, {});
EXPECT_FALSE(decrypted_pub_cert);
}
TEST_F(NearbyShareCertificateManagerImplTest,
DownloadPublicCertificatesImmediateRequest) {
size_t prev_num_requests = download_scheduler_->num_immediate_requests();
cert_manager_->DownloadPublicCertificates();
EXPECT_EQ(download_scheduler_->num_immediate_requests(),
prev_num_requests + 1);
}
TEST_F(NearbyShareCertificateManagerImplTest,
DownloadPublicCertificatesSuccess) {
DownloadPublicCertificatesFlow(/*num_pages=*/2,
DownloadPublicCertificatesResult::kSuccess);
}
TEST_F(NearbyShareCertificateManagerImplTest,
DownloadPublicCertificatesTimeout) {
DownloadPublicCertificatesFlow(/*num_pages=*/2,
DownloadPublicCertificatesResult::kTimeout);
}
TEST_F(NearbyShareCertificateManagerImplTest,
DownloadPublicCertificatesRPCFailure) {
DownloadPublicCertificatesFlow(/*num_pages=*/2,
DownloadPublicCertificatesResult::kHttpError);
}
TEST_F(NearbyShareCertificateManagerImplTest,
DownloadPublicCertificatesStoreFailure) {
DownloadPublicCertificatesFlow(
/*num_pages=*/2, DownloadPublicCertificatesResult::kStorageError);
}
TEST_F(NearbyShareCertificateManagerImplTest,
RefreshPrivateCertificates_ValidCertificates) {
cert_store_->ReplacePrivateCertificates(private_certificates_);
cert_manager_->Start();
HandlePrivateCertificateRefresh(/*expect_private_cert_refresh=*/false,
/*expected_success=*/true);
VerifyPrivateCertificates(/*expected_metadata=*/GetNearbyShareTestMetadata());
}
TEST_F(NearbyShareCertificateManagerImplTest,
RefreshPrivateCertificates_NoCertificates_UploadSuccess) {
cert_store_->ReplacePrivateCertificates(
std::vector<NearbySharePrivateCertificate>());
cert_manager_->Start();
HandlePrivateCertificateRefresh(/*expect_private_cert_refresh=*/true,
/*expected_success=*/true);
RunUpload(/*success=*/true);
VerifyPrivateCertificates(/*expected_metadata=*/GetNearbyShareTestMetadata());
}
TEST_F(NearbyShareCertificateManagerImplTest,
RefreshPrivateCertificates_NoCertificates_UploadFailure) {
cert_store_->ReplacePrivateCertificates(
std::vector<NearbySharePrivateCertificate>());
cert_manager_->Start();
HandlePrivateCertificateRefresh(/*expect_private_cert_refresh=*/true,
/*expected_success=*/true);
RunUpload(/*success=*/false);
VerifyPrivateCertificates(/*expected_metadata=*/GetNearbyShareTestMetadata());
}
TEST_F(NearbyShareCertificateManagerImplTest,
RevokePrivateCertificates_OnAllowlistChanged) {
cert_manager_->Start();
// Destroy and recreate private certificates if contacts were removed from the
// user's list of selected contacts.
size_t num_expected_calls = 0;
for (bool were_contacts_added_to_allowlist : {true, false}) {
for (bool were_contacts_removed_from_allowlist : {true, false}) {
contact_manager_->NotifyAllowlistChanged(
were_contacts_added_to_allowlist,
were_contacts_removed_from_allowlist);
if (were_contacts_removed_from_allowlist) {
++num_expected_calls;
EXPECT_TRUE(cert_store_->GetPrivateCertificates()->empty());
}
EXPECT_EQ(num_expected_calls,
private_cert_exp_scheduler_->num_immediate_requests());
}
}
}
TEST_F(NearbyShareCertificateManagerImplTest,
RevokePrivateCertificates_OnContactsUploaded) {
cert_manager_->Start();
// Destroy and recreate private certificates if the user's contact list has
// changed since the last upload.
size_t num_expected_calls = 0;
for (bool did_contacts_change_since_last_upload : {true, false}) {
contact_manager_->NotifyContactsUploaded(
did_contacts_change_since_last_upload);
if (did_contacts_change_since_last_upload) {
++num_expected_calls;
EXPECT_TRUE(cert_store_->GetPrivateCertificates()->empty());
}
EXPECT_EQ(num_expected_calls,
private_cert_exp_scheduler_->num_immediate_requests());
}
}
TEST_F(NearbyShareCertificateManagerImplTest,
RefreshPrivateCertificates_OnLocalDeviceMetadataChanged) {
cert_manager_->Start();
// Destroy and recreate private certificates if any metadata fields change.
size_t num_expected_calls = 0;
for (bool did_device_name_change : {true, false}) {
for (bool did_full_name_change : {true, false}) {
for (bool did_icon_url_change : {true, false}) {
local_device_data_manager_->NotifyLocalDeviceDataChanged(
did_device_name_change, did_full_name_change, did_icon_url_change);
if (did_device_name_change || did_full_name_change ||
did_icon_url_change) {
++num_expected_calls;
EXPECT_TRUE(cert_store_->GetPrivateCertificates()->empty());
}
EXPECT_EQ(num_expected_calls,
private_cert_exp_scheduler_->num_immediate_requests());
}
}
}
}
TEST_F(NearbyShareCertificateManagerImplTest,
RefreshPrivateCertificates_ExpiredCertificate) {
// First certificates are expired;
FastForward(kNearbyShareCertificateValidityPeriod * 1.5);
cert_store_->ReplacePrivateCertificates(private_certificates_);
cert_manager_->Start();
HandlePrivateCertificateRefresh(/*expect_private_cert_refresh=*/true,
/*expected_success=*/true);
RunUpload(/*success=*/true);
VerifyPrivateCertificates(/*expected_metadata=*/GetNearbyShareTestMetadata());
}
TEST_F(NearbyShareCertificateManagerImplTest,
RefreshPrivateCertificates_InvalidDeviceName) {
cert_store_->ReplacePrivateCertificates(
std::vector<NearbySharePrivateCertificate>());
// Device name is missing in local device data manager.
local_device_data_manager_->SetDeviceName(std::string());
cert_manager_->Start();
// Expect failure because a device name is required.
HandlePrivateCertificateRefresh(/*expect_private_cert_refresh=*/true,
/*expected_success=*/false);
}
TEST_F(NearbyShareCertificateManagerImplTest,
RefreshPrivateCertificates_InvalidBluetoothMacAddress) {
cert_store_->ReplacePrivateCertificates(
std::vector<NearbySharePrivateCertificate>());
// The bluetooth adapter returns an invalid Bluetooth MAC address.
SetBluetoothMacAddress("invalid_mac_address");
cert_manager_->Start();
HandlePrivateCertificateRefresh(/*expect_private_cert_refresh=*/true,
/*expected_success=*/true);
RunUpload(/*success=*/true);
// The MAC address is not set.
nearbyshare::proto::EncryptedMetadata metadata = GetNearbyShareTestMetadata();
metadata.clear_bluetooth_mac_address();
VerifyPrivateCertificates(/*expected_metadata=*/metadata);
}
TEST_F(NearbyShareCertificateManagerImplTest,
RefreshPrivateCertificates_MissingFullNameAndIconUrl) {
cert_store_->ReplacePrivateCertificates(
std::vector<NearbySharePrivateCertificate>());
// Full name and icon URL are missing in local device data manager.
local_device_data_manager_->SetFullName(base::nullopt);
local_device_data_manager_->SetIconUrl(base::nullopt);
cert_manager_->Start();
HandlePrivateCertificateRefresh(/*expect_private_cert_refresh=*/true,
/*expected_success=*/true);
RunUpload(/*success=*/true);
// The full name and icon URL are not set.
nearbyshare::proto::EncryptedMetadata metadata = GetNearbyShareTestMetadata();
metadata.clear_full_name();
metadata.clear_icon_url();
VerifyPrivateCertificates(/*expected_metadata=*/metadata);
}
TEST_F(NearbyShareCertificateManagerImplTest,
RemoveExpiredPublicCertificates_Success) {
cert_manager_->Start();
// The public certificate expiration scheduler notifies the certificate
// manager that a public certificate has expired.
EXPECT_EQ(0u, cert_store_->remove_expired_public_certificates_calls().size());
public_cert_exp_scheduler_->InvokeRequestCallback();
EXPECT_EQ(1u, cert_store_->remove_expired_public_certificates_calls().size());
EXPECT_EQ(t0,
cert_store_->remove_expired_public_certificates_calls().back().now);
EXPECT_EQ(0u, public_cert_exp_scheduler_->handled_results().size());
std::move(
cert_store_->remove_expired_public_certificates_calls().back().callback)
.Run(/*success=*/true);
EXPECT_EQ(1u, public_cert_exp_scheduler_->handled_results().size());
EXPECT_TRUE(public_cert_exp_scheduler_->handled_results().back());
}
TEST_F(NearbyShareCertificateManagerImplTest,
RemoveExpiredPublicCertificates_Failue) {
cert_manager_->Start();
// The public certificate expiration scheduler notifies the certificate
// manager that a public certificate has expired.
EXPECT_EQ(0u, cert_store_->remove_expired_public_certificates_calls().size());
public_cert_exp_scheduler_->InvokeRequestCallback();
EXPECT_EQ(1u, cert_store_->remove_expired_public_certificates_calls().size());
EXPECT_EQ(t0,
cert_store_->remove_expired_public_certificates_calls().back().now);
EXPECT_EQ(0u, public_cert_exp_scheduler_->handled_results().size());
std::move(
cert_store_->remove_expired_public_certificates_calls().back().callback)
.Run(/*success=*/false);
EXPECT_EQ(1u, public_cert_exp_scheduler_->handled_results().size());
EXPECT_FALSE(public_cert_exp_scheduler_->handled_results().back());
}