// gomuks - A terminal Matrix client written in Go. // Copyright (C) 2019 Tulir Asokan // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . package matrix_test import ( "testing" "github.com/stretchr/testify/assert" "maunium.net/go/gomuks/matrix" "maunium.net/go/gomuks/matrix/rooms" "maunium.net/go/mautrix" ) 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: mautrix.NewRoom("!foo:maunium.net"), }, "!bar:maunium.net": { Room: mautrix.NewRoom("!bar:maunium.net"), }, "!test:maunium.net": { Room: mautrix.NewRoom("!test:maunium.net"), }, }, } ml := &mockListener{} syncer := matrix.NewGomuksSyncer(mss) syncer.OnEventType(mautrix.EventMessage, ml.receive) syncer.OnEventType(mautrix.StateMember, ml.receive) syncer.GetFilterJSON("@tulir:maunium.net") joinEvt := &mautrix.Event{ ID: "!join:maunium.net", Type: mautrix.StateMember, Sender: "@tulir:maunium.net", StateKey: ptr("̣@tulir:maunium.net"), Content: mautrix.Content{ Membership: mautrix.MembershipJoin, }, } messageEvt := &mautrix.Event{ ID: "!msg:maunium.net", Type: mautrix.EventMessage, Content: mautrix.Content{ Body: "foo", MsgType: mautrix.MsgText, }, } unhandledEvt := &mautrix.Event{ ID: "!unhandled:maunium.net", Type: mautrix.EventType{Type: "m.room.unhandled_event"}, } inviteEvt := &mautrix.Event{ ID: "!invite:matrix.org", Type: mautrix.StateMember, Sender: "@you:matrix.org", StateKey: ptr("̣@tulir:maunium.net"), Content: mautrix.Content{ Membership: mautrix.MembershipInvite, }, } leaveEvt := &mautrix.Event{ ID: "!leave:matrix.org", Type: mautrix.StateMember, Sender: "@you:matrix.org", StateKey: ptr("̣@tulir:maunium.net"), Content: mautrix.Content{ Membership: mautrix.MembershipLeave, }, } resp := newRespSync() resp.Rooms.Join["!foo:maunium.net"] = join{ State: events{Events: []*mautrix.Event{joinEvt}}, Timeline: timeline{Events: []*mautrix.Event{messageEvt, unhandledEvt}}, } resp.Rooms.Invite["!bar:maunium.net"] = struct { State struct { Events []*mautrix.Event `json:"events"` } `json:"invite_state"` }{ State: events{Events: []*mautrix.Event{inviteEvt}}, } resp.Rooms.Leave["!test:maunium.net"] = struct { State struct { Events []*mautrix.Event `json:"events"` } `json:"state"` Timeline struct { Events []*mautrix.Event `json:"events"` Limited bool `json:"limited"` PrevBatch string `json:"prev_batch"` } `json:"timeline"` }{ State: events{Events: []*mautrix.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 } func (mss *mockSyncerSession) GetRoom(id string) *rooms.Room { return mss.rooms[id] } func (mss *mockSyncerSession) GetUserID() string { return mss.userID } type events struct { Events []*mautrix.Event `json:"events"` } type timeline struct { Events []*mautrix.Event `json:"events"` Limited bool `json:"limited"` PrevBatch string `json:"prev_batch"` } type join struct { State struct { Events []*mautrix.Event `json:"events"` } `json:"state"` Timeline struct { Events []*mautrix.Event `json:"events"` Limited bool `json:"limited"` PrevBatch string `json:"prev_batch"` } `json:"timeline"` Ephemeral struct { Events []*mautrix.Event `json:"events"` } `json:"ephemeral"` AccountData struct { Events []*mautrix.Event `json:"events"` } `json:"account_data"` } func ptr(text string) *string { return &text } type mockListener struct { received []*mautrix.Event } func (ml *mockListener) receive(source matrix.EventSource, evt *mautrix.Event) { ml.received = append(ml.received, evt) } func newRespSync() *mautrix.RespSync { resp := &mautrix.RespSync{NextBatch: "123"} resp.Rooms.Join = make(map[string]struct { State struct { Events []*mautrix.Event `json:"events"` } `json:"state"` Timeline struct { Events []*mautrix.Event `json:"events"` Limited bool `json:"limited"` PrevBatch string `json:"prev_batch"` } `json:"timeline"` Ephemeral struct { Events []*mautrix.Event `json:"events"` } `json:"ephemeral"` AccountData struct { Events []*mautrix.Event `json:"events"` } `json:"account_data"` }) resp.Rooms.Invite = make(map[string]struct { State struct { Events []*mautrix.Event `json:"events"` } `json:"invite_state"` }) resp.Rooms.Leave = make(map[string]struct { State struct { Events []*mautrix.Event `json:"events"` } `json:"state"` Timeline struct { Events []*mautrix.Event `json:"events"` Limited bool `json:"limited"` PrevBatch string `json:"prev_batch"` } `json:"timeline"` }) return resp }