Title: [222273] trunk/LayoutTests
Revision
222273
Author
[email protected]
Date
2017-09-20 11:10:56 -0700 (Wed, 20 Sep 2017)

Log Message

Make webrtc replace track tests less flaky
https://bugs.webkit.org/show_bug.cgi?id=172645
<rdar://problem/34118218>

Patch by Youenn Fablet <[email protected]> on 2017-09-20
Reviewed by Eric Carlson.

Improving stability of tests by retrying tests every 50 ms instead of once.
Doing some refactoring to put more helper routines in routine.js
Relaxing black pixel check as compression may introduce some uncertainty.
It is now considered black if RGB < (30, 30, 30).

* TestExpectations: Marking video-mute.html as Pass/Fail instead of Fail.
* webrtc/routines.js:
* webrtc/video-mute.html:
* webrtc/video-replace-muted-track.html:
* webrtc/video-replace-track-expected.txt:
* webrtc/video-replace-track-to-null.html:
* webrtc/video-replace-track.html:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (222272 => 222273)


--- trunk/LayoutTests/ChangeLog	2017-09-20 18:04:44 UTC (rev 222272)
+++ trunk/LayoutTests/ChangeLog	2017-09-20 18:10:56 UTC (rev 222273)
@@ -1,3 +1,24 @@
+2017-09-20  Youenn Fablet  <[email protected]>
+
+        Make webrtc replace track tests less flaky
+        https://bugs.webkit.org/show_bug.cgi?id=172645
+        <rdar://problem/34118218>
+
+        Reviewed by Eric Carlson.
+
+        Improving stability of tests by retrying tests every 50 ms instead of once.
+        Doing some refactoring to put more helper routines in routine.js
+        Relaxing black pixel check as compression may introduce some uncertainty.
+        It is now considered black if RGB < (30, 30, 30).
+
+        * TestExpectations: Marking video-mute.html as Pass/Fail instead of Fail.
+        * webrtc/routines.js:
+        * webrtc/video-mute.html:
+        * webrtc/video-replace-muted-track.html:
+        * webrtc/video-replace-track-expected.txt:
+        * webrtc/video-replace-track-to-null.html:
+        * webrtc/video-replace-track.html:
+
 2017-09-20  Chris Dumez  <[email protected]>
 
         Video errors should be instances of Error

Modified: trunk/LayoutTests/TestExpectations (222272 => 222273)


--- trunk/LayoutTests/TestExpectations	2017-09-20 18:04:44 UTC (rev 222272)
+++ trunk/LayoutTests/TestExpectations	2017-09-20 18:10:56 UTC (rev 222273)
@@ -798,7 +798,7 @@
 webrtc/datachannel/multiple-connections.html [ Slow ]
 webrtc/video-replace-track.html [ Pass Failure ]
 webkit.org/b/170178 webrtc/video-replace-track-to-null.html [ Pass Failure ]
-webkit.org/b/170704 webrtc/video-mute.html [ Failure ]
+webkit.org/b/170704 webrtc/video-mute.html [ Pass Failure ]
 webkit.org/b/170701 webrtc/datachannel/bufferedAmountLowThreshold-default.html [ Pass Failure ]
 webkit.org/b/173486 webrtc/video-replace-muted-track.html [ Pass Failure Timeout ]
 

Modified: trunk/LayoutTests/webrtc/routines.js (222272 => 222273)


--- trunk/LayoutTests/webrtc/routines.js	2017-09-20 18:04:44 UTC (rev 222272)
+++ trunk/LayoutTests/webrtc/routines.js	2017-09-20 18:10:56 UTC (rev 222273)
@@ -161,3 +161,41 @@
     await context.close();
     return false;
 }
