Improve debugging ability of some webrtc tests
[WebKit-https.git] / LayoutTests / webrtc / video-stats.html
1 <!doctype html>
2 <html>
3     <head>
4         <meta charset="utf-8">
5         <title>Testing basic video exchange from offerer to receiver</title>
6         <script src="../resources/testharness.js"></script>
7         <script src="../resources/testharnessreport.js"></script>
8     </head>
9     <body>
10         <script src ="routines.js"></script>
11         <script>
12 function getStatsType(connection)
13 {
14     return connection.getStats().then((report) => {
15         var reportTypes = [];
16         report.forEach((statItem) => {
17             if (reportTypes.indexOf(statItem.type) === -1)
18                 reportTypes.push(statItem.type);
19         });
20         return reportTypes.sort();
21     });
22 }
23
24 function checkStatsReportIterator(report)
25 {
26     assert_equals(Object.getOwnPropertyDescriptor(report.__proto__, Symbol.iterator).value, Object.getOwnPropertyDescriptor(report.__proto__, 'entries').value);
27     assert_equals(Object.getOwnPropertyDescriptor(report.__proto__, Symbol.iterator).value.name, "entries");
28     for (let pair of report)
29         assert_equals(pair.length, 2);
30 }
31
32 function getInboundRTPStats(connection)
33 {
34     return connection.getStats().then((report) => {
35         checkStatsReportIterator(report);
36         var stats;
37         report.forEach((statItem) => {
38             if (statItem.type === "inbound-rtp") {
39                 stats = statItem;
40             }
41         });
42         return stats;
43     });
44 }
45
46 function getOutboundRTPStats(connection)
47 {
48     return connection.getStats().then((report) => {
49         checkStatsReportIterator(report);
50         var stats;
51         report.forEach((statItem) => {
52             if (statItem.type === "outbound-rtp") {
53                 stats = statItem;
54             }
55         });
56         return stats;
57     });
58 }
59
60 function testTimestampDifference(timeStampDifference, numberOfFrames)
61 {
62     // Let's ensure timestamp is not in microseconds but milliseconds.
63     return timeStampDifference > 100000 * (numberOfFrames / 30.0);
64 }
65
66 function checkInboundFramesNumberIncreased(secondConnection, statsSecondConnection, count)
67 {
68     return getInboundRTPStats(secondConnection).then((stats) => {
69         if (stats.framesDecoded > statsSecondConnection.framesDecoded) {
70             if (testTimestampDifference(stats.timestamp - statsSecondConnection.timestamp, stats.framesDecoded - statsSecondConnection.framesDecoded))
71                 return Promise.reject("timestamp and frames increment do not match");
72             return;
73         }
74         if (++count === 20)
75             return Promise.reject("checking inbound stats frame number increasing timed out");
76         return waitFor(50).then(() => {
77             return checkInboundFramesNumberIncreased(secondConnection, statsSecondConnection, count)
78         });
79     });
80 }
81
82 function checkOutboundFramesNumberIncreased(firstConnection, statsFirstConnection, count)
83 {
84     return getOutboundRTPStats(firstConnection).then((stats) => {
85         if (stats.framesEncoded > statsFirstConnection.framesEncoded) {
86             if (testTimestampDifference(stats.timestamp - statsFirstConnection.timestamp, stats.framesEncoded - statsFirstConnection.framesEncoded))
87                 return Promise.reject("timestamp and frames increment do not match");
88             return;
89         }
90         if (++count === 20)
91             return Promise.reject("checking outbound stats frame number increasing timed out");
92         return waitFor(50).then(() => {
93             return checkOutboundFramesNumberIncreased(firstConnection, statsFirstConnection, count)
94         });
95     });
96 }
97
98 var firstConnection, secondConnection;
99 promise_test((test) => {
100     if (window.testRunner)
101         testRunner.setUserMediaPermission(true);
102
103     var localStream, remoteStream;
104     return navigator.mediaDevices.getUserMedia({ video: true}).then((stream) => {
105         localStream = stream;
106         return new Promise((resolve, reject) => {
107             createConnections((connection) => {
108                 firstConnection = connection;
109                 firstConnection.addTrack(stream.getVideoTracks()[0], stream);
110             }, (connection) => {
111                 secondConnection = connection;
112                 secondConnection.ontrack = (trackEvent) => {
113                     remoteStream = trackEvent.streams[0];
114                     resolve();
115                 };
116             });
117             setTimeout(() => reject("Test timed out"), 5000);
118         });
119     }).then(() => {
120         return getOutboundRTPStats(firstConnection);
121     }).then((stats) => {
122         assert_true(!!stats, "outbound-rtp stats should not be null");
123         assert_true(Number.isInteger(stats.framesEncoded), "framesEncoded should be an integer");
124         assert_true(Number.isInteger(stats.qpSum), "outbound qpSum should be an integer");
125         assert_true(typeof stats.timestamp === "number", "timestamp should be a double");
126         statsFirstConnection = stats;
127         return getInboundRTPStats(secondConnection);
128     }).then((stats) => {
129         assert_true(!!stats, "inbound-rtp stats should not be null");
130         assert_true(Number.isInteger(stats.framesDecoded), "framesDecoded should be an integer");
131         assert_true(Number.isInteger(stats.qpSum), "inbound qpSum should be an integer");
132         assert_true(typeof stats.timestamp === "number", "timestamp should be a double");
133         statsSecondConnection = stats;
134     }).then(() => {
135         return checkInboundFramesNumberIncreased(secondConnection, statsSecondConnection, 0);
136     }).then(() => {
137         return checkOutboundFramesNumberIncreased(firstConnection, statsFirstConnection, 0);
138     }).then(() => {
139         return getStatsType(firstConnection);
140     }).then((types) => {
141         assert_array_equals(types, ["candidate-pair", "certificate", "outbound-rtp"]);
142     }).then(() => {
143         return getStatsType(secondConnection);
144     }).then((types) => {
145         assert_array_equals(types, ["candidate-pair", "certificate", "inbound-rtp", "track"]);
146     });
147 }, "Basic video stats");
148         </script>
149     </body>
150 </html>