diff --git a/libwvdrmengine/cdm/core/include/usage_table_header.h b/libwvdrmengine/cdm/core/include/usage_table_header.h index 2a41572a..7525b302 100644 --- a/libwvdrmengine/cdm/core/include/usage_table_header.h +++ b/libwvdrmengine/cdm/core/include/usage_table_header.h @@ -17,6 +17,10 @@ #include "metrics_collections.h" #include "wv_cdm_types.h" +#if defined(UNIT_TEST) +# include +#endif + namespace wvcdm { // Offline licenses/secure stops may be securely tracked using usage @@ -133,8 +137,14 @@ class UsageTableHeader { metrics::CryptoMetrics alternate_crypto_metrics_; +#if defined(UNIT_TEST) // Test related declarations friend class UsageTableHeaderTest; + FRIEND_TEST(UsageTableHeaderTest, Shrink_NoneOfTable); + FRIEND_TEST(UsageTableHeaderTest, Shrink_PartOfTable); + FRIEND_TEST(UsageTableHeaderTest, Shrink_AllOfTable); + FRIEND_TEST(UsageTableHeaderTest, Shrink_MoreThanTable); +#endif // These setters are for testing only. Takes ownership of the pointers. void SetDeviceFiles(DeviceFiles* device_files) { diff --git a/libwvdrmengine/cdm/core/src/usage_table_header.cpp b/libwvdrmengine/cdm/core/src/usage_table_header.cpp index 3f4430bb..9233d422 100644 --- a/libwvdrmengine/cdm/core/src/usage_table_header.cpp +++ b/libwvdrmengine/cdm/core/src/usage_table_header.cpp @@ -508,10 +508,10 @@ CdmResponseType UsageTableHeader::Shrink( if (usage_entry_info_.size() < number_of_usage_entries_to_delete) { LOGW( - "UsageTableHeader::Shrink: cannot delete %d entries when usage entry " - "table size is %d", - number_of_usage_entries_to_delete, usage_entry_info_.size()); - return NO_ERROR; + "Cannot delete more entries than the table size, reducing to current " + "table size: table_size = %zu, number_to_delete = %u", + usage_entry_info_.size(), number_of_usage_entries_to_delete); + number_of_usage_entries_to_delete = usage_entry_info_.size(); } if (number_of_usage_entries_to_delete == 0) return NO_ERROR; @@ -524,7 +524,7 @@ CdmResponseType UsageTableHeader::Shrink( std::unique_ptr scoped_crypto_session; CryptoSession* crypto_session = test_crypto_session_.get(); if (crypto_session == NULL) { - scoped_crypto_session.reset((CryptoSession::MakeCryptoSession(metrics))); + scoped_crypto_session.reset(CryptoSession::MakeCryptoSession(metrics)); crypto_session = scoped_crypto_session.get(); } diff --git a/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp b/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp index e144e531..424ac36b 100644 --- a/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp +++ b/libwvdrmengine/cdm/core/test/usage_table_header_unittest.cpp @@ -2341,4 +2341,72 @@ TEST_F(UsageTableHeaderTest, StaleHeader) { EXPECT_TRUE(usage_table_header_->Init(kSecurityLevelL1, crypto_session_)); } +// Testing of the private function UsageTableHeader::Shrink. +// Don't shrink any entries. +TEST_F(UsageTableHeaderTest, Shrink_NoneOfTable) { + Init(kSecurityLevelL1, kUsageTableHeader, k10UsageEntryInfoVector); + metrics::CryptoMetrics metrics; + + // These calls are "expensive" and should be avoided if possible. + EXPECT_CALL(*crypto_session_, Open(_)).Times(0); + EXPECT_CALL(*crypto_session_, ShrinkUsageTableHeader(_, NotNull())).Times(0); + EXPECT_CALL(*device_files_, StoreUsageTableInfo(_, _)).Times(0); + + EXPECT_EQ(usage_table_header_->Shrink(&metrics, 0), NO_ERROR); +} + +// Shrink some of the table, but not all of it. +TEST_F(UsageTableHeaderTest, Shrink_PartOfTable) { + Init(kSecurityLevelL1, kUsageTableHeader, k10UsageEntryInfoVector); + const uint32_t to_shink = 5; + const std::vector shunken_entries( + k10UsageEntryInfoVector.cbegin(), + k10UsageEntryInfoVector.cend() - to_shink); + metrics::CryptoMetrics metrics; + + EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); + EXPECT_CALL(*crypto_session_, + ShrinkUsageTableHeader(shunken_entries.size(), NotNull())) + .WillOnce(Return(NO_ERROR)); + EXPECT_CALL(*device_files_, + StoreUsageTableInfo(kUsageTableHeader, shunken_entries)) + .WillOnce(Return(true)); + + EXPECT_EQ(usage_table_header_->Shrink(&metrics, to_shink), NO_ERROR); +} + +// Shrink all of the table, no entries left. +TEST_F(UsageTableHeaderTest, Shrink_AllOfTable) { + Init(kSecurityLevelL1, kUsageTableHeader, k10UsageEntryInfoVector); + metrics::CryptoMetrics metrics; + + EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); + EXPECT_CALL(*crypto_session_, ShrinkUsageTableHeader(0, NotNull())) + .WillOnce(Return(NO_ERROR)); + EXPECT_CALL(*device_files_, StoreUsageTableInfo(kUsageTableHeader, + kEmptyUsageEntryInfoVector)) + .WillOnce(Return(true)); + + EXPECT_EQ( + usage_table_header_->Shrink(&metrics, k10UsageEntryInfoVector.size()), + NO_ERROR); +} + +// Request to shrink more entries than there are in the table; should remove +// all entries, but log a warning. +TEST_F(UsageTableHeaderTest, Shrink_MoreThanTable) { + Init(kSecurityLevelL1, kUsageTableHeader, k10UsageEntryInfoVector); + metrics::CryptoMetrics metrics; + EXPECT_CALL(*crypto_session_, Open(kLevelDefault)).WillOnce(Return(NO_ERROR)); + EXPECT_CALL(*crypto_session_, ShrinkUsageTableHeader(0, NotNull())) + .WillOnce(Return(NO_ERROR)); + EXPECT_CALL(*device_files_, StoreUsageTableInfo(kUsageTableHeader, + kEmptyUsageEntryInfoVector)) + .WillOnce(Return(true)); + + EXPECT_EQ(usage_table_header_->Shrink(&metrics, + k10UsageEntryInfoVector.size() + 10), + NO_ERROR); +} + } // namespace wvcdm