Source release 19.3.0
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include <time.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
@@ -2219,6 +2220,208 @@ TEST_F(CdmTest, GetMetrics) {
|
||||
EXPECT_NE(metrics.length(), 0u);
|
||||
}
|
||||
|
||||
// These test reverse-compatibility of offline licenses. These tests are
|
||||
// disabled by default as they require multiple runs using different builds.
|
||||
// First run the *Setup* test with the old build to save the files into the test
|
||||
// data path. Then copy the *.dat files into the new build directory. Finally
|
||||
// run the remaining tests on the new build.
|
||||
// You can set GTEST_ALSO_RUN_DISABLED_TESTS variable to run these tests too.
|
||||
class OfflineReverseCompatTest : public CdmTest {
|
||||
public:
|
||||
void SaveToFiles(const std::string& session_id) {
|
||||
auto save = [](const std::string& data, const std::string& path) {
|
||||
std::ofstream os(path);
|
||||
os.write(data.data(), data.size());
|
||||
ASSERT_TRUE(os);
|
||||
};
|
||||
ASSERT_NO_FATAL_FAILURE(save(session_id, kSessionIdFile));
|
||||
|
||||
std::string data;
|
||||
ASSERT_TRUE(g_host->global_storage().SaveToString(&data));
|
||||
ASSERT_NO_FATAL_FAILURE(save(data, kGlobalStorageFile));
|
||||
|
||||
ASSERT_TRUE(g_host->per_origin_storage().SaveToString(&data));
|
||||
ASSERT_NO_FATAL_FAILURE(save(data, kPerOriginStorageFile));
|
||||
}
|
||||
|
||||
void LoadFromFiles(std::string* session_id) {
|
||||
auto load = [](const std::string& path, std::string* data) {
|
||||
std::ifstream file(path);
|
||||
ASSERT_TRUE(file);
|
||||
data->assign(std::istreambuf_iterator<char>(file),
|
||||
std::istreambuf_iterator<char>());
|
||||
};
|
||||
ASSERT_NO_FATAL_FAILURE(load(kSessionIdFile, session_id));
|
||||
|
||||
std::string data;
|
||||
ASSERT_NO_FATAL_FAILURE(load(kGlobalStorageFile, &data));
|
||||
ASSERT_TRUE(g_host->global_storage().LoadFromString(data));
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(load(kPerOriginStorageFile, &data));
|
||||
ASSERT_TRUE(g_host->per_origin_storage().LoadFromString(data));
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr const char* kSessionIdFile = "session_id.dat";
|
||||
static constexpr const char* kGlobalStorageFile = "global.dat";
|
||||
static constexpr const char* kPerOriginStorageFile = "per_origin.dat";
|
||||
};
|
||||
|
||||
TEST_F(OfflineReverseCompatTest, DISABLED_Setup) {
|
||||
constexpr const size_t kNumSessions = 20;
|
||||
std::string first_session_id;
|
||||
std::string session_id;
|
||||
std::string response;
|
||||
EnsureProvisioned();
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(CreateSessionAndFetchLicense(
|
||||
Cdm::kPersistentLicense, Cdm::kCenc, &first_session_id, &response));
|
||||
ASSERT_EQ(Cdm::kSuccess, updateWithRetry(first_session_id, response));
|
||||
ASSERT_EQ(Cdm::kSuccess, cdm_->close(first_session_id));
|
||||
|
||||
for (size_t i = 0; i < kNumSessions; i++) {
|
||||
ASSERT_NO_FATAL_FAILURE(CreateSessionAndFetchLicense(
|
||||
Cdm::kPersistentLicense, Cdm::kCenc, &session_id, &response));
|
||||
ASSERT_EQ(Cdm::kSuccess, updateWithRetry(session_id, response));
|
||||
ASSERT_EQ(Cdm::kSuccess, cdm_->close(session_id));
|
||||
}
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(SaveToFiles(first_session_id));
|
||||
}
|
||||
|
||||
TEST_F(OfflineReverseCompatTest, DISABLED_LoadAndDecrypt) {
|
||||
std::string session_id;
|
||||
ASSERT_NO_FATAL_FAILURE(LoadFromFiles(&session_id));
|
||||
ASSERT_EQ(cdm_->getProvisioningStatus(), Cdm::kProvisioned);
|
||||
|
||||
Cdm::Status status = cdm_->load(session_id);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
|
||||
Cdm::Subsample subsample;
|
||||
subsample.protected_bytes = kInputSize;
|
||||
|
||||
// Set up sample
|
||||
Cdm::Sample sample;
|
||||
sample.input.iv = kIvCenc;
|
||||
sample.input.iv_length = kIvCencSize;
|
||||
sample.input.data = kInput;
|
||||
sample.input.data_length = kInputSize;
|
||||
sample.input.subsamples = &subsample;
|
||||
sample.input.subsamples_length = 1;
|
||||
std::vector<uint8_t> output_buffer(sample.input.data_length);
|
||||
sample.output.data = output_buffer.data();
|
||||
sample.output.data_length = static_cast<uint32_t>(output_buffer.size());
|
||||
|
||||
// Set up batch to decrypt
|
||||
Cdm::DecryptionBatch batch;
|
||||
batch.samples = &sample;
|
||||
batch.samples_length = 1;
|
||||
batch.key_id = kKeyIdCtr.data();
|
||||
batch.key_id_length = static_cast<uint32_t>(kKeyIdCtr.size());
|
||||
batch.pattern = kPatternNone;
|
||||
batch.encryption_scheme = Cdm::kAesCtr;
|
||||
|
||||
std::vector<uint8_t> expected_output(kOutputCenc,
|
||||
kOutputCenc + kOutputCencSize);
|
||||
status = cdm_->decrypt(session_id, batch);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
EXPECT_EQ(expected_output, output_buffer);
|
||||
}
|
||||
|
||||
TEST_F(OfflineReverseCompatTest, DISABLED_CreateSessionThenLoad) {
|
||||
std::string session_id;
|
||||
ASSERT_NO_FATAL_FAILURE(LoadFromFiles(&session_id));
|
||||
ASSERT_EQ(cdm_->getProvisioningStatus(), Cdm::kProvisioned);
|
||||
|
||||
// This will cause us to re-provision.
|
||||
EnsureProvisioned();
|
||||
|
||||
// Create a new streaming license to use the new CDM/OEMCrypto.
|
||||
std::string new_session_id;
|
||||
std::string response;
|
||||
ASSERT_NO_FATAL_FAILURE(CreateSessionAndFetchLicense(
|
||||
Cdm::kTemporary, Cdm::kCenc, &new_session_id, &response));
|
||||
EXPECT_CALL(*this, onKeyStatusesChange(new_session_id, true));
|
||||
Cdm::Status status = updateWithRetry(new_session_id, response);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
Mock::VerifyAndClear(this);
|
||||
|
||||
// Loading the offline license should still succeed.
|
||||
status = cdm_->load(session_id);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
}
|
||||
|
||||
TEST_F(OfflineReverseCompatTest, DISABLED_LoadThenCreateSession) {
|
||||
std::string session_id;
|
||||
ASSERT_NO_FATAL_FAILURE(LoadFromFiles(&session_id));
|
||||
ASSERT_EQ(cdm_->getProvisioningStatus(), Cdm::kProvisioned);
|
||||
|
||||
// Loading the offline license should not break new sessions.
|
||||
Cdm::Status status = cdm_->load(session_id);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
ASSERT_EQ(cdm_->close(session_id), Cdm::kSuccess);
|
||||
|
||||
// This will cause us to re-provision.
|
||||
EnsureProvisioned();
|
||||
|
||||
std::string new_session_id;
|
||||
std::string response;
|
||||
ASSERT_NO_FATAL_FAILURE(CreateSessionAndFetchLicense(
|
||||
Cdm::kTemporary, Cdm::kCenc, &new_session_id, &response));
|
||||
EXPECT_CALL(*this, onKeyStatusesChange(new_session_id, true));
|
||||
status = updateWithRetry(new_session_id, response);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
Mock::VerifyAndClear(this);
|
||||
}
|
||||
|
||||
TEST_F(OfflineReverseCompatTest, DISABLED_LoadThenCreateOfflineSession) {
|
||||
std::string session_id;
|
||||
ASSERT_NO_FATAL_FAILURE(LoadFromFiles(&session_id));
|
||||
ASSERT_EQ(cdm_->getProvisioningStatus(), Cdm::kProvisioned);
|
||||
|
||||
// Loading the offline license should not break new sessions.
|
||||
Cdm::Status status = cdm_->load(session_id);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
ASSERT_EQ(cdm_->close(session_id), Cdm::kSuccess);
|
||||
|
||||
// This will cause us to re-provision.
|
||||
EnsureProvisioned();
|
||||
|
||||
std::string new_session_id;
|
||||
std::string response;
|
||||
ASSERT_NO_FATAL_FAILURE(CreateSessionAndFetchLicense(
|
||||
Cdm::kPersistentLicense, Cdm::kCenc, &new_session_id, &response));
|
||||
EXPECT_CALL(*this, onKeyStatusesChange(new_session_id, true));
|
||||
status = updateWithRetry(new_session_id, response);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
Mock::VerifyAndClear(this);
|
||||
}
|
||||
|
||||
TEST_F(OfflineReverseCompatTest, DISABLED_NewCdmInstance) {
|
||||
std::string session_id;
|
||||
ASSERT_NO_FATAL_FAILURE(LoadFromFiles(&session_id));
|
||||
ASSERT_EQ(cdm_->getProvisioningStatus(), Cdm::kProvisioned);
|
||||
|
||||
// This will cause us to re-provision.
|
||||
EnsureProvisioned();
|
||||
|
||||
std::string new_session_id;
|
||||
std::string response;
|
||||
ASSERT_NO_FATAL_FAILURE(CreateSessionAndFetchLicense(
|
||||
Cdm::kTemporary, Cdm::kCenc, &new_session_id, &response));
|
||||
EXPECT_CALL(*this, onKeyStatusesChange(new_session_id, true));
|
||||
Cdm::Status status = updateWithRetry(new_session_id, response);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
Mock::VerifyAndClear(this);
|
||||
|
||||
// Loading should still work with an entirely new CDM instance.
|
||||
ASSERT_NO_FATAL_FAILURE(RecreateCdm(true /* privacy_mode */));
|
||||
EnsureProvisioned();
|
||||
status = cdm_->load(session_id);
|
||||
ASSERT_EQ(Cdm::kSuccess, status);
|
||||
}
|
||||
|
||||
|
||||
TEST_P(CdmTestWithDecryptParam, DecryptToClearBuffer) {
|
||||
EnsureProvisioned();
|
||||
DecryptParam param = GetParam();
|
||||
|
||||
Reference in New Issue
Block a user