Split WebRTC browser tests in getusermedia and peerconnection tests.
The content browsertests file for WebRTC was growing a bit large. I
extracted the getUserMedia-focused tests into a test of its own and
left the peerconnection tests.
Also renamed all WebRTC content browsertests to use the WebRtc naming
convention, which seems to be the most common in the production code.
Note: this patch will require some filter renames on the WebRTC bots.
[email protected]
Review URL: https://codereview.chromium.org/131203005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@245524 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/browser/media/webrtc_getusermedia_browsertest.cc b/content/browser/media/webrtc_getusermedia_browsertest.cc
new file mode 100644
index 0000000..8ab99c3
--- /dev/null
+++ b/content/browser/media/webrtc_getusermedia_browsertest.cc
@@ -0,0 +1,427 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/debug/trace_event_impl.h"
+#include "base/json/json_reader.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/trace_event_analyzer.h"
+#include "base/values.h"
+#include "content/browser/media/webrtc_internals.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils.h"
+#include "content/test/webrtc_content_browsertest_base.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/perf/perf_test.h"
+
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
+using trace_analyzer::TraceAnalyzer;
+using trace_analyzer::Query;
+using trace_analyzer::TraceEventVector;
+
+namespace {
+
+static const char kGetUserMediaAndStop[] = "getUserMediaAndStop";
+static const char kGetUserMediaAndWaitAndStop[] = "getUserMediaAndWaitAndStop";
+static const char kGetUserMediaAndAnalyseAndStop[] =
+ "getUserMediaAndAnalyseAndStop";
+
+// Results returned by JS.
+static const char kOK[] = "OK";
+static const char kGetUserMediaFailed[] =
+ "GetUserMedia call failed with code undefined";
+
+std::string GenerateGetUserMediaWithMandatorySourceID(
+ const std::string& function_name,
+ const std::string& audio_source_id,
+ const std::string& video_source_id) {
+ const std::string audio_constraint =
+ "audio: {mandatory: { sourceId:\"" + audio_source_id + "\"}}, ";
+
+ const std::string video_constraint =
+ "video: {mandatory: { sourceId:\"" + video_source_id + "\"}}";
+ return function_name + "({" + audio_constraint + video_constraint + "});";
+}
+
+std::string GenerateGetUserMediaWithOptionalSourceID(
+ const std::string& function_name,
+ const std::string& audio_source_id,
+ const std::string& video_source_id) {
+ const std::string audio_constraint =
+ "audio: {optional: [{sourceId:\"" + audio_source_id + "\"}]}, ";
+
+ const std::string video_constraint =
+ "video: {optional: [{ sourceId:\"" + video_source_id + "\"}]}";
+ return function_name + "({" + audio_constraint + video_constraint + "});";
+}
+
+} // namespace
+
+namespace content {
+
+class WebRtcGetUserMediaBrowserTest: public WebRtcContentBrowserTest {
+ public:
+ WebRtcGetUserMediaBrowserTest() : trace_log_(NULL) {}
+ virtual ~WebRtcGetUserMediaBrowserTest() {}
+
+ void StartTracing() {
+ CHECK(trace_log_ == NULL) << "Can only can start tracing once";
+ trace_log_ = base::debug::TraceLog::GetInstance();
+ trace_log_->SetEnabled(base::debug::CategoryFilter("video"),
+ base::debug::TraceLog::RECORDING_MODE,
+ base::debug::TraceLog::ENABLE_SAMPLING);
+ // Check that we are indeed recording.
+ EXPECT_EQ(trace_log_->GetNumTracesRecorded(), 1);
+ }
+
+ void StopTracing() {
+ CHECK(message_loop_runner_ == NULL) << "Calling StopTracing more than once";
+ trace_log_->SetDisabled();
+ message_loop_runner_ = new MessageLoopRunner;
+ trace_log_->Flush(base::Bind(
+ &WebRtcGetUserMediaBrowserTest::OnTraceDataCollected,
+ base::Unretained(this)));
+ message_loop_runner_->Run();
+ }
+
+ void OnTraceDataCollected(
+ const scoped_refptr<base::RefCountedString>& events_str_ptr,
+ bool has_more_events) {
+ CHECK(!has_more_events);
+ recorded_trace_data_ = events_str_ptr;
+ message_loop_runner_->Quit();
+ }
+
+ TraceAnalyzer* CreateTraceAnalyzer() {
+ return TraceAnalyzer::Create("[" + recorded_trace_data_->data() + "]");
+ }
+
+ void GetSources(std::vector<std::string>* audio_ids,
+ std::vector<std::string>* video_ids) {
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ NavigateToURL(shell(), url);
+
+ std::string sources_as_json = ExecuteJavascriptAndReturnResult(
+ "getSources()");
+ EXPECT_FALSE(sources_as_json.empty());
+
+ int error_code;
+ std::string error_message;
+ scoped_ptr<base::Value> value(
+ base::JSONReader::ReadAndReturnError(sources_as_json,
+ base::JSON_ALLOW_TRAILING_COMMAS,
+ &error_code,
+ &error_message));
+
+ ASSERT_TRUE(value.get() != NULL) << error_message;
+ EXPECT_EQ(value->GetType(), base::Value::TYPE_LIST);
+
+ base::ListValue* values;
+ ASSERT_TRUE(value->GetAsList(&values));
+
+ for (base::ListValue::iterator it = values->begin();
+ it != values->end(); ++it) {
+ const base::DictionaryValue* dict;
+ std::string kind;
+ std::string id;
+ ASSERT_TRUE((*it)->GetAsDictionary(&dict));
+ ASSERT_TRUE(dict->GetString("kind", &kind));
+ ASSERT_TRUE(dict->GetString("id", &id));
+ ASSERT_FALSE(id.empty());
+ EXPECT_TRUE(kind == "audio" || kind == "video");
+ if (kind == "audio") {
+ audio_ids->push_back(id);
+ } else if (kind == "video") {
+ video_ids->push_back(id);
+ }
+ }
+ ASSERT_FALSE(audio_ids->empty());
+ ASSERT_FALSE(video_ids->empty());
+ }
+
+ private:
+ base::debug::TraceLog* trace_log_;
+ scoped_refptr<base::RefCountedString> recorded_trace_data_;
+ scoped_refptr<MessageLoopRunner> message_loop_runner_;
+};
+
+// These tests will all make a getUserMedia call with different constraints and
+// see that the success callback is called. If the error callback is called or
+// none of the callbacks are called the tests will simply time out and fail.
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, GetVideoStreamAndStop) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ NavigateToURL(shell(), url);
+
+ ASSERT_TRUE(ExecuteJavascript(
+ base::StringPrintf("%s({video: true});", kGetUserMediaAndStop)));
+
+ ExpectTitle("OK");
+}
+
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+ GetAudioAndVideoStreamAndStop) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ NavigateToURL(shell(), url);
+
+ ASSERT_TRUE(ExecuteJavascript(base::StringPrintf(
+ "%s({video: true, audio: true});", kGetUserMediaAndStop)));
+
+ ExpectTitle("OK");
+}
+
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+ GetAudioAndVideoStreamAndClone) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ NavigateToURL(shell(), url);
+
+ ASSERT_TRUE(ExecuteJavascript("getUserMediaAndClone();"));
+
+ ExpectTitle("OK");
+}
+
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+ GetUserMediaWithMandatorySourceID) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ std::vector<std::string> audio_ids;
+ std::vector<std::string> video_ids;
+ GetSources(&audio_ids, &video_ids);
+
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+
+ // Test all combinations of mandatory sourceID;
+ for (std::vector<std::string>::const_iterator video_it = video_ids.begin();
+ video_it != video_ids.end(); ++video_it) {
+ for (std::vector<std::string>::const_iterator audio_it = audio_ids.begin();
+ audio_it != audio_ids.end(); ++audio_it) {
+ NavigateToURL(shell(), url);
+ EXPECT_EQ(kOK, ExecuteJavascriptAndReturnResult(
+ GenerateGetUserMediaWithMandatorySourceID(
+ kGetUserMediaAndStop,
+ *audio_it,
+ *video_it)));
+ }
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+ GetUserMediaWithInvalidMandatorySourceID) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ std::vector<std::string> audio_ids;
+ std::vector<std::string> video_ids;
+ GetSources(&audio_ids, &video_ids);
+
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+
+ // Test with invalid mandatory audio sourceID.
+ NavigateToURL(shell(), url);
+ EXPECT_EQ(kGetUserMediaFailed, ExecuteJavascriptAndReturnResult(
+ GenerateGetUserMediaWithMandatorySourceID(
+ kGetUserMediaAndStop,
+ "something invalid",
+ video_ids[0])));
+
+ // Test with invalid mandatory video sourceID.
+ EXPECT_EQ(kGetUserMediaFailed, ExecuteJavascriptAndReturnResult(
+ GenerateGetUserMediaWithMandatorySourceID(
+ kGetUserMediaAndStop,
+ audio_ids[0],
+ "something invalid")));
+
+ // Test with empty mandatory audio sourceID.
+ EXPECT_EQ(kGetUserMediaFailed, ExecuteJavascriptAndReturnResult(
+ GenerateGetUserMediaWithMandatorySourceID(
+ kGetUserMediaAndStop,
+ "",
+ video_ids[0])));
+}
+
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+ GetUserMediaWithInvalidOptionalSourceID) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ std::vector<std::string> audio_ids;
+ std::vector<std::string> video_ids;
+ GetSources(&audio_ids, &video_ids);
+
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+
+ // Test with invalid optional audio sourceID.
+ NavigateToURL(shell(), url);
+ EXPECT_EQ(kOK, ExecuteJavascriptAndReturnResult(
+ GenerateGetUserMediaWithOptionalSourceID(
+ kGetUserMediaAndStop,
+ "something invalid",
+ video_ids[0])));
+
+ // Test with invalid optional video sourceID.
+ EXPECT_EQ(kOK, ExecuteJavascriptAndReturnResult(
+ GenerateGetUserMediaWithOptionalSourceID(
+ kGetUserMediaAndStop,
+ audio_ids[0],
+ "something invalid")));
+
+ // Test with empty optional audio sourceID.
+ EXPECT_EQ(kOK, ExecuteJavascriptAndReturnResult(
+ GenerateGetUserMediaWithOptionalSourceID(
+ kGetUserMediaAndStop,
+ "",
+ video_ids[0])));
+}
+
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, TwoGetUserMediaAndStop) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ NavigateToURL(shell(), url);
+
+ ASSERT_TRUE(ExecuteJavascript(
+ "twoGetUserMediaAndStop({video: true, audio: true});"));
+
+ ExpectTitle("OK");
+}
+
+// This test will make a simple getUserMedia page, verify that video is playing
+// in a simple local <video>, and for a couple of seconds, collect some
+// performance traces.
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+ TracePerformanceDuringGetUserMedia) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ NavigateToURL(shell(), url);
+ // Put getUserMedia to work and let it run for a couple of seconds.
+ ASSERT_TRUE(ExecuteJavascript(base::StringPrintf(
+ "%s({video: true}, 10);", kGetUserMediaAndWaitAndStop)));
+
+ // Make sure the stream is up and running, then start collecting traces.
+ ExpectTitle("Running...");
+ StartTracing();
+
+ // Wait until the page title changes to "OK". Do not sleep() here since that
+ // would stop both this code and the browser underneath.
+ ExpectTitle("OK");
+ StopTracing();
+
+ scoped_ptr<TraceAnalyzer> analyzer(CreateTraceAnalyzer());
+ analyzer->AssociateBeginEndEvents();
+ trace_analyzer::TraceEventVector events;
+ analyzer->FindEvents(
+ Query::EventNameIs("VideoCaptureController::OnIncomingCapturedFrame"),
+ &events);
+ ASSERT_GT(events.size(), 0u)
+ << "Could not collect any samples during test, this is bad";
+
+ std::string duration_us;
+ std::string interarrival_us;
+ for (size_t i = 0; i != events.size(); ++i) {
+ duration_us.append(
+ base::StringPrintf("%d,", static_cast<int>(events[i]->duration)));
+ }
+
+ for (size_t i = 1; i < events.size(); ++i) {
+ interarrival_us.append(base::StringPrintf(
+ "%d,",
+ static_cast<int>(events[i]->timestamp - events[i - 1]->timestamp)));
+ }
+
+ perf_test::PrintResultList(
+ "video_capture", "", "sample_duration", duration_us, "us", true);
+
+ perf_test::PrintResultList(
+ "video_capture", "", "interarrival_time", interarrival_us, "us", true);
+}
+
+// This test calls getUserMedia and checks for aspect ratio behavior.
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+ TestGetUserMediaAspectRatio) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+
+ std::string constraints_4_3 = GenerateGetUserMediaCall(
+ kGetUserMediaAndAnalyseAndStop, 640, 640, 480, 480, 30, 30);
+ std::string constraints_16_9 = GenerateGetUserMediaCall(
+ kGetUserMediaAndAnalyseAndStop, 640, 640, 360, 360, 30, 30);
+
+ // TODO(mcasas): add more aspect ratios, in particular 16:10 crbug.com/275594.
+
+ NavigateToURL(shell(), url);
+ ASSERT_TRUE(ExecuteJavascript(constraints_4_3));
+ ExpectTitle("4:3 letterbox");
+
+ NavigateToURL(shell(), url);
+ ASSERT_TRUE(ExecuteJavascript(constraints_16_9));
+ ExpectTitle("16:9 letterbox");
+}
+
+namespace {
+
+struct UserMediaSizes {
+ int min_width;
+ int max_width;
+ int min_height;
+ int max_height;
+ int min_frame_rate;
+ int max_frame_rate;
+};
+
+} // namespace
+
+class WebRtcConstraintsBrowserTest
+ : public WebRtcGetUserMediaBrowserTest,
+ public testing::WithParamInterface<UserMediaSizes> {
+ public:
+ WebRtcConstraintsBrowserTest() : user_media_(GetParam()) {}
+ const UserMediaSizes& user_media() const { return user_media_; }
+
+ private:
+ UserMediaSizes user_media_;
+};
+
+// This test calls getUserMedia in sequence with different constraints.
+IN_PROC_BROWSER_TEST_P(WebRtcConstraintsBrowserTest, GetUserMediaConstraints) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+
+ std::string call = GenerateGetUserMediaCall(kGetUserMediaAndStop,
+ user_media().min_width,
+ user_media().max_width,
+ user_media().min_height,
+ user_media().max_height,
+ user_media().min_frame_rate,
+ user_media().max_frame_rate);
+ DVLOG(1) << "Calling getUserMedia: " << call;
+ NavigateToURL(shell(), url);
+ ASSERT_TRUE(ExecuteJavascript(call));
+ ExpectTitle("OK");
+}
+
+static const UserMediaSizes kAllUserMediaSizes[] = {
+ {320, 320, 180, 180, 30, 30},
+ {320, 320, 240, 240, 30, 30},
+ {640, 640, 360, 360, 30, 30},
+ {640, 640, 480, 480, 30, 30},
+ {960, 960, 720, 720, 30, 30},
+ {1280, 1280, 720, 720, 30, 30},
+ {1920, 1920, 1080, 1080, 30, 30}};
+
+INSTANTIATE_TEST_CASE_P(UserMedia,
+ WebRtcConstraintsBrowserTest,
+ testing::ValuesIn(kAllUserMediaSizes));
+
+} // namespace content