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.
4
5#include "base/command_line.h"
6#include "base/files/file_util.h"
7#include "base/json/json_reader.h"
8#include "base/memory/scoped_ptr.h"
9#include "base/strings/string_split.h"
10#include "base/strings/stringprintf.h"
11#include "base/test/test_timeouts.h"
12#include "base/time/time.h"
13#include "chrome/browser/browser_process.h"
14#include "chrome/browser/media/webrtc_browsertest_base.h"
15#include "chrome/browser/media/webrtc_browsertest_common.h"
16#include "chrome/browser/media/webrtc_browsertest_perf.h"
17#include "chrome/browser/ui/browser.h"
18#include "chrome/browser/ui/browser_tabstrip.h"
19#include "chrome/browser/ui/tabs/tab_strip_model.h"
20#include "chrome/common/chrome_switches.h"
21#include "chrome/test/base/in_process_browser_test.h"
22#include "chrome/test/base/ui_test_utils.h"
23#include "content/public/test/browser_test_utils.h"
24#include "media/base/media_switches.h"
25#include "net/test/embedded_test_server/embedded_test_server.h"
26#include "testing/perf/perf_test.h"
27
28static const char kMainWebrtcTestHtmlPage[] =
29    "/webrtc/webrtc_jsep01_test.html";
30
31// Performance browsertest for WebRTC. This test is manual since it takes long
32// to execute and requires the reference files provided by the webrtc.DEPS
33// solution (which is only available on WebRTC internal bots).
34class WebRtcPerfBrowserTest : public WebRtcTestBase {
35 public:
36  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
37    DetectErrorsInJavaScript();  // Look for errors in our rather complex js.
38  }
39
40  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
41    // Ensure the infobar is enabled, since we expect that in this test.
42    EXPECT_FALSE(command_line->HasSwitch(switches::kUseFakeUIForMediaStream));
43
44    // Play a suitable, somewhat realistic video file.
45    base::FilePath input_video = test::GetReferenceFilesDir()
46        .Append(test::kReferenceFileName360p)
47        .AddExtension(test::kY4mFileExtension);
48    command_line->AppendSwitchPath(switches::kUseFileForFakeVideoCapture,
49                                   input_video);
50    command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
51  }
52
53  // Tries to extract data from peerConnectionDataStore in the webrtc-internals
54  // tab. The caller owns the parsed data. Returns NULL on failure.
55  base::DictionaryValue* GetWebrtcInternalsData(
56      content::WebContents* webrtc_internals_tab) {
57    std::string all_stats_json = ExecuteJavascript(
58        "window.domAutomationController.send("
59        "    JSON.stringify(peerConnectionDataStore));",
60        webrtc_internals_tab);
61
62    base::Value* parsed_json = base::JSONReader::Read(all_stats_json);
63    base::DictionaryValue* result;
64    if (parsed_json && parsed_json->GetAsDictionary(&result))
65      return result;
66
67    return NULL;
68  }
69
70  const base::DictionaryValue* GetDataOnFirstPeerConnection(
71      const base::DictionaryValue* all_data) {
72    base::DictionaryValue::Iterator iterator(*all_data);
73
74    const base::DictionaryValue* result;
75    if (!iterator.IsAtEnd() && iterator.value().GetAsDictionary(&result))
76      return result;
77
78    return NULL;
79  }
80};
81
82// This is manual for its long execution time.
83IN_PROC_BROWSER_TEST_F(WebRtcPerfBrowserTest,
84                       MANUAL_RunsAudioVideoCall60SecsAndLogsInternalMetrics) {
85  if (OnWinXp()) return;
86
87  ASSERT_TRUE(test::HasReferenceFilesInCheckout());
88  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
89
90  ASSERT_GE(TestTimeouts::action_max_timeout().InSeconds(), 100) <<
91      "This is a long-running test; you must specify "
92      "--ui-test-action-max-timeout to have a value of at least 100000.";
93
94  content::WebContents* left_tab =
95      OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage);
96  content::WebContents* right_tab =
97      OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage);
98
99  SetupPeerconnectionWithLocalStream(left_tab);
100  SetupPeerconnectionWithLocalStream(right_tab);
101
102  NegotiateCall(left_tab, right_tab);
103
104  StartDetectingVideo(left_tab, "remote-view");
105  StartDetectingVideo(right_tab, "remote-view");
106
107  WaitForVideoToPlay(left_tab);
108  WaitForVideoToPlay(right_tab);
109
110  // Let values stabilize, bandwidth ramp up, etc.
111  test::SleepInJavascript(left_tab, 60000);
112
113  // Start measurements.
114  chrome::AddTabAt(browser(), GURL(), -1, true);
115  ui_test_utils::NavigateToURL(browser(), GURL("chrome://webrtc-internals"));
116  content::WebContents* webrtc_internals_tab =
117      browser()->tab_strip_model()->GetActiveWebContents();
118
119  test::SleepInJavascript(left_tab, 10000);
120
121  scoped_ptr<base::DictionaryValue> all_data(
122      GetWebrtcInternalsData(webrtc_internals_tab));
123  ASSERT_TRUE(all_data.get() != NULL);
124
125  const base::DictionaryValue* first_pc_dict =
126      GetDataOnFirstPeerConnection(all_data.get());
127  ASSERT_TRUE(first_pc_dict != NULL);
128  test::PrintBweForVideoMetrics(*first_pc_dict);
129  test::PrintMetricsForAllStreams(*first_pc_dict);
130
131  HangUp(left_tab);
132  HangUp(right_tab);
133}
134