Code Monkey home page Code Monkey logo

complement's Introduction

Tests Complement Dev

Complement

Complement is a black box integration testing framework for Matrix homeservers.

Running

You need to have Go and Docker >= 20.10 installed, as well as libolm3 and libolm-dev. Then:

$ COMPLEMENT_BASE_IMAGE=some-matrix/homeserver-impl go test -v ./tests/...

For a full list of configuration options, see the automatically generated documentation. In addition to the environment variables, all normal Go test config options will work, so to just run 1 named test and include a timeout for the test run:

$ COMPLEMENT_BASE_IMAGE=complement-dendrite:latest go test -timeout 30s -run '^(TestOutboundFederationSend)$' -v ./tests/...

If you need to pass environment variables to the image under test, you can:

  1. define a pass-through prefix with e.g. COMPLEMENT_SHARE_ENV_PREFIX=PASS_; then
  2. prefix the desired environment variables with that prefix; e.g. PASS_SYNAPSE_COMPLEMENT_USE_WORKERS=true.

Dependencies

Complement supports encryption via libolm. You can install libolm3 on Debian using something like:

echo "deb http://deb.debian.org/debian buster-backports main" > /etc/apt/sources.list.d/complement.list && apt-get update && apt-get install -y libolm3 libolm-dev/buster-backports

or on Mac:

brew install libolm

If you are on an Apple Silicon Mac then you'll need to set these environment variables too so Go can find libolm:

export LIBRARY_PATH=/opt/homebrew/lib
export CPATH=/opt/homebrew/include
export PATH=/opt/homebrew/bin:$PATH

Potential conflict with firewall software

The homeserver in the test image needs to be able to make requests to the mock homeserver hosted by Complement itself, which may be blocked by firewall software. This will manifest with a subset of the tests (mostly those to do with federation) inexplicably failing.

To solve this, you will need to configure your firewall to allow such requests.

If you are using ufw, this can be done with:

sudo ufw allow in on br-+

Running using Podman

It is possible to run the test suite using Podman and the compatibility layer for Docker API. Rootless mode is also supported.

To do so you should:

  • systemctl --user start podman.service to start the rootless API daemon (can also be enabled).
  • DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock BUILDAH_FORMAT=docker COMPLEMENT_HOSTNAME_RUNNING_COMPLEMENT=host.containers.internal ...

If all the networking tests don't seem to pass, it might be because the default rootless network command pasta doesn't work in recent versions of Podman (see this issue). If that happens to you, consider changing it in Podman's configuration file located at /etc/containers/containers.conf:

default_rootless_network_cmd = "slirp4netns"

Docker image format is needed because OCI format doesn't support the HEALTHCHECK directive unfortunately.

Running against Dendrite

For instance, for Dendrite:

# build a docker image for Dendrite...
$ git clone https://github.com/matrix-org/dendrite
$ (cd dendrite && docker build -t complement-dendrite -f build/scripts/Complement.Dockerfile .)
# ...and test it
$ COMPLEMENT_BASE_IMAGE=complement-dendrite:latest go test -v ./tests/...

Running against Synapse

If you're looking to run Complement against a local dev instance of Synapse, see element-hq/synapse -> scripts-dev/complement.sh.

If you want to develop Complement tests while working on a local dev instance of Synapse, use the scripts-dev/complement.sh script and set the COMPLEMENT_DIR environment variable to the filepath of your local Complement checkout. Arguments to go test can be supplied as an argument to the script, e.g.:

COMPLEMENT_DIR=/path/to/complement scripts-dev/complement.sh -run "TestOutboundFederation(Profile|Send)"

To run Complement against a specific release of Synapse, build the "complement-synapse" image with a SYNAPSE_VERSION build argument. For example:

(cd synapse && docker build -t complement-synapse:v1.36.0 -f docker/complement/Dockerfile --build-arg=SYNAPSE_VERSION=v1.36.0 docker/complement)
COMPLEMENT_BASE_IMAGE=complement-synapse:v1.36.0 go test ./tests/...

Image requirements

If you're looking to run against a custom Dockerfile, it must meet the following requirements:

  • The Dockerfile must EXPOSE 8008 and EXPOSE 8448 for client and federation traffic respectively.
  • The homeserver should run and listen on these ports.
  • The homeserver should become healthy within COMPLEMENT_SPAWN_HS_TIMEOUT_SECS if a HEALTHCHECK is specified in the Dockerfile.
  • The homeserver needs to 200 OK requests to GET /_matrix/client/versions.
  • The homeserver needs to manage its own storage within the image.
  • The homeserver needs to accept the server name given by the environment variable SERVER_NAME at runtime.
  • The homeserver needs to assume dockerfile CMD or ENTRYPOINT instructions will be run multiple times.
  • The homeserver needs to use complement as the registration shared secret for /_synapse/admin/v1/register, if supported. If this endpoint 404s then these tests are skipped.

Developing locally

If you want to write Complement tests and hack on a homeserver implementation at the same time it can be very awkward to have to docker build the image all the time. To resolve this, Complement support "host mounts" which mount a directory from the host to the container. This is set via COMPLEMENT_HOST_MOUNTS, on the form HOST:CONTAINER[:ro][;...] where :ro makes the mount read-only.

For example, for Dendrite on Linux with the default location of $GOPATH, do a one-time setup:

$ git clone https://github.com/matrix-org/dendrite ../dendrite
$ (cd ../dendrite && docker build -t complement-dendrite-local -f build/scripts/ComplementLocal.Dockerfile .)
$ mkdir -p ../complement-go-build-cache
$ export COMPLEMENT_BASE_IMAGE=complement-dendrite-local
$ export COMPLEMENT_HOST_MOUNTS="$PWD/../dendrite:/dendrite:ro;$HOME/go:/go:ro;$PWD/../complement-go-build-cache:/root/.cache/go-build"

Then simply use go test to compile and test your locally checked out Dendrite:

$ go test -v ./tests/...

Getting prettier output

The default output isn't particularly nice to read. You can use gotestfmt to make this very pretty. To do so, ask for JSON output via go test -json then pipe the output to gotestfmt. If you are doing this in CI, make sure to set -o pipefail or else test failures will NOT result in a non-zero exit code as gotestfmt's exit code (0 as it successfully printed) will replace the previous commands exit code. See Complement's Github Actions file for an example of how to do this correctly.

Writing tests

To get started developing Complement tests, see the onboarding documentation.

Build tags

Complement uses build tags to include or exclude tests for each homeserver. Build tags are comments at the top of the file that look like:

// +build msc2403

We have tags for MSCs (the above is in msc2403_test.go) as well as general blacklists for a homeserver implementation e.g Dendrite, which has the name dendrite_blacklist. These are implemented as inverted tags such that specifying the tag results in the file not being picked up by go test. For example, apidoc_presence_test.go has:

