Start transition the metrics library to non-static API. Use gmock in tests.

Review URL: http://codereview.chromium.org/2049007
diff --git a/metrics/Makefile b/metrics/Makefile
index cb85fb9..16e1d9f 100644
--- a/metrics/Makefile
+++ b/metrics/Makefile
@@ -28,7 +28,7 @@
 	metrics_daemon_test.o
 
 DAEMON_LDFLAGS = $(LDCONFIG) -lrt -lbase -lpthread -lgflags
-TESTDAEMON_LIBS = -lgtest
+TESTDAEMON_LIBS = -lgmock -lgtest
 
 all: $(LIB) $(SHAREDLIB) $(CLIENT) $(DAEMON)
 
diff --git a/metrics/README b/metrics/README
index 912af27..d8f17c4 100644
--- a/metrics/README
+++ b/metrics/README
@@ -32,21 +32,26 @@
   $SYSROOT/usr/include/ when the metrics library is built and
   installed.
 
-- Currently, the API includes two static methods:
+- The API includes two methods:
+
+  bool MetricsLibrary::SendToUMA(const std::string& name, int sample,
+                                 int min, int max, int nbuckets)
+  sends a sample for a regular (exponential) histogram.
+
+  bool MetricsLibrary::SendEnumToUMA(const std::string& name, int sample,
+                                     int max)
+  sends a sample for an enumeration (linear) histogram.
+
+  Currently, the API also includes two deprecated static methods:
 
   bool MetricsLibrary::SendToChrome(const std::string& name, int sample,
                                     int min, int max, int nbuckets)
-  sends a sample for a regular (exponential) histogram.
-
   bool MetricsLibrary::SendEnumToChrome(const std::string& name, int sample,
                                         int max)
-  sends a sample for an enumeration (linear) histogram.
 
-  See API documentation in metrics_library.h under
+  See the API documentation in metrics_library.h under
   src/platform/metrics/.
 
-  TODO: It might be better to convert the API to a dynamic object.
-
 - On the target platform, shortly after the sample is sent it should
   be visible in Chrome through "about:histograms".
 
diff --git a/metrics/metrics_daemon.cc b/metrics/metrics_daemon.cc
index da96dc2..a66b570 100644
--- a/metrics/metrics_daemon.cc
+++ b/metrics/metrics_daemon.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "metrics_daemon.h"
-#include "metrics_library.h"
 
 #include <dbus/dbus-glib-lowlevel.h>
 #include <sys/file.h>
@@ -101,14 +100,18 @@
 };
 
 void MetricsDaemon::Run(bool run_as_daemon) {
-  Init(false);
+  MetricsLibrary metrics_lib;
+  metrics_lib.Init();
+  Init(false, &metrics_lib);
   if (!run_as_daemon || daemon(0, 0) == 0) {
     Loop();
   }
 }
 
