Revert "Cherry pick 18.4 changes to udc-widevine-dev"
This reverts commit 7186433edf.
Reason for revert: Build breakage - b/323194350
Change-Id: Ibba4f5289b8f0d5e835dfba9ceb1e601784af634
This commit is contained in:
committed by
Android (Google) Code Review
parent
7186433edf
commit
540c8dfd50
@@ -1,121 +0,0 @@
|
||||
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#include <assert.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
#include "cdm.h"
|
||||
#include "cdm_test_runner.h"
|
||||
#include "clock.h"
|
||||
#include "log.h"
|
||||
#include "reboot_test.h"
|
||||
#include "test_base.h"
|
||||
#include "test_host.h"
|
||||
|
||||
using namespace widevine;
|
||||
|
||||
// TODO(b/195338975): document how a partner should modify this so that they can
|
||||
// use a real host.
|
||||
TestHost* g_host = nullptr;
|
||||
|
||||
namespace {
|
||||
constexpr char kGlobalDumpFileName[] = "dumped_global_filesystem.dat";
|
||||
constexpr char kPerOriginDumpFileName[] = "dumped_per_origin_filesystem.dat";
|
||||
|
||||
using StorageMap = TestHost::Storage::StorageMap;
|
||||
|
||||
// Load a TestHost file system from the real file system.
|
||||
bool ReloadFileSystem(const char* file_name, StorageMap* map) {
|
||||
std::ifstream input(file_name);
|
||||
if (input.fail()) {
|
||||
// This is OK for first pass, but an error for later passes.
|
||||
LOGD("Could not read %s", file_name);
|
||||
return false;
|
||||
}
|
||||
std::string dumped_file_system((std::istreambuf_iterator<char>(input)),
|
||||
std::istreambuf_iterator<char>());
|
||||
if (!wvcdm::RebootTest::ParseDump(dumped_file_system, map)) {
|
||||
LOGE("Could not parse %s", file_name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReloadFileSystems() {
|
||||
StorageMap global_map;
|
||||
StorageMap per_origin_map;
|
||||
if (!ReloadFileSystem(kGlobalDumpFileName, &global_map) ||
|
||||
!ReloadFileSystem(kPerOriginDumpFileName, &per_origin_map)) {
|
||||
return false;
|
||||
}
|
||||
g_host->global_storage().ResetFiles(global_map);
|
||||
g_host->per_origin_storage().ResetFiles(per_origin_map);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Dump a TestHost file system to the real file system. If the dump file
|
||||
// cannot be written, this raises an exception and crashes the program. Since
|
||||
// we usually build with exceptions turned off, what this means is that the test
|
||||
// executable will halt if the file cannot be written.
|
||||
void DumpFileSystem(const char* file_name, const StorageMap& map) {
|
||||
std::string dump = wvcdm::RebootTest::DumpData(map);
|
||||
std::ofstream output(file_name);
|
||||
output << dump;
|
||||
output.close();
|
||||
}
|
||||
|
||||
void DumpFileSystems() {
|
||||
DumpFileSystem(kGlobalDumpFileName, g_host->global_storage().files());
|
||||
DumpFileSystem(kPerOriginDumpFileName, g_host->per_origin_storage().files());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
// Set up a Host and initialize the library. This makes these services
|
||||
// available to the tests. We would do this in the test suite itself, but the
|
||||
// core & OEMCrypto tests don't know they depend on this for storage.
|
||||
g_host = new TestHost();
|
||||
ReloadFileSystems();
|
||||
|
||||
// Partners will want to replace this with a real IStorage.
|
||||
Cdm::IStorage* const storage = &g_host->global_storage();
|
||||
|
||||
// Partners may also want to replace this with real implementations of IClock
|
||||
// and ITimer. If so, make not to set the command line argument
|
||||
// "--fake_sleep".
|
||||
Cdm::IClock* const clock = g_host;
|
||||
Cdm::ITimer* const timer = g_host;
|
||||
|
||||
// Partners who prefer their logs to go somewhere other than stderr may want
|
||||
// to replace this implementation.
|
||||
Cdm::ILogger* const logger = &g_stderr_logger;
|
||||
|
||||
// If the tests need a separate file system from that used by the host, that
|
||||
// should be set up here. For the reference code, we use a default test file
|
||||
// system, but save the data from the file system.
|
||||
// A separate file system might be needed, for example, if the test data needs
|
||||
// to be saved off-device. Or, for example, if the main file system limits the
|
||||
// names and types of files it can save to certificates and offline licenses.
|
||||
wvutil::FileSystem* file_system = nullptr;
|
||||
wvcdm::RebootTest::set_file_system(file_system);
|
||||
|
||||
const int test_results = Main(storage, clock, timer, logger, argc, argv);
|
||||
DumpFileSystems();
|
||||
// This is used by the test driver to know what time to use for initializing
|
||||
// the fake clock for the next pass.
|
||||
std::cout << "END_OF_TEST " << wvutil::Clock().GetCurrentTime() << "\n";
|
||||
return test_results;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,44 +0,0 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#include <assert.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cdm.h"
|
||||
#include "cdm_test_runner.h"
|
||||
#include "log.h"
|
||||
#include "test_base.h"
|
||||
#include "test_host.h"
|
||||
|
||||
using namespace widevine;
|
||||
|
||||
TestHost* g_host = nullptr;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
g_host = new TestHost();
|
||||
|
||||
// TODO(b/195338975): document that using a real IStorage means you should not
|
||||
// run the tests in $CDM_DIR/cdm/test/cdm_test.cpp
|
||||
|
||||
// Partners will want to replace this with a real IStorage.
|
||||
Cdm::IStorage* const storage = &g_host->global_storage();
|
||||
|
||||
// Partners may also want to replace this with real implementations of IClock
|
||||
// and ITimer. If so, make not to set the command line argument
|
||||
// "--fake_sleep".
|
||||
Cdm::IClock* const clock = g_host;
|
||||
Cdm::ITimer* const timer = g_host;
|
||||
|
||||
// Partners who prefer their logs to go somewhere other than stderr may want
|
||||
// to replace this implementation.
|
||||
Cdm::ILogger* const logger = &g_stderr_logger;
|
||||
|
||||
const int test_results = Main(storage, clock, timer, logger, argc, argv);
|
||||
return test_results;
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#include "cdm_test_printers.h"
|
||||
|
||||
namespace widevine {
|
||||
|
||||
void PrintTo(const Cdm::MessageType& value, ::std::ostream* os) {
|
||||
switch (value) {
|
||||
case Cdm::kLicenseRequest:
|
||||
*os << "Cdm::kLicenseRequest";
|
||||
break;
|
||||
case Cdm::kLicenseRenewal:
|
||||
*os << "Cdm::kLicenseRenewal";
|
||||
break;
|
||||
case Cdm::kLicenseRelease:
|
||||
*os << "Cdm::kLicenseRelease";
|
||||
break;
|
||||
case Cdm::kIndividualizationRequest:
|
||||
*os << "Cdm::kIndividualizationRequest";
|
||||
break;
|
||||
default:
|
||||
*os << "Unknown Cdm::MessageType value " << value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PrintTo(const Cdm::Status& value, ::std::ostream* os) {
|
||||
switch (value) {
|
||||
case Cdm::kSuccess:
|
||||
*os << "Cdm::kSuccess";
|
||||
break;
|
||||
|
||||
case Cdm::kTypeError:
|
||||
*os << "Cdm::kTypeError";
|
||||
break;
|
||||
case Cdm::kNotSupported:
|
||||
*os << "Cdm::kNotSupported";
|
||||
break;
|
||||
case Cdm::kInvalidState:
|
||||
*os << "Cdm::kInvalidState";
|
||||
break;
|
||||
case Cdm::kQuotaExceeded:
|
||||
*os << "Cdm::kQuotaExceeded";
|
||||
break;
|
||||
|
||||
case Cdm::kNeedsDeviceCertificate:
|
||||
*os << "Cdm::kNeedsDeviceCertificate";
|
||||
break;
|
||||
case Cdm::kSessionNotFound:
|
||||
*os << "Cdm::kSessionNotFound";
|
||||
break;
|
||||
case Cdm::kDecryptError:
|
||||
*os << "Cdm::kDecryptError";
|
||||
break;
|
||||
case Cdm::kNoKey:
|
||||
*os << "Cdm::kNoKey";
|
||||
break;
|
||||
case Cdm::kKeyUsageBlockedByPolicy:
|
||||
*os << "Cdm::kKeyUsageBlockedByPolicy";
|
||||
break;
|
||||
case Cdm::kRangeError:
|
||||
*os << "Cdm::kRangeError";
|
||||
break;
|
||||
case Cdm::kResourceContention:
|
||||
*os << "Cdm::kResourceContention";
|
||||
break;
|
||||
case Cdm::kSessionStateLost:
|
||||
*os << "Cdm::kSessionStateLost";
|
||||
break;
|
||||
case Cdm::kSystemStateLost:
|
||||
*os << "Cdm::kSystemStateLost";
|
||||
break;
|
||||
case Cdm::kOutputTooLarge:
|
||||
*os << "Cdm::kOutputTooLarge";
|
||||
break;
|
||||
case Cdm::kNeedsServiceCertificate:
|
||||
*os << "Cdm::kNeedsServiceCertificate";
|
||||
break;
|
||||
|
||||
case Cdm::kUnexpectedError:
|
||||
*os << "Cdm::kUnexpectedError";
|
||||
break;
|
||||
|
||||
default:
|
||||
*os << "Unknown Cdm::Status value " << value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PrintTo(const Cdm::KeyStatus& value, ::std::ostream* os) {
|
||||
switch (value) {
|
||||
case Cdm::kUsable:
|
||||
*os << "Cdm::kUsable";
|
||||
break;
|
||||
case Cdm::kExpired:
|
||||
*os << "Cdm::kExpired";
|
||||
break;
|
||||
case Cdm::kOutputRestricted:
|
||||
*os << "Cdm::kOutputRestricted";
|
||||
break;
|
||||
case Cdm::kStatusPending:
|
||||
*os << "Cdm::kStatusPending";
|
||||
break;
|
||||
case Cdm::kInternalError:
|
||||
*os << "Cdm::kInternalError";
|
||||
break;
|
||||
case Cdm::kReleased:
|
||||
*os << "Cdm::kReleased";
|
||||
break;
|
||||
default:
|
||||
*os << "Unknown Cdm::KeyStatus value " << value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace widevine
|
||||
@@ -1,21 +0,0 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
// This file adds some print methods so that when unit tests fail, the
|
||||
// will print the name of an enumeration instead of the numeric value.
|
||||
|
||||
#ifndef WVCDM_CDM_TEST_CDM_TEST_PRINTERS_H_
|
||||
#define WVCDM_CDM_TEST_CDM_TEST_PRINTERS_H_
|
||||
|
||||
#include <iostream>
|
||||
#include "cdm.h"
|
||||
|
||||
namespace widevine {
|
||||
|
||||
void PrintTo(const Cdm::MessageType& value, ::std::ostream* os);
|
||||
void PrintTo(const Cdm::Status& value, ::std::ostream* os);
|
||||
void PrintTo(const Cdm::KeyStatus& value, ::std::ostream* os);
|
||||
|
||||
} // namespace widevine
|
||||
|
||||
#endif // WVCDM_CDM_TEST_CDM_TEST_PRINTERS_H_
|
||||
@@ -1,69 +0,0 @@
|
||||
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#include <assert.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cdm.h"
|
||||
#include "log.h"
|
||||
#include "stderr_logger.h"
|
||||
#include "test_base.h"
|
||||
#include "test_host.h"
|
||||
|
||||
widevine::StderrLogger g_stderr_logger;
|
||||
std::string g_sandbox_id;
|
||||
|
||||
namespace widevine {
|
||||
namespace {
|
||||
constexpr char kSandboxIdParam[] = "--sandbox_id=";
|
||||
|
||||
// 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";
|
||||
} // namespace
|
||||
|
||||
int Main(Cdm::IStorage* storage, Cdm::IClock* clock, Cdm::ITimer* timer,
|
||||
Cdm::ILogger* logger, int argc, char** argv) {
|
||||
// Find and filter out the Sandbox ID, if any.
|
||||
std::vector<std::string> args(argv, argv + argc);
|
||||
auto sandbox_id_iter = std::find_if(std::begin(args) + 1, std::end(args),
|
||||
[](const std::string& elem) -> bool {
|
||||
return elem.find(kSandboxIdParam) == 0;
|
||||
});
|
||||
if (sandbox_id_iter != std::end(args)) {
|
||||
g_sandbox_id = sandbox_id_iter->substr(strlen(kSandboxIdParam));
|
||||
args.erase(sandbox_id_iter);
|
||||
}
|
||||
|
||||
Cdm::Status status = Cdm::initialize(
|
||||
Cdm::kOpaqueHandle, storage, clock, timer, logger,
|
||||
static_cast<Cdm::LogLevel>(wvutil::g_cutoff), g_sandbox_id);
|
||||
(void)status; // status is now used when assertions are turned off.
|
||||
assert(status == Cdm::kSuccess);
|
||||
|
||||
std::vector<const char*> new_argv(args.size());
|
||||
std::transform(
|
||||
std::begin(args), std::end(args), std::begin(new_argv),
|
||||
[](const std::string& arg) -> const char* { return arg.c_str(); });
|
||||
// This must take place after the call to Cdm::initialize() because it makes
|
||||
// calls that are only valid after the library is initialized.
|
||||
if (!wvcdm::WvCdmTestBase::Initialize(static_cast<int>(new_argv.size()),
|
||||
new_argv.data(), kExtraHelpText)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Init gtest after oemcrypto and cdm host have been initialized.
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
} // namespace widevine
|
||||
@@ -1,20 +0,0 @@
|
||||
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#ifndef WVCDM_CDM_TEST_CDM_TEST_RUNNER_H_
|
||||
#define WVCDM_CDM_TEST_CDM_TEST_RUNNER_H_
|
||||
|
||||
#include <iostream>
|
||||
#include "cdm.h"
|
||||
|
||||
namespace widevine {
|
||||
// Run all CDM tests using the specified storage, clock, and timer. It parses
|
||||
// standard command line arguments, sets some default test client info,
|
||||
// initializes a CDM object, and then runs all the tests.
|
||||
// Returns 0 on success.
|
||||
int Main(Cdm::IStorage* storage, Cdm::IClock* clock, Cdm::ITimer* timer,
|
||||
Cdm::ILogger* logger, int argc, char** argv);
|
||||
} // namespace widevine
|
||||
|
||||
#endif // WVCDM_CDM_TEST_CDM_TEST_RUNNER_H_
|
||||
@@ -4,8 +4,4 @@
|
||||
|
||||
#include "create_test_file_system.h"
|
||||
|
||||
#include "test_host.h"
|
||||
|
||||
wvutil::FileSystem* CreateTestFileSystem() {
|
||||
return new wvutil::FileSystem("", &g_host->per_origin_storage());
|
||||
}
|
||||
wvutil::FileSystem* CreateTestFileSystem() { return new wvutil::FileSystem(); }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,14 +0,0 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
@end
|
||||
|
||||
@implementation AppDelegate {
|
||||
}
|
||||
@end
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved.
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// Defined in cdm_test_main.cpp.
|
||||
int main(int argc, char** argv);
|
||||
|
||||
@interface GtestTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation GtestTests
|
||||
|
||||
- (void)testAll {
|
||||
testing::GTEST_FLAG(filter) = GTEST_FILTER;
|
||||
|
||||
char arg0[] = "tests";
|
||||
char* argv[] = {arg0, nullptr};
|
||||
XCTAssertEqual(main(1, argv), 0);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>EQHXZ8M8AV.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
// Copyright 2022 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
/**
|
||||
The test file system for the Level 3 OEMCrypto sits on top of the host file
|
||||
system. A real production version may either use the host file system or it
|
||||
may write files directly to the file system.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "level3_file_system_ce_test.h"
|
||||
|
||||
#include "test_host.h"
|
||||
|
||||
namespace wvoec3 {
|
||||
|
||||
ssize_t OEMCrypto_Level3CETestFileSystem::Read(const char* filename,
|
||||
void* buffer, size_t size) {
|
||||
if (!g_host) return 0;
|
||||
const std::string name(filename);
|
||||
if (!g_host->global_storage().exists(name)) return 0;
|
||||
std::string data;
|
||||
if (!g_host->global_storage().read(name, &data)) return 0;
|
||||
size_t bytes_read = std::min(size, data.size());
|
||||
memcpy(buffer, data.data(), bytes_read);
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
ssize_t OEMCrypto_Level3CETestFileSystem::Write(const char* filename,
|
||||
const void* buffer,
|
||||
size_t size) {
|
||||
if (!g_host) return 0;
|
||||
std::string data(static_cast<const char*>(buffer), size);
|
||||
const std::string name(filename);
|
||||
if (!g_host->global_storage().write(name, data)) return 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
bool OEMCrypto_Level3CETestFileSystem::Exists(const char* filename) {
|
||||
if (!g_host) return false;
|
||||
const std::string name(filename);
|
||||
return g_host->global_storage().exists(name);
|
||||
}
|
||||
|
||||
ssize_t OEMCrypto_Level3CETestFileSystem::FileSize(const char* filename) {
|
||||
if (!g_host) return 0;
|
||||
const std::string name(filename);
|
||||
if (!g_host->global_storage().exists(name)) return 0;
|
||||
return static_cast<ssize_t>(g_host->global_storage().size(name));
|
||||
}
|
||||
|
||||
bool OEMCrypto_Level3CETestFileSystem::Remove(const char* filename) {
|
||||
if (!g_host) return false;
|
||||
const std::string name(filename);
|
||||
if (!g_host->global_storage().exists(name)) return false;
|
||||
return g_host->global_storage().remove(name);
|
||||
}
|
||||
|
||||
} // namespace wvoec3
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
/*********************************************************************
|
||||
* level3_file_system_ce_test.h
|
||||
*
|
||||
* Test file system for CE CDM for OEMCrypto Level3 File Operations.
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef LEVEL3_FILE_SYSTEM_CE_TEST_H_
|
||||
#define LEVEL3_FILE_SYSTEM_CE_TEST_H_
|
||||
|
||||
#include "cdm.h"
|
||||
#include "file_store.h"
|
||||
#include "level3_file_system.h"
|
||||
|
||||
namespace wvoec3 {
|
||||
|
||||
class OEMCrypto_Level3CETestFileSystem : public OEMCrypto_Level3FileSystem {
|
||||
public:
|
||||
OEMCrypto_Level3CETestFileSystem() {}
|
||||
~OEMCrypto_Level3CETestFileSystem() override {}
|
||||
ssize_t Read(const char* filename, void* buffer, size_t size) override;
|
||||
ssize_t Write(const char* filename, const void* buffer, size_t size) override;
|
||||
bool Exists(const char* filename) override;
|
||||
ssize_t FileSize(const char* filename) override;
|
||||
bool Remove(const char* filename) override;
|
||||
};
|
||||
|
||||
} // namespace wvoec3
|
||||
|
||||
#endif
|
||||
@@ -1,17 +0,0 @@
|
||||
#include "level3.h"
|
||||
|
||||
#include "level3_file_system_ce_test.h"
|
||||
|
||||
namespace wvoec3 {
|
||||
|
||||
OEMCrypto_Level3FileSystem* createLevel3FileSystem() {
|
||||
return new OEMCrypto_Level3CETestFileSystem();
|
||||
}
|
||||
|
||||
void deleteLevel3FileSystem(OEMCrypto_Level3FileSystem* file_system) {
|
||||
if (file_system) {
|
||||
delete file_system;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace wvoec3
|
||||
@@ -1,349 +0,0 @@
|
||||
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#include "perf_test.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "config_test_env.h"
|
||||
#include "license_request.h"
|
||||
#include "logger_global.h"
|
||||
#include "test_host.h"
|
||||
#include "url_request.h"
|
||||
|
||||
#define ASSERT_SUCCESS(code) ASSERT_EQ(code, Cdm::kSuccess)
|
||||
#define EXPECT_SUCCESS(code) EXPECT_EQ(code, Cdm::kSuccess)
|
||||
|
||||
#define WALL_NOW std::chrono::high_resolution_clock::now()
|
||||
|
||||
TestHost* g_host = nullptr;
|
||||
widevine::StderrLogger g_stderr_logger;
|
||||
|
||||
namespace widevine {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr const size_t kTestCount = 50;
|
||||
|
||||
const wvcdm::ConfigTestEnv kTestData(wvcdm::kContentProtectionUatServer);
|
||||
CreateFuncType create_func = nullptr;
|
||||
|
||||
using TimeType = std::chrono::duration<double, std::milli>;
|
||||
|
||||
struct PerfInfo {
|
||||
double mean;
|
||||
double min;
|
||||
double max;
|
||||
double std_dev;
|
||||
|
||||
template <size_t Size>
|
||||
PerfInfo(const double (&values)[Size]) {
|
||||
static_assert(Size > 0, "Must pass at least one value");
|
||||
|
||||
// First pass to calculate min/max/mean.
|
||||
bool first = true;
|
||||
double sum = 0;
|
||||
for (auto v : values) {
|
||||
sum += v;
|
||||
if (first) {
|
||||
min = max = v;
|
||||
first = false;
|
||||
} else {
|
||||
if (v < min) min = v;
|
||||
if (v > max) max = v;
|
||||
}
|
||||
}
|
||||
mean = sum / Size;
|
||||
|
||||
// Second pass to calculate standard deviation.
|
||||
sum = 0;
|
||||
for (auto v : values) {
|
||||
sum += (v - mean) * (v - mean);
|
||||
}
|
||||
std_dev = std::sqrt(sum / Size);
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const PerfInfo& info) {
|
||||
// mean=12.33442, std-dev=1.44421, min=1.22431, max=244.1133144
|
||||
return os << "mean=" << info.mean << ", std-dev=" << info.std_dev
|
||||
<< ", min=" << info.min << ", max=" << info.max;
|
||||
}
|
||||
|
||||
class PerfTracker {
|
||||
public:
|
||||
class Test {
|
||||
public:
|
||||
Test(PerfTracker* tracker)
|
||||
: wall_start_(WALL_NOW), cpu_start_(std::clock()), tracker_(tracker) {}
|
||||
|
||||
~Test() {
|
||||
tracker_->wall_times_[tracker_->index_] =
|
||||
TimeType(WALL_NOW - wall_start_).count();
|
||||
tracker_->cpu_times_[tracker_->index_] =
|
||||
(std::clock() - cpu_start_) * 1000.0 / CLOCKS_PER_SEC;
|
||||
tracker_->index_++;
|
||||
}
|
||||
|
||||
private:
|
||||
std::chrono::high_resolution_clock::time_point wall_start_;
|
||||
std::clock_t cpu_start_;
|
||||
PerfTracker* tracker_;
|
||||
};
|
||||
|
||||
void Print(const std::string& name, size_t block_size_bytes = 0) {
|
||||
PerfInfo wall_perf(wall_times_);
|
||||
PerfInfo cpu_perf(cpu_times_);
|
||||
std::cout << name << " (wall, ms): " << wall_perf << "\n";
|
||||
std::cout << name << " (cpu, ms): " << cpu_perf << "\n";
|
||||
if (block_size_bytes) {
|
||||
// |mean| is in milliseconds.
|
||||
std::cout << name << " (wall, MBit/sec): "
|
||||
<< (block_size_bytes * 8 * 1000 / wall_perf.mean / 1024 / 1024)
|
||||
<< "\n";
|
||||
std::cout << name << " (cpu, MBit/sec): "
|
||||
<< (block_size_bytes * 8 * 1000 / cpu_perf.mean / 1024 / 1024)
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
double wall_times_[kTestCount];
|
||||
double cpu_times_[kTestCount];
|
||||
size_t index_ = 0;
|
||||
};
|
||||
|
||||
#define MEASURE_PERF(tracker, code) \
|
||||
{ \
|
||||
PerfTracker::Test test(&(tracker)); \
|
||||
code; \
|
||||
}
|
||||
|
||||
class EventListener : public Cdm::IEventListener {
|
||||
public:
|
||||
struct MessageInfo {
|
||||
std::string session_id;
|
||||
std::string message;
|
||||
Cdm::MessageType message_type;
|
||||
std::string url;
|
||||
};
|
||||
|
||||
void onMessage(const std::string& session_id, Cdm::MessageType message_type,
|
||||
const std::string& message, const std::string& url) override {
|
||||
messages.push_back({session_id, message, message_type, url});
|
||||
}
|
||||
void onKeyStatusesChange(const std::string& session_id,
|
||||
bool has_new_usable_key) override {}
|
||||
void onExpirationChange(const std::string& session_id,
|
||||
int64_t new_expiration) override {}
|
||||
void onRemoveComplete(const std::string& session_id) override {}
|
||||
|
||||
std::vector<MessageInfo> messages;
|
||||
};
|
||||
|
||||
bool SendPost(const std::string& message, std::string* response) {
|
||||
wvcdm::UrlRequest req(kTestData.license_server());
|
||||
std::string raw_response;
|
||||
if (!req.is_connected() || !req.PostRequest(message) ||
|
||||
!req.GetResponse(&raw_response)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wvcdm::LicenseRequest helper;
|
||||
helper.GetDrmMessage(raw_response, *response);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<Cdm> CreateCdm(EventListener* event_listener) {
|
||||
std::unique_ptr<Cdm> ret(
|
||||
create_func(event_listener, &g_host->per_origin_storage(), true));
|
||||
if (ret) {
|
||||
EXPECT_SUCCESS(ret->setServiceCertificate(
|
||||
Cdm::kProvisioningService,
|
||||
kTestData.provisioning_service_certificate()));
|
||||
EXPECT_SUCCESS(ret->setServiceCertificate(
|
||||
Cdm::kLicensingService, kTestData.license_service_certificate()));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
class GlobalEnv : public testing::Environment {
|
||||
public:
|
||||
GlobalEnv(InitFuncType init_func, const std::string& cert)
|
||||
: init_func_(init_func), cert_(cert) {}
|
||||
|
||||
void SetUp() override {
|
||||
// Manually set the logger because `TestHost` makes logging calls before
|
||||
// the global logger is set in |init_func_|.
|
||||
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")) {
|
||||
if (std::strcmp(verbose, "1") == 0) log_level = Cdm::kVerbose;
|
||||
}
|
||||
ASSERT_SUCCESS(init_func_(Cdm::kNoSecureOutput, &g_host->global_storage(),
|
||||
g_host, g_host, &g_stderr_logger, log_level));
|
||||
}
|
||||
|
||||
private:
|
||||
const InitFuncType init_func_;
|
||||
const std::string cert_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
class PerfTest : public testing::Test {};
|
||||
|
||||
TEST_F(PerfTest, LicenseExchange) {
|
||||
EventListener event_listener;
|
||||
auto cdm = CreateCdm(&event_listener);
|
||||
ASSERT_TRUE(cdm);
|
||||
ASSERT_EQ(cdm->getProvisioningStatus(), Cdm::kProvisioned);
|
||||
|
||||
PerfTracker create;
|
||||
PerfTracker generate;
|
||||
PerfTracker update;
|
||||
PerfTracker close;
|
||||
for (size_t i = 0; i < kTestCount; i++) {
|
||||
std::string session_id;
|
||||
MEASURE_PERF(create, ASSERT_SUCCESS(
|
||||
cdm->createSession(Cdm::kTemporary, &session_id)));
|
||||
|
||||
MEASURE_PERF(
|
||||
generate,
|
||||
ASSERT_SUCCESS(cdm->generateRequest(
|
||||
session_id, Cdm::kCenc,
|
||||
wvcdm::ConfigTestEnv::GetInitData(wvcdm::kContentIdStreaming))));
|
||||
|
||||
std::string response;
|
||||
ASSERT_TRUE(SendPost(event_listener.messages[0].message, &response));
|
||||
|
||||
MEASURE_PERF(update, ASSERT_SUCCESS(cdm->update(session_id, response)));
|
||||
|
||||
MEASURE_PERF(close, ASSERT_SUCCESS(cdm->close(session_id)));
|
||||
|
||||
event_listener.messages.pop_back();
|
||||
}
|
||||
|
||||
create.Print("Create ");
|
||||
generate.Print("Generate");
|
||||
update.Print("Update ");
|
||||
close.Print("Close ");
|
||||
}
|
||||
|
||||
class DecryptPerfTest : public PerfTest,
|
||||
public testing::WithParamInterface<bool> {};
|
||||
|
||||
TEST_P(DecryptPerfTest, Decrypt) {
|
||||
EventListener event_listener;
|
||||
auto cdm = CreateCdm(&event_listener);
|
||||
ASSERT_TRUE(cdm);
|
||||
ASSERT_EQ(cdm->getProvisioningStatus(), Cdm::kProvisioned);
|
||||
|
||||
std::string session_id;
|
||||
ASSERT_SUCCESS(cdm->createSession(Cdm::kTemporary, &session_id));
|
||||
ASSERT_SUCCESS(cdm->generateRequest(
|
||||
session_id, Cdm::kCenc,
|
||||
wvcdm::ConfigTestEnv::GetInitData(wvcdm::kContentIdStreaming)));
|
||||
|
||||
std::string response;
|
||||
ASSERT_TRUE(SendPost(event_listener.messages[0].message, &response));
|
||||
ASSERT_SUCCESS(cdm->update(session_id, response));
|
||||
|
||||
Cdm::KeyStatusMap statuses;
|
||||
ASSERT_SUCCESS(cdm->getKeyStatuses(session_id, &statuses));
|
||||
ASSERT_GT(statuses.size(), 0u);
|
||||
const std::string key_id = statuses.begin()->first;
|
||||
|
||||
// Use in-place decrypt to avoid allocations. We don't care about the data,
|
||||
// so we can just decrypt the same buffer again.
|
||||
constexpr const size_t k16M = 16 * 1024 * 1024;
|
||||
std::vector<uint8_t> buffer(k16M);
|
||||
uint8_t iv[16];
|
||||
for (auto& b : buffer) b = rand();
|
||||
|
||||
Cdm::DecryptionBatch batch;
|
||||
batch.key_id = reinterpret_cast<const uint8_t*>(key_id.data());
|
||||
batch.key_id_length = static_cast<uint32_t>(key_id.size());
|
||||
if (GetParam()) {
|
||||
batch.pattern.encrypted_blocks = batch.pattern.clear_blocks = 0;
|
||||
} else {
|
||||
batch.pattern.encrypted_blocks = 1;
|
||||
batch.pattern.clear_blocks = 9;
|
||||
}
|
||||
batch.is_secure = false;
|
||||
batch.encryption_scheme = GetParam() ? Cdm::kAesCtr : Cdm::kAesCbc;
|
||||
batch.is_video = true;
|
||||
|
||||
Cdm::Subsample subsample;
|
||||
subsample.clear_bytes = 0;
|
||||
// subsample.encrypted_bytes set in the test.
|
||||
Cdm::Sample sample;
|
||||
sample.input.iv = iv;
|
||||
sample.input.iv_length = 16;
|
||||
sample.input.data = buffer.data();
|
||||
// sample.data_length set in the test.
|
||||
sample.input.subsamples = &subsample;
|
||||
sample.input.subsamples_length = 1;
|
||||
sample.output.data = buffer.data();
|
||||
sample.output.data_offset = 0;
|
||||
sample.output.data_length = static_cast<uint32_t>(buffer.size());
|
||||
batch.samples = &sample;
|
||||
batch.samples_length = 1;
|
||||
|
||||
constexpr const size_t block_sizes[] = {8 * 1024, 256 * 1024, k16M};
|
||||
constexpr const size_t sizes_count =
|
||||
sizeof(block_sizes) / sizeof(block_sizes[0]);
|
||||
const std::string block_names[] = {" 8k", "256k", " 16M"};
|
||||
PerfTracker perf[sizes_count];
|
||||
for (size_t i = 0; i < sizes_count; i++) {
|
||||
subsample.protected_bytes = sample.input.data_length =
|
||||
sample.output.data_length = static_cast<uint32_t>(block_sizes[i]);
|
||||
for (size_t j = 0; j < kTestCount; j++) {
|
||||
MEASURE_PERF(perf[i], ASSERT_SUCCESS(cdm->decrypt(batch)));
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sizes_count; i++) {
|
||||
perf[i].Print("Decrypt " + block_names[i], block_sizes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
std::string PrintDecryptParam(const testing::TestParamInfo<bool>& info) {
|
||||
return info.param ? "CTR" : "CBC";
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(Decrypt, DecryptPerfTest, testing::Bool(),
|
||||
PrintDecryptParam);
|
||||
|
||||
int PerfTestMain(InitFuncType init_func, CreateFuncType create,
|
||||
const std::string& cert) {
|
||||
#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).
|
||||
fprintf(stderr, "Don't run performance tests in Debug mode\n");
|
||||
return 1;
|
||||
#else
|
||||
create_func = create;
|
||||
testing::AddGlobalTestEnvironment(new GlobalEnv(init_func, cert));
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace widevine
|
||||
@@ -1,24 +0,0 @@
|
||||
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#ifndef WVCDM_CDM_TEST_PERF_TEST_H_
|
||||
#define WVCDM_CDM_TEST_PERF_TEST_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "cdm.h"
|
||||
|
||||
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);
|
||||
|
||||
int PerfTestMain(InitFuncType init_func, CreateFuncType create_func,
|
||||
const std::string& cert);
|
||||
|
||||
} // namespace widevine
|
||||
|
||||
#endif // WVCDM_CDM_TEST_PERF_TEST_H_
|
||||
@@ -1,84 +0,0 @@
|
||||
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
// This uses dlopen() which is only usable on POSIX platforms. The function
|
||||
// names assume GCC/Clang.
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <tuple>
|
||||
|
||||
#include "clock.h"
|
||||
#include "perf_test.h"
|
||||
#include "test_host.h"
|
||||
|
||||
namespace widevine {
|
||||
|
||||
constexpr char kInitName[] =
|
||||
"_ZN8widevine3Cdm10initializeENS0_16SecureOutputTypeEPNS0_8IStorageEPNS0_"
|
||||
"6IClockEPNS0_6ITimerEPNS0_7ILoggerENS0_8LogLevelE";
|
||||
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.
|
||||
auto dll = dlopen(path, RTLD_NOW);
|
||||
if (!dll) {
|
||||
fprintf(stderr, "Error loading so file: %s\n", dlerror());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
auto init = reinterpret_cast<InitFuncType>(dlsym(dll, kInitName));
|
||||
auto create = reinterpret_cast<CreateFuncType>(dlsym(dll, kCreateName));
|
||||
if (!init || !create) {
|
||||
fprintf(stderr, "Error finding CDM functions: %s\n", dlerror());
|
||||
exit(1);
|
||||
}
|
||||
return std::make_tuple(init, create);
|
||||
}
|
||||
|
||||
} // namespace widevine
|
||||
|
||||
namespace wvutil {
|
||||
|
||||
int64_t Clock::GetCurrentTime() { return g_host->now() / 1000; }
|
||||
|
||||
} // namespace wvutil
|
||||
|
||||
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]);
|
||||
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);
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#include "cdm.h"
|
||||
#include "perf_test.h"
|
||||
|
||||
@interface GtestTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation GtestTests
|
||||
|
||||
- (void)testAll {
|
||||
testing::GTEST_FLAG(filter) = GTEST_FILTER;
|
||||
char arg0[] = "tests";
|
||||
char* argv[] = {arg0, nullptr};
|
||||
int argc = 1;
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
XCTAssertEqual(widevine::PerfTestMain(&widevine::Cdm::initialize, &widevine::Cdm::create, ""), 0);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,185 +0,0 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
#include "test_host.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <chrono>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "cdm_version.h"
|
||||
#include "file_store.h"
|
||||
#include "log.h"
|
||||
|
||||
using namespace widevine;
|
||||
|
||||
namespace {
|
||||
|
||||
// Some files are expected to go in global storage. All other files are expected
|
||||
// to go in per-origin storage. To help us enforce this in tests, this set
|
||||
// tracks the filenames that belong in global storage. TestHost::Storage will
|
||||
// reject attempts to access these files via per-origin storage or to access
|
||||
// files not in this list via global storage.
|
||||
const std::unordered_set<std::string> kGlobalFilenames = {
|
||||
"usgtable.bin", // CDM usage table data
|
||||
"StoredUsageTime.dat", // Reference OEMCrypto usage table data
|
||||
"GenerationNumber.dat", // Reference OEMCrypto master generation number
|
||||
"persistent.dat", // Persistent data storage for certain TEE
|
||||
// implementations
|
||||
"keybox.dat", // Legacy file for storing keybox in non-secure storage.
|
||||
// CDM data for OTA keybox renewal.
|
||||
"okp.bin",
|
||||
"debug_ignore_keybox_count.txt",
|
||||
"debug_allow_test_keybox.txt",
|
||||
// Widevine L3 data files.
|
||||
"ay64.dat",
|
||||
"ay64.dat2",
|
||||
"ay64.dat3",
|
||||
"ay64.dat4",
|
||||
"ay64.dat5",
|
||||
"ay64.dat6",
|
||||
"l3_failure_file",
|
||||
wvutil::kOemCertificateFileName,
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TestHost::TestHost() : global_storage_(true), per_origin_storage_(false) {
|
||||
Reset();
|
||||
}
|
||||
TestHost::~TestHost() { wvutil::TestSleep::set_callback(nullptr); }
|
||||
|
||||
void TestHost::Reset() {
|
||||
auto now = std::chrono::system_clock().now();
|
||||
now_ = now.time_since_epoch() / std::chrono::milliseconds(1);
|
||||
wvutil::TestSleep::set_callback(this);
|
||||
|
||||
// Surprisingly, std::priority_queue has no clear().
|
||||
while (!timers_.empty()) {
|
||||
timers_.pop();
|
||||
}
|
||||
|
||||
global_storage_.Reset();
|
||||
per_origin_storage_.Reset();
|
||||
}
|
||||
|
||||
void TestHost::ElapseTime(int64_t milliseconds) {
|
||||
// Note that, during the time rollback tests, milliseconds will be negative,
|
||||
// so we cannot assume goal_time > now_.
|
||||
int64_t goal_time = now_ + milliseconds;
|
||||
|
||||
// Walk forward from now_ to goal_time, stepping at each timer along the way
|
||||
// to fire its callback.
|
||||
while (!timers_.empty() && now_ < goal_time) {
|
||||
Timer t = timers_.top();
|
||||
ASSERT_GE(t.expiry_time(), now_);
|
||||
if (t.expiry_time() <= goal_time) {
|
||||
timers_.pop();
|
||||
now_ = t.expiry_time();
|
||||
t.client()->onTimerExpired(t.context());
|
||||
} else {
|
||||
// The next timer is further in the future than goal_time, so we are done
|
||||
// processing the timers.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// No matter what happened with the timers, update now_ to the goal_time.
|
||||
now_ = goal_time;
|
||||
}
|
||||
|
||||
size_t TestHost::NumTimers() const { return timers_.size(); }
|
||||
|
||||
int64_t TestHost::now() { return now_; }
|
||||
|
||||
void TestHost::setTimeout(int64_t delay_ms, IClient* client, void* context) {
|
||||
int64_t expiry_time = now_ + delay_ms;
|
||||
timers_.push(Timer(expiry_time, client, context));
|
||||
}
|
||||
|
||||
void TestHost::cancel(IClient* client) {
|
||||
// Filter out the timers for this client and put the rest into |others|.
|
||||
std::priority_queue<Timer> others;
|
||||
|
||||
while (timers_.size()) {
|
||||
Timer t = timers_.top();
|
||||
timers_.pop();
|
||||
|
||||
if (t.client() != client) {
|
||||
others.push(t);
|
||||
}
|
||||
}
|
||||
|
||||
// Now swap the queues.
|
||||
std::swap(timers_, others);
|
||||
}
|
||||
|
||||
TestHost::Storage::Storage(bool is_global) : is_global_(is_global) { Reset(); }
|
||||
|
||||
void TestHost::Storage::Reset() {
|
||||
files_.clear();
|
||||
}
|
||||
|
||||
bool TestHost::Storage::read(const std::string& name, std::string* data) {
|
||||
StorageMap::iterator it = files_.find(name);
|
||||
bool ok = it != files_.end();
|
||||
LOGV("read file: %s: %s", name.c_str(), ok ? "ok" : "fail");
|
||||
if (!CheckFilename(name) || !ok) return false;
|
||||
*data = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestHost::Storage::write(const std::string& name,
|
||||
const std::string& data) {
|
||||
LOGV("write file: %s", name.c_str());
|
||||
if (!CheckFilename(name)) return false;
|
||||
files_[name] = data;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestHost::Storage::exists(const std::string& name) {
|
||||
StorageMap::iterator it = files_.find(name);
|
||||
bool ok = it != files_.end();
|
||||
LOGV("exists? %s: %s", name.c_str(), ok ? "true" : "false");
|
||||
if (!CheckFilename(name)) return false;
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool TestHost::Storage::remove(const std::string& name) {
|
||||
if (name.empty()) {
|
||||
// If no name, delete all files (see DeviceFiles::DeleteAllFiles())
|
||||
LOGV("remove all files");
|
||||
files_.clear();
|
||||
return true;
|
||||
}
|
||||
LOGV("remove: %s", name.c_str());
|
||||
if (!CheckFilename(name)) return false;
|
||||
return files_.erase(name) > 0;
|
||||
}
|
||||
|
||||
int32_t TestHost::Storage::size(const std::string& name) {
|
||||
StorageMap::iterator it = files_.find(name);
|
||||
bool ok = (it != files_.end());
|
||||
LOGV("size? %s: %s", name.c_str(), ok ? "ok" : "fail");
|
||||
if (!CheckFilename(name) || !ok) return -1;
|
||||
return static_cast<int32_t>(it->second.size());
|
||||
}
|
||||
|
||||
bool TestHost::Storage::list(std::vector<std::string>* names) {
|
||||
names->clear();
|
||||
for (StorageMap::iterator it = files_.begin(); it != files_.end(); it++) {
|
||||
names->push_back(it->first);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestHost::Storage::CheckFilename(const std::string& name) {
|
||||
const bool is_global_filename =
|
||||
(kGlobalFilenames.find(name) != kGlobalFilenames.end());
|
||||
if (is_global_ != is_global_filename) {
|
||||
LOGE("Attempt to access %s in %s storage rejected.", name.c_str(),
|
||||
is_global_ ? "global" : "per-origin");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
#ifndef WVCDM_CDM_TEST_TEST_HOST_H_
|
||||
#define WVCDM_CDM_TEST_TEST_HOST_H_
|
||||
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cdm.h"
|
||||
#include "stderr_logger.h"
|
||||
#include "test_sleep.h"
|
||||
|
||||
// This provides a host environment for running CDM tests. It implements the
|
||||
// IStorage, IClock and ITimer interfaces that a host would normally implement,
|
||||
// while allowing them to be manipulated by the test.
|
||||
class TestHost : public widevine::Cdm::IClock,
|
||||
public widevine::Cdm::ITimer,
|
||||
public wvutil::TestSleep::CallBack {
|
||||
public:
|
||||
class Storage : public widevine::Cdm::IStorage {
|
||||
public:
|
||||
typedef std::map<std::string, std::string> StorageMap;
|
||||
|
||||
explicit Storage(bool is_global);
|
||||
~Storage() override {}
|
||||
void Reset();
|
||||
|
||||
// Reset the file system to contain the specified files.
|
||||
void ResetFiles(const StorageMap& files) { files_ = files; };
|
||||
const StorageMap& files() const { return files_; }
|
||||
|
||||
// widevine::Cdm::IStorage
|
||||
bool read(const std::string& name, std::string* data) override;
|
||||
bool write(const std::string& name, const std::string& data) override;
|
||||
bool exists(const std::string& name) override;
|
||||
bool remove(const std::string& name) override;
|
||||
int32_t size(const std::string& name) override;
|
||||
bool list(std::vector<std::string>* names) override;
|
||||
|
||||
private:
|
||||
bool is_global_;
|
||||
StorageMap files_;
|
||||
|
||||
bool CheckFilename(const std::string& name);
|
||||
};
|
||||
|
||||
TestHost();
|
||||
~TestHost() override;
|
||||
void Reset();
|
||||
|
||||
// Used for manipulating and inspecting timer states during testing.
|
||||
void ElapseTime(int64_t milliseconds) override;
|
||||
size_t NumTimers() const;
|
||||
|
||||
Storage& global_storage() { return global_storage_; }
|
||||
Storage& per_origin_storage() { return per_origin_storage_; }
|
||||
|
||||
// widevine::Cdm::IClock
|
||||
int64_t now() override;
|
||||
|
||||
// widevine::Cdm::ITimer
|
||||
void setTimeout(int64_t delay_ms, IClient* client, void* context) override;
|
||||
void cancel(IClient* client) override;
|
||||
|
||||
private:
|
||||
struct Timer {
|
||||
Timer(int64_t expiry_time, IClient* client, void* context)
|
||||
: expiry_time_(expiry_time), client_(client), context_(context) {}
|
||||
|
||||
bool operator<(const Timer& other) const {
|
||||
// We want to reverse the order so that the smallest expiry times go to
|
||||
// the top of the priority queue.
|
||||
return expiry_time_ > other.expiry_time_;
|
||||
}
|
||||
|
||||
int64_t expiry_time() { return expiry_time_; }
|
||||
IClient* client() { return client_; }
|
||||
void* context() { return context_; }
|
||||
|
||||
private:
|
||||
int64_t expiry_time_;
|
||||
IClient* client_;
|
||||
void* context_;
|
||||
};
|
||||
|
||||
int64_t now_;
|
||||
std::priority_queue<Timer> timers_;
|
||||
|
||||
Storage global_storage_;
|
||||
Storage per_origin_storage_;
|
||||
};
|
||||
|
||||
// Owned and managed by the test runner.
|
||||
extern TestHost* g_host;
|
||||
extern widevine::StderrLogger g_stderr_logger;
|
||||
extern std::string g_sandbox_id;
|
||||
|
||||
#endif // WVCDM_CDM_TEST_TEST_HOST_H_
|
||||
Reference in New Issue
Block a user