Source release 16.3.0
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#include "test_base.h"
|
||||
#include "test_host.h"
|
||||
#include "test_printers.h"
|
||||
#include "test_sleep.h"
|
||||
#include "url_request.h"
|
||||
|
||||
using namespace testing;
|
||||
@@ -58,7 +59,7 @@ const std::string kCencInitData = a2bs_hex(
|
||||
"edef8ba979d64acea3c827dcd51d21ed" // Widevine system id
|
||||
"00000022" // pssh data size
|
||||
// pssh data:
|
||||
"08011a0d7769646576696e655f746573"
|
||||
"08011a0d7769646576696e655f746573" // "streaming_clip9"
|
||||
"74220f73747265616d696e675f636c69"
|
||||
"7039");
|
||||
const std::string kCencPersistentInitData = a2bs_hex(
|
||||
@@ -68,7 +69,7 @@ const std::string kCencPersistentInitData = a2bs_hex(
|
||||
"edef8ba979d64acea3c827dcd51d21ed" // Widevine system id
|
||||
"00000020" // pssh data size
|
||||
// pssh data:
|
||||
"08011a0d7769646576696e655f746573"
|
||||
"08011a0d7769646576696e655f746573" // "offline_clip6"
|
||||
"74220d6f66666c696e655f636c697036");
|
||||
const std::string kInvalidCencInitData = a2bs_hex(
|
||||
"0000000c" // blob size
|
||||
@@ -83,7 +84,7 @@ const std::string kNonWidevineCencInitData = a2bs_hex(
|
||||
const std::string kWebMInitData = a2bs_hex("deadbeefdeadbeefdeadbeefdeadbeef");
|
||||
const std::string kKeyIdsInitData =
|
||||
"{\"kids\":[\"67ef0gd8pvfd0\",\"77ef0gd8pvfd0\"]}";
|
||||
const std::string kHlsInitData =
|
||||
const std::string kHlsInitData = // content_id = "bigbuckbunny"
|
||||
"#EXT-X-KEY:METHOD=SAMPLE-AES,KEYFORMAT=\"com.widevine\",KEYFORMATVERSIONS="
|
||||
"\"1\",URI=\"data:text/plain;base64,ew0KICAgInByb3ZpZGVyIjogIndpZGV2aW5lX3R"
|
||||
"lc3QiLA0KICAgImNvbnRlbnRfaWQiOiAiWW1sblluVmphMkoxYm01NSIsDQogICAia2V5X2lkc"
|
||||
@@ -331,19 +332,27 @@ class CdmTest : public WvCdmTestBase, public Cdm::IEventListener {
|
||||
Cdm::Status status = cdm_->createSession(session_type, session_id);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
|
||||
std::string init_data_type_name;
|
||||
std::string init_data;
|
||||
if (session_type == Cdm::kTemporary) {
|
||||
if (init_data_type == Cdm::kCenc) {
|
||||
init_data_type_name = CENC_INIT_DATA_FORMAT;
|
||||
init_data = kCencInitData;
|
||||
} else if (init_data_type == Cdm::kHls) {
|
||||
init_data_type_name = HLS_INIT_DATA_FORMAT;
|
||||
init_data = kHlsInitData;
|
||||
}
|
||||
} else if (session_type == Cdm::kPersistentLicense ||
|
||||
session_type == Cdm::kPersistentUsageRecord) {
|
||||
if (init_data_type == Cdm::kCenc) {
|
||||
init_data = kCencPersistentInitData;
|
||||
init_data_type_name = CENC_INIT_DATA_FORMAT;
|
||||
}
|
||||
}
|
||||
if (g_cutoff >= LOG_DEBUG) {
|
||||
InitializationData parsed_init_data(init_data_type_name, init_data);
|
||||
parsed_init_data.DumpToLogs();
|
||||
}
|
||||
ASSERT_FALSE(init_data.empty());
|
||||
|
||||
EXPECT_CALL(*this, onMessage(*session_id, Cdm::kLicenseRequest, _))
|
||||
@@ -397,26 +406,19 @@ class CdmTest : public WvCdmTestBase, public Cdm::IEventListener {
|
||||
Mock::VerifyAndClear(this);
|
||||
}
|
||||
|
||||
std::string GetProvisioningResponse(const std::string& message,
|
||||
size_t max_attempts = 10) {
|
||||
std::string GetProvisioningResponse(const std::string& message) {
|
||||
std::string uri = config_.provisioning_server();
|
||||
|
||||
LOGV("GetProvisioningResponse: URI: %s", uri.c_str());
|
||||
LOGV("GetProvisioningResponse: message:\n%s\n", b2a_hex(message).c_str());
|
||||
|
||||
std::string reply;
|
||||
uri += "&signedRequest=" + message;
|
||||
// TODO(b/139361531): Remove loop once provisioning service is stable.
|
||||
for (size_t attempt = 1; attempt <= max_attempts; attempt++) {
|
||||
FetchCertificate(uri, &reply);
|
||||
if (HasFatalFailure()) {
|
||||
LOGE("Failed to get provisioning response: attempt = %zu", attempt);
|
||||
reply.clear();
|
||||
continue;
|
||||
} else {
|
||||
LOGV("GetProvisioningResponse: response:\n%s\n", reply.c_str());
|
||||
break;
|
||||
}
|
||||
std::string reply;
|
||||
FetchCertificate(uri, &reply);
|
||||
if (HasFatalFailure()) {
|
||||
LOGE("Failed to get provisioning response");
|
||||
reply.clear();
|
||||
} else {
|
||||
LOGV("GetProvisioningResponse: response:\n%s\n", reply.c_str());
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
@@ -443,6 +445,10 @@ class CdmTest : public WvCdmTestBase, public Cdm::IEventListener {
|
||||
Cdm::InitDataType init_data_type,
|
||||
const std::string& init_data) {
|
||||
const int num_retries = 5;
|
||||
if (init_data_type == Cdm::kCenc && g_cutoff >= LOG_DEBUG) {
|
||||
InitializationData parsed_init_data(CENC_INIT_DATA_FORMAT, init_data);
|
||||
parsed_init_data.DumpToLogs();
|
||||
}
|
||||
for (int i = 0; i < num_retries; i++) {
|
||||
LOGD("attempt %d", i);
|
||||
Cdm::Status status =
|
||||
@@ -512,18 +518,19 @@ class MockTimerClient : public Cdm::ITimer::IClient {
|
||||
MOCK_METHOD1(onTimerExpired, void(void*));
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_F(CdmTest, TestHostTimer) {
|
||||
// Validate that the TestHost timers are processed in the correct order.
|
||||
// Validate that the TestHost timers are processed in the correct order and
|
||||
// on the correct timeouts.
|
||||
const int64_t kTimerDelayMs = 1000;
|
||||
void* kCtx1 = reinterpret_cast<void*>(0x1);
|
||||
void* kCtx2 = reinterpret_cast<void*>(0x2);
|
||||
void* kCtx4 = reinterpret_cast<void*>(0x4);
|
||||
|
||||
MockTimerClient client;
|
||||
|
||||
g_host->setTimeout(kTimerDelayMs * 1, &client, kCtx1);
|
||||
g_host->setTimeout(kTimerDelayMs * 2, &client, kCtx2);
|
||||
g_host->setTimeout(kTimerDelayMs * 4, &client, kCtx4);
|
||||
|
||||
EXPECT_CALL(client, onTimerExpired(kCtx1));
|
||||
g_host->ElapseTime(kTimerDelayMs);
|
||||
@@ -536,6 +543,14 @@ TEST_F(CdmTest, TestHostTimer) {
|
||||
EXPECT_CALL(client, onTimerExpired(_)).Times(0);
|
||||
g_host->ElapseTime(kTimerDelayMs);
|
||||
Mock::VerifyAndClear(&client);
|
||||
|
||||
EXPECT_CALL(client, onTimerExpired(kCtx4));
|
||||
g_host->ElapseTime(kTimerDelayMs);
|
||||
Mock::VerifyAndClear(&client);
|
||||
|
||||
EXPECT_CALL(client, onTimerExpired(_)).Times(0);
|
||||
g_host->ElapseTime(kTimerDelayMs);
|
||||
Mock::VerifyAndClear(&client);
|
||||
}
|
||||
|
||||
TEST_F(CdmTest, Initialize) {
|
||||
@@ -1649,6 +1664,65 @@ TEST_F(CdmTest, RemoveThreeUsageRecords) {
|
||||
ASSERT_EQ(Cdm::kSessionNotFound, status);
|
||||
}
|
||||
|
||||
// Reload an offline license that does not have a usage entry.
|
||||
TEST_F(CdmTest, LoadPersistentNoNonce) {
|
||||
EnsureProvisioned();
|
||||
|
||||
std::string session_id;
|
||||
ASSERT_EQ(Cdm::kSuccess,
|
||||
cdm_->createSession(Cdm::kPersistentLicense, &session_id));
|
||||
|
||||
video_widevine::WidevinePsshData pssh;
|
||||
// offline_clip1 does not have a provider session token, so it will not
|
||||
// generate a usage table entry.
|
||||
pssh.set_content_id("offline_clip1");
|
||||
const std::string init_data = MakePSSH(pssh);
|
||||
std::string license_request;
|
||||
{
|
||||
EXPECT_CALL(*this, onMessage(session_id, Cdm::kLicenseRequest, _))
|
||||
.WillOnce(SaveArg<2>(&license_request));
|
||||
ASSERT_EQ(Cdm::kSuccess,
|
||||
generateRequestWithRetry(session_id, Cdm::kCenc, init_data));
|
||||
Mock::VerifyAndClear(this);
|
||||
}
|
||||
|
||||
// Send the request to the license server and receive the license response.
|
||||
std::string license_response;
|
||||
FetchLicense(config_.license_server(), license_request, &license_response);
|
||||
|
||||
// Update the session with the new keys.
|
||||
{
|
||||
EXPECT_CALL(*this, onKeyStatusesChange(session_id, true));
|
||||
ASSERT_EQ(Cdm::kSuccess, updateWithRetry(session_id, license_response));
|
||||
Mock::VerifyAndClear(this);
|
||||
}
|
||||
|
||||
// Should be able to load the session again after closing it.
|
||||
Cdm::Status status = cdm_->close(session_id);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
EXPECT_CALL(*this, onKeyStatusesChange(session_id, true));
|
||||
status = cdm_->load(session_id);
|
||||
EXPECT_EQ(Cdm::kSuccess, status);
|
||||
Mock::VerifyAndClear(this);
|
||||
|
||||
// Should be able to load the session again after recreating the CDM.
|
||||
ASSERT_NO_FATAL_FAILURE(RecreateCdm(true /* privacy_mode */));
|
||||
EXPECT_CALL(*this, onKeyStatusesChange(session_id, true));
|
||||
status = cdm_->load(session_id);
|
||||
EXPECT_EQ(Cdm::kSuccess, status);
|
||||
Mock::VerifyAndClear(this);
|
||||
|
||||
// Should not be able to load the session again after clearing storage.
|
||||
status = cdm_->close(session_id);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
g_host->Reset();
|
||||
EnsureProvisioned();
|
||||
EXPECT_CALL(*this, onKeyStatusesChange(session_id, _)).Times(0);
|
||||
status = cdm_->load(session_id);
|
||||
EXPECT_EQ(Cdm::kSessionNotFound, status);
|
||||
Mock::VerifyAndClear(this);
|
||||
}
|
||||
|
||||
TEST_F(CdmTest, RemoveIncomplete) {
|
||||
EnsureProvisioned();
|
||||
std::string session_id;
|
||||
@@ -2414,4 +2488,6 @@ TEST_F(CdmIndividualizationTest, NoLoadWithoutProvisioning) {
|
||||
EXPECT_EQ(Cdm::kNeedsDeviceCertificate, cdm_->load(kBogusSessionId));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace widevine
|
||||
|
||||
Reference in New Issue
Block a user