mirror of
https://github.com/matrix-org/sliding-sync.git
synced 2025-03-10 13:37:11 +00:00
BREAKING: Change the API to refer to lists by keys not index positions
This provides more flexibility to refer to lists as well as delete them.
This commit is contained in:
parent
3143b60c9f
commit
ca6ceb28da
@ -34,8 +34,8 @@ func TestConn(t *testing.T) {
|
||||
c := NewConn(connID, &connHandlerMock{func(ctx context.Context, cid ConnID, req *Request, isInitial bool) (*Response, error) {
|
||||
count += 1
|
||||
return &Response{
|
||||
Lists: []ResponseList{
|
||||
{
|
||||
Lists: map[string]ResponseList{
|
||||
"a": {
|
||||
Count: count,
|
||||
},
|
||||
},
|
||||
@ -48,14 +48,14 @@ func TestConn(t *testing.T) {
|
||||
})
|
||||
assertNoError(t, err)
|
||||
assertPos(t, resp.Pos, 1)
|
||||
assertInt(t, resp.Lists[0].Count, 101)
|
||||
assertInt(t, resp.Lists["a"].Count, 101)
|
||||
|
||||
// happy case, pos=1
|
||||
resp, err = c.OnIncomingRequest(ctx, &Request{
|
||||
pos: 1,
|
||||
})
|
||||
assertPos(t, resp.Pos, 2)
|
||||
assertInt(t, resp.Lists[0].Count, 102)
|
||||
assertInt(t, resp.Lists["a"].Count, 102)
|
||||
assertNoError(t, err)
|
||||
// bogus position returns a 400
|
||||
_, err = c.OnIncomingRequest(ctx, &Request{
|
||||
@ -80,10 +80,10 @@ func TestConnBlocking(t *testing.T) {
|
||||
}
|
||||
ch := make(chan string)
|
||||
c := NewConn(connID, &connHandlerMock{func(ctx context.Context, cid ConnID, req *Request, init bool) (*Response, error) {
|
||||
if req.Lists[0].Sort[0] == "hi" {
|
||||
if req.Lists["a"].Sort[0] == "hi" {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
ch <- req.Lists[0].Sort[0]
|
||||
ch <- req.Lists["a"].Sort[0]
|
||||
return &Response{}, nil
|
||||
}})
|
||||
|
||||
@ -95,8 +95,8 @@ func TestConnBlocking(t *testing.T) {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
c.OnIncomingRequest(ctx, &Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"a": {
|
||||
Sort: []string{"hi"},
|
||||
},
|
||||
},
|
||||
@ -106,8 +106,8 @@ func TestConnBlocking(t *testing.T) {
|
||||
defer wg.Done()
|
||||
time.Sleep(1 * time.Millisecond) // this req happens 2nd
|
||||
c.OnIncomingRequest(ctx, &Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"a": {
|
||||
Sort: []string{"hi2"},
|
||||
},
|
||||
},
|
||||
@ -135,37 +135,37 @@ func TestConnRetries(t *testing.T) {
|
||||
callCount := 0
|
||||
c := NewConn(connID, &connHandlerMock{func(ctx context.Context, cid ConnID, req *Request, init bool) (*Response, error) {
|
||||
callCount += 1
|
||||
return &Response{Lists: []ResponseList{
|
||||
{
|
||||
return &Response{Lists: map[string]ResponseList{
|
||||
"a": {
|
||||
Count: 20,
|
||||
},
|
||||
}}, nil
|
||||
}})
|
||||
resp, err := c.OnIncomingRequest(ctx, &Request{})
|
||||
assertPos(t, resp.Pos, 1)
|
||||
assertInt(t, resp.Lists[0].Count, 20)
|
||||
assertInt(t, resp.Lists["a"].Count, 20)
|
||||
assertInt(t, callCount, 1)
|
||||
assertNoError(t, err)
|
||||
resp, err = c.OnIncomingRequest(ctx, &Request{pos: 1})
|
||||
assertPos(t, resp.Pos, 2)
|
||||
assertInt(t, resp.Lists[0].Count, 20)
|
||||
assertInt(t, resp.Lists["a"].Count, 20)
|
||||
assertInt(t, callCount, 2)
|
||||
assertNoError(t, err)
|
||||
// retry! Shouldn't invoke handler again
|
||||
resp, err = c.OnIncomingRequest(ctx, &Request{pos: 1})
|
||||
assertPos(t, resp.Pos, 2)
|
||||
assertInt(t, resp.Lists[0].Count, 20)
|
||||
assertInt(t, resp.Lists["a"].Count, 20)
|
||||
assertInt(t, callCount, 2) // this doesn't increment
|
||||
assertNoError(t, err)
|
||||
// retry! but with modified request body, so should invoke handler again but return older data (buffered)
|
||||
resp, err = c.OnIncomingRequest(ctx, &Request{
|
||||
pos: 1, Lists: []RequestList{
|
||||
{
|
||||
pos: 1, Lists: map[string]RequestList{
|
||||
"a": {
|
||||
Sort: []string{SortByName},
|
||||
},
|
||||
}})
|
||||
assertPos(t, resp.Pos, 2)
|
||||
assertInt(t, resp.Lists[0].Count, 20)
|
||||
assertInt(t, resp.Lists["a"].Count, 20)
|
||||
assertInt(t, callCount, 3) // this doesn't increment
|
||||
assertNoError(t, err)
|
||||
}
|
||||
@ -178,8 +178,8 @@ func TestConnBufferRes(t *testing.T) {
|
||||
callCount := 0
|
||||
c := NewConn(connID, &connHandlerMock{func(ctx context.Context, cid ConnID, req *Request, init bool) (*Response, error) {
|
||||
callCount += 1
|
||||
return &Response{Lists: []ResponseList{
|
||||
{
|
||||
return &Response{Lists: map[string]ResponseList{
|
||||
"a": {
|
||||
Count: callCount,
|
||||
},
|
||||
}}, nil
|
||||
@ -187,24 +187,24 @@ func TestConnBufferRes(t *testing.T) {
|
||||
resp, err := c.OnIncomingRequest(ctx, &Request{})
|
||||
assertNoError(t, err)
|
||||
assertPos(t, resp.Pos, 1)
|
||||
assertInt(t, resp.Lists[0].Count, 1)
|
||||
assertInt(t, resp.Lists["a"].Count, 1)
|
||||
assertInt(t, callCount, 1)
|
||||
resp, err = c.OnIncomingRequest(ctx, &Request{pos: 1})
|
||||
assertNoError(t, err)
|
||||
assertPos(t, resp.Pos, 2)
|
||||
assertInt(t, resp.Lists[0].Count, 2)
|
||||
assertInt(t, resp.Lists["a"].Count, 2)
|
||||
assertInt(t, callCount, 2)
|
||||
// retry with modified request data, should invoke handler again!
|
||||
resp, err = c.OnIncomingRequest(ctx, &Request{pos: 1, TxnID: "a"})
|
||||
assertNoError(t, err)
|
||||
assertPos(t, resp.Pos, 2)
|
||||
assertInt(t, resp.Lists[0].Count, 2)
|
||||
assertInt(t, resp.Lists["a"].Count, 2)
|
||||
assertInt(t, callCount, 3) // this DOES increment, the response is buffered and not returned yet.
|
||||
// retry with same request body, so should NOT invoke handler again and return buffered response
|
||||
resp, err = c.OnIncomingRequest(ctx, &Request{pos: 2, TxnID: "a"})
|
||||
assertNoError(t, err)
|
||||
assertPos(t, resp.Pos, 3)
|
||||
assertInt(t, resp.Lists[0].Count, 3)
|
||||
assertInt(t, resp.Lists["a"].Count, 3)
|
||||
assertInt(t, callCount, 3)
|
||||
}
|
||||
|
||||
@ -281,8 +281,8 @@ func TestConnBufferRememberInflight(t *testing.T) {
|
||||
callCount := 0
|
||||
c := NewConn(connID, &connHandlerMock{func(ctx context.Context, cid ConnID, req *Request, init bool) (*Response, error) {
|
||||
callCount += 1
|
||||
return &Response{Lists: []ResponseList{
|
||||
{
|
||||
return &Response{Lists: map[string]ResponseList{
|
||||
"a": {
|
||||
Count: callCount,
|
||||
},
|
||||
}}, nil
|
||||
@ -358,7 +358,7 @@ func TestConnBufferRememberInflight(t *testing.T) {
|
||||
assertNoError(t, err)
|
||||
}
|
||||
assertPos(t, resp.Pos, step.wantResPos)
|
||||
assertInt(t, resp.Lists[0].Count, step.wantResCount)
|
||||
assertInt(t, resp.Lists["a"].Count, step.wantResCount)
|
||||
assertInt(t, callCount, step.wantCallCount)
|
||||
}
|
||||
}
|
||||
|
@ -187,16 +187,18 @@ func (s *ConnState) onIncomingRequest(ctx context.Context, req *sync3.Request, i
|
||||
region.End()
|
||||
|
||||
// counts are AFTER events are applied, hence after liveUpdate
|
||||
for i := range response.Lists {
|
||||
response.Lists[i].Count = s.lists.Count(i)
|
||||
for listKey := range response.Lists {
|
||||
l := response.Lists[listKey]
|
||||
l.Count = s.lists.Count(listKey)
|
||||
response.Lists[listKey] = l
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *ConnState) onIncomingListRequest(ctx context.Context, builder *RoomsBuilder, listIndex int, prevReqList, nextReqList *sync3.RequestList) sync3.ResponseList {
|
||||
func (s *ConnState) onIncomingListRequest(ctx context.Context, builder *RoomsBuilder, listKey string, prevReqList, nextReqList *sync3.RequestList) sync3.ResponseList {
|
||||
defer trace.StartRegion(ctx, "onIncomingListRequest").End()
|
||||
roomList, overwritten := s.lists.AssignList(listIndex, nextReqList.Filters, nextReqList.Sort, sync3.DoNotOverwrite)
|
||||
roomList, overwritten := s.lists.AssignList(listKey, nextReqList.Filters, nextReqList.Sort, sync3.DoNotOverwrite)
|
||||
|
||||
if nextReqList.ShouldGetAllRooms() {
|
||||
if overwritten || prevReqList.FiltersChanged(nextReqList) {
|
||||
@ -251,11 +253,11 @@ func (s *ConnState) onIncomingListRequest(ctx context.Context, builder *RoomsBui
|
||||
}
|
||||
if filtersChanged {
|
||||
// we need to re-create the list as the rooms may have completely changed
|
||||
roomList, _ = s.lists.AssignList(listIndex, nextReqList.Filters, nextReqList.Sort, sync3.Overwrite)
|
||||
roomList, _ = s.lists.AssignList(listKey, nextReqList.Filters, nextReqList.Sort, sync3.Overwrite)
|
||||
}
|
||||
// resort as either we changed the sort order or we added/removed a bunch of rooms
|
||||
if err := roomList.Sort(nextReqList.Sort); err != nil {
|
||||
logger.Err(err).Int("index", listIndex).Msg("cannot sort list")
|
||||
logger.Err(err).Str("key", listKey).Msg("cannot sort list")
|
||||
}
|
||||
addedRanges = nextReqList.Ranges
|
||||
removedRanges = nil
|
||||
@ -300,17 +302,17 @@ func (s *ConnState) onIncomingListRequest(ctx context.Context, builder *RoomsBui
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ConnState) buildListSubscriptions(ctx context.Context, builder *RoomsBuilder, listDeltas []sync3.RequestListDelta) []sync3.ResponseList {
|
||||
result := make([]sync3.ResponseList, len(s.muxedReq.Lists))
|
||||
func (s *ConnState) buildListSubscriptions(ctx context.Context, builder *RoomsBuilder, listDeltas map[string]sync3.RequestListDelta) map[string]sync3.ResponseList {
|
||||
result := make(map[string]sync3.ResponseList, len(s.muxedReq.Lists))
|
||||
// loop each list and handle each independently
|
||||
for i := range listDeltas {
|
||||
if listDeltas[i].Curr == nil {
|
||||
for listKey, list := range listDeltas {
|
||||
if list.Curr == nil {
|
||||
// they deleted this list
|
||||
logger.Debug().Int("index", i).Msg("list deleted")
|
||||
s.lists.DeleteList(i)
|
||||
logger.Debug().Str("key", listKey).Msg("list deleted")
|
||||
s.lists.DeleteList(listKey)
|
||||
continue
|
||||
}
|
||||
result[i] = s.onIncomingListRequest(ctx, builder, i, listDeltas[i].Prev, listDeltas[i].Curr)
|
||||
result[listKey] = s.onIncomingListRequest(ctx, builder, listKey, list.Prev, list.Curr)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
@ -118,13 +118,15 @@ func (s *connStateLive) processLiveUpdate(ctx context.Context, up caches.Update,
|
||||
|
||||
// do per-list updates (e.g resorting, adding/removing rooms which no longer match filter)
|
||||
for _, listDelta := range delta.Lists {
|
||||
index := listDelta.ListIndex
|
||||
list := s.lists.Get(index)
|
||||
reqList := s.muxedReq.Lists[index]
|
||||
updates := s.processLiveUpdateForList(ctx, builder, up, listDelta.Op, &reqList, list, &response.Lists[index])
|
||||
listKey := listDelta.ListKey
|
||||
list := s.lists.Get(listKey)
|
||||
reqList := s.muxedReq.Lists[listKey]
|
||||
resList := response.Lists[listKey]
|
||||
updates := s.processLiveUpdateForList(ctx, builder, up, listDelta.Op, &reqList, list, &resList)
|
||||
if updates {
|
||||
hasUpdates = true
|
||||
}
|
||||
response.Lists[listKey] = resList
|
||||
}
|
||||
|
||||
// add in initial rooms FIRST as we replace whatever is in the rooms key for these rooms.
|
||||
|
@ -109,7 +109,7 @@ func TestConnStateInitial(t *testing.T) {
|
||||
t.Fatalf("UserID returned wrong value, got %v want %v", cs.UserID(), userID)
|
||||
}
|
||||
res, err := cs.OnIncomingRequest(context.Background(), ConnID, &sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges([][2]int64{
|
||||
{0, 9},
|
||||
@ -137,8 +137,8 @@ func TestConnStateInitial(t *testing.T) {
|
||||
Timeline: []json.RawMessage{timeline[roomA.RoomID]},
|
||||
},
|
||||
},
|
||||
Lists: []sync3.ResponseList{
|
||||
{
|
||||
Lists: map[string]sync3.ResponseList{
|
||||
"a": {
|
||||
Count: 3,
|
||||
Ops: []sync3.ResponseOp{
|
||||
&sync3.ResponseOpRange{
|
||||
@ -161,7 +161,7 @@ func TestConnStateInitial(t *testing.T) {
|
||||
|
||||
// request again for the diff
|
||||
res, err = cs.OnIncomingRequest(context.Background(), ConnID, &sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges([][2]int64{
|
||||
{0, 9},
|
||||
@ -177,8 +177,8 @@ func TestConnStateInitial(t *testing.T) {
|
||||
Timeline: []json.RawMessage{newEvent},
|
||||
},
|
||||
},
|
||||
Lists: []sync3.ResponseList{
|
||||
{
|
||||
Lists: map[string]sync3.ResponseList{
|
||||
"a": {
|
||||
Count: 3,
|
||||
Ops: []sync3.ResponseOp{
|
||||
&sync3.ResponseOpSingle{
|
||||
@ -201,7 +201,7 @@ func TestConnStateInitial(t *testing.T) {
|
||||
newEvent,
|
||||
}, 2)
|
||||
res, err = cs.OnIncomingRequest(context.Background(), ConnID, &sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges([][2]int64{
|
||||
{0, 9},
|
||||
@ -217,8 +217,8 @@ func TestConnStateInitial(t *testing.T) {
|
||||
Timeline: []json.RawMessage{newEvent},
|
||||
},
|
||||
},
|
||||
Lists: []sync3.ResponseList{
|
||||
{
|
||||
Lists: map[string]sync3.ResponseList{
|
||||
"a": {
|
||||
Count: 3,
|
||||
},
|
||||
},
|
||||
@ -272,7 +272,7 @@ func TestConnStateMultipleRanges(t *testing.T) {
|
||||
|
||||
// request first page
|
||||
res, err := cs.OnIncomingRequest(context.Background(), ConnID, &sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges([][2]int64{
|
||||
{0, 2},
|
||||
@ -283,8 +283,8 @@ func TestConnStateMultipleRanges(t *testing.T) {
|
||||
t.Fatalf("OnIncomingRequest returned error : %s", err)
|
||||
}
|
||||
checkResponse(t, true, res, &sync3.Response{
|
||||
Lists: []sync3.ResponseList{
|
||||
{
|
||||
Lists: map[string]sync3.ResponseList{
|
||||
"a": {
|
||||
Count: len(rooms),
|
||||
Ops: []sync3.ResponseOp{
|
||||
&sync3.ResponseOpRange{
|
||||
@ -298,7 +298,7 @@ func TestConnStateMultipleRanges(t *testing.T) {
|
||||
})
|
||||
// add on a different non-overlapping range
|
||||
res, err = cs.OnIncomingRequest(context.Background(), ConnID, &sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges([][2]int64{
|
||||
{0, 2}, {4, 6},
|
||||
@ -309,8 +309,8 @@ func TestConnStateMultipleRanges(t *testing.T) {
|
||||
t.Fatalf("OnIncomingRequest returned error : %s", err)
|
||||
}
|
||||
checkResponse(t, true, res, &sync3.Response{
|
||||
Lists: []sync3.ResponseList{
|
||||
{
|
||||
Lists: map[string]sync3.ResponseList{
|
||||
"a": {
|
||||
Count: len(rooms),
|
||||
Ops: []sync3.ResponseOp{
|
||||
&sync3.ResponseOpRange{
|
||||
@ -335,7 +335,7 @@ func TestConnStateMultipleRanges(t *testing.T) {
|
||||
}, 1)
|
||||
|
||||
res, err = cs.OnIncomingRequest(context.Background(), ConnID, &sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges([][2]int64{
|
||||
{0, 2}, {4, 6},
|
||||
@ -346,8 +346,8 @@ func TestConnStateMultipleRanges(t *testing.T) {
|
||||
t.Fatalf("OnIncomingRequest returned error : %s", err)
|
||||
}
|
||||
checkResponse(t, true, res, &sync3.Response{
|
||||
Lists: []sync3.ResponseList{
|
||||
{
|
||||
Lists: map[string]sync3.ResponseList{
|
||||
"a": {
|
||||
Count: len(rooms),
|
||||
Ops: []sync3.ResponseOp{
|
||||
&sync3.ResponseOpSingle{
|
||||
@ -377,7 +377,7 @@ func TestConnStateMultipleRanges(t *testing.T) {
|
||||
}, 1)
|
||||
t.Logf("new event %s : %s", roomIDs[9], string(newEvent))
|
||||
res, err = cs.OnIncomingRequest(context.Background(), ConnID, &sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges([][2]int64{
|
||||
{0, 2}, {4, 6},
|
||||
@ -388,8 +388,8 @@ func TestConnStateMultipleRanges(t *testing.T) {
|
||||
t.Fatalf("OnIncomingRequest returned error : %s", err)
|
||||
}
|
||||
checkResponse(t, true, res, &sync3.Response{
|
||||
Lists: []sync3.ResponseList{
|
||||
{
|
||||
Lists: map[string]sync3.ResponseList{
|
||||
"a": {
|
||||
Count: len(rooms),
|
||||
Ops: []sync3.ResponseOp{
|
||||
&sync3.ResponseOpSingle{
|
||||
@ -448,7 +448,7 @@ func TestBumpToOutsideRange(t *testing.T) {
|
||||
cs := NewConnState(userID, deviceID, userCache, globalCache, &NopExtensionHandler{}, &NopJoinTracker{}, nil)
|
||||
// Ask for A,B
|
||||
res, err := cs.OnIncomingRequest(context.Background(), ConnID, &sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges([][2]int64{
|
||||
{0, 1},
|
||||
@ -459,8 +459,8 @@ func TestBumpToOutsideRange(t *testing.T) {
|
||||
t.Fatalf("OnIncomingRequest returned error : %s", err)
|
||||
}
|
||||
checkResponse(t, true, res, &sync3.Response{
|
||||
Lists: []sync3.ResponseList{
|
||||
{
|
||||
Lists: map[string]sync3.ResponseList{
|
||||
"a": {
|
||||
Count: 4,
|
||||
Ops: []sync3.ResponseOp{
|
||||
&sync3.ResponseOpRange{
|
||||
@ -485,7 +485,7 @@ func TestBumpToOutsideRange(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
|
||||
defer cancel()
|
||||
res, err = cs.OnIncomingRequest(ctx, ConnID, &sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges([][2]int64{
|
||||
{0, 1},
|
||||
@ -495,7 +495,7 @@ func TestBumpToOutsideRange(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("OnIncomingRequest returned error : %s", err)
|
||||
}
|
||||
if len(res.Lists[0].Ops) > 0 {
|
||||
if len(res.Lists["a"].Ops) > 0 {
|
||||
t.Errorf("response returned ops, expected none")
|
||||
}
|
||||
}
|
||||
@ -561,7 +561,7 @@ func TestConnStateRoomSubscriptions(t *testing.T) {
|
||||
TimelineLimit: 20,
|
||||
},
|
||||
},
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges([][2]int64{
|
||||
{0, 1},
|
||||
@ -572,8 +572,8 @@ func TestConnStateRoomSubscriptions(t *testing.T) {
|
||||
t.Fatalf("OnIncomingRequest returned error : %s", err)
|
||||
}
|
||||
checkResponse(t, false, res, &sync3.Response{
|
||||
Lists: []sync3.ResponseList{
|
||||
{
|
||||
Lists: map[string]sync3.ResponseList{
|
||||
"a": {
|
||||
Count: len(roomIDs),
|
||||
Ops: []sync3.ResponseOp{
|
||||
&sync3.ResponseOpRange{
|
||||
@ -617,7 +617,7 @@ func TestConnStateRoomSubscriptions(t *testing.T) {
|
||||
}, 1)
|
||||
// we should get this message even though it's not in the range because we are subscribed to this room.
|
||||
res, err = cs.OnIncomingRequest(context.Background(), ConnID, &sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges([][2]int64{
|
||||
{0, 1},
|
||||
@ -628,8 +628,8 @@ func TestConnStateRoomSubscriptions(t *testing.T) {
|
||||
t.Fatalf("OnIncomingRequest returned error : %s", err)
|
||||
}
|
||||
checkResponse(t, false, res, &sync3.Response{
|
||||
Lists: []sync3.ResponseList{
|
||||
{
|
||||
Lists: map[string]sync3.ResponseList{
|
||||
"a": {
|
||||
Count: len(roomIDs),
|
||||
},
|
||||
},
|
||||
@ -651,7 +651,7 @@ func TestConnStateRoomSubscriptions(t *testing.T) {
|
||||
},
|
||||
},
|
||||
UnsubscribeRooms: []string{roomD.RoomID},
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges([][2]int64{
|
||||
{0, 1},
|
||||
@ -662,8 +662,8 @@ func TestConnStateRoomSubscriptions(t *testing.T) {
|
||||
t.Fatalf("OnIncomingRequest returned error : %s", err)
|
||||
}
|
||||
checkResponse(t, false, res, &sync3.Response{
|
||||
Lists: []sync3.ResponseList{
|
||||
{
|
||||
Lists: map[string]sync3.ResponseList{
|
||||
"a": {
|
||||
Count: len(roomIDs),
|
||||
},
|
||||
},
|
||||
@ -684,11 +684,14 @@ func checkResponse(t *testing.T, checkRoomIDsOnly bool, got, want *sync3.Respons
|
||||
if len(got.Lists) != len(want.Lists) {
|
||||
t.Errorf("got %v lists, want %v", len(got.Lists), len(want.Lists))
|
||||
}
|
||||
for i := 0; i < len(want.Lists); i++ {
|
||||
wl := want.Lists[i]
|
||||
gl := got.Lists[i]
|
||||
for listKey, wl := range want.Lists {
|
||||
gl, exists := got.Lists[listKey]
|
||||
if !exists {
|
||||
t.Errorf("no response key for '%s'", listKey)
|
||||
continue
|
||||
}
|
||||
if wl.Count > 0 && gl.Count != wl.Count {
|
||||
t.Errorf("response list %d got count %d want %d", i, gl.Count, wl.Count)
|
||||
t.Errorf("response list %v got count %d want %d", listKey, gl.Count, wl.Count)
|
||||
}
|
||||
|
||||
if len(wl.Ops) > 0 {
|
||||
|
@ -187,11 +187,11 @@ func (h *SyncLiveHandler) serve(w http.ResponseWriter, req *http.Request) error
|
||||
}
|
||||
}
|
||||
}
|
||||
for i, l := range requestBody.Lists {
|
||||
for listKey, l := range requestBody.Lists {
|
||||
if l.Ranges != nil && !l.Ranges.Valid() {
|
||||
return &internal.HandlerError{
|
||||
StatusCode: 400,
|
||||
Err: fmt.Errorf("list[%d] invalid ranges %v", i, l.Ranges),
|
||||
Err: fmt.Errorf("list[%v] invalid ranges %v", listKey, l.Ranges),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ var (
|
||||
)
|
||||
|
||||
type RoomListDelta struct {
|
||||
ListIndex int
|
||||
Op ListOp
|
||||
ListKey string
|
||||
Op ListOp
|
||||
}
|
||||
|
||||
type RoomDelta struct {
|
||||
@ -42,12 +42,13 @@ type RoomDelta struct {
|
||||
// lists.
|
||||
type InternalRequestLists struct {
|
||||
allRooms map[string]RoomConnMetadata
|
||||
lists []*FilteredSortableRooms
|
||||
lists map[string]*FilteredSortableRooms
|
||||
}
|
||||
|
||||
func NewInternalRequestLists() *InternalRequestLists {
|
||||
return &InternalRequestLists{
|
||||
allRooms: make(map[string]RoomConnMetadata, 10),
|
||||
lists: make(map[string]*FilteredSortableRooms),
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,9 +73,9 @@ func (s *InternalRequestLists) SetRoom(r RoomConnMetadata) (delta RoomDelta) {
|
||||
// filter.Include may call on this room ID in the RoomFinder, so make sure it finds it.
|
||||
s.allRooms[r.RoomID] = r
|
||||
|
||||
for i := range s.lists {
|
||||
_, alreadyExists := s.lists[i].roomIDToIndex[r.RoomID]
|
||||
shouldExist := s.lists[i].filter.Include(&r, s)
|
||||
for listKey, list := range s.lists {
|
||||
_, alreadyExists := list.roomIDToIndex[r.RoomID]
|
||||
shouldExist := list.filter.Include(&r, s)
|
||||
if shouldExist && r.HasLeft {
|
||||
shouldExist = false
|
||||
}
|
||||
@ -82,20 +83,20 @@ func (s *InternalRequestLists) SetRoom(r RoomConnMetadata) (delta RoomDelta) {
|
||||
if alreadyExists {
|
||||
if shouldExist { // could be a change
|
||||
delta.Lists = append(delta.Lists, RoomListDelta{
|
||||
ListIndex: i,
|
||||
Op: ListOpChange,
|
||||
ListKey: listKey,
|
||||
Op: ListOpChange,
|
||||
})
|
||||
} else { // removal
|
||||
delta.Lists = append(delta.Lists, RoomListDelta{
|
||||
ListIndex: i,
|
||||
Op: ListOpDel,
|
||||
ListKey: listKey,
|
||||
Op: ListOpDel,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if shouldExist { // addition
|
||||
delta.Lists = append(delta.Lists, RoomListDelta{
|
||||
ListIndex: i,
|
||||
Op: ListOpAdd,
|
||||
ListKey: listKey,
|
||||
Op: ListOpAdd,
|
||||
})
|
||||
} // else it doesn't exist and it shouldn't exist, so do nothing e.g room isn't relevant to this list
|
||||
}
|
||||
@ -109,7 +110,7 @@ func (s *InternalRequestLists) RemoveRoom(roomID string) {
|
||||
// TODO: update lists?
|
||||
}
|
||||
|
||||
func (s *InternalRequestLists) DeleteList(index int) {
|
||||
func (s *InternalRequestLists) DeleteList(listKey string) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@ -118,16 +119,18 @@ func (s *InternalRequestLists) Room(roomID string) *RoomConnMetadata {
|
||||
return &r
|
||||
}
|
||||
|
||||
func (s *InternalRequestLists) Get(listIndex int) *FilteredSortableRooms {
|
||||
return s.lists[listIndex]
|
||||
func (s *InternalRequestLists) Get(listKey string) *FilteredSortableRooms {
|
||||
return s.lists[listKey]
|
||||
}
|
||||
|
||||
// Assign a new list at the given index. If Overwrite, any existing list is replaced. If DoNotOverwrite, the existing
|
||||
// Assign a new list at the given key. If Overwrite, any existing list is replaced. If DoNotOverwrite, the existing
|
||||
// list is returned if one exists, else a new list is created. Returns the list and true if the list was overwritten.
|
||||
func (s *InternalRequestLists) AssignList(index int, filters *RequestFilters, sort []string, shouldOverwrite OverwriteVal) (*FilteredSortableRooms, bool) {
|
||||
internal.Assert("Set index is at most list size", index <= len(s.lists))
|
||||
if shouldOverwrite == DoNotOverwrite && index < len(s.lists) {
|
||||
return s.lists[index], false
|
||||
func (s *InternalRequestLists) AssignList(listKey string, filters *RequestFilters, sort []string, shouldOverwrite OverwriteVal) (*FilteredSortableRooms, bool) {
|
||||
if shouldOverwrite == DoNotOverwrite {
|
||||
_, exists := s.lists[listKey]
|
||||
if exists {
|
||||
return s.lists[listKey], false
|
||||
}
|
||||
}
|
||||
roomIDs := make([]string, len(s.allRooms))
|
||||
i := 0
|
||||
@ -143,17 +146,13 @@ func (s *InternalRequestLists) AssignList(index int, filters *RequestFilters, so
|
||||
logger.Err(err).Strs("sort_by", sort).Msg("failed to sort")
|
||||
}
|
||||
}
|
||||
if index == len(s.lists) {
|
||||
s.lists = append(s.lists, roomList)
|
||||
return roomList, true
|
||||
}
|
||||
s.lists[index] = roomList
|
||||
s.lists[listKey] = roomList
|
||||
return roomList, true
|
||||
}
|
||||
|
||||
// Count returns the count of total rooms in this list
|
||||
func (s *InternalRequestLists) Count(index int) int {
|
||||
return int(s.lists[index].Len())
|
||||
func (s *InternalRequestLists) Count(listKey string) int {
|
||||
return int(s.lists[listKey].Len())
|
||||
}
|
||||
|
||||
func (s *InternalRequestLists) Len() int {
|
||||
|
@ -27,7 +27,7 @@ var (
|
||||
|
||||
type Request struct {
|
||||
TxnID string `json:"txn_id"`
|
||||
Lists []RequestList `json:"lists"`
|
||||
Lists map[string]RequestList `json:"lists"`
|
||||
RoomSubscriptions map[string]RoomSubscription `json:"room_subscriptions"`
|
||||
UnsubscribeRooms []string `json:"unsubscribe_rooms"`
|
||||
Extensions extensions.Request `json:"extensions"`
|
||||
@ -43,6 +43,7 @@ type RequestList struct {
|
||||
Sort []string `json:"sort"`
|
||||
Filters *RequestFilters `json:"filters"`
|
||||
SlowGetAllRooms *bool `json:"slow_get_all_rooms,omitempty"`
|
||||
Deleted bool `json:"deleted,omitempty"`
|
||||
}
|
||||
|
||||
func (rl *RequestList) ShouldGetAllRooms() bool {
|
||||
@ -267,7 +268,7 @@ type RequestDelta struct {
|
||||
// room IDs to unsubscribe from
|
||||
Unsubs []string
|
||||
// The complete union of both lists (contains max(a,b) lists)
|
||||
Lists []RequestListDelta
|
||||
Lists map[string]RequestListDelta
|
||||
}
|
||||
|
||||
// Internal struct used to represent a single list delta.
|
||||
@ -294,24 +295,39 @@ func (r *Request) ApplyDelta(nextReq *Request) (result *Request, delta *RequestD
|
||||
Extensions: r.Extensions.ApplyDelta(&nextReq.Extensions),
|
||||
}
|
||||
}
|
||||
|
||||
listKeys := make(set)
|
||||
for k := range nextReq.Lists {
|
||||
listKeys[k] = struct{}{}
|
||||
}
|
||||
for k := range r.Lists {
|
||||
listKeys[k] = struct{}{}
|
||||
}
|
||||
delta = &RequestDelta{}
|
||||
lists := make([]RequestList, len(nextReq.Lists))
|
||||
for i := 0; i < len(lists); i++ {
|
||||
var existingList *RequestList
|
||||
if i < len(r.Lists) {
|
||||
existingList = &r.Lists[i]
|
||||
}
|
||||
// default to recency sort order if missing and there isn't a previous list to draw from
|
||||
if len(nextReq.Lists[i].Sort) == 0 && existingList == nil {
|
||||
nextReq.Lists[i].Sort = []string{SortByRecency}
|
||||
}
|
||||
if existingList == nil {
|
||||
// we added a list
|
||||
lists[i] = nextReq.Lists[i]
|
||||
calculatedLists := make(map[string]RequestList, len(nextReq.Lists))
|
||||
for listKey := range listKeys {
|
||||
existingList, existingOk := r.Lists[listKey]
|
||||
nextList, nextOk := nextReq.Lists[listKey]
|
||||
if !nextOk {
|
||||
// copy over what they said before (sticky), no diffs to make
|
||||
calculatedLists[listKey] = existingList
|
||||
continue
|
||||
}
|
||||
nextList := nextReq.Lists[i]
|
||||
if !existingOk {
|
||||
// we added a list
|
||||
// default to recency sort order if missing and there isn't a previous list value to draw from
|
||||
if len(nextList.Sort) == 0 {
|
||||
nextList.Sort = []string{SortByRecency}
|
||||
}
|
||||
calculatedLists[listKey] = nextList
|
||||
continue
|
||||
}
|
||||
// both existing and next exist, check for deletions
|
||||
if nextList.Deleted {
|
||||
// do not add the list to `lists` so it disappears
|
||||
continue
|
||||
}
|
||||
|
||||
// apply the delta
|
||||
rooms := nextList.Ranges
|
||||
if rooms == nil {
|
||||
rooms = existingList.Ranges
|
||||
@ -332,7 +348,6 @@ func (r *Request) ApplyDelta(nextReq *Request) (result *Request, delta *RequestD
|
||||
if includeOldRooms == nil {
|
||||
includeOldRooms = existingList.IncludeOldRooms
|
||||
}
|
||||
|
||||
timelineLimit := nextList.TimelineLimit
|
||||
if timelineLimit == 0 {
|
||||
timelineLimit = existingList.TimelineLimit
|
||||
@ -342,7 +357,7 @@ func (r *Request) ApplyDelta(nextReq *Request) (result *Request, delta *RequestD
|
||||
filters = existingList.Filters
|
||||
}
|
||||
|
||||
lists[i] = RequestList{
|
||||
calculatedLists[listKey] = RequestList{
|
||||
RoomSubscription: RoomSubscription{
|
||||
RequiredState: reqState,
|
||||
TimelineLimit: timelineLimit,
|
||||
@ -354,20 +369,20 @@ func (r *Request) ApplyDelta(nextReq *Request) (result *Request, delta *RequestD
|
||||
SlowGetAllRooms: slowGetAllRooms,
|
||||
}
|
||||
}
|
||||
result.Lists = lists
|
||||
// the delta is as large as the longest list of lists
|
||||
maxLen := len(result.Lists)
|
||||
if len(r.Lists) > maxLen {
|
||||
maxLen = len(r.Lists)
|
||||
}
|
||||
delta.Lists = make([]RequestListDelta, maxLen)
|
||||
for i := range result.Lists {
|
||||
delta.Lists[i] = RequestListDelta{
|
||||
Curr: &result.Lists[i],
|
||||
result.Lists = calculatedLists
|
||||
|
||||
delta.Lists = make(map[string]RequestListDelta, len(calculatedLists))
|
||||
for listKey := range result.Lists {
|
||||
l := result.Lists[listKey]
|
||||
delta.Lists[listKey] = RequestListDelta{
|
||||
Curr: &l,
|
||||
}
|
||||
}
|
||||
for i := range r.Lists {
|
||||
delta.Lists[i].Prev = &r.Lists[i]
|
||||
for listKey := range r.Lists {
|
||||
l := r.Lists[listKey]
|
||||
rld := delta.Lists[listKey]
|
||||
rld.Prev = &l
|
||||
delta.Lists[listKey] = rld
|
||||
}
|
||||
|
||||
// Work out subscriptions. The operations are applied as:
|
||||
@ -411,15 +426,15 @@ func (r *Request) ApplyDelta(nextReq *Request) (result *Request, delta *RequestD
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Request) GetTimelineLimit(listIndex int, roomID string) int64 {
|
||||
func (r *Request) GetTimelineLimit(listKey string, roomID string) int64 {
|
||||
if r.RoomSubscriptions != nil {
|
||||
room, ok := r.RoomSubscriptions[roomID]
|
||||
if ok && room.TimelineLimit > 0 {
|
||||
return room.TimelineLimit
|
||||
}
|
||||
}
|
||||
if r.Lists[listIndex].TimelineLimit > 0 {
|
||||
return r.Lists[listIndex].TimelineLimit
|
||||
if r.Lists[listKey].TimelineLimit > 0 {
|
||||
return r.Lists[listKey].TimelineLimit
|
||||
}
|
||||
return DefaultTimelineLimit
|
||||
}
|
||||
|
@ -224,7 +224,7 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: Request{
|
||||
Lists: []RequestList{},
|
||||
Lists: map[string]RequestList{},
|
||||
RoomSubscriptions: map[string]RoomSubscription{
|
||||
"!foo:bar": {
|
||||
TimelineLimit: 10,
|
||||
@ -235,7 +235,7 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
wantDelta: func(input *Request, d testData) RequestDelta {
|
||||
return RequestDelta{
|
||||
Subs: []string{"!foo:bar"},
|
||||
Lists: []RequestListDelta{},
|
||||
Lists: map[string]RequestListDelta{},
|
||||
}
|
||||
},
|
||||
},
|
||||
@ -243,16 +243,16 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
testData: testData{
|
||||
name: "initial: list only",
|
||||
next: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"a": {
|
||||
Ranges: [][2]int64{{0, 20}},
|
||||
Sort: []string{SortByHighlightCount},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"a": {
|
||||
Ranges: [][2]int64{{0, 20}},
|
||||
Sort: []string{SortByHighlightCount},
|
||||
},
|
||||
@ -262,10 +262,10 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
},
|
||||
wantDelta: func(input *Request, d testData) RequestDelta {
|
||||
return RequestDelta{
|
||||
Lists: []RequestListDelta{
|
||||
{
|
||||
Lists: map[string]RequestListDelta{
|
||||
"a": {
|
||||
Prev: nil,
|
||||
Curr: &d.want.Lists[0],
|
||||
Curr: listPtr(d.want.Lists["a"]),
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -275,15 +275,15 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
testData: testData{
|
||||
name: "initial: sets sort order to be by_recency if missing",
|
||||
next: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"a": {
|
||||
Ranges: [][2]int64{{0, 20}},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"a": {
|
||||
Ranges: [][2]int64{{0, 20}},
|
||||
Sort: []string{SortByRecency},
|
||||
},
|
||||
@ -293,10 +293,10 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
},
|
||||
wantDelta: func(input *Request, d testData) RequestDelta {
|
||||
return RequestDelta{
|
||||
Lists: []RequestListDelta{
|
||||
{
|
||||
Lists: map[string]RequestListDelta{
|
||||
"a": {
|
||||
Prev: nil,
|
||||
Curr: &d.want.Lists[0],
|
||||
Curr: listPtr(d.want.Lists["a"]),
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -306,19 +306,19 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
testData: testData{
|
||||
name: "initial: multiple lists",
|
||||
next: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"z": {
|
||||
Ranges: [][2]int64{{0, 20}},
|
||||
Sort: []string{SortByHighlightCount},
|
||||
},
|
||||
{
|
||||
"a": {
|
||||
Ranges: [][2]int64{{0, 10}},
|
||||
Filters: &RequestFilters{
|
||||
IsEncrypted: &boolTrue,
|
||||
},
|
||||
Sort: []string{SortByRecency},
|
||||
},
|
||||
{
|
||||
"b": {
|
||||
Ranges: [][2]int64{{0, 5}},
|
||||
Sort: []string{SortByRecency, SortByName},
|
||||
RoomSubscription: RoomSubscription{
|
||||
@ -331,19 +331,19 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"z": {
|
||||
Ranges: [][2]int64{{0, 20}},
|
||||
Sort: []string{SortByHighlightCount},
|
||||
},
|
||||
{
|
||||
"a": {
|
||||
Ranges: [][2]int64{{0, 10}},
|
||||
Filters: &RequestFilters{
|
||||
IsEncrypted: &boolTrue,
|
||||
},
|
||||
Sort: []string{SortByRecency},
|
||||
},
|
||||
{
|
||||
"b": {
|
||||
Ranges: [][2]int64{{0, 5}},
|
||||
Sort: []string{SortByRecency, SortByName},
|
||||
RoomSubscription: RoomSubscription{
|
||||
@ -359,18 +359,18 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
},
|
||||
wantDelta: func(input *Request, d testData) RequestDelta {
|
||||
return RequestDelta{
|
||||
Lists: []RequestListDelta{
|
||||
{
|
||||
Lists: map[string]RequestListDelta{
|
||||
"z": {
|
||||
Prev: nil,
|
||||
Curr: &d.want.Lists[0],
|
||||
Curr: listPtr(d.want.Lists["z"]),
|
||||
},
|
||||
{
|
||||
"a": {
|
||||
Prev: nil,
|
||||
Curr: &d.want.Lists[1],
|
||||
Curr: listPtr(d.want.Lists["a"]),
|
||||
},
|
||||
{
|
||||
"b": {
|
||||
Prev: nil,
|
||||
Curr: &d.want.Lists[2],
|
||||
Curr: listPtr(d.want.Lists["b"]),
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -380,8 +380,8 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
testData: testData{
|
||||
name: "initial: list and sub",
|
||||
next: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"f": {
|
||||
Ranges: [][2]int64{{0, 20}},
|
||||
Sort: []string{SortByHighlightCount},
|
||||
},
|
||||
@ -393,8 +393,8 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"f": {
|
||||
Ranges: [][2]int64{{0, 20}},
|
||||
Sort: []string{SortByHighlightCount},
|
||||
},
|
||||
@ -409,10 +409,10 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
wantDelta: func(input *Request, d testData) RequestDelta {
|
||||
return RequestDelta{
|
||||
Subs: []string{"!foo:bar"},
|
||||
Lists: []RequestListDelta{
|
||||
{
|
||||
Lists: map[string]RequestListDelta{
|
||||
"f": {
|
||||
Prev: nil,
|
||||
Curr: &d.want.Lists[0],
|
||||
Curr: listPtr(d.want.Lists["f"]),
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -422,8 +422,8 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
},
|
||||
{
|
||||
input: &Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"q": {
|
||||
Sort: []string{SortByName},
|
||||
RoomSubscription: RoomSubscription{
|
||||
TimelineLimit: 5,
|
||||
@ -445,8 +445,8 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
testData: testData{
|
||||
name: "overwriting of sort and updating subs without adding new ones",
|
||||
next: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"q": {
|
||||
Sort: []string{SortByRecency},
|
||||
},
|
||||
},
|
||||
@ -457,8 +457,8 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"q": {
|
||||
Sort: []string{SortByRecency},
|
||||
RoomSubscription: RoomSubscription{
|
||||
TimelineLimit: 5,
|
||||
@ -476,10 +476,10 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
return RequestDelta{
|
||||
Subs: nil,
|
||||
Unsubs: nil,
|
||||
Lists: []RequestListDelta{
|
||||
{
|
||||
Prev: &input.Lists[0],
|
||||
Curr: &d.want.Lists[0],
|
||||
Lists: map[string]RequestListDelta{
|
||||
"q": {
|
||||
Prev: listPtr(input.Lists["q"]),
|
||||
Curr: listPtr(d.want.Lists["q"]),
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -490,8 +490,8 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
testData: testData{
|
||||
name: "Adding a sub",
|
||||
next: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"q": {
|
||||
Sort: []string{SortByRecency},
|
||||
RoomSubscription: RoomSubscription{
|
||||
TimelineLimit: 5,
|
||||
@ -505,8 +505,8 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"q": {
|
||||
Sort: []string{SortByRecency},
|
||||
RoomSubscription: RoomSubscription{
|
||||
TimelineLimit: 5,
|
||||
@ -527,10 +527,10 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
return RequestDelta{
|
||||
Subs: []string{"!bar:baz"},
|
||||
Unsubs: nil,
|
||||
Lists: []RequestListDelta{
|
||||
{
|
||||
Prev: &input.Lists[0],
|
||||
Curr: &d.want.Lists[0],
|
||||
Lists: map[string]RequestListDelta{
|
||||
"q": {
|
||||
Prev: listPtr(input.Lists["q"]),
|
||||
Curr: listPtr(d.want.Lists["q"]),
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -541,16 +541,16 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
testData: testData{
|
||||
name: "Unsubscribing",
|
||||
next: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"q": {
|
||||
Sort: []string{SortByName},
|
||||
},
|
||||
},
|
||||
UnsubscribeRooms: []string{"!foo:bar"},
|
||||
},
|
||||
want: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"q": {
|
||||
Sort: []string{SortByName},
|
||||
RoomSubscription: RoomSubscription{
|
||||
TimelineLimit: 5,
|
||||
@ -564,10 +564,10 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
return RequestDelta{
|
||||
Subs: nil,
|
||||
Unsubs: []string{"!foo:bar"},
|
||||
Lists: []RequestListDelta{
|
||||
{
|
||||
Prev: &input.Lists[0],
|
||||
Curr: &d.want.Lists[0],
|
||||
Lists: map[string]RequestListDelta{
|
||||
"q": {
|
||||
Prev: listPtr(input.Lists["q"]),
|
||||
Curr: listPtr(d.want.Lists["q"]),
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -578,8 +578,8 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
testData: testData{
|
||||
name: "Subscribing/Unsubscribing in one request",
|
||||
next: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"q": {
|
||||
Sort: []string{SortByRecency},
|
||||
},
|
||||
},
|
||||
@ -591,8 +591,8 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
UnsubscribeRooms: []string{"!bar:baz"},
|
||||
},
|
||||
want: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"q": {
|
||||
Sort: []string{SortByRecency},
|
||||
RoomSubscription: RoomSubscription{
|
||||
TimelineLimit: 5,
|
||||
@ -610,10 +610,10 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
return RequestDelta{
|
||||
Subs: nil,
|
||||
Unsubs: nil,
|
||||
Lists: []RequestListDelta{
|
||||
{
|
||||
Prev: &input.Lists[0],
|
||||
Curr: &d.want.Lists[0],
|
||||
Lists: map[string]RequestListDelta{
|
||||
"q": {
|
||||
Prev: listPtr(input.Lists["q"]),
|
||||
Curr: listPtr(d.want.Lists["q"]),
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -623,11 +623,15 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
testData: testData{
|
||||
name: "deleting a list",
|
||||
next: Request{
|
||||
Lists: []RequestList{},
|
||||
Lists: map[string]RequestList{
|
||||
"q": {
|
||||
Deleted: true,
|
||||
},
|
||||
},
|
||||
RoomSubscriptions: map[string]RoomSubscription{},
|
||||
},
|
||||
want: Request{
|
||||
Lists: []RequestList{},
|
||||
Lists: map[string]RequestList{},
|
||||
RoomSubscriptions: map[string]RoomSubscription{
|
||||
"!foo:bar": {
|
||||
TimelineLimit: 10,
|
||||
@ -639,9 +643,9 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
return RequestDelta{
|
||||
Subs: nil,
|
||||
Unsubs: nil,
|
||||
Lists: []RequestListDelta{
|
||||
{
|
||||
Prev: &input.Lists[0],
|
||||
Lists: map[string]RequestListDelta{
|
||||
"q": {
|
||||
Prev: listPtr(input.Lists["q"]),
|
||||
Curr: nil,
|
||||
},
|
||||
},
|
||||
@ -652,11 +656,11 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
testData: testData{
|
||||
name: "adding a list",
|
||||
next: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"q": {
|
||||
Sort: []string{SortByRecency},
|
||||
},
|
||||
{
|
||||
"s": {
|
||||
Sort: []string{SortByHighlightCount},
|
||||
RoomSubscription: RoomSubscription{
|
||||
TimelineLimit: 9000,
|
||||
@ -666,14 +670,14 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
RoomSubscriptions: map[string]RoomSubscription{},
|
||||
},
|
||||
want: Request{
|
||||
Lists: []RequestList{
|
||||
{
|
||||
Lists: map[string]RequestList{
|
||||
"q": {
|
||||
Sort: []string{SortByRecency},
|
||||
RoomSubscription: RoomSubscription{
|
||||
TimelineLimit: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
"s": {
|
||||
Sort: []string{SortByHighlightCount},
|
||||
RoomSubscription: RoomSubscription{
|
||||
TimelineLimit: 9000,
|
||||
@ -691,14 +695,14 @@ func TestRequestApplyDeltas(t *testing.T) {
|
||||
return RequestDelta{
|
||||
Subs: nil,
|
||||
Unsubs: nil,
|
||||
Lists: []RequestListDelta{
|
||||
{
|
||||
Prev: &input.Lists[0],
|
||||
Curr: &d.want.Lists[0],
|
||||
Lists: map[string]RequestListDelta{
|
||||
"q": {
|
||||
Prev: listPtr(input.Lists["q"]),
|
||||
Curr: listPtr(d.want.Lists["q"]),
|
||||
},
|
||||
{
|
||||
"s": {
|
||||
Prev: nil,
|
||||
Curr: &d.want.Lists[1],
|
||||
Curr: listPtr(d.want.Lists["s"]),
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -1040,3 +1044,7 @@ func jsonEqual(t *testing.T, name string, got, want interface{}) {
|
||||
t.Errorf("%s\ngot %s\nwant %s", name, string(aa), string(bb))
|
||||
}
|
||||
}
|
||||
|
||||
func listPtr(l RequestList) *RequestList {
|
||||
return &l
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ const (
|
||||
)
|
||||
|
||||
type Response struct {
|
||||
Lists []ResponseList `json:"lists"`
|
||||
Lists map[string]ResponseList `json:"lists"`
|
||||
|
||||
Rooms map[string]Room `json:"rooms"`
|
||||
Extensions extensions.Response `json:"extensions"`
|
||||
@ -50,7 +50,7 @@ func (r *Response) ListOps() int {
|
||||
func (r *Response) UnmarshalJSON(b []byte) error {
|
||||
temporary := struct {
|
||||
Rooms map[string]Room `json:"rooms"`
|
||||
Lists []struct {
|
||||
Lists map[string]struct {
|
||||
Ops []json.RawMessage `json:"ops"`
|
||||
Count int `json:"count"`
|
||||
} `json:"lists"`
|
||||
@ -68,10 +68,9 @@ func (r *Response) UnmarshalJSON(b []byte) error {
|
||||
r.TxnID = temporary.TxnID
|
||||
r.Session = temporary.Session
|
||||
r.Extensions = temporary.Extensions
|
||||
r.Lists = make([]ResponseList, len(temporary.Lists))
|
||||
r.Lists = make(map[string]ResponseList, len(temporary.Lists))
|
||||
|
||||
for i := range temporary.Lists {
|
||||
l := temporary.Lists[i]
|
||||
for listKey, l := range temporary.Lists {
|
||||
var list ResponseList
|
||||
list.Count = l.Count
|
||||
for _, op := range l.Ops {
|
||||
@ -89,7 +88,7 @@ func (r *Response) UnmarshalJSON(b []byte) error {
|
||||
list.Ops = append(list.Ops, &oper)
|
||||
}
|
||||
}
|
||||
r.Lists[i] = list
|
||||
r.Lists[listKey] = list
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -34,8 +34,8 @@ func TestMultipleLists(t *testing.T) {
|
||||
|
||||
// request 2 lists, one set encrypted, one set unencrypted
|
||||
res := alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"enc": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 2}, // first 3 rooms
|
||||
@ -47,7 +47,7 @@ func TestMultipleLists(t *testing.T) {
|
||||
IsEncrypted: &boolTrue,
|
||||
},
|
||||
},
|
||||
{
|
||||
"unenc": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 2}, // first 3 rooms
|
||||
@ -63,12 +63,15 @@ func TestMultipleLists(t *testing.T) {
|
||||
})
|
||||
|
||||
m.MatchResponse(t, res,
|
||||
m.MatchLists([]m.ListMatcher{
|
||||
m.MatchV3Count(len(encryptedRoomIDs)),
|
||||
m.MatchV3Ops(m.MatchV3SyncOp(0, 2, encryptedRoomIDs[:3])),
|
||||
}, []m.ListMatcher{
|
||||
m.MatchV3Count(len(unencryptedRoomIDs)),
|
||||
m.MatchV3Ops(m.MatchV3SyncOp(0, 2, unencryptedRoomIDs[:3])),
|
||||
m.MatchLists(map[string][]m.ListMatcher{
|
||||
"enc": {
|
||||
m.MatchV3Count(len(encryptedRoomIDs)),
|
||||
m.MatchV3Ops(m.MatchV3SyncOp(0, 2, encryptedRoomIDs[:3])),
|
||||
},
|
||||
"unenc": {
|
||||
m.MatchV3Count(len(unencryptedRoomIDs)),
|
||||
m.MatchV3Ops(m.MatchV3SyncOp(0, 2, unencryptedRoomIDs[:3])),
|
||||
},
|
||||
}),
|
||||
m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
encryptedRoomIDs[0]: {},
|
||||
@ -82,13 +85,13 @@ func TestMultipleLists(t *testing.T) {
|
||||
|
||||
// now scroll one of the lists
|
||||
res = alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"enc": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 2}, // first 3 rooms still
|
||||
},
|
||||
},
|
||||
{
|
||||
"unenc": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 2}, // first 3 rooms
|
||||
[2]int64{3, 5}, // next 3 rooms
|
||||
@ -96,13 +99,16 @@ func TestMultipleLists(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}, WithPos(res.Pos))
|
||||
m.MatchResponse(t, res, m.MatchLists([]m.ListMatcher{
|
||||
m.MatchV3Count(len(encryptedRoomIDs)),
|
||||
}, []m.ListMatcher{
|
||||
m.MatchV3Count(len(unencryptedRoomIDs)),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(3, 5, unencryptedRoomIDs[3:6]),
|
||||
),
|
||||
m.MatchResponse(t, res, m.MatchLists(map[string][]m.ListMatcher{
|
||||
"enc": {
|
||||
m.MatchV3Count(len(encryptedRoomIDs)),
|
||||
},
|
||||
"unenc": {
|
||||
m.MatchV3Count(len(unencryptedRoomIDs)),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(3, 5, unencryptedRoomIDs[3:6]),
|
||||
),
|
||||
},
|
||||
}), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
unencryptedRoomIDs[3]: {},
|
||||
unencryptedRoomIDs[4]: {},
|
||||
@ -118,13 +124,13 @@ func TestMultipleLists(t *testing.T) {
|
||||
// We are tracking the first few encrypted rooms so we expect list 0 to update
|
||||
// However we do not track old unencrypted rooms so we expect no change in list 1
|
||||
res = alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"enc": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 2}, // first 3 rooms still
|
||||
},
|
||||
},
|
||||
{
|
||||
"unenc": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 2}, // first 3 rooms
|
||||
[2]int64{3, 5}, // next 3 rooms
|
||||
@ -132,14 +138,17 @@ func TestMultipleLists(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}, WithPos(res.Pos))
|
||||
m.MatchResponse(t, res, m.MatchLists([]m.ListMatcher{
|
||||
m.MatchV3Count(len(encryptedRoomIDs)),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(2),
|
||||
m.MatchV3InsertOp(0, encryptedRoomIDs[0]),
|
||||
),
|
||||
}, []m.ListMatcher{
|
||||
m.MatchV3Count(len(unencryptedRoomIDs)),
|
||||
m.MatchResponse(t, res, m.MatchLists(map[string][]m.ListMatcher{
|
||||
"enc": {
|
||||
m.MatchV3Count(len(encryptedRoomIDs)),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(2),
|
||||
m.MatchV3InsertOp(0, encryptedRoomIDs[0]),
|
||||
),
|
||||
},
|
||||
"unenc": {
|
||||
m.MatchV3Count(len(unencryptedRoomIDs)),
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
@ -171,8 +180,8 @@ func TestMultipleListsDMUpdate(t *testing.T) {
|
||||
|
||||
// request 2 lists, one set DM, one set no DM
|
||||
res := alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"dm": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 2}, // first 3 rooms
|
||||
@ -184,7 +193,7 @@ func TestMultipleListsDMUpdate(t *testing.T) {
|
||||
IsDM: &boolTrue,
|
||||
},
|
||||
},
|
||||
{
|
||||
"nodm": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 2}, // first 3 rooms
|
||||
@ -199,12 +208,15 @@ func TestMultipleListsDMUpdate(t *testing.T) {
|
||||
},
|
||||
})
|
||||
|
||||
m.MatchResponse(t, res, m.MatchLists([]m.ListMatcher{
|
||||
m.MatchV3Count(len(dmRoomIDs)),
|
||||
m.MatchV3Ops(m.MatchV3SyncOp(0, 2, dmRoomIDs[:3])),
|
||||
}, []m.ListMatcher{
|
||||
m.MatchV3Count(len(groupRoomIDs)),
|
||||
m.MatchV3Ops(m.MatchV3SyncOp(0, 2, groupRoomIDs[:3])),
|
||||
m.MatchResponse(t, res, m.MatchLists(map[string][]m.ListMatcher{
|
||||
"dm": {
|
||||
m.MatchV3Count(len(dmRoomIDs)),
|
||||
m.MatchV3Ops(m.MatchV3SyncOp(0, 2, dmRoomIDs[:3])),
|
||||
},
|
||||
"nodm": {
|
||||
m.MatchV3Count(len(groupRoomIDs)),
|
||||
m.MatchV3Ops(m.MatchV3SyncOp(0, 2, groupRoomIDs[:3])),
|
||||
},
|
||||
}))
|
||||
|
||||
// now bring the last DM room to the top with a notif
|
||||
@ -217,27 +229,30 @@ func TestMultipleListsDMUpdate(t *testing.T) {
|
||||
|
||||
// now get the delta: only the DM room should change
|
||||
res = alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"dm": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 2}, // first 3 rooms still
|
||||
},
|
||||
},
|
||||
{
|
||||
"nodm": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 2}, // first 3 rooms still
|
||||
},
|
||||
},
|
||||
},
|
||||
}, WithPos(res.Pos))
|
||||
m.MatchResponse(t, res, m.MatchLists([]m.ListMatcher{
|
||||
m.MatchV3Count(len(dmRoomIDs)),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(2),
|
||||
m.MatchV3InsertOp(0, dmRoomIDs[0]),
|
||||
),
|
||||
}, []m.ListMatcher{
|
||||
m.MatchV3Count(len(groupRoomIDs)),
|
||||
m.MatchResponse(t, res, m.MatchLists(map[string][]m.ListMatcher{
|
||||
"dm": {
|
||||
m.MatchV3Count(len(dmRoomIDs)),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(2),
|
||||
m.MatchV3InsertOp(0, dmRoomIDs[0]),
|
||||
),
|
||||
},
|
||||
"nodm": {
|
||||
m.MatchV3Count(len(groupRoomIDs)),
|
||||
},
|
||||
}), m.MatchRoomSubscription(dmRoomIDs[0], MatchRoomTimelineMostRecent(1, []Event{
|
||||
{
|
||||
Type: "m.room.message",
|
||||
@ -261,14 +276,14 @@ func TestNewListMidConnection(t *testing.T) {
|
||||
|
||||
// first request no list
|
||||
res := alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{},
|
||||
Lists: map[string]sync3.RequestList{},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchLists())
|
||||
m.MatchResponse(t, res, m.MatchLists(nil))
|
||||
|
||||
// now add a list
|
||||
res = alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 2}, // first 3 rooms
|
||||
},
|
||||
@ -278,7 +293,7 @@ func TestNewListMidConnection(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}, WithPos(res.Pos))
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(len(roomIDs)), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(roomIDs)), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 2, roomIDs[:3]),
|
||||
)))
|
||||
}
|
||||
@ -358,8 +373,8 @@ func TestMultipleOverlappingLists(t *testing.T) {
|
||||
//
|
||||
// Rooms with * are union'd
|
||||
res := alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"enc": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 4}, // first 5 rooms
|
||||
@ -374,7 +389,7 @@ func TestMultipleOverlappingLists(t *testing.T) {
|
||||
IsEncrypted: &boolTrue,
|
||||
},
|
||||
},
|
||||
{
|
||||
"dm": {
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 4}, // first 5 rooms
|
||||
@ -393,8 +408,8 @@ func TestMultipleOverlappingLists(t *testing.T) {
|
||||
})
|
||||
|
||||
m.MatchResponse(t, res,
|
||||
m.MatchList(0, m.MatchV3Ops(m.MatchV3SyncOp(0, 4, encryptedRoomIDs[:5]))),
|
||||
m.MatchList(1, m.MatchV3Ops(m.MatchV3SyncOp(0, 4, dmRoomIDs[:5]))),
|
||||
m.MatchList("enc", m.MatchV3Ops(m.MatchV3SyncOp(0, 4, encryptedRoomIDs[:5]))),
|
||||
m.MatchList("dm", m.MatchV3Ops(m.MatchV3SyncOp(0, 4, dmRoomIDs[:5]))),
|
||||
m.MatchRoomSubscriptions(map[string][]m.RoomMatcher{
|
||||
// encrypted rooms just come from the encrypted only list
|
||||
encryptedRoomIDs[0]: {
|
||||
@ -513,8 +528,8 @@ func TestNot500OnNewRooms(t *testing.T) {
|
||||
mSpace := "m.space"
|
||||
alice := registerNewUser(t)
|
||||
res := alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
SlowGetAllRooms: &boolTrue,
|
||||
Filters: &sync3.RequestFilters{
|
||||
RoomTypes: []*string{&mSpace},
|
||||
@ -524,14 +539,14 @@ func TestNot500OnNewRooms(t *testing.T) {
|
||||
})
|
||||
alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"})
|
||||
alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
SlowGetAllRooms: &boolTrue,
|
||||
Filters: &sync3.RequestFilters{
|
||||
RoomTypes: []*string{&mSpace},
|
||||
},
|
||||
},
|
||||
{
|
||||
"b": {
|
||||
Filters: &sync3.RequestFilters{
|
||||
IsDM: &boolFalse,
|
||||
},
|
||||
@ -540,12 +555,13 @@ func TestNot500OnNewRooms(t *testing.T) {
|
||||
},
|
||||
}, WithPos(res.Pos))
|
||||
alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"})
|
||||
// should not 500
|
||||
alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
SlowGetAllRooms: &boolTrue,
|
||||
},
|
||||
{
|
||||
"b": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
},
|
||||
},
|
||||
@ -557,13 +573,13 @@ func TestNot500OnNewRooms(t *testing.T) {
|
||||
func TestNewRoomNameCalculations(t *testing.T) {
|
||||
alice := registerNewUser(t)
|
||||
res := alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
SlowGetAllRooms: &boolTrue,
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(0)))
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(0)))
|
||||
|
||||
// create 10 room in parallel and at the same time spam sliding sync to ensure we get bits of
|
||||
// rooms before they are fully loaded.
|
||||
@ -591,8 +607,8 @@ func TestNewRoomNameCalculations(t *testing.T) {
|
||||
var err error
|
||||
for {
|
||||
res = alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
SlowGetAllRooms: &boolTrue,
|
||||
},
|
||||
},
|
||||
@ -638,8 +654,8 @@ func TestChangeSortOrder(t *testing.T) {
|
||||
alice := registerNewUser(t)
|
||||
|
||||
res := alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
@ -663,8 +679,8 @@ func TestChangeSortOrder(t *testing.T) {
|
||||
break
|
||||
}
|
||||
res = alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
},
|
||||
},
|
||||
@ -692,8 +708,8 @@ func TestChangeSortOrder(t *testing.T) {
|
||||
txnID := "a"
|
||||
res = alice.SlidingSync(t, sync3.Request{
|
||||
TxnID: "a",
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
Sort: []string{sync3.SortByName},
|
||||
},
|
||||
@ -701,15 +717,15 @@ func TestChangeSortOrder(t *testing.T) {
|
||||
}, WithPos(res.Pos))
|
||||
for res.TxnID != txnID {
|
||||
res = alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
},
|
||||
},
|
||||
}, WithPos(res.Pos))
|
||||
}
|
||||
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(4), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(4), m.MatchV3Ops(
|
||||
m.MatchV3InvalidateOp(0, 20),
|
||||
m.MatchV3SyncOp(0, 20, []string{gotNameToIDs["Apple"], gotNameToIDs["Kiwi"], gotNameToIDs["Lemon"], gotNameToIDs["Orange"]}),
|
||||
)))
|
||||
|
@ -30,8 +30,8 @@ func TestRoomStateTransitions(t *testing.T) {
|
||||
|
||||
// seed the proxy with Alice data
|
||||
alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
{0, 100},
|
||||
},
|
||||
@ -42,8 +42,8 @@ func TestRoomStateTransitions(t *testing.T) {
|
||||
|
||||
// bob should see the invited/joined rooms
|
||||
bobRes := bob.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
{0, 100},
|
||||
},
|
||||
@ -57,7 +57,7 @@ func TestRoomStateTransitions(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, bobRes, m.MatchList(0, m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchResponse(t, bobRes, m.MatchList("a", m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 100, []string{inviteRoomID, joinRoomID}),
|
||||
)), m.MatchRoomSubscriptions(map[string][]m.RoomMatcher{
|
||||
inviteRoomID: {
|
||||
@ -78,15 +78,15 @@ func TestRoomStateTransitions(t *testing.T) {
|
||||
|
||||
// the room should be updated with the initial flag set to replace what was in the invite state
|
||||
bobRes = bob.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
{0, 100},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, WithPos(bobRes.Pos))
|
||||
m.MatchResponse(t, bobRes, m.MatchNoV3Ops(), m.MatchList(0, m.MatchV3Count(2)), m.MatchRoomSubscription(inviteRoomID,
|
||||
m.MatchResponse(t, bobRes, m.MatchNoV3Ops(), m.MatchList("a", m.MatchV3Count(2)), m.MatchRoomSubscription(inviteRoomID,
|
||||
MatchRoomRequiredState([]Event{
|
||||
{
|
||||
Type: "m.room.create",
|
||||
@ -122,8 +122,8 @@ func TestInviteRejection(t *testing.T) {
|
||||
|
||||
// sync as bob, we should see 1 invite
|
||||
res := bob.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
Filters: &sync3.RequestFilters{
|
||||
IsInvite: &boolTrue,
|
||||
@ -131,7 +131,7 @@ func TestInviteRejection(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 20, []string{firstInviteRoomID}),
|
||||
)), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
firstInviteRoomID: {
|
||||
@ -156,13 +156,13 @@ func TestInviteRejection(t *testing.T) {
|
||||
since = bob.MustSyncUntil(t, SyncReq{Since: since}, SyncInvitedTo(bob.UserID, secondInviteRoomID))
|
||||
|
||||
res = bob.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
},
|
||||
},
|
||||
}, WithPos(res.Pos))
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(1),
|
||||
m.MatchV3InsertOp(0, secondInviteRoomID),
|
||||
)), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
@ -190,21 +190,21 @@ func TestInviteRejection(t *testing.T) {
|
||||
|
||||
// the list should be purged
|
||||
res = bob.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
},
|
||||
},
|
||||
}, WithPos(res.Pos))
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(0), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(0), m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(1),
|
||||
m.MatchV3DeleteOp(0),
|
||||
)))
|
||||
|
||||
// fresh sync -> no invites
|
||||
res = bob.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
Filters: &sync3.RequestFilters{
|
||||
IsInvite: &boolTrue,
|
||||
@ -212,7 +212,7 @@ func TestInviteRejection(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchNoV3Ops(), m.MatchRoomSubscriptionsStrict(nil), m.MatchList(0, m.MatchV3Count(0)))
|
||||
m.MatchResponse(t, res, m.MatchNoV3Ops(), m.MatchRoomSubscriptionsStrict(nil), m.MatchList("a", m.MatchV3Count(0)))
|
||||
}
|
||||
|
||||
func TestInviteAcceptance(t *testing.T) {
|
||||
@ -228,8 +228,8 @@ func TestInviteAcceptance(t *testing.T) {
|
||||
|
||||
// sync as bob, we should see 1 invite
|
||||
res := bob.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
Filters: &sync3.RequestFilters{
|
||||
IsInvite: &boolTrue,
|
||||
@ -237,7 +237,7 @@ func TestInviteAcceptance(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 20, []string{firstInviteRoomID}),
|
||||
)), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
firstInviteRoomID: {
|
||||
@ -261,13 +261,13 @@ func TestInviteAcceptance(t *testing.T) {
|
||||
alice.SlidingSyncUntilMembership(t, "", secondInviteRoomID, bob, "invite")
|
||||
|
||||
res = bob.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
},
|
||||
},
|
||||
}, WithPos(res.Pos))
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(1),
|
||||
m.MatchV3InsertOp(0, secondInviteRoomID),
|
||||
)), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
@ -295,21 +295,21 @@ func TestInviteAcceptance(t *testing.T) {
|
||||
|
||||
// the list should be purged
|
||||
res = bob.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
},
|
||||
},
|
||||
}, WithPos(res.Pos))
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(0), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(0), m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(1),
|
||||
m.MatchV3DeleteOp(0),
|
||||
)))
|
||||
|
||||
// fresh sync -> no invites
|
||||
res = bob.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
Filters: &sync3.RequestFilters{
|
||||
IsInvite: &boolTrue,
|
||||
@ -317,7 +317,7 @@ func TestInviteAcceptance(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchNoV3Ops(), m.MatchRoomSubscriptionsStrict(nil), m.MatchList(0, m.MatchV3Count(0)))
|
||||
m.MatchResponse(t, res, m.MatchNoV3Ops(), m.MatchRoomSubscriptionsStrict(nil), m.MatchList("a", m.MatchV3Count(0)))
|
||||
}
|
||||
|
||||
// test invite/join counts update and are accurate
|
||||
@ -335,13 +335,13 @@ func TestMemberCounts(t *testing.T) {
|
||||
|
||||
// sync as bob, we should see 2 invited rooms with the same join counts so as not to leak join counts
|
||||
res := bob.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 20, []string{firstRoomID, secondRoomID}, true),
|
||||
)), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
firstRoomID: {
|
||||
@ -381,8 +381,8 @@ func TestMemberCounts(t *testing.T) {
|
||||
alice.SlidingSyncUntilMembership(t, "", secondRoomID, bob, "join")
|
||||
|
||||
res = bob.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
},
|
||||
},
|
||||
@ -406,8 +406,8 @@ func TestMemberCounts(t *testing.T) {
|
||||
Content: map[string]interface{}{"body": "ping", "msgtype": "m.text"},
|
||||
})
|
||||
res = bob.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
},
|
||||
},
|
||||
@ -425,8 +425,8 @@ func TestMemberCounts(t *testing.T) {
|
||||
bob.MustSyncUntil(t, SyncReq{}, SyncLeftFrom(charlie.UserID, secondRoomID))
|
||||
|
||||
res = bob.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
},
|
||||
},
|
||||
|
@ -81,8 +81,8 @@ func TestNumLive(t *testing.T) {
|
||||
alice.SlidingSyncUntilMembership(t, "", roomID3, bob, "join")
|
||||
// at this point, roomID is at the bottom, check.
|
||||
res = bob.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 1}}, // top 2 rooms
|
||||
Sort: []string{sync3.SortByRecency},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
@ -91,7 +91,7 @@ func TestNumLive(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 1, []string{roomID3, roomID2}),
|
||||
)))
|
||||
// now send 2 live events into roomID to bump it to the top
|
||||
@ -113,8 +113,8 @@ func TestNumLive(t *testing.T) {
|
||||
alice.SlidingSyncUntilEventID(t, "", roomID, eventID4)
|
||||
// now syncing with bob should see 2 live events
|
||||
res = bob.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 1}}, // top 2 rooms
|
||||
},
|
||||
},
|
||||
|
@ -30,8 +30,8 @@ func TestPrevBatch(t *testing.T) {
|
||||
|
||||
// hit proxy
|
||||
res := client.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{[2]int64{0, 10}},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: 1,
|
||||
|
@ -33,23 +33,25 @@ func TestSecurityLiveStreamEventLeftLeak(t *testing.T) {
|
||||
|
||||
// start sync streams for Alice and Eve
|
||||
aliceRes := alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
}},
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, aliceRes, m.MatchList(0, m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchResponse(t, aliceRes, m.MatchList("a", m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 10, []string{roomID}),
|
||||
)))
|
||||
eveRes := eve.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
}},
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, eveRes, m.MatchList(0, m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchResponse(t, eveRes, m.MatchList("a", m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 10, []string{roomID}),
|
||||
)))
|
||||
|
||||
@ -70,16 +72,17 @@ func TestSecurityLiveStreamEventLeftLeak(t *testing.T) {
|
||||
|
||||
// Ensure Alice sees both events
|
||||
aliceRes = alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
RequiredState: [][2]string{
|
||||
{"m.room.name", ""},
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
},
|
||||
}},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
RequiredState: [][2]string{
|
||||
{"m.room.name", ""},
|
||||
},
|
||||
},
|
||||
}},
|
||||
}, WithPos(aliceRes.Pos))
|
||||
|
||||
timeline := aliceRes.Rooms[roomID].Timeline
|
||||
@ -107,25 +110,26 @@ func TestSecurityLiveStreamEventLeftLeak(t *testing.T) {
|
||||
kickEvent := lastTwoEvents[0]
|
||||
|
||||
// TODO: WE should be returning updated values for name and required_state
|
||||
m.MatchResponse(t, aliceRes, m.MatchList(0, m.MatchV3Count(1)), m.MatchNoV3Ops(), m.MatchRoomSubscription(
|
||||
m.MatchResponse(t, aliceRes, m.MatchList("a", m.MatchV3Count(1)), m.MatchNoV3Ops(), m.MatchRoomSubscription(
|
||||
roomID, m.MatchRoomTimelineMostRecent(2, []json.RawMessage{kickEvent, sensitiveEvent}),
|
||||
))
|
||||
|
||||
// Ensure Eve doesn't see this message in the timeline, name calc or required_state
|
||||
eveRes = eve.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
RequiredState: [][2]string{
|
||||
{"m.room.name", ""},
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
},
|
||||
}},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
RequiredState: [][2]string{
|
||||
{"m.room.name", ""},
|
||||
},
|
||||
},
|
||||
}},
|
||||
}, WithPos(eveRes.Pos))
|
||||
// the room is deleted from eve's point of view and she sees up to and including her kick event
|
||||
m.MatchResponse(t, eveRes, m.MatchList(0, m.MatchV3Count(0), m.MatchV3Ops(m.MatchV3DeleteOp(0))), m.MatchRoomSubscription(
|
||||
m.MatchResponse(t, eveRes, m.MatchList("a", m.MatchV3Count(0), m.MatchV3Ops(m.MatchV3DeleteOp(0))), m.MatchRoomSubscription(
|
||||
roomID, m.MatchRoomName(""), m.MatchRoomRequiredState(nil), m.MatchRoomTimelineMostRecent(1, []json.RawMessage{kickEvent}),
|
||||
))
|
||||
}
|
||||
@ -157,11 +161,12 @@ func TestSecurityRoomSubscriptionLeak(t *testing.T) {
|
||||
|
||||
// start sync streams for Eve, with a room subscription to alice's private room
|
||||
eveRes := eve.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
}},
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
}},
|
||||
RoomSubscriptions: map[string]sync3.RoomSubscription{
|
||||
alicePrivateRoomID: {
|
||||
TimelineLimit: 5,
|
||||
@ -172,7 +177,7 @@ func TestSecurityRoomSubscriptionLeak(t *testing.T) {
|
||||
},
|
||||
})
|
||||
// Assert that Eve doesn't see anything
|
||||
m.MatchResponse(t, eveRes, m.MatchList(0, m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchResponse(t, eveRes, m.MatchList("a", m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 10, []string{eveUnrelatedRoomID}),
|
||||
)), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
eveUnrelatedRoomID: {},
|
||||
@ -187,15 +192,16 @@ func TestSecurityRoomSubscriptionLeak(t *testing.T) {
|
||||
},
|
||||
})
|
||||
eveRes = eve.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
}},
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
}},
|
||||
}, WithPos(eveRes.Pos))
|
||||
|
||||
// Assert that Eve doesn't see anything
|
||||
m.MatchResponse(t, eveRes, m.MatchList(0, m.MatchV3Count(1)), m.MatchNoV3Ops(), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{}))
|
||||
m.MatchResponse(t, eveRes, m.MatchList("a", m.MatchV3Count(1)), m.MatchNoV3Ops(), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{}))
|
||||
}
|
||||
|
||||
// Test that events do not leak via direct space subscriptions.
|
||||
@ -231,8 +237,8 @@ func TestSecuritySpaceDataLeak(t *testing.T) {
|
||||
|
||||
// ensure eve sees nothing
|
||||
res := eve.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: [][2]int64{{0, 20}},
|
||||
Filters: &sync3.RequestFilters{
|
||||
Spaces: []string{roomA},
|
||||
@ -295,8 +301,8 @@ func TestSecuritySpaceMetadataLeak(t *testing.T) {
|
||||
|
||||
// ensure eve sees nothing
|
||||
res := eve.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: [][2]int64{{0, 20}},
|
||||
Filters: &sync3.RequestFilters{
|
||||
Spaces: []string{roomA},
|
||||
|
@ -77,8 +77,8 @@ func TestSpacesFilter(t *testing.T) {
|
||||
}
|
||||
t.Logf("requesting rooms in spaces %v", spaces)
|
||||
res := alice.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: [][2]int64{{0, 20}},
|
||||
Filters: &sync3.RequestFilters{
|
||||
Spaces: spaces,
|
||||
@ -86,7 +86,7 @@ func TestSpacesFilter(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}, opts...)
|
||||
m.MatchResponse(t, res, m.MatchList(0, listMatchers...))
|
||||
m.MatchResponse(t, res, m.MatchList("a", listMatchers...))
|
||||
return res
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,8 @@ func TestIncludeOldRooms(t *testing.T) {
|
||||
roomID := client.CreateRoom(t, map[string]interface{}{})
|
||||
|
||||
res := client.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: [][2]int64{{0, 1}},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
RequiredState: [][2]string{{"m.room.create", ""}},
|
||||
@ -26,7 +26,7 @@ func TestIncludeOldRooms(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 1, []string{roomID}),
|
||||
)))
|
||||
newRoomID := upgradeRoom(t, client, roomID)
|
||||
@ -34,15 +34,15 @@ func TestIncludeOldRooms(t *testing.T) {
|
||||
time.Sleep(100 * time.Millisecond) // let the proxy process it
|
||||
|
||||
res = client.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: [][2]int64{{0, 1}},
|
||||
},
|
||||
},
|
||||
}, WithPos(res.Pos))
|
||||
var tombstoneEventID string
|
||||
// count is 1 as we are auto-joined to the upgraded room
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(1),
|
||||
m.MatchV3InsertOp(0, newRoomID), // insert new room
|
||||
m.MatchV3DeleteOp(1), // remove old room
|
||||
@ -86,8 +86,8 @@ func TestIncludeOldRooms(t *testing.T) {
|
||||
|
||||
// now fresh sync with old rooms enabled
|
||||
res = client.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: [][2]int64{{0, 2}},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
RequiredState: [][2]string{{"m.room.member", client.UserID}},
|
||||
@ -98,7 +98,7 @@ func TestIncludeOldRooms(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 2, []string{newRoomID}),
|
||||
)), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
newRoomID: {
|
||||
@ -126,8 +126,8 @@ func TestIncludeOldRooms(t *testing.T) {
|
||||
// finally, a fresh sync without include_old_rooms -> newest room only
|
||||
// now fresh sync with old rooms enabled
|
||||
res = client.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: [][2]int64{{0, 2}},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
RequiredState: [][2]string{{"m.room.member", client.UserID}},
|
||||
@ -135,7 +135,7 @@ func TestIncludeOldRooms(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 2, []string{newRoomID}),
|
||||
)), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
newRoomID: {
|
||||
@ -271,8 +271,8 @@ func TestIncludeOldRoomsSubscriptionUnion(t *testing.T) {
|
||||
|
||||
// should union to timeline_limit=2, req_state=create+member+tombstone
|
||||
res := client.SlidingSync(t, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: [][2]int64{{0, 1}},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: 0,
|
||||
@ -293,7 +293,7 @@ func TestIncludeOldRoomsSubscriptionUnion(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 1, []string{roomB}),
|
||||
)), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
roomA: {
|
||||
|
@ -60,14 +60,15 @@ func benchNumV2Rooms(numRooms int, b *testing.B) {
|
||||
})
|
||||
// do the initial request
|
||||
v3.mustDoV3Request(b, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20}, // first few rooms
|
||||
},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: 3,
|
||||
},
|
||||
}},
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20}, // first few rooms
|
||||
},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: 3,
|
||||
},
|
||||
}},
|
||||
})
|
||||
|
||||
b.ResetTimer() // don't count setup code
|
||||
@ -75,25 +76,26 @@ func benchNumV2Rooms(numRooms int, b *testing.B) {
|
||||
// these should all take roughly the same amount of time, regardless of the value of `numRooms`
|
||||
for n := 0; n < b.N; n++ {
|
||||
v3.mustDoV3Request(b, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
// always use a fixed range else we will scale O(n) with the number of rooms
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20}, // first few rooms
|
||||
},
|
||||
// include a filter to ensure we loop over rooms
|
||||
Filters: &sync3.RequestFilters{
|
||||
IsEncrypted: &boolFalse,
|
||||
},
|
||||
// include a few required state events to force us to query the database
|
||||
// include a few timeline events to force us to query the database
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: 3,
|
||||
RequiredState: [][2]string{
|
||||
{"m.room.create", ""},
|
||||
{"m.room.member", alice},
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
// always use a fixed range else we will scale O(n) with the number of rooms
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20}, // first few rooms
|
||||
},
|
||||
},
|
||||
}},
|
||||
// include a filter to ensure we loop over rooms
|
||||
Filters: &sync3.RequestFilters{
|
||||
IsEncrypted: &boolFalse,
|
||||
},
|
||||
// include a few required state events to force us to query the database
|
||||
// include a few timeline events to force us to query the database
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: 3,
|
||||
RequiredState: [][2]string{
|
||||
{"m.room.create", ""},
|
||||
{"m.room.member", alice},
|
||||
},
|
||||
},
|
||||
}},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ func TestMultipleConnsAtStartup(t *testing.T) {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
_, body, _ := v3.doV3Request(t, ctx, aliceToken, "", sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
@ -67,7 +67,7 @@ func TestMultipleConnsAtStartup(t *testing.T) {
|
||||
|
||||
// do another /sync
|
||||
res = v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
@ -76,7 +76,7 @@ func TestMultipleConnsAtStartup(t *testing.T) {
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 10, []string{roomID}),
|
||||
)))
|
||||
}
|
||||
@ -122,7 +122,7 @@ func TestOutstandingRequestsGetCancelled(t *testing.T) {
|
||||
})
|
||||
// first request to get some data
|
||||
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 1},
|
||||
},
|
||||
@ -132,7 +132,7 @@ func TestOutstandingRequestsGetCancelled(t *testing.T) {
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 1, []string{roomA, roomB}),
|
||||
)))
|
||||
// now we do a blocking request, and a few ms later do another request which can be satisfied
|
||||
@ -146,7 +146,7 @@ func TestOutstandingRequestsGetCancelled(t *testing.T) {
|
||||
defer wg.Done()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
res2 := v3.mustDoV3RequestWithPos(t, aliceToken, pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 1},
|
||||
},
|
||||
@ -160,7 +160,7 @@ func TestOutstandingRequestsGetCancelled(t *testing.T) {
|
||||
m.MatchResponse(t, res2, m.MatchNoV3Ops())
|
||||
// retry request with new pos and we should see the new data
|
||||
res2 = v3.mustDoV3RequestWithPos(t, aliceToken, res2.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 1},
|
||||
},
|
||||
@ -170,7 +170,7 @@ func TestOutstandingRequestsGetCancelled(t *testing.T) {
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res2, m.MatchList(0, m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res2, m.MatchList("a", m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchV3InvalidateOp(0, 1),
|
||||
m.MatchV3SyncOp(0, 1, []string{roomB, roomA}),
|
||||
)))
|
||||
@ -179,7 +179,7 @@ func TestOutstandingRequestsGetCancelled(t *testing.T) {
|
||||
}
|
||||
}()
|
||||
req := sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 1},
|
||||
},
|
||||
@ -190,7 +190,7 @@ func TestOutstandingRequestsGetCancelled(t *testing.T) {
|
||||
if time.Since(startTime) > time.Second {
|
||||
t.Errorf("took >1s to process request which should have been interrupted before timing out, took %v", time.Since(startTime))
|
||||
}
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(2)), m.MatchNoV3Ops())
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(2)), m.MatchNoV3Ops())
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
@ -228,7 +228,7 @@ func TestConnectionTimeoutNotReset(t *testing.T) {
|
||||
})
|
||||
// first request to get some data
|
||||
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 0}, // first room only -> roomID
|
||||
},
|
||||
@ -238,12 +238,12 @@ func TestConnectionTimeoutNotReset(t *testing.T) {
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 0, []string{roomA}),
|
||||
)))
|
||||
// 2nd request with a 1s timeout
|
||||
req := sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 0},
|
||||
},
|
||||
@ -282,7 +282,7 @@ func TestConnectionTimeoutNotReset(t *testing.T) {
|
||||
if dur > (1500 * time.Millisecond) { // 0.5s leeway
|
||||
t.Fatalf("request took %v to complete, expected ~1s", dur)
|
||||
}
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(2)), m.MatchNoV3Ops())
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(2)), m.MatchNoV3Ops())
|
||||
|
||||
}
|
||||
|
||||
@ -377,7 +377,7 @@ func TestTxnIDResponseBuffering(t *testing.T) {
|
||||
// Send a request with room_name_like = C. Get back pos=1
|
||||
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
TxnID: "c",
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
@ -390,13 +390,13 @@ func TestTxnIDResponseBuffering(t *testing.T) {
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchTxnID("c"), m.MatchList(0, m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchTxnID("c"), m.MatchList("a", m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 10, []string{roomC}),
|
||||
)))
|
||||
// Send a request with pos=1 to filter for room_name_like = A . Discard the response.
|
||||
v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
TxnID: "a",
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
@ -413,7 +413,7 @@ func TestTxnIDResponseBuffering(t *testing.T) {
|
||||
// Send a request with pos=1 to filter for room_name_like = B. Ensure we see both A,B and the txn_id is set correctly for both.
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
TxnID: "b",
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
@ -427,7 +427,7 @@ func TestTxnIDResponseBuffering(t *testing.T) {
|
||||
}},
|
||||
})
|
||||
// this response should be the one for A
|
||||
m.MatchResponse(t, res, m.MatchTxnID("a"), m.MatchList(0, m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchTxnID("a"), m.MatchList("a", m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchV3InvalidateOp(0, 10),
|
||||
m.MatchV3SyncOp(0, 10, []string{roomA}),
|
||||
)))
|
||||
@ -436,7 +436,7 @@ func TestTxnIDResponseBuffering(t *testing.T) {
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{})
|
||||
|
||||
// now we get the response for B
|
||||
m.MatchResponse(t, res, m.MatchTxnID("b"), m.MatchList(0, m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchTxnID("b"), m.MatchList("a", m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchV3InvalidateOp(0, 10),
|
||||
m.MatchV3SyncOp(0, 10, []string{roomB}),
|
||||
)))
|
||||
|
@ -36,7 +36,7 @@ func TestExtensionE2EE(t *testing.T) {
|
||||
DeviceUnusedFallbackKeyTypes: fallbackKeyTypes,
|
||||
})
|
||||
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
@ -62,7 +62,7 @@ func TestExtensionE2EE(t *testing.T) {
|
||||
},
|
||||
})
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
@ -82,7 +82,7 @@ func TestExtensionE2EE(t *testing.T) {
|
||||
})
|
||||
v2.waitUntilEmpty(t, alice)
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
@ -111,7 +111,7 @@ func TestExtensionE2EE(t *testing.T) {
|
||||
v2.waitUntilEmpty(t, alice)
|
||||
lastPos := res.Pos
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
@ -127,7 +127,7 @@ func TestExtensionE2EE(t *testing.T) {
|
||||
|
||||
// check that changed|left persist if requesting with the same v3 position
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, lastPos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
@ -153,7 +153,7 @@ func TestExtensionE2EE(t *testing.T) {
|
||||
},
|
||||
})
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
@ -204,7 +204,7 @@ func TestExtensionToDevice(t *testing.T) {
|
||||
|
||||
// 1: check that a fresh sync returns to-device messages
|
||||
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
@ -215,11 +215,11 @@ func TestExtensionToDevice(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(0)), m.MatchToDeviceMessages(toDeviceMsgs))
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(0)), m.MatchToDeviceMessages(toDeviceMsgs))
|
||||
|
||||
// 2: repeating the fresh sync request returns the same messages (not deleted)
|
||||
res = v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
@ -230,11 +230,11 @@ func TestExtensionToDevice(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(0)), m.MatchToDeviceMessages(toDeviceMsgs))
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(0)), m.MatchToDeviceMessages(toDeviceMsgs))
|
||||
|
||||
// 3: update the since token -> no new messages
|
||||
res = v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
@ -246,7 +246,7 @@ func TestExtensionToDevice(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(0)), m.MatchToDeviceMessages([]json.RawMessage{}))
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(0)), m.MatchToDeviceMessages([]json.RawMessage{}))
|
||||
|
||||
// 4: inject live to-device messages -> receive them only.
|
||||
sinceBeforeMsgs := res.Extensions.ToDevice.NextBatch
|
||||
@ -261,7 +261,7 @@ func TestExtensionToDevice(t *testing.T) {
|
||||
})
|
||||
v2.waitUntilEmpty(t, alice)
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
@ -272,11 +272,11 @@ func TestExtensionToDevice(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(0)), m.MatchToDeviceMessages(newToDeviceMsgs))
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(0)), m.MatchToDeviceMessages(newToDeviceMsgs))
|
||||
|
||||
// 5: repeating the previous sync request returns the same live to-device messages (retransmit)
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
@ -287,11 +287,11 @@ func TestExtensionToDevice(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(0)), m.MatchToDeviceMessages(newToDeviceMsgs))
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(0)), m.MatchToDeviceMessages(newToDeviceMsgs))
|
||||
|
||||
// ack the to-device messages
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
@ -303,11 +303,11 @@ func TestExtensionToDevice(t *testing.T) {
|
||||
},
|
||||
})
|
||||
// this response contains nothing
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(0)), m.MatchToDeviceMessages([]json.RawMessage{}))
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(0)), m.MatchToDeviceMessages([]json.RawMessage{}))
|
||||
|
||||
// 6: using an old since token does not return to-device messages anymore as they were deleted.
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10}, // doesn't matter
|
||||
},
|
||||
@ -318,7 +318,7 @@ func TestExtensionToDevice(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(0)), m.MatchToDeviceMessages([]json.RawMessage{}))
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(0)), m.MatchToDeviceMessages([]json.RawMessage{}))
|
||||
}
|
||||
|
||||
// tests that the account data extension works:
|
||||
@ -399,7 +399,7 @@ func TestExtensionAccountData(t *testing.T) {
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 1}, // first two rooms A,B
|
||||
},
|
||||
@ -419,7 +419,7 @@ func TestExtensionAccountData(t *testing.T) {
|
||||
|
||||
// 5- when the range changes, make sure room account data is sent
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 2}, // A,B,C
|
||||
},
|
||||
@ -473,7 +473,7 @@ func TestExtensionAccountData(t *testing.T) {
|
||||
Enabled: true,
|
||||
},
|
||||
},
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 1}, // first two rooms A,B
|
||||
},
|
||||
@ -500,7 +500,7 @@ func TestExtensionAccountData(t *testing.T) {
|
||||
v2.waitUntilEmpty(t, alice)
|
||||
// now we should get room account data for C
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 1}, // first two rooms A,B
|
||||
},
|
||||
|
@ -30,8 +30,8 @@ func TestFiltersEncryption(t *testing.T) {
|
||||
|
||||
// connect and make sure either the encrypted room or not depending on what the filter says
|
||||
res := rig.V3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"enc": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 1}, // all rooms
|
||||
},
|
||||
@ -39,7 +39,7 @@ func TestFiltersEncryption(t *testing.T) {
|
||||
IsEncrypted: &boolTrue,
|
||||
},
|
||||
},
|
||||
{
|
||||
"noenc": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 1}, // all rooms
|
||||
},
|
||||
@ -50,17 +50,19 @@ func TestFiltersEncryption(t *testing.T) {
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchLists(
|
||||
[]m.ListMatcher{
|
||||
m.MatchV3Count(1),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 1, []string{encryptedRoomID}),
|
||||
),
|
||||
},
|
||||
[]m.ListMatcher{
|
||||
m.MatchV3Count(1),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 1, []string{unencryptedRoomID}),
|
||||
),
|
||||
map[string][]m.ListMatcher{
|
||||
"enc": {
|
||||
m.MatchV3Count(1),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 1, []string{encryptedRoomID}),
|
||||
),
|
||||
},
|
||||
"noenc": {
|
||||
m.MatchV3Count(1),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 1, []string{unencryptedRoomID}),
|
||||
),
|
||||
},
|
||||
},
|
||||
))
|
||||
|
||||
@ -69,14 +71,14 @@ func TestFiltersEncryption(t *testing.T) {
|
||||
|
||||
// now requesting the encrypted list should include it (added)
|
||||
res = rig.V3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"enc": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 1}, // all rooms
|
||||
},
|
||||
// sticky; should remember filters
|
||||
},
|
||||
{
|
||||
"noenc": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 1}, // all rooms
|
||||
},
|
||||
@ -85,54 +87,62 @@ func TestFiltersEncryption(t *testing.T) {
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchLists(
|
||||
[]m.ListMatcher{
|
||||
m.MatchV3Count(2),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(1), m.MatchV3InsertOp(0, unencryptedRoomID),
|
||||
),
|
||||
},
|
||||
[]m.ListMatcher{
|
||||
m.MatchV3Count(0),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(0),
|
||||
),
|
||||
map[string][]m.ListMatcher{
|
||||
"enc": {
|
||||
m.MatchV3Count(2),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(1), m.MatchV3InsertOp(0, unencryptedRoomID),
|
||||
),
|
||||
},
|
||||
"noenc": {
|
||||
m.MatchV3Count(0),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(0),
|
||||
),
|
||||
},
|
||||
},
|
||||
))
|
||||
|
||||
// requesting the encrypted list from scratch returns 2 rooms now
|
||||
res = rig.V3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 1}, // all rooms
|
||||
},
|
||||
Filters: &sync3.RequestFilters{
|
||||
IsEncrypted: &boolTrue,
|
||||
},
|
||||
}},
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"enc": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 1}, // all rooms
|
||||
},
|
||||
Filters: &sync3.RequestFilters{
|
||||
IsEncrypted: &boolTrue,
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchLists(
|
||||
[]m.ListMatcher{
|
||||
m.MatchV3Count(2),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 1, []string{unencryptedRoomID, encryptedRoomID}),
|
||||
),
|
||||
map[string][]m.ListMatcher{
|
||||
"enc": {
|
||||
m.MatchV3Count(2),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 1, []string{unencryptedRoomID, encryptedRoomID}),
|
||||
),
|
||||
},
|
||||
},
|
||||
))
|
||||
|
||||
// requesting the unencrypted stream from scratch returns 0 rooms
|
||||
res = rig.V3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 1}, // all rooms
|
||||
},
|
||||
Filters: &sync3.RequestFilters{
|
||||
IsEncrypted: &boolFalse,
|
||||
},
|
||||
}},
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"noenc": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 1}, // all rooms
|
||||
},
|
||||
Filters: &sync3.RequestFilters{
|
||||
IsEncrypted: &boolFalse,
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchLists(
|
||||
[]m.ListMatcher{
|
||||
m.MatchV3Count(0),
|
||||
map[string][]m.ListMatcher{
|
||||
"noenc": {
|
||||
m.MatchV3Count(0),
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
@ -152,8 +162,8 @@ func TestFiltersInvite(t *testing.T) {
|
||||
|
||||
// make sure the is_invite filter works
|
||||
res := rig.V3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"inv": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20}, // all rooms
|
||||
},
|
||||
@ -161,7 +171,7 @@ func TestFiltersInvite(t *testing.T) {
|
||||
IsInvite: &boolTrue,
|
||||
},
|
||||
},
|
||||
{
|
||||
"noinv": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20}, // all rooms
|
||||
},
|
||||
@ -172,14 +182,16 @@ func TestFiltersInvite(t *testing.T) {
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchLists(
|
||||
[]m.ListMatcher{
|
||||
m.MatchV3Count(1),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 20, []string{roomID}),
|
||||
),
|
||||
},
|
||||
[]m.ListMatcher{
|
||||
m.MatchV3Count(0),
|
||||
map[string][]m.ListMatcher{
|
||||
"inv": {
|
||||
m.MatchV3Count(1),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 20, []string{roomID}),
|
||||
),
|
||||
},
|
||||
"noinv": {
|
||||
m.MatchV3Count(0),
|
||||
},
|
||||
},
|
||||
))
|
||||
|
||||
@ -188,14 +200,14 @@ func TestFiltersInvite(t *testing.T) {
|
||||
|
||||
// now the room should move from one room to another
|
||||
res = rig.V3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"inv": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20}, // all rooms
|
||||
},
|
||||
// sticky; should remember filters
|
||||
},
|
||||
{
|
||||
"noinv": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20}, // all rooms
|
||||
},
|
||||
@ -205,18 +217,20 @@ func TestFiltersInvite(t *testing.T) {
|
||||
})
|
||||
// the room swaps from the invite list to the join list
|
||||
m.MatchResponse(t, res, m.MatchLists(
|
||||
[]m.ListMatcher{
|
||||
m.MatchV3Count(0),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(0),
|
||||
),
|
||||
},
|
||||
[]m.ListMatcher{
|
||||
m.MatchV3Count(1),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(0),
|
||||
m.MatchV3InsertOp(0, roomID),
|
||||
),
|
||||
map[string][]m.ListMatcher{
|
||||
"inv": {
|
||||
m.MatchV3Count(0),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(0),
|
||||
),
|
||||
},
|
||||
"noinv": {
|
||||
m.MatchV3Count(1),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(0),
|
||||
m.MatchV3InsertOp(0, roomID),
|
||||
),
|
||||
},
|
||||
},
|
||||
))
|
||||
}
|
||||
@ -258,8 +272,8 @@ func TestFiltersRoomName(t *testing.T) {
|
||||
|
||||
// make sure the room name filter works
|
||||
res := rig.V3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20}, // all rooms
|
||||
},
|
||||
@ -269,21 +283,19 @@ func TestFiltersRoomName(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchLists(
|
||||
[]m.ListMatcher{
|
||||
m.MatchV3Count(5),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 20, []string{
|
||||
ridApple, ridPear, ridOrange, ridPineapple, ridBanana,
|
||||
}, true),
|
||||
),
|
||||
},
|
||||
m.MatchResponse(t, res, m.MatchList("a",
|
||||
m.MatchV3Count(5),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 20, []string{
|
||||
ridApple, ridPear, ridOrange, ridPineapple, ridBanana,
|
||||
}, true),
|
||||
),
|
||||
))
|
||||
|
||||
// refine the filter
|
||||
res = rig.V3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20}, // all rooms
|
||||
},
|
||||
@ -293,16 +305,14 @@ func TestFiltersRoomName(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchLists(
|
||||
[]m.ListMatcher{
|
||||
m.MatchV3Count(2),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3InvalidateOp(0, 20),
|
||||
m.MatchV3SyncOp(0, 20, []string{
|
||||
ridApple, ridPineapple,
|
||||
}, true),
|
||||
),
|
||||
},
|
||||
m.MatchResponse(t, res, m.MatchList("a",
|
||||
m.MatchV3Count(2),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3InvalidateOp(0, 20),
|
||||
m.MatchV3SyncOp(0, 20, []string{
|
||||
ridApple, ridPineapple,
|
||||
}, true),
|
||||
),
|
||||
))
|
||||
}
|
||||
|
||||
@ -328,9 +338,9 @@ func TestFiltersRoomTypes(t *testing.T) {
|
||||
|
||||
// make sure the room_types and not_room_types filters works
|
||||
res := rig.V3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
// returns spaceRoomID only due to direct match
|
||||
{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20}, // all rooms
|
||||
},
|
||||
@ -339,7 +349,7 @@ func TestFiltersRoomTypes(t *testing.T) {
|
||||
},
|
||||
},
|
||||
// returns roomID only due to direct match (null = things without a room type)
|
||||
{
|
||||
"b": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20}, // all rooms
|
||||
},
|
||||
@ -348,7 +358,7 @@ func TestFiltersRoomTypes(t *testing.T) {
|
||||
},
|
||||
},
|
||||
// returns roomID and otherRoomID due to exclusion
|
||||
{
|
||||
"c": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20}, // all rooms
|
||||
},
|
||||
@ -357,7 +367,7 @@ func TestFiltersRoomTypes(t *testing.T) {
|
||||
},
|
||||
},
|
||||
// returns otherRoomID due to otherRoomType inclusive, roomType is excluded (override)
|
||||
{
|
||||
"d": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20}, // all rooms
|
||||
},
|
||||
@ -367,7 +377,7 @@ func TestFiltersRoomTypes(t *testing.T) {
|
||||
},
|
||||
},
|
||||
// returns no rooms as filtered room type isn't set on any rooms
|
||||
{
|
||||
"e": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20}, // all rooms
|
||||
},
|
||||
@ -376,7 +386,7 @@ func TestFiltersRoomTypes(t *testing.T) {
|
||||
},
|
||||
},
|
||||
// returns all rooms as filtered not room type isn't set on any rooms
|
||||
{
|
||||
"f": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20}, // all rooms
|
||||
},
|
||||
@ -386,26 +396,26 @@ func TestFiltersRoomTypes(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchLists(
|
||||
[]m.ListMatcher{
|
||||
m.MatchResponse(t, res, m.MatchLists(map[string][]m.ListMatcher{
|
||||
"a": {
|
||||
m.MatchV3Count(1), m.MatchV3Ops(m.MatchV3SyncOp(0, 20, []string{spaceRoomID})),
|
||||
},
|
||||
[]m.ListMatcher{
|
||||
"b": {
|
||||
m.MatchV3Count(1), m.MatchV3Ops(m.MatchV3SyncOp(0, 20, []string{roomID})),
|
||||
},
|
||||
[]m.ListMatcher{
|
||||
"c": {
|
||||
m.MatchV3Count(2), m.MatchV3Ops(m.MatchV3SyncOp(0, 20, []string{roomID, otherRoomID}, true)),
|
||||
},
|
||||
[]m.ListMatcher{
|
||||
"d": {
|
||||
m.MatchV3Count(1), m.MatchV3Ops(m.MatchV3SyncOp(0, 20, []string{otherRoomID})),
|
||||
},
|
||||
[]m.ListMatcher{
|
||||
"e": {
|
||||
m.MatchV3Count(0),
|
||||
},
|
||||
[]m.ListMatcher{
|
||||
"f": {
|
||||
m.MatchV3Count(3), m.MatchV3Ops(m.MatchV3SyncOp(0, 20, []string{roomID, otherRoomID, spaceRoomID}, true)),
|
||||
},
|
||||
))
|
||||
}))
|
||||
}
|
||||
|
||||
func TestFiltersTags(t *testing.T) {
|
||||
@ -448,8 +458,8 @@ func TestFiltersTags(t *testing.T) {
|
||||
})
|
||||
aliceToken := rig.Token(alice)
|
||||
res := rig.V3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"fav": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20},
|
||||
},
|
||||
@ -457,7 +467,7 @@ func TestFiltersTags(t *testing.T) {
|
||||
Tags: []string{tagFav},
|
||||
},
|
||||
},
|
||||
{
|
||||
"lp": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20},
|
||||
},
|
||||
@ -465,7 +475,7 @@ func TestFiltersTags(t *testing.T) {
|
||||
Tags: []string{tagLow},
|
||||
},
|
||||
},
|
||||
{
|
||||
"favlp": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20},
|
||||
},
|
||||
@ -475,21 +485,21 @@ func TestFiltersTags(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(3), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("fav", m.MatchV3Count(3), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 20, []string{fav1RoomID, fav2RoomID, favAndLowRoomID}, true),
|
||||
)), m.MatchList(1, m.MatchV3Count(3), m.MatchV3Ops(
|
||||
)), m.MatchList("lp", m.MatchV3Count(3), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 20, []string{low1RoomID, low2RoomID, favAndLowRoomID}, true),
|
||||
)), m.MatchList(2, m.MatchV3Count(5), m.MatchV3Ops(
|
||||
)), m.MatchList("favlp", m.MatchV3Count(5), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 20, []string{fav1RoomID, fav2RoomID, favAndLowRoomID, low1RoomID, low2RoomID}, true),
|
||||
)))
|
||||
|
||||
// first bump the fav1 room
|
||||
rig.FlushEvent(t, alice, fav1RoomID, testutils.NewMessageEvent(t, alice, "Hi"))
|
||||
res = rig.V3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{Ranges: sync3.SliceRanges{{0, 20}}},
|
||||
{Ranges: sync3.SliceRanges{{0, 20}}},
|
||||
{Ranges: sync3.SliceRanges{{0, 20}}},
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"fav": {Ranges: sync3.SliceRanges{{0, 20}}},
|
||||
"lp": {Ranges: sync3.SliceRanges{{0, 20}}},
|
||||
"favlp": {Ranges: sync3.SliceRanges{{0, 20}}},
|
||||
},
|
||||
})
|
||||
|
||||
@ -511,22 +521,22 @@ func TestFiltersTags(t *testing.T) {
|
||||
|
||||
// we should see DELETEs
|
||||
res = rig.V3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{Ranges: sync3.SliceRanges{{0, 20}}},
|
||||
{Ranges: sync3.SliceRanges{{0, 20}}},
|
||||
{Ranges: sync3.SliceRanges{{0, 20}}},
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"fav": {Ranges: sync3.SliceRanges{{0, 20}}},
|
||||
"lp": {Ranges: sync3.SliceRanges{{0, 20}}},
|
||||
"favlp": {Ranges: sync3.SliceRanges{{0, 20}}},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("fav", m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(0),
|
||||
)), m.MatchList(1, m.MatchV3Ops()), m.MatchList(2, m.MatchV3Count(4), m.MatchV3Ops(
|
||||
)), m.MatchList("lp", m.MatchV3Ops()), m.MatchList("favlp", m.MatchV3Count(4), m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(0),
|
||||
)))
|
||||
|
||||
// check not_tags works
|
||||
res = rig.V3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"fav": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20},
|
||||
},
|
||||
@ -534,7 +544,7 @@ func TestFiltersTags(t *testing.T) {
|
||||
Tags: []string{tagFav},
|
||||
},
|
||||
},
|
||||
{
|
||||
"nofav": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20},
|
||||
},
|
||||
@ -544,9 +554,9 @@ func TestFiltersTags(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("fav", m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 20, []string{fav2RoomID, favAndLowRoomID}, true),
|
||||
)), m.MatchList(1, m.MatchV3Count(3), m.MatchV3Ops(
|
||||
)), m.MatchList("nofav", m.MatchV3Count(3), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 20, []string{low1RoomID, low2RoomID, fav1RoomID}, true),
|
||||
)))
|
||||
|
||||
@ -568,13 +578,13 @@ func TestFiltersTags(t *testing.T) {
|
||||
})
|
||||
rig.V2.waitUntilEmpty(t, alice)
|
||||
res = rig.V3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"fav": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20},
|
||||
},
|
||||
},
|
||||
{
|
||||
"nofav": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 20},
|
||||
},
|
||||
@ -589,9 +599,9 @@ func TestFiltersTags(t *testing.T) {
|
||||
// now we have removed fav tag on FAV2 so new lists are:
|
||||
// FAVLOW
|
||||
// FAV1, LOW2, LOW1, FAV2
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("fav", m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(1),
|
||||
)), m.MatchList(1, m.MatchV3Count(4), m.MatchV3Ops(
|
||||
)), m.MatchList("nofav", m.MatchV3Count(4), m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(3),
|
||||
m.MatchV3InsertOp(3, fav2RoomID),
|
||||
)))
|
||||
|
@ -42,8 +42,8 @@ func TestStuckInvites(t *testing.T) {
|
||||
|
||||
// initial sync, should see the invite
|
||||
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 10}},
|
||||
Filters: &sync3.RequestFilters{
|
||||
IsInvite: &boolTrue,
|
||||
@ -51,7 +51,7 @@ func TestStuckInvites(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(1), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 10, []string{preSyncInviteRoomID}),
|
||||
)))
|
||||
|
||||
@ -74,13 +74,13 @@ func TestStuckInvites(t *testing.T) {
|
||||
v2.waitUntilEmpty(t, alice)
|
||||
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 10}},
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(2), m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(1),
|
||||
m.MatchV3InsertOp(0, postSyncInviteRoomID),
|
||||
)))
|
||||
@ -112,23 +112,23 @@ func TestStuckInvites(t *testing.T) {
|
||||
|
||||
// the entries are removed
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 10}},
|
||||
},
|
||||
},
|
||||
})
|
||||
// not asserting the ops here as they could be DELETE 1, DELETE 0 or DELETE 0, DELETE 0 which is hard
|
||||
// to assert.
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(0)))
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(0)))
|
||||
|
||||
// restart the server
|
||||
v3.restart(t, v2, pqString)
|
||||
|
||||
// now query for invites: there should be none if we are clearing the DB correctly.
|
||||
res = v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{{0, 10}},
|
||||
Filters: &sync3.RequestFilters{
|
||||
IsInvite: &boolTrue,
|
||||
|
54
tests-integration/lists_test.go
Normal file
54
tests-integration/lists_test.go
Normal file
@ -0,0 +1,54 @@
|
||||
package syncv3
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/matrix-org/sliding-sync/sync3"
|
||||
"github.com/matrix-org/sliding-sync/testutils/m"
|
||||
)
|
||||
|
||||
func TestListsAsKeys(t *testing.T) {
|
||||
boolTrue := true
|
||||
rig := NewTestRig(t)
|
||||
defer rig.Finish()
|
||||
encryptedRoomID := "!TestListsAsKeys_encrypted:localhost"
|
||||
unencryptedRoomID := "!TestListsAsKeys_unencrypted:localhost"
|
||||
rig.SetupV2RoomsForUser(t, alice, NoFlush, map[string]RoomDescriptor{
|
||||
encryptedRoomID: {
|
||||
IsEncrypted: true,
|
||||
},
|
||||
unencryptedRoomID: {
|
||||
IsEncrypted: false,
|
||||
},
|
||||
})
|
||||
aliceToken := rig.Token(alice)
|
||||
// make an encrypted room list, then bump both rooms and send a 2nd request with zero data
|
||||
// and make sure that we see the encrypted room message only (so the filter is still active)
|
||||
res := rig.V3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"enc": {
|
||||
Ranges: sync3.SliceRanges{{0, 20}},
|
||||
Filters: &sync3.RequestFilters{
|
||||
IsEncrypted: &boolTrue,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchLists(map[string][]m.ListMatcher{
|
||||
"enc": {
|
||||
m.MatchV3Count(1),
|
||||
},
|
||||
}), m.MatchRoomSubscription(encryptedRoomID))
|
||||
|
||||
rig.FlushText(t, alice, encryptedRoomID, "bump encrypted")
|
||||
rig.FlushText(t, alice, unencryptedRoomID, "bump unencrypted")
|
||||
|
||||
res = rig.V3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{})
|
||||
m.MatchResponse(t, res, m.MatchLists(map[string][]m.ListMatcher{
|
||||
"enc": {
|
||||
m.MatchV3Count(1),
|
||||
},
|
||||
}), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
encryptedRoomID: {},
|
||||
}))
|
||||
}
|
@ -54,19 +54,20 @@ func TestNotificationsOnTop(t *testing.T) {
|
||||
|
||||
// connect and make sure we get nobing, bing
|
||||
syncRequestBody := sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, int64(len(allRooms) - 1)}, // all rooms
|
||||
},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: int64(100),
|
||||
},
|
||||
// prefer highlights/notifs/rest, and group them by recency not counts count first, THEN eventually recency
|
||||
Sort: []string{sync3.SortByNotificationLevel, sync3.SortByRecency},
|
||||
}},
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, int64(len(allRooms) - 1)}, // all rooms
|
||||
},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: int64(100),
|
||||
},
|
||||
// prefer highlights/notifs/rest, and group them by recency not counts count first, THEN eventually recency
|
||||
Sort: []string{sync3.SortByNotificationLevel, sync3.SortByRecency},
|
||||
}},
|
||||
}
|
||||
res := v3.mustDoV3Request(t, aliceToken, syncRequestBody)
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, int64(len(allRooms)-1), []string{noBingRoomID, bingRoomID}),
|
||||
)))
|
||||
|
||||
@ -90,7 +91,7 @@ func TestNotificationsOnTop(t *testing.T) {
|
||||
})
|
||||
v2.waitUntilEmpty(t, alice)
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, syncRequestBody)
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(len(allRooms)),
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(allRooms)),
|
||||
m.MatchV3Ops(m.MatchV3DeleteOp(1), m.MatchV3InsertOp(0, bingRoomID)),
|
||||
))
|
||||
|
||||
@ -111,25 +112,26 @@ func TestNotificationsOnTop(t *testing.T) {
|
||||
})
|
||||
v2.waitUntilEmpty(t, alice)
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, syncRequestBody)
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(len(allRooms))),
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(allRooms))),
|
||||
m.MatchNoV3Ops(),
|
||||
)
|
||||
|
||||
// restart the server and sync from fresh again, it should still have the bing room on top
|
||||
v3.restart(t, v2, pqString)
|
||||
res = v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, int64(len(allRooms) - 1)}, // all rooms
|
||||
},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: int64(100),
|
||||
},
|
||||
// prefer highlight count first, THEN eventually recency
|
||||
Sort: []string{sync3.SortByNotificationLevel, sync3.SortByRecency},
|
||||
}},
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, int64(len(allRooms) - 1)}, // all rooms
|
||||
},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: int64(100),
|
||||
},
|
||||
// prefer highlight count first, THEN eventually recency
|
||||
Sort: []string{sync3.SortByNotificationLevel, sync3.SortByRecency},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchV3SyncOpFn(func(op *sync3.ResponseOpRange) error {
|
||||
if len(op.RoomIDs) != len(allRooms) {
|
||||
return fmt.Errorf("want %d rooms, got %d", len(allRooms), len(op.RoomIDs))
|
||||
|
@ -168,6 +168,10 @@ func (r *testRig) EncryptRoom(t *testing.T, userID, roomID string) {
|
||||
))
|
||||
}
|
||||
|
||||
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{
|
||||
|
@ -71,16 +71,17 @@ func TestRoomNames(t *testing.T) {
|
||||
t.Helper()
|
||||
// do a sync, make sure room names are sensible
|
||||
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, int64(len(allRooms) - 1)}, // all rooms
|
||||
},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: int64(100),
|
||||
},
|
||||
}},
|
||||
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(0, m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchV3SyncOpFn(func(op *sync3.ResponseOpRange) error {
|
||||
if len(op.RoomIDs) != len(allRooms) {
|
||||
return fmt.Errorf("want %d rooms, got %d", len(allRooms), len(op.RoomIDs))
|
||||
@ -109,14 +110,15 @@ func TestRoomNames(t *testing.T) {
|
||||
t.Helper()
|
||||
// do a sync, make sure room names are sensible
|
||||
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, int64(len(allRooms) - 1)}, // all rooms
|
||||
},
|
||||
Filters: &sync3.RequestFilters{
|
||||
RoomNameFilter: searchTerm,
|
||||
},
|
||||
}},
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, int64(len(allRooms) - 1)}, // all rooms
|
||||
},
|
||||
Filters: &sync3.RequestFilters{
|
||||
RoomNameFilter: searchTerm,
|
||||
},
|
||||
}},
|
||||
})
|
||||
matchers := make(map[string][]m.RoomMatcher, len(wantRooms))
|
||||
wantRoomIDs := make([]string, len(wantRooms))
|
||||
@ -126,7 +128,7 @@ func TestRoomNames(t *testing.T) {
|
||||
m.MatchRoomName(wantRooms[i].name),
|
||||
}
|
||||
}
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(len(wantRooms)), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(wantRooms)), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, int64(len(allRooms)-1), wantRoomIDs),
|
||||
)), m.MatchRoomSubscriptions(matchers))
|
||||
}
|
||||
|
@ -60,34 +60,36 @@ func TestSlowGetAllRoomsInitial(t *testing.T) {
|
||||
})
|
||||
// fetch all the rooms!
|
||||
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 3}, // these get ignored
|
||||
},
|
||||
SlowGetAllRooms: &boolTrue,
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: int64(numTimelineEventsPerRoom),
|
||||
},
|
||||
}},
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 3}, // these get ignored
|
||||
},
|
||||
SlowGetAllRooms: &boolTrue,
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: int64(numTimelineEventsPerRoom),
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, int64(len(allRooms)-1), allRoomIDs, true),
|
||||
)), m.MatchRoomSubscriptionsStrict(allRoomMatchers))
|
||||
|
||||
// now redo this but with a room name filter
|
||||
res = v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 3}, // these get ignored
|
||||
},
|
||||
SlowGetAllRooms: &boolTrue,
|
||||
Filters: &sync3.RequestFilters{
|
||||
RoomNameFilter: "My Room 1", // returns 1,10,11,12,13,14 etc
|
||||
},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: int64(numTimelineEventsPerRoom),
|
||||
},
|
||||
}},
|
||||
Lists: map[string]sync3.RequestList{
|
||||
"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 3}, // these get ignored
|
||||
},
|
||||
SlowGetAllRooms: &boolTrue,
|
||||
Filters: &sync3.RequestFilters{
|
||||
RoomNameFilter: "My Room 1", // returns 1,10,11,12,13,14 etc
|
||||
},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: int64(numTimelineEventsPerRoom),
|
||||
},
|
||||
}},
|
||||
})
|
||||
// remove rooms that don't have a leading 1 index as they should be filtered out
|
||||
for i := 0; i < 10; i++ {
|
||||
@ -100,7 +102,7 @@ func TestSlowGetAllRoomsInitial(t *testing.T) {
|
||||
for roomID := range allRoomMatchers {
|
||||
roomIDs = append(roomIDs, roomID)
|
||||
}
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(len(allRoomMatchers)), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(allRoomMatchers)), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, int64(len(allRoomMatchers)-1), roomIDs, true),
|
||||
)), m.MatchRoomSubscriptionsStrict(allRoomMatchers))
|
||||
|
||||
@ -125,9 +127,9 @@ func TestSlowGetAllRoomsInitial(t *testing.T) {
|
||||
v2.waitUntilEmpty(t, alice)
|
||||
// reuse the position from the room name filter test, we should get this new room
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{}},
|
||||
Lists: map[string]sync3.RequestList{},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(len(allRoomMatchers)+1)), m.MatchNoV3Ops(), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(allRoomMatchers)+1)), m.MatchNoV3Ops(), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
newRoom.roomID: {
|
||||
m.MatchRoomInitial(true),
|
||||
m.MatchRoomName(roomName),
|
||||
@ -148,9 +150,9 @@ func TestSlowGetAllRoomsInitial(t *testing.T) {
|
||||
})
|
||||
v2.waitUntilEmpty(t, alice)
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{}},
|
||||
Lists: map[string]sync3.RequestList{},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(len(allRoomMatchers)+1)), m.MatchNoV3Ops(), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(allRoomMatchers)+1)), m.MatchNoV3Ops(), m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
|
||||
allRooms[11].roomID: {
|
||||
m.MatchRoomInitial(false),
|
||||
m.MatchRoomTimelineMostRecent(1, []json.RawMessage{newEvent}),
|
||||
|
@ -158,7 +158,7 @@ func TestTimelinesLiveStream(t *testing.T) {
|
||||
|
||||
// first request => rooms 19,18,17,16
|
||||
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, int64(len(wantRooms) - 1)}, // first N rooms
|
||||
},
|
||||
@ -167,7 +167,7 @@ func TestTimelinesLiveStream(t *testing.T) {
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchV3SyncOpFn(func(op *sync3.ResponseOpRange) error {
|
||||
if len(op.RoomIDs) != len(wantRooms) {
|
||||
return fmt.Errorf("want %d rooms, got %d", len(wantRooms), len(op.RoomIDs))
|
||||
@ -190,14 +190,14 @@ func TestTimelinesLiveStream(t *testing.T) {
|
||||
|
||||
// next request, DELETE 3; INSERT 0 7;
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, int64(len(wantRooms) - 1)}, // first N rooms
|
||||
},
|
||||
// sticky remember the timeline_limit
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(3),
|
||||
m.MatchV3InsertOp(0, allRooms[7].roomID),
|
||||
)), m.MatchRoomSubscription(
|
||||
@ -208,25 +208,25 @@ func TestTimelinesLiveStream(t *testing.T) {
|
||||
|
||||
// next request, UPDATE 0 7;
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, int64(len(wantRooms) - 1)}, // first N rooms
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(len(allRooms))), m.MatchNoV3Ops())
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(allRooms))), m.MatchNoV3Ops())
|
||||
|
||||
bumpRoom(18)
|
||||
|
||||
// next request, DELETE 2; INSERT 0 18;
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, int64(len(wantRooms) - 1)}, // first N rooms
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(2),
|
||||
m.MatchV3InsertOp(0, allRooms[18].roomID),
|
||||
)), m.MatchRoomSubscription(allRooms[18].roomID, m.MatchRoomTimelineMostRecent(1, []json.RawMessage{allRooms[18].events[len(allRooms[18].events)-1]})))
|
||||
@ -266,7 +266,7 @@ func TestMultipleWindows(t *testing.T) {
|
||||
|
||||
// request 3 windows
|
||||
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 2}, // first 3 rooms
|
||||
[2]int64{10, 12}, // 3 rooms in the middle
|
||||
@ -277,7 +277,7 @@ func TestMultipleWindows(t *testing.T) {
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 2, []string{allRooms[0].roomID, allRooms[1].roomID, allRooms[2].roomID}),
|
||||
m.MatchV3SyncOp(10, 12, []string{allRooms[10].roomID, allRooms[11].roomID, allRooms[12].roomID}),
|
||||
m.MatchV3SyncOp(17, 19, []string{allRooms[17].roomID, allRooms[18].roomID, allRooms[19].roomID}),
|
||||
@ -302,7 +302,7 @@ func TestMultipleWindows(t *testing.T) {
|
||||
bumpRoom(18)
|
||||
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 2}, // first 3 rooms
|
||||
[2]int64{10, 12}, // 3 rooms in the middle
|
||||
@ -316,7 +316,7 @@ func TestMultipleWindows(t *testing.T) {
|
||||
//18 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
||||
// DELETE 2 DELETE 12 DELETE 18
|
||||
// INSERT 0,18 INSERT 10,9 INSERT 17,16
|
||||
m.MatchResponse(t, res, m.MatchList(0,
|
||||
m.MatchResponse(t, res, m.MatchList("a",
|
||||
m.MatchV3Count(len(allRooms)),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(18),
|
||||
@ -348,7 +348,7 @@ func TestInitialFlag(t *testing.T) {
|
||||
},
|
||||
})
|
||||
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
@ -357,7 +357,7 @@ func TestInitialFlag(t *testing.T) {
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 10, []string{roomID}),
|
||||
)), m.MatchRoomSubscription(roomID, m.MatchRoomInitial(true)))
|
||||
// send an update
|
||||
@ -376,7 +376,7 @@ func TestInitialFlag(t *testing.T) {
|
||||
v2.waitUntilEmpty(t, alice)
|
||||
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
@ -415,7 +415,7 @@ func TestDuplicateEventsInTimeline(t *testing.T) {
|
||||
},
|
||||
})
|
||||
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
@ -424,7 +424,7 @@ func TestDuplicateEventsInTimeline(t *testing.T) {
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0,
|
||||
m.MatchResponse(t, res, m.MatchList("a",
|
||||
m.MatchV3Ops(m.MatchV3SyncOp(0, 10, []string{roomID})),
|
||||
), m.MatchRoomSubscription(roomID, m.MatchRoomTimelineMostRecent(1, []json.RawMessage{dupeEvent})))
|
||||
}
|
||||
@ -468,7 +468,7 @@ func TestTimelineMiddleWindowZeroTimelineLimit(t *testing.T) {
|
||||
|
||||
// Request rooms 5-10 with a 0 timeline limit
|
||||
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{5, 10},
|
||||
},
|
||||
@ -478,7 +478,7 @@ func TestTimelineMiddleWindowZeroTimelineLimit(t *testing.T) {
|
||||
}},
|
||||
})
|
||||
wantRooms := allRooms[5:11]
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(len(allRooms)), m.MatchV3Ops(
|
||||
m.MatchV3SyncOpFn(func(op *sync3.ResponseOpRange) error {
|
||||
if len(op.RoomIDs) != len(wantRooms) {
|
||||
return fmt.Errorf("want %d rooms, got %d", len(wantRooms), len(op.RoomIDs))
|
||||
@ -512,21 +512,21 @@ func TestTimelineMiddleWindowZeroTimelineLimit(t *testing.T) {
|
||||
|
||||
// should see room 4, the server should not panic
|
||||
res = v3.mustDoV3RequestWithPos(t, aliceToken, res.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{5, 10},
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchLists(
|
||||
[]m.ListMatcher{
|
||||
m.MatchResponse(t, res, m.MatchLists(map[string][]m.ListMatcher{
|
||||
"a": {
|
||||
m.MatchV3Count(len(allRooms)),
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3DeleteOp(10),
|
||||
m.MatchV3InsertOp(5, allRooms[4].roomID),
|
||||
),
|
||||
},
|
||||
))
|
||||
}))
|
||||
}
|
||||
|
||||
// Regression test to ensure that the 'state' block NEVER appears when requesting a high timeline_limit.
|
||||
@ -562,7 +562,7 @@ func TestHistoryDoesntIncludeState(t *testing.T) {
|
||||
},
|
||||
})
|
||||
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
@ -571,7 +571,7 @@ func TestHistoryDoesntIncludeState(t *testing.T) {
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchList(0,
|
||||
m.MatchResponse(t, res, m.MatchList("a",
|
||||
m.MatchV3Ops(m.MatchV3SyncOp(0, 10, []string{roomID})),
|
||||
), m.MatchRoomSubscription(roomID, m.MatchRoomTimeline(room.events), m.MatchRoomPrevBatch(prevBatch)))
|
||||
}
|
||||
@ -609,27 +609,25 @@ func TestTimelineTxnID(t *testing.T) {
|
||||
})
|
||||
|
||||
aliceRes := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: 2,
|
||||
},
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
bobRes := v3.mustDoV3Request(t, bobToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: 2,
|
||||
},
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
RoomSubscription: sync3.RoomSubscription{
|
||||
TimelineLimit: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@ -666,29 +664,27 @@ func TestTimelineTxnID(t *testing.T) {
|
||||
|
||||
// now Alice syncs, she should see the event with the txn ID
|
||||
aliceRes = v3.mustDoV3RequestWithPos(t, aliceToken, aliceRes.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, aliceRes, m.MatchLists([]m.ListMatcher{m.MatchV3Count(1)}), m.MatchNoV3Ops(), m.MatchRoomSubscription(
|
||||
m.MatchResponse(t, aliceRes, m.MatchList("a", m.MatchV3Count(1)), m.MatchNoV3Ops(), m.MatchRoomSubscription(
|
||||
roomID, m.MatchRoomTimelineMostRecent(1, []json.RawMessage{newEvent}),
|
||||
))
|
||||
|
||||
// now Bob syncs, he should see the event without the txn ID
|
||||
bobRes = v3.mustDoV3RequestWithPos(t, bobToken, bobRes.Pos, sync3.Request{
|
||||
Lists: []sync3.RequestList{
|
||||
{
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
m.MatchResponse(t, bobRes, m.MatchLists([]m.ListMatcher{m.MatchV3Count(1)}), m.MatchNoV3Ops(), m.MatchRoomSubscription(
|
||||
m.MatchResponse(t, bobRes, m.MatchList("a", m.MatchV3Count(1)), m.MatchNoV3Ops(), m.MatchRoomSubscription(
|
||||
roomID, m.MatchRoomTimelineMostRecent(1, []json.RawMessage{newEventNoUnsigned}),
|
||||
))
|
||||
}
|
||||
@ -698,7 +694,7 @@ func testTimelineLoadInitialEvents(v3 *testV3Server, token string, count int, wa
|
||||
return func(t *testing.T) {
|
||||
t.Helper()
|
||||
res := v3.mustDoV3Request(t, token, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, int64(len(wantRooms) - 1)}, // first N rooms
|
||||
},
|
||||
@ -708,7 +704,7 @@ func testTimelineLoadInitialEvents(v3 *testV3Server, token string, count int, wa
|
||||
}},
|
||||
})
|
||||
|
||||
m.MatchResponse(t, res, m.MatchList(0, m.MatchV3Count(count), m.MatchV3Ops(
|
||||
m.MatchResponse(t, res, m.MatchList("a", m.MatchV3Count(count), m.MatchV3Ops(
|
||||
m.MatchV3SyncOpFn(func(op *sync3.ResponseOpRange) error {
|
||||
if len(op.RoomIDs) != len(wantRooms) {
|
||||
return fmt.Errorf("want %d rooms, got %d", len(wantRooms), len(op.RoomIDs))
|
||||
@ -755,7 +751,7 @@ func TestPrevBatchInTimeline(t *testing.T) {
|
||||
},
|
||||
})
|
||||
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
@ -764,11 +760,11 @@ func TestPrevBatchInTimeline(t *testing.T) {
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchLists([]m.ListMatcher{
|
||||
m.MatchResponse(t, res, m.MatchList("a",
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 10, []string{roomID}),
|
||||
),
|
||||
}), m.MatchRoomSubscription(roomID, m.MatchRoomPrevBatch("")))
|
||||
), m.MatchRoomSubscription(roomID, m.MatchRoomPrevBatch("")))
|
||||
|
||||
// now make a newer prev_batch and try again
|
||||
v2.queueResponse(alice, sync2.SyncResponse{
|
||||
@ -807,7 +803,7 @@ func TestPrevBatchInTimeline(t *testing.T) {
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
res := v3.mustDoV3Request(t, aliceToken, sync3.Request{
|
||||
Lists: []sync3.RequestList{{
|
||||
Lists: map[string]sync3.RequestList{"a": {
|
||||
Ranges: sync3.SliceRanges{
|
||||
[2]int64{0, 10},
|
||||
},
|
||||
@ -816,10 +812,10 @@ func TestPrevBatchInTimeline(t *testing.T) {
|
||||
},
|
||||
}},
|
||||
})
|
||||
m.MatchResponse(t, res, m.MatchLists([]m.ListMatcher{
|
||||
m.MatchResponse(t, res, m.MatchList("a",
|
||||
m.MatchV3Ops(
|
||||
m.MatchV3SyncOp(0, 10, []string{roomID}),
|
||||
),
|
||||
}), m.MatchRoomSubscription(roomID, m.MatchRoomPrevBatch(tc.wantPrevBatch)))
|
||||
), m.MatchRoomSubscription(roomID, m.MatchRoomPrevBatch(tc.wantPrevBatch)))
|
||||
}
|
||||
}
|
||||
|
@ -367,9 +367,9 @@ func MatchV3InvalidateOp(start, end int64) OpMatcher {
|
||||
|
||||
func MatchNoV3Ops() RespMatcher {
|
||||
return func(res *sync3.Response) error {
|
||||
for i, l := range res.Lists {
|
||||
for key, l := range res.Lists {
|
||||
if len(l.Ops) > 0 {
|
||||
return fmt.Errorf("MatchNoV3Ops: list %d got %d ops", i, len(l.Ops))
|
||||
return fmt.Errorf("MatchNoV3Ops: list %v got %d ops", key, len(l.Ops))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -498,10 +498,10 @@ func MatchAccountData(globals []json.RawMessage, rooms map[string][]json.RawMess
|
||||
}
|
||||
}
|
||||
|
||||
func CheckList(i int, res sync3.ResponseList, matchers ...ListMatcher) error {
|
||||
func CheckList(listKey string, res sync3.ResponseList, matchers ...ListMatcher) error {
|
||||
for _, m := range matchers {
|
||||
if err := m(res); err != nil {
|
||||
return fmt.Errorf("MatchList[%d]: %v", i, err)
|
||||
return fmt.Errorf("MatchList[%v]: %v", listKey, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -516,24 +516,24 @@ func MatchTxnID(txnID string) RespMatcher {
|
||||
}
|
||||
}
|
||||
|
||||
func MatchList(i int, matchers ...ListMatcher) RespMatcher {
|
||||
func MatchList(listKey string, matchers ...ListMatcher) RespMatcher {
|
||||
return func(res *sync3.Response) error {
|
||||
if i >= len(res.Lists) {
|
||||
return fmt.Errorf("MatchSingleList: index %d does not exist, got %d lists", i, len(res.Lists))
|
||||
if _, exists := res.Lists[listKey]; !exists {
|
||||
return fmt.Errorf("MatchSingleList: key %v does not exist, got %d lists", listKey, len(res.Lists))
|
||||
}
|
||||
list := res.Lists[i]
|
||||
return CheckList(i, list, matchers...)
|
||||
list := res.Lists[listKey]
|
||||
return CheckList(listKey, list, matchers...)
|
||||
}
|
||||
}
|
||||
|
||||
func MatchLists(matchers ...[]ListMatcher) RespMatcher {
|
||||
func MatchLists(matchers map[string][]ListMatcher) RespMatcher {
|
||||
return func(res *sync3.Response) error {
|
||||
if len(matchers) != len(res.Lists) {
|
||||
return fmt.Errorf("MatchLists: got %d matchers for %d lists", len(matchers), len(res.Lists))
|
||||
}
|
||||
for i := range matchers {
|
||||
if err := CheckList(i, res.Lists[i], matchers[i]...); err != nil {
|
||||
return fmt.Errorf("MatchLists[%d]: %v", i, err)
|
||||
for listKey, matchersForList := range matchers {
|
||||
if err := CheckList(listKey, res.Lists[listKey], matchersForList...); err != nil {
|
||||
return fmt.Errorf("MatchLists[%v]: %v", listKey, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
Loading…
x
Reference in New Issue
Block a user