Commit 54dc5e19 authored by joi@chromium.org's avatar joi@chromium.org

Add a browser test to automatically run end-to-end Hangout Services test.

NOTRY=true
BUG=291271

Review URL: https://codereview.chromium.org/59113003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@233409 0039d316-1c4b-4281-b951-d872f2087c98
parent f6a61b70
...@@ -4,11 +4,14 @@ ...@@ -4,11 +4,14 @@
#include "base/json/json_writer.h" #include "base/json/json_writer.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h" #include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h" #include "base/threading/platform_thread.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h" #include "chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h"
#include "chrome/browser/extensions/component_loader.h"
#include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_function_test_utils.h" #include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/extensions/extension_tab_util.h"
...@@ -19,6 +22,7 @@ ...@@ -19,6 +22,7 @@
#include "chrome/test/base/ui_test_utils.h" #include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/media_device_id.h" #include "content/public/browser/media_device_id.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
#include "extensions/common/permissions/permission_set.h" #include "extensions/common/permissions/permission_set.h"
#include "media/audio/audio_manager.h" #include "media/audio/audio_manager.h"
#include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/embedded_test_server.h"
...@@ -35,7 +39,36 @@ namespace extensions { ...@@ -35,7 +39,36 @@ namespace extensions {
using extension_function_test_utils::RunFunctionAndReturnError; using extension_function_test_utils::RunFunctionAndReturnError;
using extension_function_test_utils::RunFunctionAndReturnSingleResult; using extension_function_test_utils::RunFunctionAndReturnSingleResult;
class WebrtcAudioPrivateTest : public ExtensionApiTest { class AudioWaitingExtensionTest : public ExtensionApiTest {
protected:
void WaitUntilAudioIsPlaying(WebContents* tab) {
// Wait for audio to start playing. We gate this on there being one
// or more AudioOutputController objects for our tab.
bool audio_playing = false;
for (size_t remaining_tries = 50; remaining_tries > 0; --remaining_tries) {
tab->GetRenderViewHost()->GetAudioOutputControllers(
base::Bind(OnAudioControllers, &audio_playing));
base::MessageLoop::current()->RunUntilIdle();
if (audio_playing)
break;
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
}
if (!audio_playing)
FAIL() << "Audio did not start playing within ~5 seconds.";
}
// Used by the test above to wait until audio is playing.
static void OnAudioControllers(
bool* audio_playing,
const RenderViewHost::AudioOutputControllerList& list) {
if (!list.empty())
*audio_playing = true;
}
};
class WebrtcAudioPrivateTest : public AudioWaitingExtensionTest {
public: public:
WebrtcAudioPrivateTest() : enumeration_event_(false, false) { WebrtcAudioPrivateTest() : enumeration_event_(false, false) {
} }
...@@ -165,14 +198,6 @@ IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, SetActiveSinkNoMediaStream) { ...@@ -165,14 +198,6 @@ IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, SetActiveSinkNoMediaStream) {
error); error);
} }
// Used by the test below to wait until audio is playing.
static void OnAudioControllers(
bool* audio_playing,
const RenderViewHost::AudioOutputControllerList& list) {
if (!list.empty())
*audio_playing = true;
}
IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetAndSetWithMediaStream) { IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetAndSetWithMediaStream) {
// First get the list of output devices, so that we can (if // First get the list of output devices, so that we can (if
// available) set the active device to a device other than the one // available) set the active device to a device other than the one
...@@ -192,21 +217,7 @@ IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetAndSetWithMediaStream) { ...@@ -192,21 +217,7 @@ IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, GetAndSetWithMediaStream) {
WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
int tab_id = ExtensionTabUtil::GetTabId(tab); int tab_id = ExtensionTabUtil::GetTabId(tab);
// Wait for audio to start playing. We gate this on there being one WaitUntilAudioIsPlaying(tab);
// or more AudioOutputController objects for our tab.
bool audio_playing = false;
for (size_t remaining_tries = 50; remaining_tries > 0; --remaining_tries) {
tab->GetRenderViewHost()->GetAudioOutputControllers(
base::Bind(OnAudioControllers, &audio_playing));
base::MessageLoop::current()->RunUntilIdle();
if (audio_playing)
break;
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
}
if (!audio_playing)
FAIL() << "Audio did not start playing within ~5 seconds.";
std::string current_device = InvokeGetActiveSink(tab_id); std::string current_device = InvokeGetActiveSink(tab_id);
VLOG(2) << "Before setting, current device: " << current_device; VLOG(2) << "Before setting, current device: " << current_device;
...@@ -293,4 +304,39 @@ IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, TriggerEvent) { ...@@ -293,4 +304,39 @@ IN_PROC_BROWSER_TEST_F(WebrtcAudioPrivateTest, TriggerEvent) {
EXPECT_EQ("true", result); EXPECT_EQ("true", result);
} }
class HangoutServicesBrowserTest : public AudioWaitingExtensionTest {
public:
virtual void SetUp() OVERRIDE {
// Make sure the Hangout Services component extension gets loaded.
ComponentLoader::EnableBackgroundExtensionsForTesting();
AudioWaitingExtensionTest::SetUp();
}
};
IN_PROC_BROWSER_TEST_F(HangoutServicesBrowserTest,
RunComponentExtensionTest) {
// This runs the end-to-end JavaScript test for the Hangout Services
// component extension, which uses the webrtcAudioPrivate API among
// others.
ASSERT_TRUE(StartEmbeddedTestServer());
GURL url(embedded_test_server()->GetURL(
"/extensions/hangout_services_test.html"));
// The "externally connectable" extension permission doesn't seem to
// like when we use 127.0.0.1 as the host, but using localhost works.
std::string url_spec = url.spec();
ReplaceFirstSubstringAfterOffset(&url_spec, 0, "127.0.0.1", "localhost");
GURL localhost_url(url_spec);
ui_test_utils::NavigateToURL(browser(), localhost_url);
WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
WaitUntilAudioIsPlaying(tab);
ASSERT_TRUE(content::ExecuteScript(tab, "browsertestRunAllTests();"));
content::TitleWatcher title_watcher(tab, ASCIIToUTF16("success"));
title_watcher.AlsoWaitForTitle(ASCIIToUTF16("failure"));
string16 result = title_watcher.WaitAndGetTitle();
EXPECT_EQ(ASCIIToUTF16("success"), result);
}
} // namespace extensions } // namespace extensions
...@@ -13,7 +13,8 @@ the Hangout Services component extension and the APIs it uses. ...@@ -13,7 +13,8 @@ the Hangout Services component extension and the APIs it uses.
</script> </script>
<script> <script>
// //
// UI glue, leaving in HTML file with the UI elements it is using. // UI glue and other code that needs to use the document. Leaving in
// HTML file with the UI elements it is using.
// //
// Populates UI elements with initial contents. // Populates UI elements with initial contents.
...@@ -69,6 +70,39 @@ function getAssociatedDeviceFromSelection() { ...@@ -69,6 +70,39 @@ function getAssociatedDeviceFromSelection() {
alert('Associated sink ID: ' + sinkId); alert('Associated sink ID: ' + sinkId);
}); });
} }
//
// Manual tests.
//
function manualTestChooseDesktopMedia() {
chooseDesktopMedia(function(results) {
alert('Cancel ID: ' + results.cancelId +
', stream ID: ' + results.streamId);
});
}
function manualTestListenForSinksChangedEvent() {
listenForSinksChangedEvent(function(msg) {
if (msg['eventName'] && msg['eventName'] == 'onSinksChanged')
alert('Got onSinksChanged event.');
});
}
// Browser test scaffolding. Starts the test run from a browser
// test. Sets the document title to 'success' or 'failure' when the
// test completes.
function browsertestRunAllTests() {
runAllTests(function(results) {
if (results == '') {
document.title = 'success';
} else {
console.log('Test failed:');
console.log(results);
document.title = 'failure';
}
});
}
</script> </script>
</head> </head>
<body onload="populate()"> <body onload="populate()">
......
...@@ -118,24 +118,6 @@ function isExtensionEnabled(callback) { ...@@ -118,24 +118,6 @@ function isExtensionEnabled(callback) {
sendMessage({'method': 'isExtensionEnabled'}, callback); sendMessage({'method': 'isExtensionEnabled'}, callback);
} }
//
// Manual tests.
//
function manualTestChooseDesktopMedia() {
chooseDesktopMedia(function(results) {
alert('Cancel ID: ' + results.cancelId +
', stream ID: ' + results.streamId);
});
}
function manualTestListenForSinksChangedEvent() {
listenForSinksChangedEvent(function(msg) {
if (msg['eventName'] && msg['eventName'] == 'onSinksChanged')
alert('Got onSinksChanged event.');
});
}
// //
// Automated tests. // Automated tests.
// //
...@@ -160,6 +142,8 @@ var TESTS = [ ...@@ -160,6 +142,8 @@ var TESTS = [
//testTimeout, //testTimeout,
]; ];
var TEST_TIMEOUT_MS = 3000;
function runAllTests(callback) { function runAllTests(callback) {
var results = ''; var results = '';
...@@ -190,7 +174,7 @@ function runAllTests(callback) { ...@@ -190,7 +174,7 @@ function runAllTests(callback) {
function onTimeout() { function onTimeout() {
nextTest(test.name, '', true); nextTest(test.name, '', true);
} }
setTimeout(onTimeout, 3000); setTimeout(onTimeout, TEST_TIMEOUT_MS);
} }
function nextTest(testName, currentResults, timedOut) { function nextTest(testName, currentResults, timedOut) {
...@@ -291,10 +275,9 @@ function testEnabledLoggingButDiscard(callback) { ...@@ -291,10 +275,9 @@ function testEnabledLoggingButDiscard(callback) {
function testGetSinks(callback) { function testGetSinks(callback) {
getSinks(function(sinks) { getSinks(function(sinks) {
if (sinks.length == 0) // Some bots may have no audio sinks installed, in which case we
callback('Got no sinks.'); // will get an empty list here.
else callback('');
callback('');
}); });
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment