#include "base/command_line.h"
#include "base/file_util.h"
#include "base/json/json_reader.h"
+#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/process/process_metrics.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
#include "base/time/time.h"
-#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/media/webrtc_browsertest_base.h"
#include "chrome/browser/media/webrtc_browsertest_common.h"
+#include "chrome/browser/media/webrtc_browsertest_perf.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
-#include "chrome/test/ui/ui_test.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/test/browser_test_utils.h"
+#include "media/base/media_switches.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/perf/perf_test.h"
+// For fine-grained suppression.
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
static const char kMainWebrtcTestHtmlPage[] =
"/webrtc/webrtc_jsep01_test.html";
-// Top-level integration test for WebRTC. Requires a real webcam and microphone
-// on the running system. This test is not meant to run in the main browser
-// test suite since normal tester machines do not have webcams.
-class WebrtcBrowserTest : public WebRtcTestBase {
+// Top-level integration test for WebRTC. The test methods here must run
+// sequentially since they use a server binary on the system (hence they are
+// tagged as MANUAL). In addition, they need the reference videos which require
+// the webrtc.DEPS solution, which is not generally available on Chromium bots.
+class WebRtcBrowserTest : public WebRtcTestBase,
+ public testing::WithParamInterface<bool> {
public:
+ WebRtcBrowserTest() {}
virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
- PeerConnectionServerRunner::KillAllPeerConnectionServersOnCurrentSystem();
+ DetectErrorsInJavaScript(); // Look for errors in our rather complex js.
}
virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
- // This test expects real device handling and requires a real webcam / audio
- // device; it will not work with fake devices.
- EXPECT_FALSE(command_line->HasSwitch(
- switches::kUseFakeDeviceForMediaStream));
- EXPECT_FALSE(command_line->HasSwitch(
- switches::kUseFakeUIForMediaStream));
-
- // The video playback will not work without a GPU, so force its use here.
- command_line->AppendSwitch(switches::kUseGpuInTests);
- }
-
- // Ensures we didn't get any errors asynchronously (e.g. while no javascript
- // call from this test was outstanding).
- void AssertNoAsynchronousErrors(content::WebContents* tab_contents) {
- EXPECT_EQ("ok-no-errors",
- ExecuteJavascript("getAnyTestFailures()", tab_contents));
- }
-
- void EstablishCall(content::WebContents* from_tab,
- content::WebContents* to_tab) {
- ConnectToPeerConnectionServer("peer 1", from_tab);
- ConnectToPeerConnectionServer("peer 2", to_tab);
-
- EXPECT_EQ("ok-peerconnection-created",
- ExecuteJavascript("preparePeerConnection()", from_tab));
- EXPECT_EQ("ok-added",
- ExecuteJavascript("addLocalStream()", from_tab));
- EXPECT_EQ("ok-negotiating",
- ExecuteJavascript("negotiateCall()", from_tab));
-
- // Ensure the call gets up on both sides.
- EXPECT_TRUE(PollingWaitUntil("getPeerConnectionReadyState()",
- "active", from_tab));
- EXPECT_TRUE(PollingWaitUntil("getPeerConnectionReadyState()",
- "active", to_tab));
-
- AssertNoAsynchronousErrors(from_tab);
- AssertNoAsynchronousErrors(to_tab);
- }
-
- void StartDetectingVideo(content::WebContents* tab_contents,
- const std::string& video_element) {
- std::string javascript = base::StringPrintf(
- "startDetection('%s', 'frame-buffer', 320, 240)",
- video_element.c_str());
- EXPECT_EQ("ok-started", ExecuteJavascript(javascript, tab_contents));
- }
-
- void WaitForVideoToPlay(content::WebContents* tab_contents) {
- EXPECT_TRUE(PollingWaitUntil("isVideoPlaying()", "video-playing",
- tab_contents));
- }
-
- void WaitForVideoToStopPlaying(content::WebContents* tab_contents) {
- EXPECT_TRUE(PollingWaitUntil("isVideoPlaying()", "video-not-playing",
- tab_contents));
- }
-
- void HangUp(content::WebContents* from_tab) {
- EXPECT_EQ("ok-call-hung-up", ExecuteJavascript("hangUp()", from_tab));
- }
-
- void WaitUntilHangupVerified(content::WebContents* tab_contents) {
- EXPECT_TRUE(PollingWaitUntil("getPeerConnectionReadyState()",
- "no-peer-connection", tab_contents));
- }
-
- std::string ToggleLocalVideoTrack(content::WebContents* tab_contents) {
- // Toggle the only video track in the page (e.g. video track 0).
- return ExecuteJavascript("toggleLocalStream("
- "function(local) { return local.getVideoTracks()[0]; }, "
- "'video');", tab_contents);
- }
-
- std::string ToggleRemoteVideoTrack(content::WebContents* tab_contents) {
- // Toggle the only video track in the page (e.g. video track 0).
- return ExecuteJavascript("toggleRemoteStream("
- "function(local) { return local.getVideoTracks()[0]; }, "
- "'video');", tab_contents);
+ // Ensure the infobar is enabled, since we expect that in this test.
+ EXPECT_FALSE(command_line->HasSwitch(switches::kUseFakeUIForMediaStream));
+
+ // Play a suitable, somewhat realistic video file.
+ base::FilePath input_video = test::GetReferenceFilesDir()
+ .Append(test::kReferenceFileName360p)
+ .AddExtension(test::kY4mFileExtension);
+ command_line->AppendSwitchPath(switches::kUseFileForFakeVideoCapture,
+ input_video);
+ command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
+
+ // Flag used by TestWebAudioMediaStream to force garbage collection.
+ command_line->AppendSwitchASCII(switches::kJavaScriptFlags, "--expose-gc");
+
+ bool enable_audio_track_processing = GetParam();
+ if (enable_audio_track_processing)
+ command_line->AppendSwitch(switches::kEnableAudioTrackProcessing);
}
void PrintProcessMetrics(base::ProcessMetrics* process_metrics,
}
}
- std::string GetWebrtcInternalsData(
+ // Tries to extract data from peerConnectionDataStore in the webrtc-internals
+ // tab. The caller owns the parsed data. Returns NULL on failure.
+ base::DictionaryValue* GetWebrtcInternalsData(
content::WebContents* webrtc_internals_tab) {
- return ExecuteJavascript(
+ std::string all_stats_json = ExecuteJavascript(
"window.domAutomationController.send("
" JSON.stringify(peerConnectionDataStore));",
webrtc_internals_tab);
- }
- void PrintInternalMetrics(const std::string& all_stats_json) {
base::Value* parsed_json = base::JSONReader::Read(all_stats_json);
- ASSERT_TRUE(parsed_json != NULL) <<
- "Received bad JSON from webrtc-internals!";
- const base::DictionaryValue* json_dict;
- ASSERT_TRUE(parsed_json->GetAsDictionary(&json_dict));
-
- base::DictionaryValue::Iterator iterator(*json_dict);
- ASSERT_FALSE(iterator.IsAtEnd()) << "Didn't capture data about any peer "
- "connections in webrtc-internals.";
-
- const base::DictionaryValue* first_pc_dict;
- ASSERT_TRUE(iterator.value().GetAsDictionary(&first_pc_dict));
-
- std::string value;
- ASSERT_TRUE(first_pc_dict->GetString(
- "stats.bweforvideo-googAvailableSendBandwidth.values", &value));
- perf_test::PrintResult("bwe_stats", "", "available_send_bw", value, "bytes",
- false);
- ASSERT_TRUE(first_pc_dict->GetString(
- "stats.bweforvideo-googAvailableReceiveBandwidth.values", &value));
- perf_test::PrintResult("bwe_stats", "", "available_recv_bw", value, "bytes",
- false);
- ASSERT_TRUE(first_pc_dict->GetString(
- "stats.bweforvideo-googTargetEncBitrate.values", &value));
- perf_test::PrintResult("bwe_stats", "", "target_enc_bitrate",
- value, "bytes", false);
- ASSERT_TRUE(first_pc_dict->GetString(
- "stats.bweforvideo-googActualEncBitrate.values", &value));
- perf_test::PrintResult("bwe_stats", "", "actual_enc_bitrate",
- value, "bytes", false);
- ASSERT_TRUE(first_pc_dict->GetString(
- "stats.bweforvideo-googTransmitBitrate.values", &value));
- perf_test::PrintResult("bwe_stats", "", "transmit_bitrate", value, "bytes",
- false);
+ base::DictionaryValue* result;
+ if (parsed_json && parsed_json->GetAsDictionary(&result))
+ return result;
+
+ return NULL;
}
- content::WebContents* OpenTestPageAndGetUserMediaInNewTab() {
- chrome::AddBlankTabAt(browser(), -1, true);
- ui_test_utils::NavigateToURL(
- browser(), embedded_test_server()->GetURL(kMainWebrtcTestHtmlPage));
- content::WebContents* left_tab =
- browser()->tab_strip_model()->GetActiveWebContents();
- GetUserMediaAndAccept(left_tab);
- return left_tab;
+ const base::DictionaryValue* GetDataOnFirstPeerConnection(
+ const base::DictionaryValue* all_data) {
+ base::DictionaryValue::Iterator iterator(*all_data);
+
+ const base::DictionaryValue* result;
+ if (!iterator.IsAtEnd() && iterator.value().GetAsDictionary(&result))
+ return result;
+
+ return NULL;
}
- PeerConnectionServerRunner peerconnection_server_;
+ bool OnWinXp() {
+#if defined(OS_WIN)
+ return base::win::GetVersion() <= base::win::VERSION_XP;
+#else
+ return false;
+#endif
+ }
};
-IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
+static const bool kRunTestsWithFlag[] = { false, true };
+INSTANTIATE_TEST_CASE_P(WebRtcBrowserTests,
+ WebRtcBrowserTest,
+ testing::ValuesIn(kRunTestsWithFlag));
+
+IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest,
MANUAL_RunsAudioVideoWebRTCCallInTwoTabs) {
+ if (OnWinXp()) return;
+
+ ASSERT_TRUE(test::HasReferenceFilesInCheckout());
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- ASSERT_TRUE(peerconnection_server_.Start());
- content::WebContents* left_tab = OpenTestPageAndGetUserMediaInNewTab();
- content::WebContents* right_tab = OpenTestPageAndGetUserMediaInNewTab();
+ content::WebContents* left_tab =
+ OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage);
+ content::WebContents* right_tab =
+ OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage);
+
+ SetupPeerconnectionWithLocalStream(left_tab);
+ SetupPeerconnectionWithLocalStream(right_tab);
- EstablishCall(left_tab, right_tab);
+ NegotiateCall(left_tab, right_tab);
StartDetectingVideo(left_tab, "remote-view");
StartDetectingVideo(right_tab, "remote-view");
WaitForVideoToPlay(right_tab);
HangUp(left_tab);
- WaitUntilHangupVerified(left_tab);
- WaitUntilHangupVerified(right_tab);
-
- AssertNoAsynchronousErrors(left_tab);
- AssertNoAsynchronousErrors(right_tab);
-
- ASSERT_TRUE(peerconnection_server_.Stop());
}
-IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest, MANUAL_CpuUsage15Seconds) {
+IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MANUAL_CpuUsage15Seconds) {
+ if (OnWinXp()) return;
+
+ ASSERT_TRUE(test::HasReferenceFilesInCheckout());
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- ASSERT_TRUE(peerconnection_server_.Start());
base::FilePath results_file;
- ASSERT_TRUE(file_util::CreateTemporaryFile(&results_file));
+ ASSERT_TRUE(base::CreateTemporaryFile(&results_file));
- content::WebContents* left_tab = OpenTestPageAndGetUserMediaInNewTab();
+ content::WebContents* left_tab =
+ OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage);
#if defined(OS_MACOSX)
// Don't measure renderer CPU on mac: requires a mach broker we don't have
// access to from the browser test.
scoped_ptr<base::ProcessMetrics> browser_process_metrics(
base::ProcessMetrics::CreateProcessMetrics(
- base::Process::Current().handle(), NULL));
+ base::Process::Current().handle(), NULL));
browser_process_metrics->GetCPUUsage();
#else
// Measure rendering CPU on platforms that support it.
browser_process_metrics->GetCPUUsage();
#endif
- content::WebContents* right_tab = OpenTestPageAndGetUserMediaInNewTab();
+ content::WebContents* right_tab =
+ OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage);
- EstablishCall(left_tab, right_tab);
+ SetupPeerconnectionWithLocalStream(left_tab);
+ SetupPeerconnectionWithLocalStream(right_tab);
- SleepInJavascript(left_tab, 15000);
+ NegotiateCall(left_tab, right_tab);
+
+ test::SleepInJavascript(left_tab, 15000);
HangUp(left_tab);
- WaitUntilHangupVerified(left_tab);
- WaitUntilHangupVerified(right_tab);
#if !defined(OS_MACOSX)
PrintProcessMetrics(renderer_process_metrics.get(), "_r");
#endif
PrintProcessMetrics(browser_process_metrics.get(), "_b");
-
- AssertNoAsynchronousErrors(left_tab);
- AssertNoAsynchronousErrors(right_tab);
-
- ASSERT_TRUE(peerconnection_server_.Stop());
}
-IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
- MANUAL_TestMediaStreamTrackEnableDisable) {
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- ASSERT_TRUE(peerconnection_server_.Start());
-
- content::WebContents* left_tab = OpenTestPageAndGetUserMediaInNewTab();
- content::WebContents* right_tab = OpenTestPageAndGetUserMediaInNewTab();
-
- EstablishCall(left_tab, right_tab);
-
- StartDetectingVideo(left_tab, "remote-view");
- StartDetectingVideo(right_tab, "remote-view");
-
- WaitForVideoToPlay(left_tab);
- WaitForVideoToPlay(right_tab);
-
- EXPECT_EQ("ok-video-toggled-to-false", ToggleLocalVideoTrack(left_tab));
+// This is manual for its long execution time.
+IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest,
+ MANUAL_RunsAudioVideoCall60SecsAndLogsInternalMetrics) {
+ if (OnWinXp()) return;
- WaitForVideoToStopPlaying(right_tab);
-
- EXPECT_EQ("ok-video-toggled-to-true", ToggleLocalVideoTrack(left_tab));
-
- WaitForVideoToPlay(right_tab);
-
- HangUp(left_tab);
- WaitUntilHangupVerified(left_tab);
- WaitUntilHangupVerified(right_tab);
+ ASSERT_TRUE(test::HasReferenceFilesInCheckout());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- AssertNoAsynchronousErrors(left_tab);
- AssertNoAsynchronousErrors(right_tab);
+ ASSERT_GE(TestTimeouts::action_max_timeout().InSeconds(), 100) <<
+ "This is a long-running test; you must specify "
+ "--ui-test-action-max-timeout to have a value of at least 100000.";
- ASSERT_TRUE(peerconnection_server_.Stop());
-}
+ content::WebContents* left_tab =
+ OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage);
+ content::WebContents* right_tab =
+ OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage);
-IN_PROC_BROWSER_TEST_F(WebrtcBrowserTest,
- MANUAL_RunsAudioVideoCall20SecsAndLogsInternalMetrics) {
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
- ASSERT_TRUE(peerconnection_server_.Start());
+ SetupPeerconnectionWithLocalStream(left_tab);
+ SetupPeerconnectionWithLocalStream(right_tab);
- content::WebContents* left_tab = OpenTestPageAndGetUserMediaInNewTab();
- content::WebContents* right_tab = OpenTestPageAndGetUserMediaInNewTab();
-
- EstablishCall(left_tab, right_tab);
+ NegotiateCall(left_tab, right_tab);
StartDetectingVideo(left_tab, "remote-view");
StartDetectingVideo(right_tab, "remote-view");
WaitForVideoToPlay(right_tab);
// Let values stabilize, bandwidth ramp up, etc.
- SleepInJavascript(left_tab, 10000);
+ test::SleepInJavascript(left_tab, 60000);
// Start measurements.
- chrome::AddBlankTabAt(browser(), -1, true);
+ chrome::AddTabAt(browser(), GURL(), -1, true);
ui_test_utils::NavigateToURL(browser(), GURL("chrome://webrtc-internals"));
content::WebContents* webrtc_internals_tab =
browser()->tab_strip_model()->GetActiveWebContents();
- SleepInJavascript(left_tab, 10000);
+ test::SleepInJavascript(left_tab, 10000);
+
+ scoped_ptr<base::DictionaryValue> all_data(
+ GetWebrtcInternalsData(webrtc_internals_tab));
+ ASSERT_TRUE(all_data.get() != NULL);
- std::string all_stats_json = GetWebrtcInternalsData(webrtc_internals_tab);
- PrintInternalMetrics(all_stats_json);
+ const base::DictionaryValue* first_pc_dict =
+ GetDataOnFirstPeerConnection(all_data.get());
+ ASSERT_TRUE(first_pc_dict != NULL);
+ test::PrintBweForVideoMetrics(*first_pc_dict);
+ test::PrintMetricsForAllStreams(*first_pc_dict);
HangUp(left_tab);
- WaitUntilHangupVerified(left_tab);
- WaitUntilHangupVerified(right_tab);
+}
+
+IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MANUAL_TestWebAudioMediaStream) {
+ if (OnWinXp()) return;
+
+ ASSERT_TRUE(test::HasReferenceFilesInCheckout());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ GURL url(embedded_test_server()->GetURL("/webrtc/webaudio_crash.html"));
+ ui_test_utils::NavigateToURL(browser(), url);
+ content::WebContents* tab =
+ browser()->tab_strip_model()->GetActiveWebContents();
- AssertNoAsynchronousErrors(left_tab);
- AssertNoAsynchronousErrors(right_tab);
+ // A sleep is necessary to be able to detect the crash.
+ test::SleepInJavascript(tab, 1000);
- ASSERT_TRUE(peerconnection_server_.Stop());
+ ASSERT_FALSE(tab->IsCrashed());
}