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

Add tests for MSC3787 #367

Merged
merged 12 commits into from
May 27, 2022
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
matrix:
include:
- homeserver: Synapse
tags: synapse_blacklist,msc3083
tags: synapse_blacklist,msc3083,msc3787

- homeserver: Dendrite
tags: msc2836 dendrite_blacklist
Expand Down
29 changes: 19 additions & 10 deletions tests/knocking_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"time"

"github.com/matrix-org/gomatrixserverlib"

"github.com/tidwall/gjson"

"github.com/matrix-org/complement/internal/b"
Expand All @@ -32,6 +31,11 @@ const testKnockReason string = "Let me in... LET ME IN!!!"
// Knocking is currently an experimental feature and not in the matrix spec.
// This function tests knocking on local and remote room.
func TestKnocking(t *testing.T) {
// v7 is required for knocking support
doTestKnocking(t, "7", "knock")
}

func doTestKnocking(t *testing.T, roomVersion string, joinRule string) {
deployment := Deploy(t, b.BlueprintFederationTwoLocalOneRemote)
defer deployment.Destroy(t)

Expand Down Expand Up @@ -67,33 +71,33 @@ func TestKnocking(t *testing.T) {
RoomVersion string `json:"room_version"`
}{
"private_chat", // Set to private in order to get an invite-only room
"7", // Room version required for knocking.
roomVersion,
})
alice.InviteRoom(t, roomIDOne, david)
inviteWaiter.Wait(t, 5*time.Second)
serverRoomOne := srv.MustJoinRoom(t, deployment, "hs1", roomIDOne, david)

// Test knocking between two users on the same homeserver
knockingBetweenTwoUsersTest(t, roomIDOne, alice, bob, serverRoomOne, false)
knockingBetweenTwoUsersTest(t, roomIDOne, alice, bob, serverRoomOne, false, joinRule)

// Create a room for alice and charlie to test knocking with
roomIDTwo := alice.CreateRoom(t, struct {
Preset string `json:"preset"`
RoomVersion string `json:"room_version"`
}{
"private_chat", // Set to private in order to get an invite-only room
"7", // Room version required for knocking.
roomVersion,
})
inviteWaiter = NewWaiter()
alice.InviteRoom(t, roomIDTwo, david)
inviteWaiter.Wait(t, 5*time.Second)
serverRoomTwo := srv.MustJoinRoom(t, deployment, "hs1", roomIDTwo, david)

// Test knocking between two users, each on a separate homeserver
knockingBetweenTwoUsersTest(t, roomIDTwo, alice, charlie, serverRoomTwo, true)
knockingBetweenTwoUsersTest(t, roomIDTwo, alice, charlie, serverRoomTwo, true, joinRule)
}

func knockingBetweenTwoUsersTest(t *testing.T, roomID string, inRoomUser, knockingUser *client.CSAPI, serverRoom *federation.ServerRoom, testFederation bool) {
func knockingBetweenTwoUsersTest(t *testing.T, roomID string, inRoomUser, knockingUser *client.CSAPI, serverRoom *federation.ServerRoom, testFederation bool, joinRule string) {
t.Run("Knocking on a room with a join rule other than 'knock' should fail", func(t *testing.T) {
knockOnRoomWithStatus(t, knockingUser, roomID, "Can I knock anyways?", []string{"hs1"}, 403)
})
Expand All @@ -105,7 +109,7 @@ func knockingBetweenTwoUsersTest(t *testing.T, roomID string, inRoomUser, knocki
Sender: inRoomUser.UserID,
StateKey: &emptyStateKey,
Content: map[string]interface{}{
"join_rule": "knock",
"join_rule": joinRule,
},
})
})
Expand Down Expand Up @@ -367,6 +371,11 @@ func knockOnRoomWithStatus(t *testing.T, c *client.CSAPI, roomID, reason string,
// representing a knock room. For sanity-checking, this test will also create a public room and ensure it has a
// 'join_rule' representing a publicly-joinable room.
func TestKnockRoomsInPublicRoomsDirectory(t *testing.T) {
// v7 is required for knocking
doTestKnockRoomsInPublicRoomsDirectory(t, "7", "knock")
}

func doTestKnockRoomsInPublicRoomsDirectory(t *testing.T, roomVersion string, joinRule string) {
deployment := Deploy(t, b.BlueprintAlice)
defer deployment.Destroy(t)

Expand All @@ -380,7 +389,7 @@ func TestKnockRoomsInPublicRoomsDirectory(t *testing.T) {
RoomVersion string `json:"room_version"`
}{
"private_chat", // Set to private in order to get an invite-only room
"7", // Room version required for knocking.
roomVersion,
})

// Change the join_rule to allow knocking
Expand All @@ -390,12 +399,12 @@ func TestKnockRoomsInPublicRoomsDirectory(t *testing.T) {
Sender: alice.UserID,
StateKey: &emptyStateKey,
Content: map[string]interface{}{
"join_rule": "knock",
"join_rule": joinRule,
},
})

