Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Ensure create event appears in a valid section of the v2 response #690

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 115 additions & 1 deletion tests/federation_room_join_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"net/http"
"net/url"
"strings"
"sync"
"sync/atomic"
"testing"
"time"

Expand All @@ -22,8 +24,8 @@ import (

"github.com/matrix-org/complement/b"
"github.com/matrix-org/complement/client"
"github.com/matrix-org/complement/helpers"
"github.com/matrix-org/complement/federation"
"github.com/matrix-org/complement/helpers"
"github.com/matrix-org/complement/match"
"github.com/matrix-org/complement/must"
"github.com/matrix-org/complement/runtime"
Expand Down Expand Up @@ -605,3 +607,115 @@ func TestJoinFederatedRoomFromApplicationServiceBridgeUser(t *testing.T) {
as.MustJoinRoom(t, roomID, []string{"hs2"})
})
}

// Regression test for https://github.com/matrix-org/sliding-sync/issues/367
// This test won't always be able to reproduce the precise conditions for the bug to surface,
// so it may appear flakey.
func TestSeesCreateEvent(t *testing.T) {
deployment := complement.Deploy(t, 2)
defer deployment.Destroy(t)
var wg sync.WaitGroup
wg.Add(1)

alice := deployment.Register(t, "hs1", helpers.RegistrationOpts{})
bob := deployment.Register(t, "hs2", helpers.RegistrationOpts{})

roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "trusted_private_chat",
})
alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(alice.UserID, roomID))

// bob is actively syncing prior to the invite
_, bobSince := bob.MustSync(t, client.SyncReq{
TimeoutMillis: "1",
})
var start *time.Time
var stopSendingMsgs atomic.Bool
var mu sync.Mutex
liveSync := func() {
seenRoom := false
for {
mu.Lock()
if start != nil && time.Since(*start) > time.Second {
break
}
mu.Unlock()

var bobSyncResponse gjson.Result
t.Logf("since=%s", bobSince)
bobSyncResponse, bobSince = bob.MustSync(t, client.SyncReq{
Since: bobSince,
})
room := bobSyncResponse.Get("rooms.join." + client.GjsonEscape(roomID))
if !room.Exists() {
continue
}
seenRoom = true
// make sure that either:
// 1: the create event is in `state`
// 2: the create event is in `timeline[0]` with nothing in `state`.
firstTimelineEvent := room.Get("timeline.events[0]")
createInStateBlock := false
hasStateBlock := false
for _, ev := range room.Get("state.events").Array() {
hasStateBlock = true
if ev.Get("type").Str == "m.room.create" {
createInStateBlock = true
break
}
}
// 1: the create event is in `state`
if createInStateBlock {
break
}
// 2: the create event is in `timeline[0]` with nothing in `state`.
if firstTimelineEvent.Get("type").Str == "m.room.create" && !hasStateBlock {
break
}

raw := json.RawMessage(bobSyncResponse.Raw)
var v interface{}
must.NotError(t, "Unmarshal", json.Unmarshal(raw, &v))

out, err := json.MarshalIndent(v, "", " ")
must.NotError(t, "MarshalIndent", err)
t.Errorf("m.room.create event is in an invalid position in the response => %v", string(out))
break
}
if !seenRoom {
t.Errorf("failed to see room %s", roomID)
}
wg.Done()
}

// alice invites bob and he sees it
alice.InviteRoom(t, roomID, bob.UserID)
go liveSync()
go func() {
for i := 0; i < 20; i++ {
if stopSendingMsgs.Load() {
break
}
alice.Unsafe_SendEventUnsynced(t, roomID, b.Event{
Type: "m.room.message",
Content: map[string]interface{}{
"msgtype": "m.text",
"body": fmt.Sprintf("Hello %d", i),
},
})
time.Sleep(time.Millisecond * 50)
}
}()
// bob accepts the invite: he should see the create event in state
bob.MustJoinRoom(t, roomID, []string{"hs1"})

stopSendingMsgs.Store(true)

// poll for 1s longer after scrollback
mu.Lock()
now := time.Now()
start = &now
mu.Unlock()

wg.Wait()
}
Loading