1 // Copyright 2014 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_util.h"
7 #include "base/json/json_reader.h"
8 #include "base/macros.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/string_split.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/test/test_timeouts.h"
13 #include "base/time/time.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/media/webrtc_browsertest_base.h"
16 #include "chrome/browser/media/webrtc_browsertest_common.h"
17 #include "chrome/browser/media/webrtc_browsertest_perf.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_tabstrip.h"
20 #include "chrome/browser/ui/tabs/tab_strip_model.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/test/base/in_process_browser_test.h"
23 #include "chrome/test/base/ui_test_utils.h"
24 #include "content/public/test/browser_test_utils.h"
25 #include "media/base/media_switches.h"
26 #include "net/test/embedded_test_server/embedded_test_server.h"
27 #include "testing/perf/perf_test.h"
29 static const char kMainWebrtcTestHtmlPage
[] =
30 "/webrtc/webrtc_jsep01_test.html";
32 // Performance browsertest for WebRTC. This test is manual since it takes long
33 // to execute and requires the reference files provided by the webrtc.DEPS
34 // solution (which is only available on WebRTC internal bots).
35 class WebRtcPerfBrowserTest
: public WebRtcTestBase
{
37 void SetUpInProcessBrowserTestFixture() override
{
38 DetectErrorsInJavaScript(); // Look for errors in our rather complex js.
41 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
42 // Ensure the infobar is enabled, since we expect that in this test.
43 EXPECT_FALSE(command_line
->HasSwitch(switches::kUseFakeUIForMediaStream
));
45 // Play a suitable, somewhat realistic video file.
46 base::FilePath input_video
= test::GetReferenceFilesDir()
47 .Append(test::kReferenceFileName360p
)
48 .AddExtension(test::kY4mFileExtension
);
49 command_line
->AppendSwitchPath(switches::kUseFileForFakeVideoCapture
,
51 command_line
->AppendSwitch(switches::kUseFakeDeviceForMediaStream
);
54 // Tries to extract data from peerConnectionDataStore in the webrtc-internals
55 // tab. The caller owns the parsed data. Returns NULL on failure.
56 base::DictionaryValue
* GetWebrtcInternalsData(
57 content::WebContents
* webrtc_internals_tab
) {
58 std::string all_stats_json
= ExecuteJavascript(
59 "window.domAutomationController.send("
60 " JSON.stringify(peerConnectionDataStore));",
61 webrtc_internals_tab
);
63 scoped_ptr
<base::Value
> parsed_json
=
64 base::JSONReader::Read(all_stats_json
);
65 base::DictionaryValue
* result
;
66 if (parsed_json
.get() && parsed_json
->GetAsDictionary(&result
)) {
67 ignore_result(parsed_json
.release());
74 const base::DictionaryValue
* GetDataOnPeerConnection(
75 const base::DictionaryValue
* all_data
,
76 int peer_connection_index
) {
77 base::DictionaryValue::Iterator
iterator(*all_data
);
79 for (int i
= 0; i
< peer_connection_index
&& !iterator
.IsAtEnd();
80 --peer_connection_index
) {
84 const base::DictionaryValue
* result
;
85 if (!iterator
.IsAtEnd() && iterator
.value().GetAsDictionary(&result
))
91 scoped_ptr
<base::DictionaryValue
> MeasureWebRtcInternalsData(
93 chrome::AddTabAt(browser(), GURL(), -1, true);
94 ui_test_utils::NavigateToURL(browser(), GURL("chrome://webrtc-internals"));
95 content::WebContents
* webrtc_internals_tab
=
96 browser()->tab_strip_model()->GetActiveWebContents();
98 test::SleepInJavascript(webrtc_internals_tab
, duration_msec
);
100 return scoped_ptr
<base::DictionaryValue
>(
101 GetWebrtcInternalsData(webrtc_internals_tab
));
105 // This is manual for its long execution time.
106 IN_PROC_BROWSER_TEST_F(WebRtcPerfBrowserTest
,
107 MANUAL_RunsAudioVideoCall60SecsAndLogsInternalMetrics
) {
108 if (OnWinXp()) return;
110 ASSERT_TRUE(test::HasReferenceFilesInCheckout());
111 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
113 ASSERT_GE(TestTimeouts::action_max_timeout().InSeconds(), 100) <<
114 "This is a long-running test; you must specify "
115 "--ui-test-action-max-timeout to have a value of at least 100000.";
117 content::WebContents
* left_tab
=
118 OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage
);
119 content::WebContents
* right_tab
=
120 OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage
);
122 SetupPeerconnectionWithLocalStream(left_tab
);
123 SetupPeerconnectionWithLocalStream(right_tab
);
125 NegotiateCall(left_tab
, right_tab
);
127 StartDetectingVideo(left_tab
, "remote-view");
128 StartDetectingVideo(right_tab
, "remote-view");
130 WaitForVideoToPlay(left_tab
);
131 WaitForVideoToPlay(right_tab
);
133 // Let values stabilize, bandwidth ramp up, etc.
134 test::SleepInJavascript(left_tab
, 60000);
136 // Start measurements.
137 scoped_ptr
<base::DictionaryValue
> all_data
=
138 MeasureWebRtcInternalsData(10000);
139 ASSERT_TRUE(all_data
.get() != NULL
);
141 const base::DictionaryValue
* first_pc_dict
=
142 GetDataOnPeerConnection(all_data
.get(), 0);
143 ASSERT_TRUE(first_pc_dict
!= NULL
);
144 test::PrintBweForVideoMetrics(*first_pc_dict
, "");
145 test::PrintMetricsForAllStreams(*first_pc_dict
, "");
151 IN_PROC_BROWSER_TEST_F(WebRtcPerfBrowserTest
,
152 MANUAL_RunsOneWayCall60SecsAndLogsInternalMetrics
) {
153 if (OnWinXp()) return;
155 ASSERT_TRUE(test::HasReferenceFilesInCheckout());
156 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
158 ASSERT_GE(TestTimeouts::action_max_timeout().InSeconds(), 100) <<
159 "This is a long-running test; you must specify "
160 "--ui-test-action-max-timeout to have a value of at least 100000.";
162 content::WebContents
* left_tab
=
163 OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage
);
164 content::WebContents
* right_tab
=
165 OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage
);
167 SetupPeerconnectionWithLocalStream(left_tab
);
168 SetupPeerconnectionWithoutLocalStream(right_tab
);
170 NegotiateCall(left_tab
, right_tab
);
172 // Remote video will only play in one tab since the call is one-way.
173 StartDetectingVideo(right_tab
, "remote-view");
174 WaitForVideoToPlay(right_tab
);
176 // Let values stabilize, bandwidth ramp up, etc.
177 test::SleepInJavascript(left_tab
, 60000);
179 scoped_ptr
<base::DictionaryValue
> all_data
=
180 MeasureWebRtcInternalsData(10000);
181 ASSERT_TRUE(all_data
.get() != NULL
);
183 // This assumes the sending peer connection is always listed first in the
184 // data store, and the receiving second.
185 const base::DictionaryValue
* first_pc_dict
=
186 GetDataOnPeerConnection(all_data
.get(), 0);
187 ASSERT_TRUE(first_pc_dict
!= NULL
);
188 test::PrintBweForVideoMetrics(*first_pc_dict
, "_sendonly");
189 test::PrintMetricsForAllStreams(*first_pc_dict
, "_sendonly");
191 const base::DictionaryValue
* second_pc_dict
=
192 GetDataOnPeerConnection(all_data
.get(), 1);
193 ASSERT_TRUE(second_pc_dict
!= NULL
);
194 test::PrintBweForVideoMetrics(*second_pc_dict
, "_recvonly");
195 test::PrintMetricsForAllStreams(*second_pc_dict
, "_recvonly");