File: near_oom_monitor_unittest.cc

package info (click to toggle)
chromium 73.0.3683.75-1~deb9u1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 1,792,156 kB
  • sloc: cpp: 13,473,466; ansic: 1,577,080; python: 898,539; javascript: 655,737; xml: 341,883; asm: 306,070; java: 289,969; perl: 80,911; objc: 67,198; sh: 43,184; cs: 27,853; makefile: 12,092; php: 11,064; yacc: 10,373; tcl: 8,875; ruby: 3,941; lex: 1,800; pascal: 1,473; lisp: 812; awk: 41; jsp: 39; sed: 19; sql: 3
file content (133 lines) | stat: -rw-r--r-- 4,135 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/android/oom_intervention/near_oom_monitor.h"

#include "base/message_loop/message_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/test/test_mock_time_task_runner.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {
const int64_t kTestSwapTotalKB = 128 * 1024;
const int64_t kTestSwapFreeThreshold = kTestSwapTotalKB / 4;
}  // namespace

class MockNearOomMonitor : public NearOomMonitor {
 public:
  explicit MockNearOomMonitor(
      scoped_refptr<base::SequencedTaskRunner> task_runner)
      : NearOomMonitor(task_runner, kTestSwapFreeThreshold) {
    // Start with 128MB swap total and 64MB swap free.
    memory_info_.swap_total = kTestSwapTotalKB;
    memory_info_.swap_free = kTestSwapTotalKB / 2;
  }

  void SetSwapFree(int swap_free) { memory_info_.swap_free = swap_free; }

  void SimulateNonNearOom() {
    memory_info_.swap_free = memory_info_.swap_total;
  }

  void SimulateNearOom() { memory_info_.swap_free = 0; }

  bool is_get_system_memory_info_called() const {
    return is_get_system_memory_info_called_;
  }

 private:
  bool GetSystemMemoryInfo(base::SystemMemoryInfoKB* memory_info) override {
    *memory_info = memory_info_;
    is_get_system_memory_info_called_ = true;
    return true;
  }

  bool ComponentCallbackIsEnabled() override { return false; }

  base::SystemMemoryInfoKB memory_info_;
  bool is_get_system_memory_info_called_ = false;

  DISALLOW_COPY_AND_ASSIGN(MockNearOomMonitor);
};

class TestNearOomObserver {
 public:
  explicit TestNearOomObserver(NearOomMonitor* monitor) {
    DCHECK(monitor);
    subscription_ = monitor->RegisterCallback(base::Bind(
        &TestNearOomObserver::OnNearOomDetected, base::Unretained(this)));
  }

  void Unsubscribe() { subscription_.reset(); }

  bool is_detected() const { return is_detected_; }

 private:
  void OnNearOomDetected() { is_detected_ = true; }

  bool is_detected_ = false;
  std::unique_ptr<NearOomMonitor::Subscription> subscription_;

  DISALLOW_COPY_AND_ASSIGN(TestNearOomObserver);
};

class NearOomMonitorTest : public testing::Test {
 public:
  void SetUp() override {
    task_runner_ = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
    monitor_ = std::make_unique<MockNearOomMonitor>(task_runner_);
  }

 protected:
  scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
  base::MessageLoop message_loop_;
  std::unique_ptr<MockNearOomMonitor> monitor_;
};

TEST_F(NearOomMonitorTest, Observe) {
  base::TimeDelta interval =
      monitor_->GetMonitoringInterval() + base::TimeDelta::FromSeconds(1);

  TestNearOomObserver observer1(monitor_.get());
  TestNearOomObserver observer2(monitor_.get());

  monitor_->SimulateNonNearOom();
  task_runner_->FastForwardBy(interval);
  EXPECT_TRUE(monitor_->is_get_system_memory_info_called());
  EXPECT_FALSE(observer1.is_detected());
  EXPECT_FALSE(observer2.is_detected());

  observer2.Unsubscribe();

  monitor_->SimulateNearOom();
  task_runner_->FastForwardBy(interval);
  EXPECT_TRUE(observer1.is_detected());
  EXPECT_FALSE(observer2.is_detected());

  observer1.Unsubscribe();
}

TEST_F(NearOomMonitorTest, Cooldown) {
  base::TimeDelta interval =
      monitor_->GetMonitoringInterval() + base::TimeDelta::FromSeconds(1);
  base::TimeDelta cooldown_interval =
      monitor_->GetCooldownInterval() + base::TimeDelta::FromSeconds(1);

  monitor_->SimulateNearOom();

  // The first detection should happen when |interval| is passed.
  TestNearOomObserver observer1(monitor_.get());
  task_runner_->FastForwardBy(interval);
  EXPECT_TRUE(observer1.is_detected());
  observer1.Unsubscribe();

  // After a detection, the next detection shouldn't happen until
  // |cooldown_interval| is passed.
  TestNearOomObserver observer2(monitor_.get());
  task_runner_->FastForwardBy(interval);
  EXPECT_FALSE(observer2.is_detected());
  task_runner_->FastForwardBy(cooldown_interval);
  EXPECT_TRUE(observer2.is_detected());
  observer2.Unsubscribe();
}