Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / performance_monitor / performance_monitor_browsertest.cc
blob4527f8696decacab7241198bf30de8ea49056616
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.
5 #include "base/command_line.h"
6 #include "base/files/file_path.h"
7 #include "base/logging.h"
8 #include "base/path_service.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/threading/sequenced_worker_pool.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/chrome_notification_types.h"
13 #include "chrome/browser/extensions/extension_browsertest.h"
14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/performance_monitor/constants.h"
16 #include "chrome/browser/performance_monitor/database.h"
17 #include "chrome/browser/performance_monitor/metric.h"
18 #include "chrome/browser/performance_monitor/performance_monitor.h"
19 #include "chrome/browser/prefs/session_startup_pref.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/profiles/profile_manager.h"
22 #include "chrome/browser/sessions/session_service.h"
23 #include "chrome/browser/sessions/session_service_factory.h"
24 #include "chrome/browser/sessions/session_service_test_helper.h"
25 #include "chrome/browser/ui/browser.h"
26 #include "chrome/browser/ui/browser_commands.h"
27 #include "chrome/browser/ui/browser_navigator.h"
28 #include "chrome/browser/ui/browser_window.h"
29 #include "chrome/browser/ui/host_desktop.h"
30 #include "chrome/browser/ui/tabs/tab_strip_model.h"
31 #include "chrome/common/chrome_constants.h"
32 #include "chrome/common/chrome_paths.h"
33 #include "chrome/common/chrome_switches.h"
34 #include "chrome/common/chrome_version_info.h"
35 #include "chrome/common/url_constants.h"
36 #include "chrome/test/base/ui_test_utils.h"
37 #include "content/public/browser/notification_registrar.h"
38 #include "content/public/browser/notification_service.h"
39 #include "content/public/common/page_transition_types.h"
40 #include "content/public/test/browser_test_utils.h"
41 #include "content/public/test/test_navigation_observer.h"
42 #include "content/public/test/test_utils.h"
43 #include "extensions/common/extension.h"
45 #if defined(OS_CHROMEOS)
46 #include "chromeos/chromeos_switches.h"
47 #endif
49 #if defined(OS_MACOSX)
50 #include "base/mac/scoped_nsautorelease_pool.h"
51 #endif
53 using extensions::Extension;
55 namespace performance_monitor {
57 namespace {
59 const base::TimeDelta kMaxStartupTime = base::TimeDelta::FromMinutes(3);
61 // Helper struct to store the information of an extension; this is needed if the
62 // pointer to the extension ever becomes invalid (e.g., if we uninstall the
63 // extension).
64 struct ExtensionBasicInfo {
65 // Empty constructor for stl-container-happiness.
66 ExtensionBasicInfo() {
68 explicit ExtensionBasicInfo(const Extension* extension)
69 : description(extension->description()),
70 id(extension->id()),
71 name(extension->name()),
72 url(extension->url().spec()),
73 version(extension->VersionString()),
74 location(extension->location()) {
77 std::string description;
78 std::string id;
79 std::string name;
80 std::string url;
81 std::string version;
82 extensions::Manifest::Location location;
85 // Compare the fields of |extension| to those in |value|; this is a check to
86 // make sure the extension data was recorded properly in the event.
87 void ValidateExtensionInfo(const ExtensionBasicInfo extension,
88 const base::DictionaryValue* value) {
89 std::string extension_description;
90 std::string extension_id;
91 std::string extension_name;
92 std::string extension_url;
93 std::string extension_version;
94 int extension_location;
96 ASSERT_TRUE(value->GetString("extensionDescription",
97 &extension_description));
98 ASSERT_EQ(extension.description, extension_description);
99 ASSERT_TRUE(value->GetString("extensionId", &extension_id));
100 ASSERT_EQ(extension.id, extension_id);
101 ASSERT_TRUE(value->GetString("extensionName", &extension_name));
102 ASSERT_EQ(extension.name, extension_name);
103 ASSERT_TRUE(value->GetString("extensionUrl", &extension_url));
104 ASSERT_EQ(extension.url, extension_url);
105 ASSERT_TRUE(value->GetString("extensionVersion", &extension_version));
106 ASSERT_EQ(extension.version, extension_version);
107 ASSERT_TRUE(value->GetInteger("extensionLocation", &extension_location));
108 ASSERT_EQ(extension.location, extension_location);
111 // Verify that a particular event has the proper type.
112 void CheckEventType(int expected_event_type, const linked_ptr<Event>& event) {
113 int event_type = -1;
114 ASSERT_TRUE(event->data()->GetInteger("eventType", &event_type));
115 ASSERT_EQ(expected_event_type, event_type);
116 ASSERT_EQ(expected_event_type, event->type());
119 // Verify that we received the proper number of events, checking the type of
120 // each one.
121 void CheckEventTypes(const std::vector<int>& expected_event_types,
122 const Database::EventVector& events) {
123 ASSERT_EQ(expected_event_types.size(), events.size());
125 for (size_t i = 0; i < expected_event_types.size(); ++i)
126 CheckEventType(expected_event_types[i], events[i]);
129 // Check that we received the proper number of events, that each event is of the
130 // proper type, and that each event recorded the proper information about the
131 // extension.
132 void CheckExtensionEvents(
133 const std::vector<int>& expected_event_types,
134 const Database::EventVector& events,
135 const std::vector<ExtensionBasicInfo>& extension_infos) {
136 CheckEventTypes(expected_event_types, events);
138 for (size_t i = 0; i < expected_event_types.size(); ++i) {
139 ValidateExtensionInfo(extension_infos[i], events[i]->data());
140 int event_type;
141 ASSERT_TRUE(events[i]->data()->GetInteger("eventType", &event_type));
142 ASSERT_EQ(expected_event_types[i], event_type);
146 } // namespace
148 class PerformanceMonitorBrowserTest : public ExtensionBrowserTest {
149 public:
150 virtual void SetUpOnMainThread() OVERRIDE {
151 CHECK(db_dir_.CreateUniqueTempDir());
152 performance_monitor_ = PerformanceMonitor::GetInstance();
153 performance_monitor_->SetDatabasePath(db_dir_.path());
155 // PerformanceMonitor's initialization process involves a significant
156 // amount of thread-hopping between the UI thread and the background thread.
157 // If we begin the tests prior to full initialization, we cannot predict
158 // the behavior or mock synchronicity as we must. Wait for initialization
159 // to complete fully before proceeding with the test.
160 content::WindowedNotificationObserver windowed_observer(
161 chrome::NOTIFICATION_PERFORMANCE_MONITOR_INITIALIZED,
162 content::NotificationService::AllSources());
164 // We stop the timer in charge of doing timed collections so that we can
165 // enforce when, and how many times, we do these collections.
166 performance_monitor_->disable_timer_autostart_for_testing_ = true;
167 // Force metrics to be stored, regardless of switches used.
168 performance_monitor_->database_logging_enabled_ = true;
169 performance_monitor_->Initialize();
171 windowed_observer.Wait();
174 // A handle for gathering statistics from the database, which must be done on
175 // the background thread. Since we are testing, we can mock synchronicity with
176 // FlushForTesting().
177 void GatherStatistics() {
178 performance_monitor_->next_collection_time_ = base::Time::Now();
179 performance_monitor_->GatherMetricsMapOnUIThread();
181 RunAllPendingInMessageLoop(content::BrowserThread::IO);
182 content::BrowserThread::GetBlockingPool()->FlushForTesting();
185 void GetEventsOnBackgroundThread(Database::EventVector* events) {
186 // base::Time is potentially flaky in that there is no guarantee that it
187 // won't actually decrease between successive calls. If we call GetEvents
188 // and the Database uses base::Time::Now() and gets a lesser time, then it
189 // will return 0 events. Thus, we use a time that is guaranteed to be in the
190 // future (for at least the next couple hundred thousand years).
191 *events = performance_monitor_->database()->GetEvents(
192 base::Time(), base::Time::FromInternalValue(kint64max));
195 // A handle for getting the events from the database, which must be done on
196 // the background thread. Since we are testing, we can mock synchronicity
197 // with FlushForTesting().
198 Database::EventVector GetEvents() {
199 // Ensure that any event insertions happen prior to getting events in order
200 // to avoid race conditions.
201 content::BrowserThread::GetBlockingPool()->FlushForTesting();
202 content::RunAllPendingInMessageLoop();
204 Database::EventVector events;
205 content::BrowserThread::PostBlockingPoolSequencedTask(
206 Database::kDatabaseSequenceToken,
207 FROM_HERE,
208 base::Bind(&PerformanceMonitorBrowserTest::GetEventsOnBackgroundThread,
209 base::Unretained(this),
210 &events));
212 content::BrowserThread::GetBlockingPool()->FlushForTesting();
213 return events;
216 void GetStatsOnBackgroundThread(Database::MetricVector* metrics,
217 MetricType type) {
218 *metrics = *performance_monitor_->database()->GetStatsForActivityAndMetric(
219 type, base::Time(), base::Time::FromInternalValue(kint64max));
222 // A handle for getting statistics from the database (see previous comments on
223 // GetEvents() and GetEventsOnBackgroundThread).
224 Database::MetricVector GetStats(MetricType type) {
225 content::BrowserThread::GetBlockingPool()->FlushForTesting();
226 content::RunAllPendingInMessageLoop();
228 Database::MetricVector metrics;
229 content::BrowserThread::PostBlockingPoolSequencedTask(
230 Database::kDatabaseSequenceToken,
231 FROM_HERE,
232 base::Bind(&PerformanceMonitorBrowserTest::GetStatsOnBackgroundThread,
233 base::Unretained(this),
234 &metrics,
235 type));
237 content::BrowserThread::GetBlockingPool()->FlushForTesting();
238 return metrics;
241 // A handle for inserting a state value into the database, which must be done
242 // on the background thread. This is useful for mocking up a scenario in which
243 // the database has prior data stored. We mock synchronicity with
244 // FlushForTesting().
245 void AddStateValue(const std::string& key, const std::string& value) {
246 content::BrowserThread::PostBlockingPoolSequencedTask(
247 Database::kDatabaseSequenceToken,
248 FROM_HERE,
249 base::Bind(base::IgnoreResult(&Database::AddStateValue),
250 base::Unretained(performance_monitor()->database()),
251 key,
252 value));
254 content::BrowserThread::GetBlockingPool()->FlushForTesting();
257 // A handle for PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread();
258 // we mock synchronicity with FlushForTesting().
259 void CheckForVersionUpdate() {
260 content::BrowserThread::PostBlockingPoolSequencedTask(
261 Database::kDatabaseSequenceToken,
262 FROM_HERE,
263 base::Bind(&PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread,
264 base::Unretained(performance_monitor())));
266 content::BrowserThread::GetBlockingPool()->FlushForTesting();
269 PerformanceMonitor* performance_monitor() const {
270 return performance_monitor_;
273 protected:
274 base::ScopedTempDir db_dir_;
275 PerformanceMonitor* performance_monitor_;
278 class PerformanceMonitorUncleanExitBrowserTest
279 : public PerformanceMonitorBrowserTest {
280 public:
281 virtual bool SetUpUserDataDirectory() OVERRIDE {
282 base::FilePath user_data_directory;
283 PathService::Get(chrome::DIR_USER_DATA, &user_data_directory);
285 // On CrOS, if we are "logged in" with the --login-profile switch,
286 // the default profile will be different. We check if we are logged in, and,
287 // if we are, we use that profile name instead. (Note: trybots will
288 // typically be logged in with 'user'.)
289 #if defined(OS_CHROMEOS)
290 const CommandLine command_line = *CommandLine::ForCurrentProcess();
291 if (command_line.HasSwitch(chromeos::switches::kLoginProfile)) {
292 first_profile_name_ =
293 command_line.GetSwitchValueASCII(chromeos::switches::kLoginProfile);
294 } else {
295 first_profile_name_ = chrome::kInitialProfile;
297 #else
298 first_profile_name_ = chrome::kInitialProfile;
299 #endif
301 base::FilePath first_profile =
302 user_data_directory.AppendASCII(first_profile_name_);
303 CHECK(base::CreateDirectory(first_profile));
305 base::FilePath stock_prefs_file;
306 PathService::Get(chrome::DIR_TEST_DATA, &stock_prefs_file);
307 stock_prefs_file = stock_prefs_file.AppendASCII("performance_monitor")
308 .AppendASCII("unclean_exit_prefs");
309 CHECK(base::PathExists(stock_prefs_file));
311 base::FilePath first_profile_prefs_file =
312 first_profile.Append(chrome::kPreferencesFilename);
313 CHECK(base::CopyFile(stock_prefs_file, first_profile_prefs_file));
314 CHECK(base::PathExists(first_profile_prefs_file));
316 second_profile_name_ =
317 std::string(chrome::kMultiProfileDirPrefix)
318 .append(base::IntToString(1));
320 base::FilePath second_profile =
321 user_data_directory.AppendASCII(second_profile_name_);
322 CHECK(base::CreateDirectory(second_profile));
324 base::FilePath second_profile_prefs_file =
325 second_profile.Append(chrome::kPreferencesFilename);
326 CHECK(base::CopyFile(stock_prefs_file, second_profile_prefs_file));
327 CHECK(base::PathExists(second_profile_prefs_file));
329 return true;
332 protected:
333 std::string first_profile_name_;
334 std::string second_profile_name_;
337 class PerformanceMonitorSessionRestoreBrowserTest
338 : public PerformanceMonitorBrowserTest {
339 public:
340 virtual void SetUpOnMainThread() OVERRIDE {
341 SessionStartupPref pref(SessionStartupPref::LAST);
342 SessionStartupPref::SetStartupPref(browser()->profile(), pref);
343 #if defined(OS_CHROMEOS) || defined (OS_MACOSX)
344 // Undo the effect of kBrowserAliveWithNoWindows in defaults.cc so that we
345 // can get these test to work without quitting.
346 SessionServiceTestHelper helper(
347 SessionServiceFactory::GetForProfile(browser()->profile()));
348 helper.SetForceBrowserNotAliveWithNoWindows(true);
349 helper.ReleaseService();
350 #endif
352 PerformanceMonitorBrowserTest::SetUpOnMainThread();
355 Browser* QuitBrowserAndRestore(Browser* browser, int expected_tab_count) {
356 Profile* profile = browser->profile();
358 // Close the browser.
359 g_browser_process->AddRefModule();
360 content::WindowedNotificationObserver observer(
361 chrome::NOTIFICATION_BROWSER_CLOSED,
362 content::NotificationService::AllSources());
363 browser->window()->Close();
364 #if defined(OS_MACOSX)
365 // BrowserWindowController depends on the auto release pool being recycled
366 // in the message loop to delete itself, which frees the Browser object
367 // which fires this event.
368 AutoreleasePool()->Recycle();
369 #endif
370 observer.Wait();
372 // Create a new window, which should trigger session restore.
373 content::TestNavigationObserver restore_observer(NULL, expected_tab_count);
374 restore_observer.StartWatchingNewWebContents();
375 ui_test_utils::BrowserAddedObserver window_observer;
376 chrome::NewEmptyWindow(profile, chrome::GetActiveDesktop());
377 Browser* new_browser = window_observer.WaitForSingleNewBrowser();
378 restore_observer.Wait();
379 g_browser_process->ReleaseModule();
381 return new_browser;
385 // Test that PerformanceMonitor will correctly record an extension installation
386 // event.
387 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, InstallExtensionEvent) {
388 base::FilePath extension_path;
389 PathService::Get(chrome::DIR_TEST_DATA, &extension_path);
390 extension_path = extension_path.AppendASCII("performance_monitor")
391 .AppendASCII("extensions")
392 .AppendASCII("simple_extension_v1");
393 const Extension* extension = LoadExtension(extension_path);
395 std::vector<ExtensionBasicInfo> extension_infos;
396 extension_infos.push_back(ExtensionBasicInfo(extension));
398 std::vector<int> expected_event_types;
399 expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
401 Database::EventVector events = GetEvents();
402 CheckExtensionEvents(expected_event_types, events, extension_infos);
405 // Test that PerformanceMonitor will correctly record events as an extension is
406 // disabled and enabled.
407 // Test is falky, see http://crbug.com/157980
408 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest,
409 DISABLED_DisableAndEnableExtensionEvent) {
410 const int kNumEvents = 3;
412 base::FilePath extension_path;
413 PathService::Get(chrome::DIR_TEST_DATA, &extension_path);
414 extension_path = extension_path.AppendASCII("performance_monitor")
415 .AppendASCII("extensions")
416 .AppendASCII("simple_extension_v1");
417 const Extension* extension = LoadExtension(extension_path);
419 DisableExtension(extension->id());
420 EnableExtension(extension->id());
422 std::vector<ExtensionBasicInfo> extension_infos;
423 // There will be three events in all, each pertaining to the same extension:
424 // Extension Install
425 // Extension Disable
426 // Extension Enable
427 for (int i = 0; i < kNumEvents; ++i)
428 extension_infos.push_back(ExtensionBasicInfo(extension));
430 std::vector<int> expected_event_types;
431 expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
432 expected_event_types.push_back(EVENT_EXTENSION_DISABLE);
433 expected_event_types.push_back(EVENT_EXTENSION_ENABLE);
435 Database::EventVector events = GetEvents();
436 CheckExtensionEvents(expected_event_types, events, extension_infos);
439 // Test that PerformanceMonitor correctly records an extension update event.
440 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, UpdateExtensionEvent) {
441 base::ScopedTempDir temp_dir;
442 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
444 base::FilePath test_data_dir;
445 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
446 test_data_dir = test_data_dir.AppendASCII("performance_monitor")
447 .AppendASCII("extensions");
449 // We need two versions of the same extension.
450 base::FilePath pem_path = test_data_dir.AppendASCII("simple_extension.pem");
451 base::FilePath path_v1_ = PackExtensionWithOptions(
452 test_data_dir.AppendASCII("simple_extension_v1"),
453 temp_dir.path().AppendASCII("simple_extension1.crx"),
454 pem_path,
455 base::FilePath());
456 base::FilePath path_v2_ = PackExtensionWithOptions(
457 test_data_dir.AppendASCII("simple_extension_v2"),
458 temp_dir.path().AppendASCII("simple_extension2.crx"),
459 pem_path,
460 base::FilePath());
462 const extensions::Extension* extension = InstallExtension(path_v1_, 1);
464 std::vector<ExtensionBasicInfo> extension_infos;
465 extension_infos.push_back(ExtensionBasicInfo(extension));
467 ExtensionService* extension_service =
468 browser()->profile()->GetExtensionService();
470 extensions::CrxInstaller* crx_installer = NULL;
472 // Create an observer to wait for the update to finish.
473 content::WindowedNotificationObserver windowed_observer(
474 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
475 content::Source<extensions::CrxInstaller>(crx_installer));
476 ASSERT_TRUE(extension_service->
477 UpdateExtension(extension->id(), path_v2_, GURL(), &crx_installer));
478 windowed_observer.Wait();
480 extension = extension_service->GetExtensionById(
481 extension_infos[0].id, false); // don't include disabled extensions.
483 // The total series of events for this process will be:
484 // Extension Install - install version 1
485 // Extension Install - install version 2
486 // Extension Update - signal the udate to version 2
487 // We push back the corresponding ExtensionBasicInfos.
488 extension_infos.push_back(ExtensionBasicInfo(extension));
489 extension_infos.push_back(extension_infos[1]);
491 std::vector<int> expected_event_types;
492 expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
493 expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
494 expected_event_types.push_back(EVENT_EXTENSION_UPDATE);
496 Database::EventVector events = GetEvents();
498 CheckExtensionEvents(expected_event_types, events, extension_infos);
501 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, UninstallExtensionEvent) {
502 const int kNumEvents = 2;
503 base::FilePath extension_path;
504 PathService::Get(chrome::DIR_TEST_DATA, &extension_path);
505 extension_path = extension_path.AppendASCII("performance_monitor")
506 .AppendASCII("extensions")
507 .AppendASCII("simple_extension_v1");
508 const Extension* extension = LoadExtension(extension_path);
510 std::vector<ExtensionBasicInfo> extension_infos;
511 // There will be two events, both pertaining to the same extension:
512 // Extension Install
513 // Extension Uninstall
514 for (int i = 0; i < kNumEvents; ++i)
515 extension_infos.push_back(ExtensionBasicInfo(extension));
517 UninstallExtension(extension->id());
519 std::vector<int> expected_event_types;
520 expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
521 expected_event_types.push_back(EVENT_EXTENSION_UNINSTALL);
523 Database::EventVector events = GetEvents();
525 CheckExtensionEvents(expected_event_types, events, extension_infos);
528 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, NewVersionEvent) {
529 const char kOldVersion[] = "0.0";
531 // The version in the database right now will be the current version of chrome
532 // (gathered at initialization of PerformanceMonitor). Replace this with an
533 // older version so an event is generated.
534 AddStateValue(kStateChromeVersion, kOldVersion);
536 CheckForVersionUpdate();
538 chrome::VersionInfo version;
539 ASSERT_TRUE(version.is_valid());
540 std::string version_string = version.Version();
542 Database::EventVector events = GetEvents();
543 ASSERT_EQ(1u, events.size());
544 ASSERT_EQ(EVENT_CHROME_UPDATE, events[0]->type());
546 const base::DictionaryValue* value;
547 ASSERT_TRUE(events[0]->data()->GetAsDictionary(&value));
549 std::string previous_version;
550 std::string current_version;
552 ASSERT_TRUE(value->GetString("previousVersion", &previous_version));
553 ASSERT_EQ(kOldVersion, previous_version);
554 ASSERT_TRUE(value->GetString("currentVersion", &current_version));
555 ASSERT_EQ(version_string, current_version);
558 // crbug.com/160502
559 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest,
560 DISABLED_GatherStatistics) {
561 GatherStatistics();
563 // No stats should be recorded for this CPUUsage because this was the first
564 // call to GatherStatistics.
565 Database::MetricVector stats = GetStats(METRIC_CPU_USAGE);
566 ASSERT_EQ(0u, stats.size());
568 stats = GetStats(METRIC_PRIVATE_MEMORY_USAGE);
569 ASSERT_EQ(1u, stats.size());
570 EXPECT_GT(stats[0].value, 0);
572 stats = GetStats(METRIC_SHARED_MEMORY_USAGE);
573 ASSERT_EQ(1u, stats.size());
574 EXPECT_GT(stats[0].value, 0);
576 // Open new tabs to incur CPU usage.
577 for (int i = 0; i < 10; ++i) {
578 chrome::NavigateParams params(
579 browser(), ui_test_utils::GetTestUrl(
580 base::FilePath(base::FilePath::kCurrentDirectory),
581 base::FilePath(FILE_PATH_LITERAL("title1.html"))),
582 content::PAGE_TRANSITION_LINK);
583 params.disposition = NEW_BACKGROUND_TAB;
584 ui_test_utils::NavigateToURL(&params);
586 GatherStatistics();
588 // One CPUUsage stat should exist now.
589 stats = GetStats(METRIC_CPU_USAGE);
590 ASSERT_EQ(1u, stats.size());
591 EXPECT_GT(stats[0].value, 0);
593 stats = GetStats(METRIC_PRIVATE_MEMORY_USAGE);
594 ASSERT_EQ(2u, stats.size());
595 EXPECT_GT(stats[1].value, 0);
597 stats = GetStats(METRIC_SHARED_MEMORY_USAGE);
598 ASSERT_EQ(2u, stats.size());
599 EXPECT_GT(stats[1].value, 0);
602 // Disabled on other platforms because of flakiness: http://crbug.com/159172.
603 #if !defined(OS_WIN)
604 // Disabled on Windows due to a bug where Windows will return a normal exit
605 // code in the testing environment, even if the process died (this is not the
606 // case when hand-testing). This code can be traced to MSDN functions in
607 // base::GetTerminationStatus(), so there's not much we can do.
608 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest,
609 DISABLED_RendererKilledEvent) {
610 content::CrashTab(browser()->tab_strip_model()->GetActiveWebContents());
612 Database::EventVector events = GetEvents();
614 ASSERT_EQ(1u, events.size());
615 CheckEventType(EVENT_RENDERER_KILLED, events[0]);
617 // Check the url - since we never went anywhere, this should be about:blank.
618 std::string url;
619 ASSERT_TRUE(events[0]->data()->GetString("url", &url));
620 ASSERT_EQ("about:blank", url);
622 #endif // !defined(OS_WIN)
624 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, RendererCrashEvent) {
625 content::RenderProcessHostWatcher observer(
626 browser()->tab_strip_model()->GetActiveWebContents(),
627 content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
629 ui_test_utils::NavigateToURL(browser(), GURL(content::kChromeUICrashURL));
631 observer.Wait();
633 Database::EventVector events = GetEvents();
634 ASSERT_EQ(1u, events.size());
636 CheckEventType(EVENT_RENDERER_CRASH, events[0]);
638 std::string url;
639 ASSERT_TRUE(events[0]->data()->GetString("url", &url));
640 ASSERT_EQ("chrome://crash/", url);
643 IN_PROC_BROWSER_TEST_F(PerformanceMonitorUncleanExitBrowserTest,
644 OneProfileUncleanExit) {
645 // Initialize the database value (if there's no value in the database, it
646 // can't determine the last active time of the profile, and doesn't insert
647 // the event).
648 const std::string time = "12985807272597591";
649 AddStateValue(kStateProfilePrefix + first_profile_name_, time);
651 performance_monitor()->CheckForUncleanExits();
652 content::RunAllPendingInMessageLoop();
654 Database::EventVector events = GetEvents();
656 const size_t kNumEvents = 1;
657 ASSERT_EQ(kNumEvents, events.size());
659 CheckEventType(EVENT_UNCLEAN_EXIT, events[0]);
661 std::string event_profile;
662 ASSERT_TRUE(events[0]->data()->GetString("profileName", &event_profile));
663 ASSERT_EQ(first_profile_name_, event_profile);
666 IN_PROC_BROWSER_TEST_F(PerformanceMonitorUncleanExitBrowserTest,
667 TwoProfileUncleanExit) {
668 base::FilePath second_profile_path;
669 PathService::Get(chrome::DIR_USER_DATA, &second_profile_path);
670 second_profile_path = second_profile_path.AppendASCII(second_profile_name_);
672 const std::string time1 = "12985807272597591";
673 const std::string time2 = "12985807272599918";
675 // Initialize the database.
676 AddStateValue(kStateProfilePrefix + first_profile_name_, time1);
677 AddStateValue(kStateProfilePrefix + second_profile_name_, time2);
679 performance_monitor()->CheckForUncleanExits();
680 content::RunAllPendingInMessageLoop();
682 // Load the second profile, which has also exited uncleanly. Note that since
683 // the second profile is new, component extensions will be installed as part
684 // of the browser startup for that profile, generating extra events.
685 g_browser_process->profile_manager()->GetProfile(second_profile_path);
686 content::RunAllPendingInMessageLoop();
688 Database::EventVector events = GetEvents();
690 const size_t kNumUncleanExitEvents = 2;
691 size_t num_unclean_exit_events = 0;
692 for (size_t i = 0; i < events.size(); ++i) {
693 int event_type = -1;
694 if (events[i]->data()->GetInteger("eventType", &event_type) &&
695 event_type == EVENT_EXTENSION_INSTALL) {
696 continue;
698 CheckEventType(EVENT_UNCLEAN_EXIT, events[i]);
699 ++num_unclean_exit_events;
701 ASSERT_EQ(kNumUncleanExitEvents, num_unclean_exit_events);
703 std::string event_profile;
704 ASSERT_TRUE(events[0]->data()->GetString("profileName", &event_profile));
705 ASSERT_EQ(first_profile_name_, event_profile);
707 ASSERT_TRUE(events[1]->data()->GetString("profileName", &event_profile));
708 ASSERT_EQ(second_profile_name_, event_profile);
711 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, StartupTime) {
712 Database::MetricVector metrics = GetStats(METRIC_TEST_STARTUP_TIME);
714 ASSERT_EQ(1u, metrics.size());
715 ASSERT_LT(metrics[0].value, kMaxStartupTime.ToInternalValue());
718 IN_PROC_BROWSER_TEST_F(PerformanceMonitorSessionRestoreBrowserTest,
719 StartupWithSessionRestore) {
720 ui_test_utils::NavigateToURL(
721 browser(), ui_test_utils::GetTestUrl(
722 base::FilePath(base::FilePath::kCurrentDirectory),
723 base::FilePath(FILE_PATH_LITERAL("title1.html"))));
725 QuitBrowserAndRestore(browser(), 1);
727 Database::MetricVector metrics = GetStats(METRIC_TEST_STARTUP_TIME);
728 ASSERT_EQ(1u, metrics.size());
729 ASSERT_LT(metrics[0].value, kMaxStartupTime.ToInternalValue());
731 metrics = GetStats(METRIC_SESSION_RESTORE_TIME);
732 ASSERT_EQ(1u, metrics.size());
733 ASSERT_LT(metrics[0].value, kMaxStartupTime.ToInternalValue());
736 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, PageLoadTime) {
737 const base::TimeDelta kMaxLoadTime = base::TimeDelta::FromSeconds(30);
739 ui_test_utils::NavigateToURL(
740 browser(), ui_test_utils::GetTestUrl(
741 base::FilePath(base::FilePath::kCurrentDirectory),
742 base::FilePath(FILE_PATH_LITERAL("title1.html"))));
744 ui_test_utils::NavigateToURL(
745 browser(), ui_test_utils::GetTestUrl(
746 base::FilePath(base::FilePath::kCurrentDirectory),
747 base::FilePath(FILE_PATH_LITERAL("title1.html"))));
749 Database::MetricVector metrics = GetStats(METRIC_PAGE_LOAD_TIME);
751 ASSERT_EQ(2u, metrics.size());
752 ASSERT_LT(metrics[0].value, kMaxLoadTime.ToInternalValue());
753 ASSERT_LT(metrics[1].value, kMaxLoadTime.ToInternalValue());
756 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, NetworkBytesRead) {
757 base::FilePath test_dir;
758 PathService::Get(chrome::DIR_TEST_DATA, &test_dir);
760 int64 page1_size = 0;
761 ASSERT_TRUE(base::GetFileSize(test_dir.AppendASCII("title1.html"),
762 &page1_size));
764 int64 page2_size = 0;
765 ASSERT_TRUE(base::GetFileSize(test_dir.AppendASCII("title2.html"),
766 &page2_size));
768 ASSERT_TRUE(test_server()->Start());
770 ui_test_utils::NavigateToURL(
771 browser(),
772 test_server()->GetURL(std::string("files/").append("title1.html")));
774 GatherStatistics();
776 Database::MetricVector metrics = GetStats(METRIC_NETWORK_BYTES_READ);
777 ASSERT_EQ(1u, metrics.size());
778 // Since these pages are read over the "network" (actually the test_server),
779 // some extraneous information is carried along, and the best check we can do
780 // is for greater than or equal to.
781 EXPECT_GE(metrics[0].value, page1_size);
783 ui_test_utils::NavigateToURL(
784 browser(),
785 test_server()->GetURL(std::string("files/").append("title2.html")));
787 GatherStatistics();
789 metrics = GetStats(METRIC_NETWORK_BYTES_READ);
790 ASSERT_EQ(2u, metrics.size());
791 EXPECT_GE(metrics[1].value, page1_size + page2_size);
794 } // namespace performance_monitor