-void MetricsDaemon::Init(bool testing) {
+void MetricsDaemon::Init(bool testing, MetricsLibraryInterface* metrics_lib) {
   testing_ = testing;
+  DCHECK(metrics_lib != NULL);
+  metrics_lib_ = metrics_lib;
   daily_use_record_file_ = kDailyUseRecordFile;
 
   // Don't setup D-Bus and GLib in test mode.
@@ -444,9 +447,7 @@
 
 void MetricsDaemon::PublishMetric(const char* name, int sample,
                                   int min, int max, int nbuckets) {
-  LOG(INFO) << "received metric: " << name << " " << sample << " "
-            << min << " " << max << " " << nbuckets;
-  if (!testing_) {
-    MetricsLibrary::SendToChrome(name, sample, min, max, nbuckets);
-  }
+  DLOG(INFO) << "received metric: " << name << " " << sample << " "
+             << min << " " << max << " " << nbuckets;
+  metrics_lib_->SendToUMA(name, sample, min, max, nbuckets);
 }
diff --git a/metrics/metrics_daemon.h b/metrics/metrics_daemon.h
index 3ab857a..3aeaaaa 100644
--- a/metrics/metrics_daemon.h
+++ b/metrics/metrics_daemon.h
@@ -9,6 +9,8 @@
 #include <glib.h>
 #include <time.h>
 
+#include "metrics_library.h"
+
 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
 
 class MetricsDaemon {
@@ -34,18 +36,23 @@
 
  private:
   friend class MetricsDaemonTest;
-  FRIEND_TEST(MetricsDaemonTest, LogDailyUseRecord);
+  FRIEND_TEST(MetricsDaemonTest, LogDailyUseRecordBadFileLocation);
+  FRIEND_TEST(MetricsDaemonTest, LogDailyUseRecordOnLogin);
+  FRIEND_TEST(MetricsDaemonTest, LogDailyUseRecordRoundDown);
+  FRIEND_TEST(MetricsDaemonTest, LogDailyUseRecordRoundUp);
   FRIEND_TEST(MetricsDaemonTest, LookupNetworkState);
   FRIEND_TEST(MetricsDaemonTest, LookupPowerState);
   FRIEND_TEST(MetricsDaemonTest, LookupScreenSaverState);
   FRIEND_TEST(MetricsDaemonTest, LookupSessionState);
   FRIEND_TEST(MetricsDaemonTest, MessageFilter);
-  FRIEND_TEST(MetricsDaemonTest, NetStateChanged);
+  FRIEND_TEST(MetricsDaemonTest, NetStateChangedSimpleDrop);
+  FRIEND_TEST(MetricsDaemonTest, NetStateChangedSuspend);
   FRIEND_TEST(MetricsDaemonTest, PowerStateChanged);
   FRIEND_TEST(MetricsDaemonTest, PublishMetric);
   FRIEND_TEST(MetricsDaemonTest, ScreenSaverStateChanged);
   FRIEND_TEST(MetricsDaemonTest, SessionStateChanged);
-  FRIEND_TEST(MetricsDaemonTest, SetUserActiveState);
+  FRIEND_TEST(MetricsDaemonTest, SetUserActiveStateSendOnLogin);
+  FRIEND_TEST(MetricsDaemonTest, SetUserActiveStateSendOnMonitor);
 
   // The network states (see network_states.h).
   enum NetworkState {
@@ -113,7 +120,7 @@
   static const char* kSessionStates_[kNumberSessionStates];
 
   // Initializes.
-  void Init(bool testing);
+  void Init(bool testing, MetricsLibraryInterface* metrics_lib);
 
   // Creates the event loop and enters it.
   void Loop();
@@ -190,6 +197,9 @@
   // Test mode.
   bool testing_;
 
+  // The metrics library handle.
+  MetricsLibraryInterface* metrics_lib_;
+
   const char* daily_use_record_file_;
 
   // Current network state.
diff --git a/metrics/metrics_daemon_test.cc b/metrics/metrics_daemon_test.cc
index 25b0855..8180b14 100644
--- a/metrics/metrics_daemon_test.cc
+++ b/metrics/metrics_daemon_test.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "metrics_daemon.h"
+#include "metrics_library_mock.h"
 
 #include <sys/file.h>
 
@@ -12,6 +13,10 @@
 #include <base/string_util.h>
 #include <gtest/gtest.h>
 
+using ::testing::Mock;
+using ::testing::Return;
+using ::testing::StrictMock;
+
 static const char kTestDailyUseRecordFile[] = "daily-usage-test";
 static const char kDoesNotExistFile[] = "/does/not/exist";
 
@@ -20,12 +25,12 @@
 class MetricsDaemonTest : public testing::Test {
  protected:
   virtual void SetUp() {
-    daemon_.Init(true);
+    daemon_.Init(true, &metrics_lib_);
     daemon_.daily_use_record_file_ = kTestDailyUseRecordFile;
 
     // The test fixture object will be used by the log message handler.
     daemon_test_ = this;
-    logging::SetLogMessageHandler(LogMessageHandler);
+    logging::SetLogMessageHandler(HandleLogMessages);
   }
 
   virtual void TearDown() {
@@ -36,7 +41,7 @@
 
   // Collects log messages in the |daemon_log_| member string so that
   // they can be analyzed for errors and expected behavior.
-  static bool LogMessageHandler(int severity, const std::string& str) {
+  static bool HandleLogMessages(int severity, const std::string& str) {
     daemon_test_->daemon_log_.append(str);
     daemon_test_->daemon_log_.append("\n");
 
@@ -49,43 +54,32 @@
     return daemon_log_.find(pattern) != std::string::npos;
   }
 
-  // Resets the daemon log history to empty.
-  void LogReset() {
-    daemon_log_.clear();
+  // Adds a metrics library mock expectation that the specified metric
+  // will be generated.
+  void ExpectMetric(const std::string& name, int sample,
+                    int min, int max, int buckets) {
+    EXPECT_CALL(metrics_lib_, SendToUMA(name, sample, min, max, buckets))
+        .Times(1)
+        .WillOnce(Return(true))
+        .RetiresOnSaturation();
   }
 
-  // Returns true if the specified metric is found in the generated
-  // log so far, false otherwise.
-  bool AssertMetricGenerated(const std::string& name, int sample,
-                             int min, int max, int buckets) {
-    return LogContains(StringPrintf("received metric: %s %d %d %d %d",
-                                    name.c_str(), sample, min, max, buckets));
+  // Adds a metrics library mock expectation that the specified daily
+  // use time metric will be generated.
+  void ExpectDailyUseTimeMetric(int sample) {
+    ExpectMetric(MetricsDaemon::kMetricDailyUseTimeName, sample,
+                 MetricsDaemon::kMetricDailyUseTimeMin,
+                 MetricsDaemon::kMetricDailyUseTimeMax,
+                 MetricsDaemon::kMetricDailyUseTimeBuckets);
   }
 
-  // Returns true if the specified daily use time metric is found in
-  // the generated log so far, false otherwise.
-  bool AssertDailyUseTimeMetric(int sample) {
-    return AssertMetricGenerated(
-        MetricsDaemon::kMetricDailyUseTimeName, sample,
-        MetricsDaemon::kMetricDailyUseTimeMin,
-        MetricsDaemon::kMetricDailyUseTimeMax,
-        MetricsDaemon::kMetricDailyUseTimeBuckets);
-  }
-
-  // Returns true if the specified time to network drop metric is
-  // found in the generated log so far, false otherwise.
-  bool AssertTimeToNetworkDropMetric(int sample) {
-    return AssertMetricGenerated(
-        MetricsDaemon::kMetricTimeToNetworkDropName, sample,
-        MetricsDaemon::kMetricTimeToNetworkDropMin,
-        MetricsDaemon::kMetricTimeToNetworkDropMax,
-        MetricsDaemon::kMetricTimeToNetworkDropBuckets);
-  }
-
-  // Returns true if no metric can be found in the generated log so
-  // far, false otherwise.
-  bool NoMetricGenerated() {
-    return !LogContains("received metric");
+  // Adds a metrics library mock expectation that the specified time
+  // to network dropping metric will be generated.
+  void ExpectTimeToNetworkDropMetric(int sample) {
+    ExpectMetric(MetricsDaemon::kMetricTimeToNetworkDropName, sample,
+                 MetricsDaemon::kMetricTimeToNetworkDropMin,
+                 MetricsDaemon::kMetricTimeToNetworkDropMax,
+                 MetricsDaemon::kMetricTimeToNetworkDropBuckets);
   }
 
   // Asserts that the daily use record file contains the specified
@@ -125,7 +119,7 @@
 
   // Returns true if the daily use record file does not exist or is
   // empty, false otherwise.
-  bool NoOrEmptyUseRecordFile() {
+  bool AssertNoOrEmptyUseRecordFile() {
     FilePath record_file(daemon_.daily_use_record_file_);
     int64 record_file_size;
     return !file_util::PathExists(record_file) ||
@@ -167,6 +161,10 @@
   // The MetricsDaemon under test.
   MetricsDaemon daemon_;
 
+  // Metrics library mock. It's a strict mock so that all unexpected
+  // metric generation calls are marked as failures.
+  StrictMock<MetricsLibraryMock> metrics_lib_;
+
   // The accumulated metrics daemon log.
   std::string daemon_log_;
 };
@@ -174,9 +172,20 @@
 // static
 MetricsDaemonTest* MetricsDaemonTest::daemon_test_ = NULL;
 
-TEST_F(MetricsDaemonTest, LogDailyUseRecord) {
+TEST_F(MetricsDaemonTest, LogDailyUseRecordBadFileLocation) {
+  // Checks that the daemon doesn't die badly if the file can't be
+  // created.
+  daemon_.daily_use_record_file_ = kDoesNotExistFile;
+  daemon_.LogDailyUseRecord(10, 20);
+  EXPECT_TRUE(LogContains("Unable to open the daily use file: "
+                          "No such file or directory"));
   EXPECT_EQ(0, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(NoOrEmptyUseRecordFile());
+  file_util::Delete(FilePath(kDoesNotExistFile), false);
+}
+
+TEST_F(MetricsDaemonTest, LogDailyUseRecordOnLogin) {
+  EXPECT_EQ(0, daemon_.daily_use_day_last_);
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
   daemon_.LogDailyUseRecord(/* day */ 5, /* seconds */ 120);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 5, /* seconds */ 120);
@@ -190,12 +199,31 @@
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 5, /* seconds */ 360);
   EXPECT_EQ(5, daemon_.daily_use_day_last_);
 
-  EXPECT_TRUE(NoMetricGenerated());
-
-  LogReset();
+  ExpectDailyUseTimeMetric(/* sample */ 6);
   daemon_.LogDailyUseRecord(/* day */ 6, /* seconds */ 0);
-  EXPECT_TRUE(NoOrEmptyUseRecordFile());
-  EXPECT_TRUE(AssertDailyUseTimeMetric(/* sample */ 6));
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
+  EXPECT_EQ(6, daemon_.daily_use_day_last_);
+}
+
+TEST_F(MetricsDaemonTest, LogDailyUseRecordRoundDown) {
+  EXPECT_EQ(0, daemon_.daily_use_day_last_);
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
+
+  daemon_.LogDailyUseRecord(/* day */ 7, /* seconds */ 89);
+  EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 7, /* seconds */ 89);
+  EXPECT_EQ(7, daemon_.daily_use_day_last_);
+
+  ExpectDailyUseTimeMetric(/* sample */ 1);
+  daemon_.LogDailyUseRecord(/* day */ 6, /* seconds */ 15);
+  EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 6, /* seconds */ 15);
+  EXPECT_EQ(6, daemon_.daily_use_day_last_);
+}
+
+TEST_F(MetricsDaemonTest, LogDailyUseRecordRoundUp) {
+  EXPECT_EQ(0, daemon_.daily_use_day_last_);
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
+
+  daemon_.LogDailyUseRecord(/* day */ 6, /* seconds */ 0);
   EXPECT_EQ(6, daemon_.daily_use_day_last_);
 
   // Tests rounding use time to the closest minute.
@@ -203,27 +231,10 @@
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 6, /* seconds */ 90);
   EXPECT_EQ(6, daemon_.daily_use_day_last_);
 
-  LogReset();
+  ExpectDailyUseTimeMetric(/* sample */ 2);
   daemon_.LogDailyUseRecord(/* day */ 7, /* seconds */ 89);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 7, /* seconds */ 89);
-  EXPECT_TRUE(AssertDailyUseTimeMetric(/* sample */ 2));
   EXPECT_EQ(7, daemon_.daily_use_day_last_);
-
-  LogReset();
-  daemon_.LogDailyUseRecord(/* day */ 6, /* seconds */ 15);
-  EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 6, /* seconds */ 15);
-  EXPECT_TRUE(AssertDailyUseTimeMetric(/* sample */ 1));
-  EXPECT_EQ(6, daemon_.daily_use_day_last_);
-
-  // Checks that the daemon doesn't die badly if the file can't be
-  // created.
-  LogReset();
-  daemon_.daily_use_record_file_ = kDoesNotExistFile;
-  daemon_.LogDailyUseRecord(10, 20);
-  EXPECT_TRUE(LogContains("Unable to open the daily use file: "
-                          "No such file or directory"));
-  EXPECT_EQ(6, daemon_.daily_use_day_last_);
-  file_util::Delete(FilePath(kDoesNotExistFile), false);
 }
 
 TEST_F(MetricsDaemonTest, LookupNetworkState) {
@@ -320,7 +331,7 @@
   DeleteDBusMessage(msg);
 }
 
-TEST_F(MetricsDaemonTest, NetStateChanged) {
+TEST_F(MetricsDaemonTest, NetStateChangedSimpleDrop) {
   EXPECT_EQ(MetricsDaemon::kUnknownNetworkState, daemon_.network_state_);
   EXPECT_EQ(0, daemon_.network_state_last_);
   EXPECT_EQ(MetricsDaemon::kUnknownPowerState, daemon_.power_state_);
@@ -329,14 +340,21 @@
   EXPECT_EQ(MetricsDaemon::kNetworkStateOnline, daemon_.network_state_);
   EXPECT_EQ(10, daemon_.network_state_last_);
 
-  EXPECT_TRUE(NoMetricGenerated());
+  ExpectTimeToNetworkDropMetric(20);
+  daemon_.NetStateChanged("offline", /* now */ 30);
+  EXPECT_EQ(MetricsDaemon::kNetworkStateOffline, daemon_.network_state_);
+  EXPECT_EQ(30, daemon_.network_state_last_);
+}
+
+TEST_F(MetricsDaemonTest, NetStateChangedSuspend) {
+  EXPECT_EQ(MetricsDaemon::kUnknownNetworkState, daemon_.network_state_);
+  EXPECT_EQ(0, daemon_.network_state_last_);
+  EXPECT_EQ(MetricsDaemon::kUnknownPowerState, daemon_.power_state_);
 
   daemon_.NetStateChanged("offline", /* now */ 30);
   EXPECT_EQ(MetricsDaemon::kNetworkStateOffline, daemon_.network_state_);
   EXPECT_EQ(30, daemon_.network_state_last_);
-  EXPECT_TRUE(AssertTimeToNetworkDropMetric(/* sample */ 20));
 
-  LogReset();
   daemon_.NetStateChanged("online", /* now */ 60);
   EXPECT_EQ(MetricsDaemon::kNetworkStateOnline, daemon_.network_state_);
   EXPECT_EQ(60, daemon_.network_state_last_);
@@ -367,12 +385,10 @@
   EXPECT_EQ(MetricsDaemon::kNetworkStateOnline, daemon_.network_state_);
   EXPECT_EQ(105, daemon_.network_state_last_);
 
-  EXPECT_TRUE(NoMetricGenerated());
-
+  ExpectTimeToNetworkDropMetric(3);
   daemon_.NetStateChanged("offline", /* now */ 108);
   EXPECT_EQ(MetricsDaemon::kNetworkStateOffline, daemon_.network_state_);
   EXPECT_EQ(108, daemon_.network_state_last_);
-  EXPECT_TRUE(AssertTimeToNetworkDropMetric(/* sample */ 3));
 }
 
 TEST_F(MetricsDaemonTest, PowerStateChanged) {
@@ -380,13 +396,13 @@
   EXPECT_FALSE(daemon_.user_active_);
   EXPECT_EQ(0, daemon_.user_active_last_);
   EXPECT_EQ(0, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(NoOrEmptyUseRecordFile());
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
   daemon_.SetUserActiveState(/* active */ true, 7 * kSecondsPerDay + 15);
   EXPECT_TRUE(daemon_.user_active_);
   EXPECT_EQ(7 * kSecondsPerDay + 15, daemon_.user_active_last_);
   EXPECT_EQ(7, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(NoOrEmptyUseRecordFile());
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
   daemon_.PowerStateChanged("mem", 7 * kSecondsPerDay + 45);
   EXPECT_EQ(MetricsDaemon::kPowerStateMem, daemon_.power_state_);
@@ -405,14 +421,12 @@
   EXPECT_FALSE(daemon_.user_active_);
   EXPECT_EQ(7 * kSecondsPerDay + 185, daemon_.user_active_last_);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 7, /* seconds */ 30);
-
-  EXPECT_TRUE(NoMetricGenerated());
 }
 
 TEST_F(MetricsDaemonTest, PublishMetric) {
+  ExpectMetric("Dummy.Metric", 3, 1, 100, 50);
   daemon_.PublishMetric("Dummy.Metric", /* sample */ 3,
                         /* min */ 1, /* max */ 100, /* buckets */ 50);
-  EXPECT_TRUE(AssertMetricGenerated("Dummy.Metric", 3, 1, 100, 50));
 }
 
 TEST_F(MetricsDaemonTest, ScreenSaverStateChanged) {
@@ -421,7 +435,7 @@
   EXPECT_FALSE(daemon_.user_active_);
   EXPECT_EQ(0, daemon_.user_active_last_);
   EXPECT_EQ(0, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(NoOrEmptyUseRecordFile());
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
   daemon_.ScreenSaverStateChanged("locked", 5 * kSecondsPerDay + 10);
   EXPECT_EQ(MetricsDaemon::kScreenSaverStateLocked,
@@ -429,14 +443,14 @@
   EXPECT_FALSE(daemon_.user_active_);
   EXPECT_EQ(5 * kSecondsPerDay + 10, daemon_.user_active_last_);
   EXPECT_EQ(5, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(NoOrEmptyUseRecordFile());
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
   daemon_.ScreenSaverStateChanged("unlocked", 5 * kSecondsPerDay + 100);
   EXPECT_EQ(MetricsDaemon::kScreenSaverStateUnlocked,
             daemon_.screensaver_state_);
   EXPECT_TRUE(daemon_.user_active_);
   EXPECT_EQ(5 * kSecondsPerDay + 100, daemon_.user_active_last_);
-  EXPECT_TRUE(NoOrEmptyUseRecordFile());
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
   daemon_.ScreenSaverStateChanged("otherstate", 5 * kSecondsPerDay + 300);
   EXPECT_EQ(MetricsDaemon::kUnknownScreenSaverState,
@@ -444,8 +458,6 @@
   EXPECT_FALSE(daemon_.user_active_);
   EXPECT_EQ(5 * kSecondsPerDay + 300, daemon_.user_active_last_);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 5, /* seconds */ 200);
-
-  EXPECT_TRUE(NoMetricGenerated());
 }
 
 TEST_F(MetricsDaemonTest, SessionStateChanged) {
@@ -453,14 +465,14 @@
   EXPECT_FALSE(daemon_.user_active_);
   EXPECT_EQ(0, daemon_.user_active_last_);
   EXPECT_EQ(0, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(NoOrEmptyUseRecordFile());
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
   daemon_.SessionStateChanged("started", 15 * kSecondsPerDay + 20);
   EXPECT_EQ(MetricsDaemon::kSessionStateStarted, daemon_.session_state_);
   EXPECT_TRUE(daemon_.user_active_);
   EXPECT_EQ(15 * kSecondsPerDay + 20, daemon_.user_active_last_);
   EXPECT_EQ(15, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(NoOrEmptyUseRecordFile());
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
   daemon_.SessionStateChanged("stopped", 15 * kSecondsPerDay + 150);
   EXPECT_EQ(MetricsDaemon::kSessionStateStopped, daemon_.session_state_);
@@ -473,27 +485,25 @@
   EXPECT_FALSE(daemon_.user_active_);
   EXPECT_EQ(15 * kSecondsPerDay + 300, daemon_.user_active_last_);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 15, /* seconds */ 130);
-
-  EXPECT_TRUE(NoMetricGenerated());
 }
 
-TEST_F(MetricsDaemonTest, SetUserActiveState) {
+TEST_F(MetricsDaemonTest, SetUserActiveStateSendOnLogin) {
   EXPECT_FALSE(daemon_.user_active_);
   EXPECT_EQ(0, daemon_.user_active_last_);
   EXPECT_EQ(0, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(NoOrEmptyUseRecordFile());
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
   daemon_.SetUserActiveState(/* active */ false, 5 * kSecondsPerDay + 10);
   EXPECT_FALSE(daemon_.user_active_);
   EXPECT_EQ(5 * kSecondsPerDay + 10, daemon_.user_active_last_);
   EXPECT_EQ(5, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(NoOrEmptyUseRecordFile());
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
   daemon_.SetUserActiveState(/* active */ true, 6 * kSecondsPerDay + 20);
   EXPECT_TRUE(daemon_.user_active_);
   EXPECT_EQ(6 * kSecondsPerDay + 20, daemon_.user_active_last_);
   EXPECT_EQ(6, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(NoOrEmptyUseRecordFile());
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
   daemon_.SetUserActiveState(/* active */ true, 6 * kSecondsPerDay + 120);
   EXPECT_TRUE(daemon_.user_active_);
@@ -507,17 +517,26 @@
   EXPECT_EQ(6, daemon_.daily_use_day_last_);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 6, /* seconds */ 200);
 
-  EXPECT_TRUE(NoMetricGenerated());
-
-  LogReset();
+  ExpectDailyUseTimeMetric(/* sample */ 3);
   daemon_.SetUserActiveState(/* active */ true, 8 * kSecondsPerDay - 300);
   EXPECT_TRUE(daemon_.user_active_);
   EXPECT_EQ(8 * kSecondsPerDay - 300, daemon_.user_active_last_);
   EXPECT_EQ(7, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(NoOrEmptyUseRecordFile());
-  EXPECT_TRUE(AssertDailyUseTimeMetric(/* sample */ 3));
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
+}
 
-  LogReset();
+TEST_F(MetricsDaemonTest, SetUserActiveStateSendOnMonitor) {
+  EXPECT_FALSE(daemon_.user_active_);
+  EXPECT_EQ(0, daemon_.user_active_last_);
+  EXPECT_EQ(0, daemon_.daily_use_day_last_);
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
+
+  daemon_.SetUserActiveState(/* active */ true, 8 * kSecondsPerDay - 300);
+  EXPECT_TRUE(daemon_.user_active_);
+  EXPECT_EQ(8 * kSecondsPerDay - 300, daemon_.user_active_last_);
+  EXPECT_EQ(7, daemon_.daily_use_day_last_);
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
+
   daemon_.SetUserActiveState(/* active */ false, 8 * kSecondsPerDay + 300);
   EXPECT_FALSE(daemon_.user_active_);
   EXPECT_EQ(8 * kSecondsPerDay + 300, daemon_.user_active_last_);
@@ -530,15 +549,12 @@
   EXPECT_EQ(8, daemon_.daily_use_day_last_);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 8, /* seconds */ 600);
 
-  EXPECT_TRUE(NoMetricGenerated());
-
-  LogReset();
+  ExpectDailyUseTimeMetric(/* sample */ 10);
   daemon_.SetUserActiveState(/* active */ true, 9 * kSecondsPerDay + 400);
   EXPECT_TRUE(daemon_.user_active_);
   EXPECT_EQ(9 * kSecondsPerDay + 400, daemon_.user_active_last_);
   EXPECT_EQ(9, daemon_.daily_use_day_last_);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 9, /* seconds */ 800);
-  EXPECT_TRUE(AssertDailyUseTimeMetric(/* sample */ 10));
 }
 
 int main(int argc, char **argv) {
diff --git a/metrics/metrics_library.cc b/metrics/metrics_library.cc
index 95e78b2..2accb1a 100644
--- a/metrics/metrics_library.cc
+++ b/metrics/metrics_library.cc
@@ -121,6 +121,9 @@
   return message_length;
 }
 
+void MetricsLibrary::Init() {
+}
+
 // static
 bool MetricsLibrary::SendToAutotest(const string& name, int value) {
   FILE *autotest_file = fopen(kAutotestPath, "a+");
@@ -151,6 +154,11 @@
   return SendMessageToChrome(message_length, message);
 }
 
+bool MetricsLibrary::SendToUMA(const string& name, int sample,
+                               int min, int max, int nbuckets) {
+  return SendToChrome(name, sample, min, max, nbuckets);
+}
+
 //static
 bool MetricsLibrary::SendEnumToChrome(const std::string& name, int sample,
                                       int max) {
@@ -167,3 +175,8 @@
   // Send the message.
   return SendMessageToChrome(message_length, message);
 }
+
+bool MetricsLibrary::SendEnumToUMA(const std::string& name, int sample,
+                                   int max) {
+  return SendEnumToChrome(name, sample, max);
+}
diff --git a/metrics/metrics_library.h b/metrics/metrics_library.h
index 7383960..e5e9024 100644
--- a/metrics/metrics_library.h
+++ b/metrics/metrics_library.h
@@ -16,9 +16,21 @@
 
 // TODO(sosa@chromium.org): Add testing for send methods
 
-// Library used to send metrics both Autotest and Chrome.
-class MetricsLibrary {
+class MetricsLibraryInterface {
  public:
+  virtual void Init() = 0;
+  virtual bool SendToUMA(const std::string& name, int sample,
+                         int min, int max, int nbuckets) = 0;
+  virtual bool SendEnumToUMA(const std::string& name, int sample, int max) = 0;
+  virtual ~MetricsLibraryInterface() {}
+};
+
+// Library used to send metrics to both Autotest and Chrome/UMA.
+class MetricsLibrary : public MetricsLibraryInterface {
+ public:
+  // Initializes the library.
+  void Init();
+
   // Sends histogram data to Chrome for transport to UMA and returns
   // true on success. This method results in the equivalent of an
   // asynchronous non-blocking RPC to UMA_HISTOGRAM_CUSTOM_COUNTS
@@ -30,6 +42,10 @@
   // |nbuckets| is the number of histogram buckets.
   // [0,min) is the implicit underflow bucket.
   // [|max|,infinity) is the implicit overflow bucket.
+  bool SendToUMA(const std::string& name, int sample,
+                 int min, int max, int nbuckets);
+
+  // Deprecated.
   static bool SendToChrome(const std::string& name, int sample,
                            int min, int max, int nbuckets);
 
@@ -42,6 +58,9 @@
   // |max| is the maximum value of the histogram samples.
   // 0 is the implicit underflow bucket.
   // [|max|,infinity) is the implicit overflow bucket.
+  bool SendEnumToUMA(const std::string& name, int sample, int max);
+
+  // Deprecated.
   static bool SendEnumToChrome(const std::string& name, int sample, int max);
 
   // Sends to Autotest and returns true on success.
diff --git a/metrics/metrics_library_mock.h b/metrics/metrics_library_mock.h
new file mode 100644
index 0000000..ffc9342
--- /dev/null
+++ b/metrics/metrics_library_mock.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef METRICS_LIBRARY_MOCK_H_
+#define METRICS_LIBRARY_MOCK_H_
+
+#include <string>
+
+#include "metrics_library.h"
+
+#include <gmock/gmock.h>
+
+class MetricsLibraryMock : public MetricsLibraryInterface {
+ public:
+  MOCK_METHOD0(Init, void());
+  MOCK_METHOD5(SendToUMA, bool(const std::string& name, int sample,
+                               int min, int max, int nbuckets));
+  MOCK_METHOD3(SendEnumToUMA, bool(const std::string& name, int sample,
+                                   int max));
+};
+
+#endif /* METRICS_LIBRARY_MOCK_H_ */