11/**
22 * Test utilities for y-websocket protocol testing.
33 *
4- * Provides helpers for building valid and invalid protocol messages,
5- * and utilities for test coordination.
4+ * Provides helpers for building invalid/malformed messages and test coordination.
65 *
7- * NOTE: For MESSAGE_TYPE, decodeSyncMessage, and decodeMessageType ,
6+ * NOTE: For protocol functions ( MESSAGE_TYPE, encodeSyncStep1, etc.) ,
87 * import directly from '../../src/server/sync/protocol'.
98 */
109
1110import * as encoding from 'lib0/encoding' ;
12- import * as awarenessProtocol from 'y-protocols/awareness' ;
13- import * as syncProtocol from 'y-protocols/sync' ;
1411import * as Y from 'yjs' ;
15- import { MESSAGE_TYPE } from '../../src/server/sync/protocol' ;
1612
1713// ============================================================================
18- // Valid Message Builders
14+ // Invalid/Malformed Message Builders (for edge case testing)
1915// ============================================================================
2016
2117/**
22- * Build a sync step 1 message containing a state vector .
23- * This is what a client sends to ask "what updates are you missing?"
18+ * Build a truncated message of the specified type .
19+ * Contains only the message type byte with no payload.
2420 */
25- export function buildSyncStep1 ( doc : Y . Doc ) : Uint8Array {
21+ export function buildTruncatedMessage ( messageType : number ) : Uint8Array {
2622 return encoding . encode ( ( encoder ) => {
27- encoding . writeVarUint ( encoder , MESSAGE_TYPE . SYNC ) ;
28- syncProtocol . writeSyncStep1 ( encoder , doc ) ;
23+ encoding . writeVarUint ( encoder , messageType ) ;
2924 } ) ;
3025}
3126
3227/**
33- * Build a sync step 2 message containing a document diff.
34- * This is the response to sync step 1.
28+ * Build a message with an unknown message type.
3529 */
36- export function buildSyncStep2 ( doc : Y . Doc , stateVector ?: Uint8Array ) : Uint8Array {
30+ export function buildUnknownTypeMessage ( unknownType : number ) : Uint8Array {
3731 return encoding . encode ( ( encoder ) => {
38- encoding . writeVarUint ( encoder , MESSAGE_TYPE . SYNC ) ;
39- if ( stateVector ) {
40- // Generate diff based on provided state vector
41- const update = Y . encodeStateAsUpdate ( doc , stateVector ) ;
42- syncProtocol . writeUpdate ( encoder , update ) ;
43- } else {
44- // Write full document as sync step 2
45- syncProtocol . writeSyncStep2 ( encoder , doc ) ;
46- }
32+ encoding . writeVarUint ( encoder , unknownType ) ;
33+ encoding . writeVarString ( encoder , 'unknown payload' ) ;
4734 } ) ;
4835}
4936
5037/**
51- * Build a sync update message containing incremental changes .
38+ * Build an awareness message with malformed JSON state .
5239 */
53- export function buildSyncUpdate ( update : Uint8Array ) : Uint8Array {
54- return encoding . encode ( ( encoder ) => {
55- encoding . writeVarUint ( encoder , MESSAGE_TYPE . SYNC ) ;
56- syncProtocol . writeUpdate ( encoder , update ) ;
40+ export function buildMalformedAwarenessMessage ( ) : Uint8Array {
41+ const MESSAGE_TYPE_AWARENESS = 1 ;
42+
43+ // Create a raw awareness update with invalid JSON
44+ const innerUpdate = encoding . encode ( ( encoder ) => {
45+ encoding . writeVarUint ( encoder , 1 ) ; // 1 entry
46+ encoding . writeVarUint ( encoder , 12345 ) ; // clientId
47+ encoding . writeVarUint ( encoder , 1 ) ; // clock
48+ encoding . writeVarString ( encoder , '{invalid json}' ) ; // malformed JSON
5749 } ) ;
58- }
5950
60- /**
61- * Build an awareness update message.
62- */
63- export function buildAwarenessUpdate (
64- awareness : awarenessProtocol . Awareness ,
65- clientIds ?: number [ ] ,
66- ) : Uint8Array {
67- const clients = clientIds ?? Array . from ( awareness . getStates ( ) . keys ( ) ) ;
68- const update = awarenessProtocol . encodeAwarenessUpdate ( awareness , clients ) ;
6951 return encoding . encode ( ( encoder ) => {
70- encoding . writeVarUint ( encoder , MESSAGE_TYPE . AWARENESS ) ;
71- encoding . writeVarUint8Array ( encoder , update ) ;
52+ encoding . writeVarUint ( encoder , MESSAGE_TYPE_AWARENESS ) ;
53+ encoding . writeVarUint8Array ( encoder , innerUpdate ) ;
7254 } ) ;
7355}
7456
7557/**
7658 * Build a raw awareness update message from explicit data.
7759 * Useful for testing malformed or edge case awareness states.
7860 */
79- export function buildRawAwarenessMessage ( entries : Array < {
80- clientId : number ;
81- clock : number ;
82- state : string | null ; // JSON string or null
83- } > ) : Uint8Array {
61+ export function buildRawAwarenessMessage (
62+ entries : Array < {
63+ clientId : number ;
64+ clock : number ;
65+ state : string | null ; // JSON string or null
66+ } > ,
67+ ) : Uint8Array {
68+ const MESSAGE_TYPE_AWARENESS = 1 ;
69+
8470 // Build the inner awareness update
8571 const innerUpdate = encoding . encode ( ( encoder ) => {
8672 encoding . writeVarUint ( encoder , entries . length ) ;
@@ -93,58 +79,7 @@ export function buildRawAwarenessMessage(entries: Array<{
9379
9480 // Wrap in message envelope
9581 return encoding . encode ( ( encoder ) => {
96- encoding . writeVarUint ( encoder , MESSAGE_TYPE . AWARENESS ) ;
97- encoding . writeVarUint8Array ( encoder , innerUpdate ) ;
98- } ) ;
99- }
100-
101- /**
102- * Build a query awareness message.
103- */
104- export function buildQueryAwareness ( ) : Uint8Array {
105- return encoding . encode ( ( encoder ) => {
106- encoding . writeVarUint ( encoder , MESSAGE_TYPE . QUERY_AWARENESS ) ;
107- } ) ;
108- }
109-
110- // ============================================================================
111- // Invalid/Malformed Message Builders (for edge case testing)
112- // ============================================================================
113-
114- /**
115- * Build a truncated message of the specified type.
116- * Contains only the message type byte with no payload.
117- */
118- export function buildTruncatedMessage ( messageType : number ) : Uint8Array {
119- return encoding . encode ( ( encoder ) => {
120- encoding . writeVarUint ( encoder , messageType ) ;
121- } ) ;
122- }
123-
124- /**
125- * Build a message with an unknown message type.
126- */
127- export function buildUnknownTypeMessage ( unknownType : number ) : Uint8Array {
128- return encoding . encode ( ( encoder ) => {
129- encoding . writeVarUint ( encoder , unknownType ) ;
130- encoding . writeVarString ( encoder , 'unknown payload' ) ;
131- } ) ;
132- }
133-
134- /**
135- * Build an awareness message with malformed JSON state.
136- */
137- export function buildMalformedAwarenessMessage ( ) : Uint8Array {
138- // Create a raw awareness update with invalid JSON
139- const innerUpdate = encoding . encode ( ( encoder ) => {
140- encoding . writeVarUint ( encoder , 1 ) ; // 1 entry
141- encoding . writeVarUint ( encoder , 12345 ) ; // clientId
142- encoding . writeVarUint ( encoder , 1 ) ; // clock
143- encoding . writeVarString ( encoder , '{invalid json}' ) ; // malformed JSON
144- } ) ;
145-
146- return encoding . encode ( ( encoder ) => {
147- encoding . writeVarUint ( encoder , MESSAGE_TYPE . AWARENESS ) ;
82+ encoding . writeVarUint ( encoder , MESSAGE_TYPE_AWARENESS ) ;
14883 encoding . writeVarUint8Array ( encoder , innerUpdate ) ;
14984 } ) ;
15085}
@@ -187,7 +122,10 @@ export function wait(ms: number): Promise<void> {
187122/**
188123 * Create a Y.Doc with some initial content for testing.
189124 */
190- export function createTestDoc ( content ?: { mapKey ?: string ; mapValue ?: string } ) : Y . Doc {
125+ export function createTestDoc ( content ?: {
126+ mapKey ?: string ;
127+ mapValue ?: string ;
128+ } ) : Y . Doc {
191129 const doc = new Y . Doc ( ) ;
192130 if ( content ) {
193131 doc . getMap ( 'test' ) . set ( content . mapKey ?? 'key' , content . mapValue ?? 'value' ) ;
@@ -223,7 +161,9 @@ export function parseWsMessage(data: unknown): Uint8Array | null {
223161 try {
224162 const parsed = JSON . parse ( data ) ;
225163 if ( typeof parsed === 'object' && parsed !== null ) {
226- const keys = Object . keys ( parsed ) . map ( Number ) . sort ( ( a , b ) => a - b ) ;
164+ const keys = Object . keys ( parsed )
165+ . map ( Number )
166+ . sort ( ( a , b ) => a - b ) ;
227167 const arr = new Uint8Array ( keys . length ) ;
228168 for ( let i = 0 ; i < keys . length ; i ++ ) {
229169 arr [ i ] = parsed [ keys [ i ] ] ;
0 commit comments