Move metrics time helpers to metrics_utils.

The metrics module reports metrics periodically, for which it needs to
keep track of the duration since some events (for example, the update
finished). These helpers were in the common/utils.h, but they rely on
the global SystemState to access both Prefs and Clock.

Since these helpers are specific to the metric reporting, this CL moves
them to the metrics_utils.h module.

Bug: 25197634
TEST=FEATURES=test emerge-link update_engine; mmma system/update_engine

Change-Id: Ia48091adbdc56c339c69c86c91c5c01aa58c54fb
diff --git a/metrics_utils_unittest.cc b/metrics_utils_unittest.cc
index 97f0b46..e702c17 100644
--- a/metrics_utils_unittest.cc
+++ b/metrics_utils_unittest.cc
@@ -18,6 +18,10 @@
 
 #include <gtest/gtest.h>
 
+#include "update_engine/common/fake_clock.h"
+#include "update_engine/common/fake_prefs.h"
+#include "update_engine/fake_system_state.h"
+
 namespace chromeos_update_engine {
 namespace metrics_utils {
 
@@ -73,5 +77,134 @@
                               NetworkTethering::kUnknown));
 }
 
+TEST(MetricsUtilsTest, WallclockDurationHelper) {
+  FakeSystemState fake_system_state;
+  FakeClock fake_clock;
+  base::TimeDelta duration;
+  const std::string state_variable_key = "test-prefs";
+  FakePrefs fake_prefs;
+
+  fake_system_state.set_clock(&fake_clock);
+  fake_system_state.set_prefs(&fake_prefs);
+
+  // Initialize wallclock to 1 sec.
+  fake_clock.SetWallclockTime(base::Time::FromInternalValue(1000000));
+
+  // First time called so no previous measurement available.
+  EXPECT_FALSE(metrics_utils::WallclockDurationHelper(&fake_system_state,
+                                                      state_variable_key,
+                                                      &duration));
+
+  // Next time, we should get zero since the clock didn't advance.
+  EXPECT_TRUE(metrics_utils::WallclockDurationHelper(&fake_system_state,
+                                                     state_variable_key,
+                                                     &duration));
+  EXPECT_EQ(duration.InSeconds(), 0);
+
+  // We can also call it as many times as we want with it being
+  // considered a failure.
+  EXPECT_TRUE(metrics_utils::WallclockDurationHelper(&fake_system_state,
+                                                     state_variable_key,
+                                                     &duration));
+  EXPECT_EQ(duration.InSeconds(), 0);
+  EXPECT_TRUE(metrics_utils::WallclockDurationHelper(&fake_system_state,
+                                                     state_variable_key,
+                                                     &duration));
+  EXPECT_EQ(duration.InSeconds(), 0);
+
+  // Advance the clock one second, then we should get 1 sec on the
+  // next call and 0 sec on the subsequent call.
+  fake_clock.SetWallclockTime(base::Time::FromInternalValue(2000000));
+  EXPECT_TRUE(metrics_utils::WallclockDurationHelper(&fake_system_state,
+                                                     state_variable_key,
+                                                     &duration));
+  EXPECT_EQ(duration.InSeconds(), 1);
+  EXPECT_TRUE(metrics_utils::WallclockDurationHelper(&fake_system_state,
+                                                     state_variable_key,
+                                                     &duration));
+  EXPECT_EQ(duration.InSeconds(), 0);
+
+  // Advance clock two seconds and we should get 2 sec and then 0 sec.
+  fake_clock.SetWallclockTime(base::Time::FromInternalValue(4000000));
+  EXPECT_TRUE(metrics_utils::WallclockDurationHelper(&fake_system_state,
+                                                     state_variable_key,
+                                                     &duration));
+  EXPECT_EQ(duration.InSeconds(), 2);
+  EXPECT_TRUE(metrics_utils::WallclockDurationHelper(&fake_system_state,
+                                                     state_variable_key,
+                                                     &duration));
+  EXPECT_EQ(duration.InSeconds(), 0);
+
+  // There's a possibility that the wallclock can go backwards (NTP
+  // adjustments, for example) so check that we properly handle this
+  // case.
+  fake_clock.SetWallclockTime(base::Time::FromInternalValue(3000000));
+  EXPECT_FALSE(metrics_utils::WallclockDurationHelper(&fake_system_state,
+                                                      state_variable_key,
+                                                      &duration));
+  fake_clock.SetWallclockTime(base::Time::FromInternalValue(4000000));
+  EXPECT_TRUE(metrics_utils::WallclockDurationHelper(&fake_system_state,
+                                                     state_variable_key,
+                                                     &duration));
+  EXPECT_EQ(duration.InSeconds(), 1);
+}
+
+TEST(MetricsUtilsTest, MonotonicDurationHelper) {
+  int64_t storage = 0;
+  FakeSystemState fake_system_state;
+  FakeClock fake_clock;
+  base::TimeDelta duration;
+
+  fake_system_state.set_clock(&fake_clock);
+
+  // Initialize monotonic clock to 1 sec.
+  fake_clock.SetMonotonicTime(base::Time::FromInternalValue(1000000));
+
+  // First time called so no previous measurement available.
+  EXPECT_FALSE(metrics_utils::MonotonicDurationHelper(&fake_system_state,
+                                                      &storage,
+                                                      &duration));
+
+  // Next time, we should get zero since the clock didn't advance.
+  EXPECT_TRUE(metrics_utils::MonotonicDurationHelper(&fake_system_state,
+                                                     &storage,
+                                                     &duration));
+  EXPECT_EQ(duration.InSeconds(), 0);
+
+  // We can also call it as many times as we want with it being
+  // considered a failure.
+  EXPECT_TRUE(metrics_utils::MonotonicDurationHelper(&fake_system_state,
+                                                     &storage,
+                                                     &duration));
+  EXPECT_EQ(duration.InSeconds(), 0);
+  EXPECT_TRUE(metrics_utils::MonotonicDurationHelper(&fake_system_state,
+                                                     &storage,
+                                                     &duration));
+  EXPECT_EQ(duration.InSeconds(), 0);
+
+  // Advance the clock one second, then we should get 1 sec on the
+  // next call and 0 sec on the subsequent call.
+  fake_clock.SetMonotonicTime(base::Time::FromInternalValue(2000000));
+  EXPECT_TRUE(metrics_utils::MonotonicDurationHelper(&fake_system_state,
+                                                     &storage,
+                                                     &duration));
+  EXPECT_EQ(duration.InSeconds(), 1);
+  EXPECT_TRUE(metrics_utils::MonotonicDurationHelper(&fake_system_state,
+                                                     &storage,
+                                                     &duration));
+  EXPECT_EQ(duration.InSeconds(), 0);
+
+  // Advance clock two seconds and we should get 2 sec and then 0 sec.
+  fake_clock.SetMonotonicTime(base::Time::FromInternalValue(4000000));
+  EXPECT_TRUE(metrics_utils::MonotonicDurationHelper(&fake_system_state,
+                                                     &storage,
+                                                     &duration));
+  EXPECT_EQ(duration.InSeconds(), 2);
+  EXPECT_TRUE(metrics_utils::MonotonicDurationHelper(&fake_system_state,
+                                                     &storage,
+                                                     &duration));
+  EXPECT_EQ(duration.InSeconds(), 0);
+}
+
 }  // namespace metrics_utils
 }  // namespace chromeos_update_engine