Reboot test: Initialize fake clock

[ Merge of http://go/wvgerrit/143630 ]

When we run a test with the fake clock, the clock had been initialized
to the current time, or to 0. This causes a problem for reboot tests
because the clock might go backwards over the reboot. With this
change, we monitor the clock at the end of one reboot pass and
initialize the clock for the next pass based on the previous value.

Bug: 26163469
Test: GtsMediaTestCases on sunfish
Change-Id: Ibd0024f963634382af70553fced38da6e1d857d2
This commit is contained in:
Rahul Frias
2022-03-13 18:35:54 -07:00
parent 520368cea2
commit 6cda6717a9
5 changed files with 73 additions and 0 deletions

View File

@@ -11,6 +11,7 @@
#include <sstream>
#include "log.h"
#include "test_sleep.h"
using wvutil::a2b_hex;
using wvutil::FileSystem;
@@ -227,6 +228,23 @@ void RebootTest::TearDown() {
WvCdmTestBase::TearDown();
}
int64_t RebootTest::LoadTime(const std::string& key) {
int64_t value = 0;
std::istringstream input(persistent_data_[key]);
input >> value;
if (input.fail()) {
LOGE("Could not parse time '%s'", persistent_data_[key].c_str());
}
if (!input.eof()) {
LOGE("Extra text at end of time '%s'", persistent_data_[key].c_str());
}
return value;
}
void RebootTest::SaveTime(const std::string& key, int64_t time) {
persistent_data_[key] = std::to_string(time);
}
/** Test the dump and restore functions above. This does not test CDM
functionality. */
TEST_F(RebootTest, TestDumpUtil) {
@@ -277,4 +295,20 @@ TEST_F(RebootTest, FilesArePersistent) {
}
}
/** Verify that the clock moves forward over a reboot. */
TEST_F(RebootTest, TimeMovesForward) {
wvutil::TestSleep::Sleep(2);
const int64_t start = wvutil::Clock().GetCurrentTime();
wvutil::TestSleep::Sleep(2);
const int64_t end = wvutil::Clock().GetCurrentTime();
EXPECT_NEAR(end - start, 2.0, 1.0);
const std::string key = "end_time";
if (test_pass() == 0) {
// Save off the end of pass 1.
SaveTime(key, end);
} else {
int64_t previous_end = LoadTime(key);
EXPECT_LT(previous_end, start);
}
}
} // namespace wvcdm

View File

@@ -36,6 +36,12 @@ class RebootTest : public WvCdmTestBaseWithEngine {
static int test_pass() { return default_config_.test_pass(); }
// Load a previously saved time. Returns 0 if the value does not exist or
// cannot be parsed.
int64_t LoadTime(const std::string& key);
// Save a time to persistent storage.
void SaveTime(const std::string& key, int64_t time);
protected:
void SetUp() override;
void TearDown() override;

View File

@@ -122,6 +122,12 @@ void show_menu(const char* prog_name, const std::string& extra_help_text) {
<< " be used with a real OEMCrypto." << std::endl
<< std::endl;
std::cout << " --initial_time=<time>" << std::endl;
std::cout
<< " Set the initial time on the fake clock. This is ignored"
<< " if fake_sleep was not set." << std::endl
<< std::endl;
std::cout << " --pass=<N>" << std::endl;
std::cout << " Run test pass N. This is used for reboot tests that "
<< "require several passes." << std::endl
@@ -521,6 +527,14 @@ bool WvCdmTestBase::Initialize(int argc, const char* const argv[],
default_config_.set_test_pass(std::stoi(arg_value));
std::cout << "Running test pass " << default_config_.test_pass()
<< std::endl;
} else if (arg_prefix == "--initial_time") {
if (wvutil::TestSleep::real_sleep()) {
LOGD("Ignoring initial time %s because using a real clock",
arg_value.c_str());
} else {
LOGE("Setting initial fake clock time to %s", arg_value.c_str());
wvutil::TestSleep::SetFakeClock(stol(arg_value));
}
} else if (arg_prefix == "--test_data_path") {
default_config_.set_test_data_path(arg_value);
} else {

View File

@@ -58,6 +58,21 @@ void TestSleep::SyncFakeClock() {
Sleep(0);
}
void TestSleep::SetFakeClock(int64_t time_seconds) {
if (real_sleep_) {
LOGE("SetFakeClock when using a real clock. Expect other failures.");
}
// Delta could be positive or negative. If the fake clock had been initialized
// by the current time on a real clock, and then the command line
// re-initializes it to 0, then delta is negative.
int64_t delta = time_seconds - Clock().GetCurrentTime();
if (callback_ != nullptr) {
callback_->ElapseTime(delta * 1000);
} else {
LOGE("Setting fake clock with no callback. This won't work.");
}
}
bool TestSleep::RollbackSystemTime(int seconds) {
if (real_sleep_) {
#ifdef _WIN32

View File

@@ -41,6 +41,10 @@ class TestSleep {
// verify this function does not roll back the clock used by OEMCrypto.
static bool RollbackSystemTime(int seconds);
// Set the system clock to the specified time. This is only expected to work
// when real_sleep is false.
static void SetFakeClock(int64_t time_seconds);
// Roll the system clock forward to undo all previous calls to
// RollBackSystemTime. Returns true on success.
static bool ResetRollback() {