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