From 3de07ad550776a57e96399660c0ccd9c58dafcf3 Mon Sep 17 00:00:00 2001
From: Tulir Asokan <tulir@maunium.net>
Date: Tue, 24 Apr 2018 23:52:31 +0300
Subject: 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(-)

(limited to 'matrix')

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
+}
-- 
cgit v1.2.3-70-g09d2