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/browser/extension_registry.h"
44 #include "extensions/browser/extension_system.h"
45 #include "extensions/common/extension.h"
47 #if defined(OS_CHROMEOS)
48 #include "chrome/browser/chromeos/profiles/profile_helper.h"
49 #include "chromeos/chromeos_switches.h"
50 #include "components/user_manager/user_manager.h"
53 #if defined(OS_MACOSX)
54 #include "base/mac/scoped_nsautorelease_pool.h"
57 using extensions::Extension;
59 namespace performance_monitor {
63 const base::TimeDelta kMaxStartupTime = base::TimeDelta::FromMinutes(3);
65 #if defined(OS_CHROMEOS)
66 // User account email and directory hash for secondary account for multi-profile
67 // sensitive test cases.
68 const char kSecondProfileAccount[] = "profile2@test.com";
69 const char kSecondProfileHash[] = "profile2";
72 // Helper struct to store the information of an extension; this is needed if the
73 // pointer to the extension ever becomes invalid (e.g., if we uninstall the
75 struct ExtensionBasicInfo {
76 // Empty constructor for stl-container-happiness.
77 ExtensionBasicInfo() {
79 explicit ExtensionBasicInfo(const Extension* extension)
80 : description(extension->description()),
82 name(extension->name()),
83 url(extension->url().spec()),
84 version(extension->VersionString()),
85 location(extension->location()) {
88 std::string description;
93 extensions::Manifest::Location location;
96 // Compare the fields of |extension| to those in |value|; this is a check to
97 // make sure the extension data was recorded properly in the event.
98 void ValidateExtensionInfo(const ExtensionBasicInfo extension,
99 const base::DictionaryValue* value) {
100 std::string extension_description;
101 std::string extension_id;
102 std::string extension_name;
103 std::string extension_url;
104 std::string extension_version;
105 int extension_location;
107 ASSERT_TRUE(value->GetString("extensionDescription",
108 &extension_description));
109 ASSERT_EQ(extension.description, extension_description);
110 ASSERT_TRUE(value->GetString("extensionId", &extension_id));
111 ASSERT_EQ(extension.id, extension_id);
112 ASSERT_TRUE(value->GetString("extensionName", &extension_name));
113 ASSERT_EQ(extension.name, extension_name);
114 ASSERT_TRUE(value->GetString("extensionUrl", &extension_url));
115 ASSERT_EQ(extension.url, extension_url);
116 ASSERT_TRUE(value->GetString("extensionVersion", &extension_version));
117 ASSERT_EQ(extension.version, extension_version);
118 ASSERT_TRUE(value->GetInteger("extensionLocation", &extension_location));
119 ASSERT_EQ(extension.location, extension_location);
122 // Verify that a particular event has the proper type.
123 void CheckEventType(int expected_event_type, const linked_ptr<Event>& event) {
125 ASSERT_TRUE(event->data()->GetInteger("eventType", &event_type));
126 ASSERT_EQ(expected_event_type, event_type);
127 ASSERT_EQ(expected_event_type, event->type());
130 // Verify that we received the proper number of events, checking the type of
132 void CheckEventTypes(const std::vector<int>& expected_event_types,
133 const Database::EventVector& events) {
134 ASSERT_EQ(expected_event_types.size(), events.size());
136 for (size_t i = 0; i < expected_event_types.size(); ++i)
137 CheckEventType(expected_event_types[i], events[i]);
140 // Check that we received the proper number of events, that each event is of the
141 // proper type, and that each event recorded the proper information about the
143 void CheckExtensionEvents(
144 const std::vector<int>& expected_event_types,
145 const Database::EventVector& events,
146 const std::vector<ExtensionBasicInfo>& extension_infos) {
147 CheckEventTypes(expected_event_types, events);
149 for (size_t i = 0; i < expected_event_types.size(); ++i) {
150 ValidateExtensionInfo(extension_infos[i], events[i]->data());
152 ASSERT_TRUE(events[i]->data()->GetInteger("eventType", &event_type));
153 ASSERT_EQ(expected_event_types[i], event_type);
159 class PerformanceMonitorBrowserTest : public ExtensionBrowserTest {
161 virtual void SetUpOnMainThread() OVERRIDE {
162 CHECK(db_dir_.CreateUniqueTempDir());
163 performance_monitor_ = PerformanceMonitor::GetInstance();
164 performance_monitor_->SetDatabasePath(db_dir_.path());
166 // PerformanceMonitor's initialization process involves a significant
167 // amount of thread-hopping between the UI thread and the background thread.
168 // If we begin the tests prior to full initialization, we cannot predict
169 // the behavior or mock synchronicity as we must. Wait for initialization
170 // to complete fully before proceeding with the test.
171 content::WindowedNotificationObserver windowed_observer(
172 chrome::NOTIFICATION_PERFORMANCE_MONITOR_INITIALIZED,
173 content::NotificationService::AllSources());
175 // We stop the timer in charge of doing timed collections so that we can
176 // enforce when, and how many times, we do these collections.
177 performance_monitor_->disable_timer_autostart_for_testing_ = true;
178 // Force metrics to be stored, regardless of switches used.
179 performance_monitor_->database_logging_enabled_ = true;
180 performance_monitor_->Initialize();
182 windowed_observer.Wait();
185 // A handle for gathering statistics from the database, which must be done on
186 // the background thread. Since we are testing, we can mock synchronicity with
187 // FlushForTesting().
188 void GatherStatistics() {
189 performance_monitor_->next_collection_time_ = base::Time::Now();
190 performance_monitor_->GatherMetricsMapOnUIThread();
192 RunAllPendingInMessageLoop(content::BrowserThread::IO);
193 content::BrowserThread::GetBlockingPool()->FlushForTesting();
196 void GetEventsOnBackgroundThread(Database::EventVector* events) {
197 // base::Time is potentially flaky in that there is no guarantee that it
198 // won't actually decrease between successive calls. If we call GetEvents
199 // and the Database uses base::Time::Now() and gets a lesser time, then it
200 // will return 0 events. Thus, we use a time that is guaranteed to be in the
201 // future (for at least the next couple hundred thousand years).
202 *events = performance_monitor_->database()->GetEvents(
203 base::Time(), base::Time::FromInternalValue(kint64max));
206 // A handle for getting the events from the database, which must be done on
207 // the background thread. Since we are testing, we can mock synchronicity
208 // with FlushForTesting().
209 Database::EventVector GetEvents() {
210 // Ensure that any event insertions happen prior to getting events in order
211 // to avoid race conditions.
212 content::BrowserThread::GetBlockingPool()->FlushForTesting();
213 content::RunAllPendingInMessageLoop();
215 Database::EventVector events;
216 content::BrowserThread::PostBlockingPoolSequencedTask(
217 Database::kDatabaseSequenceToken,
219 base::Bind(&PerformanceMonitorBrowserTest::GetEventsOnBackgroundThread,
220 base::Unretained(this),
223 content::BrowserThread::GetBlockingPool()->FlushForTesting();
227 void GetStatsOnBackgroundThread(Database::MetricVector* metrics,
229 *metrics = *performance_monitor_->database()->GetStatsForActivityAndMetric(
230 type, base::Time(), base::Time::FromInternalValue(kint64max));
233 // A handle for getting statistics from the database (see previous comments on
234 // GetEvents() and GetEventsOnBackgroundThread).
235 Database::MetricVector GetStats(MetricType type) {
236 content::BrowserThread::GetBlockingPool()->FlushForTesting();
237 content::RunAllPendingInMessageLoop();
239 Database::MetricVector metrics;
240 content::BrowserThread::PostBlockingPoolSequencedTask(
241 Database::kDatabaseSequenceToken,
243 base::Bind(&PerformanceMonitorBrowserTest::GetStatsOnBackgroundThread,
244 base::Unretained(this),
248 content::BrowserThread::GetBlockingPool()->FlushForTesting();
252 // A handle for inserting a state value into the database, which must be done
253 // on the background thread. This is useful for mocking up a scenario in which
254 // the database has prior data stored. We mock synchronicity with
255 // FlushForTesting().
256 void AddStateValue(const std::string& key, const std::string& value) {
257 content::BrowserThread::PostBlockingPoolSequencedTask(
258 Database::kDatabaseSequenceToken,
260 base::Bind(base::IgnoreResult(&Database::AddStateValue),
261 base::Unretained(performance_monitor()->database()),
265 content::BrowserThread::GetBlockingPool()->FlushForTesting();
268 // A handle for PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread();
269 // we mock synchronicity with FlushForTesting().
270 void CheckForVersionUpdate() {
271 content::BrowserThread::PostBlockingPoolSequencedTask(
272 Database::kDatabaseSequenceToken,
274 base::Bind(&PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread,
275 base::Unretained(performance_monitor())));
277 content::BrowserThread::GetBlockingPool()->FlushForTesting();
280 PerformanceMonitor* performance_monitor() const {
281 return performance_monitor_;
285 base::ScopedTempDir db_dir_;
286 PerformanceMonitor* performance_monitor_;
289 class PerformanceMonitorUncleanExitBrowserTest
290 : public PerformanceMonitorBrowserTest,
291 public testing::WithParamInterface<bool> {
293 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
294 PerformanceMonitorBrowserTest::SetUpCommandLine(command_line);
295 #if defined(OS_CHROMEOS)
296 command_line->AppendSwitch(
297 chromeos::switches::kIgnoreUserProfileMappingForTests);
301 virtual bool SetUpUserDataDirectory() OVERRIDE {
302 base::FilePath user_data_directory;
303 PathService::Get(chrome::DIR_USER_DATA, &user_data_directory);
305 // On CrOS, if we are "logged in" with the --login-profile switch,
306 // the default profile will be different. We check if we are logged in, and,
307 // if we are, we use that profile name instead. (Note: trybots will
308 // typically be logged in with 'user'.)
309 #if defined(OS_CHROMEOS)
310 const CommandLine command_line = *CommandLine::ForCurrentProcess();
311 if (command_line.HasSwitch(chromeos::switches::kLoginProfile)) {
312 first_profile_name_ =
313 command_line.GetSwitchValueASCII(chromeos::switches::kLoginProfile);
315 first_profile_name_ = chrome::kInitialProfile;
318 first_profile_name_ = chrome::kInitialProfile;
321 base::FilePath first_profile =
322 user_data_directory.AppendASCII(first_profile_name_);
323 CHECK(base::CreateDirectory(first_profile));
325 base::FilePath stock_prefs_file;
326 PathService::Get(chrome::DIR_TEST_DATA, &stock_prefs_file);
327 stock_prefs_file = stock_prefs_file.AppendASCII("performance_monitor")
328 .AppendASCII("unclean_exit_prefs");
329 CHECK(base::PathExists(stock_prefs_file));
331 base::FilePath first_profile_prefs_file =
332 first_profile.Append(chrome::kPreferencesFilename);
333 CHECK(base::CopyFile(stock_prefs_file, first_profile_prefs_file));
334 CHECK(base::PathExists(first_profile_prefs_file));
336 second_profile_name_ =
337 std::string(chrome::kMultiProfileDirPrefix)
338 .append(base::IntToString(1));
339 #if defined(OS_CHROMEOS)
341 second_profile_name_ = chromeos::ProfileHelper::GetUserProfileDir(
342 kSecondProfileHash).BaseName().value();
346 base::FilePath second_profile =
347 user_data_directory.AppendASCII(second_profile_name_);
348 CHECK(base::CreateDirectory(second_profile));
350 base::FilePath second_profile_prefs_file =
351 second_profile.Append(chrome::kPreferencesFilename);
352 CHECK(base::CopyFile(stock_prefs_file, second_profile_prefs_file));
353 CHECK(base::PathExists(second_profile_prefs_file));
358 #if defined(OS_CHROMEOS)
359 virtual void AddSecondUserAccount() {
360 // Add second user account for multi-profile test.
362 user_manager::UserManager::Get()->UserLoggedIn(
363 kSecondProfileAccount, kSecondProfileHash, false);
369 std::string first_profile_name_;
370 std::string second_profile_name_;
373 class PerformanceMonitorSessionRestoreBrowserTest
374 : public PerformanceMonitorBrowserTest {
376 virtual void SetUpOnMainThread() OVERRIDE {
377 SessionStartupPref pref(SessionStartupPref::LAST);
378 SessionStartupPref::SetStartupPref(browser()->profile(), pref);
379 #if defined(OS_CHROMEOS) || defined (OS_MACOSX)
380 // Undo the effect of kBrowserAliveWithNoWindows in defaults.cc so that we
381 // can get these test to work without quitting.
382 SessionServiceTestHelper helper(
383 SessionServiceFactory::GetForProfile(browser()->profile()));
384 helper.SetForceBrowserNotAliveWithNoWindows(true);
385 helper.ReleaseService();
388 PerformanceMonitorBrowserTest::SetUpOnMainThread();
391 Browser* QuitBrowserAndRestore(Browser* browser, int expected_tab_count) {
392 Profile* profile = browser->profile();
394 // Close the browser.
395 g_browser_process->AddRefModule();
396 content::WindowedNotificationObserver observer(
397 chrome::NOTIFICATION_BROWSER_CLOSED,
398 content::NotificationService::AllSources());
399 browser->window()->Close();
400 #if defined(OS_MACOSX)
401 // BrowserWindowController depends on the auto release pool being recycled
402 // in the message loop to delete itself, which frees the Browser object
403 // which fires this event.
404 AutoreleasePool()->Recycle();
408 // Create a new window, which should trigger session restore.
409 content::TestNavigationObserver restore_observer(NULL, expected_tab_count);
410 restore_observer.StartWatchingNewWebContents();
411 ui_test_utils::BrowserAddedObserver window_observer;
412 chrome::NewEmptyWindow(profile, chrome::GetActiveDesktop());
413 Browser* new_browser = window_observer.WaitForSingleNewBrowser();
414 restore_observer.Wait();
415 g_browser_process->ReleaseModule();
421 // Test that PerformanceMonitor will correctly record an extension installation
423 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, InstallExtensionEvent) {
424 base::FilePath extension_path;
425 PathService::Get(chrome::DIR_TEST_DATA, &extension_path);
426 extension_path = extension_path.AppendASCII("performance_monitor")
427 .AppendASCII("extensions")
428 .AppendASCII("simple_extension_v1");
429 const Extension* extension = LoadExtension(extension_path);
431 std::vector<ExtensionBasicInfo> extension_infos;
432 extension_infos.push_back(ExtensionBasicInfo(extension));
434 std::vector<int> expected_event_types;
435 expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
437 Database::EventVector events = GetEvents();
438 CheckExtensionEvents(expected_event_types, events, extension_infos);
441 // Test that PerformanceMonitor will correctly record events as an extension is
442 // disabled and enabled.
443 // Test is falky, see http://crbug.com/157980
444 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest,
445 DISABLED_DisableAndEnableExtensionEvent) {
446 const int kNumEvents = 3;
448 base::FilePath extension_path;
449 PathService::Get(chrome::DIR_TEST_DATA, &extension_path);
450 extension_path = extension_path.AppendASCII("performance_monitor")
451 .AppendASCII("extensions")
452 .AppendASCII("simple_extension_v1");
453 const Extension* extension = LoadExtension(extension_path);
455 DisableExtension(extension->id());
456 EnableExtension(extension->id());
458 std::vector<ExtensionBasicInfo> extension_infos;
459 // There will be three events in all, each pertaining to the same extension:
463 for (int i = 0; i < kNumEvents; ++i)
464 extension_infos.push_back(ExtensionBasicInfo(extension));
466 std::vector<int> expected_event_types;
467 expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
468 expected_event_types.push_back(EVENT_EXTENSION_DISABLE);
469 expected_event_types.push_back(EVENT_EXTENSION_ENABLE);
471 Database::EventVector events = GetEvents();
472 CheckExtensionEvents(expected_event_types, events, extension_infos);
475 // Test that PerformanceMonitor correctly records an extension update event.
476 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, UpdateExtensionEvent) {
477 base::ScopedTempDir temp_dir;
478 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
480 base::FilePath test_data_dir;
481 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
482 test_data_dir = test_data_dir.AppendASCII("performance_monitor")
483 .AppendASCII("extensions");
485 // We need two versions of the same extension.
486 base::FilePath pem_path = test_data_dir.AppendASCII("simple_extension.pem");
487 base::FilePath path_v1_ = PackExtensionWithOptions(
488 test_data_dir.AppendASCII("simple_extension_v1"),
489 temp_dir.path().AppendASCII("simple_extension1.crx"),
492 base::FilePath path_v2_ = PackExtensionWithOptions(
493 test_data_dir.AppendASCII("simple_extension_v2"),
494 temp_dir.path().AppendASCII("simple_extension2.crx"),
498 const extensions::Extension* extension = InstallExtension(path_v1_, 1);
500 std::vector<ExtensionBasicInfo> extension_infos;
501 extension_infos.push_back(ExtensionBasicInfo(extension));
503 ExtensionService* extension_service = extensions::ExtensionSystem::Get(
504 browser()->profile())->extension_service();
506 extensions::CrxInstaller* crx_installer = NULL;
508 // Create an observer to wait for the update to finish.
509 content::WindowedNotificationObserver windowed_observer(
510 extensions::NOTIFICATION_CRX_INSTALLER_DONE,
511 content::Source<extensions::CrxInstaller>(crx_installer));
512 ASSERT_TRUE(extension_service->UpdateExtension(
513 extension->id(), path_v2_, true, &crx_installer));
514 windowed_observer.Wait();
516 extension = extensions::ExtensionRegistry::Get(
517 browser()->profile())->enabled_extensions().GetByID(
518 extension_infos[0].id);
520 // The total series of events for this process will be:
521 // Extension Install - install version 1
522 // Extension Install - install version 2
523 // Extension Update - signal the udate to version 2
524 // We push back the corresponding ExtensionBasicInfos.
525 extension_infos.push_back(ExtensionBasicInfo(extension));
526 extension_infos.push_back(extension_infos[1]);
528 std::vector<int> expected_event_types;
529 expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
530 expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
531 expected_event_types.push_back(EVENT_EXTENSION_UPDATE);
533 Database::EventVector events = GetEvents();
535 CheckExtensionEvents(expected_event_types, events, extension_infos);
538 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, UninstallExtensionEvent) {
539 const int kNumEvents = 2;
540 base::FilePath extension_path;
541 PathService::Get(chrome::DIR_TEST_DATA, &extension_path);
542 extension_path = extension_path.AppendASCII("performance_monitor")
543 .AppendASCII("extensions")
544 .AppendASCII("simple_extension_v1");
545 const Extension* extension = LoadExtension(extension_path);
547 std::vector<ExtensionBasicInfo> extension_infos;
548 // There will be two events, both pertaining to the same extension:
550 // Extension Uninstall
551 for (int i = 0; i < kNumEvents; ++i)
552 extension_infos.push_back(ExtensionBasicInfo(extension));
554 UninstallExtension(extension->id());
556 std::vector<int> expected_event_types;
557 expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
558 expected_event_types.push_back(EVENT_EXTENSION_UNINSTALL);
560 Database::EventVector events = GetEvents();
562 CheckExtensionEvents(expected_event_types, events, extension_infos);
565 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, NewVersionEvent) {
566 const char kOldVersion[] = "0.0";
568 // The version in the database right now will be the current version of chrome
569 // (gathered at initialization of PerformanceMonitor). Replace this with an
570 // older version so an event is generated.
571 AddStateValue(kStateChromeVersion, kOldVersion);
573 CheckForVersionUpdate();
575 chrome::VersionInfo version;
576 ASSERT_TRUE(version.is_valid());
577 std::string version_string = version.Version();
579 Database::EventVector events = GetEvents();
580 ASSERT_EQ(1u, events.size());
581 ASSERT_EQ(EVENT_CHROME_UPDATE, events[0]->type());
583 const base::DictionaryValue* value;
584 ASSERT_TRUE(events[0]->data()->GetAsDictionary(&value));
586 std::string previous_version;
587 std::string current_version;
589 ASSERT_TRUE(value->GetString("previousVersion", &previous_version));
590 ASSERT_EQ(kOldVersion, previous_version);
591 ASSERT_TRUE(value->GetString("currentVersion", ¤t_version));
592 ASSERT_EQ(version_string, current_version);
596 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest,
597 DISABLED_GatherStatistics) {
600 // No stats should be recorded for this CPUUsage because this was the first
601 // call to GatherStatistics.
602 Database::MetricVector stats = GetStats(METRIC_CPU_USAGE);
603 ASSERT_EQ(0u, stats.size());
605 stats = GetStats(METRIC_PRIVATE_MEMORY_USAGE);
606 ASSERT_EQ(1u, stats.size());
607 EXPECT_GT(stats[0].value, 0);
609 stats = GetStats(METRIC_SHARED_MEMORY_USAGE);
610 ASSERT_EQ(1u, stats.size());
611 EXPECT_GT(stats[0].value, 0);
613 // Open new tabs to incur CPU usage.
614 for (int i = 0; i < 10; ++i) {
615 chrome::NavigateParams params(
616 browser(), ui_test_utils::GetTestUrl(
617 base::FilePath(base::FilePath::kCurrentDirectory),
618 base::FilePath(FILE_PATH_LITERAL("title1.html"))),
619 content::PAGE_TRANSITION_LINK);
620 params.disposition = NEW_BACKGROUND_TAB;
621 ui_test_utils::NavigateToURL(¶ms);
625 // One CPUUsage stat should exist now.
626 stats = GetStats(METRIC_CPU_USAGE);
627 ASSERT_EQ(1u, stats.size());
628 EXPECT_GT(stats[0].value, 0);
630 stats = GetStats(METRIC_PRIVATE_MEMORY_USAGE);
631 ASSERT_EQ(2u, stats.size());
632 EXPECT_GT(stats[1].value, 0);
634 stats = GetStats(METRIC_SHARED_MEMORY_USAGE);
635 ASSERT_EQ(2u, stats.size());
636 EXPECT_GT(stats[1].value, 0);
639 // Disabled on other platforms because of flakiness: http://crbug.com/159172.
641 // Disabled on Windows due to a bug where Windows will return a normal exit
642 // code in the testing environment, even if the process died (this is not the
643 // case when hand-testing). This code can be traced to MSDN functions in
644 // base::GetTerminationStatus(), so there's not much we can do.
645 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest,
646 DISABLED_RendererKilledEvent) {
647 content::CrashTab(browser()->tab_strip_model()->GetActiveWebContents());
649 Database::EventVector events = GetEvents();
651 ASSERT_EQ(1u, events.size());
652 CheckEventType(EVENT_RENDERER_KILLED, events[0]);
654 // Check the url - since we never went anywhere, this should be about:blank.
656 ASSERT_TRUE(events[0]->data()->GetString("url", &url));
657 ASSERT_EQ("about:blank", url);
659 #endif // !defined(OS_WIN)
661 // TODO(jam): http://crbug.com/350550
662 #if !(defined(OS_CHROMEOS) && defined(ADDRESS_SANITIZER))
663 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, RendererCrashEvent) {
664 content::RenderProcessHostWatcher observer(
665 browser()->tab_strip_model()->GetActiveWebContents(),
666 content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
668 ui_test_utils::NavigateToURL(browser(), GURL(content::kChromeUICrashURL));
672 Database::EventVector events = GetEvents();
673 ASSERT_EQ(1u, events.size());
675 CheckEventType(EVENT_RENDERER_CRASH, events[0]);
678 ASSERT_TRUE(events[0]->data()->GetString("url", &url));
679 ASSERT_EQ("chrome://crash/", url);
683 IN_PROC_BROWSER_TEST_P(PerformanceMonitorUncleanExitBrowserTest,
684 OneProfileUncleanExit) {
685 // Initialize the database value (if there's no value in the database, it
686 // can't determine the last active time of the profile, and doesn't insert
688 const std::string time = "12985807272597591";
689 AddStateValue(kStateProfilePrefix + first_profile_name_, time);
691 performance_monitor()->CheckForUncleanExits();
692 content::RunAllPendingInMessageLoop();
694 Database::EventVector events = GetEvents();
696 const size_t kNumEvents = 1;
697 ASSERT_EQ(kNumEvents, events.size());
699 CheckEventType(EVENT_UNCLEAN_EXIT, events[0]);
701 std::string event_profile;
702 ASSERT_TRUE(events[0]->data()->GetString("profileName", &event_profile));
703 ASSERT_EQ(first_profile_name_, event_profile);
706 IN_PROC_BROWSER_TEST_P(PerformanceMonitorUncleanExitBrowserTest,
707 TwoProfileUncleanExit) {
708 #if defined(OS_CHROMEOS)
709 AddSecondUserAccount();
712 base::FilePath second_profile_path;
713 PathService::Get(chrome::DIR_USER_DATA, &second_profile_path);
714 second_profile_path = second_profile_path.AppendASCII(second_profile_name_);
716 const std::string time1 = "12985807272597591";
717 const std::string time2 = "12985807272599918";
719 // Initialize the database.
720 AddStateValue(kStateProfilePrefix + first_profile_name_, time1);
721 AddStateValue(kStateProfilePrefix + second_profile_name_, time2);
723 performance_monitor()->CheckForUncleanExits();
724 content::RunAllPendingInMessageLoop();
726 // Load the second profile, which has also exited uncleanly. Note that since
727 // the second profile is new, component extensions will be installed as part
728 // of the browser startup for that profile, generating extra events.
729 g_browser_process->profile_manager()->GetProfile(second_profile_path);
730 content::RunAllPendingInMessageLoop();
732 Database::EventVector events = GetEvents();
734 const size_t kNumUncleanExitEvents = 2;
735 size_t num_unclean_exit_events = 0;
736 for (size_t i = 0; i < events.size(); ++i) {
738 if (events[i]->data()->GetInteger("eventType", &event_type) &&
739 event_type == EVENT_EXTENSION_INSTALL) {
742 CheckEventType(EVENT_UNCLEAN_EXIT, events[i]);
743 ++num_unclean_exit_events;
745 ASSERT_EQ(kNumUncleanExitEvents, num_unclean_exit_events);
747 std::string event_profile;
748 ASSERT_TRUE(events[0]->data()->GetString("profileName", &event_profile));
749 ASSERT_EQ(first_profile_name_, event_profile);
751 ASSERT_TRUE(events[1]->data()->GetString("profileName", &event_profile));
752 ASSERT_EQ(second_profile_name_, event_profile);
755 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, StartupTime) {
756 Database::MetricVector metrics = GetStats(METRIC_TEST_STARTUP_TIME);
758 ASSERT_EQ(1u, metrics.size());
759 ASSERT_LT(metrics[0].value, kMaxStartupTime.ToInternalValue());
762 IN_PROC_BROWSER_TEST_F(PerformanceMonitorSessionRestoreBrowserTest,
763 StartupWithSessionRestore) {
764 ui_test_utils::NavigateToURL(
765 browser(), ui_test_utils::GetTestUrl(
766 base::FilePath(base::FilePath::kCurrentDirectory),
767 base::FilePath(FILE_PATH_LITERAL("title1.html"))));
769 QuitBrowserAndRestore(browser(), 1);
771 Database::MetricVector metrics = GetStats(METRIC_TEST_STARTUP_TIME);
772 ASSERT_EQ(1u, metrics.size());
773 ASSERT_LT(metrics[0].value, kMaxStartupTime.ToInternalValue());
775 metrics = GetStats(METRIC_SESSION_RESTORE_TIME);
776 ASSERT_EQ(1u, metrics.size());
777 ASSERT_LT(metrics[0].value, kMaxStartupTime.ToInternalValue());
780 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, PageLoadTime) {
781 const base::TimeDelta kMaxLoadTime = base::TimeDelta::FromSeconds(30);
783 ui_test_utils::NavigateToURL(
784 browser(), ui_test_utils::GetTestUrl(
785 base::FilePath(base::FilePath::kCurrentDirectory),
786 base::FilePath(FILE_PATH_LITERAL("title1.html"))));
788 ui_test_utils::NavigateToURL(
789 browser(), ui_test_utils::GetTestUrl(
790 base::FilePath(base::FilePath::kCurrentDirectory),
791 base::FilePath(FILE_PATH_LITERAL("title1.html"))));
793 Database::MetricVector metrics = GetStats(METRIC_PAGE_LOAD_TIME);
795 ASSERT_EQ(2u, metrics.size());
796 ASSERT_LT(metrics[0].value, kMaxLoadTime.ToInternalValue());
797 ASSERT_LT(metrics[1].value, kMaxLoadTime.ToInternalValue());
800 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, NetworkBytesRead) {
801 base::FilePath test_dir;
802 PathService::Get(chrome::DIR_TEST_DATA, &test_dir);
804 int64 page1_size = 0;
805 ASSERT_TRUE(base::GetFileSize(test_dir.AppendASCII("title1.html"),
808 int64 page2_size = 0;
809 ASSERT_TRUE(base::GetFileSize(test_dir.AppendASCII("title2.html"),
812 ASSERT_TRUE(test_server()->Start());
814 ui_test_utils::NavigateToURL(
816 test_server()->GetURL(std::string("files/").append("title1.html")));
820 Database::MetricVector metrics = GetStats(METRIC_NETWORK_BYTES_READ);
821 ASSERT_EQ(1u, metrics.size());
822 // Since these pages are read over the "network" (actually the test_server),
823 // some extraneous information is carried along, and the best check we can do
824 // is for greater than or equal to.
825 EXPECT_GE(metrics[0].value, page1_size);
827 ui_test_utils::NavigateToURL(
829 test_server()->GetURL(std::string("files/").append("title2.html")));
833 metrics = GetStats(METRIC_NETWORK_BYTES_READ);
834 ASSERT_EQ(2u, metrics.size());
835 EXPECT_GE(metrics[1].value, page1_size + page2_size);
838 INSTANTIATE_TEST_CASE_P(PerformanceMonitorUncleanExitBrowserTestInstantiation,
839 PerformanceMonitorUncleanExitBrowserTest,
842 } // namespace performance_monitor