task_manager_browsertest_util.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// Use of this source code is governed by a BSD-style license that can be
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// found in the LICENSE file.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com#include "chrome/browser/task_manager/task_manager_browsertest_util.h"
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com#include "base/message_loop/message_loop.h"
8ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com#include "base/run_loop.h"
9ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com#include "base/strings/string16.h"
10ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com#include "base/strings/string_util.h"
11ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com#include "base/strings/utf_string_conversions.h"
122047f00e4698f83499ab91911999a65c21a951c9epoger@google.com#include "base/test/test_timeouts.h"
132047f00e4698f83499ab91911999a65c21a951c9epoger@google.com#include "base/timer/timer.h"
14ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com#include "chrome/browser/browser_process.h"
152047f00e4698f83499ab91911999a65c21a951c9epoger@google.com#include "chrome/browser/profiles/profile.h"
16ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com#include "chrome/browser/task_manager/resource_provider.h"
172047f00e4698f83499ab91911999a65c21a951c9epoger@google.com#include "chrome/browser/task_manager/task_manager.h"
18ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com#include "grit/generated_resources.h"
19ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com#include "testing/gtest/include/gtest/gtest.h"
20ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com#include "ui/base/l10n/l10n_util.h"
21ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
22ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.comnamespace task_manager {
23ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.comnamespace browsertest_util {
24ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
25ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.comnamespace {
26d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com
27ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.comclass ResourceChangeObserver : public TaskManagerModelObserver {
28ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com public:
29ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com  ResourceChangeObserver(const TaskManagerModel* model,
30ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com                         int required_count,
31ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com                         const base::string16& title_pattern)
32ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com      : model_(model),
33ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        required_count_(required_count),
34ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        title_pattern_(title_pattern) {}
3580e39a77b16f4396eed230efea1d0b2fc8cbfb00reed@android.com
36ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com  virtual void OnModelChanged() OVERRIDE {
37ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    OnResourceChange();
38ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com  }
394b7577b042966657c776fd95c67f9363af57945freed@android.com
404b7577b042966657c776fd95c67f9363af57945freed@android.com  virtual void OnItemsChanged(int start, int length) OVERRIDE {
414b7577b042966657c776fd95c67f9363af57945freed@android.com    OnResourceChange();
424b7577b042966657c776fd95c67f9363af57945freed@android.com  }
434b7577b042966657c776fd95c67f9363af57945freed@android.com
444b7577b042966657c776fd95c67f9363af57945freed@android.com  virtual void OnItemsAdded(int start, int length) OVERRIDE {
454b7577b042966657c776fd95c67f9363af57945freed@android.com    OnResourceChange();
464b7577b042966657c776fd95c67f9363af57945freed@android.com  }
474b7577b042966657c776fd95c67f9363af57945freed@android.com
484b7577b042966657c776fd95c67f9363af57945freed@android.com  virtual void OnItemsRemoved(int start, int length) OVERRIDE {
494b7577b042966657c776fd95c67f9363af57945freed@android.com    OnResourceChange();
504b7577b042966657c776fd95c67f9363af57945freed@android.com  }
514b7577b042966657c776fd95c67f9363af57945freed@android.com
524b7577b042966657c776fd95c67f9363af57945freed@android.com  void RunUntilSatisfied() {
534b7577b042966657c776fd95c67f9363af57945freed@android.com    // See if the condition is satisfied without having to run the loop. This
544b7577b042966657c776fd95c67f9363af57945freed@android.com    // check has to be placed after the installation of the
554b7577b042966657c776fd95c67f9363af57945freed@android.com    // TaskManagerModelObserver, because resources may change before that.
564b7577b042966657c776fd95c67f9363af57945freed@android.com    if (IsSatisfied())
574b7577b042966657c776fd95c67f9363af57945freed@android.com      return;
58ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
59ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    timer_.Start(FROM_HERE,
60ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com                 TestTimeouts::action_timeout(),
61ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com                 this,
62ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com                 &ResourceChangeObserver::OnTimeout);
63ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
64ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    run_loop_.Run();
65ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
66ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    // If we succeeded normally (no timeout), check our post condition again
67ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    // before returning control to the test. If it is no longer satisfied, the
68ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    // test is likely flaky: we were waiting for a state that was only achieved
69ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    // emphemerally), so treat this as a failure.
70ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    if (!IsSatisfied() && timer_.IsRunning()) {
714b7577b042966657c776fd95c67f9363af57945freed@android.com      FAIL() << "Wait condition satisfied only emphemerally. Likely test "
72ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com             << "problem. Maybe wait instead for the state below?\n"
73ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com             << DumpTaskManagerModel();
74ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    }
75ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
76ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    timer_.Stop();
774b7577b042966657c776fd95c67f9363af57945freed@android.com  }
78ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
79ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com private:
80ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com  void OnResourceChange() {
81ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    if (!IsSatisfied())
82ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com      return;
83ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
84ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    base::MessageLoop::current()->PostTask(FROM_HERE, run_loop_.QuitClosure());
85ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com  }
86ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
874b7577b042966657c776fd95c67f9363af57945freed@android.com  bool IsSatisfied() { return CountMatches() == required_count_; }
884b7577b042966657c776fd95c67f9363af57945freed@android.com
8980e39a77b16f4396eed230efea1d0b2fc8cbfb00reed@android.com  int CountMatches() {
90ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    int match_count = 0;
91ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    for (int i = 0; i < model_->ResourceCount(); i++) {
92ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com      task_manager::Resource::Type type = model_->GetResourceType(i);
93ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com      // Skip system infrastructure resources.
94ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com      if (type == task_manager::Resource::BROWSER ||
95ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com          type == task_manager::Resource::NACL ||
96ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com          type == task_manager::Resource::GPU ||
97ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com          type == task_manager::Resource::UTILITY ||
98ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com          type == task_manager::Resource::ZYGOTE ||
99ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com          type == task_manager::Resource::SANDBOX_HELPER) {
100ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        continue;
101ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com      }
102ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
103ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com      if (MatchPattern(model_->GetResourceTitle(i), title_pattern_)) {
104ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        match_count++;
105ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com      }
106ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    }
107ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    return match_count;
108ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com  }
109ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
110ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com  void OnTimeout() {
111ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    base::MessageLoop::current()->PostTask(FROM_HERE, run_loop_.QuitClosure());
112ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    FAIL() << "Timed out.\n" << DumpTaskManagerModel();
113ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com  }
11480e39a77b16f4396eed230efea1d0b2fc8cbfb00reed@android.com
115ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com  testing::Message DumpTaskManagerModel() {
116ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    testing::Message task_manager_state_dump;
11780e39a77b16f4396eed230efea1d0b2fc8cbfb00reed@android.com    task_manager_state_dump << "Waiting for exactly " << required_count_
118ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com                            << " matches of wildcard pattern \""
119ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com                            << base::UTF16ToASCII(title_pattern_) << "\"\n";
120ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    task_manager_state_dump << "Currently there are " << CountMatches()
121ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com                            << " matches.\n";
122ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    task_manager_state_dump << "Current Task Manager Model is:\n";
123ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    for (int i = 0; i < model_->ResourceCount(); i++) {
124ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com      task_manager_state_dump
125ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com          << "  > " << base::UTF16ToASCII(model_->GetResourceTitle(i)) << "\n";
126ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    }
1271ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    return task_manager_state_dump;
128ba7983e55ce15ddcd5534011935178760164fb9dbungeman@google.com  }
1291ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com
1301ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com  const TaskManagerModel* model_;
1311ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com  const int required_count_;
1321ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com  const base::string16 title_pattern_;
1331ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com  base::RunLoop run_loop_;
1341ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com  base::OneShotTimer<ResourceChangeObserver> timer_;
1351ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com};
1361ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com
1371ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com}  // namespace
1381ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com
1391ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.comvoid WaitForTaskManagerRows(int required_count,
1401ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com                            const base::string16& title_pattern) {
1411ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com  TaskManagerModel* model = TaskManager::GetInstance()->model();
1421ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com
1431ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com  ResourceChangeObserver observer(model, required_count, title_pattern);
1441ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com  model->AddObserver(&observer);
1451ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com  observer.RunUntilSatisfied();
1461ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com  model->RemoveObserver(&observer);
1471ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com}
1481ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com
149ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.combase::string16 MatchTab(const char* title) {
150ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com  return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_TAB_PREFIX,
151d8730ea8b25d692c0656f8cf03f02aecfab2a17creed@android.com                                    base::ASCIIToUTF16(title));
152d8730ea8b25d692c0656f8cf03f02aecfab2a17creed@android.com}
153
154base::string16 MatchAnyTab() { return MatchTab("*"); }
155
156base::string16 MatchAboutBlankTab() { return MatchTab("about:blank"); }
157
158base::string16 MatchExtension(const char* title) {
159  return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_EXTENSION_PREFIX,
160                                    base::ASCIIToUTF16(title));
161}
162
163base::string16 MatchAnyExtension() { return MatchExtension("*"); }
164
165base::string16 MatchApp(const char* title) {
166  return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_APP_PREFIX,
167                                    base::ASCIIToUTF16(title));
168}
169
170base::string16 MatchAnyApp() { return MatchApp("*"); }
171
172base::string16 MatchWebView(const char* title) {
173  return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_WEBVIEW_TAG_PREFIX,
174                                    base::ASCIIToUTF16(title));
175}
176
177base::string16 MatchAnyWebView() { return MatchWebView("*"); }
178
179base::string16 MatchBackground(const char* title) {
180  return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_BACKGROUND_PREFIX,
181                                    base::ASCIIToUTF16(title));
182}
183base::string16 MatchAnyBackground() { return MatchBackground("*"); }
184
185}  // namespace browsertest_util
186}  // namespace task_manager
187