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

Add tests for EDUs during fast joins #465

Merged
merged 21 commits into from
Oct 26, 2022
Merged
Changes from 3 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
245 changes: 244 additions & 1 deletion tests/federation_room_join_partial_state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,249 @@ func TestPartialStateJoin(t *testing.T) {
t.Logf("Alice sent event event ID %s", eventID)
})

// we should be able to receive typing EDU over federation during the resync
t.Run("CanReceiveTypingDuringPartialStateJoin", func(t *testing.T) {
deployment := Deploy(t, b.BlueprintAlice)
defer deployment.Destroy(t)
alice := deployment.Client(t, "hs1", "@alice:hs1")

server := createTestServer(t, deployment)
cancel := server.Listen()
defer cancel()
serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t))
psjResult := beginPartialStateJoin(t, server, serverRoom, alice)
defer psjResult.Destroy()

derekUserId := psjResult.Server.UserID("derek")

content, _ := json.Marshal(map[string]interface{}{
"room_id": serverRoom.RoomID,
"user_id": derekUserId,
"typing": true,
})
edu := gomatrixserverlib.EDU{
Type: "m.typing",
Content: content,
}
DMRobertson marked this conversation as resolved.
Show resolved Hide resolved
psjResult.Server.MustSendTransaction(t, deployment, "hs1", []json.RawMessage{}, []gomatrixserverlib.EDU{edu})

psjResult.FinishStateRequest()
DMRobertson marked this conversation as resolved.
Show resolved Hide resolved
alice.MustSyncUntil(t,
DMRobertson marked this conversation as resolved.
Show resolved Hide resolved
DMRobertson marked this conversation as resolved.
Show resolved Hide resolved
client.SyncReq{},
client.SyncEphemeralHas(serverRoom.RoomID, func(result gjson.Result) bool {
if result.Get("type").Str != "m.typing" {
return false
}
for _, item := range result.Get("content").Get("user_ids").Array() {
if item.Str == derekUserId {
return true
}
}
return false
DMRobertson marked this conversation as resolved.
Show resolved Hide resolved
}),
)
})

// we should be able to receive presence EDU over federation during the resync
t.Run("CanReceivePresenceDuringPartialStateJoin", func(t *testing.T) {
deployment := Deploy(t, b.BlueprintAlice)
defer deployment.Destroy(t)
alice := deployment.Client(t, "hs1", "@alice:hs1")

server := createTestServer(t, deployment)
cancel := server.Listen()
defer cancel()
serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t))
psjResult := beginPartialStateJoin(t, server, serverRoom, alice)
defer psjResult.Destroy()

derekUserId := psjResult.Server.UserID("derek")

content, _ := json.Marshal(map[string]interface{}{
"push": []map[string]interface{}{
map[string]interface{}{
"user_id": derekUserId,
"presence": "online",
"last_active_ago": 100,
},
},
})
edu := gomatrixserverlib.EDU{
Type: "m.presence",
Content: content,
}
psjResult.Server.MustSendTransaction(t, deployment, "hs1", []json.RawMessage{}, []gomatrixserverlib.EDU{edu})

// for now we just check that the fed transaction is accepted,
// presence is not always going down the sync for some reason

// psjResult.FinishStateRequest()
// alice.MustSyncUntil(t,
// client.SyncReq{},
// func(userID string, sync gjson.Result) error {
// for _, e := range sync.Get("presence").Get("events").Array() {
// t.Logf("lllll %s", e)
// if e.Get("sender").Str == derekUserId {
// return nil
// }
// }
// return fmt.Errorf("No presence update from %s", derekUserId)
// },
// )
DMRobertson marked this conversation as resolved.
Show resolved Hide resolved
})

// we should be able to receive to_device EDU over federation during the resync
t.Run("CanReceiveToDeviceDuringPartialStateJoin", func(t *testing.T) {
deployment := Deploy(t, b.BlueprintAlice)
defer deployment.Destroy(t)
alice := deployment.Client(t, "hs1", "@alice:hs1")

server := createTestServer(t, deployment)
cancel := server.Listen()
defer cancel()
serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t))
psjResult := beginPartialStateJoin(t, server, serverRoom, alice)
defer psjResult.Destroy()

derekUserId := psjResult.Server.UserID("derek")

content, _ := json.Marshal(map[string]interface{}{
"message_id": "hiezohf6Hoo7kaev",
"sender": derekUserId,
"type": "m.test",
"messages": map[string]interface{}{
alice.UserID: map[string]interface{}{
"*": map[string]interface{}{},
},
},
})
edu := gomatrixserverlib.EDU{
Type: "m.direct_to_device",
Content: content,
}
psjResult.Server.MustSendTransaction(t, deployment, "hs1", []json.RawMessage{}, []gomatrixserverlib.EDU{edu})

psjResult.FinishStateRequest()
alice.MustSyncUntil(t,
client.SyncReq{},
func(userID string, sync gjson.Result) error {
for _, e := range sync.Get("to_device").Get("events").Array() {
if e.Get("sender").Str == derekUserId && e.Get("type").Str == "m.test" {
return nil
}
}
return fmt.Errorf("No to_device update from %s", derekUserId)
},
)
})

