Added a few edge case unittests for InvalidateEntry(). am: 1e5e221909 am: 51f5315a62 am: 41ed193982
Change-Id: I10f31db405bf622ee6b7c4fc82790b3190f57c1d
This commit is contained in:
@@ -132,7 +132,6 @@ bool RetrieveUsageInfoLicense(DeviceFiles* device_files,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
UsageTableHeader::UsageTableHeader()
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user