Source release 19.1.0
This commit is contained in:
@@ -56,7 +56,7 @@ class MockCdmEngineImpl : public CdmEngine {
|
||||
public:
|
||||
MockCdmEngineImpl(wvutil::FileSystem* file_system,
|
||||
std::shared_ptr<EngineMetrics> metrics)
|
||||
: CdmEngine(file_system, metrics) {}
|
||||
: CdmEngine(file_system, std::move(metrics)) {}
|
||||
MOCK_METHOD(CdmResponseType, OpenSession,
|
||||
(const CdmKeySystem&, CdmClientPropertySet*, const CdmSessionId&,
|
||||
WvCdmEventListener*),
|
||||
@@ -119,7 +119,7 @@ class WvCdmEngineMetricsImplTest : public ::testing::Test {
|
||||
std::shared_ptr<EngineMetrics> engine_metrics(new EngineMetrics);
|
||||
test_cdm_metrics_engine_.reset(
|
||||
new CdmEngineMetricsImpl<StrictMock<MockCdmEngineImpl>>(
|
||||
file_system_.get(), engine_metrics));
|
||||
file_system_.get(), std::move(engine_metrics)));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@@ -301,10 +301,6 @@ void InitVectorConstants() {
|
||||
case 3:
|
||||
kOverFullUsageEntryInfoVector.push_back(kUsageEntryInfoSecureStop2);
|
||||
break;
|
||||
default:
|
||||
kOverFullUsageEntryInfoVector.push_back(
|
||||
kUsageEntryInfoStorageTypeUnknown);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -794,8 +790,8 @@ TEST_P(CdmUsageTableInitializationTest, RestoreUsageTable_AtCapacity) {
|
||||
EXPECT_CALL(*device_files_,
|
||||
RetrieveUsageTableInfo(NotNull(), NotNull(), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kUsageTableHeader),
|
||||
SetArgPointee<1>(usage_entries), SetArgPointee<2>(false),
|
||||
Return(true)));
|
||||
SetArgPointee<1>(std::move(usage_entries)),
|
||||
SetArgPointee<2>(false), Return(true)));
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
LoadUsageTableHeader(security_level, kUsageTableHeader))
|
||||
.WillOnce(Return(CdmResponseType(NO_ERROR)));
|
||||
@@ -822,8 +818,8 @@ TEST_P(CdmUsageTableInitializationTest,
|
||||
EXPECT_CALL(*device_files_,
|
||||
RetrieveUsageTableInfo(NotNull(), NotNull(), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kUsageTableHeader),
|
||||
SetArgPointee<1>(usage_entries), SetArgPointee<2>(false),
|
||||
Return(true)));
|
||||
SetArgPointee<1>(std::move(usage_entries)),
|
||||
SetArgPointee<2>(false), Return(true)));
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
LoadUsageTableHeader(security_level, kUsageTableHeader))
|
||||
.WillOnce(Return(CdmResponseType(NO_ERROR)));
|
||||
@@ -3588,7 +3584,7 @@ TEST_F(CdmUsageTableTest, StaleHeader) {
|
||||
EXPECT_CALL(*device_files_,
|
||||
RetrieveUsageTableInfo(NotNull(), NotNull(), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kUsageTableHeader),
|
||||
SetArgPointee<1>(entry_info_list),
|
||||
SetArgPointee<1>(std::move(entry_info_list)),
|
||||
SetArgPointee<2>(false), Return(true)));
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
LoadUsageTableHeader(kLevelDefault, kUsageTableHeader))
|
||||
@@ -4136,6 +4132,7 @@ TEST_F(CdmUsageTableTest, DetermineLicenseToRemove_BasicPriorities) {
|
||||
CdmUsageEntryInfo streaming_entry_info;
|
||||
streaming_entry_info.storage_type = kStorageUsageInfo;
|
||||
streaming_entry_info.last_use_time = kLruBaseTime;
|
||||
streaming_entry_info.offline_license_expiry_time = 0;
|
||||
usage_entry_info_list.push_back(streaming_entry_info);
|
||||
constexpr UsageEntryIndex streaming_entry_index = 2;
|
||||
|
||||
@@ -4144,6 +4141,7 @@ TEST_F(CdmUsageTableTest, DetermineLicenseToRemove_BasicPriorities) {
|
||||
unknown_entry_info.storage_type = kStorageTypeUnknown;
|
||||
// Should be chosen regardless of |last_use_time|.
|
||||
unknown_entry_info.last_use_time = kCurrentTime;
|
||||
unknown_entry_info.offline_license_expiry_time = 0;
|
||||
usage_entry_info_list.push_back(unknown_entry_info);
|
||||
constexpr UsageEntryIndex unknown_entry_index = 3;
|
||||
|
||||
|
||||
@@ -201,7 +201,7 @@ class MockCryptoSession : public TestCryptoSession {
|
||||
MOCK_METHOD(CdmSecurityLevel, GetSecurityLevel, (), (override));
|
||||
MOCK_METHOD(CdmResponseType, LoadProvisioning,
|
||||
(const std::string&, const std::string&, const std::string&,
|
||||
std::string*),
|
||||
const std::string&, std::string*),
|
||||
(override));
|
||||
};
|
||||
|
||||
@@ -458,7 +458,7 @@ TEST_P(CertificateProvisioningTest, ProvisioningResponseSuccess) {
|
||||
.WillByDefault(Return(kSecurityLevelL3));
|
||||
EXPECT_CALL(*crypto_session, LoadProvisioning)
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArgPointee<3>(kWrappedPrivateKey),
|
||||
.WillOnce(DoAll(SetArgPointee<4>(kWrappedPrivateKey),
|
||||
Return(CdmResponseType(NO_ERROR))));
|
||||
|
||||
MockFile* file = new MockFile();
|
||||
|
||||
@@ -85,7 +85,7 @@ class CoreIntegrationTest : public WvCdmTestBaseWithEngine {
|
||||
const std::string origin, std::string* spoid,
|
||||
std::string* drm_certificate_serial_number) {
|
||||
std::string name = app_package_name + origin;
|
||||
return Provision(name, spoid, drm_certificate_serial_number);
|
||||
return Provision(std::move(name), spoid, drm_certificate_serial_number);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -5206,7 +5206,7 @@ TEST_P(DeviceFilesStoreTest, StoreLicense) {
|
||||
EXPECT_CALL(file_system, Open(StrEq(license_path), IsCreateFileFlagSet()))
|
||||
.WillOnce(Return(ByMove(std::unique_ptr<File>(file))));
|
||||
EXPECT_CALL(*file, Write(_, _))
|
||||
.With(AllArgs(StrAndLenContains(expected_substrings)))
|
||||
.With(AllArgs(StrAndLenContains(std::move(expected_substrings))))
|
||||
.WillOnce(ReturnArg<1>());
|
||||
EXPECT_CALL(*file, Read(_, _)).Times(0);
|
||||
|
||||
@@ -5226,7 +5226,7 @@ TEST_P(DeviceFilesStoreTest, StoreLicense) {
|
||||
kLicenseTestData[license_num].playback_start_time,
|
||||
kLicenseTestData[license_num].last_playback_time,
|
||||
kLicenseTestData[license_num].grace_period_end_time,
|
||||
app_parameters,
|
||||
std::move(app_parameters),
|
||||
kLicenseTestData[license_num].usage_entry,
|
||||
kLicenseTestData[license_num].usage_entry_index,
|
||||
kLicenseTestData[license_num].drm_certificate,
|
||||
@@ -5271,7 +5271,7 @@ TEST_F(DeviceFilesTest, StoreLicenses) {
|
||||
.WillOnce(Return(ByMove(std::unique_ptr<File>(file))));
|
||||
|
||||
EXPECT_CALL(*file, Write(_, _))
|
||||
.With(AllArgs(StrAndLenContains(expected_substrings)))
|
||||
.With(AllArgs(StrAndLenContains(std::move(expected_substrings))))
|
||||
.WillOnce(ReturnArg<1>());
|
||||
EXPECT_CALL(*file, Read(_, _)).Times(0);
|
||||
}
|
||||
@@ -5295,7 +5295,7 @@ TEST_F(DeviceFilesTest, StoreLicenses) {
|
||||
kLicenseTestData[i].playback_start_time,
|
||||
kLicenseTestData[i].last_playback_time,
|
||||
kLicenseTestData[i].grace_period_end_time,
|
||||
app_parameters,
|
||||
std::move(app_parameters),
|
||||
kLicenseTestData[i].usage_entry,
|
||||
kLicenseTestData[i].usage_entry_index,
|
||||
kLicenseTestData[i].drm_certificate,
|
||||
@@ -5980,7 +5980,7 @@ TEST_P(DeviceFilesUsageInfoListTest, UsageInfoList) {
|
||||
}
|
||||
|
||||
EXPECT_CALL(file_system, List(StrEq(device_base_path_), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(file_list), Return(true)));
|
||||
.WillOnce(DoAll(SetArgPointee<1>(std::move(file_list)), Return(true)));
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
EXPECT_TRUE(device_files.Init(kSecurityLevelL1));
|
||||
@@ -6030,7 +6030,7 @@ TEST_P(DeviceFilesUsageInfoTest, Store) {
|
||||
EXPECT_CALL(file_system, Open(StrEq(path), _))
|
||||
.WillOnce(Return(ByMove(std::unique_ptr<File>(file))));
|
||||
EXPECT_CALL(*file, Write(_, _))
|
||||
.With(AllArgs(StrAndLenContains(usage_data_fields)))
|
||||
.With(AllArgs(StrAndLenContains(std::move(usage_data_fields))))
|
||||
.WillOnce(ReturnArg<1>());
|
||||
|
||||
DeviceFiles device_files(&file_system);
|
||||
@@ -6336,7 +6336,7 @@ TEST_P(DeviceFilesUsageInfoTest, UpdateUsageInfo) {
|
||||
.WillOnce(Return(ByMove(std::unique_ptr<File>(next_file))));
|
||||
|
||||
EXPECT_CALL(*next_file, Write(_, _))
|
||||
.With(AllArgs(StrAndLenContains(usage_data_fields)))
|
||||
.With(AllArgs(StrAndLenContains(std::move(usage_data_fields))))
|
||||
.WillOnce(ReturnArg<1>());
|
||||
}
|
||||
|
||||
@@ -6451,7 +6451,7 @@ TEST_P(DeviceFilesUsageTableTest, Store) {
|
||||
EXPECT_CALL(file_system, Open(StrEq(path), _))
|
||||
.WillOnce(Return(ByMove(std::unique_ptr<File>(file))));
|
||||
EXPECT_CALL(*file, Write(_, _))
|
||||
.With(AllArgs(StrAndLenContains(entry_data)))
|
||||
.With(AllArgs(StrAndLenContains(std::move(entry_data))))
|
||||
.WillOnce(ReturnArg<1>());
|
||||
EXPECT_CALL(*file, Read(_, _)).Times(0);
|
||||
|
||||
|
||||
@@ -1062,7 +1062,6 @@ class CdmUseCase_LicenseWithRenewal : public RenewalTest {
|
||||
|
||||
void SetUp() override {
|
||||
RenewalTest::SetUp();
|
||||
if(Test::IsSkipped()) return;
|
||||
const uint64_t next_renewal =
|
||||
start_of_playback_ + initial_policy_.renewal_delay;
|
||||
// Allow playback within the initial renewal window.
|
||||
@@ -1268,7 +1267,6 @@ class CdmUseCase_LicenseWithRenewalPlayback : public RenewalTest {
|
||||
|
||||
void SetUp() override {
|
||||
RenewalTest::SetUp();
|
||||
if(Test::IsSkipped()) return;
|
||||
uint64_t next_renewal = start_of_playback_ + initial_policy_.renewal_delay;
|
||||
// Allow playback within the initial renewal window.
|
||||
SleepUntil(start_of_playback_);
|
||||
@@ -1586,7 +1584,6 @@ class CdmUseCase_RenewOnLicenseLoad : public RenewalTest {
|
||||
|
||||
void SetUp() override {
|
||||
RenewalTest::SetUp();
|
||||
if(Test::IsSkipped()) return;
|
||||
// The Renew on License Load feature is only supported on v18+ servers.
|
||||
if (config_.ServerOlderThan(18) ||
|
||||
wvoec::global_features.api_version < 18) {
|
||||
@@ -1734,7 +1731,6 @@ class CdmUseCase_Heartbeat : public RenewalTest {
|
||||
|
||||
void SetUp() override {
|
||||
RenewalTest::SetUp();
|
||||
if(Test::IsSkipped()) return;
|
||||
const uint64_t next_renewal =
|
||||
start_of_playback_ + initial_policy_.renewal_delay;
|
||||
// Allow playback within the initial renewal window.
|
||||
|
||||
@@ -275,18 +275,14 @@ bool FakeProvisioningServer::MakeResponse(
|
||||
// Next, we derive the keys from the keybox device key. This is Provisioning
|
||||
// 2.0 specific.
|
||||
// TODO(b/141438127): Add support for provisioing 3.0.
|
||||
std::string mac_context;
|
||||
GenerateMacContext(serialized_message, &mac_context);
|
||||
std::vector<uint8_t> mac_context_v(mac_context.begin(), mac_context.end());
|
||||
std::string enc_context;
|
||||
GenerateEncryptContext(serialized_message, &enc_context);
|
||||
std::vector<uint8_t> enc_context_v(enc_context.begin(), enc_context.end());
|
||||
wvoec::KeyDeriver key_deriver;
|
||||
std::vector<uint8_t> serialized_message_v(serialized_message.begin(),
|
||||
serialized_message.end());
|
||||
// Not only is this Prov 2.0 specific, it assumes the device is using the
|
||||
// standard test keybox.
|
||||
key_deriver.DeriveKeys(wvoec::kTestKeybox.device_key_,
|
||||
sizeof(wvoec::kTestKeybox.device_key_), mac_context_v,
|
||||
enc_context_v);
|
||||
sizeof(wvoec::kTestKeybox.device_key_),
|
||||
serialized_message_v);
|
||||
|
||||
// Create a structure to hold the RSA private key. This is used by the key
|
||||
// deriver to encrypt the key.
|
||||
|
||||
@@ -309,6 +309,7 @@ bool HttpSocket::Connect(int timeout_in_ms) {
|
||||
if (socket_fd_ < 0) {
|
||||
LOGE("Cannot open socket %s (port %s): errno = %d", domain_name_.c_str(),
|
||||
port_.c_str(), GetError());
|
||||
freeaddrinfo(addr_info);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -318,6 +319,7 @@ bool HttpSocket::Connect(int timeout_in_ms) {
|
||||
if (ioctlsocket(socket_fd_, FIONBIO, &mode) != 0) {
|
||||
LOGE("ioctlsocket error %s (port %s), wsa error = %d", domain_name_.c_str(),
|
||||
port_.c_str(), WSAGetLastError());
|
||||
freeaddrinfo(addr_info);
|
||||
CloseSocket();
|
||||
return false;
|
||||
}
|
||||
@@ -326,12 +328,14 @@ bool HttpSocket::Connect(int timeout_in_ms) {
|
||||
if (original_flags == -1) {
|
||||
LOGE("fcntl error %s (port %s), errno = %d", domain_name_.c_str(),
|
||||
port_.c_str(), errno);
|
||||
freeaddrinfo(addr_info);
|
||||
CloseSocket();
|
||||
return false;
|
||||
}
|
||||
if (fcntl(socket_fd_, F_SETFL, original_flags | O_NONBLOCK) == -1) {
|
||||
LOGE("fcntl error %s (port %s), errno = %d", domain_name_.c_str(),
|
||||
port_.c_str(), errno);
|
||||
freeaddrinfo(addr_info);
|
||||
CloseSocket();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -75,6 +75,13 @@ void LicenseHolder::ReloadLicense() {
|
||||
<< "Failed to reload license for " << content_id();
|
||||
}
|
||||
|
||||
void LicenseHolder::FailReloadLicense() {
|
||||
const CdmResponseType status =
|
||||
cdm_engine_->RestoreKey(session_id_, key_set_id_);
|
||||
ASSERT_NE(KEY_ADDED, status)
|
||||
<< "Unexpected success loading license for " << content_id();
|
||||
}
|
||||
|
||||
void LicenseHolder::GenerateAndPostRenewalRequest(
|
||||
const std::string& policy_id) {
|
||||
event_listener_.set_renewal_needed(false);
|
||||
@@ -86,28 +93,70 @@ void LicenseHolder::GenerateAndPostRenewalRequest(
|
||||
MessageDumper::DumpRenewalRequest(request);
|
||||
}
|
||||
const std::string url = MakeUrl(config_.renewal_server(), policy_id);
|
||||
renewal_in_flight_.reset(new UrlRequest(url));
|
||||
ASSERT_TRUE(renewal_in_flight_->is_connected())
|
||||
request_in_flight_.reset(new UrlRequest(url));
|
||||
ASSERT_TRUE(request_in_flight_->is_connected())
|
||||
<< "Failed for " << content_id();
|
||||
renewal_in_flight_->PostRequest(request.message);
|
||||
request_in_flight_->PostRequest(request.message);
|
||||
}
|
||||
|
||||
void LicenseHolder::FetchRenewal() {
|
||||
ASSERT_NE(renewal_in_flight_, nullptr) << "Failed for " << content_id();
|
||||
ASSERT_NE(request_in_flight_, nullptr) << "Failed for " << content_id();
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
renewal_in_flight_->AssertOkResponse(&renewal_response_))
|
||||
request_in_flight_->AssertOkResponse(&request_response_))
|
||||
<< "Renewal failed for " << content_id();
|
||||
}
|
||||
|
||||
void LicenseHolder::LoadRenewal() {
|
||||
LicenseRequest license_request;
|
||||
license_request.GetDrmMessage(renewal_response_, renewal_message_);
|
||||
license_request.GetDrmMessage(request_response_, request_message_);
|
||||
if (config_.dump_golden_data()) {
|
||||
MessageDumper::DumpRenewal(renewal_message_);
|
||||
MessageDumper::DumpRenewal(request_message_);
|
||||
}
|
||||
EXPECT_EQ(KEY_ADDED, cdm_engine_->RenewKey(session_id_, renewal_message_))
|
||||
EXPECT_EQ(KEY_ADDED, cdm_engine_->RenewKey(session_id_, request_message_))
|
||||
<< "Failed for " << content_id();
|
||||
}
|
||||
|
||||
void LicenseHolder::GenerateAndPostReleaseRequest(
|
||||
const std::string& policy_id) {
|
||||
event_listener_.set_renewal_needed(false);
|
||||
CdmKeyRequest request;
|
||||
CdmAppParameterMap empty_app_parameters;
|
||||
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();
|
||||
const CdmResponseType result = cdm_engine_->GenerateKeyRequest(
|
||||
session_id_, key_set_id_, init_data, kLicenseTypeRelease,
|
||||
empty_app_parameters, &request);
|
||||
ASSERT_EQ(KEY_MESSAGE, result) << "Failed for " << content_id();
|
||||
if (config_.dump_golden_data()) {
|
||||
// TODO (b/295956275) vickymin: write DumpReleaseRequest function
|
||||
// MessageDumper::DumpReleaseRequest(request);
|
||||
}
|
||||
const std::string url = MakeUrl(config_.renewal_server(), policy_id);
|
||||
request_in_flight_.reset(new UrlRequest(url));
|
||||
ASSERT_TRUE(request_in_flight_->is_connected())
|
||||
<< "Failed for " << content_id();
|
||||
request_in_flight_->PostRequest(request.message);
|
||||
}
|
||||
|
||||
void LicenseHolder::FetchRelease() {
|
||||
ASSERT_NE(request_in_flight_, nullptr) << "Failed for " << content_id();
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
request_in_flight_->AssertOkResponse(&request_response_))
|
||||
<< "Renewal failed for " << content_id();
|
||||
}
|
||||
|
||||
void LicenseHolder::LoadRelease() {
|
||||
LicenseRequest license_request;
|
||||
license_request.GetDrmMessage(request_response_, request_message_);
|
||||
if (config_.dump_golden_data()) {
|
||||
// TODO (b/295956275) vickymin: write DumpRelease function
|
||||
// MessageDumper::DumpRelease(request_message_);
|
||||
}
|
||||
}
|
||||
|
||||
void LicenseHolder::RemoveLicense() {
|
||||
EXPECT_EQ(NO_ERROR, cdm_engine_->RemoveLicense(session_id_))
|
||||
<< "Failed for " << content_id();
|
||||
|
||||
@@ -66,12 +66,20 @@ class LicenseHolder {
|
||||
// ReloadLicense(). Also, the key_set_id must have been set previously. The
|
||||
// key_set_id is set by calling LoadLicense(), or by calling set_key_set_id().
|
||||
void ReloadLicense();
|
||||
// Attempt to reload a license, but expect a failure.
|
||||
void FailReloadLicense();
|
||||
// Generate the renewal request, and send it to the server.
|
||||
void GenerateAndPostRenewalRequest(const std::string& policy_id);
|
||||
// Fetch the renewal response. This can add a few seconds of latency.
|
||||
void FetchRenewal();
|
||||
// Load the renewal response that was fetched in FetchRenewal().
|
||||
void LoadRenewal();
|
||||
// Generate the release request, and send it to the server.
|
||||
void GenerateAndPostReleaseRequest(const std::string& policy_id);
|
||||
// Fetch the release response. This can add a few seconds of latency.
|
||||
void FetchRelease();
|
||||
// Load the release response that was fetched in FetchRelease().
|
||||
void LoadRelease();
|
||||
// Releases the license and frees up entry in usage table.
|
||||
void RemoveLicense();
|
||||
|
||||
@@ -118,9 +126,9 @@ class LicenseHolder {
|
||||
CdmEngine* cdm_engine_ = nullptr;
|
||||
const ConfigTestEnv& config_;
|
||||
SimpleEventListener event_listener_;
|
||||
std::unique_ptr<UrlRequest> renewal_in_flight_;
|
||||
std::string renewal_message_;
|
||||
std::string renewal_response_;
|
||||
std::unique_ptr<UrlRequest> request_in_flight_;
|
||||
std::string request_message_;
|
||||
std::string request_response_;
|
||||
|
||||
// Generate the license request.
|
||||
void GenerateKeyRequest(const InitializationData& init_data,
|
||||
|
||||
@@ -136,7 +136,6 @@ const std::string kFakeKeyTooLong =
|
||||
const std::string kFakeKeyTooShort = a2bs_hex("06e247e7f924208011");
|
||||
const std::string kFakeIv = a2bs_hex("3d515a3ee0be1687080ac59da9e0d69a");
|
||||
const std::string kFakeBuildInfo = "Mock Crypto Session - License Test";
|
||||
const uint32_t kDefaultOemCryptoVersion = 18;
|
||||
|
||||
class MockCryptoSession : public TestCryptoSession {
|
||||
public:
|
||||
@@ -207,7 +206,7 @@ class CdmLicenseTestPeer : public CdmLicense {
|
||||
|
||||
using CdmLicense::HandleNewEntitledKeys;
|
||||
|
||||
void set_entitlement_keys(License license) {
|
||||
void set_entitlement_keys(const License& license) {
|
||||
entitlement_keys_.CopyFrom(license.key());
|
||||
}
|
||||
};
|
||||
@@ -216,85 +215,84 @@ class CdmLicenseTest : public WvCdmTestBase {
|
||||
protected:
|
||||
CdmLicenseTest(const std::string& pssh = (kCencInitDataHdr + kCencPssh))
|
||||
: pssh_(pssh) {}
|
||||
|
||||
void SetUp() override {
|
||||
WvCdmTestBase::SetUp();
|
||||
crypto_session_.reset(new MockCryptoSession(&crypto_metrics_));
|
||||
clock_ = new MockClock();
|
||||
crypto_session_ = new MockCryptoSession(&crypto_metrics_);
|
||||
init_data_ = new InitializationData(CENC_INIT_DATA_FORMAT, pssh_);
|
||||
policy_engine_ = new MockPolicyEngine(crypto_session_);
|
||||
|
||||
ON_CALL(*crypto_session_, GetSupportedCertificateTypes(NotNull()))
|
||||
.WillByDefault(
|
||||
DoAll(SetArgPointee<0>(kDefaultSupportedCertTypes), Return(true)));
|
||||
// PolicyEngine will call GetApiVersion() on creation.
|
||||
EXPECT_CALL(*crypto_session_, GetApiVersion(NotNull()))
|
||||
.WillRepeatedly(
|
||||
DoAll(SetArgPointee<0>(kDefaultOemCryptoVersion), Return(true)));
|
||||
|
||||
policy_engine_.reset(new MockPolicyEngine(crypto_session_.get()));
|
||||
|
||||
init_data_ = InitializationData(CENC_INIT_DATA_FORMAT, pssh_);
|
||||
|
||||
clock_ = new MockClock();
|
||||
cdm_license_.reset(new CdmLicenseTestPeer(kCdmSessionId, clock_));
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
// Nullify pointers for objects owned by CdmLicense.
|
||||
clock_ = nullptr;
|
||||
|
||||
cdm_license_.reset();
|
||||
|
||||
// Release mock objects used by the CdmLicense.
|
||||
// Order is important.
|
||||
policy_engine_.reset();
|
||||
crypto_session_.reset();
|
||||
delete cdm_license_;
|
||||
delete policy_engine_;
|
||||
delete init_data_;
|
||||
delete crypto_session_;
|
||||
delete clock_;
|
||||
}
|
||||
|
||||
metrics::CryptoMetrics crypto_metrics_;
|
||||
MockClock* clock_ = nullptr; // Owned by |cdm_license_|.
|
||||
std::unique_ptr<CdmLicenseTestPeer> cdm_license_;
|
||||
std::unique_ptr<MockPolicyEngine> policy_engine_;
|
||||
std::unique_ptr<MockCryptoSession> crypto_session_;
|
||||
virtual void CreateCdmLicense() {
|
||||
cdm_license_ = new CdmLicenseTestPeer(kCdmSessionId, clock_);
|
||||
clock_ = nullptr;
|
||||
}
|
||||
|
||||
InitializationData init_data_;
|
||||
CdmLicenseTestPeer* cdm_license_ = nullptr;
|
||||
MockClock* clock_ = nullptr;
|
||||
metrics::CryptoMetrics crypto_metrics_;
|
||||
MockCryptoSession* crypto_session_ = nullptr;
|
||||
InitializationData* init_data_ = nullptr;
|
||||
MockPolicyEngine* policy_engine_ = nullptr;
|
||||
std::string pssh_;
|
||||
};
|
||||
|
||||
TEST_F(CdmLicenseTest, InitSuccess) {
|
||||
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
|
||||
|
||||
CreateCdmLicense();
|
||||
EXPECT_TRUE(cdm_license_->Init(false, kEmptyServiceCertificate,
|
||||
crypto_session_.get(), policy_engine_.get()));
|
||||
crypto_session_, policy_engine_));
|
||||
}
|
||||
|
||||
TEST_F(CdmLicenseTest, InitFail_CryptoSessionNull) {
|
||||
CreateCdmLicense();
|
||||
EXPECT_FALSE(cdm_license_->Init(false, kEmptyServiceCertificate, nullptr,
|
||||
policy_engine_.get()));
|
||||
policy_engine_));
|
||||
}
|
||||
|
||||
TEST_F(CdmLicenseTest, InitFail_PolicyEngineNull) {
|
||||
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
|
||||
|
||||
CreateCdmLicense();
|
||||
EXPECT_FALSE(cdm_license_->Init(false, kEmptyServiceCertificate,
|
||||
crypto_session_.get(), nullptr));
|
||||
crypto_session_, nullptr));
|
||||
}
|
||||
|
||||
TEST_F(CdmLicenseTest, InitWithEmptyServiceCert) {
|
||||
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
|
||||
|
||||
CreateCdmLicense();
|
||||
EXPECT_TRUE(cdm_license_->Init(true, kEmptyServiceCertificate,
|
||||
crypto_session_.get(), policy_engine_.get()));
|
||||
crypto_session_, policy_engine_));
|
||||
}
|
||||
|
||||
TEST_F(CdmLicenseTest, InitWithInvalidServiceCert) {
|
||||
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
|
||||
|
||||
CreateCdmLicense();
|
||||
EXPECT_FALSE(cdm_license_->Init(true, kInvalidServiceCertificate,
|
||||
crypto_session_.get(), policy_engine_.get()));
|
||||
crypto_session_, policy_engine_));
|
||||
}
|
||||
|
||||
TEST_F(CdmLicenseTest, InitWithServiceCert) {
|
||||
EXPECT_CALL(*crypto_session_, IsOpen()).WillOnce(Return(true));
|
||||
|
||||
CreateCdmLicense();
|
||||
EXPECT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate,
|
||||
crypto_session_.get(), policy_engine_.get()));
|
||||
crypto_session_, policy_engine_));
|
||||
}
|
||||
|
||||
TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) {
|
||||
@@ -337,14 +335,15 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) {
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(kWatermarkingConfigurable), Return(true)));
|
||||
|
||||
CreateCdmLicense();
|
||||
EXPECT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate,
|
||||
crypto_session_.get(), policy_engine_.get()));
|
||||
crypto_session_, policy_engine_));
|
||||
|
||||
CdmAppParameterMap app_parameters;
|
||||
CdmKeyMessage signed_request;
|
||||
std::string server_url;
|
||||
EXPECT_EQ(cdm_license_->PrepareKeyRequest(
|
||||
init_data_, kToken, kLicenseTypeStreaming, app_parameters,
|
||||
*init_data_, kToken, kLicenseTypeStreaming, app_parameters,
|
||||
&signed_request, &server_url),
|
||||
KEY_MESSAGE);
|
||||
|
||||
@@ -428,6 +427,7 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) {
|
||||
EXPECT_EQ(kLicenseStartTime, license_request.request_time());
|
||||
EXPECT_EQ(video_widevine::VERSION_2_1, license_request.protocol_version());
|
||||
EXPECT_EQ(kNonce, license_request.key_control_nonce());
|
||||
EXPECT_FALSE(license_request.client_version().empty());
|
||||
}
|
||||
|
||||
TEST_F(CdmLicenseTest, PrepareKeyRequestValidationV15) {
|
||||
@@ -470,14 +470,15 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidationV15) {
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(kWatermarkingNotSupported), Return(true)));
|
||||
|
||||
CreateCdmLicense();
|
||||
EXPECT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate,
|
||||
crypto_session_.get(), policy_engine_.get()));
|
||||
crypto_session_, policy_engine_));
|
||||
|
||||
CdmAppParameterMap app_parameters;
|
||||
CdmKeyMessage signed_request;
|
||||
std::string server_url;
|
||||
EXPECT_EQ(cdm_license_->PrepareKeyRequest(
|
||||
init_data_, kToken, kLicenseTypeStreaming, app_parameters,
|
||||
*init_data_, kToken, kLicenseTypeStreaming, app_parameters,
|
||||
&signed_request, &server_url),
|
||||
KEY_MESSAGE);
|
||||
|
||||
@@ -561,6 +562,7 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidationV15) {
|
||||
EXPECT_EQ(kLicenseStartTime, license_request.request_time());
|
||||
EXPECT_EQ(video_widevine::VERSION_2_1, license_request.protocol_version());
|
||||
EXPECT_EQ(kNonce, license_request.key_control_nonce());
|
||||
EXPECT_FALSE(license_request.client_version().empty());
|
||||
}
|
||||
|
||||
struct EntitledKeyVariant {
|
||||
@@ -614,8 +616,9 @@ TEST_P(CdmLicenseEntitledKeyTest, LoadsEntitledKeys) {
|
||||
}
|
||||
|
||||
// Set up the CdmLicense with the mocks and fake entitlement key
|
||||
EXPECT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate,
|
||||
crypto_session_.get(), policy_engine_.get()));
|
||||
CreateCdmLicense();
|
||||
ASSERT_TRUE(cdm_license_->Init(true, kDefaultServiceCertificate,
|
||||
crypto_session_, policy_engine_));
|
||||
cdm_license_->set_entitlement_keys(entitlement_license);
|
||||
|
||||
// Call the function under test and check its return value
|
||||
|
||||
@@ -34,9 +34,10 @@ void DumpHeader(std::ofstream* out, const std::string& type) {
|
||||
|
||||
void DumpHex(std::ofstream* out, const std::string& name,
|
||||
const std::string& value) {
|
||||
const auto out_flags = out->flags();
|
||||
*out << "const uint8_t " << name << "_raw[] = {\n";
|
||||
*out << " ";
|
||||
for (unsigned int i = 0; i < value.length(); i++) {
|
||||
for (size_t i = 0; i < value.length(); i++) {
|
||||
if ((i > 0) && (i % 10 == 0)) *out << "\n ";
|
||||
uint8_t c = value[i];
|
||||
*out << "0x" << std::hex << std::setw(2) << std::setfill('0') << int(c)
|
||||
@@ -46,7 +47,7 @@ void DumpHex(std::ofstream* out, const std::string& name,
|
||||
*out << name << "_ = std::string (\n"
|
||||
<< " reinterpret_cast<const char *>(" << name << "_raw), \n"
|
||||
<< " sizeof(" << name << "_raw));\n";
|
||||
*out << std::dec; // Turn off hex when we're done.
|
||||
out->flags(out_flags); // Restore flags when we're done.
|
||||
}
|
||||
|
||||
void LogTimer(const char* field, bool set, int64_t time) {
|
||||
@@ -251,7 +252,7 @@ void MessageDumper::DumpProvisioningRequest(
|
||||
void MessageDumper::DumpProvisioning(const CdmProvisioningResponse& response) {
|
||||
if (wvoec::global_features.derive_key_method ==
|
||||
wvoec::DeviceFeatures::TEST_PROVISION_40) {
|
||||
LOGD("Provisioning 4.0 does not have a v17 core message.");
|
||||
LOGD("Provisioning 4.0 does not have a core message.");
|
||||
} else {
|
||||
SignedProvisioningMessage signed_response;
|
||||
if (!signed_response.ParseFromString(response)) {
|
||||
|
||||
@@ -135,7 +135,7 @@ class ParallelCdmTest : public WvCdmTestBaseWithEngine,
|
||||
url.c_str());
|
||||
HttpHeaderFields fields;
|
||||
if (url_request.GetDebugHeaderFields(http_response, &fields)) {
|
||||
for (auto field : fields) {
|
||||
for (const auto& field : fields) {
|
||||
LOGD(" %s: %s", field.first.c_str(), field.second.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,11 +210,12 @@ class PolicyEngineTest : public WvCdmTestBase {
|
||||
void ExpectSessionKeysChange(CdmKeyStatus expected_key_status,
|
||||
bool expected_has_new_usable_key,
|
||||
KeyId expected_keyid) {
|
||||
EXPECT_CALL(mock_event_listener_,
|
||||
OnSessionKeysChange(kSessionId,
|
||||
UnorderedElementsAre(Pair(
|
||||
expected_keyid, expected_key_status)),
|
||||
expected_has_new_usable_key));
|
||||
EXPECT_CALL(
|
||||
mock_event_listener_,
|
||||
OnSessionKeysChange(kSessionId,
|
||||
UnorderedElementsAre(Pair(std::move(expected_keyid),
|
||||
expected_key_status)),
|
||||
expected_has_new_usable_key));
|
||||
}
|
||||
|
||||
void ExpectSessionKeysChange(CdmKeyStatus expected_key1_status,
|
||||
@@ -266,7 +267,7 @@ class PolicyEngineTestV18 : public PolicyEngineTest {
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(PolicyEngineTestV16, NoLicense) {
|
||||
TEST_F(PolicyEngineTest, NoLicense) {
|
||||
EXPECT_FALSE(policy_engine_->CanDecryptContent(kKeyId));
|
||||
}
|
||||
|
||||
@@ -2825,10 +2826,6 @@ TEST_F(PolicyEngineTestV16, PlaybackOk_RestoreWithoutPlaybackTimes) {
|
||||
EXPECT_TRUE(policy_engine_->CanDecryptContent(kKeyId));
|
||||
}
|
||||
|
||||
TEST_F(PolicyEngineTestV18, NoLicense) {
|
||||
EXPECT_FALSE(policy_engine_->CanDecryptContent(kKeyId));
|
||||
}
|
||||
|
||||
// These tests exercise license policy when OEMCrypto supports v18.
|
||||
// The following scenarios are from the duration-and-renewal doc.
|
||||
// Verifies correct reporting of events, OnSessionRenewalNeeded,
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "provisioning_holder.h"
|
||||
#include "test_base.h"
|
||||
#include "test_printers.h"
|
||||
#include "test_sleep.h"
|
||||
#include "wv_cdm_types.h"
|
||||
|
||||
namespace wvcdm {
|
||||
@@ -76,10 +77,67 @@ TEST_F(CorePIGTest, OfflineWithPST) {
|
||||
ASSERT_NO_FATAL_FAILURE(holder.CloseSession());
|
||||
}
|
||||
|
||||
// This test verifies that the system can download and install license with a
|
||||
// key that requires secure buffers. It also verifies that we cannot decrypt to
|
||||
// a non-secure buffer using this key, but that we can decrypt to a secure
|
||||
// buffer, if the test harness supports secure buffers.
|
||||
TEST_F(CorePIGTest, OfflineMultipleLicensesWithDefrag) {
|
||||
const KeyId key_id = "0000000000000000";
|
||||
|
||||
// 1. Open a session, load license, close session
|
||||
LicenseHolder holder1("CDM_OfflineWithPST", &cdm_engine_, config_);
|
||||
holder1.set_can_persist(true);
|
||||
ASSERT_NO_FATAL_FAILURE(holder1.OpenSession());
|
||||
ASSERT_NO_FATAL_FAILURE(holder1.FetchLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(holder1.LoadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(holder1.CloseSession());
|
||||
|
||||
// 2. Open a session, load license, keep session open
|
||||
LicenseHolder holder2("CDM_OfflineWithPST", &cdm_engine_, config_);
|
||||
holder2.set_can_persist(true);
|
||||
ASSERT_NO_FATAL_FAILURE(holder2.OpenSession());
|
||||
ASSERT_NO_FATAL_FAILURE(holder2.FetchLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(holder2.LoadLicense());
|
||||
|
||||
// 3. Remove first license
|
||||
ASSERT_NO_FATAL_FAILURE(holder1.OpenSession());
|
||||
ASSERT_NO_FATAL_FAILURE(holder1.ReloadLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(holder1.RemoveLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(holder1.CloseSession());
|
||||
|
||||
// 4. Open a session, load license
|
||||
LicenseHolder holder3("CDM_OfflineWithPST", &cdm_engine_, config_);
|
||||
holder3.set_can_persist(true);
|
||||
ASSERT_NO_FATAL_FAILURE(holder3.OpenSession());
|
||||
ASSERT_NO_FATAL_FAILURE(holder3.FetchLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(holder3.LoadLicense());
|
||||
EXPECT_EQ(NO_ERROR, holder3.Decrypt(key_id));
|
||||
ASSERT_NO_FATAL_FAILURE(holder3.CloseSession());
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(holder2.CloseSession());
|
||||
|
||||
// Ensure first offline license can no longer be used
|
||||
ASSERT_NO_FATAL_FAILURE(holder1.OpenSession());
|
||||
ASSERT_NO_FATAL_FAILURE(holder1.FailReloadLicense());
|
||||
EXPECT_NE(NO_ERROR, holder1.Decrypt(key_id));
|
||||
ASSERT_NO_FATAL_FAILURE(holder1.CloseSession());
|
||||
|
||||
// Ensure second and third offline licenses can be used
|
||||
ASSERT_NO_FATAL_FAILURE(holder2.OpenSession());
|
||||
ASSERT_NO_FATAL_FAILURE(holder2.ReloadLicense());
|
||||
EXPECT_EQ(NO_ERROR, holder2.Decrypt(key_id));
|
||||
ASSERT_NO_FATAL_FAILURE(holder2.RemoveLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(holder2.CloseSession());
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(holder3.OpenSession());
|
||||
ASSERT_NO_FATAL_FAILURE(holder3.ReloadLicense());
|
||||
EXPECT_EQ(NO_ERROR, holder3.Decrypt(key_id));
|
||||
ASSERT_NO_FATAL_FAILURE(holder3.RemoveLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(holder3.CloseSession());
|
||||
}
|
||||
|
||||
/**
|
||||
* This test verifies that the system can download and install license with a
|
||||
* key that requires secure buffers. It also verifies that we cannot decrypt to
|
||||
* a non-secure buffer using this key, but that we can decrypt to a secure
|
||||
* buffer, if the test harness supports secure buffers.
|
||||
*/
|
||||
TEST_F(CorePIGTest, OfflineHWSecureRequired) {
|
||||
LicenseHolder holder("CDM_OfflineHWSecureRequired", &cdm_engine_, config_);
|
||||
holder.set_can_persist(true);
|
||||
@@ -118,6 +176,50 @@ TEST_F(CorePIGTest, OfflineHWSecureRequired) {
|
||||
ASSERT_NO_FATAL_FAILURE(holder.CloseSession());
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be able to request license, perform playback, generate a license
|
||||
* release, and receive the release response.
|
||||
*/
|
||||
TEST_F(CorePIGTest, LicenseRelease1) {
|
||||
LicenseHolder holder("CDM_UnlimitedStreaming_can_persist", &cdm_engine_,
|
||||
config_);
|
||||
holder.set_can_persist(true);
|
||||
const KeyId key_id = "0000000000000000";
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(holder.OpenSession());
|
||||
ASSERT_NO_FATAL_FAILURE(holder.FetchLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(holder.LoadLicense());
|
||||
EXPECT_EQ(NO_ERROR, holder.Decrypt(key_id));
|
||||
ASSERT_NO_FATAL_FAILURE(holder.GenerateAndPostReleaseRequest(
|
||||
"CDM_UnlimitedStreaming_can_persist"));
|
||||
EXPECT_NE(NO_ERROR, holder.Decrypt(key_id));
|
||||
ASSERT_NO_FATAL_FAILURE(holder.FetchRelease());
|
||||
ASSERT_NO_FATAL_FAILURE(holder.LoadRelease());
|
||||
EXPECT_NE(NO_ERROR, holder.Decrypt(key_id));
|
||||
ASSERT_NO_FATAL_FAILURE(holder.CloseSession());
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be able to request license, wait some time, generate a license
|
||||
* release, and receive the release response.
|
||||
*/
|
||||
TEST_F(CorePIGTest, LicenseRelease2) {
|
||||
LicenseHolder holder("CDM_UnlimitedStreaming_can_persist", &cdm_engine_,
|
||||
config_);
|
||||
holder.set_can_persist(true);
|
||||
const KeyId key_id = "0000000000000000";
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(holder.OpenSession());
|
||||
ASSERT_NO_FATAL_FAILURE(holder.FetchLicense());
|
||||
ASSERT_NO_FATAL_FAILURE(holder.LoadLicense());
|
||||
wvutil::TestSleep::Sleep(10);
|
||||
ASSERT_NO_FATAL_FAILURE(holder.GenerateAndPostReleaseRequest(
|
||||
"CDM_UnlimitedStreaming_can_persist"));
|
||||
ASSERT_NO_FATAL_FAILURE(holder.FetchRelease());
|
||||
ASSERT_NO_FATAL_FAILURE(holder.LoadRelease());
|
||||
ASSERT_NO_FATAL_FAILURE(holder.CloseSession());
|
||||
}
|
||||
|
||||
TEST_F(CorePIGTest, CastReceiverProvisioningUsingCdm) {
|
||||
const std::string digest_hex_str =
|
||||
// digest info header
|
||||
|
||||
@@ -185,6 +185,7 @@ std::string ProvisioningHolder::DumpProvAttempt(const std::string& request,
|
||||
if (result != OEMCrypto_SUCCESS) {
|
||||
info << "--- ERROR GETTING BCC. result=" << result;
|
||||
} else {
|
||||
bcc.resize(bcc_length);
|
||||
info << "BCC = (len=" << bcc_length << ") "
|
||||
<< wvutil::unlimited_b2a_hex(bcc) << "\n"
|
||||
<< "Additional Sig = (len=" << signature_length << ") "
|
||||
|
||||
@@ -145,14 +145,60 @@ void show_menu(const char* prog_name, const std::string& extra_help_text) {
|
||||
|
||||
std::cout << " --dump_golden_data" << std::endl;
|
||||
std::cout << " Dump the license request and response from the server."
|
||||
<< std::endl
|
||||
<< std::endl;
|
||||
|
||||
std::cout << " --skip-slow-tests" << std::endl;
|
||||
std::cout << " Skips tests that are known to be slow." << std::endl;
|
||||
std::cout << " --skip-sleepy-tests" << std::endl;
|
||||
std::cout << " Skips tests that sleep a lot." << std::endl;
|
||||
std::cout << " --run-sleepy-tests" << std::endl;
|
||||
std::cout << " Allow tests that sleep a lot (used with --skip-slow-tests)"
|
||||
<< std::endl;
|
||||
std::cout << " --skip-decryption-stress-tests" << std::endl;
|
||||
std::cout << " Skips decryption stress tests." << std::endl;
|
||||
std::cout << " --run-decryption-stress-tests" << std::endl;
|
||||
std::cout << " Allow decryption stress tests (used with "
|
||||
<< "--skip-slow-tests)" << std::endl;
|
||||
std::cout << " --skip-request-flood-tests" << std::endl;
|
||||
std::cout << " Skips tests that generate a lot of requests." << std::endl;
|
||||
std::cout << " --run-request-flood-tests" << std::endl;
|
||||
std::cout << " Allow tests that generate a lot of requests (used with "
|
||||
<< "--skip-slow-tests)" << std::endl;
|
||||
std::cout << " --skip-multi-thread-stress-tests" << std::endl;
|
||||
std::cout << " Skips tests that stress thread protections." << std::endl;
|
||||
std::cout << " --run-multi-thread-stress-tests" << std::endl;
|
||||
std::cout << " Allow tests that stress thread protections (used with "
|
||||
<< "--skip-slow-tests)" << std::endl;
|
||||
std::cout << " --skip-usage-table-stress-tests" << std::endl;
|
||||
std::cout << " Skips tests that stess the usage table." << std::endl;
|
||||
std::cout << " --run-usage-table-stress-tests" << std::endl;
|
||||
std::cout << " Allow tests that stess the usage table (used with "
|
||||
<< "--skip-slow-tests)" << std::endl
|
||||
<< std::endl;
|
||||
|
||||
std::cout << extra_help_text << std::endl;
|
||||
}
|
||||
|
||||
enum OptionalBool {
|
||||
kBoolUnset,
|
||||
kBoolFalse,
|
||||
kBoolTrue,
|
||||
};
|
||||
|
||||
bool UnwrapOptionalBool(OptionalBool value, bool default_value) {
|
||||
return (value == kBoolUnset) ? default_value : (value == kBoolTrue);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Static WvCdmTestBase variables.
|
||||
std::unique_ptr<ConfigTestEnv> WvCdmTestBase::default_config_;
|
||||
bool WvCdmTestBase::use_qa_test_keybox_ = false;
|
||||
bool WvCdmTestBase::skip_sleepy_tests_ = false;
|
||||
bool WvCdmTestBase::skip_decryption_stress_tests_ = false;
|
||||
bool WvCdmTestBase::skip_request_flood_tests_ = false;
|
||||
bool WvCdmTestBase::skip_multi_thread_stress_tests_ = false;
|
||||
bool WvCdmTestBase::skip_usage_table_stress_tests_ = false;
|
||||
|
||||
void WvCdmTestBase::StripeBuffer(std::vector<uint8_t>* buffer, size_t size,
|
||||
uint8_t init) {
|
||||
@@ -208,7 +254,6 @@ TestCryptoSession::TestCryptoSession(metrics::CryptoMetrics* crypto_metrics,
|
||||
|
||||
void TestCryptoSession::MaybeInstallTestKeybox() {
|
||||
if (IsTestKeyboxNeeded()) {
|
||||
CryptoSession::SetAllowTestKeybox(true);
|
||||
ReinitializeForTest();
|
||||
WvCdmTestBase::InstallTestRootOfTrust();
|
||||
}
|
||||
@@ -312,8 +357,7 @@ void WvCdmTestBase::InstallTestRootOfTrust() {
|
||||
}
|
||||
}
|
||||
|
||||
WvCdmTestBase::WvCdmTestBase()
|
||||
: config_(*default_config_), binary_provisioning_(false) {
|
||||
WvCdmTestBase::WvCdmTestBase() : config_(*default_config_) {
|
||||
const ::testing::TestInfo* const test_info =
|
||||
::testing::UnitTest::GetInstance()->current_test_info();
|
||||
|
||||
@@ -374,53 +418,29 @@ void WvCdmTestBase::EnsureProvisioned() {
|
||||
ASSERT_EQ(NO_ERROR, cdm_engine.CloseSession(session_id));
|
||||
}
|
||||
|
||||
bool WvCdmTestBase::ExtractSignedMessage(const std::string& response,
|
||||
std::string* result) {
|
||||
static const std::string kMessageStart = "\"signedResponse\": \"";
|
||||
static const std::string kMessageEnd = "\"";
|
||||
std::string response_string;
|
||||
size_t start = response.find(kMessageStart);
|
||||
|
||||
if (start == response.npos) {
|
||||
// Assume serialized protobuf message.
|
||||
result->assign(response);
|
||||
} else {
|
||||
// Assume JSON-wrapped protobuf.
|
||||
size_t end = response.find(kMessageEnd, start + kMessageStart.length());
|
||||
if (end == response.npos) {
|
||||
LOGE("ExtractSignedMessage cannot locate end substring");
|
||||
result->clear();
|
||||
return false;
|
||||
}
|
||||
size_t result_string_size = end - start - kMessageStart.length();
|
||||
result->assign(response, start + kMessageStart.length(),
|
||||
result_string_size);
|
||||
}
|
||||
|
||||
if (result->empty()) {
|
||||
LOGE("ExtractSignedMessage: Response message is empty");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WvCdmTestBase::Initialize(int argc, const char* const argv[],
|
||||
const std::string& extra_help_text) {
|
||||
Properties::Init();
|
||||
bool is_cast_receiver = false;
|
||||
bool filter_tests = true;
|
||||
bool show_usage = false;
|
||||
int verbosity = 0;
|
||||
|
||||
bool skip_slow_tests = false;
|
||||
OptionalBool skip_sleepy_tests = kBoolUnset;
|
||||
OptionalBool skip_decryption_stress_tests = kBoolUnset;
|
||||
OptionalBool skip_request_flood_tests = kBoolUnset;
|
||||
OptionalBool skip_multi_thread_stress_tests = kBoolUnset;
|
||||
OptionalBool skip_usage_table_stress_tests = kBoolUnset;
|
||||
|
||||
default_config_.reset(new ConfigTestEnv(kContentProtectionUatServer));
|
||||
|
||||
// Skip the first element, which is the program name.
|
||||
const std::vector<std::string> args(argv + 1, argv + argc);
|
||||
for (const std::string& arg : args) {
|
||||
if (arg == "--verbose" || arg == "-v") {
|
||||
if (arg == "--help" || arg == "-h") {
|
||||
show_usage = true;
|
||||
} else if (arg == "--verbose" || arg == "-v") {
|
||||
++verbosity;
|
||||
} else if (arg == "--no_filter") {
|
||||
filter_tests = false;
|
||||
} else if (arg == "--cast") {
|
||||
is_cast_receiver = true;
|
||||
} else if (arg == "--fake_sleep") {
|
||||
@@ -435,6 +455,28 @@ bool WvCdmTestBase::Initialize(int argc, const char* const argv[],
|
||||
} else if (arg == "--dump_golden_data") {
|
||||
default_config_->set_dump_golden_data(true);
|
||||
testing::AddGlobalTestEnvironment(new MessageDumper);
|
||||
} else if (arg == "--skip-slow-tests") {
|
||||
skip_slow_tests = true;
|
||||
} else if (arg == "--skip-sleepy-tests") {
|
||||
skip_sleepy_tests = kBoolTrue;
|
||||
} else if (arg == "--run-sleepy-tests") {
|
||||
skip_sleepy_tests = kBoolFalse;
|
||||
} else if (arg == "--skip-decryption-stress-tests") {
|
||||
skip_decryption_stress_tests = kBoolTrue;
|
||||
} else if (arg == "--run-decryption-stress-tests") {
|
||||
skip_decryption_stress_tests = kBoolFalse;
|
||||
} else if (arg == "--skip-request-flood-tests") {
|
||||
skip_request_flood_tests = kBoolTrue;
|
||||
} else if (arg == "--run-request-flood-tests") {
|
||||
skip_request_flood_tests = kBoolFalse;
|
||||
} else if (arg == "--skip-multi-thread-stress-tests") {
|
||||
skip_multi_thread_stress_tests = kBoolTrue;
|
||||
} else if (arg == "--run-multi-thread-stress-tests") {
|
||||
skip_multi_thread_stress_tests = kBoolFalse;
|
||||
} else if (arg == "--skip-usage-table-stress-tests") {
|
||||
skip_usage_table_stress_tests = kBoolTrue;
|
||||
} else if (arg == "--run-usage-table-stress-tests") {
|
||||
skip_usage_table_stress_tests = kBoolFalse;
|
||||
} else {
|
||||
const auto index = arg.find('=');
|
||||
if (index == std::string::npos) {
|
||||
@@ -529,12 +571,16 @@ bool WvCdmTestBase::Initialize(int argc, const char* const argv[],
|
||||
// support being a cast receiver.
|
||||
wvoec::global_features.set_cast_receiver(is_cast_receiver);
|
||||
}
|
||||
// If the user requests --no_filter, we don't change the filter, otherwise, we
|
||||
// filter out features that are not supported.
|
||||
if (filter_tests) {
|
||||
::testing::GTEST_FLAG(filter) =
|
||||
wvoec::global_features.RestrictFilter(::testing::GTEST_FLAG(filter));
|
||||
}
|
||||
|
||||
skip_sleepy_tests_ = UnwrapOptionalBool(skip_sleepy_tests, skip_slow_tests);
|
||||
skip_decryption_stress_tests_ =
|
||||
UnwrapOptionalBool(skip_decryption_stress_tests, skip_slow_tests);
|
||||
skip_request_flood_tests_ =
|
||||
UnwrapOptionalBool(skip_request_flood_tests, skip_slow_tests);
|
||||
skip_multi_thread_stress_tests_ =
|
||||
UnwrapOptionalBool(skip_multi_thread_stress_tests, skip_slow_tests);
|
||||
skip_usage_table_stress_tests_ =
|
||||
UnwrapOptionalBool(skip_usage_table_stress_tests, skip_slow_tests);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,16 +48,22 @@ class WvCdmTestBase : public ::testing::Test {
|
||||
// Calls Provision() if not already provisioned.
|
||||
virtual void EnsureProvisioned();
|
||||
|
||||
// Locate the portion of the server's provisioning response message that is
|
||||
// between the strings jason_start_substr and json_end_substr. Returns the
|
||||
// string through *result. If the start substring match fails, assume the
|
||||
// entire string represents a serialized protobuf mesaage and return true with
|
||||
// the entire string. If the end_substring match fails, return false with an
|
||||
// empty *result.
|
||||
bool ExtractSignedMessage(const std::string& response, std::string* result);
|
||||
virtual bool skip_sleepy_tests() const { return skip_sleepy_tests_; }
|
||||
virtual bool skip_decryption_stress_tests() const {
|
||||
return skip_decryption_stress_tests_;
|
||||
}
|
||||
virtual bool skip_request_flood_tests() const {
|
||||
return skip_request_flood_tests_;
|
||||
}
|
||||
virtual bool skip_multi_thread_stress_tests() const {
|
||||
return skip_multi_thread_stress_tests_;
|
||||
}
|
||||
virtual bool skip_usage_table_stress_tests() const {
|
||||
return skip_usage_table_stress_tests_;
|
||||
}
|
||||
|
||||
// Fill a buffer with some nonconstant data of the given size. The first
|
||||
// byte will be set to <init> to help you find the buffer when debugging.
|
||||
// Fill a buffer with some nonconstant data of the given size. The first byte
|
||||
// will be set to <init> to help you find the buffer when debugging.
|
||||
static void StripeBuffer(std::vector<uint8_t>* buffer, size_t size,
|
||||
uint8_t init);
|
||||
|
||||
@@ -86,7 +92,15 @@ class WvCdmTestBase : public ::testing::Test {
|
||||
|
||||
// This should be set by test subclasses BEFORE calling SetUp -- i.e. in the
|
||||
// tests's constructor.
|
||||
bool binary_provisioning_;
|
||||
bool binary_provisioning_ = false;
|
||||
|
||||
private:
|
||||
// Skip flags for long running tests.
|
||||
static bool skip_sleepy_tests_;
|
||||
static bool skip_decryption_stress_tests_;
|
||||
static bool skip_request_flood_tests_;
|
||||
static bool skip_multi_thread_stress_tests_;
|
||||
static bool skip_usage_table_stress_tests_;
|
||||
};
|
||||
|
||||
// This just makes the constructor public so that we can create one with dummy
|
||||
@@ -95,7 +109,7 @@ class TestCdmEngine : public CdmEngine {
|
||||
public:
|
||||
TestCdmEngine(wvutil::FileSystem* file_system,
|
||||
std::shared_ptr<metrics::EngineMetrics> metrics)
|
||||
: CdmEngine(file_system, metrics) {}
|
||||
: CdmEngine(file_system, std::move(metrics)) {}
|
||||
const CdmSession* GetCdmSession(std::string sessionId) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -79,3 +79,20 @@ void PrintTo(const SystemState& state, std::ostream* os) {
|
||||
}
|
||||
} // namespace okp
|
||||
} // namespace wvcdm
|
||||
|
||||
namespace std {
|
||||
void PrintTo(future_status status, ostream* os) {
|
||||
switch (status) {
|
||||
case future_status::ready:
|
||||
*os << "future_status::ready";
|
||||
return;
|
||||
case future_status::timeout:
|
||||
*os << "future_status::timeout";
|
||||
return;
|
||||
case future_status::deferred:
|
||||
*os << "future_status::deferred";
|
||||
return;
|
||||
}
|
||||
*os << "<unknown(" << static_cast<int>(status) << ")>";
|
||||
}
|
||||
} // namespace std
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#ifndef CDM_TEST_PRINTERS_H_
|
||||
#define CDM_TEST_PRINTERS_H_
|
||||
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
|
||||
#include "OEMCryptoCENC.h"
|
||||
@@ -24,4 +25,9 @@ namespace okp {
|
||||
void PrintTo(const SystemState& state, std::ostream* os);
|
||||
} // namespace okp
|
||||
} // namespace wvcdm
|
||||
|
||||
namespace std {
|
||||
void PrintTo(future_status status, ostream* os);
|
||||
} // namespace std
|
||||
|
||||
#endif // CDM_TEST_PRINTERS_H_
|
||||
|
||||
@@ -120,7 +120,7 @@ bool UrlRequest::GetResponse(std::string* message) {
|
||||
}
|
||||
}
|
||||
|
||||
ConcatenateChunkedResponse(response, message);
|
||||
ConcatenateChunkedResponse(std::move(response), message);
|
||||
LOGV("HTTP response from %s: (%zu): %s", socket_.url().c_str(),
|
||||
message->size(), message->c_str());
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user