// we should be able to receive receipt EDU over federation during the resync
t.Run("CanReceiveReceiptDuringPartialStateJoin", func(t *testing.T) {
deployment := Deploy(t, b.BlueprintAlice)
defer deployment.Destroy(t)
alice := deployment.Client(t, "hs1", "@alice:hs1")

server := createTestServer(t, deployment)
cancel := server.Listen()
defer cancel()
serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t))
psjResult := beginPartialStateJoin(t, server, serverRoom, alice)
defer psjResult.Destroy()

derekUserId := psjResult.Server.UserID("derek")

content, _ := json.Marshal(map[string]interface{}{
serverRoom.RoomID: map[string]interface{}{
"m.read": map[string]interface{}{
derekUserId: map[string]interface{}{
"data": map[string]interface{}{
"ts": 1436451550453,
},
"event_ids": []string{"mytesteventid"},
},
},
},
})
edu := gomatrixserverlib.EDU{
Type: "m.receipt",
Content: content,
}
psjResult.Server.MustSendTransaction(t, deployment, "hs1", []json.RawMessage{}, []gomatrixserverlib.EDU{edu})

psjResult.FinishStateRequest()
alice.MustSyncUntil(t,
client.SyncReq{},
client.SyncEphemeralHas(serverRoom.RoomID, func(result gjson.Result) bool {
if result.Get("type").Str != "m.receipt" {
return false
}

if result.Get("content").Get("mytesteventid").Get("m\\.read").Get(strings.Replace(derekUserId, ".", "\\.", -1)).Get("ts").Int() == 1436451550453 {
return true
}
return false
}),
)
})

// we should be able to receive device list update EDU over federation during the resync
t.Run("CanReceiveDeviceListUpdateDuringPartialStateJoin", func(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit dubious about this test TBH, I don't think it tests anything particularly useful as is and may just cause confusion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't fully follow this either. Shouldn't the device list update be send to Alice, even if she and Derek aren't in an encrypted room?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As in: Alice should get told via /sync that Derek's device list has changed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Synapse currently, yes, though its a bit of a grey area and we've certainly talked about only sending device list updates for E2EE enabled devices and/or users who share rooms.

OTOH, I think all the current integration tests assume this, so I don't see a problem assuming it here

deployment := Deploy(t, b.BlueprintAlice)
defer deployment.Destroy(t)
alice := deployment.Client(t, "hs1", "@alice:hs1")

server := createTestServer(t, deployment)
cancel := server.Listen()
defer cancel()
serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t))
psjResult := beginPartialStateJoin(t, server, serverRoom, alice)
defer psjResult.Destroy()

derekUserId := psjResult.Server.UserID("derek")

content, _ := json.Marshal(map[string]interface{}{
"device_id": "QBUAZIFURK",
"stream_id": 1,
"user_id": derekUserId,
})
edu := gomatrixserverlib.EDU{
Type: "m.device_list_update",
Content: content,
}
psjResult.Server.MustSendTransaction(t, deployment, "hs1", []json.RawMessage{}, []gomatrixserverlib.EDU{edu})

// If we want to check the sync we need to have an encrypted room,
// for now just check that the fed transaction is accepted.
})

// we should be able to receive signing key update EDU over federation during the resync
t.Run("CanReceiveSigningKeyUpdateDuringPartialStateJoin", func(t *testing.T) {
deployment := Deploy(t, b.BlueprintAlice)
defer deployment.Destroy(t)
alice := deployment.Client(t, "hs1", "@alice:hs1")

server := createTestServer(t, deployment)
cancel := server.Listen()
defer cancel()
serverRoom := createTestRoom(t, server, alice.GetDefaultRoomVersion(t))
psjResult := beginPartialStateJoin(t, server, serverRoom, alice)
defer psjResult.Destroy()

derekUserId := psjResult.Server.UserID("derek")

content, _ := json.Marshal(map[string]interface{}{
"user_id": derekUserId,
})
edu := gomatrixserverlib.EDU{
Type: "m.signing_key_update",
Content: content,
}
psjResult.Server.MustSendTransaction(t, deployment, "hs1", []json.RawMessage{}, []gomatrixserverlib.EDU{edu})

// If we want to check the sync we need to have an encrypted room,
// for now just check that the fed transaction is accepted.
})

// we should be able to receive events over federation during the resync
t.Run("CanReceiveEventsDuringPartialStateJoin", func(t *testing.T) {
deployment := Deploy(t, b.BlueprintAlice)
Expand Down Expand Up @@ -1575,7 +1818,7 @@ func testReceiveEventDuringPartialStateJoin(
"GET",
[]string{"_matrix", "client", "v3", "rooms", psjResult.ServerRoom.RoomID, "state", "m.room.member", "@non-existent:remote"},
)

// check the server's idea of the state at the event. We do this by making a `state_ids` request over federation
stateReq = gomatrixserverlib.NewFederationRequest("GET", "hs1",
fmt.Sprintf("/_matrix/federation/v1/state_ids/%s?event_id=%s",
Expand Down