1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "components/metrics/file_metrics_provider.h"
6 
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/files/file_util.h"
10 #include "base/files/memory_mapped_file.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/metrics/histogram.h"
13 #include "base/metrics/histogram_flattener.h"
14 #include "base/metrics/histogram_snapshot_manager.h"
15 #include "base/metrics/persistent_histogram_allocator.h"
16 #include "base/metrics/persistent_memory_allocator.h"
17 #include "base/metrics/sparse_histogram.h"
18 #include "base/metrics/statistics_recorder.h"
19 #include "base/stl_util.h"
20 #include "base/strings/stringprintf.h"
21 #include "base/synchronization/waitable_event.h"
22 #include "base/test/test_simple_task_runner.h"
23 #include "base/threading/thread_task_runner_handle.h"
24 #include "base/time/time.h"
25 #include "components/metrics/metrics_pref_names.h"
26 #include "components/metrics/persistent_system_profile.h"
27 #include "components/prefs/pref_registry_simple.h"
28 #include "components/prefs/testing_pref_service.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h"
31 #include "third_party/metrics_proto/system_profile.pb.h"
32 
33 namespace {
34 const char kMetricsName[] = "TestMetrics";
35 const char kMetricsFilename[] = "file.metrics";
36 }  // namespace
37 
38 namespace metrics {
39 
40 class HistogramFlattenerDeltaRecorder : public base::HistogramFlattener {
41  public:
HistogramFlattenerDeltaRecorder()42   HistogramFlattenerDeltaRecorder() {}
43 
RecordDelta(const base::HistogramBase & histogram,const base::HistogramSamples & snapshot)44   void RecordDelta(const base::HistogramBase& histogram,
45                    const base::HistogramSamples& snapshot) override {
46     // Only remember locally created histograms; they have exactly 2 chars.
47     if (strlen(histogram.histogram_name()) == 2)
48       recorded_delta_histogram_names_.push_back(histogram.histogram_name());
49   }
50 
GetRecordedDeltaHistogramNames()51   std::vector<std::string> GetRecordedDeltaHistogramNames() {
52     return recorded_delta_histogram_names_;
53   }
54 
55  private:
56   std::vector<std::string> recorded_delta_histogram_names_;
57 
58   DISALLOW_COPY_AND_ASSIGN(HistogramFlattenerDeltaRecorder);
59 };
60 
61 
62 class FileMetricsProviderTest : public testing::TestWithParam<bool> {
63  protected:
64   const size_t kSmallFileSize = 64 << 10;  // 64 KiB
65   const size_t kLargeFileSize =  2 << 20;  //  2 MiB
66 
67   enum : int { kMaxCreateHistograms = 10 };
68 
FileMetricsProviderTest()69   FileMetricsProviderTest()
70       : create_large_files_(GetParam()),
71         task_runner_(new base::TestSimpleTaskRunner()),
72         thread_task_runner_handle_(task_runner_),
73         statistics_recorder_(
74             base::StatisticsRecorder::CreateTemporaryForTesting()),
75         prefs_(new TestingPrefServiceSimple) {
76     EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
77     FileMetricsProvider::RegisterPrefs(prefs_->registry(), kMetricsName);
78     FileMetricsProvider::SetTaskRunnerForTesting(task_runner_);
79   }
80 
~FileMetricsProviderTest()81   ~FileMetricsProviderTest() override {
82     // Clear out any final remaining tasks.
83     task_runner_->RunUntilIdle();
84     FileMetricsProvider::SetTaskRunnerForTesting(nullptr);
85     DCHECK_EQ(0U, filter_actions_remaining_);
86     // If a global histogram allocator exists at this point then it likely
87     // acquired histograms that will continue to point to the released
88     // memory and potentially cause use-after-free memory corruption.
89     DCHECK(!base::GlobalHistogramAllocator::Get());
90   }
91 
prefs()92   TestingPrefServiceSimple* prefs() { return prefs_.get(); }
temp_dir()93   base::FilePath temp_dir() { return temp_dir_.GetPath(); }
metrics_file()94   base::FilePath metrics_file() {
95     return temp_dir_.GetPath().AppendASCII(kMetricsFilename);
96   }
97 
provider()98   FileMetricsProvider* provider() {
99     if (!provider_)
100       provider_.reset(new FileMetricsProvider(prefs()));
101     return provider_.get();
102   }
103 
OnDidCreateMetricsLog()104   void OnDidCreateMetricsLog() {
105     provider()->OnDidCreateMetricsLog();
106   }
107 
HasPreviousSessionData()108   bool HasPreviousSessionData() { return provider()->HasPreviousSessionData(); }
109 
MergeHistogramDeltas()110   void MergeHistogramDeltas() {
111     provider()->MergeHistogramDeltas();
112   }
113 
HasIndependentMetrics()114   bool HasIndependentMetrics() { return provider()->HasIndependentMetrics(); }
115 
ProvideIndependentMetrics(ChromeUserMetricsExtension * uma_proto,base::HistogramSnapshotManager * snapshot_manager)116   bool ProvideIndependentMetrics(
117       ChromeUserMetricsExtension* uma_proto,
118       base::HistogramSnapshotManager* snapshot_manager) {
119     bool success = false;
120     bool success_set = false;
121     provider()->ProvideIndependentMetrics(
122         base::BindOnce(
123             [](bool* success_ptr, bool* set_ptr, bool s) {
124               *success_ptr = s;
125               *set_ptr = true;
126             },
127             &success, &success_set),
128         uma_proto, snapshot_manager);
129 
130     RunTasks();
131     CHECK(success_set);
132     return success;
133   }
134 
RecordInitialHistogramSnapshots(base::HistogramSnapshotManager * snapshot_manager)135   void RecordInitialHistogramSnapshots(
136       base::HistogramSnapshotManager* snapshot_manager) {
137     provider()->RecordInitialHistogramSnapshots(snapshot_manager);
138   }
139 
GetSnapshotHistogramCount()140   size_t GetSnapshotHistogramCount() {
141     // Merge the data from the allocator into the StatisticsRecorder.
142     provider()->MergeHistogramDeltas();
143 
144     // Flatten what is known to see what has changed since the last time.
145     HistogramFlattenerDeltaRecorder flattener;
146     base::HistogramSnapshotManager snapshot_manager(&flattener);
147     // "true" to the begin() includes histograms held in persistent storage.
148     base::StatisticsRecorder::PrepareDeltas(true, base::Histogram::kNoFlags,
149                                             base::Histogram::kNoFlags,
150                                             &snapshot_manager);
151     return flattener.GetRecordedDeltaHistogramNames().size();
152   }
153 
GetIndependentHistogramCount()154   size_t GetIndependentHistogramCount() {
155     HistogramFlattenerDeltaRecorder flattener;
156     base::HistogramSnapshotManager snapshot_manager(&flattener);
157     ChromeUserMetricsExtension uma_proto;
158     provider()->ProvideIndependentMetrics(base::BindOnce([](bool success) {}),
159                                           &uma_proto, &snapshot_manager);
160 
161     RunTasks();
162     return flattener.GetRecordedDeltaHistogramNames().size();
163   }
164 
CreateGlobalHistograms(int histogram_count)165   void CreateGlobalHistograms(int histogram_count) {
166     DCHECK_GT(kMaxCreateHistograms, histogram_count);
167 
168     // Create both sparse and normal histograms in the allocator.
169     created_histograms_[0] = base::SparseHistogram::FactoryGet("h0", 0);
170     created_histograms_[0]->Add(0);
171     for (int i = 1; i < histogram_count; ++i) {
172       created_histograms_[i] = base::Histogram::FactoryGet(
173           base::StringPrintf("h%d", i), 1, 100, 10, 0);
174       created_histograms_[i]->Add(i);
175     }
176   }
177 
RunTasks()178   void RunTasks() {
179     // Run pending tasks twice: Once for IPC calls, once for replies. Don't
180     // use RunUntilIdle() because that can do more work than desired.
181     task_runner_->RunPendingTasks();
182     task_runner_->RunPendingTasks();
183   }
184 
WriteMetricsFile(const base::FilePath & path,base::PersistentHistogramAllocator * metrics)185   void WriteMetricsFile(const base::FilePath& path,
186                         base::PersistentHistogramAllocator* metrics) {
187     base::File writer(path,
188                       base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
189     // Use DCHECK so the stack-trace will indicate where this was called.
190     DCHECK(writer.IsValid()) << path.value();
191     size_t file_size = create_large_files_ ? metrics->size() : metrics->used();
192     int written = writer.Write(0, (const char*)metrics->data(), file_size);
193     DCHECK_EQ(static_cast<int>(file_size), written);
194   }
195 
WriteMetricsFileAtTime(const base::FilePath & path,base::PersistentHistogramAllocator * metrics,base::Time write_time)196   void WriteMetricsFileAtTime(const base::FilePath& path,
197                               base::PersistentHistogramAllocator* metrics,
198                               base::Time write_time) {
199     WriteMetricsFile(path, metrics);
200     base::TouchFile(path, write_time, write_time);
201   }
202 
203   std::unique_ptr<base::PersistentHistogramAllocator>
CreateMetricsFileWithHistograms(const base::FilePath & file_path,base::Time write_time,int histogram_count,base::OnceCallback<void (base::PersistentHistogramAllocator *)> callback)204   CreateMetricsFileWithHistograms(
205       const base::FilePath& file_path,
206       base::Time write_time,
207       int histogram_count,
208       base::OnceCallback<void(base::PersistentHistogramAllocator*)> callback) {
209     base::GlobalHistogramAllocator::CreateWithLocalMemory(
210         create_large_files_ ? kLargeFileSize : kSmallFileSize,
211         0, kMetricsName);
212 
213     CreateGlobalHistograms(histogram_count);
214 
215     std::unique_ptr<base::PersistentHistogramAllocator> histogram_allocator =
216         base::GlobalHistogramAllocator::ReleaseForTesting();
217     std::move(callback).Run(histogram_allocator.get());
218 
219     WriteMetricsFileAtTime(file_path, histogram_allocator.get(), write_time);
220     return histogram_allocator;
221   }
222 
223   std::unique_ptr<base::PersistentHistogramAllocator>
CreateMetricsFileWithHistograms(int histogram_count)224   CreateMetricsFileWithHistograms(int histogram_count) {
225     return CreateMetricsFileWithHistograms(
226         metrics_file(), base::Time::Now(), histogram_count,
227         base::BindOnce([](base::PersistentHistogramAllocator* allocator) {}));
228   }
229 
GetCreatedHistogram(int index)230   base::HistogramBase* GetCreatedHistogram(int index) {
231     DCHECK_GT(kMaxCreateHistograms, index);
232     return created_histograms_[index];
233   }
234 
SetFilterActions(FileMetricsProvider::Params * params,const FileMetricsProvider::FilterAction * actions,size_t count)235   void SetFilterActions(FileMetricsProvider::Params* params,
236                         const FileMetricsProvider::FilterAction* actions,
237                         size_t count) {
238     filter_actions_ = actions;
239     filter_actions_remaining_ = count;
240     params->filter = base::BindRepeating(
241         &FileMetricsProviderTest::FilterSourcePath, base::Unretained(this));
242   }
243 
244   const bool create_large_files_;
245 
246  private:
FilterSourcePath(const base::FilePath & path)247   FileMetricsProvider::FilterAction FilterSourcePath(
248       const base::FilePath& path) {
249     DCHECK_LT(0U, filter_actions_remaining_);
250     --filter_actions_remaining_;
251     return *filter_actions_++;
252   }
253 
254   scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
255   base::ThreadTaskRunnerHandle thread_task_runner_handle_;
256 
257   std::unique_ptr<base::StatisticsRecorder> statistics_recorder_;
258   base::ScopedTempDir temp_dir_;
259   std::unique_ptr<TestingPrefServiceSimple> prefs_;
260   std::unique_ptr<FileMetricsProvider> provider_;
261   base::HistogramBase* created_histograms_[kMaxCreateHistograms];
262 
263   const FileMetricsProvider::FilterAction* filter_actions_ = nullptr;
264   size_t filter_actions_remaining_ = 0;
265 
266   DISALLOW_COPY_AND_ASSIGN(FileMetricsProviderTest);
267 };
268 
269 // Run all test cases with both small and large files.
270 INSTANTIATE_TEST_SUITE_P(SmallAndLargeFiles,
271                          FileMetricsProviderTest,
272                          testing::Bool());
273 
TEST_P(FileMetricsProviderTest,AccessMetrics)274 TEST_P(FileMetricsProviderTest, AccessMetrics) {
275   ASSERT_FALSE(PathExists(metrics_file()));
276 
277   base::Time metrics_time = base::Time::Now() - base::TimeDelta::FromMinutes(5);
278   std::unique_ptr<base::PersistentHistogramAllocator> histogram_allocator =
279       CreateMetricsFileWithHistograms(2);
280   ASSERT_TRUE(PathExists(metrics_file()));
281   base::TouchFile(metrics_file(), metrics_time, metrics_time);
282 
283   // Register the file and allow the "checker" task to run.
284   provider()->RegisterSource(FileMetricsProvider::Params(
285       metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
286       FileMetricsProvider::ASSOCIATE_CURRENT_RUN, kMetricsName));
287 
288   // Record embedded snapshots via snapshot-manager.
289   OnDidCreateMetricsLog();
290   RunTasks();
291   EXPECT_EQ(2U, GetSnapshotHistogramCount());
292   EXPECT_FALSE(base::PathExists(metrics_file()));
293 
294   // Make sure a second call to the snapshot-recorder doesn't break anything.
295   OnDidCreateMetricsLog();
296   RunTasks();
297   EXPECT_EQ(0U, GetSnapshotHistogramCount());
298 
299   // File should have been deleted but recreate it to test behavior should
300   // the file not be deleteable by this process.
301   WriteMetricsFileAtTime(metrics_file(), histogram_allocator.get(),
302                          metrics_time);
303 
304   // Second full run on the same file should produce nothing.
305   OnDidCreateMetricsLog();
306   RunTasks();
307   EXPECT_EQ(0U, GetSnapshotHistogramCount());
308   EXPECT_FALSE(base::PathExists(metrics_file()));
309 
310   // Recreate the file to indicate that it is "new" and must be recorded.
311   metrics_time = metrics_time + base::TimeDelta::FromMinutes(1);
312   WriteMetricsFileAtTime(metrics_file(), histogram_allocator.get(),
313                          metrics_time);
314 
315   // This run should again have "new" histograms.
316   OnDidCreateMetricsLog();
317   RunTasks();
318   EXPECT_EQ(2U, GetSnapshotHistogramCount());
319   EXPECT_FALSE(base::PathExists(metrics_file()));
320 }
321 
TEST_P(FileMetricsProviderTest,AccessTimeLimitedFile)322 TEST_P(FileMetricsProviderTest, AccessTimeLimitedFile) {
323   ASSERT_FALSE(PathExists(metrics_file()));
324 
325   base::Time metrics_time = base::Time::Now() - base::TimeDelta::FromHours(5);
326   std::unique_ptr<base::PersistentHistogramAllocator> histogram_allocator =
327       CreateMetricsFileWithHistograms(2);
328   ASSERT_TRUE(PathExists(metrics_file()));
329   base::TouchFile(metrics_file(), metrics_time, metrics_time);
330 
331   // Register the file and allow the "checker" task to run.
332   FileMetricsProvider::Params params(
333       metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
334       FileMetricsProvider::ASSOCIATE_CURRENT_RUN, kMetricsName);
335   params.max_age = base::TimeDelta::FromHours(1);
336   provider()->RegisterSource(params);
337 
338   // Attempt to access the file should return nothing.
339   OnDidCreateMetricsLog();
340   RunTasks();
341   EXPECT_EQ(0U, GetSnapshotHistogramCount());
342   EXPECT_FALSE(base::PathExists(metrics_file()));
343 }
344 
TEST_P(FileMetricsProviderTest,FilterDelaysFile)345 TEST_P(FileMetricsProviderTest, FilterDelaysFile) {
346   ASSERT_FALSE(PathExists(metrics_file()));
347 
348   base::Time now_time = base::Time::Now();
349   base::Time metrics_time = now_time - base::TimeDelta::FromMinutes(5);
350   std::unique_ptr<base::PersistentHistogramAllocator> histogram_allocator =
351       CreateMetricsFileWithHistograms(2);
352   ASSERT_TRUE(PathExists(metrics_file()));
353   base::TouchFile(metrics_file(), metrics_time, metrics_time);
354   base::File::Info fileinfo;
355   ASSERT_TRUE(base::GetFileInfo(metrics_file(), &fileinfo));
356   EXPECT_GT(base::Time::Now(), fileinfo.last_modified);
357 
358   // Register the file and allow the "checker" task to run.
359   FileMetricsProvider::Params params(
360       metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
361       FileMetricsProvider::ASSOCIATE_CURRENT_RUN, kMetricsName);
362   const FileMetricsProvider::FilterAction actions[] = {
363       FileMetricsProvider::FILTER_TRY_LATER,
364       FileMetricsProvider::FILTER_PROCESS_FILE};
365   SetFilterActions(&params, actions, base::size(actions));
366   provider()->RegisterSource(params);
367 
368   // Processing the file should touch it but yield no results. File timestamp
369   // accuracy is limited so compare the touched time to a couple seconds past.
370   OnDidCreateMetricsLog();
371   RunTasks();
372   EXPECT_EQ(0U, GetSnapshotHistogramCount());
373   EXPECT_TRUE(base::PathExists(metrics_file()));
374   ASSERT_TRUE(base::GetFileInfo(metrics_file(), &fileinfo));
375   EXPECT_LT(metrics_time, fileinfo.last_modified);
376   EXPECT_LE(now_time - base::TimeDelta::FromSeconds(2), fileinfo.last_modified);
377 
378   // Second full run on the same file should process the file.
379   OnDidCreateMetricsLog();
380   RunTasks();
381   EXPECT_EQ(2U, GetSnapshotHistogramCount());
382   EXPECT_FALSE(base::PathExists(metrics_file()));
383 }
384 
TEST_P(FileMetricsProviderTest,FilterSkipsFile)385 TEST_P(FileMetricsProviderTest, FilterSkipsFile) {
386   ASSERT_FALSE(PathExists(metrics_file()));
387 
388   base::Time now_time = base::Time::Now();
389   base::Time metrics_time = now_time - base::TimeDelta::FromMinutes(5);
390   std::unique_ptr<base::PersistentHistogramAllocator> histogram_allocator =
391       CreateMetricsFileWithHistograms(2);
392   ASSERT_TRUE(PathExists(metrics_file()));
393   base::TouchFile(metrics_file(), metrics_time, metrics_time);
394   base::File::Info fileinfo;
395   ASSERT_TRUE(base::GetFileInfo(metrics_file(), &fileinfo));
396   EXPECT_GT(base::Time::Now(), fileinfo.last_modified);
397 
398   // Register the file and allow the "checker" task to run.
399   FileMetricsProvider::Params params(
400       metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
401       FileMetricsProvider::ASSOCIATE_CURRENT_RUN, kMetricsName);
402   const FileMetricsProvider::FilterAction actions[] = {
403       FileMetricsProvider::FILTER_SKIP_FILE};
404   SetFilterActions(&params, actions, base::size(actions));
405   provider()->RegisterSource(params);
406 
407   // Processing the file should delete it.
408   OnDidCreateMetricsLog();
409   RunTasks();
410   EXPECT_EQ(0U, GetSnapshotHistogramCount());
411   EXPECT_FALSE(base::PathExists(metrics_file()));
412 }
413 
TEST_P(FileMetricsProviderTest,AccessDirectory)414 TEST_P(FileMetricsProviderTest, AccessDirectory) {
415   ASSERT_FALSE(PathExists(metrics_file()));
416 
417   base::GlobalHistogramAllocator::CreateWithLocalMemory(
418       64 << 10, 0, kMetricsName);
419   base::GlobalHistogramAllocator* allocator =
420       base::GlobalHistogramAllocator::Get();
421   base::HistogramBase* histogram;
422 
423   // Create files starting with a timestamp a few minutes back.
424   base::Time base_time = base::Time::Now() - base::TimeDelta::FromMinutes(10);
425 
426   // Create some files in an odd order. The files are "touched" back in time to
427   // ensure that each file has a later timestamp on disk than the previous one.
428   base::ScopedTempDir metrics_files;
429   EXPECT_TRUE(metrics_files.CreateUniqueTempDir());
430   WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII(".foo.pma"),
431                          allocator, base_time);
432   WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("_bar.pma"),
433                          allocator, base_time);
434 
435   histogram = base::Histogram::FactoryGet("h1", 1, 100, 10, 0);
436   histogram->Add(1);
437   WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("a1.pma"),
438                          allocator,
439                          base_time + base::TimeDelta::FromMinutes(1));
440 
441   histogram = base::Histogram::FactoryGet("h2", 1, 100, 10, 0);
442   histogram->Add(2);
443   WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("c2.pma"),
444                          allocator,
445                          base_time + base::TimeDelta::FromMinutes(2));
446 
447   histogram = base::Histogram::FactoryGet("h3", 1, 100, 10, 0);
448   histogram->Add(3);
449   WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("b3.pma"),
450                          allocator,
451                          base_time + base::TimeDelta::FromMinutes(3));
452 
453   histogram = base::Histogram::FactoryGet("h4", 1, 100, 10, 0);
454   histogram->Add(3);
455   WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("d4.pma"),
456                          allocator,
457                          base_time + base::TimeDelta::FromMinutes(4));
458 
459   base::TouchFile(metrics_files.GetPath().AppendASCII("b3.pma"),
460                   base_time + base::TimeDelta::FromMinutes(5),
461                   base_time + base::TimeDelta::FromMinutes(5));
462 
463   WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("baz"), allocator,
464                          base_time + base::TimeDelta::FromMinutes(6));
465 
466   // The global allocator has to be detached here so that no metrics created
467   // by code called below get stored in it as that would make for potential
468   // use-after-free operations if that code is called again.
469   base::GlobalHistogramAllocator::ReleaseForTesting();
470 
471   // Register the file and allow the "checker" task to run.
472   provider()->RegisterSource(FileMetricsProvider::Params(
473       metrics_files.GetPath(),
474       FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_DIR,
475       FileMetricsProvider::ASSOCIATE_CURRENT_RUN, kMetricsName));
476 
477   // Files could come out in the order: a1, c2, d4, b3. They are recognizeable
478   // by the number of histograms contained within each.
479   const uint32_t expect_order[] = {1, 2, 4, 3, 0};
480   for (size_t i = 0; i < base::size(expect_order); ++i) {
481     // Record embedded snapshots via snapshot-manager.
482     OnDidCreateMetricsLog();
483     RunTasks();
484     EXPECT_EQ(expect_order[i], GetSnapshotHistogramCount()) << i;
485   }
486 
487   EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("a1.pma")));
488   EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("c2.pma")));
489   EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("b3.pma")));
490   EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("d4.pma")));
491   EXPECT_TRUE(
492       base::PathExists(metrics_files.GetPath().AppendASCII(".foo.pma")));
493   EXPECT_TRUE(
494       base::PathExists(metrics_files.GetPath().AppendASCII("_bar.pma")));
495   EXPECT_TRUE(base::PathExists(metrics_files.GetPath().AppendASCII("baz")));
496 }
497 
TEST_P(FileMetricsProviderTest,AccessDirectoryWithInvalidFiles)498 TEST_P(FileMetricsProviderTest, AccessDirectoryWithInvalidFiles) {
499   ASSERT_FALSE(PathExists(metrics_file()));
500 
501   // Create files starting with a timestamp a few minutes back.
502   base::Time base_time = base::Time::Now() - base::TimeDelta::FromMinutes(10);
503 
504   base::ScopedTempDir metrics_files;
505   EXPECT_TRUE(metrics_files.CreateUniqueTempDir());
506 
507   CreateMetricsFileWithHistograms(
508       metrics_files.GetPath().AppendASCII("h1.pma"),
509       base_time + base::TimeDelta::FromMinutes(1), 1,
510       base::BindOnce([](base::PersistentHistogramAllocator* allocator) {
511         allocator->memory_allocator()->SetMemoryState(
512             base::PersistentMemoryAllocator::MEMORY_DELETED);
513       }));
514 
515   CreateMetricsFileWithHistograms(
516       metrics_files.GetPath().AppendASCII("h2.pma"),
517       base_time + base::TimeDelta::FromMinutes(2), 2,
518       base::BindOnce([](base::PersistentHistogramAllocator* allocator) {
519         SystemProfileProto profile_proto;
520         SystemProfileProto::FieldTrial* trial = profile_proto.add_field_trial();
521         trial->set_name_id(123);
522         trial->set_group_id(456);
523 
524         PersistentSystemProfile persistent_profile;
525         persistent_profile.RegisterPersistentAllocator(
526             allocator->memory_allocator());
527         persistent_profile.SetSystemProfile(profile_proto, true);
528       }));
529 
530   CreateMetricsFileWithHistograms(
531       metrics_files.GetPath().AppendASCII("h3.pma"),
532       base_time + base::TimeDelta::FromMinutes(3), 3,
533       base::BindOnce([](base::PersistentHistogramAllocator* allocator) {
534         allocator->memory_allocator()->SetMemoryState(
535             base::PersistentMemoryAllocator::MEMORY_DELETED);
536       }));
537 
538   {
539     base::File empty(metrics_files.GetPath().AppendASCII("h4.pma"),
540                      base::File::FLAG_CREATE | base::File::FLAG_WRITE);
541   }
542   base::TouchFile(metrics_files.GetPath().AppendASCII("h4.pma"),
543                   base_time + base::TimeDelta::FromMinutes(4),
544                   base_time + base::TimeDelta::FromMinutes(4));
545 
546   // Register the file and allow the "checker" task to run.
547   provider()->RegisterSource(FileMetricsProvider::Params(
548       metrics_files.GetPath(),
549       FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_DIR,
550       FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE, kMetricsName));
551 
552   // No files yet.
553   EXPECT_EQ(0U, GetIndependentHistogramCount());
554   EXPECT_TRUE(base::PathExists(metrics_files.GetPath().AppendASCII("h1.pma")));
555   EXPECT_TRUE(base::PathExists(metrics_files.GetPath().AppendASCII("h2.pma")));
556   EXPECT_TRUE(base::PathExists(metrics_files.GetPath().AppendASCII("h3.pma")));
557   EXPECT_TRUE(base::PathExists(metrics_files.GetPath().AppendASCII("h4.pma")));
558 
559   // H1 should be skipped and H2 available.
560   OnDidCreateMetricsLog();
561   RunTasks();
562   EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("h1.pma")));
563   EXPECT_TRUE(base::PathExists(metrics_files.GetPath().AppendASCII("h2.pma")));
564   EXPECT_TRUE(base::PathExists(metrics_files.GetPath().AppendASCII("h3.pma")));
565   EXPECT_TRUE(base::PathExists(metrics_files.GetPath().AppendASCII("h4.pma")));
566 
567   // H2 should be read and the file deleted.
568   EXPECT_EQ(2U, GetIndependentHistogramCount());
569   RunTasks();
570   EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("h2.pma")));
571 
572   // Nothing else should be found but the last (valid but empty) file will
573   // stick around to be processed later (should it get expanded).
574   EXPECT_EQ(0U, GetIndependentHistogramCount());
575   RunTasks();
576   EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("h3.pma")));
577   EXPECT_TRUE(base::PathExists(metrics_files.GetPath().AppendASCII("h4.pma")));
578 }
579 
TEST_P(FileMetricsProviderTest,AccessTimeLimitedDirectory)580 TEST_P(FileMetricsProviderTest, AccessTimeLimitedDirectory) {
581   ASSERT_FALSE(PathExists(metrics_file()));
582 
583   base::GlobalHistogramAllocator::CreateWithLocalMemory(64 << 10, 0,
584                                                         kMetricsName);
585   base::GlobalHistogramAllocator* allocator =
586       base::GlobalHistogramAllocator::Get();
587   base::HistogramBase* histogram;
588 
589   // Create one old file and one new file.
590   base::ScopedTempDir metrics_files;
591   EXPECT_TRUE(metrics_files.CreateUniqueTempDir());
592   histogram = base::Histogram::FactoryGet("h1", 1, 100, 10, 0);
593   histogram->Add(1);
594   WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("a1.pma"),
595                          allocator,
596                          base::Time::Now() - base::TimeDelta::FromHours(1));
597 
598   histogram = base::Histogram::FactoryGet("h2", 1, 100, 10, 0);
599   histogram->Add(2);
600   WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("b2.pma"),
601                          allocator, base::Time::Now());
602 
603   // The global allocator has to be detached here so that no metrics created
604   // by code called below get stored in it as that would make for potential
605   // use-after-free operations if that code is called again.
606   base::GlobalHistogramAllocator::ReleaseForTesting();
607 
608   // Register the file and allow the "checker" task to run.
609   FileMetricsProvider::Params params(
610       metrics_files.GetPath(),
611       FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_DIR,
612       FileMetricsProvider::ASSOCIATE_CURRENT_RUN, kMetricsName);
613   params.max_age = base::TimeDelta::FromMinutes(30);
614   provider()->RegisterSource(params);
615 
616   // Only b2, with 2 histograms, should be read.
617   OnDidCreateMetricsLog();
618   RunTasks();
619   EXPECT_EQ(2U, GetSnapshotHistogramCount());
620   OnDidCreateMetricsLog();
621   RunTasks();
622   EXPECT_EQ(0U, GetSnapshotHistogramCount());
623 
624   EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("a1.pma")));
625   EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("b2.pma")));
626 }
627 
TEST_P(FileMetricsProviderTest,AccessCountLimitedDirectory)628 TEST_P(FileMetricsProviderTest, AccessCountLimitedDirectory) {
629   ASSERT_FALSE(PathExists(metrics_file()));
630 
631   base::GlobalHistogramAllocator::CreateWithLocalMemory(64 << 10, 0,
632                                                         kMetricsName);
633   base::GlobalHistogramAllocator* allocator =
634       base::GlobalHistogramAllocator::Get();
635   base::HistogramBase* histogram;
636 
637   // Create one old file and one new file.
638   base::ScopedTempDir metrics_files;
639   EXPECT_TRUE(metrics_files.CreateUniqueTempDir());
640   histogram = base::Histogram::FactoryGet("h1", 1, 100, 10, 0);
641   histogram->Add(1);
642   WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("a1.pma"),
643                          allocator,
644                          base::Time::Now() - base::TimeDelta::FromHours(1));
645 
646   histogram = base::Histogram::FactoryGet("h2", 1, 100, 10, 0);
647   histogram->Add(2);
648   WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("b2.pma"),
649                          allocator, base::Time::Now());
650 
651   // The global allocator has to be detached here so that no metrics created
652   // by code called below get stored in it as that would make for potential
653   // use-after-free operations if that code is called again.
654   base::GlobalHistogramAllocator::ReleaseForTesting();
655 
656   // Register the file and allow the "checker" task to run.
657   FileMetricsProvider::Params params(
658       metrics_files.GetPath(),
659       FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_DIR,
660       FileMetricsProvider::ASSOCIATE_CURRENT_RUN, kMetricsName);
661   params.max_dir_files = 1;
662   provider()->RegisterSource(params);
663 
664   // Only b2, with 2 histograms, should be read.
665   OnDidCreateMetricsLog();
666   RunTasks();
667   EXPECT_EQ(2U, GetSnapshotHistogramCount());
668   OnDidCreateMetricsLog();
669   RunTasks();
670   EXPECT_EQ(0U, GetSnapshotHistogramCount());
671 
672   EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("a1.pma")));
673   EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("b2.pma")));
674 }
675 
TEST_P(FileMetricsProviderTest,AccessSizeLimitedDirectory)676 TEST_P(FileMetricsProviderTest, AccessSizeLimitedDirectory) {
677   // This only works with large files that are big enough to count.
678   if (!create_large_files_)
679     return;
680 
681   ASSERT_FALSE(PathExists(metrics_file()));
682 
683   size_t file_size_kib = 64;
684   base::GlobalHistogramAllocator::CreateWithLocalMemory(file_size_kib << 10, 0,
685                                                         kMetricsName);
686   base::GlobalHistogramAllocator* allocator =
687       base::GlobalHistogramAllocator::Get();
688   base::HistogramBase* histogram;
689 
690   // Create one old file and one new file.
691   base::ScopedTempDir metrics_files;
692   EXPECT_TRUE(metrics_files.CreateUniqueTempDir());
693   histogram = base::Histogram::FactoryGet("h1", 1, 100, 10, 0);
694   histogram->Add(1);
695   WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("a1.pma"),
696                          allocator,
697                          base::Time::Now() - base::TimeDelta::FromHours(1));
698 
699   histogram = base::Histogram::FactoryGet("h2", 1, 100, 10, 0);
700   histogram->Add(2);
701   WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("b2.pma"),
702                          allocator, base::Time::Now());
703 
704   // The global allocator has to be detached here so that no metrics created
705   // by code called below get stored in it as that would make for potential
706   // use-after-free operations if that code is called again.
707   base::GlobalHistogramAllocator::ReleaseForTesting();
708 
709   // Register the file and allow the "checker" task to run.
710   FileMetricsProvider::Params params(
711       metrics_files.GetPath(),
712       FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_DIR,
713       FileMetricsProvider::ASSOCIATE_CURRENT_RUN, kMetricsName);
714   params.max_dir_kib = file_size_kib + 1;
715   provider()->RegisterSource(params);
716 
717   // Only b2, with 2 histograms, should be read.
718   OnDidCreateMetricsLog();
719   RunTasks();
720   EXPECT_EQ(2U, GetSnapshotHistogramCount());
721   OnDidCreateMetricsLog();
722   RunTasks();
723   EXPECT_EQ(0U, GetSnapshotHistogramCount());
724 
725   EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("a1.pma")));
726   EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("b2.pma")));
727 }
728 
TEST_P(FileMetricsProviderTest,AccessFilteredDirectory)729 TEST_P(FileMetricsProviderTest, AccessFilteredDirectory) {
730   ASSERT_FALSE(PathExists(metrics_file()));
731 
732   base::GlobalHistogramAllocator::CreateWithLocalMemory(64 << 10, 0,
733                                                         kMetricsName);
734   base::GlobalHistogramAllocator* allocator =
735       base::GlobalHistogramAllocator::Get();
736   base::HistogramBase* histogram;
737 
738   // Create files starting with a timestamp a few minutes back.
739   base::Time base_time = base::Time::Now() - base::TimeDelta::FromMinutes(10);
740 
741   // Create some files in an odd order. The files are "touched" back in time to
742   // ensure that each file has a later timestamp on disk than the previous one.
743   base::ScopedTempDir metrics_files;
744   EXPECT_TRUE(metrics_files.CreateUniqueTempDir());
745 
746   histogram = base::Histogram::FactoryGet("h1", 1, 100, 10, 0);
747   histogram->Add(1);
748   WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("a1.pma"),
749                          allocator,
750                          base_time + base::TimeDelta::FromMinutes(1));
751 
752   histogram = base::Histogram::FactoryGet("h2", 1, 100, 10, 0);
753   histogram->Add(2);
754   WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("c2.pma"),
755                          allocator,
756                          base_time + base::TimeDelta::FromMinutes(2));
757 
758   histogram = base::Histogram::FactoryGet("h3", 1, 100, 10, 0);
759   histogram->Add(3);
760   WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("b3.pma"),
761                          allocator,
762                          base_time + base::TimeDelta::FromMinutes(3));
763 
764   histogram = base::Histogram::FactoryGet("h4", 1, 100, 10, 0);
765   histogram->Add(3);
766   WriteMetricsFileAtTime(metrics_files.GetPath().AppendASCII("d4.pma"),
767                          allocator,
768                          base_time + base::TimeDelta::FromMinutes(4));
769 
770   base::TouchFile(metrics_files.GetPath().AppendASCII("b3.pma"),
771                   base_time + base::TimeDelta::FromMinutes(5),
772                   base_time + base::TimeDelta::FromMinutes(5));
773 
774   // The global allocator has to be detached here so that no metrics created
775   // by code called below get stored in it as that would make for potential
776   // use-after-free operations if that code is called again.
777   base::GlobalHistogramAllocator::ReleaseForTesting();
778 
779   // Register the file and allow the "checker" task to run.
780   FileMetricsProvider::Params params(
781       metrics_files.GetPath(),
782       FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_DIR,
783       FileMetricsProvider::ASSOCIATE_CURRENT_RUN, kMetricsName);
784   const FileMetricsProvider::FilterAction actions[] = {
785       FileMetricsProvider::FILTER_PROCESS_FILE,   // a1
786       FileMetricsProvider::FILTER_TRY_LATER,      // c2
787       FileMetricsProvider::FILTER_SKIP_FILE,      // d4
788       FileMetricsProvider::FILTER_PROCESS_FILE,   // b3
789       FileMetricsProvider::FILTER_PROCESS_FILE};  // c2 (again)
790   SetFilterActions(&params, actions, base::size(actions));
791   provider()->RegisterSource(params);
792 
793   // Files could come out in the order: a1, b3, c2. They are recognizeable
794   // by the number of histograms contained within each.
795   const uint32_t expect_order[] = {1, 3, 2, 0};
796   for (size_t i = 0; i < base::size(expect_order); ++i) {
797     // Record embedded snapshots via snapshot-manager.
798     OnDidCreateMetricsLog();
799     RunTasks();
800     EXPECT_EQ(expect_order[i], GetSnapshotHistogramCount()) << i;
801   }
802 
803   EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("a1.pma")));
804   EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("c2.pma")));
805   EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("b3.pma")));
806   EXPECT_FALSE(base::PathExists(metrics_files.GetPath().AppendASCII("d4.pma")));
807 }
808 
TEST_P(FileMetricsProviderTest,AccessReadWriteMetrics)809 TEST_P(FileMetricsProviderTest, AccessReadWriteMetrics) {
810   // Create a global histogram allocator that maps to a file.
811   ASSERT_FALSE(PathExists(metrics_file()));
812   base::GlobalHistogramAllocator::CreateWithFile(
813       metrics_file(),
814       create_large_files_ ? kLargeFileSize : kSmallFileSize,
815       0, kMetricsName);
816   CreateGlobalHistograms(2);
817   ASSERT_TRUE(PathExists(metrics_file()));
818   base::HistogramBase* h0 = GetCreatedHistogram(0);
819   base::HistogramBase* h1 = GetCreatedHistogram(1);
820   DCHECK(h0);
821   DCHECK(h1);
822   std::unique_ptr<base::PersistentHistogramAllocator> histogram_allocator =
823       base::GlobalHistogramAllocator::ReleaseForTesting();
824 
825   // Register the file and allow the "checker" task to run.
826   provider()->RegisterSource(FileMetricsProvider::Params(
827       metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ACTIVE_FILE,
828       FileMetricsProvider::ASSOCIATE_CURRENT_RUN));
829 
830   // Record embedded snapshots via snapshot-manager.
831   OnDidCreateMetricsLog();
832   RunTasks();
833   EXPECT_EQ(2U, GetSnapshotHistogramCount());
834   EXPECT_TRUE(base::PathExists(metrics_file()));
835 
836   // Make sure a second call to the snapshot-recorder doesn't break anything.
837   OnDidCreateMetricsLog();
838   RunTasks();
839   EXPECT_EQ(0U, GetSnapshotHistogramCount());
840   EXPECT_TRUE(base::PathExists(metrics_file()));
841 
842   // Change a histogram and ensure that it's counted.
843   h0->Add(0);
844   EXPECT_EQ(1U, GetSnapshotHistogramCount());
845   EXPECT_TRUE(base::PathExists(metrics_file()));
846 
847   // Change the other histogram and verify.
848   h1->Add(11);
849   EXPECT_EQ(1U, GetSnapshotHistogramCount());
850   EXPECT_TRUE(base::PathExists(metrics_file()));
851 }
852 
TEST_P(FileMetricsProviderTest,AccessInitialMetrics)853 TEST_P(FileMetricsProviderTest, AccessInitialMetrics) {
854   ASSERT_FALSE(PathExists(metrics_file()));
855   CreateMetricsFileWithHistograms(2);
856 
857   // Register the file and allow the "checker" task to run.
858   ASSERT_TRUE(PathExists(metrics_file()));
859   provider()->RegisterSource(FileMetricsProvider::Params(
860       metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
861       FileMetricsProvider::ASSOCIATE_PREVIOUS_RUN, kMetricsName));
862 
863   // Record embedded snapshots via snapshot-manager.
864   ASSERT_TRUE(HasPreviousSessionData());
865   RunTasks();
866   {
867     HistogramFlattenerDeltaRecorder flattener;
868     base::HistogramSnapshotManager snapshot_manager(&flattener);
869     RecordInitialHistogramSnapshots(&snapshot_manager);
870     EXPECT_EQ(2U, flattener.GetRecordedDeltaHistogramNames().size());
871   }
872   EXPECT_TRUE(base::PathExists(metrics_file()));
873   OnDidCreateMetricsLog();
874   RunTasks();
875   EXPECT_FALSE(base::PathExists(metrics_file()));
876 
877   // A run for normal histograms should produce nothing.
878   CreateMetricsFileWithHistograms(2);
879   OnDidCreateMetricsLog();
880   RunTasks();
881   EXPECT_EQ(0U, GetSnapshotHistogramCount());
882   EXPECT_TRUE(base::PathExists(metrics_file()));
883   OnDidCreateMetricsLog();
884   RunTasks();
885   EXPECT_TRUE(base::PathExists(metrics_file()));
886 }
887 
TEST_P(FileMetricsProviderTest,AccessEmbeddedProfileMetricsWithoutProfile)888 TEST_P(FileMetricsProviderTest, AccessEmbeddedProfileMetricsWithoutProfile) {
889   ASSERT_FALSE(PathExists(metrics_file()));
890   CreateMetricsFileWithHistograms(2);
891 
892   // Register the file and allow the "checker" task to run.
893   ASSERT_TRUE(PathExists(metrics_file()));
894   provider()->RegisterSource(FileMetricsProvider::Params(
895       metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
896       FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE, kMetricsName));
897 
898   // Record embedded snapshots via snapshot-manager.
899   OnDidCreateMetricsLog();
900   RunTasks();
901   {
902     HistogramFlattenerDeltaRecorder flattener;
903     base::HistogramSnapshotManager snapshot_manager(&flattener);
904     ChromeUserMetricsExtension uma_proto;
905 
906     // A read of metrics with internal profiles should return nothing.
907     EXPECT_FALSE(HasIndependentMetrics());
908     EXPECT_FALSE(ProvideIndependentMetrics(&uma_proto, &snapshot_manager));
909   }
910   EXPECT_TRUE(base::PathExists(metrics_file()));
911   OnDidCreateMetricsLog();
912   RunTasks();
913   EXPECT_FALSE(base::PathExists(metrics_file()));
914 }
915 
TEST_P(FileMetricsProviderTest,AccessEmbeddedProfileMetricsWithProfile)916 TEST_P(FileMetricsProviderTest, AccessEmbeddedProfileMetricsWithProfile) {
917   ASSERT_FALSE(PathExists(metrics_file()));
918   CreateMetricsFileWithHistograms(
919       metrics_file(), base::Time::Now(), 2,
920       base::BindOnce([](base::PersistentHistogramAllocator* allocator) {
921         SystemProfileProto profile_proto;
922         SystemProfileProto::FieldTrial* trial = profile_proto.add_field_trial();
923         trial->set_name_id(123);
924         trial->set_group_id(456);
925 
926         PersistentSystemProfile persistent_profile;
927         persistent_profile.RegisterPersistentAllocator(
928             allocator->memory_allocator());
929         persistent_profile.SetSystemProfile(profile_proto, true);
930       }));
931 
932   // Register the file and allow the "checker" task to run.
933   ASSERT_TRUE(PathExists(metrics_file()));
934   provider()->RegisterSource(FileMetricsProvider::Params(
935       metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
936       FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE, kMetricsName));
937 
938   // Record embedded snapshots via snapshot-manager.
939   OnDidCreateMetricsLog();
940   RunTasks();
941   {
942     HistogramFlattenerDeltaRecorder flattener;
943     base::HistogramSnapshotManager snapshot_manager(&flattener);
944     RecordInitialHistogramSnapshots(&snapshot_manager);
945     EXPECT_EQ(0U, flattener.GetRecordedDeltaHistogramNames().size());
946 
947     // A read of metrics with internal profiles should return one result.
948     ChromeUserMetricsExtension uma_proto;
949     EXPECT_TRUE(HasIndependentMetrics());
950     EXPECT_TRUE(ProvideIndependentMetrics(&uma_proto, &snapshot_manager));
951     EXPECT_FALSE(HasIndependentMetrics());
952     EXPECT_FALSE(ProvideIndependentMetrics(&uma_proto, &snapshot_manager));
953   }
954   RunTasks();
955   EXPECT_FALSE(base::PathExists(metrics_file()));
956 }
957 
TEST_P(FileMetricsProviderTest,AccessEmbeddedFallbackMetricsWithoutProfile)958 TEST_P(FileMetricsProviderTest, AccessEmbeddedFallbackMetricsWithoutProfile) {
959   ASSERT_FALSE(PathExists(metrics_file()));
960   CreateMetricsFileWithHistograms(2);
961 
962   // Register the file and allow the "checker" task to run.
963   ASSERT_TRUE(PathExists(metrics_file()));
964   provider()->RegisterSource(FileMetricsProvider::Params(
965       metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
966       FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE_OR_PREVIOUS_RUN,
967       kMetricsName));
968 
969   // Record embedded snapshots via snapshot-manager.
970   ASSERT_TRUE(HasPreviousSessionData());
971   RunTasks();
972   {
973     HistogramFlattenerDeltaRecorder flattener;
974     base::HistogramSnapshotManager snapshot_manager(&flattener);
975     RecordInitialHistogramSnapshots(&snapshot_manager);
976     EXPECT_EQ(2U, flattener.GetRecordedDeltaHistogramNames().size());
977 
978     // A read of metrics with internal profiles should return nothing.
979     ChromeUserMetricsExtension uma_proto;
980     EXPECT_FALSE(HasIndependentMetrics());
981     EXPECT_FALSE(ProvideIndependentMetrics(&uma_proto, &snapshot_manager));
982   }
983   EXPECT_TRUE(base::PathExists(metrics_file()));
984   OnDidCreateMetricsLog();
985   RunTasks();
986   EXPECT_FALSE(base::PathExists(metrics_file()));
987 }
988 
TEST_P(FileMetricsProviderTest,AccessEmbeddedFallbackMetricsWithProfile)989 TEST_P(FileMetricsProviderTest, AccessEmbeddedFallbackMetricsWithProfile) {
990   ASSERT_FALSE(PathExists(metrics_file()));
991   CreateMetricsFileWithHistograms(
992       metrics_file(), base::Time::Now(), 2,
993       base::BindOnce([](base::PersistentHistogramAllocator* allocator) {
994         SystemProfileProto profile_proto;
995         SystemProfileProto::FieldTrial* trial = profile_proto.add_field_trial();
996         trial->set_name_id(123);
997         trial->set_group_id(456);
998 
999         PersistentSystemProfile persistent_profile;
1000         persistent_profile.RegisterPersistentAllocator(
1001             allocator->memory_allocator());
1002         persistent_profile.SetSystemProfile(profile_proto, true);
1003       }));
1004 
1005   // Register the file and allow the "checker" task to run.
1006   ASSERT_TRUE(PathExists(metrics_file()));
1007   provider()->RegisterSource(FileMetricsProvider::Params(
1008       metrics_file(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_FILE,
1009       FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE_OR_PREVIOUS_RUN,
1010       kMetricsName));
1011 
1012   // Record embedded snapshots via snapshot-manager.
1013   EXPECT_FALSE(HasPreviousSessionData());
1014   RunTasks();
1015   {
1016     HistogramFlattenerDeltaRecorder flattener;
1017     base::HistogramSnapshotManager snapshot_manager(&flattener);
1018     RecordInitialHistogramSnapshots(&snapshot_manager);
1019     EXPECT_EQ(0U, flattener.GetRecordedDeltaHistogramNames().size());
1020 
1021     // A read of metrics with internal profiles should return one result.
1022     ChromeUserMetricsExtension uma_proto;
1023     EXPECT_TRUE(HasIndependentMetrics());
1024     EXPECT_TRUE(ProvideIndependentMetrics(&uma_proto, &snapshot_manager));
1025     EXPECT_FALSE(HasIndependentMetrics());
1026     EXPECT_FALSE(ProvideIndependentMetrics(&uma_proto, &snapshot_manager));
1027   }
1028   RunTasks();
1029   EXPECT_FALSE(base::PathExists(metrics_file()));
1030 }
1031 
TEST_P(FileMetricsProviderTest,AccessEmbeddedProfileMetricsFromDir)1032 TEST_P(FileMetricsProviderTest, AccessEmbeddedProfileMetricsFromDir) {
1033   const int file_count = 3;
1034   base::Time file_base_time = base::Time::Now();
1035   std::vector<base::FilePath> file_names;
1036   for (int i = 0; i < file_count; ++i) {
1037     CreateMetricsFileWithHistograms(
1038         metrics_file(), base::Time::Now(), 2,
1039         base::BindOnce([](base::PersistentHistogramAllocator* allocator) {
1040           SystemProfileProto profile_proto;
1041           SystemProfileProto::FieldTrial* trial =
1042               profile_proto.add_field_trial();
1043           trial->set_name_id(123);
1044           trial->set_group_id(456);
1045 
1046           PersistentSystemProfile persistent_profile;
1047           persistent_profile.RegisterPersistentAllocator(
1048               allocator->memory_allocator());
1049           persistent_profile.SetSystemProfile(profile_proto, true);
1050         }));
1051     ASSERT_TRUE(PathExists(metrics_file()));
1052     char new_name[] = "hX";
1053     new_name[1] = '1' + i;
1054     base::FilePath file_name = temp_dir().AppendASCII(new_name).AddExtension(
1055         base::PersistentMemoryAllocator::kFileExtension);
1056     base::Time file_time =
1057         file_base_time - base::TimeDelta::FromMinutes(file_count - i);
1058     base::TouchFile(metrics_file(), file_time, file_time);
1059     base::Move(metrics_file(), file_name);
1060     file_names.push_back(std::move(file_name));
1061   }
1062 
1063   // Register the file and allow the "checker" task to run.
1064   provider()->RegisterSource(FileMetricsProvider::Params(
1065       temp_dir(), FileMetricsProvider::SOURCE_HISTOGRAMS_ATOMIC_DIR,
1066       FileMetricsProvider::ASSOCIATE_INTERNAL_PROFILE));
1067 
1068   OnDidCreateMetricsLog();
1069   RunTasks();
1070 
1071   // A read of metrics with internal profiles should return one result.
1072   HistogramFlattenerDeltaRecorder flattener;
1073   base::HistogramSnapshotManager snapshot_manager(&flattener);
1074   ChromeUserMetricsExtension uma_proto;
1075   for (int i = 0; i < file_count; ++i) {
1076     EXPECT_TRUE(HasIndependentMetrics()) << i;
1077     EXPECT_TRUE(ProvideIndependentMetrics(&uma_proto, &snapshot_manager)) << i;
1078     RunTasks();
1079   }
1080   EXPECT_FALSE(HasIndependentMetrics());
1081   EXPECT_FALSE(ProvideIndependentMetrics(&uma_proto, &snapshot_manager));
1082 
1083   OnDidCreateMetricsLog();
1084   RunTasks();
1085   for (const auto& file_name : file_names)
1086     EXPECT_FALSE(base::PathExists(file_name));
1087 }
1088 
1089 }  // namespace metrics
1090