• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "chrome/browser/task_manager/task_manager_browsertest_util.h"
6 
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 "grit/generated_resources.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "ui/base/l10n/l10n_util.h"
21 
22 namespace task_manager {
23 namespace browsertest_util {
24 
25 namespace {
26 
27 class ResourceChangeObserver : public TaskManagerModelObserver {
28  public:
ResourceChangeObserver(const TaskManagerModel * model,int required_count,const base::string16 & title_pattern)29   ResourceChangeObserver(const TaskManagerModel* model,
30                          int required_count,
31                          const base::string16& title_pattern)
32       : model_(model),
33         required_count_(required_count),
34         title_pattern_(title_pattern) {}
35 
OnModelChanged()36   virtual void OnModelChanged() OVERRIDE {
37     OnResourceChange();
38   }
39 
OnItemsChanged(int start,int length)40   virtual void OnItemsChanged(int start, int length) OVERRIDE {
41     OnResourceChange();
42   }
43 
OnItemsAdded(int start,int length)44   virtual void OnItemsAdded(int start, int length) OVERRIDE {
45     OnResourceChange();
46   }
47 
OnItemsRemoved(int start,int length)48   virtual void OnItemsRemoved(int start, int length) OVERRIDE {
49     OnResourceChange();
50   }
51 
RunUntilSatisfied()52   void RunUntilSatisfied() {
53     // See if the condition is satisfied without having to run the loop. This
54     // check has to be placed after the installation of the
55     // TaskManagerModelObserver, because resources may change before that.
56     if (IsSatisfied())
57       return;
58 
59     timer_.Start(FROM_HERE,
60                  TestTimeouts::action_timeout(),
61                  this,
62                  &ResourceChangeObserver::OnTimeout);
63 
64     run_loop_.Run();
65 
66     // If we succeeded normally (no timeout), check our post condition again
67     // before returning control to the test. If it is no longer satisfied, the
68     // test is likely flaky: we were waiting for a state that was only achieved
69     // emphemerally), so treat this as a failure.
70     if (!IsSatisfied() && timer_.IsRunning()) {
71       FAIL() << "Wait condition satisfied only emphemerally. Likely test "
72              << "problem. Maybe wait instead for the state below?\n"
73              << DumpTaskManagerModel();
74     }
75 
76     timer_.Stop();
77   }
78 
79  private:
OnResourceChange()80   void OnResourceChange() {
81     if (!IsSatisfied())
82       return;
83 
84     base::MessageLoop::current()->PostTask(FROM_HERE, run_loop_.QuitClosure());
85   }
86 
IsSatisfied()87   bool IsSatisfied() { return CountMatches() == required_count_; }
88 
CountMatches()89   int CountMatches() {
90     int match_count = 0;
91     for (int i = 0; i < model_->ResourceCount(); i++) {
92       task_manager::Resource::Type type = model_->GetResourceType(i);
93       // Skip system infrastructure resources.
94       if (type == task_manager::Resource::BROWSER ||
95           type == task_manager::Resource::NACL ||
96           type == task_manager::Resource::GPU ||
97           type == task_manager::Resource::UTILITY ||
98           type == task_manager::Resource::ZYGOTE ||
99           type == task_manager::Resource::SANDBOX_HELPER) {
100         continue;
101       }
102 
103       if (MatchPattern(model_->GetResourceTitle(i), title_pattern_)) {
104         match_count++;
105       }
106     }
107     return match_count;
108   }
109 
OnTimeout()110   void OnTimeout() {
111     base::MessageLoop::current()->PostTask(FROM_HERE, run_loop_.QuitClosure());
112     FAIL() << "Timed out.\n" << DumpTaskManagerModel();
113   }
114 
DumpTaskManagerModel()115   testing::Message DumpTaskManagerModel() {
116     testing::Message task_manager_state_dump;
117     task_manager_state_dump << "Waiting for exactly " << required_count_
118                             << " matches of wildcard pattern \""
119                             << base::UTF16ToASCII(title_pattern_) << "\"\n";
120     task_manager_state_dump << "Currently there are " << CountMatches()
121                             << " matches.\n";
122     task_manager_state_dump << "Current Task Manager Model is:\n";
123     for (int i = 0; i < model_->ResourceCount(); i++) {
124       task_manager_state_dump
125           << "  > " << base::UTF16ToASCII(model_->GetResourceTitle(i)) << "\n";
126     }
127     return task_manager_state_dump;
128   }
129 
130   const TaskManagerModel* model_;
131   const int required_count_;
132   const base::string16 title_pattern_;
133   base::RunLoop run_loop_;
134   base::OneShotTimer<ResourceChangeObserver> timer_;
135 };
136 
137 }  // namespace
138 
WaitForTaskManagerRows(int required_count,const base::string16 & title_pattern)139 void WaitForTaskManagerRows(int required_count,
140                             const base::string16& title_pattern) {
141   TaskManagerModel* model = TaskManager::GetInstance()->model();
142 
143   ResourceChangeObserver observer(model, required_count, title_pattern);
144   model->AddObserver(&observer);
145   observer.RunUntilSatisfied();
146   model->RemoveObserver(&observer);
147 }
148 
MatchTab(const char * title)149 base::string16 MatchTab(const char* title) {
150   return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_TAB_PREFIX,
151                                     base::ASCIIToUTF16(title));
152 }
153 
MatchAnyTab()154 base::string16 MatchAnyTab() { return MatchTab("*"); }
155 
MatchAboutBlankTab()156 base::string16 MatchAboutBlankTab() { return MatchTab("about:blank"); }
157 
MatchExtension(const char * title)158 base::string16 MatchExtension(const char* title) {
159   return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_EXTENSION_PREFIX,
160                                     base::ASCIIToUTF16(title));
161 }
162 
MatchAnyExtension()163 base::string16 MatchAnyExtension() { return MatchExtension("*"); }
164 
MatchApp(const char * title)165 base::string16 MatchApp(const char* title) {
166   return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_APP_PREFIX,
167                                     base::ASCIIToUTF16(title));
168 }
169 
MatchAnyApp()170 base::string16 MatchAnyApp() { return MatchApp("*"); }
171 
MatchWebView(const char * title)172 base::string16 MatchWebView(const char* title) {
173   return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_WEBVIEW_TAG_PREFIX,
174                                     base::ASCIIToUTF16(title));
175 }
176 
MatchAnyWebView()177 base::string16 MatchAnyWebView() { return MatchWebView("*"); }
178 
MatchBackground(const char * title)179 base::string16 MatchBackground(const char* title) {
180   return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_BACKGROUND_PREFIX,
181                                     base::ASCIIToUTF16(title));
182 }
183 
MatchAnyBackground()184 base::string16 MatchAnyBackground() { return MatchBackground("*"); }
185 
MatchPrint(const char * title)186 base::string16 MatchPrint(const char* title) {
187   return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PRINT_PREFIX,
188                                     base::ASCIIToUTF16(title));
189 }
190 
MatchAnyPrint()191 base::string16 MatchAnyPrint() { return MatchPrint("*"); }
192 
193 }  // namespace browsertest_util
194 }  // namespace task_manager
195