Home | History | Annotate | Download | only in uploader
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <memory>
     18 
     19 #include <base/at_exit.h>
     20 #include <base/files/file_util.h>
     21 #include <base/files/scoped_temp_dir.h>
     22 #include <base/logging.h>
     23 #include <base/metrics/sparse_histogram.h>
     24 #include <base/metrics/statistics_recorder.h>
     25 #include <base/sys_info.h>
     26 #include <gtest/gtest.h>
     27 
     28 #include "constants.h"
     29 #include "persistent_integer.h"
     30 #include "uploader/metrics_log.h"
     31 #include "uploader/mock/mock_system_profile_setter.h"
     32 #include "uploader/mock/sender_mock.h"
     33 #include "uploader/proto/chrome_user_metrics_extension.pb.h"
     34 #include "uploader/proto/histogram_event.pb.h"
     35 #include "uploader/proto/system_profile.pb.h"
     36 #include "uploader/system_profile_cache.h"
     37 #include "uploader/upload_service.h"
     38 
     39 class UploadServiceTest : public testing::Test {
     40  protected:
     41   virtual void SetUp() {
     42     CHECK(dir_.CreateUniqueTempDir());
     43     // Make sure the statistics recorder is inactive (contains no metrics) then
     44     // initialize it.
     45     ASSERT_FALSE(base::StatisticsRecorder::IsActive());
     46     base::StatisticsRecorder::Initialize();
     47 
     48     private_dir_ = dir_.path().Append("private");
     49     shared_dir_ = dir_.path().Append("shared");
     50 
     51     EXPECT_TRUE(base::CreateDirectory(private_dir_));
     52     EXPECT_TRUE(base::CreateDirectory(shared_dir_));
     53 
     54     ASSERT_EQ(0, base::WriteFile(shared_dir_.Append(metrics::kConsentFileName),
     55                                  "", 0));
     56 
     57     upload_service_.reset(new UploadService(
     58         "", base::TimeDelta(), base::TimeDelta(), private_dir_, shared_dir_));
     59     counters_ = upload_service_->counters_;
     60 
     61     upload_service_->sender_.reset(new SenderMock);
     62     upload_service_->InitForTest(new MockSystemProfileSetter);
     63     upload_service_->GatherHistograms();
     64     upload_service_->Reset();
     65   }
     66 
     67   void SendSparseHistogram(const std::string& name, int sample) {
     68     base::HistogramBase* histogram = base::SparseHistogram::FactoryGet(
     69         name, base::Histogram::kUmaTargetedHistogramFlag);
     70     histogram->Add(sample);
     71   }
     72 
     73   void SendHistogram(
     74       const std::string& name, int sample, int min, int max, int nbuckets) {
     75     base::HistogramBase* histogram = base::Histogram::FactoryGet(
     76         name, min, max, nbuckets, base::Histogram::kUmaTargetedHistogramFlag);
     77     histogram->Add(sample);
     78   }
     79 
     80   void SetTestingProperty(const std::string& name, const std::string& value) {
     81     base::FilePath filepath =
     82         dir_.path().Append("etc/os-release.d").Append(name);
     83     ASSERT_TRUE(base::CreateDirectory(filepath.DirName()));
     84     ASSERT_EQ(value.size(),
     85               base::WriteFile(filepath, value.data(), value.size()));
     86   }
     87 
     88   const metrics::SystemProfileProto_Stability GetCurrentStability() {
     89     EXPECT_TRUE(upload_service_->current_log_.get());
     90 
     91     return upload_service_->current_log_->uma_proto()
     92         ->system_profile()
     93         .stability();
     94   }
     95 
     96   base::ScopedTempDir dir_;
     97   std::unique_ptr<UploadService> upload_service_;
     98 
     99   std::unique_ptr<base::AtExitManager> exit_manager_;
    100   std::shared_ptr<CrashCounters> counters_;
    101   base::FilePath private_dir_;
    102   base::FilePath shared_dir_;
    103 };
    104 
    105 TEST_F(UploadServiceTest, FailedSendAreRetried) {
    106   SenderMock* sender = new SenderMock();
    107   upload_service_->sender_.reset(sender);
    108 
    109   sender->set_should_succeed(false);
    110 
    111   SendSparseHistogram("hello", 1);
    112   upload_service_->UploadEvent();
    113   EXPECT_EQ(1, sender->send_call_count());
    114   std::string sent_string = sender->last_message();
    115 
    116   upload_service_->UploadEvent();
    117   EXPECT_EQ(2, sender->send_call_count());
    118   EXPECT_EQ(sent_string, sender->last_message());
    119 }
    120 
    121 TEST_F(UploadServiceTest, DiscardLogsAfterTooManyFailedUpload) {
    122   SenderMock* sender = new SenderMock();
    123   upload_service_->sender_.reset(sender);
    124 
    125   sender->set_should_succeed(false);
    126 
    127   SendSparseHistogram("hello", 1);
    128 
    129   for (int i = 0; i < UploadService::kMaxFailedUpload; i++) {
    130     upload_service_->UploadEvent();
    131   }
    132 
    133   EXPECT_TRUE(upload_service_->HasStagedLog());
    134   upload_service_->UploadEvent();
    135   EXPECT_FALSE(upload_service_->HasStagedLog());
    136 
    137   // Log a new sample. The failed upload counter should be reset.
    138   SendSparseHistogram("hello", 1);
    139   for (int i = 0; i < UploadService::kMaxFailedUpload; i++) {
    140     upload_service_->UploadEvent();
    141   }
    142   // The log is not discarded after multiple failed uploads.
    143   EXPECT_TRUE(upload_service_->HasStagedLog());
    144 }
    145 
    146 TEST_F(UploadServiceTest, EmptyLogsAreNotSent) {
    147   SenderMock* sender = new SenderMock();
    148   upload_service_->sender_.reset(sender);
    149   upload_service_->UploadEvent();
    150   EXPECT_FALSE(upload_service_->current_log_);
    151   EXPECT_EQ(0, sender->send_call_count());
    152 }
    153 
    154 TEST_F(UploadServiceTest, LogEmptyByDefault) {
    155   // current_log_ should be initialized later as it needs AtExitManager to exist
    156   // in order to gather system information from SysInfo.
    157   EXPECT_FALSE(upload_service_->current_log_);
    158 }
    159 
    160 TEST_F(UploadServiceTest, CanSendMultipleTimes) {
    161   SenderMock* sender = new SenderMock();
    162   upload_service_->sender_.reset(sender);
    163 
    164   SendSparseHistogram("hello", 1);
    165 
    166   upload_service_->UploadEvent();
    167 
    168   std::string first_message = sender->last_message();
    169   SendSparseHistogram("hello", 2);
    170 
    171   upload_service_->UploadEvent();
    172 
    173   EXPECT_NE(first_message, sender->last_message());
    174 }
    175 
    176 TEST_F(UploadServiceTest, LogEmptyAfterUpload) {
    177   SendSparseHistogram("hello", 2);
    178 
    179   upload_service_->UploadEvent();
    180   EXPECT_FALSE(upload_service_->current_log_);
    181 }
    182 
    183 TEST_F(UploadServiceTest, LogContainsAggregatedValues) {
    184   SendHistogram("foo", 11, 0, 42, 10);
    185   SendHistogram("foo", 12, 0, 42, 10);
    186 
    187   upload_service_->GatherHistograms();
    188   metrics::ChromeUserMetricsExtension* proto =
    189       upload_service_->current_log_->uma_proto();
    190   EXPECT_EQ(1, proto->histogram_event().size());
    191 }
    192 
    193 TEST_F(UploadServiceTest, LogContainsCrashCounts) {
    194   // By default, there is no current log.
    195   upload_service_->GatherHistograms();
    196   EXPECT_FALSE(upload_service_->current_log_);
    197 
    198   // If the user crash counter is incremented, we add the count to the current
    199   // log.
    200   counters_->IncrementUserCrashCount();
    201   upload_service_->GatherHistograms();
    202   EXPECT_EQ(1, GetCurrentStability().other_user_crash_count());
    203 
    204   // If the kernel crash counter is incremented, we add the count to the current
    205   // log.
    206   counters_->IncrementKernelCrashCount();
    207   upload_service_->GatherHistograms();
    208   EXPECT_EQ(1, GetCurrentStability().kernel_crash_count());
    209 
    210   // If the kernel crash counter is incremented, we add the count to the current
    211   // log.
    212   counters_->IncrementUncleanShutdownCount();
    213   counters_->IncrementUncleanShutdownCount();
    214   upload_service_->GatherHistograms();
    215   EXPECT_EQ(2, GetCurrentStability().unclean_system_shutdown_count());
    216 
    217   // If no counter is incremented, the reported numbers don't change.
    218   upload_service_->GatherHistograms();
    219   EXPECT_EQ(1, GetCurrentStability().other_user_crash_count());
    220   EXPECT_EQ(1, GetCurrentStability().kernel_crash_count());
    221   EXPECT_EQ(2, GetCurrentStability().unclean_system_shutdown_count());
    222 }
    223 
    224 TEST_F(UploadServiceTest, ExtractChannelFromString) {
    225   EXPECT_EQ(SystemProfileCache::ProtoChannelFromString("developer-build"),
    226             metrics::SystemProfileProto::CHANNEL_UNKNOWN);
    227 
    228   EXPECT_EQ(metrics::SystemProfileProto::CHANNEL_DEV,
    229             SystemProfileCache::ProtoChannelFromString("dev-channel"));
    230 
    231   EXPECT_EQ(metrics::SystemProfileProto::CHANNEL_STABLE,
    232             SystemProfileCache::ProtoChannelFromString("stable-channel"));
    233 
    234   EXPECT_EQ(metrics::SystemProfileProto::CHANNEL_UNKNOWN,
    235             SystemProfileCache::ProtoChannelFromString("this is a test"));
    236 }
    237 
    238 TEST_F(UploadServiceTest, ValuesInConfigFileAreSent) {
    239   SenderMock* sender = new SenderMock();
    240   upload_service_->sender_.reset(sender);
    241 
    242   SetTestingProperty(metrics::kProductId, "hello");
    243   SetTestingProperty(metrics::kProductVersion, "1.2.3.4");
    244 
    245   SendSparseHistogram("hello", 1);
    246 
    247   // Reset to create the new log with the profile setter.
    248   upload_service_->system_profile_setter_.reset(
    249       new SystemProfileCache(true, dir_.path()));
    250   upload_service_->Reset();
    251   upload_service_->UploadEvent();
    252 
    253   EXPECT_EQ(1, sender->send_call_count());
    254   EXPECT_TRUE(sender->is_good_proto());
    255   EXPECT_EQ(1, sender->last_message_proto().histogram_event().size());
    256 
    257   EXPECT_NE(0, sender->last_message_proto().client_id());
    258   EXPECT_NE(0, sender->last_message_proto().system_profile().build_timestamp());
    259   EXPECT_NE(0, sender->last_message_proto().session_id());
    260 }
    261 
    262 TEST_F(UploadServiceTest, PersistentGUID) {
    263   std::string tmp_file = dir_.path().Append("tmpfile").value();
    264 
    265   std::string first_guid = SystemProfileCache::GetPersistentGUID(tmp_file);
    266   std::string second_guid = SystemProfileCache::GetPersistentGUID(tmp_file);
    267 
    268   // The GUID are cached.
    269   EXPECT_EQ(first_guid, second_guid);
    270 
    271   base::DeleteFile(base::FilePath(tmp_file), false);
    272 
    273   first_guid = SystemProfileCache::GetPersistentGUID(tmp_file);
    274   base::DeleteFile(base::FilePath(tmp_file), false);
    275   second_guid = SystemProfileCache::GetPersistentGUID(tmp_file);
    276 
    277   // Random GUIDs are generated (not all the same).
    278   EXPECT_NE(first_guid, second_guid);
    279 }
    280 
    281 TEST_F(UploadServiceTest, SessionIdIncrementedAtInitialization) {
    282   SetTestingProperty(metrics::kProductId, "hello");
    283   SystemProfileCache cache(true, dir_.path());
    284   cache.Initialize();
    285   int session_id = cache.profile_.session_id;
    286   cache.initialized_ = false;
    287   cache.Initialize();
    288   EXPECT_EQ(cache.profile_.session_id, session_id + 1);
    289 }
    290 
    291 // The product id must be set for metrics to be uploaded.
    292 // If it is not set, the system profile cache should fail to initialize.
    293 TEST_F(UploadServiceTest, ProductIdMandatory) {
    294   SystemProfileCache cache(true, dir_.path());
    295   ASSERT_FALSE(cache.Initialize());
    296   SetTestingProperty(metrics::kProductId, "");
    297   ASSERT_FALSE(cache.Initialize());
    298   SetTestingProperty(metrics::kProductId, "hello");
    299   ASSERT_TRUE(cache.Initialize());
    300 }
    301 
    302 TEST_F(UploadServiceTest, CurrentLogSavedAndResumed) {
    303   SendHistogram("hello", 10, 0, 100, 10);
    304   upload_service_->PersistToDisk();
    305   EXPECT_EQ(
    306       1, upload_service_->current_log_->uma_proto()->histogram_event().size());
    307   upload_service_.reset(new UploadService(
    308       "", base::TimeDelta(), base::TimeDelta(), private_dir_, shared_dir_));
    309   upload_service_->InitForTest(nullptr);
    310 
    311   SendHistogram("hello", 10, 0, 100, 10);
    312   upload_service_->GatherHistograms();
    313   EXPECT_EQ(2, upload_service_->GetOrCreateCurrentLog()
    314                    ->uma_proto()
    315                    ->histogram_event()
    316                    .size());
    317 }
    318 
    319 TEST_F(UploadServiceTest, PersistEmptyLog) {
    320   upload_service_->PersistToDisk();
    321   EXPECT_FALSE(base::PathExists(upload_service_->saved_log_path_));
    322 }
    323 
    324 TEST_F(UploadServiceTest, CorruptedSavedLog) {
    325   // Write a bogus saved log.
    326   EXPECT_EQ(5, base::WriteFile(upload_service_->saved_log_path_, "hello", 5));
    327 
    328   upload_service_.reset(new UploadService(
    329       "", base::TimeDelta(), base::TimeDelta(), private_dir_, shared_dir_));
    330 
    331   upload_service_->InitForTest(nullptr);
    332   // If the log is unreadable, we drop it and continue execution.
    333   ASSERT_NE(nullptr, upload_service_->GetOrCreateCurrentLog());
    334   ASSERT_FALSE(base::PathExists(upload_service_->saved_log_path_));
    335 }
    336