Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2893)

Unified Diff: base/win/memory_pressure_monitor_unittest.cc

Issue 1122863005: Create base::win::MemoryPressureMonitor class. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed grt@'s comments on patchset 3. Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/win/memory_pressure_monitor_unittest.cc
diff --git a/base/win/memory_pressure_monitor_unittest.cc b/base/win/memory_pressure_monitor_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..8d7e3ca03a6a750f67d300018008220a104153ab
--- /dev/null
+++ b/base/win/memory_pressure_monitor_unittest.cc
@@ -0,0 +1,231 @@
+// Copyright 2015 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 "base/win/memory_pressure_monitor.h"
+
+#include "base/basictypes.h"
+#include "base/memory/memory_pressure_listener.h"
+#include "base/message_loop/message_loop.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace win {
+
+namespace {
+
+struct PressureSettings {
+ int phys;
+ int virt;
+ MemoryPressureListener::MemoryPressureLevel level;
+};
+
+} // namespace
+
+// This is outside of the anonymous namespace so that it can be seen as a friend
+// to the monitor class.
+class TestMemoryPressureMonitor : public MemoryPressureMonitor {
+ public:
+ using MemoryPressureMonitor::CalculateCurrentPressureLevel;
+ using MemoryPressureMonitor::CheckMemoryPressure;
+
+ static const DWORDLONG k4GB = 4ull * 1024 * 1024 * 1024;
+
+ TestMemoryPressureMonitor() {
+ // Disable any timers which are going on and set a special memory reporting
+ // function.
+ StopObserving();
+ }
+
+ virtual ~TestMemoryPressureMonitor() {}
+
+ MOCK_METHOD1(OnMemoryPressure,
+ void(MemoryPressureListener::MemoryPressureLevel level));
+
+ // Sets up the memory status to reflect the provided loads.
+ void SetMemoryLoad(int phys_load_pct, int virt_load_pct) {
+ mem_status_.dwMemoryLoad = static_cast<DWORD>(phys_load_pct);
+ mem_status_.ullTotalPhys = k4GB;
+ mem_status_.ullAvailPhys = (k4GB * (100 - phys_load_pct)) / 100;
+ mem_status_.ullTotalPageFile = k4GB;
+ mem_status_.ullAvailPageFile = k4GB;
+ mem_status_.ullTotalVirtual = k4GB;
+ mem_status_.ullAvailVirtual = (k4GB * (100 - virt_load_pct)) / 100;
+ }
+
+ // Sets up the memory status to reflect the provided absolute memory left.
+ // This uses quite small total memory quantities so that the absolute memory
+ // limits have a chance to kick in.
+ void SetMemoryFree(int phys_left_mb) {
+ static DWORDLONG kMBBytes = 1024 * 1024;
+
+ // Figure out an amount of memory that makes sense for the desired
+ // quantities of memory to be left.
+ DWORDLONG total_mb = 64; // Minimum of 64MB.
+ while (total_mb < phys_left_mb)
+ total_mb *= 2;
+ DWORDLONG total_bytes = total_mb * kMBBytes;
+
+ mem_status_.ullTotalPhys = total_bytes;
+ mem_status_.ullAvailPhys =
+ static_cast<DWORDLONG>(phys_left_mb) * kMBBytes;
+ mem_status_.ullTotalPageFile = total_bytes;
+ mem_status_.ullAvailPageFile = total_bytes;
+ mem_status_.ullTotalVirtual = k4GB;
+ mem_status_.ullAvailVirtual = k4GB;
+ mem_status_.dwMemoryLoad = static_cast<DWORD>(
+ 100 * (mem_status_.ullTotalPhys - mem_status_.ullAvailPhys) /
+ mem_status_.ullTotalPhys);
+ }
+
+ private:
+ bool GetSystemMemoryStatus(MEMORYSTATUSEX* mem_status) override {
+ // Simply copy the memory status set by the test fixture.
+ *mem_status = mem_status_;
+ return true;
+ }
+
+ MEMORYSTATUSEX mem_status_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestMemoryPressureMonitor);
+};
+
+// Tests the fundamental direct calculation of memory pressure.
+TEST(WinMemoryPressureMonitorTest, CalculateCurrentMemoryPressureLevel) {
+ base::MessageLoopForUI message_loop;
+ TestMemoryPressureMonitor monitor;
+
+ // A bunch of memory load settings and the expected memory pressure.
+ const PressureSettings kLoadSettings[] = {
+ { 10, 10, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE },
+ { 40, 40, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE },
+ { 65, 10, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE },
+ { 65, 65, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE },
+ { 98, 10, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
+ { 98, 65, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
+ { 98, 98, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
+#if !defined(ARCH_CPU_64_BITS)
+ // This simulates low virtual memory, which is only applicable on
+ // 32-bit systems.
+ { 10, 65, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE },
+ { 10, 98, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
+ { 65, 98, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
+#endif // !defined(ARCH_CPU_64_BITS)
+ };
+
+ for (const PressureSettings& setting : kLoadSettings) {
+ monitor.SetMemoryLoad(setting.phys, setting.virt);
+ EXPECT_EQ(setting.level, monitor.CalculateCurrentPressureLevel());
+ }
+
+ // A bunch of free memory settings and the expected memory pressure. The
+ // 'virt' parameter is ignored, thus zeroed.
+ const PressureSettings kFreeSettings[] = {
+ { 500, 0, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE },
+ { 250, 0, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE },
+ { 250, 0, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE },
+ { 50, 0, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
+ { 50, 0, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
+ { 50, 0, MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL },
+ };
+
+ for (const PressureSettings& setting : kFreeSettings) {
+ monitor.SetMemoryFree(setting.phys);
+ EXPECT_EQ(setting.level, monitor.CalculateCurrentPressureLevel());
+ }
+}
+
+// This test tests the various transition states from memory pressure, looking
+// for the correct behavior on event reposting as well as state updates.
+TEST(WinMemoryPressureMonitorTest, CheckMemoryPressure) {
+ base::MessageLoopForUI message_loop;
+ testing::StrictMock<TestMemoryPressureMonitor> monitor;
grt (UTC plus 2) 2015/05/06 16:31:09 to force Google Mock to evaluate all expectation f
chrisha 2015/05/06 16:59:04 Ooh, didn't know about VerifyAndClearExpectations,
+ MemoryPressureListener listener(
+ base::Bind(&TestMemoryPressureMonitor::OnMemoryPressure,
+ base::Unretained(&monitor)));
+
+ // Checking the memory pressure at 0% load should not produce any
+ // events.
+ monitor.SetMemoryLoad(0, 0);
+ monitor.CheckMemoryPressure();
+ message_loop.RunUntilIdle();
+ EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
+ monitor.GetCurrentPressureLevel());
+
+ // Setting the memory level to 80% should produce a moderate pressure level.
+ EXPECT_CALL(monitor,
+ OnMemoryPressure(MemoryPressureListener::
+ MEMORY_PRESSURE_LEVEL_MODERATE));
+ monitor.SetMemoryLoad(80, 80);
+ monitor.CheckMemoryPressure();
+ message_loop.RunUntilIdle();
+ EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
+ monitor.GetCurrentPressureLevel());
+
+ // Check that the event gets reposted after a while.
+ for (int i = 0; i < monitor.kModeratePressureCooldownCycles; ++i) {
+ if (i + 1 == monitor.kModeratePressureCooldownCycles) {
+ EXPECT_CALL(monitor,
+ OnMemoryPressure(MemoryPressureListener::
+ MEMORY_PRESSURE_LEVEL_MODERATE));
+ }
+ monitor.CheckMemoryPressure();
+ message_loop.RunUntilIdle();
+ EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
+ monitor.GetCurrentPressureLevel());
+ }
+
+ // Setting the memory usage to 99% should produce critical levels.
+ EXPECT_CALL(monitor,
+ OnMemoryPressure(MemoryPressureListener::
+ MEMORY_PRESSURE_LEVEL_CRITICAL));
+ monitor.SetMemoryLoad(99, 99);
+ monitor.CheckMemoryPressure();
+ message_loop.RunUntilIdle();
+ EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
+ monitor.GetCurrentPressureLevel());
+
+ // Calling it again should immediately produce a second call.
+ EXPECT_CALL(monitor,
+ OnMemoryPressure(MemoryPressureListener::
+ MEMORY_PRESSURE_LEVEL_CRITICAL));
+ monitor.CheckMemoryPressure();
+ message_loop.RunUntilIdle();
+ EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
+ monitor.GetCurrentPressureLevel());
+
+ // When lowering the pressure again there should be a notification and the
+ // pressure should go back to moderate.
+ EXPECT_CALL(monitor,
+ OnMemoryPressure(MemoryPressureListener::
+ MEMORY_PRESSURE_LEVEL_MODERATE));
+ monitor.SetMemoryLoad(80, 80);
+ monitor.CheckMemoryPressure();
+ message_loop.RunUntilIdle();
+ EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
+ monitor.GetCurrentPressureLevel());
+
+ // Check that the event gets reposted after a while.
+ for (int i = 0; i < monitor.kModeratePressureCooldownCycles; ++i) {
+ if (i + 1 == monitor.kModeratePressureCooldownCycles) {
+ EXPECT_CALL(monitor,
+ OnMemoryPressure(MemoryPressureListener::
+ MEMORY_PRESSURE_LEVEL_MODERATE));
+ }
+ monitor.CheckMemoryPressure();
+ message_loop.RunUntilIdle();
+ EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
+ monitor.GetCurrentPressureLevel());
+ }
+
+ // Going down to no pressure should not produce an notification.
+ monitor.SetMemoryLoad(0, 0);
+ monitor.CheckMemoryPressure();
+ message_loop.RunUntilIdle();
+ EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
+ monitor.GetCurrentPressureLevel());
+}
+
+} // namespace win
+} // namespace base

Powered by Google App Engine
This is Rietveld 408576698