From 46b17ae3481274cf97cc87e5290199e788c25814 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 17 Sep 2025 16:59:55 +0100 Subject: [PATCH] test: recieve lots of data Adds a test that opens a datachannel. When the remote receives notification of the new channel it writes lots of data into it and closes the channel. The local peer counts the received bytes and asserts that it received them all. This test currently fails intermittently, largely down to the amount of load the process is under at the time. You can run similar code in a browser here: https://codepen.io/achingbrain/pen/KwVPZBP?editors=0012 This works in Chrome and Firefox Nightly, though Firefox is a bit slow. --- test/fixtures/connect.ts | 26 +++++++++ test/jest-tests/polyfill.test.ts | 98 ++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 test/fixtures/connect.ts diff --git a/test/fixtures/connect.ts b/test/fixtures/connect.ts new file mode 100644 index 0000000..7834813 --- /dev/null +++ b/test/fixtures/connect.ts @@ -0,0 +1,26 @@ +import { eventPromise } from './event-promise'; + +export async function connect (peer1: RTCPeerConnection, peer2: RTCPeerConnection): Promise { + const dc: RTCDataChannel = peer1.createDataChannel(''); + + // Actions + const peer1Offer = await peer1.createOffer(); + await peer2.setRemoteDescription(peer1Offer); + + const peer2Answer = await peer2.createAnswer(); + await peer1.setRemoteDescription(peer2Answer); + + peer1.addEventListener('icecandidate', (e: RTCPeerConnectionIceEvent) => { + peer2.addIceCandidate(e.candidate); + }); + + peer2.addEventListener('icecandidate', (e: RTCPeerConnectionIceEvent) => { + peer1.addIceCandidate(e.candidate); + }); + + await eventPromise(dc, 'open'); + + dc.close(); + + await eventPromise(dc, 'close'); +} diff --git a/test/jest-tests/polyfill.test.ts b/test/jest-tests/polyfill.test.ts index 77fad5b..b145138 100644 --- a/test/jest-tests/polyfill.test.ts +++ b/test/jest-tests/polyfill.test.ts @@ -3,6 +3,7 @@ import { expect, jest } from '@jest/globals'; import { RTCPeerConnection } from '../../src/polyfill/index'; import { PeerConnection } from '../../src/lib/index'; import { eventPromise } from '../fixtures/event-promise'; +import { connect } from '../fixtures/connect'; // Polyfill for Promise.withResolvers for Node < 20 if (!Promise.withResolvers) { @@ -328,4 +329,101 @@ describe('polyfill', () => { expect(spy).toHaveBeenCalled(); expect(connectionState).toEqual(originalFunc()); }); + + test('it should send lots of data', async () => { + const chunkSize = 1024; + const count = 1024 * 10; + const bytes = chunkSize * count; + let received = 0; + + const peer1 = new RTCPeerConnection(); + const peer2 = new RTCPeerConnection(); + + await connect(peer1, peer2); + + const receivedAllMessages = Promise.withResolvers(); + + const incomingChannelPromise = Promise.withResolvers(); + let incomingChannel + + peer2.ondatachannel = async (evt): Promise => { + // prevent gc of channel + incomingChannelPromise.resolve(evt.channel) + incomingChannel = evt.channel; + + incomingChannel.onmessage = (evt): void => { + received += evt.data.byteLength; + + if (received === bytes) { + receivedAllMessages.resolve(); + } + } + }; + + const outgoingChannel = peer1.createDataChannel(''); + await eventPromise(outgoingChannel, 'open') + + for (let i = 0; i < count; i++) { + outgoingChannel.send(new Uint8Array(chunkSize)); + } + + outgoingChannel.close(); + + await Promise.any([ + receivedAllMessages.promise, + incomingChannelPromise.promise.then(channel => { + return eventPromise(channel, 'close') + }) + ]); + + expect(received).toEqual(bytes); + + peer1.close(); + peer2.close(); + }); + + test('it should receive lots of data', async () => { + const chunkSize = 1024; + const count = 1024 * 10; + const bytes = chunkSize * count; + + const peer1 = new RTCPeerConnection(); + const peer2 = new RTCPeerConnection(); + + await connect(peer1, peer2); + + const receivedAllMessages = Promise.withResolvers(); + + peer2.ondatachannel = async (evt): Promise => { + const channel = evt.channel; + channel.bufferedAmountLowThreshold = 0; + + for (let i = 0; i < count; i++) { + channel.send(new Uint8Array(chunkSize)); + } + + channel.close(); + }; + + const dc = peer1.createDataChannel(''); + let received = 0; + + dc.onmessage = (evt): void => { + received += evt.data.byteLength; + + if (received === bytes) { + receivedAllMessages.resolve(); + } + }; + + await Promise.any([ + receivedAllMessages.promise, + eventPromise(dc, 'close') + ]); + + expect(received).toEqual(bytes); + + peer1.close(); + peer2.close(); + }); });