Measure and report time between user-space process crashes.
BUG=none
TEST=unit tests, gmerged on the device and inspected
logs, about:histograms,etc.
Review URL: http://codereview.chromium.org/2736008
diff --git a/metrics/counter.cc b/metrics/counter.cc
index 34fcf71..58dbae4 100644
--- a/metrics/counter.cc
+++ b/metrics/counter.cc
@@ -58,11 +58,16 @@
}
void TaggedCounter::UpdateInternal(int tag, int count, bool flush) {
- // If there's no new data and the last record in the aggregation
- // file is with the same tag, there's nothing to do.
- if (!flush && count <= 0 &&
- record_state_ == kRecordValid && record_.tag() == tag)
- return;
+ if (flush) {
+ // Flushing but record is null, so nothing to do.
+ if (record_state_ == kRecordNull)
+ return;
+ } else {
+ // If there's no new data and the last record in the aggregation
+ // file is with the same tag, there's nothing to do.
+ if (count <= 0 && record_state_ == kRecordValid && record_.tag() == tag)
+ return;
+ }
DLOG(INFO) << "tag: " << tag << " count: " << count << " flush: " << flush;
DCHECK(filename_);
@@ -78,7 +83,7 @@
ReadRecord(fd);
ReportRecord(tag, flush);
- UpdateRecord(tag, count);
+ UpdateRecord(tag, count, flush);
WriteRecord(fd);
HANDLE_EINTR(close(fd));
@@ -89,7 +94,7 @@
return;
if (HANDLE_EINTR(read(fd, &record_, sizeof(record_))) == sizeof(record_)) {
- if (record_.count() > 0) {
+ if (record_.count() >= 0) {
record_state_ = kRecordValid;
return;
}
@@ -106,7 +111,7 @@
void TaggedCounter::ReportRecord(int tag, bool flush) {
// If no valid record, there's nothing to report.
if (record_state_ != kRecordValid) {
- DCHECK(record_state_ == kRecordNull);
+ DCHECK_EQ(record_state_, kRecordNull);
return;
}
@@ -121,9 +126,11 @@
record_state_ = kRecordNullDirty;
}
-void TaggedCounter::UpdateRecord(int tag, int count) {
- if (count <= 0)
+void TaggedCounter::UpdateRecord(int tag, int count, bool flush) {
+ if (flush) {
+ DCHECK(record_state_ == kRecordNull || record_state_ == kRecordNullDirty);
return;
+ }
switch (record_state_) {
case kRecordNull:
@@ -137,8 +144,10 @@
// If there's an existing record for the current tag,
// accumulates the counts.
DCHECK_EQ(record_.tag(), tag);
- record_.Add(count);
- record_state_ = kRecordValidDirty;
+ if (count > 0) {
+ record_.Add(count);
+ record_state_ = kRecordValidDirty;
+ }
break;
default:
diff --git a/metrics/counter.h b/metrics/counter.h
index aac00af..876b107 100644
--- a/metrics/counter.h
+++ b/metrics/counter.h
@@ -22,8 +22,7 @@
public:
// Callback type used for reporting aggregated or flushed data.
// Once this callback is invoked by the counter, the reported
- // aggregated data is discarded. Only aggregated data with positive
- // counts is reported.
+ // aggregated data is discarded.
//
// |handle| is the |reporter_handle| pointer passed through Init.
// |tag| is the tag associated with the aggregated count.
@@ -124,8 +123,9 @@
// Updates the cached record given the new |tag| and |count|. This
// method expects either a null cached record, or a valid cached
- // record with the same tag as |tag|.
- void UpdateRecord(int tag, int count);
+ // record with the same tag as |tag|. If |flush| is true, the method
+ // asserts that the cached record is null and returns.
+ void UpdateRecord(int tag, int count, bool flush);
// If the cached record state is dirty, updates the persistent
// storage specified through file descriptor |fd| and switches the
diff --git a/metrics/counter_test.cc b/metrics/counter_test.cc
index f9a191f..605e859 100644
--- a/metrics/counter_test.cc
+++ b/metrics/counter_test.cc
@@ -230,8 +230,8 @@
ExpectReporterCall(/* tag */ 31, /* count */ 60);
counter_.Init(kTestRecordFile, &Reporter, this);
counter_.Update(/* tag */ 32, /* count */ 0);
- EXPECT_TRUE(AssertNoOrEmptyRecordFile());
- EXPECT_EQ(TaggedCounter::kRecordNull, counter_.record_state_);
+ EXPECT_PRED_FORMAT2(AssertRecord, /* day */ 32, /* seconds */ 0);
+ EXPECT_EQ(TaggedCounter::kRecordValid, counter_.record_state_);
}
TEST_F(TaggedCounterTest, Update) {
@@ -250,8 +250,8 @@
ExpectReporterCall(/* tag */ 21, /* count */ 15);
counter_.Update(/* tag */ 22, /* count */ 0);
- EXPECT_TRUE(AssertNoOrEmptyRecordFile());
- EXPECT_EQ(TaggedCounter::kRecordNull, counter_.record_state_);
+ EXPECT_PRED_FORMAT2(AssertRecord, /* day */ 22, /* seconds */ 0);
+ EXPECT_EQ(TaggedCounter::kRecordValid, counter_.record_state_);
}
} // namespace chromeos_metrics
diff --git a/metrics/metrics_daemon.cc b/metrics/metrics_daemon.cc
index e93c9a8..6cbe8e8 100644
--- a/metrics/metrics_daemon.cc
+++ b/metrics/metrics_daemon.cc
@@ -15,6 +15,7 @@
using base::TimeTicks;
#define SAFE_MESSAGE(e) (e.message ? e.message : "unknown error")
+#define DBUS_IFACE_CRASH_REPORTER "org.chromium.CrashReporter"
#define DBUS_IFACE_FLIMFLAM_MANAGER "org.chromium.flimflam.Manager"
#define DBUS_IFACE_POWER_MANAGER "org.chromium.PowerManager"
#define DBUS_IFACE_SESSION_MANAGER "org.chromium.SessionManagerInterface"
@@ -23,11 +24,16 @@
// TODO(petkov): This file should probably live in a user-specific stateful
// location, e.g., /home/chronos/user.
static const char kDailyUseRecordFile[] = "/var/log/metrics/daily-usage";
+static const char kUserCrashIntervalRecordFile[] =
+ "/var/log/metrics/user-crash-interval";
static const int kSecondsPerMinute = 60;
static const int kMinutesPerHour = 60;
static const int kHoursPerDay = 24;
static const int kMinutesPerDay = kHoursPerDay * kMinutesPerHour;
+static const int kSecondsPerDay = kSecondsPerMinute * kMinutesPerDay;
+static const int kDaysPerWeek = 7;
+static const int kSecondsPerWeek = kSecondsPerDay * kDaysPerWeek;
// The daily use monitor is scheduled to a 1-minute interval after
// initial user activity and then it's exponentially backed off to
@@ -52,9 +58,20 @@
8 /* hours */ * kMinutesPerHour * kSecondsPerMinute;
const int MetricsDaemon::kMetricTimeToNetworkDropBuckets = 50;
+const char MetricsDaemon::kMetricUserCrashIntervalName[] =
+ "Logging.UserCrashInterval";
+const int MetricsDaemon::kMetricUserCrashIntervalMin = 1;
+const int MetricsDaemon::kMetricUserCrashIntervalMax = 4 * kSecondsPerWeek;
+const int MetricsDaemon::kMetricUserCrashIntervalBuckets = 50;
+
// static
const char* MetricsDaemon::kDBusMatches_[] = {
"type='signal',"
+ "interface='" DBUS_IFACE_CRASH_REPORTER "',"
+ "path='/',"
+ "member='UserCrash'",
+
+ "type='signal',"
"sender='org.chromium.flimflam',"
"interface='" DBUS_IFACE_FLIMFLAM_MANAGER "',"
"path='/',"
@@ -111,6 +128,9 @@
metrics_lib_ = metrics_lib;
daily_use_.reset(new chromeos_metrics::TaggedCounter());
daily_use_->Init(kDailyUseRecordFile, &DailyUseReporter, this);
+ user_crash_interval_.reset(new chromeos_metrics::TaggedCounter());
+ user_crash_interval_->Init(kUserCrashIntervalRecordFile,
+ &UserCrashIntervalReporter, this);
// Don't setup D-Bus and GLib in test mode.
if (testing)
@@ -130,7 +150,7 @@
dbus_connection_setup_with_g_main(connection, NULL);
// Registers D-Bus matches for the signals we would like to catch.
- for (unsigned int m = 0; m < sizeof(kDBusMatches_) / sizeof(char*); m++) {
+ for (unsigned int m = 0; m < arraysize(kDBusMatches_); m++) {
const char* match = kDBusMatches_[m];
DLOG(INFO) << "adding dbus match: " << match;
dbus_bus_add_match(connection, match, &error);
@@ -171,7 +191,11 @@
DBusMessageIter iter;
dbus_message_iter_init(message, &iter);
- if (strcmp(interface, DBUS_IFACE_FLIMFLAM_MANAGER) == 0) {
+ if (strcmp(interface, DBUS_IFACE_CRASH_REPORTER) == 0) {
+ CHECK(strcmp(dbus_message_get_member(message),
+ "UserCrash") == 0);
+ daemon->ProcessUserCrash();
+ } else if (strcmp(interface, DBUS_IFACE_FLIMFLAM_MANAGER) == 0) {
CHECK(strcmp(dbus_message_get_member(message),
"StateChanged") == 0);
@@ -295,6 +319,7 @@
TimeDelta since_epoch = now - Time();
int day = since_epoch.InDays();
daily_use_->Update(day, seconds);
+ user_crash_interval_->Update(0, seconds);
// Schedules a use monitor on inactive->active transitions and
// unschedules it on active->inactive transitions.
@@ -309,6 +334,14 @@
user_active_last_ = now;
}
+void MetricsDaemon::ProcessUserCrash() {
+ // Counts the active use time up to now.
+ SetUserActiveState(user_active_, Time::Now());
+
+ // Reports the active use time since the last crash and resets it.
+ user_crash_interval_->Flush();
+}
+
// static
gboolean MetricsDaemon::UseMonitorStatic(gpointer data) {
return static_cast<MetricsDaemon*>(data)->UseMonitor() ? TRUE : FALSE;
@@ -371,6 +404,9 @@
// static
void MetricsDaemon::DailyUseReporter(void* handle, int tag, int count) {
+ if (count <= 0)
+ return;
+
MetricsDaemon* daemon = static_cast<MetricsDaemon*>(handle);
int minutes = (count + kSecondsPerMinute / 2) / kSecondsPerMinute;
daemon->SendMetric(kMetricDailyUseTimeName, minutes,
@@ -379,6 +415,16 @@
kMetricDailyUseTimeBuckets);
}
+// static
+void MetricsDaemon::UserCrashIntervalReporter(void* handle,
+ int tag, int count) {
+ MetricsDaemon* daemon = static_cast<MetricsDaemon*>(handle);
+ daemon->SendMetric(kMetricUserCrashIntervalName, count,
+ kMetricUserCrashIntervalMin,
+ kMetricUserCrashIntervalMax,
+ kMetricUserCrashIntervalBuckets);
+}
+
void MetricsDaemon::SendMetric(const std::string& name, int sample,
int min, int max, int nbuckets) {
DLOG(INFO) << "received metric: " << name << " " << sample << " "
diff --git a/metrics/metrics_daemon.h b/metrics/metrics_daemon.h
index ee80596..50958b8 100644
--- a/metrics/metrics_daemon.h
+++ b/metrics/metrics_daemon.h
@@ -40,11 +40,13 @@
FRIEND_TEST(MetricsDaemonTest, NetStateChangedSimpleDrop);
FRIEND_TEST(MetricsDaemonTest, NetStateChangedSuspend);
FRIEND_TEST(MetricsDaemonTest, PowerStateChanged);
+ FRIEND_TEST(MetricsDaemonTest, ProcessUserCrash);
FRIEND_TEST(MetricsDaemonTest, ScreenSaverStateChanged);
FRIEND_TEST(MetricsDaemonTest, SendMetric);
FRIEND_TEST(MetricsDaemonTest, SessionStateChanged);
FRIEND_TEST(MetricsDaemonTest, SetUserActiveState);
FRIEND_TEST(MetricsDaemonTest, SetUserActiveStateTimeJump);
+ FRIEND_TEST(MetricsDaemonTest, UserCrashIntervalReporter);
// The network states (see network_states.h).
enum NetworkState {
@@ -87,6 +89,10 @@
static const int kMetricTimeToNetworkDropMin;
static const int kMetricTimeToNetworkDropMax;
static const int kMetricTimeToNetworkDropBuckets;
+ static const char kMetricUserCrashIntervalName[];
+ static const int kMetricUserCrashIntervalMin;
+ static const int kMetricUserCrashIntervalMax;
+ static const int kMetricUserCrashIntervalBuckets;
// D-Bus message match strings.
static const char* kDBusMatches_[];
@@ -142,6 +148,10 @@
// the usage file, the |seconds| are accumulated.
void LogDailyUseRecord(int day, int seconds);
+ // Updates the active use time and logs time between user-space
+ // process crashes.
+ void ProcessUserCrash();
+
// Callbacks for the daily use monitor. The daily use monitor uses
// LogDailyUseRecord to aggregate current usage data and send it to
// UMA, if necessary. It also reschedules itself using an
@@ -169,8 +179,14 @@
void SendMetric(const std::string& name, int sample,
int min, int max, int nbuckets);
+ // TaggedCounter callback to process aggregated daily usage data and
+ // send to UMA.
static void DailyUseReporter(void* data, int tag, int count);
+ // TaggedCounter callback to process time between user-space process
+ // crashes and send to UMA.
+ static void UserCrashIntervalReporter(void* data, int tag, int count);
+
// Test mode.
bool testing_;
@@ -195,13 +211,17 @@
// started, screen is not locked.
bool user_active_;
- // Timestamps last user active update. Active use time is
- // aggregated each day before sending to UMA so using time since the
- // epoch as the timestamp.
+ // Timestamps last user active update. Active use time is aggregated
+ // each day before sending to UMA so using time since the epoch as
+ // the timestamp.
base::Time user_active_last_;
+ // Daily active use time in seconds.
scoped_ptr<chromeos_metrics::TaggedCounterInterface> daily_use_;
+ // Active use time between user-space process crashes.
+ scoped_ptr<chromeos_metrics::TaggedCounterInterface> user_crash_interval_;
+
// Sleep period until the next daily usage aggregation performed by
// the daily use monitor (see ScheduleUseMonitor).
int usemon_interval_;
diff --git a/metrics/metrics_daemon_test.cc b/metrics/metrics_daemon_test.cc
index 7119c85..1f2c0fa 100644
--- a/metrics/metrics_daemon_test.cc
+++ b/metrics/metrics_daemon_test.cc
@@ -42,12 +42,19 @@
protected:
virtual void SetUp() {
EXPECT_EQ(NULL, daemon_.daily_use_.get());
+ EXPECT_EQ(NULL, daemon_.user_crash_interval_.get());
daemon_.Init(true, &metrics_lib_);
// Tests constructor initialization. Switches to mock counters.
EXPECT_TRUE(NULL != daemon_.daily_use_.get());
+ EXPECT_TRUE(NULL != daemon_.user_crash_interval_.get());
+
+ // Allocates mock counter and transfers ownership.
daily_use_ = new StrictMock<TaggedCounterMock>();
- daemon_.daily_use_.reset(daily_use_); // Transfers ownership.
+ daemon_.daily_use_.reset(daily_use_);
+ user_crash_interval_ = new StrictMock<TaggedCounterMock>();
+ daemon_.user_crash_interval_.reset(user_crash_interval_);
+
EXPECT_FALSE(daemon_.user_active_);
EXPECT_TRUE(daemon_.user_active_last_.is_null());
EXPECT_EQ(MetricsDaemon::kUnknownNetworkState, daemon_.network_state_);
@@ -58,10 +65,24 @@
virtual void TearDown() {}
- // Adds a daily use aggregation counter expectation that the
+ // Adds active use aggregation counters update expectations that the
// specified tag/count update will be generated.
- void ExpectDailyUseUpdate(int tag, int count) {
- EXPECT_CALL(*daily_use_, Update(tag, count))
+ void ExpectActiveUseUpdate(int daily_tag, int count) {
+ EXPECT_CALL(*daily_use_, Update(daily_tag, count))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*user_crash_interval_, Update(0, count))
+ .Times(1)
+ .RetiresOnSaturation();
+ }
+
+ // Adds active use aggregation counters update expectations that
+ // ignore the update arguments.
+ void IgnoreActiveUseUpdate() {
+ EXPECT_CALL(*daily_use_, Update(_, _))
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*user_crash_interval_, Update(_, _))
.Times(1)
.RetiresOnSaturation();
}
@@ -134,11 +155,11 @@
// metric generation calls are marked as failures.
StrictMock<MetricsLibraryMock> metrics_lib_;
- // Daily use time aggregation counter mock. It's a strict mock so
- // that all unexpected update calls are marked as failures. It's a
- // pointer so that it can replace the scoped_ptr allocated by the
- // daemon.
+ // Counter mocks. They are strict mocks so that all unexpected
+ // update calls are marked as failures. They are pointers so that
+ // they can replace the scoped_ptr's allocated by the daemon.
StrictMock<TaggedCounterMock>* daily_use_;
+ StrictMock<TaggedCounterMock>* user_crash_interval_;
};
TEST_F(MetricsDaemonTest, DailyUseReporter) {
@@ -147,6 +168,10 @@
ExpectDailyUseTimeMetric(/* sample */ 1);
MetricsDaemon::DailyUseReporter(&daemon_, /* tag */ 23, /* count */ 89);
+
+ // There should be no metrics generated for the calls below.
+ MetricsDaemon::DailyUseReporter(&daemon_, /* tag */ 50, /* count */ 0);
+ MetricsDaemon::DailyUseReporter(&daemon_, /* tag */ 60, /* count */ -5);
}
TEST_F(MetricsDaemonTest, LookupNetworkState) {
@@ -183,6 +208,18 @@
EXPECT_EQ(DBUS_HANDLER_RESULT_NOT_YET_HANDLED, res);
DeleteDBusMessage(msg);
+ IgnoreActiveUseUpdate();
+ EXPECT_CALL(*user_crash_interval_, Flush())
+ .Times(1)
+ .RetiresOnSaturation();
+ msg = NewDBusSignalString("/",
+ "org.chromium.CrashReporter",
+ "UserCrash",
+ "");
+ res = MetricsDaemon::MessageFilter(/* connection */ NULL, msg, &daemon_);
+ EXPECT_EQ(DBUS_HANDLER_RESULT_HANDLED, res);
+ DeleteDBusMessage(msg);
+
msg = NewDBusSignalString("/",
"org.chromium.flimflam.Manager",
"StateChanged",
@@ -203,9 +240,7 @@
EXPECT_EQ(DBUS_HANDLER_RESULT_HANDLED, res);
DeleteDBusMessage(msg);
- EXPECT_CALL(*daily_use_, Update(_, 0))
- .Times(1)
- .RetiresOnSaturation();
+ IgnoreActiveUseUpdate();
msg = NewDBusSignalString("/",
"org.chromium.PowerManager",
"ScreenIsUnlocked",
@@ -216,9 +251,7 @@
EXPECT_EQ(DBUS_HANDLER_RESULT_HANDLED, res);
DeleteDBusMessage(msg);
- EXPECT_CALL(*daily_use_, Update(_, 0))
- .Times(1)
- .RetiresOnSaturation();
+ IgnoreActiveUseUpdate();
msg = NewDBusSignalString("/org/chromium/SessionManager",
"org.chromium.SessionManagerInterface",
"SessionStateChanged",
@@ -283,13 +316,13 @@
}
TEST_F(MetricsDaemonTest, PowerStateChanged) {
- ExpectDailyUseUpdate(7, 0);
+ ExpectActiveUseUpdate(7, 0);
daemon_.SetUserActiveState(/* active */ true,
TestTime(7 * kSecondsPerDay + 15));
EXPECT_TRUE(daemon_.user_active_);
EXPECT_EQ(TestTime(7 * kSecondsPerDay + 15), daemon_.user_active_last_);
- ExpectDailyUseUpdate(7, 30);
+ ExpectActiveUseUpdate(7, 30);
daemon_.PowerStateChanged("mem", TestTime(7 * kSecondsPerDay + 45));
EXPECT_EQ(MetricsDaemon::kPowerStateMem, daemon_.power_state_);
EXPECT_FALSE(daemon_.user_active_);
@@ -300,13 +333,21 @@
EXPECT_FALSE(daemon_.user_active_);
EXPECT_EQ(TestTime(7 * kSecondsPerDay + 45), daemon_.user_active_last_);
- ExpectDailyUseUpdate(7, 0);
+ ExpectActiveUseUpdate(7, 0);
daemon_.PowerStateChanged("otherstate", TestTime(7 * kSecondsPerDay + 185));
EXPECT_EQ(MetricsDaemon::kUnknownPowerState, daemon_.power_state_);
EXPECT_FALSE(daemon_.user_active_);
EXPECT_EQ(TestTime(7 * kSecondsPerDay + 185), daemon_.user_active_last_);
}
+TEST_F(MetricsDaemonTest, ProcessUserCrash) {
+ IgnoreActiveUseUpdate();
+ EXPECT_CALL(*user_crash_interval_, Flush())
+ .Times(1)
+ .RetiresOnSaturation();
+ daemon_.ProcessUserCrash();
+}
+
TEST_F(MetricsDaemonTest, SendMetric) {
ExpectMetric("Dummy.Metric", 3, 1, 100, 50);
daemon_.SendMetric("Dummy.Metric", /* sample */ 3,
@@ -314,19 +355,19 @@
}
TEST_F(MetricsDaemonTest, SessionStateChanged) {
- ExpectDailyUseUpdate(15, 0);
+ ExpectActiveUseUpdate(15, 0);
daemon_.SessionStateChanged("started", TestTime(15 * kSecondsPerDay + 20));
EXPECT_EQ(MetricsDaemon::kSessionStateStarted, daemon_.session_state_);
EXPECT_TRUE(daemon_.user_active_);
EXPECT_EQ(TestTime(15 * kSecondsPerDay + 20), daemon_.user_active_last_);
- ExpectDailyUseUpdate(15, 130);
+ ExpectActiveUseUpdate(15, 130);
daemon_.SessionStateChanged("stopped", TestTime(15 * kSecondsPerDay + 150));
EXPECT_EQ(MetricsDaemon::kSessionStateStopped, daemon_.session_state_);
EXPECT_FALSE(daemon_.user_active_);
EXPECT_EQ(TestTime(15 * kSecondsPerDay + 150), daemon_.user_active_last_);
- ExpectDailyUseUpdate(15, 0);
+ ExpectActiveUseUpdate(15, 0);
daemon_.SessionStateChanged("otherstate",
TestTime(15 * kSecondsPerDay + 300));
EXPECT_EQ(MetricsDaemon::kUnknownSessionState, daemon_.session_state_);
@@ -335,31 +376,31 @@
}
TEST_F(MetricsDaemonTest, SetUserActiveState) {
- ExpectDailyUseUpdate(5, 0);
+ ExpectActiveUseUpdate(5, 0);
daemon_.SetUserActiveState(/* active */ false,
TestTime(5 * kSecondsPerDay + 10));
EXPECT_FALSE(daemon_.user_active_);
EXPECT_EQ(TestTime(5 * kSecondsPerDay + 10), daemon_.user_active_last_);
- ExpectDailyUseUpdate(6, 0);
+ ExpectActiveUseUpdate(6, 0);
daemon_.SetUserActiveState(/* active */ true,
TestTime(6 * kSecondsPerDay + 20));
EXPECT_TRUE(daemon_.user_active_);
EXPECT_EQ(TestTime(6 * kSecondsPerDay + 20), daemon_.user_active_last_);
- ExpectDailyUseUpdate(6, 100);
+ ExpectActiveUseUpdate(6, 100);
daemon_.SetUserActiveState(/* active */ true,
TestTime(6 * kSecondsPerDay + 120));
EXPECT_TRUE(daemon_.user_active_);
EXPECT_EQ(TestTime(6 * kSecondsPerDay + 120), daemon_.user_active_last_);
- ExpectDailyUseUpdate(6, 110);
+ ExpectActiveUseUpdate(6, 110);
daemon_.SetUserActiveState(/* active */ false,
TestTime(6 * kSecondsPerDay + 230));
EXPECT_FALSE(daemon_.user_active_);
EXPECT_EQ(TestTime(6 * kSecondsPerDay + 230), daemon_.user_active_last_);
- ExpectDailyUseUpdate(6, 0);
+ ExpectActiveUseUpdate(6, 0);
daemon_.SetUserActiveState(/* active */ false,
TestTime(6 * kSecondsPerDay + 260));
EXPECT_FALSE(daemon_.user_active_);
@@ -367,25 +408,33 @@
}
TEST_F(MetricsDaemonTest, SetUserActiveStateTimeJump) {
- ExpectDailyUseUpdate(10, 0);
+ ExpectActiveUseUpdate(10, 0);
daemon_.SetUserActiveState(/* active */ true,
TestTime(10 * kSecondsPerDay + 500));
EXPECT_TRUE(daemon_.user_active_);
EXPECT_EQ(TestTime(10 * kSecondsPerDay + 500), daemon_.user_active_last_);
- ExpectDailyUseUpdate(10, 0);
+ ExpectActiveUseUpdate(10, 0);
daemon_.SetUserActiveState(/* active */ true,
TestTime(10 * kSecondsPerDay + 300));
EXPECT_TRUE(daemon_.user_active_);
EXPECT_EQ(TestTime(10 * kSecondsPerDay + 300), daemon_.user_active_last_);
- ExpectDailyUseUpdate(10, 0);
+ ExpectActiveUseUpdate(10, 0);
daemon_.SetUserActiveState(/* active */ true,
TestTime(10 * kSecondsPerDay + 1000));
EXPECT_TRUE(daemon_.user_active_);
EXPECT_EQ(TestTime(10 * kSecondsPerDay + 1000), daemon_.user_active_last_);
}
+TEST_F(MetricsDaemonTest, UserCrashIntervalReporter) {
+ ExpectMetric(MetricsDaemon::kMetricUserCrashIntervalName, 50,
+ MetricsDaemon::kMetricUserCrashIntervalMin,
+ MetricsDaemon::kMetricUserCrashIntervalMax,
+ MetricsDaemon::kMetricUserCrashIntervalBuckets);
+ MetricsDaemon::UserCrashIntervalReporter(&daemon_, 0, 50);
+}
+
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();