+
+function isVideoBlack(canvas, video, startX, startY, grabbedWidth, grabbedHeight)
+{
+    canvas.width = video.videoWidth;
+    canvas.height = video.videoHeight;
+    if (!grabbedHeight) {
+        startX = 0;
+        startY = 0;
+        grabbedWidth = canvas.width;
+        grabbedHeight = canvas.height;
+    }
+
+    canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
+
+    imageData = canvas.getContext('2d').getImageData(startX, startY, grabbedWidth, grabbedHeight);
+    data = ""
+    for (var cptr = 0; cptr < grabbedWidth * grabbedHeight; ++cptr) {
+        // Approximatively black pixels.
+        if (data[4 * cptr] > 30 || data[4 * cptr + 1] > 30 || data[4 * cptr + 2] > 30)
+            return false;
+    }
+    return true;
+}
+
+async function checkVideoBlack(expected, canvas, video, errorMessage, counter)
+{
+    if (isVideoBlack(canvas, video) === expected)
+        return Promise.resolve();
+
+    if (counter > 50) {
+        if (!errorMessage)
+            errorMessage = "checkVideoBlack timed out expecting " + expected;
+        return Promise.reject(errorMessage);
+    }
+
+    await waitFor(50);
+    return checkVideoBlack(expected, canvas, video, errorMessage, ++counter);
+}

Modified: trunk/LayoutTests/webrtc/video-mute.html (222272 => 222273)


--- trunk/LayoutTests/webrtc/video-mute.html	2017-09-20 18:04:44 UTC (rev 222272)
+++ trunk/LayoutTests/webrtc/video-mute.html	2017-09-20 18:10:56 UTC (rev 222273)
@@ -15,41 +15,6 @@
         <canvas id="canvas3" width="320" height="240"></canvas>
         <script src =""
         <script>
-function isVideoBlack(id)
-{
-    var canvas = document.getElementById(id);
-    canvas.width = video.videoWidth;
-    canvas.height = video.videoHeight;
-    canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
-
-    imageData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);
-    data = ""
-    for (var cptr = 0; cptr < canvas.width * canvas.height; ++cptr) {
-        // Approximatively black pixels.
-        if (data[4 * cptr] > 10 || data[4 * cptr + 1] > 10 || data[4 * cptr + 2] > 10)
-            return false;
-    }
-    return true;
-}
-
-function pollVideoBlackCheck(expected, id, resolve)
-{
-    if (isVideoBlack(id) === expected) {
-        resolve();
-        return;
-    }
-
-    setTimeout(() => pollVideoBlackCheck(expected, id, resolve), 50);
-}
-
-function checkVideoBlack(expected, id)
-{
-    return new Promise((resolve, reject) => {
-       pollVideoBlackCheck(expected, id, resolve);
-        setTimeout(() => reject("checkVideoBlack timed out for " + id + " expected " + expected), 5000);
-    });
-}
-
 var track;
 var remoteTrack;
 var receivingConnection;
