From 3de07ad550776a57e96399660c0ccd9c58dafcf3 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Tue, 24 Apr 2018 23:52:31 +0300 Subject: [PATCH] Add tests for syncer and fix some bugs --- matrix/matrix.go | 4 +- matrix/sync.go | 3 +- matrix/sync_test.go | 184 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 187 insertions(+), 4 deletions(-) diff --git a/matrix/matrix.go b/matrix/matrix.go index 2e97ef4..ee5d9bd 100644 --- a/matrix/matrix.go +++ b/matrix/matrix.go @@ -295,9 +295,7 @@ func (c *Container) processOwnMembershipChange(evt *gomatrix.Event) { func (c *Container) HandleMembership(evt *gomatrix.Event) { if evt.StateKey != nil && *evt.StateKey == c.config.Session.UserID { c.processOwnMembershipChange(evt) - } - - if !c.config.Session.InitialSyncDone /*&& evt.Timestamp < time.Now().Add(-1*time.Hour).Unix()*/ { + } else if !c.config.Session.InitialSyncDone /*&& evt.Timestamp < time.Now().Add(-1*time.Hour).Unix()*/ { // We don't care about other users' membership events in the initial sync. return } diff --git a/matrix/sync.go b/matrix/sync.go index 8ad7ad5..8ff3d39 100644 --- a/matrix/sync.go +++ b/matrix/sync.go @@ -74,7 +74,8 @@ func (s *GomuksSyncer) ProcessResponse(res *gomatrix.RespSync, since string) (er for roomID, roomData := range res.Rooms.Leave { room := s.Session.GetRoom(roomID) - s.processSyncEvents(room, roomData.Timeline.Events, true, true) + s.processSyncEvents(room, roomData.State.Events, true, true) + s.processSyncEvents(room, roomData.Timeline.Events, false, false) if len(room.PrevBatch) == 0 { room.PrevBatch = roomData.Timeline.PrevBatch diff --git a/matrix/sync_test.go b/matrix/sync_test.go index 886e168..14f8969 100644 --- a/matrix/sync_test.go +++ b/matrix/sync_test.go @@ -17,9 +17,119 @@ package matrix_test import ( + "testing" + + "github.com/stretchr/testify/assert" + "maunium.net/go/gomatrix" + "maunium.net/go/gomuks/matrix" "maunium.net/go/gomuks/matrix/rooms" ) +func TestGomuksSyncer_ProcessResponse_Initial(t *testing.T) { + syncer := matrix.NewGomuksSyncer(&mockSyncerSession{}) + var initDoneCalled = false + syncer.InitDoneCallback = func() { + initDoneCalled = true + } + + syncer.ProcessResponse(newRespSync(), "") + assert.True(t, syncer.FirstSyncDone) + assert.True(t, initDoneCalled) +} + +func TestGomuksSyncer_ProcessResponse(t *testing.T) { + mss := &mockSyncerSession{ + userID: "@tulir:maunium.net", + rooms: map[string]*rooms.Room{ + "!foo:maunium.net": { + Room: gomatrix.NewRoom("!foo:maunium.net"), + }, + "!bar:maunium.net": { + Room: gomatrix.NewRoom("!bar:maunium.net"), + }, + "!test:maunium.net": { + Room: gomatrix.NewRoom("!test:maunium.net"), + }, + }, + } + ml := &mockListener{} + syncer := matrix.NewGomuksSyncer(mss) + syncer.OnEventType("m.room.member", ml.receive) + syncer.OnEventType("m.room.message", ml.receive) + + joinEvt := &gomatrix.Event{ + ID: "!join:maunium.net", + Type: "m.room.member", + Sender: "@tulir:maunium.net", + StateKey: ptr("̣@tulir:maunium.net"), + Content: map[string]interface{}{ + "membership": "join", + }, + } + messageEvt := &gomatrix.Event{ + ID: "!msg:maunium.net", + Type: "m.room.message", + Content: map[string]interface{}{ + "body": "foo", + "msgtype": "m.text", + }, + } + unhandledEvt := &gomatrix.Event{ + ID: "!unhandled:maunium.net", + Type: "m.room.unhandled_event", + } + inviteEvt := &gomatrix.Event{ + ID: "!invite:matrix.org", + Type: "m.room.member", + Sender: "@you:matrix.org", + StateKey: ptr("̣@tulir:maunium.net"), + Content: map[string]interface{}{ + "membership": "invite", + }, + } + leaveEvt := &gomatrix.Event{ + ID: "!leave:matrix.org", + Type: "m.room.member", + Sender: "@you:matrix.org", + StateKey: ptr("̣@tulir:maunium.net"), + Content: map[string]interface{}{ + "membership": "leave", + }, + } + + resp := newRespSync() + resp.Rooms.Join["!foo:maunium.net"] = join{ + State: events{Events: []*gomatrix.Event{joinEvt}}, + Timeline: timeline{Events: []*gomatrix.Event{messageEvt, unhandledEvt}}, + } + resp.Rooms.Invite["!bar:maunium.net"] = struct { + State struct { + Events []*gomatrix.Event `json:"events"` + } `json:"invite_state"` + }{ + State: events{Events: []*gomatrix.Event{inviteEvt}}, + } + resp.Rooms.Leave["!test:maunium.net"] = struct { + State struct { + Events []*gomatrix.Event `json:"events"` + } `json:"state"` + Timeline struct { + Events []*gomatrix.Event `json:"events"` + Limited bool `json:"limited"` + PrevBatch string `json:"prev_batch"` + } `json:"timeline"` + }{ + State: events{Events: []*gomatrix.Event{leaveEvt}}, + } + + syncer.ProcessResponse(resp, "since") + assert.Contains(t, ml.received, joinEvt, joinEvt.ID) + assert.Contains(t, ml.received, messageEvt, messageEvt.ID) + assert.NotContains(t, ml.received, unhandledEvt, unhandledEvt.ID) + assert.Contains(t, ml.received, inviteEvt, inviteEvt.ID) + assert.Contains(t, ml.received, leaveEvt, leaveEvt.ID) +} + type mockSyncerSession struct { rooms map[string]*rooms.Room userID string @@ -32,3 +142,77 @@ func (mss *mockSyncerSession) GetRoom(id string) *rooms.Room { func (mss *mockSyncerSession) GetUserID() string { return mss.userID } + +type events struct { + Events []*gomatrix.Event `json:"events"` +} + +type timeline struct { + Events []*gomatrix.Event `json:"events"` + Limited bool `json:"limited"` + PrevBatch string `json:"prev_batch"` +} +type join struct { + State struct { + Events []*gomatrix.Event `json:"events"` + } `json:"state"` + Timeline struct { + Events []*gomatrix.Event `json:"events"` + Limited bool `json:"limited"` + PrevBatch string `json:"prev_batch"` + } `json:"timeline"` + Ephemeral struct { + Events []*gomatrix.Event `json:"events"` + } `json:"ephemeral"` + AccountData struct { + Events []*gomatrix.Event `json:"events"` + } `json:"account_data"` +} + +func ptr(text string) *string { + return &text +} + +type mockListener struct { + received []*gomatrix.Event +} + +func (ml *mockListener) receive(evt *gomatrix.Event) { + ml.received = append(ml.received, evt) +} + +func newRespSync() *gomatrix.RespSync { + resp := &gomatrix.RespSync{NextBatch: "123"} + resp.Rooms.Join = make(map[string]struct { + State struct { + Events []*gomatrix.Event `json:"events"` + } `json:"state"` + Timeline struct { + Events []*gomatrix.Event `json:"events"` + Limited bool `json:"limited"` + PrevBatch string `json:"prev_batch"` + } `json:"timeline"` + Ephemeral struct { + Events []*gomatrix.Event `json:"events"` + } `json:"ephemeral"` + AccountData struct { + Events []*gomatrix.Event `json:"events"` + } `json:"account_data"` + }) + resp.Rooms.Invite = make(map[string]struct { + State struct { + Events []*gomatrix.Event `json:"events"` + } `json:"invite_state"` + }) + resp.Rooms.Leave = make(map[string]struct { + State struct { + Events []*gomatrix.Event `json:"events"` + } `json:"state"` + Timeline struct { + Events []*gomatrix.Event `json:"events"` + Limited bool `json:"limited"` + PrevBatch string `json:"prev_batch"` + } `json:"timeline"` + }) + return resp +}