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