1// Copyright (c) 2012 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 <algorithm>
6#include <vector>
7
8#include "base/logging.h"
9#include "base/strings/string16.h"
10#include "base/time/time.h"
11#include "chrome/browser/chromeos/memory/oom_priority_manager.h"
12#include "chrome/common/url_constants.h"
13#include "testing/gtest/include/gtest/gtest.h"
14#include "url/gurl.h"
15
16namespace chromeos {
17
18typedef testing::Test OomPriorityManagerTest;
19
20namespace {
21enum TestIndicies {
22  kSelected,
23  kPinned,
24  kApp,
25  kPlayingAudio,
26  kRecent,
27  kOld,
28  kReallyOld,
29  kOldButPinned,
30  kReloadableUI,
31};
32}  // namespace
33
34// Tests the sorting comparator so that we know it's producing the
35// desired order.
36TEST_F(OomPriorityManagerTest, Comparator) {
37  chromeos::OomPriorityManager::TabStatsList test_list;
38  const base::TimeTicks now = base::TimeTicks::Now();
39
40  // Add kSelected last to verify we are sorting the array.
41
42  {
43    OomPriorityManager::TabStats stats;
44    stats.is_pinned = true;
45    stats.renderer_handle = kPinned;
46    test_list.push_back(stats);
47  }
48
49  {
50    OomPriorityManager::TabStats stats;
51    stats.is_app = true;
52    stats.renderer_handle = kApp;
53    test_list.push_back(stats);
54  }
55
56  {
57    OomPriorityManager::TabStats stats;
58    stats.is_playing_audio = true;
59    stats.renderer_handle = kPlayingAudio;
60    test_list.push_back(stats);
61  }
62
63  {
64    OomPriorityManager::TabStats stats;
65    stats.last_active = now - base::TimeDelta::FromSeconds(10);
66    stats.renderer_handle = kRecent;
67    test_list.push_back(stats);
68  }
69
70  {
71    OomPriorityManager::TabStats stats;
72    stats.last_active = now - base::TimeDelta::FromMinutes(15);
73    stats.renderer_handle = kOld;
74    test_list.push_back(stats);
75  }
76
77  {
78    OomPriorityManager::TabStats stats;
79    stats.last_active = now - base::TimeDelta::FromDays(365);
80    stats.renderer_handle = kReallyOld;
81    test_list.push_back(stats);
82  }
83
84  {
85    OomPriorityManager::TabStats stats;
86    stats.is_pinned = true;
87    stats.last_active = now - base::TimeDelta::FromDays(365);
88    stats.renderer_handle = kOldButPinned;
89    test_list.push_back(stats);
90  }
91
92  {
93    OomPriorityManager::TabStats stats;
94    stats.is_reloadable_ui = true;
95    stats.renderer_handle = kReloadableUI;
96    test_list.push_back(stats);
97  }
98
99  // This entry sorts to the front, so by adding it last we verify that
100  // we are actually sorting the array.
101  {
102    OomPriorityManager::TabStats stats;
103    stats.is_selected = true;
104    stats.renderer_handle = kSelected;
105    test_list.push_back(stats);
106  }
107
108  std::sort(test_list.begin(),
109            test_list.end(),
110            OomPriorityManager::CompareTabStats);
111
112  int index = 0;
113  EXPECT_EQ(kSelected, test_list[index++].renderer_handle);
114  EXPECT_EQ(kPinned, test_list[index++].renderer_handle);
115  EXPECT_EQ(kOldButPinned, test_list[index++].renderer_handle);
116  EXPECT_EQ(kApp, test_list[index++].renderer_handle);
117  EXPECT_EQ(kPlayingAudio, test_list[index++].renderer_handle);
118  EXPECT_EQ(kRecent, test_list[index++].renderer_handle);
119  EXPECT_EQ(kOld, test_list[index++].renderer_handle);
120  EXPECT_EQ(kReallyOld, test_list[index++].renderer_handle);
121  EXPECT_EQ(kReloadableUI, test_list[index++].renderer_handle);
122}
123
124TEST_F(OomPriorityManagerTest, IsReloadableUI) {
125  EXPECT_TRUE(OomPriorityManager::IsReloadableUI(
126      GURL(chrome::kChromeUIDownloadsURL)));
127  EXPECT_TRUE(OomPriorityManager::IsReloadableUI(
128      GURL(chrome::kChromeUIHistoryURL)));
129  EXPECT_TRUE(OomPriorityManager::IsReloadableUI(
130      GURL(chrome::kChromeUINewTabURL)));
131  EXPECT_TRUE(OomPriorityManager::IsReloadableUI(
132      GURL(chrome::kChromeUISettingsURL)));
133
134  // Debugging URLs are not included.
135  EXPECT_FALSE(OomPriorityManager::IsReloadableUI(
136      GURL(chrome::kChromeUIDiscardsURL)));
137  EXPECT_FALSE(OomPriorityManager::IsReloadableUI(
138      GURL(chrome::kChromeUINetInternalsURL)));
139
140  // Prefix matches are included.
141  EXPECT_TRUE(OomPriorityManager::IsReloadableUI(
142      GURL("chrome://settings/fakeSetting")));
143}
144
145TEST_F(OomPriorityManagerTest, GetProcessHandles) {
146  OomPriorityManager::TabStats stats;
147  std::vector<base::ProcessHandle> handles;
148
149  // Empty stats list gives empty handles list.
150  OomPriorityManager::TabStatsList empty_list;
151  handles = OomPriorityManager::GetProcessHandles(empty_list);
152  EXPECT_EQ(0u, handles.size());
153
154  // Two tabs in two different processes generates two handles out.
155  OomPriorityManager::TabStatsList two_list;
156  stats.renderer_handle = 100;
157  two_list.push_back(stats);
158  stats.renderer_handle = 101;
159  two_list.push_back(stats);
160  handles = OomPriorityManager::GetProcessHandles(two_list);
161  EXPECT_EQ(2u, handles.size());
162  EXPECT_EQ(100, handles[0]);
163  EXPECT_EQ(101, handles[1]);
164
165  // Zero handles are removed.
166  OomPriorityManager::TabStatsList zero_handle_list;
167  stats.renderer_handle = 0;
168  zero_handle_list.push_back(stats);
169  handles = OomPriorityManager::GetProcessHandles(zero_handle_list);
170  EXPECT_EQ(0u, handles.size());
171
172  // Two tabs in the same process generates one handle out. When a duplicate
173  // occurs the later instance is dropped.
174  OomPriorityManager::TabStatsList same_process_list;
175  stats.renderer_handle = 100;
176  same_process_list.push_back(stats);
177  stats.renderer_handle = 101;
178  same_process_list.push_back(stats);
179  stats.renderer_handle = 100;  // Duplicate.
180  same_process_list.push_back(stats);
181  handles = OomPriorityManager::GetProcessHandles(same_process_list);
182  EXPECT_EQ(2u, handles.size());
183  EXPECT_EQ(100, handles[0]);
184  EXPECT_EQ(101, handles[1]);
185}
186
187}  // namespace chromeos
188