Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / tab_capture / tab_capture_performancetest.cc
1 // Copyright 2013 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/basictypes.h"
6 #include "base/command_line.h"
7 #if defined(OS_MACOSX)
8 #include "base/mac/mac_util.h"
9 #endif
10 #include "base/strings/stringprintf.h"
11 #include "base/test/trace_event_analyzer.h"
12 #include "base/win/windows_version.h"
13 #include "chrome/browser/extensions/extension_apitest.h"
14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/extensions/tab_helper.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
18 #include "chrome/common/chrome_switches.h"
19 #include "chrome/common/chrome_version_info.h"
20 #include "chrome/test/base/test_launcher_utils.h"
21 #include "chrome/test/base/test_switches.h"
22 #include "chrome/test/base/tracing.h"
23 #include "content/public/common/content_switches.h"
24 #include "extensions/common/feature_switch.h"
25 #include "extensions/common/features/base_feature_provider.h"
26 #include "extensions/common/features/complex_feature.h"
27 #include "extensions/common/features/feature.h"
28 #include "extensions/common/features/simple_feature.h"
29 #include "extensions/common/switches.h"
30 #include "extensions/test/extension_test_message_listener.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32 #include "testing/perf/perf_test.h"
33 #include "ui/compositor/compositor_switches.h"
34 #include "ui/gl/gl_switches.h"
35
36 namespace {
37
38 const char kExtensionId[] = "ddchlicdkolnonkihahngkmmmjnjlkkf";
39
40 enum TestFlags {
41   kUseGpu              = 1 << 0, // Only execute test if --enable-gpu was given
42                                  // on the command line.  This is required for
43                                  // tests that run on GPU.
44   kForceGpuComposited  = 1 << 1, // Force the test to use the compositor.
45   kDisableVsync        = 1 << 2, // Do not limit framerate to vertical refresh.
46                                  // when on GPU, nor to 60hz when not on GPU.
47   kTestThroughWebRTC   = 1 << 3, // Send captured frames through webrtc
48   kSmallWindow         = 1 << 4, // 1 = 800x600, 0 = 2000x1000
49
50   kScaleQualityMask    = 3 << 5, // two bits select which scaling quality
51   kScaleQualityDefault = 0 << 5, // to use on aura.
52   kScaleQualityFast    = 1 << 5,
53   kScaleQualityGood    = 2 << 5,
54   kScaleQualityBest    = 3 << 5,
55 };
56
57 class TabCapturePerformanceTest
58     : public ExtensionApiTest,
59       public testing::WithParamInterface<int> {
60  public:
61   TabCapturePerformanceTest() {}
62
63   bool HasFlag(TestFlags flag) const {
64     return (GetParam() & flag) == flag;
65   }
66
67   bool IsGpuAvailable() const {
68     return CommandLine::ForCurrentProcess()->HasSwitch("enable-gpu");
69   }
70
71   std::string ScalingMethod() const {
72     switch (GetParam() & kScaleQualityMask) {
73       case kScaleQualityFast:
74         return "fast";
75       case kScaleQualityGood:
76         return "good";
77       case kScaleQualityBest:
78         return "best";
79       default:
80         return "";
81     }
82   }
83
84   std::string GetSuffixForTestFlags() {
85     std::string suffix;
86     if (HasFlag(kForceGpuComposited))
87       suffix += "_comp";
88     if (HasFlag(kUseGpu))
89       suffix += "_gpu";
90     if (HasFlag(kDisableVsync))
91       suffix += "_novsync";
92     if (HasFlag(kTestThroughWebRTC))
93       suffix += "_webrtc";
94     if (!ScalingMethod().empty())
95       suffix += "_scale" + ScalingMethod();
96     if (HasFlag(kSmallWindow))
97       suffix += "_small";
98     return suffix;
99   }
100
101   void SetUp() override {
102     EnablePixelOutput();
103     ExtensionApiTest::SetUp();
104   }
105
106   void SetUpCommandLine(CommandLine* command_line) override {
107     if (!ScalingMethod().empty()) {
108       command_line->AppendSwitchASCII(switches::kTabCaptureUpscaleQuality,
109                                       ScalingMethod());
110       command_line->AppendSwitchASCII(switches::kTabCaptureDownscaleQuality,
111                                       ScalingMethod());
112     }
113
114     // Some of the tests may launch http requests through JSON or AJAX
115     // which causes a security error (cross domain request) when the page
116     // is loaded from the local file system ( file:// ). The following switch
117     // fixes that error.
118     command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);
119
120     if (HasFlag(kSmallWindow)) {
121       command_line->AppendSwitchASCII(switches::kWindowSize, "800,600");
122     } else {
123       command_line->AppendSwitchASCII(switches::kWindowSize, "2000,1500");
124     }
125
126     if (!HasFlag(kUseGpu))
127       command_line->AppendSwitch(switches::kDisableGpu);
128
129     if (HasFlag(kDisableVsync))
130       command_line->AppendSwitch(switches::kDisableGpuVsync);
131
132     command_line->AppendSwitchASCII(
133         extensions::switches::kWhitelistedExtensionID,
134         kExtensionId);
135     ExtensionApiTest::SetUpCommandLine(command_line);
136   }
137
138   bool PrintResults(trace_analyzer::TraceAnalyzer *analyzer,
139                     const std::string& test_name,
140                     const std::string& event_name,
141                     const std::string& unit) {
142     trace_analyzer::TraceEventVector events;
143     trace_analyzer::Query query =
144         trace_analyzer::Query::EventNameIs(event_name) &&
145         (trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_BEGIN) ||
146          trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_COMPLETE) ||
147          trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_BEGIN) ||
148          trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_FLOW_BEGIN) ||
149          trace_analyzer::Query::EventPhaseIs(TRACE_EVENT_PHASE_INSTANT));
150     analyzer->FindEvents(query, &events);
151     if (events.size() < 20) {
152       LOG(ERROR) << "Not enough events of type " << event_name << " found ("
153                  << events.size() << ").";
154       return false;
155     }
156
157     // Ignore some events for startup/setup/caching.
158     trace_analyzer::TraceEventVector rate_events(events.begin() + 3,
159                                                  events.end() - 3);
160     trace_analyzer::RateStats stats;
161     if (!GetRateStats(rate_events, &stats, NULL)) {
162       LOG(ERROR) << "GetRateStats failed";
163       return false;
164     }
165     double mean_ms = stats.mean_us / 1000.0;
166     double std_dev_ms = stats.standard_deviation_us / 1000.0;
167     std::string mean_and_error = base::StringPrintf("%f,%f", mean_ms,
168                                                     std_dev_ms);
169     perf_test::PrintResultMeanAndError(test_name,
170                                        GetSuffixForTestFlags(),
171                                        event_name,
172                                        mean_and_error,
173                                        unit,
174                                        true);
175     return true;
176   }
177
178   void RunTest(const std::string& test_name) {
179     if (HasFlag(kUseGpu) && !IsGpuAvailable()) {
180       LOG(WARNING) <<
181           "Test skipped: requires gpu. Pass --enable-gpu on the command "
182           "line if use of GPU is desired.";
183       return;
184     }
185
186     std::string json_events;
187     ASSERT_TRUE(tracing::BeginTracing("gpu,mirroring"));
188     std::string page = "performance.html";
189     page += HasFlag(kTestThroughWebRTC) ? "?WebRTC=1" : "?WebRTC=0";
190     // Ideally we'd like to run a higher capture rate when vsync is disabled,
191     // but libjingle currently doesn't allow that.
192     // page += HasFlag(kDisableVsync) ? "&fps=300" : "&fps=30";
193     page += "&fps=30";
194     ASSERT_TRUE(RunExtensionSubtest("tab_capture", page)) << message_;
195     ASSERT_TRUE(tracing::EndTracing(&json_events));
196     scoped_ptr<trace_analyzer::TraceAnalyzer> analyzer;
197     analyzer.reset(trace_analyzer::TraceAnalyzer::Create(json_events));
198
199     // The printed result will be the average time between frames in the
200     // browser window.
201     bool gpu_frames = PrintResults(
202         analyzer.get(),
203         test_name,
204         "RenderWidget::didCommitAndDrawCompositorFrame",
205         "ms");
206     EXPECT_TRUE(gpu_frames);
207
208     // This prints out the average time between capture events.
209     // As the capture frame rate is capped at 30fps, this score
210     // cannot get any better than (lower) 33.33 ms.
211     EXPECT_TRUE(PrintResults(analyzer.get(),
212                              test_name,
213                              "Capture",
214                              "ms"));
215   }
216 };
217
218 }  // namespace
219
220 IN_PROC_BROWSER_TEST_P(TabCapturePerformanceTest, Performance) {
221   RunTest("TabCapturePerformance");
222 }
223
224 // Note: First argument is optional and intentionally left blank.
225 // (it's a prefix for the generated test cases)
226 INSTANTIATE_TEST_CASE_P(
227     ,
228     TabCapturePerformanceTest,
229     testing::Values(
230         0,
231         kUseGpu | kForceGpuComposited,
232         kDisableVsync,
233         kDisableVsync | kUseGpu | kForceGpuComposited,
234         kTestThroughWebRTC,
235         kTestThroughWebRTC | kUseGpu | kForceGpuComposited,
236         kTestThroughWebRTC | kDisableVsync,
237         kTestThroughWebRTC | kDisableVsync | kUseGpu | kForceGpuComposited));
238
239 #if defined(USE_AURA)
240 // TODO(hubbe):
241 // These are temporary tests for the purpose of determining what the
242 // appropriate scaling quality is. Once that has been determined,
243 // these tests will be removed.
244
245 const int kScalingTestBase =
246     kTestThroughWebRTC | kDisableVsync | kUseGpu | kForceGpuComposited;
247
248 INSTANTIATE_TEST_CASE_P(
249     ScalingTests,
250     TabCapturePerformanceTest,
251     testing::Values(
252         kScalingTestBase | kScaleQualityFast,
253         kScalingTestBase | kScaleQualityGood,
254         kScalingTestBase | kScaleQualityBest,
255         kScalingTestBase | kScaleQualityFast | kSmallWindow,
256         kScalingTestBase | kScaleQualityGood | kSmallWindow,
257         kScalingTestBase | kScaleQualityBest | kSmallWindow));
258
259 #endif  // USE_AURA