// +build !dendrite_blacklist

and all Dendrite tests run with -tags="dendrite_blacklist" to cause this file to be skipped. You can run tests with build tags like this:

COMPLEMENT_BASE_IMAGE=complement-synapse:latest go test -v -tags="synapse_blacklist,msc2403" ./tests/...

This runs Complement with a Synapse HS and ignores tests which Synapse doesn't implement, and includes tests for MSC2403.

Why 'Complement'?

Because MC = 1 - M

Complement PKI

As the Matrix federation protocol expects federation endpoints to be served with valid TLS certs, Complement will create a self-signed CA cert to use for creating valid TLS certs in homeserver containers, and mount these files onto your homeserver container:

  • /complement/ca/ca.crt: the public certificate for the CA. The homeserver under test should be configured to trust certificates signed by this CA (e.g. by adding it to the trusted cert store in /etc/ca-certificates).
  • /complement/ca/ca.key: the CA's private key. This is needed to sign the homeserver's certificate.

For example, to sign your certificate for the homeserver, run at each container start (Ubuntu):

openssl genrsa -out $SERVER_NAME.key 2048
openssl req -new -sha256 -key $SERVER_NAME.key -subj "/C=US/ST=CA/O=MyOrg, Inc./CN=$SERVER_NAME" -out $SERVER_NAME.csr
openssl x509 -req -in $SERVER_NAME.csr -CA /complement/ca/ca.crt -CAkey /complement/ca/ca.key -CAcreateserial -out $SERVER_NAME.crt -days 1 -sha256

To add the CA cert to your trust store (Ubuntu):

cp /complement/ca/ca.crt /usr/local/share/ca-certificates/complement.crt
update-ca-certificates

Sytest parity

As of 10 February 2023:

$ go build ./cmd/sytest-coverage
$ ./sytest-coverage -v
10apidoc/01register 10/10 tests
    ✓ POST $ep_name admin with shared secret
    ✓ POST $ep_name with shared secret disallows symbols
    ✓ POST $ep_name with shared secret downcases capitals
    ✓ POST $ep_name with shared secret
    ✓ POST /register allows registration of usernames with '$chr'
    ✓ POST /register rejects registration of usernames with '$q'
    ✓ GET /register yields a set of flows
    ✓ POST /register can create a user
    ✓ POST /register downcases capitals in usernames
    ✓ POST /register returns the same device_id as that in the request

10apidoc/01request-encoding 1/1 tests
    ✓ POST rejects invalid utf-8 in JSON

10apidoc/02login 6/6 tests
    ✓ GET /login yields a set of flows
    ✓ POST /login as non-existing user is rejected
    ✓ POST /login can log in as a user with just the local part of the id
    ✓ POST /login can log in as a user
    ✓ POST /login returns the same device_id as that in the request
    ✓ POST /login wrong password is rejected

10apidoc/04version 1/1 tests
    ✓ Version responds 200 OK with valid structure

10apidoc/10profile-displayname 2/2 tests
    ✓ GET /profile/:user_id/displayname publicly accessible
    ✓ PUT /profile/:user_id/displayname sets my name

10apidoc/11profile-avatar_url 2/2 tests
    ✓ GET /profile/:user_id/avatar_url publicly accessible
    ✓ PUT /profile/:user_id/avatar_url sets my avatar

10apidoc/12device_management 8/8 tests
    ✓ DELETE /device/{deviceId} requires UI auth user to match device owner
    ✓ DELETE /device/{deviceId} with no body gives a 401
    ✓ DELETE /device/{deviceId}
    ✓ GET /device/{deviceId} gives a 404 for unknown devices
    ✓ GET /device/{deviceId}
    ✓ GET /devices
    ✓ PUT /device/{deviceId} gives a 404 for unknown devices
    ✓ PUT /device/{deviceId} updates device fields

10apidoc/13ui-auth 0/4 tests
10apidoc/20presence 2/2 tests
    ✓ GET /presence/:user_id/status fetches initial status
    ✓ PUT /presence/:user_id/status updates my presence

10apidoc/30room-create 10/10 tests
    ✓ Can /sync newly created room
    ✓ POST /createRoom creates a room with the given version
    ✓ POST /createRoom ignores attempts to set the room version via creation_content
    ✓ POST /createRoom makes a private room with invites
    ✓ POST /createRoom makes a private room
    ✓ POST /createRoom makes a public room
    ✓ POST /createRoom makes a room with a name
    ✓ POST /createRoom makes a room with a topic
    ✓ POST /createRoom rejects attempts to create rooms with numeric versions
    ✓ POST /createRoom rejects attempts to create rooms with unknown versions

10apidoc/31room-state 13/13 tests
    ✓ GET /directory/room/:room_alias yields room ID
    ✓ GET /joined_rooms lists newly-created room
    ✓ GET /publicRooms lists newly-created room
    ✓ GET /rooms/:room_id/joined_members fetches my membership
    ✓ GET /rooms/:room_id/state fetches entire room state
    ✓ GET /rooms/:room_id/state/m.room.member/:user_id fetches my membership
    ✓ GET /rooms/:room_id/state/m.room.member/:user_id?format=event fetches my membership event
    ✓ GET /rooms/:room_id/state/m.room.name gets name
    ✓ GET /rooms/:room_id/state/m.room.power_levels fetches powerlevels
    ✓ GET /rooms/:room_id/state/m.room.topic gets topic
    ✓ POST /createRoom with creation content
    ✓ POST /rooms/:room_id/state/m.room.name sets name
    ✓ POST /rooms/:room_id/state/m.room.topic sets topic

10apidoc/32room-alias 2/2 tests
    ✓ GET /rooms/:room_id/aliases lists aliases
    ✓ PUT /directory/room/:room_alias creates alias

10apidoc/33room-members 8/8 tests
    ✓ POST /join/:room_alias can join a room with custom content
    ✓ POST /join/:room_alias can join a room
    ✓ POST /join/:room_id can join a room with custom content
    ✓ POST /join/:room_id can join a room
    ✓ POST /rooms/:room_id/ban can ban a user
    ✓ POST /rooms/:room_id/invite can send an invite
    ✓ POST /rooms/:room_id/join can join a room
    ✓ POST /rooms/:room_id/leave can leave a room

10apidoc/34room-messages 5/5 tests
    ✓ GET /rooms/:room_id/messages lazy loads members correctly
    ✓ GET /rooms/:room_id/messages returns a message
    ✓ POST /rooms/:room_id/send/:event_type sends a message
    ✓ PUT /rooms/:room_id/send/:event_type/:txn_id deduplicates the same txn id
    ✓ PUT /rooms/:room_id/send/:event_type/:txn_id sends a message

10apidoc/35room-typing 1/1 tests
    ✓ PUT /rooms/:room_id/typing/:user_id sets typing notification

