@@ -558,3 +558,71 @@ func TestSoftFailedStickyEvents(t *testing.T) {
558558 mustHaveStickyEventID (t , stickyEventID , syncResp .stickyEvents )
559559 })
560560}
561+
562+ func TestStickyEventsChunkedInSync (t * testing.T ) {
563+ deployment := complement .Deploy (t , 1 )
564+ defer deployment .Destroy (t )
565+
566+ alice := deployment .Register (t , "hs1" , helpers.RegistrationOpts {})
567+ bob := deployment .Register (t , "hs1" , helpers.RegistrationOpts {})
568+
569+ roomID := alice .MustCreateRoom (t , map [string ]interface {}{"preset" : "public_chat" })
570+ bob .MustJoinRoom (t , roomID , []spec.ServerName {"hs1" })
571+ _ , bobSince := bob .MustSync (t , client.SyncReq {})
572+ t .Logf ("before any sticky events: since=%s" , bobSince )
573+
574+ // This test assumes 3x /sync requests is enough to see all numMsgsToSend.
575+ // This test assumes 1x /sync will not return more than expectedMaxChunk sticky events.
576+ // As such, this test allows servers to return ceiling(numMsgsToSend/3) ~ expectedMaxChunk events
577+ // per /sync request.
578+ // Currently this means 84-230 per /sync.
579+ numMsgsToSend := 250
580+ expectedMaxChunk := 230
581+
582+ // send many sticky events
583+ stickyEventIDs := make (map [string ]bool )
584+ for i := 0 ; i < numMsgsToSend ; i ++ {
585+ eventID := sendStickyEvent (t , alice , roomID , b.Event {
586+ Type : "m.room.message" ,
587+ Content : map [string ]interface {}{
588+ "msgtype" : "m.text" ,
589+ "body" : fmt .Sprintf ("msg %d" , i ),
590+ },
591+ }, withStickyDuration (1000 * 60 * 30 ))
592+ stickyEventIDs [eventID ] = true
593+ }
594+
595+ // do a single /sync request on bob
596+ resp , bobSince := bob .MustSync (t , client.SyncReq {Since : bobSince })
597+ t .Logf ("after 1st /sync: since=%s" , bobSince )
598+
599+ removeStickyEvents := func (resp gjson.Result ) {
600+ // bob should not see all the sticky events.
601+ // This includes timeline events (e.g N-25 sticky events + 25 timeline events is still N sticky events).
602+ sticky := resp .Get ("rooms.join." + client .GjsonEscape (roomID ) + ".msc4354_sticky.events" ).Array ()
603+ for _ , ev := range sticky {
604+ delete (stickyEventIDs , ev .Get ("event_id" ).Str )
605+ }
606+ timeline := resp .Get ("rooms.join." + client .GjsonEscape (roomID ) + ".timeline.events" ).Array ()
607+ for _ , ev := range timeline {
608+ delete (stickyEventIDs , ev .Get ("event_id" ).Str )
609+ }
610+ t .Logf ("/sync contained %d sticky events and %d timeline events" , len (sticky ), len (timeline ))
611+ }
612+ removeStickyEvents (resp )
613+
614+ // we expect a max chunk of expectedMaxChunk
615+ if len (stickyEventIDs ) < (numMsgsToSend - expectedMaxChunk ) {
616+ ct .Fatalf (t , "sent %d sticky events, first sync contained %d, too many sticky events in one /sync" , numMsgsToSend , numMsgsToSend - len (stickyEventIDs ))
617+ }
618+
619+ resp , bobSince = bob .MustSync (t , client.SyncReq {Since : bobSince , TimeoutMillis : "0" })
620+ t .Logf ("after 2nd /sync: since=%s" , bobSince )
621+ removeStickyEvents (resp )
622+ resp , _ = bob .MustSync (t , client.SyncReq {Since : bobSince , TimeoutMillis : "0" })
623+ t .Logf ("after 3rd /sync: since=%s" , bobSince )
624+ removeStickyEvents (resp )
625+ if len (stickyEventIDs ) != 0 {
626+ ct .Fatalf (t , "failed to see all sticky events, missing %d" , len (stickyEventIDs ))
627+ }
628+ }
0 commit comments