зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1503039 - Add tests for GeckoView MediaElement r=snorp,esawin,imanol
Differential Revision: https://phabricator.services.mozilla.com/D10137 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
0f23fd4558
Коммит
2b3ed2f223
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head><title>Bad Video Path</title></head>
|
||||
<body>
|
||||
<video controls preload>
|
||||
<source src="videos/fileDoesNotExist.ogg"></source>
|
||||
</video>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head><title>MP4 Video</title></head>
|
||||
<body>
|
||||
<video controls preload>
|
||||
<source src="videos/short.mp4"></source>
|
||||
</video>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head><title>OGG Video</title></head>
|
||||
<body>
|
||||
<video controls preload>
|
||||
<source src="videos/video.ogg"></source>
|
||||
</video>
|
||||
</body>
|
||||
</html>
|
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head><title>WebM Video</title></head>
|
||||
<body>
|
||||
<video controls preload>
|
||||
<source src="videos/gizmo.webm"></source>
|
||||
</video>
|
||||
</body>
|
||||
</html>
|
|
@ -41,6 +41,10 @@ open class BaseSessionTest(noErrorCollector: Boolean = false) {
|
|||
const val SAVE_STATE_PATH = "/assets/www/saveState.html"
|
||||
const val TITLE_CHANGE_HTML_PATH = "/assets/www/titleChange.html"
|
||||
const val TRACKERS_PATH = "/assets/www/trackers.html"
|
||||
const val VIDEO_OGG_PATH = "/assets/www/ogg.html"
|
||||
const val VIDEO_MP4_PATH = "/assets/www/mp4.html"
|
||||
const val VIDEO_WEBM_PATH = "/assets/www/webm.html"
|
||||
const val VIDEO_BAD_PATH = "/assets/www/badVideoPath.html"
|
||||
const val UNKNOWN_HOST_URI = "http://www.test.invalid/"
|
||||
const val FULLSCREEN_PATH = "/assets/www/fullscreen.html"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,413 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
package org.mozilla.geckoview.test
|
||||
|
||||
import org.mozilla.geckoview.GeckoSession
|
||||
import org.mozilla.geckoview.MediaElement
|
||||
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
|
||||
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.TimeoutMillis
|
||||
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDevToolsAPI
|
||||
import org.mozilla.geckoview.test.util.Callbacks
|
||||
|
||||
import android.support.test.filters.MediumTest
|
||||
import android.support.test.runner.AndroidJUnit4
|
||||
import org.hamcrest.Matchers.*
|
||||
import org.junit.Assume.assumeThat
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@TimeoutMillis(45000)
|
||||
@MediumTest
|
||||
class MediaElementTest : BaseSessionTest() {
|
||||
|
||||
interface MediaElementDelegate : MediaElement.Delegate {
|
||||
override fun onPlaybackStateChange(mediaElement: MediaElement, mediaState: Int) {}
|
||||
override fun onReadyStateChange(mediaElement: MediaElement, readyState: Int) {}
|
||||
override fun onMetadataChange(mediaElement: MediaElement, metaData: MediaElement.Metadata) {}
|
||||
override fun onLoadProgress(mediaElement: MediaElement, progressInfo: MediaElement.LoadProgressInfo) {}
|
||||
override fun onVolumeChange(mediaElement: MediaElement, volume: Double, muted: Boolean) {}
|
||||
override fun onTimeChange(mediaElement: MediaElement, time: Double) {}
|
||||
override fun onPlaybackRateChange(mediaElement: MediaElement, rate: Double) {}
|
||||
override fun onFullscreenChange(mediaElement: MediaElement, fullscreen: Boolean) {}
|
||||
override fun onError(mediaElement: MediaElement, errorCode: Int) {}
|
||||
}
|
||||
|
||||
private fun setupPrefsAndDelegates(path: String) {
|
||||
sessionRule.setPrefsUntilTestEnd(mapOf(
|
||||
"media.autoplay.enabled.user-gestures-needed" to false,
|
||||
"media.autoplay.default" to 0,
|
||||
"media.autoplay.ask-permission" to false,
|
||||
"full-screen-api.allow-trusted-requests-only" to false))
|
||||
|
||||
sessionRule.session.loadTestPath(path)
|
||||
sessionRule.waitUntilCalled(object : Callbacks.MediaDelegate {
|
||||
@AssertCalled
|
||||
override fun onMediaAdd(session: GeckoSession, element: MediaElement) {
|
||||
sessionRule.addExternalDelegateUntilTestEnd(
|
||||
MediaElementDelegate::class,
|
||||
element::setDelegate,
|
||||
{ element.delegate = null },
|
||||
object : MediaElementDelegate {})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun waitUntilVideoReady(path: String, waitState: Int = MediaElement.MEDIA_READY_STATE_HAVE_ENOUGH_DATA): MediaElement {
|
||||
setupPrefsAndDelegates(path)
|
||||
var ready = false
|
||||
var result: MediaElement? = null
|
||||
while (!ready) {
|
||||
sessionRule.waitUntilCalled(object : MediaElementDelegate {
|
||||
@AssertCalled
|
||||
override fun onReadyStateChange(mediaElement: MediaElement, readyState: Int) {
|
||||
if (readyState == waitState) {
|
||||
ready = true
|
||||
result = mediaElement
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
if (result == null) {
|
||||
throw IllegalStateException("No MediaElement Found")
|
||||
}
|
||||
return result!!
|
||||
}
|
||||
|
||||
private fun waitForPlaybackStateChange(waitState: Int, lambda: (element: MediaElement, state: Int) -> Unit = { _: MediaElement, _: Int -> }) {
|
||||
var waiting = true
|
||||
while (waiting) {
|
||||
sessionRule.waitUntilCalled(object : MediaElementDelegate {
|
||||
@AssertCalled
|
||||
override fun onPlaybackStateChange(mediaElement: MediaElement, mediaState: Int) {
|
||||
if (mediaState == waitState) {
|
||||
waiting = false
|
||||
lambda(mediaElement, mediaState)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun waitForMetadata(path: String): MediaElement.Metadata? {
|
||||
setupPrefsAndDelegates(path)
|
||||
var meta: MediaElement.Metadata? = null
|
||||
while (meta == null) {
|
||||
sessionRule.waitUntilCalled(object : MediaElementDelegate {
|
||||
@AssertCalled
|
||||
override fun onMetadataChange(mediaElement: MediaElement, metaData: MediaElement.Metadata) {
|
||||
meta = metaData
|
||||
}
|
||||
})
|
||||
}
|
||||
return meta
|
||||
}
|
||||
|
||||
private fun playMedia(path: String) {
|
||||
val mediaElement = waitUntilVideoReady(path)
|
||||
mediaElement.play()
|
||||
waitForPlaybackStateChange(MediaElement.MEDIA_STATE_PLAY)
|
||||
waitForPlaybackStateChange(MediaElement.MEDIA_STATE_PLAYING)
|
||||
}
|
||||
|
||||
private fun playMediaFromScript(path: String) {
|
||||
waitUntilVideoReady(path)
|
||||
sessionRule.evaluateJS(mainSession, "$('video').play()")
|
||||
waitForPlaybackStateChange(MediaElement.MEDIA_STATE_PLAY)
|
||||
waitForPlaybackStateChange(MediaElement.MEDIA_STATE_PLAYING)
|
||||
}
|
||||
|
||||
private fun pauseMedia(path: String) {
|
||||
val mediaElement = waitUntilVideoReady(path)
|
||||
mediaElement.play()
|
||||
waitForPlaybackStateChange(MediaElement.MEDIA_STATE_PLAYING) { element: MediaElement, _: Int ->
|
||||
element.pause()
|
||||
}
|
||||
waitForPlaybackStateChange(MediaElement.MEDIA_STATE_PAUSE)
|
||||
}
|
||||
|
||||
private fun timeMedia(path: String, limit: Double) {
|
||||
val mediaElement = waitUntilVideoReady(path)
|
||||
mediaElement.play()
|
||||
var waiting = true
|
||||
while (waiting) {
|
||||
sessionRule.waitUntilCalled(object : MediaElementDelegate {
|
||||
@AssertCalled
|
||||
override fun onTimeChange(mediaElement: MediaElement, time: Double) {
|
||||
if (time > limit) {
|
||||
waiting = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun seekMedia(path: String, seek: Double) {
|
||||
val media = waitUntilVideoReady(path)
|
||||
media.seek(seek)
|
||||
var waiting = true
|
||||
// Sometimes we get a MediaElement.MEDIA_STATE_SUSPEND state change. So just wait until
|
||||
// the test receives the SEEKING state change or time out.
|
||||
while (waiting) {
|
||||
sessionRule.waitUntilCalled(object : MediaElementDelegate {
|
||||
@AssertCalled
|
||||
override fun onPlaybackStateChange(mediaElement: MediaElement, mediaState: Int) {
|
||||
if (mediaState == MediaElement.MEDIA_STATE_SEEKING) {
|
||||
waiting = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
waiting = true
|
||||
while (waiting) {
|
||||
sessionRule.waitUntilCalled(object : MediaElementDelegate {
|
||||
@AssertCalled
|
||||
override fun onTimeChange(mediaElement: MediaElement, time: Double) {
|
||||
if (time >= seek) {
|
||||
waiting = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
sessionRule.waitUntilCalled(object : MediaElementDelegate {
|
||||
@AssertCalled
|
||||
override fun onPlaybackStateChange(mediaElement: MediaElement, mediaState: Int) {
|
||||
assertThat("Done seeking", mediaState, equalTo(MediaElement.MEDIA_STATE_SEEKED))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun fullscreenMedia(path: String) {
|
||||
waitUntilVideoReady(path)
|
||||
sessionRule.evaluateJS(mainSession, "$('video').requestFullscreen()")
|
||||
var waiting = true
|
||||
while (waiting) {
|
||||
sessionRule.waitUntilCalled(object : MediaElementDelegate {
|
||||
@AssertCalled
|
||||
override fun onFullscreenChange(mediaElement: MediaElement, fullscreen: Boolean) {
|
||||
if (fullscreen) {
|
||||
waiting = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun oggPlayMedia() {
|
||||
playMedia(VIDEO_OGG_PATH)
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun oggPlayMediaFromScript() {
|
||||
playMediaFromScript(VIDEO_OGG_PATH)
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun oggPauseMedia() {
|
||||
pauseMedia(VIDEO_OGG_PATH)
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun oggTimeMedia() {
|
||||
timeMedia(VIDEO_OGG_PATH, 2.0)
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun oggMetadataMedia() {
|
||||
val meta = waitForMetadata(VIDEO_OGG_PATH)
|
||||
assertThat("Current source is set", meta?.currentSource, equalTo("resource://android/assets/www/videos/video.ogg"))
|
||||
assertThat("Width is set", meta?.width, equalTo(320L))
|
||||
assertThat("Height is set", meta?.height, equalTo(240L))
|
||||
assertThat("Video is seekable", meta?.isSeekable, equalTo(true))
|
||||
// Disabled duration test for Bug 1510393
|
||||
// assertThat("Duration is set", meta?.duration, closeTo(4.0, 0.1))
|
||||
assertThat("Contains one video track", meta?.videoTrackCount, equalTo(1))
|
||||
assertThat("Contains one audio track", meta?.audioTrackCount, equalTo(0))
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun oggSeekMedia() {
|
||||
seekMedia(VIDEO_OGG_PATH, 2.0)
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun oggFullscreenMedia() {
|
||||
fullscreenMedia(VIDEO_OGG_PATH)
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun webmPlayMedia() {
|
||||
playMedia(VIDEO_WEBM_PATH)
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun webmPlayMediaFromScript() {
|
||||
playMediaFromScript(VIDEO_WEBM_PATH)
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun webmPauseMedia() {
|
||||
pauseMedia(VIDEO_WEBM_PATH)
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun webmTimeMedia() {
|
||||
timeMedia(VIDEO_WEBM_PATH, 0.2)
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun webmMetadataMedia() {
|
||||
val meta = waitForMetadata(VIDEO_WEBM_PATH)
|
||||
assertThat("Current source is set", meta?.currentSource, equalTo("resource://android/assets/www/videos/gizmo.webm"))
|
||||
assertThat("Width is set", meta?.width, equalTo(560L))
|
||||
assertThat("Height is set", meta?.height, equalTo(320L))
|
||||
assertThat("Video is seekable", meta?.isSeekable, equalTo(true))
|
||||
assertThat("Duration is set", meta?.duration, closeTo(5.6, 0.1))
|
||||
assertThat("Contains one video track", meta?.videoTrackCount, equalTo(1))
|
||||
assertThat("Contains one audio track", meta?.audioTrackCount, equalTo(1))
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun webmSeekMedia() {
|
||||
seekMedia(VIDEO_WEBM_PATH, 0.2)
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun webmFullscreenMedia() {
|
||||
fullscreenMedia(VIDEO_WEBM_PATH)
|
||||
}
|
||||
|
||||
private fun waitForVolumeChange(volumeLevel: Double, isMuted: Boolean) {
|
||||
sessionRule.waitUntilCalled(object : MediaElementDelegate {
|
||||
@AssertCalled
|
||||
override fun onVolumeChange(mediaElement: MediaElement, volume: Double, muted: Boolean) {
|
||||
assertThat("Volume was set", volume, closeTo(volumeLevel, 0.0001))
|
||||
assertThat("Not muted", muted, equalTo(isMuted))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun webmVolumeMedia() {
|
||||
val media = waitUntilVideoReady(VIDEO_WEBM_PATH)
|
||||
val volumeLevel = 0.5
|
||||
val volumeLevel2 = 0.75
|
||||
media.setVolume(volumeLevel)
|
||||
waitForVolumeChange(volumeLevel, false)
|
||||
media.setMuted(true)
|
||||
waitForVolumeChange(volumeLevel, true)
|
||||
media.setVolume(volumeLevel2)
|
||||
waitForVolumeChange(volumeLevel2, true)
|
||||
media.setMuted(false)
|
||||
waitForVolumeChange(volumeLevel2, false)
|
||||
}
|
||||
|
||||
// NOTE: All MP4 tests are disabled on automation by Bug 1503952
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun mp4PlayMedia() {
|
||||
assumeThat(sessionRule.env.isAutomation, equalTo(false))
|
||||
playMedia(VIDEO_MP4_PATH)
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun mp4PlayMediaFromScript() {
|
||||
assumeThat(sessionRule.env.isAutomation, equalTo(false))
|
||||
playMediaFromScript(VIDEO_MP4_PATH)
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun mp4PauseMedia() {
|
||||
assumeThat(sessionRule.env.isAutomation, equalTo(false))
|
||||
pauseMedia(VIDEO_MP4_PATH)
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun mp4TimeMedia() {
|
||||
assumeThat(sessionRule.env.isAutomation, equalTo(false))
|
||||
timeMedia(VIDEO_MP4_PATH, 0.2)
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun mp4MetadataMedia() {
|
||||
assumeThat(sessionRule.env.isAutomation, equalTo(false))
|
||||
val meta = waitForMetadata(VIDEO_MP4_PATH)
|
||||
assertThat("Current source is set", meta?.currentSource, equalTo("resource://android/assets/www/videos/short.mp4"))
|
||||
assertThat("Width is set", meta?.width, equalTo(320L))
|
||||
assertThat("Height is set", meta?.height, equalTo(240L))
|
||||
assertThat("Video is seekable", meta?.isSeekable, equalTo(true))
|
||||
assertThat("Duration is set", meta?.duration, closeTo(0.5, 0.1))
|
||||
assertThat("Contains one video track", meta?.videoTrackCount, equalTo(1))
|
||||
assertThat("Contains one audio track", meta?.audioTrackCount, equalTo(1))
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun mp4SeekMedia() {
|
||||
assumeThat(sessionRule.env.isAutomation, equalTo(false))
|
||||
seekMedia(VIDEO_MP4_PATH, 0.2)
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun mp4FullscreenMedia() {
|
||||
assumeThat(sessionRule.env.isAutomation, equalTo(false))
|
||||
fullscreenMedia(VIDEO_MP4_PATH)
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun mp4VolumeMedia() {
|
||||
assumeThat(sessionRule.env.isAutomation, equalTo(false))
|
||||
val media = waitUntilVideoReady(VIDEO_MP4_PATH)
|
||||
val volumeLevel = 0.5
|
||||
val volumeLevel2 = 0.75
|
||||
media.setVolume(volumeLevel)
|
||||
waitForVolumeChange(volumeLevel, false)
|
||||
media.setMuted(true)
|
||||
waitForVolumeChange(volumeLevel, true)
|
||||
media.setVolume(volumeLevel2)
|
||||
waitForVolumeChange(volumeLevel2, true)
|
||||
media.setMuted(false)
|
||||
waitForVolumeChange(volumeLevel2, false)
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@WithDevToolsAPI
|
||||
@Test
|
||||
fun badMediaPath() {
|
||||
// Disabled on automation by Bug 1503957
|
||||
assumeThat(sessionRule.env.isAutomation, equalTo(false))
|
||||
setupPrefsAndDelegates(VIDEO_BAD_PATH)
|
||||
sessionRule.waitForPageStop()
|
||||
sessionRule.waitUntilCalled(object : MediaElementDelegate {
|
||||
@AssertCalled
|
||||
override fun onError(mediaElement: MediaElement, errorCode: Int) {
|
||||
assertThat("Got media error", errorCode, equalTo(MediaElement.MEDIA_ERROR_NETWORK_NO_SOURCE))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче