// 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 #include #include #include #include #include #include #include #include #if defined(__linux__) # include #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"; // Load a TestHost file system from the real file system. bool ReloadFileSystem(const char* file_name, TestHost::Storage* store) { 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(input)), std::istreambuf_iterator()); if (!store->LoadFromString(dumped_file_system)) { LOGE("Could not parse %s", file_name); return false; } return true; } bool ReloadFileSystems() { return ReloadFileSystem(kGlobalDumpFileName, &g_host->global_storage()) && ReloadFileSystem(kPerOriginDumpFileName, &g_host->per_origin_storage()); } // 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 TestHost::Storage& store) { std::string dump; (void)store.SaveToString(&dump); std::ofstream output(file_name); output << dump; output.close(); } void DumpFileSystems() { DumpFileSystem(kGlobalDumpFileName, g_host->global_storage()); DumpFileSystem(kPerOriginDumpFileName, g_host->per_origin_storage()); } } // 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 spearate 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; }