diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index e18b0d05..c9c22422 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -4415,6 +4415,22 @@ class DISABLED_UsageTableTest : public DISABLED_GenericDRMTest, s.close(); } + void PrintDotsWhileSleep(time_t total_seconds, time_t interval_seconds) { + time_t dot_time = interval_seconds; + time_t elapsed_time = 0; + time_t start_time = time(NULL); + do { + sleep(1); + elapsed_time = time(NULL) - start_time; + if (elapsed_time >= dot_time) { + cout << "."; + cout.flush(); + dot_time += interval_seconds; + } + } while (elapsed_time < total_seconds); + cout << endl; + } + protected: bool new_mac_keys_; }; @@ -4434,7 +4450,7 @@ TEST_P(DISABLED_UsageTableTest, OnlineLicense) { ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_UpdateUsageTable()); s.GenerateReport(pst); - s.GenerateReport(pst); + s.GenerateReport(pst); // test repeated report generation s.GenerateReport(pst); s.GenerateReport(pst); EXPECT_EQ(kUnused, s.pst_report()->status); @@ -5334,6 +5350,104 @@ TEST_P(DISABLED_UsageTableTest, TimingTest) { } } +TEST_P(DISABLED_UsageTableTest, VerifyUsageTimes) { + if (OEMCrypto_SupportsUsageTable()) { + std::string pst = "my_pst"; + ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_UpdateUsageTable()); + Session s; + s.open(); + s.GenerateDerivedKeys(); + s.FillSimpleMessage( + 0, wvoec_mock::kControlNonceEnabled | wvoec_mock::kControlNonceRequired, + s.get_nonce(), pst); + s.EncryptAndSign(); + s.LoadTestKeys(pst, new_mac_keys_); + + const int kLicenseReceivedTimeTolerance = kSpeedMultiplier; + ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_UpdateUsageTable()); + s.GenerateReport(pst); + EXPECT_EQ(kUnused, s.pst_report()->status); + EXPECT_NEAR(wvcdm::htonll64(s.pst_report()->seconds_since_license_received), + 0, kLicenseReceivedTimeTolerance); + + const time_t kDotIntervalInSeconds = 5; + const time_t kIdleInSeconds = 20; + const time_t kPlaybackLoopInSeconds = 2 * 60; + const time_t kUsageTableTimeTolerance = 10; + + cout << "This test verifies the elapsed time reported in the usage table " + "for a 2 minute simulated playback." << endl; + cout << "The total time for this test is about " << + kPlaybackLoopInSeconds + 2 * kIdleInSeconds << " seconds." << endl; + cout << "Wait " << kIdleInSeconds << + " seconds to verify usage table time before playback." << endl; + + PrintDotsWhileSleep(kIdleInSeconds, kDotIntervalInSeconds); + + ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_UpdateUsageTable()); + s.GenerateReport(pst); + EXPECT_EQ(kUnused, s.pst_report()->status); + EXPECT_NEAR(wvcdm::htonll64(s.pst_report()->seconds_since_license_received), + kIdleInSeconds, kLicenseReceivedTimeTolerance); + cout << "Start simulated playback..." << endl; + + time_t dot_time = kDotIntervalInSeconds; + time_t playback_time = 0; + time_t start_time = time(NULL); + do { + s.TestDecryptCTR(); + s.GenerateReport(pst); + EXPECT_EQ(kActive, s.pst_report()->status); + playback_time = time(NULL) - start_time; + ASSERT_LE(0, playback_time); + if (playback_time >= dot_time) { + cout << "."; + cout.flush(); + dot_time += kDotIntervalInSeconds; + } + } while (playback_time < kPlaybackLoopInSeconds); + cout << "\nSimulated playback time = " << playback_time << " seconds.\n"; + + ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_UpdateUsageTable()); + s.GenerateReport(pst); + EXPECT_NEAR(wvcdm::htonll64(s.pst_report()->seconds_since_license_received), + playback_time + kIdleInSeconds, kLicenseReceivedTimeTolerance); + EXPECT_NEAR(wvcdm::htonll64(s.pst_report()->seconds_since_first_decrypt), + playback_time, kUsageTableTimeTolerance); + EXPECT_NEAR(wvcdm::htonll64(s.pst_report()->seconds_since_last_decrypt), + 0, kUsageTableTimeTolerance); + EXPECT_NEAR( + wvcdm::htonll64(s.pst_report()->seconds_since_first_decrypt) - + wvcdm::htonll64(s.pst_report()->seconds_since_last_decrypt), + playback_time, kUsageTableTimeTolerance); + + cout << "Wait another " << kIdleInSeconds << " seconds " + "to verify usage table time since playback ended." << endl; + PrintDotsWhileSleep(kIdleInSeconds, kDotIntervalInSeconds); + + // At this point, this is what we expect: + // idle playback loop idle + // |-----|-------------------------|-----| + // |<--->| = seconds_since_last_decrypt + // |<----------------------------->| = seconds_since_first_decrypt + // |<------------------------------------| = seconds_since_license_received + ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_UpdateUsageTable()); + s.GenerateReport(pst); + EXPECT_NEAR(wvcdm::htonll64(s.pst_report()->seconds_since_license_received), + playback_time + 2 * kIdleInSeconds, + kLicenseReceivedTimeTolerance); + EXPECT_NEAR(wvcdm::htonll64(s.pst_report()->seconds_since_first_decrypt), + playback_time + kIdleInSeconds, kUsageTableTimeTolerance); + EXPECT_NEAR(wvcdm::htonll64(s.pst_report()->seconds_since_last_decrypt), + kIdleInSeconds, kUsageTableTimeTolerance); + + DeactivatePST(pst); + s.GenerateReport(pst); + EXPECT_EQ(kInactive, s.pst_report()->status); + s.TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE); + } +} + INSTANTIATE_TEST_CASE_P(TestUsageTables, DISABLED_UsageTableTest, Values(true, false)); // With and without new_mac_keys.