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