10apidoc/36room-levels 3/3 tests
    ✓ GET /rooms/:room_id/state/m.room.power_levels can fetch levels
    ✓ PUT /rooms/:room_id/state/m.room.power_levels can set levels
    ✓ PUT power_levels should not explode if the old power levels were empty

10apidoc/37room-receipts 1/1 tests
    ✓ POST /rooms/:room_id/receipt can create receipts

10apidoc/38room-read-marker 1/1 tests
    ✓ POST /rooms/:room_id/read_markers can create read marker

10apidoc/40content 2/2 tests
    ✓ GET /media/v3/download can fetch the value again
    ✓ POST /media/v3/upload can create an upload

10apidoc/45server-capabilities 2/2 tests
    ✓ GET /capabilities is present and well formed for registered user
    ✓ GET /v3/capabilities is not public

11register 1/7 tests
    × Register with a recaptcha
    × Can register using an email address
    ✓ registration accepts non-ascii passwords
    × registration is idempotent, with username specified
    × registration is idempotent, without username specified
    × registration remembers parameters
    × registration with inhibit_login inhibits login

12login/01threepid-and-password 0/1 tests
12login/02cas 0/3 tests
13logout 4/4 tests
    ✓ Can logout all devices
    ✓ Can logout current device
    ✓ Request to logout with invalid an access token is rejected
    ✓ Request to logout without an access token is rejected

14account/01change-password 7/7 tests
    ✓ After changing password, a different session no longer works by default
    ✓ After changing password, can log in with new password
    ✓ After changing password, can't log in with old password
    ✓ After changing password, different sessions can optionally be kept
    ✓ After changing password, existing session still works
    ✓ Pushers created with a different access token are deleted on password change
    ✓ Pushers created with a the same access token are not deleted on password change

14account/02deactivate 3/4 tests
    × After deactivating account, can't log in with an email
    ✓ After deactivating account, can't log in with password
    ✓ Can deactivate account
    ✓ Can't deactivate account with wrong password

21presence-events 0/2 tests
30rooms/01state 5/5 tests
    ✓ Joining room twice is idempotent
    ✓ Room creation reports m.room.create to myself
    ✓ Room creation reports m.room.member to myself
    ✓ Setting room topic reports m.room.topic to myself
    ✓ Setting state twice is idempotent

30rooms/02members-local 3/3 tests
    ✓ Existing members see new members' join events
    ✓ Existing members see new members' presence
    ✓ New room members see their own join event

30rooms/03members-remote 2/5 tests
    × Existing members see new member's presence
    ✓ Existing members see new members' join events
    ✓ New room members see their own join event
    × Remote users can join room by alias
    × Remote users may not join unfederated rooms

30rooms/04messages 0/9 tests
30rooms/05aliases 13/13 tests
    ✓ Canonical alias can be set
    ✓ Canonical alias can include alt_aliases
    ✓ Alias creators can delete alias with no ops
    ✓ Alias creators can delete canonical alias with no ops
    ✓ Can delete canonical alias
    ✓ Deleting a non-existent alias should return a 404
    ✓ Only room members can list aliases of a room
    ✓ Regular users can add and delete aliases in the default room configuration
    ✓ Regular users can add and delete aliases when m.room.aliases is restricted
    ✓ Remote room alias queries can handle Unicode
    ✓ Room aliases can contain Unicode
    ✓ Users can't delete other's aliases
    ✓ Users with sufficient power-level can delete other's aliases

30rooms/06invite 13/13 tests
    ✓ Can invite users to invite-only rooms
    ✓ Test that we can be reinvited to a room we created
    ✓ Invited user can reject invite for empty room
    ✓ Invited user can reject invite over federation for empty room
    ✓ Invited user can reject invite over federation several times
    ✓ Invited user can reject invite over federation
    ✓ Invited user can reject invite
    ✓ Invited user can reject local invite after originator leaves
    ✓ Invited user can see room metadata
    ✓ Remote invited user can see room metadata
    ✓ Uninvited users cannot join the room
    ✓ Users cannot invite a user that is already in the room
    ✓ Users cannot invite themselves to a room

30rooms/07ban 0/2 tests
30rooms/08levels 0/3 tests
30rooms/09eventstream 0/2 tests
30rooms/10redactions 0/6 tests
30rooms/11leaving 5/5 tests
    ✓ Can get 'm.room.name' state for a departed room (SPEC-216)
    ✓ Can get rooms/{roomId}/members for a departed room (SPEC-216)
    ✓ Can get rooms/{roomId}/messages for a departed room (SPEC-216)
    ✓ Can get rooms/{roomId}/state for a departed room (SPEC-216)
    ✓ Getting messages going forward is limited for a departed room (SPEC-216)

30rooms/12thirdpartyinvite 0/13 tests
30rooms/13guestaccess 0/11 tests
30rooms/14override-per-room 0/2 tests
30rooms/15kick 2/2 tests
    ✓ Users cannot kick users from a room they are not in
    ✓ Users cannot kick users who have already left a room

30rooms/20typing 3/3 tests
    ✓ Typing can be explicitly stopped
    ✓ Typing notification sent to local room members
    ✓ Typing notifications also sent to remote room members

30rooms/21receipts 0/2 tests
30rooms/22profile 1/1 tests
    ✓ $datum updates affect room member events

30rooms/30history-visibility 0/2 tests
30rooms/31forget 5/5 tests
    ✓ Can forget room you've been kicked from
    ✓ Can re-join room if re-invited
    ✓ Can't forget room you're still in
    ✓ Forgetting room does not show up in v2 /sync
    ✓ Forgotten room messages cannot be paginated

30rooms/32erasure 0/1 tests
30rooms/40joinedapis 0/2 tests
30rooms/50context 0/4 tests
30rooms/51event 3/3 tests
    ✓ /event/ does not allow access to events before the user joined
    ✓ /event/ on joined room works
    ✓ /event/ on non world readable room does not work

30rooms/52members 3/3 tests
    ✓ Can filter rooms/{roomId}/members
    ✓ Can get rooms/{roomId}/members at a given point
    ✓ Can get rooms/{roomId}/members

30rooms/60version_upgrade 0/19 tests
30rooms/70publicroomslist 0/5 tests
31sync/01filter 2/2 tests
    ✓ Can create filter
    ✓ Can download filter

31sync/02sync 1/1 tests
    ✓ Can sync

31sync/03joined 6/6 tests
    ✓ Can sync a joined room
    ✓ Full state sync includes joined rooms
    ✓ Get presence for newly joined members in incremental sync
    ✓ Newly joined room has correct timeline in incremental sync
    ✓ Newly joined room includes presence in incremental sync
    ✓ Newly joined room is included in an incremental sync

