blob: 89f6b1b4d7a425f2d05688d14315227454a3d4be [file] [log] [blame]
Soares Chen17354db2017-06-13 18:39:041<!doctype html>
2<meta charset=utf-8>
Byron Campen [:bwc]bb9278b2019-07-10 15:11:083<meta name="timeout" content="long">
Soares Chen17354db2017-06-13 18:39:044<title>RTCDataChannel.prototype.bufferedAmount</title>
5<script src="/resources/testharness.js"></script>
6<script src="/resources/testharnessreport.js"></script>
7<script src="RTCPeerConnection-helper.js"></script>
8<script>
youennf0e97d092019-03-23 18:02:569'use strict';
Soares Chen17354db2017-06-13 18:39:0410
youennf0e97d092019-03-23 18:02:5611// Test is based on the following revision:
12// https://rawgit.com/w3c/webrtc-pc/1cc5bfc3ff18741033d804c4a71f7891242fb5b3/webrtc.html
Soares Chen17354db2017-06-13 18:39:0413
youennf0e97d092019-03-23 18:02:5614// The following helper functions are called from RTCPeerConnection-helper.js:
15// createDataChannelPair
16// awaitMessage
Soares Chen17354db2017-06-13 18:39:0417
youennf0e97d092019-03-23 18:02:5618/*
19 6.2. RTCDataChannel
20 interface RTCDataChannel : EventTarget {
Soares Chen17354db2017-06-13 18:39:0421 ...
youennf0e97d092019-03-23 18:02:5622 readonly attribute unsigned long bufferedAmount;
23 void send(USVString data);
24 void send(Blob data);
25 void send(ArrayBuffer data);
26 void send(ArrayBufferView data);
Soares Chen17354db2017-06-13 18:39:0427 };
Soares Chen17354db2017-06-13 18:39:0428
youennf0e97d092019-03-23 18:02:5629 bufferedAmount
30 The bufferedAmount attribute must return the number of bytes of application
31 data (UTF-8 text and binary data) that have been queued using send() but that,
32 as of the last time the event loop started executing a task, had not yet been
33 transmitted to the network. (This thus includes any text sent during the
34 execution of the current task, regardless of whether the user agent is able
35 to transmit text asynchronously with script execution.) This does not include
36 framing overhead incurred by the protocol, or buffering done by the operating
37 system or network hardware. The value of the [[BufferedAmount]] slot will only
38 increase with each call to the send() method as long as the [[ReadyState]] slot
39 is open; however, the slot does not reset to zero once the channel closes. When
40 the underlying data transport sends data from its queue, the user agent MUST
41 queue a task that reduces [[BufferedAmount]] with the number of bytes that was
42 sent.
Soares Chen17354db2017-06-13 18:39:0443
Soares Chen17354db2017-06-13 18:39:0444
youennf0e97d092019-03-23 18:02:5645 [WebMessaging]
46 interface MessageEvent : Event {
47 readonly attribute any data;
48 ...
49 };
50 */
Soares Chen17354db2017-06-13 18:39:0451
youennf0e97d092019-03-23 18:02:5652// Simple ASCII encoded string
53const helloString = 'hello';
54// ASCII encoded buffer representation of the string
55const helloBuffer = Uint8Array.of(0x68, 0x65, 0x6c, 0x6c, 0x6f);
56const helloBlob = new Blob([helloBuffer]);
Soares Chen17354db2017-06-13 18:39:0457
youennf0e97d092019-03-23 18:02:5658// Unicode string with multiple code units
59const unicodeString = '世界你好';
60// UTF-8 encoded buffer representation of the string
61const unicodeBuffer = Uint8Array.of(
62 0xe4, 0xb8, 0x96, 0xe7, 0x95, 0x8c,
63 0xe4, 0xbd, 0xa0, 0xe5, 0xa5, 0xbd);
Soares Chen17354db2017-06-13 18:39:0464
youennf0e97d092019-03-23 18:02:5665/*
66 Ensure .bufferedAmount is 0 initially for both sides.
67 */
68promise_test(async (t) => {
69 const pc1 = new RTCPeerConnection();
70 const pc2 = new RTCPeerConnection();
71 t.add_cleanup(() => pc1.close());
72 t.add_cleanup(() => pc2.close());
Soares Chen17354db2017-06-13 18:39:0473
youennf0e97d092019-03-23 18:02:5674 const [dc1, dc2] = await createDataChannelPair(pc1, pc2);
Soares Chen17354db2017-06-13 18:39:0475
youennf0e97d092019-03-23 18:02:5676 assert_equals(dc1.bufferedAmount, 0, 'Expect bufferedAmount to be 0');
77 assert_equals(dc2.bufferedAmount, 0, 'Expect bufferedAmount to be 0');
78}, 'bufferedAmount initial value should be 0 for both peers');
Soares Chen17354db2017-06-13 18:39:0479
youennf0e97d092019-03-23 18:02:5680/*
81 6.2. send()
82 3. Execute the sub step that corresponds to the type of the methods argument:
Soares Chen17354db2017-06-13 18:39:0483
youennf0e97d092019-03-23 18:02:5684 string object
85 Let data be the object and increase the bufferedAmount attribute
86 by the number of bytes needed to express data as UTF-8.
87 */
88promise_test(async (t) => {
89 const pc1 = new RTCPeerConnection();
90 const pc2 = new RTCPeerConnection();
91 t.add_cleanup(() => pc1.close());
92 t.add_cleanup(() => pc2.close());
Soares Chen17354db2017-06-13 18:39:0493
youennf0e97d092019-03-23 18:02:5694 const [dc1, dc2] = await createDataChannelPair(pc1, pc2);
Soares Chen17354db2017-06-13 18:39:0495
youennf0e97d092019-03-23 18:02:5696 dc1.send(unicodeString);
97 assert_equals(dc1.bufferedAmount, unicodeBuffer.byteLength,
98 'Expect bufferedAmount to be the byte length of the unicode string');
Soares Chen17354db2017-06-13 18:39:0499
youennf0e97d092019-03-23 18:02:56100 await awaitMessage(dc2);
101 assert_equals(dc1.bufferedAmount, 0,
102 'Expect sender bufferedAmount to be reduced after message is sent');
103}, 'bufferedAmount should increase to byte length of encoded unicode string sent');
Soares Chen17354db2017-06-13 18:39:04104
youennf0e97d092019-03-23 18:02:56105/*
106 6.2. send()
107 3. Execute the sub step that corresponds to the type of the methods argument:
108 ArrayBuffer object
109 Let data be the data stored in the buffer described by the ArrayBuffer
110 object and increase the bufferedAmount attribute by the length of the
111 ArrayBuffer in bytes.
112 */
113promise_test(async (t) => {
114 const pc1 = new RTCPeerConnection();
115 const pc2 = new RTCPeerConnection();
116 t.add_cleanup(() => pc1.close());
117 t.add_cleanup(() => pc2.close());
Soares Chen17354db2017-06-13 18:39:04118
youennf0e97d092019-03-23 18:02:56119 const [dc1, dc2] = await createDataChannelPair(pc1, pc2);
Soares Chen17354db2017-06-13 18:39:04120
youennf0e97d092019-03-23 18:02:56121 dc1.send(helloBuffer.buffer);
122 assert_equals(dc1.bufferedAmount, helloBuffer.byteLength,
123 'Expect bufferedAmount to increase to byte length of sent buffer');
Soares Chen17354db2017-06-13 18:39:04124
youennf0e97d092019-03-23 18:02:56125 await awaitMessage(dc2);
126 assert_equals(dc1.bufferedAmount, 0,
127 'Expect sender bufferedAmount to be reduced after message is sent');
128}, 'bufferedAmount should increase to byte length of buffer sent');
Soares Chen17354db2017-06-13 18:39:04129
youennf0e97d092019-03-23 18:02:56130/*
131 6.2. send()
132 3. Execute the sub step that corresponds to the type of the methods argument:
133 Blob object
134 Let data be the raw data represented by the Blob object and increase
135 the bufferedAmount attribute by the size of data, in bytes.
136 */
137promise_test(async (t) => {
138 const pc1 = new RTCPeerConnection();
139 const pc2 = new RTCPeerConnection();
140 t.add_cleanup(() => pc1.close());
141 t.add_cleanup(() => pc2.close());
142
143 const [dc1, dc2] = await createDataChannelPair(pc1, pc2);
144
145 dc1.send(helloBlob);
146 assert_equals(dc1.bufferedAmount, helloBlob.size,
147 'Expect bufferedAmount to increase to size of sent blob');
148
149 await awaitMessage(dc2);
150 assert_equals(dc1.bufferedAmount, 0,
151 'Expect sender bufferedAmount to be reduced after message is sent');
152}, 'bufferedAmount should increase to size of blob sent');
153
154// Test sending 3 messages: helloBuffer, unicodeString, helloBlob
155promise_test(async (t) => {
156 const resolver = new Resolver();
157 const pc1 = new RTCPeerConnection();
158 const pc2 = new RTCPeerConnection();
159 t.add_cleanup(() => pc1.close());
160 t.add_cleanup(() => pc2.close());
161
162 let messageCount = 0;
163
164 const [dc1, dc2] = await createDataChannelPair(pc1, pc2);
165 const onMessage = t.step_func(() => {
166 if (++messageCount === 3) {
167 assert_equals(dc1.bufferedAmount, 0,
168 'Expect sender bufferedAmount to be reduced after message is sent');
169 resolver.resolve();
170 }
171 });
172
173 dc2.addEventListener('message', onMessage);
174
175 dc1.send(helloBuffer);
176 assert_equals(dc1.bufferedAmount, helloString.length,
177 'Expect bufferedAmount to be the total length of all messages queued to send');
178
179 dc1.send(unicodeString);
180 assert_equals(dc1.bufferedAmount,
181 helloString.length + unicodeBuffer.byteLength,
182 'Expect bufferedAmount to be the total length of all messages queued to send');
183
184 dc1.send(helloBlob);
185 assert_equals(dc1.bufferedAmount,
186 helloString.length*2 + unicodeBuffer.byteLength,
187 'Expect bufferedAmount to be the total length of all messages queued to send');
188
189 await resolver;
190}, 'bufferedAmount should increase by byte length for each message sent');
191
192promise_test(async (t) => {
193 const pc1 = new RTCPeerConnection();
194 const pc2 = new RTCPeerConnection();
195 t.add_cleanup(() => pc1.close());
196 t.add_cleanup(() => pc2.close());
197
198 const [dc1] = await createDataChannelPair(pc1, pc2);
199
200 dc1.send(helloBuffer.buffer);
201 assert_equals(dc1.bufferedAmount, helloBuffer.byteLength,
202 'Expect bufferedAmount to increase to byte length of sent buffer');
203
204 dc1.close();
205 assert_equals(dc1.bufferedAmount, helloBuffer.byteLength,
206 'Expect bufferedAmount to not decrease immediately after closing the channel');
207}, 'bufferedAmount should not decrease immediately after initiating closure');
208
209promise_test(async (t) => {
210 const pc1 = new RTCPeerConnection();
211 const pc2 = new RTCPeerConnection();
212 t.add_cleanup(() => pc1.close());
213 t.add_cleanup(() => pc2.close());
214
215 const [dc1] = await createDataChannelPair(pc1, pc2);
216
217 dc1.send(helloBuffer.buffer);
218 assert_equals(dc1.bufferedAmount, helloBuffer.byteLength,
219 'Expect bufferedAmount to increase to byte length of sent buffer');
220
221 pc1.close();
222 assert_equals(dc1.bufferedAmount, helloBuffer.byteLength,
223 'Expect bufferedAmount to not decrease after closing the peer connection');
224}, 'bufferedAmount should not decrease after closing the peer connection');
Soares Chen17354db2017-06-13 18:39:04225
Marina Ciocea791052b2019-03-12 06:56:04226 promise_test(async t => {
227 const [channel1, channel2] = await createDataChannelPair();
228 channel1.addEventListener('bufferedamountlow', t.step_func_done(() => {
229 assert_true(channel1.bufferedAmount <= channel1.bufferedAmountLowThreshold);
230 }));
231 const eventWatcher = new EventWatcher(t, channel1, ['bufferedamountlow']);
232 channel1.send(helloString);
233 await eventWatcher.wait_for(['bufferedamountlow']);
234 }, 'Data channel bufferedamountlow event fires after send() is complete');
235
236 promise_test(async t => {
237 const [channel1, channel2] = await createDataChannelPair();
238 channel1.send(helloString);
239 assert_equals(channel1.bufferedAmount, helloString.length);
240 await awaitMessage(channel2);
241 assert_equals(channel1.bufferedAmount, 0);
242 }, 'Data channel bufferedamount is data.length on send(data)');
243
244 promise_test(async t => {
245 const [channel1, channel2] = await createDataChannelPair();
246 channel1.send(helloString);
247 assert_equals(channel1.bufferedAmount, helloString.length);
248 assert_equals(channel1.bufferedAmount, helloString.length);
249 }, 'Data channel bufferedamount returns the same amount if no more data is' +
250 ' sent on the channel');
251
252 promise_test(async t => {
253 const [channel1, channel2] = await createDataChannelPair();
254 let eventFireCount = 0;
255 channel1.addEventListener('bufferedamountlow', t.step_func(() => {
256 assert_true(channel1.bufferedAmount <= channel1.bufferedAmountLowThreshold);
257 assert_equals(++eventFireCount, 1);
258 }));
259 const eventWatcher = new EventWatcher(t, channel1, ['bufferedamountlow']);
260 channel1.send(helloString);
261 assert_equals(channel1.bufferedAmount, helloString.length);
262 channel1.send(helloString);
263 assert_equals(channel1.bufferedAmount, 2 * helloString.length);
264 await eventWatcher.wait_for(['bufferedamountlow']);
265 }, 'Data channel bufferedamountlow event fires only once after multiple' +
266 ' consecutive send() calls');
267
268 promise_test(async t => {
269 const [channel1, channel2] = await createDataChannelPair();
270 const eventWatcher = new EventWatcher(t, channel1, ['bufferedamountlow']);
271 channel1.send(helloString);
272 assert_equals(channel1.bufferedAmount, helloString.length);
273 await eventWatcher.wait_for(['bufferedamountlow']);
274 assert_equals(await awaitMessage(channel2), helloString);
275 channel1.send(helloString);
276 assert_equals(channel1.bufferedAmount, helloString.length);
277 await eventWatcher.wait_for(['bufferedamountlow']);
278 assert_equals(await awaitMessage(channel2), helloString);
279 }, 'Data channel bufferedamountlow event fires after each sent message');
280
Soares Chen17354db2017-06-13 18:39:04281</script>