Add Windows support for clock-change test.
(This is a merge of http://go/wvgerrit/70363) Test: Android Unit Tests Bug: 122953649 Change-Id: I47d2120b4d280be316072c38fd7282e14f68c6a0
This commit is contained in:
committed by
John Bruce
parent
8efec483c9
commit
ea4e6d8c37
@@ -13,9 +13,14 @@
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
@@ -86,6 +91,37 @@ int GetRandBytes(unsigned char* buf, int num) {
|
||||
// returns 1 on success, -1 if not supported, or 0 if other failure.
|
||||
return RAND_bytes(buf, num);
|
||||
}
|
||||
|
||||
/** @return The Unix time of the given time point. */
|
||||
template <typename Duration>
|
||||
uint64_t UnixTime(const std::chrono::time_point<std::chrono::system_clock,
|
||||
Duration>& point) {
|
||||
return point.time_since_epoch() / std::chrono::seconds(1);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
using NativeTime = SYSTEMTIME;
|
||||
#else
|
||||
using NativeTime = timeval;
|
||||
#endif
|
||||
|
||||
void AddNativeTime(int64_t delta_seconds, NativeTime* time) {
|
||||
#ifdef _WIN32
|
||||
// See remarks from this for why this series is used.
|
||||
// https://msdn.microsoft.com/en-us/f77cdf86-0f97-4a89-b565-95b46fa7d65b
|
||||
FILETIME file_time;
|
||||
ASSERT_TRUE(SystemTimeToFileTime(time, &file_time));
|
||||
uint64_t long_time = static_cast<uint64_t>(file_time.dwLowDateTime) |
|
||||
(static_cast<uint64_t>(file_time.dwHighDateTime) << 32);
|
||||
long_time += delta_seconds * 1e7; // long_time is in 100-nanosecond intervals.
|
||||
file_time.dwLowDateTime = long_time & ((1ull << 32) - 1);
|
||||
file_time.dwHighDateTime = long_time >> 32;
|
||||
ASSERT_TRUE(FileTimeToSystemTime(&file_time, time));
|
||||
#else
|
||||
time->tv_sec += delta_seconds;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class OEMCryptoClientTest : public ::testing::Test, public SessionUtil {
|
||||
@@ -4881,6 +4917,22 @@ class UsageTableTest : public GenericCryptoTest {
|
||||
void SetUp() override {
|
||||
GenericCryptoTest::SetUp();
|
||||
new_mac_keys_ = true;
|
||||
did_change_system_time_ = false;
|
||||
test_start_steady_ = steady_clock_.now();
|
||||
#ifdef _WIN32
|
||||
GetSystemTime(&test_start_wall_);
|
||||
#else
|
||||
ASSERT_EQ(0, gettimeofday(&test_start_wall_, nullptr));
|
||||
#endif
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
if (did_change_system_time_) {
|
||||
const auto delta = steady_clock_.now() - test_start_steady_;
|
||||
const int64_t delta_sec = delta / std::chrono::seconds(1);
|
||||
ASSERT_NO_FATAL_FAILURE(SetWallTimeDelta(delta_sec));
|
||||
}
|
||||
GenericCryptoTest::TearDown();
|
||||
}
|
||||
|
||||
virtual void ShutDown() {
|
||||
@@ -4925,7 +4977,26 @@ class UsageTableTest : public GenericCryptoTest {
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Sets the current wall-clock time to a delta based on the start of the
|
||||
* test.
|
||||
*/
|
||||
void SetWallTimeDelta(int64_t delta_seconds) {
|
||||
did_change_system_time_ = true;
|
||||
NativeTime time = test_start_wall_;
|
||||
ASSERT_NO_FATAL_FAILURE(AddNativeTime(delta_seconds, &time));
|
||||
#ifdef _WIN32
|
||||
ASSERT_TRUE(SetSystemTime(&time));
|
||||
#else
|
||||
ASSERT_EQ(0, settimeofday(&time, nullptr));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool new_mac_keys_;
|
||||
bool did_change_system_time_;
|
||||
std::chrono::steady_clock steady_clock_;
|
||||
std::chrono::time_point<std::chrono::steady_clock> test_start_steady_;
|
||||
NativeTime test_start_wall_;
|
||||
};
|
||||
|
||||
// Some usage tables we want to check a license either with or without a
|
||||
@@ -6284,23 +6355,19 @@ TEST_F(UsageTableTest, TimeRollbackPrevention) {
|
||||
cout << "This test temporarily rolls back the system time in order to verify "
|
||||
<< "that the usage report accounts for the change. It then rolls "
|
||||
<< "the time back forward to the absolute time." << endl;
|
||||
// We use clock_gettime(CLOCK_REALTIME, ...) over time(...) so we can easily
|
||||
// set the time using clock_settime.
|
||||
timespec current_time;
|
||||
ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, ¤t_time));
|
||||
time_t loaded = current_time.tv_sec;
|
||||
std::chrono::system_clock wall_clock;
|
||||
std::chrono::steady_clock monotonic_clock;
|
||||
const auto loaded = wall_clock.now();
|
||||
ASSERT_NO_FATAL_FAILURE(LoadOfflineLicense(s1, pst));
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(s1.open());
|
||||
ASSERT_NO_FATAL_FAILURE(s1.ReloadUsageEntry());
|
||||
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s1));
|
||||
ASSERT_NO_FATAL_FAILURE(s1.LoadTestKeys(pst, new_mac_keys_));
|
||||
ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, ¤t_time));
|
||||
time_t first_decrypt = current_time.tv_sec;
|
||||
const auto first_decrypt = wall_clock.now();
|
||||
// Monotonic clock can't be changed. We use this since system clock will be
|
||||
// unreliable.
|
||||
ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, ¤t_time));
|
||||
time_t first_decrypt_monotonic = current_time.tv_sec;
|
||||
const auto first_decrypt_monotonic = monotonic_clock.now();
|
||||
ASSERT_NO_FATAL_FAILURE(s1.TestDecryptCTR());
|
||||
ASSERT_NO_FATAL_FAILURE(s1.UpdateUsageEntry(&encrypted_usage_header_));
|
||||
ASSERT_NO_FATAL_FAILURE(s1.close());
|
||||
@@ -6316,20 +6383,17 @@ TEST_F(UsageTableTest, TimeRollbackPrevention) {
|
||||
ASSERT_NO_FATAL_FAILURE(s1.UpdateUsageEntry(&encrypted_usage_header_));
|
||||
ASSERT_NO_FATAL_FAILURE(s1.close());
|
||||
|
||||
ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, ¤t_time));
|
||||
// Rollback the wall clock time.
|
||||
cout << "Rolling the system time back..." << endl;
|
||||
timeval current_time_of_day = {};
|
||||
current_time_of_day.tv_sec = current_time.tv_sec - kLongDuration * 10;
|
||||
ASSERT_EQ(0, settimeofday(¤t_time_of_day, NULL));
|
||||
ASSERT_NO_FATAL_FAILURE(SetWallTimeDelta(
|
||||
-static_cast<int64_t>(kLongDuration) * 10));
|
||||
|
||||
// Try to playback again.
|
||||
ASSERT_NO_FATAL_FAILURE(s1.open());
|
||||
ASSERT_NO_FATAL_FAILURE(s1.ReloadUsageEntry());
|
||||
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s1));
|
||||
ASSERT_NO_FATAL_FAILURE(s1.LoadTestKeys(pst, new_mac_keys_));
|
||||
ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, ¤t_time));
|
||||
time_t third_decrypt = current_time.tv_sec;
|
||||
const auto third_decrypt_monotonic = monotonic_clock.now();
|
||||
ASSERT_NO_FATAL_FAILURE(s1.TestDecryptCTR());
|
||||
ASSERT_NO_FATAL_FAILURE(s1.UpdateUsageEntry(&encrypted_usage_header_));
|
||||
ASSERT_NO_FATAL_FAILURE(s1.GenerateReport(pst));
|
||||
@@ -6337,18 +6401,18 @@ TEST_F(UsageTableTest, TimeRollbackPrevention) {
|
||||
|
||||
// Restore wall clock to its original position to verify that OEMCrypto does
|
||||
// not report negative times.
|
||||
ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, ¤t_time));
|
||||
current_time_of_day.tv_sec =
|
||||
first_decrypt + current_time.tv_sec - first_decrypt_monotonic;
|
||||
const auto test_duration = third_decrypt_monotonic - first_decrypt_monotonic;
|
||||
cout << "Rolling the system time forward to the absolute time..." << endl;
|
||||
ASSERT_EQ(0, settimeofday(¤t_time_of_day, NULL));
|
||||
ASSERT_NO_FATAL_FAILURE(SetWallTimeDelta(
|
||||
test_duration / std::chrono::seconds(1)));
|
||||
// Need to update time created since the verification checks the time of PST
|
||||
// report creation.
|
||||
expected.time_created = current_time_of_day.tv_sec;
|
||||
expected.time_created = UnixTime(wall_clock.now());
|
||||
|
||||
const auto end_time = first_decrypt + test_duration;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
s1.VerifyReport(expected, loaded, first_decrypt,
|
||||
first_decrypt + third_decrypt - first_decrypt_monotonic));
|
||||
s1.VerifyReport(expected, UnixTime(loaded), UnixTime(first_decrypt),
|
||||
UnixTime(end_time)));
|
||||
ASSERT_NO_FATAL_FAILURE(s1.close());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user