Skip to content

Commit

Permalink
Test for partial-state responses from /send_join (#320)
Browse files Browse the repository at this point in the history
MSC3706 adds extensions to /send_join for partial state. Here we add a test which checks the response is correct. (The test is skipped if the server does not support it).

Tests the implementation which was introduced in matrix-org/synapse#11967
  • Loading branch information
richvdh authored Feb 17, 2022
1 parent face844 commit 18aa82f
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 7 deletions.
2 changes: 2 additions & 0 deletions dockerfiles/synapse/homeserver.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,5 @@ experimental_features:
spaces_enabled: true
# Enable history backfilling support
msc2716_enabled: true
# server-side support for partial state in /send_join
msc3706_enabled: true
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ require (
github.com/docker/go-connections v0.4.0
github.com/gorilla/mux v1.8.0
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16
github.com/matrix-org/gomatrixserverlib v0.0.0-20220214133635-20632dd262ed
github.com/matrix-org/gomatrixserverlib v0.0.0-20220217085017-e92d47416973
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4
github.com/morikuni/aec v1.0.0 // indirect
github.com/sirupsen/logrus v1.8.1
Expand Down
9 changes: 5 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
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.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
Expand Down Expand Up @@ -436,10 +437,12 @@ github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHef
github.com/matrix-org/gomatrix v0.0.0-20190528120928-7df988a63f26/go.mod h1:3fxX6gUjWyI/2Bt7J1OLhpCzOfO/bB3AiX0cJtEKud0=
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16 h1:ZtO5uywdd5dLDCud4r0r55eP4j9FuUNpl60Gmntcop4=
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
github.com/matrix-org/gomatrixserverlib v0.0.0-20220106115324-39c7d37db009 h1:RV3hT9eHpBSjg0m8W44bgonVUrJI866FkfrW6lf03a0=
github.com/matrix-org/gomatrixserverlib v0.0.0-20220106115324-39c7d37db009/go.mod h1:qFvhfbQ5orQxlH9vCiFnP4dW27xxnWHdNUBKyj/fbiY=
github.com/matrix-org/gomatrixserverlib v0.0.0-20220214133635-20632dd262ed h1:R8EiLWArq7KT96DrUq1xq9scPh8vLwKKeCTnORPyjhU=
github.com/matrix-org/gomatrixserverlib v0.0.0-20220214133635-20632dd262ed/go.mod h1:qFvhfbQ5orQxlH9vCiFnP4dW27xxnWHdNUBKyj/fbiY=
github.com/matrix-org/gomatrixserverlib v0.0.0-20220214182556-d5581e0dccf6 h1:AHrGktqua3V0GUqAN3sQZAxuRXFTV3dQikYkoAzsAbU=
github.com/matrix-org/gomatrixserverlib v0.0.0-20220214182556-d5581e0dccf6/go.mod h1:+WF5InseAMgi1fTnU46JH39IDpEvLep0fDzx9LDf2Bo=
github.com/matrix-org/gomatrixserverlib v0.0.0-20220217085017-e92d47416973 h1:LbyGlBQwzt2jByuKNBllgCPUtqBQqCaAywP57yQOYhw=
github.com/matrix-org/gomatrixserverlib v0.0.0-20220217085017-e92d47416973/go.mod h1:+WF5InseAMgi1fTnU46JH39IDpEvLep0fDzx9LDf2Bo=
github.com/matrix-org/util v0.0.0-20190711121626-527ce5ddefc7/go.mod h1:vVQlW/emklohkZnOPwD3LrZUBqdfsbiyO3p1lNV8F6U=
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4 h1:eCEHXWDv9Rm335MSuB49mFUK44bwZPFSDde3ORE3syk=
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4/go.mod h1:vVQlW/emklohkZnOPwD3LrZUBqdfsbiyO3p1lNV8F6U=
Expand Down Expand Up @@ -685,8 +688,6 @@ golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
Expand Down
32 changes: 30 additions & 2 deletions internal/must/must.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import (
"strings"
"testing"

"github.com/matrix-org/gomatrixserverlib"
"github.com/tidwall/gjson"

"github.com/matrix-org/gomatrixserverlib"

"github.com/matrix-org/complement/internal/match"
)

Expand Down Expand Up @@ -182,10 +183,37 @@ func HaveInOrder(t *testing.T, gots []string, wants []string) {
}
}

// CheckOffAll checks that a list contains exactly the given items, in any order.
//
// if an item is not present, the test is failed.
// if an item not present in the want list is present, the test is failed.
// Items are compared using reflect.DeepEqual
func CheckOffAll(t *testing.T, items []interface{}, wantItems []interface{}) {
t.Helper()
remaining := CheckOffAllAllowUnwanted(t, items, wantItems)
if len(remaining) > 0 {
t.Errorf("CheckOffAll: unexpected items %v", remaining)
}
}

// 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.
//
// if an item is not present, the test is failed.
// Items are compared using reflect.DeepEqual
func CheckOffAllAllowUnwanted(t *testing.T, items []interface{}, wantItems []interface{}) []interface{} {
t.Helper()
for _, wantItem := range wantItems {
items = CheckOff(t, items, wantItem)
}
return items
}

// 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 reflect.DeepEqual
func CheckOff(t *testing.T, items []interface{}, wantItem interface{}) []interface{} {
t.Helper()
// check off the item
want := -1
for i, w := range items {
Expand All @@ -195,7 +223,7 @@ func CheckOff(t *testing.T, items []interface{}, wantItem interface{}) []interfa
}
}
if want == -1 {
t.Errorf("CheckOff: unexpected item %s", wantItem)
t.Errorf("CheckOff: item %s not present", wantItem)
return items
}
// delete the wanted item
Expand Down
77 changes: 77 additions & 0 deletions tests/federation_room_join_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ import (
"fmt"
"net/http"
"net/url"
"strings"
"testing"
"time"

"github.com/matrix-org/gomatrix"

"github.com/matrix-org/gomatrixserverlib"

"github.com/tidwall/gjson"
"github.com/tidwall/sjson"

"github.com/matrix-org/complement/internal/b"
Expand Down Expand Up @@ -445,3 +448,77 @@ func testValidationForSendMembershipEndpoint(t *testing.T, baseApiPath, expected
assertRequestFails(t, event)
})
}

