223 lines
5.9 KiB
Go
Raw Normal View History

package syncv3
import (
"encoding/json"
"sort"
"testing"
"time"
"github.com/matrix-org/sliding-sync/sync2"
"github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils"
)
type FlushEnum int
var (
NoFlush FlushEnum = 1
Flush FlushEnum = 2
)
type testRig struct {
V2 *testV2Server
V3 *testV3Server
tokens map[string]string
}
func (r *testRig) Finish() {
r.V2.close()
r.V3.close()
}
func (r *testRig) Token(userID string) string {
return r.tokens[userID]
}
func (r *testRig) SetupV2RoomsForUser(t *testing.T, v2UserID string, f FlushEnum, data map[string]RoomDescriptor) {
// allocate a user
_, userExists := r.tokens[v2UserID]
if !userExists {
r.tokens[v2UserID] = "access_token_for_" + v2UserID
r.V2.addAccount(t, v2UserID, r.tokens[v2UserID])
}
inviteRooms := make(map[string]sync2.SyncV2InviteResponse)
joinRooms := make(map[string]sync2.SyncV2JoinResponse)
roomIDs := make([]string, len(data))
i := 0
for roomID := range data {
roomIDs[i] = roomID
i++
}
sort.Strings(roomIDs) // ensure we always create rooms deterministically
for _, roomID := range roomIDs {
time.Sleep(time.Millisecond)
descriptor := data[roomID]
if descriptor.MembershipOfSyncer == "" {
descriptor.MembershipOfSyncer = "join"
}
switch descriptor.MembershipOfSyncer {
case "invite":
inviteRooms[roomID] = sync2.SyncV2InviteResponse{
InviteState: sync2.EventsResponse{
Events: []json.RawMessage{testutils.NewStateEvent(t, "m.room.member", v2UserID, "@inviter:localhost", map[string]interface{}{
"membership": "invite",
})},
},
}
case "join":
creator := descriptor.Creator
if creator == "" {
creator = v2UserID
}
timestamp := time.Now()
// configure the room
var timeline []json.RawMessage
if descriptor.IsEncrypted {
timeline = append(timeline, testutils.NewStateEvent(
t, "m.room.encryption", "", creator, map[string]interface{}{
"algorithm": "m.megolm.v1.aes-sha2",
"rotation_period_ms": 604800000,
"rotation_period_msgs": 100,
},
))
}
if descriptor.Name != "" {
timeline = append(timeline, testutils.NewStateEvent(
t, "m.room.name", "", creator, map[string]interface{}{
"name": descriptor.Name,
},
))
}
for _, userID := range descriptor.InvitedUsers {
timeline = append(timeline, testutils.NewStateEvent(
t, "m.room.member", userID, creator, map[string]interface{}{
"membership": "invite",
},
))
}
for _, userID := range descriptor.JoinedUsers {
timeline = append(timeline, testutils.NewJoinEvent(
t, userID,
))
}
var stateBlock []json.RawMessage
if descriptor.RoomType != "" {
stateBlock = createRoomStateWithCreateEvent(t, creator,
testutils.NewStateEvent(t, "m.room.create", "", creator, map[string]interface{}{"creator": creator, "type": descriptor.RoomType}, testutils.WithTimestamp(timestamp)),
timestamp)
} else {
stateBlock = createRoomState(t, creator, timestamp)
}
// A valid v2 response always has a timeline entry with state.
if len(timeline) == 0 {
timeline = []json.RawMessage{
stateBlock[len(stateBlock)-1],
}
stateBlock = stateBlock[:len(stateBlock)-1]
}
joinRooms[roomID] = sync2.SyncV2JoinResponse{
State: sync2.EventsResponse{
Events: stateBlock,
},
Timeline: sync2.TimelineResponse{
Events: timeline,
},
}
if len(descriptor.Tags) > 0 {
tagContent := make(map[string]interface{})
for tagName, order := range descriptor.Tags {
tagContent[tagName] = map[string]interface{}{
"order": order,
}
}
jr := joinRooms[roomID]
jr.AccountData = sync2.EventsResponse{
Events: []json.RawMessage{testutils.NewAccountData(
t, "m.tag", map[string]interface{}{
"tags": tagContent,
},
)},
}
joinRooms[roomID] = jr
}
default:
t.Fatalf("unknown value for descriptor.MembershipOfSyncer")
}
}
r.V2.queueResponse(v2UserID, sync2.SyncResponse{
Rooms: sync2.SyncRoomsResponse{
Invite: inviteRooms,
Join: joinRooms,
},
})
if f == Flush {
if !userExists {
// do a single request to flush it
_ = r.V3.mustDoV3Request(t, r.tokens[v2UserID], sync3.Request{})
} else {
// there is already a poller running for this user, wait for it to get the data.
r.V2.waitUntilEmpty(t, v2UserID)
}
}
}
func (r *testRig) JoinRoom(t *testing.T, userID, roomID string) {
r.FlushEvent(t, userID, roomID, testutils.NewJoinEvent(t, userID))
}
func (r *testRig) EncryptRoom(t *testing.T, userID, roomID string) {
r.FlushEvent(t, userID, roomID, testutils.NewStateEvent(
t, "m.room.encryption", "", userID, map[string]interface{}{
"algorithm": "m.megolm.v1.aes-sha2",
"rotation_period_ms": 604800000,
"rotation_period_msgs": 100,
},
))
}
func (r *testRig) FlushText(t *testing.T, userID, roomID, text string) {
r.FlushEvent(t, userID, roomID, testutils.NewMessageEvent(t, userID, text))
}
func (r *testRig) FlushEvent(t *testing.T, userID, roomID string, event json.RawMessage) {
r.V2.queueResponse(userID, sync2.SyncResponse{
Rooms: sync2.SyncRoomsResponse{
Join: v2JoinTimeline(roomEvents{
roomID: roomID,
events: []json.RawMessage{event},
}),
},
})
r.V2.waitUntilEmpty(t, userID)
}
func (r *testRig) Room(roomID string) *TestRoom {
return nil
}
func NewTestRig(t testutils.TestBenchInterface) *testRig {
pqString := testutils.PrepareDBConnectionString()
// setup code
v2 := runTestV2Server(t)
rig := &testRig{
V2: v2,
V3: runTestServer(t, v2, pqString),
tokens: make(map[string]string),
}
return rig
}
type RoomDescriptor struct {
Creator string
JoinedUsers []string
InvitedUsers []string
MembershipOfSyncer string
IsEncrypted bool
RoomType string
Name string
Tags map[string]float64
}
type TestRoom struct {
}