@@ -91,12 +56,12 @@
 }, "Ensuring connection state is connected");
 
 promise_test((test) => {
-    return checkVideoBlack(false, "canvas1");
+    return checkVideoBlack(false, canvas1, video);
 }, "Track is enabled, video should not be black");
 
 promise_test((test) => {
     track.enabled = false;
-    return checkVideoBlack(true, "canvas2");
+    return checkVideoBlack(true, canvas2, video);
 }, "Track is disabled, video should be black");
 
 promise_test((test) => {
@@ -116,7 +81,7 @@
 
 promise_test((test) => {
     track.enabled = true;
-    return checkVideoBlack(true, "canvas2");
+    return checkVideoBlack(false, canvas2, video);
 }, "Track is enabled, video should not be black");
 
         </script>

Modified: trunk/LayoutTests/webrtc/video-replace-muted-track.html (222272 => 222273)


--- trunk/LayoutTests/webrtc/video-replace-muted-track.html	2017-09-20 18:04:44 UTC (rev 222272)
+++ trunk/LayoutTests/webrtc/video-replace-muted-track.html	2017-09-20 18:10:56 UTC (rev 222273)
@@ -12,64 +12,6 @@
         <canvas id="canvas" width="640" height="480"></canvas>
         <script src =""
         <script>
-function isVideoBlack()
-{
-    canvas.width = video.videoWidth;
-    canvas.height = video.videoHeight;
-    canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
-
-    imageData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);
-    data = ""
-    for (var cptr = 0; cptr < canvas.width * canvas.height; ++cptr) {
-        // Approximatively black pixels.
-        if (data[4 * cptr] > 10 || data[4 * cptr + 1] > 10 || data[4 * cptr + 2] > 10)
-            return false;
-    }
-    return true;
-}
-
-var stopPolling = false;
-function pollVideoBlackCheck(expected, resolve, delay)
-{
-    if (isVideoBlack() === expected || stopPolling) {
-        resolve(true);
-        return;
-    }
-
-    setTimeout(() => pollVideoBlackCheck(expected, resolve), delay);
-}
-
-async function checkVideoBlack(expected, duration, id, delay)
-{
-    stopPolling = false;
-    return new Promise((resolve, reject) => {
-        pollVideoBlackCheck(expected, resolve, delay);
-        setTimeout(() => {
-            resolve(false);
-            stopPolling = true;
-        }, duration);
-    });
-}
-
-function grabImagePixels()
-{
-    canvas.width = video.videoWidth;
-    canvas.height = video.videoHeight;
-    canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
-
-    imageData = canvas.getContext('2d').getImageData(20, 20, 2, 2);
-    return imageData.data;
-}
-
-async function checkForNoBlackFrames()
-{
-    for (var cptr = 0; cptr < 10; cptr++) {
-        if (!(await checkVideoBlack(true, 1500, "test3", 50)))
-            return true;
-    }
-    return false;
-}
-
 promise_test((test) => {
     if (window.testRunner)
         testRunner.setUserMediaPermission(true);
@@ -94,22 +36,15 @@
         return video.play();
     }).then(() => {
         firstTrack.enabled = false;
-        return waitFor(200);
+        return checkVideoBlack(true, canvas, video, "Check we receive black frames after disabling the track");
     }).then(() => {
         return navigator.mediaDevices.getUserMedia({ video: { facingMode: { exact: ["environment"] } } });
     }).then((stream) => {
         return sender.replaceTrack(stream.getVideoTracks()[0]);
     }).then(() => {
-        return waitFor(200);
+        return checkVideoBlack(false, canvas, video, "Check we receive some non black frames");
     }).then(() => {
-        return checkVideoBlack(false, 5000, "test2", 200);
-    }).then((result) => {
-        assert_true(result, "expect to receive some non black frames");
-    }).then(() => {
-        // Let's ensure there are no black frames being received.
-        return checkForNoBlackFrames();
-    }).then((result) => {
-        assert_true(result, "check no black frame");
+        return checkVideoBlack(true, canvas, video, "Check we do not receive any black frame", 40).then(assert_unreached, () => { });
     });
 }, "Switching from disabled to enabled track");
         </script>

Modified: trunk/LayoutTests/webrtc/video-replace-track-expected.txt (222272 => 222273)


--- trunk/LayoutTests/webrtc/video-replace-track-expected.txt	2017-09-20 18:04:44 UTC (rev 222272)
+++ trunk/LayoutTests/webrtc/video-replace-track-expected.txt	2017-09-20 18:10:56 UTC (rev 222273)
@@ -2,10 +2,4 @@
 PASS Switching from front to back camera 
 PASS Switching from front to back camera, with lower resolution 
 PASS Switching from front to back camera, with higher resolution 
-PASS testFrontCameraImage test1 
-PASS testBackCameraImage test1 
-PASS testFrontCameraImage test2 
-PASS testBackCameraImage test2 
-PASS testFrontCameraImage test3 
-PASS testBackCameraImage test4 
 

Modified: trunk/LayoutTests/webrtc/video-replace-track-to-null.html (222272 => 222273)


--- trunk/LayoutTests/webrtc/video-replace-track-to-null.html	2017-09-20 18:04:44 UTC (rev 222272)
+++ trunk/LayoutTests/webrtc/video-replace-track-to-null.html	2017-09-20 18:10:56 UTC (rev 222273)
@@ -15,60 +15,48 @@
 video = document.getElementById("video");
 canvas = document.getElementById("canvas");
 
-function grabImagePixels()
+async function getOutboundRTPStatsNumberOfEncodedFrames(connection)
 {
-    canvas.width = video.videoWidth;
-    canvas.height = video.videoHeight;
-    canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
-
-    imageData = canvas.getContext('2d').getImageData(20, 20, 100, 100);
-    return imageData.data;
- }
-
-var firstFrameData;
-
-function storeFrame()
-{
-    firstFrameData = grabImagePixels();
+    var report = await connection.getStats();
+    var framesEncoded;
+    report.forEach((statItem) => {
+        if (statItem.type === "outbound-rtp") {
+            framesEncoded = statItem.framesEncoded;
+        }
+    });
+    return framesEncoded;
 }
 
