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.
5 #include "chrome/browser/task_manager/task_manager_browsertest_util.h"
7 #include "base/command_line.h"
8 #include "base/location.h"
9 #include "base/run_loop.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/strings/pattern.h"
12 #include "base/strings/string16.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/test/test_timeouts.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "base/timer/timer.h"
18 #include "chrome/browser/browser_process.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/task_manager/resource_provider.h"
21 #include "chrome/browser/task_manager/task_manager.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "chrome/grit/generated_resources.h"
24 #include "extensions/strings/grit/extensions_strings.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "ui/base/l10n/l10n_util.h"
28 namespace task_manager
{
29 namespace browsertest_util
{
33 class ResourceChangeObserver
: public TaskManagerModelObserver
{
35 ResourceChangeObserver(const TaskManagerModel
* model
,
37 const base::string16
& title_pattern
,
38 ColumnSpecifier column_specifier
,
39 size_t min_column_value
)
41 required_count_(required_count
),
42 title_pattern_(title_pattern
),
43 column_specifier_(column_specifier
),
44 min_column_value_(min_column_value
) {}
46 void OnModelChanged() override
{ OnResourceChange(); }
48 void OnItemsChanged(int start
, int length
) override
{ OnResourceChange(); }
50 void OnItemsAdded(int start
, int length
) override
{ OnResourceChange(); }
52 void OnItemsRemoved(int start
, int length
) override
{ OnResourceChange(); }
54 void RunUntilSatisfied() {
55 // See if the condition is satisfied without having to run the loop. This
56 // check has to be placed after the installation of the
57 // TaskManagerModelObserver, because resources may change before that.
61 timer_
.Start(FROM_HERE
,
62 TestTimeouts::action_timeout(),
64 &ResourceChangeObserver::OnTimeout
);
68 // If we succeeded normally (no timeout), check our post condition again
69 // before returning control to the test. If it is no longer satisfied, the
70 // test is likely flaky: we were waiting for a state that was only achieved
71 // emphemerally), so treat this as a failure.
72 if (!IsSatisfied() && timer_
.IsRunning()) {
73 FAIL() << "Wait condition satisfied only emphemerally. Likely test "
74 << "problem. Maybe wait instead for the state below?\n"
75 << DumpTaskManagerModel();
82 void OnResourceChange() {
86 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
87 run_loop_
.QuitClosure());
90 bool IsSatisfied() { return CountMatches() == required_count_
; }
94 for (int i
= 0; i
< model_
->ResourceCount(); i
++) {
95 if (!base::MatchPattern(model_
->GetResourceTitle(i
), title_pattern_
))
98 if (GetColumnValue(i
) < min_column_value_
)
106 size_t GetColumnValue(int index
) {
108 bool success
= false;
109 switch (column_specifier_
) {
113 success
= model_
->GetV8Memory(index
, &value
);
116 success
= model_
->GetV8MemoryUsed(index
, &value
);
118 case SQLITE_MEMORY_USED
:
119 success
= model_
->GetSqliteMemoryUsedBytes(index
, &value
);
127 const char* GetColumnName() {
128 switch (column_specifier_
) {
134 return "V8 Memory Used";
135 case SQLITE_MEMORY_USED
:
136 return "SQLite Memory Used";
142 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
,
143 run_loop_
.QuitClosure());
144 FAIL() << "Timed out.\n" << DumpTaskManagerModel();
147 testing::Message
DumpTaskManagerModel() {
148 testing::Message task_manager_state_dump
;
149 task_manager_state_dump
<< "Waiting for exactly " << required_count_
150 << " matches of wildcard pattern \""
151 << base::UTF16ToASCII(title_pattern_
) << "\"";
152 if (min_column_value_
> 0) {
153 task_manager_state_dump
<< " && [" << GetColumnName()
154 << " >= " << min_column_value_
<< "]";
156 task_manager_state_dump
<< "\nCurrently there are " << CountMatches()
158 task_manager_state_dump
<< "\nCurrent Task Manager Model is:";
159 for (int i
= 0; i
< model_
->ResourceCount(); i
++) {
160 task_manager_state_dump
161 << "\n > " << std::setw(40) << std::left
162 << base::UTF16ToASCII(model_
->GetResourceTitle(i
));
163 if (min_column_value_
> 0) {
164 task_manager_state_dump
<< " [" << GetColumnName()
165 << " == " << GetColumnValue(i
) << "]";
168 return task_manager_state_dump
;
171 const TaskManagerModel
* model_
;
172 const int required_count_
;
173 const base::string16 title_pattern_
;
174 const ColumnSpecifier column_specifier_
;
175 const size_t min_column_value_
;
176 base::RunLoop run_loop_
;
177 base::OneShotTimer
<ResourceChangeObserver
> timer_
;
182 void EnableOldTaskManager() {
183 base::CommandLine::ForCurrentProcess()->AppendSwitch(
184 switches::kDisableNewTaskManager
);
187 void WaitForTaskManagerRows(int required_count
,
188 const base::string16
& title_pattern
) {
189 TaskManagerModel
* model
= TaskManager::GetInstance()->model();
191 const int column_value_dont_care
= 0;
192 ResourceChangeObserver
observer(model
, required_count
, title_pattern
,
193 COLUMN_NONE
, column_value_dont_care
);
194 model
->AddObserver(&observer
);
195 observer
.RunUntilSatisfied();
196 model
->RemoveObserver(&observer
);
199 void WaitForTaskManagerStatToExceed(const base::string16
& title_pattern
,
200 ColumnSpecifier column_getter
,
201 size_t min_column_value
) {
202 TaskManagerModel
* model
= TaskManager::GetInstance()->model();
204 const int wait_for_one_match
= 1;
205 ResourceChangeObserver
observer(model
, wait_for_one_match
, title_pattern
,
206 column_getter
, min_column_value
);
207 model
->AddObserver(&observer
);
208 observer
.RunUntilSatisfied();
209 model
->RemoveObserver(&observer
);
212 base::string16
MatchTab(const char* title
) {
213 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_TAB_PREFIX
,
214 base::ASCIIToUTF16(title
));
217 base::string16
MatchAnyTab() { return MatchTab("*"); }
219 base::string16
MatchAboutBlankTab() { return MatchTab("about:blank"); }
221 base::string16
MatchExtension(const char* title
) {
222 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_EXTENSION_PREFIX
,
223 base::ASCIIToUTF16(title
));
226 base::string16
MatchAnyExtension() { return MatchExtension("*"); }
228 base::string16
MatchApp(const char* title
) {
229 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_APP_PREFIX
,
230 base::ASCIIToUTF16(title
));
233 base::string16
MatchAnyApp() { return MatchApp("*"); }
235 base::string16
MatchWebView(const char* title
) {
236 return l10n_util::GetStringFUTF16(
237 IDS_EXTENSION_TASK_MANAGER_WEBVIEW_TAG_PREFIX
,
238 base::ASCIIToUTF16(title
));
241 base::string16
MatchAnyWebView() { return MatchWebView("*"); }
243 base::string16
MatchBackground(const char* title
) {
244 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_BACKGROUND_PREFIX
,
245 base::ASCIIToUTF16(title
));
248 base::string16
MatchAnyBackground() { return MatchBackground("*"); }
250 base::string16
MatchPrint(const char* title
) {
251 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PRINT_PREFIX
,
252 base::ASCIIToUTF16(title
));
255 base::string16
MatchAnyPrint() { return MatchPrint("*"); }
257 base::string16
MatchSubframe(const char* title
) {
258 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_SUBFRAME_PREFIX
,
259 base::ASCIIToUTF16(title
));
262 base::string16
MatchAnySubframe() {
263 return MatchSubframe("*");
266 base::string16
MatchUtility(const base::string16
& title
) {
267 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_UTILITY_PREFIX
, title
);
270 base::string16
MatchAnyUtility() {
271 return MatchUtility(base::ASCIIToUTF16("*"));
274 } // namespace browsertest_util
275 } // namespace task_manager