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();
|
||||
|
||||
@@ -7,11 +7,14 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cdm.h"
|
||||
#include "log.h"
|
||||
#include "oec_device_features.h"
|
||||
#include "stderr_logger.h"
|
||||
#include "test_base.h"
|
||||
#include "test_host.h"
|
||||
@@ -22,13 +25,56 @@ std::string g_sandbox_id;
|
||||
namespace widevine {
|
||||
namespace {
|
||||
constexpr char kSandboxIdParam[] = "--sandbox_id=";
|
||||
constexpr char kCertPathParam[] = "--cert_path=";
|
||||
constexpr char kCertKeyPathParam[] = "--cert_key_path=";
|
||||
|
||||
// Following the pattern established by help text in test_base.cpp
|
||||
constexpr char kExtraHelpText[] =
|
||||
" --sandbox_id=<sandbox_id>\n"
|
||||
" Specifies the Sandbox ID that should be sent to OEMCrypto via\n"
|
||||
" OEMCrypto_SetSandbox(). On most platforms, since Sandbox IDs are not\n"
|
||||
" in use, this parameter should be omitted.\n";
|
||||
" in use, this parameter should be omitted.\n"
|
||||
" --cert_path=<cert_path>\n"
|
||||
" Path to a preloaded DRM certificate. This may speed up some tests\n"
|
||||
" by skipping the provisioning step. On most platforms, this parameter\n"
|
||||
" parameter should be omitted.\n"
|
||||
" --cert_key_path=<cert_key_path>\n"
|
||||
" Path to a key in preloaded DRM certificate. This should only be used\n"
|
||||
" if the device has a baked in cert.\n";
|
||||
|
||||
bool ReadFile(const std::string& path, std::string* output) {
|
||||
output->clear();
|
||||
std::ifstream fs(path, std::ios::in | std::ios::binary);
|
||||
if (!fs) {
|
||||
LOGE("Failed to open %s: %s", path.c_str(), strerror(errno));
|
||||
return false;
|
||||
}
|
||||
std::stringstream buffer;
|
||||
buffer << fs.rdbuf();
|
||||
*output = buffer.str();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Reads a file from the command line arguments.
|
||||
// The file path is expected to be the first argument after the flag.
|
||||
// For example, if the flag is "--cert_path=" and the command line is
|
||||
// cdm_test_runner --cert_path=/path/to/cert
|
||||
// then the file at /path/to/cert will be read.
|
||||
// The flag will be removed from the command line arguments.
|
||||
bool ReadFileFromArg(const char* path_flag, std::vector<std::string>& args,
|
||||
std::string* data) {
|
||||
auto path_iter = std::find_if(std::begin(args) + 1, std::end(args),
|
||||
[path_flag](const std::string& elem) -> bool {
|
||||
return elem.find(path_flag) == 0;
|
||||
});
|
||||
if (path_iter != std::end(args)) {
|
||||
const std::string path = path_iter->substr(strlen(path_flag));
|
||||
args.erase(path_iter);
|
||||
return ReadFile(path, data);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int Main(Cdm::IStorage* storage, Cdm::IClock* clock, Cdm::ITimer* timer,
|
||||
@@ -50,6 +96,15 @@ int Main(Cdm::IStorage* storage, Cdm::IClock* clock, Cdm::ITimer* timer,
|
||||
(void)status; // status is now used when assertions are turned off.
|
||||
assert(status == Cdm::kSuccess);
|
||||
|
||||
std::string data;
|
||||
if (ReadFileFromArg(kCertPathParam, args, &data)) {
|
||||
g_host->set_baked_in_cert(data);
|
||||
}
|
||||
if (ReadFileFromArg(kCertKeyPathParam, args, &data)) {
|
||||
wvoec::global_features.set_rsa_test_key(
|
||||
std::vector<uint8_t>(data.begin(), data.end()));
|
||||
}
|
||||
|
||||
std::vector<const char*> new_argv(args.size());
|
||||
std::transform(
|
||||
std::begin(args), std::end(args), std::begin(new_argv),
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "test_host.h"
|
||||
|
||||
wvutil::FileSystem* CreateTestFileSystem() {
|
||||
return new wvutil::FileSystem("", &g_host->per_origin_storage());
|
||||
std::unique_ptr<wvutil::FileSystem> CreateTestFileSystem() {
|
||||
return std::make_unique<wvutil::FileSystem>("",
|
||||
&g_host->per_origin_storage());
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ bool SendPost(const std::string& message, std::string* response) {
|
||||
|
||||
std::unique_ptr<Cdm> CreateCdm(EventListener* event_listener) {
|
||||
std::unique_ptr<Cdm> ret(
|
||||
create_func(event_listener, &g_host->per_origin_storage(), true));
|
||||
create_func(event_listener, &g_host->per_origin_storage(), true, false));
|
||||
if (ret) {
|
||||
EXPECT_SUCCESS(ret->setServiceCertificate(
|
||||
Cdm::kProvisioningService,
|
||||
@@ -182,8 +182,7 @@ std::unique_ptr<Cdm> CreateCdm(EventListener* event_listener) {
|
||||
|
||||
class GlobalEnv : public testing::Environment {
|
||||
public:
|
||||
GlobalEnv(InitFuncType init_func, const std::string& cert)
|
||||
: init_func_(init_func), cert_(cert) {}
|
||||
GlobalEnv(InitFuncType init_func) : init_func_(init_func) {}
|
||||
|
||||
void SetUp() override {
|
||||
// Manually set the logger because `TestHost` makes logging calls before
|
||||
@@ -191,7 +190,6 @@ class GlobalEnv : public testing::Environment {
|
||||
g_logger = &g_stderr_logger;
|
||||
|
||||
g_host = new TestHost;
|
||||
if (!cert_.empty()) g_host->per_origin_storage().write("cert.bin", cert_);
|
||||
|
||||
Cdm::LogLevel log_level = Cdm::kErrors;
|
||||
if (const char* verbose = getenv("VERBOSE_OUTPUT")) {
|
||||
@@ -203,7 +201,6 @@ class GlobalEnv : public testing::Environment {
|
||||
|
||||
private:
|
||||
const InitFuncType init_func_;
|
||||
const std::string cert_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@@ -331,8 +328,7 @@ std::string PrintDecryptParam(const testing::TestParamInfo<bool>& info) {
|
||||
INSTANTIATE_TEST_SUITE_P(Decrypt, DecryptPerfTest, testing::Bool(),
|
||||
PrintDecryptParam);
|
||||
|
||||
int PerfTestMain(InitFuncType init_func, CreateFuncType create,
|
||||
const std::string& cert) {
|
||||
int PerfTestMain(InitFuncType init_func, CreateFuncType create) {
|
||||
#ifdef _DEBUG
|
||||
// Don't use #error since we build all targets and we don't want to fail the
|
||||
// debug build (and we can't have configuration-specific targets).
|
||||
@@ -340,7 +336,7 @@ int PerfTestMain(InitFuncType init_func, CreateFuncType create,
|
||||
return 1;
|
||||
#else
|
||||
create_func = create;
|
||||
testing::AddGlobalTestEnvironment(new GlobalEnv(init_func, cert));
|
||||
testing::AddGlobalTestEnvironment(new GlobalEnv(init_func));
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
#endif
|
||||
|
||||
@@ -14,10 +14,10 @@ namespace widevine {
|
||||
using InitFuncType = Cdm::Status (*)(Cdm::SecureOutputType, Cdm::IStorage*,
|
||||
Cdm::IClock*, Cdm::ITimer*, Cdm::ILogger*,
|
||||
Cdm::LogLevel);
|
||||
using CreateFuncType = Cdm* (*)(Cdm::IEventListener*, Cdm::IStorage*, bool);
|
||||
using CreateFuncType =
|
||||
Cdm* (*)(Cdm::IEventListener*, Cdm::IStorage*, bool, bool);
|
||||
|
||||
int PerfTestMain(InitFuncType init_func, CreateFuncType create_func,
|
||||
const std::string& cert);
|
||||
int PerfTestMain(InitFuncType init_func, CreateFuncType create_func);
|
||||
|
||||
} // namespace widevine
|
||||
|
||||
|
||||
@@ -24,24 +24,6 @@ constexpr char kInitName[] =
|
||||
constexpr char kCreateName[] =
|
||||
"_ZN8widevine3Cdm6createEPNS0_14IEventListenerEPNS0_8IStorageEbb";
|
||||
|
||||
bool ReadFile(const std::string& path, std::string* output) {
|
||||
constexpr size_t kReadSize = 8 * 1024;
|
||||
std::ifstream fs(path, std::ios::in | std::ios::binary);
|
||||
if (!fs) return false;
|
||||
while (true) {
|
||||
const size_t offset = output->size();
|
||||
output->resize(output->size() + kReadSize);
|
||||
fs.read(&output->at(offset), kReadSize);
|
||||
if (fs.eof()) {
|
||||
output->resize(offset + fs.gcount());
|
||||
return true;
|
||||
} else if (!fs) {
|
||||
fprintf(stderr, "Error reading from cert file\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple<InitFuncType, CreateFuncType> LoadCdm(const char* path) {
|
||||
// Note we will leak the library object; but this is just for tests and will
|
||||
// be unloaded when we exit anyway.
|
||||
@@ -70,15 +52,11 @@ int64_t Clock::GetCurrentTime() { return g_host->now() / 1000; }
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Usage: %s <CDM_SO_PATH> <CERT_PATH>\n", argv[0]);
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s <CDM_SO_PATH>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string cert;
|
||||
if (!widevine::ReadFile(argv[2], &cert))
|
||||
return 1;
|
||||
|
||||
auto funcs = widevine::LoadCdm(argv[1]);
|
||||
return widevine::PerfTestMain(std::get<0>(funcs), std::get<1>(funcs), cert);
|
||||
return widevine::PerfTestMain(std::get<0>(funcs), std::get<1>(funcs));
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
int argc = 1;
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
XCTAssertEqual(widevine::PerfTestMain(&widevine::Cdm::initialize, &widevine::Cdm::create, ""), 0);
|
||||
XCTAssertEqual(widevine::PerfTestMain(&widevine::Cdm::initialize, &widevine::Cdm::create), 0);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -137,6 +137,11 @@ bool TestHost::Storage::SaveToString(std::string* data) const {
|
||||
}
|
||||
|
||||
bool TestHost::Storage::read(const std::string& name, std::string* data) {
|
||||
if (wvutil::kLegacyCertificateFileName == name &&
|
||||
!g_host->baked_in_cert().empty()) {
|
||||
*data = g_host->baked_in_cert();
|
||||
return true;
|
||||
}
|
||||
StorageMap::iterator it = files_.find(name);
|
||||
bool ok = it != files_.end();
|
||||
LOGV("read file: %s: %s", name.c_str(), ok ? "ok" : "fail");
|
||||
@@ -148,12 +153,21 @@ bool TestHost::Storage::read(const std::string& name, std::string* data) {
|
||||
bool TestHost::Storage::write(const std::string& name,
|
||||
const std::string& data) {
|
||||
LOGV("write file: %s", name.c_str());
|
||||
if (wvutil::kLegacyCertificateFileName == name &&
|
||||
!g_host->baked_in_cert().empty()) {
|
||||
return false;
|
||||
}
|
||||
if (!CheckFilename(name)) return false;
|
||||
files_[name] = data;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestHost::Storage::exists(const std::string& name) {
|
||||
if (wvutil::kLegacyCertificateFileName == name &&
|
||||
!g_host->baked_in_cert().empty()) {
|
||||
LOGV("exists? %s: always", name.c_str());
|
||||
return true;
|
||||
}
|
||||
StorageMap::iterator it = files_.find(name);
|
||||
bool ok = it != files_.end();
|
||||
LOGV("exists? %s: %s", name.c_str(), ok ? "true" : "false");
|
||||
@@ -174,6 +188,11 @@ bool TestHost::Storage::remove(const std::string& name) {
|
||||
}
|
||||
|
||||
int32_t TestHost::Storage::size(const std::string& name) {
|
||||
if (wvutil::kLegacyCertificateFileName == name &&
|
||||
!g_host->baked_in_cert().empty()) {
|
||||
LOGV("size? %s: always", name.c_str());
|
||||
return static_cast<int32_t>(g_host->baked_in_cert().size());
|
||||
}
|
||||
StorageMap::iterator it = files_.find(name);
|
||||
bool ok = (it != files_.end());
|
||||
LOGV("size? %s: %s", name.c_str(), ok ? "ok" : "fail");
|
||||
|
||||
@@ -69,6 +69,13 @@ class TestHost : public widevine::Cdm::IClock,
|
||||
void setTimeout(int64_t delay_ms, IClient* client, void* context) override;
|
||||
void cancel(IClient* client) override;
|
||||
|
||||
// If this is set, then the storage will return this as a baked in cert.
|
||||
// Trying to write a new cert will generate an error.
|
||||
const std::string& baked_in_cert() const { return baked_in_cert_; };
|
||||
void set_baked_in_cert(const std::string& baked_in_cert) {
|
||||
baked_in_cert_ = baked_in_cert;
|
||||
};
|
||||
|
||||
private:
|
||||
struct Timer {
|
||||
Timer(int64_t expiry_time, IClient* client, void* context)
|
||||
@@ -95,6 +102,7 @@ class TestHost : public widevine::Cdm::IClock,
|
||||
|
||||
Storage global_storage_;
|
||||
Storage per_origin_storage_;
|
||||
std::string baked_in_cert_;
|
||||
};
|
||||
|
||||
// Owned and managed by the test runner.
|
||||
|
||||
26
cdm/test/test_version.cpp
Normal file
26
cdm/test/test_version.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright 2022 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "cdm.h"
|
||||
#include "cdm_version.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s <VERSION>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* bundle_version = argv[1];
|
||||
fprintf(stderr, "Header: " CDM_VERSION "\n");
|
||||
fprintf(stderr, "Library: %s\n", widevine::Cdm::version());
|
||||
fprintf(stderr, "Bundle: %s\n", bundle_version);
|
||||
if (strcmp(CDM_VERSION, widevine::Cdm::version()) ||
|
||||
strcmp(CDM_VERSION, bundle_version)) {
|
||||
fprintf(stderr, "ERROR: Mismatched version\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
28
cdm/test/test_version_xctest.mm
Normal file
28
cdm/test/test_version_xctest.mm
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright 2022 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#include <stdio.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#include "cdm.h"
|
||||
#include "cdm_version.h"
|
||||
|
||||
#define STR(s) [NSString stringWithUTF8String:s]
|
||||
|
||||
@interface VersionTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation VersionTests
|
||||
|
||||
- (void)testVersion {
|
||||
fprintf(stderr, "Header: " CDM_VERSION "\n");
|
||||
fprintf(stderr, "Library: %s\n", widevine::Cdm::version());
|
||||
fprintf(stderr, "Bundle: " EXPECTED_CDM_VERSION "\n");
|
||||
|
||||
XCTAssertEqual(STR(CDM_VERSION), STR(widevine::Cdm::version()));
|
||||
XCTAssertEqual(STR(CDM_VERSION), STR(EXPECTED_CDM_VERSION));
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user