From 23df0cf02f7ba9a87aa107bc6b29e17bc5fc0d02 Mon Sep 17 00:00:00 2001 From: Devon Hudson Date: Wed, 20 Sep 2023 17:36:27 -0600 Subject: [PATCH 01/10] Update gomatrixserverlib --- go.mod | 2 + go.sum | 17 +-- internal/federation/handle.go | 114 ++++++++++-------- internal/federation/server.go | 107 ++++++++-------- internal/federation/server_room.go | 32 ++--- internal/must/must.go | 4 +- tests/direct_messaging_test.go | 8 +- tests/federation_event_auth_test.go | 15 +-- tests/federation_query_profile_test.go | 9 +- tests/federation_redaction_test.go | 2 +- tests/federation_room_event_auth_test.go | 16 +-- ...federation_room_get_missing_events_test.go | 56 +++++---- tests/federation_room_invite_test.go | 3 +- tests/federation_room_join_test.go | 46 ++++--- tests/federation_room_send_test.go | 2 +- tests/federation_rooms_invite_test.go | 4 +- tests/knocking_test.go | 4 +- 17 files changed, 243 insertions(+), 198 deletions(-) diff --git a/go.mod b/go.mod index 89275817..15f11631 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,7 @@ module github.com/matrix-org/complement +replace github.com/matrix-org/gomatrixserverlib => ../../../gomatrixserverlib/main/ + go 1.16 require ( diff --git a/go.sum b/go.sum index aa4f34b5..0d64b652 100644 --- a/go.sum +++ b/go.sum @@ -62,7 +62,6 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= @@ -78,13 +77,10 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230113181222-67e060196d05 h1:b0bSn6mQXKC0rktS5CZS/4imu643NYccnpSCv/w6xWc= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230113181222-67e060196d05/go.mod h1:Mtifyr8q8htcBeugvlDnkBcNUy5LO8OzUoplAf1+mb4= github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4/go.mod h1:vVQlW/emklohkZnOPwD3LrZUBqdfsbiyO3p1lNV8F6U= github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y= github.com/matrix-org/util v0.0.0-20221111132719-399730281e66/go.mod h1:iBI1foelCqA09JJgPV0FYz4qA5dUXYOxMi57FxKBdd4= github.com/mattn/go-sqlite3 v1.14.13/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 h1:yH0SvLzcbZxcJXho2yh7CqdENGMQe73Cw3woZBpPli0= github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= @@ -179,7 +175,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -193,9 +188,9 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220513224357-95641704303c/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220919232410-f2f64ebce3c1/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -225,13 +220,13 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -254,7 +249,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -275,7 +269,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY= gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0= gopkg.in/macaroon.v2 v2.1.0/go.mod h1:OUb+TQP/OP0WOerC2Jp/3CwhIKyIa9kQjuc7H24e6/o= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= diff --git a/internal/federation/handle.go b/internal/federation/handle.go index c6374495..0261879a 100644 --- a/internal/federation/handle.go +++ b/internal/federation/handle.go @@ -10,6 +10,8 @@ import ( "github.com/gorilla/mux" "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/gomatrixserverlib/fclient" + "github.com/matrix-org/gomatrixserverlib/spec" "github.com/matrix-org/util" ) @@ -17,8 +19,8 @@ import ( // HandleMakeSendJoinRequests. func MakeJoinRequestsHandler(s *Server, w http.ResponseWriter, req *http.Request) { // Check federation signature - fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest( - req, time.Now(), gomatrixserverlib.ServerName(s.serverName), nil, s.keyRing, + fedReq, errResp := fclient.VerifyHTTPRequest( + req, time.Now(), spec.ServerName(s.serverName), nil, s.keyRing, ) if fedReq == nil { w.WriteHeader(errResp.Code) @@ -53,62 +55,62 @@ func MakeJoinRequestsHandler(s *Server, w http.ResponseWriter, req *http.Request // MakeRespMakeJoin makes the response for a /make_join request, without verifying any signatures // or dealing with HTTP responses itself. -func MakeRespMakeJoin(s *Server, room *ServerRoom, userID string) (resp gomatrixserverlib.RespMakeJoin, err error) { +func MakeRespMakeJoin(s *Server, room *ServerRoom, userID string) (resp fclient.RespMakeJoin, err error) { // Generate a join event - builder := gomatrixserverlib.EventBuilder{ - Sender: userID, + proto := gomatrixserverlib.ProtoEvent{ + SenderID: userID, RoomID: room.RoomID, Type: "m.room.member", StateKey: &userID, PrevEvents: []string{room.Timeline[len(room.Timeline)-1].EventID()}, Depth: room.Timeline[len(room.Timeline)-1].Depth() + 1, } - err = builder.SetContent(map[string]interface{}{"membership": gomatrixserverlib.Join}) + err = proto.SetContent(map[string]interface{}{"membership": spec.Join}) if err != nil { err = fmt.Errorf("make_join cannot set membership content: %w", err) return } - stateNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(&builder) + stateNeeded, err := gomatrixserverlib.StateNeededForProtoEvent(&proto) if err != nil { err = fmt.Errorf("make_join cannot calculate auth_events: %w", err) return } - builder.AuthEvents = room.AuthEvents(stateNeeded) + proto.AuthEvents = room.AuthEvents(stateNeeded) - resp = gomatrixserverlib.RespMakeJoin{ + resp = fclient.RespMakeJoin{ RoomVersion: room.Version, - JoinEvent: builder, + JoinEvent: proto, } return } // MakeRespMakeKnock makes the response for a /make_knock request, without verifying any signatures // or dealing with HTTP responses itself. -func MakeRespMakeKnock(s *Server, room *ServerRoom, userID string) (resp gomatrixserverlib.RespMakeKnock, err error) { +func MakeRespMakeKnock(s *Server, room *ServerRoom, userID string) (resp fclient.RespMakeKnock, err error) { // Generate a knock event - builder := gomatrixserverlib.EventBuilder{ - Sender: userID, + proto := gomatrixserverlib.ProtoEvent{ + SenderID: userID, RoomID: room.RoomID, Type: "m.room.member", StateKey: &userID, PrevEvents: []string{room.Timeline[len(room.Timeline)-1].EventID()}, Depth: room.Timeline[len(room.Timeline)-1].Depth() + 1, } - err = builder.SetContent(map[string]interface{}{"membership": gomatrixserverlib.Join}) + err = proto.SetContent(map[string]interface{}{"membership": spec.Join}) if err != nil { err = fmt.Errorf("make_knock cannot set membership content: %w", err) return } - stateNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(&builder) + stateNeeded, err := gomatrixserverlib.StateNeededForProtoEvent(&proto) if err != nil { err = fmt.Errorf("make_knock cannot calculate auth_events: %w", err) return } - builder.AuthEvents = room.AuthEvents(stateNeeded) + proto.AuthEvents = room.AuthEvents(stateNeeded) - resp = gomatrixserverlib.RespMakeKnock{ + resp = fclient.RespMakeKnock{ RoomVersion: room.Version, - KnockEvent: builder, + KnockEvent: proto, } return } @@ -124,8 +126,8 @@ func MakeRespMakeKnock(s *Server, room *ServerRoom, userID string) (resp gomatri // servers in the room. When omitServersInRoom is true, a misbehaving server is simulated and only // the current server is returned to the joining server. func SendJoinRequestsHandler(s *Server, w http.ResponseWriter, req *http.Request, expectPartialState bool, omitServersInRoom bool) { - fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest( - req, time.Now(), gomatrixserverlib.ServerName(s.serverName), nil, s.keyRing, + fedReq, errResp := fclient.VerifyHTTPRequest( + req, time.Now(), spec.ServerName(s.serverName), nil, s.keyRing, ) if fedReq == nil { w.WriteHeader(errResp.Code) @@ -154,7 +156,13 @@ func SendJoinRequestsHandler(s *Server, w http.ResponseWriter, req *http.Request w.Write([]byte("complement: HandleMakeSendJoinRequests send_join unexpected room ID: " + roomID)) return } - event, err := gomatrixserverlib.NewEventFromUntrustedJSON(fedReq.Content(), room.Version) + verImpl, err := gomatrixserverlib.GetRoomVersion(room.Version) + if err != nil { + w.WriteHeader(500) + w.Write([]byte("complement: HandleMakeSendJoinRequests send_join unexpected room version: " + err.Error())) + return + } + event, err := verImpl.NewEventFromUntrustedJSON(fedReq.Content()) if err != nil { w.WriteHeader(500) w.Write([]byte("complement: HandleMakeSendJoinRequests send_join cannot parse event JSON: " + err.Error())) @@ -162,7 +170,7 @@ func SendJoinRequestsHandler(s *Server, w http.ResponseWriter, req *http.Request } // build the state list *before* we insert the new event - var stateEvents []*gomatrixserverlib.Event + var stateEvents []gomatrixserverlib.PDU room.StateMutex.RLock() for _, ev := range room.State { // filter out non-critical memberships if this is a partial-state join @@ -188,8 +196,8 @@ func SendJoinRequestsHandler(s *Server, w http.ResponseWriter, req *http.Request log.Printf("Received send-join of event %s", event.EventID()) // return state and auth chain - b, err := json.Marshal(gomatrixserverlib.RespSendJoin{ - Origin: gomatrixserverlib.ServerName(s.serverName), + b, err := json.Marshal(fclient.RespSendJoin{ + Origin: spec.ServerName(s.serverName), AuthEvents: gomatrixserverlib.NewEventJSONsFromEvents(authEvents), StateEvents: gomatrixserverlib.NewEventJSONsFromEvents(stateEvents), MembersOmitted: expectPartialState, @@ -235,12 +243,12 @@ func HandlePartialStateMakeSendJoinRequests() func(*Server) { // HandleInviteRequests is an option which makes the server process invite requests. // // inviteCallback is a callback function that if non-nil will be called and passed the incoming invite event -func HandleInviteRequests(inviteCallback func(*gomatrixserverlib.Event)) func(*Server) { +func HandleInviteRequests(inviteCallback func(gomatrixserverlib.PDU)) func(*Server) { return func(s *Server) { // https://matrix.org/docs/spec/server_server/r0.1.4#put-matrix-federation-v2-invite-roomid-eventid s.mux.Handle("/_matrix/federation/v2/invite/{roomID}/{eventID}", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest( - req, time.Now(), gomatrixserverlib.ServerName(s.serverName), nil, s.keyRing, + fedReq, errResp := fclient.VerifyHTTPRequest( + req, time.Now(), spec.ServerName(s.serverName), nil, s.keyRing, ) if fedReq == nil { w.WriteHeader(errResp.Code) @@ -249,7 +257,7 @@ func HandleInviteRequests(inviteCallback func(*gomatrixserverlib.Event)) func(*S return } - var inviteRequest gomatrixserverlib.InviteV2Request + var inviteRequest fclient.InviteV2Request if err := json.Unmarshal(fedReq.Content(), &inviteRequest); err != nil { log.Printf( "complement: Unable to unmarshal incoming /invite request: %s", @@ -291,10 +299,10 @@ func HandleDirectoryLookups() func(*Server) { s.mux.Handle("/_matrix/federation/v1/query/directory", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { alias := req.URL.Query().Get("room_alias") if roomID, ok := s.aliases[alias]; ok { - b, err := json.Marshal(gomatrixserverlib.RespDirectory{ + b, err := json.Marshal(fclient.RespDirectory{ RoomID: roomID, - Servers: []gomatrixserverlib.ServerName{ - gomatrixserverlib.ServerName(s.serverName), + Servers: []spec.ServerName{ + spec.ServerName(s.serverName), }, }) if err != nil { @@ -321,7 +329,7 @@ func HandleEventRequests() func(*Server) { srv.mux.Handle("/_matrix/federation/v1/event/{eventID}", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { vars := mux.Vars(req) eventID := vars["eventID"] - var event *gomatrixserverlib.Event + var event gomatrixserverlib.PDU // find the event RoomLoop: for _, room := range srv.rooms { @@ -340,8 +348,8 @@ func HandleEventRequests() func(*Server) { } txn := gomatrixserverlib.Transaction{ - Origin: gomatrixserverlib.ServerName(srv.serverName), - OriginServerTS: gomatrixserverlib.AsTimestamp(time.Now()), + Origin: spec.ServerName(srv.serverName), + OriginServerTS: spec.AsTimestamp(time.Now()), PDUs: []json.RawMessage{ event.JSON(), }, @@ -376,7 +384,7 @@ func HandleEventAuthRequests() func(*Server) { } // find the event - var event *gomatrixserverlib.Event + var event gomatrixserverlib.PDU for _, ev := range room.Timeline { if ev.EventID() == eventID { event = ev @@ -391,8 +399,8 @@ func HandleEventAuthRequests() func(*Server) { return } - authEvents := room.AuthChainForEvents([]*gomatrixserverlib.Event{event}) - resp := gomatrixserverlib.RespEventAuth{ + authEvents := room.AuthChainForEvents([]gomatrixserverlib.PDU{event}) + resp := fclient.RespEventAuth{ gomatrixserverlib.NewEventJSONsFromEvents(authEvents), } respJSON, err := json.Marshal(resp) @@ -413,15 +421,15 @@ func HandleKeyRequests() func(*Server) { keymux := srv.mux.PathPrefix("/_matrix/key/v2").Subrouter() keyFn := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { k := gomatrixserverlib.ServerKeys{} - k.ServerName = gomatrixserverlib.ServerName(srv.serverName) + k.ServerName = spec.ServerName(srv.serverName) publicKey := srv.Priv.Public().(ed25519.PublicKey) k.VerifyKeys = map[gomatrixserverlib.KeyID]gomatrixserverlib.VerifyKey{ srv.KeyID: { - Key: gomatrixserverlib.Base64Bytes(publicKey), + Key: spec.Base64Bytes(publicKey), }, } k.OldVerifyKeys = map[gomatrixserverlib.KeyID]gomatrixserverlib.OldVerifyKey{} - k.ValidUntilTS = gomatrixserverlib.AsTimestamp(time.Now().Add(24 * time.Hour)) + k.ValidUntilTS = spec.AsTimestamp(time.Now().Add(24 * time.Hour)) toSign, err := json.Marshal(k.ServerKeyFields) if err != nil { w.WriteHeader(500) @@ -484,7 +492,7 @@ func HandleMediaRequests(mediaIds map[string]func(w http.ResponseWriter)) func(* // HandleTransactionRequests is an option which will process GET /_matrix/federation/v1/send/{transactionID} requests universally when requested. // pduCallback and eduCallback are functions that if non-nil will be called and passed each PDU or EDU event received in the transaction. // Callbacks will be fired AFTER the event has been stored onto the respective ServerRoom. -func HandleTransactionRequests(pduCallback func(*gomatrixserverlib.Event), eduCallback func(gomatrixserverlib.EDU)) func(*Server) { +func HandleTransactionRequests(pduCallback func(gomatrixserverlib.PDU), eduCallback func(gomatrixserverlib.EDU)) func(*Server) { return func(srv *Server) { srv.mux.Handle("/_matrix/federation/v1/send/{transactionID}", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { // Extract the transaction ID from the request vars @@ -492,8 +500,8 @@ func HandleTransactionRequests(pduCallback func(*gomatrixserverlib.Event), eduCa transactionID := vars["transactionID"] // Check federation signature - fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest( - req, time.Now(), gomatrixserverlib.ServerName(srv.serverName), nil, srv.keyRing, + fedReq, errResp := fclient.VerifyHTTPRequest( + req, time.Now(), spec.ServerName(srv.serverName), nil, srv.keyRing, ) if fedReq == nil { log.Printf( @@ -540,8 +548,8 @@ func HandleTransactionRequests(pduCallback func(*gomatrixserverlib.Event), eduCa } // Construct a response and fill as we process each PDU - response := gomatrixserverlib.RespSend{} - response.PDUs = make(map[string]gomatrixserverlib.PDUResult) + response := fclient.RespSend{} + response.PDUs = make(map[string]fclient.PDUResult) for _, pdu := range transaction.PDUs { var header struct { RoomID string `json:"room_id"` @@ -561,10 +569,18 @@ func HandleTransactionRequests(pduCallback func(*gomatrixserverlib.Event), eduCa log.Printf("complement: Transaction '%s': Failed to find local room: %s", transaction.TransactionID, header.RoomID) continue } - roomVersion := gomatrixserverlib.RoomVersion(room.Version) - var event *gomatrixserverlib.Event - event, err = gomatrixserverlib.NewEventFromUntrustedJSON(pdu, roomVersion) + var event gomatrixserverlib.PDU + verImpl, err := gomatrixserverlib.GetRoomVersion(room.Version) + if err != nil { + log.Printf( + "complement: Transaction '%s': Failed to get room version '%s': %s", + transaction.TransactionID, event.EventID(), err.Error(), + ) + continue + } + + event, err = verImpl.NewEventFromUntrustedJSON(pdu) if err != nil { // We were unable to verify or process this event. log.Printf( @@ -580,7 +596,7 @@ func HandleTransactionRequests(pduCallback func(*gomatrixserverlib.Event), eduCa room.AddEvent(event) // Add this PDU as a success to the response - response.PDUs[event.EventID()] = gomatrixserverlib.PDUResult{} + response.PDUs[event.EventID()] = fclient.PDUResult{} // Run the PDU callback function with this event if pduCallback != nil { diff --git a/internal/federation/server.go b/internal/federation/server.go index 7959619d..ece6a749 100644 --- a/internal/federation/server.go +++ b/internal/federation/server.go @@ -21,6 +21,8 @@ import ( "time" "github.com/matrix-org/gomatrix" + "github.com/matrix-org/gomatrixserverlib/fclient" + "github.com/matrix-org/gomatrixserverlib/spec" "github.com/gorilla/mux" "github.com/matrix-org/gomatrixserverlib" @@ -76,9 +78,11 @@ func NewServer(t *testing.T, deployment *docker.Deployment, opts ...func(*Server } fetcher := &basicKeyFetcher{ KeyFetcher: &gomatrixserverlib.DirectKeyFetcher{ - Client: gomatrixserverlib.NewClient( - gomatrixserverlib.WithTransport(&docker.RoundTripper{Deployment: deployment}), + Client: fclient.NewClient( + fclient.WithTransport(&docker.RoundTripper{Deployment: deployment}), ), + IsLocalServerName: func(s spec.ServerName) bool { return s == spec.ServerName(deployment.Config.HostnameRunningComplement) }, + LocalPublicKey: []byte(pub), }, srv: srv, } @@ -182,18 +186,18 @@ func (s *Server) MustMakeRoom(t *testing.T, roomVer gomatrixserverlib.RoomVersio // FederationClient returns a client which will sign requests using this server's key. // // The requests will be routed according to the deployment map in `deployment`. -func (s *Server) FederationClient(deployment *docker.Deployment) *gomatrixserverlib.FederationClient { +func (s *Server) FederationClient(deployment *docker.Deployment) fclient.FederationClient { if !s.listening { s.t.Fatalf("FederationClient() called before Listen() - this is not supported because Listen() chooses a high-numbered port and thus changes the server name and thus changes the way federation requests are signed. Ensure you Listen() first!") } - identity := gomatrixserverlib.SigningIdentity{ - ServerName: gomatrixserverlib.ServerName(s.ServerName()), + identity := fclient.SigningIdentity{ + ServerName: spec.ServerName(s.ServerName()), KeyID: s.KeyID, PrivateKey: s.Priv, } - f := gomatrixserverlib.NewFederationClient( - []*gomatrixserverlib.SigningIdentity{&identity}, - gomatrixserverlib.WithTransport(&docker.RoundTripper{Deployment: deployment}), + f := fclient.NewFederationClient( + []*fclient.SigningIdentity{&identity}, + fclient.WithTransport(&docker.RoundTripper{Deployment: deployment}), ) return f } @@ -207,8 +211,8 @@ func (s *Server) MustSendTransaction(t *testing.T, deployment *docker.Deployment defer cancel() resp, err := cli.SendTransaction(ctx, gomatrixserverlib.Transaction{ TransactionID: gomatrixserverlib.TransactionID(fmt.Sprintf("complement-%d", time.Now().Nanosecond())), - Origin: gomatrixserverlib.ServerName(s.ServerName()), - Destination: gomatrixserverlib.ServerName(destination), + Origin: spec.ServerName(s.ServerName()), + Destination: spec.ServerName(destination), PDUs: pdus, EDUs: edus, }) @@ -229,10 +233,10 @@ func (s *Server) SendFederationRequest( ctx context.Context, t *testing.T, deployment *docker.Deployment, - req gomatrixserverlib.FederationRequest, + req fclient.FederationRequest, resBody interface{}, ) error { - if err := req.Sign(gomatrixserverlib.ServerName(s.serverName), s.KeyID, s.Priv); err != nil { + if err := req.Sign(spec.ServerName(s.serverName), s.KeyID, s.Priv); err != nil { return err } @@ -241,7 +245,7 @@ func (s *Server) SendFederationRequest( return err } - httpClient := gomatrixserverlib.NewClient(gomatrixserverlib.WithTransport(&docker.RoundTripper{Deployment: deployment})) + httpClient := fclient.NewClient(fclient.WithTransport(&docker.RoundTripper{Deployment: deployment})) start := time.Now() err = httpClient.DoRequestAndParseResponse(ctx, httpReq, resBody) @@ -260,8 +264,8 @@ func (s *Server) DoFederationRequest( ctx context.Context, t *testing.T, deployment *docker.Deployment, - req gomatrixserverlib.FederationRequest) (*http.Response, error) { - if err := req.Sign(gomatrixserverlib.ServerName(s.serverName), s.KeyID, s.Priv); err != nil { + req fclient.FederationRequest) (*http.Response, error) { + if err := req.Sign(spec.ServerName(s.serverName), s.KeyID, s.Priv); err != nil { return nil, err } @@ -270,7 +274,7 @@ func (s *Server) DoFederationRequest( return nil, err } - httpClient := gomatrixserverlib.NewClient(gomatrixserverlib.WithTransport(&docker.RoundTripper{Deployment: deployment})) + httpClient := fclient.NewClient(fclient.WithTransport(&docker.RoundTripper{Deployment: deployment})) start := time.Now() var resp *http.Response @@ -286,7 +290,7 @@ func (s *Server) DoFederationRequest( // MustCreateEvent will create and sign a new latest event for the given room. // It does not insert this event into the room however. See ServerRoom.AddEvent for that. -func (s *Server) MustCreateEvent(t *testing.T, room *ServerRoom, ev b.Event) *gomatrixserverlib.Event { +func (s *Server) MustCreateEvent(t *testing.T, room *ServerRoom, ev b.Event) gomatrixserverlib.PDU { t.Helper() content, err := json.Marshal(ev.Content) if err != nil { @@ -310,8 +314,8 @@ func (s *Server) MustCreateEvent(t *testing.T, room *ServerRoom, ev b.Event) *go // the usual behaviour. prevEvents = room.ForwardExtremities } - eb := gomatrixserverlib.EventBuilder{ - Sender: ev.Sender, + proto := gomatrixserverlib.ProtoEvent{ + SenderID: ev.Sender, Depth: int64(room.Depth + 1), // depth starts at 1 Type: ev.Type, StateKey: ev.StateKey, @@ -322,15 +326,20 @@ func (s *Server) MustCreateEvent(t *testing.T, room *ServerRoom, ev b.Event) *go AuthEvents: ev.AuthEvents, Redacts: ev.Redacts, } - if eb.AuthEvents == nil { + if proto.AuthEvents == nil { var stateNeeded gomatrixserverlib.StateNeeded - stateNeeded, err = gomatrixserverlib.StateNeededForEventBuilder(&eb) + stateNeeded, err = gomatrixserverlib.StateNeededForProtoEvent(&proto) if err != nil { t.Fatalf("MustCreateEvent: failed to work out auth_events : %s", err) } - eb.AuthEvents = room.AuthEvents(stateNeeded) + proto.AuthEvents = room.AuthEvents(stateNeeded) } - signedEvent, err := eb.Build(time.Now(), gomatrixserverlib.ServerName(s.serverName), s.KeyID, s.Priv, room.Version) + verImpl, err := gomatrixserverlib.GetRoomVersion(room.Version) + if err != nil { + t.Fatalf("MustCreateEvent: invalid room version: %s", err) + } + eb := verImpl.NewEventBuilderFromProtoEvent(&proto) + signedEvent, err := eb.Build(time.Now(), spec.ServerName(s.serverName), s.KeyID, s.Priv) if err != nil { t.Fatalf("MustCreateEvent: failed to sign event: %s", err) } @@ -339,20 +348,25 @@ func (s *Server) MustCreateEvent(t *testing.T, room *ServerRoom, ev b.Event) *go // MustJoinRoom will make the server send a make_join and a send_join to join a room // It returns the resultant room. -func (s *Server) MustJoinRoom(t *testing.T, deployment *docker.Deployment, remoteServer gomatrixserverlib.ServerName, roomID string, userID string, partialState ...bool) *ServerRoom { +func (s *Server) MustJoinRoom(t *testing.T, deployment *docker.Deployment, remoteServer spec.ServerName, roomID string, userID string, partialState ...bool) *ServerRoom { t.Helper() - origin := gomatrixserverlib.ServerName(s.serverName) + origin := spec.ServerName(s.serverName) fedClient := s.FederationClient(deployment) - makeJoinResp, err := fedClient.MakeJoin(context.Background(), origin, remoteServer, roomID, userID, SupportedRoomVersions()) + makeJoinResp, err := fedClient.MakeJoin(context.Background(), origin, remoteServer, roomID, userID) if err != nil { t.Fatalf("MustJoinRoom: make_join failed: %v", err) } roomVer := makeJoinResp.RoomVersion - joinEvent, err := makeJoinResp.JoinEvent.Build(time.Now(), origin, s.KeyID, s.Priv, roomVer) + verImpl, err := gomatrixserverlib.GetRoomVersion(makeJoinResp.RoomVersion) + if err != nil { + t.Fatalf("MustJoinRoom: invalid room version: %v", err) + } + eb := verImpl.NewEventBuilderFromProtoEvent(&makeJoinResp.JoinEvent) + joinEvent, err := eb.Build(time.Now(), origin, s.KeyID, s.Priv) if err != nil { t.Fatalf("MustJoinRoom: failed to sign event: %v", err) } - var sendJoinResp gomatrixserverlib.RespSendJoin + var sendJoinResp fclient.RespSendJoin if len(partialState) == 0 || !partialState[0] { // Default to doing a regular join. sendJoinResp, err = fedClient.SendJoin(context.Background(), origin, remoteServer, joinEvent) @@ -376,11 +390,11 @@ func (s *Server) MustJoinRoom(t *testing.T, deployment *docker.Deployment, remot } // Leaves a room. If this is rejecting an invite then a make_leave request is made first, before send_leave. -func (s *Server) MustLeaveRoom(t *testing.T, deployment *docker.Deployment, remoteServer gomatrixserverlib.ServerName, roomID string, userID string) { +func (s *Server) MustLeaveRoom(t *testing.T, deployment *docker.Deployment, remoteServer spec.ServerName, roomID string, userID string) { t.Helper() - origin := gomatrixserverlib.ServerName(s.serverName) + origin := spec.ServerName(s.serverName) fedClient := s.FederationClient(deployment) - var leaveEvent *gomatrixserverlib.Event + var leaveEvent gomatrixserverlib.PDU room := s.rooms[roomID] if room == nil { // e.g rejecting an invite @@ -388,8 +402,12 @@ func (s *Server) MustLeaveRoom(t *testing.T, deployment *docker.Deployment, remo if err != nil { t.Fatalf("MustLeaveRoom: (rejecting invite) make_leave failed: %v", err) } - roomVer := makeLeaveResp.RoomVersion - leaveEvent, err = makeLeaveResp.LeaveEvent.Build(time.Now(), origin, s.KeyID, s.Priv, roomVer) + verImpl, err := gomatrixserverlib.GetRoomVersion(makeLeaveResp.RoomVersion) + if err != nil { + t.Fatalf("MustLeaveRoom: invalid room version: %v", err) + } + eb := verImpl.NewEventBuilderFromProtoEvent(&makeLeaveResp.LeaveEvent) + leaveEvent, err = eb.Build(time.Now(), origin, s.KeyID, s.Priv) if err != nil { t.Fatalf("MustLeaveRoom: (rejecting invite) failed to sign event: %v", err) } @@ -416,11 +434,11 @@ func (s *Server) MustLeaveRoom(t *testing.T, deployment *docker.Deployment, remo // ValidFederationRequest is a wrapper around http.HandlerFunc which automatically validates the incoming // federation request and supports sending back JSON. Fails the test if the request is not valid. -func (s *Server) ValidFederationRequest(t *testing.T, handler func(fr *gomatrixserverlib.FederationRequest, pathParams map[string]string) util.JSONResponse) http.HandlerFunc { +func (s *Server) ValidFederationRequest(t *testing.T, handler func(fr *fclient.FederationRequest, pathParams map[string]string) util.JSONResponse) http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { // Check federation signature - fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest( - req, time.Now(), gomatrixserverlib.ServerName(s.serverName), nil, s.keyRing, + fedReq, errResp := fclient.VerifyHTTPRequest( + req, time.Now(), spec.ServerName(s.serverName), nil, s.keyRing, ) if fedReq == nil { t.Errorf( @@ -575,7 +593,7 @@ func (d *nopKeyDatabase) StoreKeys(ctx context.Context, results map[gomatrixserv } func (f *nopKeyDatabase) FetchKeys( ctx context.Context, - requests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp) ( + requests map[gomatrixserverlib.PublicKeyLookupRequest]spec.Timestamp) ( map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult, error, ) { return nil, nil @@ -591,7 +609,7 @@ type basicKeyFetcher struct { func (f *basicKeyFetcher) FetchKeys( ctx context.Context, - requests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp) ( + requests map[gomatrixserverlib.PublicKeyLookupRequest]spec.Timestamp) ( map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult, error, ) { result := make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult, len(requests)) @@ -599,10 +617,10 @@ func (f *basicKeyFetcher) FetchKeys( if string(req.ServerName) == f.srv.serverName && req.KeyID == f.srv.KeyID { publicKey := f.srv.Priv.Public().(ed25519.PublicKey) result[req] = gomatrixserverlib.PublicKeyLookupResult{ - ValidUntilTS: gomatrixserverlib.AsTimestamp(time.Now().Add(24 * time.Hour)), + ValidUntilTS: spec.AsTimestamp(time.Now().Add(24 * time.Hour)), ExpiredTS: gomatrixserverlib.PublicKeyNotExpired, VerifyKey: gomatrixserverlib.VerifyKey{ - Key: gomatrixserverlib.Base64Bytes(publicKey), + Key: spec.Base64Bytes(publicKey), }, } } else { @@ -615,12 +633,3 @@ func (f *basicKeyFetcher) FetchKeys( func (f *basicKeyFetcher) FetcherName() string { return "basicKeyFetcher" } - -// SupportedRoomVersions is a convenience method which returns a list of the room versions supported by gomatrixserverlib. -func SupportedRoomVersions() []gomatrixserverlib.RoomVersion { - supportedRoomVersions := make([]gomatrixserverlib.RoomVersion, 0, 10) - for v := range gomatrixserverlib.SupportedRoomVersions() { - supportedRoomVersions = append(supportedRoomVersions, v) - } - return supportedRoomVersions -} diff --git a/internal/federation/server_room.go b/internal/federation/server_room.go index c17d94ab..82e1ef7f 100644 --- a/internal/federation/server_room.go +++ b/internal/federation/server_room.go @@ -15,9 +15,9 @@ import ( type ServerRoom struct { Version gomatrixserverlib.RoomVersion RoomID string - State map[string]*gomatrixserverlib.Event + State map[string]gomatrixserverlib.PDU StateMutex sync.RWMutex - Timeline []*gomatrixserverlib.Event + Timeline []gomatrixserverlib.PDU TimelineMutex sync.RWMutex ForwardExtremities []string Depth int64 @@ -28,14 +28,14 @@ func newRoom(roomVer gomatrixserverlib.RoomVersion, roomId string) *ServerRoom { return &ServerRoom{ RoomID: roomId, Version: roomVer, - State: make(map[string]*gomatrixserverlib.Event), + State: make(map[string]gomatrixserverlib.PDU), ForwardExtremities: make([]string, 0), } } // AddEvent adds a new event to the timeline, updating current state if it is a state event. // Updates depth and forward extremities. -func (r *ServerRoom) AddEvent(ev *gomatrixserverlib.Event) { +func (r *ServerRoom) AddEvent(ev gomatrixserverlib.PDU) { if ev.StateKey() != nil { r.replaceCurrentState(ev) } @@ -78,7 +78,7 @@ func (r *ServerRoom) AuthEvents(sn gomatrixserverlib.StateNeeded) (eventIDs []st // replaceCurrentState inserts a new state event for this room or replaces current state depending // on the (type, state_key) provided. -func (r *ServerRoom) replaceCurrentState(ev *gomatrixserverlib.Event) { +func (r *ServerRoom) replaceCurrentState(ev gomatrixserverlib.PDU) { tuple := fmt.Sprintf("%s\x1f%s", ev.Type(), *ev.StateKey()) r.StateMutex.Lock() r.State[tuple] = ev @@ -86,7 +86,7 @@ func (r *ServerRoom) replaceCurrentState(ev *gomatrixserverlib.Event) { } // CurrentState returns the state event for the given (type, state_key) or nil. -func (r *ServerRoom) CurrentState(evType, stateKey string) *gomatrixserverlib.Event { +func (r *ServerRoom) CurrentState(evType, stateKey string) gomatrixserverlib.PDU { tuple := fmt.Sprintf("%s\x1f%s", evType, stateKey) r.StateMutex.RLock() state := r.State[tuple] @@ -95,7 +95,7 @@ func (r *ServerRoom) CurrentState(evType, stateKey string) *gomatrixserverlib.Ev } // AllCurrentState returns all the current state events -func (r *ServerRoom) AllCurrentState() (events []*gomatrixserverlib.Event) { +func (r *ServerRoom) AllCurrentState() (events []gomatrixserverlib.PDU) { r.StateMutex.RLock() for _, ev := range r.State { events = append(events, ev) @@ -105,17 +105,17 @@ func (r *ServerRoom) AllCurrentState() (events []*gomatrixserverlib.Event) { } // AuthChain returns all auth events for all events in the current state TODO: recursively -func (r *ServerRoom) AuthChain() (chain []*gomatrixserverlib.Event) { +func (r *ServerRoom) AuthChain() (chain []gomatrixserverlib.PDU) { return r.AuthChainForEvents(r.AllCurrentState()) } // AuthChainForEvents returns all auth events for all events in the given state -func (r *ServerRoom) AuthChainForEvents(events []*gomatrixserverlib.Event) (chain []*gomatrixserverlib.Event) { +func (r *ServerRoom) AuthChainForEvents(events []gomatrixserverlib.PDU) (chain []gomatrixserverlib.PDU) { chainMap := make(map[string]bool) // build a map of all events in the room // Timeline and State contain different sets of events, so check them both. - eventsByID := map[string]*gomatrixserverlib.Event{} + eventsByID := map[string]gomatrixserverlib.PDU{} r.TimelineMutex.RLock() for _, ev := range r.Timeline { eventsByID[ev.EventID()] = ev @@ -128,7 +128,7 @@ func (r *ServerRoom) AuthChainForEvents(events []*gomatrixserverlib.Event) (chai r.StateMutex.RUnlock() // a queue of events whose auth events are to be included in the auth chain - queue := []*gomatrixserverlib.Event{} + queue := []gomatrixserverlib.PDU{} queue = append(queue, events...) // get all the auth events recursively @@ -255,16 +255,10 @@ func InitialRoomEvents(roomVer gomatrixserverlib.RoomVersion, creator string) [] // EventIDsOrReferences converts a list of events into a list of EventIDs or EventReferences, // depending on the room version -func (r *ServerRoom) EventIDsOrReferences(events []*gomatrixserverlib.Event) (refs []interface{}) { +func (r *ServerRoom) EventIDsOrReferences(events []gomatrixserverlib.PDU) (refs []interface{}) { refs = make([]interface{}, len(events)) - eventFormat, _ := r.Version.EventFormat() for i, ev := range events { - switch eventFormat { - case gomatrixserverlib.EventFormatV1: - refs[i] = ev.EventReference() - default: - refs[i] = ev.EventID() - } + refs[i] = ev.EventID() } return } diff --git a/internal/must/must.go b/internal/must/must.go index d7cd9c33..4b218c00 100644 --- a/internal/must/must.go +++ b/internal/must/must.go @@ -12,7 +12,7 @@ import ( "github.com/tidwall/gjson" - "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/gomatrixserverlib/fclient" "github.com/matrix-org/complement/internal/match" ) @@ -118,7 +118,7 @@ func MatchResponse(t *testing.T, res *http.Response, m match.HTTPResponse) []byt } // MatchFederationRequest performs JSON assertions on incoming federation requests. -func MatchFederationRequest(t *testing.T, fedReq *gomatrixserverlib.FederationRequest, matchers ...match.JSON) { +func MatchFederationRequest(t *testing.T, fedReq *fclient.FederationRequest, matchers ...match.JSON) { t.Helper() content := fedReq.Content() if !gjson.ValidBytes(content) { diff --git a/tests/direct_messaging_test.go b/tests/direct_messaging_test.go index 6b310a03..6d1a7558 100644 --- a/tests/direct_messaging_test.go +++ b/tests/direct_messaging_test.go @@ -11,6 +11,8 @@ import ( "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/gomatrixserverlib/fclient" + "github.com/matrix-org/gomatrixserverlib/spec" "github.com/matrix-org/gomatrixserverlib" "github.com/tidwall/gjson" @@ -132,13 +134,13 @@ func TestIsDirectFlagFederation(t *testing.T) { "membership": "invite", "is_direct": true, }, - }).Headered(roomVer) - inviteReq, err := gomatrixserverlib.NewInviteV2Request(dmInviteEvent, []gomatrixserverlib.InviteV2StrippedState{}) + }) // TODO: Used to call `.Headered(roomVer)` is that needed? + inviteReq, err := fclient.NewInviteV2Request(dmInviteEvent, []gomatrixserverlib.InviteStrippedState{}) if err != nil { t.Fatalf("failed to make invite request: %s", err) } _, since := alice.MustSync(t, client.SyncReq{}) - _, err = srv.FederationClient(deployment).SendInviteV2(context.Background(), gomatrixserverlib.ServerName(srv.ServerName()), "hs1", inviteReq) + _, err = srv.FederationClient(deployment).SendInviteV2(context.Background(), spec.ServerName(srv.ServerName()), "hs1", inviteReq) if err != nil { t.Fatalf("failed to send invite v2: %s", err) } diff --git a/tests/federation_event_auth_test.go b/tests/federation_event_auth_test.go index cbad14ea..395b131d 100644 --- a/tests/federation_event_auth_test.go +++ b/tests/federation_event_auth_test.go @@ -8,6 +8,7 @@ import ( "github.com/matrix-org/complement/internal/b" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/gomatrixserverlib/spec" "github.com/matrix-org/gomatrixserverlib" ) @@ -21,10 +22,10 @@ import ( // - Charlie on Complement joins the room over federation, then leaves, then rejoins // - Alice updates join rules for the room (test waits until it sees this event over federation) // At this point we can then test: -// - /event_auth for the join rules event just returns the chain for the join rules event, which -// just means it returns the auth_events as that is equal to the auth chain for this event. -// - /event_auth for the latest join event returns the complete auth chain for Charlie (all the -// joins and leaves are included), without any extraneous events. +// - /event_auth for the join rules event just returns the chain for the join rules event, which +// just means it returns the auth_events as that is equal to the auth chain for this event. +// - /event_auth for the latest join event returns the complete auth chain for Charlie (all the +// joins and leaves are included), without any extraneous events. func TestEventAuth(t *testing.T) { deployment := Deploy(t, b.BlueprintOneToOneRoom) defer deployment.Destroy(t) @@ -32,14 +33,14 @@ func TestEventAuth(t *testing.T) { alice := deployment.Client(t, "hs1", "@alice:hs1") // create a remote homeserver which will make the /event_auth request - var joinRuleEvent *gomatrixserverlib.Event + var joinRuleEvent gomatrixserverlib.PDU waiter := NewWaiter() srv := federation.NewServer(t, deployment, federation.HandleKeyRequests(), federation.HandleMakeSendJoinRequests(), federation.HandleTransactionRequests( // listen for the new join rule event - func(ev *gomatrixserverlib.Event) { + func(ev gomatrixserverlib.PDU) { if jr, _ := ev.JoinRule(); jr == "invite" { joinRuleEvent = ev waiter.Finish() @@ -77,7 +78,7 @@ func TestEventAuth(t *testing.T) { getEventAuth := func(t *testing.T, eventID string, wantAuthEventIDs []string) { t.Helper() t.Logf("/event_auth for %s - want %v", eventID, wantAuthEventIDs) - eventAuthResp, err := srv.FederationClient(deployment).GetEventAuth(context.Background(), gomatrixserverlib.ServerName(srv.ServerName()), "hs1", room.Version, roomID, eventID) + eventAuthResp, err := srv.FederationClient(deployment).GetEventAuth(context.Background(), spec.ServerName(srv.ServerName()), "hs1", room.Version, roomID, eventID) must.NotError(t, "failed to /event_auth", err) if len(eventAuthResp.AuthEvents) == 0 { t.Fatalf("/event_auth returned 0 auth events") diff --git a/tests/federation_query_profile_test.go b/tests/federation_query_profile_test.go index 91a1d102..35e07edd 100644 --- a/tests/federation_query_profile_test.go +++ b/tests/federation_query_profile_test.go @@ -6,7 +6,8 @@ import ( "net/http" "testing" - "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/gomatrixserverlib/fclient" + "github.com/matrix-org/gomatrixserverlib/spec" "github.com/matrix-org/complement/internal/b" "github.com/matrix-org/complement/internal/client" @@ -79,11 +80,11 @@ func TestInboundFederationProfile(t *testing.T) { ) cancel := srv.Listen() defer cancel() - origin := gomatrixserverlib.ServerName(srv.ServerName()) + origin := spec.ServerName(srv.ServerName()) // sytest: Non-numeric ports in server names are rejected t.Run("Non-numeric ports in server names are rejected", func(t *testing.T) { - fedReq := gomatrixserverlib.NewFederationRequest( + fedReq := fclient.NewFederationRequest( "GET", origin, "hs1", @@ -114,7 +115,7 @@ func TestInboundFederationProfile(t *testing.T) { }), ) - fedReq := gomatrixserverlib.NewFederationRequest( + fedReq := fclient.NewFederationRequest( "GET", origin, "hs1", diff --git a/tests/federation_redaction_test.go b/tests/federation_redaction_test.go index 22765d76..ef9a89a6 100644 --- a/tests/federation_redaction_test.go +++ b/tests/federation_redaction_test.go @@ -27,7 +27,7 @@ func TestFederationRedactSendsWithoutEvent(t *testing.T) { federation.HandleMakeSendJoinRequests(), federation.HandleTransactionRequests( // listen for PDU events in transactions - func(ev *gomatrixserverlib.Event) { + func(ev gomatrixserverlib.PDU) { defer waiter.Finish() if ev.Type() != wantEventType { diff --git a/tests/federation_room_event_auth_test.go b/tests/federation_room_event_auth_test.go index 0292f411..b469edc8 100644 --- a/tests/federation_room_event_auth_test.go +++ b/tests/federation_room_event_auth_test.go @@ -13,6 +13,8 @@ import ( "github.com/gorilla/mux" "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/gomatrixserverlib/fclient" + "github.com/matrix-org/gomatrixserverlib/spec" "github.com/tidwall/gjson" "github.com/matrix-org/complement/internal/b" @@ -87,7 +89,7 @@ func TestInboundFederationRejectsEventsWithRejectedAuthEvents(t *testing.T) { /* Create a handler for /event_auth */ // a map from event ID to events to be returned by /event_auth - eventAuthMap := make(map[string][]*gomatrixserverlib.Event) + eventAuthMap := make(map[string][]gomatrixserverlib.PDU) srv.Mux().HandleFunc("/_matrix/federation/v1/event_auth/{roomID}/{eventID}", func(w http.ResponseWriter, req *http.Request) { vars := mux.Vars(req) eventID := vars["eventID"] @@ -98,7 +100,7 @@ func TestInboundFederationRejectsEventsWithRejectedAuthEvents(t *testing.T) { _, _ = w.Write([]byte("{}")) return } - res := gomatrixserverlib.RespEventAuth{AuthEvents: gomatrixserverlib.NewEventJSONsFromEvents(authEvents)} + res := fclient.RespEventAuth{AuthEvents: gomatrixserverlib.NewEventJSONsFromEvents(authEvents)} responseBytes, _ := json.Marshal(&res) w.WriteHeader(200) _, _ = w.Write(responseBytes) @@ -126,9 +128,9 @@ func TestInboundFederationRejectsEventsWithRejectedAuthEvents(t *testing.T) { }) _, err := fedClient.SendTransaction(context.Background(), gomatrixserverlib.Transaction{ TransactionID: "complement1", - Origin: gomatrixserverlib.ServerName(srv.ServerName()), + Origin: spec.ServerName(srv.ServerName()), Destination: "hs1", - OriginServerTS: gomatrixserverlib.AsTimestamp(time.Now()), + OriginServerTS: spec.AsTimestamp(time.Now()), PDUs: []json.RawMessage{ rejectedEvent.JSON(), }, @@ -157,7 +159,7 @@ func TestInboundFederationRejectsEventsWithRejectedAuthEvents(t *testing.T) { // create a regular event which refers to the outlier event in its auth events, // so that the outlier gets pulled in. - sentEventAuthEvents := []*gomatrixserverlib.Event{ + sentEventAuthEvents := []gomatrixserverlib.PDU{ room.CurrentState("m.room.create", ""), room.CurrentState("m.room.join_rules", ""), room.CurrentState("m.room.power_levels", ""), @@ -197,9 +199,9 @@ func TestInboundFederationRejectsEventsWithRejectedAuthEvents(t *testing.T) { _, err = fedClient.SendTransaction(context.Background(), gomatrixserverlib.Transaction{ TransactionID: "complement2", - Origin: gomatrixserverlib.ServerName(srv.ServerName()), + Origin: spec.ServerName(srv.ServerName()), Destination: "hs1", - OriginServerTS: gomatrixserverlib.AsTimestamp(time.Now()), + OriginServerTS: spec.AsTimestamp(time.Now()), PDUs: []json.RawMessage{ sentEvent1.JSON(), sentEvent2.JSON(), diff --git a/tests/federation_room_get_missing_events_test.go b/tests/federation_room_get_missing_events_test.go index 1aeeb791..0c74ee92 100644 --- a/tests/federation_room_get_missing_events_test.go +++ b/tests/federation_room_get_missing_events_test.go @@ -9,6 +9,8 @@ import ( "time" "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/gomatrixserverlib/fclient" + "github.com/matrix-org/gomatrixserverlib/spec" "github.com/matrix-org/util" "github.com/tidwall/gjson" @@ -96,7 +98,7 @@ func TestGetMissingEventsGapFilling(t *testing.T) { // 4) Respond to /get_missing_events with the missing events if the request is well-formed. srv.Mux().HandleFunc( "/_matrix/federation/v1/get_missing_events/{roomID}", - srv.ValidFederationRequest(t, func(fr *gomatrixserverlib.FederationRequest, pathParams map[string]string) util.JSONResponse { + srv.ValidFederationRequest(t, func(fr *fclient.FederationRequest, pathParams map[string]string) util.JSONResponse { if pathParams["roomID"] != roomID { t.Errorf("Received /get_missing_events for the wrong room: %s", roomID) return util.JSONResponse{ @@ -205,8 +207,9 @@ func TestOutboundFederationIgnoresMissingEventWithBadJSONForRoomVersion6(t *test if err != nil { t.Fatalf("failed to marshal badEvent content %+v", badEvent.Content) } - eb := gomatrixserverlib.EventBuilder{ - Sender: badEvent.Sender, + + proto := gomatrixserverlib.ProtoEvent{ + SenderID: badEvent.Sender, Depth: int64(room.Depth + 1), // depth starts at 1 Type: badEvent.Type, StateKey: badEvent.StateKey, @@ -214,13 +217,20 @@ func TestOutboundFederationIgnoresMissingEventWithBadJSONForRoomVersion6(t *test RoomID: room.RoomID, PrevEvents: room.ForwardExtremities, } - stateNeeded, err := gomatrixserverlib.StateNeededForEventBuilder(&eb) + var stateNeeded gomatrixserverlib.StateNeeded + stateNeeded, err = gomatrixserverlib.StateNeededForProtoEvent(&proto) if err != nil { - t.Fatalf("failed to work out auth_events : %s", err) + t.Fatalf("failed to create event: failed to work out auth_events : %s", err) } - eb.AuthEvents = room.AuthEvents(stateNeeded) + proto.AuthEvents = room.AuthEvents(stateNeeded) + // we have to create this event as a v5 event which doesn't assert floats yet - signedBadEvent, err := eb.Build(time.Now(), gomatrixserverlib.ServerName(srv.ServerName()), srv.KeyID, srv.Priv, gomatrixserverlib.RoomVersionV5) + verImpl, err := gomatrixserverlib.GetRoomVersion(gomatrixserverlib.RoomVersionV5) + if err != nil { + t.Fatalf("failed to create event: invalid room version: %s", err) + } + eb := verImpl.NewEventBuilderFromProtoEvent(&proto) + signedBadEvent, err := eb.Build(time.Now(), spec.ServerName(srv.ServerName()), srv.KeyID, srv.Priv) if err != nil { t.Fatalf("failed to sign event: %s", err) } @@ -248,9 +258,9 @@ func TestOutboundFederationIgnoresMissingEventWithBadJSONForRoomVersion6(t *test // return the bad event, which should result in the transaction failing. w.WriteHeader(200) res := struct { - Events []*gomatrixserverlib.Event `json:"events"` + Events []gomatrixserverlib.PDU `json:"events"` }{ - Events: []*gomatrixserverlib.Event{signedBadEvent}, + Events: []gomatrixserverlib.PDU{signedBadEvent}, } var responseBytes []byte responseBytes, err = json.Marshal(&res) @@ -261,8 +271,8 @@ func TestOutboundFederationIgnoresMissingEventWithBadJSONForRoomVersion6(t *test fedClient := srv.FederationClient(deployment) resp, err := fedClient.SendTransaction(context.Background(), gomatrixserverlib.Transaction{ TransactionID: "wut", - Origin: gomatrixserverlib.ServerName(srv.ServerName()), - Destination: gomatrixserverlib.ServerName("hs1"), + Origin: spec.ServerName(srv.ServerName()), + Destination: spec.ServerName("hs1"), PDUs: []json.RawMessage{ sentEvent.JSON(), }, @@ -307,8 +317,8 @@ func TestOutboundFederationIgnoresMissingEventWithBadJSONForRoomVersion6(t *test resp, err = fedClient.SendTransaction(context.Background(), gomatrixserverlib.Transaction{ TransactionID: "t2", - Origin: gomatrixserverlib.ServerName(srv.ServerName()), - Destination: gomatrixserverlib.ServerName("hs1"), + Origin: spec.ServerName(srv.ServerName()), + Destination: spec.ServerName("hs1"), PDUs: []json.RawMessage{ message3.JSON(), }, @@ -350,7 +360,7 @@ func TestInboundCanReturnMissingEvents(t *testing.T) { stateKey := "" // Set the history visibility for this room alice.SendEventSynced(t, roomID, b.Event{ - Type: gomatrixserverlib.MRoomHistoryVisibility, + Type: spec.MRoomHistoryVisibility, Content: map[string]interface{}{ "history_visibility": visibility, }, @@ -369,9 +379,9 @@ func TestInboundCanReturnMissingEvents(t *testing.T) { room := srv.MustJoinRoom(t, deployment, "hs1", roomID, charlie) alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(charlie, roomID)) - req := gomatrixserverlib.NewFederationRequest( + req := fclient.NewFederationRequest( "POST", - gomatrixserverlib.ServerName(srv.ServerName()), + spec.ServerName(srv.ServerName()), "hs1", fmt.Sprintf("/_matrix/federation/v1/get_missing_events/%s", roomID), ) @@ -390,7 +400,7 @@ func TestInboundCanReturnMissingEvents(t *testing.T) { }) must.NotError(t, "failed to set content", err) - result := gomatrixserverlib.RespMissingEvents{} + result := fclient.RespMissingEvents{} err = srv.SendFederationRequest(context.Background(), t, deployment, req, &result) must.NotError(t, "get_missing_events failed", err) if len(result.Events) == 0 { @@ -406,7 +416,7 @@ func TestInboundCanReturnMissingEvents(t *testing.T) { // * the message events := result.Events.UntrustedEvents(roomVersion) - verifyMsgEvent := func(ev *gomatrixserverlib.Event) { + verifyMsgEvent := func(ev gomatrixserverlib.PDU) { must.EqualStr(t, ev.Type(), "m.room.message", "not a message event") // if the history vis is 'joined' or 'invite', we should get redacted // copies of the events before we joined. @@ -424,20 +434,20 @@ func TestInboundCanReturnMissingEvents(t *testing.T) { } for i, ev := range events { - must.EqualStr(t, ev.RoomID(), roomID, "unexpected roomID") + must.EqualStr(t, ev.RoomID().String(), roomID, "unexpected roomID") switch i { case 0: must.EqualStr(t, ev.Type(), "m.room.member", "not a membership event") must.EqualStr(t, *ev.StateKey(), alice.UserID, "unexpected creator") case 1: - must.EqualStr(t, ev.Type(), gomatrixserverlib.MRoomPowerLevels, "not a powerlevel event") + must.EqualStr(t, ev.Type(), spec.MRoomPowerLevels, "not a powerlevel event") case 2: - must.EqualStr(t, ev.Type(), gomatrixserverlib.MRoomJoinRules, "not a join_rules event") + must.EqualStr(t, ev.Type(), spec.MRoomJoinRules, "not a join_rules event") case 3: - must.EqualStr(t, ev.Type(), gomatrixserverlib.MRoomHistoryVisibility, "not a history_visiblity event") + must.EqualStr(t, ev.Type(), spec.MRoomHistoryVisibility, "not a history_visiblity event") case 4: if visibility != gomatrixserverlib.HistoryVisibilityShared { // shared -> shared no-ops - must.EqualStr(t, ev.Type(), gomatrixserverlib.MRoomHistoryVisibility, "not a history_visiblity event") + must.EqualStr(t, ev.Type(), spec.MRoomHistoryVisibility, "not a history_visiblity event") } else { verifyMsgEvent(ev) } diff --git a/tests/federation_room_invite_test.go b/tests/federation_room_invite_test.go index a66f7b8c..b277480d 100644 --- a/tests/federation_room_invite_test.go +++ b/tests/federation_room_invite_test.go @@ -15,7 +15,6 @@ import ( // We start with two users in a room - alice@hs1, and 'delia' on the Complement test server. // alice sends an invite to charlie@hs2, which he rejects. // We check that delia sees the rejection. -// func TestFederationRejectInvite(t *testing.T) { deployment := Deploy(t, b.BlueprintFederationTwoLocalOneRemote) defer deployment.Destroy(t) @@ -27,7 +26,7 @@ func TestFederationRejectInvite(t *testing.T) { srv := federation.NewServer(t, deployment, federation.HandleKeyRequests(), - federation.HandleTransactionRequests(func(ev *gomatrixserverlib.Event) { + federation.HandleTransactionRequests(func(ev gomatrixserverlib.PDU) { sk := "" if ev.StateKey() != nil { sk = *ev.StateKey() diff --git a/tests/federation_room_join_test.go b/tests/federation_room_join_test.go index 5c302f94..5cdc7b1a 100644 --- a/tests/federation_room_join_test.go +++ b/tests/federation_room_join_test.go @@ -11,6 +11,8 @@ import ( "time" "github.com/matrix-org/gomatrix" + "github.com/matrix-org/gomatrixserverlib/fclient" + "github.com/matrix-org/gomatrixserverlib/spec" "github.com/matrix-org/gomatrixserverlib" @@ -167,7 +169,9 @@ func TestJoinFederatedRoomWithUnverifiableEvents(t *testing.T) { raw := signedEvent.JSON() raw, err := sjson.SetRawBytes(raw, "signatures", []byte(`{}`)) must.NotError(t, "failed to strip signatures key from event", err) - unsignedEvent, err := gomatrixserverlib.NewEventFromTrustedJSON(raw, false, ver) + verImpl, err := gomatrixserverlib.GetRoomVersion(room.Version) + must.NotError(t, "failed to get room version", err) + unsignedEvent, err := verImpl.NewEventFromTrustedJSON(raw, false) must.NotError(t, "failed to make Event from unsigned event JSON", err) room.AddEvent(unsignedEvent) alice.JoinRoom(t, roomAlias, nil) @@ -195,7 +199,9 @@ func TestJoinFederatedRoomWithUnverifiableEvents(t *testing.T) { raw := signedEvent.JSON() raw, err = sjson.SetRawBytes(raw, "signatures", rawSig) must.NotError(t, "failed to modify signatures key from event", err) - unsignedEvent, err := gomatrixserverlib.NewEventFromTrustedJSON(raw, false, ver) + verImpl, err := gomatrixserverlib.GetRoomVersion(room.Version) + must.NotError(t, "failed to get room version", err) + unsignedEvent, err := verImpl.NewEventFromTrustedJSON(raw, false) must.NotError(t, "failed to make Event from unsigned event JSON", err) room.AddEvent(unsignedEvent) alice.JoinRoom(t, roomAlias, nil) @@ -224,7 +230,9 @@ func TestJoinFederatedRoomWithUnverifiableEvents(t *testing.T) { raw := signedEvent.JSON() raw, err = sjson.SetRawBytes(raw, "signatures", rawSig) must.NotError(t, "failed to modify signatures key from event", err) - unsignedEvent, err := gomatrixserverlib.NewEventFromTrustedJSON(raw, false, ver) + verImpl, err := gomatrixserverlib.GetRoomVersion(room.Version) + must.NotError(t, "failed to get room version", err) + unsignedEvent, err := verImpl.NewEventFromTrustedJSON(raw, false) must.NotError(t, "failed to make Event from unsigned event JSON", err) room.AddEvent(unsignedEvent) alice.JoinRoom(t, roomAlias, nil) @@ -255,7 +263,9 @@ func TestJoinFederatedRoomWithUnverifiableEvents(t *testing.T) { must.NotError(t, "failed to marshal bad signature block", err) rawEvent, err = sjson.SetRawBytes(rawEvent, "signatures", rawSig) must.NotError(t, "failed to modify signatures key from event", err) - badlySignedEvent, err := gomatrixserverlib.NewEventFromTrustedJSON(rawEvent, false, ver) + verImpl, err := gomatrixserverlib.GetRoomVersion(room.Version) + must.NotError(t, "failed to get room version", err) + badlySignedEvent, err := verImpl.NewEventFromTrustedJSON(rawEvent, false) must.NotError(t, "failed to make Event from badly signed event JSON", err) room.AddEvent(badlySignedEvent) t.Logf("Created badly signed auth event %s", badlySignedEvent.EventID()) @@ -297,7 +307,7 @@ func TestBannedUserCannotSendJoin(t *testing.T) { federation.HandleTransactionRequests(nil, nil), ) cancel := srv.Listen() - origin := gomatrixserverlib.ServerName(srv.ServerName()) + origin := spec.ServerName(srv.ServerName()) defer cancel() fedClient := srv.FederationClient(deployment) @@ -320,13 +330,17 @@ func TestBannedUserCannotSendJoin(t *testing.T) { }) // charlie sends a make_join for a different user - makeJoinResp, err := fedClient.MakeJoin(context.Background(), origin, "hs1", roomID, srv.UserID("charlie2"), federation.SupportedRoomVersions()) + makeJoinResp, err := fedClient.MakeJoin(context.Background(), origin, "hs1", roomID, srv.UserID("charlie2")) must.NotError(t, "MakeJoin", err) // ... and does a switcheroo to turn it into a join for himself - makeJoinResp.JoinEvent.Sender = charlie + makeJoinResp.JoinEvent.SenderID = charlie makeJoinResp.JoinEvent.StateKey = &charlie - joinEvent, err := makeJoinResp.JoinEvent.Build(time.Now(), gomatrixserverlib.ServerName(srv.ServerName()), srv.KeyID, srv.Priv, makeJoinResp.RoomVersion) + + verImpl, err := gomatrixserverlib.GetRoomVersion(makeJoinResp.RoomVersion) + must.NotError(t, "JoinEvent.GetRoomVersion", err) + eb := verImpl.NewEventBuilderFromProtoEvent(&makeJoinResp.JoinEvent) + joinEvent, err := eb.Build(time.Now(), spec.ServerName(srv.ServerName()), srv.KeyID, srv.Priv) must.NotError(t, "JoinEvent.Build", err) // SendJoin should return a 403. @@ -404,14 +418,14 @@ func testValidationForSendMembershipEndpoint(t *testing.T, baseApiPath, expected // a helper function which makes a send_* request to the given path and checks // that it fails with a 400 error - assertRequestFails := func(t *testing.T, event *gomatrixserverlib.Event) { + assertRequestFails := func(t *testing.T, event gomatrixserverlib.PDU) { path := fmt.Sprintf("%s/%s/%s", baseApiPath, - url.PathEscape(event.RoomID()), + url.PathEscape(event.RoomID().String()), url.PathEscape(event.EventID()), ) t.Logf("PUT %s", path) - req := gomatrixserverlib.NewFederationRequest("PUT", gomatrixserverlib.ServerName(srv.ServerName()), "hs1", path) + req := fclient.NewFederationRequest("PUT", spec.ServerName(srv.ServerName()), "hs1", path) if err := req.SetContent(event); err != nil { t.Errorf("req.SetContent: %v", err) return @@ -500,7 +514,7 @@ func TestSendJoinPartialStateResponse(t *testing.T) { ) cancel := srv.Listen() defer cancel() - origin := gomatrixserverlib.ServerName(srv.ServerName()) + origin := spec.ServerName(srv.ServerName()) // annoyingly we can't get to the room that alice and bob already share (see https://github.com/matrix-org/complement/issues/254) // so we have to create a new one. @@ -513,14 +527,16 @@ func TestSendJoinPartialStateResponse(t *testing.T) { // now we send a make_join... charlie := srv.UserID("charlie") fedClient := srv.FederationClient(deployment) - makeJoinResp, err := fedClient.MakeJoin(context.Background(), origin, "hs1", roomID, charlie, federation.SupportedRoomVersions()) + makeJoinResp, err := fedClient.MakeJoin(context.Background(), origin, "hs1", roomID, charlie) if err != nil { t.Fatalf("make_join failed: %v", err) } // ... construct a signed join event ... - roomVer := makeJoinResp.RoomVersion - joinEvent, err := makeJoinResp.JoinEvent.Build(time.Now(), origin, srv.KeyID, srv.Priv, roomVer) + verImpl, err := gomatrixserverlib.GetRoomVersion(makeJoinResp.RoomVersion) + must.NotError(t, "JoinEvent.GetRoomVersion", err) + eb := verImpl.NewEventBuilderFromProtoEvent(&makeJoinResp.JoinEvent) + joinEvent, err := eb.Build(time.Now(), spec.ServerName(srv.ServerName()), srv.KeyID, srv.Priv) if err != nil { t.Fatalf("failed to sign join event: %v", err) } diff --git a/tests/federation_room_send_test.go b/tests/federation_room_send_test.go index fc4ed33a..f9993640 100644 --- a/tests/federation_room_send_test.go +++ b/tests/federation_room_send_test.go @@ -32,7 +32,7 @@ func TestOutboundFederationSend(t *testing.T) { federation.HandleMakeSendJoinRequests(), federation.HandleTransactionRequests( // listen for PDU events in transactions - func(ev *gomatrixserverlib.Event) { + func(ev gomatrixserverlib.PDU) { defer waiter.Finish() if ev.Type() != wantEventType { diff --git a/tests/federation_rooms_invite_test.go b/tests/federation_rooms_invite_test.go index 0bdd688d..e33c1b76 100644 --- a/tests/federation_rooms_invite_test.go +++ b/tests/federation_rooms_invite_test.go @@ -3,7 +3,7 @@ package tests import ( "testing" - "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/gomatrixserverlib/spec" "github.com/tidwall/gjson" "github.com/matrix-org/complement/internal/b" @@ -96,7 +96,7 @@ func TestFederationRoomsInvite(t *testing.T) { bob.MustSyncUntil(t, client.SyncReq{}, client.SyncTimelineHas(roomID, func(result gjson.Result) bool { // We expect a membership event .. - if result.Get("type").Str != gomatrixserverlib.MRoomMember { + if result.Get("type").Str != spec.MRoomMember { return false } // .. for Bob diff --git a/tests/knocking_test.go b/tests/knocking_test.go index e84f7ca8..fb1fd18a 100644 --- a/tests/knocking_test.go +++ b/tests/knocking_test.go @@ -57,7 +57,7 @@ func doTestKnocking(t *testing.T, roomVersion string, joinRule string) { inviteWaiter := NewWaiter() srv := federation.NewServer(t, deployment, federation.HandleKeyRequests(), - federation.HandleInviteRequests(func(ev *gomatrixserverlib.Event) { + federation.HandleInviteRequests(func(ev gomatrixserverlib.PDU) { inviteWaiter.Finish() }), federation.HandleTransactionRequests(nil, nil), @@ -146,7 +146,7 @@ func knockingBetweenTwoUsersTest(t *testing.T, roomID string, inRoomUser, knocki // wait for the membership to arrive over federation start := time.Now() knockerState := serverRoom.CurrentState("m.room.member", knockingUser.UserID) - for knockerState == nil && time.Since(start) < 5 * time.Second { + for knockerState == nil && time.Since(start) < 5*time.Second { time.Sleep(100 * time.Millisecond) knockerState = serverRoom.CurrentState("m.room.member", knockingUser.UserID) } From f67f3d74f53f1ec2d3093cfc67c971ff8c10bb47 Mon Sep 17 00:00:00 2001 From: Devon Hudson Date: Wed, 20 Sep 2023 19:18:05 -0600 Subject: [PATCH 02/10] Make gmsl updates work with synapse --- go.mod | 10 +- go.sum | 39 ++-- internal/federation/server.go | 9 + ...federation_room_join_partial_state_test.go | 167 ++++++++++-------- 4 files changed, 130 insertions(+), 95 deletions(-) diff --git a/go.mod b/go.mod index 15f11631..a15825c9 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,5 @@ module github.com/matrix-org/complement -replace github.com/matrix-org/gomatrixserverlib => ../../../gomatrixserverlib/main/ - go 1.16 require ( @@ -14,17 +12,17 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/gorilla/mux v1.8.0 github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 - github.com/matrix-org/gomatrixserverlib v0.0.0-20230113181222-67e060196d05 + github.com/matrix-org/gomatrixserverlib v0.0.0-20230921011113-50a984a43e59 github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect - github.com/sirupsen/logrus v1.9.0 - github.com/tidwall/gjson v1.14.4 + github.com/sirupsen/logrus v1.9.3 + github.com/tidwall/gjson v1.16.0 github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 - golang.org/x/crypto v0.5.0 // indirect + golang.org/x/crypto v0.13.0 // indirect golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 // indirect golang.org/x/image v0.5.0 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect diff --git a/go.sum b/go.sum index 0d64b652..b743947c 100644 --- a/go.sum +++ b/go.sum @@ -62,6 +62,7 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= @@ -77,10 +78,13 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230921011113-50a984a43e59 h1:m6CjtPbM91Z+HGjVOBN9rDytLP5dnOukey71y9wBzPE= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230921011113-50a984a43e59/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4/go.mod h1:vVQlW/emklohkZnOPwD3LrZUBqdfsbiyO3p1lNV8F6U= github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y= github.com/matrix-org/util v0.0.0-20221111132719-399730281e66/go.mod h1:iBI1foelCqA09JJgPV0FYz4qA5dUXYOxMi57FxKBdd4= github.com/mattn/go-sqlite3 v1.14.13/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 h1:yH0SvLzcbZxcJXho2yh7CqdENGMQe73Cw3woZBpPli0= github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= @@ -104,8 +108,9 @@ github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfF github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -119,8 +124,8 @@ github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vl github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= -github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg= +github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= @@ -143,8 +148,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -176,6 +181,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -188,15 +195,17 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220513224357-95641704303c/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220907140024-f12130a52804/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -220,21 +229,24 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -250,6 +262,8 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -269,6 +283,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY= gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0= gopkg.in/macaroon.v2 v2.1.0/go.mod h1:OUb+TQP/OP0WOerC2Jp/3CwhIKyIa9kQjuc7H24e6/o= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= diff --git a/internal/federation/server.go b/internal/federation/server.go index ece6a749..e9159253 100644 --- a/internal/federation/server.go +++ b/internal/federation/server.go @@ -633,3 +633,12 @@ func (f *basicKeyFetcher) FetchKeys( func (f *basicKeyFetcher) FetcherName() string { return "basicKeyFetcher" } + +// SupportedRoomVersions is a convenience method which returns a list of the room versions supported by gomatrixserverlib. +func SupportedRoomVersions() []gomatrixserverlib.RoomVersion { + supportedRoomVersions := make([]gomatrixserverlib.RoomVersion, 0, 10) + for v := range gomatrixserverlib.StableRoomVersions() { + supportedRoomVersions = append(supportedRoomVersions, v) + } + return supportedRoomVersions +} diff --git a/tests/federation_room_join_partial_state_test.go b/tests/federation_room_join_partial_state_test.go index 0562cea7..c3cbd36d 100644 --- a/tests/federation_room_join_partial_state_test.go +++ b/tests/federation_room_join_partial_state_test.go @@ -10,7 +10,6 @@ import ( "context" "encoding/json" "fmt" - "github.com/matrix-org/complement/runtime" "io/ioutil" "net" "net/http" @@ -21,11 +20,15 @@ import ( "testing" "time" + "github.com/matrix-org/complement/runtime" + "github.com/gorilla/mux" "github.com/tidwall/gjson" "github.com/matrix-org/gomatrix" "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/gomatrixserverlib/fclient" + "github.com/matrix-org/gomatrixserverlib/spec" "github.com/matrix-org/complement/internal/b" "github.com/matrix-org/complement/internal/client" @@ -38,7 +41,7 @@ import ( type server struct { *federation.Server - pduHandlers map[int]func(*gomatrixserverlib.Event) bool + pduHandlers map[int]func(gomatrixserverlib.PDU) bool eduHandlers map[int]func(gomatrixserverlib.EDU) bool nextPDUHandlerKey int @@ -53,7 +56,7 @@ func createTestServer(t *testing.T, deployment *docker.Deployment, opts ...func( t.Helper() server := &server{ - pduHandlers: map[int]func(*gomatrixserverlib.Event) bool{}, + pduHandlers: map[int]func(gomatrixserverlib.PDU) bool{}, eduHandlers: map[int]func(gomatrixserverlib.EDU) bool{}, nextPDUHandlerKey: 0, nextEDUHandlerKey: 0, @@ -65,7 +68,7 @@ func createTestServer(t *testing.T, deployment *docker.Deployment, opts ...func( federation.HandlePartialStateMakeSendJoinRequests(), federation.HandleEventRequests(), federation.HandleTransactionRequests( - func(e *gomatrixserverlib.Event) { + func(e gomatrixserverlib.PDU) { expected := false for _, pduHandler := range server.pduHandlers { expected = pduHandler(e) || expected @@ -98,7 +101,7 @@ func createTestServer(t *testing.T, deployment *docker.Deployment, opts ...func( // AddPDUHandler adds a PDU callback that returns `true` if it expected the given PDU. // When a PDU is received which is not expected by any PDU callback, the ongoing test is failed. // Returns a function to remove the PDU callback. -func (s *server) AddPDUHandler(pduHandler func(*gomatrixserverlib.Event) bool) func() { +func (s *server) AddPDUHandler(pduHandler func(gomatrixserverlib.PDU) bool) func() { pduHandlerKey := s.nextPDUHandlerKey s.nextPDUHandlerKey++ s.pduHandlers[pduHandlerKey] = pduHandler @@ -125,9 +128,9 @@ func (s *server) AddEDUHandler(eduHandler func(gomatrixserverlib.EDU) bool) func func (s *server) WithWaitForLeave( t *testing.T, room *federation.ServerRoom, userID string, leaveAction func(), ) { - leaveChannel := make(chan *gomatrixserverlib.Event, 10) + leaveChannel := make(chan gomatrixserverlib.PDU, 10) removePDUHandler := s.AddPDUHandler( - func(e *gomatrixserverlib.Event) bool { + func(e gomatrixserverlib.PDU) bool { if membership, _ := e.Membership(); e.Type() == "m.room.member" && *e.StateKey() == userID && membership == "leave" { @@ -164,7 +167,7 @@ func TestPartialStateJoin(t *testing.T) { createMembershipEvent := func( t *testing.T, signingServer *server, room *federation.ServerRoom, userId string, membership string, - ) *gomatrixserverlib.Event { + ) gomatrixserverlib.PDU { t.Helper() return signingServer.MustCreateEvent(t, room, b.Event{ @@ -180,7 +183,7 @@ func TestPartialStateJoin(t *testing.T) { // createJoinEvent creates a join event for the given user createJoinEvent := func( t *testing.T, signingServer *server, room *federation.ServerRoom, userId string, - ) *gomatrixserverlib.Event { + ) gomatrixserverlib.PDU { t.Helper() return createMembershipEvent(t, signingServer, room, userId, "join") @@ -189,7 +192,7 @@ func TestPartialStateJoin(t *testing.T) { // createLeaveEvent creates a leave event for the given user createLeaveEvent := func( t *testing.T, signingServer *server, room *federation.ServerRoom, userId string, - ) *gomatrixserverlib.Event { + ) gomatrixserverlib.PDU { t.Helper() return createMembershipEvent(t, signingServer, room, userId, "leave") @@ -300,7 +303,7 @@ func TestPartialStateJoin(t *testing.T) { ) t.Log("4. Have Alice send a message to the remote room.") - removePDUHandler := server.AddPDUHandler(func(*gomatrixserverlib.Event) bool { return true }) + removePDUHandler := server.AddPDUHandler(func(gomatrixserverlib.PDU) bool { return true }) defer removePDUHandler() messageId := alice.SendEventUnsynced(t, serverRoom.RoomID, b.Event{ Type: "m.room.message", @@ -463,9 +466,9 @@ func TestPartialStateJoin(t *testing.T) { psjResult := beginPartialStateJoin(t, server, serverRoom, alice) defer psjResult.Destroy(t) - pdusChannel := make(chan *gomatrixserverlib.Event) + pdusChannel := make(chan gomatrixserverlib.PDU) removePDUHandler := server.AddPDUHandler( - func(e *gomatrixserverlib.Event) bool { + func(e gomatrixserverlib.PDU) bool { pdusChannel <- e return true @@ -858,7 +861,7 @@ func TestPartialStateJoin(t *testing.T) { // the HS will make a /get_missing_events request for the missing prev events of event B handleGetMissingEventsRequests(t, server, serverRoom, - []string{eventB.EventID()}, []*gomatrixserverlib.Event{eventA}) + []string{eventB.EventID()}, []gomatrixserverlib.PDU{eventA}) // send event B to hs1 testReceiveEventDuringPartialStateJoin(t, deployment, alice, psjResult, eventB, syncToken) @@ -898,7 +901,7 @@ func TestPartialStateJoin(t *testing.T) { // the HS will make a /get_missing_events request for the missing prev event of event B handleGetMissingEventsRequests(t, server, serverRoom, - []string{eventB.EventID()}, []*gomatrixserverlib.Event{eventA}) + []string{eventB.EventID()}, []gomatrixserverlib.PDU{eventA}) // send event B to hs1 testReceiveEventDuringPartialStateJoin(t, deployment, alice, psjResult, eventB, syncToken) @@ -939,7 +942,7 @@ func TestPartialStateJoin(t *testing.T) { // the HS will make a /get_missing_events request for the missing prev event of event C, // to which we respond with event B only. handleGetMissingEventsRequests(t, server, serverRoom, - []string{eventC.EventID()}, []*gomatrixserverlib.Event{eventB}) + []string{eventC.EventID()}, []gomatrixserverlib.PDU{eventB}) // dedicated state_ids and state handlers for event A handleStateIdsRequests(t, server, serverRoom, eventA.EventID(), serverRoom.AllCurrentState(), nil, nil) @@ -981,10 +984,10 @@ func TestPartialStateJoin(t *testing.T) { ) err := client.SyncStateHas(serverRoom.RoomID, func(ev gjson.Result) bool { - return ev.Get("type").Str == "m.room.member" && ev.Get("state_key").Str == event.Sender() + return ev.Get("type").Str == "m.room.member" && ev.Get("state_key").Str == string(event.SenderID()) })(alice.UserID, syncRes) if err != nil { - t.Errorf("Did not find %s's m.room.member event in lazy-loading /sync response: %s", event.Sender(), err) + t.Errorf("Did not find %s's m.room.member event in lazy-loading /sync response: %s", event.SenderID(), err) } }) @@ -1051,10 +1054,10 @@ func TestPartialStateJoin(t *testing.T) { } err = client.SyncStateHas(serverRoom.RoomID, func(ev gjson.Result) bool { - return ev.Get("type").Str == "m.room.member" && ev.Get("state_key").Str == event2.Sender() + return ev.Get("type").Str == "m.room.member" && ev.Get("state_key").Str == string(event2.SenderID()) })(alice.UserID, syncRes) if err != nil { - t.Errorf("Did not find %s's m.room.member event in lazy-loading /sync response: %s", event2.Sender(), err) + t.Errorf("Did not find %s's m.room.member event in lazy-loading /sync response: %s", event2.SenderID(), err) } }) @@ -1099,10 +1102,10 @@ func TestPartialStateJoin(t *testing.T) { ) err := client.SyncStateHas(serverRoom.RoomID, func(ev gjson.Result) bool { - return ev.Get("type").Str == "m.room.member" && ev.Get("state_key").Str == event.Sender() + return ev.Get("type").Str == "m.room.member" && ev.Get("state_key").Str == string(event.SenderID()) })(alice.UserID, syncRes) if err != nil { - t.Errorf("Did not find %s's m.room.member event in lazy-loading /sync response: %s", event.Sender(), err) + t.Errorf("Did not find %s's m.room.member event in lazy-loading /sync response: %s", event.SenderID(), err) } }) @@ -1409,7 +1412,7 @@ func TestPartialStateJoin(t *testing.T) { // next, we want to create 100 outliers. So, charlie creates 100 state events, and // then persuades the system under test to create a backwards extremity using those events as // part of the room state. - outliers := make([]*gomatrixserverlib.Event, 100) + outliers := make([]gomatrixserverlib.PDU, 100) outlierEventIDs := make([]string, len(outliers)) for i := range outliers { body := fmt.Sprintf("outlier event %d", i) @@ -1432,7 +1435,7 @@ func TestPartialStateJoin(t *testing.T) { // dedicated get_missing_event handler for timelineEvent2. // we grudgingly return a single event. handleGetMissingEventsRequests(t, server, serverRoom, - []string{timelineEvent2.EventID()}, []*gomatrixserverlib.Event{timelineEvent1}, + []string{timelineEvent2.EventID()}, []gomatrixserverlib.PDU{timelineEvent1}, ) // dedicated state_ids and state handlers for timelineEvent1's prev event (ie, the last outlier event) @@ -1612,7 +1615,7 @@ func TestPartialStateJoin(t *testing.T) { Content: map[string]interface{}{ "body": "bad state event", }, - AuthEvents: serverRoom.EventIDsOrReferences([]*gomatrixserverlib.Event{ + AuthEvents: serverRoom.EventIDsOrReferences([]gomatrixserverlib.PDU{ serverRoom.CurrentState("m.room.create", ""), serverRoom.CurrentState("m.room.power_levels", ""), derekJoinEvent, @@ -1693,7 +1696,7 @@ func TestPartialStateJoin(t *testing.T) { StateKey: &elsie, Sender: derek, Content: map[string]interface{}{"membership": "leave"}, - AuthEvents: serverRoom.EventIDsOrReferences([]*gomatrixserverlib.Event{ + AuthEvents: serverRoom.EventIDsOrReferences([]gomatrixserverlib.PDU{ serverRoom.CurrentState("m.room.create", ""), serverRoom.CurrentState("m.room.power_levels", ""), derekJoinEvent, @@ -1713,7 +1716,7 @@ func TestPartialStateJoin(t *testing.T) { StateKey: b.Ptr(""), Sender: elsie, Content: map[string]interface{}{"body": "rejected state"}, - AuthEvents: serverRoom.EventIDsOrReferences([]*gomatrixserverlib.Event{ + AuthEvents: serverRoom.EventIDsOrReferences([]gomatrixserverlib.PDU{ serverRoom.CurrentState("m.room.create", ""), serverRoom.CurrentState("m.room.power_levels", ""), elsieJoinEvent, @@ -1793,7 +1796,7 @@ func TestPartialStateJoin(t *testing.T) { fedClient2 := testServer2.FederationClient(deployment) // charlie sends a make_join - _, err := fedClient2.MakeJoin(context.Background(), gomatrixserverlib.ServerName(testServer2.ServerName()), "hs1", roomID, testServer2.UserID("charlie"), federation.SupportedRoomVersions()) + _, err := fedClient2.MakeJoin(context.Background(), spec.ServerName(testServer2.ServerName()), "hs1", roomID, testServer2.UserID("charlie")) if err == nil { t.Errorf("MakeJoin returned 200, want 404") @@ -1855,12 +1858,17 @@ func TestPartialStateJoin(t *testing.T) { } // daniel then tries to /send_join via the homeserver under test - joinEvent, err := makeJoinResp.JoinEvent.Build(time.Now(), gomatrixserverlib.ServerName(testServer2.ServerName()), testServer2.KeyID, testServer2.Priv, makeJoinResp.RoomVersion) + verImpl, err := gomatrixserverlib.GetRoomVersion(serverRoom.Version) + if err != nil { + t.Fatalf("MakeRespMakeJoin: invalid room version: %s", err) + } + eb := verImpl.NewEventBuilderFromProtoEvent(&makeJoinResp.JoinEvent) + joinEvent, err := eb.Build(time.Now(), spec.ServerName(testServer2.ServerName()), testServer2.KeyID, testServer2.Priv) must.NotError(t, "JoinEvent.Build", err) // SendJoin should return a 404 because the homeserver under test has not // finished its partial join. - _, err = fedClient2.SendJoin(context.Background(), gomatrixserverlib.ServerName(testServer2.ServerName()), "hs1", joinEvent) + _, err = fedClient2.SendJoin(context.Background(), spec.ServerName(testServer2.ServerName()), "hs1", joinEvent) if err == nil { t.Errorf("SendJoin returned 200, want 404") } else if httpError, ok := err.(gomatrix.HTTPError); ok { @@ -1966,7 +1974,7 @@ func TestPartialStateJoin(t *testing.T) { fedClient2 := testServer2.FederationClient(deployment) // charlie sends a make_knock - _, err := fedClient2.MakeKnock(context.Background(), gomatrixserverlib.ServerName(testServer2.ServerName()), "hs1", roomID, testServer2.UserID("charlie"), federation.SupportedRoomVersions()) + _, err := fedClient2.MakeKnock(context.Background(), spec.ServerName(testServer2.ServerName()), "hs1", roomID, testServer2.UserID("charlie"), federation.SupportedRoomVersions()) if err == nil { t.Errorf("MakeKnock returned 200, want 404") @@ -2028,12 +2036,17 @@ func TestPartialStateJoin(t *testing.T) { } // daniel then tries to /send_knock via the homeserver under test - knockEvent, err := makeKnockResp.KnockEvent.Build(time.Now(), gomatrixserverlib.ServerName(testServer2.ServerName()), testServer2.KeyID, testServer2.Priv, makeKnockResp.RoomVersion) + verImpl, err := gomatrixserverlib.GetRoomVersion(serverRoom.Version) + if err != nil { + t.Fatalf("MakeRespMakeJoin: invalid room version: %s", err) + } + eb := verImpl.NewEventBuilderFromProtoEvent(&makeKnockResp.KnockEvent) + knockEvent, err := eb.Build(time.Now(), spec.ServerName(testServer2.ServerName()), testServer2.KeyID, testServer2.Priv) must.NotError(t, "KnockEvent.Build", err) // SendKnock should return a 404 because the homeserver under test has not // finished its partial join. - _, err = fedClient2.SendKnock(context.Background(), gomatrixserverlib.ServerName(testServer2.ServerName()), "hs1", knockEvent) + _, err = fedClient2.SendKnock(context.Background(), spec.ServerName(testServer2.ServerName()), "hs1", knockEvent) if err == nil { t.Errorf("SendKnock returned 200, want 404") } else if httpError, ok := err.(gomatrix.HTTPError); ok { @@ -2173,7 +2186,7 @@ func TestPartialStateJoin(t *testing.T) { server2Room := server2.MustJoinRoom( t, deployment, - gomatrixserverlib.ServerName(server1.ServerName()), + spec.ServerName(server1.ServerName()), room.RoomID, server2.UserID("elsie"), true, @@ -2221,7 +2234,7 @@ func TestPartialStateJoin(t *testing.T) { server2Room := server2.MustJoinRoom( t, deployment, - gomatrixserverlib.ServerName(server1.ServerName()), + spec.ServerName(server1.ServerName()), room.RoomID, server2.UserID("elsie"), true, @@ -2263,7 +2276,7 @@ func TestPartialStateJoin(t *testing.T) { server2.MustJoinRoom( t, deployment, - gomatrixserverlib.ServerName(server1.ServerName()), + spec.ServerName(server1.ServerName()), room.RoomID, server2.UserID("elsie"), true, @@ -2337,7 +2350,7 @@ func TestPartialStateJoin(t *testing.T) { server2Room = server2.MustJoinRoom( t, deployment, - gomatrixserverlib.ServerName(server1.ServerName()), + spec.ServerName(server1.ServerName()), room.RoomID, elsie, true, @@ -2358,7 +2371,7 @@ func TestPartialStateJoin(t *testing.T) { StateKey: b.Ptr(elsie), Sender: derek, Content: map[string]interface{}{"membership": "leave"}, - AuthEvents: room.EventIDsOrReferences([]*gomatrixserverlib.Event{ + AuthEvents: room.EventIDsOrReferences([]gomatrixserverlib.PDU{ room.CurrentState("m.room.create", ""), room.CurrentState("m.room.power_levels", ""), derekJoinEvent, @@ -2519,7 +2532,7 @@ func TestPartialStateJoin(t *testing.T) { server2Room := server2.MustJoinRoom( t, deployment, - gomatrixserverlib.ServerName(server1.ServerName()), + spec.ServerName(server1.ServerName()), room.RoomID, server2.UserID("elsie"), true, @@ -2550,7 +2563,7 @@ func TestPartialStateJoin(t *testing.T) { server2.MustJoinRoom( t, deployment, - gomatrixserverlib.ServerName(server1.ServerName()), + spec.ServerName(server1.ServerName()), room.RoomID, server2.UserID("elsie"), true, @@ -2591,17 +2604,17 @@ func TestPartialStateJoin(t *testing.T) { makeRespUserDeviceKeys := func( userID string, deviceID string, - ) gomatrixserverlib.RespUserDeviceKeys { - return gomatrixserverlib.RespUserDeviceKeys{ + ) fclient.RespUserDeviceKeys { + return fclient.RespUserDeviceKeys{ UserID: userID, DeviceID: deviceID, Algorithms: []string{ "m.megolm.v1.aes-sha2", }, - Keys: map[gomatrixserverlib.KeyID]gomatrixserverlib.Base64Bytes{ + Keys: map[gomatrixserverlib.KeyID]spec.Base64Bytes{ "ed25519:JLAFKJWSCS": []byte("lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI"), }, - Signatures: map[string]map[gomatrixserverlib.KeyID]gomatrixserverlib.Base64Bytes{ + Signatures: map[string]map[gomatrixserverlib.KeyID]spec.Base64Bytes{ userID: { "ed25519:JLAFKJWSCS": []byte("dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA"), }, @@ -2624,10 +2637,10 @@ func TestPartialStateJoin(t *testing.T) { userDevicesQueryChannel <- userID // Make up a device list for the user. - responseBytes, _ := json.Marshal(gomatrixserverlib.RespUserDevices{ + responseBytes, _ := json.Marshal(fclient.RespUserDevices{ UserID: userID, StreamID: lastDeviceStreamID, - Devices: []gomatrixserverlib.RespUserDevice{ + Devices: []fclient.RespUserDevice{ { DeviceID: deviceID, DisplayName: fmt.Sprintf("%s's device", userID), @@ -2658,19 +2671,19 @@ func TestPartialStateJoin(t *testing.T) { } // Make up keys for every device requested. - deviceKeys := make(map[string]map[string]gomatrixserverlib.DeviceKeys) + deviceKeys := make(map[string]map[string]fclient.DeviceKeys) for userID := range queryKeysRequest.DeviceKeys { userDevicesQueryChannel <- userID deviceID := fmt.Sprintf("%s_device", userID) - deviceKeys[userID] = map[string]gomatrixserverlib.DeviceKeys{ + deviceKeys[userID] = map[string]fclient.DeviceKeys{ deviceID: { RespUserDeviceKeys: makeRespUserDeviceKeys(userID, deviceID), }, } } - responseBytes, _ := json.Marshal(gomatrixserverlib.RespQueryKeys{ + responseBytes, _ := json.Marshal(fclient.RespQueryKeys{ DeviceKeys: deviceKeys, }) w.WriteHeader(200) @@ -3160,7 +3173,7 @@ func TestPartialStateJoin(t *testing.T) { StateKey: b.Ptr(derek), Sender: fred, Content: map[string]interface{}{"membership": "ban"}, - AuthEvents: room.EventIDsOrReferences([]*gomatrixserverlib.Event{ + AuthEvents: room.EventIDsOrReferences([]gomatrixserverlib.PDU{ room.CurrentState("m.room.create", ""), room.CurrentState("m.room.power_levels", ""), fredJoinEvent, @@ -3473,7 +3486,7 @@ func TestPartialStateJoin(t *testing.T) { psjResult := beginPartialStateJoin(t, server, serverRoom, alice) defer psjResult.Destroy(t) - server.AddPDUHandler(func(e *gomatrixserverlib.Event) bool { return true }) + server.AddPDUHandler(func(e gomatrixserverlib.PDU) bool { return true }) bob.JoinRoom(t, serverRoom.RoomID, []string{server.ServerName()}) alice.MustSyncUntil(t, client.SyncReq{ @@ -3505,9 +3518,9 @@ func TestPartialStateJoin(t *testing.T) { psjResult := beginPartialStateJoin(t, server, serverRoom, alice) defer psjResult.Destroy(t) - pdusChannel := make(chan *gomatrixserverlib.Event) + pdusChannel := make(chan gomatrixserverlib.PDU) removePDUHandler := server.AddPDUHandler( - func(e *gomatrixserverlib.Event) bool { + func(e gomatrixserverlib.PDU) bool { pdusChannel <- e return true @@ -3562,7 +3575,7 @@ func TestPartialStateJoin(t *testing.T) { leaveCompleted := NewWaiter() t.Log("Alice starts a leave request") - server.AddPDUHandler(func(e *gomatrixserverlib.Event) bool { return true }) + server.AddPDUHandler(func(e gomatrixserverlib.PDU) bool { return true }) go func() { alice.LeaveRoom(t, serverRoom.RoomID) t.Log("Alice's leave request completed") @@ -3605,9 +3618,9 @@ func TestPartialStateJoin(t *testing.T) { // Prepare to listen for leave events from the HS under test. // We're only expecting one leave event, but give the channel extra capacity // to avoid deadlock if the HS does something silly. - leavesChannel := make(chan *gomatrixserverlib.Event, 10) + leavesChannel := make(chan gomatrixserverlib.PDU, 10) server.AddPDUHandler( - func(e *gomatrixserverlib.Event) bool { + func(e gomatrixserverlib.PDU) bool { if e.Type() == "m.room.member" { if ok := gjson.ValidBytes(e.Content()); !ok { t.Fatalf("Received event %s with invalid content: %v", e.EventID(), e.Content()) @@ -3634,8 +3647,8 @@ func TestPartialStateJoin(t *testing.T) { case <-time.After(1 * time.Second): t.Fatal("Resident server did not receive Alice's leave") case e := <-leavesChannel: - if e.Sender() != alice.UserID { - t.Errorf("Unexpected leave event %s for %s", e.EventID(), e.Sender()) + if string(e.SenderID()) != alice.UserID { + t.Errorf("Unexpected leave event %s for %s", e.EventID(), e.SenderID()) } } }) @@ -3674,7 +3687,7 @@ func TestPartialStateJoin(t *testing.T) { ) t.Log("Alice leaves the room") - server.AddPDUHandler(func(e *gomatrixserverlib.Event) bool { return true }) + server.AddPDUHandler(func(e gomatrixserverlib.PDU) bool { return true }) alice.LeaveRoom(t, serverRoom.RoomID) t.Log("Alice sees Alice's leave") @@ -3711,7 +3724,7 @@ func TestPartialStateJoin(t *testing.T) { ) t.Log("Alice leaves the room") - server.AddPDUHandler(func(e *gomatrixserverlib.Event) bool { return true }) + server.AddPDUHandler(func(e gomatrixserverlib.PDU) bool { return true }) alice.LeaveRoom(t, serverRoom.RoomID) t.Log("Alice sees Alice's leave") @@ -3755,7 +3768,7 @@ func TestPartialStateJoin(t *testing.T) { ) t.Log("Alice leaves the room") - server.AddPDUHandler(func(e *gomatrixserverlib.Event) bool { return true }) + server.AddPDUHandler(func(e gomatrixserverlib.PDU) bool { return true }) alice.LeaveRoom(t, serverRoom.RoomID) t.Log("Alice sees Alice's leave") @@ -3801,7 +3814,7 @@ func TestPartialStateJoin(t *testing.T) { StateKey: b.Ptr(alice.UserID), Sender: server.UserID("charlie"), Content: map[string]interface{}{"membership": "leave"}, - AuthEvents: serverRoom.EventIDsOrReferences([]*gomatrixserverlib.Event{ + AuthEvents: serverRoom.EventIDsOrReferences([]gomatrixserverlib.PDU{ serverRoom.CurrentState("m.room.create", ""), serverRoom.CurrentState("m.room.power_levels", ""), serverRoom.CurrentState("m.room.member", alice.UserID), @@ -3853,7 +3866,7 @@ func TestPartialStateJoin(t *testing.T) { StateKey: b.Ptr(alice.UserID), Sender: server.UserID("charlie"), Content: map[string]interface{}{"membership": "ban"}, - AuthEvents: serverRoom.EventIDsOrReferences([]*gomatrixserverlib.Event{ + AuthEvents: serverRoom.EventIDsOrReferences([]gomatrixserverlib.PDU{ serverRoom.CurrentState("m.room.create", ""), serverRoom.CurrentState("m.room.power_levels", ""), serverRoom.CurrentState("m.room.member", alice.UserID), @@ -4038,7 +4051,7 @@ func TestPartialStateJoin(t *testing.T) { t.Log("Alice purges that room") // Ignore PDUs (leaves from shutting down the room). - server.AddPDUHandler(func(e *gomatrixserverlib.Event) bool { return true }) + server.AddPDUHandler(func(e gomatrixserverlib.PDU) bool { return true }) alice.MustDoFunc(t, "DELETE", []string{"_synapse", "admin", "v1", "rooms", serverRoom.RoomID}, client.WithJSONBody(t, map[string]interface{}{})) // Note: clients don't get told about purged rooms. No leave event for you! @@ -4077,7 +4090,7 @@ func TestPartialStateJoin(t *testing.T) { // sends the given event to the homeserver under test, checks that a client can see it and checks // the state at the event. returns the new sync token after the event. func testReceiveEventDuringPartialStateJoin( - t *testing.T, deployment *docker.Deployment, alice *client.CSAPI, psjResult partialStateJoinResult, event *gomatrixserverlib.Event, syncToken string, + t *testing.T, deployment *docker.Deployment, alice *client.CSAPI, psjResult partialStateJoinResult, event gomatrixserverlib.PDU, syncToken string, ) string { // send the event to the homeserver psjResult.Server.MustSendTransaction(t, deployment, "hs1", []json.RawMessage{event.JSON()}, nil) @@ -4093,13 +4106,13 @@ func testReceiveEventDuringPartialStateJoin( // is resolved. For now, we use this to check whether Synapse has calculated the partial state // flag for the last event correctly. - stateReq := gomatrixserverlib.NewFederationRequest("GET", gomatrixserverlib.ServerName(psjResult.Server.ServerName()), "hs1", + stateReq := fclient.NewFederationRequest("GET", spec.ServerName(psjResult.Server.ServerName()), "hs1", fmt.Sprintf("/_matrix/federation/v1/state_ids/%s?event_id=%s", url.PathEscape(psjResult.ServerRoom.RoomID), url.QueryEscape(event.EventID()), ), ) - var respStateIDs gomatrixserverlib.RespStateIDs + var respStateIDs fclient.RespStateIDs ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() err := psjResult.Server.SendFederationRequest(ctx, t, deployment, stateReq, &respStateIDs) @@ -4137,7 +4150,7 @@ func testReceiveEventDuringPartialStateJoin( ) // check the server's idea of the state at the event. We do this by making a `state_ids` request over federation - stateReq = gomatrixserverlib.NewFederationRequest("GET", gomatrixserverlib.ServerName(psjResult.Server.ServerName()), "hs1", + stateReq = fclient.NewFederationRequest("GET", spec.ServerName(psjResult.Server.ServerName()), "hs1", fmt.Sprintf("/_matrix/federation/v1/state_ids/%s?event_id=%s", url.PathEscape(psjResult.ServerRoom.RoomID), url.QueryEscape(event.EventID()), @@ -4329,7 +4342,7 @@ func (psj *partialStateJoinResult) Destroy(t *testing.T) { } // send a message into the room without letting the homeserver under test know about it. -func (psj *partialStateJoinResult) CreateMessageEvent(t *testing.T, senderLocalpart string, prevEventIDs []string) *gomatrixserverlib.Event { +func (psj *partialStateJoinResult) CreateMessageEvent(t *testing.T, senderLocalpart string, prevEventIDs []string) gomatrixserverlib.PDU { var prevEvents interface{} if prevEventIDs == nil { prevEvents = nil @@ -4368,7 +4381,7 @@ func (psj *partialStateJoinResult) FinishStateRequest() { // if sendResponseWaiter is not nil, we will Wait() for it to finish before sending the response. func handleStateIdsRequests( t *testing.T, srv *server, serverRoom *federation.ServerRoom, - eventID string, roomState []*gomatrixserverlib.Event, + eventID string, roomState []gomatrixserverlib.PDU, requestReceivedWaiter *Waiter, sendResponseWaiter *Waiter, ) { srv.Mux().NewRoute().Methods("GET").Path( @@ -4385,7 +4398,7 @@ func handleStateIdsRequests( } t.Logf("Replying to /state_ids request for event %s", queryParams["event_id"]) - res := gomatrixserverlib.RespStateIDs{ + res := fclient.RespStateIDs{ AuthEventIDs: eventIDsFromEvents(serverRoom.AuthChainForEvents(roomState)), StateEventIDs: eventIDsFromEvents(roomState), } @@ -4408,7 +4421,7 @@ func handleStateIdsRequests( // if sendResponseWaiter is not nil, we will Wait() for it to finish before sending the response. func handleStateRequests( t *testing.T, srv *server, serverRoom *federation.ServerRoom, - eventID string, roomState []*gomatrixserverlib.Event, + eventID string, roomState []gomatrixserverlib.PDU, requestReceivedWaiter *Waiter, sendResponseWaiter *Waiter, ) { srv.Mux().NewRoute().Methods("GET").Path( @@ -4426,7 +4439,7 @@ func handleStateRequests( t.Logf("Replying to /state request for event %s", queryParams["event_id"]) - res := gomatrixserverlib.RespState{ + res := fclient.RespState{ AuthEvents: gomatrixserverlib.NewEventJSONsFromEvents(serverRoom.AuthChainForEvents(roomState)), StateEvents: gomatrixserverlib.NewEventJSONsFromEvents(roomState), } @@ -4447,14 +4460,14 @@ func handleStateRequests( // must match those listed in "expectedLatestEvents" (otherwise the test is failed). func handleGetMissingEventsRequests( t *testing.T, srv *server, serverRoom *federation.ServerRoom, - expectedLatestEvents []string, eventsToReturn []*gomatrixserverlib.Event, + expectedLatestEvents []string, eventsToReturn []gomatrixserverlib.PDU, ) { srv.Mux().HandleFunc(fmt.Sprintf("/_matrix/federation/v1/get_missing_events/%s", serverRoom.RoomID), func(w http.ResponseWriter, req *http.Request) { body, err := ioutil.ReadAll(req.Body) if err != nil { t.Fatalf("unable to read /get_missing_events request body: %s", err) } - var getMissingEventsRequest gomatrixserverlib.MissingEvents + var getMissingEventsRequest fclient.MissingEvents err = json.Unmarshal(body, &getMissingEventsRequest) if err != nil { t.Fatalf("unable to unmarshall /get_missing_events request body: %s", err) @@ -4465,7 +4478,7 @@ func handleGetMissingEventsRequests( t.Fatalf("getMissingEventsRequest.LatestEvents: got %v, wanted %v", getMissingEventsRequest, expectedLatestEvents) } - responseBytes, _ := json.Marshal(gomatrixserverlib.RespMissingEvents{ + responseBytes, _ := json.Marshal(fclient.RespMissingEvents{ Events: gomatrixserverlib.NewEventJSONsFromEvents(eventsToReturn), }) w.WriteHeader(200) @@ -4473,7 +4486,7 @@ func handleGetMissingEventsRequests( }).Methods("POST") } -func eventIDsFromEvents(he []*gomatrixserverlib.Event) []string { +func eventIDsFromEvents(he []gomatrixserverlib.PDU) []string { eventIDs := make([]string, len(he)) for i := range he { eventIDs[i] = he[i].EventID() From 9cadaadc1fdad6a2d73b4dd3cb2b2655e08a713b Mon Sep 17 00:00:00 2001 From: Devon Hudson Date: Thu, 21 Sep 2023 11:09:38 -0600 Subject: [PATCH 03/10] Remove todo comment --- tests/direct_messaging_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/direct_messaging_test.go b/tests/direct_messaging_test.go index 6d1a7558..44b8b8af 100644 --- a/tests/direct_messaging_test.go +++ b/tests/direct_messaging_test.go @@ -134,7 +134,7 @@ func TestIsDirectFlagFederation(t *testing.T) { "membership": "invite", "is_direct": true, }, - }) // TODO: Used to call `.Headered(roomVer)` is that needed? + }) inviteReq, err := fclient.NewInviteV2Request(dmInviteEvent, []gomatrixserverlib.InviteStrippedState{}) if err != nil { t.Fatalf("failed to make invite request: %s", err) From 970af4a92ac9da3d5a1a34bd9a3c5761d9cc7fb9 Mon Sep 17 00:00:00 2001 From: Devon Hudson Date: Thu, 21 Sep 2023 11:12:57 -0600 Subject: [PATCH 04/10] Update gmsl to main --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a15825c9..ce52cfd6 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/gorilla/mux v1.8.0 github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 - github.com/matrix-org/gomatrixserverlib v0.0.0-20230921011113-50a984a43e59 + github.com/matrix-org/gomatrixserverlib v0.0.0-20230921171121-0466775328c7 github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect github.com/morikuni/aec v1.0.0 // indirect diff --git a/go.sum b/go.sum index b743947c..a3e2ea9b 100644 --- a/go.sum +++ b/go.sum @@ -78,8 +78,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230921011113-50a984a43e59 h1:m6CjtPbM91Z+HGjVOBN9rDytLP5dnOukey71y9wBzPE= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230921011113-50a984a43e59/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230921171121-0466775328c7 h1:NhPNNFLHwdDb/upeicBh1GkxX/sFinEp5HF1WBqPtiY= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230921171121-0466775328c7/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4/go.mod h1:vVQlW/emklohkZnOPwD3LrZUBqdfsbiyO3p1lNV8F6U= github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y= github.com/matrix-org/util v0.0.0-20221111132719-399730281e66/go.mod h1:iBI1foelCqA09JJgPV0FYz4qA5dUXYOxMi57FxKBdd4= From 911cfa5eef1c8e5865fb7e4480e6a84bd29684fe Mon Sep 17 00:00:00 2001 From: Devon Hudson Date: Mon, 25 Sep 2023 20:32:23 -0600 Subject: [PATCH 05/10] Small tweaks to work with pseudoIDs --- internal/federation/server.go | 44 ++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/internal/federation/server.go b/internal/federation/server.go index e9159253..c82827a7 100644 --- a/internal/federation/server.go +++ b/internal/federation/server.go @@ -23,6 +23,7 @@ import ( "github.com/matrix-org/gomatrix" "github.com/matrix-org/gomatrixserverlib/fclient" "github.com/matrix-org/gomatrixserverlib/spec" + "github.com/tidwall/sjson" "github.com/gorilla/mux" "github.com/matrix-org/gomatrixserverlib" @@ -361,17 +362,54 @@ func (s *Server) MustJoinRoom(t *testing.T, deployment *docker.Deployment, remot if err != nil { t.Fatalf("MustJoinRoom: invalid room version: %v", err) } + + var senderID spec.SenderID + signingKey := s.Priv + keyID := s.KeyID + origOrigin := origin + switch roomVer { + case gomatrixserverlib.RoomVersionPseudoIDs: + _, key, err := ed25519.GenerateKey(nil) + if err != nil { + t.Fatalf("MustJoinRoom: failed generating senderID: %v", err) + } + senderID, signingKey, err = spec.SenderIDFromPseudoIDKey(key), key, nil + keyID = "ed25519:1" + origin = spec.ServerName(senderID) + mapping := gomatrixserverlib.MXIDMapping{ + UserRoomKey: senderID, + UserID: userID, + } + if err = mapping.Sign(origOrigin, s.KeyID, s.Priv); err != nil { + t.Fatalf("MustJoinRoom: failed signing mxid_mapping: %v", err) + } + + path := "mxid_mapping" + eventJSON, err := sjson.SetBytes(makeJoinResp.JoinEvent.Content, path, mapping) + if err != nil { + t.Fatalf("MustJoinRoom: failed setting mxid_mapping in content: %v", err) + } + eventJSON = gomatrixserverlib.CanonicalJSONAssumeValid(eventJSON) + makeJoinResp.JoinEvent.Content = eventJSON + default: + senderID = spec.SenderID(userID) + } + + stateKey := string(senderID) + makeJoinResp.JoinEvent.SenderID = string(senderID) + makeJoinResp.JoinEvent.StateKey = &stateKey + eb := verImpl.NewEventBuilderFromProtoEvent(&makeJoinResp.JoinEvent) - joinEvent, err := eb.Build(time.Now(), origin, s.KeyID, s.Priv) + joinEvent, err := eb.Build(time.Now(), origin, keyID, signingKey) if err != nil { t.Fatalf("MustJoinRoom: failed to sign event: %v", err) } var sendJoinResp fclient.RespSendJoin if len(partialState) == 0 || !partialState[0] { // Default to doing a regular join. - sendJoinResp, err = fedClient.SendJoin(context.Background(), origin, remoteServer, joinEvent) + sendJoinResp, err = fedClient.SendJoin(context.Background(), origOrigin, remoteServer, joinEvent) } else { - sendJoinResp, err = fedClient.SendJoinPartialState(context.Background(), origin, remoteServer, joinEvent) + sendJoinResp, err = fedClient.SendJoinPartialState(context.Background(), origOrigin, remoteServer, joinEvent) } if err != nil { t.Fatalf("MustJoinRoom: send_join failed: %v", err) From 6cad09b8dbe6875f8309d83fdc3cbef8ccf0aa5e Mon Sep 17 00:00:00 2001 From: reivilibre Date: Wed, 27 Sep 2023 12:16:10 +0100 Subject: [PATCH 06/10] Add empty request bodies to /forget calls in TestRoomForget (#652) * Add empty request bodies to /forget calls * /join also needs an empty request body --- tests/csapi/apidoc_room_forget_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/csapi/apidoc_room_forget_test.go b/tests/csapi/apidoc_room_forget_test.go index 54f8837b..84aea63c 100644 --- a/tests/csapi/apidoc_room_forget_test.go +++ b/tests/csapi/apidoc_room_forget_test.go @@ -26,7 +26,7 @@ func TestRoomForget(t *testing.T) { t.Run("Can't forget room you're still in", func(t *testing.T) { t.Parallel() roomID := alice.CreateRoom(t, map[string]interface{}{"preset": "private_chat"}) - res := alice.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}) + res := alice.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusBadRequest, JSON: []match.JSON{ @@ -47,7 +47,7 @@ func TestRoomForget(t *testing.T) { }, }) alice.LeaveRoom(t, roomID) - alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}) + alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) res := alice.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusForbidden, @@ -71,7 +71,7 @@ func TestRoomForget(t *testing.T) { alice.LeaveRoom(t, roomID) // Ensure Alice left the room bob.MustSyncUntil(t, client.SyncReq{}, client.SyncLeftFrom(alice.UserID, roomID)) - alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}) + alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) bob.SendEventSynced(t, roomID, b.Event{ Type: "m.room.message", Content: map[string]interface{}{ @@ -117,7 +117,7 @@ func TestRoomForget(t *testing.T) { alice.LeaveRoom(t, roomID) // Ensure Alice left the room bob.MustSyncUntil(t, client.SyncReq{}, client.SyncLeftFrom(alice.UserID, roomID)) - alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}) + alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) bob.SendEventSynced(t, roomID, b.Event{ Type: "m.room.message", Content: map[string]interface{}{ @@ -197,9 +197,9 @@ func TestRoomForget(t *testing.T) { bob.LeaveRoom(t, roomID) // Ensure Bob has really left the room alice.MustSyncUntil(t, client.SyncReq{}, client.SyncLeftFrom(bob.UserID, roomID)) - bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}) + bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) // Try to re-join - joinRes := bob.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "join", roomID}) + joinRes := bob.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "join", roomID}, client.WithJSONBody(t, struct{}{})) must.MatchResponse(t, joinRes, match.HTTPResponse{ StatusCode: http.StatusForbidden, JSON: []match.JSON{ @@ -251,11 +251,11 @@ func TestRoomForget(t *testing.T) { // Bob rejects the invite bob.LeaveRoom(t, roomID) // Bob tries to forget about this room - bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}) + bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) // Alice also leaves the room alice.LeaveRoom(t, roomID) // Alice tries to forget about this room - alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}) + alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) }) }) } From e7227482f36cc6965d6a288eabf9e97719691de0 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Fri, 29 Sep 2023 12:20:08 +0100 Subject: [PATCH 07/10] Drop attachment requirements for media download (#646) Chooses whether to use an inline or attachment Content-Disposition header based on the type of media being downloaded. --- internal/data/data.go | 3 ++ internal/data/matrix-logo.svg | 18 +++++++++ tests/media_filename_test.go | 76 ++++++++++++++++++++++++++--------- 3 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 internal/data/matrix-logo.svg diff --git a/internal/data/data.go b/internal/data/data.go index c4455d2c..586c5c49 100644 --- a/internal/data/data.go +++ b/internal/data/data.go @@ -7,3 +7,6 @@ var MatrixPng []byte //go:embed large.png var LargePng []byte + +//go:embed matrix-logo.svg +var MatrixSvg []byte diff --git a/internal/data/matrix-logo.svg b/internal/data/matrix-logo.svg new file mode 100644 index 00000000..900a5aa0 --- /dev/null +++ b/internal/data/matrix-logo.svg @@ -0,0 +1,18 @@ + + + + matrix logo white + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/media_filename_test.go b/tests/media_filename_test.go index 637c996f..c1138a79 100644 --- a/tests/media_filename_test.go +++ b/tests/media_filename_test.go @@ -8,6 +8,7 @@ import ( "github.com/matrix-org/complement/internal/b" "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/data" + "github.com/matrix-org/complement/runtime" ) const asciiFileName = "ascii" @@ -43,8 +44,9 @@ func TestMediaFilenames(t *testing.T) { mxcUri := alice.UploadContent(t, data.MatrixPng, filename, "image/png") - name := downloadForFilename(t, alice, mxcUri, "") + name, _ := downloadForFilename(t, alice, mxcUri, "") + // filename is not required, but if it's an attachment then check it matches if name != filename { t.Fatalf("Incorrect filename '%s', expected '%s'", name, filename) } @@ -55,10 +57,11 @@ func TestMediaFilenames(t *testing.T) { t.Run("Can download specifying a different ASCII file name", func(t *testing.T) { t.Parallel() - mxcUri := alice.UploadContent(t, data.MatrixPng, "test.png", "image/png") + mxcUri := alice.UploadContent(t, data.MatrixPng, asciiFileName, "image/png") const altName = "file.png" - filename := downloadForFilename(t, alice, mxcUri, altName) + filename, _ := downloadForFilename(t, alice, mxcUri, altName) + if filename != altName { t.Fatalf("filename did not match, expected '%s', got '%s'", altName, filename) } @@ -83,7 +86,8 @@ func TestMediaFilenames(t *testing.T) { const diffUnicodeFilename = "\u2615" // coffee emoji - filename := downloadForFilename(t, alice, mxcUri, diffUnicodeFilename) + filename, _ := downloadForFilename(t, alice, mxcUri, diffUnicodeFilename) + if filename != diffUnicodeFilename { t.Fatalf("filename did not match, expected '%s', got '%s'", diffUnicodeFilename, filename) } @@ -95,7 +99,7 @@ func TestMediaFilenames(t *testing.T) { mxcUri := alice.UploadContent(t, data.MatrixPng, unicodeFileName, "image/png") - filename := downloadForFilename(t, alice, mxcUri, "") + filename, _ := downloadForFilename(t, alice, mxcUri, "") if filename != unicodeFileName { t.Fatalf("filename did not match, expected '%s', got '%s'", unicodeFileName, filename) @@ -108,18 +112,54 @@ func TestMediaFilenames(t *testing.T) { mxcUri := alice.UploadContent(t, data.MatrixPng, unicodeFileName, "image/png") - filename := downloadForFilename(t, bob, mxcUri, "") + filename, _ := downloadForFilename(t, bob, mxcUri, "") if filename != unicodeFileName { t.Fatalf("filename did not match, expected '%s', got '%s'", unicodeFileName, filename) } }) + + t.Run("Will serve safe media types as inline", func(t *testing.T) { + if runtime.Homeserver != runtime.Synapse { + // We need to check that this security behaviour is being correctly run in + // Synapse, but since this is not part of the Matrix spec we do not assume + // other homeservers are doing so. + t.Skip("Skipping test of Content-Disposition header requirements on non-Synapse homeserver") + } + t.Parallel() + + mxcUri := alice.UploadContent(t, data.MatrixPng, "", "image/png") + + _, isAttachment := downloadForFilename(t, bob, mxcUri, "") + + if isAttachment { + t.Fatal("Expected file to be served as inline") + } + }) + + t.Run("Will serve unsafe media types as attachments", func(t *testing.T) { + if runtime.Homeserver != runtime.Synapse { + // We need to check that this security behaviour is being correctly run in + // Synapse, but since this is not part of the Matrix spec we do not assume + // other homeservers are doing so. + t.Skip("Skipping test of Content-Disposition header requirements on non-Synapse homeserver") + } + t.Parallel() + + mxcUri := alice.UploadContent(t, data.MatrixSvg, "", "image/svg") + + _, isAttachment := downloadForFilename(t, bob, mxcUri, "") + + if !isAttachment { + t.Fatal("Expected file to be served as an attachment") + } + }) }) }) } -// Returns content disposition information like (mediatype, filename) -func downloadForFilename(t *testing.T, c *client.CSAPI, mxcUri string, diffName string) string { +// Returns content disposition information like (filename, isAttachment) +func downloadForFilename(t *testing.T, c *client.CSAPI, mxcUri string, diffName string) (filename string, isAttachment bool) { t.Helper() origin, mediaId := client.SplitMxc(mxcUri) @@ -138,16 +178,16 @@ func downloadForFilename(t *testing.T, c *client.CSAPI, mxcUri string, diffName if err != nil { t.Fatalf("Got err when parsing content disposition: %s", err) } - - if mediaType != "attachment" { - t.Fatalf("Found unexpected mediatype %s, expected attachment", mediaType) + filename, hasFilename := params["filename"] + if mediaType == "attachment" { + if hasFilename { + return filename, true + } else { + return "", true + } } - - if filename, ok := params["filename"]; ok { - return filename - } else { - t.Fatalf("Content Disposition did not have filename") - - return "" + if mediaType != "inline" { + t.Fatalf("Found unexpected mediatype %s, expected 'attachment' or 'inline'", mediaType) } + return filename, false } From 67a1cceb5a46375dd0ae9089f76065acd3d45ec6 Mon Sep 17 00:00:00 2001 From: kegsay Date: Wed, 4 Oct 2023 15:12:02 +0100 Subject: [PATCH 08/10] Client refactor (#658) * refactor: make client public and rename/reshuffle functions - Remove `Func` from `MustDoFunc` and `DoFunc`. They were called that to differentiate from the old-style `Do` and `MustDo` which are no more. - Move sync functions to a new file. - Move registration/login functions to a new file. - Move `/internal/client` to `/client`. * Add TestLike interface for using the client without a testing.T Also fix bad merge conflict * Add GenerateOneTimeKeys, Prefix Unsafe_ to unsafe functions * Add dedicated federation.Event Fixes #381 * Unbreak partial state test * Only fail the test if the Sender is different * Update build tag tests * Prefer GetJSONFieldStr as it does more validation * Review comments --- client/auth.go | 163 +++ client/client.go | 647 ++++++++++ client/sync.go | 391 ++++++ internal/b/blueprints.go | 18 - internal/client/client.go | 1117 ----------------- internal/docker/deployment.go | 2 +- internal/federation/server.go | 7 +- internal/federation/server_room.go | 22 +- .../account_change_password_pushers_test.go | 10 +- tests/csapi/account_change_password_test.go | 18 +- tests/csapi/account_deactivate_test.go | 8 +- tests/csapi/admin_test.go | 10 +- tests/csapi/apidoc_device_management_test.go | 36 +- tests/csapi/apidoc_login_test.go | 18 +- tests/csapi/apidoc_logout_test.go | 20 +- tests/csapi/apidoc_presence_test.go | 13 +- tests/csapi/apidoc_profile_avatar_url_test.go | 6 +- .../csapi/apidoc_profile_displayname_test.go | 6 +- tests/csapi/apidoc_register_test.go | 38 +- tests/csapi/apidoc_request_encoding_test.go | 4 +- tests/csapi/apidoc_room_alias_test.go | 14 +- tests/csapi/apidoc_room_create_test.go | 10 +- tests/csapi/apidoc_room_forget_test.go | 26 +- .../apidoc_room_history_visibility_test.go | 4 +- tests/csapi/apidoc_room_members_test.go | 26 +- tests/csapi/apidoc_room_receipts_test.go | 6 +- tests/csapi/apidoc_room_state_test.go | 34 +- tests/csapi/apidoc_search_test.go | 20 +- .../csapi/apidoc_server_capabilities_test.go | 2 +- tests/csapi/apidoc_version_test.go | 2 +- tests/csapi/device_lists_test.go | 6 +- tests/csapi/e2e_key_backup_test.go | 16 +- tests/csapi/ignored_users_test.go | 10 +- tests/csapi/invalid_test.go | 12 +- tests/csapi/keychanges_test.go | 12 +- tests/csapi/media_misc_test.go | 6 +- tests/csapi/power_levels_test.go | 10 +- tests/csapi/push_test.go | 10 +- tests/csapi/room_ban_test.go | 4 +- tests/csapi/room_kick_test.go | 6 +- tests/csapi/room_leave_test.go | 16 +- tests/csapi/room_members_test.go | 12 +- .../room_messages_relation_filter_test.go | 20 +- tests/csapi/room_messages_test.go | 28 +- tests/csapi/room_profile_test.go | 4 +- tests/csapi/room_relations_test.go | 42 +- tests/csapi/room_threads_test.go | 16 +- tests/csapi/room_typing_test.go | 8 +- tests/csapi/rooms_invite_test.go | 12 +- tests/csapi/rooms_members_local_test.go | 4 +- tests/csapi/rooms_state_test.go | 4 +- tests/csapi/sync_archive_test.go | 8 +- tests/csapi/sync_filter_test.go | 6 +- tests/csapi/sync_test.go | 15 +- tests/csapi/thread_notifications_test.go | 10 +- tests/csapi/to_device_test.go | 2 +- tests/csapi/txnid_test.go | 81 +- tests/csapi/upload_keys_test.go | 70 +- tests/csapi/url_preview_test.go | 4 +- .../user_directory_display_names_test.go | 18 +- tests/csapi/user_query_keys_test.go | 4 +- tests/direct_messaging_test.go | 4 +- tests/federation_acl_test.go | 4 +- tests/federation_presence_test.go | 6 +- tests/federation_query_profile_test.go | 6 +- tests/federation_redaction_test.go | 19 +- tests/federation_room_alias_test.go | 6 +- tests/federation_room_ban_test.go | 6 +- tests/federation_room_event_auth_test.go | 18 +- ...federation_room_get_missing_events_test.go | 10 +- ...federation_room_join_partial_state_test.go | 88 +- tests/federation_room_join_test.go | 24 +- tests/federation_room_typing_test.go | 4 +- tests/federation_rooms_invite_test.go | 4 +- tests/federation_unreject_rejected_test.go | 12 +- tests/federation_upload_keys_test.go | 64 +- tests/knocking_test.go | 20 +- tests/media_filename_test.go | 4 +- tests/media_thumbnail_test.go | 4 +- tests/msc2836_test.go | 48 +- tests/msc3391_test.go | 10 +- tests/msc3890_test.go | 10 +- tests/restricted_room_hierarchy_test.go | 4 +- tests/restricted_rooms_test.go | 6 +- tests/room_hierarchy_test.go | 22 +- tests/room_timestamp_to_event_test.go | 18 +- tests/unknown_endpoints_test.go | 6 +- 87 files changed, 1799 insertions(+), 1802 deletions(-) create mode 100644 client/auth.go create mode 100644 client/client.go create mode 100644 client/sync.go delete mode 100644 internal/client/client.go diff --git a/client/auth.go b/client/auth.go new file mode 100644 index 00000000..c469166b --- /dev/null +++ b/client/auth.go @@ -0,0 +1,163 @@ +package client + +import ( + "crypto/hmac" + "crypto/sha1" + "encoding/hex" + "io" + + "github.com/tidwall/gjson" +) + +const ( + SharedSecret = "complement" +) + +type LoginOpt func(map[string]interface{}) + +func WithDeviceID(deviceID string) LoginOpt { + return func(loginBody map[string]interface{}) { + loginBody["device_id"] = deviceID + } +} + +// LoginUser will log in to a homeserver and create a new device on an existing user. +func (c *CSAPI) LoginUser(t TestLike, localpart, password string, opts ...LoginOpt) (userID, accessToken, deviceID string) { + t.Helper() + reqBody := map[string]interface{}{ + "identifier": map[string]interface{}{ + "type": "m.id.user", + "user": localpart, + }, + "password": password, + "type": "m.login.password", + } + + for _, opt := range opts { + opt(reqBody) + } + + res := c.MustDo(t, "POST", []string{"_matrix", "client", "v3", "login"}, WithJSONBody(t, reqBody)) + + body, err := io.ReadAll(res.Body) + if err != nil { + t.Fatalf("unable to read response body: %v", err) + } + + userID = GetJSONFieldStr(t, body, "user_id") + accessToken = GetJSONFieldStr(t, body, "access_token") + deviceID = GetJSONFieldStr(t, body, "device_id") + return userID, accessToken, deviceID +} + +// LoginUserWithRefreshToken will log in to a homeserver, with refresh token enabled, +// and create a new device on an existing user. +func (c *CSAPI) LoginUserWithRefreshToken(t TestLike, localpart, password string) (userID, accessToken, refreshToken, deviceID string, expiresInMs int64) { + t.Helper() + reqBody := map[string]interface{}{ + "identifier": map[string]interface{}{ + "type": "m.id.user", + "user": localpart, + }, + "password": password, + "type": "m.login.password", + "refresh_token": true, + } + res := c.MustDo(t, "POST", []string{"_matrix", "client", "v3", "login"}, WithJSONBody(t, reqBody)) + + body, err := io.ReadAll(res.Body) + if err != nil { + t.Fatalf("unable to read response body: %v", err) + } + + userID = GetJSONFieldStr(t, body, "user_id") + accessToken = GetJSONFieldStr(t, body, "access_token") + deviceID = GetJSONFieldStr(t, body, "device_id") + refreshToken = GetJSONFieldStr(t, body, "refresh_token") + expiresInMs = gjson.GetBytes(body, "expires_in_ms").Int() + return userID, accessToken, refreshToken, deviceID, expiresInMs +} + +// RefreshToken will consume a refresh token and return a new access token and refresh token. +func (c *CSAPI) ConsumeRefreshToken(t TestLike, refreshToken string) (newAccessToken, newRefreshToken string, expiresInMs int64) { + t.Helper() + reqBody := map[string]interface{}{ + "refresh_token": refreshToken, + } + res := c.MustDo(t, "POST", []string{"_matrix", "client", "v3", "refresh"}, WithJSONBody(t, reqBody)) + + body, err := io.ReadAll(res.Body) + if err != nil { + t.Fatalf("unable to read response body: %v", err) + } + + newAccessToken = GetJSONFieldStr(t, body, "access_token") + newRefreshToken = GetJSONFieldStr(t, body, "refresh_token") + expiresInMs = gjson.GetBytes(body, "expires_in_ms").Int() + return newAccessToken, newRefreshToken, expiresInMs +} + +// RegisterUser will register the user with given parameters and +// return user ID, access token and device ID. It fails the test on network error. +func (c *CSAPI) RegisterUser(t TestLike, localpart, password string) (userID, accessToken, deviceID string) { + t.Helper() + reqBody := map[string]interface{}{ + "auth": map[string]string{ + "type": "m.login.dummy", + }, + "username": localpart, + "password": password, + } + res := c.MustDo(t, "POST", []string{"_matrix", "client", "v3", "register"}, WithJSONBody(t, reqBody)) + + body, err := io.ReadAll(res.Body) + if err != nil { + t.Fatalf("unable to read response body: %v", err) + } + + userID = GetJSONFieldStr(t, body, "user_id") + accessToken = GetJSONFieldStr(t, body, "access_token") + deviceID = GetJSONFieldStr(t, body, "device_id") + return userID, accessToken, deviceID +} + +// RegisterSharedSecret registers a new account with a shared secret via HMAC +// See https://github.com/matrix-org/synapse/blob/e550ab17adc8dd3c48daf7fedcd09418a73f524b/synapse/_scripts/register_new_matrix_user.py#L40 +func (c *CSAPI) RegisterSharedSecret(t TestLike, user, pass string, isAdmin bool) (userID, accessToken, deviceID string) { + resp := c.Do(t, "GET", []string{"_synapse", "admin", "v1", "register"}) + if resp.StatusCode != 200 { + t.Skipf("Homeserver image does not support shared secret registration, /_synapse/admin/v1/register returned HTTP %d", resp.StatusCode) + return + } + body := ParseJSON(t, resp) + nonce := gjson.GetBytes(body, "nonce") + if !nonce.Exists() { + t.Fatalf("Malformed shared secret GET response: %s", string(body)) + } + mac := hmac.New(sha1.New, []byte(SharedSecret)) + mac.Write([]byte(nonce.Str)) + mac.Write([]byte("\x00")) + mac.Write([]byte(user)) + mac.Write([]byte("\x00")) + mac.Write([]byte(pass)) + mac.Write([]byte("\x00")) + if isAdmin { + mac.Write([]byte("admin")) + } else { + mac.Write([]byte("notadmin")) + } + sig := mac.Sum(nil) + reqBody := map[string]interface{}{ + "nonce": nonce.Str, + "username": user, + "password": pass, + "mac": hex.EncodeToString(sig), + "admin": isAdmin, + } + resp = c.MustDo(t, "POST", []string{"_synapse", "admin", "v1", "register"}, WithJSONBody(t, reqBody)) + body = ParseJSON(t, resp) + userID = GetJSONFieldStr(t, body, "user_id") + accessToken = GetJSONFieldStr(t, body, "access_token") + deviceID = GetJSONFieldStr(t, body, "device_id") + return userID, accessToken, deviceID +} diff --git a/client/client.go b/client/client.go new file mode 100644 index 00000000..20b2fdf6 --- /dev/null +++ b/client/client.go @@ -0,0 +1,647 @@ +package client + +import ( + "bytes" + "context" // nolint:gosec + "encoding/json" + "fmt" + "io" + "net/http" + "net/http/httputil" + "net/url" + "strconv" + "strings" + "sync/atomic" + "time" + + "github.com/matrix-org/gomatrixserverlib" + "github.com/tidwall/gjson" + "maunium.net/go/mautrix/crypto/olm" + + "github.com/matrix-org/complement/internal/b" +) + +// TestLike is an interface that testing.T satisfies. All client functions accept a TestLike interface, +// with the intention of a `testing.T` being passed into them. However, the client may be used in non-test +// scenarios e.g benchmarks, which can then use the same client by just implementing this interface. +type TestLike interface { + Helper() + Logf(msg string, args ...interface{}) + Skipf(msg string, args ...interface{}) + Error(args ...interface{}) + Errorf(msg string, args ...interface{}) + Fatalf(msg string, args ...interface{}) +} + +type ctxKey string + +const ( + CtxKeyWithRetryUntil ctxKey = "complement_retry_until" // contains *retryUntilParams +) + +type retryUntilParams struct { + timeout time.Duration + untilFn func(*http.Response) bool +} + +// RequestOpt is a functional option which will modify an outgoing HTTP request. +// See functions starting with `With...` in this package for more info. +type RequestOpt func(req *http.Request) + +type CSAPI struct { + UserID string + AccessToken string + DeviceID string + BaseURL string + Client *http.Client + // how long are we willing to wait for MustSyncUntil.... calls + SyncUntilTimeout time.Duration + // True to enable verbose logging + Debug bool + + txnID int64 +} + +// UploadContent uploads the provided content with an optional file name. Fails the test on error. Returns the MXC URI. +func (c *CSAPI) UploadContent(t TestLike, fileBody []byte, fileName string, contentType string) string { + t.Helper() + query := url.Values{} + if fileName != "" { + query.Set("filename", fileName) + } + res := c.MustDo( + t, "POST", []string{"_matrix", "media", "v3", "upload"}, + WithRawBody(fileBody), WithContentType(contentType), WithQueries(query), + ) + body := ParseJSON(t, res) + return GetJSONFieldStr(t, body, "content_uri") +} + +// DownloadContent downloads media from the server, returning the raw bytes and the Content-Type. Fails the test on error. +func (c *CSAPI) DownloadContent(t TestLike, mxcUri string) ([]byte, string) { + t.Helper() + origin, mediaId := SplitMxc(mxcUri) + res := c.MustDo(t, "GET", []string{"_matrix", "media", "v3", "download", origin, mediaId}) + contentType := res.Header.Get("Content-Type") + b, err := io.ReadAll(res.Body) + if err != nil { + t.Error(err) + } + return b, contentType +} + +// CreateRoom creates a room with an optional HTTP request body. Fails the test on error. Returns the room ID. +func (c *CSAPI) CreateRoom(t TestLike, creationContent interface{}) string { + t.Helper() + res := c.MustDo(t, "POST", []string{"_matrix", "client", "v3", "createRoom"}, WithJSONBody(t, creationContent)) + body := ParseJSON(t, res) + return GetJSONFieldStr(t, body, "room_id") +} + +// JoinRoom joins the room ID or alias given, else fails the test. Returns the room ID. +func (c *CSAPI) JoinRoom(t TestLike, roomIDOrAlias string, serverNames []string) string { + t.Helper() + // construct URL query parameters + query := make(url.Values, len(serverNames)) + for _, serverName := range serverNames { + query.Add("server_name", serverName) + } + // join the room + res := c.MustDo( + t, "POST", []string{"_matrix", "client", "v3", "join", roomIDOrAlias}, + WithQueries(query), WithJSONBody(t, map[string]interface{}{}), + ) + // return the room ID if we joined with it + if roomIDOrAlias[0] == '!' { + return roomIDOrAlias + } + // otherwise we should be told the room ID if we joined via an alias + body := ParseJSON(t, res) + return GetJSONFieldStr(t, body, "room_id") +} + +// LeaveRoom leaves the room ID, else fails the test. +func (c *CSAPI) LeaveRoom(t TestLike, roomID string) { + t.Helper() + // leave the room + body := map[string]interface{}{} + c.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "leave"}, WithJSONBody(t, body)) +} + +// InviteRoom invites userID to the room ID, else fails the test. +func (c *CSAPI) InviteRoom(t TestLike, roomID string, userID string) { + t.Helper() + // Invite the user to the room + body := map[string]interface{}{ + "user_id": userID, + } + c.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "invite"}, WithJSONBody(t, body)) +} + +func (c *CSAPI) GetGlobalAccountData(t TestLike, eventType string) *http.Response { + return c.MustDo(t, "GET", []string{"_matrix", "client", "v3", "user", c.UserID, "account_data", eventType}) +} + +func (c *CSAPI) SetGlobalAccountData(t TestLike, eventType string, content map[string]interface{}) *http.Response { + return c.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "user", c.UserID, "account_data", eventType}, WithJSONBody(t, content)) +} + +func (c *CSAPI) GetRoomAccountData(t TestLike, roomID string, eventType string) *http.Response { + return c.MustDo(t, "GET", []string{"_matrix", "client", "v3", "user", c.UserID, "rooms", roomID, "account_data", eventType}) +} + +func (c *CSAPI) SetRoomAccountData(t TestLike, roomID string, eventType string, content map[string]interface{}) *http.Response { + return c.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "user", c.UserID, "rooms", roomID, "account_data", eventType}, WithJSONBody(t, content)) +} + +// GetAllPushRules fetches all configured push rules for a user from the homeserver. +// Push rules are returned as a parsed gjson result +// +// Example of printing the IDs of all underride rules of the current user: +// +// allPushRules := c.GetAllPushRules(t) +// globalUnderridePushRules := allPushRules.Get("global").Get("underride").Array() +// +// for index, rule := range globalUnderridePushRules { +// fmt.Printf("This rule's ID is: %s\n", rule.Get("rule_id").Str) +// } +// +// Push rules are returned in the same order received from the homeserver. +func (c *CSAPI) GetAllPushRules(t TestLike) gjson.Result { + t.Helper() + + // We have to supply an empty string to the end of this path in order to generate a trailing slash. + // See https://github.com/matrix-org/matrix-spec/issues/457 + res := c.MustDo(t, "GET", []string{"_matrix", "client", "v3", "pushrules", ""}) + pushRulesBytes := ParseJSON(t, res) + return gjson.ParseBytes(pushRulesBytes) +} + +// GetPushRule queries the contents of a client's push rule by scope, kind and rule ID. +// A parsed gjson result is returned. Fails the test if the query to server returns a non-2xx status code. +// +// Example of checking that a global underride rule contains the expected actions: +// +// containsDisplayNameRule := c.GetPushRule(t, "global", "underride", ".m.rule.contains_display_name") +// must.MatchGJSON( +// t, +// containsDisplayNameRule, +// match.JSONKeyEqual("actions", []interface{}{ +// "notify", +// map[string]interface{}{"set_tweak": "sound", "value": "default"}, +// map[string]interface{}{"set_tweak": "highlight"}, +// }), +// ) +func (c *CSAPI) GetPushRule(t TestLike, scope string, kind string, ruleID string) gjson.Result { + t.Helper() + + res := c.MustDo(t, "GET", []string{"_matrix", "client", "v3", "pushrules", scope, kind, ruleID}) + pushRuleBytes := ParseJSON(t, res) + return gjson.ParseBytes(pushRuleBytes) +} + +// SetPushRule creates a new push rule on the user, or modifies an existing one. +// If `before` or `after` parameters are not set to an empty string, their values +// will be set as the `before` and `after` query parameters respectively on the +// "set push rules" client endpoint: +// https://spec.matrix.org/v1.5/client-server-api/#put_matrixclientv3pushrulesscopekindruleid +// +// Example of setting a push rule with ID 'com.example.rule2' that must come after 'com.example.rule1': +// +// c.SetPushRule(t, "global", "underride", "com.example.rule2", map[string]interface{}{ +// "actions": []string{"dont_notify"}, +// }, nil, "com.example.rule1") +func (c *CSAPI) SetPushRule(t TestLike, scope string, kind string, ruleID string, body map[string]interface{}, before string, after string) *http.Response { + t.Helper() + + // If the `before` or `after` arguments have been provided, construct same-named query parameters + queryParams := url.Values{} + if before != "" { + queryParams.Add("before", before) + } + if after != "" { + queryParams.Add("after", after) + } + + return c.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "pushrules", scope, kind, ruleID}, WithJSONBody(t, body), WithQueries(queryParams)) +} + +// Unsafe_SendEventUnsynced sends `e` into the room. This function is UNSAFE as it does not wait +// for the event to be fully processed. This can cause flakey tests. Prefer `SendEventSynced`. +// Returns the event ID of the sent event. +func (c *CSAPI) Unsafe_SendEventUnsynced(t TestLike, roomID string, e b.Event) string { + t.Helper() + txnID := int(atomic.AddInt64(&c.txnID, 1)) + return c.Unsafe_SendEventUnsyncedWithTxnID(t, roomID, e, strconv.Itoa(txnID)) +} + +// SendEventUnsyncedWithTxnID sends `e` into the room with a prescribed transaction ID. +// This is useful for writing tests that interrogate transaction semantics. This function is UNSAFE +// as it does not wait for the event to be fully processed. This can cause flakey tests. Prefer `SendEventSynced`. +// Returns the event ID of the sent event. +func (c *CSAPI) Unsafe_SendEventUnsyncedWithTxnID(t TestLike, roomID string, e b.Event, txnID string) string { + t.Helper() + paths := []string{"_matrix", "client", "v3", "rooms", roomID, "send", e.Type, txnID} + if e.StateKey != nil { + paths = []string{"_matrix", "client", "v3", "rooms", roomID, "state", e.Type, *e.StateKey} + } + if e.Sender != "" && e.Sender != c.UserID { + t.Fatalf("Event.Sender must not be set, as this is set by the client in use (%s)", c.UserID) + } + res := c.MustDo(t, "PUT", paths, WithJSONBody(t, e.Content)) + body := ParseJSON(t, res) + eventID := GetJSONFieldStr(t, body, "event_id") + return eventID +} + +// SendEventSynced sends `e` into the room and waits for its event ID to come down /sync. +// Returns the event ID of the sent event. +func (c *CSAPI) SendEventSynced(t TestLike, roomID string, e b.Event) string { + t.Helper() + eventID := c.Unsafe_SendEventUnsynced(t, roomID, e) + t.Logf("SendEventSynced waiting for event ID %s", eventID) + c.MustSyncUntil(t, SyncReq{}, SyncTimelineHas(roomID, func(r gjson.Result) bool { + return r.Get("event_id").Str == eventID + })) + return eventID +} + +// SendRedaction sends a redaction request. Will fail if the returned HTTP request code is not 200 +func (c *CSAPI) SendRedaction(t TestLike, roomID string, e b.Event, eventID string) string { + t.Helper() + txnID := int(atomic.AddInt64(&c.txnID, 1)) + paths := []string{"_matrix", "client", "v3", "rooms", roomID, "redact", eventID, strconv.Itoa(txnID)} + res := c.MustDo(t, "PUT", paths, WithJSONBody(t, e.Content)) + body := ParseJSON(t, res) + return GetJSONFieldStr(t, body, "event_id") +} + +// GetCapbabilities queries the server's capabilities +func (c *CSAPI) GetCapabilities(t TestLike) []byte { + t.Helper() + res := c.MustDo(t, "GET", []string{"_matrix", "client", "v3", "capabilities"}) + body, err := io.ReadAll(res.Body) + if err != nil { + t.Fatalf("unable to read response body: %v", err) + } + return body +} + +// GetDefaultRoomVersion returns the server's default room version +func (c *CSAPI) GetDefaultRoomVersion(t TestLike) gomatrixserverlib.RoomVersion { + t.Helper() + capabilities := c.GetCapabilities(t) + defaultVersion := gjson.GetBytes(capabilities, `capabilities.m\.room_versions.default`) + if !defaultVersion.Exists() { + // spec says use RoomV1 in this case + return gomatrixserverlib.RoomVersionV1 + } + + return gomatrixserverlib.RoomVersion(defaultVersion.Str) +} + +func (c *CSAPI) GenerateOneTimeKeys(t TestLike, otkCount uint) (deviceKeys map[string]interface{}, oneTimeKeys map[string]interface{}) { + t.Helper() + account := olm.NewAccount() + ed25519Key, curveKey := account.IdentityKeys() + + ed25519KeyID := fmt.Sprintf("ed25519:%s", c.DeviceID) + curveKeyID := fmt.Sprintf("curve25519:%s", c.DeviceID) + + deviceKeys = map[string]interface{}{ + "user_id": c.UserID, + "device_id": c.DeviceID, + "algorithms": []interface{}{"m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"}, + "keys": map[string]interface{}{ + ed25519KeyID: ed25519Key.String(), + curveKeyID: curveKey.String(), + }, + } + + signature, _ := account.SignJSON(deviceKeys) + + deviceKeys["signatures"] = map[string]interface{}{ + c.UserID: map[string]interface{}{ + ed25519KeyID: signature, + }, + } + + account.GenOneTimeKeys(otkCount) + oneTimeKeys = map[string]interface{}{} + + for kid, key := range account.OneTimeKeys() { + keyID := fmt.Sprintf("signed_curve25519:%s", kid) + keyMap := map[string]interface{}{ + "key": key.String(), + } + + signature, _ = account.SignJSON(keyMap) + + keyMap["signatures"] = map[string]interface{}{ + c.UserID: map[string]interface{}{ + ed25519KeyID: signature, + }, + } + + oneTimeKeys[keyID] = keyMap + } + return deviceKeys, oneTimeKeys +} + +// WithRawBody sets the HTTP request body to `body` +func WithRawBody(body []byte) RequestOpt { + return func(req *http.Request) { + req.Body = io.NopCloser(bytes.NewReader(body)) + req.GetBody = func() (io.ReadCloser, error) { + r := bytes.NewReader(body) + return io.NopCloser(r), nil + } + // we need to manually set this because we don't set the body + // in http.NewRequest due to using functional options, and only in NewRequest + // does the stdlib set this for us. + req.ContentLength = int64(len(body)) + } +} + +// WithContentType sets the HTTP request Content-Type header to `cType` +func WithContentType(cType string) RequestOpt { + return func(req *http.Request) { + req.Header.Set("Content-Type", cType) + } +} + +// WithJSONBody sets the HTTP request body to the JSON serialised form of `obj` +func WithJSONBody(t TestLike, obj interface{}) RequestOpt { + return func(req *http.Request) { + t.Helper() + b, err := json.Marshal(obj) + if err != nil { + t.Fatalf("CSAPI.Do failed to marshal JSON body: %s", err) + } + WithRawBody(b)(req) + } +} + +// WithQueries sets the query parameters on the request. +// This function should not be used to set an "access_token" parameter for Matrix authentication. +// Instead, set CSAPI.AccessToken. +func WithQueries(q url.Values) RequestOpt { + return func(req *http.Request) { + req.URL.RawQuery = q.Encode() + } +} + +// WithRetryUntil will retry the request until the provided function returns true. Times out after +// `timeout`, which will then fail the test. +func WithRetryUntil(timeout time.Duration, untilFn func(res *http.Response) bool) RequestOpt { + return func(req *http.Request) { + until := req.Context().Value(CtxKeyWithRetryUntil).(*retryUntilParams) + until.timeout = timeout + until.untilFn = untilFn + } +} + +// MustDo is the same as Do but fails the test if the returned HTTP response code is not 2xx. +func (c *CSAPI) MustDo(t TestLike, method string, paths []string, opts ...RequestOpt) *http.Response { + t.Helper() + res := c.Do(t, method, paths, opts...) + if res.StatusCode < 200 || res.StatusCode >= 300 { + defer res.Body.Close() + body, _ := io.ReadAll(res.Body) + t.Fatalf("CSAPI.MustDo %s %s returned non-2xx code: %s - body: %s", method, res.Request.URL.String(), res.Status, string(body)) + } + return res +} + +// Do performs an arbitrary HTTP request to the server. This function supports RequestOpts to set +// extra information on the request such as an HTTP request body, query parameters and content-type. +// See all functions in this package starting with `With...`. +// +// Fails the test if an HTTP request could not be made or if there was a network error talking to the +// server. To do assertions on the HTTP response, see the `must` package. For example: +// +// must.MatchResponse(t, res, match.HTTPResponse{ +// StatusCode: 400, +// JSON: []match.JSON{ +// match.JSONKeyEqual("errcode", "M_INVALID_USERNAME"), +// }, +// }) +func (c *CSAPI) Do(t TestLike, method string, paths []string, opts ...RequestOpt) *http.Response { + t.Helper() + for i := range paths { + paths[i] = url.PathEscape(paths[i]) + } + reqURL := c.BaseURL + "/" + strings.Join(paths, "/") + req, err := http.NewRequest(method, reqURL, nil) + if err != nil { + t.Fatalf("CSAPI.Do failed to create http.NewRequest: %s", err) + } + // set defaults before RequestOpts + if c.AccessToken != "" { + req.Header.Set("Authorization", "Bearer "+c.AccessToken) + } + retryUntil := &retryUntilParams{} + ctx := context.WithValue(req.Context(), CtxKeyWithRetryUntil, retryUntil) + req = req.WithContext(ctx) + + // set functional options + for _, o := range opts { + o(req) + } + // set defaults after RequestOpts + if req.Header.Get("Content-Type") == "" { + req.Header.Set("Content-Type", "application/json") + } + // debug log the request + if c.Debug { + t.Logf("Making %s request to %s (%s)", method, req.URL, c.AccessToken) + contentType := req.Header.Get("Content-Type") + if contentType == "application/json" || strings.HasPrefix(contentType, "text/") { + if req.Body != nil { + body, _ := io.ReadAll(req.Body) + t.Logf("Request body: %s", string(body)) + req.Body = io.NopCloser(bytes.NewBuffer(body)) + } + } else { + t.Logf("Request body: ", contentType) + } + } + now := time.Now() + for { + // Perform the HTTP request + res, err := c.Client.Do(req) + if err != nil { + t.Fatalf("CSAPI.Do response returned error: %s", err) + } + // debug log the response + if c.Debug && res != nil { + var dump []byte + dump, err = httputil.DumpResponse(res, true) + if err != nil { + t.Fatalf("CSAPI.Do failed to dump response body: %s", err) + } + t.Logf("%s", string(dump)) + } + if retryUntil == nil || retryUntil.timeout == 0 { + return res // don't retry + } + + // check the condition, make a copy of the response body first in case the check consumes it + var resBody []byte + if res.Body != nil { + resBody, err = io.ReadAll(res.Body) + if err != nil { + t.Fatalf("CSAPI.Do failed to read response body for RetryUntil check: %s", err) + } + res.Body = io.NopCloser(bytes.NewBuffer(resBody)) + } + if retryUntil.untilFn(res) { + // remake the response and return + res.Body = io.NopCloser(bytes.NewBuffer(resBody)) + return res + } + // condition not satisfied, do we timeout yet? + if time.Since(now) > retryUntil.timeout { + t.Fatalf("CSAPI.Do RetryUntil: %v %v timed out after %v", method, req.URL, retryUntil.timeout) + } + t.Logf("CSAPI.Do RetryUntil: %v %v response condition not yet met, retrying", method, req.URL) + // small sleep to avoid tight-looping + time.Sleep(100 * time.Millisecond) + } +} + +// NewLoggedClient returns an http.Client which logs requests/responses +func NewLoggedClient(t TestLike, hsName string, cli *http.Client) *http.Client { + t.Helper() + if cli == nil { + cli = &http.Client{ + Timeout: 30 * time.Second, + } + } + transport := cli.Transport + if transport == nil { + transport = http.DefaultTransport + } + cli.Transport = &loggedRoundTripper{t, hsName, transport} + return cli +} + +type loggedRoundTripper struct { + t TestLike + hsName string + wrap http.RoundTripper +} + +func (t *loggedRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + start := time.Now() + res, err := t.wrap.RoundTrip(req) + if err != nil { + t.t.Logf("[CSAPI] %s %s%s => error: %s (%s)", req.Method, t.hsName, req.URL.Path, err, time.Since(start)) + } else { + t.t.Logf("[CSAPI] %s %s%s => %s (%s)", req.Method, t.hsName, req.URL.Path, res.Status, time.Since(start)) + } + return res, err +} + +// GetJSONFieldStr extracts a value from a byte-encoded JSON body given a search key +func GetJSONFieldStr(t TestLike, body []byte, wantKey string) string { + t.Helper() + res := gjson.GetBytes(body, wantKey) + if !res.Exists() { + t.Fatalf("JSONFieldStr: key '%s' missing from %s", wantKey, string(body)) + } + if res.Str == "" { + t.Fatalf("JSONFieldStr: key '%s' is not a string, body: %s", wantKey, string(body)) + } + return res.Str +} + +func GetJSONFieldStringArray(t TestLike, body []byte, wantKey string) []string { + t.Helper() + + res := gjson.GetBytes(body, wantKey) + + if !res.Exists() { + t.Fatalf("JSONFieldStr: key '%s' missing from %s", wantKey, string(body)) + } + + arrLength := len(res.Array()) + arr := make([]string, arrLength) + i := 0 + res.ForEach(func(key, value gjson.Result) bool { + arr[i] = value.Str + + // Keep iterating + i++ + return true + }) + + return arr +} + +// ParseJSON parses a JSON-encoded HTTP Response body into a byte slice +func ParseJSON(t TestLike, res *http.Response) []byte { + t.Helper() + defer res.Body.Close() + body, err := io.ReadAll(res.Body) + if err != nil { + t.Fatalf("MustParseJSON: reading HTTP response body returned %s", err) + } + if !gjson.ValidBytes(body) { + t.Fatalf("MustParseJSON: Response is not valid JSON") + } + return body +} + +// GjsonEscape escapes . and * from the input so it can be used with gjson.Get +func GjsonEscape(in string) string { + in = strings.ReplaceAll(in, ".", `\.`) + in = strings.ReplaceAll(in, "*", `\*`) + return in +} + +func checkArrayElements(object gjson.Result, key string, check func(gjson.Result) bool) error { + array := object.Get(key) + if !array.Exists() { + return fmt.Errorf("Key %s does not exist", key) + } + if !array.IsArray() { + return fmt.Errorf("Key %s exists but it isn't an array", key) + } + goArray := array.Array() + for _, ev := range goArray { + if check(ev) { + return nil + } + } + return fmt.Errorf("check function did not pass while iterating over %d elements: %v", len(goArray), array.Raw) +} + +// Splits an MXC URI into its origin and media ID parts +func SplitMxc(mxcUri string) (string, string) { + mxcParts := strings.Split(strings.TrimPrefix(mxcUri, "mxc://"), "/") + origin := mxcParts[0] + mediaId := strings.Join(mxcParts[1:], "/") + + return origin, mediaId +} + +// SendToDeviceMessages sends to-device messages over /sendToDevice/. +// +// The messages parameter is nested as follows: +// user_id -> device_id -> content (map[string]interface{}) +func (c *CSAPI) SendToDeviceMessages(t TestLike, evType string, messages map[string]map[string]map[string]interface{}) { + t.Helper() + txnID := int(atomic.AddInt64(&c.txnID, 1)) + c.MustDo( + t, + "PUT", + []string{"_matrix", "client", "v3", "sendToDevice", evType, strconv.Itoa(txnID)}, + WithJSONBody( + t, + map[string]map[string]map[string]map[string]interface{}{ + "messages": messages, + }, + ), + ) +} diff --git a/client/sync.go b/client/sync.go new file mode 100644 index 00000000..99495426 --- /dev/null +++ b/client/sync.go @@ -0,0 +1,391 @@ +package client + +import ( + "fmt" + "net/url" + "strings" + "time" + + "github.com/tidwall/gjson" +) + +// SyncCheckOpt is a functional option for use with MustSyncUntil which should return if +// the response satisfies the check, else return a human friendly error. +// The result object is the entire /sync response from this request. +type SyncCheckOpt func(clientUserID string, topLevelSyncJSON gjson.Result) error + +// SyncReq contains all the /sync request configuration options. The empty struct `SyncReq{}` is valid +// which will do a full /sync due to lack of a since token. +type SyncReq struct { + // A point in time to continue a sync from. This should be the next_batch token returned by an + // earlier call to this endpoint. + Since string + // The ID of a filter created using the filter API or a filter JSON object encoded as a string. + // The server will detect whether it is an ID or a JSON object by whether the first character is + // a "{" open brace. Passing the JSON inline is best suited to one off requests. Creating a + // filter using the filter API is recommended for clients that reuse the same filter multiple + // times, for example in long poll requests. + Filter string + // Controls whether to include the full state for all rooms the user is a member of. + // If this is set to true, then all state events will be returned, even if since is non-empty. + // The timeline will still be limited by the since parameter. In this case, the timeout parameter + // will be ignored and the query will return immediately, possibly with an empty timeline. + // If false, and since is non-empty, only state which has changed since the point indicated by + // since will be returned. + // By default, this is false. + FullState bool + // Controls whether the client is automatically marked as online by polling this API. If this + // parameter is omitted then the client is automatically marked as online when it uses this API. + // Otherwise if the parameter is set to “offline” then the client is not marked as being online + // when it uses this API. When set to “unavailable”, the client is marked as being idle. + // One of: [offline online unavailable]. + SetPresence string + // The maximum time to wait, in milliseconds, before returning this request. If no events + // (or other data) become available before this time elapses, the server will return a response + // with empty fields. + // By default, this is 1000 for Complement testing. + TimeoutMillis string // string for easier conversion to query params +} + +// MustSyncUntil blocks and continually calls /sync (advancing the since token) until all the +// check functions return no error. Returns the final/latest since token. +// +// Initial /sync example: (no since token) +// +// bob.InviteRoom(t, roomID, alice.UserID) +// alice.JoinRoom(t, roomID, nil) +// alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(alice.UserID, roomID)) +// +// Incremental /sync example: (test controls since token) +// +// since := alice.MustSyncUntil(t, client.SyncReq{TimeoutMillis: "0"}) // get a since token +// bob.InviteRoom(t, roomID, alice.UserID) +// since = alice.MustSyncUntil(t, client.SyncReq{Since: since}, client.SyncInvitedTo(alice.UserID, roomID)) +// alice.JoinRoom(t, roomID, nil) +// alice.MustSyncUntil(t, client.SyncReq{Since: since}, client.SyncJoinedTo(alice.UserID, roomID)) +// +// Checking multiple parts of /sync: +// +// alice.MustSyncUntil( +// t, client.SyncReq{}, +// client.SyncJoinedTo(alice.UserID, roomID), +// client.SyncJoinedTo(alice.UserID, roomID2), +// client.SyncJoinedTo(alice.UserID, roomID3), +// ) +// +// Check functions are unordered and independent. Once a check function returns true it is removed +// from the list of checks and won't be called again. +// +// In the unlikely event that you want all the checkers to pass *explicitly* in a single /sync +// response (e.g to assert some form of atomic update which updates multiple parts of the /sync +// response at once) then make your own checker function which does this. +// +// In the unlikely event that you need ordering on your checks, call MustSyncUntil multiple times +// with a single checker, and reuse the returned since token, as in the "Incremental sync" example. +// +// Will time out after CSAPI.SyncUntilTimeout. Returns the `next_batch` token from the final +// response. +func (c *CSAPI) MustSyncUntil(t TestLike, syncReq SyncReq, checks ...SyncCheckOpt) string { + t.Helper() + start := time.Now() + numResponsesReturned := 0 + checkers := make([]struct { + check SyncCheckOpt + errs []string + }, len(checks)) + for i := range checks { + c := checkers[i] + c.check = checks[i] + checkers[i] = c + } + printErrors := func() string { + err := "Checkers:\n" + for _, c := range checkers { + err += strings.Join(c.errs, "\n") + err += ", \n" + } + return err + } + for { + if time.Since(start) > c.SyncUntilTimeout { + t.Fatalf("%s MustSyncUntil: timed out after %v. Seen %d /sync responses. %s", c.UserID, time.Since(start), numResponsesReturned, printErrors()) + } + response, nextBatch := c.MustSync(t, syncReq) + syncReq.Since = nextBatch + numResponsesReturned += 1 + + for i := 0; i < len(checkers); i++ { + err := checkers[i].check(c.UserID, response) + if err == nil { + // check passed, removed from checkers + checkers = append(checkers[:i], checkers[i+1:]...) + i-- + } else { + c := checkers[i] + c.errs = append(c.errs, fmt.Sprintf("[t=%v] Response #%d: %s", time.Since(start), numResponsesReturned, err)) + checkers[i] = c + } + } + if len(checkers) == 0 { + // every checker has passed! + return syncReq.Since + } + } +} + +// Perform a single /sync request with the given request options. To sync until something happens, +// see `MustSyncUntil`. +// +// Fails the test if the /sync request does not return 200 OK. +// Returns the top-level parsed /sync response JSON as well as the next_batch token from the response. +func (c *CSAPI) MustSync(t TestLike, syncReq SyncReq) (gjson.Result, string) { + t.Helper() + query := url.Values{ + "timeout": []string{"1000"}, + } + // configure the HTTP request based on SyncReq + if syncReq.TimeoutMillis != "" { + query["timeout"] = []string{syncReq.TimeoutMillis} + } + if syncReq.Since != "" { + query["since"] = []string{syncReq.Since} + } + if syncReq.Filter != "" { + query["filter"] = []string{syncReq.Filter} + } + if syncReq.FullState { + query["full_state"] = []string{"true"} + } + if syncReq.SetPresence != "" { + query["set_presence"] = []string{syncReq.SetPresence} + } + res := c.MustDo(t, "GET", []string{"_matrix", "client", "v3", "sync"}, WithQueries(query)) + body := ParseJSON(t, res) + result := gjson.ParseBytes(body) + nextBatch := GetJSONFieldStr(t, body, "next_batch") + return result, nextBatch +} + +// Check that the timeline for `roomID` has an event which passes the check function. +func SyncTimelineHas(roomID string, check func(gjson.Result) bool) SyncCheckOpt { + return func(clientUserID string, topLevelSyncJSON gjson.Result) error { + err := checkArrayElements( + topLevelSyncJSON, "rooms.join."+GjsonEscape(roomID)+".timeline.events", check, + ) + if err == nil { + return nil + } + return fmt.Errorf("SyncTimelineHas(%s): %s", roomID, err) + } +} + +// Check that the timeline for `roomID` has an event which matches the event ID. +func SyncTimelineHasEventID(roomID string, eventID string) SyncCheckOpt { + return SyncTimelineHas(roomID, func(ev gjson.Result) bool { + return ev.Get("event_id").Str == eventID + }) +} + +// Check that the state section for `roomID` has an event which passes the check function. +// Note that the state section of a sync response only contains the change in state up to the start +// of the timeline and will not contain the entire state of the room for incremental or +// `lazy_load_members` syncs. +func SyncStateHas(roomID string, check func(gjson.Result) bool) SyncCheckOpt { + return func(clientUserID string, topLevelSyncJSON gjson.Result) error { + err := checkArrayElements( + topLevelSyncJSON, "rooms.join."+GjsonEscape(roomID)+".state.events", check, + ) + if err == nil { + return nil + } + return fmt.Errorf("SyncStateHas(%s): %s", roomID, err) + } +} + +func SyncEphemeralHas(roomID string, check func(gjson.Result) bool) SyncCheckOpt { + return func(clientUserID string, topLevelSyncJSON gjson.Result) error { + err := checkArrayElements( + topLevelSyncJSON, "rooms.join."+GjsonEscape(roomID)+".ephemeral.events", check, + ) + if err == nil { + return nil + } + return fmt.Errorf("SyncEphemeralHas(%s): %s", roomID, err) + } +} + +// Check that the sync contains presence from a user, optionally with an expected presence (set to nil to not check), +// and optionally with extra checks. +func SyncPresenceHas(fromUser string, expectedPresence *string, checks ...func(gjson.Result) bool) SyncCheckOpt { + return func(clientUserID string, topLevelSyncJSON gjson.Result) error { + presenceEvents := topLevelSyncJSON.Get("presence.events") + if !presenceEvents.Exists() { + return fmt.Errorf("presence.events does not exist") + } + for _, x := range presenceEvents.Array() { + if !(x.Get("type").Exists() && + x.Get("sender").Exists() && + x.Get("content").Exists() && + x.Get("content.presence").Exists()) { + return fmt.Errorf( + "malformatted presence event, expected the following fields: [sender, type, content, content.presence]: %s", + x.Raw, + ) + } else if x.Get("sender").Str != fromUser { + continue + } else if expectedPresence != nil && x.Get("content.presence").Str != *expectedPresence { + return fmt.Errorf( + "found presence for user %s, but not expected presence: got %s, want %s", + fromUser, x.Get("content.presence").Str, *expectedPresence, + ) + } else { + for i, check := range checks { + if !check(x) { + return fmt.Errorf("matched presence event to user %s, but check %d did not pass", fromUser, i) + } + } + return nil + } + } + return fmt.Errorf("did not find %s in presence events", fromUser) + } +} + +// Checks that `userID` gets invited to `roomID`. +// +// This checks different parts of the /sync response depending on the client making the request. +// If the client is also the person being invited to the room then the 'invite' block will be inspected. +// If the client is different to the person being invited then the 'join' block will be inspected. +func SyncInvitedTo(userID, roomID string) SyncCheckOpt { + return func(clientUserID string, topLevelSyncJSON gjson.Result) error { + // two forms which depend on what the client user is: + // - passively viewing an invite for a room you're joined to (timeline events) + // - actively being invited to a room. + if clientUserID == userID { + // active + err := checkArrayElements( + topLevelSyncJSON, "rooms.invite."+GjsonEscape(roomID)+".invite_state.events", + func(ev gjson.Result) bool { + return ev.Get("type").Str == "m.room.member" && ev.Get("state_key").Str == userID && ev.Get("content.membership").Str == "invite" + }, + ) + if err != nil { + return fmt.Errorf("SyncInvitedTo(%s): %s", roomID, err) + } + return nil + } + // passive + return SyncTimelineHas(roomID, func(ev gjson.Result) bool { + return ev.Get("type").Str == "m.room.member" && ev.Get("state_key").Str == userID && ev.Get("content.membership").Str == "invite" + })(clientUserID, topLevelSyncJSON) + } +} + +// Check that `userID` gets joined to `roomID` by inspecting the join timeline for a membership event. +// +// Additional checks can be passed to narrow down the check, all must pass. +func SyncJoinedTo(userID, roomID string, checks ...func(gjson.Result) bool) SyncCheckOpt { + checkJoined := func(ev gjson.Result) bool { + if ev.Get("type").Str == "m.room.member" && ev.Get("state_key").Str == userID && ev.Get("content.membership").Str == "join" { + for _, check := range checks { + if !check(ev) { + // short-circuit, bail early + return false + } + } + // passed both basic join check and all other checks + return true + } + return false + } + return func(clientUserID string, topLevelSyncJSON gjson.Result) error { + // Check both the timeline and the state events for the join event + // since on initial sync, the state events may only be in + // .state.events. + firstErr := checkArrayElements( + topLevelSyncJSON, "rooms.join."+GjsonEscape(roomID)+".timeline.events", checkJoined, + ) + if firstErr == nil { + return nil + } + + secondErr := checkArrayElements( + topLevelSyncJSON, "rooms.join."+GjsonEscape(roomID)+".state.events", checkJoined, + ) + if secondErr == nil { + return nil + } + return fmt.Errorf("SyncJoinedTo(%s): %s & %s", roomID, firstErr, secondErr) + } +} + +// Check that `userID` is leaving `roomID` by inspecting the timeline for a membership event, or witnessing `roomID` in `rooms.leave` +// Note: This will not work properly with initial syncs, see https://github.com/matrix-org/matrix-doc/issues/3537 +func SyncLeftFrom(userID, roomID string) SyncCheckOpt { + return func(clientUserID string, topLevelSyncJSON gjson.Result) error { + // two forms which depend on what the client user is: + // - passively viewing a membership for a room you're joined in + // - actively leaving the room + if clientUserID == userID { + // active + events := topLevelSyncJSON.Get("rooms.leave." + GjsonEscape(roomID)) + if !events.Exists() { + return fmt.Errorf("no leave section for room %s", roomID) + } else { + return nil + } + } + // passive + return SyncTimelineHas(roomID, func(ev gjson.Result) bool { + return ev.Get("type").Str == "m.room.member" && ev.Get("state_key").Str == userID && ev.Get("content.membership").Str == "leave" + })(clientUserID, topLevelSyncJSON) + } +} + +// Calls the `check` function for each global account data event, and returns with success if the +// `check` function returns true for at least one event. +func SyncGlobalAccountDataHas(check func(gjson.Result) bool) SyncCheckOpt { + return func(clientUserID string, topLevelSyncJSON gjson.Result) error { + return checkArrayElements(topLevelSyncJSON, "account_data.events", check) + } +} + +// Calls the `check` function for each account data event for the given room, +// and returns with success if the `check` function returns true for at least +// one event. +func SyncRoomAccountDataHas(roomID string, check func(gjson.Result) bool) SyncCheckOpt { + return func(clientUserID string, topLevelSyncJSON gjson.Result) error { + err := checkArrayElements( + topLevelSyncJSON, "rooms.join."+GjsonEscape(roomID)+".account_data.events", check, + ) + if err == nil { + return nil + } + return fmt.Errorf("SyncRoomAccountDataHas(%s): %s", roomID, err) + } +} + +// Check that sync has received a to-device message, +// with optional user filtering. +// +// If fromUser == "", all messages will be passed through to the check function. +// `check` will be called for all messages that have passed the filter. +// +// `check` gets passed the full event, including sender and type. +func SyncToDeviceHas(fromUser string, check func(gjson.Result) bool) SyncCheckOpt { + return func(clientUserID string, topLevelSyncJSON gjson.Result) error { + err := checkArrayElements( + topLevelSyncJSON, "to_device.events", func(result gjson.Result) bool { + if fromUser != "" && result.Get("sender").Str != fromUser { + return false + } else { + return check(result) + } + }, + ) + if err == nil { + return nil + } + return fmt.Errorf("SyncToDeviceHas(%v): %s", fromUser, err) + } +} diff --git a/internal/b/blueprints.go b/internal/b/blueprints.go index 70976776..11aea5c2 100644 --- a/internal/b/blueprints.go +++ b/internal/b/blueprints.go @@ -97,24 +97,6 @@ type Event struct { Sender string StateKey *string Content map[string]interface{} - - /* The following fields are ignored in blueprints as clients are unable to set them. - * They are used with federation.Server. - */ - - Unsigned map[string]interface{} - - // The events needed to authenticate this event. - // This can be either []EventReference for room v1/v2, or []string for room v3 onwards. - // If it is left at nil, MustCreateEvent will populate it automatically based on the room state. - AuthEvents interface{} - - // The prev events of the event if we want to override or falsify them. - // If it is left at nil, MustCreateEvent will populate it automatically based on the forward extremities. - PrevEvents interface{} - - // If this is a redaction, the event that it redacts - Redacts string } func MustValidate(bp Blueprint) Blueprint { diff --git a/internal/client/client.go b/internal/client/client.go deleted file mode 100644 index 2accca90..00000000 --- a/internal/client/client.go +++ /dev/null @@ -1,1117 +0,0 @@ -package client - -import ( - "bytes" - "context" - "crypto/hmac" - "crypto/sha1" // nolint:gosec - "encoding/hex" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/http/httputil" - "net/url" - "strconv" - "strings" - "sync/atomic" - "testing" - "time" - - "github.com/matrix-org/gomatrixserverlib" - "github.com/tidwall/gjson" - - "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/must" -) - -const ( - SharedSecret = "complement" -) - -type CtxKey string - -const ( - CtxKeyWithRetryUntil CtxKey = "complement_retry_until" // contains *retryUntilParams -) - -type retryUntilParams struct { - timeout time.Duration - untilFn func(*http.Response) bool -} - -// RequestOpt is a functional option which will modify an outgoing HTTP request. -// See functions starting with `With...` in this package for more info. -type RequestOpt func(req *http.Request) - -// SyncCheckOpt is a functional option for use with MustSyncUntil which should return if -// the response satisfies the check, else return a human friendly error. -// The result object is the entire /sync response from this request. -type SyncCheckOpt func(clientUserID string, topLevelSyncJSON gjson.Result) error - -// SyncReq contains all the /sync request configuration options. The empty struct `SyncReq{}` is valid -// which will do a full /sync due to lack of a since token. -type SyncReq struct { - // A point in time to continue a sync from. This should be the next_batch token returned by an - // earlier call to this endpoint. - Since string - // The ID of a filter created using the filter API or a filter JSON object encoded as a string. - // The server will detect whether it is an ID or a JSON object by whether the first character is - // a "{" open brace. Passing the JSON inline is best suited to one off requests. Creating a - // filter using the filter API is recommended for clients that reuse the same filter multiple - // times, for example in long poll requests. - Filter string - // Controls whether to include the full state for all rooms the user is a member of. - // If this is set to true, then all state events will be returned, even if since is non-empty. - // The timeline will still be limited by the since parameter. In this case, the timeout parameter - // will be ignored and the query will return immediately, possibly with an empty timeline. - // If false, and since is non-empty, only state which has changed since the point indicated by - // since will be returned. - // By default, this is false. - FullState bool - // Controls whether the client is automatically marked as online by polling this API. If this - // parameter is omitted then the client is automatically marked as online when it uses this API. - // Otherwise if the parameter is set to “offline” then the client is not marked as being online - // when it uses this API. When set to “unavailable”, the client is marked as being idle. - // One of: [offline online unavailable]. - SetPresence string - // The maximum time to wait, in milliseconds, before returning this request. If no events - // (or other data) become available before this time elapses, the server will return a response - // with empty fields. - // By default, this is 1000 for Complement testing. - TimeoutMillis string // string for easier conversion to query params -} - -type CSAPI struct { - UserID string - AccessToken string - DeviceID string - BaseURL string - Client *http.Client - // how long are we willing to wait for MustSyncUntil.... calls - SyncUntilTimeout time.Duration - // True to enable verbose logging - Debug bool - - txnID int64 -} - -// UploadContent uploads the provided content with an optional file name. Fails the test on error. Returns the MXC URI. -func (c *CSAPI) UploadContent(t *testing.T, fileBody []byte, fileName string, contentType string) string { - t.Helper() - query := url.Values{} - if fileName != "" { - query.Set("filename", fileName) - } - res := c.MustDoFunc( - t, "POST", []string{"_matrix", "media", "v3", "upload"}, - WithRawBody(fileBody), WithContentType(contentType), WithQueries(query), - ) - body := ParseJSON(t, res) - return GetJSONFieldStr(t, body, "content_uri") -} - -// DownloadContent downloads media from the server, returning the raw bytes and the Content-Type. Fails the test on error. -func (c *CSAPI) DownloadContent(t *testing.T, mxcUri string) ([]byte, string) { - t.Helper() - origin, mediaId := SplitMxc(mxcUri) - res := c.MustDoFunc(t, "GET", []string{"_matrix", "media", "v3", "download", origin, mediaId}) - contentType := res.Header.Get("Content-Type") - b, err := ioutil.ReadAll(res.Body) - if err != nil { - t.Error(err) - } - return b, contentType -} - -// CreateRoom creates a room with an optional HTTP request body. Fails the test on error. Returns the room ID. -func (c *CSAPI) CreateRoom(t *testing.T, creationContent interface{}) string { - t.Helper() - res := c.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "createRoom"}, WithJSONBody(t, creationContent)) - body := ParseJSON(t, res) - return GetJSONFieldStr(t, body, "room_id") -} - -// JoinRoom joins the room ID or alias given, else fails the test. Returns the room ID. -func (c *CSAPI) JoinRoom(t *testing.T, roomIDOrAlias string, serverNames []string) string { - t.Helper() - // construct URL query parameters - query := make(url.Values, len(serverNames)) - for _, serverName := range serverNames { - query.Add("server_name", serverName) - } - // join the room - res := c.MustDoFunc( - t, "POST", []string{"_matrix", "client", "v3", "join", roomIDOrAlias}, - WithQueries(query), WithJSONBody(t, map[string]interface{}{}), - ) - // return the room ID if we joined with it - if roomIDOrAlias[0] == '!' { - return roomIDOrAlias - } - // otherwise we should be told the room ID if we joined via an alias - body := ParseJSON(t, res) - return GetJSONFieldStr(t, body, "room_id") -} - -// LeaveRoom leaves the room ID, else fails the test. -func (c *CSAPI) LeaveRoom(t *testing.T, roomID string) { - t.Helper() - // leave the room - body := map[string]interface{}{} - c.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "leave"}, WithJSONBody(t, body)) -} - -// InviteRoom invites userID to the room ID, else fails the test. -func (c *CSAPI) InviteRoom(t *testing.T, roomID string, userID string) { - t.Helper() - // Invite the user to the room - body := map[string]interface{}{ - "user_id": userID, - } - c.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "invite"}, WithJSONBody(t, body)) -} - -func (c *CSAPI) GetGlobalAccountData(t *testing.T, eventType string) *http.Response { - return c.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "user", c.UserID, "account_data", eventType}) -} - -func (c *CSAPI) SetGlobalAccountData(t *testing.T, eventType string, content map[string]interface{}) *http.Response { - return c.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "user", c.UserID, "account_data", eventType}, WithJSONBody(t, content)) -} - -func (c *CSAPI) GetRoomAccountData(t *testing.T, roomID string, eventType string) *http.Response { - return c.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "user", c.UserID, "rooms", roomID, "account_data", eventType}) -} - -func (c *CSAPI) SetRoomAccountData(t *testing.T, roomID string, eventType string, content map[string]interface{}) *http.Response { - return c.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "user", c.UserID, "rooms", roomID, "account_data", eventType}, WithJSONBody(t, content)) -} - -// GetAllPushRules fetches all configured push rules for a user from the homeserver. -// Push rules are returned as a parsed gjson result -// -// Example of printing the IDs of all underride rules of the current user: -// -// allPushRules := c.GetAllPushRules(t) -// globalUnderridePushRules := allPushRules.Get("global").Get("underride").Array() -// -// for index, rule := range globalUnderridePushRules { -// fmt.Printf("This rule's ID is: %s\n", rule.Get("rule_id").Str) -// } -// -// Push rules are returned in the same order received from the homeserver. -func (c *CSAPI) GetAllPushRules(t *testing.T) gjson.Result { - t.Helper() - - // We have to supply an empty string to the end of this path in order to generate a trailing slash. - // See https://github.com/matrix-org/matrix-spec/issues/457 - res := c.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "pushrules", ""}) - pushRulesBytes := ParseJSON(t, res) - return gjson.ParseBytes(pushRulesBytes) -} - -// GetPushRule queries the contents of a client's push rule by scope, kind and rule ID. -// A parsed gjson result is returned. Fails the test if the query to server returns a non-2xx status code. -// -// Example of checking that a global underride rule contains the expected actions: -// -// containsDisplayNameRule := c.GetPushRule(t, "global", "underride", ".m.rule.contains_display_name") -// must.MatchGJSON( -// t, -// containsDisplayNameRule, -// match.JSONKeyEqual("actions", []interface{}{ -// "notify", -// map[string]interface{}{"set_tweak": "sound", "value": "default"}, -// map[string]interface{}{"set_tweak": "highlight"}, -// }), -// ) -func (c *CSAPI) GetPushRule(t *testing.T, scope string, kind string, ruleID string) gjson.Result { - t.Helper() - - res := c.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "pushrules", scope, kind, ruleID}) - pushRuleBytes := ParseJSON(t, res) - return gjson.ParseBytes(pushRuleBytes) -} - -// SetPushRule creates a new push rule on the user, or modifies an existing one. -// If `before` or `after` parameters are not set to an empty string, their values -// will be set as the `before` and `after` query parameters respectively on the -// "set push rules" client endpoint: -// https://spec.matrix.org/v1.5/client-server-api/#put_matrixclientv3pushrulesscopekindruleid -// -// Example of setting a push rule with ID 'com.example.rule2' that must come after 'com.example.rule1': -// -// c.SetPushRule(t, "global", "underride", "com.example.rule2", map[string]interface{}{ -// "actions": []string{"dont_notify"}, -// }, nil, "com.example.rule1") -func (c *CSAPI) SetPushRule(t *testing.T, scope string, kind string, ruleID string, body map[string]interface{}, before string, after string) *http.Response { - t.Helper() - - // If the `before` or `after` arguments have been provided, construct same-named query parameters - queryParams := url.Values{} - if before != "" { - queryParams.Add("before", before) - } - if after != "" { - queryParams.Add("after", after) - } - - return c.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "pushrules", scope, kind, ruleID}, WithJSONBody(t, body), WithQueries(queryParams)) -} - -// SendEventUnsynced sends `e` into the room. -// Returns the event ID of the sent event. -func (c *CSAPI) SendEventUnsynced(t *testing.T, roomID string, e b.Event) string { - t.Helper() - txnID := int(atomic.AddInt64(&c.txnID, 1)) - return c.SendEventUnsyncedWithTxnID(t, roomID, e, strconv.Itoa(txnID)) -} - -// SendEventUnsyncedWithTxnID sends `e` into the room with a prescribed transaction ID. -// This is useful for writing tests that interrogate transaction semantics. -// Returns the event ID of the sent event. -func (c *CSAPI) SendEventUnsyncedWithTxnID(t *testing.T, roomID string, e b.Event, txnID string) string { - t.Helper() - paths := []string{"_matrix", "client", "v3", "rooms", roomID, "send", e.Type, txnID} - if e.StateKey != nil { - paths = []string{"_matrix", "client", "v3", "rooms", roomID, "state", e.Type, *e.StateKey} - } - res := c.MustDoFunc(t, "PUT", paths, WithJSONBody(t, e.Content)) - body := ParseJSON(t, res) - eventID := GetJSONFieldStr(t, body, "event_id") - return eventID -} - -// SendEventSynced sends `e` into the room and waits for its event ID to come down /sync. -// Returns the event ID of the sent event. -func (c *CSAPI) SendEventSynced(t *testing.T, roomID string, e b.Event) string { - t.Helper() - eventID := c.SendEventUnsynced(t, roomID, e) - t.Logf("SendEventSynced waiting for event ID %s", eventID) - c.MustSyncUntil(t, SyncReq{}, SyncTimelineHas(roomID, func(r gjson.Result) bool { - return r.Get("event_id").Str == eventID - })) - return eventID -} - -// SendRedaction sends a redaction request. Will fail if the returned HTTP request code is not 200 -func (c *CSAPI) SendRedaction(t *testing.T, roomID string, e b.Event, eventID string) string { - t.Helper() - txnID := int(atomic.AddInt64(&c.txnID, 1)) - paths := []string{"_matrix", "client", "v3", "rooms", roomID, "redact", eventID, strconv.Itoa(txnID)} - res := c.MustDoFunc(t, "PUT", paths, WithJSONBody(t, e.Content)) - body := ParseJSON(t, res) - return GetJSONFieldStr(t, body, "event_id") -} - -// Perform a single /sync request with the given request options. To sync until something happens, -// see `MustSyncUntil`. -// -// Fails the test if the /sync request does not return 200 OK. -// Returns the top-level parsed /sync response JSON as well as the next_batch token from the response. -func (c *CSAPI) MustSync(t *testing.T, syncReq SyncReq) (gjson.Result, string) { - t.Helper() - query := url.Values{ - "timeout": []string{"1000"}, - } - // configure the HTTP request based on SyncReq - if syncReq.TimeoutMillis != "" { - query["timeout"] = []string{syncReq.TimeoutMillis} - } - if syncReq.Since != "" { - query["since"] = []string{syncReq.Since} - } - if syncReq.Filter != "" { - query["filter"] = []string{syncReq.Filter} - } - if syncReq.FullState { - query["full_state"] = []string{"true"} - } - if syncReq.SetPresence != "" { - query["set_presence"] = []string{syncReq.SetPresence} - } - res := c.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "sync"}, WithQueries(query)) - body := ParseJSON(t, res) - result := gjson.ParseBytes(body) - nextBatch := GetJSONFieldStr(t, body, "next_batch") - return result, nextBatch -} - -// MustSyncUntil blocks and continually calls /sync (advancing the since token) until all the -// check functions return no error. Returns the final/latest since token. -// -// Initial /sync example: (no since token) -// bob.InviteRoom(t, roomID, alice.UserID) -// alice.JoinRoom(t, roomID, nil) -// alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(alice.UserID, roomID)) -// -// Incremental /sync example: (test controls since token) -// since := alice.MustSyncUntil(t, client.SyncReq{TimeoutMillis: "0"}) // get a since token -// bob.InviteRoom(t, roomID, alice.UserID) -// since = alice.MustSyncUntil(t, client.SyncReq{Since: since}, client.SyncInvitedTo(alice.UserID, roomID)) -// alice.JoinRoom(t, roomID, nil) -// alice.MustSyncUntil(t, client.SyncReq{Since: since}, client.SyncJoinedTo(alice.UserID, roomID)) -// -// Checking multiple parts of /sync: -// alice.MustSyncUntil( -// t, client.SyncReq{}, -// client.SyncJoinedTo(alice.UserID, roomID), -// client.SyncJoinedTo(alice.UserID, roomID2), -// client.SyncJoinedTo(alice.UserID, roomID3), -// ) -// -// Check functions are unordered and independent. Once a check function returns true it is removed -// from the list of checks and won't be called again. -// -// In the unlikely event that you want all the checkers to pass *explicitly* in a single /sync -// response (e.g to assert some form of atomic update which updates multiple parts of the /sync -// response at once) then make your own checker function which does this. -// -// In the unlikely event that you need ordering on your checks, call MustSyncUntil multiple times -// with a single checker, and reuse the returned since token, as in the "Incremental sync" example. -// -// Will time out after CSAPI.SyncUntilTimeout. Returns the `next_batch` token from the final -// response. -func (c *CSAPI) MustSyncUntil(t *testing.T, syncReq SyncReq, checks ...SyncCheckOpt) string { - t.Helper() - start := time.Now() - numResponsesReturned := 0 - checkers := make([]struct { - check SyncCheckOpt - errs []string - }, len(checks)) - for i := range checks { - c := checkers[i] - c.check = checks[i] - checkers[i] = c - } - printErrors := func() string { - err := "Checkers:\n" - for _, c := range checkers { - err += strings.Join(c.errs, "\n") - err += ", \n" - } - return err - } - for { - if time.Since(start) > c.SyncUntilTimeout { - t.Fatalf("%s MustSyncUntil: timed out after %v. Seen %d /sync responses. %s", c.UserID, time.Since(start), numResponsesReturned, printErrors()) - } - response, nextBatch := c.MustSync(t, syncReq) - syncReq.Since = nextBatch - numResponsesReturned += 1 - - for i := 0; i < len(checkers); i++ { - err := checkers[i].check(c.UserID, response) - if err == nil { - // check passed, removed from checkers - checkers = append(checkers[:i], checkers[i+1:]...) - i-- - } else { - c := checkers[i] - c.errs = append(c.errs, fmt.Sprintf("[t=%v] Response #%d: %s", time.Since(start), numResponsesReturned, err)) - checkers[i] = c - } - } - if len(checkers) == 0 { - // every checker has passed! - return syncReq.Since - } - } -} - -type LoginOpt func(map[string]interface{}) - -func WithDeviceID(deviceID string) LoginOpt { - return func(loginBody map[string]interface{}) { - loginBody["device_id"] = deviceID - } -} - -// LoginUser will log in to a homeserver and create a new device on an existing user. -func (c *CSAPI) LoginUser(t *testing.T, localpart, password string, opts ...LoginOpt) (userID, accessToken, deviceID string) { - t.Helper() - reqBody := map[string]interface{}{ - "identifier": map[string]interface{}{ - "type": "m.id.user", - "user": localpart, - }, - "password": password, - "type": "m.login.password", - } - - for _, opt := range opts { - opt(reqBody) - } - - res := c.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "login"}, WithJSONBody(t, reqBody)) - - body, err := ioutil.ReadAll(res.Body) - if err != nil { - t.Fatalf("unable to read response body: %v", err) - } - - userID = gjson.GetBytes(body, "user_id").Str - accessToken = gjson.GetBytes(body, "access_token").Str - deviceID = gjson.GetBytes(body, "device_id").Str - return userID, accessToken, deviceID -} - -// LoginUserWithRefreshToken will log in to a homeserver, with refresh token enabled, -// and create a new device on an existing user. -func (c *CSAPI) LoginUserWithRefreshToken(t *testing.T, localpart, password string) (userID, accessToken, refreshToken, deviceID string, expiresInMs int64) { - t.Helper() - reqBody := map[string]interface{}{ - "identifier": map[string]interface{}{ - "type": "m.id.user", - "user": localpart, - }, - "password": password, - "type": "m.login.password", - "refresh_token": true, - } - res := c.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "login"}, WithJSONBody(t, reqBody)) - - body, err := ioutil.ReadAll(res.Body) - if err != nil { - t.Fatalf("unable to read response body: %v", err) - } - - userID = gjson.GetBytes(body, "user_id").Str - accessToken = gjson.GetBytes(body, "access_token").Str - deviceID = gjson.GetBytes(body, "device_id").Str - refreshToken = gjson.GetBytes(body, "refresh_token").Str - expiresInMs = gjson.GetBytes(body, "expires_in_ms").Int() - return userID, accessToken, refreshToken, deviceID, expiresInMs -} - -// RefreshToken will consume a refresh token and return a new access token and refresh token. -func (c *CSAPI) ConsumeRefreshToken(t *testing.T, refreshToken string) (newAccessToken, newRefreshToken string, expiresInMs int64) { - t.Helper() - reqBody := map[string]interface{}{ - "refresh_token": refreshToken, - } - res := c.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "refresh"}, WithJSONBody(t, reqBody)) - - body, err := ioutil.ReadAll(res.Body) - if err != nil { - t.Fatalf("unable to read response body: %v", err) - } - - newAccessToken = gjson.GetBytes(body, "access_token").Str - newRefreshToken = gjson.GetBytes(body, "refresh_token").Str - expiresInMs = gjson.GetBytes(body, "expires_in_ms").Int() - return newAccessToken, newRefreshToken, expiresInMs -} - -// RegisterUser will register the user with given parameters and -// return user ID, access token and device ID. It fails the test on network error. -func (c *CSAPI) RegisterUser(t *testing.T, localpart, password string) (userID, accessToken, deviceID string) { - t.Helper() - reqBody := map[string]interface{}{ - "auth": map[string]string{ - "type": "m.login.dummy", - }, - "username": localpart, - "password": password, - } - res := c.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "register"}, WithJSONBody(t, reqBody)) - - body, err := ioutil.ReadAll(res.Body) - if err != nil { - t.Fatalf("unable to read response body: %v", err) - } - - userID = gjson.GetBytes(body, "user_id").Str - accessToken = gjson.GetBytes(body, "access_token").Str - deviceID = gjson.GetBytes(body, "device_id").Str - return userID, accessToken, deviceID -} - -// RegisterSharedSecret registers a new account with a shared secret via HMAC -// See https://github.com/matrix-org/synapse/blob/e550ab17adc8dd3c48daf7fedcd09418a73f524b/synapse/_scripts/register_new_matrix_user.py#L40 -func (c *CSAPI) RegisterSharedSecret(t *testing.T, user, pass string, isAdmin bool) (userID, accessToken, deviceID string) { - resp := c.DoFunc(t, "GET", []string{"_synapse", "admin", "v1", "register"}) - if resp.StatusCode != 200 { - t.Skipf("Homeserver image does not support shared secret registration, /_synapse/admin/v1/register returned HTTP %d", resp.StatusCode) - return - } - body := must.ParseJSON(t, resp.Body) - nonce := gjson.GetBytes(body, "nonce") - if !nonce.Exists() { - t.Fatalf("Malformed shared secret GET response: %s", string(body)) - } - mac := hmac.New(sha1.New, []byte(SharedSecret)) - mac.Write([]byte(nonce.Str)) - mac.Write([]byte("\x00")) - mac.Write([]byte(user)) - mac.Write([]byte("\x00")) - mac.Write([]byte(pass)) - mac.Write([]byte("\x00")) - if isAdmin { - mac.Write([]byte("admin")) - } else { - mac.Write([]byte("notadmin")) - } - sig := mac.Sum(nil) - reqBody := map[string]interface{}{ - "nonce": nonce.Str, - "username": user, - "password": pass, - "mac": hex.EncodeToString(sig), - "admin": isAdmin, - } - resp = c.MustDoFunc(t, "POST", []string{"_synapse", "admin", "v1", "register"}, WithJSONBody(t, reqBody)) - body = must.ParseJSON(t, resp.Body) - userID = gjson.GetBytes(body, "user_id").Str - accessToken = gjson.GetBytes(body, "access_token").Str - deviceID = gjson.GetBytes(body, "device_id").Str - return userID, accessToken, deviceID -} - -// GetCapbabilities queries the server's capabilities -func (c *CSAPI) GetCapabilities(t *testing.T) []byte { - t.Helper() - res := c.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "capabilities"}) - body, err := ioutil.ReadAll(res.Body) - if err != nil { - t.Fatalf("unable to read response body: %v", err) - } - return body -} - -// GetDefaultRoomVersion returns the server's default room version -func (c *CSAPI) GetDefaultRoomVersion(t *testing.T) gomatrixserverlib.RoomVersion { - t.Helper() - capabilities := c.GetCapabilities(t) - defaultVersion := gjson.GetBytes(capabilities, `capabilities.m\.room_versions.default`) - if !defaultVersion.Exists() { - // spec says use RoomV1 in this case - return gomatrixserverlib.RoomVersionV1 - } - - return gomatrixserverlib.RoomVersion(defaultVersion.Str) -} - -// WithRawBody sets the HTTP request body to `body` -func WithRawBody(body []byte) RequestOpt { - return func(req *http.Request) { - req.Body = ioutil.NopCloser(bytes.NewReader(body)) - req.GetBody = func() (io.ReadCloser, error) { - r := bytes.NewReader(body) - return ioutil.NopCloser(r), nil - } - // we need to manually set this because we don't set the body - // in http.NewRequest due to using functional options, and only in NewRequest - // does the stdlib set this for us. - req.ContentLength = int64(len(body)) - } -} - -// WithContentType sets the HTTP request Content-Type header to `cType` -func WithContentType(cType string) RequestOpt { - return func(req *http.Request) { - req.Header.Set("Content-Type", cType) - } -} - -// WithJSONBody sets the HTTP request body to the JSON serialised form of `obj` -func WithJSONBody(t *testing.T, obj interface{}) RequestOpt { - return func(req *http.Request) { - t.Helper() - b, err := json.Marshal(obj) - if err != nil { - t.Fatalf("CSAPI.Do failed to marshal JSON body: %s", err) - } - WithRawBody(b)(req) - } -} - -// WithQueries sets the query parameters on the request. -// This function should not be used to set an "access_token" parameter for Matrix authentication. -// Instead, set CSAPI.AccessToken. -func WithQueries(q url.Values) RequestOpt { - return func(req *http.Request) { - req.URL.RawQuery = q.Encode() - } -} - -// WithRetryUntil will retry the request until the provided function returns true. Times out after -// `timeout`, which will then fail the test. -func WithRetryUntil(timeout time.Duration, untilFn func(res *http.Response) bool) RequestOpt { - return func(req *http.Request) { - until := req.Context().Value(CtxKeyWithRetryUntil).(*retryUntilParams) - until.timeout = timeout - until.untilFn = untilFn - } -} - -// MustDoFunc is the same as DoFunc but fails the test if the returned HTTP response code is not 2xx. -func (c *CSAPI) MustDoFunc(t *testing.T, method string, paths []string, opts ...RequestOpt) *http.Response { - t.Helper() - res := c.DoFunc(t, method, paths, opts...) - if res.StatusCode < 200 || res.StatusCode >= 300 { - defer res.Body.Close() - body, _ := ioutil.ReadAll(res.Body) - t.Fatalf("CSAPI.MustDoFunc %s %s returned non-2xx code: %s - body: %s", method, res.Request.URL.String(), res.Status, string(body)) - } - return res -} - -// DoFunc performs an arbitrary HTTP request to the server. This function supports RequestOpts to set -// extra information on the request such as an HTTP request body, query parameters and content-type. -// See all functions in this package starting with `With...`. -// -// Fails the test if an HTTP request could not be made or if there was a network error talking to the -// server. To do assertions on the HTTP response, see the `must` package. For example: -// must.MatchResponse(t, res, match.HTTPResponse{ -// StatusCode: 400, -// JSON: []match.JSON{ -// match.JSONKeyEqual("errcode", "M_INVALID_USERNAME"), -// }, -// }) -func (c *CSAPI) DoFunc(t *testing.T, method string, paths []string, opts ...RequestOpt) *http.Response { - t.Helper() - for i := range paths { - paths[i] = url.PathEscape(paths[i]) - } - reqURL := c.BaseURL + "/" + strings.Join(paths, "/") - req, err := http.NewRequest(method, reqURL, nil) - if err != nil { - t.Fatalf("CSAPI.DoFunc failed to create http.NewRequest: %s", err) - } - // set defaults before RequestOpts - if c.AccessToken != "" { - req.Header.Set("Authorization", "Bearer "+c.AccessToken) - } - retryUntil := &retryUntilParams{} - ctx := context.WithValue(req.Context(), CtxKeyWithRetryUntil, retryUntil) - req = req.WithContext(ctx) - - // set functional options - for _, o := range opts { - o(req) - } - // set defaults after RequestOpts - if req.Header.Get("Content-Type") == "" { - req.Header.Set("Content-Type", "application/json") - } - // debug log the request - if c.Debug { - t.Logf("Making %s request to %s (%s)", method, req.URL, c.AccessToken) - contentType := req.Header.Get("Content-Type") - if contentType == "application/json" || strings.HasPrefix(contentType, "text/") { - if req.Body != nil { - body, _ := ioutil.ReadAll(req.Body) - t.Logf("Request body: %s", string(body)) - req.Body = ioutil.NopCloser(bytes.NewBuffer(body)) - } - } else { - t.Logf("Request body: ", contentType) - } - } - now := time.Now() - for { - // Perform the HTTP request - res, err := c.Client.Do(req) - if err != nil { - t.Fatalf("CSAPI.DoFunc response returned error: %s", err) - } - // debug log the response - if c.Debug && res != nil { - var dump []byte - dump, err = httputil.DumpResponse(res, true) - if err != nil { - t.Fatalf("CSAPI.DoFunc failed to dump response body: %s", err) - } - t.Logf("%s", string(dump)) - } - if retryUntil == nil || retryUntil.timeout == 0 { - return res // don't retry - } - - // check the condition, make a copy of the response body first in case the check consumes it - var resBody []byte - if res.Body != nil { - resBody, err = ioutil.ReadAll(res.Body) - if err != nil { - t.Fatalf("CSAPI.DoFunc failed to read response body for RetryUntil check: %s", err) - } - res.Body = io.NopCloser(bytes.NewBuffer(resBody)) - } - if retryUntil.untilFn(res) { - // remake the response and return - res.Body = io.NopCloser(bytes.NewBuffer(resBody)) - return res - } - // condition not satisfied, do we timeout yet? - if time.Since(now) > retryUntil.timeout { - t.Fatalf("CSAPI.DoFunc RetryUntil: %v %v timed out after %v", method, req.URL, retryUntil.timeout) - } - t.Logf("CSAPI.DoFunc RetryUntil: %v %v response condition not yet met, retrying", method, req.URL) - // small sleep to avoid tight-looping - time.Sleep(100 * time.Millisecond) - } -} - -// NewLoggedClient returns an http.Client which logs requests/responses -func NewLoggedClient(t *testing.T, hsName string, cli *http.Client) *http.Client { - t.Helper() - if cli == nil { - cli = &http.Client{ - Timeout: 30 * time.Second, - } - } - transport := cli.Transport - if transport == nil { - transport = http.DefaultTransport - } - cli.Transport = &loggedRoundTripper{t, hsName, transport} - return cli -} - -type loggedRoundTripper struct { - t *testing.T - hsName string - wrap http.RoundTripper -} - -func (t *loggedRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - start := time.Now() - res, err := t.wrap.RoundTrip(req) - if err != nil { - t.t.Logf("[CSAPI] %s %s%s => error: %s (%s)", req.Method, t.hsName, req.URL.Path, err, time.Since(start)) - } else { - t.t.Logf("[CSAPI] %s %s%s => %s (%s)", req.Method, t.hsName, req.URL.Path, res.Status, time.Since(start)) - } - return res, err -} - -// GetJSONFieldStr extracts a value from a byte-encoded JSON body given a search key -func GetJSONFieldStr(t *testing.T, body []byte, wantKey string) string { - t.Helper() - res := gjson.GetBytes(body, wantKey) - if !res.Exists() { - t.Fatalf("JSONFieldStr: key '%s' missing from %s", wantKey, string(body)) - } - if res.Str == "" { - t.Fatalf("JSONFieldStr: key '%s' is not a string, body: %s", wantKey, string(body)) - } - return res.Str -} - -func GetJSONFieldStringArray(t *testing.T, body []byte, wantKey string) []string { - t.Helper() - - res := gjson.GetBytes(body, wantKey) - - if !res.Exists() { - t.Fatalf("JSONFieldStr: key '%s' missing from %s", wantKey, string(body)) - } - - arrLength := len(res.Array()) - arr := make([]string, arrLength) - i := 0 - res.ForEach(func(key, value gjson.Result) bool { - arr[i] = value.Str - - // Keep iterating - i++ - return true - }) - - return arr -} - -// ParseJSON parses a JSON-encoded HTTP Response body into a byte slice -func ParseJSON(t *testing.T, res *http.Response) []byte { - t.Helper() - defer res.Body.Close() - body, err := ioutil.ReadAll(res.Body) - if err != nil { - t.Fatalf("MustParseJSON: reading HTTP response body returned %s", err) - } - if !gjson.ValidBytes(body) { - t.Fatalf("MustParseJSON: Response is not valid JSON") - } - return body -} - -// GjsonEscape escapes . and * from the input so it can be used with gjson.Get -func GjsonEscape(in string) string { - in = strings.ReplaceAll(in, ".", `\.`) - in = strings.ReplaceAll(in, "*", `\*`) - return in -} - -// Check that the timeline for `roomID` has an event which passes the check function. -func SyncTimelineHas(roomID string, check func(gjson.Result) bool) SyncCheckOpt { - return func(clientUserID string, topLevelSyncJSON gjson.Result) error { - err := loopArray( - topLevelSyncJSON, "rooms.join."+GjsonEscape(roomID)+".timeline.events", check, - ) - if err == nil { - return nil - } - return fmt.Errorf("SyncTimelineHas(%s): %s", roomID, err) - } -} - -// Check that the timeline for `roomID` has an event which matches the event ID. -func SyncTimelineHasEventID(roomID string, eventID string) SyncCheckOpt { - return SyncTimelineHas(roomID, func(ev gjson.Result) bool { - return ev.Get("event_id").Str == eventID - }) -} - -// Check that the state section for `roomID` has an event which passes the check function. -// Note that the state section of a sync response only contains the change in state up to the start -// of the timeline and will not contain the entire state of the room for incremental or -// `lazy_load_members` syncs. -func SyncStateHas(roomID string, check func(gjson.Result) bool) SyncCheckOpt { - return func(clientUserID string, topLevelSyncJSON gjson.Result) error { - err := loopArray( - topLevelSyncJSON, "rooms.join."+GjsonEscape(roomID)+".state.events", check, - ) - if err == nil { - return nil - } - return fmt.Errorf("SyncStateHas(%s): %s", roomID, err) - } -} - -func SyncEphemeralHas(roomID string, check func(gjson.Result) bool) SyncCheckOpt { - return func(clientUserID string, topLevelSyncJSON gjson.Result) error { - err := loopArray( - topLevelSyncJSON, "rooms.join."+GjsonEscape(roomID)+".ephemeral.events", check, - ) - if err == nil { - return nil - } - return fmt.Errorf("SyncEphemeralHas(%s): %s", roomID, err) - } -} - -// Check that the sync contains presence from a user, optionally with an expected presence (set to nil to not check), -// and optionally with extra checks. -func SyncPresenceHas(fromUser string, expectedPresence *string, checks ...func(gjson.Result) bool) SyncCheckOpt { - return func(clientUserID string, topLevelSyncJSON gjson.Result) error { - presenceEvents := topLevelSyncJSON.Get("presence.events") - if !presenceEvents.Exists() { - return fmt.Errorf("presence.events does not exist") - } - for _, x := range presenceEvents.Array() { - if !(x.Get("type").Exists() && - x.Get("sender").Exists() && - x.Get("content").Exists() && - x.Get("content.presence").Exists()) { - return fmt.Errorf( - "malformatted presence event, expected the following fields: [sender, type, content, content.presence]: %s", - x.Raw, - ) - } else if x.Get("sender").Str != fromUser { - continue - } else if expectedPresence != nil && x.Get("content.presence").Str != *expectedPresence { - return fmt.Errorf( - "found presence for user %s, but not expected presence: got %s, want %s", - fromUser, x.Get("content.presence").Str, *expectedPresence, - ) - } else { - for i, check := range checks { - if !check(x) { - return fmt.Errorf("matched presence event to user %s, but check %d did not pass", fromUser, i) - } - } - return nil - } - } - return fmt.Errorf("did not find %s in presence events", fromUser) - } -} - -// Checks that `userID` gets invited to `roomID`. -// -// This checks different parts of the /sync response depending on the client making the request. -// If the client is also the person being invited to the room then the 'invite' block will be inspected. -// If the client is different to the person being invited then the 'join' block will be inspected. -func SyncInvitedTo(userID, roomID string) SyncCheckOpt { - return func(clientUserID string, topLevelSyncJSON gjson.Result) error { - // two forms which depend on what the client user is: - // - passively viewing an invite for a room you're joined to (timeline events) - // - actively being invited to a room. - if clientUserID == userID { - // active - err := loopArray( - topLevelSyncJSON, "rooms.invite."+GjsonEscape(roomID)+".invite_state.events", - func(ev gjson.Result) bool { - return ev.Get("type").Str == "m.room.member" && ev.Get("state_key").Str == userID && ev.Get("content.membership").Str == "invite" - }, - ) - if err != nil { - return fmt.Errorf("SyncInvitedTo(%s): %s", roomID, err) - } - return nil - } - // passive - return SyncTimelineHas(roomID, func(ev gjson.Result) bool { - return ev.Get("type").Str == "m.room.member" && ev.Get("state_key").Str == userID && ev.Get("content.membership").Str == "invite" - })(clientUserID, topLevelSyncJSON) - } -} - -// Check that `userID` gets joined to `roomID` by inspecting the join timeline for a membership event. -// -// Additional checks can be passed to narrow down the check, all must pass. -func SyncJoinedTo(userID, roomID string, checks ...func(gjson.Result) bool) SyncCheckOpt { - checkJoined := func(ev gjson.Result) bool { - if ev.Get("type").Str == "m.room.member" && ev.Get("state_key").Str == userID && ev.Get("content.membership").Str == "join" { - for _, check := range checks { - if !check(ev) { - // short-circuit, bail early - return false - } - } - // passed both basic join check and all other checks - return true - } - return false - } - return func(clientUserID string, topLevelSyncJSON gjson.Result) error { - // Check both the timeline and the state events for the join event - // since on initial sync, the state events may only be in - // .state.events. - firstErr := loopArray( - topLevelSyncJSON, "rooms.join."+GjsonEscape(roomID)+".timeline.events", checkJoined, - ) - if firstErr == nil { - return nil - } - - secondErr := loopArray( - topLevelSyncJSON, "rooms.join."+GjsonEscape(roomID)+".state.events", checkJoined, - ) - if secondErr == nil { - return nil - } - return fmt.Errorf("SyncJoinedTo(%s): %s & %s", roomID, firstErr, secondErr) - } -} - -// Check that `userID` is leaving `roomID` by inspecting the timeline for a membership event, or witnessing `roomID` in `rooms.leave` -// Note: This will not work properly with initial syncs, see https://github.com/matrix-org/matrix-doc/issues/3537 -func SyncLeftFrom(userID, roomID string) SyncCheckOpt { - return func(clientUserID string, topLevelSyncJSON gjson.Result) error { - // two forms which depend on what the client user is: - // - passively viewing a membership for a room you're joined in - // - actively leaving the room - if clientUserID == userID { - // active - events := topLevelSyncJSON.Get("rooms.leave." + GjsonEscape(roomID)) - if !events.Exists() { - return fmt.Errorf("no leave section for room %s", roomID) - } else { - return nil - } - } - // passive - return SyncTimelineHas(roomID, func(ev gjson.Result) bool { - return ev.Get("type").Str == "m.room.member" && ev.Get("state_key").Str == userID && ev.Get("content.membership").Str == "leave" - })(clientUserID, topLevelSyncJSON) - } -} - -// Calls the `check` function for each global account data event, and returns with success if the -// `check` function returns true for at least one event. -func SyncGlobalAccountDataHas(check func(gjson.Result) bool) SyncCheckOpt { - return func(clientUserID string, topLevelSyncJSON gjson.Result) error { - return loopArray(topLevelSyncJSON, "account_data.events", check) - } -} - -// Calls the `check` function for each account data event for the given room, -// and returns with success if the `check` function returns true for at least -// one event. -func SyncRoomAccountDataHas(roomID string, check func(gjson.Result) bool) SyncCheckOpt { - return func(clientUserID string, topLevelSyncJSON gjson.Result) error { - err := loopArray( - topLevelSyncJSON, "rooms.join."+GjsonEscape(roomID)+".account_data.events", check, - ) - if err == nil { - return nil - } - return fmt.Errorf("SyncRoomAccountDataHas(%s): %s", roomID, err) - } -} - -func loopArray(object gjson.Result, key string, check func(gjson.Result) bool) error { - array := object.Get(key) - if !array.Exists() { - return fmt.Errorf("Key %s does not exist", key) - } - if !array.IsArray() { - return fmt.Errorf("Key %s exists but it isn't an array", key) - } - goArray := array.Array() - for _, ev := range goArray { - if check(ev) { - return nil - } - } - return fmt.Errorf("check function did not pass while iterating over %d elements: %v", len(goArray), array.Raw) -} - -// Splits an MXC URI into its origin and media ID parts -func SplitMxc(mxcUri string) (string, string) { - mxcParts := strings.Split(strings.TrimPrefix(mxcUri, "mxc://"), "/") - origin := mxcParts[0] - mediaId := strings.Join(mxcParts[1:], "/") - - return origin, mediaId -} - -// SendToDeviceMessages sends to-device messages over /sendToDevice/. -// -// The messages parameter is nested as follows: -// user_id -> device_id -> content (map[string]interface{}) -func (c *CSAPI) SendToDeviceMessages(t *testing.T, evType string, messages map[string]map[string]map[string]interface{}) { - t.Helper() - txnID := int(atomic.AddInt64(&c.txnID, 1)) - c.MustDoFunc( - t, - "PUT", - []string{"_matrix", "client", "v3", "sendToDevice", evType, strconv.Itoa(txnID)}, - WithJSONBody( - t, - map[string]map[string]map[string]map[string]interface{}{ - "messages": messages, - }, - ), - ) -} - -// Check that sync has received a to-device message, -// with optional user filtering. -// -// If fromUser == "", all messages will be passed through to the check function. -// `check` will be called for all messages that have passed the filter. -// -// `check` gets passed the full event, including sender and type. -func SyncToDeviceHas(fromUser string, check func(gjson.Result) bool) SyncCheckOpt { - return func(clientUserID string, topLevelSyncJSON gjson.Result) error { - err := loopArray( - topLevelSyncJSON, "to_device.events", func(result gjson.Result) bool { - if fromUser != "" && result.Get("sender").Str != fromUser { - return false - } else { - return check(result) - } - }, - ) - if err == nil { - return nil - } - return fmt.Errorf("SyncToDeviceHas(%v): %s", fromUser, err) - } -} diff --git a/internal/docker/deployment.go b/internal/docker/deployment.go index cefb2404..00b0dc2f 100644 --- a/internal/docker/deployment.go +++ b/internal/docker/deployment.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/matrix-org/complement/internal/client" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/config" ) diff --git a/internal/federation/server.go b/internal/federation/server.go index c82827a7..448db2c8 100644 --- a/internal/federation/server.go +++ b/internal/federation/server.go @@ -29,7 +29,6 @@ import ( "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/util" - "github.com/matrix-org/complement/internal/b" "github.com/matrix-org/complement/internal/config" "github.com/matrix-org/complement/internal/docker" ) @@ -162,7 +161,7 @@ func (s *Server) MakeAliasMapping(aliasLocalpart, roomID string) string { // MustMakeRoom will add a room to this server so it is accessible to other servers when prompted via federation. // The `events` will be added to this room. Returns the created room. -func (s *Server) MustMakeRoom(t *testing.T, roomVer gomatrixserverlib.RoomVersion, events []b.Event) *ServerRoom { +func (s *Server) MustMakeRoom(t *testing.T, roomVer gomatrixserverlib.RoomVersion, events []Event) *ServerRoom { if !s.listening { s.t.Fatalf("MustMakeRoom() called before Listen() - this is not supported because Listen() chooses a high-numbered port and thus changes the server name and thus changes the room ID. Ensure you Listen() first!") } @@ -291,7 +290,7 @@ func (s *Server) DoFederationRequest( // MustCreateEvent will create and sign a new latest event for the given room. // It does not insert this event into the room however. See ServerRoom.AddEvent for that. -func (s *Server) MustCreateEvent(t *testing.T, room *ServerRoom, ev b.Event) gomatrixserverlib.PDU { +func (s *Server) MustCreateEvent(t *testing.T, room *ServerRoom, ev Event) gomatrixserverlib.PDU { t.Helper() content, err := json.Marshal(ev.Content) if err != nil { @@ -451,7 +450,7 @@ func (s *Server) MustLeaveRoom(t *testing.T, deployment *docker.Deployment, remo } } else { // make the leave event - leaveEvent = s.MustCreateEvent(t, room, b.Event{ + leaveEvent = s.MustCreateEvent(t, room, Event{ Type: "m.room.member", StateKey: &userID, Sender: userID, diff --git a/internal/federation/server_room.go b/internal/federation/server_room.go index 82e1ef7f..a0b46c55 100644 --- a/internal/federation/server_room.go +++ b/internal/federation/server_room.go @@ -11,6 +11,24 @@ import ( "github.com/matrix-org/complement/internal/b" ) +type Event struct { + Type string + Sender string + StateKey *string + Content map[string]interface{} + + Unsigned map[string]interface{} + // The events needed to authenticate this event. + // This can be either []EventReference for room v1/v2, or []string for room v3 onwards. + // If it is left at nil, MustCreateEvent will populate it automatically based on the room state. + AuthEvents interface{} + // The prev events of the event if we want to override or falsify them. + // If it is left at nil, MustCreateEvent will populate it automatically based on the forward extremities. + PrevEvents interface{} + // If this is a redaction, the event that it redacts + Redacts string +} + // ServerRoom represents a room on this test federation server type ServerRoom struct { Version gomatrixserverlib.RoomVersion @@ -212,13 +230,13 @@ func initialPowerLevelsContent(roomCreator string) (c gomatrixserverlib.PowerLev } // InitialRoomEvents returns the initial set of events that get created when making a room. -func InitialRoomEvents(roomVer gomatrixserverlib.RoomVersion, creator string) []b.Event { +func InitialRoomEvents(roomVer gomatrixserverlib.RoomVersion, creator string) []Event { // need to serialise/deserialise to get map[string]interface{} annoyingly plContent := initialPowerLevelsContent(creator) plBytes, _ := json.Marshal(plContent) var plContentMap map[string]interface{} json.Unmarshal(plBytes, &plContentMap) - return []b.Event{ + return []Event{ { Type: "m.room.create", StateKey: b.Ptr(""), diff --git a/tests/csapi/account_change_password_pushers_test.go b/tests/csapi/account_change_password_pushers_test.go index 3291fc88..38a1d0d5 100644 --- a/tests/csapi/account_change_password_pushers_test.go +++ b/tests/csapi/account_change_password_pushers_test.go @@ -6,8 +6,8 @@ package csapi_tests import ( "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" @@ -37,13 +37,13 @@ func TestChangePasswordPushers(t *testing.T) { "lang": "en", }) - _ = sessionOptional.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "pushers", "set"}, reqBody) + _ = sessionOptional.MustDo(t, "POST", []string{"_matrix", "client", "v3", "pushers", "set"}, reqBody) changePassword(t, passwordClient, password1, password2) pushersSize := 0 - res := passwordClient.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "pushers"}) + res := passwordClient.Do(t, "GET", []string{"_matrix", "client", "v3", "pushers"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, JSON: []match.JSON{ @@ -73,13 +73,13 @@ func TestChangePasswordPushers(t *testing.T) { "lang": "en", }) - _ = passwordClient.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "pushers", "set"}, reqBody) + _ = passwordClient.MustDo(t, "POST", []string{"_matrix", "client", "v3", "pushers", "set"}, reqBody) changePassword(t, passwordClient, password2, password1) pushersSize := 0 - res := passwordClient.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "pushers"}) + res := passwordClient.Do(t, "GET", []string{"_matrix", "client", "v3", "pushers"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, JSON: []match.JSON{ diff --git a/tests/csapi/account_change_password_test.go b/tests/csapi/account_change_password_test.go index 2369f793..736bfe5c 100644 --- a/tests/csapi/account_change_password_test.go +++ b/tests/csapi/account_change_password_test.go @@ -4,8 +4,8 @@ import ( "io/ioutil" "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/docker" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" @@ -34,7 +34,7 @@ func TestChangePassword(t *testing.T) { "type": "m.login.password", "password": password1, }) - res := unauthedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "login"}, reqBody) + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "login"}, reqBody) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 403, JSON: []match.JSON{ @@ -53,7 +53,7 @@ func TestChangePassword(t *testing.T) { "type": "m.login.password", "password": password2, }) - res := unauthedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "login"}, reqBody) + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "login"}, reqBody) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, JSON: []match.JSON{ @@ -63,14 +63,14 @@ func TestChangePassword(t *testing.T) { }) // sytest: After changing password, existing session still works t.Run("After changing password, existing session still works", func(t *testing.T) { - res := passwordClient.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "account", "whoami"}) + res := passwordClient.Do(t, "GET", []string{"_matrix", "client", "v3", "account", "whoami"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, }) }) // sytest: After changing password, a different session no longer works by default t.Run("After changing password, a different session no longer works by default", func(t *testing.T) { - res := sessionTest.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "account", "whoami"}) + res := sessionTest.Do(t, "GET", []string{"_matrix", "client", "v3", "account", "whoami"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 401, }) @@ -89,12 +89,12 @@ func TestChangePassword(t *testing.T) { "logout_devices": false, }) - res := passwordClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "account", "password"}, reqBody) + res := passwordClient.Do(t, "POST", []string{"_matrix", "client", "v3", "account", "password"}, reqBody) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, }) - res = sessionOptional.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "account", "whoami"}) + res = sessionOptional.Do(t, "GET", []string{"_matrix", "client", "v3", "account", "whoami"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, @@ -113,7 +113,7 @@ func changePassword(t *testing.T, passwordClient *client.CSAPI, oldPassword stri "new_password": newPassword, }) - res := passwordClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "account", "password"}, reqBody) + res := passwordClient.Do(t, "POST", []string{"_matrix", "client", "v3", "account", "password"}, reqBody) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, @@ -130,7 +130,7 @@ func createSession(t *testing.T, deployment *docker.Deployment, userID, password "type": "m.login.password", "password": password, }) - res := authedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "login"}, reqBody) + res := authedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "login"}, reqBody) body, err := ioutil.ReadAll(res.Body) if err != nil { t.Fatalf("unable to read response body: %v", err) diff --git a/tests/csapi/account_deactivate_test.go b/tests/csapi/account_deactivate_test.go index e2faeb45..95982e73 100644 --- a/tests/csapi/account_deactivate_test.go +++ b/tests/csapi/account_deactivate_test.go @@ -6,8 +6,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -23,7 +23,7 @@ func TestDeactivateAccount(t *testing.T) { // at least one auth flow involving a password. t.Run("Password flow is available", func(t *testing.T) { reqBody := client.WithJSONBody(t, map[string]interface{}{}) - res := authedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "account", "deactivate"}, reqBody) + res := authedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "account", "deactivate"}, reqBody) rawBody := must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 401, @@ -97,7 +97,7 @@ func TestDeactivateAccount(t *testing.T) { "type": "m.login.password", "password": password, }) - res := unauthedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "login"}, reqBody) + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "login"}, reqBody) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 403, }) @@ -114,7 +114,7 @@ func deactivateAccount(t *testing.T, authedClient *client.CSAPI, password string }, }) - res := authedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "account", "deactivate"}, reqBody) + res := authedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "account", "deactivate"}, reqBody) return res } diff --git a/tests/csapi/admin_test.go b/tests/csapi/admin_test.go index 1c8d47bf..df844df4 100644 --- a/tests/csapi/admin_test.go +++ b/tests/csapi/admin_test.go @@ -7,8 +7,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -40,7 +40,7 @@ func TestServerNotices(t *testing.T) { roomID string ) t.Run("/send_server_notice is not allowed as normal user", func(t *testing.T) { - res := alice.DoFunc(t, "POST", []string{"_synapse", "admin", "v1", "send_server_notice"}) + res := alice.Do(t, "POST", []string{"_synapse", "admin", "v1", "send_server_notice"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusForbidden, JSON: []match.JSON{ @@ -55,7 +55,7 @@ func TestServerNotices(t *testing.T) { roomID = syncUntilInvite(t, alice) }) t.Run("Alice cannot reject the invite", func(t *testing.T) { - res := alice.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "leave"}) + res := alice.Do(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "leave"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusForbidden, JSON: []match.JSON{ @@ -91,9 +91,9 @@ func TestServerNotices(t *testing.T) { func sendServerNotice(t *testing.T, admin *client.CSAPI, reqBody client.RequestOpt, txnID *string) (eventID string) { var res *http.Response if txnID != nil { - res = admin.MustDoFunc(t, "PUT", []string{"_synapse", "admin", "v1", "send_server_notice", *txnID}, reqBody) + res = admin.MustDo(t, "PUT", []string{"_synapse", "admin", "v1", "send_server_notice", *txnID}, reqBody) } else { - res = admin.MustDoFunc(t, "POST", []string{"_synapse", "admin", "v1", "send_server_notice"}, reqBody) + res = admin.MustDo(t, "POST", []string{"_synapse", "admin", "v1", "send_server_notice"}, reqBody) } body := must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, diff --git a/tests/csapi/apidoc_device_management_test.go b/tests/csapi/apidoc_device_management_test.go index a0fe3fc3..72204b56 100644 --- a/tests/csapi/apidoc_device_management_test.go +++ b/tests/csapi/apidoc_device_management_test.go @@ -5,8 +5,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -30,9 +30,9 @@ func TestDeviceManagement(t *testing.T) { "device_id": deviceID, "initial_device_display_name": "device display", }) - _ = unauthedClient.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "login"}, reqBody) + _ = unauthedClient.MustDo(t, "POST", []string{"_matrix", "client", "v3", "login"}, reqBody) - res := authedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "devices", deviceID}) + res := authedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "devices", deviceID}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ @@ -45,7 +45,7 @@ func TestDeviceManagement(t *testing.T) { // sytest: GET /device/{deviceId} gives a 404 for unknown devices t.Run("GET /device/{deviceId} gives a 404 for unknown devices", func(t *testing.T) { - res := authedClient.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "devices", "unknown_device"}) + res := authedClient.Do(t, "GET", []string{"_matrix", "client", "v3", "devices", "unknown_device"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 404, @@ -66,13 +66,13 @@ func TestDeviceManagement(t *testing.T) { "device_id": deviceIDSecond, "initial_device_display_name": "device display", }) - _ = unauthedClient.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "login"}, reqBody) + _ = unauthedClient.MustDo(t, "POST", []string{"_matrix", "client", "v3", "login"}, reqBody) wantDeviceIDs := map[string]bool{ deviceID: true, deviceIDSecond: true, } - res := authedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "devices"}) + res := authedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "devices"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, JSON: []match.JSON{ @@ -97,9 +97,9 @@ func TestDeviceManagement(t *testing.T) { reqBody := client.WithJSONBody(t, map[string]interface{}{ "display_name": "new device display", }) - _ = authedClient.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "devices", deviceID}, reqBody) + _ = authedClient.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "devices", deviceID}, reqBody) - res := authedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "devices", deviceID}) + res := authedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "devices", deviceID}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ @@ -114,7 +114,7 @@ func TestDeviceManagement(t *testing.T) { reqBody := client.WithJSONBody(t, map[string]interface{}{ "display_name": "new device display", }) - res := authedClient.DoFunc(t, "PUT", []string{"_matrix", "client", "v3", "devices", "unknown_device"}, reqBody) + res := authedClient.Do(t, "PUT", []string{"_matrix", "client", "v3", "devices", "unknown_device"}, reqBody) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 404, @@ -127,7 +127,7 @@ func TestDeviceManagement(t *testing.T) { session2.MustSync(t, client.SyncReq{}) // sytest: DELETE /device/{deviceId} with no body gives a 401 - res := authedClient.DoFunc(t, "DELETE", []string{"_matrix", "client", "v3", "devices", newDeviceID}) + res := authedClient.Do(t, "DELETE", []string{"_matrix", "client", "v3", "devices", newDeviceID}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 401, JSON: []match.JSON{ @@ -149,7 +149,7 @@ func TestDeviceManagement(t *testing.T) { }, }) - res = authedClient.DoFunc(t, "DELETE", []string{"_matrix", "client", "v3", "devices", newDeviceID}, reqBody) + res = authedClient.Do(t, "DELETE", []string{"_matrix", "client", "v3", "devices", newDeviceID}, reqBody) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 401, JSON: []match.JSON{ @@ -174,19 +174,19 @@ func TestDeviceManagement(t *testing.T) { }, }) - res = authedClient.DoFunc(t, "DELETE", []string{"_matrix", "client", "v3", "devices", newDeviceID}, reqBody) + res = authedClient.Do(t, "DELETE", []string{"_matrix", "client", "v3", "devices", newDeviceID}, reqBody) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, }) // verify device is deleted - res = authedClient.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "devices", newDeviceID}) + res = authedClient.Do(t, "GET", []string{"_matrix", "client", "v3", "devices", newDeviceID}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 404, }) // check that the accesstoken is invalidated - res = session2.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "sync"}) + res = session2.Do(t, "GET", []string{"_matrix", "client", "v3", "sync"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 401, }) @@ -210,13 +210,13 @@ func TestDeviceManagement(t *testing.T) { }, }) - res := authedClient.DoFunc(t, "DELETE", []string{"_matrix", "client", "v3", "devices", newDeviceID}, reqBody) + res := authedClient.Do(t, "DELETE", []string{"_matrix", "client", "v3", "devices", newDeviceID}, reqBody) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 403, }) // verify device still exists - res = authedClient.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "devices", newDeviceID}) + res = authedClient.Do(t, "GET", []string{"_matrix", "client", "v3", "devices", newDeviceID}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, }) @@ -233,13 +233,13 @@ func TestDeviceManagement(t *testing.T) { }, }) - res = authedClient.DoFunc(t, "DELETE", []string{"_matrix", "client", "v3", "devices", newDeviceID}, reqBody) + res = authedClient.Do(t, "DELETE", []string{"_matrix", "client", "v3", "devices", newDeviceID}, reqBody) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, }) // verify device is deleted - res = authedClient.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "devices", newDeviceID}) + res = authedClient.Do(t, "GET", []string{"_matrix", "client", "v3", "devices", newDeviceID}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 404, }) diff --git a/tests/csapi/apidoc_login_test.go b/tests/csapi/apidoc_login_test.go index fe11e3ae..d2319e35 100644 --- a/tests/csapi/apidoc_login_test.go +++ b/tests/csapi/apidoc_login_test.go @@ -7,8 +7,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -22,7 +22,7 @@ func TestLogin(t *testing.T) { // sytest: GET /login yields a set of flows t.Run("GET /login yields a set of flows", func(t *testing.T) { t.Parallel() - res := unauthedClient.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "login"}, client.WithRawBody(json.RawMessage(`{}`))) + res := unauthedClient.Do(t, "GET", []string{"_matrix", "client", "v3", "login"}, client.WithRawBody(json.RawMessage(`{}`))) must.MatchResponse(t, res, match.HTTPResponse{ Headers: map[string]string{ "Content-Type": "application/json", @@ -43,7 +43,7 @@ func TestLogin(t *testing.T) { // sytest: POST /login can log in as a user t.Run("POST /login can login as user", func(t *testing.T) { t.Parallel() - res := unauthedClient.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "login"}, client.WithRawBody(json.RawMessage(`{ + res := unauthedClient.MustDo(t, "POST", []string{"_matrix", "client", "v3", "login"}, client.WithRawBody(json.RawMessage(`{ "type": "m.login.password", "identifier": { "type": "m.id.user", @@ -62,7 +62,7 @@ func TestLogin(t *testing.T) { t.Run("POST /login returns the same device_id as that in the request", func(t *testing.T) { t.Parallel() deviceID := "test_device_id" - res := unauthedClient.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "login"}, client.WithRawBody(json.RawMessage(`{ + res := unauthedClient.MustDo(t, "POST", []string{"_matrix", "client", "v3", "login"}, client.WithRawBody(json.RawMessage(`{ "type": "m.login.password", "identifier": { "type": "m.id.user", @@ -83,7 +83,7 @@ func TestLogin(t *testing.T) { t.Run("POST /login can log in as a user with just the local part of the id", func(t *testing.T) { t.Parallel() - res := unauthedClient.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "login"}, client.WithRawBody(json.RawMessage(`{ + res := unauthedClient.MustDo(t, "POST", []string{"_matrix", "client", "v3", "login"}, client.WithRawBody(json.RawMessage(`{ "type": "m.login.password", "identifier": { "type": "m.id.user", @@ -101,7 +101,7 @@ func TestLogin(t *testing.T) { // sytest: POST /login as non-existing user is rejected t.Run("POST /login as non-existing user is rejected", func(t *testing.T) { t.Parallel() - res := unauthedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "login"}, client.WithRawBody(json.RawMessage(`{ + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "login"}, client.WithRawBody(json.RawMessage(`{ "type": "m.login.password", "identifier": { "type": "m.id.user", @@ -116,7 +116,7 @@ func TestLogin(t *testing.T) { // sytest: POST /login wrong password is rejected t.Run("POST /login wrong password is rejected", func(t *testing.T) { t.Parallel() - res := unauthedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "login"}, client.WithRawBody(json.RawMessage(`{ + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "login"}, client.WithRawBody(json.RawMessage(`{ "type": "m.login.password", "identifier": { "type": "m.id.user", @@ -136,7 +136,7 @@ func TestLogin(t *testing.T) { t.Run("Login with uppercase username works and GET /whoami afterwards also", func(t *testing.T) { t.Parallel() // login should be possible with uppercase username - res := unauthedClient.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "login"}, client.WithRawBody(json.RawMessage(`{ + res := unauthedClient.MustDo(t, "POST", []string{"_matrix", "client", "v3", "login"}, client.WithRawBody(json.RawMessage(`{ "type": "m.login.password", "identifier": { "type": "m.id.user", @@ -151,7 +151,7 @@ func TestLogin(t *testing.T) { unauthedClient.UserID = js.Get("user_id").Str unauthedClient.AccessToken = js.Get("access_token").Str // check that we can successfully query /whoami - unauthedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "account", "whoami"}) + unauthedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "account", "whoami"}) }) }) } diff --git a/tests/csapi/apidoc_logout_test.go b/tests/csapi/apidoc_logout_test.go index 2b9afbb0..49b94c84 100644 --- a/tests/csapi/apidoc_logout_test.go +++ b/tests/csapi/apidoc_logout_test.go @@ -22,18 +22,18 @@ func TestLogout(t *testing.T) { // sytest: Can logout current device t.Run("Can logout current device", func(t *testing.T) { deviceID, clientToLogout := createSession(t, deployment, verifyClientUser.UserID, password) - res := clientToLogout.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "devices"}) + res := clientToLogout.MustDo(t, "GET", []string{"_matrix", "client", "v3", "devices"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONKeyArrayOfSize("devices", 2), }, }) - res = clientToLogout.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "logout"}) + res = clientToLogout.MustDo(t, "POST", []string{"_matrix", "client", "v3", "logout"}) // the session should be invalidated - res = clientToLogout.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "sync"}) + res = clientToLogout.Do(t, "GET", []string{"_matrix", "client", "v3", "sync"}) must.MatchResponse(t, res, match.HTTPResponse{StatusCode: http.StatusUnauthorized}) // verify with first device - res = verifyClientUser.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "devices"}) + res = verifyClientUser.MustDo(t, "GET", []string{"_matrix", "client", "v3", "devices"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONKeyArrayOfSize("devices", 1), @@ -49,25 +49,25 @@ func TestLogout(t *testing.T) { // sytest: Can logout all devices t.Run("Can logout all devices", func(t *testing.T) { _, clientToLogout := createSession(t, deployment, verifyClientUser.UserID, password) - res := clientToLogout.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "devices"}) + res := clientToLogout.MustDo(t, "GET", []string{"_matrix", "client", "v3", "devices"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONKeyArrayOfSize("devices", 2), }, }) - res = clientToLogout.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "logout", "all"}) + res = clientToLogout.MustDo(t, "POST", []string{"_matrix", "client", "v3", "logout", "all"}) must.MatchResponse(t, res, match.HTTPResponse{StatusCode: http.StatusOK}) // all sessions should be invalidated - res = clientToLogout.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "sync"}) + res = clientToLogout.Do(t, "GET", []string{"_matrix", "client", "v3", "sync"}) must.MatchResponse(t, res, match.HTTPResponse{StatusCode: http.StatusUnauthorized}) - res = verifyClientUser.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "sync"}) + res = verifyClientUser.Do(t, "GET", []string{"_matrix", "client", "v3", "sync"}) must.MatchResponse(t, res, match.HTTPResponse{StatusCode: http.StatusUnauthorized}) }) // sytest: Request to logout with invalid an access token is rejected t.Run("Request to logout with invalid an access token is rejected", func(t *testing.T) { _, clientToLogout := createSession(t, deployment, verifyClientUser.UserID, password) clientToLogout.AccessToken = "invalidAccessToken" - res := clientToLogout.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "logout"}) + res := clientToLogout.Do(t, "POST", []string{"_matrix", "client", "v3", "logout"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusUnauthorized, JSON: []match.JSON{ @@ -79,7 +79,7 @@ func TestLogout(t *testing.T) { t.Run("Request to logout without an access token is rejected", func(t *testing.T) { _, clientToLogout := createSession(t, deployment, verifyClientUser.UserID, password) clientToLogout.AccessToken = "" - res := clientToLogout.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "logout"}) + res := clientToLogout.Do(t, "POST", []string{"_matrix", "client", "v3", "logout"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusUnauthorized, JSON: []match.JSON{ diff --git a/tests/csapi/apidoc_presence_test.go b/tests/csapi/apidoc_presence_test.go index 95a5f763..274460da 100644 --- a/tests/csapi/apidoc_presence_test.go +++ b/tests/csapi/apidoc_presence_test.go @@ -1,3 +1,4 @@ +//go:build !dendrite_blacklist // +build !dendrite_blacklist // Rationale for being included in Dendrite's blacklist: https://github.com/matrix-org/complement/pull/104#discussion_r617646624 @@ -9,8 +10,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -24,7 +25,7 @@ func TestPresence(t *testing.T) { // sytest: GET /presence/:user_id/status fetches initial status t.Run("GET /presence/:user_id/status fetches initial status", func(t *testing.T) { - res := alice.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "presence", "@alice:hs1", "status"}) + res := alice.Do(t, "GET", []string{"_matrix", "client", "v3", "presence", "@alice:hs1", "status"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONKeyPresent("presence"), @@ -38,11 +39,11 @@ func TestPresence(t *testing.T) { "status_msg": statusMsg, "presence": "online", }) - res := alice.DoFunc(t, "PUT", []string{"_matrix", "client", "v3", "presence", "@alice:hs1", "status"}, reqBody) + res := alice.Do(t, "PUT", []string{"_matrix", "client", "v3", "presence", "@alice:hs1", "status"}, reqBody) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, }) - res = alice.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "presence", "@alice:hs1", "status"}) + res = alice.Do(t, "GET", []string{"_matrix", "client", "v3", "presence", "@alice:hs1", "status"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONKeyPresent("presence"), @@ -63,7 +64,7 @@ func TestPresence(t *testing.T) { _, bobSinceToken := bob.MustSync(t, client.SyncReq{TimeoutMillis: "0"}) statusMsg := "Update for room members" - alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "presence", "@alice:hs1", "status"}, + alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "presence", "@alice:hs1", "status"}, client.WithJSONBody(t, map[string]interface{}{ "status_msg": statusMsg, "presence": "online", @@ -80,7 +81,7 @@ func TestPresence(t *testing.T) { t.Run("Presence changes to UNAVAILABLE are reported to local room members", func(t *testing.T) { _, bobSinceToken := bob.MustSync(t, client.SyncReq{TimeoutMillis: "0"}) - alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "presence", "@alice:hs1", "status"}, + alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "presence", "@alice:hs1", "status"}, client.WithJSONBody(t, map[string]interface{}{ "presence": "unavailable", }), diff --git a/tests/csapi/apidoc_profile_avatar_url_test.go b/tests/csapi/apidoc_profile_avatar_url_test.go index b8c41261..bafdb429 100644 --- a/tests/csapi/apidoc_profile_avatar_url_test.go +++ b/tests/csapi/apidoc_profile_avatar_url_test.go @@ -3,8 +3,8 @@ package csapi_tests import ( "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -20,7 +20,7 @@ func TestProfileAvatarURL(t *testing.T) { reqBody := client.WithJSONBody(t, map[string]interface{}{ "avatar_url": avatarURL, }) - res := authedClient.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "profile", authedClient.UserID, "avatar_url"}, reqBody) + res := authedClient.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "profile", authedClient.UserID, "avatar_url"}, reqBody) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, @@ -29,7 +29,7 @@ func TestProfileAvatarURL(t *testing.T) { // sytest: GET /profile/:user_id/avatar_url publicly accessible t.Run("GET /profile/:user_id/avatar_url publicly accessible", func(t *testing.T) { - res := unauthedClient.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "profile", authedClient.UserID, "avatar_url"}) + res := unauthedClient.Do(t, "GET", []string{"_matrix", "client", "v3", "profile", authedClient.UserID, "avatar_url"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, diff --git a/tests/csapi/apidoc_profile_displayname_test.go b/tests/csapi/apidoc_profile_displayname_test.go index 09545411..58eeebb4 100644 --- a/tests/csapi/apidoc_profile_displayname_test.go +++ b/tests/csapi/apidoc_profile_displayname_test.go @@ -3,8 +3,8 @@ package csapi_tests import ( "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -20,11 +20,11 @@ func TestProfileDisplayName(t *testing.T) { reqBody := client.WithJSONBody(t, map[string]interface{}{ "displayname": displayName, }) - _ = authedClient.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "profile", authedClient.UserID, "displayname"}, reqBody) + _ = authedClient.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "profile", authedClient.UserID, "displayname"}, reqBody) }) // sytest: GET /profile/:user_id/displayname publicly accessible t.Run("GET /profile/:user_id/displayname publicly accessible", func(t *testing.T) { - res := unauthedClient.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "profile", authedClient.UserID, "displayname"}) + res := unauthedClient.Do(t, "GET", []string{"_matrix", "client", "v3", "profile", authedClient.UserID, "displayname"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, JSON: []match.JSON{ diff --git a/tests/csapi/apidoc_register_test.go b/tests/csapi/apidoc_register_test.go index bed7d72d..f62703fc 100644 --- a/tests/csapi/apidoc_register_test.go +++ b/tests/csapi/apidoc_register_test.go @@ -13,8 +13,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -42,7 +42,7 @@ func TestRegistration(t *testing.T) { // The name in Sytest is different, the test is actually doing a POST request. t.Run("POST {} returns a set of flows", func(t *testing.T) { t.Parallel() - res := unauthedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(`{}`))) + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(`{}`))) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 401, Headers: map[string]string{ @@ -61,7 +61,7 @@ func TestRegistration(t *testing.T) { // sytest: POST /register can create a user t.Run("POST /register can create a user", func(t *testing.T) { t.Parallel() - res := unauthedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(`{ + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(`{ "auth": { "type": "m.login.dummy" }, @@ -78,7 +78,7 @@ func TestRegistration(t *testing.T) { // sytest: POST /register downcases capitals in usernames t.Run("POST /register downcases capitals in usernames", func(t *testing.T) { t.Parallel() - res := unauthedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(`{ + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(`{ "auth": { "type": "m.login.dummy" }, @@ -96,7 +96,7 @@ func TestRegistration(t *testing.T) { t.Run("POST /register returns the same device_id as that in the request", func(t *testing.T) { t.Parallel() deviceID := "my_device_id" - res := unauthedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(`{ + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(`{ "auth": { "type": "m.login.dummy" }, @@ -132,7 +132,7 @@ func TestRegistration(t *testing.T) { `'`, } for _, ch := range specialChars { - res := unauthedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "register"}, + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithJSONBody(t, map[string]interface{}{ "auth": map[string]string{ "type": "m.login.dummy", @@ -150,7 +150,7 @@ func TestRegistration(t *testing.T) { }) t.Run("POST /register rejects if user already exists", func(t *testing.T) { t.Parallel() - res := unauthedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(`{ + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(`{ "auth": { "type": "m.login.dummy" }, @@ -163,7 +163,7 @@ func TestRegistration(t *testing.T) { match.JSONKeyTypeEqual("user_id", gjson.String), }, }) - res = unauthedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(`{ + res = unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(`{ "auth": { "type": "m.login.dummy" }, @@ -232,7 +232,7 @@ func TestRegistration(t *testing.T) { "password": "übers3kr1t", "device_id": "xyzzy", "initial_device_display_name": "display_name"} - resp := unauthedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithJSONBody(t, reqJson)) + resp := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithJSONBody(t, reqJson)) body, err := ioutil.ReadAll(resp.Body) session := gjson.GetBytes(body, "session") if err != nil { @@ -250,7 +250,7 @@ func TestRegistration(t *testing.T) { "initial_device_display_name": "display_name", "auth": auth, } - resp2 := unauthedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithJSONBody(t, reqBody)) + resp2 := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithJSONBody(t, reqBody)) must.MatchResponse(t, resp2, match.HTTPResponse{JSON: []match.JSON{ match.JSONKeyPresent("access_token"), }}) @@ -259,7 +259,7 @@ func TestRegistration(t *testing.T) { t.Run("GET /register/available returns available for unregistered user name", func(t *testing.T) { t.Parallel() testUserName := "username_should_be_available" - res := unauthedClient.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "register", "available"}, client.WithQueries(url.Values{ + res := unauthedClient.Do(t, "GET", []string{"_matrix", "client", "v3", "register", "available"}, client.WithQueries(url.Values{ "username": []string{testUserName}, })) must.MatchResponse(t, res, match.HTTPResponse{ @@ -275,9 +275,9 @@ func TestRegistration(t *testing.T) { testUserName := "username_not_available" // Don't need the return value here, just need a user to be registered to test against _ = deployment.NewUser(t, testUserName, "hs1") - res := unauthedClient.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "register", "available"}, client.WithQueries(url.Values{ - "username": []string{testUserName}, - })) + res := unauthedClient.Do(t, "GET", []string{"_matrix", "client", "v3", "register", "available"}, client.WithQueries(url.Values{ + "username": []string{testUserName}, + })) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 400, JSON: []match.JSON{ @@ -290,9 +290,9 @@ func TestRegistration(t *testing.T) { t.Run("GET /register/available returns M_INVALID_USERNAME for invalid user name", func(t *testing.T) { t.Parallel() testUserName := "username,should_not_be_valid" - res := unauthedClient.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "register", "available"}, client.WithQueries(url.Values{ - "username": []string{testUserName}, - })) + res := unauthedClient.Do(t, "GET", []string{"_matrix", "client", "v3", "register", "available"}, client.WithQueries(url.Values{ + "username": []string{testUserName}, + })) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 400, JSON: []match.JSON{ @@ -306,7 +306,7 @@ func TestRegistration(t *testing.T) { // registerSharedSecret tries to register using a shared secret, returns the *http.Response func registerSharedSecret(t *testing.T, c *client.CSAPI, user, pass string, isAdmin bool) *http.Response { - resp := c.DoFunc(t, "GET", []string{"_synapse", "admin", "v1", "register"}) + resp := c.Do(t, "GET", []string{"_synapse", "admin", "v1", "register"}) if resp.StatusCode != 200 { t.Skipf("Homeserver image does not support shared secret registration, /_synapse/admin/v1/register returned HTTP %d", resp.StatusCode) return resp @@ -336,6 +336,6 @@ func registerSharedSecret(t *testing.T, c *client.CSAPI, user, pass string, isAd "mac": hex.EncodeToString(sig), "admin": isAdmin, } - resp = c.DoFunc(t, "POST", []string{"_synapse", "admin", "v1", "register"}, client.WithJSONBody(t, reqBody)) + resp = c.Do(t, "POST", []string{"_synapse", "admin", "v1", "register"}, client.WithJSONBody(t, reqBody)) return resp } diff --git a/tests/csapi/apidoc_request_encoding_test.go b/tests/csapi/apidoc_request_encoding_test.go index 969b1299..e65e091c 100644 --- a/tests/csapi/apidoc_request_encoding_test.go +++ b/tests/csapi/apidoc_request_encoding_test.go @@ -5,8 +5,8 @@ import ( "encoding/json" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -18,7 +18,7 @@ func TestRequestEncodingFails(t *testing.T) { testString := `{ "test":"a` + "\x81" + `" }` // sytest: POST rejects invalid utf-8 in JSON t.Run("POST rejects invalid utf-8 in JSON", func(t *testing.T) { - res := unauthedClient.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(testString))) + res := unauthedClient.Do(t, "POST", []string{"_matrix", "client", "v3", "register"}, client.WithRawBody(json.RawMessage(testString))) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 400, JSON: []match.JSON{ diff --git a/tests/csapi/apidoc_room_alias_test.go b/tests/csapi/apidoc_room_alias_test.go index 6b727f91..bb89eec4 100644 --- a/tests/csapi/apidoc_room_alias_test.go +++ b/tests/csapi/apidoc_room_alias_test.go @@ -7,28 +7,28 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) func setRoomAliasResp(t *testing.T, c *client.CSAPI, roomID, roomAlias string) *http.Response { - return c.DoFunc(t, "PUT", []string{"_matrix", "client", "v3", "directory", "room", roomAlias}, client.WithJSONBody(t, map[string]interface{}{ + return c.Do(t, "PUT", []string{"_matrix", "client", "v3", "directory", "room", roomAlias}, client.WithJSONBody(t, map[string]interface{}{ "room_id": roomID, })) } func getRoomAliasResp(t *testing.T, c *client.CSAPI, roomAlias string) *http.Response { - return c.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "directory", "room", roomAlias}) + return c.Do(t, "GET", []string{"_matrix", "client", "v3", "directory", "room", roomAlias}) } func deleteRoomAliasResp(t *testing.T, c *client.CSAPI, roomAlias string) *http.Response { - return c.DoFunc(t, "DELETE", []string{"_matrix", "client", "v3", "directory", "room", roomAlias}) + return c.Do(t, "DELETE", []string{"_matrix", "client", "v3", "directory", "room", roomAlias}) } func listRoomAliasesResp(t *testing.T, c *client.CSAPI, roomID string) *http.Response { - return c.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "aliases"}) + return c.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "aliases"}) } func setCanonicalAliasResp(t *testing.T, c *client.CSAPI, roomID string, roomAlias string, altAliases *[]string) *http.Response { @@ -39,7 +39,7 @@ func setCanonicalAliasResp(t *testing.T, c *client.CSAPI, roomID string, roomAli content["alt_aliases"] = altAliases } - return c.DoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.canonical_alias"}, client.WithJSONBody(t, content)) + return c.Do(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.canonical_alias"}, client.WithJSONBody(t, content)) } func mustSetCanonicalAlias(t *testing.T, c *client.CSAPI, roomID string, roomAlias string, altAliases *[]string) string { @@ -109,7 +109,7 @@ func TestRoomAlias(t *testing.T) { // // If (4) arrives at the reader before (2), the reader responds with // old data. Bodge around this by retrying for up to a second. - res = alice.DoFunc( + res = alice.Do( t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "aliases"}, diff --git a/tests/csapi/apidoc_room_create_test.go b/tests/csapi/apidoc_room_create_test.go index 20d720a7..84d62ac6 100644 --- a/tests/csapi/apidoc_room_create_test.go +++ b/tests/csapi/apidoc_room_create_test.go @@ -5,14 +5,14 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) func doCreateRoom(t *testing.T, c *client.CSAPI, json map[string]interface{}, match match.HTTPResponse) { - res := c.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "createRoom"}, client.WithJSONBody(t, json)) + res := c.Do(t, "POST", []string{"_matrix", "client", "v3", "createRoom"}, client.WithJSONBody(t, json)) must.MatchResponse(t, res, match) } @@ -60,7 +60,7 @@ func TestRoomCreate(t *testing.T) { "topic": "Test Room", "preset": "public_chat", }) - res := alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.topic"}) + res := alice.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.topic"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, JSON: []match.JSON{ @@ -75,7 +75,7 @@ func TestRoomCreate(t *testing.T) { "name": "Test Room", "preset": "public_chat", }) - res := alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.name"}) + res := alice.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.name"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, JSON: []match.JSON{ @@ -90,7 +90,7 @@ func TestRoomCreate(t *testing.T) { "room_version": "2", "preset": "public_chat", }) - res := alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.create"}) + res := alice.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.create"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, JSON: []match.JSON{ diff --git a/tests/csapi/apidoc_room_forget_test.go b/tests/csapi/apidoc_room_forget_test.go index 84aea63c..a7f886d5 100644 --- a/tests/csapi/apidoc_room_forget_test.go +++ b/tests/csapi/apidoc_room_forget_test.go @@ -8,8 +8,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -26,7 +26,7 @@ func TestRoomForget(t *testing.T) { t.Run("Can't forget room you're still in", func(t *testing.T) { t.Parallel() roomID := alice.CreateRoom(t, map[string]interface{}{"preset": "private_chat"}) - res := alice.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) + res := alice.Do(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusBadRequest, JSON: []match.JSON{ @@ -47,8 +47,8 @@ func TestRoomForget(t *testing.T) { }, }) alice.LeaveRoom(t, roomID) - alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) - res := alice.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}) + alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) + res := alice.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusForbidden, JSON: []match.JSON{ @@ -71,7 +71,7 @@ func TestRoomForget(t *testing.T) { alice.LeaveRoom(t, roomID) // Ensure Alice left the room bob.MustSyncUntil(t, client.SyncReq{}, client.SyncLeftFrom(alice.UserID, roomID)) - alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) + alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) bob.SendEventSynced(t, roomID, b.Event{ Type: "m.room.message", Content: map[string]interface{}{ @@ -117,7 +117,7 @@ func TestRoomForget(t *testing.T) { alice.LeaveRoom(t, roomID) // Ensure Alice left the room bob.MustSyncUntil(t, client.SyncReq{}, client.SyncLeftFrom(alice.UserID, roomID)) - alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) + alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) bob.SendEventSynced(t, roomID, b.Event{ Type: "m.room.message", Content: map[string]interface{}{ @@ -152,7 +152,7 @@ func TestRoomForget(t *testing.T) { }, }) // Kick Bob - alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "kick"}, + alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "kick"}, client.WithJSONBody(t, map[string]interface{}{ "user_id": bob.UserID, }), @@ -197,9 +197,9 @@ func TestRoomForget(t *testing.T) { bob.LeaveRoom(t, roomID) // Ensure Bob has really left the room alice.MustSyncUntil(t, client.SyncReq{}, client.SyncLeftFrom(bob.UserID, roomID)) - bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) + bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) // Try to re-join - joinRes := bob.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "join", roomID}, client.WithJSONBody(t, struct{}{})) + joinRes := bob.Do(t, "POST", []string{"_matrix", "client", "v3", "join", roomID}, client.WithJSONBody(t, struct{}{})) must.MatchResponse(t, joinRes, match.HTTPResponse{ StatusCode: http.StatusForbidden, JSON: []match.JSON{ @@ -214,7 +214,7 @@ func TestRoomForget(t *testing.T) { queryParams.Set("dir", "b") queryParams.Set("limit", "100") // Check if we can see Bobs previous message - res := bob.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) + res := bob.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) msgRes := &msgResult{} must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, @@ -234,7 +234,7 @@ func TestRoomForget(t *testing.T) { msgRes.found = false // We should now be able to see the new message queryParams.Set("limit", "1") - res = bob.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) + res = bob.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{findMessageId(messageID, msgRes)}, @@ -251,11 +251,11 @@ func TestRoomForget(t *testing.T) { // Bob rejects the invite bob.LeaveRoom(t, roomID) // Bob tries to forget about this room - bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) + bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) // Alice also leaves the room alice.LeaveRoom(t, roomID) // Alice tries to forget about this room - alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) + alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "forget"}, client.WithJSONBody(t, struct{}{})) }) }) } diff --git a/tests/csapi/apidoc_room_history_visibility_test.go b/tests/csapi/apidoc_room_history_visibility_test.go index a8b153d3..3857f20e 100644 --- a/tests/csapi/apidoc_room_history_visibility_test.go +++ b/tests/csapi/apidoc_room_history_visibility_test.go @@ -6,8 +6,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -15,7 +15,7 @@ import ( // TODO most of this can be refactored into data-driven tests func fetchEvent(t *testing.T, c *client.CSAPI, roomId, eventId string) *http.Response { - return c.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomId, "event", eventId}) + return c.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomId, "event", eventId}) } func createRoomWithVisibility(t *testing.T, c *client.CSAPI, visibility string) string { diff --git a/tests/csapi/apidoc_room_members_test.go b/tests/csapi/apidoc_room_members_test.go index 731a151f..c32d5fd5 100644 --- a/tests/csapi/apidoc_room_members_test.go +++ b/tests/csapi/apidoc_room_members_test.go @@ -5,8 +5,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -25,7 +25,7 @@ func TestRoomMembers(t *testing.T) { "preset": "public_chat", }) - res := bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "join"}) + res := bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "join"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ @@ -46,7 +46,7 @@ func TestRoomMembers(t *testing.T) { "room_alias_name": "room_alias_random", }) - res := bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "join", "#room_alias_random:hs1"}) + res := bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "join", "#room_alias_random:hs1"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ @@ -66,7 +66,7 @@ func TestRoomMembers(t *testing.T) { "preset": "public_chat", }) - res := bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "join", roomID}) + res := bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "join", roomID}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ @@ -144,7 +144,7 @@ func TestRoomMembers(t *testing.T) { joinBody := client.WithJSONBody(t, map[string]string{"foo": "bar"}) - res := bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "join", roomID}, joinBody) + res := bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "join", roomID}, joinBody) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ @@ -155,7 +155,7 @@ func TestRoomMembers(t *testing.T) { }) alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, roomID)) - res = alice.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.member", bob.UserID}) + res = alice.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.member", bob.UserID}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ @@ -173,7 +173,7 @@ func TestRoomMembers(t *testing.T) { "room_alias_name": "room_alias_random2", }) joinBody := client.WithJSONBody(t, map[string]string{"foo": "bar"}) - res := bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "join", "#room_alias_random2:hs1"}, joinBody) + res := bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "join", "#room_alias_random2:hs1"}, joinBody) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ @@ -184,7 +184,7 @@ func TestRoomMembers(t *testing.T) { }) alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, roomID)) - res = alice.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.member", bob.UserID}) + res = alice.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.member", bob.UserID}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ @@ -202,7 +202,7 @@ func TestRoomMembers(t *testing.T) { "preset": "public_chat", }) - bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "join", roomID}) + bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "join", roomID}) alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, roomID)) // ban bob from room @@ -210,7 +210,7 @@ func TestRoomMembers(t *testing.T) { "user_id": bob.UserID, "reason": "Testing", }) - res := alice.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "ban"}, banBody) + res := alice.Do(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "ban"}, banBody) must.MatchResponse(t, res, match.HTTPResponse{StatusCode: 200}) alice.MustSyncUntil(t, client.SyncReq{}, client.SyncTimelineHas(roomID, func(ev gjson.Result) bool { if ev.Get("type").Str != "m.room.member" || ev.Get("state_key").Str != bob.UserID { @@ -219,7 +219,7 @@ func TestRoomMembers(t *testing.T) { return ev.Get("content.membership").Str == "ban" })) // verify bob is banned - res = alice.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.member", bob.UserID}) + res = alice.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.member", bob.UserID}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONKeyEqual("membership", "ban"), @@ -233,7 +233,7 @@ func TestRoomMembers(t *testing.T) { roomID := alice.CreateRoom(t, map[string]interface{}{}) alice.InviteRoom(t, roomID, bob.UserID) alice.MustSyncUntil(t, client.SyncReq{}, client.SyncInvitedTo(bob.UserID, roomID)) - res := alice.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.member", bob.UserID}) + res := alice.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.member", bob.UserID}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONKeyEqual("membership", "invite"), @@ -252,7 +252,7 @@ func TestRoomMembers(t *testing.T) { bob.LeaveRoom(t, roomID) alice.MustSyncUntil(t, client.SyncReq{}, client.SyncLeftFrom(bob.UserID, roomID)) - res := alice.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.member", bob.UserID}) + res := alice.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.member", bob.UserID}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONKeyEqual("membership", "leave"), diff --git a/tests/csapi/apidoc_room_receipts_test.go b/tests/csapi/apidoc_room_receipts_test.go index f3a83ffb..3048af1e 100644 --- a/tests/csapi/apidoc_room_receipts_test.go +++ b/tests/csapi/apidoc_room_receipts_test.go @@ -3,8 +3,8 @@ package csapi_tests import ( "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/docker" "github.com/tidwall/gjson" ) @@ -41,7 +41,7 @@ func TestRoomReceipts(t *testing.T) { alice := deployment.Client(t, "hs1", "@alice:hs1") roomID, eventID := createRoomForReadReceipts(t, alice, deployment) - alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "receipt", "m.read", eventID}, client.WithJSONBody(t, struct{}{})) + alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "receipt", "m.read", eventID}, client.WithJSONBody(t, struct{}{})) // Make sure the read receipt shows up in sync. alice.MustSyncUntil(t, client.SyncReq{}, syncHasReadReceipt(roomID, alice.UserID, eventID)) @@ -58,7 +58,7 @@ func TestRoomReadMarkers(t *testing.T) { "m.fully_read": eventID, "m.read": eventID, }) - alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "read_markers"}, reqBody) + alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "read_markers"}, reqBody) // Make sure the read receipt shows up in sync. alice.MustSyncUntil(t, client.SyncReq{}, syncHasReadReceipt(roomID, alice.UserID, eventID)) diff --git a/tests/csapi/apidoc_room_state_test.go b/tests/csapi/apidoc_room_state_test.go index 3355acc1..8e3cb4db 100644 --- a/tests/csapi/apidoc_room_state_test.go +++ b/tests/csapi/apidoc_room_state_test.go @@ -8,8 +8,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -26,7 +26,7 @@ func TestRoomState(t *testing.T) { "visibility": "public", "preset": "public_chat", }) - res := authedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.member", authedClient.UserID}) + res := authedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.member", authedClient.UserID}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONKeyPresent("membership"), @@ -44,7 +44,7 @@ func TestRoomState(t *testing.T) { "visibility": "public", "preset": "public_chat", }) - res := authedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.member", authedClient.UserID}, client.WithQueries(queryParams)) + res := authedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.member", authedClient.UserID}, client.WithQueries(queryParams)) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONKeyPresent("sender"), @@ -65,7 +65,7 @@ func TestRoomState(t *testing.T) { "preset": "public_chat", "room_alias_name": "room_alias", }) - res := authedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.power_levels"}) + res := authedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.power_levels"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ @@ -88,7 +88,7 @@ func TestRoomState(t *testing.T) { "preset": "public_chat", }) - res := authedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "joined_members"}) + res := authedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "joined_members"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONKeyPresent("joined"), @@ -106,7 +106,7 @@ func TestRoomState(t *testing.T) { "preset": "public_chat", }) - authedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "publicRooms"}, + authedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "publicRooms"}, client.WithRetryUntil(time.Second, func(res *http.Response) bool { foundRoom := false @@ -142,7 +142,7 @@ func TestRoomState(t *testing.T) { "room_alias_name": "room_new", }) - res := authedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "directory", "room", "#room_new:hs1"}) + res := authedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "directory", "room", "#room_new:hs1"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ @@ -161,7 +161,7 @@ func TestRoomState(t *testing.T) { "visibility": "public", "preset": "public_chat", }) - res := authedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "joined_rooms"}) + res := authedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "joined_rooms"}) foundRoom := false @@ -193,7 +193,7 @@ func TestRoomState(t *testing.T) { "name": "room_name_test", }) - res := authedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.name"}) + res := authedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.name"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ @@ -215,9 +215,9 @@ func TestRoomState(t *testing.T) { "name": "room_test_name", }) - _ = authedClient.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.name"}, reqBody) + _ = authedClient.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.name"}, reqBody) - res := authedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.name"}) + res := authedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.name"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ @@ -236,7 +236,7 @@ func TestRoomState(t *testing.T) { "topic": "room_topic_test", }) - res := authedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.topic"}) + res := authedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.topic"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ @@ -258,9 +258,9 @@ func TestRoomState(t *testing.T) { "topic": "room_test_topic", }) - _ = authedClient.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.topic"}, reqBody) + _ = authedClient.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.topic"}, reqBody) - res := authedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.topic"}) + res := authedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.topic"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ @@ -288,7 +288,7 @@ func TestRoomState(t *testing.T) { "m.room.topic": true, } - res := authedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state"}) + res := authedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ @@ -318,7 +318,7 @@ func TestRoomState(t *testing.T) { }, }) - res := authedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.create"}) + res := authedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.create"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ @@ -331,7 +331,7 @@ func TestRoomState(t *testing.T) { t.Parallel() roomID := authedClient.CreateRoom(t, map[string]interface{}{}) authedClient.LeaveRoom(t, roomID) - res := authedClient.DoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomID, "joined_members"}) + res := authedClient.Do(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomID, "joined_members"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusForbidden, JSON: []match.JSON{ diff --git a/tests/csapi/apidoc_search_test.go b/tests/csapi/apidoc_search_test.go index 2b98a042..dd40ff09 100644 --- a/tests/csapi/apidoc_search_test.go +++ b/tests/csapi/apidoc_search_test.go @@ -9,8 +9,8 @@ import ( "github.com/matrix-org/util" "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -50,7 +50,7 @@ func TestSearch(t *testing.T) { }, }) - resp := alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "search"}, searchRequest) + resp := alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "search"}, searchRequest) sce := "search_categories.room_events" result0 := sce + ".results.0.result" must.MatchResponse(t, resp, match.HTTPResponse{ @@ -103,7 +103,7 @@ func TestSearch(t *testing.T) { }, }) - resp := alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "search"}, searchRequest) + resp := alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "search"}, searchRequest) sce := "search_categories.room_events" result0 := sce + ".results.0.result" resBefore := sce + ".results.0.context.events_before" @@ -160,7 +160,7 @@ func TestSearch(t *testing.T) { }, }) - resp := alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "search"}, searchRequest) + resp := alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "search"}, searchRequest) // First search result nextBatch := checkBackpaginateResult(t, resp, 20, eventIDs[19], eventIDs[10]) @@ -172,14 +172,14 @@ func TestSearch(t *testing.T) { values := url.Values{} values.Set("next_batch", nextBatch) params := client.WithQueries(values) - resp = alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "search"}, searchRequest, params) + resp = alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "search"}, searchRequest, params) // Second search result nextBatch = checkBackpaginateResult(t, resp, 20, eventIDs[9], eventIDs[0]) // At this point we expect next_batch to be empty values.Set("next_batch", nextBatch) params = client.WithQueries(values) - resp = alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "search"}, searchRequest, params) + resp = alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "search"}, searchRequest, params) // third search result sce := "search_categories.room_events" result0 := sce + ".results.0.result" @@ -215,7 +215,7 @@ func TestSearch(t *testing.T) { upgradeBody := client.WithJSONBody(t, map[string]string{ "new_version": "9", }) - upgradeResp := alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "upgrade"}, upgradeBody) + upgradeResp := alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "upgrade"}, upgradeBody) body := must.ParseJSON(t, upgradeResp.Body) newRoomID := must.GetJSONFieldStr(t, body, "replacement_room") t.Logf("Replaced room %s with %s", roomID, newRoomID) @@ -241,7 +241,7 @@ func TestSearch(t *testing.T) { }, }) - resp := alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "search"}, searchRequest) + resp := alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "search"}, searchRequest) sce := "search_categories.room_events" expectedEvents := map[string]string{ @@ -301,7 +301,7 @@ func TestSearch(t *testing.T) { // redact the event redactBody := client.WithJSONBody(t, map[string]interface{}{"reason": "testing"}) txnID := util.RandomString(8) // random string, as time.Now().Unix() might create the same txnID - resp := alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "redact", redactedEventID, txnID}, redactBody) + resp := alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "redact", redactedEventID, txnID}, redactBody) j := must.ParseJSON(t, resp.Body) redactionEventID := must.GetJSONFieldStr(t, j, "event_id") // wait for the redaction to come down sync @@ -320,7 +320,7 @@ func TestSearch(t *testing.T) { }, }) - resp = alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "search"}, searchRequest) + resp = alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "search"}, searchRequest) sce := "search_categories.room_events" result0 := sce + ".results.0.result" must.MatchResponse(t, resp, match.HTTPResponse{ diff --git a/tests/csapi/apidoc_server_capabilities_test.go b/tests/csapi/apidoc_server_capabilities_test.go index e33b5f78..13912ee5 100644 --- a/tests/csapi/apidoc_server_capabilities_test.go +++ b/tests/csapi/apidoc_server_capabilities_test.go @@ -27,7 +27,7 @@ func TestServerCapabilities(t *testing.T) { ) // sytest: GET /v3/capabilities is not public - res := unauthedClient.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "capabilities"}) + res := unauthedClient.Do(t, "GET", []string{"_matrix", "client", "v3", "capabilities"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusUnauthorized, }) diff --git a/tests/csapi/apidoc_version_test.go b/tests/csapi/apidoc_version_test.go index d0ce70f5..df7e6dd4 100644 --- a/tests/csapi/apidoc_version_test.go +++ b/tests/csapi/apidoc_version_test.go @@ -28,7 +28,7 @@ func TestVersionStructure(t *testing.T) { // sytest: Version responds 200 OK with valid structure t.Run("Version responds 200 OK with valid structure", func(t *testing.T) { - res := client.MustDoFunc(t, "GET", []string{"_matrix", "client", "versions"}) + res := client.MustDo(t, "GET", []string{"_matrix", "client", "versions"}) // Matches; // - r0.?.? diff --git a/tests/csapi/device_lists_test.go b/tests/csapi/device_lists_test.go index a8ae6d90..bdd759b0 100644 --- a/tests/csapi/device_lists_test.go +++ b/tests/csapi/device_lists_test.go @@ -5,8 +5,8 @@ import ( "sync/atomic" "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/docker" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" @@ -38,7 +38,7 @@ func TestDeviceListUpdates(t *testing.T) { ed25519KeyID := fmt.Sprintf("ed25519:%s", user.DeviceID) curve25519KeyID := fmt.Sprintf("curve25519:%s", user.DeviceID) - user.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "upload"}, + user.MustDo(t, "POST", []string{"_matrix", "client", "v3", "keys", "upload"}, client.WithJSONBody(t, map[string]interface{}{ "device_keys": map[string]interface{}{ "user_id": user.UserID, @@ -67,7 +67,7 @@ func TestDeviceListUpdates(t *testing.T) { mustQueryKeys := func(t *testing.T, user *client.CSAPI, userID string, check []match.JSON) { t.Helper() - res := user.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "query"}, + res := user.Do(t, "POST", []string{"_matrix", "client", "v3", "keys", "query"}, client.WithJSONBody(t, map[string]interface{}{ "device_keys": map[string]interface{}{ userID: []string{}, diff --git a/tests/csapi/e2e_key_backup_test.go b/tests/csapi/e2e_key_backup_test.go index 65f9425d..6b832381 100644 --- a/tests/csapi/e2e_key_backup_test.go +++ b/tests/csapi/e2e_key_backup_test.go @@ -6,8 +6,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -21,9 +21,9 @@ type backupKey struct { // This test checks that the rules for replacing room keys are implemented correctly. // Specifically: // -// if the keys have different values for is_verified, then it will keep the key that has is_verified set to true; -// if they have the same values for is_verified, then it will keep the key with a lower first_message_index; -// and finally, is is_verified and first_message_index are equal, then it will keep the key with a lower forwarded_count. +// if the keys have different values for is_verified, then it will keep the key that has is_verified set to true; +// if they have the same values for is_verified, then it will keep the key with a lower first_message_index; +// and finally, is is_verified and first_message_index are equal, then it will keep the key with a lower forwarded_count. func TestE2EKeyBackupReplaceRoomKeyRules(t *testing.T) { deployment := Deploy(t, b.BlueprintAlice) defer deployment.Destroy(t) @@ -32,7 +32,7 @@ func TestE2EKeyBackupReplaceRoomKeyRules(t *testing.T) { alice := deployment.Client(t, "hs1", userID) // make a new key backup - res := alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "room_keys", "version"}, client.WithJSONBody(t, map[string]interface{}{ + res := alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "room_keys", "version"}, client.WithJSONBody(t, map[string]interface{}{ "algorithm": "m.megolm_backup.v1", "auth_data": map[string]interface{}{ "foo": "bar", @@ -123,7 +123,7 @@ func TestE2EKeyBackupReplaceRoomKeyRules(t *testing.T) { t.Run(fmt.Sprintf("%+v", tc.input), func(t *testing.T) { t.Parallel() // insert the key that will be tested against - alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "room_keys", "keys", roomID, tc.sessionID}, + alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "room_keys", "keys", roomID, tc.sessionID}, client.WithQueries(map[string][]string{"version": {backupVersion}}), client.WithJSONBody(t, map[string]interface{}{ "first_message_index": tc.input.firstMessageIndex, "forwarded_count": tc.input.forwardedCount, @@ -133,7 +133,7 @@ func TestE2EKeyBackupReplaceRoomKeyRules(t *testing.T) { ) // now check that each key in keysThatDontReplace do not replace this key for _, testKey := range tc.keysThatDontReplace { - alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "room_keys", "keys", roomID, tc.sessionID}, + alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "room_keys", "keys", roomID, tc.sessionID}, client.WithQueries(map[string][]string{"version": {backupVersion}}), client.WithJSONBody(t, map[string]interface{}{ "first_message_index": testKey.firstMessageIndex, "forwarded_count": testKey.forwardedCount, @@ -141,7 +141,7 @@ func TestE2EKeyBackupReplaceRoomKeyRules(t *testing.T) { "session_data": map[string]interface{}{"a": "b"}, }), ) - checkResp := alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "room_keys", "keys", roomID, tc.sessionID}, + checkResp := alice.MustDo(t, "GET", []string{"_matrix", "client", "v3", "room_keys", "keys", roomID, tc.sessionID}, client.WithQueries(map[string][]string{"version": {backupVersion}}), ) must.MatchResponse(t, checkResp, match.HTTPResponse{ diff --git a/tests/csapi/ignored_users_test.go b/tests/csapi/ignored_users_test.go index 9001985f..ab35205d 100644 --- a/tests/csapi/ignored_users_test.go +++ b/tests/csapi/ignored_users_test.go @@ -10,14 +10,16 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) // The Spec says here -// https://spec.matrix.org/v1.1/client-server-api/#server-behaviour-13 +// +// https://spec.matrix.org/v1.1/client-server-api/#server-behaviour-13 +// // that // > Servers must not send room invites from ignored users to clients. // @@ -40,7 +42,7 @@ func TestInviteFromIgnoredUsersDoesNotAppearInSync(t *testing.T) { alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(alice.UserID, publicRoom)) // Alice ignores Bob. - alice.MustDoFunc( + alice.MustDo( t, "PUT", []string{"_matrix", "client", "v3", "user", alice.UserID, "account_data", "m.ignored_user_list"}, @@ -82,7 +84,7 @@ func TestInviteFromIgnoredUsersDoesNotAppearInSync(t *testing.T) { } // Note: SyncUntil only runs its callback on array elements. I want to investigate an object. // So let's make the HTTP request more directly. - response := alice.MustDoFunc( + response := alice.MustDo( t, "GET", []string{"_matrix", "client", "v3", "sync"}, diff --git a/tests/csapi/invalid_test.go b/tests/csapi/invalid_test.go index c6a074dd..be5e37e7 100644 --- a/tests/csapi/invalid_test.go +++ b/tests/csapi/invalid_test.go @@ -4,8 +4,8 @@ import ( "strings" "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/complement/runtime" @@ -34,7 +34,7 @@ func TestJson(t *testing.T) { } for _, testCase := range testCases { - res := alice.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "complement.dummy"}, client.WithJSONBody(t, testCase)) + res := alice.Do(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "complement.dummy"}, client.WithJSONBody(t, testCase)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 400, @@ -56,7 +56,7 @@ func TestJson(t *testing.T) { } for _, testCase := range testCases { - res := alice.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "complement.dummy"}, client.WithJSONBody(t, testCase)) + res := alice.Do(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "complement.dummy"}, client.WithJSONBody(t, testCase)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 400, @@ -177,7 +177,7 @@ func TestFilter(t *testing.T) { filters := getFilters() for _, filter := range filters { - res := alice.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "user", alice.UserID, "filter"}, client.WithJSONBody(t, filter)) + res := alice.Do(t, "POST", []string{"_matrix", "client", "v3", "user", alice.UserID, "filter"}, client.WithJSONBody(t, filter)) if res.StatusCode >= 500 || res.StatusCode < 400 { t.Errorf("Expected 4XX status code, got %d for testing filter %s", res.StatusCode, filter) @@ -205,7 +205,7 @@ func TestEvent(t *testing.T) { "body": strings.Repeat("and they dont stop coming ", 2700), // 2700 * 26 == 70200 } - res := alice.DoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "1"}, client.WithJSONBody(t, event)) + res := alice.Do(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "1"}, client.WithJSONBody(t, event)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 413, @@ -219,7 +219,7 @@ func TestEvent(t *testing.T) { "body": strings.Repeat("Dormammu, I've Come To Bargain.\n", 2200), // 2200 * 32 == 70400 } - res := alice.DoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "marvel.universe.fate"}, client.WithJSONBody(t, stateEvent)) + res := alice.Do(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "marvel.universe.fate"}, client.WithJSONBody(t, stateEvent)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 413, diff --git a/tests/csapi/keychanges_test.go b/tests/csapi/keychanges_test.go index 7e8f719a..ffc25c12 100644 --- a/tests/csapi/keychanges_test.go +++ b/tests/csapi/keychanges_test.go @@ -8,8 +8,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -39,7 +39,7 @@ func TestKeyChangesLocal(t *testing.T) { "password": password, }) // Create a new device by logging in - res := unauthedClient.MustDoFunc(t, "POST", []string{"_matrix", "client", "r0", "login"}, reqBody) + res := unauthedClient.MustDo(t, "POST", []string{"_matrix", "client", "r0", "login"}, reqBody) loginResp := must.ParseJSON(t, res.Body) unauthedClient.AccessToken = must.GetJSONFieldStr(t, loginResp, "access_token") unauthedClient.DeviceID = must.GetJSONFieldStr(t, loginResp, "device_id") @@ -63,7 +63,7 @@ func TestKeyChangesLocal(t *testing.T) { queryParams := url.Values{} queryParams.Set("from", nextBatch1) queryParams.Set("to", nextBatch) - resp := alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "keys", "changes"}, client.WithQueries(queryParams)) + resp := alice.MustDo(t, "GET", []string{"_matrix", "client", "v3", "keys", "changes"}, client.WithQueries(queryParams)) must.MatchResponse(t, resp, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -77,7 +77,7 @@ func TestKeyChangesLocal(t *testing.T) { bob.UserID: {}, }, }) - resp = alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "query"}, queryKeys) + resp = alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "keys", "query"}, queryKeys) keyCount := 0 must.MatchResponse(t, resp, match.HTTPResponse{ StatusCode: http.StatusOK, @@ -97,10 +97,10 @@ func TestKeyChangesLocal(t *testing.T) { func mustUploadKeys(t *testing.T, user *client.CSAPI) { t.Helper() - deviceKeys, oneTimeKeys := generateKeys(t, user, 5) + deviceKeys, oneTimeKeys := user.GenerateOneTimeKeys(t, 5) reqBody := client.WithJSONBody(t, map[string]interface{}{ "device_keys": deviceKeys, "one_time_keys": oneTimeKeys, }) - user.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "upload"}, reqBody) + user.MustDo(t, "POST", []string{"_matrix", "client", "v3", "keys", "upload"}, reqBody) } diff --git a/tests/csapi/media_misc_test.go b/tests/csapi/media_misc_test.go index a6b81c21..3ae93476 100644 --- a/tests/csapi/media_misc_test.go +++ b/tests/csapi/media_misc_test.go @@ -6,8 +6,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/data" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" @@ -45,7 +45,7 @@ func TestRoomImageRoundtrip(t *testing.T) { }, }) - messages := alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomId, "messages"}, client.WithQueries(url.Values{ + messages := alice.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomId, "messages"}, client.WithQueries(url.Values{ "filter": []string{`{"contains_url":true}`}, "dir": []string{"b"}, })) @@ -66,7 +66,7 @@ func TestMediaConfig(t *testing.T) { alice := deployment.Client(t, "hs1", "@alice:hs1") - res := alice.MustDoFunc(t, "GET", []string{"_matrix", "media", "v3", "config"}) + res := alice.MustDo(t, "GET", []string{"_matrix", "media", "v3", "config"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ diff --git a/tests/csapi/power_levels_test.go b/tests/csapi/power_levels_test.go index 21f0f063..90a73019 100644 --- a/tests/csapi/power_levels_test.go +++ b/tests/csapi/power_levels_test.go @@ -6,8 +6,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -58,7 +58,7 @@ func TestPowerLevels(t *testing.T) { // sytest: GET /rooms/:room_id/state/m.room.power_levels can fetch levels t.Run("GET /rooms/:room_id/state/m.room.power_levels can fetch levels", func(t *testing.T) { // Test if the old state still exists - res := alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.power_levels"}) + res := alice.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.power_levels"}) // note: before v10 we technically cannot assume that powerlevel integers are json numbers, // as they can be both strings and numbers. @@ -123,7 +123,7 @@ func TestPowerLevels(t *testing.T) { Content: PLContent, }) - res := alice.MustDoFunc( + res := alice.MustDo( t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "event", eventId}, @@ -157,7 +157,7 @@ func TestPowerLevels(t *testing.T) { }) // This should give a 403 (not a 500) - res := alice.DoFunc( + res := alice.Do( t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.power_levels"}, @@ -170,7 +170,7 @@ func TestPowerLevels(t *testing.T) { }) // Test if the old state still exists - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.power_levels"}) + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.power_levels"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, diff --git a/tests/csapi/push_test.go b/tests/csapi/push_test.go index b5db96e5..1ce0ec4b 100644 --- a/tests/csapi/push_test.go +++ b/tests/csapi/push_test.go @@ -7,8 +7,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -58,7 +58,7 @@ func TestPushSync(t *testing.T) { "actions": []string{"notify"}, }) - alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "pushrules", "global", "room", "!foo:example.com"}, body) + alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "pushrules", "global", "room", "!foo:example.com"}, body) }) }) @@ -69,7 +69,7 @@ func TestPushSync(t *testing.T) { "enabled": false, }) - alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "pushrules", "global", "room", "!foo:example.com", "enabled"}, body) + alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "pushrules", "global", "room", "!foo:example.com", "enabled"}, body) }) }) @@ -80,7 +80,7 @@ func TestPushSync(t *testing.T) { "enabled": true, }) - alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "pushrules", "global", "room", "!foo:example.com", "enabled"}, body) + alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "pushrules", "global", "room", "!foo:example.com", "enabled"}, body) }) }) @@ -91,7 +91,7 @@ func TestPushSync(t *testing.T) { "actions": []string{"dont_notify"}, }) - alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "pushrules", "global", "room", "!foo:example.com", "actions"}, body) + alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "pushrules", "global", "room", "!foo:example.com", "actions"}, body) }) }) } diff --git a/tests/csapi/room_ban_test.go b/tests/csapi/room_ban_test.go index bb2e99a7..54bd9020 100644 --- a/tests/csapi/room_ban_test.go +++ b/tests/csapi/room_ban_test.go @@ -3,8 +3,8 @@ package csapi_tests import ( "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -59,7 +59,7 @@ func TestNotPresentUserCannotBanOthers(t *testing.T) { bob.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, roomID)) - res := charlie.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "ban"}, client.WithJSONBody(t, map[string]interface{}{ + res := charlie.Do(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "ban"}, client.WithJSONBody(t, map[string]interface{}{ "user_id": bob.UserID, "reason": "testing", })) diff --git a/tests/csapi/room_kick_test.go b/tests/csapi/room_kick_test.go index 6e6ef1e5..38312fd6 100644 --- a/tests/csapi/room_kick_test.go +++ b/tests/csapi/room_kick_test.go @@ -3,8 +3,8 @@ package csapi_tests import ( "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -21,7 +21,7 @@ func TestCannotKickNonPresentUser(t *testing.T) { "preset": "public_chat", }) - resp := alice.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "kick"}, + resp := alice.Do(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "kick"}, client.WithJSONBody(t, map[string]interface{}{ "user_id": bob.UserID, "reason": "testing", @@ -53,7 +53,7 @@ func TestCannotKickLeftUser(t *testing.T) { alice.MustSyncUntil(t, client.SyncReq{}, client.SyncLeftFrom(bob.UserID, roomID)) - resp := alice.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "kick"}, + resp := alice.Do(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "kick"}, client.WithJSONBody(t, map[string]interface{}{ "user_id": bob.UserID, "reason": "testing", diff --git a/tests/csapi/room_leave_test.go b/tests/csapi/room_leave_test.go index 98662573..db3257b4 100644 --- a/tests/csapi/room_leave_test.go +++ b/tests/csapi/room_leave_test.go @@ -7,8 +7,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -123,7 +123,7 @@ func TestLeftRoomFixture(t *testing.T) { // sytest: Can get rooms/{roomId}/state for a departed room (SPEC-216) t.Run("Can get rooms/{roomId}/state for a departed room", func(t *testing.T) { // Bob gets the old state - resp := bob.MustDoFunc( + resp := bob.MustDo( t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", madeUpStateKey}, @@ -135,7 +135,7 @@ func TestLeftRoomFixture(t *testing.T) { }) // ...While Alice gets the new state - resp = alice.MustDoFunc( + resp = alice.MustDo( t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", madeUpStateKey}, @@ -149,7 +149,7 @@ func TestLeftRoomFixture(t *testing.T) { // sytest: Can get rooms/{roomId}/members for a departed room (SPEC-216) t.Run("Can get rooms/{roomId}/members for a departed room", func(t *testing.T) { - resp := bob.MustDoFunc( + resp := bob.MustDo( t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "members"}, @@ -174,7 +174,7 @@ func TestLeftRoomFixture(t *testing.T) { // sytest: Can get rooms/{roomId}/messages for a departed room (SPEC-216) t.Run("Can get rooms/{roomId}/messages for a departed room", func(t *testing.T) { - resp := bob.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(url.Values{ + resp := bob.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(url.Values{ "dir": []string{"b"}, "limit": []string{"3"}, "from": []string{bobSinceToken}, @@ -200,7 +200,7 @@ func TestLeftRoomFixture(t *testing.T) { // sytest: Can get 'm.room.name' state for a departed room (SPEC-216) t.Run("Can get 'm.room.name' state for a departed room", func(t *testing.T) { // Bob gets the old name - resp := bob.MustDoFunc( + resp := bob.MustDo( t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.name"}, @@ -212,7 +212,7 @@ func TestLeftRoomFixture(t *testing.T) { }) // ...While Alice gets the new name - resp = alice.MustDoFunc( + resp = alice.MustDo( t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.name"}, @@ -227,7 +227,7 @@ func TestLeftRoomFixture(t *testing.T) { // sytest: Getting messages going forward is limited for a departed room (SPEC-216) t.Run("Getting messages going forward is limited for a departed room", func(t *testing.T) { // TODO: try this with the most recent since token too - resp := bob.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(url.Values{ + resp := bob.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(url.Values{ "dir": []string{"f"}, "limit": []string{"100"}, "from": []string{bobSinceToken}, diff --git a/tests/csapi/room_members_test.go b/tests/csapi/room_members_test.go index 4cfeb567..f5c2fda6 100644 --- a/tests/csapi/room_members_test.go +++ b/tests/csapi/room_members_test.go @@ -7,8 +7,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -34,7 +34,7 @@ func TestGetRoomMembers(t *testing.T) { alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, roomID)) - resp := alice.MustDoFunc( + resp := alice.MustDo( t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "members"}, @@ -91,7 +91,7 @@ func TestGetRoomMembersAtPoint(t *testing.T) { }, }) - resp := alice.MustDoFunc( + resp := alice.MustDo( t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "members"}, @@ -138,7 +138,7 @@ func TestGetFilteredRoomMembers(t *testing.T) { alice.MustSyncUntil(t, client.SyncReq{}, client.SyncLeftFrom(bob.UserID, roomID)) t.Run("not_membership", func(t *testing.T) { - resp := alice.MustDoFunc( + resp := alice.MustDo( t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "members"}, @@ -163,7 +163,7 @@ func TestGetFilteredRoomMembers(t *testing.T) { }) t.Run("membership/leave", func(t *testing.T) { - resp := alice.MustDoFunc( + resp := alice.MustDo( t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "members"}, @@ -188,7 +188,7 @@ func TestGetFilteredRoomMembers(t *testing.T) { }) t.Run("membership/join", func(t *testing.T) { - resp := alice.MustDoFunc( + resp := alice.MustDo( t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "members"}, diff --git a/tests/csapi/room_messages_relation_filter_test.go b/tests/csapi/room_messages_relation_filter_test.go index 225894bb..62657f6f 100644 --- a/tests/csapi/room_messages_relation_filter_test.go +++ b/tests/csapi/room_messages_relation_filter_test.go @@ -10,8 +10,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/complement/runtime" @@ -30,13 +30,13 @@ func TestFilterMessagesByRelType(t *testing.T) { beforeToken := alice.MustSyncUntil(t, client.SyncReq{}) // Send messages with different relations. - res := alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-1"}, client.WithJSONBody(t, map[string]interface{}{ + res := alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-1"}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": "Message without a relation", })) rootEventID := client.GetJSONFieldStr(t, client.ParseJSON(t, res), "event_id") - res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-2"}, client.WithJSONBody(t, map[string]interface{}{ + res = alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-2"}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": "Threaded Reply", "m.relates_to": map[string]interface{}{ @@ -46,7 +46,7 @@ func TestFilterMessagesByRelType(t *testing.T) { })) threadEventID := client.GetJSONFieldStr(t, client.ParseJSON(t, res), "event_id") - res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-3"}, client.WithJSONBody(t, map[string]interface{}{ + res = alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-3"}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": "Reference Reply", "m.relates_to": map[string]interface{}{ @@ -66,7 +66,7 @@ func TestFilterMessagesByRelType(t *testing.T) { queryParams.Set("dir", "f") queryParams.Set("from", beforeToken) queryParams.Set("filter", `{ "org.matrix.msc3874.rel_types" : ["m.thread"] }`) - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -84,7 +84,7 @@ func TestFilterMessagesByRelType(t *testing.T) { queryParams.Set("dir", "f") queryParams.Set("from", beforeToken) queryParams.Set("filter", `{ "org.matrix.msc3874.rel_types" : ["m.reference"] }`) - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -102,7 +102,7 @@ func TestFilterMessagesByRelType(t *testing.T) { queryParams.Set("dir", "f") queryParams.Set("from", beforeToken) queryParams.Set("filter", `{ "org.matrix.msc3874.rel_types" : ["m.thread", "m.reference"] }`) - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -120,7 +120,7 @@ func TestFilterMessagesByRelType(t *testing.T) { queryParams.Set("dir", "f") queryParams.Set("from", beforeToken) queryParams.Set("filter", `{ "org.matrix.msc3874.not_rel_types" : ["m.thread"] }`) - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -138,7 +138,7 @@ func TestFilterMessagesByRelType(t *testing.T) { queryParams.Set("dir", "f") queryParams.Set("from", beforeToken) queryParams.Set("filter", `{ "org.matrix.msc3874.not_rel_types" : ["m.reference"] }`) - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -156,7 +156,7 @@ func TestFilterMessagesByRelType(t *testing.T) { queryParams.Set("dir", "f") queryParams.Set("from", beforeToken) queryParams.Set("filter", `{ "org.matrix.msc3874.not_rel_types" : ["m.thread", "m.reference"] }`) - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ diff --git a/tests/csapi/room_messages_test.go b/tests/csapi/room_messages_test.go index 48e30234..5fba1d25 100644 --- a/tests/csapi/room_messages_test.go +++ b/tests/csapi/room_messages_test.go @@ -8,8 +8,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/complement/runtime" @@ -31,7 +31,7 @@ func TestSendAndFetchMessage(t *testing.T) { _, token := alice.MustSync(t, client.SyncReq{}) // first use the non-txn endpoint - alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message"}, client.WithJSONBody(t, map[string]interface{}{ + alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message"}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": testMessage, })) @@ -45,7 +45,7 @@ func TestSendAndFetchMessage(t *testing.T) { queryParams := url.Values{} queryParams.Set("dir", "f") queryParams.Set("from", token) - res := alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) + res := alice.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -71,7 +71,7 @@ func TestFetchMessagesFromNonExistentRoom(t *testing.T) { // then request messages from the room queryParams := url.Values{} queryParams.Set("dir", "b") - res := alice.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) + res := alice.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusForbidden, }) @@ -89,13 +89,13 @@ func TestSendMessageWithTxn(t *testing.T) { const txnID = "lorem" - res := alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", txnID}, client.WithJSONBody(t, map[string]interface{}{ + res := alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", txnID}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": "test", })) eventID := client.GetJSONFieldStr(t, client.ParseJSON(t, res), "event_id") - res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", txnID}, client.WithJSONBody(t, map[string]interface{}{ + res = alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", txnID}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": "test", })) @@ -166,7 +166,7 @@ func TestRoomMessagesLazyLoading(t *testing.T) { queryParams.Set("filter", `{ "lazy_load_members" : true }`) queryParams.Set("from", beforeToken) queryParams.Set("to", afterToken) - res := alice.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) + res := alice.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -189,11 +189,13 @@ func TestRoomMessagesLazyLoading(t *testing.T) { } // TODO We should probably see if this should be removed. -// Sytest tests for a very specific bug; check if local user member event loads properly when going backwards from a prev_event. -// However, note that the sytest *only* checks for the *local, single* user in a room to be included in `/messages`. -// This function exists here for sytest exhaustiveness, but I question its usefulness, thats why TestRoomMessagesLazyLoading -// exists to do a more generic check. -// We should probably see if this should be removed. +// +// Sytest tests for a very specific bug; check if local user member event loads properly when going backwards from a prev_event. +// However, note that the sytest *only* checks for the *local, single* user in a room to be included in `/messages`. +// This function exists here for sytest exhaustiveness, but I question its usefulness, thats why TestRoomMessagesLazyLoading +// exists to do a more generic check. +// We should probably see if this should be removed. +// // sytest: GET /rooms/:room_id/messages lazy loads members correctly func TestRoomMessagesLazyLoadingLocalUser(t *testing.T) { deployment := Deploy(t, b.BlueprintAlice) @@ -217,7 +219,7 @@ func TestRoomMessagesLazyLoadingLocalUser(t *testing.T) { queryParams.Set("dir", "b") queryParams.Set("filter", `{ "lazy_load_members" : true }`) queryParams.Set("from", token) - res := alice.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) + res := alice.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(queryParams)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ diff --git a/tests/csapi/room_profile_test.go b/tests/csapi/room_profile_test.go index a8c2b100..bbf60986 100644 --- a/tests/csapi/room_profile_test.go +++ b/tests/csapi/room_profile_test.go @@ -5,8 +5,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" ) func TestAvatarUrlUpdate(t *testing.T) { @@ -32,7 +32,7 @@ func testProfileFieldUpdate(t *testing.T, field string) { sinceToken := alice.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(alice.UserID, roomID)) - alice.MustDoFunc( + alice.MustDo( t, "PUT", []string{"_matrix", "client", "v3", "profile", alice.UserID, field}, diff --git a/tests/csapi/room_relations_test.go b/tests/csapi/room_relations_test.go index 2ca85433..adbe4eb6 100644 --- a/tests/csapi/room_relations_test.go +++ b/tests/csapi/room_relations_test.go @@ -8,8 +8,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/complement/runtime" @@ -23,14 +23,14 @@ func TestRelations(t *testing.T) { roomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) _, token := alice.MustSync(t, client.SyncReq{}) - res := alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-1"}, client.WithJSONBody(t, map[string]interface{}{ + res := alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-1"}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": "root", })) rootEventID := client.GetJSONFieldStr(t, client.ParseJSON(t, res), "event_id") // Send a few related messages. - res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-2"}, client.WithJSONBody(t, map[string]interface{}{ + res = alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-2"}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": "reply", "m.relates_to": map[string]interface{}{ @@ -40,7 +40,7 @@ func TestRelations(t *testing.T) { })) threadEventID := client.GetJSONFieldStr(t, client.ParseJSON(t, res), "event_id") - res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.dummy", "txn-3"}, client.WithJSONBody(t, map[string]interface{}{ + res = alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.dummy", "txn-3"}, client.WithJSONBody(t, map[string]interface{}{ "m.relates_to": map[string]interface{}{ "event_id": rootEventID, "rel_type": "m.thread", @@ -48,7 +48,7 @@ func TestRelations(t *testing.T) { })) dummyEventID := client.GetJSONFieldStr(t, client.ParseJSON(t, res), "event_id") - res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-4"}, client.WithJSONBody(t, map[string]interface{}{ + res = alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-4"}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": "* edited root", "m.new_content": map[string]interface{}{ @@ -68,7 +68,7 @@ func TestRelations(t *testing.T) { })) // Request the relations. - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}) + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -82,7 +82,7 @@ func TestRelations(t *testing.T) { }) // Also test filtering by the relation type. - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID, "m.thread"}) + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID, "m.thread"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -96,7 +96,7 @@ func TestRelations(t *testing.T) { }) // And test filtering by relation type + event type. - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID, "m.thread", "m.room.message"}) + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID, "m.thread", "m.room.message"}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -118,7 +118,7 @@ func TestRelationsPagination(t *testing.T) { roomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) _, token := alice.MustSync(t, client.SyncReq{}) - res := alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-1"}, client.WithJSONBody(t, map[string]interface{}{ + res := alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-1"}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": "root", })) @@ -127,7 +127,7 @@ func TestRelationsPagination(t *testing.T) { // Create some related events. event_ids := [10]string{} for i := 0; i < 10; i++ { - res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", fmt.Sprintf("txn-%d", 2+i)}, client.WithJSONBody(t, map[string]interface{}{ + res = alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", fmt.Sprintf("txn-%d", 2+i)}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": fmt.Sprintf("reply %d", i), "m.relates_to": map[string]interface{}{ @@ -146,7 +146,7 @@ func TestRelationsPagination(t *testing.T) { // Fetch the first page. queryParams := url.Values{} queryParams.Set("limit", "3") - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}, client.WithQueries(queryParams)) + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}, client.WithQueries(queryParams)) body := must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -161,7 +161,7 @@ func TestRelationsPagination(t *testing.T) { // Fetch the next page. queryParams.Set("from", client.GetJSONFieldStr(t, body, "next_batch")) - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}, client.WithQueries(queryParams)) + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}, client.WithQueries(queryParams)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -178,7 +178,7 @@ func TestRelationsPagination(t *testing.T) { queryParams = url.Values{} queryParams.Set("limit", "3") queryParams.Set("dir", "f") - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}, client.WithQueries(queryParams)) + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}, client.WithQueries(queryParams)) body = must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -193,7 +193,7 @@ func TestRelationsPagination(t *testing.T) { // Fetch the next page in the forward direction. queryParams.Set("from", client.GetJSONFieldStr(t, body, "next_batch")) - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}, client.WithQueries(queryParams)) + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}, client.WithQueries(queryParams)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -217,7 +217,7 @@ func TestRelationsPaginationSync(t *testing.T) { roomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) _, token := alice.MustSync(t, client.SyncReq{}) - rootEventID := alice.SendEventUnsynced(t, roomID, b.Event{ + rootEventID := alice.Unsafe_SendEventUnsynced(t, roomID, b.Event{ Type: "m.room.message", Content: map[string]interface{}{ "msgtype": "m.text", @@ -227,9 +227,9 @@ func TestRelationsPaginationSync(t *testing.T) { }) // Create some related events. - event_id := "" + eventID := "" for i := 0; i < 5; i++ { - event_id = alice.SendEventUnsynced(t, roomID, b.Event{ + eventID = alice.Unsafe_SendEventUnsynced(t, roomID, b.Event{ Type: "m.room.message", Content: map[string]interface{}{ "msgtype": "m.text", @@ -245,13 +245,13 @@ func TestRelationsPaginationSync(t *testing.T) { // Sync and keep the token. nextBatch := alice.MustSyncUntil(t, client.SyncReq{Since: token}, client.SyncTimelineHas(roomID, func(r gjson.Result) bool { - return r.Get("event_id").Str == event_id + return r.Get("event_id").Str == eventID })) // Create more related events. event_ids := [5]string{} for i := 0; i < 5; i++ { - event_ids[i] = alice.SendEventUnsynced(t, roomID, b.Event{ + event_ids[i] = alice.Unsafe_SendEventUnsynced(t, roomID, b.Event{ Type: "m.room.message", Content: map[string]interface{}{ "msgtype": "m.text", @@ -273,7 +273,7 @@ func TestRelationsPaginationSync(t *testing.T) { queryParams.Set("limit", "3") queryParams.Set("from", nextBatch) queryParams.Set("dir", "f") - res := alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}, client.WithQueries(queryParams)) + res := alice.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}, client.WithQueries(queryParams)) body := must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -288,7 +288,7 @@ func TestRelationsPaginationSync(t *testing.T) { // Fetch the next page. queryParams.Set("from", client.GetJSONFieldStr(t, body, "next_batch")) - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}, client.WithQueries(queryParams)) + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}, client.WithQueries(queryParams)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ diff --git a/tests/csapi/room_threads_test.go b/tests/csapi/room_threads_test.go index f324f00f..27d756ee 100644 --- a/tests/csapi/room_threads_test.go +++ b/tests/csapi/room_threads_test.go @@ -6,8 +6,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/complement/runtime" @@ -40,20 +40,20 @@ func TestThreadsEndpoint(t *testing.T) { _, token := alice.MustSync(t, client.SyncReq{}) // Create 2 threads in the room. - res := alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-1"}, client.WithJSONBody(t, map[string]interface{}{ + res := alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-1"}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": "Thread 1 Root", })) threadID1 := client.GetJSONFieldStr(t, client.ParseJSON(t, res), "event_id") - res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-2"}, client.WithJSONBody(t, map[string]interface{}{ + res = alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-2"}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": "Thraed 2 Root", })) threadID2 := client.GetJSONFieldStr(t, client.ParseJSON(t, res), "event_id") // Add threaded replies. - res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-3"}, client.WithJSONBody(t, map[string]interface{}{ + res = alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-3"}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": "Thread 1 Reply", "m.relates_to": map[string]interface{}{ @@ -63,7 +63,7 @@ func TestThreadsEndpoint(t *testing.T) { })) replyID1 := client.GetJSONFieldStr(t, client.ParseJSON(t, res), "event_id") - res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-4"}, client.WithJSONBody(t, map[string]interface{}{ + res = alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-4"}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": "Thread 2 Reply", "m.relates_to": map[string]interface{}{ @@ -79,7 +79,7 @@ func TestThreadsEndpoint(t *testing.T) { })) // Request the threads. - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "threads"}) + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "threads"}) body := must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, }) @@ -88,7 +88,7 @@ func TestThreadsEndpoint(t *testing.T) { checkResults(t, body, []string{threadKey(threadID2, replyID2), threadKey(threadID1, replyID1)}) // Update thread 1 and ensure it gets updated. - res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-5"}, client.WithJSONBody(t, map[string]interface{}{ + res = alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-5"}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": "Thread 1 Reply 2", "m.relates_to": map[string]interface{}{ @@ -103,7 +103,7 @@ func TestThreadsEndpoint(t *testing.T) { return r.Get("event_id").Str == replyID3 })) - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "threads"}) + res = alice.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "threads"}) body = must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, }) diff --git a/tests/csapi/room_typing_test.go b/tests/csapi/room_typing_test.go index 8cf46426..fc55acd5 100644 --- a/tests/csapi/room_typing_test.go +++ b/tests/csapi/room_typing_test.go @@ -5,8 +5,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -25,7 +25,7 @@ func TestTyping(t *testing.T) { token := bob.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, roomID)) - alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "typing", alice.UserID}, client.WithJSONBody(t, map[string]interface{}{ + alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "typing", alice.UserID}, client.WithJSONBody(t, map[string]interface{}{ "typing": true, "timeout": 10000, })) @@ -57,7 +57,7 @@ func TestTyping(t *testing.T) { // sytest: Typing can be explicitly stopped t.Run("Typing can be explicitly stopped", func(t *testing.T) { - alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "typing", alice.UserID}, client.WithJSONBody(t, map[string]interface{}{ + alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "typing", alice.UserID}, client.WithJSONBody(t, map[string]interface{}{ "typing": false, })) @@ -89,7 +89,7 @@ func TestLeakyTyping(t *testing.T) { _, charlieToken := charlie.MustSync(t, client.SyncReq{TimeoutMillis: "0"}) // Alice types in that room. Bob should see her typing. - alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "typing", alice.UserID}, client.WithJSONBody(t, map[string]interface{}{ + alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "typing", alice.UserID}, client.WithJSONBody(t, map[string]interface{}{ "typing": true, "timeout": 10000, })) diff --git a/tests/csapi/rooms_invite_test.go b/tests/csapi/rooms_invite_test.go index b960c1a0..521208f8 100644 --- a/tests/csapi/rooms_invite_test.go +++ b/tests/csapi/rooms_invite_test.go @@ -4,8 +4,8 @@ import ( "net/http" "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/tidwall/gjson" @@ -38,7 +38,7 @@ func TestRoomsInvite(t *testing.T) { roomID := alice.CreateRoom(t, map[string]interface{}{ "preset": "private_chat", }) - res := bob.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "join", roomID}) + res := bob.Do(t, "POST", []string{"_matrix", "client", "v3", "join", roomID}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusForbidden, }) @@ -88,7 +88,7 @@ func TestRoomsInvite(t *testing.T) { body := client.WithJSONBody(t, map[string]interface{}{ "user_id": alice.UserID, }) - res := alice.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "invite"}, body) + res := alice.Do(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "invite"}, body) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusForbidden, }) @@ -109,7 +109,7 @@ func TestRoomsInvite(t *testing.T) { body := client.WithJSONBody(t, map[string]interface{}{ "user_id": bob.UserID, }) - res := alice.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "invite"}, body) + res := alice.Do(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "invite"}, body) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusForbidden, }) @@ -149,7 +149,7 @@ func TestRoomsInvite(t *testing.T) { bob.UserID: 100, }, }) - alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.power_levels"}, reqBody) + alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.power_levels"}, reqBody) // Alice leaves the room alice.LeaveRoom(t, roomID) @@ -180,7 +180,7 @@ func verifyState(t *testing.T, res gjson.Result, roomID string, cl *client.CSAPI eventContent := event.Get("content." + field).Str eventStateKey := event.Get("state_key").Str - res := cl.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", eventType, eventStateKey}) + res := cl.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", eventType, eventStateKey}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ diff --git a/tests/csapi/rooms_members_local_test.go b/tests/csapi/rooms_members_local_test.go index 09ae5356..6b2796ff 100644 --- a/tests/csapi/rooms_members_local_test.go +++ b/tests/csapi/rooms_members_local_test.go @@ -3,8 +3,8 @@ package csapi_tests import ( "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/runtime" ) @@ -18,7 +18,7 @@ func TestMembersLocal(t *testing.T) { bob := deployment.RegisterUser(t, "hs1", "bob", "bobspassword", false) roomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) - bob.MustDoFunc( + bob.MustDo( t, "PUT", []string{"_matrix", "client", "v3", "presence", bob.UserID, "status"}, client.WithJSONBody(t, map[string]interface{}{ "presence": "online", diff --git a/tests/csapi/rooms_state_test.go b/tests/csapi/rooms_state_test.go index 624a7b04..c00da6d2 100644 --- a/tests/csapi/rooms_state_test.go +++ b/tests/csapi/rooms_state_test.go @@ -9,8 +9,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/must" ) @@ -134,7 +134,7 @@ func TestRoomCreationReportsEventsToMyself(t *testing.T) { } func getEventIdForState(t *testing.T, client *client.CSAPI, roomID, evType, stateKey string) *string { - res := client.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state"}) + res := client.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state"}) jsonBody := must.ParseJSON(t, res.Body) result := gjson.ParseBytes(jsonBody) diff --git a/tests/csapi/sync_archive_test.go b/tests/csapi/sync_archive_test.go index 19994e75..fadc03ce 100644 --- a/tests/csapi/sync_archive_test.go +++ b/tests/csapi/sync_archive_test.go @@ -5,8 +5,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/runtime" ) @@ -306,7 +306,8 @@ func TestOlderLeftRoomsNotInLeaveSection(t *testing.T) { } // sytest: We should see our own leave event, even if history_visibility is -// restricted (SYN-662) +// +// restricted (SYN-662) func TestLeaveEventVisibility(t *testing.T) { runtime.SkipIf(t, runtime.Dendrite) // FIXME: https://github.com/matrix-org/dendrite/issues/1323 @@ -392,7 +393,8 @@ func TestLeaveEventVisibility(t *testing.T) { } // sytest: We should see our own leave event when rejecting an invite, -// even if history_visibility is restricted (riot-web/3462) +// +// even if history_visibility is restricted (riot-web/3462) func TestLeaveEventInviteRejection(t *testing.T) { runtime.SkipIf(t, runtime.Dendrite) // FIXME: https://github.com/matrix-org/dendrite/issues/1323 diff --git a/tests/csapi/sync_filter_test.go b/tests/csapi/sync_filter_test.go index 3a8dce11..64ae1122 100644 --- a/tests/csapi/sync_filter_test.go +++ b/tests/csapi/sync_filter_test.go @@ -6,8 +6,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -35,7 +35,7 @@ func TestSyncFilter(t *testing.T) { }, }, }) - res := authedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "user", "@alice:hs1", "filter", filterID}) + res := authedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "user", "@alice:hs1", "filter", filterID}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONKeyPresent("room"), @@ -48,7 +48,7 @@ func TestSyncFilter(t *testing.T) { func createFilter(t *testing.T, c *client.CSAPI, filterContent map[string]interface{}) string { t.Helper() - res := c.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "user", c.UserID, "filter"}, client.WithJSONBody(t, filterContent)) + res := c.MustDo(t, "POST", []string{"_matrix", "client", "v3", "user", c.UserID, "filter"}, client.WithJSONBody(t, filterContent)) if res.StatusCode != 200 { t.Fatalf("MatchResponse got status %d want 200", res.StatusCode) } diff --git a/tests/csapi/sync_test.go b/tests/csapi/sync_test.go index f9d9410e..918e9637 100644 --- a/tests/csapi/sync_test.go +++ b/tests/csapi/sync_test.go @@ -8,8 +8,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/runtime" ) @@ -291,17 +291,16 @@ func TestSync(t *testing.T) { // a good event - in another room - to act as a sentinel. It's not // guaranteed, but hopefully if the sentinel is received, so was the // redaction. - redactionEvent := srv.MustCreateEvent(t, redactionRoom, b.Event{ + redactionEvent := srv.MustCreateEvent(t, redactionRoom, federation.Event{ Type: "m.room.redaction", Sender: charlie, Content: map[string]interface{}{}, - Redacts: "$12345", - }) + Redacts: "$12345"}) redactionRoom.AddEvent(redactionEvent) t.Logf("Created redaction event %s", redactionEvent.EventID()) srv.MustSendTransaction(t, deployment, "hs1", []json.RawMessage{redactionEvent.JSON()}, nil) - sentinelEvent := srv.MustCreateEvent(t, sentinelRoom, b.Event{ + sentinelEvent := srv.MustCreateEvent(t, sentinelRoom, federation.Event{ Type: "m.room.test", Sender: charlie, Content: map[string]interface{}{"body": "1234"}, @@ -318,7 +317,7 @@ func TestSync(t *testing.T) { pdus := make([]json.RawMessage, 11) var lastSentEventId string for i := range pdus { - ev := srv.MustCreateEvent(t, redactionRoom, b.Event{ + ev := srv.MustCreateEvent(t, redactionRoom, federation.Event{ Type: "m.room.message", Sender: charlie, Content: map[string]interface{}{}, @@ -403,8 +402,8 @@ func TestPresenceSyncDifferentRooms(t *testing.T) { reqBody := client.WithJSONBody(t, map[string]interface{}{ "presence": "online", }) - bob.DoFunc(t, "PUT", []string{"_matrix", "client", "v3", "presence", "@bob:hs1", "status"}, reqBody) - charlie.DoFunc(t, "PUT", []string{"_matrix", "client", "v3", "presence", "@charlie:hs1", "status"}, reqBody) + bob.Do(t, "PUT", []string{"_matrix", "client", "v3", "presence", "@bob:hs1", "status"}, reqBody) + charlie.Do(t, "PUT", []string{"_matrix", "client", "v3", "presence", "@charlie:hs1", "status"}, reqBody) // Alice should see that Bob and Charlie are online. She may see this happen // simultaneously in one /sync response, or separately in two /sync diff --git a/tests/csapi/thread_notifications_test.go b/tests/csapi/thread_notifications_test.go index 09847b64..a0e7bea8 100644 --- a/tests/csapi/thread_notifications_test.go +++ b/tests/csapi/thread_notifications_test.go @@ -6,8 +6,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/runtime" ) @@ -194,7 +194,7 @@ func TestThreadedReceipts(t *testing.T) { // Mark the first event as read with a threaded receipt. This causes only the // notification from that event to be marked as read and only impacts the main // timeline. - bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "receipt", "m.read", eventA}, client.WithJSONBody(t, map[string]interface{}{"thread_id": "main"})) + bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "receipt", "m.read", eventA}, client.WithJSONBody(t, map[string]interface{}{"thread_id": "main"})) bob.MustSyncUntil( t, client.SyncReq{Since: bobNextBatch}, client.SyncTimelineHas(roomID, func(r gjson.Result) bool { @@ -221,7 +221,7 @@ func TestThreadedReceipts(t *testing.T) { // Mark the first thread event as read. This causes only the notification from // that event to be marked as read and only impacts the thread timeline. - bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "receipt", "m.read", eventB}, client.WithJSONBody(t, map[string]interface{}{"thread_id": eventA})) + bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "receipt", "m.read", eventB}, client.WithJSONBody(t, map[string]interface{}{"thread_id": eventA})) bob.MustSyncUntil( t, client.SyncReq{Since: bobNextBatch}, client.SyncTimelineHas(roomID, func(r gjson.Result) bool { @@ -249,7 +249,7 @@ func TestThreadedReceipts(t *testing.T) { ) // Use an unthreaded receipt to mark the second thread event and an unthreaded event as read. - bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "receipt", "m.read", eventD}, client.WithJSONBody(t, struct{}{})) + bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "receipt", "m.read", eventD}, client.WithJSONBody(t, struct{}{})) bob.MustSyncUntil( t, client.SyncReq{Since: bobNextBatch}, client.SyncTimelineHas(roomID, func(r gjson.Result) bool { @@ -277,7 +277,7 @@ func TestThreadedReceipts(t *testing.T) { // Finally, mark the entire thread as read, using the annotation. // // Note that this will *not* affect the main timeline. - bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "receipt", "m.read", eventG}, client.WithJSONBody(t, map[string]interface{}{"thread_id": eventA})) + bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "receipt", "m.read", eventG}, client.WithJSONBody(t, map[string]interface{}{"thread_id": eventA})) bob.MustSyncUntil( t, client.SyncReq{Since: bobNextBatch}, client.SyncTimelineHas(roomID, func(r gjson.Result) bool { diff --git a/tests/csapi/to_device_test.go b/tests/csapi/to_device_test.go index d98a12c4..3b8606b5 100644 --- a/tests/csapi/to_device_test.go +++ b/tests/csapi/to_device_test.go @@ -6,8 +6,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" ) // sytest: Can send a message directly to a device using PUT /sendToDevice diff --git a/tests/csapi/txnid_test.go b/tests/csapi/txnid_test.go index 5ff7f512..e91e9cbb 100644 --- a/tests/csapi/txnid_test.go +++ b/tests/csapi/txnid_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/complement/runtime" "github.com/tidwall/gjson" @@ -27,7 +27,7 @@ func TestTxnInEvent(t *testing.T) { txnId := "abcdefg" // Let's send an event, and wait for it to appear in the timeline. - eventID := c.SendEventUnsyncedWithTxnID(t, roomID, b.Event{ + eventID := c.Unsafe_SendEventUnsyncedWithTxnID(t, roomID, b.Event{ Type: "m.room.message", Content: map[string]interface{}{ "msgtype": "m.text", @@ -36,7 +36,7 @@ func TestTxnInEvent(t *testing.T) { }, txnId) // The transaction ID should be present on the GET /rooms/{roomID}/event/{eventID} response. - res := c.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "event", eventID}) + res := c.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "event", eventID}) body := client.ParseJSON(t, res) result := gjson.ParseBytes(body) unsignedTxnId := result.Get("unsigned.transaction_id") @@ -47,7 +47,6 @@ func TestTxnInEvent(t *testing.T) { must.EqualStr(t, unsignedTxnId.Str, txnId, fmt.Sprintf("Event had an incorrect 'unsigned.transaction_id' on GET /rooms/%s/event/%s response", eventID, roomID)) } - func mustHaveTransactionIDForEvent(t *testing.T, roomID, eventID, expectedTxnId string) client.SyncCheckOpt { return client.SyncTimelineHas(roomID, func(r gjson.Result) bool { if r.Get("event_id").Str == eventID { @@ -83,7 +82,7 @@ func TestTxnScopeOnLocalEcho(t *testing.T) { txnId := "abdefgh" // Let's send an event, and wait for it to appear in the timeline. - eventID := c1.SendEventUnsyncedWithTxnID(t, roomID, b.Event{ + eventID := c1.Unsafe_SendEventUnsyncedWithTxnID(t, roomID, b.Event{ Type: "m.room.message", Content: map[string]interface{}{ "msgtype": "m.text", @@ -129,7 +128,7 @@ func TestTxnIdempotencyScopedToDevice(t *testing.T) { }, } // send an event with set txnId - eventID1 := c1.SendEventUnsyncedWithTxnID(t, roomID, event, txnId) + eventID1 := c1.Unsafe_SendEventUnsyncedWithTxnID(t, roomID, event, txnId) // Create a second client, inheriting the first device ID. c2 := deployment.Client(t, "hs1", "") @@ -137,7 +136,7 @@ func TestTxnIdempotencyScopedToDevice(t *testing.T) { must.EqualStr(t, c1.DeviceID, c2.DeviceID, "Device ID should be the same") // send another event with the same txnId via the second client - eventID2 := c2.SendEventUnsyncedWithTxnID(t, roomID, event, txnId) + eventID2 := c2.Unsafe_SendEventUnsyncedWithTxnID(t, roomID, event, txnId) // the two events should have the same event IDs as they came from the same device must.EqualStr(t, eventID2, eventID1, "Expected eventID1 and eventID2 to be the same from two clients sharing the same device ID") @@ -179,20 +178,20 @@ func TestTxnIdempotency(t *testing.T) { } // we send the event and get an event ID back - eventID1 := c1.SendEventUnsyncedWithTxnID(t, roomID1, event1, txnId) + eventID1 := c1.Unsafe_SendEventUnsyncedWithTxnID(t, roomID1, event1, txnId) // we send the identical event again and should get back the same event ID - eventID2 := c1.SendEventUnsyncedWithTxnID(t, roomID1, event1, txnId) + eventID2 := c1.Unsafe_SendEventUnsyncedWithTxnID(t, roomID1, event1, txnId) must.EqualStr(t, eventID2, eventID1, "Expected eventID1 and eventID2 to be the same, but they were not") // even if we change the content we should still get back the same event ID as transaction ID is the same - eventID3 := c1.SendEventUnsyncedWithTxnID(t, roomID1, event2, txnId) + eventID3 := c1.Unsafe_SendEventUnsyncedWithTxnID(t, roomID1, event2, txnId) must.EqualStr(t, eventID3, eventID1, "Expected eventID3 and eventID2 to be the same even with different content, but they were not") // if we change the room ID we should be able to use the same transaction ID - eventID4 := c1.SendEventUnsyncedWithTxnID(t, roomID2, event1, txnId) + eventID4 := c1.Unsafe_SendEventUnsyncedWithTxnID(t, roomID2, event1, txnId) must.NotEqualStr(t, eventID4, eventID3, "Expected eventID4 and eventID3 to be different, but they were not") } @@ -200,47 +199,47 @@ func TestTxnIdempotency(t *testing.T) { // TestTxnIdWithRefreshToken tests that when a client refreshes its access token, // it still gets back a transaction ID in the sync response and idempotency is respected. func TestTxnIdWithRefreshToken(t *testing.T) { - // Dendrite and Conduit don't support refresh tokens yet. - runtime.SkipIf(t, runtime.Dendrite, runtime.Conduit) + // Dendrite and Conduit don't support refresh tokens yet. + runtime.SkipIf(t, runtime.Dendrite, runtime.Conduit) - deployment := Deploy(t, b.BlueprintCleanHS) - defer deployment.Destroy(t) + deployment := Deploy(t, b.BlueprintCleanHS) + defer deployment.Destroy(t) - deployment.RegisterUser(t, "hs1", "alice", "password", false) + deployment.RegisterUser(t, "hs1", "alice", "password", false) - c := deployment.Client(t, "hs1", "") + c := deployment.Client(t, "hs1", "") - var refreshToken string - c.UserID, c.AccessToken, refreshToken, c.DeviceID, _ = c.LoginUserWithRefreshToken(t, "alice", "password") + var refreshToken string + c.UserID, c.AccessToken, refreshToken, c.DeviceID, _ = c.LoginUserWithRefreshToken(t, "alice", "password") - // Create a room where we can send events. - roomID := c.CreateRoom(t, map[string]interface{}{}) + // Create a room where we can send events. + roomID := c.CreateRoom(t, map[string]interface{}{}) txnId := "abcdef" // We send an event - eventID1 := c.SendEventUnsyncedWithTxnID(t, roomID, b.Event{ - Type: "m.room.message", - Content: map[string]interface{}{ - "msgtype": "m.text", - "body": "first", - }, - }, txnId) - - // Use the refresh token to get a new access token. - c.AccessToken, refreshToken, _ = c.ConsumeRefreshToken(t, refreshToken) - - // When syncing, we should find the event and it should also have the correct transaction ID even + eventID1 := c.Unsafe_SendEventUnsyncedWithTxnID(t, roomID, b.Event{ + Type: "m.room.message", + Content: map[string]interface{}{ + "msgtype": "m.text", + "body": "first", + }, + }, txnId) + + // Use the refresh token to get a new access token. + c.AccessToken, refreshToken, _ = c.ConsumeRefreshToken(t, refreshToken) + + // When syncing, we should find the event and it should also have the correct transaction ID even // though the access token is different. - c.MustSyncUntil(t, client.SyncReq{}, mustHaveTransactionIDForEvent(t, roomID, eventID1, txnId)) + c.MustSyncUntil(t, client.SyncReq{}, mustHaveTransactionIDForEvent(t, roomID, eventID1, txnId)) // We try sending the event again with the same transaction ID - eventID2 := c.SendEventUnsyncedWithTxnID(t, roomID, b.Event{ - Type: "m.room.message", - Content: map[string]interface{}{ - "msgtype": "m.text", - "body": "first", - }, - }, txnId) + eventID2 := c.Unsafe_SendEventUnsyncedWithTxnID(t, roomID, b.Event{ + Type: "m.room.message", + Content: map[string]interface{}{ + "msgtype": "m.text", + "body": "first", + }, + }, txnId) // The event should have been deduplicated and we should get back the same event ID must.EqualStr(t, eventID2, eventID1, "Expected eventID1 and eventID2 to be the same from a client using a refresh token") diff --git a/tests/csapi/upload_keys_test.go b/tests/csapi/upload_keys_test.go index e1127411..d7b96e59 100644 --- a/tests/csapi/upload_keys_test.go +++ b/tests/csapi/upload_keys_test.go @@ -7,10 +7,9 @@ import ( "testing" "github.com/tidwall/gjson" - "maunium.net/go/mautrix/crypto/olm" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/complement/runtime" @@ -23,7 +22,8 @@ func TestUploadKey(t *testing.T) { alice := deployment.Client(t, "hs1", "@alice:hs1") bob := deployment.Client(t, "hs1", "@bob:hs1") - deviceKeys, oneTimeKeys := generateKeys(t, alice, 1) + deviceKeys, oneTimeKeys := alice.GenerateOneTimeKeys(t, 1) + t.Run("Parallel", func(t *testing.T) { // sytest: Can upload device keys t.Run("Can upload device keys", func(t *testing.T) { @@ -31,7 +31,7 @@ func TestUploadKey(t *testing.T) { "device_keys": deviceKeys, "one_time_keys": oneTimeKeys, }) - resp := alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "upload"}, reqBody) + resp := alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "keys", "upload"}, reqBody) must.MatchResponse(t, resp, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -64,7 +64,7 @@ func TestUploadKey(t *testing.T) { }, "one_time_keys": oneTimeKeys, }) - resp := bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "upload"}, reqBody) + resp := bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "keys", "upload"}, reqBody) must.MatchResponse(t, resp, match.HTTPResponse{ StatusCode: http.StatusBadRequest, JSON: []match.JSON{ @@ -83,7 +83,7 @@ func TestUploadKey(t *testing.T) { "device_id": alice.DeviceID, }, }) - resp := bob.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "upload"}, reqBody) + resp := bob.Do(t, "POST", []string{"_matrix", "client", "v3", "keys", "upload"}, reqBody) must.MatchResponse(t, resp, match.HTTPResponse{ StatusCode: http.StatusBadRequest, }) @@ -96,7 +96,7 @@ func TestUploadKey(t *testing.T) { alice.UserID: {}, }, }) - resp := alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "query"}, reqBody) + resp := alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "keys", "query"}, reqBody) must.MatchResponse(t, resp, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -111,7 +111,7 @@ func TestUploadKey(t *testing.T) { alice.UserID: {alice.DeviceID}, }, }) - resp := alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "query"}, reqBody) + resp := alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "keys", "query"}, reqBody) deviceKeysField := "device_keys." + client.GjsonEscape(alice.UserID) + "." + client.GjsonEscape(alice.DeviceID) must.MatchResponse(t, resp, match.HTTPResponse{ StatusCode: http.StatusOK, @@ -131,7 +131,7 @@ func TestUploadKey(t *testing.T) { bob.UserID: {}, }, }) - resp := alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "query"}, reqBody) + resp := alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "keys", "query"}, reqBody) deviceKeysField := "device_keys." + client.GjsonEscape(bob.UserID) must.MatchResponse(t, resp, match.HTTPResponse{ StatusCode: http.StatusOK, @@ -151,7 +151,7 @@ func TestUploadKey(t *testing.T) { }, }, }) - resp := alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "claim"}, reqBody) + resp := alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "keys", "claim"}, reqBody) otksField := "one_time_keys." + client.GjsonEscape(alice.UserID) + "." + client.GjsonEscape(alice.DeviceID) must.MatchResponse(t, resp, match.HTTPResponse{ StatusCode: http.StatusOK, @@ -162,7 +162,7 @@ func TestUploadKey(t *testing.T) { }) // there should be no OTK left now - resp = alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "claim"}, reqBody) + resp = alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "keys", "claim"}, reqBody) must.MatchResponse(t, resp, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -172,51 +172,3 @@ func TestUploadKey(t *testing.T) { }) }) } - -func generateKeys(t *testing.T, user *client.CSAPI, otkCount uint) (deviceKeys map[string]interface{}, oneTimeKeys map[string]interface{}) { - t.Helper() - account := olm.NewAccount() - ed25519Key, curveKey := account.IdentityKeys() - - ed25519KeyID := fmt.Sprintf("ed25519:%s", user.DeviceID) - curveKeyID := fmt.Sprintf("curve25519:%s", user.DeviceID) - - deviceKeys = map[string]interface{}{ - "user_id": user.UserID, - "device_id": user.DeviceID, - "algorithms": []interface{}{"m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"}, - "keys": map[string]interface{}{ - ed25519KeyID: ed25519Key.String(), - curveKeyID: curveKey.String(), - }, - } - - signature, _ := account.SignJSON(deviceKeys) - - deviceKeys["signatures"] = map[string]interface{}{ - user.UserID: map[string]interface{}{ - ed25519KeyID: signature, - }, - } - - account.GenOneTimeKeys(otkCount) - oneTimeKeys = map[string]interface{}{} - - for kid, key := range account.OneTimeKeys() { - keyID := fmt.Sprintf("signed_curve25519:%s", kid) - keyMap := map[string]interface{}{ - "key": key.String(), - } - - signature, _ = account.SignJSON(keyMap) - - keyMap["signatures"] = map[string]interface{}{ - user.UserID: map[string]interface{}{ - ed25519KeyID: signature, - }, - } - - oneTimeKeys[keyID] = keyMap - } - return deviceKeys, oneTimeKeys -} diff --git a/tests/csapi/url_preview_test.go b/tests/csapi/url_preview_test.go index d8896c9a..6ee28e18 100644 --- a/tests/csapi/url_preview_test.go +++ b/tests/csapi/url_preview_test.go @@ -10,8 +10,8 @@ import ( "github.com/gorilla/mux" "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/data" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" @@ -64,7 +64,7 @@ func TestUrlPreview(t *testing.T) { alice := deployment.Client(t, "hs1", "@alice:hs1") - res := alice.MustDoFunc(t, "GET", []string{"_matrix", "media", "v3", "preview_url"}, + res := alice.MustDo(t, "GET", []string{"_matrix", "media", "v3", "preview_url"}, client.WithQueries(url.Values{ "url": []string{webServer.URL + "/test.html"}, }), diff --git a/tests/csapi/user_directory_display_names_test.go b/tests/csapi/user_directory_display_names_test.go index d208f20e..78c81e3c 100644 --- a/tests/csapi/user_directory_display_names_test.go +++ b/tests/csapi/user_directory_display_names_test.go @@ -7,8 +7,8 @@ package csapi_tests import ( "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -50,7 +50,7 @@ func setupUsers(t *testing.T) (*client.CSAPI, *client.CSAPI, *client.CSAPI, func // Alice sets her profile displayname. This ensures that her // public name, private name and userid localpart are all // distinguishable, even case-insensitively. - alice.MustDoFunc( + alice.MustDo( t, "PUT", []string{"_matrix", "client", "v3", "profile", alice.UserID, "displayname"}, @@ -66,7 +66,7 @@ func setupUsers(t *testing.T) (*client.CSAPI, *client.CSAPI, *client.CSAPI, func func checkExpectations(t *testing.T, bob, eve *client.CSAPI) { t.Run("Eve can find Alice by profile display name", func(t *testing.T) { - res := eve.MustDoFunc( + res := eve.MustDo( t, "POST", []string{"_matrix", "client", "v3", "user_directory", "search"}, @@ -78,7 +78,7 @@ func checkExpectations(t *testing.T, bob, eve *client.CSAPI) { }) t.Run("Eve can find Alice by mxid", func(t *testing.T) { - res := eve.MustDoFunc( + res := eve.MustDo( t, "POST", []string{"_matrix", "client", "v3", "user_directory", "search"}, @@ -90,7 +90,7 @@ func checkExpectations(t *testing.T, bob, eve *client.CSAPI) { }) t.Run("Eve cannot find Alice by room-specific name that Eve is not privy to", func(t *testing.T) { - res := eve.MustDoFunc( + res := eve.MustDo( t, "POST", []string{"_matrix", "client", "v3", "user_directory", "search"}, @@ -102,7 +102,7 @@ func checkExpectations(t *testing.T, bob, eve *client.CSAPI) { }) t.Run("Bob can find Alice by profile display name", func(t *testing.T) { - res := bob.MustDoFunc( + res := bob.MustDo( t, "POST", []string{"_matrix", "client", "v3", "user_directory", "search"}, @@ -116,7 +116,7 @@ func checkExpectations(t *testing.T, bob, eve *client.CSAPI) { }) t.Run("Bob can find Alice by mxid", func(t *testing.T) { - res := bob.MustDoFunc( + res := bob.MustDo( t, "POST", []string{"_matrix", "client", "v3", "user_directory", "search"}, @@ -145,7 +145,7 @@ func TestRoomSpecificUsernameChange(t *testing.T) { alice.JoinRoom(t, privateRoom, nil) // Alice reveals her private name to Bob - alice.MustDoFunc( + alice.MustDo( t, "PUT", []string{"_matrix", "client", "v3", "rooms", privateRoom, "state", "m.room.member", alice.UserID}, @@ -174,7 +174,7 @@ func TestRoomSpecificUsernameAtJoin(t *testing.T) { alice.JoinRoom(t, privateRoom, nil) // Alice reveals her private name to Bob - alice.MustDoFunc( + alice.MustDo( t, "PUT", []string{"_matrix", "client", "v3", "rooms", privateRoom, "state", "m.room.member", alice.UserID}, diff --git a/tests/csapi/user_query_keys_test.go b/tests/csapi/user_query_keys_test.go index bc1e00ce..b9ece4cf 100644 --- a/tests/csapi/user_query_keys_test.go +++ b/tests/csapi/user_query_keys_test.go @@ -3,8 +3,8 @@ package csapi_tests import ( "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -20,7 +20,7 @@ func TestKeysQueryWithDeviceIDAsObjectFails(t *testing.T) { userID := "@alice:hs1" alice := deployment.Client(t, "hs1", userID) - res := alice.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "query"}, + res := alice.Do(t, "POST", []string{"_matrix", "client", "v3", "keys", "query"}, client.WithJSONBody(t, map[string]interface{}{ "device_keys": map[string]interface{}{ "@bob:hs1": map[string]bool{ diff --git a/tests/direct_messaging_test.go b/tests/direct_messaging_test.go index 44b8b8af..93854111 100644 --- a/tests/direct_messaging_test.go +++ b/tests/direct_messaging_test.go @@ -6,8 +6,8 @@ import ( "testing" "time" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" @@ -126,7 +126,7 @@ func TestIsDirectFlagFederation(t *testing.T) { bob := srv.UserID("bob") room := srv.MustMakeRoom(t, roomVer, federation.InitialRoomEvents(roomVer, bob)) - dmInviteEvent := srv.MustCreateEvent(t, room, b.Event{ + dmInviteEvent := srv.MustCreateEvent(t, room, federation.Event{ Type: "m.room.member", StateKey: &alice.UserID, Sender: bob, diff --git a/tests/federation_acl_test.go b/tests/federation_acl_test.go index adcc729e..ead0a429 100644 --- a/tests/federation_acl_test.go +++ b/tests/federation_acl_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/complement/runtime" @@ -142,7 +142,7 @@ func TestACLs(t *testing.T) { } // Validate the ACL event is actually in the rooms state - res := user.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.server_acl"}) + res := user.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.server_acl"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONKeyEqual("allow", []string{"*"}), diff --git a/tests/federation_presence_test.go b/tests/federation_presence_test.go index 64adeb23..5dd412a7 100644 --- a/tests/federation_presence_test.go +++ b/tests/federation_presence_test.go @@ -5,8 +5,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" ) func TestRemotePresence(t *testing.T) { @@ -21,7 +21,7 @@ func TestRemotePresence(t *testing.T) { _, bobSinceToken := bob.MustSync(t, client.SyncReq{TimeoutMillis: "0"}) statusMsg := "Update for room members" - alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "presence", "@alice:hs1", "status"}, + alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "presence", "@alice:hs1", "status"}, client.WithJSONBody(t, map[string]interface{}{ "status_msg": statusMsg, "presence": "online", @@ -38,7 +38,7 @@ func TestRemotePresence(t *testing.T) { t.Run("Presence changes to UNAVAILABLE are reported to remote room members", func(t *testing.T) { _, bobSinceToken := bob.MustSync(t, client.SyncReq{TimeoutMillis: "0"}) - alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "presence", "@alice:hs1", "status"}, + alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "presence", "@alice:hs1", "status"}, client.WithJSONBody(t, map[string]interface{}{ "presence": "unavailable", }), diff --git a/tests/federation_query_profile_test.go b/tests/federation_query_profile_test.go index 35e07edd..39cae7c3 100644 --- a/tests/federation_query_profile_test.go +++ b/tests/federation_query_profile_test.go @@ -9,8 +9,8 @@ import ( "github.com/matrix-org/gomatrixserverlib/fclient" "github.com/matrix-org/gomatrixserverlib/spec" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" @@ -60,7 +60,7 @@ func TestOutboundFederationProfile(t *testing.T) { // query the display name which should do an outbound federation hit unauthedClient := deployment.Client(t, "hs1", "") - res := unauthedClient.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "profile", remoteUserID, "displayname"}) + res := unauthedClient.MustDo(t, "GET", []string{"_matrix", "client", "v3", "profile", remoteUserID, "displayname"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONKeyEqual("displayname", remoteDisplayName), @@ -106,7 +106,7 @@ func TestInboundFederationProfile(t *testing.T) { t.Run("Inbound federation can query profile data", func(t *testing.T) { const alicePublicName = "Alice Cooper" - alice.MustDoFunc( + alice.MustDo( t, "PUT", []string{"_matrix", "client", "v3", "profile", alice.UserID, "displayname"}, diff --git a/tests/federation_redaction_test.go b/tests/federation_redaction_test.go index ef9a89a6..29c2c00b 100644 --- a/tests/federation_redaction_test.go +++ b/tests/federation_redaction_test.go @@ -1,12 +1,13 @@ package tests import ( + "testing" + "time" + "github.com/matrix-org/complement/internal/b" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/runtime" "github.com/matrix-org/gomatrixserverlib" - "testing" - "time" ) // test that a redaction is sent out over federation even if we don't have the original event @@ -56,13 +57,12 @@ func TestFederationRedactSendsWithoutEvent(t *testing.T) { alice.JoinRoom(t, roomAlias, []string{srv.ServerName()}) // inject event to redact in the room - badEvent := srv.MustCreateEvent(t, serverRoom, b.Event{ + badEvent := srv.MustCreateEvent(t, serverRoom, federation.Event{ Type: "m.room.message", Sender: charlie, Content: map[string]interface{}{ "body": "666", - }, - }) + }}) serverRoom.AddEvent(badEvent) eventID := badEvent.EventID() @@ -70,9 +70,12 @@ func TestFederationRedactSendsWithoutEvent(t *testing.T) { eventToRedact := eventID + ":" + fullServerName // the client sends a request to the local homeserver to send the redaction - res := alice.SendRedaction(t, serverRoom.RoomID, b.Event{Type: wantEventType, Content: map[string]interface{}{ - "msgtype": "m.room.redaction"}, - Redacts: eventToRedact}, eventToRedact) + res := alice.SendRedaction(t, serverRoom.RoomID, b.Event{ + Type: wantEventType, + Content: map[string]interface{}{ + "reason": "reasons...", + }, + }, eventToRedact) // wait for redaction to arrive at remote homeserver waiter.Wait(t, 1*time.Second) diff --git a/tests/federation_room_alias_test.go b/tests/federation_room_alias_test.go index 5792fb70..20561174 100644 --- a/tests/federation_room_alias_test.go +++ b/tests/federation_room_alias_test.go @@ -3,8 +3,8 @@ package tests import ( "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -21,11 +21,11 @@ func TestRemoteAliasRequestsUnderstandUnicode(t *testing.T) { roomID := alice.CreateRoom(t, map[string]interface{}{}) - alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "directory", "room", unicodeAlias}, client.WithJSONBody(t, map[string]interface{}{ + alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "directory", "room", unicodeAlias}, client.WithJSONBody(t, map[string]interface{}{ "room_id": roomID, })) - res := bob.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "directory", "room", unicodeAlias}) + res := bob.Do(t, "GET", []string{"_matrix", "client", "v3", "directory", "room", unicodeAlias}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, JSON: []match.JSON{ diff --git a/tests/federation_room_ban_test.go b/tests/federation_room_ban_test.go index 0eae4920..444a5306 100644 --- a/tests/federation_room_ban_test.go +++ b/tests/federation_room_ban_test.go @@ -3,8 +3,8 @@ package tests import ( "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/runtime" ) @@ -25,13 +25,13 @@ func TestUnbanViaInvite(t *testing.T) { alice.JoinRoom(t, roomID, []string{"hs2"}) // Ban Alice - bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "ban"}, client.WithJSONBody(t, map[string]interface{}{ + bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "ban"}, client.WithJSONBody(t, map[string]interface{}{ "user_id": alice.UserID, })) alice.MustSyncUntil(t, client.SyncReq{}, client.SyncLeftFrom(alice.UserID, roomID)) // Unban Alice - bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "unban"}, client.WithJSONBody(t, map[string]interface{}{ + bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "unban"}, client.WithJSONBody(t, map[string]interface{}{ "user_id": alice.UserID, })) bob.MustSyncUntil(t, client.SyncReq{}, client.SyncLeftFrom(alice.UserID, roomID)) diff --git a/tests/federation_room_event_auth_test.go b/tests/federation_room_event_auth_test.go index b469edc8..3a317ba4 100644 --- a/tests/federation_room_event_auth_test.go +++ b/tests/federation_room_event_auth_test.go @@ -17,8 +17,8 @@ import ( "github.com/matrix-org/gomatrixserverlib/spec" "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/must" ) @@ -118,7 +118,7 @@ func TestInboundFederationRejectsEventsWithRejectedAuthEvents(t *testing.T) { charlieMembershipEvent := room.CurrentState("m.room.member", charlie) // have Charlie send a PL event which will be rejected - rejectedEvent := srv.MustCreateEvent(t, room, b.Event{ + rejectedEvent := srv.MustCreateEvent(t, room, federation.Event{ Type: "m.room.power_levels", StateKey: b.Ptr(""), Sender: charlie, @@ -140,7 +140,7 @@ func TestInboundFederationRejectsEventsWithRejectedAuthEvents(t *testing.T) { // create an event to be pulled in as an outlier, which is valid according to its prev events, // but uses the rejected event among its auth events. - outlierEvent := srv.MustCreateEvent(t, room, b.Event{ + outlierEvent := srv.MustCreateEvent(t, room, federation.Event{ Type: "m.room.member", StateKey: &charlie, Sender: charlie, @@ -166,7 +166,7 @@ func TestInboundFederationRejectsEventsWithRejectedAuthEvents(t *testing.T) { charlieMembershipEvent, outlierEvent, } - sentEvent1 := srv.MustCreateEvent(t, room, b.Event{ + sentEvent1 := srv.MustCreateEvent(t, room, federation.Event{ Type: "m.room.message", Sender: charlie, Content: map[string]interface{}{"body": "sentEvent1"}, @@ -178,7 +178,7 @@ func TestInboundFederationRejectsEventsWithRejectedAuthEvents(t *testing.T) { // another a regular event which refers to the outlier event, but // this time we will give a different answer to /event_auth - sentEvent2 := srv.MustCreateEvent(t, room, b.Event{ + sentEvent2 := srv.MustCreateEvent(t, room, federation.Event{ Type: "m.room.message", Sender: charlie, Content: map[string]interface{}{"body": "sentEvent1"}, @@ -190,7 +190,7 @@ func TestInboundFederationRejectsEventsWithRejectedAuthEvents(t *testing.T) { t.Logf("Created sent event 2 %s", sentEvent2.EventID()) // finally, a genuine regular event. - sentinelEvent := srv.MustCreateEvent(t, room, b.Event{ + sentinelEvent := srv.MustCreateEvent(t, room, federation.Event{ Type: "m.room.message", Sender: charlie, Content: map[string]interface{}{"body": "sentinelEvent"}, @@ -221,7 +221,7 @@ func TestInboundFederationRejectsEventsWithRejectedAuthEvents(t *testing.T) { // now inspect the results. Each of the rejected events should give a 404 for /event t.Run("Outlier should be rejected", func(t *testing.T) { - res := alice.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", room.RoomID, "event", outlierEvent.EventID()}) + res := alice.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", room.RoomID, "event", outlierEvent.EventID()}) defer res.Body.Close() if res.StatusCode != 404 { t.Errorf("Expected a 404 when fetching outlier event, but got %d", res.StatusCode) @@ -229,7 +229,7 @@ func TestInboundFederationRejectsEventsWithRejectedAuthEvents(t *testing.T) { }) t.Run("sent event 1 should be rejected", func(t *testing.T) { - res := alice.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", room.RoomID, "event", sentEvent1.EventID()}) + res := alice.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", room.RoomID, "event", sentEvent1.EventID()}) defer res.Body.Close() if res.StatusCode != 404 { t.Errorf("Expected a 404 when fetching sent event 1, but got %d", res.StatusCode) @@ -237,7 +237,7 @@ func TestInboundFederationRejectsEventsWithRejectedAuthEvents(t *testing.T) { }) t.Run("sent event 2 should be rejected", func(t *testing.T) { - res := alice.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", room.RoomID, "event", sentEvent2.EventID()}) + res := alice.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", room.RoomID, "event", sentEvent2.EventID()}) defer res.Body.Close() if res.StatusCode != 404 { t.Errorf("Expected a 404 when fetching sent event 2, but got %d", res.StatusCode) diff --git a/tests/federation_room_get_missing_events_test.go b/tests/federation_room_get_missing_events_test.go index 0c74ee92..a568af79 100644 --- a/tests/federation_room_get_missing_events_test.go +++ b/tests/federation_room_get_missing_events_test.go @@ -14,8 +14,8 @@ import ( "github.com/matrix-org/util" "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" @@ -73,7 +73,7 @@ func TestGetMissingEventsGapFilling(t *testing.T) { var missingEventIDs []string numMissingEvents := 5 for i := 0; i < numMissingEvents; i++ { - missingEvent := srv.MustCreateEvent(t, srvRoom, b.Event{ + missingEvent := srv.MustCreateEvent(t, srvRoom, federation.Event{ Sender: bob, Type: "m.room.message", Content: map[string]interface{}{ @@ -86,7 +86,7 @@ func TestGetMissingEventsGapFilling(t *testing.T) { } // 3) Inject a final event into Complement - mostRecentEvent := srv.MustCreateEvent(t, srvRoom, b.Event{ + mostRecentEvent := srv.MustCreateEvent(t, srvRoom, federation.Event{ Sender: bob, Type: "m.room.message", Content: map[string]interface{}{ @@ -237,7 +237,7 @@ func TestOutboundFederationIgnoresMissingEventWithBadJSONForRoomVersion6(t *test room.AddEvent(signedBadEvent) // send the first "good" event, referencing the broken event as a prev_event - sentEvent := srv.MustCreateEvent(t, room, b.Event{ + sentEvent := srv.MustCreateEvent(t, room, federation.Event{ Type: "m.room.message", Sender: charlie, Content: map[string]interface{}{ @@ -291,7 +291,7 @@ func TestOutboundFederationIgnoresMissingEventWithBadJSONForRoomVersion6(t *test // it just ignores it, so we need to send another event referring to the // first one and check that we get a /get_missing_events request. - message3 := srv.MustCreateEvent(t, room, b.Event{ + message3 := srv.MustCreateEvent(t, room, federation.Event{ Type: "m.room.message", Sender: charlie, Content: map[string]interface{}{ diff --git a/tests/federation_room_join_partial_state_test.go b/tests/federation_room_join_partial_state_test.go index c3cbd36d..49ad59e0 100644 --- a/tests/federation_room_join_partial_state_test.go +++ b/tests/federation_room_join_partial_state_test.go @@ -30,8 +30,8 @@ import ( "github.com/matrix-org/gomatrixserverlib/fclient" "github.com/matrix-org/gomatrixserverlib/spec" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/docker" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/match" @@ -170,7 +170,7 @@ func TestPartialStateJoin(t *testing.T) { ) gomatrixserverlib.PDU { t.Helper() - return signingServer.MustCreateEvent(t, room, b.Event{ + return signingServer.MustCreateEvent(t, room, federation.Event{ Type: "m.room.member", StateKey: b.Ptr(userId), Sender: userId, @@ -305,7 +305,7 @@ func TestPartialStateJoin(t *testing.T) { t.Log("4. Have Alice send a message to the remote room.") removePDUHandler := server.AddPDUHandler(func(gomatrixserverlib.PDU) bool { return true }) defer removePDUHandler() - messageId := alice.SendEventUnsynced(t, serverRoom.RoomID, b.Event{ + messageId := alice.Unsafe_SendEventUnsynced(t, serverRoom.RoomID, b.Event{ Type: "m.room.message", Content: map[string]interface{}{ "body": "Hello world", @@ -478,7 +478,7 @@ func TestPartialStateJoin(t *testing.T) { alice.Client.Timeout = 2 * time.Second paths := []string{"_matrix", "client", "v3", "rooms", serverRoom.RoomID, "send", "m.room.message", "0"} - res := alice.MustDoFunc(t, "PUT", paths, client.WithJSONBody(t, map[string]interface{}{ + res := alice.MustDo(t, "PUT", paths, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": "Hello world!", })) @@ -1135,7 +1135,7 @@ func TestPartialStateJoin(t *testing.T) { go func() { queryParams := url.Values{} queryParams.Set("at", syncToken) - clientMembersRequestResponseChan <- alice.MustDoFunc( + clientMembersRequestResponseChan <- alice.MustDo( t, "GET", []string{"_matrix", "client", "v3", "rooms", serverRoom.RoomID, "members"}, @@ -1328,7 +1328,7 @@ func TestPartialStateJoin(t *testing.T) { // we will do a gappy sync after, which will only pick up the last message. var lastEventID string for i := 0; i < 2; i++ { - event := server.MustCreateEvent(t, serverRoom, b.Event{ + event := server.MustCreateEvent(t, serverRoom, federation.Event{ Type: "m.room.message", Sender: server.UserID("derek"), Content: map[string]interface{}{ @@ -1416,7 +1416,7 @@ func TestPartialStateJoin(t *testing.T) { outlierEventIDs := make([]string, len(outliers)) for i := range outliers { body := fmt.Sprintf("outlier event %d", i) - outliers[i] = server.MustCreateEvent(t, serverRoom, b.Event{ + outliers[i] = server.MustCreateEvent(t, serverRoom, federation.Event{ Type: "outlier_state", Sender: server.UserID("charlie"), StateKey: b.Ptr(fmt.Sprintf("state_%d", i)), @@ -1517,7 +1517,7 @@ func TestPartialStateJoin(t *testing.T) { federation.HandleEventAuthRequests()(server.Server) // derek sends a state event, despite not having permission to send state. This should be rejected. - badStateEvent := server.MustCreateEvent(t, serverRoom, b.Event{ + badStateEvent := server.MustCreateEvent(t, serverRoom, federation.Event{ Type: "m.room.test", StateKey: b.Ptr(""), Sender: server.UserID("derek"), @@ -1545,7 +1545,7 @@ func TestPartialStateJoin(t *testing.T) { // ... and check that the bad state event is *not* visible must.MatchResponse(t, - alice.DoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", serverRoom.RoomID, "event", badStateEvent.EventID()}), + alice.Do(t, "GET", []string{"_matrix", "client", "r0", "rooms", serverRoom.RoomID, "event", badStateEvent.EventID()}), match.HTTPResponse{ StatusCode: 404, JSON: []match.JSON{ @@ -1561,7 +1561,7 @@ func TestPartialStateJoin(t *testing.T) { // check that the bad state event is *still* not visible must.MatchResponse(t, - alice.DoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", serverRoom.RoomID, "event", badStateEvent.EventID()}), + alice.Do(t, "GET", []string{"_matrix", "client", "r0", "rooms", serverRoom.RoomID, "event", badStateEvent.EventID()}), match.HTTPResponse{ StatusCode: 404, JSON: []match.JSON{ @@ -1608,7 +1608,7 @@ func TestPartialStateJoin(t *testing.T) { // derek now sends a state event with auth_events that say he was in the room. It will be // accepted during the faster join, but should then ultimately be rejected. - badStateEvent := server.MustCreateEvent(t, serverRoom, b.Event{ + badStateEvent := server.MustCreateEvent(t, serverRoom, federation.Event{ Type: "m.room.test", StateKey: b.Ptr(""), Sender: derek, @@ -1639,7 +1639,7 @@ func TestPartialStateJoin(t *testing.T) { // the bad state event should now *not* be visible must.MatchResponse(t, - alice.DoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", serverRoom.RoomID, "event", badStateEvent.EventID()}), + alice.Do(t, "GET", []string{"_matrix", "client", "r0", "rooms", serverRoom.RoomID, "event", badStateEvent.EventID()}), match.HTTPResponse{ StatusCode: 404, JSON: []match.JSON{ @@ -1691,7 +1691,7 @@ func TestPartialStateJoin(t *testing.T) { // Derek now kicks Elsie, with auth_events that say he was in the room. It will be // accepted during the faster join, but should then ultimately be rejected. - badKickEvent := server.MustCreateEvent(t, serverRoom, b.Event{ + badKickEvent := server.MustCreateEvent(t, serverRoom, federation.Event{ Type: "m.room.member", StateKey: &elsie, Sender: derek, @@ -1711,7 +1711,7 @@ func TestPartialStateJoin(t *testing.T) { t.Logf("derek created bad kick event %s with auth events %#v", badKickEvent.EventID(), badKickEvent.AuthEventIDs()) // elsie sends some state. This should be rejected during the faster join, but ultimately accepted. - rejectedStateEvent := server.MustCreateEvent(t, serverRoom, b.Event{ + rejectedStateEvent := server.MustCreateEvent(t, serverRoom, federation.Event{ Type: "m.room.test", StateKey: b.Ptr(""), Sender: elsie, @@ -1739,7 +1739,7 @@ func TestPartialStateJoin(t *testing.T) { // ... but the rejected state event should not. syncToken = awaitEventViaSync(t, alice, serverRoom.RoomID, sentinelEvent.EventID(), syncToken) must.MatchResponse(t, - alice.DoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", serverRoom.RoomID, "event", rejectedStateEvent.EventID()}), + alice.Do(t, "GET", []string{"_matrix", "client", "r0", "rooms", serverRoom.RoomID, "event", rejectedStateEvent.EventID()}), match.HTTPResponse{ StatusCode: 404, JSON: []match.JSON{ @@ -1755,7 +1755,7 @@ func TestPartialStateJoin(t *testing.T) { // the bad kick event should now *not* be visible must.MatchResponse(t, - alice.DoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", serverRoom.RoomID, "event", badKickEvent.EventID()}), + alice.Do(t, "GET", []string{"_matrix", "client", "r0", "rooms", serverRoom.RoomID, "event", badKickEvent.EventID()}), match.HTTPResponse{ StatusCode: 404, JSON: []match.JSON{ @@ -1902,7 +1902,7 @@ func TestPartialStateJoin(t *testing.T) { // attempts to joined_members should now block. Fire off a goroutine to try it. jmResponseChan := make(chan *http.Response) go func() { - response := alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", serverRoom.RoomID, "joined_members"}) + response := alice.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", serverRoom.RoomID, "joined_members"}) jmResponseChan <- response close(jmResponseChan) }() @@ -2130,7 +2130,7 @@ func TestPartialStateJoin(t *testing.T) { renameDevice := func(t *testing.T, user *client.CSAPI, displayName string) { t.Helper() - user.MustDoFunc( + user.MustDo( t, "PUT", []string{"_matrix", "client", "v3", "devices", user.DeviceID}, @@ -2331,7 +2331,7 @@ func TestPartialStateJoin(t *testing.T) { var powerLevelsContent map[string]interface{} json.Unmarshal(room.CurrentState("m.room.power_levels", "").Content(), &powerLevelsContent) powerLevelsContent["users"].(map[string]interface{})[derek] = 100 - room.AddEvent(server1.MustCreateEvent(t, room, b.Event{ + room.AddEvent(server1.MustCreateEvent(t, room, federation.Event{ Type: "m.room.power_levels", StateKey: b.Ptr(""), Sender: server1.UserID("charlie"), @@ -2366,7 +2366,7 @@ func TestPartialStateJoin(t *testing.T) { t.Log("@charlie, @derek and @elsie received device list update.") // @derek:server1 "kicks" @elsie:server2. - badKickEvent := server1.MustCreateEvent(t, room, b.Event{ + badKickEvent := server1.MustCreateEvent(t, room, federation.Event{ Type: "m.room.member", StateKey: b.Ptr(elsie), Sender: derek, @@ -2739,7 +2739,7 @@ func TestPartialStateJoin(t *testing.T) { mustQueryKeys := func(t *testing.T, user *client.CSAPI, userID string) { t.Helper() - user.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "query"}, + user.MustDo(t, "POST", []string{"_matrix", "client", "v3", "keys", "query"}, client.WithJSONBody(t, map[string]interface{}{ "device_keys": map[string]interface{}{ userID: []string{}, @@ -2829,7 +2829,7 @@ func TestPartialStateJoin(t *testing.T) { syncDeviceListsHas(section, expectedUserID), ) - res := user.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "keys", "changes"}, + res := user.MustDo(t, "GET", []string{"_matrix", "client", "v3", "keys", "changes"}, client.WithQueries(url.Values{ "from": []string{syncToken}, "to": []string{nextSyncToken}, @@ -3141,7 +3141,7 @@ func TestPartialStateJoin(t *testing.T) { json.Unmarshal(room.CurrentState("m.room.power_levels", "").Content(), &powerLevelsContent) powerLevelsContent["users"].(map[string]interface{})[derek] = 50 powerLevelsContent["users"].(map[string]interface{})[fred] = 100 - room.AddEvent(server.MustCreateEvent(t, room, b.Event{ + room.AddEvent(server.MustCreateEvent(t, room, federation.Event{ Type: "m.room.power_levels", StateKey: b.Ptr(""), Sender: charlie, @@ -3168,7 +3168,7 @@ func TestPartialStateJoin(t *testing.T) { // @fred is really in the room. // This event has to be a ban, rather than a kick, otherwise state resolution can bring // @derek back into the room and ruin the test setup. - badKickEvent := server.MustCreateEvent(t, room, b.Event{ + badKickEvent := server.MustCreateEvent(t, room, federation.Event{ Type: "m.room.member", StateKey: b.Ptr(derek), Sender: fred, @@ -3188,7 +3188,7 @@ func TestPartialStateJoin(t *testing.T) { // @derek kicks @elsie. // This is incorrectly rejected since the homeserver under test incorrectly thinks // @derek had been kicked from the room. - kickEvent := server.MustCreateEvent(t, room, b.Event{ + kickEvent := server.MustCreateEvent(t, room, federation.Event{ Type: "m.room.member", StateKey: b.Ptr(elsie), Sender: derek, @@ -3205,7 +3205,7 @@ func TestPartialStateJoin(t *testing.T) { // Check that the last kick was incorrectly rejected. must.MatchResponse(t, - alice.DoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", room.RoomID, "event", kickEvent.EventID()}), + alice.Do(t, "GET", []string{"_matrix", "client", "r0", "rooms", room.RoomID, "event", kickEvent.EventID()}), match.HTTPResponse{ StatusCode: 404, JSON: []match.JSON{ @@ -3398,7 +3398,7 @@ func TestPartialStateJoin(t *testing.T) { // Alice creates an alias for the room aliasName := "#t40alice-room:hs1" - alice.MustDoFunc( + alice.MustDo( t, "PUT", []string{"_matrix", "client", "v3", "directory", "room", aliasName}, @@ -3408,7 +3408,7 @@ func TestPartialStateJoin(t *testing.T) { ) // Alice then queries that alias - response := alice.MustDoFunc( + response := alice.MustDo( t, "GET", []string{"_matrix", "client", "v3", "directory", "room", aliasName}, @@ -3449,7 +3449,7 @@ func TestPartialStateJoin(t *testing.T) { // Alice creates an alias for the room aliasName := "#t41alice-room:hs1" - alice.MustDoFunc( + alice.MustDo( t, "PUT", []string{"_matrix", "client", "v3", "directory", "room", aliasName}, @@ -3459,7 +3459,7 @@ func TestPartialStateJoin(t *testing.T) { ) // Alice then deletes that alias - response := alice.MustDoFunc( + response := alice.MustDo( t, "DELETE", []string{"_matrix", "client", "v3", "directory", "room", aliasName}, @@ -3528,7 +3528,7 @@ func TestPartialStateJoin(t *testing.T) { ) defer removePDUHandler() - alice.MustDoFunc(t, + alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "profile", alice.UserID, "displayname"}, client.WithJSONBody(t, map[string]interface{}{ @@ -3809,7 +3809,7 @@ func TestPartialStateJoin(t *testing.T) { ) t.Log("A resident server user kicks Alice from the room.") - kickEvent := server.MustCreateEvent(t, serverRoom, b.Event{ + kickEvent := server.MustCreateEvent(t, serverRoom, federation.Event{ Type: "m.room.member", StateKey: b.Ptr(alice.UserID), Sender: server.UserID("charlie"), @@ -3861,7 +3861,7 @@ func TestPartialStateJoin(t *testing.T) { ) t.Log("A resident server user bans Alice from the room.") - banEvent := server.MustCreateEvent(t, serverRoom, b.Event{ + banEvent := server.MustCreateEvent(t, serverRoom, federation.Event{ Type: "m.room.member", StateKey: b.Ptr(alice.UserID), Sender: server.UserID("charlie"), @@ -3890,7 +3890,7 @@ func TestPartialStateJoin(t *testing.T) { t.Log("Alice tries to rejoin...") queryParams := url.Values{} queryParams.Add("server_name", server.ServerName()) - response := alice.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "join", serverRoom.RoomID}, client.WithQueries(queryParams)) + response := alice.Do(t, "POST", []string{"_matrix", "client", "v3", "join", serverRoom.RoomID}, client.WithQueries(queryParams)) t.Log("... but Alice was forbidden from rejoining") must.MatchResponse(t, response, match.HTTPResponse{StatusCode: http.StatusForbidden}) @@ -3922,12 +3922,12 @@ func TestPartialStateJoin(t *testing.T) { reqBody := client.WithJSONBody(t, map[string]interface{}{ "visibility": "public", }) - terry.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "directory", "list", "room", serverRoom.RoomID}, reqBody) + terry.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "directory", "list", "room", serverRoom.RoomID}, reqBody) assertPublicRoomDirectoryMemberCountEquals := func(t *testing.T, expectedMemberCount int64) { // In Synapse, rooms stats are updated by a background job which runs asynchronously. // To account for that, we check for up to 3 seconds that the job has completed. - terry.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "publicRooms"}, + terry.MustDo(t, "GET", []string{"_matrix", "client", "v3", "publicRooms"}, client.WithRetryUntil(time.Second*3, func(res *http.Response) bool { body, err := ioutil.ReadAll(res.Body) if err != nil { @@ -3977,7 +3977,7 @@ func TestPartialStateJoin(t *testing.T) { // The user directory is updated by a background job in Synapse which runs // asynchronously. We check for up to 3 seconds that the job has completed, after which // the job should have finished and the user directory should be up to date. - rocky.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "user_directory", "search"}, reqBody, + rocky.MustDo(t, "POST", []string{"_matrix", "client", "v3", "user_directory", "search"}, reqBody, client.WithRetryUntil(time.Second*3, func(res *http.Response) bool { body, err := ioutil.ReadAll(res.Body) if err != nil { @@ -3998,7 +3998,7 @@ func TestPartialStateJoin(t *testing.T) { reqBody := client.WithJSONBody(t, map[string]interface{}{ "search_term": "rod", }) - res := rocky.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "user_directory", "search"}, reqBody) + res := rocky.MustDo(t, "POST", []string{"_matrix", "client", "v3", "user_directory", "search"}, reqBody) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, JSON: []match.JSON{ @@ -4052,7 +4052,7 @@ func TestPartialStateJoin(t *testing.T) { t.Log("Alice purges that room") // Ignore PDUs (leaves from shutting down the room). server.AddPDUHandler(func(e gomatrixserverlib.PDU) bool { return true }) - alice.MustDoFunc(t, "DELETE", []string{"_synapse", "admin", "v1", "rooms", serverRoom.RoomID}, client.WithJSONBody(t, map[string]interface{}{})) + alice.MustDo(t, "DELETE", []string{"_synapse", "admin", "v1", "rooms", serverRoom.RoomID}, client.WithJSONBody(t, map[string]interface{}{})) // Note: clients don't get told about purged rooms. No leave event for you! t.Log("Alice does an initial sync after the purge, until the response does not include the purged room") @@ -4066,7 +4066,7 @@ func TestPartialStateJoin(t *testing.T) { matcher := match.JSONKeyMissing( fmt.Sprintf("rooms.join.%s", client.GjsonEscape(serverRoom.RoomID)), ) - alice.MustDoFunc( + alice.MustDo( t, "GET", []string{"_matrix", "client", "v3", "sync"}, @@ -4143,7 +4143,7 @@ func testReceiveEventDuringPartialStateJoin( // our request may be rejected due to https://github.com/matrix-org/synapse/issues/13288. // By way of a workaround, request a remote user's current membership, which should block until the current state // is updated. - alice.DoFunc( + alice.Do( t, "GET", []string{"_matrix", "client", "v3", "rooms", psjResult.ServerRoom.RoomID, "state", "m.room.member", "@non-existent:remote"}, @@ -4196,7 +4196,7 @@ func awaitEventArrival(t *testing.T, timeout time.Duration, alice *client.CSAPI, t.Helper() // Alice should be able to see the event with an /event request. We might have to try it a few times. - alice.DoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomID, "event", eventID}, + alice.Do(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomID, "event", eventID}, client.WithRetryUntil(timeout, func(res *http.Response) bool { if res.StatusCode == 200 { return true @@ -4221,7 +4221,7 @@ func awaitPartialStateJoinCompletion( // Use a `/members` request to wait for the room to be un-partial stated. // We avoid using `/sync`, as it only waits (or used to wait) for full state at // particular events, rather than the whole room. - user.MustDoFunc( + user.MustDo( t, "GET", []string{"_matrix", "client", "v3", "rooms", room.RoomID, "members"}, @@ -4350,7 +4350,7 @@ func (psj *partialStateJoinResult) CreateMessageEvent(t *testing.T, senderLocalp prevEvents = prevEventIDs } - event := psj.Server.MustCreateEvent(t, psj.ServerRoom, b.Event{ + event := psj.Server.MustCreateEvent(t, psj.ServerRoom, federation.Event{ Type: "m.room.message", Sender: psj.Server.UserID(senderLocalpart), Content: map[string]interface{}{ diff --git a/tests/federation_room_join_test.go b/tests/federation_room_join_test.go index 5cdc7b1a..7ee127f9 100644 --- a/tests/federation_room_join_test.go +++ b/tests/federation_room_join_test.go @@ -19,8 +19,8 @@ import ( "github.com/tidwall/gjson" "github.com/tidwall/sjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" @@ -81,7 +81,7 @@ func TestJoinViaRoomIDAndServerName(t *testing.T) { queryParams := url.Values{} queryParams.Set("server_name", "hs1") - res := bob.DoFunc(t, "POST", []string{"_matrix", "client", "v3", "join", serverRoom.RoomID}, client.WithQueries(queryParams)) + res := bob.Do(t, "POST", []string{"_matrix", "client", "v3", "join", serverRoom.RoomID}, client.WithQueries(queryParams)) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 200, JSON: []match.JSON{ @@ -158,7 +158,7 @@ func TestJoinFederatedRoomWithUnverifiableEvents(t *testing.T) { room := srv.MustMakeRoom(t, ver, federation.InitialRoomEvents(ver, charlie)) roomAlias := srv.MakeAliasMapping("MissingSignatures", room.RoomID) // create a normal event then remove the signatures key - signedEvent := srv.MustCreateEvent(t, room, b.Event{ + signedEvent := srv.MustCreateEvent(t, room, federation.Event{ Sender: charlie, StateKey: b.Ptr(""), Type: "m.room.name", @@ -181,7 +181,7 @@ func TestJoinFederatedRoomWithUnverifiableEvents(t *testing.T) { room := srv.MustMakeRoom(t, ver, federation.InitialRoomEvents(ver, charlie)) roomAlias := srv.MakeAliasMapping("BadSignatures", room.RoomID) // create a normal event then modify the signatures - signedEvent := srv.MustCreateEvent(t, room, b.Event{ + signedEvent := srv.MustCreateEvent(t, room, federation.Event{ Sender: charlie, StateKey: b.Ptr(""), Type: "m.room.name", @@ -212,7 +212,7 @@ func TestJoinFederatedRoomWithUnverifiableEvents(t *testing.T) { roomAlias := srv.MakeAliasMapping("UnobtainableKeys", room.RoomID) // create a normal event then modify the signatures to have a bogus key ID which Complement does // not have the keys for - signedEvent := srv.MustCreateEvent(t, room, b.Event{ + signedEvent := srv.MustCreateEvent(t, room, federation.Event{ Sender: charlie, StateKey: b.Ptr(""), Type: "m.room.name", @@ -246,7 +246,7 @@ func TestJoinFederatedRoomWithUnverifiableEvents(t *testing.T) { roomAlias := srv.MakeAliasMapping("UnverifiableAuthEvents", room.RoomID) // create a normal event then modify the signatures - rawEvent := srv.MustCreateEvent(t, room, b.Event{ + rawEvent := srv.MustCreateEvent(t, room, federation.Event{ Sender: charlie, StateKey: &charlie, Type: "m.room.member", @@ -271,7 +271,7 @@ func TestJoinFederatedRoomWithUnverifiableEvents(t *testing.T) { t.Logf("Created badly signed auth event %s", badlySignedEvent.EventID()) // and now add another event which will use it as an auth event. - goodEvent := srv.MustCreateEvent(t, room, b.Event{ + goodEvent := srv.MustCreateEvent(t, room, federation.Event{ Sender: charlie, StateKey: &charlie, Type: "m.room.member", @@ -361,7 +361,7 @@ func TestBannedUserCannotSendJoin(t *testing.T) { } // Alice checks the room state to check that charlie isn't a member - res := alice.MustDoFunc( + res := alice.MustDo( t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.member", charlie}, @@ -453,7 +453,7 @@ func testValidationForSendMembershipEndpoint(t *testing.T, baseApiPath, expected } t.Run("regular event", func(t *testing.T) { - event := srv.MustCreateEvent(t, room, b.Event{ + event := srv.MustCreateEvent(t, room, federation.Event{ Type: "m.room.message", Sender: charlie, Content: map[string]interface{}{"body": "bzz"}, @@ -461,7 +461,7 @@ func testValidationForSendMembershipEndpoint(t *testing.T, baseApiPath, expected assertRequestFails(t, event) }) t.Run("non-state membership event", func(t *testing.T) { - event := srv.MustCreateEvent(t, room, b.Event{ + event := srv.MustCreateEvent(t, room, federation.Event{ Type: "m.room.member", Sender: charlie, Content: map[string]interface{}{"body": "bzz"}, @@ -475,7 +475,7 @@ func testValidationForSendMembershipEndpoint(t *testing.T, baseApiPath, expected if membershipType == expectedMembership { continue } - event := srv.MustCreateEvent(t, room, b.Event{ + event := srv.MustCreateEvent(t, room, federation.Event{ Type: "m.room.member", Sender: charlie, StateKey: &charlie, @@ -488,7 +488,7 @@ func testValidationForSendMembershipEndpoint(t *testing.T, baseApiPath, expected // right sort of membership, but mismatched state_key t.Run("event with mismatched state key", func(t *testing.T) { - event := srv.MustCreateEvent(t, room, b.Event{ + event := srv.MustCreateEvent(t, room, federation.Event{ Type: "m.room.member", Sender: charlie, StateKey: b.Ptr(srv.UserID("doris")), diff --git a/tests/federation_room_typing_test.go b/tests/federation_room_typing_test.go index 14af3305..aa892d90 100644 --- a/tests/federation_room_typing_test.go +++ b/tests/federation_room_typing_test.go @@ -5,8 +5,8 @@ import ( "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" ) func awaitTyping(userId string) func(result gjson.Result) bool { @@ -41,7 +41,7 @@ func TestRemoteTyping(t *testing.T) { bobToken := bob.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, roomID)) charlieToken := charlie.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(charlie.UserID, roomID)) - alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "typing", alice.UserID}, client.WithJSONBody(t, map[string]interface{}{ + alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "typing", alice.UserID}, client.WithJSONBody(t, map[string]interface{}{ "typing": true, "timeout": 10000, })) diff --git a/tests/federation_rooms_invite_test.go b/tests/federation_rooms_invite_test.go index e33c1b76..7e4b0663 100644 --- a/tests/federation_rooms_invite_test.go +++ b/tests/federation_rooms_invite_test.go @@ -6,8 +6,8 @@ import ( "github.com/matrix-org/gomatrixserverlib/spec" "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -128,7 +128,7 @@ func verifyState(t *testing.T, res gjson.Result, wantFields, wantValues map[stri wantValue := wantValues[eventType] eventStateKey := event.Get("state_key").Str - res := cl.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", eventType, eventStateKey}) + res := cl.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", eventType, eventStateKey}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ diff --git a/tests/federation_unreject_rejected_test.go b/tests/federation_unreject_rejected_test.go index a372cd0d..e255dfa9 100644 --- a/tests/federation_unreject_rejected_test.go +++ b/tests/federation_unreject_rejected_test.go @@ -4,8 +4,8 @@ import ( "encoding/json" "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/federation" ) @@ -44,20 +44,20 @@ func TestUnrejectRejectedEvents(t *testing.T) { // Create the events. Event A will have whatever the current forward // extremities are as prev events. Event B will refer to event A only // to guarantee the test will work. - eventA := srv.MustCreateEvent(t, serverRoom, b.Event{ + eventA := srv.MustCreateEvent(t, serverRoom, federation.Event{ Type: "m.event.a", Sender: bob, Content: map[string]interface{}{ "event": "A", }, }) - eventB := srv.MustCreateEvent(t, serverRoom, b.Event{ - Type: "m.event.b", - Sender: bob, - PrevEvents: []string{eventA.EventID()}, + eventB := srv.MustCreateEvent(t, serverRoom, federation.Event{ + Type: "m.event.b", + Sender: bob, Content: map[string]interface{}{ "event": "B", }, + PrevEvents: []string{eventA.EventID()}, }) // Send event B into the room. Event A at this point is unknown diff --git a/tests/federation_upload_keys_test.go b/tests/federation_upload_keys_test.go index 8baea823..23a5ccdd 100644 --- a/tests/federation_upload_keys_test.go +++ b/tests/federation_upload_keys_test.go @@ -7,10 +7,9 @@ import ( "testing" "github.com/tidwall/gjson" - "maunium.net/go/mautrix/crypto/olm" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -25,13 +24,13 @@ func TestFederationKeyUploadQuery(t *testing.T) { // Do an initial sync so that we can see the changes come down sync. _, nextBatchBeforeKeyUpload := bob.MustSync(t, client.SyncReq{}) - deviceKeys, oneTimeKeys := generateKeys(t, alice, 1) + deviceKeys, oneTimeKeys := alice.GenerateOneTimeKeys(t, 1) // Upload keys reqBody := client.WithJSONBody(t, map[string]interface{}{ "device_keys": deviceKeys, "one_time_keys": oneTimeKeys, }) - resp := alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "upload"}, reqBody) + resp := alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "keys", "upload"}, reqBody) must.MatchResponse(t, resp, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -61,7 +60,7 @@ func TestFederationKeyUploadQuery(t *testing.T) { }, }, }) - resp = bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "claim"}, reqBody) + resp = bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "keys", "claim"}, reqBody) otksField := "one_time_keys." + client.GjsonEscape(alice.UserID) + "." + client.GjsonEscape(alice.DeviceID) must.MatchResponse(t, resp, match.HTTPResponse{ StatusCode: http.StatusOK, @@ -70,9 +69,8 @@ func TestFederationKeyUploadQuery(t *testing.T) { match.JSONKeyEqual(otksField, oneTimeKeys), }, }) - // there should be no OTK left now - resp = bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "claim"}, reqBody) + resp = bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "keys", "claim"}, reqBody) must.MatchResponse(t, resp, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ @@ -102,7 +100,7 @@ func TestFederationKeyUploadQuery(t *testing.T) { body := client.WithJSONBody(t, map[string]interface{}{ "display_name": displayName, }) - alice.MustDoFunc(t, http.MethodPut, []string{"_matrix", "client", "v3", "devices", alice.DeviceID}, body) + alice.MustDo(t, http.MethodPut, []string{"_matrix", "client", "v3", "devices", alice.DeviceID}, body) // wait for bob to receive the displayname change bob.MustSyncUntil(t, client.SyncReq{Since: nextBatch}, func(clientUserID string, topLevelSyncJSON gjson.Result) error { devicesChanged := topLevelSyncJSON.Get("device_lists.changed") @@ -120,7 +118,7 @@ func TestFederationKeyUploadQuery(t *testing.T) { alice.UserID: []string{}, }, }) - resp = bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "keys", "query"}, reqBody) + resp = bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "keys", "query"}, reqBody) deviceKeysField := "device_keys." + client.GjsonEscape(alice.UserID) + "." + client.GjsonEscape(alice.DeviceID) must.MatchResponse(t, resp, match.HTTPResponse{ @@ -135,51 +133,3 @@ func TestFederationKeyUploadQuery(t *testing.T) { }) }) } - -func generateKeys(t *testing.T, user *client.CSAPI, otkCount uint) (deviceKeys map[string]interface{}, oneTimeKeys map[string]interface{}) { - t.Helper() - account := olm.NewAccount() - ed25519Key, curveKey := account.IdentityKeys() - - ed25519KeyID := fmt.Sprintf("ed25519:%s", user.DeviceID) - curveKeyID := fmt.Sprintf("curve25519:%s", user.DeviceID) - - deviceKeys = map[string]interface{}{ - "user_id": user.UserID, - "device_id": user.DeviceID, - "algorithms": []interface{}{"m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"}, - "keys": map[string]interface{}{ - ed25519KeyID: ed25519Key.String(), - curveKeyID: curveKey.String(), - }, - } - - signature, _ := account.SignJSON(deviceKeys) - - deviceKeys["signatures"] = map[string]interface{}{ - user.UserID: map[string]interface{}{ - ed25519KeyID: signature, - }, - } - - account.GenOneTimeKeys(otkCount) - oneTimeKeys = map[string]interface{}{} - - for kid, key := range account.OneTimeKeys() { - keyID := fmt.Sprintf("signed_curve25519:%s", kid) - keyMap := map[string]interface{}{ - "key": key.String(), - } - - signature, _ = account.SignJSON(keyMap) - - keyMap["signatures"] = map[string]interface{}{ - user.UserID: map[string]interface{}{ - ed25519KeyID: signature, - }, - } - - oneTimeKeys[keyID] = keyMap - } - return deviceKeys, oneTimeKeys -} diff --git a/tests/knocking_test.go b/tests/knocking_test.go index fb1fd18a..80802bea 100644 --- a/tests/knocking_test.go +++ b/tests/knocking_test.go @@ -19,8 +19,8 @@ import ( "github.com/matrix-org/gomatrixserverlib" "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" @@ -122,7 +122,7 @@ func knockingBetweenTwoUsersTest(t *testing.T, roomID string, inRoomUser, knocki "server_name": []string{"hs1"}, } - res := knockingUser.DoFunc( + res := knockingUser.Do( t, "POST", []string{"_matrix", "client", "v3", "join", roomID}, @@ -181,7 +181,7 @@ func knockingBetweenTwoUsersTest(t *testing.T, roomID string, inRoomUser, knocki _, since := knockingUser.MustSync(t, client.SyncReq{TimeoutMillis: "0"}) // Rescind knock - knockingUser.MustDoFunc( + knockingUser.MustDo( t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "leave"}, @@ -218,7 +218,7 @@ func knockingBetweenTwoUsersTest(t *testing.T, roomID string, inRoomUser, knocki // // In the case of federation, this test will still check that a knock can be // carried out after a previous knock is rejected. - inRoomUser.MustDoFunc( + inRoomUser.MustDo( t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "kick"}, @@ -241,7 +241,7 @@ func knockingBetweenTwoUsersTest(t *testing.T, roomID string, inRoomUser, knocki t.Run("A user can knock on a room without a reason", func(t *testing.T) { // Reject the knock - inRoomUser.MustDoFunc( + inRoomUser.MustDo( t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "kick"}, @@ -256,7 +256,7 @@ func knockingBetweenTwoUsersTest(t *testing.T, roomID string, inRoomUser, knocki }) t.Run("A user in the room can accept a knock", func(t *testing.T) { - inRoomUser.MustDoFunc( + inRoomUser.MustDo( t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "invite"}, @@ -285,7 +285,7 @@ func knockingBetweenTwoUsersTest(t *testing.T, roomID string, inRoomUser, knocki // // In the case of federation, this test will still check that a knock can not be // carried out after a ban. - inRoomUser.MustDoFunc( + inRoomUser.MustDo( t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "ban"}, @@ -349,7 +349,7 @@ func knockOnRoomWithStatus(t *testing.T, c *client.CSAPI, roomID, reason string, } // Knock on the room - res := c.DoFunc( + res := c.Do( t, "POST", []string{"_matrix", "client", "v3", "knock", roomID}, @@ -416,7 +416,7 @@ func doTestKnockRoomsInPublicRoomsDirectory(t *testing.T, roomVersion string, jo // It will then query the directory and ensure the room is listed, and has a given 'join_rule' entry func publishAndCheckRoomJoinRule(t *testing.T, c *client.CSAPI, roomID, expectedJoinRule string) { // Publish the room to the public room directory - c.MustDoFunc( + c.MustDo( t, "PUT", []string{"_matrix", "client", "v3", "directory", "list", "room", roomID}, @@ -426,7 +426,7 @@ func publishAndCheckRoomJoinRule(t *testing.T, c *client.CSAPI, roomID, expected ) // Check that we can see the room in the directory - c.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "publicRooms"}, + c.MustDo(t, "GET", []string{"_matrix", "client", "v3", "publicRooms"}, client.WithRetryUntil(time.Second, func(res *http.Response) bool { roomFound := false must.MatchResponse(t, res, match.HTTPResponse{ diff --git a/tests/media_filename_test.go b/tests/media_filename_test.go index c1138a79..2106353a 100644 --- a/tests/media_filename_test.go +++ b/tests/media_filename_test.go @@ -5,8 +5,8 @@ import ( "mime" "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/data" "github.com/matrix-org/complement/runtime" ) @@ -172,7 +172,7 @@ func downloadForFilename(t *testing.T, c *client.CSAPI, mxcUri string, diffName path = []string{"_matrix", "media", "v3", "download", origin, mediaId} } - res := c.MustDoFunc(t, "GET", path) + res := c.MustDo(t, "GET", path) mediaType, params, err := mime.ParseMediaType(res.Header.Get("Content-Disposition")) if err != nil { diff --git a/tests/media_thumbnail_test.go b/tests/media_thumbnail_test.go index 97808150..16bcc8a2 100644 --- a/tests/media_thumbnail_test.go +++ b/tests/media_thumbnail_test.go @@ -9,8 +9,8 @@ import ( "strings" "testing" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/data" ) @@ -52,7 +52,7 @@ func fetchAndValidateThumbnail(t *testing.T, c *client.CSAPI, mxcUri string) { origin, mediaId := client.SplitMxc(mxcUri) - res := c.MustDoFunc(t, "GET", []string{"_matrix", "media", "v3", "thumbnail", origin, mediaId}, client.WithQueries(url.Values{ + res := c.MustDo(t, "GET", []string{"_matrix", "media", "v3", "thumbnail", origin, mediaId}, client.WithQueries(url.Values{ "width": []string{"32"}, "height": []string{"32"}, "method": []string{"scale"}, diff --git a/tests/msc2836_test.go b/tests/msc2836_test.go index 20b191ad..bce90b8e 100644 --- a/tests/msc2836_test.go +++ b/tests/msc2836_test.go @@ -18,8 +18,8 @@ import ( "github.com/matrix-org/gomatrixserverlib" "github.com/tidwall/gjson" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" @@ -27,11 +27,13 @@ import ( // This test checks that federated threading works when the remote server joins after the messages // have been sent. The test configures a thread like: -// A -// | -// B -// / \ -// C D +// +// A +// | +// B +// / \ +// C D +// // Then a remote server joins the room. /event_relationships is then hit with event ID 'D' which the // joined server does not have. This should cause a remote /event_relationships request to service the // request. The request parameters will pull in events D,B. This gets repeated for a second time with @@ -94,7 +96,7 @@ func TestEventRelationships(t *testing.T) { bob.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, roomID)) // Now hit /event_relationships with eventD - res := bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "unstable", "event_relationships"}, client.WithJSONBody(t, map[string]interface{}{ + res := bob.MustDo(t, "POST", []string{"_matrix", "client", "unstable", "event_relationships"}, client.WithJSONBody(t, map[string]interface{}{ "event_id": eventD, "room_id": roomID, // required so the server knows which servers to ask "direction": "down", // no newer events, so nothing should be added @@ -126,7 +128,7 @@ func TestEventRelationships(t *testing.T) { }, []string{eventC, eventD}) // now hit /event_relationships again with B, which should return everything (and fetch the missing events A,C) - res = bob.MustDoFunc(t, "POST", []string{"_matrix", "client", "unstable", "event_relationships"}, client.WithJSONBody(t, map[string]interface{}{ + res = bob.MustDo(t, "POST", []string{"_matrix", "client", "unstable", "event_relationships"}, client.WithJSONBody(t, map[string]interface{}{ "event_id": eventB, "room_id": roomID, // required so the server knows which servers to ask "direction": "down", // this pulls in C,D @@ -171,13 +173,15 @@ func TestEventRelationships(t *testing.T) { // This test checks that the homeserver makes a federated request to /event_relationships // when walking a thread when it encounters an unknown event ID. The test configures a // room on the Complement server with a thread which has following shape: -// A -// / \ -// B C -// | -// D <- Test server joins here -// | -// E +// +// A +// / \ +// B C +// | +// D <- Test server joins here +// | +// E +// // The test server is notified of event E in a /send transaction after joining the room. // The client on the test server then hits /event_relationships with event ID 'E' and direction 'up'. // This *should* cause the server to walk up the thread, realise it is missing event D and then ask @@ -205,7 +209,7 @@ func TestFederatedEventRelationships(t *testing.T) { roomVer := alice.GetDefaultRoomVersion(t) charlie := srv.UserID("charlie") room := srv.MustMakeRoom(t, roomVer, federation.InitialRoomEvents(roomVer, charlie)) - eventA := srv.MustCreateEvent(t, room, b.Event{ + eventA := srv.MustCreateEvent(t, room, federation.Event{ Type: "m.room.message", Sender: charlie, Content: map[string]interface{}{ @@ -214,7 +218,7 @@ func TestFederatedEventRelationships(t *testing.T) { }, }) room.AddEvent(eventA) - eventB := srv.MustCreateEvent(t, room, b.Event{ + eventB := srv.MustCreateEvent(t, room, federation.Event{ Type: "m.room.message", Sender: charlie, Content: map[string]interface{}{ @@ -229,7 +233,7 @@ func TestFederatedEventRelationships(t *testing.T) { room.AddEvent(eventB) // wait 1ms to ensure that the timestamp changes, which is important when using the recent_first flag time.Sleep(1 * time.Millisecond) - eventC := srv.MustCreateEvent(t, room, b.Event{ + eventC := srv.MustCreateEvent(t, room, federation.Event{ Type: "m.room.message", Sender: charlie, Content: map[string]interface{}{ @@ -242,7 +246,7 @@ func TestFederatedEventRelationships(t *testing.T) { }, }) room.AddEvent(eventC) - eventD := srv.MustCreateEvent(t, room, b.Event{ + eventD := srv.MustCreateEvent(t, room, federation.Event{ Type: "m.room.message", Sender: charlie, Content: map[string]interface{}{ @@ -303,7 +307,7 @@ func TestFederatedEventRelationships(t *testing.T) { alice.JoinRoom(t, room.RoomID, []string{srv.ServerName()}) // send a new child in the thread (child of D) so the HS has something to latch on to. - eventE := srv.MustCreateEvent(t, room, b.Event{ + eventE := srv.MustCreateEvent(t, room, federation.Event{ Type: "m.room.message", Sender: charlie, Content: map[string]interface{}{ @@ -335,7 +339,7 @@ func TestFederatedEventRelationships(t *testing.T) { })) // Hit /event_relationships to make sure it spiders the whole thing by asking /event_relationships on Complement - res := alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "unstable", "event_relationships"}, client.WithJSONBody(t, map[string]interface{}{ + res := alice.MustDo(t, "POST", []string{"_matrix", "client", "unstable", "event_relationships"}, client.WithJSONBody(t, map[string]interface{}{ "event_id": eventE.EventID(), "max_depth": 10, "direction": "up", @@ -356,7 +360,7 @@ func TestFederatedEventRelationships(t *testing.T) { must.HaveInOrder(t, gotEventIDs, []string{eventE.EventID(), eventD.EventID(), eventC.EventID(), eventA.EventID()}) // now querying for the children of A should return A,B,C (it should've been remembered B from the previous /event_relationships request) - res = alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "unstable", "event_relationships"}, client.WithJSONBody(t, map[string]interface{}{ + res = alice.MustDo(t, "POST", []string{"_matrix", "client", "unstable", "event_relationships"}, client.WithJSONBody(t, map[string]interface{}{ "event_id": eventA.EventID(), "max_depth": 1, "direction": "down", diff --git a/tests/msc3391_test.go b/tests/msc3391_test.go index e74f9703..d824bb97 100644 --- a/tests/msc3391_test.go +++ b/tests/msc3391_test.go @@ -12,7 +12,7 @@ import ( "testing" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" @@ -152,7 +152,7 @@ func deleteUserAccountData(t *testing.T, c *client.CSAPI, viaDelete bool) { // Delete user account data if viaDelete { // Delete via the DELETE method - c.MustDoFunc( + c.MustDo( t, "DELETE", []string{"_matrix", "client", "unstable", "org.matrix.msc3391", "user", c.UserID, "account_data", testAccountDataType}, @@ -174,7 +174,7 @@ func deleteUserAccountData(t *testing.T, c *client.CSAPI, viaDelete bool) { ) // Also check the account data item is no longer found - res := c.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "user", c.UserID, "account_data", testAccountDataType}) + res := c.Do(t, "GET", []string{"_matrix", "client", "v3", "user", c.UserID, "account_data", testAccountDataType}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 404, }) @@ -210,7 +210,7 @@ func deleteRoomAccountData(t *testing.T, c *client.CSAPI, viaDelete bool, roomID // Delete room account data if viaDelete { // Delete via the DELETE method - c.MustDoFunc( + c.MustDo( t, "DELETE", []string{"_matrix", "client", "unstable", "org.matrix.msc3391", "user", c.UserID, "rooms", roomID, "account_data", testAccountDataType}, @@ -232,7 +232,7 @@ func deleteRoomAccountData(t *testing.T, c *client.CSAPI, viaDelete bool, roomID ) // Also check the account data item is no longer found - res := c.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "user", c.UserID, "room", roomID, "account_data", testAccountDataType}) + res := c.Do(t, "GET", []string{"_matrix", "client", "v3", "user", c.UserID, "room", roomID, "account_data", testAccountDataType}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 404, }) diff --git a/tests/msc3890_test.go b/tests/msc3890_test.go index 9cb4df4c..a73972ad 100644 --- a/tests/msc3890_test.go +++ b/tests/msc3890_test.go @@ -11,7 +11,7 @@ import ( "testing" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/tidwall/gjson" @@ -68,8 +68,8 @@ func TestDeletingDeviceRemovesDeviceLocalNotificationSettings(t *testing.T) { client.SyncGlobalAccountDataHas(checkAccountDataContent), ) // Also check via the dedicated account data endpoint to ensure the similar check later is not 404'ing for some other reason. - // Using `MustDoFunc` ensures that the response code is 2xx. - res := aliceDeviceOne.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "user", aliceDeviceOne.UserID, "account_data", accountDataType}) + // Using `MustDo` ensures that the response code is 2xx. + res := aliceDeviceOne.MustDo(t, "GET", []string{"_matrix", "client", "v3", "user", aliceDeviceOne.UserID, "account_data", accountDataType}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONKeyEqual("is_silenced", true), @@ -77,10 +77,10 @@ func TestDeletingDeviceRemovesDeviceLocalNotificationSettings(t *testing.T) { }) // Log out the second device - aliceDeviceTwo.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "logout"}) + aliceDeviceTwo.MustDo(t, "POST", []string{"_matrix", "client", "v3", "logout"}) // Using the first device, check that the local notification setting account data for the deleted device was removed. - res = aliceDeviceOne.DoFunc(t, "GET", []string{"_matrix", "client", "v3", "user", aliceDeviceOne.UserID, "account_data", accountDataType}) + res = aliceDeviceOne.Do(t, "GET", []string{"_matrix", "client", "v3", "user", aliceDeviceOne.UserID, "account_data", accountDataType}) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: 404, JSON: []match.JSON{ diff --git a/tests/restricted_room_hierarchy_test.go b/tests/restricted_room_hierarchy_test.go index 54231706..9c7a97e1 100644 --- a/tests/restricted_room_hierarchy_test.go +++ b/tests/restricted_room_hierarchy_test.go @@ -8,7 +8,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -17,7 +17,7 @@ import ( func requestAndAssertSummary(t *testing.T, user *client.CSAPI, space string, expected_rooms []interface{}) { t.Helper() - res := user.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", space, "hierarchy"}) + res := user.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", space, "hierarchy"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONCheckOff("rooms", expected_rooms, func(r gjson.Result) interface{} { diff --git a/tests/restricted_rooms_test.go b/tests/restricted_rooms_test.go index c55c4ce5..674ec2ee 100644 --- a/tests/restricted_rooms_test.go +++ b/tests/restricted_rooms_test.go @@ -9,7 +9,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/docker" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" @@ -22,7 +22,7 @@ func failJoinRoom(t *testing.T, c *client.CSAPI, roomIDOrAlias string, serverNam // This is copied from Client.JoinRoom to test a join failure. query := make(url.Values, 1) query.Set("server_name", serverName) - res := c.DoFunc( + res := c.Do( t, "POST", []string{"_matrix", "client", "v3", "join", roomIDOrAlias}, @@ -272,7 +272,7 @@ func doTestRestrictedRoomsRemoteJoinLocalUser(t *testing.T, roomVersion string, body := map[string]interface{}{ "user_id": bob.UserID, } - res := alice.DoFunc( + res := alice.Do( t, "POST", []string{"_matrix", "client", "v3", "rooms", room, "invite"}, diff --git a/tests/room_hierarchy_test.go b/tests/room_hierarchy_test.go index 1d929ff2..a9d18156 100644 --- a/tests/room_hierarchy_test.go +++ b/tests/room_hierarchy_test.go @@ -21,7 +21,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -219,7 +219,7 @@ func TestClientSpacesSummary(t *testing.T) { // - Rooms are returned correctly along with the custom fields `room_type`. // - Events are returned correctly. t.Run("query whole graph", func(t *testing.T) { - res := alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", root, "hierarchy"}) + res := alice.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", root, "hierarchy"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONCheckOff("rooms", []interface{}{ @@ -257,7 +257,7 @@ func TestClientSpacesSummary(t *testing.T) { // Should only include R1, SS1, and R2. query := make(url.Values, 1) query.Set("max_depth", "1") - res := alice.MustDoFunc( + res := alice.MustDo( t, "GET", []string{"_matrix", "client", "v1", "rooms", root, "hierarchy"}, @@ -283,7 +283,7 @@ func TestClientSpacesSummary(t *testing.T) { // Should only include R1, SS1, and R2. query := make(url.Values, 1) query.Set("suggested_only", "true") - res := alice.MustDoFunc( + res := alice.MustDo( t, "GET", []string{"_matrix", "client", "v1", "rooms", root, "hierarchy"}, @@ -309,7 +309,7 @@ func TestClientSpacesSummary(t *testing.T) { // The initial page should only include Root, R1, SS1, and SS2. query := make(url.Values, 1) query.Set("limit", "4") - res := alice.MustDoFunc( + res := alice.MustDo( t, "GET", []string{"_matrix", "client", "v1", "rooms", root, "hierarchy"}, @@ -328,7 +328,7 @@ func TestClientSpacesSummary(t *testing.T) { // The following page should include R3, R4, and R2. query = make(url.Values, 1) query.Set("from", client.GetJSONFieldStr(t, body, "next_batch")) - res = alice.MustDoFunc( + res = alice.MustDo( t, "GET", []string{"_matrix", "client", "v1", "rooms", root, "hierarchy"}, @@ -352,7 +352,7 @@ func TestClientSpacesSummary(t *testing.T) { StateKey: &ss1, Content: map[string]interface{}{}, }) - res := alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", root, "hierarchy"}) + res := alice.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", root, "hierarchy"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONCheckOff("rooms", []interface{}{ @@ -464,7 +464,7 @@ func TestClientSpacesSummaryJoinRules(t *testing.T) { bob := deployment.Client(t, "hs1", "@bob:hs1") bob.JoinRoom(t, root, []string{"hs1"}) - res := bob.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", root, "hierarchy"}) + res := bob.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", root, "hierarchy"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONCheckOff("rooms", []interface{}{ @@ -482,7 +482,7 @@ func TestClientSpacesSummaryJoinRules(t *testing.T) { alice.InviteRoom(t, r1, bob.UserID) alice.InviteRoom(t, r3, bob.UserID) - res = bob.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", root, "hierarchy"}) + res = bob.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", root, "hierarchy"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONCheckOff("rooms", []interface{}{ @@ -499,7 +499,7 @@ func TestClientSpacesSummaryJoinRules(t *testing.T) { // Invite to SS1 and it now appears, as well as the rooms under it. alice.InviteRoom(t, ss1, bob.UserID) - res = bob.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", root, "hierarchy"}) + res = bob.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", root, "hierarchy"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONCheckOff("rooms", []interface{}{ @@ -627,7 +627,7 @@ func TestFederatedClientSpaces(t *testing.T) { } t.Logf("rooms: %v", allEvents) - res := alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", root, "hierarchy"}) + res := alice.MustDo(t, "GET", []string{"_matrix", "client", "v1", "rooms", root, "hierarchy"}) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ match.JSONCheckOff("rooms", []interface{}{ diff --git a/tests/room_timestamp_to_event_test.go b/tests/room_timestamp_to_event_test.go index b3085d89..236d8e91 100644 --- a/tests/room_timestamp_to_event_test.go +++ b/tests/room_timestamp_to_event_test.go @@ -16,7 +16,7 @@ import ( "time" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/tidwall/gjson" @@ -119,7 +119,7 @@ func TestJumpToDateEndpoint(t *testing.T) { // Make the `/timestamp_to_event` request from Bob's perspective (non room member) timestamp := makeTimestampFromTime(timeBeforeRoomCreation) timestampString := strconv.FormatInt(timestamp, 10) - timestampToEventRes := nonMemberUser.DoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "timestamp_to_event"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ + timestampToEventRes := nonMemberUser.Do(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "timestamp_to_event"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ "ts": []string{timestampString}, "dir": []string{"f"}, })) @@ -147,7 +147,7 @@ func TestJumpToDateEndpoint(t *testing.T) { // Make the `/timestamp_to_event` request from Bob's perspective (non room member) timestamp := makeTimestampFromTime(timeBeforeRoomCreation) timestampString := strconv.FormatInt(timestamp, 10) - timestampToEventRes := nonMemberUser.DoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "timestamp_to_event"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ + timestampToEventRes := nonMemberUser.Do(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "timestamp_to_event"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ "ts": []string{timestampString}, "dir": []string{"f"}, })) @@ -198,7 +198,7 @@ func TestJumpToDateEndpoint(t *testing.T) { mustCheckEventisReturnedForTime(t, remoteCharlie, roomID, eventB.AfterTimestamp, "b", eventB.EventID) // Get a pagination token from eventB - contextRes := remoteCharlie.MustDoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomID, "context", eventB.EventID}, client.WithContentType("application/json"), client.WithQueries(url.Values{ + contextRes := remoteCharlie.MustDo(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomID, "context", eventB.EventID}, client.WithContentType("application/json"), client.WithQueries(url.Values{ "limit": []string{"0"}, })) contextResResBody := client.ParseJSON(t, contextRes) @@ -212,7 +212,7 @@ func TestJumpToDateEndpoint(t *testing.T) { }) // Paginate backwards from eventB - messagesRes := remoteCharlie.MustDoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomID, "messages"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ + messagesRes := remoteCharlie.MustDo(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomID, "messages"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ "dir": []string{"b"}, "limit": []string{"100"}, "from": []string{paginationToken}, @@ -289,7 +289,7 @@ func sendMessageWithTimestamp(t *testing.T, as *client.CSAPI, c *client.CSAPI, r // // We can't use as.SendEventSynced(...) because application services can't use // the /sync API. - sendRes := as.DoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", getTxnID("sendMessageWithTimestamp-txn")}, client.WithContentType("application/json"), client.WithJSONBody(t, map[string]interface{}{ + sendRes := as.Do(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", getTxnID("sendMessageWithTimestamp-txn")}, client.WithContentType("application/json"), client.WithJSONBody(t, map[string]interface{}{ "body": message, "msgtype": "m.text", }), client.WithQueries(url.Values{ @@ -311,7 +311,7 @@ func mustCheckEventisReturnedForTime(t *testing.T, c *client.CSAPI, roomID strin givenTimestamp := makeTimestampFromTime(givenTime) timestampString := strconv.FormatInt(givenTimestamp, 10) - timestampToEventRes := c.DoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "timestamp_to_event"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ + timestampToEventRes := c.Do(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "timestamp_to_event"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ "ts": []string{timestampString}, "dir": []string{direction}, })) @@ -348,7 +348,7 @@ func fetchUntilMessagesResponseHas(t *testing.T, c *client.CSAPI, roomID string, t.Fatalf("fetchUntilMessagesResponseHas timed out. Called check function %d times", checkCounter) } - messagesRes := c.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ + messagesRes := c.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ "dir": []string{"b"}, "limit": []string{"100"}, })) @@ -378,7 +378,7 @@ func fetchUntilMessagesResponseHas(t *testing.T, c *client.CSAPI, roomID string, func getDebugMessageListFromMessagesResponse(t *testing.T, c *client.CSAPI, roomID string, expectedEventId string, actualEventId string, givenTimestamp int64) string { t.Helper() - messagesRes := c.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ + messagesRes := c.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ // The events returned will be from the newest -> oldest since we're going backwards "dir": []string{"b"}, "limit": []string{"100"}, diff --git a/tests/unknown_endpoints_test.go b/tests/unknown_endpoints_test.go index f777ac44..19bd908f 100644 --- a/tests/unknown_endpoints_test.go +++ b/tests/unknown_endpoints_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/matrix-org/complement/internal/b" - "github.com/matrix-org/complement/internal/client" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) @@ -13,7 +13,7 @@ import ( func queryUnknownEndpoint(t *testing.T, user *client.CSAPI, paths []string) { t.Helper() - res := user.DoFunc(t, "GET", paths) + res := user.Do(t, "GET", paths) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusNotFound, JSON: []match.JSON{ @@ -25,7 +25,7 @@ func queryUnknownEndpoint(t *testing.T, user *client.CSAPI, paths []string) { func queryUnknownMethod(t *testing.T, user *client.CSAPI, method string, paths []string) { t.Helper() - res := user.DoFunc(t, method, paths) + res := user.Do(t, method, paths) must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusMethodNotAllowed, JSON: []match.JSON{ From 765746a8f8af41e9f082ee2683d24030c5ab8f17 Mon Sep 17 00:00:00 2001 From: kegsay Date: Wed, 4 Oct 2023 16:15:25 +0100 Subject: [PATCH 09/10] Move /internal/b to /b (#659) The API is unchanged and is suitable to be made public. --- {internal/b => b}/alice.go | 0 {internal/b => b}/blueprints.go | 0 {internal/b => b}/clean_hs.go | 0 {internal/b => b}/federation_one_to_one_room.go | 0 {internal/b => b}/federation_two_local_one_remote.go | 0 {internal/b => b}/hs_with_application_service.go | 0 {internal/b => b}/one_to_one_room.go | 0 {internal/b => b}/perf_e2ee_room.go | 0 {internal/b => b}/perf_many_messages.go | 0 {internal/b => b}/perf_many_rooms.go | 0 client/client.go | 2 +- cmd/account-snapshot/internal/blueprint.go | 2 +- cmd/account-snapshot/main.go | 2 +- cmd/homerunner/route_create.go | 8 ++++---- cmd/homerunner/setup.go | 2 +- cmd/perftest/test.go | 2 +- internal/docker/builder.go | 2 +- internal/docker/labels.go | 2 +- internal/federation/server_room.go | 2 +- internal/instruction/runner.go | 2 +- tests/csapi/account_change_password_pushers_test.go | 2 +- tests/csapi/account_change_password_test.go | 2 +- tests/csapi/account_data_test.go | 2 +- tests/csapi/account_deactivate_test.go | 2 +- tests/csapi/admin_test.go | 2 +- tests/csapi/apidoc_content_test.go | 2 +- tests/csapi/apidoc_device_management_test.go | 2 +- tests/csapi/apidoc_login_test.go | 2 +- tests/csapi/apidoc_logout_test.go | 2 +- tests/csapi/apidoc_presence_test.go | 2 +- tests/csapi/apidoc_profile_avatar_url_test.go | 2 +- tests/csapi/apidoc_profile_displayname_test.go | 2 +- tests/csapi/apidoc_register_test.go | 2 +- tests/csapi/apidoc_request_encoding_test.go | 2 +- tests/csapi/apidoc_room_alias_test.go | 2 +- tests/csapi/apidoc_room_create_test.go | 2 +- tests/csapi/apidoc_room_forget_test.go | 2 +- tests/csapi/apidoc_room_history_visibility_test.go | 2 +- tests/csapi/apidoc_room_members_test.go | 2 +- tests/csapi/apidoc_room_receipts_test.go | 2 +- tests/csapi/apidoc_room_state_test.go | 2 +- tests/csapi/apidoc_search_test.go | 2 +- tests/csapi/apidoc_server_capabilities_test.go | 2 +- tests/csapi/apidoc_version_test.go | 2 +- tests/csapi/device_lists_test.go | 2 +- tests/csapi/e2e_key_backup_test.go | 2 +- tests/csapi/ignored_users_test.go | 2 +- tests/csapi/invalid_test.go | 2 +- tests/csapi/keychanges_test.go | 2 +- tests/csapi/main_test.go | 2 +- tests/csapi/media_misc_test.go | 2 +- tests/csapi/power_levels_test.go | 2 +- tests/csapi/push_test.go | 2 +- tests/csapi/room_ban_test.go | 2 +- tests/csapi/room_kick_test.go | 2 +- tests/csapi/room_leave_test.go | 2 +- tests/csapi/room_members_test.go | 2 +- tests/csapi/room_messages_relation_filter_test.go | 2 +- tests/csapi/room_messages_test.go | 2 +- tests/csapi/room_profile_test.go | 2 +- tests/csapi/room_relations_test.go | 2 +- tests/csapi/room_threads_test.go | 2 +- tests/csapi/room_typing_test.go | 2 +- tests/csapi/rooms_invite_test.go | 2 +- tests/csapi/rooms_members_local_test.go | 2 +- tests/csapi/rooms_state_test.go | 2 +- tests/csapi/sync_archive_test.go | 2 +- tests/csapi/sync_filter_test.go | 2 +- tests/csapi/sync_test.go | 2 +- tests/csapi/thread_notifications_test.go | 2 +- tests/csapi/to_device_test.go | 2 +- tests/csapi/txnid_test.go | 2 +- tests/csapi/upload_keys_test.go | 2 +- tests/csapi/url_preview_test.go | 2 +- tests/csapi/user_directory_display_names_test.go | 2 +- tests/csapi/user_query_keys_test.go | 2 +- tests/direct_messaging_test.go | 2 +- tests/federation_acl_test.go | 2 +- tests/federation_event_auth_test.go | 2 +- tests/federation_keys_test.go | 2 +- tests/federation_presence_test.go | 2 +- tests/federation_query_profile_test.go | 2 +- tests/federation_redaction_test.go | 2 +- tests/federation_room_alias_test.go | 2 +- tests/federation_room_ban_test.go | 2 +- tests/federation_room_event_auth_test.go | 2 +- tests/federation_room_get_missing_events_test.go | 2 +- tests/federation_room_invite_test.go | 2 +- tests/federation_room_join_partial_state_test.go | 2 +- tests/federation_room_join_test.go | 2 +- tests/federation_room_send_test.go | 2 +- tests/federation_room_typing_test.go | 2 +- tests/federation_rooms_invite_test.go | 2 +- tests/federation_unreject_rejected_test.go | 2 +- tests/federation_upload_keys_test.go | 2 +- tests/knock_restricted_test.go | 2 +- tests/knocking_test.go | 2 +- tests/main_test.go | 2 +- tests/media_filename_test.go | 2 +- tests/media_nofilename_test.go | 2 +- tests/media_thumbnail_test.go | 2 +- tests/msc2836_test.go | 2 +- tests/msc3391_test.go | 2 +- tests/msc3890_test.go | 2 +- tests/msc3930_test.go | 2 +- tests/restricted_room_hierarchy_test.go | 2 +- tests/restricted_rooms_test.go | 2 +- tests/room_hierarchy_test.go | 2 +- tests/room_timestamp_to_event_test.go | 2 +- tests/unknown_endpoints_test.go | 2 +- 110 files changed, 103 insertions(+), 103 deletions(-) rename {internal/b => b}/alice.go (100%) rename {internal/b => b}/blueprints.go (100%) rename {internal/b => b}/clean_hs.go (100%) rename {internal/b => b}/federation_one_to_one_room.go (100%) rename {internal/b => b}/federation_two_local_one_remote.go (100%) rename {internal/b => b}/hs_with_application_service.go (100%) rename {internal/b => b}/one_to_one_room.go (100%) rename {internal/b => b}/perf_e2ee_room.go (100%) rename {internal/b => b}/perf_many_messages.go (100%) rename {internal/b => b}/perf_many_rooms.go (100%) diff --git a/internal/b/alice.go b/b/alice.go similarity index 100% rename from internal/b/alice.go rename to b/alice.go diff --git a/internal/b/blueprints.go b/b/blueprints.go similarity index 100% rename from internal/b/blueprints.go rename to b/blueprints.go diff --git a/internal/b/clean_hs.go b/b/clean_hs.go similarity index 100% rename from internal/b/clean_hs.go rename to b/clean_hs.go diff --git a/internal/b/federation_one_to_one_room.go b/b/federation_one_to_one_room.go similarity index 100% rename from internal/b/federation_one_to_one_room.go rename to b/federation_one_to_one_room.go diff --git a/internal/b/federation_two_local_one_remote.go b/b/federation_two_local_one_remote.go similarity index 100% rename from internal/b/federation_two_local_one_remote.go rename to b/federation_two_local_one_remote.go diff --git a/internal/b/hs_with_application_service.go b/b/hs_with_application_service.go similarity index 100% rename from internal/b/hs_with_application_service.go rename to b/hs_with_application_service.go diff --git a/internal/b/one_to_one_room.go b/b/one_to_one_room.go similarity index 100% rename from internal/b/one_to_one_room.go rename to b/one_to_one_room.go diff --git a/internal/b/perf_e2ee_room.go b/b/perf_e2ee_room.go similarity index 100% rename from internal/b/perf_e2ee_room.go rename to b/perf_e2ee_room.go diff --git a/internal/b/perf_many_messages.go b/b/perf_many_messages.go similarity index 100% rename from internal/b/perf_many_messages.go rename to b/perf_many_messages.go diff --git a/internal/b/perf_many_rooms.go b/b/perf_many_rooms.go similarity index 100% rename from internal/b/perf_many_rooms.go rename to b/perf_many_rooms.go diff --git a/client/client.go b/client/client.go index 20b2fdf6..027d40b0 100644 --- a/client/client.go +++ b/client/client.go @@ -18,7 +18,7 @@ import ( "github.com/tidwall/gjson" "maunium.net/go/mautrix/crypto/olm" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" ) // TestLike is an interface that testing.T satisfies. All client functions accept a TestLike interface, diff --git a/cmd/account-snapshot/internal/blueprint.go b/cmd/account-snapshot/internal/blueprint.go index 064dced4..92c0a636 100644 --- a/cmd/account-snapshot/internal/blueprint.go +++ b/cmd/account-snapshot/internal/blueprint.go @@ -5,7 +5,7 @@ import ( "log" "regexp" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/tidwall/gjson" ) diff --git a/cmd/account-snapshot/main.go b/cmd/account-snapshot/main.go index 5aad079d..491e5fe4 100644 --- a/cmd/account-snapshot/main.go +++ b/cmd/account-snapshot/main.go @@ -7,8 +7,8 @@ import ( "log" "os" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/cmd/account-snapshot/internal" - "github.com/matrix-org/complement/internal/b" ) /* diff --git a/cmd/homerunner/route_create.go b/cmd/homerunner/route_create.go index 01896e75..4adb5a2e 100644 --- a/cmd/homerunner/route_create.go +++ b/cmd/homerunner/route_create.go @@ -5,7 +5,7 @@ import ( "fmt" "time" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/docker" "github.com/matrix-org/util" ) @@ -22,9 +22,9 @@ type ResCreate struct { } // RouteCreate handles creating blueprint deployments. There are 3 supported types of requests: -// - A: Creating a blueprint from the static ones in `internal/b` : This is what Complement does. -// - B: Creating an in-line blueprint where the blueprint is in the request. -// - C: Creating a deployment from a pre-made blueprint image, e.g using account-snapshot. +// - A: Creating a blueprint from the static ones in `internal/b` : This is what Complement does. +// - B: Creating an in-line blueprint where the blueprint is in the request. +// - C: Creating a deployment from a pre-made blueprint image, e.g using account-snapshot. func RouteCreate(ctx context.Context, rt *Runtime, rc *ReqCreate) util.JSONResponse { // Use case A: if the blueprint name is given, check for static ones knownBlueprint, ok := b.KnownBlueprints[rc.BlueprintName] diff --git a/cmd/homerunner/setup.go b/cmd/homerunner/setup.go index 1f88cb96..2daf28b8 100644 --- a/cmd/homerunner/setup.go +++ b/cmd/homerunner/setup.go @@ -8,7 +8,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/docker" ) diff --git a/cmd/perftest/test.go b/cmd/perftest/test.go index 8c9144fd..ca1f0ac5 100644 --- a/cmd/perftest/test.go +++ b/cmd/perftest/test.go @@ -7,7 +7,7 @@ import ( "net/url" "time" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/docker" "github.com/matrix-org/complement/internal/instruction" ) diff --git a/internal/docker/builder.go b/internal/docker/builder.go index 3389862d..9a2f86b3 100644 --- a/internal/docker/builder.go +++ b/internal/docker/builder.go @@ -25,7 +25,7 @@ import ( "github.com/docker/docker/pkg/stdcopy" "github.com/docker/go-connections/nat" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/config" "github.com/matrix-org/complement/internal/instruction" ) diff --git a/internal/docker/labels.go b/internal/docker/labels.go index 9e6a4404..98f5caf9 100644 --- a/internal/docker/labels.go +++ b/internal/docker/labels.go @@ -5,7 +5,7 @@ import ( "github.com/docker/docker/api/types/filters" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" ) // label returns a filter for the presence of certain labels ("complement_context") or a match of diff --git a/internal/federation/server_room.go b/internal/federation/server_room.go index a0b46c55..e6ae68a3 100644 --- a/internal/federation/server_room.go +++ b/internal/federation/server_room.go @@ -8,7 +8,7 @@ import ( "github.com/matrix-org/gomatrixserverlib" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" ) type Event struct { diff --git a/internal/instruction/runner.go b/internal/instruction/runner.go index ec8e7039..0e31f745 100644 --- a/internal/instruction/runner.go +++ b/internal/instruction/runner.go @@ -18,7 +18,7 @@ import ( "github.com/tidwall/gjson" "maunium.net/go/mautrix/crypto/olm" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" ) // An instruction for the runner to run. diff --git a/tests/csapi/account_change_password_pushers_test.go b/tests/csapi/account_change_password_pushers_test.go index 38a1d0d5..6b75d579 100644 --- a/tests/csapi/account_change_password_pushers_test.go +++ b/tests/csapi/account_change_password_pushers_test.go @@ -7,7 +7,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" diff --git a/tests/csapi/account_change_password_test.go b/tests/csapi/account_change_password_test.go index 736bfe5c..efdaeb3c 100644 --- a/tests/csapi/account_change_password_test.go +++ b/tests/csapi/account_change_password_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/docker" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" diff --git a/tests/csapi/account_data_test.go b/tests/csapi/account_data_test.go index 1490896b..e79f5371 100644 --- a/tests/csapi/account_data_test.go +++ b/tests/csapi/account_data_test.go @@ -3,7 +3,7 @@ package csapi_tests import ( "testing" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/account_deactivate_test.go b/tests/csapi/account_deactivate_test.go index 95982e73..fc3033b0 100644 --- a/tests/csapi/account_deactivate_test.go +++ b/tests/csapi/account_deactivate_test.go @@ -7,7 +7,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/admin_test.go b/tests/csapi/admin_test.go index df844df4..5b89a406 100644 --- a/tests/csapi/admin_test.go +++ b/tests/csapi/admin_test.go @@ -8,7 +8,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/apidoc_content_test.go b/tests/csapi/apidoc_content_test.go index 2c56f0a2..36aeace3 100644 --- a/tests/csapi/apidoc_content_test.go +++ b/tests/csapi/apidoc_content_test.go @@ -4,7 +4,7 @@ import ( "bytes" "testing" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/data" ) diff --git a/tests/csapi/apidoc_device_management_test.go b/tests/csapi/apidoc_device_management_test.go index 72204b56..541f3541 100644 --- a/tests/csapi/apidoc_device_management_test.go +++ b/tests/csapi/apidoc_device_management_test.go @@ -6,7 +6,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/apidoc_login_test.go b/tests/csapi/apidoc_login_test.go index d2319e35..d8a2f65a 100644 --- a/tests/csapi/apidoc_login_test.go +++ b/tests/csapi/apidoc_login_test.go @@ -8,7 +8,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/apidoc_logout_test.go b/tests/csapi/apidoc_logout_test.go index 49b94c84..9d883761 100644 --- a/tests/csapi/apidoc_logout_test.go +++ b/tests/csapi/apidoc_logout_test.go @@ -7,7 +7,7 @@ import ( "github.com/tidwall/gjson" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/apidoc_presence_test.go b/tests/csapi/apidoc_presence_test.go index 274460da..ec64a9f4 100644 --- a/tests/csapi/apidoc_presence_test.go +++ b/tests/csapi/apidoc_presence_test.go @@ -11,7 +11,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/apidoc_profile_avatar_url_test.go b/tests/csapi/apidoc_profile_avatar_url_test.go index bafdb429..06e91cb9 100644 --- a/tests/csapi/apidoc_profile_avatar_url_test.go +++ b/tests/csapi/apidoc_profile_avatar_url_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/apidoc_profile_displayname_test.go b/tests/csapi/apidoc_profile_displayname_test.go index 58eeebb4..7762e7fb 100644 --- a/tests/csapi/apidoc_profile_displayname_test.go +++ b/tests/csapi/apidoc_profile_displayname_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/apidoc_register_test.go b/tests/csapi/apidoc_register_test.go index f62703fc..96f65ded 100644 --- a/tests/csapi/apidoc_register_test.go +++ b/tests/csapi/apidoc_register_test.go @@ -14,7 +14,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/apidoc_request_encoding_test.go b/tests/csapi/apidoc_request_encoding_test.go index e65e091c..33534383 100644 --- a/tests/csapi/apidoc_request_encoding_test.go +++ b/tests/csapi/apidoc_request_encoding_test.go @@ -6,7 +6,7 @@ import ( "encoding/json" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/apidoc_room_alias_test.go b/tests/csapi/apidoc_room_alias_test.go index bb89eec4..f157d6f0 100644 --- a/tests/csapi/apidoc_room_alias_test.go +++ b/tests/csapi/apidoc_room_alias_test.go @@ -8,7 +8,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/apidoc_room_create_test.go b/tests/csapi/apidoc_room_create_test.go index 84d62ac6..6e7d76d6 100644 --- a/tests/csapi/apidoc_room_create_test.go +++ b/tests/csapi/apidoc_room_create_test.go @@ -6,7 +6,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/apidoc_room_forget_test.go b/tests/csapi/apidoc_room_forget_test.go index a7f886d5..197a4bf7 100644 --- a/tests/csapi/apidoc_room_forget_test.go +++ b/tests/csapi/apidoc_room_forget_test.go @@ -9,7 +9,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/apidoc_room_history_visibility_test.go b/tests/csapi/apidoc_room_history_visibility_test.go index 3857f20e..e6ccd18d 100644 --- a/tests/csapi/apidoc_room_history_visibility_test.go +++ b/tests/csapi/apidoc_room_history_visibility_test.go @@ -7,7 +7,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/apidoc_room_members_test.go b/tests/csapi/apidoc_room_members_test.go index c32d5fd5..79230f54 100644 --- a/tests/csapi/apidoc_room_members_test.go +++ b/tests/csapi/apidoc_room_members_test.go @@ -6,7 +6,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/apidoc_room_receipts_test.go b/tests/csapi/apidoc_room_receipts_test.go index 3048af1e..50724877 100644 --- a/tests/csapi/apidoc_room_receipts_test.go +++ b/tests/csapi/apidoc_room_receipts_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/docker" "github.com/tidwall/gjson" ) diff --git a/tests/csapi/apidoc_room_state_test.go b/tests/csapi/apidoc_room_state_test.go index 8e3cb4db..06b7dac2 100644 --- a/tests/csapi/apidoc_room_state_test.go +++ b/tests/csapi/apidoc_room_state_test.go @@ -9,7 +9,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/apidoc_search_test.go b/tests/csapi/apidoc_search_test.go index dd40ff09..a2945e60 100644 --- a/tests/csapi/apidoc_search_test.go +++ b/tests/csapi/apidoc_search_test.go @@ -10,7 +10,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/apidoc_server_capabilities_test.go b/tests/csapi/apidoc_server_capabilities_test.go index 13912ee5..b7e1024b 100644 --- a/tests/csapi/apidoc_server_capabilities_test.go +++ b/tests/csapi/apidoc_server_capabilities_test.go @@ -4,7 +4,7 @@ import ( "net/http" "testing" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/apidoc_version_test.go b/tests/csapi/apidoc_version_test.go index df7e6dd4..ed756210 100644 --- a/tests/csapi/apidoc_version_test.go +++ b/tests/csapi/apidoc_version_test.go @@ -7,7 +7,7 @@ import ( "github.com/tidwall/gjson" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/device_lists_test.go b/tests/csapi/device_lists_test.go index bdd759b0..8ffecb78 100644 --- a/tests/csapi/device_lists_test.go +++ b/tests/csapi/device_lists_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/docker" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" diff --git a/tests/csapi/e2e_key_backup_test.go b/tests/csapi/e2e_key_backup_test.go index 6b832381..fbf6c594 100644 --- a/tests/csapi/e2e_key_backup_test.go +++ b/tests/csapi/e2e_key_backup_test.go @@ -7,7 +7,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/ignored_users_test.go b/tests/csapi/ignored_users_test.go index ab35205d..a1f9fe80 100644 --- a/tests/csapi/ignored_users_test.go +++ b/tests/csapi/ignored_users_test.go @@ -11,7 +11,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/invalid_test.go b/tests/csapi/invalid_test.go index be5e37e7..e3f4cd6e 100644 --- a/tests/csapi/invalid_test.go +++ b/tests/csapi/invalid_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/complement/runtime" diff --git a/tests/csapi/keychanges_test.go b/tests/csapi/keychanges_test.go index ffc25c12..95f9c8af 100644 --- a/tests/csapi/keychanges_test.go +++ b/tests/csapi/keychanges_test.go @@ -9,7 +9,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/main_test.go b/tests/csapi/main_test.go index dfff20cb..f0eae339 100644 --- a/tests/csapi/main_test.go +++ b/tests/csapi/main_test.go @@ -12,7 +12,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/config" "github.com/matrix-org/complement/internal/docker" ) diff --git a/tests/csapi/media_misc_test.go b/tests/csapi/media_misc_test.go index 3ae93476..61159da0 100644 --- a/tests/csapi/media_misc_test.go +++ b/tests/csapi/media_misc_test.go @@ -7,7 +7,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/data" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" diff --git a/tests/csapi/power_levels_test.go b/tests/csapi/power_levels_test.go index 90a73019..dd24c8c5 100644 --- a/tests/csapi/power_levels_test.go +++ b/tests/csapi/power_levels_test.go @@ -7,7 +7,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/push_test.go b/tests/csapi/push_test.go index 1ce0ec4b..53e63b55 100644 --- a/tests/csapi/push_test.go +++ b/tests/csapi/push_test.go @@ -8,7 +8,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/room_ban_test.go b/tests/csapi/room_ban_test.go index 54bd9020..80e838eb 100644 --- a/tests/csapi/room_ban_test.go +++ b/tests/csapi/room_ban_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/room_kick_test.go b/tests/csapi/room_kick_test.go index 38312fd6..72957fe6 100644 --- a/tests/csapi/room_kick_test.go +++ b/tests/csapi/room_kick_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/room_leave_test.go b/tests/csapi/room_leave_test.go index db3257b4..2cd7870a 100644 --- a/tests/csapi/room_leave_test.go +++ b/tests/csapi/room_leave_test.go @@ -8,7 +8,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/room_members_test.go b/tests/csapi/room_members_test.go index f5c2fda6..0419955b 100644 --- a/tests/csapi/room_members_test.go +++ b/tests/csapi/room_members_test.go @@ -8,7 +8,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/room_messages_relation_filter_test.go b/tests/csapi/room_messages_relation_filter_test.go index 62657f6f..e64b0bf4 100644 --- a/tests/csapi/room_messages_relation_filter_test.go +++ b/tests/csapi/room_messages_relation_filter_test.go @@ -11,7 +11,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/complement/runtime" diff --git a/tests/csapi/room_messages_test.go b/tests/csapi/room_messages_test.go index 5fba1d25..8edf50c8 100644 --- a/tests/csapi/room_messages_test.go +++ b/tests/csapi/room_messages_test.go @@ -9,7 +9,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/complement/runtime" diff --git a/tests/csapi/room_profile_test.go b/tests/csapi/room_profile_test.go index bbf60986..3a798a57 100644 --- a/tests/csapi/room_profile_test.go +++ b/tests/csapi/room_profile_test.go @@ -6,7 +6,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" ) func TestAvatarUrlUpdate(t *testing.T) { diff --git a/tests/csapi/room_relations_test.go b/tests/csapi/room_relations_test.go index adbe4eb6..f2bc76b9 100644 --- a/tests/csapi/room_relations_test.go +++ b/tests/csapi/room_relations_test.go @@ -9,7 +9,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/complement/runtime" diff --git a/tests/csapi/room_threads_test.go b/tests/csapi/room_threads_test.go index 27d756ee..b5938744 100644 --- a/tests/csapi/room_threads_test.go +++ b/tests/csapi/room_threads_test.go @@ -7,7 +7,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/complement/runtime" diff --git a/tests/csapi/room_typing_test.go b/tests/csapi/room_typing_test.go index fc55acd5..0300b850 100644 --- a/tests/csapi/room_typing_test.go +++ b/tests/csapi/room_typing_test.go @@ -6,7 +6,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/rooms_invite_test.go b/tests/csapi/rooms_invite_test.go index 521208f8..dd33c39c 100644 --- a/tests/csapi/rooms_invite_test.go +++ b/tests/csapi/rooms_invite_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/tidwall/gjson" diff --git a/tests/csapi/rooms_members_local_test.go b/tests/csapi/rooms_members_local_test.go index 6b2796ff..abdf2c9d 100644 --- a/tests/csapi/rooms_members_local_test.go +++ b/tests/csapi/rooms_members_local_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/runtime" ) diff --git a/tests/csapi/rooms_state_test.go b/tests/csapi/rooms_state_test.go index c00da6d2..81e12961 100644 --- a/tests/csapi/rooms_state_test.go +++ b/tests/csapi/rooms_state_test.go @@ -10,7 +10,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/sync_archive_test.go b/tests/csapi/sync_archive_test.go index fadc03ce..8dfdd21c 100644 --- a/tests/csapi/sync_archive_test.go +++ b/tests/csapi/sync_archive_test.go @@ -6,7 +6,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/runtime" ) diff --git a/tests/csapi/sync_filter_test.go b/tests/csapi/sync_filter_test.go index 64ae1122..42a02bf3 100644 --- a/tests/csapi/sync_filter_test.go +++ b/tests/csapi/sync_filter_test.go @@ -7,7 +7,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/sync_test.go b/tests/csapi/sync_test.go index 918e9637..e1c68b1b 100644 --- a/tests/csapi/sync_test.go +++ b/tests/csapi/sync_test.go @@ -9,7 +9,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/runtime" ) diff --git a/tests/csapi/thread_notifications_test.go b/tests/csapi/thread_notifications_test.go index a0e7bea8..4009afb1 100644 --- a/tests/csapi/thread_notifications_test.go +++ b/tests/csapi/thread_notifications_test.go @@ -7,7 +7,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/runtime" ) diff --git a/tests/csapi/to_device_test.go b/tests/csapi/to_device_test.go index 3b8606b5..57bc5833 100644 --- a/tests/csapi/to_device_test.go +++ b/tests/csapi/to_device_test.go @@ -7,7 +7,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" ) // sytest: Can send a message directly to a device using PUT /sendToDevice diff --git a/tests/csapi/txnid_test.go b/tests/csapi/txnid_test.go index e91e9cbb..82d71934 100644 --- a/tests/csapi/txnid_test.go +++ b/tests/csapi/txnid_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/complement/runtime" "github.com/tidwall/gjson" diff --git a/tests/csapi/upload_keys_test.go b/tests/csapi/upload_keys_test.go index d7b96e59..362be943 100644 --- a/tests/csapi/upload_keys_test.go +++ b/tests/csapi/upload_keys_test.go @@ -9,7 +9,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/complement/runtime" diff --git a/tests/csapi/url_preview_test.go b/tests/csapi/url_preview_test.go index 6ee28e18..a32a18ce 100644 --- a/tests/csapi/url_preview_test.go +++ b/tests/csapi/url_preview_test.go @@ -11,7 +11,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/data" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" diff --git a/tests/csapi/user_directory_display_names_test.go b/tests/csapi/user_directory_display_names_test.go index 78c81e3c..90730985 100644 --- a/tests/csapi/user_directory_display_names_test.go +++ b/tests/csapi/user_directory_display_names_test.go @@ -8,7 +8,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/csapi/user_query_keys_test.go b/tests/csapi/user_query_keys_test.go index b9ece4cf..30452e18 100644 --- a/tests/csapi/user_query_keys_test.go +++ b/tests/csapi/user_query_keys_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/direct_messaging_test.go b/tests/direct_messaging_test.go index 93854111..77b42c49 100644 --- a/tests/direct_messaging_test.go +++ b/tests/direct_messaging_test.go @@ -7,7 +7,7 @@ import ( "time" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" diff --git a/tests/federation_acl_test.go b/tests/federation_acl_test.go index ead0a429..886c52ce 100644 --- a/tests/federation_acl_test.go +++ b/tests/federation_acl_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/complement/runtime" diff --git a/tests/federation_event_auth_test.go b/tests/federation_event_auth_test.go index 395b131d..f4c75921 100644 --- a/tests/federation_event_auth_test.go +++ b/tests/federation_event_auth_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/gomatrixserverlib/spec" diff --git a/tests/federation_keys_test.go b/tests/federation_keys_test.go index 026db928..61605f71 100644 --- a/tests/federation_keys_test.go +++ b/tests/federation_keys_test.go @@ -12,7 +12,7 @@ import ( "github.com/tidwall/gjson" "github.com/tidwall/sjson" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/docker" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" diff --git a/tests/federation_presence_test.go b/tests/federation_presence_test.go index 5dd412a7..eede5b94 100644 --- a/tests/federation_presence_test.go +++ b/tests/federation_presence_test.go @@ -6,7 +6,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" ) func TestRemotePresence(t *testing.T) { diff --git a/tests/federation_query_profile_test.go b/tests/federation_query_profile_test.go index 39cae7c3..739997be 100644 --- a/tests/federation_query_profile_test.go +++ b/tests/federation_query_profile_test.go @@ -10,7 +10,7 @@ import ( "github.com/matrix-org/gomatrixserverlib/spec" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" diff --git a/tests/federation_redaction_test.go b/tests/federation_redaction_test.go index 29c2c00b..5531e3f0 100644 --- a/tests/federation_redaction_test.go +++ b/tests/federation_redaction_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/runtime" "github.com/matrix-org/gomatrixserverlib" diff --git a/tests/federation_room_alias_test.go b/tests/federation_room_alias_test.go index 20561174..d8ef6d28 100644 --- a/tests/federation_room_alias_test.go +++ b/tests/federation_room_alias_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/federation_room_ban_test.go b/tests/federation_room_ban_test.go index 444a5306..cb69078f 100644 --- a/tests/federation_room_ban_test.go +++ b/tests/federation_room_ban_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/runtime" ) diff --git a/tests/federation_room_event_auth_test.go b/tests/federation_room_event_auth_test.go index 3a317ba4..d85b07ac 100644 --- a/tests/federation_room_event_auth_test.go +++ b/tests/federation_room_event_auth_test.go @@ -18,7 +18,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/federation_room_get_missing_events_test.go b/tests/federation_room_get_missing_events_test.go index a568af79..966b8570 100644 --- a/tests/federation_room_get_missing_events_test.go +++ b/tests/federation_room_get_missing_events_test.go @@ -15,7 +15,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" diff --git a/tests/federation_room_invite_test.go b/tests/federation_room_invite_test.go index b277480d..a08152c0 100644 --- a/tests/federation_room_invite_test.go +++ b/tests/federation_room_invite_test.go @@ -6,7 +6,7 @@ import ( "github.com/matrix-org/gomatrixserverlib" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" ) diff --git a/tests/federation_room_join_partial_state_test.go b/tests/federation_room_join_partial_state_test.go index 49ad59e0..d6f93631 100644 --- a/tests/federation_room_join_partial_state_test.go +++ b/tests/federation_room_join_partial_state_test.go @@ -31,7 +31,7 @@ import ( "github.com/matrix-org/gomatrixserverlib/spec" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/docker" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/match" diff --git a/tests/federation_room_join_test.go b/tests/federation_room_join_test.go index 7ee127f9..0ae833fd 100644 --- a/tests/federation_room_join_test.go +++ b/tests/federation_room_join_test.go @@ -20,7 +20,7 @@ import ( "github.com/tidwall/sjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" diff --git a/tests/federation_room_send_test.go b/tests/federation_room_send_test.go index f9993640..85568798 100644 --- a/tests/federation_room_send_test.go +++ b/tests/federation_room_send_test.go @@ -6,7 +6,7 @@ import ( "github.com/matrix-org/gomatrixserverlib" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" ) diff --git a/tests/federation_room_typing_test.go b/tests/federation_room_typing_test.go index aa892d90..d072a135 100644 --- a/tests/federation_room_typing_test.go +++ b/tests/federation_room_typing_test.go @@ -6,7 +6,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" ) func awaitTyping(userId string) func(result gjson.Result) bool { diff --git a/tests/federation_rooms_invite_test.go b/tests/federation_rooms_invite_test.go index 7e4b0663..a4e808c5 100644 --- a/tests/federation_rooms_invite_test.go +++ b/tests/federation_rooms_invite_test.go @@ -7,7 +7,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/federation_unreject_rejected_test.go b/tests/federation_unreject_rejected_test.go index e255dfa9..ce799ac5 100644 --- a/tests/federation_unreject_rejected_test.go +++ b/tests/federation_unreject_rejected_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" ) diff --git a/tests/federation_upload_keys_test.go b/tests/federation_upload_keys_test.go index 23a5ccdd..acc3add8 100644 --- a/tests/federation_upload_keys_test.go +++ b/tests/federation_upload_keys_test.go @@ -9,7 +9,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/knock_restricted_test.go b/tests/knock_restricted_test.go index 91d4d897..3398bb35 100644 --- a/tests/knock_restricted_test.go +++ b/tests/knock_restricted_test.go @@ -11,7 +11,7 @@ package tests import ( "testing" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" ) var ( diff --git a/tests/knocking_test.go b/tests/knocking_test.go index 80802bea..e51d4e71 100644 --- a/tests/knocking_test.go +++ b/tests/knocking_test.go @@ -20,7 +20,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" diff --git a/tests/main_test.go b/tests/main_test.go index f88e69ea..8d5a88e9 100644 --- a/tests/main_test.go +++ b/tests/main_test.go @@ -12,7 +12,7 @@ import ( "github.com/sirupsen/logrus" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/config" "github.com/matrix-org/complement/internal/docker" ) diff --git a/tests/media_filename_test.go b/tests/media_filename_test.go index 2106353a..3ccca8e0 100644 --- a/tests/media_filename_test.go +++ b/tests/media_filename_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/data" "github.com/matrix-org/complement/runtime" ) diff --git a/tests/media_nofilename_test.go b/tests/media_nofilename_test.go index 76c2a87c..24aa0165 100644 --- a/tests/media_nofilename_test.go +++ b/tests/media_nofilename_test.go @@ -6,7 +6,7 @@ import ( "strings" "testing" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/media_thumbnail_test.go b/tests/media_thumbnail_test.go index 16bcc8a2..a067483b 100644 --- a/tests/media_thumbnail_test.go +++ b/tests/media_thumbnail_test.go @@ -10,7 +10,7 @@ import ( "testing" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/data" ) diff --git a/tests/msc2836_test.go b/tests/msc2836_test.go index bce90b8e..ac469326 100644 --- a/tests/msc2836_test.go +++ b/tests/msc2836_test.go @@ -19,7 +19,7 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" diff --git a/tests/msc3391_test.go b/tests/msc3391_test.go index d824bb97..92da974a 100644 --- a/tests/msc3391_test.go +++ b/tests/msc3391_test.go @@ -11,7 +11,7 @@ import ( "fmt" "testing" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" diff --git a/tests/msc3890_test.go b/tests/msc3890_test.go index a73972ad..4c61d86b 100644 --- a/tests/msc3890_test.go +++ b/tests/msc3890_test.go @@ -10,7 +10,7 @@ package tests import ( "testing" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" diff --git a/tests/msc3930_test.go b/tests/msc3930_test.go index 04d6bb7f..3e2a9c3a 100644 --- a/tests/msc3930_test.go +++ b/tests/msc3930_test.go @@ -17,7 +17,7 @@ import ( "math" "testing" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" ) diff --git a/tests/restricted_room_hierarchy_test.go b/tests/restricted_room_hierarchy_test.go index 9c7a97e1..c067c654 100644 --- a/tests/restricted_room_hierarchy_test.go +++ b/tests/restricted_room_hierarchy_test.go @@ -7,7 +7,7 @@ import ( "github.com/tidwall/gjson" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" diff --git a/tests/restricted_rooms_test.go b/tests/restricted_rooms_test.go index 674ec2ee..fd601e48 100644 --- a/tests/restricted_rooms_test.go +++ b/tests/restricted_rooms_test.go @@ -8,7 +8,7 @@ import ( "github.com/tidwall/gjson" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/docker" "github.com/matrix-org/complement/internal/match" diff --git a/tests/room_hierarchy_test.go b/tests/room_hierarchy_test.go index a9d18156..c5fe56e4 100644 --- a/tests/room_hierarchy_test.go +++ b/tests/room_hierarchy_test.go @@ -20,7 +20,7 @@ import ( "github.com/tidwall/gjson" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" diff --git a/tests/room_timestamp_to_event_test.go b/tests/room_timestamp_to_event_test.go index 236d8e91..f0decbec 100644 --- a/tests/room_timestamp_to_event_test.go +++ b/tests/room_timestamp_to_event_test.go @@ -15,7 +15,7 @@ import ( "testing" "time" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" diff --git a/tests/unknown_endpoints_test.go b/tests/unknown_endpoints_test.go index 19bd908f..cdac1805 100644 --- a/tests/unknown_endpoints_test.go +++ b/tests/unknown_endpoints_test.go @@ -4,7 +4,7 @@ import ( "net/http" "testing" - "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" From 9e57f77a6fe8341f199ee38245f83521f1d12689 Mon Sep 17 00:00:00 2001 From: kegsay Date: Thu, 5 Oct 2023 17:44:22 +0100 Subject: [PATCH 10/10] Move must and match packages out of internal; add generic must functions (#661) * Move must and match packages out of internal; add generic must functions * add more useful must functions * Add typing helper functions * More general tidyup of ./tests * Prefer gjson.Result in more places as it is more expressive * Patch up mscs * Make ParseJSON and GetJSONFieldStr return/accept gjson not bytes * Remove unused function --- client/client.go | 11 ++ client/sync.go | 28 ++++ go.mod | 38 +++-- go.sum | 125 +--------------- {internal/match => match}/http.go | 0 {internal/match => match}/json.go | 131 ++++++++++------- {internal/must => must}/must.go | 137 +++++++++++++----- .../account_change_password_pushers_test.go | 4 +- tests/csapi/account_change_password_test.go | 4 +- tests/csapi/account_data_test.go | 4 +- tests/csapi/account_deactivate_test.go | 4 +- tests/csapi/admin_test.go | 4 +- tests/csapi/apidoc_device_management_test.go | 4 +- tests/csapi/apidoc_login_test.go | 9 +- tests/csapi/apidoc_logout_test.go | 4 +- tests/csapi/apidoc_presence_test.go | 4 +- tests/csapi/apidoc_profile_avatar_url_test.go | 4 +- .../csapi/apidoc_profile_displayname_test.go | 4 +- tests/csapi/apidoc_register_test.go | 10 +- tests/csapi/apidoc_request_encoding_test.go | 4 +- tests/csapi/apidoc_room_alias_test.go | 9 +- tests/csapi/apidoc_room_create_test.go | 4 +- tests/csapi/apidoc_room_forget_test.go | 4 +- .../apidoc_room_history_visibility_test.go | 4 +- tests/csapi/apidoc_room_members_test.go | 8 +- tests/csapi/apidoc_room_state_test.go | 4 +- tests/csapi/apidoc_search_test.go | 8 +- .../csapi/apidoc_server_capabilities_test.go | 4 +- tests/csapi/apidoc_version_test.go | 8 +- tests/csapi/device_lists_test.go | 4 +- tests/csapi/e2e_key_backup_test.go | 12 +- tests/csapi/ignored_users_test.go | 4 +- tests/csapi/invalid_test.go | 4 +- tests/csapi/keychanges_test.go | 4 +- tests/csapi/media_misc_test.go | 4 +- tests/csapi/power_levels_test.go | 12 +- tests/csapi/push_test.go | 4 +- tests/csapi/room_ban_test.go | 4 +- tests/csapi/room_kick_test.go | 4 +- tests/csapi/room_leave_test.go | 4 +- tests/csapi/room_members_test.go | 16 +- .../room_messages_relation_filter_test.go | 4 +- tests/csapi/room_messages_test.go | 4 +- tests/csapi/room_relations_test.go | 4 +- tests/csapi/room_threads_test.go | 4 +- tests/csapi/room_typing_test.go | 91 ++---------- tests/csapi/rooms_invite_test.go | 4 +- tests/csapi/rooms_state_test.go | 21 ++- tests/csapi/sync_filter_test.go | 4 +- tests/csapi/txnid_test.go | 22 +-- tests/csapi/upload_keys_test.go | 4 +- tests/csapi/url_preview_test.go | 10 +- .../user_directory_display_names_test.go | 4 +- tests/csapi/user_query_keys_test.go | 4 +- tests/direct_messaging_test.go | 16 +- tests/federation_acl_test.go | 30 +--- tests/federation_event_auth_test.go | 15 +- tests/federation_keys_test.go | 41 ++---- tests/federation_query_profile_test.go | 4 +- tests/federation_redaction_test.go | 10 +- tests/federation_room_alias_test.go | 4 +- tests/federation_room_ban_test.go | 4 +- tests/federation_room_event_auth_test.go | 2 +- ...federation_room_get_missing_events_test.go | 22 +-- ...federation_room_join_partial_state_test.go | 53 ++----- tests/federation_room_join_test.go | 16 +- tests/federation_room_typing_test.go | 29 +--- tests/federation_rooms_invite_test.go | 4 +- tests/federation_upload_keys_test.go | 4 +- tests/knocking_test.go | 12 +- tests/media_nofilename_test.go | 14 +- tests/media_thumbnail_test.go | 6 +- tests/msc2836_test.go | 13 +- tests/msc3391_test.go | 39 +---- tests/msc3890_test.go | 9 +- tests/msc3930_test.go | 4 +- tests/restricted_room_hierarchy_test.go | 4 +- tests/restricted_rooms_test.go | 21 +-- tests/room_hierarchy_test.go | 4 +- tests/room_timestamp_to_event_test.go | 16 +- tests/unknown_endpoints_test.go | 4 +- 81 files changed, 538 insertions(+), 704 deletions(-) rename {internal/match => match}/http.go (100%) rename {internal/match => match}/json.go (75%) rename {internal/must => must}/must.go (61%) diff --git a/client/client.go b/client/client.go index 027d40b0..307ae8d2 100644 --- a/client/client.go +++ b/client/client.go @@ -276,6 +276,17 @@ func (c *CSAPI) SendRedaction(t TestLike, roomID string, e b.Event, eventID stri return GetJSONFieldStr(t, body, "event_id") } +// SendTyping marks this user as typing until the timeout is reached. If isTyping is false, timeout is ignored. +func (c *CSAPI) SendTyping(t TestLike, roomID string, isTyping bool, timeoutMillis int) { + content := map[string]interface{}{ + "typing": isTyping, + } + if isTyping { + content["timeout"] = timeoutMillis + } + c.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "typing", c.UserID}, WithJSONBody(t, content)) +} + // GetCapbabilities queries the server's capabilities func (c *CSAPI) GetCapabilities(t TestLike) []byte { t.Helper() diff --git a/client/sync.go b/client/sync.go index 99495426..461465f0 100644 --- a/client/sync.go +++ b/client/sync.go @@ -3,6 +3,8 @@ package client import ( "fmt" "net/url" + "reflect" + "sort" "strings" "time" @@ -365,6 +367,32 @@ func SyncRoomAccountDataHas(roomID string, check func(gjson.Result) bool) SyncCh } } +// SyncUsersTyping passes when all users in `userIDs` are typing in the same typing EDU. +// It must see a typing EDU first before returning, even if the list of user IDs is empty. +func SyncUsersTyping(roomID string, userIDs []string) SyncCheckOpt { + // don't sort the input slice the test gave us. + userIDsCopy := make([]string, len(userIDs)) + copy(userIDsCopy, userIDs) + sort.Strings(userIDsCopy) + return SyncEphemeralHas(roomID, func(r gjson.Result) bool { + if r.Get("type").Str != "m.typing" { + return false + } + + var usersSeenTyping []string + for _, item := range r.Get("content").Get("user_ids").Array() { + usersSeenTyping = append(usersSeenTyping, item.Str) + } + // special case to support nil and 0 length slices + if len(usersSeenTyping) == 0 && len(userIDsCopy) == 0 { + return true + } + sort.Strings(userIDsCopy) + sort.Strings(usersSeenTyping) + return reflect.DeepEqual(userIDsCopy, usersSeenTyping) + }) +} + // Check that sync has received a to-device message, // with optional user filtering. // diff --git a/go.mod b/go.mod index ce52cfd6..60fe636f 100644 --- a/go.mod +++ b/go.mod @@ -1,32 +1,46 @@ module github.com/matrix-org/complement -go 1.16 +go 1.18 require ( - github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect - github.com/Microsoft/go-winio v0.5.2 // indirect - github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/docker v20.10.24+incompatible github.com/docker/go-connections v0.4.0 - github.com/docker/go-units v0.4.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect github.com/gorilla/mux v1.8.0 github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 github.com/matrix-org/gomatrixserverlib v0.0.0-20230921171121-0466775328c7 github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 + github.com/sirupsen/logrus v1.9.3 + github.com/tidwall/gjson v1.16.0 + github.com/tidwall/sjson v1.2.5 + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 + gonum.org/v1/plot v0.11.0 + maunium.net/go/mautrix v0.11.0 +) + +require ( + git.sr.ht/~sbinet/gg v0.3.1 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Microsoft/go-winio v0.5.2 // indirect + github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b // indirect + github.com/docker/distribution v2.8.2+incompatible // indirect + github.com/docker/go-units v0.4.0 // indirect + github.com/go-fonts/liberation v0.2.0 // indirect + github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81 // indirect + github.com/go-pdf/fpdf v0.6.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect - github.com/sirupsen/logrus v1.9.3 - github.com/tidwall/gjson v1.16.0 + github.com/pkg/errors v0.9.1 // indirect + github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect - github.com/tidwall/sjson v1.2.5 golang.org/x/crypto v0.13.0 // indirect - golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 // indirect golang.org/x/image v0.5.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.12.0 // indirect + golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect - gonum.org/v1/plot v0.11.0 gotest.tools/v3 v3.0.3 // indirect - maunium.net/go/mautrix v0.11.0 ) diff --git a/go.sum b/go.sum index a3e2ea9b..11b35ba7 100644 --- a/go.sum +++ b/go.sum @@ -1,22 +1,17 @@ -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= git.sr.ht/~sbinet/gg v0.3.1 h1:LNhjNn8DerC8f9DHLz6lS0YYul/b602DUxDgGkd/Aik= git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw= github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -29,21 +24,14 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/frankban/quicktest v1.0.0/go.mod h1:R98jIehRai+d1/3Hv2//jOVCTJhW1VBavT6B6CuGq2k= -github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/go-fonts/dejavu v0.1.0 h1:JSajPXURYqpr+Cu8U9bt8K+XcACIHWqWrvWCKyeFmVQ= github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= github.com/go-fonts/latin-modern v0.2.0 h1:5/Tv1Ek/QCr20C6ZOz15vw3g7GELYL98KWr8Hgo+3vk= github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= -github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= github.com/go-fonts/liberation v0.2.0 h1:jAkAWJP4S+OsrPLZM4/eC9iW7CtHy+HBXrEwZXWo5VM= github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81 h1:6zl3BbBhdnMkpSj2YY30qV3gDcVBGtFgVsV3+/i+mKQ= github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= @@ -53,44 +41,26 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= -github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= github.com/matrix-org/gomatrixserverlib v0.0.0-20230921171121-0466775328c7 h1:NhPNNFLHwdDb/upeicBh1GkxX/sFinEp5HF1WBqPtiY= github.com/matrix-org/gomatrixserverlib v0.0.0-20230921171121-0466775328c7/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= -github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4/go.mod h1:vVQlW/emklohkZnOPwD3LrZUBqdfsbiyO3p1lNV8F6U= github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y= github.com/matrix-org/util v0.0.0-20221111132719-399730281e66/go.mod h1:iBI1foelCqA09JJgPV0FYz4qA5dUXYOxMi57FxKBdd4= -github.com/mattn/go-sqlite3 v1.14.13/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= -github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 h1:yH0SvLzcbZxcJXho2yh7CqdENGMQe73Cw3woZBpPli0= github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= @@ -103,27 +73,17 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg= github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= @@ -131,172 +91,95 @@ github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JT github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp19pSNM= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.12/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20180723164146-c126467f60eb/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI= golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220513224357-95641704303c/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220907140024-f12130a52804/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= gonum.org/v1/gonum v0.11.0 h1:f1IJhK4Km5tBJmaiJXtk/PkL4cdVX6J+tGiM187uT5E= -gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= -gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= gonum.org/v1/plot v0.11.0 h1:z2ZkgNqW34d0oYUzd80RRlc0L9kWtenqK4kflZG1lGc= gonum.org/v1/plot v0.11.0/go.mod h1:fH9YnKnDKax0u5EzHVXvhN5HJwtMFWIOLNuhgUahbCQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY= -gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0= -gopkg.in/macaroon.v2 v2.1.0/go.mod h1:OUb+TQP/OP0WOerC2Jp/3CwhIKyIa9kQjuc7H24e6/o= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -maunium.net/go/maulogger/v2 v2.3.2/go.mod h1:TYWy7wKwz/tIXTpsx8G3mZseIRiC5DoMxSZazOHy68A= maunium.net/go/mautrix v0.11.0 h1:B1FBHcvE4Mud+AC+zgNQQOw0JxSVrt40watCejhVA7w= maunium.net/go/mautrix v0.11.0/go.mod h1:K29EcHwsNg6r7fMfwvi0GHQ9o5wSjqB9+Q8RjCIQEjA= rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/internal/match/http.go b/match/http.go similarity index 100% rename from internal/match/http.go rename to match/http.go diff --git a/internal/match/json.go b/match/json.go similarity index 75% rename from internal/match/json.go rename to match/json.go index 068000ee..3b1b3829 100644 --- a/internal/match/json.go +++ b/match/json.go @@ -1,3 +1,21 @@ +// package match contains matchers for HTTP and JSON data. +// +// Matchers are composable functions which check for the data specified, returning a golang error if a matcher fails. +// They are typically used with the 'must' package in the following way: +// +// res := user.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.server_acl"}) +// must.MatchResponse(t, res, match.HTTPResponse{ +// StatusCode: 200, +// JSON: []match.JSON{ +// match.JSONKeyEqual("allow", []string{"*"}), +// match.JSONKeyEqual("deny", []string{"hs2"}), +// match.JSONKeyEqual("allow_ip_literals", true), +// }, +// }) +// +// Matchers have no concept of tests, and do not automatically fail tests if the match fails. This can be useful +// when you want to repeatedly perform a check until it succeeds (e.g from /sync). If you want matches to fail a test, +// you can use the 'must' package. package match import ( @@ -11,45 +29,36 @@ import ( // JSON will perform some matches on the given JSON body, returning an error on a mis-match. // It can be assumed that the bytes are valid JSON. -type JSON func(body []byte) error +type JSON func(body gjson.Result) error // JSONKeyEqual returns a matcher which will check that `wantKey` is present and its value matches `wantValue`. // `wantKey` can be nested, see https://godoc.org/github.com/tidwall/gjson#Get for details. // `wantValue` is matched via JSONDeepEqual and the JSON takes the forms according to https://godoc.org/github.com/tidwall/gjson#Result.Value func JSONKeyEqual(wantKey string, wantValue interface{}) JSON { - return func(body []byte) error { - res := gjson.GetBytes(body, wantKey) + return func(body gjson.Result) error { + res := body + if wantKey != "" { + res = body.Get(wantKey) + } if !res.Exists() { return fmt.Errorf("key '%s' missing", wantKey) } gotValue := res.Value() - if !JSONDeepEqual([]byte(res.Raw), wantValue) { + if !jsonDeepEqual([]byte(res.Raw), wantValue) { return fmt.Errorf( "key '%s' got '%v' (type %T) want '%v' (type %T)", wantKey, gotValue, gotValue, wantValue, wantValue, ) - } else { - return nil } + return nil } } -// JSONDeepEqual compares raw json with a json-serializable value, seeing if they're equal. -func JSONDeepEqual(gotJson []byte, wantValue interface{}) bool { - // marshal what the test gave us - wantBytes, _ := json.Marshal(wantValue) - // re-marshal what the network gave us to acount for key ordering - var gotVal interface{} - _ = json.Unmarshal(gotJson, &gotVal) - gotBytes, _ := json.Marshal(gotVal) - return bytes.Equal(gotBytes, wantBytes) -} - // JSONKeyPresent returns a matcher which will check that `wantKey` is present in the JSON object. // `wantKey` can be nested, see https://godoc.org/github.com/tidwall/gjson#Get for details. func JSONKeyPresent(wantKey string) JSON { - return func(body []byte) error { - res := gjson.GetBytes(body, wantKey) + return func(body gjson.Result) error { + res := body.Get(wantKey) if !res.Exists() { return fmt.Errorf("key '%s' missing", wantKey) } @@ -60,8 +69,8 @@ func JSONKeyPresent(wantKey string) JSON { // JSONKeyMissing returns a matcher which will check that `forbiddenKey` is not present in the JSON object. // `forbiddenKey` can be nested, see https://godoc.org/github.com/tidwall/gjson#Get for details. func JSONKeyMissing(forbiddenKey string) JSON { - return func(body []byte) error { - res := gjson.GetBytes(body, forbiddenKey) + return func(body gjson.Result) error { + res := body.Get(forbiddenKey) if res.Exists() { return fmt.Errorf("key '%s' present", forbiddenKey) } @@ -72,8 +81,8 @@ func JSONKeyMissing(forbiddenKey string) JSON { // JSONKeyTypeEqual returns a matcher which will check that `wantKey` is present and its value is of the type `wantType`. // `wantKey` can be nested, see https://godoc.org/github.com/tidwall/gjson#Get for details. func JSONKeyTypeEqual(wantKey string, wantType gjson.Type) JSON { - return func(body []byte) error { - res := gjson.GetBytes(body, wantKey) + return func(body gjson.Result) error { + res := body.Get(wantKey) if !res.Exists() { return fmt.Errorf("key '%s' missing", wantKey) } @@ -88,8 +97,8 @@ func JSONKeyTypeEqual(wantKey string, wantType gjson.Type) JSON { // its value is an array with the given size. // `wantKey` can be nested, see https://godoc.org/github.com/tidwall/gjson#Get for details. func JSONKeyArrayOfSize(wantKey string, wantSize int) JSON { - return func(body []byte) error { - res := gjson.GetBytes(body, wantKey) + return func(body gjson.Result) error { + res := body.Get(wantKey) if !res.Exists() { return fmt.Errorf("key '%s' missing", wantKey) } @@ -105,8 +114,8 @@ func JSONKeyArrayOfSize(wantKey string, wantSize int) JSON { } func jsonCheckOffInternal(wantKey string, wantItems []interface{}, allowUnwantedItems bool, mapper func(gjson.Result) interface{}, fn func(interface{}, gjson.Result) error) JSON { - return func(body []byte) error { - res := gjson.GetBytes(body, wantKey) + return func(body gjson.Result) error { + res := body.Get(wantKey) if !res.Exists() { return fmt.Errorf("JSONCheckOff: missing key '%s'", wantKey) } @@ -130,7 +139,7 @@ func jsonCheckOffInternal(wantKey string, wantItems []interface{}, allowUnwanted want := -1 for i, w := range wantItems { wBytes, _ := json.Marshal(w) - if JSONDeepEqual(wBytes, item) { + if jsonDeepEqual(wBytes, item) { want = i break } @@ -166,6 +175,7 @@ func jsonCheckOffInternal(wantKey string, wantItems []interface{}, allowUnwanted } } +// EXPERIMENTAL // JSONCheckOffAllowUnwanted returns a matcher which will loop over `wantKey` and ensure that the items // (which can be array elements or object keys) // are present exactly once in any order in `wantItems`. Allows unexpected items or items @@ -177,17 +187,19 @@ func jsonCheckOffInternal(wantKey string, wantItems []interface{}, allowUnwanted // it's an object). // // Usage: (ensures `events` has these events in any order, with the right event type) -// JSONCheckOffAllowUnwanted("events", []interface{}{"$foo:bar", "$baz:quuz"}, func(r gjson.Result) interface{} { -// return r.Get("event_id").Str -// }, func(eventID interface{}, eventBody gjson.Result) error { -// if eventBody.Get("type").Str != "m.room.message" { -// return fmt.Errorf("expected event to be 'm.room.message'") -// } -// }) +// +// JSONCheckOffAllowUnwanted("events", []interface{}{"$foo:bar", "$baz:quuz"}, func(r gjson.Result) interface{} { +// return r.Get("event_id").Str +// }, func(eventID interface{}, eventBody gjson.Result) error { +// if eventBody.Get("type").Str != "m.room.message" { +// return fmt.Errorf("expected event to be 'm.room.message'") +// } +// }) func JSONCheckOffAllowUnwanted(wantKey string, wantItems []interface{}, mapper func(gjson.Result) interface{}, fn func(interface{}, gjson.Result) error) JSON { return jsonCheckOffInternal(wantKey, wantItems, true, mapper, fn) } +// EXPERIMENTAL // JSONCheckOff returns a matcher which will loop over `wantKey` and ensure that the items // (which can be array elements or object keys) // are present exactly once in any order in `wantItems`. If there are unexpected items or items @@ -199,13 +211,14 @@ func JSONCheckOffAllowUnwanted(wantKey string, wantItems []interface{}, mapper f // it's an object). // // Usage: (ensures `events` has these events in any order, with the right event type) -// JSONCheckOff("events", []interface{}{"$foo:bar", "$baz:quuz"}, func(r gjson.Result) interface{} { -// return r.Get("event_id").Str -// }, func(eventID interface{}, eventBody gjson.Result) error { -// if eventBody.Get("type").Str != "m.room.message" { -// return fmt.Errorf("expected event to be 'm.room.message'") -// } -// }) +// +// JSONCheckOff("events", []interface{}{"$foo:bar", "$baz:quuz"}, func(r gjson.Result) interface{} { +// return r.Get("event_id").Str +// }, func(eventID interface{}, eventBody gjson.Result) error { +// if eventBody.Get("type").Str != "m.room.message" { +// return fmt.Errorf("expected event to be 'm.room.message'") +// } +// }) func JSONCheckOff(wantKey string, wantItems []interface{}, mapper func(gjson.Result) interface{}, fn func(interface{}, gjson.Result) error) JSON { return jsonCheckOffInternal(wantKey, wantItems, false, mapper, fn) } @@ -213,22 +226,19 @@ func JSONCheckOff(wantKey string, wantItems []interface{}, mapper func(gjson.Res // JSONArrayEach returns a matcher which will check that `wantKey` is an array then loops over each // item calling `fn`. If `fn` returns an error, iterating stops and an error is returned. func JSONArrayEach(wantKey string, fn func(gjson.Result) error) JSON { - return func(body []byte) error { - var res gjson.Result - if wantKey == "" { - res = gjson.ParseBytes(body) - } else { - res = gjson.GetBytes(body, wantKey) + return func(body gjson.Result) error { + if wantKey != "" { + body = body.Get(wantKey) } - if !res.Exists() { + if !body.Exists() { return fmt.Errorf("missing key '%s'", wantKey) } - if !res.IsArray() { + if !body.IsArray() { return fmt.Errorf("key '%s' is not an array", wantKey) } var err error - res.ForEach(func(_, val gjson.Result) bool { + body.ForEach(func(_, val gjson.Result) bool { err = fn(val) return err == nil }) @@ -239,8 +249,8 @@ func JSONArrayEach(wantKey string, fn func(gjson.Result) error) JSON { // JSONMapEach returns a matcher which will check that `wantKey` is a map then loops over each // item calling `fn`. If `fn` returns an error, iterating stops and an error is returned. func JSONMapEach(wantKey string, fn func(k, v gjson.Result) error) JSON { - return func(body []byte) error { - res := gjson.GetBytes(body, wantKey) + return func(body gjson.Result) error { + res := body.Get(wantKey) if !res.Exists() { return fmt.Errorf("missing key '%s'", wantKey) } @@ -256,10 +266,11 @@ func JSONMapEach(wantKey string, fn func(k, v gjson.Result) error) JSON { } } +// EXPERIMENTAL // AnyOf takes 1 or more `checkers`, and builds a new checker which accepts a given // json body iff it's accepted by at least one of the original `checkers`. func AnyOf(checkers ...JSON) JSON { - return func(body []byte) error { + return func(body gjson.Result) error { if len(checkers) == 0 { return fmt.Errorf("must provide at least one checker to AnyOf") } @@ -281,3 +292,15 @@ func AnyOf(checkers ...JSON) JSON { return fmt.Errorf(builder.String()) } } + +// jsonDeepEqual compares raw json with a json-serializable value, seeing if they're equal. +// It forces `gotJson` through a JSON parser to ensure keys/whitespace are identical to the marshalled form of `wantValue`. +func jsonDeepEqual(gotJson []byte, wantValue interface{}) bool { + // marshal what the test gave us + wantBytes, _ := json.Marshal(wantValue) + // re-marshal what the network gave us to acount for key ordering + var gotVal interface{} + _ = json.Unmarshal(gotJson, &gotVal) + gotBytes, _ := json.Marshal(gotVal) + return bytes.Equal(gotBytes, wantBytes) +} diff --git a/internal/must/must.go b/must/must.go similarity index 61% rename from internal/must/must.go rename to must/must.go index 4b218c00..5ba0a84a 100644 --- a/internal/must/must.go +++ b/must/must.go @@ -2,19 +2,21 @@ package must import ( + "bytes" "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "strings" "testing" "github.com/tidwall/gjson" + "golang.org/x/exp/slices" "github.com/matrix-org/gomatrixserverlib/fclient" - "github.com/matrix-org/complement/internal/match" + "github.com/matrix-org/complement/client" + "github.com/matrix-org/complement/match" ) // NotError will ensure `err` is nil else terminate the test with `msg`. @@ -25,23 +27,25 @@ func NotError(t *testing.T, msg string, err error) { } } +// EXPERIMENTAL // ParseJSON will ensure that the HTTP request/response body is valid JSON, then return the body, else terminate the test. -func ParseJSON(t *testing.T, b io.ReadCloser) []byte { +func ParseJSON(t *testing.T, b io.ReadCloser) gjson.Result { t.Helper() - body, err := ioutil.ReadAll(b) + body, err := io.ReadAll(b) if err != nil { t.Fatalf("MustParseJSON: reading body returned %s", err) } if !gjson.ValidBytes(body) { t.Fatalf("MustParseJSON: not valid JSON") } - return body + return gjson.ParseBytes(body) } +// EXPERIMENTAL // MatchRequest consumes the HTTP request and performs HTTP-level assertions on it. Returns the raw response body. func MatchRequest(t *testing.T, req *http.Request, m match.HTTPRequest) []byte { t.Helper() - body, err := ioutil.ReadAll(req.Body) + body, err := io.ReadAll(req.Body) if err != nil { t.Fatalf("MatchRequest: Failed to read request body: %s", err) } @@ -59,8 +63,9 @@ func MatchRequest(t *testing.T, req *http.Request, m match.HTTPRequest) []byte { if !gjson.ValidBytes(body) { t.Fatalf("MatchRequest request body is not valid JSON - %s", contextStr) } + parsedBody := gjson.ParseBytes(body) for _, jm := range m.JSON { - if err = jm(body); err != nil { + if err = jm(parsedBody); err != nil { t.Fatalf("MatchRequest %s - %s", err, contextStr) } } @@ -68,6 +73,7 @@ func MatchRequest(t *testing.T, req *http.Request, m match.HTTPRequest) []byte { return body } +// EXPERIMENTAL // MatchSuccess consumes the HTTP response and fails if the response is non-2xx. func MatchSuccess(t *testing.T, res *http.Response) { if res.StatusCode < 200 || res.StatusCode > 299 { @@ -75,6 +81,7 @@ func MatchSuccess(t *testing.T, res *http.Response) { } } +// EXPERIMENTAL // MatchFailure consumes the HTTP response and fails if the response is 2xx. func MatchFailure(t *testing.T, res *http.Response) { if res.StatusCode >= 200 && res.StatusCode <= 299 { @@ -82,10 +89,11 @@ func MatchFailure(t *testing.T, res *http.Response) { } } +// EXPERIMENTAL // MatchResponse consumes the HTTP response and performs HTTP-level assertions on it. Returns the raw response body. func MatchResponse(t *testing.T, res *http.Response, m match.HTTPResponse) []byte { t.Helper() - body, err := ioutil.ReadAll(res.Body) + body, err := io.ReadAll(res.Body) if err != nil { t.Fatalf("MatchResponse: Failed to read response body: %s", err) } @@ -108,8 +116,9 @@ func MatchResponse(t *testing.T, res *http.Response, m match.HTTPResponse) []byt if !gjson.ValidBytes(body) { t.Fatalf("MatchResponse response body is not valid JSON - %s", contextStr) } + parsedBody := gjson.ParseBytes(body) for _, jm := range m.JSON { - if err = jm(body); err != nil { + if err = jm(parsedBody); err != nil { t.Fatalf("MatchResponse %s - %s", err, contextStr) } } @@ -125,27 +134,23 @@ func MatchFederationRequest(t *testing.T, fedReq *fclient.FederationRequest, mat t.Fatalf("MatchFederationRequest content is not valid JSON - %s", fedReq.RequestURI()) } + parsedContent := gjson.ParseBytes(content) for _, jm := range matchers { - if err := jm(content); err != nil { + if err := jm(parsedContent); err != nil { t.Fatalf("MatchFederationRequest %s - %s", err, fedReq.RequestURI()) } } } +// EXPERIMENTAL // MatchGJSON performs JSON assertions on a gjson.Result object. func MatchGJSON(t *testing.T, jsonResult gjson.Result, matchers ...match.JSON) { t.Helper() - MatchJSON(t, jsonResult.Raw, matchers...) -} - -// MatchJSON performs JSON assertions on a raw JSON string. -func MatchJSON(t *testing.T, json string, matchers ...match.JSON) { - t.Helper() - - MatchJSONBytes(t, []byte(json), matchers...) + MatchJSONBytes(t, []byte(jsonResult.Raw), matchers...) } +// EXPERIMENTAL // MatchJSONBytes performs JSON assertions on a raw json byte slice. func MatchJSONBytes(t *testing.T, rawJson []byte, matchers ...match.JSON) { t.Helper() @@ -154,29 +159,33 @@ func MatchJSONBytes(t *testing.T, rawJson []byte, matchers ...match.JSON) { t.Fatalf("MatchJSONBytes: rawJson is not valid JSON") } + body := gjson.ParseBytes(rawJson) for _, jm := range matchers { - if err := jm(rawJson); err != nil { - t.Fatalf("MatchJSONBytes %s", err) + if err := jm(body); err != nil { + t.Fatalf("MatchJSONBytes %s with input = %v", err, string(rawJson)) } } } -// EqualStr ensures that got==want else logs an error. -func EqualStr(t *testing.T, got, want, msg string) { +// Equal ensures that got==want else logs an error. +// The 'msg' is displayed with the error to provide extra context. +func Equal[V comparable](t *testing.T, got, want V, msg string) { t.Helper() if got != want { - t.Errorf("EqualStr %s: got '%s' want '%s'", msg, got, want) + t.Errorf("Equal %s: got '%v' want '%v'", msg, got, want) } } -// NotEqualStr ensures that got!=want else logs an error. -func NotEqualStr(t *testing.T, got, want, msg string) { +// NotEqual ensures that got!=want else logs an error. +// The 'msg' is displayed with the error to provide extra context. +func NotEqual[V comparable](t *testing.T, got, want V, msg string) { t.Helper() if got == want { - t.Errorf("NotEqualStr %s: got '%s', but didn't want it", msg, got) + t.Errorf("NotEqual %s: got '%v', want '%v'", msg, got, want) } } +// EXPERIMENTAL // StartWithStr ensures that got starts with wantPrefix else logs an error. func StartWithStr(t *testing.T, got, wantPrefix, msg string) { t.Helper() @@ -187,31 +196,75 @@ func StartWithStr(t *testing.T, got, wantPrefix, msg string) { // GetJSONFieldStr extracts the string value under `wantKey` or fails the test. // The format of `wantKey` is specified at https://godoc.org/github.com/tidwall/gjson#Get -func GetJSONFieldStr(t *testing.T, body []byte, wantKey string) string { +func GetJSONFieldStr(t *testing.T, body gjson.Result, wantKey string) string { t.Helper() - res := gjson.GetBytes(body, wantKey) + res := body.Get(wantKey) if res.Index == 0 { - t.Fatalf("JSONFieldStr: key '%s' missing from %s", wantKey, string(body)) + t.Fatalf("JSONFieldStr: key '%s' missing from %s", wantKey, body.Raw) } if res.Str == "" { - t.Fatalf("JSONFieldStr: key '%s' is not a string, body: %s", wantKey, string(body)) + t.Fatalf("JSONFieldStr: key '%s' is not a string, body: %s", wantKey, body.Raw) } return res.Str } -// HaveInOrder checks that the two string slices match exactly, failing the test on mismatches or omissions. -func HaveInOrder(t *testing.T, gots []string, wants []string) { +// EXPERIMENTAL +// HaveInOrder checks that the two slices match exactly, failing the test on mismatches or omissions. +func HaveInOrder[V comparable](t *testing.T, gots []V, wants []V) { t.Helper() if len(gots) != len(wants) { - t.Fatalf("HaveEventsInOrder: length mismatch, got %v want %v", gots, wants) + t.Fatalf("HaveInOrder: length mismatch, got %v want %v", gots, wants) } for i := range gots { if gots[i] != wants[i] { - t.Errorf("HaveEventsInOrder: index %d got %s want %s", i, gots[i], wants[i]) + t.Errorf("HaveInOrder: index %d got %v want %v", i, gots[i], wants[i]) + } + } +} + +// EXPERIMENTAL +// ContainSubset checks that every item in smaller is in larger, failing the test if at least 1 item isn't. Ignores extra elements +// in larger. Ignores ordering. +func ContainSubset[V comparable](t *testing.T, larger []V, smaller []V) { + t.Helper() + if len(larger) < len(smaller) { + t.Fatalf("ContainSubset: length mismatch, larger=%d smaller=%d", len(larger), len(smaller)) + } + for i, item := range smaller { + if !slices.Contains(larger, item) { + t.Fatalf("ContainSubset: element not found in larger set: smaller[%d] (%v) larger=%v", i, item, larger) } } } +// EXPERIMENTAL +// NotContainSubset checks that every item in smaller is NOT in larger, failing the test if at least 1 item is. Ignores extra elements +// in larger. Ignores ordering. +func NotContainSubset[V comparable](t *testing.T, larger []V, smaller []V) { + t.Helper() + if len(larger) < len(smaller) { + t.Fatalf("NotContainSubset: length mismatch, larger=%d smaller=%d", len(larger), len(smaller)) + } + for i, item := range smaller { + if slices.Contains(larger, item) { + t.Fatalf("NotContainSubset: element found in larger set: smaller[%d] (%v)", i, item) + } + } +} + +// EXPERIMENTAL +// GetTimelineEventIDs returns the timeline event IDs in the sync response for the given room ID. If the room is missing +// this returns a 0 element slice. +func GetTimelineEventIDs(t *testing.T, topLevelSyncJSON gjson.Result, roomID string) []string { + timeline := topLevelSyncJSON.Get(fmt.Sprintf("rooms.join.%s.timeline.events", client.GjsonEscape(roomID))).Array() + eventIDs := make([]string, len(timeline)) + for i := range timeline { + eventIDs[i] = timeline[i].Get("event_id").Str + } + return eventIDs +} + +// EXPERIMENTAL // CheckOffAll checks that a list contains exactly the given items, in any order. // // if an item is not present, the test is failed. @@ -225,6 +278,7 @@ func CheckOffAll(t *testing.T, items []interface{}, wantItems []interface{}) { } } +// EXPERIMENTAL // CheckOffAllAllowUnwanted checks that a list contains all of the given items, in any order. // The updated list with the matched items removed from it is returned. // @@ -238,16 +292,17 @@ func CheckOffAllAllowUnwanted(t *testing.T, items []interface{}, wantItems []int return items } +// EXPERIMENTAL // CheckOff an item from the list. If the item is not present the test is failed. // The updated list with the matched item removed from it is returned. Items are -// compared using match.JSONDeepEqual +// compared using JSON deep equal. func CheckOff(t *testing.T, items []interface{}, wantItem interface{}) []interface{} { t.Helper() // check off the item want := -1 for i, w := range items { wBytes, _ := json.Marshal(w) - if match.JSONDeepEqual(wBytes, wantItem) { + if jsonDeepEqual(wBytes, wantItem) { want = i break } @@ -260,3 +315,13 @@ func CheckOff(t *testing.T, items []interface{}, wantItem interface{}) []interfa items = append(items[:want], items[want+1:]...) return items } + +func jsonDeepEqual(gotJson []byte, wantValue interface{}) bool { + // marshal what the test gave us + wantBytes, _ := json.Marshal(wantValue) + // re-marshal what the network gave us to acount for key ordering + var gotVal interface{} + _ = json.Unmarshal(gotJson, &gotVal) + gotBytes, _ := json.Marshal(gotVal) + return bytes.Equal(gotBytes, wantBytes) +} diff --git a/tests/csapi/account_change_password_pushers_test.go b/tests/csapi/account_change_password_pushers_test.go index 6b75d579..e7ff0c94 100644 --- a/tests/csapi/account_change_password_pushers_test.go +++ b/tests/csapi/account_change_password_pushers_test.go @@ -8,8 +8,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/tidwall/gjson" ) diff --git a/tests/csapi/account_change_password_test.go b/tests/csapi/account_change_password_test.go index efdaeb3c..47e780f7 100644 --- a/tests/csapi/account_change_password_test.go +++ b/tests/csapi/account_change_password_test.go @@ -7,8 +7,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/docker" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/tidwall/gjson" ) diff --git a/tests/csapi/account_data_test.go b/tests/csapi/account_data_test.go index e79f5371..70680e14 100644 --- a/tests/csapi/account_data_test.go +++ b/tests/csapi/account_data_test.go @@ -4,8 +4,8 @@ import ( "testing" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func TestAddAccountData(t *testing.T) { diff --git a/tests/csapi/account_deactivate_test.go b/tests/csapi/account_deactivate_test.go index fc3033b0..494c68b8 100644 --- a/tests/csapi/account_deactivate_test.go +++ b/tests/csapi/account_deactivate_test.go @@ -8,8 +8,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func TestDeactivateAccount(t *testing.T) { diff --git a/tests/csapi/admin_test.go b/tests/csapi/admin_test.go index 5b89a406..6d7d475c 100644 --- a/tests/csapi/admin_test.go +++ b/tests/csapi/admin_test.go @@ -9,8 +9,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // Check if this homeserver supports Synapse-style admin registration. diff --git a/tests/csapi/apidoc_device_management_test.go b/tests/csapi/apidoc_device_management_test.go index 541f3541..80baa196 100644 --- a/tests/csapi/apidoc_device_management_test.go +++ b/tests/csapi/apidoc_device_management_test.go @@ -7,8 +7,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func TestDeviceManagement(t *testing.T) { diff --git a/tests/csapi/apidoc_login_test.go b/tests/csapi/apidoc_login_test.go index d8a2f65a..a6bc29b0 100644 --- a/tests/csapi/apidoc_login_test.go +++ b/tests/csapi/apidoc_login_test.go @@ -7,10 +7,10 @@ import ( "github.com/tidwall/gjson" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/client" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func TestLogin(t *testing.T) { @@ -145,9 +145,8 @@ func TestLogin(t *testing.T) { "password": "superuser" }`))) // extract access_token - body := must.ParseJSON(t, res.Body) + js := must.ParseJSON(t, res.Body) defer res.Body.Close() - js := gjson.ParseBytes(body) unauthedClient.UserID = js.Get("user_id").Str unauthedClient.AccessToken = js.Get("access_token").Str // check that we can successfully query /whoami diff --git a/tests/csapi/apidoc_logout_test.go b/tests/csapi/apidoc_logout_test.go index 9d883761..14925d11 100644 --- a/tests/csapi/apidoc_logout_test.go +++ b/tests/csapi/apidoc_logout_test.go @@ -8,8 +8,8 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func TestLogout(t *testing.T) { diff --git a/tests/csapi/apidoc_presence_test.go b/tests/csapi/apidoc_presence_test.go index ec64a9f4..85457d3f 100644 --- a/tests/csapi/apidoc_presence_test.go +++ b/tests/csapi/apidoc_presence_test.go @@ -12,8 +12,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func TestPresence(t *testing.T) { diff --git a/tests/csapi/apidoc_profile_avatar_url_test.go b/tests/csapi/apidoc_profile_avatar_url_test.go index 06e91cb9..f7bc3d75 100644 --- a/tests/csapi/apidoc_profile_avatar_url_test.go +++ b/tests/csapi/apidoc_profile_avatar_url_test.go @@ -5,8 +5,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func TestProfileAvatarURL(t *testing.T) { diff --git a/tests/csapi/apidoc_profile_displayname_test.go b/tests/csapi/apidoc_profile_displayname_test.go index 7762e7fb..3b224852 100644 --- a/tests/csapi/apidoc_profile_displayname_test.go +++ b/tests/csapi/apidoc_profile_displayname_test.go @@ -5,8 +5,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func TestProfileDisplayName(t *testing.T) { diff --git a/tests/csapi/apidoc_register_test.go b/tests/csapi/apidoc_register_test.go index 96f65ded..34de38b2 100644 --- a/tests/csapi/apidoc_register_test.go +++ b/tests/csapi/apidoc_register_test.go @@ -13,10 +13,10 @@ import ( "github.com/tidwall/gjson" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/client" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // TODO: @@ -312,9 +312,9 @@ func registerSharedSecret(t *testing.T, c *client.CSAPI, user, pass string, isAd return resp } body := must.ParseJSON(t, resp.Body) - nonce := gjson.GetBytes(body, "nonce") + nonce := body.Get("nonce") if !nonce.Exists() { - t.Fatalf("Malformed shared secret GET response: %s", string(body)) + t.Fatalf("Malformed shared secret GET response: %s", body.Raw) } mac := hmac.New(sha1.New, []byte(client.SharedSecret)) mac.Write([]byte(nonce.Str)) diff --git a/tests/csapi/apidoc_request_encoding_test.go b/tests/csapi/apidoc_request_encoding_test.go index 33534383..e180ab33 100644 --- a/tests/csapi/apidoc_request_encoding_test.go +++ b/tests/csapi/apidoc_request_encoding_test.go @@ -7,8 +7,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func TestRequestEncodingFails(t *testing.T) { diff --git a/tests/csapi/apidoc_room_alias_test.go b/tests/csapi/apidoc_room_alias_test.go index f157d6f0..dc134ee5 100644 --- a/tests/csapi/apidoc_room_alias_test.go +++ b/tests/csapi/apidoc_room_alias_test.go @@ -7,10 +7,10 @@ import ( "github.com/tidwall/gjson" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/client" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func setRoomAliasResp(t *testing.T, c *client.CSAPI, roomID, roomAlias string) *http.Response { @@ -120,8 +120,9 @@ func TestRoomAlias(t *testing.T) { return false } eventResBody := client.ParseJSON(t, res) + parsedEventResBody := gjson.ParseBytes(eventResBody) matcher := match.JSONKeyEqual("aliases", []interface{}{roomAlias}) - err := matcher(eventResBody) + err := matcher(parsedEventResBody) if err != nil { t.Log(err) return false diff --git a/tests/csapi/apidoc_room_create_test.go b/tests/csapi/apidoc_room_create_test.go index 6e7d76d6..eefb8305 100644 --- a/tests/csapi/apidoc_room_create_test.go +++ b/tests/csapi/apidoc_room_create_test.go @@ -7,8 +7,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func doCreateRoom(t *testing.T, c *client.CSAPI, json map[string]interface{}, match match.HTTPResponse) { diff --git a/tests/csapi/apidoc_room_forget_test.go b/tests/csapi/apidoc_room_forget_test.go index 197a4bf7..dcce4d1f 100644 --- a/tests/csapi/apidoc_room_forget_test.go +++ b/tests/csapi/apidoc_room_forget_test.go @@ -10,8 +10,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // These tests ensure that forgetting about rooms works as intended diff --git a/tests/csapi/apidoc_room_history_visibility_test.go b/tests/csapi/apidoc_room_history_visibility_test.go index e6ccd18d..1dfb3022 100644 --- a/tests/csapi/apidoc_room_history_visibility_test.go +++ b/tests/csapi/apidoc_room_history_visibility_test.go @@ -8,8 +8,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // TODO most of this can be refactored into data-driven tests diff --git a/tests/csapi/apidoc_room_members_test.go b/tests/csapi/apidoc_room_members_test.go index 79230f54..48223d1b 100644 --- a/tests/csapi/apidoc_room_members_test.go +++ b/tests/csapi/apidoc_room_members_test.go @@ -5,10 +5,10 @@ import ( "github.com/tidwall/gjson" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/client" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func TestRoomMembers(t *testing.T) { @@ -82,7 +82,7 @@ func TestRoomMembers(t *testing.T) { if ev.Get("type").Str != "m.room.member" || ev.Get("state_key").Str != bob.UserID { return false } - must.EqualStr(t, ev.Get("content").Get("membership").Str, "join", "Bob failed to join the room") + must.Equal(t, ev.Get("content").Get("membership").Str, "join", "Bob failed to join the room") return true }, )) diff --git a/tests/csapi/apidoc_room_state_test.go b/tests/csapi/apidoc_room_state_test.go index 06b7dac2..af33f6cb 100644 --- a/tests/csapi/apidoc_room_state_test.go +++ b/tests/csapi/apidoc_room_state_test.go @@ -10,8 +10,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func TestRoomState(t *testing.T) { diff --git a/tests/csapi/apidoc_search_test.go b/tests/csapi/apidoc_search_test.go index a2945e60..f7603301 100644 --- a/tests/csapi/apidoc_search_test.go +++ b/tests/csapi/apidoc_search_test.go @@ -9,10 +9,10 @@ import ( "github.com/matrix-org/util" "github.com/tidwall/gjson" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/client" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // Note: In contrast to Sytest, we define a filter.rooms on each search request, this is to mimic @@ -263,7 +263,7 @@ func TestSearch(t *testing.T) { match.JSONKeyEqual("result.content.body", expectedEvents[eventID.(string)]), } for _, jm := range matchers { - if err := jm([]byte(result.Raw)); err != nil { + if err := jm(result); err != nil { return err } } diff --git a/tests/csapi/apidoc_server_capabilities_test.go b/tests/csapi/apidoc_server_capabilities_test.go index b7e1024b..b0ea1620 100644 --- a/tests/csapi/apidoc_server_capabilities_test.go +++ b/tests/csapi/apidoc_server_capabilities_test.go @@ -5,8 +5,8 @@ import ( "testing" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func TestServerCapabilities(t *testing.T) { diff --git a/tests/csapi/apidoc_version_test.go b/tests/csapi/apidoc_version_test.go index ed756210..635ef318 100644 --- a/tests/csapi/apidoc_version_test.go +++ b/tests/csapi/apidoc_version_test.go @@ -8,8 +8,8 @@ import ( "github.com/tidwall/gjson" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // https://spec.matrix.org/v1.1/#specification-versions @@ -52,8 +52,8 @@ func TestVersionStructure(t *testing.T) { return nil }), // Check when unstable_features is present if it's an object - func(body []byte) error { - res := gjson.GetBytes(body, "unstable_features") + func(body gjson.Result) error { + res := body.Get("unstable_features") if !res.Exists() { return nil } diff --git a/tests/csapi/device_lists_test.go b/tests/csapi/device_lists_test.go index 8ffecb78..6c9eb00c 100644 --- a/tests/csapi/device_lists_test.go +++ b/tests/csapi/device_lists_test.go @@ -8,8 +8,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/docker" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/matrix-org/complement/runtime" "maunium.net/go/mautrix/crypto/olm" diff --git a/tests/csapi/e2e_key_backup_test.go b/tests/csapi/e2e_key_backup_test.go index fbf6c594..d61cf32f 100644 --- a/tests/csapi/e2e_key_backup_test.go +++ b/tests/csapi/e2e_key_backup_test.go @@ -4,12 +4,10 @@ import ( "fmt" "testing" - "github.com/tidwall/gjson" - - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/client" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) type backupKey struct { @@ -40,9 +38,9 @@ func TestE2EKeyBackupReplaceRoomKeyRules(t *testing.T) { })) defer res.Body.Close() body := must.ParseJSON(t, res.Body) - backupVersion := gjson.GetBytes(body, "version").Str + backupVersion := body.Get("version").Str if backupVersion == "" { - t.Fatalf("failed to get 'version' key from response: %s", string(body)) + t.Fatalf("failed to get 'version' key from response: %s", body.Raw) } testCases := []struct { diff --git a/tests/csapi/ignored_users_test.go b/tests/csapi/ignored_users_test.go index a1f9fe80..ee75290d 100644 --- a/tests/csapi/ignored_users_test.go +++ b/tests/csapi/ignored_users_test.go @@ -12,8 +12,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // The Spec says here diff --git a/tests/csapi/invalid_test.go b/tests/csapi/invalid_test.go index e3f4cd6e..80d14240 100644 --- a/tests/csapi/invalid_test.go +++ b/tests/csapi/invalid_test.go @@ -6,8 +6,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/matrix-org/complement/runtime" ) diff --git a/tests/csapi/keychanges_test.go b/tests/csapi/keychanges_test.go index 95f9c8af..0666c6c9 100644 --- a/tests/csapi/keychanges_test.go +++ b/tests/csapi/keychanges_test.go @@ -10,8 +10,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func TestKeyChangesLocal(t *testing.T) { diff --git a/tests/csapi/media_misc_test.go b/tests/csapi/media_misc_test.go index 61159da0..c244abfd 100644 --- a/tests/csapi/media_misc_test.go +++ b/tests/csapi/media_misc_test.go @@ -9,8 +9,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/data" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/matrix-org/complement/runtime" ) diff --git a/tests/csapi/power_levels_test.go b/tests/csapi/power_levels_test.go index dd24c8c5..772a5596 100644 --- a/tests/csapi/power_levels_test.go +++ b/tests/csapi/power_levels_test.go @@ -6,10 +6,10 @@ import ( "github.com/tidwall/gjson" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/client" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // This test ensures that an authorised (PL 100) user is able to modify the users_default value @@ -92,9 +92,9 @@ func TestPowerLevels(t *testing.T) { } }), - func(body []byte) error { - userDefault := int(gjson.GetBytes(body, "users_default").Num) - thisUser := int(gjson.GetBytes(body, "users."+client.GjsonEscape(alice.UserID)).Num) + func(body gjson.Result) error { + userDefault := int(body.Get("users_default").Num) + thisUser := int(body.Get("users." + client.GjsonEscape(alice.UserID)).Num) if thisUser > userDefault { return nil diff --git a/tests/csapi/push_test.go b/tests/csapi/push_test.go index 53e63b55..d8c8c33c 100644 --- a/tests/csapi/push_test.go +++ b/tests/csapi/push_test.go @@ -9,8 +9,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // sytest: Getting push rules doesn't corrupt the cache SYN-390 diff --git a/tests/csapi/room_ban_test.go b/tests/csapi/room_ban_test.go index 80e838eb..b64ba97f 100644 --- a/tests/csapi/room_ban_test.go +++ b/tests/csapi/room_ban_test.go @@ -5,8 +5,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // This is technically a tad different from the sytest, in that it doesnt try to ban a @random_dude:test, diff --git a/tests/csapi/room_kick_test.go b/tests/csapi/room_kick_test.go index 72957fe6..9fdc4a2a 100644 --- a/tests/csapi/room_kick_test.go +++ b/tests/csapi/room_kick_test.go @@ -5,8 +5,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // sytest: Users cannot kick users from a room they are not in diff --git a/tests/csapi/room_leave_test.go b/tests/csapi/room_leave_test.go index 2cd7870a..30d3ac6c 100644 --- a/tests/csapi/room_leave_test.go +++ b/tests/csapi/room_leave_test.go @@ -9,8 +9,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func TestLeftRoomFixture(t *testing.T) { diff --git a/tests/csapi/room_members_test.go b/tests/csapi/room_members_test.go index 0419955b..8958faaa 100644 --- a/tests/csapi/room_members_test.go +++ b/tests/csapi/room_members_test.go @@ -7,10 +7,10 @@ import ( "github.com/tidwall/gjson" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/client" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // Maps every object by extracting `type` and `state_key` into a "$type|$state_key" string. @@ -43,7 +43,7 @@ func TestGetRoomMembers(t *testing.T) { must.MatchResponse(t, resp, match.HTTPResponse{ JSON: []match.JSON{ match.JSONArrayEach("chunk.#.room_id", func(result gjson.Result) error { - must.EqualStr(t, result.Str, roomID, "unexpected roomID") + must.Equal(t, result.Str, roomID, "unexpected roomID") return nil }), match.JSONCheckOff("chunk", @@ -103,7 +103,7 @@ func TestGetRoomMembersAtPoint(t *testing.T) { must.MatchResponse(t, resp, match.HTTPResponse{ JSON: []match.JSON{ match.JSONArrayEach("chunk.#.room_id", func(result gjson.Result) error { - must.EqualStr(t, result.Str, roomID, "unexpected roomID") + must.Equal(t, result.Str, roomID, "unexpected roomID") return nil }), match.JSONCheckOff("chunk", @@ -150,7 +150,7 @@ func TestGetFilteredRoomMembers(t *testing.T) { must.MatchResponse(t, resp, match.HTTPResponse{ JSON: []match.JSON{ match.JSONArrayEach("chunk.#.room_id", func(result gjson.Result) error { - must.EqualStr(t, result.Str, roomID, "unexpected roomID") + must.Equal(t, result.Str, roomID, "unexpected roomID") return nil }), match.JSONCheckOff("chunk", @@ -175,7 +175,7 @@ func TestGetFilteredRoomMembers(t *testing.T) { must.MatchResponse(t, resp, match.HTTPResponse{ JSON: []match.JSON{ match.JSONArrayEach("chunk.#.room_id", func(result gjson.Result) error { - must.EqualStr(t, result.Str, roomID, "unexpected roomID") + must.Equal(t, result.Str, roomID, "unexpected roomID") return nil }), match.JSONCheckOff("chunk", @@ -200,7 +200,7 @@ func TestGetFilteredRoomMembers(t *testing.T) { must.MatchResponse(t, resp, match.HTTPResponse{ JSON: []match.JSON{ match.JSONArrayEach("chunk.#.room_id", func(result gjson.Result) error { - must.EqualStr(t, result.Str, roomID, "unexpected roomID") + must.Equal(t, result.Str, roomID, "unexpected roomID") return nil }), match.JSONCheckOff("chunk", diff --git a/tests/csapi/room_messages_relation_filter_test.go b/tests/csapi/room_messages_relation_filter_test.go index e64b0bf4..6d04cc86 100644 --- a/tests/csapi/room_messages_relation_filter_test.go +++ b/tests/csapi/room_messages_relation_filter_test.go @@ -12,8 +12,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/matrix-org/complement/runtime" ) diff --git a/tests/csapi/room_messages_test.go b/tests/csapi/room_messages_test.go index 8edf50c8..506a2657 100644 --- a/tests/csapi/room_messages_test.go +++ b/tests/csapi/room_messages_test.go @@ -10,8 +10,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/matrix-org/complement/runtime" ) diff --git a/tests/csapi/room_relations_test.go b/tests/csapi/room_relations_test.go index f2bc76b9..e5bcfd53 100644 --- a/tests/csapi/room_relations_test.go +++ b/tests/csapi/room_relations_test.go @@ -10,8 +10,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/matrix-org/complement/runtime" ) diff --git a/tests/csapi/room_threads_test.go b/tests/csapi/room_threads_test.go index b5938744..713b4081 100644 --- a/tests/csapi/room_threads_test.go +++ b/tests/csapi/room_threads_test.go @@ -8,8 +8,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/matrix-org/complement/runtime" ) diff --git a/tests/csapi/room_typing_test.go b/tests/csapi/room_typing_test.go index 0300b850..055188b8 100644 --- a/tests/csapi/room_typing_test.go +++ b/tests/csapi/room_typing_test.go @@ -3,12 +3,8 @@ package csapi_tests import ( "testing" - "github.com/tidwall/gjson" - - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/client" ) // sytest: PUT /rooms/:room_id/typing/:user_id sets typing notification @@ -24,50 +20,17 @@ func TestTyping(t *testing.T) { bob.JoinRoom(t, roomID, nil) token := bob.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, roomID)) - - alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "typing", alice.UserID}, client.WithJSONBody(t, map[string]interface{}{ - "typing": true, - "timeout": 10000, - })) + alice.SendTyping(t, roomID, true, 10000) // sytest: Typing notification sent to local room members t.Run("Typing notification sent to local room members", func(t *testing.T) { - var usersSeenTyping []interface{} - - bob.MustSyncUntil(t, client.SyncReq{Since: token}, client.SyncEphemeralHas(roomID, func(result gjson.Result) bool { - if result.Get("type").Str != "m.typing" { - return false - } - - var res = false - - for _, item := range result.Get("content").Get("user_ids").Array() { - usersSeenTyping = append(usersSeenTyping, item.Str) - - if item.Str == alice.UserID { - res = true - } - } - - return res - })) - - must.CheckOffAll(t, usersSeenTyping, []interface{}{alice.UserID}) + bob.MustSyncUntil(t, client.SyncReq{Since: token}, client.SyncUsersTyping(roomID, []string{alice.UserID})) }) // sytest: Typing can be explicitly stopped t.Run("Typing can be explicitly stopped", func(t *testing.T) { - alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "typing", alice.UserID}, client.WithJSONBody(t, map[string]interface{}{ - "typing": false, - })) - - bob.MustSyncUntil(t, client.SyncReq{Since: token}, client.SyncEphemeralHas(roomID, func(result gjson.Result) bool { - if result.Get("type").Str != "m.typing" { - return false - } - - return len(result.Get("content").Get("user_ids").Array()) == 0 - })) + alice.SendTyping(t, roomID, false, 0) + bob.MustSyncUntil(t, client.SyncReq{Since: token}, client.SyncUsersTyping(roomID, []string{})) }) } @@ -89,41 +52,13 @@ func TestLeakyTyping(t *testing.T) { _, charlieToken := charlie.MustSync(t, client.SyncReq{TimeoutMillis: "0"}) // Alice types in that room. Bob should see her typing. - alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "typing", alice.UserID}, client.WithJSONBody(t, map[string]interface{}{ - "typing": true, - "timeout": 10000, - })) - - bob.MustSyncUntil(t, client.SyncReq{Since: bobToken}, client.SyncEphemeralHas(roomID, func(result gjson.Result) bool { - if result.Get("type").Str != "m.typing" { - return false - } - - err := match.JSONCheckOff("content.user_ids", []interface{}{ - alice.UserID, - }, func(result gjson.Result) interface{} { - return result.Str - }, nil)([]byte(result.Raw)) - - return err == nil - })) - - // Charlie is not in the room, so should not see Alice typing. - res, _ := charlie.MustSync(t, client.SyncReq{TimeoutMillis: "2000", Since: charlieToken}) - - err := client.SyncEphemeralHas(roomID, func(result gjson.Result) bool { - if result.Get("type").Str != "m.typing" { - return false - } - for _, item := range result.Get("content").Get("user_ids").Array() { - if item.Str == charlie.UserID { - return true - } - } - return false - })(charlie.UserID, res) - - if err == nil { - t.Fatalf("Received unexpected typing notification: %s", res.Raw) + alice.SendTyping(t, roomID, true, 10000) + + bob.MustSyncUntil(t, client.SyncReq{Since: bobToken}, client.SyncUsersTyping(roomID, []string{alice.UserID})) + + // Charlie is not in the room, so should not see Alice typing, or anything from that room at all. + res, _ := charlie.MustSync(t, client.SyncReq{TimeoutMillis: "1000", Since: charlieToken}) + if res.Get("rooms.join." + client.GjsonEscape(roomID)).Exists() { + t.Fatalf("Received unexpected room: %s", res.Raw) } } diff --git a/tests/csapi/rooms_invite_test.go b/tests/csapi/rooms_invite_test.go index dd33c39c..99840acf 100644 --- a/tests/csapi/rooms_invite_test.go +++ b/tests/csapi/rooms_invite_test.go @@ -6,8 +6,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/tidwall/gjson" ) diff --git a/tests/csapi/rooms_state_test.go b/tests/csapi/rooms_state_test.go index 81e12961..0d9c9d90 100644 --- a/tests/csapi/rooms_state_test.go +++ b/tests/csapi/rooms_state_test.go @@ -9,9 +9,9 @@ import ( "github.com/tidwall/gjson" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/client" + "github.com/matrix-org/complement/must" ) func TestRoomCreationReportsEventsToMyself(t *testing.T) { @@ -32,8 +32,8 @@ func TestRoomCreationReportsEventsToMyself(t *testing.T) { if ev.Get("type").Str != "m.room.create" { return false } - must.EqualStr(t, ev.Get("sender").Str, userID, "wrong sender") - must.EqualStr(t, ev.Get("content").Get("creator").Str, userID, "wrong content.creator") + must.Equal(t, ev.Get("sender").Str, userID, "wrong sender") + must.Equal(t, ev.Get("content").Get("creator").Str, userID, "wrong content.creator") return true })) }) @@ -46,9 +46,9 @@ func TestRoomCreationReportsEventsToMyself(t *testing.T) { if ev.Get("type").Str != "m.room.member" { return false } - must.EqualStr(t, ev.Get("sender").Str, userID, "wrong sender") - must.EqualStr(t, ev.Get("state_key").Str, userID, "wrong state_key") - must.EqualStr(t, ev.Get("content").Get("membership").Str, "join", "wrong content.membership") + must.Equal(t, ev.Get("sender").Str, userID, "wrong sender") + must.Equal(t, ev.Get("state_key").Str, userID, "wrong state_key") + must.Equal(t, ev.Get("content").Get("membership").Str, "join", "wrong content.membership") return true })) }) @@ -74,8 +74,8 @@ func TestRoomCreationReportsEventsToMyself(t *testing.T) { if !ev.Get("state_key").Exists() { return false } - must.EqualStr(t, ev.Get("sender").Str, userID, "wrong sender") - must.EqualStr(t, ev.Get("content").Get("topic").Str, roomTopic, "wrong content.topic") + must.Equal(t, ev.Get("sender").Str, userID, "wrong sender") + must.Equal(t, ev.Get("content").Get("topic").Str, roomTopic, "wrong content.topic") return true })) }) @@ -136,8 +136,7 @@ func TestRoomCreationReportsEventsToMyself(t *testing.T) { func getEventIdForState(t *testing.T, client *client.CSAPI, roomID, evType, stateKey string) *string { res := client.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state"}) - jsonBody := must.ParseJSON(t, res.Body) - result := gjson.ParseBytes(jsonBody) + result := must.ParseJSON(t, res.Body) for _, ev := range result.Array() { if ev.Get("type").Str == evType && ev.Get("state_key").Str == stateKey { diff --git a/tests/csapi/sync_filter_test.go b/tests/csapi/sync_filter_test.go index 42a02bf3..de25a87b 100644 --- a/tests/csapi/sync_filter_test.go +++ b/tests/csapi/sync_filter_test.go @@ -8,8 +8,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func TestSyncFilter(t *testing.T) { diff --git a/tests/csapi/txnid_test.go b/tests/csapi/txnid_test.go index 82d71934..340a7fab 100644 --- a/tests/csapi/txnid_test.go +++ b/tests/csapi/txnid_test.go @@ -4,9 +4,9 @@ import ( "fmt" "testing" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/client" + "github.com/matrix-org/complement/must" "github.com/matrix-org/complement/runtime" "github.com/tidwall/gjson" ) @@ -44,7 +44,7 @@ func TestTxnInEvent(t *testing.T) { t.Fatalf("Event did not have a 'unsigned.transaction_id' on the GET /rooms/%s/event/%s response", roomID, eventID) } - must.EqualStr(t, unsignedTxnId.Str, txnId, fmt.Sprintf("Event had an incorrect 'unsigned.transaction_id' on GET /rooms/%s/event/%s response", eventID, roomID)) + must.Equal(t, unsignedTxnId.Str, txnId, fmt.Sprintf("Event had an incorrect 'unsigned.transaction_id' on GET /rooms/%s/event/%s response", eventID, roomID)) } func mustHaveTransactionIDForEvent(t *testing.T, roomID, eventID, expectedTxnId string) client.SyncCheckOpt { @@ -55,7 +55,7 @@ func mustHaveTransactionIDForEvent(t *testing.T, roomID, eventID, expectedTxnId t.Fatalf("Event %s in room %s should have a 'unsigned.transaction_id', but it did not", eventID, roomID) } - must.EqualStr(t, unsignedTxnId.Str, expectedTxnId, fmt.Sprintf("Event %s in room %s had an incorrect 'unsigned.transaction_id'", eventID, roomID)) + must.Equal(t, unsignedTxnId.Str, expectedTxnId, fmt.Sprintf("Event %s in room %s had an incorrect 'unsigned.transaction_id'", eventID, roomID)) return true } @@ -96,7 +96,7 @@ func TestTxnScopeOnLocalEcho(t *testing.T) { // Create a second client, inheriting the first device ID. c2 := deployment.Client(t, "hs1", "") c2.UserID, c2.AccessToken, c2.DeviceID = c2.LoginUser(t, "alice", "password", client.WithDeviceID(c1.DeviceID)) - must.EqualStr(t, c1.DeviceID, c2.DeviceID, "Device ID should be the same") + must.Equal(t, c1.DeviceID, c2.DeviceID, "Device ID should be the same") // When syncing, we should find the event and it should have the same transaction ID on the second client. c2.MustSyncUntil(t, client.SyncReq{}, mustHaveTransactionIDForEvent(t, roomID, eventID, txnId)) @@ -133,13 +133,13 @@ func TestTxnIdempotencyScopedToDevice(t *testing.T) { // Create a second client, inheriting the first device ID. c2 := deployment.Client(t, "hs1", "") c2.UserID, c2.AccessToken, c2.DeviceID = c2.LoginUser(t, "alice", "password", client.WithDeviceID(c1.DeviceID)) - must.EqualStr(t, c1.DeviceID, c2.DeviceID, "Device ID should be the same") + must.Equal(t, c1.DeviceID, c2.DeviceID, "Device ID should be the same") // send another event with the same txnId via the second client eventID2 := c2.Unsafe_SendEventUnsyncedWithTxnID(t, roomID, event, txnId) // the two events should have the same event IDs as they came from the same device - must.EqualStr(t, eventID2, eventID1, "Expected eventID1 and eventID2 to be the same from two clients sharing the same device ID") + must.Equal(t, eventID2, eventID1, "Expected eventID1 and eventID2 to be the same from two clients sharing the same device ID") } // TestTxnIdempotency tests that PUT requests idempotency follows required semantics @@ -183,17 +183,17 @@ func TestTxnIdempotency(t *testing.T) { // we send the identical event again and should get back the same event ID eventID2 := c1.Unsafe_SendEventUnsyncedWithTxnID(t, roomID1, event1, txnId) - must.EqualStr(t, eventID2, eventID1, "Expected eventID1 and eventID2 to be the same, but they were not") + must.Equal(t, eventID2, eventID1, "Expected eventID1 and eventID2 to be the same, but they were not") // even if we change the content we should still get back the same event ID as transaction ID is the same eventID3 := c1.Unsafe_SendEventUnsyncedWithTxnID(t, roomID1, event2, txnId) - must.EqualStr(t, eventID3, eventID1, "Expected eventID3 and eventID2 to be the same even with different content, but they were not") + must.Equal(t, eventID3, eventID1, "Expected eventID3 and eventID2 to be the same even with different content, but they were not") // if we change the room ID we should be able to use the same transaction ID eventID4 := c1.Unsafe_SendEventUnsyncedWithTxnID(t, roomID2, event1, txnId) - must.NotEqualStr(t, eventID4, eventID3, "Expected eventID4 and eventID3 to be different, but they were not") + must.NotEqual(t, eventID4, eventID3, "Expected eventID4 and eventID3 to be different, but they were not") } // TestTxnIdWithRefreshToken tests that when a client refreshes its access token, @@ -242,5 +242,5 @@ func TestTxnIdWithRefreshToken(t *testing.T) { }, txnId) // The event should have been deduplicated and we should get back the same event ID - must.EqualStr(t, eventID2, eventID1, "Expected eventID1 and eventID2 to be the same from a client using a refresh token") + must.Equal(t, eventID2, eventID1, "Expected eventID1 and eventID2 to be the same from a client using a refresh token") } diff --git a/tests/csapi/upload_keys_test.go b/tests/csapi/upload_keys_test.go index 362be943..4d0775a9 100644 --- a/tests/csapi/upload_keys_test.go +++ b/tests/csapi/upload_keys_test.go @@ -10,8 +10,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/matrix-org/complement/runtime" ) diff --git a/tests/csapi/url_preview_test.go b/tests/csapi/url_preview_test.go index a32a18ce..f9bd85f9 100644 --- a/tests/csapi/url_preview_test.go +++ b/tests/csapi/url_preview_test.go @@ -10,12 +10,12 @@ import ( "github.com/gorilla/mux" "github.com/tidwall/gjson" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/data" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" "github.com/matrix-org/complement/internal/web" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/matrix-org/complement/runtime" ) @@ -80,8 +80,8 @@ func TestUrlPreview(t *testing.T) { match.JSONKeyEqual(e("matrix:image:size"), 2239.0), match.JSONKeyEqual(e("og:image:height"), 129.0), match.JSONKeyEqual(e("og:image:width"), 279.0), - func(body []byte) error { - res := gjson.GetBytes(body, e("og:image")) + func(body gjson.Result) error { + res := body.Get(e("og:image")) if !res.Exists() { return fmt.Errorf("can not find key og:image") } diff --git a/tests/csapi/user_directory_display_names_test.go b/tests/csapi/user_directory_display_names_test.go index 90730985..ba626a0c 100644 --- a/tests/csapi/user_directory_display_names_test.go +++ b/tests/csapi/user_directory_display_names_test.go @@ -9,8 +9,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) const aliceUserID = "@alice:hs1" diff --git a/tests/csapi/user_query_keys_test.go b/tests/csapi/user_query_keys_test.go index 30452e18..8529311d 100644 --- a/tests/csapi/user_query_keys_test.go +++ b/tests/csapi/user_query_keys_test.go @@ -5,8 +5,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // Endpoint: https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-keys-query diff --git a/tests/direct_messaging_test.go b/tests/direct_messaging_test.go index 77b42c49..2693accb 100644 --- a/tests/direct_messaging_test.go +++ b/tests/direct_messaging_test.go @@ -6,11 +6,11 @@ import ( "testing" "time" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/federation" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/matrix-org/gomatrixserverlib/fclient" "github.com/matrix-org/gomatrixserverlib/spec" @@ -42,15 +42,7 @@ func TestWriteMDirectAccountData(t *testing.T) { if r.Get("type").Str != "m.direct" { return false } - content := r.Get("content") - rooms := content.Get(bob.UserID) - if !rooms.Exists() || !rooms.IsArray() { - t.Errorf("m.direct event missing rooms array for user %s", bob.UserID) - return false - } - if rooms.Array()[0].Str != roomID { - t.Errorf("m.direct room for %s mismatch: got %v want %v", bob.UserID, rooms.Str, roomID) - } + must.MatchGJSON(t, r, match.JSONKeyEqual("content."+client.GjsonEscape(bob.UserID), []string{roomID})) return true } t.Logf("%s: global account data set; syncing until it arrives", time.Now()) // synapse#13334 diff --git a/tests/federation_acl_test.go b/tests/federation_acl_test.go index 886c52ce..74f265a3 100644 --- a/tests/federation_acl_test.go +++ b/tests/federation_acl_test.go @@ -1,13 +1,12 @@ package tests import ( - "fmt" "testing" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/client" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/matrix-org/complement/runtime" ) @@ -120,30 +119,17 @@ func TestACLs(t *testing.T) { syncResp, _ := user.MustSync(t, client.SyncReq{}) // we don't expect eventID (blocked) to be in the sync response - events := syncResp.Get(fmt.Sprintf("rooms.join.%s.timeline.events", client.GjsonEscape(roomID))).Array() - for _, ev := range events { - if ev.Get("event_id").Str == eventID { - t.Fatalf("unexpected eventID from ACLed room: %s", eventID) - } - } + events := must.GetTimelineEventIDs(t, syncResp, roomID) + must.NotContainSubset(t, events, []string{eventID}) // also check that our sentinel event is present - var seenSentinelEvent bool - events = syncResp.Get(fmt.Sprintf("rooms.join.%s.timeline.events", client.GjsonEscape(sentinelRoom))).Array() - for _, ev := range events { - if ev.Get("event_id").Str == sentinelEventID { - seenSentinelEvent = true - break - } - } - - if !seenSentinelEvent { - t.Fatalf("expected to see sentinel event but didn't") - } + events = must.GetTimelineEventIDs(t, syncResp, sentinelRoom) + must.ContainSubset(t, events, []string{sentinelEventID}) // Validate the ACL event is actually in the rooms state res := user.Do(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.server_acl"}) must.MatchResponse(t, res, match.HTTPResponse{ + StatusCode: 200, JSON: []match.JSON{ match.JSONKeyEqual("allow", []string{"*"}), match.JSONKeyEqual("deny", []string{"hs2"}), diff --git a/tests/federation_event_auth_test.go b/tests/federation_event_auth_test.go index f4c75921..6404cadb 100644 --- a/tests/federation_event_auth_test.go +++ b/tests/federation_event_auth_test.go @@ -7,7 +7,7 @@ import ( "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/must" "github.com/matrix-org/gomatrixserverlib/spec" "github.com/matrix-org/gomatrixserverlib" @@ -92,16 +92,11 @@ func TestEventAuth(t *testing.T) { t.Fatalf("got %d valid auth events (%d total), wanted %d.\n%s\nwant: %s", len(gotAuthEvents), len(eventAuthResp.AuthEvents), len(wantAuthEventIDs), msg, wantAuthEventIDs) } // make sure all the events match - wantIDs := map[string]bool{} - for _, id := range wantAuthEventIDs { - wantIDs[id] = true - } - for _, e := range gotAuthEvents { - delete(wantIDs, e.EventID()) - } - if len(wantIDs) > 0 { - t.Errorf("missing events %v", wantIDs) + gotIDs := make([]string, len(gotAuthEvents)) + for i := range gotIDs { + gotIDs[i] = gotAuthEvents[i].EventID() } + must.ContainSubset(t, gotIDs, wantAuthEventIDs) } t.Run("returns auth events for the requested event", func(t *testing.T) { diff --git a/tests/federation_keys_test.go b/tests/federation_keys_test.go index 61605f71..785565d6 100644 --- a/tests/federation_keys_test.go +++ b/tests/federation_keys_test.go @@ -14,8 +14,8 @@ import ( "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/docker" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // TODO: @@ -56,13 +56,10 @@ func TestInboundFederationKeys(t *testing.T) { key := v.Get("key") - // Test key existence and string type - if !key.Exists() { - return fmt.Errorf("verify_keys: Key '%s' has no 'key' field", k.Str) - } - if key.Type != gjson.String { - return fmt.Errorf("verify_keys: Key '%s' has 'key' with unexpected type, expected String, got '%s'", k.Str, key.Type.String()) - } + must.MatchGJSON(t, v, + match.JSONKeyPresent("key"), + match.JSONKeyTypeEqual("key", gjson.String), + ) var keyBytes []byte keyBytes, err = base64.RawStdEncoding.DecodeString(key.Str) @@ -79,26 +76,18 @@ func TestInboundFederationKeys(t *testing.T) { return fmt.Errorf("old_verify_keys: Key '%s' has no 'ed25519:' prefix", k.Str) } - expiredTs := v.Get("expired_ts") + must.MatchGJSON(t, v, + match.JSONKeyPresent("expired_ts"), + match.JSONKeyTypeEqual("expired_ts", gjson.Number), + ) - // Test expired_ts existence and number type - if !expiredTs.Exists() { - return fmt.Errorf("old_verify_keys: Key '%s' has no 'expired_ts' field", k.Str) - } - if expiredTs.Type != gjson.Number { - return fmt.Errorf("old_verify_keys: Key '%s' has expired_ts with unexpected type, expected Number, got '%s'", k.Str, expiredTs.Type.String()) - } + must.MatchGJSON(t, v, + match.JSONKeyPresent("key"), + match.JSONKeyTypeEqual("key", gjson.String), + ) key := v.Get("key") - // Test key existence and string type - if !key.Exists() { - return fmt.Errorf("old_verify_keys: Key '%s' has no 'key' field", k.Str) - } - if key.Type != gjson.String { - return fmt.Errorf("old_verify_keys: Key '%s' has 'key' with unexpected type, expected String, got '%s'", k.Str, key.Type.String()) - } - var keyBytes []byte keyBytes, err = base64.RawStdEncoding.DecodeString(key.Str) if err != nil { @@ -193,7 +182,7 @@ func checkKeysAndSignatures(t *testing.T, body []byte, jsonObj gjson.Result, key // Test signatures for all verify_keys, these *have* to exist. for keyName, keyBytes := range keys { - sigBase64 := must.GetJSONFieldStr(t, body, fmt.Sprintf("signatures.hs1.%s", keyName)) + sigBase64 := must.GetJSONFieldStr(t, jsonObj, fmt.Sprintf("signatures.hs1.%s", keyName)) var sigBytes []byte sigBytes, err = base64.RawStdEncoding.DecodeString(sigBase64) diff --git a/tests/federation_query_profile_test.go b/tests/federation_query_profile_test.go index 739997be..db214255 100644 --- a/tests/federation_query_profile_test.go +++ b/tests/federation_query_profile_test.go @@ -12,8 +12,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // TODO: diff --git a/tests/federation_redaction_test.go b/tests/federation_redaction_test.go index 5531e3f0..00a86c87 100644 --- a/tests/federation_redaction_test.go +++ b/tests/federation_redaction_test.go @@ -6,6 +6,7 @@ import ( "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" + "github.com/matrix-org/complement/must" "github.com/matrix-org/complement/runtime" "github.com/matrix-org/gomatrixserverlib" ) @@ -31,9 +32,7 @@ func TestFederationRedactSendsWithoutEvent(t *testing.T) { func(ev gomatrixserverlib.PDU) { defer waiter.Finish() - if ev.Type() != wantEventType { - t.Errorf("Wrong event type, got %s want %s", ev.Type(), wantEventType) - } + must.Equal(t, ev.Type(), wantEventType, "wrong event type") }, nil, ), @@ -89,8 +88,5 @@ func TestFederationRedactSendsWithoutEvent(t *testing.T) { } // check that the event id of the redaction sent by alice is the same as the redaction event in the room - if res != lastEvent.EventID() { - t.Fatalf("Incorrent event id %s, wanted %s.", res, lastEvent.EventID()) - } - + must.Equal(t, lastEvent.EventID(), res, "incorrect event id") } diff --git a/tests/federation_room_alias_test.go b/tests/federation_room_alias_test.go index d8ef6d28..6ad1e63b 100644 --- a/tests/federation_room_alias_test.go +++ b/tests/federation_room_alias_test.go @@ -5,8 +5,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // sytest: Remote room alias queries can handle Unicode diff --git a/tests/federation_room_ban_test.go b/tests/federation_room_ban_test.go index cb69078f..2295870c 100644 --- a/tests/federation_room_ban_test.go +++ b/tests/federation_room_ban_test.go @@ -3,16 +3,14 @@ package tests import ( "testing" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/runtime" + "github.com/matrix-org/complement/client" ) // Regression test for https://github.com/matrix-org/synapse/issues/1563 // Create a federation room. Bob bans Alice. Bob unbans Alice. Bob invites Alice (unbanning her). Ensure the invite is // received and can be accepted. func TestUnbanViaInvite(t *testing.T) { - runtime.SkipIf(t, runtime.Synapse) // FIXME: https://github.com/matrix-org/synapse/issues/1563 deployment := Deploy(t, b.BlueprintFederationOneToOneRoom) defer deployment.Destroy(t) diff --git a/tests/federation_room_event_auth_test.go b/tests/federation_room_event_auth_test.go index d85b07ac..923a53fe 100644 --- a/tests/federation_room_event_auth_test.go +++ b/tests/federation_room_event_auth_test.go @@ -20,7 +20,7 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/must" ) func TestInboundFederationRejectsEventsWithRejectedAuthEvents(t *testing.T) { diff --git a/tests/federation_room_get_missing_events_test.go b/tests/federation_room_get_missing_events_test.go index 966b8570..e93d0f70 100644 --- a/tests/federation_room_get_missing_events_test.go +++ b/tests/federation_room_get_missing_events_test.go @@ -14,11 +14,11 @@ import ( "github.com/matrix-org/util" "github.com/tidwall/gjson" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/federation" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // TODO: @@ -417,7 +417,7 @@ func TestInboundCanReturnMissingEvents(t *testing.T) { events := result.Events.UntrustedEvents(roomVersion) verifyMsgEvent := func(ev gomatrixserverlib.PDU) { - must.EqualStr(t, ev.Type(), "m.room.message", "not a message event") + must.Equal(t, ev.Type(), "m.room.message", "not a message event") // if the history vis is 'joined' or 'invite', we should get redacted // copies of the events before we joined. if visibility == gomatrixserverlib.HistoryVisibilityJoined || visibility == gomatrixserverlib.HistoryVisibilityInvited { @@ -434,20 +434,20 @@ func TestInboundCanReturnMissingEvents(t *testing.T) { } for i, ev := range events { - must.EqualStr(t, ev.RoomID().String(), roomID, "unexpected roomID") + must.Equal(t, ev.RoomID().String(), roomID, "unexpected roomID") switch i { case 0: - must.EqualStr(t, ev.Type(), "m.room.member", "not a membership event") - must.EqualStr(t, *ev.StateKey(), alice.UserID, "unexpected creator") + must.Equal(t, ev.Type(), "m.room.member", "not a membership event") + must.Equal(t, *ev.StateKey(), alice.UserID, "unexpected creator") case 1: - must.EqualStr(t, ev.Type(), spec.MRoomPowerLevels, "not a powerlevel event") + must.Equal(t, ev.Type(), spec.MRoomPowerLevels, "not a powerlevel event") case 2: - must.EqualStr(t, ev.Type(), spec.MRoomJoinRules, "not a join_rules event") + must.Equal(t, ev.Type(), spec.MRoomJoinRules, "not a join_rules event") case 3: - must.EqualStr(t, ev.Type(), spec.MRoomHistoryVisibility, "not a history_visiblity event") + must.Equal(t, ev.Type(), spec.MRoomHistoryVisibility, "not a history_visiblity event") case 4: if visibility != gomatrixserverlib.HistoryVisibilityShared { // shared -> shared no-ops - must.EqualStr(t, ev.Type(), spec.MRoomHistoryVisibility, "not a history_visiblity event") + must.Equal(t, ev.Type(), spec.MRoomHistoryVisibility, "not a history_visiblity event") } else { verifyMsgEvent(ev) } diff --git a/tests/federation_room_join_partial_state_test.go b/tests/federation_room_join_partial_state_test.go index d6f93631..8f83164d 100644 --- a/tests/federation_room_join_partial_state_test.go +++ b/tests/federation_room_join_partial_state_test.go @@ -30,12 +30,12 @@ import ( "github.com/matrix-org/gomatrixserverlib/fclient" "github.com/matrix-org/gomatrixserverlib/spec" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/docker" "github.com/matrix-org/complement/internal/federation" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) type server struct { @@ -357,7 +357,7 @@ func TestPartialStateJoin(t *testing.T) { return strings.Join([]string{result.Map()["type"].Str, result.Map()["state_key"].Str}, "|") }, nil, ) - if err := matcher([]byte(roomRes.Raw)); err != nil { + if err := matcher(roomRes); err != nil { t.Errorf("Did not find expected state events in /sync response: %s", err) } } @@ -527,16 +527,7 @@ func TestPartialStateJoin(t *testing.T) { client.SyncReq{ Filter: buildLazyLoadingSyncFilter(nil), }, - client.SyncEphemeralHas(serverRoom.RoomID, func(result gjson.Result) bool { - if result.Get("type").Str != "m.typing" { - return false - } - user_ids := result.Get("content.user_ids").Array() - if len(user_ids) != 1 { - return false - } - return user_ids[0].Str == derekUserId - }), + client.SyncUsersTyping(serverRoom.RoomID, []string{derekUserId}), ) // Alice should still be able to see incoming PDUs in the room during @@ -568,10 +559,7 @@ func TestPartialStateJoin(t *testing.T) { Filter: buildLazyLoadingSyncFilter(nil), Since: aliceNextBatch, }, - client.SyncEphemeralHas(serverRoom.RoomID, func(result gjson.Result) bool { - return (result.Get("type").Str == "m.typing" && - result.Get("content.user_ids.#").Int() == 0) - }), + client.SyncUsersTyping(serverRoom.RoomID, []string{}), ) }) @@ -774,7 +762,7 @@ func TestPartialStateJoin(t *testing.T) { func(r gjson.Result) interface{} { return r.Str }, nil, ) - return matcher([]byte(res.Raw)) + return matcher(res) }, ) }) @@ -1377,10 +1365,10 @@ func TestPartialStateJoin(t *testing.T) { return strings.Join([]string{result.Map()["type"].Str, result.Map()["state_key"].Str}, "|") }, nil, ) - if err := timelineMatcher([]byte(roomRes.Raw)); err != nil { + if err := timelineMatcher(roomRes); err != nil { t.Errorf("Unexpected timeline events found in gappy /sync response: %s", err) } - if err := stateMatcher([]byte(roomRes.Raw)); err != nil { + if err := stateMatcher(roomRes); err != nil { t.Errorf("Did not find derek's m.room.member event in gappy /sync response: %s", err) } }) @@ -1805,10 +1793,7 @@ func TestPartialStateJoin(t *testing.T) { if httpError.Code != 404 { t.Errorf("expected 404, got %d", httpError.Code) } - errcode := must.GetJSONFieldStr(t, httpError.Contents, "errcode") - if errcode != "M_NOT_FOUND" { - t.Errorf("errcode: got %s, want M_NOT_FOUND", errcode) - } + must.MatchGJSON(t, gjson.ParseBytes(httpError.Contents), match.JSONKeyEqual("errcode", "M_NOT_FOUND")) } else { t.Errorf("MakeJoin: non-HTTPError: %v", err) } @@ -1876,10 +1861,7 @@ func TestPartialStateJoin(t *testing.T) { if httpError.Code != 404 { t.Errorf("expected 404, got %d", httpError.Code) } - errcode := must.GetJSONFieldStr(t, httpError.Contents, "errcode") - if errcode != "M_NOT_FOUND" { - t.Errorf("errcode: got %s, want M_NOT_FOUND", errcode) - } + must.MatchGJSON(t, gjson.ParseBytes(httpError.Contents), match.JSONKeyEqual("errcode", "M_NOT_FOUND")) } else { t.Errorf("SendJoin: non-HTTPError: %v", err) } @@ -1983,10 +1965,7 @@ func TestPartialStateJoin(t *testing.T) { if httpError.Code != 404 { t.Errorf("expected 404, got %d", httpError.Code) } - errcode := must.GetJSONFieldStr(t, httpError.Contents, "errcode") - if errcode != "M_NOT_FOUND" { - t.Errorf("errcode: got %s, want M_NOT_FOUND", errcode) - } + must.MatchGJSON(t, gjson.ParseBytes(httpError.Contents), match.JSONKeyEqual("errcode", "M_NOT_FOUND")) } else { t.Errorf("MakeKnock: non-HTTPError: %v", err) } @@ -2054,10 +2033,7 @@ func TestPartialStateJoin(t *testing.T) { if httpError.Code != 404 { t.Errorf("expected 404, got %d", httpError.Code) } - errcode := must.GetJSONFieldStr(t, httpError.Contents, "errcode") - if errcode != "M_NOT_FOUND" { - t.Errorf("errcode: got %s, want M_NOT_FOUND", errcode) - } + must.MatchGJSON(t, gjson.ParseBytes(httpError.Contents), match.JSONKeyEqual("errcode", "M_NOT_FOUND")) } else { t.Errorf("SendKnock: non-HTTPError: %v", err) } @@ -4072,7 +4048,8 @@ func TestPartialStateJoin(t *testing.T) { []string{"_matrix", "client", "v3", "sync"}, client.WithQueries(queryParams), client.WithRetryUntil(5*time.Second, func(res *http.Response) bool { - body := client.ParseJSON(t, res) + body := must.ParseJSON(t, res.Body) + res.Body.Close() err := matcher(body) return err == nil }), diff --git a/tests/federation_room_join_test.go b/tests/federation_room_join_test.go index 0ae833fd..a6942c69 100644 --- a/tests/federation_room_join_test.go +++ b/tests/federation_room_join_test.go @@ -19,11 +19,11 @@ import ( "github.com/tidwall/gjson" "github.com/tidwall/sjson" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/federation" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/matrix-org/complement/runtime" ) @@ -352,10 +352,7 @@ func TestBannedUserCannotSendJoin(t *testing.T) { if httpError.Code != 403 { t.Errorf("expected 403, got %d", httpError.Code) } - errcode := must.GetJSONFieldStr(t, httpError.Contents, "errcode") - if errcode != "M_FORBIDDEN" { - t.Errorf("errcode: got %s, want M_FORBIDDEN", errcode) - } + must.MatchJSONBytes(t, httpError.Contents, match.JSONKeyEqual("errcode", "M_FORBIDDEN")) } else { t.Errorf("SendJoin: non-HTTPError: %v", err) } @@ -366,9 +363,10 @@ func TestBannedUserCannotSendJoin(t *testing.T) { "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "state", "m.room.member", charlie}, ) - stateResp := client.ParseJSON(t, res) + stateResp := must.ParseJSON(t, res.Body) + res.Body.Close() membership := must.GetJSONFieldStr(t, stateResp, "membership") - must.EqualStr(t, membership, "ban", "membership of charlie") + must.Equal(t, membership, "ban", "membership of charlie") } // This test checks that we cannot submit anything via /v1/send_join except a join. diff --git a/tests/federation_room_typing_test.go b/tests/federation_room_typing_test.go index d072a135..8f84d727 100644 --- a/tests/federation_room_typing_test.go +++ b/tests/federation_room_typing_test.go @@ -3,28 +3,10 @@ package tests import ( "testing" - "github.com/tidwall/gjson" - - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" + "github.com/matrix-org/complement/client" ) -func awaitTyping(userId string) func(result gjson.Result) bool { - return func(result gjson.Result) bool { - if result.Get("type").Str != "m.typing" { - return false - } - - for _, item := range result.Get("content").Get("user_ids").Array() { - if item.Str == userId { - return true - } - } - - return false - } -} - // sytest: Typing notifications also sent to remote room members func TestRemoteTyping(t *testing.T) { deployment := Deploy(t, b.BlueprintFederationTwoLocalOneRemote) @@ -41,12 +23,9 @@ func TestRemoteTyping(t *testing.T) { bobToken := bob.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(bob.UserID, roomID)) charlieToken := charlie.MustSyncUntil(t, client.SyncReq{}, client.SyncJoinedTo(charlie.UserID, roomID)) - alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "typing", alice.UserID}, client.WithJSONBody(t, map[string]interface{}{ - "typing": true, - "timeout": 10000, - })) + alice.SendTyping(t, roomID, true, 10000) - bob.MustSyncUntil(t, client.SyncReq{Since: bobToken}, client.SyncEphemeralHas(roomID, awaitTyping(alice.UserID))) + bob.MustSyncUntil(t, client.SyncReq{Since: bobToken}, client.SyncUsersTyping(roomID, []string{alice.UserID})) - charlie.MustSyncUntil(t, client.SyncReq{Since: charlieToken}, client.SyncEphemeralHas(roomID, awaitTyping(alice.UserID))) + charlie.MustSyncUntil(t, client.SyncReq{Since: charlieToken}, client.SyncUsersTyping(roomID, []string{alice.UserID})) } diff --git a/tests/federation_rooms_invite_test.go b/tests/federation_rooms_invite_test.go index a4e808c5..5da77328 100644 --- a/tests/federation_rooms_invite_test.go +++ b/tests/federation_rooms_invite_test.go @@ -8,8 +8,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func TestFederationRoomsInvite(t *testing.T) { diff --git a/tests/federation_upload_keys_test.go b/tests/federation_upload_keys_test.go index acc3add8..f1cc422b 100644 --- a/tests/federation_upload_keys_test.go +++ b/tests/federation_upload_keys_test.go @@ -10,8 +10,8 @@ import ( "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func TestFederationKeyUploadQuery(t *testing.T) { diff --git a/tests/knocking_test.go b/tests/knocking_test.go index e51d4e71..372cdc60 100644 --- a/tests/knocking_test.go +++ b/tests/knocking_test.go @@ -19,11 +19,11 @@ import ( "github.com/matrix-org/gomatrixserverlib" "github.com/tidwall/gjson" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/federation" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // A reason to include in the request body when testing knock reason parameters @@ -167,8 +167,8 @@ func knockingBetweenTwoUsersTest(t *testing.T, roomID string, inRoomUser, knocki if ev.Get("type").Str != "m.room.member" || ev.Get("sender").Str != knockingUser.UserID { return false } - must.EqualStr(t, ev.Get("content").Get("reason").Str, testKnockReason, "incorrect reason for knock") - must.EqualStr(t, ev.Get("content").Get("membership").Str, "knock", "incorrect membership for knocking user") + must.Equal(t, ev.Get("content").Get("reason").Str, testKnockReason, "incorrect reason for knock") + must.Equal(t, ev.Get("content").Get("membership").Str, "knock", "incorrect membership for knocking user") return true })) }) @@ -201,7 +201,7 @@ func knockingBetweenTwoUsersTest(t *testing.T, roomID string, inRoomUser, knocki if ev.Get("type").Str != "m.room.member" || ev.Get("sender").Str != knockingUser.UserID { continue } - must.EqualStr(t, ev.Get("content").Get("membership").Str, "leave", "expected leave membership after rescinding a knock") + must.Equal(t, ev.Get("content").Get("membership").Str, "leave", "expected leave membership after rescinding a knock") return nil } return fmt.Errorf("leave timeline for %s doesn't have leave event for %s", roomID, knockingUser.UserID) diff --git a/tests/media_nofilename_test.go b/tests/media_nofilename_test.go index 24aa0165..e7bb61fe 100644 --- a/tests/media_nofilename_test.go +++ b/tests/media_nofilename_test.go @@ -8,7 +8,7 @@ import ( "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/internal/federation" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/must" ) // Can handle uploads and remote/local downloads without a file name @@ -43,14 +43,14 @@ func TestMediaWithoutFileName(t *testing.T) { t.Run("Can upload without a file name", func(t *testing.T) { t.Parallel() mxc := alice.UploadContent(t, file, fileName, contentType) - must.NotEqualStr(t, mxc, "", "did not return an MXC URI") + must.NotEqual(t, mxc, "", "did not return an MXC URI") must.StartWithStr(t, mxc, "mxc://", "returned invalid MXC URI") }) // sytest: Can download without a file name locally t.Run("Can download without a file name locally", func(t *testing.T) { t.Parallel() mxc := alice.UploadContent(t, file, fileName, contentType) - must.NotEqualStr(t, mxc, "", "did not return an MXC URI") + must.NotEqual(t, mxc, "", "did not return an MXC URI") must.StartWithStr(t, mxc, "mxc://", "returned invalid MXC URI") b, ct := alice.DownloadContent(t, mxc) @@ -62,14 +62,14 @@ func TestMediaWithoutFileName(t *testing.T) { // For now, we're operating under the assumption that homeservers are free to add other // directives. All we're going to check is the mime-type. mimeType := strings.Split(ct, ";")[0] - must.EqualStr( + must.Equal( t, mimeType, contentType, fmt.Sprintf( "Wrong mime-type returned in Content-Type returned. got Content-Type '%s', extracted mime-type '%s', expected mime-type: '%s'", ct, mimeType, contentType, ), ) - must.EqualStr(t, string(b), string(file), "wrong file content returned") + must.Equal(t, string(b), string(file), "wrong file content returned") }) // sytest: Can download without a file name over federation t.Run("Can download without a file name over federation", func(t *testing.T) { @@ -84,14 +84,14 @@ func TestMediaWithoutFileName(t *testing.T) { // For now, we're operating under the assumption that homeservers are free to add other // directives. All we're going to check is the mime-type. mimeType := strings.Split(ct, ";")[0] - must.EqualStr( + must.Equal( t, mimeType, contentType, fmt.Sprintf( "Wrong mime-type returned in Content-Type returned. got Content-Type '%s', extracted mime-type '%s', expected mime-type: '%s'", ct, mimeType, contentType, ), ) - must.EqualStr(t, string(b), string(remoteFile), "wrong file content returned") + must.Equal(t, string(b), string(remoteFile), "wrong file content returned") }) }) } diff --git a/tests/media_thumbnail_test.go b/tests/media_thumbnail_test.go index a067483b..8d6d0e63 100644 --- a/tests/media_thumbnail_test.go +++ b/tests/media_thumbnail_test.go @@ -4,13 +4,13 @@ import ( "bytes" "image/jpeg" "image/png" - "io/ioutil" + "io" "net/url" "strings" "testing" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/data" ) @@ -62,7 +62,7 @@ func fetchAndValidateThumbnail(t *testing.T, c *client.CSAPI, mxcUri string) { t.Fatalf("thumbnail request for uploaded file failed") } - body, err := ioutil.ReadAll(res.Body) + body, err := io.ReadAll(res.Body) if err != nil { t.Fatalf("thumbnail request for uploaded file failed: %s", err) diff --git a/tests/msc2836_test.go b/tests/msc2836_test.go index ac469326..582d3392 100644 --- a/tests/msc2836_test.go +++ b/tests/msc2836_test.go @@ -16,13 +16,14 @@ import ( "time" "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/gomatrixserverlib/spec" "github.com/tidwall/gjson" - "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/b" + "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/federation" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // This test checks that federated threading works when the remote server joins after the messages @@ -323,9 +324,9 @@ func TestFederatedEventRelationships(t *testing.T) { fedClient := srv.FederationClient(deployment) _, err := fedClient.SendTransaction(context.Background(), gomatrixserverlib.Transaction{ TransactionID: "complement", - Origin: gomatrixserverlib.ServerName(srv.ServerName()), - Destination: gomatrixserverlib.ServerName("hs1"), - OriginServerTS: gomatrixserverlib.AsTimestamp(time.Now()), + Origin: spec.ServerName(srv.ServerName()), + Destination: spec.ServerName("hs1"), + OriginServerTS: spec.AsTimestamp(time.Now()), PDUs: []json.RawMessage{ eventE.JSON(), }, diff --git a/tests/msc3391_test.go b/tests/msc3391_test.go index 92da974a..86754120 100644 --- a/tests/msc3391_test.go +++ b/tests/msc3391_test.go @@ -13,8 +13,8 @@ import ( "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/tidwall/gjson" ) @@ -81,17 +81,7 @@ func createUserAccountData(t *testing.T, c *client.CSAPI) { res := c.GetGlobalAccountData(t, testAccountDataType) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ - func(body []byte) error { - if !match.JSONDeepEqual(body, testAccountDataContent) { - return fmt.Errorf( - "Expected %s for room account data content, got '%s'", - testAccountDataType, - string(body), - ) - } - - return nil - }, + match.JSONKeyEqual("", testAccountDataContent), }, }) } @@ -121,17 +111,7 @@ func createRoomAccountData(t *testing.T, c *client.CSAPI, roomID string) { res := c.GetRoomAccountData(t, roomID, testAccountDataType) must.MatchResponse(t, res, match.HTTPResponse{ JSON: []match.JSON{ - func(body []byte) error { - if !match.JSONDeepEqual(body, testAccountDataContent) { - return fmt.Errorf( - "Expected %s for room account data content, got '%s'", - testAccountDataType, - string(body), - ) - } - - return nil - }, + match.JSONKeyEqual("", testAccountDataContent), }, }) } @@ -259,10 +239,7 @@ func checkAccountDataContent(r gjson.Result) bool { if r.Get("type").Str != testAccountDataType { return false } - content := r.Get("content") - - // Ensure the content of this account data type is as we expect - return match.JSONDeepEqual([]byte(content.Raw), testAccountDataContent) + return match.JSONKeyEqual("content", testAccountDataContent)(r) == nil } // checkEmptyAccountData checks that the content of a user or account data object @@ -272,11 +249,9 @@ func checkEmptyAccountData(r gjson.Result) bool { if r.Get("type").Str != testAccountDataType { return false } - content := r.Get("content") - // Ensure the content of this account data type is an empty map. // This means that it has been deleted. - return match.JSONDeepEqual([]byte(content.Raw), map[string]interface{}{}) + return match.JSONKeyEqual("content", map[string]interface{}{})(r) == nil } // checkAccountDataTypeNotPresent checks that a given account data event type is not present @@ -291,4 +266,4 @@ func checkAccountDataTypeNotPresent(r gjson.Result) error { // We did not see our test type. return nil -} \ No newline at end of file +} diff --git a/tests/msc3890_test.go b/tests/msc3890_test.go index 4c61d86b..dab5d15a 100644 --- a/tests/msc3890_test.go +++ b/tests/msc3890_test.go @@ -12,8 +12,8 @@ import ( "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/tidwall/gjson" ) @@ -53,10 +53,7 @@ func TestDeletingDeviceRemovesDeviceLocalNotificationSettings(t *testing.T) { if r.Get("type").Str != accountDataType { return false } - content := r.Get("content") - - // Ensure the content of this account data type is as we expect - return match.JSONDeepEqual([]byte(content.Raw), accountDataContent) + return match.JSONKeyEqual("content", accountDataContent)(r) == nil } // Check that the content of the user account data for this type has been set successfully diff --git a/tests/msc3930_test.go b/tests/msc3930_test.go index 3e2a9c3a..27200b75 100644 --- a/tests/msc3930_test.go +++ b/tests/msc3930_test.go @@ -18,8 +18,8 @@ import ( "testing" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) const pollResponseRuleID = ".org.matrix.msc3930.rule.poll_response" diff --git a/tests/restricted_room_hierarchy_test.go b/tests/restricted_room_hierarchy_test.go index c067c654..285c8ba6 100644 --- a/tests/restricted_room_hierarchy_test.go +++ b/tests/restricted_room_hierarchy_test.go @@ -9,8 +9,8 @@ import ( "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) // Request the room summary and ensure the expected rooms are in the response. diff --git a/tests/restricted_rooms_test.go b/tests/restricted_rooms_test.go index fd601e48..64cc5b1b 100644 --- a/tests/restricted_rooms_test.go +++ b/tests/restricted_rooms_test.go @@ -11,8 +11,8 @@ import ( "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/client" "github.com/matrix-org/complement/internal/docker" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/matrix-org/complement/runtime" ) @@ -299,8 +299,8 @@ func doTestRestrictedRoomsRemoteJoinLocalUser(t *testing.T, roomVersion string, if ev.Get("type").Str != "m.room.member" || ev.Get("state_key").Str != bob.UserID { return false } - must.EqualStr(t, ev.Get("sender").Str, bob.UserID, "Bob should have joined by himself") - must.EqualStr(t, ev.Get("content").Get("membership").Str, "join", "Bob failed to join the room") + must.Equal(t, ev.Get("sender").Str, bob.UserID, "Bob should have joined by himself") + must.Equal(t, ev.Get("content").Get("membership").Str, "join", "Bob failed to join the room") return true }, @@ -328,7 +328,7 @@ func doTestRestrictedRoomsRemoteJoinLocalUser(t *testing.T, roomVersion string, if ev.Get("type").Str != "m.room.member" || ev.Get("state_key").Str != charlie.UserID { return false } - must.EqualStr(t, ev.Get("content").Get("membership").Str, "leave", "Charlie failed to leave the room") + must.Equal(t, ev.Get("content").Get("membership").Str, "leave", "Charlie failed to leave the room") return true }, @@ -436,8 +436,8 @@ func doTestRestrictedRoomsRemoteJoinFailOver(t *testing.T, roomVersion string, j if ev.Get("type").Str != "m.room.member" || ev.Get("state_key").Str != charlie.UserID { return false } - must.EqualStr(t, ev.Get("content").Get("membership").Str, "join", "Charlie failed to join the room") - must.EqualStr(t, ev.Get("content").Get("join_authorised_via_users_server").Str, alice.UserID, "Join authorised via incorrect server") + must.Equal(t, ev.Get("content").Get("membership").Str, "join", "Charlie failed to join the room") + must.Equal(t, ev.Get("content").Get("join_authorised_via_users_server").Str, alice.UserID, "Join authorised via incorrect server") return true }, @@ -487,9 +487,10 @@ func doTestRestrictedRoomsRemoteJoinFailOver(t *testing.T, roomVersion string, j if ev.Get("type").Str != "m.room.member" || ev.Get("state_key").Str != charlie.UserID { return false } - must.EqualStr(t, ev.Get("content").Get("membership").Str, "join", "Charlie failed to join the room") - must.EqualStr(t, ev.Get("content").Get("join_authorised_via_users_server").Str, alice.UserID, "Join authorised via incorrect server") - + must.MatchGJSON(t, ev, + match.JSONKeyEqual("content.membership", "join"), + match.JSONKeyEqual("content.join_authorised_via_users_server", alice.UserID), + ) return true }, )) diff --git a/tests/room_hierarchy_test.go b/tests/room_hierarchy_test.go index c5fe56e4..90522aaf 100644 --- a/tests/room_hierarchy_test.go +++ b/tests/room_hierarchy_test.go @@ -22,8 +22,8 @@ import ( "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) var ( diff --git a/tests/room_timestamp_to_event_test.go b/tests/room_timestamp_to_event_test.go index f0decbec..21f8297e 100644 --- a/tests/room_timestamp_to_event_test.go +++ b/tests/room_timestamp_to_event_test.go @@ -17,9 +17,10 @@ import ( "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" "github.com/tidwall/gjson" + "golang.org/x/exp/slices" ) func TestJumpToDateEndpoint(t *testing.T) { @@ -395,7 +396,8 @@ func getDebugMessageListFromMessagesResponse(t *testing.T, c *client.CSAPI, room } // Make the events go from oldest-in-time -> newest-in-time - events := reverseGjsonArray(keyRes.Array()) + events := keyRes.Array() + slices.Reverse(events) if len(events) == 0 { t.Fatalf( "getDebugMessageListFromMessagesResponse found no messages in the room(%s).", @@ -464,11 +466,3 @@ const AnsiColorYellow string = "33" func decorateStringWithAnsiColor(inputString, decorationColor string) string { return fmt.Sprintf("\033[%sm%s\033[0m", decorationColor, inputString) } - -func reverseGjsonArray(in []gjson.Result) []gjson.Result { - out := make([]gjson.Result, len(in)) - for i := 0; i < len(in); i++ { - out[i] = in[len(in)-i-1] - } - return out -} diff --git a/tests/unknown_endpoints_test.go b/tests/unknown_endpoints_test.go index cdac1805..024cd611 100644 --- a/tests/unknown_endpoints_test.go +++ b/tests/unknown_endpoints_test.go @@ -6,8 +6,8 @@ import ( "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/internal/match" - "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" ) func queryUnknownEndpoint(t *testing.T, user *client.CSAPI, paths []string) {