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 "chrome/browser/memory/memory_kills_monitor.h"
6 
7 #include "base/metrics/histogram_base.h"
8 #include "base/metrics/histogram_samples.h"
9 #include "base/metrics/statistics_recorder.h"
10 #include "base/stl_util.h"
11 #include "base/time/time.h"
12 #include "chrome/browser/memory/memory_kills_histogram.h"
13 #include "content/public/test/browser_task_environment.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 
16 namespace memory {
17 
18 namespace {
19 
GetLowMemoryKillsCountHistogram()20 base::HistogramBase* GetLowMemoryKillsCountHistogram() {
21   return base::StatisticsRecorder::FindHistogram(
22       "Memory.LowMemoryKiller.Count");
23 }
24 
GetOOMKillsCountHistogram()25 base::HistogramBase* GetOOMKillsCountHistogram() {
26   return base::StatisticsRecorder::FindHistogram("Memory.OOMKills.Count");
27 }
28 
29 }  // namespace.
30 
31 class MemoryKillsMonitorTest : public testing::Test {
32  private:
33   content::BrowserTaskEnvironment task_environment_;
34 };
35 
TEST_F(MemoryKillsMonitorTest,TestHistograms)36 TEST_F(MemoryKillsMonitorTest, TestHistograms) {
37   std::unique_ptr<base::StatisticsRecorder> statistic_recorder(
38       base::StatisticsRecorder::CreateTemporaryForTesting());
39 
40   MemoryKillsMonitor* g_memory_kills_monitor_unittest_instance =
41       MemoryKillsMonitor::GetForTesting();
42 
43   MemoryKillsMonitor::LogLowMemoryKill("APP", 123);
44   MemoryKillsMonitor::LogLowMemoryKill("APP", 100);
45   MemoryKillsMonitor::LogLowMemoryKill("TAB", 10000);
46 
47   auto* lmk_count_histogram = GetLowMemoryKillsCountHistogram();
48   auto* oom_count_histogram = GetOOMKillsCountHistogram();
49   // Before StartMonitoring() is called, nothing is recorded.
50   ASSERT_FALSE(lmk_count_histogram);
51   ASSERT_FALSE(oom_count_histogram);
52 
53   // Start monitoring.
54   g_memory_kills_monitor_unittest_instance->StartMonitoring();
55   lmk_count_histogram = GetLowMemoryKillsCountHistogram();
56   oom_count_histogram = GetOOMKillsCountHistogram();
57   ASSERT_TRUE(lmk_count_histogram);
58   ASSERT_TRUE(oom_count_histogram);
59   {
60     auto count_samples = lmk_count_histogram->SnapshotSamples();
61     EXPECT_EQ(1, count_samples->TotalCount());
62     EXPECT_EQ(1, count_samples->GetCount(0));
63   }
64   {
65     auto count_samples = oom_count_histogram->SnapshotSamples();
66     EXPECT_EQ(1, count_samples->TotalCount());
67     EXPECT_EQ(1, count_samples->GetCount(0));
68   }
69 
70   // Low memory kills.
71   MemoryKillsMonitor::LogLowMemoryKill("APP", 123);
72   MemoryKillsMonitor::LogLowMemoryKill("APP", 100);
73   MemoryKillsMonitor::LogLowMemoryKill("TAB", 10000);
74   lmk_count_histogram = GetLowMemoryKillsCountHistogram();
75   ASSERT_TRUE(lmk_count_histogram);
76   {
77     auto count_samples = lmk_count_histogram->SnapshotSamples();
78     EXPECT_EQ(4, count_samples->TotalCount());
79     // The zero count is implicitly added when StartMonitoring() is called.
80     EXPECT_EQ(1, count_samples->GetCount(0));
81     EXPECT_EQ(1, count_samples->GetCount(1));
82     EXPECT_EQ(1, count_samples->GetCount(2));
83     EXPECT_EQ(1, count_samples->GetCount(3));
84   }
85 
86   {
87     auto* histogram_freed_size = base::StatisticsRecorder::FindHistogram(
88         "Memory.LowMemoryKiller.FreedSize");
89     ASSERT_TRUE(histogram_freed_size);
90     auto freed_size_samples = histogram_freed_size->SnapshotSamples();
91     EXPECT_EQ(3, freed_size_samples->TotalCount());
92     // 123 and 100 are in the same bucket.
93     EXPECT_EQ(2, freed_size_samples->GetCount(123));
94     EXPECT_EQ(2, freed_size_samples->GetCount(100));
95     EXPECT_EQ(1, freed_size_samples->GetCount(10000));
96   }
97 
98   {
99     auto* histogram_time_delta = base::StatisticsRecorder::FindHistogram(
100         "Memory.LowMemoryKiller.TimeDelta");
101     ASSERT_TRUE(histogram_time_delta);
102     auto time_delta_samples = histogram_time_delta->SnapshotSamples();
103     EXPECT_EQ(3, time_delta_samples->TotalCount());
104     // First time delta is set to kMaxMemoryKillTimeDelta.
105     EXPECT_EQ(1, time_delta_samples->GetCount(
106                      kMaxMemoryKillTimeDelta.InMilliseconds()));
107     // Time delta for the other 2 events depends on Now() so we skip testing it
108     // here.
109   }
110 
111   // OOM kills.
112   // Simulate getting 3 more oom kills.
113   g_memory_kills_monitor_unittest_instance->CheckOOMKillImpl(
114       g_memory_kills_monitor_unittest_instance->last_oom_kills_count_ + 3);
115 
116   oom_count_histogram = GetOOMKillsCountHistogram();
117   ASSERT_TRUE(oom_count_histogram);
118   {
119     auto count_samples = oom_count_histogram->SnapshotSamples();
120     EXPECT_EQ(4, count_samples->TotalCount());
121     // The zero count is implicitly added when StartMonitoring() is called.
122     EXPECT_EQ(1, count_samples->GetCount(0));
123     EXPECT_EQ(1, count_samples->GetCount(1));
124     EXPECT_EQ(1, count_samples->GetCount(2));
125     EXPECT_EQ(1, count_samples->GetCount(3));
126   }
127 
128   lmk_count_histogram = GetLowMemoryKillsCountHistogram();
129   ASSERT_TRUE(lmk_count_histogram);
130   {
131     auto count_samples = lmk_count_histogram->SnapshotSamples();
132     // Ensure zero count is not increased.
133     EXPECT_EQ(1, count_samples->GetCount(0));
134   }
135   oom_count_histogram = GetOOMKillsCountHistogram();
136   ASSERT_TRUE(oom_count_histogram);
137   {
138     auto count_samples = oom_count_histogram->SnapshotSamples();
139     // Ensure zero count is not increased.
140     EXPECT_EQ(1, count_samples->GetCount(0));
141   }
142 }
143 
144 }  // namespace memory
145