31sync/04timeline 0/9 tests
31sync/05presence 0/3 tests
31sync/06state 0/14 tests
31sync/07invited 0/3 tests
31sync/08polling 0/2 tests
31sync/09archived 8/8 tests
    ✓ Archived rooms only contain history from before the user left
    ✓ Left rooms appear in the leave section of full state sync
    ✓ Left rooms appear in the leave section of sync
    ✓ Newly left rooms appear in the leave section of gapped sync
    ✓ Newly left rooms appear in the leave section of incremental sync
    ✓ Previously left rooms don't appear in the leave section of sync
    ✓ We should see our own leave event when rejecting an invite,
    ✓ We should see our own leave event, even if history_visibility is

31sync/10archived-ban 0/3 tests
31sync/11typing 0/3 tests
31sync/12receipts 0/2 tests
31sync/13filtered_sync 0/2 tests
31sync/14read-markers 0/3 tests
31sync/15lazy-members 0/12 tests
31sync/16room-summary 0/4 tests
31sync/17peeking 0/4 tests
32room-versions 0/6 tests
40presence 5/5 tests
    ✓ Presence can be set from sync
    ✓ Presence changes are also reported to remote room members
    ✓ Presence changes are reported to local room members
    ✓ Presence changes to UNAVAILABLE are reported to local room members
    ✓ Presence changes to UNAVAILABLE are reported to remote room members

41end-to-end-keys/01-upload-key 6/6 tests
    ✓ Can query device keys using POST
    ✓ Can query specific device keys using POST
    ✓ Can upload device keys
    ✓ Rejects invalid device keys
    ✓ Should reject keys claiming to belong to a different user
    ✓ query for user with no keys returns empty key dict

41end-to-end-keys/03-one-time-keys 1/1 tests
    ✓ Can claim one time key using POST

41end-to-end-keys/04-query-key-federation 1/1 tests
    ✓ Can query remote device keys using POST

41end-to-end-keys/05-one-time-key-federation 1/1 tests
    ✓ Can claim remote one time key using POST

41end-to-end-keys/06-device-lists 0/15 tests
41end-to-end-keys/07-backup 0/10 tests
41end-to-end-keys/08-cross-signing 0/8 tests
42tags 0/7 tests
44account_data 4/6 tests
    ✓ Can add account data to room
    ✓ Can add account data
    ✓ Can get account data without syncing
    ✓ Can get room account data without syncing
    × Latest account data appears in v2 /sync
    × New account data appears in incremental v2 /sync

45openid 0/3 tests
46direct/01directmessage 3/3 tests
    ✓ Can recv a device message using /sync
    ✓ Can send a message directly to a device using PUT /sendToDevice
    ✓ Can send a to-device message to two users which both receive it using /sync

46direct/02reliability 0/2 tests
46direct/03polling 0/1 tests
46direct/04federation 0/2 tests
46direct/05wildcard 0/4 tests
48admin 0/1 tests
49ignore 0/3 tests
50federation/01keys 1/4 tests
    × Federation key API can act as a notary server via a $method request
    ✓ Federation key API allows unsigned requests for keys
    × Key notary server must not overwrite a valid key with a spurious result from the origin server
    × Key notary server should return an expired key if it can't find any others

50federation/02server-names 1/1 tests
    ✓ Non-numeric ports in server names are rejected

50federation/10query-profile 2/2 tests
    ✓ Inbound federation can query profile data
    ✓ Outbound federation can query profile data

50federation/11query-directory 0/2 tests
50federation/30room-join 0/19 tests
50federation/31room-send 0/5 tests
50federation/32room-getevent 0/2 tests
50federation/33room-get-missing-events 2/4 tests
    ✓ Inbound federation can return missing events for $vis visibility
    × Outbound federation can request missing events
    ✓ Outbound federation will ignore a missing event with bad JSON for room version 6
    × outliers whose auth_events are in a different room are correctly rejected

50federation/34room-backfill 0/5 tests
50federation/35room-invite 0/11 tests
50federation/36state 0/13 tests
50federation/37public-rooms 0/1 tests
50federation/38receipts 0/2 tests
50federation/39redactions 0/4 tests
50federation/40devicelists 0/7 tests
50federation/40publicroomlist 0/1 tests
50federation/41power-levels 0/2 tests
50federation/43typing 0/1 tests
50federation/44presence 0/1 tests
50federation/50no-deextrem-outliers 0/1 tests
50federation/50server-acl-endpoints 0/1 tests
50federation/51transactions 0/2 tests
50federation/52soft-fail 0/3 tests
51media/01unicode 4/5 tests
    × Alternative server names do not cause a routing loop
    ✓ Can download specifying a different Unicode file name
    ✓ Can download with Unicode file name locally
    ✓ Can download with Unicode file name over federation
    ✓ Can upload with Unicode file name

51media/02nofilename 3/3 tests
    ✓ Can download without a file name locally
    ✓ Can download without a file name over federation
    ✓ Can upload without a file name

51media/03ascii 5/5 tests
    ✓ Can download file '$filename'
    ✓ Can download specifying a different ASCII file name
    ✓ Can fetch images in room
    ✓ Can send image in room message
    ✓ Can upload with ASCII file name

51media/10thumbnail 2/2 tests
    ✓ POSTed media can be thumbnailed
    ✓ Remote media can be thumbnailed

51media/20urlpreview 1/1 tests
    ✓ Test URL preview

51media/30config 1/1 tests
    ✓ Can read configuration endpoint

52user-directory/01public 0/7 tests
52user-directory/02private 0/3 tests
54identity 0/6 tests
60app-services/01as-create 0/7 tests
60app-services/02ghost 0/6 tests
60app-services/03passive 0/3 tests
60app-services/04asuser 0/2 tests
60app-services/05lookup3pe 0/4 tests
60app-services/06publicroomlist 0/2 tests
60app-services/07deactivate 0/1 tests
61push/01message-pushed 0/7 tests
61push/02add_rules 0/7 tests
61push/03_unread_count 0/2 tests
61push/05_set_actions 0/4 tests
61push/06_get_pusher 0/1 tests
61push/07_set_enabled 0/2 tests
61push/08_rejected_pushers 0/1 tests
61push/09_notifications_api 0/1 tests
61push/80torture 0/3 tests
80torture/03events 1/1 tests
    ✓ Event size limits

80torture/10filters 1/1 tests
    ✓ Check creating invalid filters returns 4xx

80torture/20json 3/3 tests
    ✓ Invalid JSON floats
    ✓ Invalid JSON integers
    ✓ Invalid JSON special values

90jira/SYN-205 1/1 tests
    ✓ Rooms can be created with an initial invite list (SYN-205)

90jira/SYN-328 1/1 tests
    ✓ Typing notifications don't leak

90jira/SYN-343 1/1 tests
    ✓ Non-present room members cannot ban others

