RTCDataChannel-stats.html (7992B)
1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <meta name="timeout" content="long"/> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="../webrtc/RTCPeerConnection-helper.js"></script> 9 <script src="../webrtc/RTCDataChannel-helper.js"></script> 10 <script src="../webrtc/RTCDataChannel-worker-shim.js"></script> 11 </head> 12 <body> 13 <script> 14 15 async function getDcStats(pc) { 16 const stats = await pc.getStats(); 17 return [...stats.values()].filter(({type}) => type == "data-channel"); 18 } 19 20 // Oh boy here we go! 21 for (const which of ['neither', 'offerer', 'answerer']) { 22 23 promise_test(async test => { 24 const {offerer, answerer, offererChannel, answererChannel} = 25 await makeDataChannelTestFixture(which, {}, 26 which == 'offerer' ? new WorkerBackedDataChannel() : null, 27 which == 'answerer' ? new WorkerBackedDataChannel() : null); 28 29 const dcStats1 = await getDcStats(offerer); 30 assert_equals(dcStats1.length, 1, 31 "One RTCDataChannel results in one data-channel stats object (offerer)"); 32 33 const dcStats2 = await getDcStats(answerer); 34 assert_equals(dcStats2.length, 1, 35 "One RTCDataChannel results in one data-channel stats object (answerer)"); 36 }, `${which} on worker: Check that RTCDataChannelStats are present`); 37 38 promise_test(async test => { 39 const {offerer, answerer, offererChannel, answererChannel} = 40 await makeDataChannelTestFixture(which, {}, 41 which == 'offerer' ? new WorkerBackedDataChannel() : null, 42 which == 'answerer' ? new WorkerBackedDataChannel() : null); 43 44 test.add_cleanup(() => offerer.close()); 45 test.add_cleanup(() => answerer.close()); 46 47 for (const [pc, channel, type] of [ 48 [offerer, offererChannel, "offerer"], 49 [answerer, answererChannel, "answerer"], 50 ]) { 51 const dcStats = await getDcStats(pc); 52 assert_equals(dcStats.length, 1, 53 `One RTCDataChannel results in one data-channel stats object (${type})`); 54 55 assert_equals(dcStats[0].label, channel.label, 56 `Stats label should match (${type})`); 57 assert_equals(dcStats[0].protocol, channel.protocol, 58 `Stats protocol should match (${type})`); 59 assert_equals(dcStats[0].dataChannelIdentifier, channel.id, 60 `Stats dataChannelIdentifier/id should match (${type})`); 61 assert_equals(dcStats[0].state, channel.readyState, 62 `Stats state/readyState should match (${type})`); 63 assert_equals(dcStats[0].messagesSent, 0, 64 `Initial messagesSent should be 0 (${type})`); 65 assert_equals(dcStats[0].bytesSent, 0, 66 `Initial bytesSent should be 0 (${type})`); 67 assert_equals(dcStats[0].messagesReceived, 0, 68 `Initial messagesReceived should be 0 (${type})`); 69 assert_equals(dcStats[0].bytesReceived, 0, 70 `Initial bytesReceived should be 0 (${type})`); 71 }; 72 }, `${which} on worker: Check that RTCDataChannelStats have a valid initial state`); 73 74 async function getDcCounterStats(pc) { 75 const dcStats = await getDcStats(pc); 76 return { 77 bytesSent: dcStats[0].bytesSent, 78 bytesReceived: dcStats[0].bytesReceived, 79 messagesSent: dcStats[0].messagesSent, 80 messagesReceived: dcStats[0].messagesReceived, 81 }; 82 } 83 84 promise_test(async test => { 85 const {offerer, answerer, offererChannel, answererChannel} = 86 await makeDataChannelTestFixture(which, {}, 87 which == 'offerer' ? new WorkerBackedDataChannel() : null, 88 which == 'answerer' ? new WorkerBackedDataChannel() : null); 89 90 test.add_cleanup(() => offerer.close()); 91 test.add_cleanup(() => answerer.close()); 92 93 for (const message of ['hello', '', '世界你好']) { 94 for (const [sender, senderDc, receiver, receiverDc] of [ 95 [offerer, offererChannel, answerer, answererChannel], 96 [answerer, answererChannel, offerer, offererChannel], 97 ]) { 98 const senderCountersBefore = await getDcCounterStats(sender); 99 const receiverCountersBefore = await getDcCounterStats(receiver); 100 101 senderDc.send(message); 102 const recvEvent = await new Promise(r => receiverDc.onmessage = r); 103 assert_equals(recvEvent.data, message); 104 const encoder = new TextEncoder(); 105 const byteLength = encoder.encode(message).length; 106 107 const senderCountersAfter = await getDcCounterStats(sender); 108 const receiverCountersAfter = await getDcCounterStats(receiver); 109 110 // Don't bother checking the other way around for zeroes 111 assert_equals(senderCountersAfter.bytesSent, 112 senderCountersBefore.bytesSent + byteLength, 113 "Got expected sender bytesSent"); 114 assert_equals(senderCountersAfter.messagesSent, 115 senderCountersBefore.messagesSent + 1, 116 "Got expected sender messagesSent"); 117 118 assert_equals(receiverCountersAfter.bytesReceived, 119 receiverCountersBefore.bytesReceived + byteLength, 120 "Got expected receiver bytesReceived"); 121 assert_equals(receiverCountersAfter.messagesReceived, 122 receiverCountersBefore.messagesReceived + 1, 123 "Got expected receiver messagesReceived"); 124 } 125 } 126 }, `${which} on worker: Check that RTCDataChannelStats messages/bytes Sent/Received are correct for various strings`); 127 128 // ASCII encoded buffer representation of the string 129 const helloBuffer = Uint8Array.of(0x68, 0x65, 0x6c, 0x6c, 0x6f); 130 const emptyBuffer = new Uint8Array(); 131 const helloBlob = new Blob([helloBuffer]); 132 133 // UTF-8 encoded buffer representation of the string 134 const unicodeBuffer = Uint8Array.of( 135 0xe4, 0xb8, 0x96, 0xe7, 0x95, 0x8c, 136 0xe4, 0xbd, 0xa0, 0xe5, 0xa5, 0xbd); 137 138 // TODO: How finely-grained should we make these? Each one requires ICE, so we 139 // can't do each case separately. What should the top-level loop be? 140 for (const binaryType of ["arraybuffer", "blob"]) { 141 promise_test(async test => { 142 const {offerer, answerer, offererChannel, answererChannel} = 143 await makeDataChannelTestFixture(which, {}, 144 which == 'offerer' ? new WorkerBackedDataChannel() : null, 145 which == 'answerer' ? new WorkerBackedDataChannel() : null); 146 147 test.add_cleanup(() => offerer.close()); 148 test.add_cleanup(() => answerer.close()); 149 150 for (const [message, bytes] of [ 151 [helloBlob, 5], 152 [helloBuffer.buffer, 5], 153 [helloBuffer, 5], 154 [unicodeBuffer, 12] 155 ]) { 156 for (const [sender, senderDc, receiver, receiverDc] of [ 157 [offerer, offererChannel, answerer, answererChannel], 158 [answerer, answererChannel, offerer, offererChannel], 159 ]) { 160 161 receiver.binaryType = binaryType; 162 163 const senderCountersBefore = await getDcCounterStats(sender); 164 const receiverCountersBefore = await getDcCounterStats(receiver); 165 166 senderDc.send(message); 167 const recvEvent = await new Promise(r => receiverDc.onmessage = r); 168 169 const senderCountersAfter = await getDcCounterStats(sender); 170 const receiverCountersAfter = await getDcCounterStats(receiver); 171 172 assert_equals(senderCountersAfter.bytesSent, 173 senderCountersBefore.bytesSent + bytes, 174 "Got expected sender bytesSent"); 175 assert_equals(senderCountersAfter.messagesSent, 176 senderCountersBefore.messagesSent + 1, 177 "Got expected sender messagesSent"); 178 179 assert_equals(receiverCountersAfter.bytesReceived, 180 receiverCountersBefore.bytesReceived + bytes, 181 "Got expected receiver bytesReceived"); 182 assert_equals(receiverCountersAfter.messagesReceived, 183 receiverCountersBefore.messagesReceived + 1, 184 "Got expected receiver messagesReceived"); 185 } 186 } 187 }, `${which} on worker: Check that RTCDataChannelStats messages/bytes Sent/Received are correct for various binary messages received as ${binaryType}`); 188 } 189 } 190 </script> 191 </body> 192 </html>