1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/environment.h"
6#include "base/file_util.h"
7#include "base/path_service.h"
8#include "base/strings/string_number_conversions.h"
9#include "base/strings/stringprintf.h"
10#include "base/sys_info.h"
11#include "base/time/time.h"
12#include "chrome/common/chrome_constants.h"
13#include "chrome/common/chrome_paths.h"
14#include "chrome/common/env_vars.h"
15#include "chrome/test/automation/automation_proxy.h"
16#include "chrome/test/base/ui_test_utils.h"
17#include "chrome/test/perf/perf_test.h"
18#include "chrome/test/ui/ui_perf_test.h"
19#include "net/base/net_util.h"
20#include "testing/perf/perf_test.h"
21
22using base::TimeDelta;
23
24namespace {
25
26class ShutdownTest : public UIPerfTest {
27 public:
28  ShutdownTest() {
29    show_window_ = true;
30  }
31  virtual void SetUp() {}
32  virtual void TearDown() {}
33
34  enum TestSize {
35    SIMPLE,  // Runs with no command line arguments (loads about:blank).
36    TWENTY_TABS,  // Opens 5 copies of 4 different test pages.
37  };
38
39  void SetUpTwentyTabs() {
40    int window_count;
41    ASSERT_TRUE(automation()->GetBrowserWindowCount(&window_count));
42    ASSERT_EQ(1, window_count);
43    scoped_refptr<BrowserProxy> browser_proxy(
44        automation()->GetBrowserWindow(0));
45    ASSERT_TRUE(browser_proxy.get());
46
47    const base::FilePath kFastShutdownDir(FILE_PATH_LITERAL("fast_shutdown"));
48    const base::FilePath kCurrentDir(base::FilePath::kCurrentDirectory);
49    const base::FilePath test_cases[] = {
50      ui_test_utils::GetTestFilePath(kFastShutdownDir,
51          base::FilePath(FILE_PATH_LITERAL("on_before_unloader.html"))),
52      ui_test_utils::GetTestFilePath(kCurrentDir,
53          base::FilePath(FILE_PATH_LITERAL("animated-gifs.html"))),
54      ui_test_utils::GetTestFilePath(kCurrentDir,
55          base::FilePath(FILE_PATH_LITERAL("french_page.html"))),
56      ui_test_utils::GetTestFilePath(kCurrentDir,
57          base::FilePath(FILE_PATH_LITERAL("setcookie.html"))),
58    };
59
60    for (size_t i = 0; i < arraysize(test_cases); i++) {
61      ASSERT_TRUE(base::PathExists(test_cases[i]));
62      for (size_t j = 0; j < 5; j++) {
63        ASSERT_TRUE(browser_proxy->AppendTab(
64            net::FilePathToFileURL(test_cases[i])));
65      }
66    }
67  }
68
69  void RunShutdownTest(const char* graph, const char* trace,
70                       bool important, TestSize test_size,
71                       ProxyLauncher::ShutdownType shutdown_type) {
72#if defined(NDEBUG)
73    const int kNumCyclesMax = 20;
74#else
75    // Debug builds are too slow and we can't run that many cycles in a
76    // reasonable amount of time.
77    const int kNumCyclesMax = 10;
78#endif
79    int numCycles = kNumCyclesMax;
80    scoped_ptr<base::Environment> env(base::Environment::Create());
81    std::string numCyclesEnv;
82    if (env->GetVar(env_vars::kStartupTestsNumCycles, &numCyclesEnv) &&
83        base::StringToInt(numCyclesEnv, &numCycles)) {
84      if (numCycles <= kNumCyclesMax) {
85        VLOG(1) << env_vars::kStartupTestsNumCycles
86                << " set in environment, so setting numCycles to " << numCycles;
87      } else {
88        VLOG(1) << env_vars::kStartupTestsNumCycles
89                << " is higher than the max, setting numCycles to "
90                << kNumCyclesMax;
91        numCycles = kNumCyclesMax;
92      }
93    }
94
95    TimeDelta timings[kNumCyclesMax];
96    for (int i = 0; i < numCycles; ++i) {
97      UITest::SetUp();
98      if (test_size == TWENTY_TABS) {
99        SetUpTwentyTabs();
100      }
101      set_shutdown_type(shutdown_type);
102      UITest::TearDown();
103      timings[i] = browser_quit_time();
104
105      if (i == 0) {
106        // Re-use the profile data after first run so that the noise from
107        // creating databases doesn't impact all the runs.
108        clear_profile_ = false;
109        // Clear template_user_data_ so we don't try to copy it over each time
110        // through.
111        set_template_user_data(base::FilePath());
112      }
113    }
114
115    std::string times;
116    for (int i = 0; i < numCycles; ++i)
117      base::StringAppendF(&times, "%.2f,", timings[i].InMillisecondsF());
118    perf_test::PrintResultList(
119        graph, std::string(), trace, times, "ms", important);
120  }
121};
122
123TEST_F(ShutdownTest, DISABLED_SimpleWindowClose) {
124  RunShutdownTest("shutdown", "simple-window-close",
125                  true, /* important */ SIMPLE, ProxyLauncher::WINDOW_CLOSE);
126}
127
128TEST_F(ShutdownTest, SimpleUserQuit) {
129  RunShutdownTest("shutdown", "simple-user-quit",
130                  true, /* important */ SIMPLE, ProxyLauncher::USER_QUIT);
131}
132
133TEST_F(ShutdownTest, SimpleSessionEnding) {
134  RunShutdownTest("shutdown", "simple-session-ending",
135                  true, /* important */ SIMPLE, ProxyLauncher::SESSION_ENDING);
136}
137
138// http://crbug.com/110471
139#if defined(OS_WIN) && !defined(NDEBUG)
140#define MAYBE_TwentyTabsWindowClose DISABLED_TwentyTabsWindowClose
141#define MAYBE_TwentyTabsUserQuit DISABLED_TwentyTabsUserQuit
142#else
143#define MAYBE_TwentyTabsWindowClose TwentyTabsWindowClose
144#define MAYBE_TwentyTabsUserQuit TwentyTabsUserQuit
145#endif
146
147TEST_F(ShutdownTest, MAYBE_TwentyTabsWindowClose) {
148  RunShutdownTest("shutdown", "twentytabs-window-close",
149                  true, /* important */ TWENTY_TABS,
150                  ProxyLauncher::WINDOW_CLOSE);
151}
152
153TEST_F(ShutdownTest, MAYBE_TwentyTabsUserQuit) {
154  RunShutdownTest("shutdown", "twentytabs-user-quit",
155                  true, /* important */ TWENTY_TABS, ProxyLauncher::USER_QUIT);
156}
157
158// http://crbug.com/40671
159#if defined(OS_WIN) && !defined(NDEBUG)
160#define MAYBE_TwentyTabsSessionEnding DISABLED_TwentyTabsSessionEnding
161#else
162#define MAYBE_TwentyTabsSessionEnding TwentyTabsSessionEnding
163#endif
164
165TEST_F(ShutdownTest, MAYBE_TwentyTabsSessionEnding) {
166  RunShutdownTest("shutdown", "twentytabs-session-ending",
167                  true, /* important */ TWENTY_TABS,
168                  ProxyLauncher::SESSION_ENDING);
169}
170
171}  // namespace
172