90jira/SYN-390 1/1 tests
    ✓ Getting push rules doesn't corrupt the cache SYN-390

90jira/SYN-516 0/1 tests
90jira/SYN-627 0/1 tests

TOTAL: 220/610 tests converted

complement's People

Contributors

andrewdoh avatar anoadragon453 avatar ara4n avatar callahad avatar clokep avatar dependabot[bot] avatar devonh avatar erikjohnston avatar gdlol avatar h-shay avatar half-shot avatar hughns avatar kegsay avatar madlittlemods avatar meenal06 avatar michaelkaye avatar neilalexander avatar oliverpool avatar poljar avatar realtyem avatar reivilibre avatar richvdh avatar s7evink avatar sandhose avatar shadowjonathan avatar squahtx avatar sumnerevans avatar tommie avatar turt2live avatar valkum avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

complement's Issues

Consider removing COMPLEMENT_CA and having it always on

Before too many more homeserver dockerfiles are written, what do people think about removing the COMPLEMENT_CA environment variable, and making its behaviour the default? /ca will just be mounted in all docker containers, and homeserverd dockerfiles can choose to use the certificate and key in /ca or not.

Existing dockerfiles, such as the Synapse Monolith one will need to be updated, but I've been planning to adjust that one to use Complement's CA anyhow.

Complement pipeline will currently use the latest Synapse release when building on branch `master`

When running Complement tests against Synapse in CI, the current Complement buildkite pipeline code will check to see if a similarly-named branch exists on Synapse's repo.

As is often the case, if the name of the branch is master, we'll end up looking for a branch named master on Synapse's side which then grabs the latest release of Synapse, rather than Synapse's develop branch.

This can cause CI to fail on Complement master while the latest release of Synapse does not support tests that are intended to be run against Synapse develop. We saw this recently with TestKnocking, which then magically fixed itself after Synapse 1.37.0 was released today.

The fix is to insert some bash to say "if $BUILDKITE_BRANCH is master, use Synapse develop".

Support E2EE rooms

And actually decrypting them. We support olm as a dependency now so it should be possible.

Helper function format

We are sprouting helper functions which are missing:

  • t as the first arg
  • t.Helper() called in the function itself.

E.g:

func FailJoinRoom(c *client.CSAPI, t *testing.T, roomIDOrAlias string, serverName string)

The latter means if the helper function fails the test, the line number of the helper function is returned (which is unhelpful) instead of the caller. E.g msc3083_test.go:25: CSAPI.MustDoWithStatusRaw POST http://172.17.0.1:49215/_matrix/client/r0/join/%21axRzfYYvbjlmsBAGdx:hs1?access_token=syt_Ym9i_gWbzZkqCcutSaHXBQTbq_0Ohh5T&server_name=hs1 returned HTTP 200, expected 403 which maps to

