1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/metrics/metrics_service.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/bind.h"
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/message_loop/message_loop.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/prefs/testing_pref_service.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/threading/platform_thread.h"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/metrics/client_info.h"
15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/metrics/compression_utils.h"
1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "components/metrics/metrics_log.h"
17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/metrics/metrics_pref_names.h"
1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "components/metrics/metrics_state_manager.h"
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/metrics/test_metrics_service_client.h"
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/variations/metrics_util.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace metrics {
24b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace {
26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid StoreNoClientInfoBackup(const ClientInfo& /* client_info */) {
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_ptr<ClientInfo> ReturnNoBackup() {
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return scoped_ptr<ClientInfo>();
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass TestMetricsProvider : public metrics::MetricsProvider {
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public:
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  explicit TestMetricsProvider(bool has_stability_metrics) :
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      has_stability_metrics_(has_stability_metrics),
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      provide_stability_metrics_called_(false) {
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual bool HasStabilityMetrics() OVERRIDE { return has_stability_metrics_; }
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void ProvideStabilityMetrics(
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      SystemProfileProto* system_profile_proto) OVERRIDE {
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    provide_stability_metrics_called_ = true;
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool provide_stability_metrics_called() const {
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return provide_stability_metrics_called_;
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private:
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool has_stability_metrics_;
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool provide_stability_metrics_called_;
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DISALLOW_COPY_AND_ASSIGN(TestMetricsProvider);
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class TestMetricsService : public MetricsService {
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TestMetricsService(MetricsStateManager* state_manager,
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     MetricsServiceClient* client,
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     PrefService* local_state)
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      : MetricsService(state_manager, client, local_state) {}
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~TestMetricsService() {}
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  using MetricsService::log_manager;
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestMetricsService);
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class TestMetricsLog : public MetricsLog {
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TestMetricsLog(const std::string& client_id,
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 int session_id,
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 MetricsServiceClient* client,
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 PrefService* local_state)
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      : MetricsLog(client_id,
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   session_id,
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   MetricsLog::ONGOING_LOG,
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   client,
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   local_state) {}
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~TestMetricsLog() {}
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestMetricsLog);
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
90b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class MetricsServiceTest : public testing::Test {
91b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) public:
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MetricsServiceTest() : is_metrics_reporting_enabled_(false) {
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MetricsService::RegisterPrefs(testing_local_state_.registry());
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    metrics_state_manager_ = MetricsStateManager::Create(
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        GetLocalState(),
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        base::Bind(&MetricsServiceTest::is_metrics_reporting_enabled,
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   base::Unretained(this)),
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base::Bind(&StoreNoClientInfoBackup),
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base::Bind(&ReturnNoBackup));
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~MetricsServiceTest() {
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MetricsService::SetExecutionPhase(MetricsService::UNINITIALIZED_PHASE,
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      GetLocalState());
105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
106b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MetricsStateManager* GetMetricsStateManager() {
108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return metrics_state_manager_.get();
109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PrefService* GetLocalState() { return &testing_local_state_; }
112b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
113010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Sets metrics reporting as enabled for testing.
114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void EnableMetricsReporting() {
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    is_metrics_reporting_enabled_ = true;
116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Waits until base::TimeTicks::Now() no longer equals |value|. This should
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // take between 1-15ms per the documented resolution of base::TimeTicks.
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void WaitUntilTimeChanges(const base::TimeTicks& value) {
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    while (base::TimeTicks::Now() == value) {
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Returns true if there is a synthetic trial in the given vector that matches
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // the given trial name and trial group; returns false otherwise.
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool HasSyntheticTrial(
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      const std::vector<variations::ActiveGroupId>& synthetic_trials,
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      const std::string& trial_name,
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      const std::string& trial_group) {
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    uint32 trial_name_hash = HashName(trial_name);
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    uint32 trial_group_hash = HashName(trial_group);
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (std::vector<variations::ActiveGroupId>::const_iterator it =
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)             synthetic_trials.begin();
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         it != synthetic_trials.end(); ++it) {
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if ((*it).name == trial_name_hash && (*it).group == trial_group_hash)
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return true;
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
143b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) private:
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool is_metrics_reporting_enabled() const {
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return is_metrics_reporting_enabled_;
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool is_metrics_reporting_enabled_;
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TestingPrefServiceSimple testing_local_state_;
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<MetricsStateManager> metrics_state_manager_;
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::MessageLoop message_loop;
152b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
153b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MetricsServiceTest);
154b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)};
155b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(MetricsServiceTest, InitialStabilityLogAfterCleanShutDown) {
159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EnableMetricsReporting();
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  GetLocalState()->SetBoolean(prefs::kStabilityExitedCleanly, true);
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TestMetricsServiceClient client;
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TestMetricsService service(
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      GetMetricsStateManager(), &client, GetLocalState());
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TestMetricsProvider* test_provider = new TestMetricsProvider(false);
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  service.RegisterMetricsProvider(
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      scoped_ptr<metrics::MetricsProvider>(test_provider));
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  service.InitializeMetricsRecordingState();
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // No initial stability log should be generated.
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(service.log_manager()->has_unsent_logs());
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(service.log_manager()->has_staged_log());
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The test provider should not have been called upon to provide stability
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // metrics.
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(test_provider->provide_stability_metrics_called());
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_F(MetricsServiceTest, InitialStabilityLogAtProviderRequest) {
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EnableMetricsReporting();
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Save an existing system profile to prefs, to correspond to what would be
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // saved from a previous session.
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TestMetricsServiceClient client;
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TestMetricsLog log("client", 1, &client, GetLocalState());
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  log.RecordEnvironment(std::vector<metrics::MetricsProvider*>(),
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        std::vector<variations::ActiveGroupId>(),
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        0);
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Record stability build time and version from previous session, so that
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // stability metrics (including exited cleanly flag) won't be cleared.
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  GetLocalState()->SetInt64(prefs::kStabilityStatsBuildTime,
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            MetricsLog::GetBuildTime());
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  GetLocalState()->SetString(prefs::kStabilityStatsVersion,
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             client.GetVersionString());
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Set the clean exit flag, as that will otherwise cause a stabilty
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // log to be produced, irrespective provider requests.
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  GetLocalState()->SetBoolean(prefs::kStabilityExitedCleanly, true);
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TestMetricsService service(
2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      GetMetricsStateManager(), &client, GetLocalState());
2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Add a metrics provider that requests a stability log.
2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TestMetricsProvider* test_provider = new TestMetricsProvider(true);
2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  service.RegisterMetricsProvider(
2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      scoped_ptr<MetricsProvider>(test_provider));
2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  service.InitializeMetricsRecordingState();
2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The initial stability log should be generated and persisted in unsent logs.
2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MetricsLogManager* log_manager = service.log_manager();
2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(log_manager->has_unsent_logs());
2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(log_manager->has_staged_log());
2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The test provider should have been called upon to provide stability
2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // metrics.
2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(test_provider->provide_stability_metrics_called());
2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Stage the log and retrieve it.
2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  log_manager->StageNextLogForUpload();
2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(log_manager->has_staged_log());
2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string uncompressed_log;
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(GzipUncompress(log_manager->staged_log(),
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                      &uncompressed_log));
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ChromeUserMetricsExtension uma_log;
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(uma_log.ParseFromString(uncompressed_log));
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(uma_log.has_client_id());
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(uma_log.has_session_id());
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(uma_log.has_system_profile());
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(0, uma_log.user_action_event_size());
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(0, uma_log.omnibox_event_size());
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(0, uma_log.histogram_event_size());
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(0, uma_log.profiler_event_size());
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(0, uma_log.perf_data_size());
2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // As there wasn't an unclean shutdown, this log has zero crash count.
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(0, uma_log.system_profile().stability().crash_count());
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(MetricsServiceTest, InitialStabilityLogAfterCrash) {
245010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  EnableMetricsReporting();
2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  GetLocalState()->ClearPref(prefs::kStabilityExitedCleanly);
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Set up prefs to simulate restarting after a crash.
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Save an existing system profile to prefs, to correspond to what would be
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // saved from a previous session.
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TestMetricsServiceClient client;
253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  TestMetricsLog log("client", 1, &client, GetLocalState());
2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  log.RecordEnvironment(std::vector<MetricsProvider*>(),
255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                        std::vector<variations::ActiveGroupId>(),
256116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                        0);
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Record stability build time and version from previous session, so that
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // stability metrics (including exited cleanly flag) won't be cleared.
2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  GetLocalState()->SetInt64(prefs::kStabilityStatsBuildTime,
2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            MetricsLog::GetBuildTime());
2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  GetLocalState()->SetString(prefs::kStabilityStatsVersion,
2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             client.GetVersionString());
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  GetLocalState()->SetBoolean(prefs::kStabilityExitedCleanly, false);
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  TestMetricsService service(
268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      GetMetricsStateManager(), &client, GetLocalState());
269010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  service.InitializeMetricsRecordingState();
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The initial stability log should be generated and persisted in unsent logs.
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MetricsLogManager* log_manager = service.log_manager();
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(log_manager->has_unsent_logs());
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(log_manager->has_staged_log());
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Stage the log and retrieve it.
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  log_manager->StageNextLogForUpload();
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(log_manager->has_staged_log());
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::string uncompressed_log;
281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(metrics::GzipUncompress(log_manager->staged_log(),
282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                      &uncompressed_log));
283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  metrics::ChromeUserMetricsExtension uma_log;
285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(uma_log.ParseFromString(uncompressed_log));
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(uma_log.has_client_id());
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(uma_log.has_session_id());
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(uma_log.has_system_profile());
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, uma_log.user_action_event_size());
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, uma_log.omnibox_event_size());
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, uma_log.histogram_event_size());
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, uma_log.profiler_event_size());
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, uma_log.perf_data_size());
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(1, uma_log.system_profile().stability().crash_count());
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(MetricsServiceTest, RegisterSyntheticTrial) {
300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  metrics::TestMetricsServiceClient client;
301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MetricsService service(GetMetricsStateManager(), &client, GetLocalState());
302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
303f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Add two synthetic trials and confirm that they show up in the list.
304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SyntheticTrialGroup trial1(metrics::HashName("TestTrial1"),
305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             metrics::HashName("Group1"));
306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  service.RegisterSyntheticFieldTrial(trial1);
307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SyntheticTrialGroup trial2(metrics::HashName("TestTrial2"),
309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             metrics::HashName("Group2"));
310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  service.RegisterSyntheticFieldTrial(trial2);
311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Ensure that time has advanced by at least a tick before proceeding.
312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  WaitUntilTimeChanges(base::TimeTicks::Now());
313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
31446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  service.log_manager_.BeginLoggingWithLog(scoped_ptr<MetricsLog>(
315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new MetricsLog("clientID",
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     1,
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     MetricsLog::INITIAL_STABILITY_LOG,
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     &client,
319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     GetLocalState())));
320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Save the time when the log was started (it's okay for this to be greater
321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // than the time recorded by the above call since it's used to ensure the
322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // value changes).
323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const base::TimeTicks begin_log_time = base::TimeTicks::Now();
324f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<variations::ActiveGroupId> synthetic_trials;
326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  service.GetCurrentSyntheticFieldTrials(&synthetic_trials);
327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ(2U, synthetic_trials.size());
328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial1", "Group1"));
329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2"));
330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Ensure that time has advanced by at least a tick before proceeding.
332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  WaitUntilTimeChanges(begin_log_time);
333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
334f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Change the group for the first trial after the log started.
335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SyntheticTrialGroup trial3(metrics::HashName("TestTrial1"),
336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             metrics::HashName("Group2"));
337f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  service.RegisterSyntheticFieldTrial(trial3);
338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  service.GetCurrentSyntheticFieldTrials(&synthetic_trials);
339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ(1U, synthetic_trials.size());
340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2"));
341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Add a new trial after the log started and confirm that it doesn't show up.
343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SyntheticTrialGroup trial4(metrics::HashName("TestTrial3"),
344a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             metrics::HashName("Group3"));
345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  service.RegisterSyntheticFieldTrial(trial4);
346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  service.GetCurrentSyntheticFieldTrials(&synthetic_trials);
347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ(1U, synthetic_trials.size());
348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2"));
349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
350a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Ensure that time has advanced by at least a tick before proceeding.
351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  WaitUntilTimeChanges(base::TimeTicks::Now());
352a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Start a new log and ensure all three trials appear in it.
354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  service.log_manager_.FinishCurrentLog();
355c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  service.log_manager_.BeginLoggingWithLog(
35646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      scoped_ptr<MetricsLog>(new MetricsLog(
357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          "clientID", 1, MetricsLog::ONGOING_LOG, &client, GetLocalState())));
358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  service.GetCurrentSyntheticFieldTrials(&synthetic_trials);
359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ(3U, synthetic_trials.size());
360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial1", "Group2"));
361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial2", "Group2"));
362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial3", "Group3"));
363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  service.log_manager_.FinishCurrentLog();
364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
365effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace metrics
367