Files
nearby/presence/implementation/credential_manager_impl_test.cc
T
2024-03-15 10:57:58 -07:00

673 lines
28 KiB
C++

// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "presence/implementation/credential_manager_impl.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "net/proto2/contrib/parse_proto/testing.h"
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "internal/platform/count_down_latch.h"
#include "internal/platform/credential_storage_impl.h"
#include "internal/platform/implementation/credential_callbacks.h"
#include "internal/platform/implementation/crypto.h"
#include "internal/platform/logging.h"
#include "internal/platform/medium_environment.h"
#include "internal/proto/credential.pb.h"
#include "presence/implementation/base_broadcast_request.h"
namespace nearby {
namespace presence {
namespace {
using ::nearby::CountDownLatch;
using ::nearby::Crypto;
using ::nearby::MediumEnvironment;
using ::nearby::internal::IdentityType;
using ::nearby::internal::LocalCredential;
using ::nearby::internal::DeviceIdentityMetaData;
using ::nearby::internal::SharedCredential;
using ::nearby::internal::IdentityType::IDENTITY_TYPE_PRIVATE;
using ::nearby::internal::IdentityType::IDENTITY_TYPE_TRUSTED;
using ::protobuf_matchers::EqualsProto;
using ::testing::UnorderedPointwise;
using ::testing::status::StatusIs;
constexpr absl::string_view kManagerAppId = "TEST_MANAGER_APP";
constexpr absl::string_view kAccountName = "";
constexpr int kExpectedPresenceCredentialListSize = 6;
constexpr int kExpectedPresenceCredentialValidDays = 5;
DeviceIdentityMetaData CreateTestDeviceIdentityMetaData() {
DeviceIdentityMetaData device_identity_metadata;
device_identity_metadata.set_device_type(
internal::DeviceType::DEVICE_TYPE_PHONE);
device_identity_metadata.set_device_name("NP test device");
device_identity_metadata.set_bluetooth_mac_address("FF:FF:FF:FF:FF:FF");
device_identity_metadata.set_device_id("\x12\xab\xcd");
return device_identity_metadata;
}
CredentialSelector BuildDefaultCredentialSelector() {
CredentialSelector credential_selector;
credential_selector.manager_app_id = std::string(kManagerAppId);
credential_selector.account_name = std::string(kAccountName);
credential_selector.identity_type = IDENTITY_TYPE_PRIVATE;
return credential_selector;
}
class CredentialManagerImplTest : public ::testing::Test {
public:
class MockCredentialStorage : public nearby::CredentialStorageImpl {
public:
MOCK_METHOD(void, SaveCredentials,
(absl::string_view manager_app_id,
absl::string_view account_name,
const std::vector<LocalCredential>& private_credentials,
const std::vector<SharedCredential>& public_credentials,
PublicCredentialType public_credential_type,
SaveCredentialsResultCallback callback),
(override));
MOCK_METHOD(
void, GetPublicCredentials,
(const ::nearby::presence::CredentialSelector& credential_selector,
::nearby::presence::PublicCredentialType public_credential_type,
::nearby::presence::GetPublicCredentialsResultCallback callback),
(override));
};
class MockCredentialManager : public CredentialManagerImpl {
public:
explicit MockCredentialManager(SingleThreadExecutor* executor)
: CredentialManagerImpl(executor) {}
MOCK_METHOD(std::string, EncryptDeviceIdentityMetaData,
(absl::string_view metadata_encryption_key,
absl::string_view key_seed, absl::string_view metadata_string),
(override));
};
~CredentialManagerImplTest() override { executor_.Shutdown(); }
// Waits for active tasks in the background thread to complete.
void Fence() {
// A runnable on medium environment thread can add a task on "our" executor,
// and vice-versa. We need to wait for tasks on both threads in a loop a few
// times to make sure that all tasks have finished.
for (int i = 0; i < 3; i++) {
MediumEnvironment::Instance().Sync();
CountDownLatch latch(1);
executor_.Execute([&]() { latch.CountDown(); });
latch.Await();
}
}
void AddLocalIdentity(absl::string_view manager_app_id,
absl::string_view account_name,
IdentityType identity_type) {
auto public_credentials = GenerateCredentialsSync(
CreateTestDeviceIdentityMetaData(), manager_app_id, {identity_type},
/*credential_life_cycle_days=*/kExpectedPresenceCredentialValidDays,
/*contiguous_copy_of_credentials=*/1);
EXPECT_OK(public_credentials);
}
absl::StatusOr<std::vector<SharedCredential>> GenerateCredentialsSync(
const DeviceIdentityMetaData& device_identity_metadata,
absl::string_view manager_app_id,
const std::vector<IdentityType>& identity_types,
int credential_life_cycle_days, int contiguous_copy_of_credentials) {
absl::StatusOr<std::vector<SharedCredential>> public_credentials;
CountDownLatch latch(1);
credential_manager_.GenerateCredentials(
device_identity_metadata, manager_app_id, identity_types,
credential_life_cycle_days, contiguous_copy_of_credentials,
{.credentials_generated_cb =
[&](absl::StatusOr<std::vector<SharedCredential>> credentials) {
public_credentials = credentials;
latch.CountDown();
}});
EXPECT_TRUE(latch.Await().Ok());
return public_credentials;
}
std::vector<LocalCredential> GetLocalCredentialsSync(
CredentialSelector credential_selector) {
auto private_credentials = credential_manager_.GetLocalCredentialsSync(
credential_selector, absl::Seconds(1));
EXPECT_TRUE(private_credentials.ok());
return private_credentials.GetResult();
}
std::vector<SharedCredential> GetPublicCredentialsSync(
CredentialSelector credential_selector,
PublicCredentialType public_credential_type) {
auto public_credentials = credential_manager_.GetPublicCredentialsSync(
credential_selector, public_credential_type, absl::Seconds(1));
EXPECT_TRUE(public_credentials.ok());
return public_credentials.GetResult();
}
protected:
SingleThreadExecutor executor_;
CredentialManagerImpl credential_manager_{&executor_};
MockCredentialManager mock_credential_manager_{&executor_};
};
TEST_F(CredentialManagerImplTest, CreateOneCredentialSuccessfully) {
auto device_identity_metadata = CreateTestDeviceIdentityMetaData();
constexpr absl::Time kStartTime = absl::FromUnixSeconds(100000);
constexpr absl::Time kEndTime = absl::FromUnixSeconds(200000);
auto credentials = credential_manager_.CreateLocalCredential(
device_identity_metadata, IDENTITY_TYPE_PRIVATE, kStartTime, kEndTime);
LocalCredential private_credential = credentials.first;
// Verify the private credential.
EXPECT_EQ(private_credential.identity_type(), IDENTITY_TYPE_PRIVATE);
EXPECT_FALSE(private_credential.secret_id().empty());
EXPECT_EQ(private_credential.start_time_millis(),
absl::ToUnixMillis(kStartTime));
EXPECT_EQ(private_credential.end_time_millis(), absl::ToUnixMillis(kEndTime));
EXPECT_EQ(private_credential.key_seed().size(),
CredentialManagerImpl::kAuthenticityKeyByteSize);
EXPECT_FALSE(private_credential.connection_signing_key().key().empty());
EXPECT_EQ(private_credential.metadata_encryption_key_v0().size(),
kBaseMetadataSize);
SharedCredential public_credential = credentials.second;
// Verify the public credential.
EXPECT_EQ(public_credential.identity_type(), IDENTITY_TYPE_PRIVATE);
EXPECT_FALSE(public_credential.secret_id().empty());
EXPECT_EQ(private_credential.key_seed(), public_credential.key_seed());
EXPECT_LE(public_credential.start_time_millis(),
absl::ToUnixMillis(kStartTime));
EXPECT_GE(public_credential.start_time_millis(),
absl::ToUnixMillis(kStartTime - absl::Hours(3)));
EXPECT_GE(public_credential.end_time_millis(), absl::ToUnixMillis(kEndTime));
EXPECT_LE(public_credential.end_time_millis(),
absl::ToUnixMillis(kEndTime + absl::Hours(3)));
EXPECT_EQ(Crypto::Sha256(private_credential.metadata_encryption_key_v0())
.AsStringView(),
public_credential.metadata_encryption_key_tag_v0());
EXPECT_FALSE(
public_credential.connection_signature_verification_key().empty());
EXPECT_FALSE(public_credential.encrypted_metadata_bytes_v0().empty());
auto decrypted_metadata = credential_manager_.DecryptDeviceIdentityMetaData(
private_credential.metadata_encryption_key_v0(),
public_credential.key_seed(),
public_credential.encrypted_metadata_bytes_v0());
EXPECT_EQ(device_identity_metadata.SerializeAsString(), decrypted_metadata);
}
TEST_F(CredentialManagerImplTest, GenerateCredentialsSuccessfully) {
auto device_identity_metadata = CreateTestDeviceIdentityMetaData();
std::vector<IdentityType> identityTypes{IDENTITY_TYPE_PRIVATE};
absl::Time previous_start_time;
absl::Time previous_end_time;
auto public_credentials = GenerateCredentialsSync(
device_identity_metadata, kManagerAppId, identityTypes,
kExpectedPresenceCredentialValidDays,
kExpectedPresenceCredentialListSize);
EXPECT_OK(public_credentials);
EXPECT_EQ(public_credentials->size(), kExpectedPresenceCredentialListSize);
for (int i = 0; i < kExpectedPresenceCredentialListSize; i++) {
SharedCredential& public_credential = public_credentials->at(i);
EXPECT_EQ(public_credential.identity_type(), IDENTITY_TYPE_PRIVATE);
EXPECT_FALSE(public_credential.secret_id().empty());
absl::Time start_time_millis =
absl::FromUnixMillis(public_credential.start_time_millis());
absl::Time end_time_millis =
absl::FromUnixMillis(public_credential.end_time_millis());
if (i > 0) {
EXPECT_GT(start_time_millis, previous_start_time);
EXPECT_GE(previous_end_time, start_time_millis);
EXPECT_GT(end_time_millis, previous_end_time);
}
EXPECT_LT(start_time_millis +
absl::Hours(24) * kExpectedPresenceCredentialValidDays,
end_time_millis);
EXPECT_FALSE(public_credential.encrypted_metadata_bytes_v0().empty());
previous_start_time = start_time_millis;
previous_end_time = end_time_millis;
}
}
TEST_F(CredentialManagerImplTest,
SubscribeCallsCallbackWithExistingCredentials) {
absl::StatusOr<std::vector<SharedCredential>> public_credentials1;
absl::StatusOr<std::vector<SharedCredential>> public_credentials2;
AddLocalIdentity(kManagerAppId, kAccountName, IDENTITY_TYPE_PRIVATE);
SubscriberId id1 = credential_manager_.SubscribeForPublicCredentials(
CredentialSelector{.manager_app_id = std::string(kManagerAppId),
.account_name = std::string(kAccountName),
.identity_type = IDENTITY_TYPE_PRIVATE},
PublicCredentialType::kLocalPublicCredential,
{.credentials_fetched_cb =
[&](absl::StatusOr<std::vector<SharedCredential>> credentials) {
public_credentials1 = std::move(credentials);
}});
SubscriberId id2 = credential_manager_.SubscribeForPublicCredentials(
CredentialSelector{.manager_app_id = std::string(kManagerAppId),
.account_name = std::string(kAccountName),
.identity_type = IDENTITY_TYPE_PRIVATE},
PublicCredentialType::kLocalPublicCredential,
{.credentials_fetched_cb =
[&](absl::StatusOr<std::vector<SharedCredential>> credentials) {
public_credentials2 = std::move(credentials);
}});
Fence();
EXPECT_OK(public_credentials1);
EXPECT_OK(public_credentials2);
EXPECT_EQ(public_credentials1->size(), kExpectedPresenceCredentialListSize);
EXPECT_EQ(public_credentials2->size(), kExpectedPresenceCredentialListSize);
// Cleanup
credential_manager_.UnsubscribeFromPublicCredentials(id1);
credential_manager_.UnsubscribeFromPublicCredentials(id2);
Fence();
}
TEST_F(CredentialManagerImplTest,
SubscribeCallsCallbackWithUpdatedCredentials) {
absl::StatusOr<std::vector<SharedCredential>> public_credentials;
SubscriberId id = credential_manager_.SubscribeForPublicCredentials(
CredentialSelector{.manager_app_id = std::string(kManagerAppId),
.account_name = std::string(kAccountName),
.identity_type = IDENTITY_TYPE_PRIVATE},
PublicCredentialType::kLocalPublicCredential,
{.credentials_fetched_cb =
[&](absl::StatusOr<std::vector<SharedCredential>> credentials) {
public_credentials = std::move(credentials);
}});
Fence();
EXPECT_THAT(public_credentials, StatusIs(absl::StatusCode::kUnknown));
AddLocalIdentity(kManagerAppId, kAccountName, IDENTITY_TYPE_PRIVATE);
Fence();
ASSERT_OK(public_credentials);
EXPECT_EQ(public_credentials->size(), kExpectedPresenceCredentialListSize);
// Cleanup
credential_manager_.UnsubscribeFromPublicCredentials(id);
Fence();
}
TEST_F(CredentialManagerImplTest, NoCallbacksAfterUnsubscribe) {
absl::StatusOr<std::vector<SharedCredential>> public_credentials;
SubscriberId id = credential_manager_.SubscribeForPublicCredentials(
CredentialSelector{.manager_app_id = std::string(kManagerAppId),
.account_name = std::string(kAccountName),
.identity_type = IDENTITY_TYPE_PRIVATE},
PublicCredentialType::kLocalPublicCredential,
{.credentials_fetched_cb =
[&](absl::StatusOr<std::vector<SharedCredential>> credentials) {
public_credentials = std::move(credentials);
}});
credential_manager_.UnsubscribeFromPublicCredentials(id);
AddLocalIdentity(kManagerAppId, kAccountName, IDENTITY_TYPE_PRIVATE);
Fence();
EXPECT_THAT(public_credentials, StatusIs(absl::StatusCode::kUnknown));
}
TEST_F(CredentialManagerImplTest,
GenerateCredentialsSuccessfullyButStoreFailed) {
auto device_identity_metadata = CreateTestDeviceIdentityMetaData();
auto credential_storage_ptr =
std::make_unique<CredentialManagerImplTest::MockCredentialStorage>();
EXPECT_CALL(*credential_storage_ptr, SaveCredentials)
.WillOnce(::testing::Invoke(
[](absl::string_view manager_app_id, absl::string_view account_name,
const std::vector<LocalCredential>& private_credentials,
const std::vector<SharedCredential>& public_credentials,
PublicCredentialType public_credential_type,
SaveCredentialsResultCallback callback) {
callback.credentials_saved_cb(
absl::FailedPreconditionError("Expected failure"));
}));
credential_manager_ =
CredentialManagerImpl(&executor_, std::move(credential_storage_ptr));
std::vector<IdentityType> identityTypes{IDENTITY_TYPE_PRIVATE};
auto public_credentials = GenerateCredentialsSync(
device_identity_metadata, kManagerAppId, identityTypes,
kExpectedPresenceCredentialValidDays,
kExpectedPresenceCredentialListSize);
EXPECT_THAT(public_credentials,
StatusIs(absl::StatusCode::kFailedPrecondition));
}
TEST_F(CredentialManagerImplTest, UpdateRemotePublicCredentialsSuccessfully) {
SharedCredential public_credential_for_test;
public_credential_for_test.set_identity_type(
IdentityType::IDENTITY_TYPE_TRUSTED);
std::vector<SharedCredential> public_credentials{
{public_credential_for_test}};
nearby::CountDownLatch updated_latch(1);
UpdateRemotePublicCredentialsCallback update_credentials_cb{
.credentials_updated_cb =
[&updated_latch](absl::Status status) {
if (status.ok()) {
updated_latch.CountDown();
}
},
};
credential_manager_.UpdateRemotePublicCredentials(
kManagerAppId, kAccountName, public_credentials,
std::move(update_credentials_cb));
EXPECT_TRUE(updated_latch.Await().Ok());
}
TEST_F(CredentialManagerImplTest,
UpdateRemotePublicCredentialsNotifiesSubscribers) {
absl::StatusOr<std::vector<SharedCredential>> subscribed_credentials;
SharedCredential public_credential_for_test;
public_credential_for_test.set_identity_type(
IdentityType::IDENTITY_TYPE_PRIVATE);
std::vector<SharedCredential> public_credentials{
{public_credential_for_test}};
nearby::CountDownLatch updated_latch(1);
UpdateRemotePublicCredentialsCallback update_credentials_cb{
.credentials_updated_cb =
[&updated_latch](absl::Status status) {
if (status.ok()) {
updated_latch.CountDown();
}
},
};
SubscriberId id1 = credential_manager_.SubscribeForPublicCredentials(
CredentialSelector{.manager_app_id = std::string(kManagerAppId),
.account_name = std::string(kAccountName),
.identity_type = internal::IDENTITY_TYPE_PRIVATE},
PublicCredentialType::kRemotePublicCredential,
{.credentials_fetched_cb =
[&](absl::StatusOr<std::vector<SharedCredential>> credentials) {
subscribed_credentials = std::move(credentials);
}});
SubscriberId id2 = credential_manager_.SubscribeForPublicCredentials(
CredentialSelector{.manager_app_id = std::string(kManagerAppId),
.account_name = std::string(kAccountName),
.identity_type = internal::IDENTITY_TYPE_TRUSTED},
PublicCredentialType::kRemotePublicCredential,
{.credentials_fetched_cb =
[&](absl::StatusOr<std::vector<SharedCredential>> credentials) {
// This callback should not be called because there are no Trusted
// credentials in this test.
GTEST_FAIL();
}});
credential_manager_.UpdateRemotePublicCredentials(
kManagerAppId, kAccountName, public_credentials,
std::move(update_credentials_cb));
EXPECT_TRUE(updated_latch.Await().Ok());
Fence();
EXPECT_OK(subscribed_credentials);
EXPECT_EQ(subscribed_credentials->size(), 1);
credential_manager_.UnsubscribeFromPublicCredentials(id1);
credential_manager_.UnsubscribeFromPublicCredentials(id2);
}
TEST_F(CredentialManagerImplTest, GetLocalCredentialsFailed) {
absl::StatusOr<std::vector<LocalCredential>> private_credentials;
CredentialSelector credential_selector = BuildDefaultCredentialSelector();
credential_manager_.GetLocalCredentials(
credential_selector,
{.credentials_fetched_cb =
[&](absl::StatusOr<std::vector<LocalCredential>> credentials) {
private_credentials = std::move(credentials);
}});
EXPECT_THAT(private_credentials, StatusIs(absl::StatusCode::kNotFound));
}
TEST_F(CredentialManagerImplTest, GetPublicCredentialsFailed) {
absl::StatusOr<std::vector<SharedCredential>> public_credentials;
CredentialSelector credential_selector = BuildDefaultCredentialSelector();
CountDownLatch latch(1);
credential_manager_.GetPublicCredentials(
credential_selector, PublicCredentialType::kLocalPublicCredential,
{.credentials_fetched_cb =
[&](absl::StatusOr<std::vector<SharedCredential>> credentials) {
public_credentials = std::move(credentials);
latch.CountDown();
}});
EXPECT_TRUE(latch.Await().Ok());
EXPECT_THAT(public_credentials, StatusIs(absl::StatusCode::kNotFound));
}
TEST_F(CredentialManagerImplTest, GetCredentialsSuccessfully) {
auto device_identity_metadata = CreateTestDeviceIdentityMetaData();
std::vector<IdentityType> identity_types{IDENTITY_TYPE_PRIVATE};
CredentialSelector credential_selector = BuildDefaultCredentialSelector();
auto public_credentials = GenerateCredentialsSync(
device_identity_metadata, kManagerAppId, identity_types,
kExpectedPresenceCredentialValidDays,
kExpectedPresenceCredentialListSize);
EXPECT_OK(public_credentials);
EXPECT_EQ(public_credentials->size(), kExpectedPresenceCredentialListSize);
auto private_credentials = GetLocalCredentialsSync(credential_selector);
EXPECT_FALSE(private_credentials.empty());
}
TEST_F(CredentialManagerImplTest, PublicCredentialsFailEncryption) {
auto device_identity_metadata = CreateTestDeviceIdentityMetaData();
absl::StatusOr<std::vector<SharedCredential>> public_credentials;
auto credential_manager_ptr =
std::make_unique<CredentialManagerImplTest::MockCredentialManager>(
&executor_);
EXPECT_CALL(*credential_manager_ptr, EncryptDeviceIdentityMetaData)
.WillOnce(::testing::Invoke(
[](absl::string_view metadata_encryption_key,
absl::string_view key_seed,
absl::string_view metadata_string) { return ""; }));
std::vector<IdentityType> identity_types{IDENTITY_TYPE_PRIVATE};
CountDownLatch latch(1);
credential_manager_ptr->GenerateCredentials(
device_identity_metadata, kManagerAppId, identity_types,
kExpectedPresenceCredentialValidDays, 1,
{.credentials_generated_cb =
[&](absl::StatusOr<std::vector<SharedCredential>> credentials) {
public_credentials = std::move(credentials);
latch.CountDown();
}});
EXPECT_TRUE(latch.Await().Ok());
EXPECT_THAT(public_credentials, StatusIs(absl::StatusCode::kInvalidArgument));
}
TEST_F(CredentialManagerImplTest, UpdateLocalCredential) {
constexpr int kSelectedCredentialId = 2;
constexpr uint16_t kSalt = 1000;
absl::Status update_status = absl::UnknownError("");
auto device_identity_metadata = CreateTestDeviceIdentityMetaData();
std::vector<IdentityType> identity_types{IDENTITY_TYPE_PRIVATE,
IDENTITY_TYPE_TRUSTED};
CredentialSelector credential_selector = BuildDefaultCredentialSelector();
auto public_credentials = GenerateCredentialsSync(
device_identity_metadata, kManagerAppId, identity_types,
kExpectedPresenceCredentialValidDays,
kExpectedPresenceCredentialListSize);
auto private_credentials = GetLocalCredentialsSync(credential_selector);
EXPECT_EQ(kExpectedPresenceCredentialListSize, private_credentials.size());
ASSERT_OK(public_credentials);
// Modify a private credential
auto credential = private_credentials.at(kSelectedCredentialId);
EXPECT_TRUE(
private_credentials.at(kSelectedCredentialId).consumed_salts().empty());
credential.mutable_consumed_salts()->insert({kSalt, true});
credential_manager_.UpdateLocalCredential(
credential_selector, credential,
{[&](absl::Status status) { update_status = status; }});
EXPECT_OK(update_status);
// Verify that the modified credential has the new field in the new
// retrieved list of credentials.
auto modified_private_credentials =
GetLocalCredentialsSync(credential_selector);
EXPECT_TRUE(modified_private_credentials.at(kSelectedCredentialId)
.consumed_salts()
.at(kSalt));
}
TEST_F(CredentialManagerImplTest, EncryptAndDecryptDeviceIdentityMetaData) {
constexpr absl::string_view kMetadataEncryptionKeyBase16 =
"6331578C6E244074111B2ED0BBDB";
constexpr absl::string_view kSeed = "123456";
auto encrypted_meta_data = credential_manager_.EncryptDeviceIdentityMetaData(
kMetadataEncryptionKeyBase16, kSeed,
CreateTestDeviceIdentityMetaData().SerializeAsString());
auto decrypted_meta_data = credential_manager_.DecryptDeviceIdentityMetaData(
kMetadataEncryptionKeyBase16, kSeed, encrypted_meta_data);
DeviceIdentityMetaData device_identity_metadata;
ASSERT_TRUE(device_identity_metadata.ParseFromString(decrypted_meta_data));
EXPECT_EQ(device_identity_metadata.device_id(), "\x12\xab\xcd");
EXPECT_EQ(device_identity_metadata.device_type(),
internal::DeviceType::DEVICE_TYPE_PHONE);
EXPECT_EQ(device_identity_metadata.device_name(), "NP test device");
EXPECT_EQ(device_identity_metadata.bluetooth_mac_address(),
"FF:FF:FF:FF:FF:FF");
}
TEST_F(CredentialManagerImplTest, RefillCredentialsInGetLocalCredentials) {
auto device_identity_metadata = CreateTestDeviceIdentityMetaData();
std::vector<IdentityType> identity_types{IDENTITY_TYPE_PRIVATE};
CredentialSelector credential_selector = BuildDefaultCredentialSelector();
auto public_credentials = GenerateCredentialsSync(
device_identity_metadata, kManagerAppId, identity_types,
kExpectedPresenceCredentialValidDays, 1);
EXPECT_OK(public_credentials);
EXPECT_EQ(1, public_credentials->size());
// only generate 1 creds, expecting GetLocal would trigger refill to
// kExpectedPresenceCredentialListSize.
auto private_credentials = GetLocalCredentialsSync(credential_selector);
EXPECT_EQ(kExpectedPresenceCredentialListSize, private_credentials.size());
}
TEST_F(CredentialManagerImplTest, RefillCredentialsInGetSharedCredentials) {
auto device_identity_metadata = CreateTestDeviceIdentityMetaData();
std::vector<IdentityType> identity_types{IDENTITY_TYPE_PRIVATE};
CredentialSelector credential_selector = BuildDefaultCredentialSelector();
auto public_credentials = GenerateCredentialsSync(
device_identity_metadata, kManagerAppId, identity_types,
kExpectedPresenceCredentialValidDays, 1);
EXPECT_OK(public_credentials);
EXPECT_EQ(1, public_credentials->size());
// Only generated 1 creds, expecting GetPublicCredentials for
// kLocalPublicCredential type would trigger refill to
// kExpectedPresenceCredentialListSize.
auto refilled_public_credentials = GetPublicCredentialsSync(
credential_selector, PublicCredentialType::kLocalPublicCredential);
EXPECT_EQ(kExpectedPresenceCredentialListSize,
refilled_public_credentials.size());
}
TEST_F(CredentialManagerImplTest, RefillExpiredCredsInGetLocal) {
auto device_identity_metadata = CreateTestDeviceIdentityMetaData();
std::vector<IdentityType> identity_types{IDENTITY_TYPE_PRIVATE};
CredentialSelector credential_selector = BuildDefaultCredentialSelector();
auto public_credentials = GenerateCredentialsSync(
device_identity_metadata, kManagerAppId, identity_types,
kExpectedPresenceCredentialValidDays,
kExpectedPresenceCredentialListSize);
ASSERT_OK(public_credentials);
EXPECT_EQ(public_credentials->size(), kExpectedPresenceCredentialListSize);
// Now generated kExpectedPresenceCredentialListSize valid creds, read out the
// local creds list, then manually update the first credential's end time to
// make it expired.
auto private_credentials = GetLocalCredentialsSync(credential_selector);
EXPECT_EQ(kExpectedPresenceCredentialListSize, private_credentials.size());
auto expiring_local_credential = private_credentials.at(0);
expiring_local_credential.set_end_time_millis(
absl::ToUnixMillis(absl::Now() - absl::Hours(1)));
CountDownLatch update_local_cred_latch(1);
credential_manager_.UpdateLocalCredential(
credential_selector, expiring_local_credential,
{
.credentials_saved_cb =
[&](absl::Status status) {
EXPECT_OK(status);
update_local_cred_latch.CountDown();
},
});
EXPECT_TRUE(update_local_cred_latch.Await().Ok());
auto refilled_private_credentials =
GetLocalCredentialsSync(credential_selector);
EXPECT_EQ(kExpectedPresenceCredentialListSize,
refilled_private_credentials.size());
// Verifying the expired one private_credentials->at(0) is pruned in the new
// list.
EXPECT_EQ(private_credentials.at(1).secret_id(),
refilled_private_credentials.at(0).secret_id());
// Verifying the new generated cred's start time is the same as previously
// existing list's last cred's end time.
EXPECT_EQ(
private_credentials.at(5).end_time_millis(),
refilled_private_credentials.at(kExpectedPresenceCredentialListSize - 1)
.start_time_millis());
}
} // namespace
} // namespace presence
} // namespace nearby