c.MustDoWithStatusRaw(

Related: #110

TestJoinViaRoomIDAndServerName assumes the homeserver will extract domain names from room IDs

// join the room by room ID alone - the server will need to extract the domain for this to work.
alice := deployment.Client(t, "hs1", "@alice:hs1")
alice.JoinRoom(t, serverRoom.RoomID)

Room IDs are meant to be treated as opaque strings, and thus homeservers are not supposed to extract domain names from them. Having a test that relies on this functionality does not seem right.

(Yes, Dendrite will currently extract domain names from room IDs as a last resort).

sytest-coverage: Coverage script is broken after cs-api revamping

Describe the bug

Coverage script can no longer be run because of the cs-api directory added.

To Reproduce
Steps to reproduce the behavior:

  • Run the go run ./cmd/sytest-coverage

Expected behavior

Sytest coverage should be outputted

Screenshots

panic: ./tests/csapi:1:1: illegal UTF-8 encoding (and 1 more errors)

goroutine 1 [running]:
main.main()
	/Volumes/T7/code/complement/cmd/sytest-coverage/main.go:56 +0xf45
exit status 2

Parallelise tests by default

Tests are currently only run sequentially, unless t.Parallel() is called in a subtest. This will not scale as we increase the number of tests. The go test framework will parallelise tests in different packages by default, but the environments are completely isolated from each other so test suites cannot co-ordinate who is making what blueprint, or when to clean up docker containers. It would be good to figure out a way of doing this such that we have the ability to have at least some parallelisation by default to make it not scale with the number of tests quite so badly.

We may be able to do the package solution, provided we have some co-ordination mechanism for cleanup, even if it's just a naive "okay, all packages get their own namespace to work with". From a sheer complexity PoV this may actually be the best solution as it's easier to reason about (in that you don't need to care about who set up what, at the cost of making O(n) blueprints where n is the number of packages). Then the problem is how to slice and dice the existing tests. I tried this briefly, and we cannot split based entirely on feature, due to how the build tags work. If a directory has test files which are all build tagged up (e.g MSCs) then go test complains that there is nothing testable there (when the tag is not specified). We could add a dummy test file, but that is icky given we then expect new MSCs to add new directories causing the writer of the test to know about this. We could split based on protocol (CS API, SS API, ST API) but that reduces the amount of helper function sharing that can be done, which is typically per-feature (think registration, knocking). Currently all non-test functions share a global namespace as they are all in the same package which is a bit gross in terms of having a mess of global functions lying around.

Thoughts welcome.

Synapse tests run against `master` branch instead of `develop` by default

=== RUN   TestRestrictedRoomsRemoteJoinLocalUser
    msc3083_test.go:191: Deploy times: 6.570039ms blueprints, 3.985522787s containers
    client.go:370: POST hs2/_matrix/client/r0/createRoom => 200 OK (226.771354ms)
    client.go:370: POST hs2/_matrix/client/r0/createRoom => 400 Bad Request (5.686334ms)
    msc3083_test.go:204: CSAPI.MustDo POST http://172.17.0.1:49305/_matrix/client/r0/createRoom returned HTTP 400

https://github.com/matrix-org/complement/runs/3180791920#step:7:1029

Make `Sync*` functions validate sync response

Currently functions such as SyncUntil do little to validate the JSON they're actually getting, I think it could be an easy win to develop a generic validation function, which walks the entire sync response and validates it, before handing it back to the caller.

Support HS upgrade tests

Dendrite has https://github.com/matrix-org/dendrite/tree/master/cmd/dendrite-upgrade-tests which will automatically pull and run different versions of dendrite with the same database and ensure db migrations work correctly. It can be run for example by doing ./dendrite-upgrade-tests --from 0.1.0 --to 0.3.1. This will:

  • Fetch semver looking tags from github (or HEAD).
  • Sort them.
  • Pull archives for each release.
  • Execute a Dockerfile with the build context set to the root directory of the release.
  • Run the lowest semver, make some users and rooms, send a few messages, tear down the server.
  • Keep the database as a docker volume.
  • Repeat with the next lowest semver up until --to.
  • Test that the last HS run has the original users/rooms/messages from all previous runs.

It looks like Synapse has some bisectability baked into the Complement Synapse image:

ARG SYNAPSE_VERSION=latest

If Complement standardised the format of this (e.g thou shalt accept the build arg HS_VERSION=$semver) then we could, in theory, make https://github.com/matrix-org/dendrite/tree/master/cmd/dendrite-upgrade-tests work for any HS (modulo working out how to do persistence, as currently Dendrite uses postgres and that assumption is baked into the upgrade testing infra: this could just be stating that the directory /data is persisted across runs and you need to just dump your DB there).

This arguably is and isn't feature creep. It is feature creep because it has nothing to do with the integration tests in /tests. It isn't feature creep because it is still ultimately testing HSes, just the upgrade paths.

Thoughts @richvdh (on the basis that you added SYNAPSE_VERSION?

Build tag configuration duplicated in many places

Currently the build tags get duplicated in a handful of places:

Note that the build tags are homeserver specific (and might vary based on the version of the homeserver).

It would be great if complement was able to know which build tags to use somehow by inspecting a file or the homeserver capabilities. This would help avoid the various configs above getting out of sync.

Additionally we should probably:

  • Remove the buildkite CI for complement.
  • Remove the unused pipeline for Synapse.

Tail end of server logs appearing above the rest of the logs

Logs: buildkite.log

At line 1974 in the log file you can see that I seem to be experiencing logs being cut off when I have quite a lot of them.

Interestingly it actually looks like a chunk of logs are being spurted out, before Complement actually prints them on line 2518.

And if you look at the end of the actual logs... that lines up with the beginning of the spurted out logs.

So somehow the tail end of the server logs are being printed out above the rest of them...

I initially wondered if this was a bug with piping the logs to less and viewing them there. But the same happens even without less involved.

BlueprintFederationOneToOne does not work on homeservers that do not extract the domain from room IDs

The blueprint for creating a one-to-one room between two federated homeservers (BlueprintFederationOneToOne) fails on homeservers that do not extract domain names from room IDs.

This is because an instruction will be generated on the second homeserver asking to join the room without providing any server_name query parameters.

I've created a PR to allow instructions to carry query parameters: #37

However this does not solve the full problem, as we still need a way to encode into the blueprint that a room was originally created on hs1, ideally without extracting the domain from the room ID in complement. Perhaps we could add a OriginServerName key to Room objects when creating a room in blueprints, which other homeservers can then retrieve via the room's Ref?

Think about adding `sync_next_batch` equivalent variable to `CSAPI`

While looking through sytests, there seems to be a concept of storing/updating the next_batch of previous syncs with user objects (CSAPI objects in complement)

This could be quite helpful when "checkpointing" sync to a particular moment in the test fairly easily.

However, i suspect that adding this would be a massive breaking internal change, as every test in complement has basically acted with since: null up until this point.

Either that, or add an additional bool to every Sync* function which signifies if it should try to continue from the last-stored next_batch variable.

Add documentation on build tags/homeserver blacklists

People may be confused on how exactly to run optional tests, or how they should implement white/blacklists for their homeservers.

I don't think we should document every build tag that's placed in, but just a quick summary of where and why we normally use them would be good.

Rename 'CI' environment variable to 'COMPLEMENT_IN_DOCKER' or similar

This grew out of a discussion here, where it was found that the CI environment variable is used by Complement to know whether it is running inside of a docker container already (and thus needs to talk to the host's docker socket) or is running on the host directly. It's assumed that if Complement is running inside of docker, CI=true.

@richvdh proposed to rename this variable to COMPLEMENT_IN_DOCKER (or something similar) instead, as it's more descriptive of what the variable actually specifies. Plus people won't be tempted to add CI-specific things outside of what's necessary (and thus making CI code split further from production code) 😇.

Make it work on linux

Linux doesn't have host.docker.internal by default, you need additional CLI args when you run the network/container, so we need to do that on startup if running under linux

TestMediaWithoutFileName test does not allow changes in content type between media upload and download

The tests:

  • Can download without a file name locally
  • Can download without a file name over federation

that are a part of TestMediaWithoutFileName both have a check for the Content-Type header value that was provided during initial upload of the test media. They ensure this value does not change between uploading and downloading media and its associated metadata.

Synapse will however augment the content type of text files in order to specify UTF-8 as their encoding. The reasoning behind this is at matrix-org/synapse#7043.

While the spec doesn't explicitly state that the Content-Type response header when downloading a file needs to exactly match what was provided during upload, it does state that it should be the content type of the file, and so homeservers should at least try to get it right.

The original sytest this was taken from, Can download without a file name locally, did not check Content-Header. I personally think it is valuable to do so, but we may want to make an exception for this modification, as it does seem to be beneficial and not against the spec, however vague it might be.

Allow "user-defined" list of skipped tests

Currently, through the use of runtime.SkipIf, tests (from within that test) are skipped depending on which known runtime/server it is testing against.

This is fine considering that synapse and dendrite are closely developed with complement, however, there's a problem if server X comes into play.

Server X's developers are not part of Element or Matrix.org, and developed their own homeserver off on the side, engaging in the community and open spirit of matrix itself.

However, they are still in the middle of development on that homeserver, many features and endpoints not finalized, yet they still want to use Complement.

The current option would be to PR against Complement's codebase, and register their own server.

Then, every time they have added a feature, or complement adds another incompatible test, they would have to STW and wait until the skipIf addition or removal PR has proceeded.

Even still, if they would CI against :latest, and Complement adds new tests, old CI runs cannot be comprehensively retried unless the exact image hash is known and still up.


These points may be doable, however, they have a few breaking points;

  • What if the developers (for whatever reason) refuse to use github, or simply do not find it feasable to contribute in the public?
  • What if their homeserver project is semi-secretive, and it's name shouldn't be known?
  • What about their development speed, if it has to constantly await complement's approval?

All of these issues could sap or otherwise burn those developer's motivation or patience to work on matrix, and it would raise the threshold of motivation and effort to develop matrix homeservers, while i think these issues are completely avoidable.

Synapse and Dendrite don't have to deal with some of these questions, because their development is pretty closely tied with Complement's developers and internal development channels. But, i hope that some of the above can illustrate the difficulty (and defacto "centralisation") that the current setup requires for a homeserver to start and keep using complement.

In this scenario, the homeserver awaits complement's development.


Let me propose the following instead;

Complement should try to read a complement.yml in the current directory when it starts to run, this file can give a blacklist or whitelist of test items that this run wishes to (exclusively) include or exclude.

(This list can also be compressed in JSON in an environment variable, such as COMPLEMENT_TASKLIST)

Complement then selects or unselects to-be-ran tests, this could possibly be done by a boilerplate checkSkip() invocation at the start of every test.

In this scenario, the homeserver developers could submit whitelist additions/blacklist removals to incrementally support more and more tests for their homeserver, with the definition file for such existing on their development branch, while complement only has to read that at runtime. Complement awaits the homeserver's development.


Additionally, some more features;

Tags could be introduced, something akin to tag:v1.1, which enables every test which is geared towards matrix v1.1 compatibility.

Globs for test names could be used, blacklist: ["test:federation*"], which would exclude all tests starting with "federation" (though, test naming depends a bit on #241 resolution, so this is likely not accurate, nor possibly useful)

Complement is not using a Content-Type of application/json for federation request responses

When running the test Outbound federation can query profile data, Synapse attempts to query for profile information, however the handler returns JSON information with a Content-Type of text/plain; charset=utf-8:

2020-11-04 16:53:11,545 - synapse.http.matrixfederationclient - 190 - WARNING - GET-1 - {GET-O-1} [host.docker.internal] Error reading response GET matrix://host.docker.internal/_matrix/federation/v1/query/profile?user_id=%40user%3Ahost.docker.internal&field=displayname: Failed to send request: RuntimeError: Content-Type not application/json: was 'text/plain; charset=utf-8'

The federation api spec states that responses should use a Content-Type of application/json unless otherwise stated.

Adding w.Header().Set("Content-Type", "application/json") to the request handler function fixes this test. I'm not sure whether we want to manually add this everywhere or we can have this be the default for federation responses.

Homerunner fails with `failed to ContainerCommit`

A recent change seems to have broken Homerunner. If I install from master and try to run:

curl -XPOST -d '{"base_image_uri":"complement-dendrite", "blueprint_name":"federation_one_to_one_room"}' http://localhost:54321/create

I get this error:

2021/08/04 17:38:49 .federation_one_to_one_room.hs1 : failed to ContainerCommit: invalid reference format
2021/08/04 17:38:49 .federation_one_to_one_room.hs2 : failed to ContainerCommit: invalid reference format
2021/08/04 17:38:50 could not construct blueprint: .federation_one_to_one_room.hs1 : failed to ContainerCommit: invalid reference format
2021/08/04 17:38:50 could not construct blueprint: .federation_one_to_one_room.hs2 : failed to ContainerCommit: invalid reference format

Error handling in constructHomeserver could be unified

Considering this code (with 2 places where an err != nil can happen):

if err != nil {
log.Printf("%s : failed to deployBaseImage: %s\n", contextStr, err)
containerID := ""
if dep != nil {
containerID = dep.ContainerID
}
printLogs(d.Docker, containerID, contextStr)
return result{
err: err,
}
}
d.log("%s : deployed base image to %s (%s)\n", contextStr, dep.BaseURL, dep.ContainerID)
err = runner.Run(hs, dep.BaseURL)
if err != nil {
d.log("%s : failed to run instructions: %s\n", contextStr, err)
}

If the deploy fails (first err != nil) it gets logged to the standard output via log.Printf (and printLogs is called explicitely).
If the runner fails, it gets logged to the Builder (and printLogs is called by the parent).

I think those 2 error logging should be unified: what do you think is the best approach?

I would recommend having some logging to the standard output, since it can impact the rest of the test.

For instance adding an err param to printLogs, which will get printed at the end of the server log if not nil, called inside construct.

I would be glad to make a PR for this.


Background info: I am trying to understand how #39 can be fixed, and I discovered that the Blueprints has an error (but only after spending a couple of hours and finally adding COMPLEMENT_DEBUG=1 :)

2020/11/17 22:57:42 federation_one_to_one_room.hs2 : failed to run instructions: federation_one_to_one_room.hs2 : request http://localhost:32902/_matrix/client/r0/join/%21IiiKfQGoJGEqTPCTXN:hs1?access_token=MDAxMWxvY2F0aW9uIGhzMgowMDEzaWRlbnRpZmllciBrZXkKMDAxMGNpZCBnZW4gPSAxCjAwMWJjaWQgdXNlcl9pZCA9IEBib2I6aHMyCjAwMTZjaWQgdHlwZSA9IGFjY2VzcwowMDIxY2lkIG5vbmNlID0gbjNjbkNJeUs7bmxhMFBubAowMDJmc2lnbmF0dXJlIGjnOvc29ANDh6mwUukBi_1NocFirh6_gE1ZoogwQotxCg returned HTTP 404 Not Found : {"errcode":"M_UNKNOWN","error":"No known servers"}

Add more docs for how the federation requirements work for images

Some implementations care quite a lot about what hostname they are expected to be, and presumably complement spins up multiple images to create a local federation for some tests. How is the image meant to know what hostname it is running for?

The real world example of this is my matrix-media-repo project: it needs to know which domain it is running for so it can accurately bind all the routes, media IDs, etc.

Consider using a single file-naming scheme and test grouping methodology

Currently, while browsing the test repository, i find it difficult to navigate to tests i expect to exist, and/or not to exist, as the file naming scheme (and test grouping) seems to be all over the place.

I think it'll be worth it (for organisational purposes) to organise files and scope tests such that someone new coming into the repository can find their way and discover related tests better.


Some current complaints and notes are that some files seem to inherit sytest's vague naming scheme (apidoc, federation, etc.), some simply document and test MSCs, and some restrict themselves to very narrow scopes (account_change_password_pushers_test.go)

Test log output is no longer streamed as the test runs since CSAPI tests moved to `tests/csapi` (multiple packages in tests)

Before #171 and the csapi package was added, I was able to run Complement tests and see the log output as it runs. But nowadays, all of the test log output is buffered and only printed when all of the tests finish.

This is caused by Go deciding to not stream log output when there are multiple packages present (we have tests and csapi in the ./tests/... directory):

Related:


I liked the streaming behavior before to see the test progress but it's also important when I try to hook up Element to the homeserver and rooms from Complement to be able to see the log output of room ID's, etc to join and inspect, https://github.com/matrix-org/complement/blob/master/ONBOARDING.md#how-do-i-hook-up-a-matrix-client-like-element-to-the-homeservers-spun-up-by-complement-after-a-test-runs

As a workaround, I can get the log streaming behavior I want by being very selective about the files to run: go test -v -run TestImportHistoricalMessages ./tests/main_test.go ./tests/msc2716_test.go but this is manual process adjusting our generic Synapse test runner every time.

Potential solutions

  1. Move all tests to the tests package.
  2. Just wait for upstream Go changes although there is a possibility this won't change and just the documentation will be updated with this caveat
  3. Run each test package in their own process to still get parallel but still get stream output
  4. Can we run tests in parallel without separate packages? #171

Empty 'access_token' parameter passed to /_matrix/client/r0/register

Complement calls /_matrix/client/r0/register with an empty access_token query parameter, which causes Synapse to fail the request. It is valid to call /register with an access token if you're an application service registering a user in your namespace.

=== CONT  TestRegistration/parallel/POST_/register_returns_the_same_device_id_as_that_in_the_request
    client.go:196: Making POST request to http://localhost:32857/_matrix/client/r0/register?access_token=
    client.go:196: Request body: {"auth":{"type":"m.login.dummy"},"username":"user-device","password":"sUp3rs3kr1t","device_id":"my_device_id"}
=== CONT  TestRegistration
    client.go:262: POST /_matrix/client/r0/register => 401 Unauthorized (1.981009ms)
=== CONT  TestRegistration/parallel/POST_/register_returns_the_same_device_id_as_that_in_the_request
    client.go:196: HTTP/1.1 401 Unauthorized
        Transfer-Encoding: chunked
        Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization
        Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, OPTIONS
        Access-Control-Allow-Origin: *
        Cache-Control: no-cache, no-store, must-revalidate
        Content-Type: application/json
        Date: Wed, 04 Nov 2020 16:53:03 GMT
        Server: Synapse/1.22.1
        
        55
        {"errcode":"M_UNKNOWN_TOKEN","error":"Unrecognised access token","soft_logout":false}
        0
        
    apidoc_register_test.go:92: CSAPI.MustDo POST http://localhost:32857/_matrix/client/r0/register?access_token= returned HTTP 401

The question of whether Synapse should just ignore an empty access_token query parameter is a good one. The spec doesn't really say one way or the other, so it's probably not good to fail a homeserver for this. Though I'm not sure where using an empty access_token would even be valid either.

Just wanted to get your thoughts on whether you think this should be solved Synapse-side or Complement-side.

Replace COMPLEMENT_VERSION_CHECK_ITERATIONS

It's really not clear what this is supposed to do, and what it controls. It ultimately controls how long we're willing to wait for the HS to deploy when using docker run so rename it to COMPLEMENT_SPAWN_HS_TIMEOUT_SECS perhaps. Given we sleep a bit between checks, we can deprecate COMPLEMENT_VERSION_CHECK_ITERATIONS and automatically convert it to a time in the new format.

Account snapshot fails on malfored Matrix ID

Describe the bug

Account snapshot fails when it encounters an invalid Matrix ID @signalbot in this case where the suffix :homeserver.tld is somehow missing

To Reproduce

  1. Remove the :homeserver.tld bit in a read receipt event in sync_snapshot.json
  2. Run the account-snapshot script again

Expected behavior
The event should probably be dropped

Desktop (please complete the following information):

  • OS: macOS 11.4
  • Version: latest

Additional context

2021/06/28 14:02:03 Invalid matrix identifier: @signalbot
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x40 pc=0x1291501]

goroutine 1 [running]:
github.com/matrix-org/complement/cmd/account-snapshot/internal.ConvertToBlueprint(0x0, 0x13213ad, 0x3, 0xc000c9c0c0, 0xc, 0xc000711770)
        /path/to/complement/cmd/account-snapshot/internal/blueprint.go:24 +0x41
main.main()
        /path/to/complement/cmd/account-snapshot/main.go:80 +0x4cf

Support host mounts in containers

Developers often want to run new tests against a local version of their HS. This is cumbersome at present as you have to rebuild a docker image before you can run the test. Instead, we can expose directory on the container which will be volume mounted from a new env var e.g:

COMPLEMENT_MOUNT=/Users/me/my/local/dendrite
COMPLEMENT_BASE_IMAGE=dendrite-which-reads-mounted-dir:latest
go test ./...
  • Should we just expose the source location or also the destination location e.g COMPLEMENT_MOUNT=/Users/me/my/local/dendrite:/data
  • We should standardise the mounted directories (as /ca is done for COMPLEMENT_CA=1) as we will inevitably expand this in the future (e.g appservices need registration YAML files in the container)

We can either be prescriptive and say that we map to a static directory layout:

/complement
    |__ /appservice
    |__ /ca
    |__ /mount

or we can make this configurable e.g:

COMPLEMENT_MOUNT=/Users/me/my/local/dendrite:/mnt
COMPLEMENT_CA=/Users/me/my/ca:/certs
COMPLEMENT_AS=/Users/me/my/appservices:/as

This feels wrong though as it then ties env vars to a specific docker image which isn't what we're trying to do here (we want them to be interchangeable), so let's be prescriptive.

Synapse will not pass TestKeysQueryWithDeviceIDAsObjectFails due to backwards-compatibility handling

TestKeysQueryWithDeviceIDAsObjectFails checks that non-spec compliant behaviour does not occur. This behaviour was specifically being exhibited by Element iOS (issue). Synapse will likely maintain backwards compatibility here for the long line of old Element iOS clients, and thus Synapse is unlikely to pass this test any time soon.

We'd like to get Synapse passing all of a subset of tests in order to have Complement not soft-fail in our CI. Perhaps one solution is to add a build tag for backwards-compatibility checks such as this one, which Synapse can disable?

Autogen per-test docs for discoverability

While working on importing sytests, i found myself ctrl-shift-f-ing on keywords to see what tests already existed to see if a sytest would fit that file, however, I think that this displays some poor test discoverability.

However, when i was documenting some sytests (and their behaviour), i came upon something like the following format;

sytest:
  - name: "Non-present room members cannot ban others"
    type:
      - power_level
      - ban
    desc:
      When a user does not exist in a room, but has powerlevels there, it should not be able to ban users.
    variants:
      - user has never entered the room
      - user has left the room
      - user has been kicked while ban is sent out
      - user server has been ACL-d
  - name: "New federated private chats get full presence information (SYN-115)"
    # ...

I think it would be useful to programmatically document (and maybe link) these tests, so that a quick glance can see which ones exist, what it does, what variants of behaviour it's also testing, and also in which "areas" of testing matrix it exists.


For a final variant of above schema, i think adding a path (something like tests/csapi/rooms_state_test.go:TestRoomCreationReportsEventsToMyself) would help auto-identify the corresponding function.

Could Complement be extended to load and run out-of-repository tests?

The context here is that we 'need' some way to run integration tests for non-Matrix-standard features, such as those implemented by custom Synapse modules or maybe even Synapse-specific behaviours (if/where there is good reason).

Without knowing too much, Complement seems basically perfect for this use case, but it really wouldn't make sense to add these kinds of tests straight to Complement's repository.

It would be nice to have out-of-repository test suites (for example: alongside a Synapse module, say https://github.com/matrix-org/synapse-user-restrictions/, but you can also imagine weirder customer-specific modules).
Is Complement suitable for being extended this way? What would it take?

I'm not familiar with Go, so I can't easily suggest the right approach (I can speculate, but I'll refrain from doing so for now).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.