Source release 16.4.0
This commit is contained in:
22
core/test/Android.bp
Normal file
22
core/test/Android.bp
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (C) 2020 The Android Open Source Project$
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");$
|
||||
// you may not use this file except in compliance with the License.$
|
||||
// You may obtain a copy of the License at$
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0$
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software$
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,$
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.$
|
||||
// See the License for the specific language governing permissions and$
|
||||
// limitations under the License.
|
||||
|
||||
filegroup {
|
||||
name: "vts_cdm_core_test_srcs",
|
||||
srcs: [
|
||||
"url_request.cpp",
|
||||
"license_request.cpp",
|
||||
"http_socket.cpp",
|
||||
],
|
||||
}
|
||||
@@ -15,8 +15,8 @@
|
||||
#include "cdm_engine.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "metrics.pb.h"
|
||||
#include "wv_cdm_event_listener.h"
|
||||
#include "wv_metrics.pb.h"
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::ByRef;
|
||||
@@ -233,7 +233,7 @@ TEST_F(WvCdmEngineMetricsImplTest, GenerateKeyRequest) {
|
||||
}
|
||||
|
||||
TEST_F(WvCdmEngineMetricsImplTest, AddKey) {
|
||||
CdmLicenseType license_type;
|
||||
CdmLicenseType license_type = {};
|
||||
CdmKeySetId key_set_id;
|
||||
|
||||
EXPECT_CALL(*test_cdm_metrics_engine_,
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "initialization_data.h"
|
||||
#include "license_request.h"
|
||||
#include "log.h"
|
||||
#include "metrics.pb.h"
|
||||
#include "properties.h"
|
||||
#include "string_conversions.h"
|
||||
#include "test_base.h"
|
||||
@@ -27,6 +26,7 @@
|
||||
#include "url_request.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
#include "wv_cdm_types.h"
|
||||
#include "wv_metrics.pb.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
@@ -48,12 +48,9 @@ const std::string kFakeSessionId = "TotallyARealSession123456789";
|
||||
|
||||
} // namespace
|
||||
|
||||
class WvCdmEnginePreProvTest : public WvCdmTestBase {
|
||||
class WvCdmEnginePreProvTest : public WvCdmTestBaseWithEngine {
|
||||
public:
|
||||
WvCdmEnginePreProvTest()
|
||||
: dummy_engine_metrics_(new EngineMetrics),
|
||||
cdm_engine_(&file_system_, dummy_engine_metrics_),
|
||||
session_opened_(false) {}
|
||||
WvCdmEnginePreProvTest() : session_opened_(false) {}
|
||||
|
||||
~WvCdmEnginePreProvTest() override {}
|
||||
|
||||
@@ -109,16 +106,13 @@ class WvCdmEnginePreProvTest : public WvCdmTestBase {
|
||||
LicenseRequest license_request;
|
||||
license_request.GetDrmMessage(http_response, *response);
|
||||
|
||||
LOGV("response: size=%u, string:\n%s\n", response->size(),
|
||||
LOGV("response: size = %zu, string =\n%s\n", response->size(),
|
||||
Base64SafeEncode(
|
||||
std::vector<uint8_t>(response->begin(), response->end()))
|
||||
.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
FileSystem file_system_;
|
||||
shared_ptr<metrics::EngineMetrics> dummy_engine_metrics_;
|
||||
CdmEngine cdm_engine_;
|
||||
bool session_opened_;
|
||||
std::string key_msg_;
|
||||
std::string session_id_;
|
||||
@@ -239,7 +233,7 @@ class WvCdmEngineTest : public WvCdmEnginePreProvTest {
|
||||
std::string drm_msg;
|
||||
LicenseRequest lic_request;
|
||||
lic_request.GetDrmMessage(response, drm_msg);
|
||||
LOGV("drm msg: %u bytes\r\n%s", drm_msg.size(),
|
||||
LOGV("drm msg: %zu bytes\r\n%s", drm_msg.size(),
|
||||
HexEncode(reinterpret_cast<const uint8_t*>(drm_msg.data()),
|
||||
drm_msg.size())
|
||||
.c_str());
|
||||
@@ -402,14 +396,37 @@ TEST_F(WvCdmEngineTest, LoadKey) {
|
||||
holder.SignAndLoadLicense();
|
||||
}
|
||||
|
||||
TEST_F(WvCdmEngineTest, LicenseRenewal) {
|
||||
// This test generates a renewal and then requests the renewal using the server
|
||||
// url specified in the license. This is what most apps would do, but you should
|
||||
// skip this test when you want to set the license and renewal server on the
|
||||
// command line.
|
||||
TEST_F(WvCdmEngineTest, LicenseRenewalSpecifiedServer) {
|
||||
GenerateKeyRequest(binary_key_id(), kCencMimeType);
|
||||
VerifyNewKeyResponse(config_.license_server(), config_.client_auth());
|
||||
|
||||
GenerateRenewalRequest();
|
||||
VerifyRenewalKeyResponse(
|
||||
server_url_.empty() ? config_.license_server() : server_url_,
|
||||
config_.client_auth());
|
||||
if (!server_url_.empty()) {
|
||||
// If the license server put a URL for the renewal in the license, we should
|
||||
// be able to verify the renewal against that server.
|
||||
VerifyRenewalKeyResponse(server_url_, config_.client_auth());
|
||||
} else {
|
||||
// If the license server did not give us a URL, we won't verify it.
|
||||
LOGE("License server did not set renewal URL. license_url=%s.",
|
||||
config_.license_server().c_str());
|
||||
// This is OK when you are using a local, debug, license server, but it
|
||||
// should NOT happen if using UAT or UAT nightly.
|
||||
EXPECT_EQ(std::string::npos, config_.license_server().find("proxy.uat"));
|
||||
}
|
||||
}
|
||||
|
||||
// This test generates a renewal and then requests the renewal from the same
|
||||
// server from which we requested the original license.
|
||||
TEST_F(WvCdmEngineTest, LicenseRenewalSameServer) {
|
||||
GenerateKeyRequest(binary_key_id(), kCencMimeType);
|
||||
VerifyNewKeyResponse(config_.license_server(), config_.client_auth());
|
||||
|
||||
GenerateRenewalRequest();
|
||||
VerifyRenewalKeyResponse(config_.license_server(), config_.client_auth());
|
||||
}
|
||||
|
||||
TEST_F(WvCdmEngineTest, ParseDecryptHashStringTest) {
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
#include "cdm_session.h"
|
||||
#include "crypto_key.h"
|
||||
#include "metrics.pb.h"
|
||||
#include "properties.h"
|
||||
#include "service_certificate.h"
|
||||
#include "string_conversions.h"
|
||||
@@ -17,6 +16,7 @@
|
||||
#include "test_printers.h"
|
||||
#include "usage_table_header.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
#include "wv_metrics.pb.h"
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::DoAll;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "crypto_session.h"
|
||||
@@ -12,12 +13,16 @@
|
||||
#include "key_session.h"
|
||||
#include "license_protocol.pb.h"
|
||||
#include "log.h"
|
||||
#include "metrics.pb.h"
|
||||
#include "metrics_collections.h"
|
||||
#include "platform.h"
|
||||
#include "test_base.h"
|
||||
#include "test_printers.h"
|
||||
#include "wv_cdm_types.h"
|
||||
#include "wv_metrics.pb.h"
|
||||
|
||||
using ::testing::AllOf;
|
||||
using ::testing::Ge;
|
||||
using ::testing::Le;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -296,7 +301,7 @@ TEST_F(CryptoSessionMetricsTest, OpenSessionValidMetrics) {
|
||||
// lite, convert these tests to use Message-based convenience functions.
|
||||
|
||||
// Validate common metrics regardless of provisioning type.
|
||||
EXPECT_EQ(1, metrics_proto.oemcrypto_initialize_time_us().size());
|
||||
ASSERT_EQ(1, metrics_proto.oemcrypto_initialize_time_us().size());
|
||||
EXPECT_TRUE(metrics_proto.oemcrypto_initialize_time_us(0)
|
||||
.attributes()
|
||||
.has_oem_crypto_result());
|
||||
@@ -327,7 +332,8 @@ TEST_F(CryptoSessionMetricsTest, OpenSessionValidMetrics) {
|
||||
EXPECT_EQ(OEMCrypto_OEMCertificate,
|
||||
metrics_proto.oemcrypto_provisioning_method().int_value());
|
||||
ASSERT_EQ(1, metrics_proto.oemcrypto_get_oem_public_certificate().size());
|
||||
EXPECT_EQ(1, metrics_proto.oemcrypto_get_oem_public_certificate(0).count());
|
||||
EXPECT_THAT(metrics_proto.oemcrypto_get_oem_public_certificate(0).count(),
|
||||
AllOf(Ge(1), Le(2)));
|
||||
} else if (token_type == kClientTokenDrmCert) {
|
||||
// TODO(blueeyes): Add support for getting the system id from a
|
||||
// pre-installed DRM certificate..
|
||||
@@ -373,8 +379,9 @@ TEST_F(CryptoSessionMetricsTest, GetProvisioningTokenValidMetrics) {
|
||||
|
||||
EXPECT_EQ(OEMCrypto_OEMCertificate,
|
||||
metrics_proto.oemcrypto_provisioning_method().int_value());
|
||||
EXPECT_EQ(1, metrics_proto.oemcrypto_get_oem_public_certificate().size());
|
||||
EXPECT_EQ(1, metrics_proto.oemcrypto_get_oem_public_certificate(0).count());
|
||||
ASSERT_EQ(1, metrics_proto.oemcrypto_get_oem_public_certificate().size());
|
||||
EXPECT_THAT(metrics_proto.oemcrypto_get_oem_public_certificate(0).count(),
|
||||
AllOf(Ge(1), Le(2)));
|
||||
|
||||
ASSERT_EQ(1, metrics_proto.crypto_session_get_token().size());
|
||||
EXPECT_EQ(1, metrics_proto.crypto_session_get_token(0).count());
|
||||
|
||||
1632
core/test/duration_use_case_test.cpp
Normal file
1632
core/test/duration_use_case_test.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -29,12 +29,9 @@
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
class WvGenericCryptoTest : public WvCdmTestBase {
|
||||
class WvGenericCryptoTest : public WvCdmTestBaseWithEngine {
|
||||
public:
|
||||
WvGenericCryptoTest()
|
||||
: dummy_engine_metrics_(new metrics::EngineMetrics),
|
||||
cdm_engine_(&file_system_, dummy_engine_metrics_),
|
||||
holder_(&cdm_engine_) {}
|
||||
WvGenericCryptoTest() : holder_(&cdm_engine_) {}
|
||||
|
||||
void SetUp() override {
|
||||
WvCdmTestBase::SetUp();
|
||||
@@ -74,9 +71,6 @@ class WvGenericCryptoTest : public WvCdmTestBase {
|
||||
}
|
||||
|
||||
protected:
|
||||
FileSystem file_system_;
|
||||
std::shared_ptr<metrics::EngineMetrics> dummy_engine_metrics_;
|
||||
CdmEngine cdm_engine_;
|
||||
TestLicenseHolder holder_;
|
||||
|
||||
KeyId ency_id_;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <future>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
@@ -31,6 +32,8 @@ namespace wvcdm {
|
||||
|
||||
namespace {
|
||||
|
||||
using HttpHeaderFields = std::map<std::string, std::string>;
|
||||
|
||||
constexpr const int kHttpOk = 200;
|
||||
const std::string kCencMimeType = "cenc";
|
||||
|
||||
@@ -67,13 +70,9 @@ const std::vector<uint8_t> kClearData = a2b_hex(
|
||||
|
||||
} // namespace
|
||||
|
||||
class ParallelCdmTest : public WvCdmTestBase,
|
||||
class ParallelCdmTest : public WvCdmTestBaseWithEngine,
|
||||
public ::testing::WithParamInterface<int> {
|
||||
public:
|
||||
ParallelCdmTest()
|
||||
: dummy_engine_metrics_(new metrics::EngineMetrics()),
|
||||
cdm_engine_(&file_system_, dummy_engine_metrics_) {}
|
||||
|
||||
void SetUp() override {
|
||||
WvCdmTestBase::SetUp();
|
||||
EnsureProvisioned();
|
||||
@@ -125,15 +124,23 @@ class ParallelCdmTest : public WvCdmTestBase,
|
||||
ASSERT_TRUE(url_request.is_connected());
|
||||
url_request.PostRequest(key_request.message);
|
||||
if (url_request.GetResponse(&http_response)) {
|
||||
int status_code = url_request.GetStatusCode(http_response);
|
||||
ASSERT_EQ(kHttpOk, status_code);
|
||||
request_ok = true;
|
||||
break;
|
||||
} else {
|
||||
LOGW("License request failed: sid = %s, attempt = %zu",
|
||||
session_id.c_str(), attempt);
|
||||
std::this_thread::sleep_for(kRequestRetryWait);
|
||||
const int status_code = url_request.GetStatusCode(http_response);
|
||||
if (status_code == kHttpOk) {
|
||||
request_ok = true;
|
||||
break;
|
||||
}
|
||||
LOGW("License response error: code = %d, url = %s", status_code,
|
||||
url.c_str());
|
||||
HttpHeaderFields fields;
|
||||
if (url_request.GetDebugHeaderFields(http_response, &fields)) {
|
||||
for (auto field : fields) {
|
||||
LOGD(" %s: %s", field.first.c_str(), field.second.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
LOGW("License request failed: sid = %s, attempt = %zu",
|
||||
session_id.c_str(), attempt);
|
||||
std::this_thread::sleep_for(kRequestRetryWait);
|
||||
}
|
||||
ASSERT_TRUE(request_ok);
|
||||
LicenseRequest license_request;
|
||||
@@ -232,10 +239,6 @@ class ParallelCdmTest : public WvCdmTestBase,
|
||||
ASSERT_NO_FATAL_FAILURE(CloseSession(session_id));
|
||||
}
|
||||
}
|
||||
|
||||
FileSystem file_system_;
|
||||
shared_ptr<metrics::EngineMetrics> dummy_engine_metrics_;
|
||||
CdmEngine cdm_engine_;
|
||||
};
|
||||
|
||||
TEST_P(ParallelCdmTest, ParallelLicenseRequests) {
|
||||
|
||||
@@ -238,7 +238,7 @@ TEST_F(PolicyEngineConstraintsTest, IsPermissiveWithoutAResolution) {
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(HDCP_NO_DIGITAL_OUTPUT),
|
||||
Return(GET_HDCP_CAPABILITY_FAILED)));
|
||||
|
||||
policy_engine_->SetLicense(license_, false);
|
||||
policy_engine_->SetLicense(license_, false, false);
|
||||
policy_engine_->OnTimerEvent();
|
||||
|
||||
EXPECT_TRUE(policy_engine_->CanDecryptContent(kKeyId1));
|
||||
@@ -270,7 +270,7 @@ TEST_F(PolicyEngineConstraintsTest, HandlesResolutionsBasedOnConstraints) {
|
||||
.WillRepeatedly(
|
||||
DoAll(SetArgPointee<0>(HDCP_NO_DIGITAL_OUTPUT), Return(NO_ERROR)));
|
||||
|
||||
policy_engine_->SetLicense(license_, false);
|
||||
policy_engine_->SetLicense(license_, false, false);
|
||||
policy_engine_->NotifyResolution(1, kTargetRes1);
|
||||
policy_engine_->OnTimerEvent();
|
||||
EXPECT_TRUE(policy_engine_->CanDecryptContent(kKeyId1));
|
||||
@@ -334,7 +334,7 @@ TEST_F(PolicyEngineConstraintsTest,
|
||||
}
|
||||
|
||||
policy_engine_->NotifyResolution(1, kTargetRes1);
|
||||
policy_engine_->SetLicense(license_, false);
|
||||
policy_engine_->SetLicense(license_, false, false);
|
||||
policy_engine_->OnTimerEvent();
|
||||
policy_engine_->OnTimerEvent();
|
||||
policy_engine_->OnTimerEvent();
|
||||
@@ -367,7 +367,7 @@ TEST_F(PolicyEngineConstraintsTest, HandlesConstraintOverridingHdcp) {
|
||||
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(HDCP_V2), Return(NO_ERROR)));
|
||||
|
||||
policy_engine_->SetLicense(license_, false);
|
||||
policy_engine_->SetLicense(license_, false, false);
|
||||
policy_engine_->NotifyResolution(1, kTargetRes1);
|
||||
policy_engine_->OnTimerEvent();
|
||||
EXPECT_TRUE(policy_engine_->CanDecryptContent(kKeyId1));
|
||||
@@ -409,7 +409,7 @@ TEST_F(PolicyEngineConstraintsTest, HandlesNoHdcp) {
|
||||
EXPECT_CALL(crypto_session_, GetHdcpCapabilities(_, _))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(HDCP_NONE), Return(NO_ERROR)));
|
||||
|
||||
policy_engine_->SetLicense(license_, false);
|
||||
policy_engine_->SetLicense(license_, false, false);
|
||||
|
||||
policy_engine_->NotifyResolution(1, kTargetRes1);
|
||||
policy_engine_->OnTimerEvent();
|
||||
@@ -453,7 +453,7 @@ TEST_F(PolicyEngineConstraintsTest, UsesDefaultHdcpWhenResolutionNotSet) {
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(HDCP_NO_DIGITAL_OUTPUT),
|
||||
Return(GET_HDCP_CAPABILITY_FAILED)));
|
||||
|
||||
policy_engine_->SetLicense(license_, false);
|
||||
policy_engine_->SetLicense(license_, false, false);
|
||||
policy_engine_->OnTimerEvent();
|
||||
EXPECT_TRUE(policy_engine_->CanDecryptContent(kKeyId1));
|
||||
EXPECT_FALSE(policy_engine_->CanDecryptContent(kKeyId2));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
195
core/test/policy_integration_test.cpp
Normal file
195
core/test/policy_integration_test.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
// These tests perform various end-to-end actions similar to what an application
|
||||
// would do. They verify that policies specified on UAT are honored on the
|
||||
// device.
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "cdm_engine.h"
|
||||
#include "clock.h"
|
||||
#include "config_test_env.h"
|
||||
#include "initialization_data.h"
|
||||
#include "license_request.h"
|
||||
#include "log.h"
|
||||
#include "metrics_collections.h"
|
||||
#include "test_base.h"
|
||||
#include "test_printers.h"
|
||||
#include "test_sleep.h"
|
||||
#include "url_request.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
#include "wv_cdm_types.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
namespace {
|
||||
constexpr int kHttpOk = 200;
|
||||
const std::string kCencMimeType = "cenc";
|
||||
} // namespace
|
||||
|
||||
// Core Policy Integration Test
|
||||
class CorePIGTest : public WvCdmTestBaseWithEngine {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
WvCdmTestBase::SetUp();
|
||||
EnsureProvisioned();
|
||||
}
|
||||
|
||||
void OpenSession(CdmSessionId* session_id) {
|
||||
CdmResponseType status = cdm_engine_.OpenSession(
|
||||
config_.key_system(), nullptr, nullptr, session_id);
|
||||
ASSERT_EQ(NO_ERROR, status);
|
||||
ASSERT_TRUE(cdm_engine_.IsOpenSession(*session_id));
|
||||
}
|
||||
|
||||
void CloseSession(const CdmSessionId& session_id) {
|
||||
CdmResponseType status = cdm_engine_.CloseSession(session_id);
|
||||
ASSERT_EQ(NO_ERROR, status);
|
||||
ASSERT_FALSE(cdm_engine_.IsOpenSession(session_id));
|
||||
}
|
||||
|
||||
// Create a license request for the given content_id and requesting the
|
||||
// specified license_type.
|
||||
void GenerateKeyRequest(const CdmSessionId& session_id,
|
||||
const std::string& content_id,
|
||||
CdmKeyRequest* key_request,
|
||||
CdmLicenseType license_type) {
|
||||
video_widevine::WidevinePsshData pssh;
|
||||
pssh.set_content_id(content_id);
|
||||
const std::string init_data_string = MakePSSH(pssh);
|
||||
const InitializationData init_data(kCencMimeType, init_data_string);
|
||||
init_data.DumpToLogs();
|
||||
CdmAppParameterMap empty_app_parameters;
|
||||
CdmKeySetId empty_key_set_id;
|
||||
CdmResponseType result = cdm_engine_.GenerateKeyRequest(
|
||||
session_id, empty_key_set_id, init_data, license_type,
|
||||
empty_app_parameters, key_request);
|
||||
ASSERT_EQ(KEY_MESSAGE, result);
|
||||
ASSERT_EQ(kKeyRequestTypeInitial, key_request->type);
|
||||
}
|
||||
|
||||
// Send the request to the server and get the response.
|
||||
void GetKeyResponse(const CdmKeyRequest& key_request,
|
||||
std::string* key_response) {
|
||||
const std::string url = config_.license_server() + config_.client_auth();
|
||||
UrlRequest url_request(url);
|
||||
ASSERT_TRUE(url_request.is_connected());
|
||||
|
||||
std::string http_response;
|
||||
url_request.PostRequest(key_request.message);
|
||||
ASSERT_TRUE(url_request.GetResponse(&http_response));
|
||||
int status_code = url_request.GetStatusCode(http_response);
|
||||
ASSERT_EQ(kHttpOk, status_code);
|
||||
|
||||
LicenseRequest license_request;
|
||||
license_request.GetDrmMessage(http_response, *key_response);
|
||||
}
|
||||
|
||||
// Load the license response into the specified session. Verify it has the
|
||||
// correct license type (either streaming or offline).
|
||||
void AddKey(const CdmSessionId& session_id, const std::string& key_response,
|
||||
CdmLicenseType expected_license_type, CdmKeySetId* key_set_id) {
|
||||
CdmLicenseType license_type;
|
||||
CdmResponseType status =
|
||||
cdm_engine_.AddKey(session_id, key_response, &license_type, key_set_id);
|
||||
ASSERT_EQ(KEY_ADDED, status);
|
||||
ASSERT_EQ(expected_license_type, license_type);
|
||||
}
|
||||
|
||||
// Reload the license response into the specified session.
|
||||
void RestoreKey(const CdmSessionId& session_id,
|
||||
const CdmKeySetId& key_set_id) {
|
||||
CdmResponseType status = cdm_engine_.RestoreKey(session_id, key_set_id);
|
||||
ASSERT_EQ(KEY_ADDED, status);
|
||||
}
|
||||
|
||||
// Use the key to decrypt.
|
||||
void Decrypt(const CdmSessionId& session_id, const KeyId& key_id) {
|
||||
constexpr size_t buffer_size = 500;
|
||||
const std::vector<uint8_t> input(buffer_size, 0);
|
||||
std::vector<uint8_t> output(buffer_size, 0);
|
||||
const std::vector<uint8_t> iv(KEY_IV_SIZE, 0);
|
||||
Decrypt(session_id, key_id, input, iv, &output, NO_ERROR);
|
||||
}
|
||||
|
||||
// Try to use the key to decrypt, but expect the key has expired.
|
||||
void FailDecrypt(const CdmSessionId& session_id, const KeyId& key_id) {
|
||||
constexpr size_t buffer_size = 500;
|
||||
const std::vector<uint8_t> input(buffer_size, 0);
|
||||
std::vector<uint8_t> output(buffer_size, 0);
|
||||
const std::vector<uint8_t> iv(KEY_IV_SIZE, 0);
|
||||
Decrypt(session_id, key_id, input, iv, &output, NEED_KEY);
|
||||
}
|
||||
|
||||
void Decrypt(const CdmSessionId& session_id, const KeyId& key_id,
|
||||
const std::vector<uint8_t>& input,
|
||||
const std::vector<uint8_t>& iv, std::vector<uint8_t>* output,
|
||||
CdmResponseType expected_status) {
|
||||
CdmDecryptionParametersV16 params(key_id);
|
||||
params.is_secure = false;
|
||||
CdmDecryptionSample sample(input.data(), output->data(), 0, input.size(),
|
||||
iv);
|
||||
CdmDecryptionSubsample subsample(0, input.size());
|
||||
sample.subsamples.push_back(subsample);
|
||||
params.samples.push_back(sample);
|
||||
|
||||
CdmResponseType status = cdm_engine_.DecryptV16(session_id, params);
|
||||
ASSERT_EQ(expected_status, status);
|
||||
}
|
||||
};
|
||||
|
||||
// An offline license with nonce not required.
|
||||
TEST_F(CorePIGTest, OfflineNoNonce) {
|
||||
const std::string content_id = "2015_tears";
|
||||
const KeyId key_id = "0000000000000000";
|
||||
|
||||
const CdmLicenseType license_type = kLicenseTypeOffline;
|
||||
CdmSessionId session_id;
|
||||
ASSERT_NO_FATAL_FAILURE(OpenSession(&session_id));
|
||||
CdmKeyRequest key_request;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GenerateKeyRequest(session_id, content_id, &key_request, license_type));
|
||||
std::string key_response;
|
||||
ASSERT_NO_FATAL_FAILURE(GetKeyResponse(key_request, &key_response));
|
||||
CdmKeySetId key_set_id;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
AddKey(session_id, key_response, license_type, &key_set_id));
|
||||
ASSERT_NO_FATAL_FAILURE(Decrypt(session_id, key_id));
|
||||
ASSERT_NO_FATAL_FAILURE(CloseSession(session_id));
|
||||
ASSERT_NO_FATAL_FAILURE(OpenSession(&session_id));
|
||||
ASSERT_NO_FATAL_FAILURE(RestoreKey(session_id, key_set_id));
|
||||
ASSERT_NO_FATAL_FAILURE(Decrypt(session_id, key_id));
|
||||
ASSERT_NO_FATAL_FAILURE(CloseSession(session_id));
|
||||
}
|
||||
|
||||
// An offline license with nonce and provider session token.
|
||||
TEST_F(CorePIGTest, OfflineWithPST) {
|
||||
const std::string content_id = "offline_clip2";
|
||||
const KeyId key_id =
|
||||
"\x32\x60\xF3\x9E\x12\xCC\xF6\x53\x52\x99\x90\x16\x8A\x35\x83\xFF";
|
||||
const CdmLicenseType license_type = kLicenseTypeOffline;
|
||||
CdmSessionId session_id;
|
||||
ASSERT_NO_FATAL_FAILURE(OpenSession(&session_id));
|
||||
CdmKeyRequest key_request;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
GenerateKeyRequest(session_id, content_id, &key_request, license_type));
|
||||
std::string key_response;
|
||||
ASSERT_NO_FATAL_FAILURE(GetKeyResponse(key_request, &key_response));
|
||||
CdmKeySetId key_set_id;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
AddKey(session_id, key_response, license_type, &key_set_id));
|
||||
ASSERT_NO_FATAL_FAILURE(Decrypt(session_id, key_id));
|
||||
ASSERT_NO_FATAL_FAILURE(CloseSession(session_id));
|
||||
ASSERT_NO_FATAL_FAILURE(OpenSession(&session_id));
|
||||
ASSERT_NO_FATAL_FAILURE(RestoreKey(session_id, key_set_id));
|
||||
ASSERT_NO_FATAL_FAILURE(Decrypt(session_id, key_id));
|
||||
ASSERT_NO_FATAL_FAILURE(CloseSession(session_id));
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
@@ -290,8 +290,8 @@ void WvCdmTestBase::Provision() {
|
||||
if (config_.provisioning_server() == "fake") {
|
||||
LOGD("Using fake provisioning server.");
|
||||
|
||||
CdmEngine cdm_engine(&file_system,
|
||||
std::shared_ptr<EngineMetrics>(new EngineMetrics));
|
||||
TestCdmEngine cdm_engine(&file_system,
|
||||
std::shared_ptr<EngineMetrics>(new EngineMetrics));
|
||||
FakeProvisioningServer server;
|
||||
CdmResponseType result = cdm_engine.GetProvisioningRequest(
|
||||
cert_type, cert_authority, server.service_certificate(), kLevelDefault,
|
||||
@@ -309,8 +309,8 @@ void WvCdmTestBase::Provision() {
|
||||
EXPECT_EQ(NO_ERROR, result);
|
||||
} else {
|
||||
// TODO(fredgc): provision for different SPOIDs.
|
||||
CdmEngine cdm_engine(&file_system,
|
||||
std::shared_ptr<EngineMetrics>(new EngineMetrics));
|
||||
TestCdmEngine cdm_engine(&file_system,
|
||||
std::shared_ptr<EngineMetrics>(new EngineMetrics));
|
||||
|
||||
CdmResponseType result = cdm_engine.GetProvisioningRequest(
|
||||
cert_type, cert_authority, config_.provisioning_service_certificate(),
|
||||
@@ -387,8 +387,8 @@ void WvCdmTestBase::Provision() {
|
||||
void WvCdmTestBase::EnsureProvisioned() {
|
||||
CdmSessionId session_id;
|
||||
FileSystem file_system;
|
||||
CdmEngine cdm_engine(&file_system,
|
||||
std::shared_ptr<EngineMetrics>(new EngineMetrics));
|
||||
TestCdmEngine cdm_engine(&file_system,
|
||||
std::shared_ptr<EngineMetrics>(new EngineMetrics));
|
||||
CdmResponseType status = cdm_engine.OpenSession(config_.key_system(), nullptr,
|
||||
nullptr, &session_id);
|
||||
if (status == NEED_PROVISIONING) {
|
||||
|
||||
@@ -76,6 +76,27 @@ class WvCdmTestBase : public ::testing::Test {
|
||||
bool binary_provisioning_;
|
||||
};
|
||||
|
||||
// This just makes the constructor public so that we can create one with dummy
|
||||
// metrics and file system.
|
||||
class TestCdmEngine : public CdmEngine {
|
||||
public:
|
||||
TestCdmEngine(FileSystem* file_system,
|
||||
std::shared_ptr<metrics::EngineMetrics> metrics)
|
||||
: CdmEngine(file_system, metrics) {}
|
||||
};
|
||||
|
||||
class WvCdmTestBaseWithEngine : public WvCdmTestBase {
|
||||
public:
|
||||
WvCdmTestBaseWithEngine()
|
||||
: dummy_engine_metrics_(new metrics::EngineMetrics()),
|
||||
cdm_engine_(&file_system_, dummy_engine_metrics_) {}
|
||||
|
||||
protected:
|
||||
FileSystem file_system_;
|
||||
shared_ptr<metrics::EngineMetrics> dummy_engine_metrics_;
|
||||
TestCdmEngine cdm_engine_;
|
||||
};
|
||||
|
||||
class TestCryptoSession : public CryptoSession {
|
||||
public:
|
||||
explicit TestCryptoSession(metrics::CryptoMetrics* crypto_metrics);
|
||||
|
||||
@@ -596,6 +596,9 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
|
||||
case NO_MATCHING_ENTITLEMENT_KEY:
|
||||
*os << "NO_MATCHING_ENTITLEMENT_KEY";
|
||||
break;
|
||||
case NO_SRM_VERSION:
|
||||
*os << "NO_SRM_VERSION";
|
||||
break;
|
||||
case NONCE_GENERATION_ERROR:
|
||||
*os << "NONCE_GENERATION_ERROR";
|
||||
break;
|
||||
@@ -722,6 +725,9 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
|
||||
case RESTORE_OFFLINE_LICENSE_ERROR_2:
|
||||
*os << "RESTORE_OFFLINE_LICENSE_ERROR_2";
|
||||
break;
|
||||
case RESTORE_OFFLINE_LICENSE_ERROR_3:
|
||||
*os << "RESTORE_OFFLINE_LICENSE_ERROR_3";
|
||||
break;
|
||||
case REWRAP_DEVICE_RSA_KEY_ERROR:
|
||||
*os << "REWRAP_DEVICE_RSA_KEY_ERROR";
|
||||
break;
|
||||
|
||||
@@ -21,6 +21,10 @@ const int kConnectTimeoutMs = 15000;
|
||||
const int kWriteTimeoutMs = 12000;
|
||||
const int kReadTimeoutMs = 12000;
|
||||
|
||||
const std::string kGoogleHeaderUpper("X-Google");
|
||||
const std::string kGoogleHeaderLower("x-google");
|
||||
const std::string kCrLf("\r\n");
|
||||
|
||||
// Concatenate all chunks into one blob and returns the response with
|
||||
// header information.
|
||||
void ConcatenateChunkedResponse(const std::string http_response,
|
||||
@@ -37,7 +41,7 @@ void ConcatenateChunkedResponse(const std::string http_response,
|
||||
sscanf(&http_response[chunk_size_pos], "%zx", &chunk_size);
|
||||
if (chunk_size > http_response.size()) {
|
||||
// precaution, in case we misread chunk size
|
||||
LOGE("invalid chunk size %u", chunk_size);
|
||||
LOGE("Invalid chunk size %zu", chunk_size);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -48,7 +52,6 @@ void ConcatenateChunkedResponse(const std::string http_response,
|
||||
// chunk size\r\n
|
||||
// chunk data\r\n
|
||||
// 0\r\n
|
||||
const std::string kCrLf = "\r\n";
|
||||
size_t chunk_pos = http_response.find(kCrLf, chunk_size_pos);
|
||||
modified_response->assign(http_response, 0, chunk_size_pos);
|
||||
|
||||
@@ -61,7 +64,7 @@ void ConcatenateChunkedResponse(const std::string http_response,
|
||||
sscanf(&http_response[chunk_size_pos], "%zx", &chunk_size);
|
||||
if (chunk_size > http_response.size()) {
|
||||
// precaution, in case we misread chunk size
|
||||
LOGE("invalid chunk size %u", chunk_size);
|
||||
LOGE("Invalid chunk size %zu", chunk_size);
|
||||
break;
|
||||
}
|
||||
chunk_pos = http_response.find(kCrLf, chunk_size_pos);
|
||||
@@ -101,11 +104,12 @@ bool UrlRequest::GetResponse(std::string* message) {
|
||||
// non-blocking mode.
|
||||
while (true) {
|
||||
char read_buffer[kReadBufferSize];
|
||||
int bytes = socket_.Read(read_buffer, sizeof(read_buffer), kReadTimeoutMs);
|
||||
const int bytes =
|
||||
socket_.Read(read_buffer, sizeof(read_buffer), kReadTimeoutMs);
|
||||
if (bytes > 0) {
|
||||
response.append(read_buffer, bytes);
|
||||
} else if (bytes < 0) {
|
||||
LOGE("read error, errno = %d", errno);
|
||||
LOGE("Read error, errno = %d", errno);
|
||||
return false;
|
||||
} else {
|
||||
// end of stream.
|
||||
@@ -114,7 +118,9 @@ bool UrlRequest::GetResponse(std::string* message) {
|
||||
}
|
||||
|
||||
ConcatenateChunkedResponse(response, message);
|
||||
LOGV("HTTP response: (%d): %s", message->size(), message->c_str());
|
||||
LOGV("HTTP response from %s://%s:%d%s: (%zu): %s", socket_.scheme().c_str(),
|
||||
socket_.domain_name().c_str(), socket_.port(),
|
||||
socket_.resource_path().c_str(), message->size(), message->c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -131,6 +137,45 @@ int UrlRequest::GetStatusCode(const std::string& response) {
|
||||
return status_code;
|
||||
}
|
||||
|
||||
// static
|
||||
bool UrlRequest::GetDebugHeaderFields(
|
||||
const std::string& response, std::map<std::string, std::string>* fields) {
|
||||
if (fields == nullptr) return false;
|
||||
fields->clear();
|
||||
|
||||
const auto find_next = [&](size_t pos) -> size_t {
|
||||
// Some of Google's HTTPS return header fields in lower case,
|
||||
// this lambda will check for both and return the position that
|
||||
// that is next or npos if none are found.
|
||||
const size_t lower_pos = response.find(kGoogleHeaderLower, pos + 1);
|
||||
const size_t upper_pos = response.find(kGoogleHeaderUpper, pos + 1);
|
||||
if (lower_pos == std::string::npos) return upper_pos;
|
||||
if (upper_pos == std::string::npos || lower_pos < upper_pos)
|
||||
return lower_pos;
|
||||
return upper_pos;
|
||||
};
|
||||
|
||||
// Search is relatively simple, and may pick up additional matches within
|
||||
// the body of the request. This is not anticiapted for the limited use
|
||||
// cases of parsing provisioning/license/renewal responses.
|
||||
for (size_t key_pos = find_next(0); key_pos != std::string::npos;
|
||||
key_pos = find_next(key_pos)) {
|
||||
const size_t end_key_pos = response.find(":", key_pos);
|
||||
const size_t end_value_pos = response.find(kCrLf, key_pos);
|
||||
// Skip if the colon cannot be found. Technically possible to find
|
||||
// "X-Google" inside the value of a nother header field.
|
||||
if (end_key_pos == std::string::npos || end_value_pos == std::string::npos)
|
||||
continue;
|
||||
const size_t value_pos = end_key_pos + 2;
|
||||
if (end_value_pos < value_pos) continue;
|
||||
const std::string key = response.substr(key_pos, end_key_pos - key_pos);
|
||||
const std::string value =
|
||||
response.substr(value_pos, end_value_pos - value_pos);
|
||||
fields->insert({key, value});
|
||||
}
|
||||
return !fields->empty();
|
||||
}
|
||||
|
||||
bool UrlRequest::PostRequestWithPath(const std::string& path,
|
||||
const std::string& data) {
|
||||
std::string request;
|
||||
@@ -160,7 +205,7 @@ bool UrlRequest::PostRequestWithPath(const std::string& path,
|
||||
|
||||
const int ret =
|
||||
socket_.Write(request.c_str(), request.size(), kWriteTimeoutMs);
|
||||
LOGV("HTTP request: (%d): %s", request.size(), b2a_hex(request).c_str());
|
||||
LOGV("HTTP request: (%zu): %s", request.size(), b2a_hex(request).c_str());
|
||||
return ret != -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
#ifndef CDM_TEST_URL_REQUEST_H_
|
||||
#define CDM_TEST_URL_REQUEST_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "disallow_copy_and_assign.h"
|
||||
#include "http_socket.h"
|
||||
|
||||
@@ -27,6 +29,10 @@ class UrlRequest {
|
||||
bool GetResponse(std::string* message);
|
||||
static int GetStatusCode(const std::string& response);
|
||||
|
||||
static bool GetDebugHeaderFields(
|
||||
const std::string& response,
|
||||
std::map<std::string, std::string>* header_fields);
|
||||
|
||||
private:
|
||||
bool PostRequestWithPath(const std::string& path, const std::string& data);
|
||||
|
||||
|
||||
104
core/test/url_request_unittest.cpp
Normal file
104
core/test/url_request_unittest.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#include "url_request.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "test_base.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
namespace {
|
||||
|
||||
// A sample HTTP response which contains an HTTP header with several
|
||||
// standard and non-standard header fields. The fields of interests
|
||||
// those beginning with "X-Google-" or "x-google-".
|
||||
const std::string kSampleResponse =
|
||||
"HTTP/2 301\r\n"
|
||||
"Location: https://www.google.com/\r\b"
|
||||
"Content-Type: text/html; charset=UTF-8\r\n"
|
||||
"X-Google-GFE-Backend-Request-Info: eid=7js14zjC48OpziR0VCF02a0\r\n"
|
||||
"x-google-signals: FRAMEWORK=TEST\r\n"
|
||||
"X-Google-Binary-Version: 322287520\r\n"
|
||||
"X-Google-Request-Cost: 2.50\r\n"
|
||||
"Date: Thu, 23 Jul 2020 22:52:55 GMT\r\n"
|
||||
"Expires: Sat, 22 Aug 2020 22:52:55 GMT\r\n"
|
||||
"Cache-Control: public, max-age=2592000\r\n"
|
||||
"x-google-data-version: 322866295\r\n"
|
||||
"Server: gws\r\n"
|
||||
"X-Google-Debug-Label: /srv/alt/job/service.number/1380\r\n"
|
||||
"Content-Length: 220\r\n"
|
||||
"X-XSS-Protection: 0\r\n"
|
||||
"X-Frame-Options: SAMEORIGIN\r\n"
|
||||
"X-Google-Service: web\r\n"
|
||||
"X-Google-DOS-Service-Trace: main:home\r\n"
|
||||
"Alt-Svc: h3-29=\":443\"; ma=2592000,h3-27=\":443\"; "
|
||||
"ma=2592000,h3-25=\":443\"; ma=2592000,h3-T050=\":443\"; "
|
||||
"ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; "
|
||||
"ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; "
|
||||
"v=\"46,43\"\r\n"
|
||||
"\r\n"
|
||||
"<HTML><HEAD><meta http-equiv=\"content-type\" "
|
||||
"content=\"text/html;charset=utf-8\">\r\n"
|
||||
"<TITLE>301 Moved</TITLE></HEAD><BODY>\r\n"
|
||||
"<H1>301 Moved</H1>\r\n"
|
||||
"The document has moved\r\n"
|
||||
"<A HREF=\"https://www.google.com/\">here</A>.\r\n"
|
||||
"</BODY></HTML>\r\n\r\n";
|
||||
|
||||
// A map containing all the Google debug header fields found in
|
||||
// |kSampleResponse|.
|
||||
const std::map<std::string, std::string> kSampleFields = {
|
||||
{"X-Google-GFE-Backend-Request-Info", "eid=7js14zjC48OpziR0VCF02a0"},
|
||||
{"x-google-signals", "FRAMEWORK=TEST"},
|
||||
{"X-Google-Binary-Version", "322287520"},
|
||||
{"X-Google-Request-Cost", "2.50"},
|
||||
{"x-google-data-version", "322866295"},
|
||||
{"X-Google-Debug-Label", "/srv/alt/job/service.number/1380"},
|
||||
{"X-Google-Service", "web"},
|
||||
{"X-Google-DOS-Service-Trace", "main:home"}};
|
||||
|
||||
// A sample HTTP response which does not contain any special header fields.
|
||||
const std::string kFieldlessResponse =
|
||||
"HTTP/2 301\r\n"
|
||||
"Location: https://www.google.com/\r\b"
|
||||
"Content-Type: text/html; charset=UTF-8\r\n"
|
||||
"Date: Thu, 23 Jul 2020 22:52:55 GMT\r\n"
|
||||
"Content-Length: 220\r\n"
|
||||
"\r\n"
|
||||
"<HTML><HEAD><meta http-equiv=\"content-type\" "
|
||||
"content=\"text/html;charset=utf-8\">\r\n"
|
||||
"<TITLE>301 Moved</TITLE></HEAD><BODY>\r\n"
|
||||
"<H1>301 Moved</H1>\r\n"
|
||||
"The document has moved\r\n"
|
||||
"<A HREF=\"https://www.google.com/\">here</A>.\r\n"
|
||||
"</BODY></HTML>\r\n\r\n";
|
||||
|
||||
} // namespace
|
||||
|
||||
class UrlRequestTest : public WvCdmTestBase {
|
||||
protected:
|
||||
void SetUp() override { WvCdmTestBase::SetUp(); }
|
||||
void TearDown() override {}
|
||||
};
|
||||
|
||||
TEST_F(UrlRequestTest, ParseDebugHeader) {
|
||||
// Output map cannot be null.
|
||||
EXPECT_FALSE(UrlRequest::GetDebugHeaderFields(kSampleResponse, nullptr));
|
||||
std::map<std::string, std::string> fields;
|
||||
// Expect false if no debug information can be determined.
|
||||
EXPECT_FALSE(UrlRequest::GetDebugHeaderFields(kFieldlessResponse, &fields));
|
||||
// Expect success.
|
||||
EXPECT_TRUE(UrlRequest::GetDebugHeaderFields(kSampleResponse, &fields));
|
||||
EXPECT_EQ(kSampleFields.size(), fields.size());
|
||||
for (auto it = kSampleFields.cbegin(); it != kSampleFields.cend(); ++it) {
|
||||
auto field = fields.find(it->first);
|
||||
EXPECT_NE(fields.end(), field);
|
||||
EXPECT_EQ(it->second, field->second) << "Key: \"" << it->first << "\"";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
@@ -688,6 +688,27 @@ TEST_P(UsageTableHeaderInitializationTest, UsageEntriesAtCapacity) {
|
||||
EXPECT_TRUE(usage_table_header_->Init(GetParam(), crypto_session_));
|
||||
}
|
||||
|
||||
TEST_P(UsageTableHeaderInitializationTest,
|
||||
UsageEntries_NoCapacity_UnderMinimum) {
|
||||
crypto_session_->SetMaximumUsageTableEntries(0); // Unlimited.
|
||||
std::vector<CdmUsageEntryInfo> usage_entries = kOverFullUsageEntryInfoVector;
|
||||
constexpr size_t kHalfMinCapacity = kDefaultTableCapacity / 2;
|
||||
usage_entries.resize(kHalfMinCapacity);
|
||||
const SecurityLevel security_level =
|
||||
(GetParam() == kSecurityLevelL3) ? kLevel3 : kLevelDefault;
|
||||
EXPECT_CALL(*device_files_,
|
||||
RetrieveUsageTableInfo(NotNull(), NotNull(), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kUsageTableHeader),
|
||||
SetArgPointee<1>(usage_entries), SetArgPointee<2>(false),
|
||||
Return(true)));
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
LoadUsageTableHeader(security_level, kUsageTableHeader))
|
||||
.WillOnce(Return(NO_ERROR));
|
||||
// No expectations of creating or deleting entries if the number of entries
|
||||
// is less than minimally required capacity.
|
||||
EXPECT_TRUE(usage_table_header_->Init(GetParam(), crypto_session_));
|
||||
}
|
||||
|
||||
TEST_P(UsageTableHeaderInitializationTest, UsageEntries_NoCapacity) {
|
||||
crypto_session_->SetMaximumUsageTableEntries(0); // Unlimited.
|
||||
std::vector<CdmUsageEntryInfo> usage_entries = kOverFullUsageEntryInfoVector;
|
||||
@@ -3999,13 +4020,6 @@ TEST_F(UsageTableHeaderTest, PotentialTableCapacity_Unlimited) {
|
||||
MockUsageTableHeader* mock_usage_table_header = SetUpMock();
|
||||
// Zero indicates that the table size is unlimited.
|
||||
crypto_session_->SetMaximumUsageTableEntries(0u);
|
||||
// Expect calls to make a delete entry.
|
||||
EXPECT_CALL(*crypto_session_, Open(_)).WillOnce(Return(NO_ERROR));
|
||||
const size_t test_index = kUsageEntryInfoVector.size();
|
||||
EXPECT_CALL(*mock_usage_table_header, AddEntry(_, _, _, _, _, NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<5>(test_index), Return(NO_ERROR)));
|
||||
EXPECT_CALL(*mock_usage_table_header, InvalidateEntry(test_index, _, _, _))
|
||||
.WillOnce(Return(NO_ERROR));
|
||||
|
||||
Init(kSecurityLevelL1, kUsageTableHeader, kUsageEntryInfoVector);
|
||||
constexpr size_t kZero = 0u;
|
||||
|
||||
Reference in New Issue
Block a user