// Publish the room to the public room directory and check that the 'join_rule' key is knock
publishAndCheckRoomJoinRule(t, alice, roomID, "knock")
publishAndCheckRoomJoinRule(t, alice, roomID, joinRule)

// Create a public room
roomID = alice.CreateRoom(t, struct {
Expand Down
81 changes: 81 additions & 0 deletions tests/msc3787_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//go:build msc3787
// +build msc3787

// This file contains tests for a join rule which mixes concepts of restricted joins
// and knocking. This is currently experimental and defined by MSC3787, found here:
// https://github.com/matrix-org/matrix-spec-proposals/pull/3787
//
// Generally, this is a combination of knocking_test and restricted_rooms_test.

package tests

import (
"testing"

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

var (
msc3787RoomVersion = "org.matrix.msc3787"
msc3787JoinRule = "knock_restricted"
)

// See TestKnocking
func TestKnockingInMSC3787Room(t *testing.T) {
doTestKnocking(t, msc3787RoomVersion, msc3787JoinRule)
}

// See TestKnockRoomsInPublicRoomsDirectory
func TestKnockRoomsInPublicRoomsDirectoryInMSC3787Room(t *testing.T) {
doTestKnockRoomsInPublicRoomsDirectory(t, msc3787RoomVersion, msc3787JoinRule)
}

// See TestCannotSendKnockViaSendKnock
func TestCannotSendKnockViaSendKnockInMSC3787Room(t *testing.T) {
testValidationForSendMembershipEndpoint(t, "/_matrix/federation/v1/send_knock", "knock",
map[string]interface{}{
"preset": "public_chat",
"room_version": msc3787RoomVersion,
},
)
}

// See TestRestrictedRoomsLocalJoin
func TestRestrictedRoomsLocalJoinInMSC3787Room(t *testing.T) {
deployment := Deploy(t, b.BlueprintOneToOneRoom)
defer deployment.Destroy(t)

// Setup the user, allowed room, and restricted room.
alice, allowed_room, room := setupRestrictedRoom(t, deployment, msc3787RoomVersion, msc3787JoinRule)

// Create a second user on the same homeserver.
bob := deployment.Client(t, "hs1", "@bob:hs1")

// Execute the checks.
checkRestrictedRoom(t, alice, bob, allowed_room, room, msc3787JoinRule)
}

// See TestRestrictedRoomsRemoteJoin
func TestRestrictedRoomsRemoteJoinInMSC3787Room(t *testing.T) {
deployment := Deploy(t, b.BlueprintFederationOneToOneRoom)
defer deployment.Destroy(t)

// Setup the user, allowed room, and restricted room.
alice, allowed_room, room := setupRestrictedRoom(t, deployment, msc3787RoomVersion, msc3787JoinRule)

// Create a second user on a different homeserver.
bob := deployment.Client(t, "hs2", "@bob:hs2")

// Execute the checks.
checkRestrictedRoom(t, alice, bob, allowed_room, room, msc3787JoinRule)
}

// See TestRestrictedRoomsRemoteJoinLocalUser
func TestRestrictedRoomsRemoteJoinLocalUserInMSC3787Room(t *testing.T) {
doTestRestrictedRoomsRemoteJoinLocalUser(t, msc3787RoomVersion, msc3787JoinRule)
}

// See TestRestrictedRoomsRemoteJoinFailOver
func TestRestrictedRoomsRemoteJoinFailOverInMSC3787Room(t *testing.T) {
doTestRestrictedRoomsRemoteJoinFailOver(t, msc3787RoomVersion, msc3787JoinRule)
}
34 changes: 21 additions & 13 deletions tests/restricted_rooms_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func failJoinRoom(t *testing.T, c *client.CSAPI, roomIDOrAlias string, serverNam

// Creates two rooms on room version 8 and sets the second room to have
// restricted join rules with allow set to the first room.
func setupRestrictedRoom(t *testing.T, deployment *docker.Deployment) (*client.CSAPI, string, string) {
func setupRestrictedRoom(t *testing.T, deployment *docker.Deployment, roomVersion string, joinRule string) (*client.CSAPI, string, string) {
t.Helper()

alice := deployment.Client(t, "hs1", "@alice:hs1")
Expand All @@ -48,13 +48,13 @@ func setupRestrictedRoom(t *testing.T, deployment *docker.Deployment) (*client.C
room := alice.CreateRoom(t, map[string]interface{}{
"preset": "public_chat",
"name": "Room",
"room_version": "8",
"room_version": roomVersion,
"initial_state": []map[string]interface{}{
{
"type": "m.room.join_rules",
"state_key": "",
"content": map[string]interface{}{
"join_rule": "restricted",
"join_rule": joinRule,
"allow": []map[string]interface{}{
{
"type": "m.room_membership",
Expand All @@ -70,7 +70,7 @@ func setupRestrictedRoom(t *testing.T, deployment *docker.Deployment) (*client.C
return alice, allowed_room, room
}

func checkRestrictedRoom(t *testing.T, alice *client.CSAPI, bob *client.CSAPI, allowed_room string, room string) {
func checkRestrictedRoom(t *testing.T, alice *client.CSAPI, bob *client.CSAPI, allowed_room string, room string, joinRule string) {
t.Helper()

t.Run("Join should fail initially", func(t *testing.T) {
Expand Down Expand Up @@ -142,7 +142,7 @@ func checkRestrictedRoom(t *testing.T, alice *client.CSAPI, bob *client.CSAPI, a
Sender: alice.UserID,
StateKey: &emptyStateKey,
Content: map[string]interface{}{
"join_rule": "restricted",
"join_rule": joinRule,
"allow": []string{"invalid"},
},
},
Expand All @@ -158,7 +158,7 @@ func checkRestrictedRoom(t *testing.T, alice *client.CSAPI, bob *client.CSAPI, a
Sender: alice.UserID,
StateKey: &emptyStateKey,
Content: map[string]interface{}{
"join_rule": "restricted",
"join_rule": joinRule,
"allow": "invalid",
},
},
Expand All @@ -174,13 +174,13 @@ func TestRestrictedRoomsLocalJoin(t *testing.T) {
defer deployment.Destroy(t)

// Setup the user, allowed room, and restricted room.
alice, allowed_room, room := setupRestrictedRoom(t, deployment)
alice, allowed_room, room := setupRestrictedRoom(t, deployment, "8", "restricted")

// Create a second user on the same homeserver.
bob := deployment.Client(t, "hs1", "@bob:hs1")

// Execute the checks.
checkRestrictedRoom(t, alice, bob, allowed_room, room)
checkRestrictedRoom(t, alice, bob, allowed_room, room, "restricted")
}

// Test joining a room with join rules restricted to membership in another room.
Expand All @@ -189,18 +189,22 @@ func TestRestrictedRoomsRemoteJoin(t *testing.T) {
defer deployment.Destroy(t)

// Setup the user, allowed room, and restricted room.
alice, allowed_room, room := setupRestrictedRoom(t, deployment)
alice, allowed_room, room := setupRestrictedRoom(t, deployment, "8", "restricted")

// Create a second user on a different homeserver.
bob := deployment.Client(t, "hs2", "@bob:hs2")

// Execute the checks.
checkRestrictedRoom(t, alice, bob, allowed_room, room)
checkRestrictedRoom(t, alice, bob, allowed_room, room, "restricted")
}

// A server will do a remote join for a local user if it is unable to to issue
// joins in a restricted room it is already participating in.
func TestRestrictedRoomsRemoteJoinLocalUser(t *testing.T) {
doTestRestrictedRoomsRemoteJoinLocalUser(t, "8", "restricted")
}

func doTestRestrictedRoomsRemoteJoinLocalUser(t *testing.T, roomVersion string, joinRule string) {
deployment := Deploy(t, b.BlueprintFederationTwoLocalOneRemote)
defer deployment.Destroy(t)

Expand All @@ -217,13 +221,13 @@ func TestRestrictedRoomsRemoteJoinLocalUser(t *testing.T) {
room := charlie.CreateRoom(t, map[string]interface{}{
"preset": "public_chat",
"name": "Room",
"room_version": "8",
"room_version": roomVersion,
"initial_state": []map[string]interface{}{
{
"type": "m.room.join_rules",
"state_key": "",
"content": map[string]interface{}{
"join_rule": "restricted",
"join_rule": joinRule,
"allow": []map[string]interface{}{
{
"type": "m.room_membership",
Expand Down Expand Up @@ -322,6 +326,10 @@ func TestRestrictedRoomsRemoteJoinLocalUser(t *testing.T) {
// * hs2 joins the room
// * hs3 attempts to join via hs2 (should fail) and hs1 (should work)
func TestRestrictedRoomsRemoteJoinFailOver(t *testing.T) {
doTestRestrictedRoomsRemoteJoinFailOver(t, "8", "restricted")
}

func doTestRestrictedRoomsRemoteJoinFailOver(t *testing.T, roomVersion string, joinRule string) {
deployment := Deploy(t, b.Blueprint{
Name: "federation_three_homeservers",
Homeservers: []b.Homeserver{
Expand Down Expand Up @@ -357,7 +365,7 @@ func TestRestrictedRoomsRemoteJoinFailOver(t *testing.T) {
defer deployment.Destroy(t)

// Setup the user, allowed room, and restricted room.
alice, allowed_room, room := setupRestrictedRoom(t, deployment)
alice, allowed_room, room := setupRestrictedRoom(t, deployment, roomVersion, joinRule)

// Raise the power level so that only alice can invite.
state_key := ""
Expand Down