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