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/login/users/user_manager.h"
49 #include "chrome/browser/chromeos/profiles/profile_helper.h"
50 #include "chromeos/chromeos_switches.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 chromeos::UserManager::Get()->UserLoggedIn(kSecondProfileAccount
,
370 std::string first_profile_name_
;
371 std::string second_profile_name_
;
374 class PerformanceMonitorSessionRestoreBrowserTest
375 : public PerformanceMonitorBrowserTest
{
377 virtual void SetUpOnMainThread() OVERRIDE
{
378 SessionStartupPref
pref(SessionStartupPref::LAST
);
379 SessionStartupPref::SetStartupPref(browser()->profile(), pref
);
380 #if defined(OS_CHROMEOS) || defined (OS_MACOSX)
381 // Undo the effect of kBrowserAliveWithNoWindows in defaults.cc so that we
382 // can get these test to work without quitting.
383 SessionServiceTestHelper
helper(
384 SessionServiceFactory::GetForProfile(browser()->profile()));
385 helper
.SetForceBrowserNotAliveWithNoWindows(true);
386 helper
.ReleaseService();
389 PerformanceMonitorBrowserTest::SetUpOnMainThread();
392 Browser
* QuitBrowserAndRestore(Browser
* browser
, int expected_tab_count
) {
393 Profile
* profile
= browser
->profile();
395 // Close the browser.
396 g_browser_process
->AddRefModule();
397 content::WindowedNotificationObserver
observer(
398 chrome::NOTIFICATION_BROWSER_CLOSED
,
399 content::NotificationService::AllSources());
400 browser
->window()->Close();
401 #if defined(OS_MACOSX)
402 // BrowserWindowController depends on the auto release pool being recycled
403 // in the message loop to delete itself, which frees the Browser object
404 // which fires this event.
405 AutoreleasePool()->Recycle();
409 // Create a new window, which should trigger session restore.
410 content::TestNavigationObserver
restore_observer(NULL
, expected_tab_count
);
411 restore_observer
.StartWatchingNewWebContents();
412 ui_test_utils::BrowserAddedObserver window_observer
;
413 chrome::NewEmptyWindow(profile
, chrome::GetActiveDesktop());
414 Browser
* new_browser
= window_observer
.WaitForSingleNewBrowser();
415 restore_observer
.Wait();
416 g_browser_process
->ReleaseModule();
422 // Test that PerformanceMonitor will correctly record an extension installation
424 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest
, InstallExtensionEvent
) {
425 base::FilePath extension_path
;
426 PathService::Get(chrome::DIR_TEST_DATA
, &extension_path
);
427 extension_path
= extension_path
.AppendASCII("performance_monitor")
428 .AppendASCII("extensions")
429 .AppendASCII("simple_extension_v1");
430 const Extension
* extension
= LoadExtension(extension_path
);
432 std::vector
<ExtensionBasicInfo
> extension_infos
;
433 extension_infos
.push_back(ExtensionBasicInfo(extension
));
435 std::vector
<int> expected_event_types
;
436 expected_event_types
.push_back(EVENT_EXTENSION_INSTALL
);
438 Database::EventVector events
= GetEvents();
439 CheckExtensionEvents(expected_event_types
, events
, extension_infos
);
442 // Test that PerformanceMonitor will correctly record events as an extension is
443 // disabled and enabled.
444 // Test is falky, see http://crbug.com/157980
445 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest
,
446 DISABLED_DisableAndEnableExtensionEvent
) {
447 const int kNumEvents
= 3;
449 base::FilePath extension_path
;
450 PathService::Get(chrome::DIR_TEST_DATA
, &extension_path
);
451 extension_path
= extension_path
.AppendASCII("performance_monitor")
452 .AppendASCII("extensions")
453 .AppendASCII("simple_extension_v1");
454 const Extension
* extension
= LoadExtension(extension_path
);
456 DisableExtension(extension
->id());
457 EnableExtension(extension
->id());
459 std::vector
<ExtensionBasicInfo
> extension_infos
;
460 // There will be three events in all, each pertaining to the same extension:
464 for (int i
= 0; i
< kNumEvents
; ++i
)
465 extension_infos
.push_back(ExtensionBasicInfo(extension
));
467 std::vector
<int> expected_event_types
;
468 expected_event_types
.push_back(EVENT_EXTENSION_INSTALL
);
469 expected_event_types
.push_back(EVENT_EXTENSION_DISABLE
);
470 expected_event_types
.push_back(EVENT_EXTENSION_ENABLE
);
472 Database::EventVector events
= GetEvents();
473 CheckExtensionEvents(expected_event_types
, events
, extension_infos
);
476 // Test that PerformanceMonitor correctly records an extension update event.
477 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest
, UpdateExtensionEvent
) {
478 base::ScopedTempDir temp_dir
;
479 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
481 base::FilePath test_data_dir
;
482 PathService::Get(chrome::DIR_TEST_DATA
, &test_data_dir
);
483 test_data_dir
= test_data_dir
.AppendASCII("performance_monitor")
484 .AppendASCII("extensions");
486 // We need two versions of the same extension.
487 base::FilePath pem_path
= test_data_dir
.AppendASCII("simple_extension.pem");
488 base::FilePath path_v1_
= PackExtensionWithOptions(
489 test_data_dir
.AppendASCII("simple_extension_v1"),
490 temp_dir
.path().AppendASCII("simple_extension1.crx"),
493 base::FilePath path_v2_
= PackExtensionWithOptions(
494 test_data_dir
.AppendASCII("simple_extension_v2"),
495 temp_dir
.path().AppendASCII("simple_extension2.crx"),
499 const extensions::Extension
* extension
= InstallExtension(path_v1_
, 1);
501 std::vector
<ExtensionBasicInfo
> extension_infos
;
502 extension_infos
.push_back(ExtensionBasicInfo(extension
));
504 ExtensionService
* extension_service
= extensions::ExtensionSystem::Get(
505 browser()->profile())->extension_service();
507 extensions::CrxInstaller
* crx_installer
= NULL
;
509 // Create an observer to wait for the update to finish.
510 content::WindowedNotificationObserver
windowed_observer(
511 chrome::NOTIFICATION_CRX_INSTALLER_DONE
,
512 content::Source
<extensions::CrxInstaller
>(crx_installer
));
513 ASSERT_TRUE(extension_service
->UpdateExtension(
514 extension
->id(), path_v2_
, true, &crx_installer
));
515 windowed_observer
.Wait();
517 extension
= extensions::ExtensionRegistry::Get(
518 browser()->profile())->enabled_extensions().GetByID(
519 extension_infos
[0].id
);
521 // The total series of events for this process will be:
522 // Extension Install - install version 1
523 // Extension Install - install version 2
524 // Extension Update - signal the udate to version 2
525 // We push back the corresponding ExtensionBasicInfos.
526 extension_infos
.push_back(ExtensionBasicInfo(extension
));
527 extension_infos
.push_back(extension_infos
[1]);
529 std::vector
<int> expected_event_types
;
530 expected_event_types
.push_back(EVENT_EXTENSION_INSTALL
);
531 expected_event_types
.push_back(EVENT_EXTENSION_INSTALL
);
532 expected_event_types
.push_back(EVENT_EXTENSION_UPDATE
);
534 Database::EventVector events
= GetEvents();
536 CheckExtensionEvents(expected_event_types
, events
, extension_infos
);
539 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest
, UninstallExtensionEvent
) {
540 const int kNumEvents
= 2;
541 base::FilePath extension_path
;
542 PathService::Get(chrome::DIR_TEST_DATA
, &extension_path
);
543 extension_path
= extension_path
.AppendASCII("performance_monitor")
544 .AppendASCII("extensions")
545 .AppendASCII("simple_extension_v1");
546 const Extension
* extension
= LoadExtension(extension_path
);
548 std::vector
<ExtensionBasicInfo
> extension_infos
;
549 // There will be two events, both pertaining to the same extension:
551 // Extension Uninstall
552 for (int i
= 0; i
< kNumEvents
; ++i
)
553 extension_infos
.push_back(ExtensionBasicInfo(extension
));
555 UninstallExtension(extension
->id());
557 std::vector
<int> expected_event_types
;
558 expected_event_types
.push_back(EVENT_EXTENSION_INSTALL
);
559 expected_event_types
.push_back(EVENT_EXTENSION_UNINSTALL
);
561 Database::EventVector events
= GetEvents();
563 CheckExtensionEvents(expected_event_types
, events
, extension_infos
);
566 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest
, NewVersionEvent
) {
567 const char kOldVersion
[] = "0.0";
569 // The version in the database right now will be the current version of chrome
570 // (gathered at initialization of PerformanceMonitor). Replace this with an
571 // older version so an event is generated.
572 AddStateValue(kStateChromeVersion
, kOldVersion
);
574 CheckForVersionUpdate();
576 chrome::VersionInfo version
;
577 ASSERT_TRUE(version
.is_valid());
578 std::string version_string
= version
.Version();
580 Database::EventVector events
= GetEvents();
581 ASSERT_EQ(1u, events
.size());
582 ASSERT_EQ(EVENT_CHROME_UPDATE
, events
[0]->type());
584 const base::DictionaryValue
* value
;
585 ASSERT_TRUE(events
[0]->data()->GetAsDictionary(&value
));
587 std::string previous_version
;
588 std::string current_version
;
590 ASSERT_TRUE(value
->GetString("previousVersion", &previous_version
));
591 ASSERT_EQ(kOldVersion
, previous_version
);
592 ASSERT_TRUE(value
->GetString("currentVersion", ¤t_version
));
593 ASSERT_EQ(version_string
, current_version
);
597 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest
,
598 DISABLED_GatherStatistics
) {
601 // No stats should be recorded for this CPUUsage because this was the first
602 // call to GatherStatistics.
603 Database::MetricVector stats
= GetStats(METRIC_CPU_USAGE
);
604 ASSERT_EQ(0u, stats
.size());
606 stats
= GetStats(METRIC_PRIVATE_MEMORY_USAGE
);
607 ASSERT_EQ(1u, stats
.size());
608 EXPECT_GT(stats
[0].value
, 0);
610 stats
= GetStats(METRIC_SHARED_MEMORY_USAGE
);
611 ASSERT_EQ(1u, stats
.size());
612 EXPECT_GT(stats
[0].value
, 0);
614 // Open new tabs to incur CPU usage.
615 for (int i
= 0; i
< 10; ++i
) {
616 chrome::NavigateParams
params(
617 browser(), ui_test_utils::GetTestUrl(
618 base::FilePath(base::FilePath::kCurrentDirectory
),
619 base::FilePath(FILE_PATH_LITERAL("title1.html"))),
620 content::PAGE_TRANSITION_LINK
);
621 params
.disposition
= NEW_BACKGROUND_TAB
;
622 ui_test_utils::NavigateToURL(¶ms
);
626 // One CPUUsage stat should exist now.
627 stats
= GetStats(METRIC_CPU_USAGE
);
628 ASSERT_EQ(1u, stats
.size());
629 EXPECT_GT(stats
[0].value
, 0);
631 stats
= GetStats(METRIC_PRIVATE_MEMORY_USAGE
);
632 ASSERT_EQ(2u, stats
.size());
633 EXPECT_GT(stats
[1].value
, 0);
635 stats
= GetStats(METRIC_SHARED_MEMORY_USAGE
);
636 ASSERT_EQ(2u, stats
.size());
637 EXPECT_GT(stats
[1].value
, 0);
640 // Disabled on other platforms because of flakiness: http://crbug.com/159172.
642 // Disabled on Windows due to a bug where Windows will return a normal exit
643 // code in the testing environment, even if the process died (this is not the
644 // case when hand-testing). This code can be traced to MSDN functions in
645 // base::GetTerminationStatus(), so there's not much we can do.
646 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest
,
647 DISABLED_RendererKilledEvent
) {
648 content::CrashTab(browser()->tab_strip_model()->GetActiveWebContents());
650 Database::EventVector events
= GetEvents();
652 ASSERT_EQ(1u, events
.size());
653 CheckEventType(EVENT_RENDERER_KILLED
, events
[0]);
655 // Check the url - since we never went anywhere, this should be about:blank.
657 ASSERT_TRUE(events
[0]->data()->GetString("url", &url
));
658 ASSERT_EQ("about:blank", url
);
660 #endif // !defined(OS_WIN)
662 // TODO(jam): http://crbug.com/350550
663 #if !(defined(OS_CHROMEOS) && defined(ADDRESS_SANITIZER))
664 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest
, RendererCrashEvent
) {
665 content::RenderProcessHostWatcher
observer(
666 browser()->tab_strip_model()->GetActiveWebContents(),
667 content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT
);
669 ui_test_utils::NavigateToURL(browser(), GURL(content::kChromeUICrashURL
));
673 Database::EventVector events
= GetEvents();
674 ASSERT_EQ(1u, events
.size());
676 CheckEventType(EVENT_RENDERER_CRASH
, events
[0]);
679 ASSERT_TRUE(events
[0]->data()->GetString("url", &url
));
680 ASSERT_EQ("chrome://crash/", url
);
684 IN_PROC_BROWSER_TEST_P(PerformanceMonitorUncleanExitBrowserTest
,
685 OneProfileUncleanExit
) {
686 // Initialize the database value (if there's no value in the database, it
687 // can't determine the last active time of the profile, and doesn't insert
689 const std::string time
= "12985807272597591";
690 AddStateValue(kStateProfilePrefix
+ first_profile_name_
, time
);
692 performance_monitor()->CheckForUncleanExits();
693 content::RunAllPendingInMessageLoop();
695 Database::EventVector events
= GetEvents();
697 const size_t kNumEvents
= 1;
698 ASSERT_EQ(kNumEvents
, events
.size());
700 CheckEventType(EVENT_UNCLEAN_EXIT
, events
[0]);
702 std::string event_profile
;
703 ASSERT_TRUE(events
[0]->data()->GetString("profileName", &event_profile
));
704 ASSERT_EQ(first_profile_name_
, event_profile
);
707 IN_PROC_BROWSER_TEST_P(PerformanceMonitorUncleanExitBrowserTest
,
708 TwoProfileUncleanExit
) {
709 #if defined(OS_CHROMEOS)
710 AddSecondUserAccount();
713 base::FilePath second_profile_path
;
714 PathService::Get(chrome::DIR_USER_DATA
, &second_profile_path
);
715 second_profile_path
= second_profile_path
.AppendASCII(second_profile_name_
);
717 const std::string time1
= "12985807272597591";
718 const std::string time2
= "12985807272599918";
720 // Initialize the database.
721 AddStateValue(kStateProfilePrefix
+ first_profile_name_
, time1
);
722 AddStateValue(kStateProfilePrefix
+ second_profile_name_
, time2
);
724 performance_monitor()->CheckForUncleanExits();
725 content::RunAllPendingInMessageLoop();
727 // Load the second profile, which has also exited uncleanly. Note that since
728 // the second profile is new, component extensions will be installed as part
729 // of the browser startup for that profile, generating extra events.
730 g_browser_process
->profile_manager()->GetProfile(second_profile_path
);
731 content::RunAllPendingInMessageLoop();
733 Database::EventVector events
= GetEvents();
735 const size_t kNumUncleanExitEvents
= 2;
736 size_t num_unclean_exit_events
= 0;
737 for (size_t i
= 0; i
< events
.size(); ++i
) {
739 if (events
[i
]->data()->GetInteger("eventType", &event_type
) &&
740 event_type
== EVENT_EXTENSION_INSTALL
) {
743 CheckEventType(EVENT_UNCLEAN_EXIT
, events
[i
]);
744 ++num_unclean_exit_events
;
746 ASSERT_EQ(kNumUncleanExitEvents
, num_unclean_exit_events
);
748 std::string event_profile
;
749 ASSERT_TRUE(events
[0]->data()->GetString("profileName", &event_profile
));
750 ASSERT_EQ(first_profile_name_
, event_profile
);
752 ASSERT_TRUE(events
[1]->data()->GetString("profileName", &event_profile
));
753 ASSERT_EQ(second_profile_name_
, event_profile
);
756 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest
, StartupTime
) {
757 Database::MetricVector metrics
= GetStats(METRIC_TEST_STARTUP_TIME
);
759 ASSERT_EQ(1u, metrics
.size());
760 ASSERT_LT(metrics
[0].value
, kMaxStartupTime
.ToInternalValue());
763 IN_PROC_BROWSER_TEST_F(PerformanceMonitorSessionRestoreBrowserTest
,
764 StartupWithSessionRestore
) {
765 ui_test_utils::NavigateToURL(
766 browser(), ui_test_utils::GetTestUrl(
767 base::FilePath(base::FilePath::kCurrentDirectory
),
768 base::FilePath(FILE_PATH_LITERAL("title1.html"))));
770 QuitBrowserAndRestore(browser(), 1);
772 Database::MetricVector metrics
= GetStats(METRIC_TEST_STARTUP_TIME
);
773 ASSERT_EQ(1u, metrics
.size());
774 ASSERT_LT(metrics
[0].value
, kMaxStartupTime
.ToInternalValue());
776 metrics
= GetStats(METRIC_SESSION_RESTORE_TIME
);
777 ASSERT_EQ(1u, metrics
.size());
778 ASSERT_LT(metrics
[0].value
, kMaxStartupTime
.ToInternalValue());
781 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest
, PageLoadTime
) {
782 const base::TimeDelta kMaxLoadTime
= base::TimeDelta::FromSeconds(30);
784 ui_test_utils::NavigateToURL(
785 browser(), ui_test_utils::GetTestUrl(
786 base::FilePath(base::FilePath::kCurrentDirectory
),
787 base::FilePath(FILE_PATH_LITERAL("title1.html"))));
789 ui_test_utils::NavigateToURL(
790 browser(), ui_test_utils::GetTestUrl(
791 base::FilePath(base::FilePath::kCurrentDirectory
),
792 base::FilePath(FILE_PATH_LITERAL("title1.html"))));
794 Database::MetricVector metrics
= GetStats(METRIC_PAGE_LOAD_TIME
);
796 ASSERT_EQ(2u, metrics
.size());
797 ASSERT_LT(metrics
[0].value
, kMaxLoadTime
.ToInternalValue());
798 ASSERT_LT(metrics
[1].value
, kMaxLoadTime
.ToInternalValue());
801 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest
, NetworkBytesRead
) {
802 base::FilePath test_dir
;
803 PathService::Get(chrome::DIR_TEST_DATA
, &test_dir
);
805 int64 page1_size
= 0;
806 ASSERT_TRUE(base::GetFileSize(test_dir
.AppendASCII("title1.html"),
809 int64 page2_size
= 0;
810 ASSERT_TRUE(base::GetFileSize(test_dir
.AppendASCII("title2.html"),
813 ASSERT_TRUE(test_server()->Start());
815 ui_test_utils::NavigateToURL(
817 test_server()->GetURL(std::string("files/").append("title1.html")));
821 Database::MetricVector metrics
= GetStats(METRIC_NETWORK_BYTES_READ
);
822 ASSERT_EQ(1u, metrics
.size());
823 // Since these pages are read over the "network" (actually the test_server),
824 // some extraneous information is carried along, and the best check we can do
825 // is for greater than or equal to.
826 EXPECT_GE(metrics
[0].value
, page1_size
);
828 ui_test_utils::NavigateToURL(
830 test_server()->GetURL(std::string("files/").append("title2.html")));
834 metrics
= GetStats(METRIC_NETWORK_BYTES_READ
);
835 ASSERT_EQ(2u, metrics
.size());
836 EXPECT_GE(metrics
[1].value
, page1_size
+ page2_size
);
839 INSTANTIATE_TEST_CASE_P(PerformanceMonitorUncleanExitBrowserTestInstantiation
,
840 PerformanceMonitorUncleanExitBrowserTest
,
843 } // namespace performance_monitor