// Tests an implementation's support for MSC3706-style partial-state responses to send_join.
//
// Will be skipped if the server returns a full-state response.
func TestSendJoinPartialStateResponse(t *testing.T) {
// start with a homeserver with two users
deployment := Deploy(t, b.BlueprintOneToOneRoom)
defer deployment.Destroy(t)

srv := federation.NewServer(t, deployment,
federation.HandleKeyRequests(),
)
cancel := srv.Listen()
defer cancel()

// 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.
// alice creates a room, which bob joins
alice := deployment.Client(t, "hs1", "@alice:hs1")
bob := deployment.Client(t, "hs1", "@bob:hs1")
roomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"})
bob.JoinRoom(t, roomID, nil)

// now we send a make_join...
charlie := srv.UserID("charlie")
fedClient := srv.FederationClient(deployment)
makeJoinResp, err := fedClient.MakeJoin(context.Background(), "hs1", roomID, charlie, federation.SupportedRoomVersions())
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(), gomatrixserverlib.ServerName(srv.ServerName()), srv.KeyID, srv.Priv, roomVer)
if err != nil {
t.Fatalf("failed to sign join event: %v", err)
}

// and send_join it, with the magic param
sendJoinResp, err := fedClient.SendJoinPartialState(context.Background(), "hs1", joinEvent)
if err != nil {
t.Fatalf("send_join failed: %v", err)
}

if !sendJoinResp.PartialState {
t.Skip("Server does not support partial_state")
}

// check the returned state events match those expected
var returnedStateEventKeys []interface{}
for _, ev := range sendJoinResp.StateEvents {
returnedStateEventKeys = append(returnedStateEventKeys, typeAndStateKeyForEvent(gjson.ParseBytes(ev)))
}
must.CheckOffAll(t, returnedStateEventKeys, []interface{}{
"m.room.create|", "m.room.power_levels|", "m.room.join_rules|", "m.room.history_visibility|",
})

// check the returned auth events match those expected
var returnedAuthEventKeys []interface{}
for _, ev := range sendJoinResp.AuthEvents {
returnedAuthEventKeys = append(returnedAuthEventKeys, typeAndStateKeyForEvent(gjson.ParseBytes(ev)))
}
must.CheckOffAll(t, returnedAuthEventKeys, []interface{}{
"m.room.member|" + alice.UserID,
})

// check the server list. Only one, so we can use HaveInOrder even though the list is unordered
must.HaveInOrder(t, sendJoinResp.ServersInRoom, []string{"hs1"})
}

// given an event JSON, return the type and state_key, joined with a "|"
func typeAndStateKeyForEvent(result gjson.Result) string {
return strings.Join([]string{result.Map()["type"].Str, result.Map()["state_key"].Str}, "|")
}

0 comments on commit 18aa82f

Please sign in to comment.