-function checkCameraImageIsDifferent()
+async function testFrameEncodedStarted(connection, count, previousFramesNumber)
 {
-    data = ""
+    var framesEncodedNumber = await getOutboundRTPStatsNumberOfEncodedFrames(connection);
+    if (previousFramesNumber && framesEncodedNumber > previousFramesNumber)
+        return;
 
-    assert_true(data[0] < 20);
-    assert_true(data[1] < 20);
-    assert_true(data[2] < 20);
+    if (count === undefined)
+        count = 0;
 
-    var same = true;
-    for (var cptr = 0; cptr < data.length; ++cptr) {
-        if (data[cptr] != firstFrameData[cptr]) {
-            same = false;
-            break;
-        }
-    }
-    return !same;
+    if (count >= 20)
+        return Promise.reject("test increasing frame encoded timed out");
+
+    await waitFor(100);
+    return testFrameEncodedStarted(connection, ++count, framesEncodedNumber);
 }
 
-function testCameraImage(resolve, reject, counter)
+async function testFrameEncodedStopped(connection, count, previousFramesNumber)
 {
-    if (!counter)
-        counter = 0;
-
-    if (checkCameraImageIsDifferent()) {
-        resolve();
+    var framesEncodedNumber = await getOutboundRTPStatsNumberOfEncodedFrames(connection);
+    if (previousFramesNumber && framesEncodedNumber === previousFramesNumber)
         return;
-    }
-    if (++counter === 40) {
-        reject("testCameraImage timed out");
-        return;
-    }
-    setTimeout(() => testCameraImage(resolve, reject, counter), 100);
-}
 
