Changed UsageTableHeader::Shrink to tolerate over shrinking.

[ Merge of http://go/wvgerrit/83804 ]

There is a private helper method in `UsageTableHeader` which is used by
other methods to shrink the table by removing a specified number of
entries.

Prior to this change, if `Shrink` was called to remove more entries
than there are, it would: 1) do nothing and 2) return `NO_ERROR`.
Obviously, at least one of those action should change.

Instead of doing nothing, it will simply remove all the entries from
the table and return `NO_ERROR`.  A warning will be logged that it was
requested to shrink by more entries than there are.

Four (4) new tests have been created to ensure that `Shrink()` works as
expected.

Test: Linux unit tests
Bug: 138242127
Change-Id: Idedd922bd883d7ae1b84ce8ec1255fdce00c0948
This commit is contained in:
Alex Dale
2019-07-31 12:06:58 -07:00
parent 0b3edf73a8
commit 79a28e5ddb
3 changed files with 83 additions and 5 deletions

View File

@@ -17,6 +17,10 @@
#include "metrics_collections.h"
#include "wv_cdm_types.h"
#if defined(UNIT_TEST)
# include <gtest/gtest_prod.h>
#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) {

View File

@@ -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<CryptoSession> 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();
}

View File

@@ -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<CdmUsageEntryInfo> 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