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/message_loop/message_loop.h"
8 #include "base/run_loop.h"
9 #include "base/strings/string16.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/test/test_timeouts.h"
13 #include "base/timer/timer.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/task_manager/resource_provider.h"
17 #include "chrome/browser/task_manager/task_manager.h"
18 #include "chrome/grit/generated_resources.h"
19 #include "extensions/strings/grit/extensions_strings.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "ui/base/l10n/l10n_util.h"
23 namespace task_manager
{
24 namespace browsertest_util
{
28 class ResourceChangeObserver
: public TaskManagerModelObserver
{
30 ResourceChangeObserver(const TaskManagerModel
* model
,
32 const base::string16
& title_pattern
)
34 required_count_(required_count
),
35 title_pattern_(title_pattern
) {}
37 void OnModelChanged() override
{ OnResourceChange(); }
39 void OnItemsChanged(int start
, int length
) override
{ OnResourceChange(); }
41 void OnItemsAdded(int start
, int length
) override
{ OnResourceChange(); }
43 void OnItemsRemoved(int start
, int length
) override
{ OnResourceChange(); }
45 void RunUntilSatisfied() {
46 // See if the condition is satisfied without having to run the loop. This
47 // check has to be placed after the installation of the
48 // TaskManagerModelObserver, because resources may change before that.
52 timer_
.Start(FROM_HERE
,
53 TestTimeouts::action_timeout(),
55 &ResourceChangeObserver::OnTimeout
);
59 // If we succeeded normally (no timeout), check our post condition again
60 // before returning control to the test. If it is no longer satisfied, the
61 // test is likely flaky: we were waiting for a state that was only achieved
62 // emphemerally), so treat this as a failure.
63 if (!IsSatisfied() && timer_
.IsRunning()) {
64 FAIL() << "Wait condition satisfied only emphemerally. Likely test "
65 << "problem. Maybe wait instead for the state below?\n"
66 << DumpTaskManagerModel();
73 void OnResourceChange() {
77 base::MessageLoop::current()->PostTask(FROM_HERE
, run_loop_
.QuitClosure());
80 bool IsSatisfied() { return CountMatches() == required_count_
; }
84 for (int i
= 0; i
< model_
->ResourceCount(); i
++) {
85 task_manager::Resource::Type type
= model_
->GetResourceType(i
);
86 // Skip system infrastructure resources.
87 if (type
== task_manager::Resource::BROWSER
||
88 type
== task_manager::Resource::NACL
||
89 type
== task_manager::Resource::GPU
||
90 type
== task_manager::Resource::UTILITY
||
91 type
== task_manager::Resource::ZYGOTE
||
92 type
== task_manager::Resource::SANDBOX_HELPER
) {
96 if (MatchPattern(model_
->GetResourceTitle(i
), title_pattern_
)) {
104 base::MessageLoop::current()->PostTask(FROM_HERE
, run_loop_
.QuitClosure());
105 FAIL() << "Timed out.\n" << DumpTaskManagerModel();
108 testing::Message
DumpTaskManagerModel() {
109 testing::Message task_manager_state_dump
;
110 task_manager_state_dump
<< "Waiting for exactly " << required_count_
111 << " matches of wildcard pattern \""
112 << base::UTF16ToASCII(title_pattern_
) << "\"\n";
113 task_manager_state_dump
<< "Currently there are " << CountMatches()
115 task_manager_state_dump
<< "Current Task Manager Model is:\n";
116 for (int i
= 0; i
< model_
->ResourceCount(); i
++) {
117 task_manager_state_dump
118 << " > " << base::UTF16ToASCII(model_
->GetResourceTitle(i
)) << "\n";
120 return task_manager_state_dump
;
123 const TaskManagerModel
* model_
;
124 const int required_count_
;
125 const base::string16 title_pattern_
;
126 base::RunLoop run_loop_
;
127 base::OneShotTimer
<ResourceChangeObserver
> timer_
;
132 void WaitForTaskManagerRows(int required_count
,
133 const base::string16
& title_pattern
) {
134 TaskManagerModel
* model
= TaskManager::GetInstance()->model();
136 ResourceChangeObserver
observer(model
, required_count
, title_pattern
);
137 model
->AddObserver(&observer
);
138 observer
.RunUntilSatisfied();
139 model
->RemoveObserver(&observer
);
142 base::string16
MatchTab(const char* title
) {
143 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_TAB_PREFIX
,
144 base::ASCIIToUTF16(title
));
147 base::string16
MatchAnyTab() { return MatchTab("*"); }
149 base::string16
MatchAboutBlankTab() { return MatchTab("about:blank"); }
151 base::string16
MatchExtension(const char* title
) {
152 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_EXTENSION_PREFIX
,
153 base::ASCIIToUTF16(title
));
156 base::string16
MatchAnyExtension() { return MatchExtension("*"); }
158 base::string16
MatchApp(const char* title
) {
159 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_APP_PREFIX
,
160 base::ASCIIToUTF16(title
));
163 base::string16
MatchAnyApp() { return MatchApp("*"); }
165 base::string16
MatchWebView(const char* title
) {
166 return l10n_util::GetStringFUTF16(
167 IDS_EXTENSION_TASK_MANAGER_WEBVIEW_TAG_PREFIX
,
168 base::ASCIIToUTF16(title
));
171 base::string16
MatchAnyWebView() { return MatchWebView("*"); }
173 base::string16
MatchBackground(const char* title
) {
174 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_BACKGROUND_PREFIX
,
175 base::ASCIIToUTF16(title
));
178 base::string16
MatchAnyBackground() { return MatchBackground("*"); }
180 base::string16
MatchPrint(const char* title
) {
181 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PRINT_PREFIX
,
182 base::ASCIIToUTF16(title
));
185 base::string16
MatchAnyPrint() { return MatchPrint("*"); }
187 base::string16
MatchSubframe(const char* title
) {
188 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_SUBFRAME_PREFIX
,
189 base::ASCIIToUTF16(title
));
192 base::string16
MatchAnySubframe() {
193 return MatchSubframe("*");
196 } // namespace browsertest_util
197 } // namespace task_manager