Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test for partial-state responses from /send_join #320

Merged
merged 3 commits into from
Feb 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dockerfiles/synapse/homeserver.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,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}, "|")
}