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 "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:
     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 
     36   virtual void OnModelChanged() OVERRIDE {
     37     OnResourceChange();
     38   }
     39 
     40   virtual void OnItemsChanged(int start, int length) OVERRIDE {
     41     OnResourceChange();
     42   }
     43 
     44   virtual void OnItemsAdded(int start, int length) OVERRIDE {
     45     OnResourceChange();
     46   }
     47 
     48   virtual void OnItemsRemoved(int start, int length) OVERRIDE {
     49     OnResourceChange();
     50   }
     51 
     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:
     80   void OnResourceChange() {
     81     if (!IsSatisfied())
     82       return;
     83 
     84     base::MessageLoop::current()->PostTask(FROM_HERE, run_loop_.QuitClosure());
     85   }
     86 
     87   bool IsSatisfied() { return CountMatches() == required_count_; }
     88 
     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 
    110   void OnTimeout() {
    111     base::MessageLoop::current()->PostTask(FROM_HERE, run_loop_.QuitClosure());
    112     FAIL() << "Timed out.\n" << DumpTaskManagerModel();
    113   }
    114 
    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 
    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 
    149 base::string16 MatchTab(const char* title) {
    150   return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_TAB_PREFIX,
    151                                     base::ASCIIToUTF16(title));
    152 }
    153 
    154 base::string16 MatchAnyTab() { return MatchTab("*"); }
    155 
    156 base::string16 MatchAboutBlankTab() { return MatchTab("about:blank"); }
    157 
    158 base::string16 MatchExtension(const char* title) {
    159   return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_EXTENSION_PREFIX,
    160                                     base::ASCIIToUTF16(title));
    161 }
    162 
    163 base::string16 MatchAnyExtension() { return MatchExtension("*"); }
    164 
    165 base::string16 MatchApp(const char* title) {
    166   return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_APP_PREFIX,
    167                                     base::ASCIIToUTF16(title));
    168 }
    169 
    170 base::string16 MatchAnyApp() { return MatchApp("*"); }
    171 
    172 base::string16 MatchWebView(const char* title) {
    173   return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_WEBVIEW_TAG_PREFIX,
    174                                     base::ASCIIToUTF16(title));
    175 }
    176 
    177 base::string16 MatchAnyWebView() { return MatchWebView("*"); }
    178 
    179 base::string16 MatchBackground(const char* title) {
    180   return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_BACKGROUND_PREFIX,
    181                                     base::ASCIIToUTF16(title));
    182 }
    183 
    184 base::string16 MatchAnyBackground() { return MatchBackground("*"); }
    185 
    186 base::string16 MatchPrint(const char* title) {
    187   return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PRINT_PREFIX,
    188                                     base::ASCIIToUTF16(title));
    189 }
    190 
    191 base::string16 MatchAnyPrint() { return MatchPrint("*"); }
    192 
    193 }  // namespace browsertest_util
    194 }  // namespace task_manager
    195