blob: e9ace4f90e5e7a63b4acb44539db30d93068aa8f [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/developer/forensics/feedback/annotations/time_provider.h"
#include <fuchsia/time/cpp/fidl.h>
#include <lib/zx/time.h>
#include <memory>
#include <gtest/gtest.h>
#include "src/developer/forensics/feedback/annotations/constants.h"
#include "src/developer/forensics/testing/unit_test_fixture.h"
#include "src/lib/timekeeper/test_clock.h"
namespace forensics::feedback {
namespace {
constexpr timekeeper::time_utc kUtcTime((zx::hour(7) + zx::min(14) + zx::sec(52)).get());
constexpr zx::time_boot kUptime((zx::hour(2) + zx::min(14) + zx::sec(52)).get());
constexpr zx::time_monotonic kRuntime((zx::hour(1) + zx::min(14) + zx::sec(52)).get());
constexpr char kUtcTimeStr[] = "1970-01-01 07:14:52 GMT";
constexpr char kUptimeStr[] = "000d02h14m52s";
constexpr char kRuntimeStr[] = "000d01h14m52s";
class TimeProviderTest : public UnitTestFixture {
public:
TimeProviderTest() {
zx_clock_create_args_v1_t clock_args{.backstop_time = 0};
FX_CHECK(zx::clock::create(0u, &clock_args, &clock_handle_) == ZX_OK);
}
protected:
void SignalLoggingQualityClock() {
if (const zx_status_t status =
clock_handle_.signal(/*clear_mask=*/0,
/*set_mask=*/fuchsia::time::SIGNAL_UTC_CLOCK_LOGGING_QUALITY);
status != ZX_OK) {
FX_PLOGS(FATAL, status) << "Failed to achieve logging quality clock";
}
}
void SetUpTimeProvider() {
auto clock = std::make_unique<timekeeper::TestClock>();
clock->SetUtc(kUtcTime);
clock->SetBoot(kUptime);
clock->SetMonotonic(kRuntime);
time_provider_ = std::make_unique<TimeProvider>(
dispatcher(), zx::unowned_clock(clock_handle_.get_handle()), std::move(clock));
}
zx::clock clock_handle_;
std::unique_ptr<TimeProvider> time_provider_;
};
TEST_F(TimeProviderTest, Check_LoggingQualityClock) {
SetUpTimeProvider();
EXPECT_FALSE(time_provider_->Get().at(kDeviceUtcTimeKey).HasValue());
SignalLoggingQualityClock();
RunLoopUntilIdle();
ASSERT_TRUE(time_provider_->Get().at(kDeviceUtcTimeKey).HasValue());
EXPECT_EQ(time_provider_->Get().at(kDeviceUtcTimeKey).Value(), kUtcTimeStr);
}
TEST_F(TimeProviderTest, Check_LoggingQualityClockBeforeFeedback) {
SignalLoggingQualityClock();
SetUpTimeProvider();
RunLoopUntilIdle();
ASSERT_TRUE(time_provider_->Get().at(kDeviceUtcTimeKey).HasValue());
EXPECT_EQ(time_provider_->Get().at(kDeviceUtcTimeKey).Value(), kUtcTimeStr);
}
TEST_F(TimeProviderTest, Check_NotReadyOnClockStarted) {
SetUpTimeProvider();
EXPECT_FALSE(time_provider_->Get().at(kDeviceUtcTimeKey).HasValue());
ASSERT_EQ(
clock_handle_.update(zx::clock::update_args().set_value(zx::time_monotonic(kUtcTime.get()))),
ZX_OK);
RunLoopUntilIdle();
EXPECT_FALSE(time_provider_->Get().at(kDeviceUtcTimeKey).HasValue());
}
TEST_F(TimeProviderTest, Check_NotReadyOnClockSynchronized) {
SetUpTimeProvider();
EXPECT_FALSE(time_provider_->Get().at(kDeviceUtcTimeKey).HasValue());
ASSERT_EQ(clock_handle_.signal(
/*clear_mask=*/0, /*set_mask=*/fuchsia::time::SIGNAL_UTC_CLOCK_SYNCHRONIZED),
ZX_OK);
RunLoopUntilIdle();
EXPECT_FALSE(time_provider_->Get().at(kDeviceUtcTimeKey).HasValue());
}
TEST_F(TimeProviderTest, GetValuesCorrect) {
SetUpTimeProvider();
SignalLoggingQualityClock();
RunLoopUntilIdle();
ASSERT_TRUE(time_provider_->Get().at(kDeviceUtcTimeKey).HasValue());
EXPECT_EQ(time_provider_->Get().at(kDeviceUtcTimeKey).Value(), kUtcTimeStr);
ASSERT_TRUE(time_provider_->Get().at(kDeviceUptimeKey).HasValue());
EXPECT_EQ(time_provider_->Get().at(kDeviceUptimeKey).Value(), kUptimeStr);
ASSERT_TRUE(time_provider_->Get().at(kDeviceRuntimeKey).HasValue());
EXPECT_EQ(time_provider_->Get().at(kDeviceRuntimeKey).Value(), kRuntimeStr);
ASSERT_TRUE(time_provider_->Get().at(kDeviceTotalSuspendedTimeKey).HasValue());
EXPECT_EQ(time_provider_->Get().at(kDeviceTotalSuspendedTimeKey).Value(), "000d01h00m00s");
}
} // namespace
} // namespace forensics::feedback