sliding-sync/tests-integration/room_names_test.go

201 lines
6.4 KiB
Go
Raw Permalink Normal View History

package syncv3
import (
"encoding/json"
"fmt"
"testing"
"time"
"github.com/matrix-org/sliding-sync/sync2"
"github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils"
"github.com/matrix-org/sliding-sync/testutils/m"
)
// Test that room names come through sanely. Additional testing to ensure we copy hero slices correctly.
func TestRoomNames(t *testing.T) {
pqString := testutils.PrepareDBConnectionString()
// setup code
v2 := runTestV2Server(t)
v3 := runTestServer(t, v2, pqString)
defer v2.close()
defer v3.close()
bob := "@TestRoomNames_bob:localhost"
2023-04-04 20:03:47 +01:00
// make 4 rooms, last room is most recent, and send A,B,C into each room
latestTimestamp := time.Now()
allRooms := []roomEvents{
{
roomID: "!TestRoomNames_dm:localhost",
name: "Bob",
events: append(createRoomState(t, alice, latestTimestamp), []json.RawMessage{
testutils.NewStateEvent(t, "m.room.member", bob, bob, map[string]interface{}{"membership": "join", "displayname": "Bob"}, testutils.WithTimestamp(latestTimestamp.Add(3*time.Second))),
}...),
},
{
roomID: "!TestRoomNames_named:localhost",
name: "My Room Name",
events: append(createRoomState(t, alice, latestTimestamp), []json.RawMessage{
testutils.NewStateEvent(t, "m.room.name", "", alice, map[string]interface{}{"name": "My Room Name"}, testutils.WithTimestamp(latestTimestamp.Add(2*time.Second))),
}...),
},
{
roomID: "!TestRoomNames_empty:localhost",
name: "Empty Room",
events: createRoomState(t, alice, latestTimestamp.Add(time.Second)),
},
{
roomID: "!TestRoomNames_dm_name_set_after_join:localhost",
name: "Bob",
state: append(createRoomState(t, alice, latestTimestamp), []json.RawMessage{
2022-07-12 15:12:02 +01:00
testutils.NewJoinEvent(t, bob, testutils.WithTimestamp(latestTimestamp)),
}...),
events: []json.RawMessage{
testutils.NewStateEvent(
t, "m.room.member", bob, bob, map[string]interface{}{"membership": "join", "displayname": "Bob"}, testutils.WithTimestamp(latestTimestamp),
testutils.WithUnsigned(map[string]interface{}{
"prev_content": map[string]interface{}{
"membership": "join",
},
})),
},
},
}
v2.addAccount(t, alice, aliceToken)
v2.queueResponse(alice, sync2.SyncResponse{
Rooms: sync2.SyncRoomsResponse{
Join: v2JoinTimeline(allRooms...),
},
})
checkRoomNames := func(sessionID string) {
t.Helper()
// do a sync, make sure room names are sensible
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
Lists: map[string]sync3.RequestList{
"a": {
Ranges: sync3.SliceRanges{
[2]int64{0, int64(len(allRooms) - 1)}, // all rooms
},
RoomSubscription: sync3.RoomSubscription{
TimelineLimit: int64(100),
},
}},
})
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
m.MatchV3SyncOpFn(func(op *sync3.ResponseOpRange) error {
2022-05-27 09:54:17 +01:00
if len(op.RoomIDs) != len(allRooms) {
return fmt.Errorf("want %d rooms, got %d", len(allRooms), len(op.RoomIDs))
}
for i := range allRooms {
err := allRooms[i].MatchRoom(op.RoomIDs[i],
2022-05-27 09:54:17 +01:00
res.Rooms[op.RoomIDs[i]],
m.MatchRoomName(allRooms[i].name),
)
if err != nil {
return err
}
}
return nil
}),
)))
}
checkRoomNames("a")
// restart the server and repeat the tests, should still be the same when reading from the database
v3.restart(t, v2, pqString)
checkRoomNames("b")
// now check that we can filter the rooms by name
checkRoomNameFilter := func(searchTerm string, wantRooms []roomEvents) {
t.Helper()
// do a sync, make sure room names are sensible
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
Lists: map[string]sync3.RequestList{
"a": {
Ranges: sync3.SliceRanges{
2023-04-04 20:03:47 +01:00
[2]int64{0, (int64(len(allRooms)) - 1)}, // all rooms
},
Filters: &sync3.RequestFilters{
RoomNameFilter: searchTerm,
},
}},
})
matchers := make(map[string][]m.RoomMatcher, len(wantRooms))
2022-05-27 09:54:17 +01:00
wantRoomIDs := make([]string, len(wantRooms))
for i := range wantRooms {
2022-05-27 09:54:17 +01:00
wantRoomIDs[i] = wantRooms[i].roomID
matchers[wantRooms[i].roomID] = []m.RoomMatcher{
m.MatchRoomName(wantRooms[i].name),
}
}
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(wantRooms)), m.MatchV3Ops(
2023-04-04 20:03:47 +01:00
m.MatchV3SyncOp(0, int64(len(wantRooms)-1), wantRoomIDs),
)), m.MatchRoomSubscriptions(matchers))
}
// case-insensitive matching
checkRoomNameFilter("my room name", []roomEvents{allRooms[1]})
// partial matching
checkRoomNameFilter("room na", []roomEvents{allRooms[1]})
// multiple matches
checkRoomNameFilter("bob", []roomEvents{allRooms[0], allRooms[3]})
}
// Tests that rooms have their names updated when events come in
func TestRoomNameUpdates(t *testing.T) {
rig := NewTestRig(t)
defer rig.Finish()
roomID := "!a:localhost"
rig.SetupV2RoomsForUser(t, alice, NoFlush, map[string]RoomDescriptor{
roomID: {},
})
aliceToken := rig.Token(alice)
res := rig.V3.mustDoV3Request(t, aliceToken, sync3.Request{
RoomSubscriptions: map[string]sync3.RoomSubscription{
roomID: {
TimelineLimit: 0,
},
},
})
m.MatchResponse(t, res, m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
roomID: {
m.MatchJoinCount(1),
m.MatchRoomName("Empty Room"),
},
}))
// Test hero calculation
rig.FlushEvent(t, alice, roomID, testutils.NewStateEvent(t, "m.room.member", bob, bob, map[string]interface{}{
"membership": "join",
"displayname": "Bob",
}))
res = rig.V3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{})
m.MatchResponse(t, res, m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
roomID: {
m.MatchJoinCount(2),
m.MatchRoomName("Bob"),
},
}))
// Test canonical alias
rig.FlushEvent(t, alice, roomID, testutils.NewStateEvent(t, "m.room.canonical_alias", "", alice, map[string]interface{}{
"alias": "#alias:example.com",
}))
res = rig.V3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{})
m.MatchResponse(t, res, m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
roomID: {
m.MatchRoomName("#alias:example.com"),
},
}))
// Test room name
rig.FlushEvent(t, alice, roomID, testutils.NewStateEvent(t, "m.room.name", "", alice, map[string]interface{}{
"name": "My Room Name",
}))
res = rig.V3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{})
m.MatchResponse(t, res, m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
roomID: {
m.MatchRoomName("My Room Name"),
},
}))
}