50 lines
1.5 KiB
TypeScript
50 lines
1.5 KiB
TypeScript
|
|
/**
|
||
|
|
* Glare = both peers initiate at the same instant. The manager resolves
|
||
|
|
* deterministically: the address with the lexically-larger value yields
|
||
|
|
* to the smaller one's offer.
|
||
|
|
*/
|
||
|
|
import { afterEach, describe, expect, it } from 'bun:test';
|
||
|
|
import { MemoryRtcFactory } from '../src/memory-rtc.js';
|
||
|
|
import { MemoryShadeBridge, WebRtcSignalingChannel } from '../src/signaling.js';
|
||
|
|
import { WebRtcConnectionManager } from '../src/manager.js';
|
||
|
|
|
||
|
|
afterEach(() => {
|
||
|
|
MemoryRtcFactory.reset();
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('Glare resolution', () => {
|
||
|
|
it('two simultaneous getOrCreate() calls converge on a single connection', async () => {
|
||
|
|
const { a, b } = MemoryShadeBridge.linked('alice', 'bob');
|
||
|
|
const aliceSig = new WebRtcSignalingChannel(a);
|
||
|
|
const bobSig = new WebRtcSignalingChannel(b);
|
||
|
|
const factory = new MemoryRtcFactory();
|
||
|
|
const alice = new WebRtcConnectionManager({ factory, signaling: aliceSig });
|
||
|
|
const bob = new WebRtcConnectionManager({
|
||
|
|
factory,
|
||
|
|
signaling: bobSig,
|
||
|
|
receiver: {
|
||
|
|
async onChunk() {
|
||
|
|
return { lastSeq: 0 };
|
||
|
|
},
|
||
|
|
async onResumeQuery() {
|
||
|
|
return null;
|
||
|
|
},
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
// Both kick off at once.
|
||
|
|
const [aConn, bConn] = await Promise.all([
|
||
|
|
alice.getOrCreate('bob'),
|
||
|
|
bob.getOrCreate('alice'),
|
||
|
|
]);
|
||
|
|
|
||
|
|
expect(aConn.state).toBe('connected');
|
||
|
|
expect(bConn.state).toBe('connected');
|
||
|
|
expect(alice.isConnected('bob')).toBe(true);
|
||
|
|
expect(bob.isConnected('alice')).toBe(true);
|
||
|
|
|
||
|
|
alice.destroy();
|
||
|
|
bob.destroy();
|
||
|
|
});
|
||
|
|
});
|