Added a few edge case unittests for InvalidateEntry(). am: 1e5e221909 am: 51f5315a62 am: 41ed193982

Change-Id: I10f31db405bf622ee6b7c4fc82790b3190f57c1d
This commit is contained in:
Alex Dale
2020-05-01 01:57:40 +00:00
committed by Automerger Merge Worker
2 changed files with 526 additions and 8 deletions

View File

@@ -132,7 +132,6 @@ bool RetrieveUsageInfoLicense(DeviceFiles* device_files,
}
return true;
}
} // namespace
UsageTableHeader::UsageTableHeader()

View File

@@ -1787,7 +1787,7 @@ TEST_F(UsageTableHeaderTest, InvalidateEntry_LastEntriesAreStorageTypeUnknown) {
.WillOnce(DoAll(SetArgPointee<0>(kYetAnotherUsageEntry),
SetArgPointee<1>(kUsageEntry), Return(NO_ERROR)));
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kYetAnotherUsageEntry, _))
.WillOnce(Return(NO_ERROR));
.WillOnce(Return(true));
EXPECT_CALL(*device_files_, StoreLicense(_, NotNull()))
.WillOnce(Return(true));
@@ -2069,7 +2069,7 @@ TEST_F(UsageTableHeaderTest,
EXPECT_CALL(*crypto_session_, LoadUsageEntry(3, kUsageEntry))
.WillOnce(Return(LOAD_USAGE_ENTRY_INVALID_SESSION));
// Excect a call to shrink table to cut off only the unknown entries
// Expect a call to shrink table to cut off only the unknown entries
// at the end of the table.
EXPECT_CALL(*crypto_session_,
ShrinkUsageTableHeader(kLevelDefault, 5, NotNull()))
@@ -2171,7 +2171,7 @@ TEST_F(
EXPECT_CALL(*crypto_session_, LoadUsageEntry(3, kUsageEntry))
.WillOnce(Return(LOAD_USAGE_ENTRY_INVALID_SESSION));
// Excect a call to shrink table to cut off only the unknown entries
// Expect a call to shrink table to cut off only the unknown entries
// at the end of the table.
EXPECT_CALL(*crypto_session_,
ShrinkUsageTableHeader(kLevelDefault, 5, NotNull()))
@@ -2588,14 +2588,11 @@ TEST_F(UsageTableHeaderTest,
// # of usage entries 7 3
TEST_F(UsageTableHeaderTest,
InvalidateEntry_LastEntriesAreSecureStopAndUnknknown) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
const CdmUsageEntryInfo usage_entry_info_array[] = {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoSecureStop1, kUsageEntryInfoSecureStop2,
kUsageEntryInfoSecureStop3, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoStorageTypeUnknown};
ToVector(usage_entry_info_vector, usage_entry_info_array,
sizeof(usage_entry_info_array));
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
const uint32_t usage_entry_number_to_be_deleted =
@@ -2684,6 +2681,528 @@ TEST_F(UsageTableHeaderTest,
EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size());
}
// Initial Test state:
// 1. Usage entry to be deleted is not last (Secure stop 1)
// 2. All other entries are invalid.
//
// Attempting to delete the entry in (1) will result in:
// a. The entry will be marked as kStorageTypeUnknown.
// b. Defrag is skipped (no calls to Move()).
// c. Usage table will be resized.
// e. Updated table will be saved.
// f. InvalidateEntry() will return NO_ERROR.
//
// Storage type Usage entries
// at start at end
// ============= ======== ======
// Storage Type Unknown 0 Deleted
// Storage Type Unknown 1 Deleted
// Storage Type Unknown 2 Deleted
// Secure stop 1 3 Deleted
// Storage Type Unknown 4 Deleted
// Storage Type Unknown 5 Deleted
// Storage Type Unknown 6 Deleted
//
// # of usage entries 7 0
TEST_F(UsageTableHeaderTest, InvalidateEntry_NoValidSessionsAfter) {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoSecureStop1,
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoStorageTypeUnknown};
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
const uint32_t usage_entry_number_to_be_deleted =
3; // kUsageEntryInfoSecureStop1
metrics::CryptoMetrics metrics;
// No calls related to defragging, just shrinking the table and save.
EXPECT_CALL(*crypto_session_,
ShrinkUsageTableHeader(kLevelDefault, 0, NotNull()))
.WillOnce(
DoAll(SetArgPointee<2>(kAnotherUsageTableHeader), Return(NO_ERROR)));
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kAnotherUsageTableHeader,
kEmptyUsageEntryInfoVector))
.WillOnce(Return(true));
EXPECT_EQ(NO_ERROR, usage_table_header_->InvalidateEntry(
usage_entry_number_to_be_deleted, true, device_files_,
&metrics));
EXPECT_TRUE(usage_table_header_->usage_entry_info().empty());
}
// 1. Usage entry to be deleted is last valid entry (Secure stop 1)
// 2. There exists an entry to be moved (Offline License 1)
// 3. OEMCrypto is at max sessions, and any attempt to open a new session
// will fail with INSUFFICIENT_CRYPTO_RESOURCES.
//
// Attempting to delete the entry in (1) will result in:
// a. The entry will be marked as kStorageTypeUnknown.
// b. Only remaining entry is selected for move (Offline license 1)
// c. Opening session for move will fail.
// d. Defrag is aborted; but shrink is still made up to last valid.
// e. Usage table will be resized.
// f. Updated table will be saved.
// g. InvalidateEntry() will return NO_ERROR.
//
// Storage type Usage entries
// at start at end
// ============= ======== ======
// Storage Type Unknown 0 0
// Offline License 1 1 1
// Secure Stop 1 2 Deleted
// Storage Type Unknown 3 Deleted
//
// # of usage entries 4 2
TEST_F(UsageTableHeaderTest, InvalidateEntry_MaxSessionReached) {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense1,
kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown};
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
const uint32_t usage_entry_number_to_be_deleted =
2; // kUsageEntryInfoSecureStop1
metrics::CryptoMetrics metrics;
// Expected calls for moving offline license 1 (position 1) to position 0.
// But will fail when opening a crypto session.
const DeviceFiles::CdmLicenseData offline_license_1_data{
kUsageEntryInfoOfflineLicense1.key_set_id,
kActiveLicenseState,
kPsshData,
kKeyRequest,
kKeyResponse,
kKeyRenewalRequest,
kKeyRenewalResponse,
kReleaseServerUrl,
kPlaybackStartTime,
kPlaybackStartTime + kPlaybackDuration,
kGracePeriodEndTime,
kEmptyAppParameters,
kUsageEntry,
static_cast<uint32_t>(1)};
EXPECT_CALL(*device_files_,
RetrieveLicense(kUsageEntryInfoOfflineLicense1.key_set_id,
NotNull(), NotNull()))
.WillOnce(DoAll(SetArgPointee<1>(offline_license_1_data), Return(true)));
EXPECT_CALL(*crypto_session_, Open(kLevelDefault))
.WillRepeatedly(Return(INSUFFICIENT_CRYPTO_RESOURCES));
// Despite being unable to open session, the table should be resized to
// exclude the trailing invalid entries.
EXPECT_CALL(*crypto_session_,
ShrinkUsageTableHeader(kLevelDefault, 2, NotNull()))
.WillOnce(
DoAll(SetArgPointee<2>(kAnotherUsageTableHeader), Return(NO_ERROR)));
EXPECT_CALL(*device_files_,
StoreUsageTableInfo(kAnotherUsageTableHeader,
ElementsAre(kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoOfflineLicense1)))
.WillOnce(Return(true));
EXPECT_EQ(NO_ERROR, usage_table_header_->InvalidateEntry(
usage_entry_number_to_be_deleted, true, device_files_,
&metrics));
// Check the end state of the usage table.
constexpr size_t expected_size = 2;
EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size());
}
// 1. Usage entry to be deleted is first valid entry (Secure stop 1)
// 2. There exists an entry to be moved (Offline License 1)
// 3. OEMCrypto is at max sessions, and any attempt to open a new session
// will fail with INSUFFICIENT_CRYPTO_RESOURCES.
//
// Attempting to delete the entry in (1) will result in:
// a. The entry will be marked as kStorageTypeUnknown.
// b. Only remaining entry is selected for move (Offline license 1)
// c. Opening session for move will fail.
// d. Defrag is aborted; but shrink is still made up to last valid.
// e. Usage table will be resized.
// f. Updated table will be saved.
// g. InvalidateEntry() will return NO_ERROR.
//
// Storage type Usage entries
// at start at end
// ============= ======== ======
// Secure Stop 1 0 0 (Storage type unknown)
// Offline License 1 1 1 (Failed to move)
// Storage Type Unknown 2 Deleted
// Storage Type Unknown 3 Deleted
//
// # of usage entries 4 2
TEST_F(UsageTableHeaderTest, InvalidateEntry_FirstEntry_MaxSessionReached) {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoSecureStop1, kUsageEntryInfoOfflineLicense1,
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoStorageTypeUnknown};
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
const uint32_t usage_entry_number_to_be_deleted =
0; // kUsageEntryInfoSecureStop1
metrics::CryptoMetrics metrics;
// Expected calls for moving offline license 1 (position 1) to position 0.
// But will fail when opening a crypto session.
const DeviceFiles::CdmLicenseData offline_license_1_data{
kUsageEntryInfoOfflineLicense1.key_set_id,
kActiveLicenseState,
kPsshData,
kKeyRequest,
kKeyResponse,
kKeyRenewalRequest,
kKeyRenewalResponse,
kReleaseServerUrl,
kPlaybackStartTime,
kPlaybackStartTime + kPlaybackDuration,
kGracePeriodEndTime,
kEmptyAppParameters,
kUsageEntry,
static_cast<uint32_t>(1)};
EXPECT_CALL(*device_files_,
RetrieveLicense(kUsageEntryInfoOfflineLicense1.key_set_id,
NotNull(), NotNull()))
.WillOnce(DoAll(SetArgPointee<1>(offline_license_1_data), Return(true)));
EXPECT_CALL(*crypto_session_, Open(kLevelDefault))
.WillRepeatedly(Return(INSUFFICIENT_CRYPTO_RESOURCES));
// Despite being unable to open session, the table should be resized to
// exclude the trailing invalid entries.
EXPECT_CALL(*crypto_session_,
ShrinkUsageTableHeader(kLevelDefault, 2, NotNull()))
.WillOnce(
DoAll(SetArgPointee<2>(kAnotherUsageTableHeader), Return(NO_ERROR)));
EXPECT_CALL(*device_files_,
StoreUsageTableInfo(kAnotherUsageTableHeader,
ElementsAre(kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoOfflineLicense1)))
.WillOnce(Return(true));
EXPECT_EQ(NO_ERROR, usage_table_header_->InvalidateEntry(
usage_entry_number_to_be_deleted, true, device_files_,
&metrics));
// Check the end state of the usage table.
constexpr size_t expected_size = 2;
EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size());
}
// 1. Usage entry to be deleted is last valid entry (Secure stop 1)
// 2. There exists an entry to be moved (Offline License 1)
// 3. Moving entry will result in a system invalidation error.
//
// Attempting to delete the entry in (1) will result in:
// a. The entry will be marked as kStorageTypeUnknown.
// b. Only remaining entry is selected for move (Offline license 1)
// c. Moving entry will result in system invalidation.
// d. Defrag is aborted; no call to Shrink()
// f. Updated table will be saved.
// g. InvalidateEntry() will return SYSTEM_INVALIDATED_ERROR.
//
// Storage type Usage entries
// at start at end
// ============= ======== ======
// Storage Type Unknown 0 0
// Offline License 1 1 1
// Secure Stop 1 2 2 (Storage Type Unknown)
// Storage Type Unknown 3 3
//
// # of usage entries 4 4
TEST_F(UsageTableHeaderTest, InvalidateEntry_SystemInvalidation_OnMove) {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense1,
kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown};
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
const uint32_t usage_entry_number_to_be_deleted =
2; // kUsageEntryInfoSecureStop1
metrics::CryptoMetrics metrics;
// Expected calls for moving offline license 1 (position 1) to position 0.
// But will fail when moving.
const DeviceFiles::CdmLicenseData offline_license_1_data{
kUsageEntryInfoOfflineLicense1.key_set_id,
kActiveLicenseState,
kPsshData,
kKeyRequest,
kKeyResponse,
kKeyRenewalRequest,
kKeyRenewalResponse,
kReleaseServerUrl,
kPlaybackStartTime,
kPlaybackStartTime + kPlaybackDuration,
kGracePeriodEndTime,
kEmptyAppParameters,
kUsageEntry,
static_cast<uint32_t>(1)};
EXPECT_CALL(*device_files_,
RetrieveLicense(kUsageEntryInfoOfflineLicense1.key_set_id,
NotNull(), NotNull()))
.WillOnce(DoAll(SetArgPointee<1>(offline_license_1_data), Return(true)));
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(*crypto_session_, LoadUsageEntry(1, kUsageEntry));
EXPECT_CALL(*crypto_session_, MoveUsageEntry(0))
.WillOnce(Return(SYSTEM_INVALIDATED_ERROR));
// Defrag is aborted, and table is saved, but no call to shrink().
EXPECT_CALL(
*device_files_,
StoreUsageTableInfo(kUsageTableHeader,
ElementsAre(kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoOfflineLicense1,
kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoStorageTypeUnknown)))
.WillOnce(Return(true));
EXPECT_EQ(SYSTEM_INVALIDATED_ERROR, usage_table_header_->InvalidateEntry(
usage_entry_number_to_be_deleted,
true, device_files_, &metrics));
// Check the end state of the usage table.
constexpr size_t expected_size = 4;
EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size());
}
// 1. Usage entry to be deleted is last valid entry (Secure stop 1)
// 2. There exists an entry to be moved (Offline License 1)
// 3. Moving entry will result in a session invalidation error.
//
// Note: This is very similar to InvalidateEntry_SystemInvalidation_OnMove
// except that the error returned is not of importance to the calling
// session and is ignored (NO_ERROR returned).
//
// Attempting to delete the entry in (1) will result in:
// a. The entry will be marked as kStorageTypeUnknown.
// b. Only remaining entry is selected for move (Offline license 1)
// c. Moving entry will result in session invalidation.
// d. Defrag is aborted; no call to Shrink()
// f. Updated table will be saved.
// g. InvalidateEntry() will return NO_ERROR.
//
// Storage type Usage entries
// at start at end
// ============= ======== ======
// Storage Type Unknown 0 0
// Offline License 1 1 1
// Secure Stop 1 2 2 (Storage Type Unknown)
// Storage Type Unknown 3 3
//
// # of usage entries 4 4
TEST_F(UsageTableHeaderTest, InvalidateEntry_SessionInvalidation_OnMove) {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense1,
kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown};
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
const uint32_t usage_entry_number_to_be_deleted =
2; // kUsageEntryInfoSecureStop1
metrics::CryptoMetrics metrics;
// Expected calls for moving offline license 1 (position 1) to position 0.
// But will fail when moving.
const DeviceFiles::CdmLicenseData offline_license_1_data{
kUsageEntryInfoOfflineLicense1.key_set_id,
kActiveLicenseState,
kPsshData,
kKeyRequest,
kKeyResponse,
kKeyRenewalRequest,
kKeyRenewalResponse,
kReleaseServerUrl,
kPlaybackStartTime,
kPlaybackStartTime + kPlaybackDuration,
kGracePeriodEndTime,
kEmptyAppParameters,
kUsageEntry,
static_cast<uint32_t>(1)};
EXPECT_CALL(*device_files_,
RetrieveLicense(kUsageEntryInfoOfflineLicense1.key_set_id,
NotNull(), NotNull()))
.WillOnce(DoAll(SetArgPointee<1>(offline_license_1_data), Return(true)));
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(*crypto_session_, LoadUsageEntry(1, kUsageEntry));
EXPECT_CALL(*crypto_session_, MoveUsageEntry(0))
.WillOnce(Return(SESSION_LOST_STATE_ERROR));
// Defrag is aborted, and table is saved, but no call to shrink().
EXPECT_CALL(
*device_files_,
StoreUsageTableInfo(kUsageTableHeader,
ElementsAre(kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoOfflineLicense1,
kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoStorageTypeUnknown)))
.WillOnce(Return(true));
// The underlying error should not be returned to the caller.
EXPECT_EQ(NO_ERROR, usage_table_header_->InvalidateEntry(
usage_entry_number_to_be_deleted, true, device_files_,
&metrics));
// Check the end state of the usage table.
constexpr size_t expected_size = 4;
EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size());
}
// 1. Usage entry to be deleted is last valid entry (Secure stop 1)
// 2. There exists an entry to be moved (Offline License 1)
// 3. Shrinking table will fail due to an unspecified entry being in use.
//
// Attempting to delete the entry in (1) will result in:
// a. The entry will be marked as kStorageTypeUnknown.
// b. Only remaining entry is selected for move (Offline license 1)
// c. Entry will be moved successfully.
// d. Shrinking table fill fail with SHRINK_USAGE_TABLE_HEADER_ENTRY_IN_USE.
// f. Updated table will be saved, with trailing invalid entries.
// g. InvalidateEntry() will return NO_ERROR.
//
// Storage type Usage entries
// at start at end
// ============= ======== ======
// Storage Type Unknown 0 1 (swapped Offline License 1)
// Offline License 1 1 0 (moved)
// Secure Stop 1 2 2 (Storage Type Unknown)
// Storage Type Unknown 3 3
//
// # of usage entries 4 4
TEST_F(UsageTableHeaderTest, InvalidateEntry_ShrinkFails) {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense1,
kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown};
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
const uint32_t usage_entry_number_to_be_deleted =
2; // kUsageEntryInfoSecureStop1
metrics::CryptoMetrics metrics;
// Expected calls for moving offline license 1 (position 1) to position 0.
const DeviceFiles::CdmLicenseData offline_license_1_data{
kUsageEntryInfoOfflineLicense1.key_set_id,
kActiveLicenseState,
kPsshData,
kKeyRequest,
kKeyResponse,
kKeyRenewalRequest,
kKeyRenewalResponse,
kReleaseServerUrl,
kPlaybackStartTime,
kPlaybackStartTime + kPlaybackDuration,
kGracePeriodEndTime,
kEmptyAppParameters,
kUsageEntry,
static_cast<uint32_t>(1)};
EXPECT_CALL(*device_files_,
RetrieveLicense(kUsageEntryInfoOfflineLicense1.key_set_id,
NotNull(), NotNull()))
.Times(2) // First to get entry, then again to update.
.WillRepeatedly(
DoAll(SetArgPointee<1>(offline_license_1_data), Return(true)));
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(*crypto_session_, LoadUsageEntry(1, kUsageEntry));
EXPECT_CALL(*crypto_session_, MoveUsageEntry(0)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(*crypto_session_, UpdateUsageEntry(NotNull(), NotNull()))
.WillOnce(DoAll(SetArgPointee<0>(kAnotherUsageTableHeader),
SetArgPointee<1>(kUsageEntry), Return(NO_ERROR)));
EXPECT_CALL(
*device_files_,
StoreUsageTableInfo(kAnotherUsageTableHeader,
ElementsAre(kUsageEntryInfoOfflineLicense1,
kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoStorageTypeUnknown)))
.WillOnce(Return(true));
EXPECT_CALL(*device_files_, StoreLicense(_, NotNull()))
.WillOnce(Return(true));
// Expect a call to shrink table, but will fail due to an unspecified
// entry being in use.
EXPECT_CALL(*crypto_session_,
ShrinkUsageTableHeader(kLevelDefault, 1, NotNull()))
.WillOnce(Return(SHRINK_USAGE_TABLE_HEADER_ENTRY_IN_USE));
EXPECT_EQ(NO_ERROR, usage_table_header_->InvalidateEntry(
usage_entry_number_to_be_deleted, true, device_files_,
&metrics));
// Check the end state of the usage table.
constexpr size_t expected_size = 4;
EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size());
}
// 1. Usage entry to be deleted is last valid entry (Secure stop 1)
// 2. There exists an entry to be moved (Offline License 1)
// 3. Moving entry cannot be done as the destination is in use.
// (this is unexpected but possible in normal operation)
//
// Attempting to delete the entry in (1) will result in:
// a. The entry will be marked as kStorageTypeUnknown.
// b. Only remaining entry is selected for move (Offline license 1)
// c. Call to move will fail with MOVE_USAGE_ENTRY_DESTINATION_IN_USE.
// d. Usage table will be resized.
// e. Updated table will be saved.
// f. InvalidateEntry() will return NO_ERROR.
//
// Storage type Usage entries
// at start at end
// ============= ======== ======
// Storage Type Unknown 0 0
// Offline License 1 1 1 (unable to move)
// Secure Stop 1 2 Deleted
// Storage Type Unknown 3 Deleted
//
// # of usage entries 4 2
TEST_F(UsageTableHeaderTest, InvalidateEntry_DestinationInUse_OnMove) {
const std::vector<CdmUsageEntryInfo> usage_entry_info_vector = {
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoOfflineLicense1,
kUsageEntryInfoSecureStop1, kUsageEntryInfoStorageTypeUnknown};
Init(kSecurityLevelL1, kUsageTableHeader, usage_entry_info_vector);
const uint32_t usage_entry_number_to_be_deleted =
2; // kUsageEntryInfoSecureStop1
metrics::CryptoMetrics metrics;
// Expected calls for moving offline license 1 (position 1) to position 0.
// But will fail due to the destination being in use.
const DeviceFiles::CdmLicenseData offline_license_1_data{
kUsageEntryInfoOfflineLicense1.key_set_id,
kActiveLicenseState,
kPsshData,
kKeyRequest,
kKeyResponse,
kKeyRenewalRequest,
kKeyRenewalResponse,
kReleaseServerUrl,
kPlaybackStartTime,
kPlaybackStartTime + kPlaybackDuration,
kGracePeriodEndTime,
kEmptyAppParameters,
kUsageEntry,
static_cast<uint32_t>(1)};
EXPECT_CALL(*device_files_,
RetrieveLicense(kUsageEntryInfoOfflineLicense1.key_set_id,
NotNull(), NotNull()))
.WillOnce(DoAll(SetArgPointee<1>(offline_license_1_data), Return(true)));
EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(*crypto_session_, LoadUsageEntry(1, kUsageEntry));
EXPECT_CALL(*crypto_session_, MoveUsageEntry(0))
.WillOnce(Return(MOVE_USAGE_ENTRY_DESTINATION_IN_USE));
// No expectations for updating the entry or the header from the move
// operation.
// Shrink table down to the last valid entry.
EXPECT_CALL(*crypto_session_,
ShrinkUsageTableHeader(kLevelDefault, 2, NotNull()))
.WillOnce(DoAll(SetArgPointee<2>(kAnotherUsageEntry), Return(NO_ERROR)));
EXPECT_CALL(*device_files_,
StoreUsageTableInfo(kAnotherUsageEntry,
ElementsAre(kUsageEntryInfoStorageTypeUnknown,
kUsageEntryInfoOfflineLicense1)))
.WillOnce(Return(true));
EXPECT_EQ(NO_ERROR, usage_table_header_->InvalidateEntry(
usage_entry_number_to_be_deleted, true, device_files_,
&metrics));
// Check the end state of the usage table.
constexpr size_t expected_size = 2;
EXPECT_EQ(expected_size, usage_table_header_->usage_entry_info().size());
}
// If the crypto session says the usage table header is stale, init should fail.
TEST_F(UsageTableHeaderTest, StaleHeader) {
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;