Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: chrome/browser/task_manager/legacy_task_manager_tester.cc

Issue 1955123002: [Part 4 of 6] Split LegacyTaskManagerTester into its own file. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@tm_file_split3
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/task_manager/task_manager_browsertest_util.h" 5 #include "chrome/browser/task_manager/legacy_task_manager_tester.h"
6 6
7 #include "base/bind_helpers.h"
8 #include "base/command_line.h"
9 #include "base/location.h"
10 #include "base/memory/ptr_util.h" 7 #include "base/memory/ptr_util.h"
11 #include "base/run_loop.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/strings/pattern.h"
14 #include "base/strings/string16.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/test/test_timeouts.h"
18 #include "base/thread_task_runner_handle.h"
19 #include "base/timer/timer.h"
20 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/sessions/session_tab_helper.h" 8 #include "chrome/browser/sessions/session_tab_helper.h"
23 #include "chrome/browser/task_management/task_manager_interface.h"
24 #include "chrome/browser/task_manager/resource_provider.h" 9 #include "chrome/browser/task_manager/resource_provider.h"
25 #include "chrome/browser/task_manager/task_manager.h" 10 #include "chrome/browser/task_manager/task_manager.h"
26 #include "chrome/browser/ui/browser_dialogs.h" 11 #include "chrome/browser/ui/browser_dialogs.h"
27 #include "chrome/browser/ui/task_manager/task_manager_table_model.h"
28 #include "chrome/common/chrome_switches.h"
29 #include "chrome/grit/generated_resources.h" 12 #include "chrome/grit/generated_resources.h"
30 #include "extensions/strings/grit/extensions_strings.h" 13 #include "extensions/strings/grit/extensions_strings.h"
31 #include "testing/gtest/include/gtest/gtest.h" 14
32 #include "ui/base/l10n/l10n_util.h" 15 using ColumnSpecifier = task_manager::browsertest_util::ColumnSpecifier;
33 #include "ui/base/models/table_model_observer.h"
34 16
35 namespace task_manager { 17 namespace task_manager {
36 namespace browsertest_util {
37 18
38 namespace { 19 class LegacyTaskManagerTester : public browsertest_util::TaskManagerTester,
39 20 public TaskManagerModelObserver {
40 // Returns whether chrome::ShowTaskManager() will, for the current platform and
41 // command line, show a view backed by a task_management::TaskManagerTableModel.
42 bool IsNewTaskManagerViewEnabled() {
43 #if defined(OS_MACOSX)
44 if (!chrome::ToolkitViewsDialogsEnabled())
45 return false;
46 #endif
47 return switches::NewTaskManagerEnabled();
48 }
49
50 // Temporarily intercepts the calls between a TableModel and its Observer,
51 // running |callback| whenever anything happens.
52 class ScopedInterceptTableModelObserver : public ui::TableModelObserver {
53 public: 21 public:
54 ScopedInterceptTableModelObserver( 22 explicit LegacyTaskManagerTester(const base::Closure& on_resource_change)
55 ui::TableModel* model_to_intercept,
56 ui::TableModelObserver* real_table_model_observer,
57 const base::Closure& callback)
58 : model_to_intercept_(model_to_intercept),
59 real_table_model_observer_(real_table_model_observer),
60 callback_(callback) {
61 model_to_intercept_->SetObserver(this);
62 }
63
64 ~ScopedInterceptTableModelObserver() override {
65 model_to_intercept_->SetObserver(real_table_model_observer_);
66 }
67
68 // ui::TableModelObserver:
69 void OnModelChanged() override {
70 real_table_model_observer_->OnModelChanged();
71 callback_.Run();
72 }
73 void OnItemsChanged(int start, int length) override {
74 real_table_model_observer_->OnItemsChanged(start, length);
75 callback_.Run();
76 }
77 void OnItemsAdded(int start, int length) override {
78 real_table_model_observer_->OnItemsAdded(start, length);
79 callback_.Run();
80 }
81 void OnItemsRemoved(int start, int length) override {
82 real_table_model_observer_->OnItemsRemoved(start, length);
83 callback_.Run();
84 }
85
86 private:
87 ui::TableModel* model_to_intercept_;
88 ui::TableModelObserver* real_table_model_observer_;
89 base::Closure callback_;
90 };
91
92 } // namespace
93
94 // Implementation of TaskManagerTester for the 'new' TaskManager.
95 class TaskManagerTesterImpl : public TaskManagerTester {
96 public:
97 explicit TaskManagerTesterImpl(const base::Closure& on_resource_change)
98 : model_(GetRealModel()) {
99 // Eavesdrop the model->view conversation, since the model only supports
100 // single observation.
101 if (!on_resource_change.is_null()) {
102 interceptor_.reset(new ScopedInterceptTableModelObserver(
103 model_, model_->table_model_observer_, on_resource_change));
104 }
105 }
106
107 ~TaskManagerTesterImpl() override {
108 CHECK_EQ(GetRealModel(), model_) << "Task Manager should not be hidden "
109 "while TaskManagerTester is alive. "
110 "This indicates a test bug.";
111 }
112
113 // TaskManagerTester:
114 int GetRowCount() override { return model_->RowCount(); }
115
116 base::string16 GetRowTitle(int row) override {
117 return model_->GetText(row, IDS_TASK_MANAGER_TASK_COLUMN);
118 }
119
120 void ToggleColumnVisibility(ColumnSpecifier column) override {
121 int column_id = 0;
122 switch (column) {
123 case ColumnSpecifier::COLUMN_NONE:
124 return;
125 case ColumnSpecifier::SQLITE_MEMORY_USED:
126 column_id = IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN;
127 break;
128 case ColumnSpecifier::V8_MEMORY_USED:
129 case ColumnSpecifier::V8_MEMORY:
130 column_id = IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN;
131 break;
132 }
133 model_->ToggleColumnVisibility(column_id);
134 }
135
136 int64_t GetColumnValue(ColumnSpecifier column, int row) override {
137 task_management::TaskId task_id = model_->tasks_[row];
138 int64_t value = 0;
139 int64_t ignored = 0;
140 bool success = false;
141
142 switch (column) {
143 case ColumnSpecifier::COLUMN_NONE:
144 break;
145 case ColumnSpecifier::V8_MEMORY:
146 success = task_manager()->GetV8Memory(task_id, &value, &ignored);
147 break;
148 case ColumnSpecifier::V8_MEMORY_USED:
149 success = task_manager()->GetV8Memory(task_id, &ignored, &value);
150 break;
151 case ColumnSpecifier::SQLITE_MEMORY_USED:
152 value = task_manager()->GetSqliteMemoryUsed(task_id);
153 success = true;
154 break;
155 }
156 if (!success)
157 return 0;
158 return value;
159 }
160
161 int32_t GetTabId(int row) override {
162 task_management::TaskId task_id = model_->tasks_[row];
163 return task_manager()->GetTabId(task_id);
164 }
165
166 void Kill(int row) override { model_->KillTask(row); }
167
168 private:
169 task_management::TaskManagerInterface* task_manager() {
170 return model_->observed_task_manager();
171 }
172
173 // Returns the TaskManagerTableModel for the the visible NewTaskManagerView.
174 static task_management::TaskManagerTableModel* GetRealModel() {
175 CHECK(IsNewTaskManagerViewEnabled());
176 // This downcast is safe, as long as the new task manager is enabled.
177 task_management::TaskManagerTableModel* result =
178 static_cast<task_management::TaskManagerTableModel*>(
179 chrome::ShowTaskManager(nullptr));
180 return result;
181 }
182
183 task_management::TaskManagerTableModel* model_;
184 std::unique_ptr<ScopedInterceptTableModelObserver> interceptor_;
185 };
186
187 namespace {
188
189 class LegacyTaskManagerTesterImpl : public TaskManagerTester,
190 public TaskManagerModelObserver {
191 public:
192 explicit LegacyTaskManagerTesterImpl(const base::Closure& on_resource_change)
193 : on_resource_change_(on_resource_change), 23 : on_resource_change_(on_resource_change),
194 model_(TaskManager::GetInstance()->model()) { 24 model_(TaskManager::GetInstance()->model()) {
195 if (!on_resource_change_.is_null()) 25 if (!on_resource_change_.is_null())
196 model_->AddObserver(this); 26 model_->AddObserver(this);
197 } 27 }
198 ~LegacyTaskManagerTesterImpl() override { 28 ~LegacyTaskManagerTester() override {
199 if (!on_resource_change_.is_null()) 29 if (!on_resource_change_.is_null())
200 model_->RemoveObserver(this); 30 model_->RemoveObserver(this);
201 } 31 }
202 32
203 // TaskManagerTester: 33 // TaskManagerTester:
204 int GetRowCount() override { return model_->ResourceCount(); } 34 int GetRowCount() override { return model_->ResourceCount(); }
205 35
206 base::string16 GetRowTitle(int row) override { 36 base::string16 GetRowTitle(int row) override {
207 return model_->GetResourceTitle(row); 37 return model_->GetResourceTitle(row);
208 } 38 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 80
251 private: 81 private:
252 void OnResourceChange() { 82 void OnResourceChange() {
253 if (!on_resource_change_.is_null()) 83 if (!on_resource_change_.is_null())
254 on_resource_change_.Run(); 84 on_resource_change_.Run();
255 } 85 }
256 base::Closure on_resource_change_; 86 base::Closure on_resource_change_;
257 TaskManagerModel* model_; 87 TaskManagerModel* model_;
258 }; 88 };
259 89
260 // Helper class to run a message loop until a TaskManagerTester is in an 90 std::unique_ptr<browsertest_util::TaskManagerTester>
261 // expected state. If timeout occurs, an ASCII version of the task manager's 91 CreateLegacyTaskManagerTester(const base::Closure& callback) {
262 // contents, along with a summary of the expected state, are dumped to test 92 return base::WrapUnique(new LegacyTaskManagerTester(callback));
263 // output, to assist debugging.
264 class ResourceChangeObserver {
265 public:
266 ResourceChangeObserver(int required_count,
267 const base::string16& title_pattern,
268 ColumnSpecifier column_specifier,
269 size_t min_column_value)
270 : required_count_(required_count),
271 title_pattern_(title_pattern),
272 column_specifier_(column_specifier),
273 min_column_value_(min_column_value) {
274 base::Closure callback = base::Bind(
275 &ResourceChangeObserver::OnResourceChange, base::Unretained(this));
276
277 if (IsNewTaskManagerViewEnabled())
278 task_manager_tester_.reset(new TaskManagerTesterImpl(callback));
279 else
280 task_manager_tester_.reset(new LegacyTaskManagerTesterImpl(callback));
281 }
282
283 void RunUntilSatisfied() {
284 // See if the condition is satisfied without having to run the loop. This
285 // check has to be placed after the installation of the
286 // TaskManagerModelObserver, because resources may change before that.
287 if (IsSatisfied())
288 return;
289
290 timer_.Start(FROM_HERE, TestTimeouts::action_timeout(), this,
291 &ResourceChangeObserver::OnTimeout);
292
293 run_loop_.Run();
294
295 // If we succeeded normally (no timeout), check our post condition again
296 // before returning control to the test. If it is no longer satisfied, the
297 // test is likely flaky: we were waiting for a state that was only achieved
298 // emphemerally), so treat this as a failure.
299 if (!IsSatisfied() && timer_.IsRunning()) {
300 FAIL() << "Wait condition satisfied only emphemerally. Likely test "
301 << "problem. Maybe wait instead for the state below?\n"
302 << DumpTaskManagerModel();
303 }
304
305 timer_.Stop();
306 }
307
308 private:
309 void OnResourceChange() {
310 if (!IsSatisfied())
311 return;
312
313 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
314 run_loop_.QuitClosure());
315 }
316
317 bool IsSatisfied() { return CountMatches() == required_count_; }
318
319 int CountMatches() {
320 int match_count = 0;
321 for (int i = 0; i < task_manager_tester_->GetRowCount(); i++) {
322 if (!base::MatchPattern(task_manager_tester_->GetRowTitle(i),
323 title_pattern_))
324 continue;
325
326 if (GetColumnValue(i) < min_column_value_)
327 continue;
328
329 match_count++;
330 }
331 return match_count;
332 }
333
334 int64_t GetColumnValue(int index) {
335 return task_manager_tester_->GetColumnValue(column_specifier_, index);
336 }
337
338 const char* GetColumnName() {
339 switch (column_specifier_) {
340 case ColumnSpecifier::COLUMN_NONE:
341 return "N/A";
342 case ColumnSpecifier::V8_MEMORY:
343 return "V8 Memory";
344 case ColumnSpecifier::V8_MEMORY_USED:
345 return "V8 Memory Used";
346 case ColumnSpecifier::SQLITE_MEMORY_USED:
347 return "SQLite Memory Used";
348 }
349 return "N/A";
350 }
351
352 void OnTimeout() {
353 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
354 run_loop_.QuitClosure());
355 FAIL() << "Timed out.\n" << DumpTaskManagerModel();
356 }
357
358 testing::Message DumpTaskManagerModel() {
359 testing::Message task_manager_state_dump;
360 task_manager_state_dump << "Waiting for exactly " << required_count_
361 << " matches of wildcard pattern \""
362 << base::UTF16ToASCII(title_pattern_) << "\"";
363 if (min_column_value_ > 0) {
364 task_manager_state_dump << " && [" << GetColumnName()
365 << " >= " << min_column_value_ << "]";
366 }
367 task_manager_state_dump << "\nCurrently there are " << CountMatches()
368 << " matches.";
369 task_manager_state_dump << "\nCurrent Task Manager Model is:";
370 for (int i = 0; i < task_manager_tester_->GetRowCount(); i++) {
371 task_manager_state_dump
372 << "\n > " << std::setw(40) << std::left
373 << base::UTF16ToASCII(task_manager_tester_->GetRowTitle(i));
374 if (min_column_value_ > 0) {
375 task_manager_state_dump << " [" << GetColumnName()
376 << " == " << GetColumnValue(i) << "]";
377 }
378 }
379 return task_manager_state_dump;
380 }
381
382 std::unique_ptr<TaskManagerTester> task_manager_tester_;
383 const int required_count_;
384 const base::string16 title_pattern_;
385 const ColumnSpecifier column_specifier_;
386 const int64_t min_column_value_;
387 base::RunLoop run_loop_;
388 base::OneShotTimer timer_;
389 };
390
391 } // namespace
392
393 std::unique_ptr<TaskManagerTester> GetTaskManagerTester() {
394 if (IsNewTaskManagerViewEnabled())
395 return base::WrapUnique(new TaskManagerTesterImpl(base::Closure()));
396 else
397 return base::WrapUnique(new LegacyTaskManagerTesterImpl(base::Closure()));
398 } 93 }
399 94
400 void WaitForTaskManagerRows(int required_count,
401 const base::string16& title_pattern) {
402 const int column_value_dont_care = 0;
403 ResourceChangeObserver observer(required_count, title_pattern,
404 ColumnSpecifier::COLUMN_NONE,
405 column_value_dont_care);
406 observer.RunUntilSatisfied();
407 }
408
409 void WaitForTaskManagerStatToExceed(const base::string16& title_pattern,
410 ColumnSpecifier column_getter,
411 size_t min_column_value) {
412 const int wait_for_one_match = 1;
413 ResourceChangeObserver observer(wait_for_one_match, title_pattern,
414 column_getter, min_column_value);
415 observer.RunUntilSatisfied();
416 }
417
418 base::string16 MatchTab(const char* title) {
419 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_TAB_PREFIX,
420 base::ASCIIToUTF16(title));
421 }
422
423 base::string16 MatchAnyTab() {
424 return MatchTab("*");
425 }
426
427 base::string16 MatchAboutBlankTab() {
428 return MatchTab("about:blank");
429 }
430
431 base::string16 MatchExtension(const char* title) {
432 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_EXTENSION_PREFIX,
433 base::ASCIIToUTF16(title));
434 }
435
436 base::string16 MatchAnyExtension() {
437 return MatchExtension("*");
438 }
439
440 base::string16 MatchApp(const char* title) {
441 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_APP_PREFIX,
442 base::ASCIIToUTF16(title));
443 }
444
445 base::string16 MatchAnyApp() {
446 return MatchApp("*");
447 }
448
449 base::string16 MatchWebView(const char* title) {
450 return l10n_util::GetStringFUTF16(
451 IDS_EXTENSION_TASK_MANAGER_WEBVIEW_TAG_PREFIX, base::ASCIIToUTF16(title));
452 }
453
454 base::string16 MatchAnyWebView() {
455 return MatchWebView("*");
456 }
457
458 base::string16 MatchBackground(const char* title) {
459 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_BACKGROUND_PREFIX,
460 base::ASCIIToUTF16(title));
461 }
462
463 base::string16 MatchAnyBackground() {
464 return MatchBackground("*");
465 }
466
467 base::string16 MatchPrint(const char* title) {
468 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PRINT_PREFIX,
469 base::ASCIIToUTF16(title));
470 }
471
472 base::string16 MatchAnyPrint() {
473 return MatchPrint("*");
474 }
475
476 base::string16 MatchSubframe(const char* title) {
477 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_SUBFRAME_PREFIX,
478 base::ASCIIToUTF16(title));
479 }
480
481 base::string16 MatchAnySubframe() {
482 return MatchSubframe("*");
483 }
484
485 base::string16 MatchUtility(const base::string16& title) {
486 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_UTILITY_PREFIX, title);
487 }
488
489 base::string16 MatchAnyUtility() {
490 return MatchUtility(base::ASCIIToUTF16("*"));
491 }
492
493 } // namespace browsertest_util
494 } // namespace task_manager 95 } // namespace task_manager
OLDNEW
« no previous file with comments | « chrome/browser/task_manager/legacy_task_manager_tester.h ('k') | chrome/browser/task_manager/task_manager_browsertest_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698