-function testStoppedImage()
-{
-    assert_array_equals(grabImagePixels(), firstFrameData);
+    if (count === undefined)
+        count = 0;
+
+    if (count === 20)
+        return Promise.reject("test that number of encoded frames stopped increasing timed out");
+
+    await waitFor(100);
+    return testFrameEncodedStopped(connection, ++count, framesEncodedNumber);
 }
 
 promise_test((test) => {
@@ -77,11 +65,13 @@
 
     var sender;
     var frontStream;
+    var connection;
     return navigator.mediaDevices.getUserMedia({ video: true }).then((stream) => {
         frontStream = stream;
     }).then(() => {
         return new Promise((resolve, reject) => {
             createConnections((firstConnection) => {
+                connection = firstConnection;
                 sender = firstConnection.addTrack(frontStream.getVideoTracks()[0], frontStream);
             }, (secondConnection) => {
                 secondConnection._ontrack_ = (trackEvent) => {
@@ -94,25 +84,14 @@
         video.srcObject = remoteStream;
         return video.play();
     }).then(() => {
-        return waitFor(100);
+        return testFrameEncodedStarted(connection);
     }).then(() => {
-        storeFrame();
-        return waitFor(100);
     }).then(() => {
-        return new Promise((resolve, reject) => {
-            testCameraImage(resolve, reject);
-        });
-    }).then(() => {
         promise = sender.replaceTrack(null);
         assert_true(!!sender.track);
         return promise;
     }).then(() => {
-        return waitFor(100);
-    }).then(() => {
-        storeFrame();
-        return waitFor(100);
-    }).then(() => {
-        testStoppedImage();
+        return testFrameEncodedStopped(connection);
     });
 }, "Stopping sending video using replaceTrack");
         </script>

Modified: trunk/LayoutTests/webrtc/video-replace-track.html (222272 => 222273)


--- trunk/LayoutTests/webrtc/video-replace-track.html	2017-09-20 18:04:44 UTC (rev 222272)
+++ trunk/LayoutTests/webrtc/video-replace-track.html	2017-09-20 18:10:56 UTC (rev 222273)
@@ -5,6 +5,7 @@
         <title>Testing basic video exchange from offerer to receiver</title>
         <script src=""
         <script src=""
+        <script src=""
     </head>
     <body>
 <div id="log"></div>
@@ -25,30 +26,41 @@
     return imageData.data;
  }
 
-function testFrontCameraImage(testName)
+async function testFrontCameraImage(counter)
 {
-    test(() => {
-        data = ""
+    if (!counter)
+        counter = 0;
 
-        assert_true(data[0] < 20, "1");
-        assert_true(data[1] < 20, "2");
-        assert_true(data[2] < 20, "3");
-    }, "testFrontCameraImage " + testName);
+    if (isVideoBlack(canvas, video, 20, 20, 2 ,2))
+        return;
+
+    if (counter >= 20)
+        return Promise.reject("testFrontCameraImage timed out");
+
+    await waitFor(50);
+    return testFrontCameraImage(++counter);
 }
 
-function testBackCameraImage(testName)
+function isBetween100And200(value)
 {
-    test(() => {
-        data = ""
+     return data[0] > 100 && data[0] < 200;
+}
 
-        assert_true(data[0] > 100, "1");
-        assert_true(data[1] > 100, "2");
-        assert_true(data[2] > 100, "3");
+async function testBackCameraImage(counter)
+{
+    if (!counter)
+        counter = 0;
 
-        assert_true(data[0] < 200, "4");
-        assert_true(data[1] < 200, "5");
-        assert_true(data[2] < 200, "6");
-    }, "testBackCameraImage " + testName);
+    data = ""
+
+    if(isBetween100And200(data[0]) && isBetween100And200(data[1]) && isBetween100And200(data[2]))
+        return;
+
+    if (counter >= 20)
+        return Promise.reject("testFrontCameraImage timed out");
+
+    await waitFor(50);
+    return testBackCameraImage(++counter);
 }
 
 promise_test((test) => {
@@ -74,7 +86,8 @@
         video.srcObject = remoteStream;
         return video.play();
     }).then(() => {
-        testFrontCameraImage("test1");
+        return testFrontCameraImage();
+    }).then(() => {
         return navigator.mediaDevices.getUserMedia({ video: { facingMode: { exact: ["environment"] } } });
     }).then((stream) => {
         backStream = stream;
@@ -84,9 +97,7 @@
         return promise;
     }).then(() => {
         assert_true(sender.track === backStream.getVideoTracks()[0]);
-        return waitFor(500);
-    }).then(() => {
-        testBackCameraImage("test1");
+        return testBackCameraImage();
     });
 }, "Switching from front to back camera");
 
@@ -115,7 +126,8 @@
         video.srcObject = remoteStream;
         return video.play();
     }).then(() => {
-        testFrontCameraImage("test2");
+        return testFrontCameraImage();
+    }).then(() => {
         return navigator.mediaDevices.getUserMedia({ video: { width: 320, height: 240, facingMode: { exact: ["environment"] } } });
     }).then((stream) => {
         backStream = stream;
@@ -122,9 +134,7 @@
         assert_true(backStream.getVideoTracks()[0].getSettings().height === 240, "backStream should be small");
         return sender.replaceTrack(backStream.getVideoTracks()[0]);
     }).then(() => {
-        return waitFor(500);
-    }).then(() => {
-        testBackCameraImage("test2");
+        return testBackCameraImage();
     });
 }, "Switching from front to back camera, with lower resolution");
 
@@ -154,7 +164,8 @@
         video.srcObject = remoteStream;
         return video.play();
     }).then(() => {
-        testFrontCameraImage("test3");
+        return testFrontCameraImage();
+    }).then(() => {
         return navigator.mediaDevices.getUserMedia({ video: { width: 640, height: 480 , facingMode: { exact: ["environment"] } } });
     }).then((stream) => {
         backStream = stream;
@@ -161,9 +172,7 @@
         assert_true(backStream.getVideoTracks()[0].getSettings().height === 480, "back stream should be big");
         return sender.replaceTrack(backStream.getVideoTracks()[0]);
     }).then(() => {
-        return waitFor(500);
-    }).then(() => {
-        testBackCameraImage("test4");
+        return testBackCameraImage();
     });
 
 }, "Switching from front to back camera, with higher resolution");
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to