From 8942f7682a239e309523bbfdf0ac05fff7456a01 Mon Sep 17 00:00:00 2001 From: Rahul Frias Date: Tue, 12 Mar 2019 11:47:10 -0700 Subject: [PATCH] Add unit tests to remove usage entries [ Merge of http://go/wvgerrit/74343 ] This replicates a Netflix test that adds secure stops and removes them one at a time, while some of the sessions are still open. Usage enties will be deleted at the time, but the usage header table will not be shrunk if the last entry is in use. This happens later when sessions are closed and the last usage entry is no longer in use. Bug: 120894148 Test: WV unit/integration tests, CE CDM tests Change-Id: Ib572950afc61754fe5f3c417e650d5d08503425a --- .../cdm/core/src/usage_table_header.cpp | 3 +- .../cdm/test/request_license_test.cpp | 112 ++++++++++++++++++ 2 files changed, 114 insertions(+), 1 deletion(-) diff --git a/libwvdrmengine/cdm/core/src/usage_table_header.cpp b/libwvdrmengine/cdm/core/src/usage_table_header.cpp index 92f4bf45..1fe88e92 100644 --- a/libwvdrmengine/cdm/core/src/usage_table_header.cpp +++ b/libwvdrmengine/cdm/core/src/usage_table_header.cpp @@ -500,7 +500,8 @@ CdmResponseType UsageTableHeader::StoreEntry(uint32_t usage_entry_number, CdmResponseType UsageTableHeader::Shrink( metrics::CryptoMetrics* metrics, uint32_t number_of_usage_entries_to_delete) { - LOGI("UsageTableHeader::Shrink: %d", number_of_usage_entries_to_delete); + LOGI("UsageTableHeader::Shrink: %d (of %d)", + number_of_usage_entries_to_delete, usage_entry_info_.size()); if (usage_entry_info_.empty()) { LOGE("UsageTableHeader::Shrink: usage entry info table unexpectedly empty"); return NO_USAGE_ENTRIES; diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index ad089154..a5efbffe 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -1632,6 +1632,28 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase { key_set_id_.size() > 0); } + bool VerifyDecryption(const CdmSessionId& session_id, + const SubSampleInfo& data) { + std::vector decrypt_buffer(data.encrypt_data.size()); + CdmDecryptionParameters decryption_parameters( + &data.key_id, &data.encrypt_data.front(), data.encrypt_data.size(), + &data.iv, data.block_offset, &decrypt_buffer[0]); + decryption_parameters.is_encrypted = data.is_encrypted; + decryption_parameters.is_secure = data.is_secure; + decryption_parameters.subsample_flags = data.subsample_flags; + CdmResponseType status = decryptor_.Decrypt(session_id, + data.validate_key_id, + decryption_parameters); + EXPECT_EQ(NO_ERROR, status); + if (status != NO_ERROR) + return false; + + bool result = std::equal(data.decrypt_data.begin(), data.decrypt_data.end(), + decrypt_buffer.begin()); + EXPECT_TRUE(result); + return result; + } + void Unprovision() { EXPECT_EQ(NO_ERROR, decryptor_.Unprovision(kSecurityLevelL1, kDefaultCdmIdentifier)); @@ -3196,6 +3218,96 @@ TEST_F(WvCdmRequestLicenseTest, UsageInfoRetryTest) { } } +TEST_F(WvCdmRequestLicenseTest, UsageInfo_ReleaseThreeRecords) { + Unprovision(); + Provision(kLevelDefault); + + CdmSecurityLevel security_level = GetDefaultSecurityLevel(); + std::string app_id = ""; + FileSystem file_system; + DeviceFiles handle(&file_system); + EXPECT_TRUE(handle.Init(security_level)); + std::vector psts; + EXPECT_TRUE(handle.DeleteAllUsageInfoForApp( + DeviceFiles::GetUsageInfoFileName(app_id), + &psts)); + + std::string session_id_clip3, session_id_clip4, session_id_clip7; + + // Open session for streaming_clip3 and verify decryption is successful + decryptor_.OpenSession(config_.key_system(), NULL, kDefaultCdmIdentifier, + NULL, &session_id_clip3); + + session_id_ = session_id_clip3; + GenerateKeyRequest(kPsshStreamingClip3, kLicenseTypeStreaming, NULL); + VerifyUsageKeyRequestResponse(config_.license_server(), + config_.client_auth()); + + EXPECT_TRUE(VerifyDecryption(session_id_clip3, + usage_info_sub_samples_icp[0])); + + // Open session for streaming_clip4 and verify decryption is successful + decryptor_.OpenSession(config_.key_system(), NULL, kDefaultCdmIdentifier, + NULL, &session_id_clip4); + + session_id_ = session_id_clip4; + GenerateKeyRequest(kPsshStreamingClip4, kLicenseTypeStreaming, NULL); + VerifyUsageKeyRequestResponse(config_.license_server(), + config_.client_auth()); + + EXPECT_TRUE(VerifyDecryption(session_id_clip4, + usage_info_sub_samples_icp[1])); + + // Open session for streaming_clip7 and verify decryption is successful + decryptor_.OpenSession(config_.key_system(), NULL, kDefaultCdmIdentifier, + NULL, &session_id_clip7); + + session_id_ = session_id_clip7; + GenerateKeyRequest(kPsshStreamingClip7, kLicenseTypeStreaming, NULL); + VerifyUsageKeyRequestResponse(config_.license_server(), + config_.client_auth()); + + EXPECT_TRUE(VerifyDecryption(session_id_clip7, + usage_info_sub_samples_icp[4])); + + // Close session for streaming_clip4 and release usage information + decryptor_.CloseSession(session_id_clip4); + + CdmUsageInfo usage_info; + CdmUsageInfoReleaseMessage release_msg; + CdmResponseType status = decryptor_.GetUsageInfo( + app_id, kProviderSessionTokenStreamingClip4, kDefaultCdmIdentifier, + &usage_info); + EXPECT_EQ(KEY_MESSAGE, status); + EXPECT_EQ(1, usage_info.size()); + release_msg = GetUsageInfoResponse(config_.license_server(), + config_.client_auth(), usage_info[0]); + EXPECT_EQ(NO_ERROR, + decryptor_.ReleaseUsageInfo(release_msg, kDefaultCdmIdentifier)); + + decryptor_.CloseSession(session_id_clip7); + + status = decryptor_.GetUsageInfo(app_id, kProviderSessionTokenStreamingClip7, + kDefaultCdmIdentifier, &usage_info); + EXPECT_EQ(KEY_MESSAGE, status); + EXPECT_EQ(1, usage_info.size()); + release_msg = GetUsageInfoResponse(config_.license_server(), + config_.client_auth(), usage_info[0]); + EXPECT_EQ(NO_ERROR, + decryptor_.ReleaseUsageInfo(release_msg, kDefaultCdmIdentifier)); + + decryptor_.CloseSession(session_id_clip3); + + status = decryptor_.GetUsageInfo(app_id, kProviderSessionTokenStreamingClip3, + kDefaultCdmIdentifier, &usage_info); + EXPECT_EQ(KEY_MESSAGE, status); + EXPECT_EQ(1, usage_info.size()); + release_msg = GetUsageInfoResponse(config_.license_server(), + config_.client_auth(), usage_info[0]); + EXPECT_EQ(NO_ERROR, + decryptor_.ReleaseUsageInfo(release_msg, kDefaultCdmIdentifier)); +} + class WvCdmUsageInfoTest : public WvCdmRequestLicenseTest, public ::testing::WithParamInterface {};