aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Alexander <neilalexander@users.noreply.github.com>2021-07-14 13:46:35 +0100
committerNeil Alexander <neilalexander@users.noreply.github.com>2021-07-14 13:46:35 +0100
commitfa1397c21efa118a33d88c07a7f3fed7a6ca2e18 (patch)
tree3a1d842da3435c82165b2ac654e32c60dea31b60
parent2713d1935e30508277c626ba7a8f4937e23c1281 (diff)
Remove unused binaries
-rw-r--r--cmd/create-room-events/main.go147
-rw-r--r--cmd/kafka-producer/main.go93
-rw-r--r--cmd/mediaapi-integration-tests/TESTS.md69
-rw-r--r--cmd/mediaapi-integration-tests/main.go269
-rw-r--r--cmd/mediaapi-integration-tests/totem.jpgbin1933782 -> 0 bytes
-rw-r--r--cmd/roomserver-integration-tests/main.go442
-rw-r--r--cmd/syncserver-integration-tests/main.go563
-rw-r--r--cmd/syncserver-integration-tests/testdata.go102
8 files changed, 0 insertions, 1685 deletions
diff --git a/cmd/create-room-events/main.go b/cmd/create-room-events/main.go
deleted file mode 100644
index 23b44193..00000000
--- a/cmd/create-room-events/main.go
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2017 Vector Creations Ltd
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Generate a list of matrix room events for load testing.
-// Writes the events to stdout by default.
-package main
-
-import (
- "encoding/base64"
- "encoding/json"
- "flag"
- "fmt"
- "os"
- "strings"
- "time"
-
- "github.com/matrix-org/dendrite/roomserver/api"
- "github.com/matrix-org/gomatrixserverlib"
- "golang.org/x/crypto/ed25519"
-)
-
-const usage = `Usage: %s
-
-Generate a list of matrix room events for load testing.
-Writes the events to stdout separated by new lines
-
-Arguments:
-
-`
-
-var (
- serverName = flag.String("server-name", "localhost", "The name of the matrix server to generate events for")
- keyID = flag.String("key-id", "ed25519:auto", "The ID of the key used to sign the events")
- privateKeyString = flag.String("private-key", defaultKey, "Base64 encoded private key to sign events with")
- roomID = flag.String("room-id", "!roomid:$SERVER_NAME", "The room ID to generate events in")
- userID = flag.String("user-id", "@userid:$SERVER_NAME", "The user ID to use as the event sender")
- messageCount = flag.Int("message-count", 10, "The number of m.room.messsage events to generate")
- format = flag.String("Format", "InputRoomEvent", "The output format to use for the messages: InputRoomEvent or Event")
- ver = flag.String("version", string(gomatrixserverlib.RoomVersionV1), "Room version to generate events as")
-)
-
-// By default we use a private key of 0.
-const defaultKey = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-
-var privateKey ed25519.PrivateKey
-var emptyString = ""
-var now time.Time
-var b gomatrixserverlib.EventBuilder
-var eventID int
-
-func main() {
- flag.Usage = func() {
- fmt.Fprintf(os.Stderr, usage, os.Args[0])
- flag.PrintDefaults()
- }
-
- flag.Parse()
- *userID = strings.Replace(*userID, "$SERVER_NAME", *serverName, 1)
- *roomID = strings.Replace(*roomID, "$SERVER_NAME", *serverName, 1)
-
- // Decode the ed25519 private key.
- privateKeyBytes, err := base64.RawStdEncoding.DecodeString(*privateKeyString)
- if err != nil {
- panic(err)
- }
- privateKey = ed25519.PrivateKey(privateKeyBytes)
-
- // Build a m.room.create event.
- b.Sender = *userID
- b.RoomID = *roomID
- b.Type = "m.room.create"
- b.StateKey = &emptyString
- b.SetContent(map[string]string{"creator": *userID}) // nolint: errcheck
- create := buildAndOutput()
-
- // Build a m.room.member event.
- b.Type = "m.room.member"
- b.StateKey = userID
- b.SetContent(map[string]string{"membership": gomatrixserverlib.Join}) // nolint: errcheck
- b.AuthEvents = []gomatrixserverlib.EventReference{create}
- member := buildAndOutput()
-
- // Build a number of m.room.message events.
- b.Type = "m.room.message"
- b.StateKey = nil
- b.SetContent(map[string]string{"body": "Test Message"}) // nolint: errcheck
- b.AuthEvents = []gomatrixserverlib.EventReference{create, member}
- for i := 0; i < *messageCount; i++ {
- buildAndOutput()
- }
-}
-
-// Build an event and write the event to the output.
-func buildAndOutput() gomatrixserverlib.EventReference {
- eventID++
- now = time.Unix(0, 0)
- name := gomatrixserverlib.ServerName(*serverName)
- key := gomatrixserverlib.KeyID(*keyID)
-
- event, err := b.Build(
- now, name, key, privateKey,
- gomatrixserverlib.RoomVersion(*ver),
- )
- if err != nil {
- panic(err)
- }
- writeEvent(event)
- reference := event.EventReference()
- b.PrevEvents = []gomatrixserverlib.EventReference{reference}
- b.Depth++
- return reference
-}
-
-// Write an event to the output.
-func writeEvent(event *gomatrixserverlib.Event) {
- encoder := json.NewEncoder(os.Stdout)
- if *format == "InputRoomEvent" {
- var ire api.InputRoomEvent
- ire.Kind = api.KindNew
- ire.Event = event.Headered(gomatrixserverlib.RoomVersion(*ver))
- authEventIDs := []string{}
- for _, ref := range b.AuthEvents.([]gomatrixserverlib.EventReference) {
- authEventIDs = append(authEventIDs, ref.EventID)
- }
- ire.AuthEventIDs = authEventIDs
- if err := encoder.Encode(ire); err != nil {
- panic(err)
- }
- } else if *format == "Event" {
- if err := encoder.Encode(event); err != nil {
- panic(err)
- }
- } else {
- panic(fmt.Errorf("Format %q is not valid, must be %q or %q", *format, "InputRoomEvent", "Event"))
- }
-}
diff --git a/cmd/kafka-producer/main.go b/cmd/kafka-producer/main.go
deleted file mode 100644
index 18ee3cdf..00000000
--- a/cmd/kafka-producer/main.go
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2017 Vector Creations Ltd
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "bufio"
- "flag"
- "fmt"
- "os"
- "strings"
-
- sarama "github.com/Shopify/sarama"
-)
-
-const usage = `Usage: %s
-
-Reads a list of newline separated messages from stdin and writes them to a single partition in kafka.
-
-Arguments:
-
-`
-
-var (
- brokerList = flag.String("brokers", os.Getenv("KAFKA_PEERS"), "The comma separated list of brokers in the Kafka cluster. You can also set the KAFKA_PEERS environment variable")
- topic = flag.String("topic", "", "REQUIRED: the topic to produce to")
- partition = flag.Int("partition", 0, "The partition to produce to. All the messages will be written to this partition.")
-)
-
-func main() {
- flag.Usage = func() {
- fmt.Fprintf(os.Stderr, usage, os.Args[0])
- flag.PrintDefaults()
- }
-
- flag.Parse()
-
- if *brokerList == "" {
- fmt.Fprintln(os.Stderr, "no -brokers specified. Alternatively, set the KAFKA_PEERS environment variable")
- os.Exit(1)
- }
-
- if *topic == "" {
- fmt.Fprintln(os.Stderr, "no -topic specified")
- os.Exit(1)
- }
-
- config := sarama.NewConfig()
- config.Producer.RequiredAcks = sarama.WaitForAll
- config.Producer.Return.Successes = true
- config.Producer.Partitioner = sarama.NewManualPartitioner
-
- producer, err := sarama.NewSyncProducer(strings.Split(*brokerList, ","), config)
- if err != nil {
- fmt.Fprintln(os.Stderr, "Failed to open Kafka producer:", err)
- os.Exit(1)
- }
- defer func() {
- if err := producer.Close(); err != nil {
- fmt.Fprintln(os.Stderr, "Failed to close Kafka producer cleanly:", err)
- }
- }()
-
- scanner := bufio.NewScanner(os.Stdin)
- for scanner.Scan() {
- line := scanner.Bytes()
- message := &sarama.ProducerMessage{
- Topic: *topic,
- Partition: int32(*partition),
- Value: sarama.ByteEncoder(line),
- }
- if _, _, err := producer.SendMessage(message); err != nil {
- fmt.Fprintln(os.Stderr, "Failed to send message:", err)
- os.Exit(1)
- }
-
- }
- if err := scanner.Err(); err != nil {
- fmt.Fprintln(os.Stderr, "reading standard input:", err)
- }
-
-}
diff --git a/cmd/mediaapi-integration-tests/TESTS.md b/cmd/mediaapi-integration-tests/TESTS.md
deleted file mode 100644
index 82777f45..00000000
--- a/cmd/mediaapi-integration-tests/TESTS.md
+++ /dev/null
@@ -1,69 +0,0 @@
-# Media API Tests
-
-## Implemented
-
-* functional
- * upload
- * normal case
- * download
- * local file
- * existing
- * non-existing
- * remote file
- * existing
- * thumbnail
- * original file formats
- * JPEG
- * local file
- * existing
- * remote file
- * existing
- * cache
- * cold
- * hot
- * pre-generation according to configuration
- * scale
- * crop
- * dynamic generation
- * cold cache
- * larger than original
- * scale
-
-## TODO
-
-* functional
- * upload
- * file too large
- * 0-byte file?
- * invalid filename
- * invalid content-type
- * download
- * invalid origin
- * invalid media id
- * thumbnail
- * original file formats
- * GIF
- * PNG
- * BMP
- * SVG
- * PDF
- * TIFF
- * WEBP
- * local file
- * non-existing
- * remote file
- * non-existing
- * pre-generation according to configuration
- * manual verification + hash check for regressions?
- * dynamic generation
- * hot cache
- * limit on dimensions?
- * 0x0
- * crop
-* load
- * 100 parallel requests
- * same file
- * different local files
- * different remote files
- * pre-generated thumbnails
- * non-pre-generated thumbnails
diff --git a/cmd/mediaapi-integration-tests/main.go b/cmd/mediaapi-integration-tests/main.go
deleted file mode 100644
index 8a5a0d54..00000000
--- a/cmd/mediaapi-integration-tests/main.go
+++ /dev/null
@@ -1,269 +0,0 @@
-// Copyright 2017 Vector Creations Ltd
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "fmt"
- "io/ioutil"
- "net/http"
- "os"
- "os/exec"
- "path"
- "path/filepath"
- "time"
-
- "github.com/matrix-org/dendrite/internal/test"
- "github.com/matrix-org/gomatrixserverlib"
- "gopkg.in/yaml.v2"
-)
-
-var (
- // How long to wait for the server to write the expected output messages.
- // This needs to be high enough to account for the time it takes to create
- // the postgres database tables which can take a while on travis.
- timeoutString = test.Defaulting(os.Getenv("TIMEOUT"), "10s")
- // The name of maintenance database to connect to in order to create the test database.
- postgresDatabase = test.Defaulting(os.Getenv("POSTGRES_DATABASE"), "postgres")
- // The name of the test database to create.
- testDatabaseName = test.Defaulting(os.Getenv("DATABASE_NAME"), "mediaapi_test")
- // Postgres docker container name (for running psql). If not set, psql must be in PATH.
- postgresContainerName = os.Getenv("POSTGRES_CONTAINER")
- // Test image to be uploaded/downloaded
- testJPEG = test.Defaulting(os.Getenv("TEST_JPEG_PATH"), "cmd/mediaapi-integration-tests/totem.jpg")
- kafkaURI = test.Defaulting(os.Getenv("KAFKA_URIS"), "localhost:9092")
-)
-
-var thumbnailSizes = (`
-- width: 32
- height: 32
- method: crop
-- width: 96
- height: 96
- method: crop
-- width: 320
- height: 240
- method: scale
-- width: 640
- height: 480
- method: scale
-- width: 800
- height: 600
- method: scale
-`)
-
-const serverType = "media-api"
-
-const testMediaID = "1VuVy8u_hmDllD8BrcY0deM34Bl7SPJeY9J6BkMmpx0"
-const testContentType = "image/jpeg"
-const testOrigin = "localhost:18001"
-
-var testDatabaseTemplate = "dbname=%s sslmode=disable binary_parameters=yes"
-
-var timeout time.Duration
-
-var port = 10000
-
-func startMediaAPI(suffix string, dynamicThumbnails bool) (*exec.Cmd, chan error, *exec.Cmd, string, string) {
- dir, err := ioutil.TempDir("", serverType+"-server-test"+suffix)
- if err != nil {
- panic(err)
- }
-
- proxyAddr := "localhost:1800" + suffix
-
- database := fmt.Sprintf(testDatabaseTemplate, testDatabaseName+suffix)
- cfg, nextPort, err := test.MakeConfig(dir, kafkaURI, database, "localhost", port)
- if err != nil {
- panic(err)
- }
- cfg.Global.ServerName = gomatrixserverlib.ServerName(proxyAddr)
- cfg.MediaAPI.DynamicThumbnails = dynamicThumbnails
- if err = yaml.Unmarshal([]byte(thumbnailSizes), &cfg.MediaAPI.ThumbnailSizes); err != nil {
- panic(err)
- }
-
- port = nextPort
- if err = test.WriteConfig(cfg, dir); err != nil {
- panic(err)
- }
-
- serverArgs := []string{
- "--config", filepath.Join(dir, test.ConfigFile),
- }
-
- databases := []string{
- testDatabaseName + suffix,
- }
-
- proxyCmd, _ := test.StartProxy(proxyAddr, cfg)
-
- test.InitDatabase(
- postgresDatabase,
- postgresContainerName,
- databases,
- )
-
- cmd, cmdChan := test.CreateBackgroundCommand(
- filepath.Join(filepath.Dir(os.Args[0]), "dendrite-"+serverType+"-server"),
- serverArgs,
- )
-
- fmt.Printf("==TESTSERVER== STARTED %v -> %v : %v\n", proxyAddr, cfg.MediaAPI.InternalAPI.Listen, dir)
- return cmd, cmdChan, proxyCmd, proxyAddr, dir
-}
-
-func cleanUpServer(cmd *exec.Cmd, dir string) {
- // ensure server is dead, only cleaning up so don't care about errors this returns
- cmd.Process.Kill() // nolint: errcheck
- if err := os.RemoveAll(dir); err != nil {
- fmt.Printf("WARNING: Failed to remove temporary directory %v: %q\n", dir, err)
- }
-}
-
-// Runs a battery of media API server tests
-// The tests will pause at various points in this list to conduct tests on the HTTP responses before continuing.
-func main() {
- fmt.Println("==TESTING==", os.Args[0])
-
- var err error
- timeout, err = time.ParseDuration(timeoutString)
- if err != nil {
- fmt.Printf("ERROR: Invalid timeout string %v: %q\n", timeoutString, err)
- return
- }
-
- // create server1 with only pre-generated thumbnails allowed
- server1Cmd, server1CmdChan, server1ProxyCmd, server1ProxyAddr, server1Dir := startMediaAPI("1", false)
- defer cleanUpServer(server1Cmd, server1Dir)
- defer server1ProxyCmd.Process.Kill() // nolint: errcheck
- testDownload(server1ProxyAddr, server1ProxyAddr, "doesnotexist", 404, server1CmdChan)
-
- // upload a JPEG file
- testUpload(
- server1ProxyAddr, testJPEG,
- )
-
- // download that JPEG file
- testDownload(server1ProxyAddr, testOrigin, testMediaID, 200, server1CmdChan)
-
- // thumbnail that JPEG file
- testThumbnail(64, 64, "crop", server1ProxyAddr, server1CmdChan)
-
- // create server2 with dynamic thumbnail generation
- server2Cmd, server2CmdChan, server2ProxyCmd, server2ProxyAddr, server2Dir := startMediaAPI("2", true)
- defer cleanUpServer(server2Cmd, server2Dir)
- defer server2ProxyCmd.Process.Kill() // nolint: errcheck
- testDownload(server2ProxyAddr, server2ProxyAddr, "doesnotexist", 404, server2CmdChan)
-
- // pre-generated thumbnail that JPEG file via server2
- testThumbnail(800, 600, "scale", server2ProxyAddr, server2CmdChan)
-
- // download that JPEG file via server2
- testDownload(server2ProxyAddr, testOrigin, testMediaID, 200, server2CmdChan)
-
- // dynamic thumbnail that JPEG file via server2
- testThumbnail(1920, 1080, "scale", server2ProxyAddr, server2CmdChan)
-
- // thumbnail that JPEG file via server2
- testThumbnail(10000, 10000, "scale", server2ProxyAddr, server2CmdChan)
-
-}
-
-func getMediaURI(host, endpoint, query string, components []string) string {
- pathComponents := []string{host, "_matrix/media/v1", endpoint}
- pathComponents = append(pathComponents, components...)
- return "https://" + path.Join(pathComponents...) + query
-}
-
-func testUpload(host, filePath string) {
- fmt.Printf("==TESTING== upload %v to %v\n", filePath, host)
- file, err := os.Open(filePath)
- defer file.Close() // nolint: errcheck, staticcheck, megacheck
- if err != nil {
- panic(err)
- }
- filename := filepath.Base(filePath)
- stat, err := file.Stat()
- if os.IsNotExist(err) {
- panic(err)
- }
- fileSize := stat.Size()
-
- req, err := http.NewRequest(
- "POST",
- getMediaURI(host, "upload", "?filename="+filename, nil),
- file,
- )
- if err != nil {
- panic(err)
- }
- req.ContentLength = fileSize
- req.Header.Set("Content-Type", testContentType)
-
- wantedBody := `{"content_uri": "mxc://localhost:18001/` + testMediaID + `"}`
- testReq := &test.Request{
- Req: req,
- WantedStatusCode: 200,
- WantedBody: test.CanonicalJSONInput([]string{wantedBody})[0],
- }
- if err := testReq.Do(); err != nil {
- panic(err)
- }
- fmt.Printf("==TESTING== upload %v to %v PASSED\n", filePath, host)
-}
-
-func testDownload(host, origin, mediaID string, wantedStatusCode int, serverCmdChan chan error) {
- req, err := http.NewRequest(
- "GET",
- getMediaURI(host, "download", "", []string{
- origin,
- mediaID,
- }),
- nil,
- )
- if err != nil {
- panic(err)
- }
- testReq := &test.Request{
- Req: req,
- WantedStatusCode: wantedStatusCode,
- WantedBody: "",
- }
- testReq.Run(fmt.Sprintf("download mxc://%v/%v from %v", origin, mediaID, host), timeout, serverCmdChan)
-}
-
-func testThumbnail(width, height int, resizeMethod, host string, serverCmdChan chan error) {
- query := fmt.Sprintf("?width=%v&height=%v", width, height)
- if resizeMethod != "" {
- query += "&method=" + resizeMethod
- }
- req, err := http.NewRequest(
- "GET",
- getMediaURI(host, "thumbnail", query, []string{
- testOrigin,
- testMediaID,
- }),
- nil,
- )
- if err != nil {
- panic(err)
- }
- testReq := &test.Request{
- Req: req,
- WantedStatusCode: 200,
- WantedBody: "",
- }
- testReq.Run(fmt.Sprintf("thumbnail mxc://%v/%v%v from %v", testOrigin, testMediaID, query, host), timeout, serverCmdChan)
-}
diff --git a/cmd/mediaapi-integration-tests/totem.jpg b/cmd/mediaapi-integration-tests/totem.jpg
deleted file mode 100644
index 9cc2d424..00000000
--- a/cmd/mediaapi-integration-tests/totem.jpg
+++ /dev/null
Binary files differ
diff --git a/cmd/roomserver-integration-tests/main.go b/cmd/roomserver-integration-tests/main.go
deleted file mode 100644
index ff3f06b6..00000000
--- a/cmd/roomserver-integration-tests/main.go
+++ /dev/null
@@ -1,442 +0,0 @@
-// Copyright 2017 Vector Creations Ltd
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "context"
- "fmt"
- "io/ioutil"
- "os"
- "os/exec"
- "path/filepath"
- "strings"
- "time"
-
- "encoding/json"
-
- "net/http"
-
- "github.com/matrix-org/dendrite/internal/caching"
- "github.com/matrix-org/dendrite/internal/test"
- "github.com/matrix-org/dendrite/roomserver/api"
- "github.com/matrix-org/dendrite/roomserver/inthttp"
- "github.com/matrix-org/dendrite/setup/config"
- "github.com/matrix-org/gomatrixserverlib"
-)
-
-var (
- // Path to where kafka is installed.
- kafkaDir = defaulting(os.Getenv("KAFKA_DIR"), "kafka")
- // The URI the kafka zookeeper is listening on.
- zookeeperURI = defaulting(os.Getenv("ZOOKEEPER_URI"), "localhost:2181")
- // The URI the kafka server is listening on.
- kafkaURI = defaulting(os.Getenv("KAFKA_URIS"), "localhost:9092")
- // How long to wait for the roomserver to write the expected output messages.
- // This needs to be high enough to account for the time it takes to create
- // the postgres database tables which can take a while on travis.
- timeoutString = defaulting(os.Getenv("TIMEOUT"), "60s")
- // Timeout for http client
- timeoutHTTPClient = defaulting(os.Getenv("TIMEOUT_HTTP"), "30s")
- // The name of maintenance database to connect to in order to create the test database.
- postgresDatabase = defaulting(os.Getenv("POSTGRES_DATABASE"), "postgres")
- // The name of the test database to create.
- testDatabaseName = defaulting(os.Getenv("DATABASE_NAME"), "roomserver_test")
- // The postgres connection config for connecting to the test database.
- testDatabase = defaulting(os.Getenv("DATABASE"), fmt.Sprintf("dbname=%s binary_parameters=yes", testDatabaseName))
-)
-
-var exe = test.KafkaExecutor{
- ZookeeperURI: zookeeperURI,
- KafkaDirectory: kafkaDir,
- KafkaURI: kafkaURI,
- // Send stdout and stderr to our stderr so that we see error messages from
- // the kafka process.
- OutputWriter: os.Stderr,
-}
-
-func defaulting(value, defaultValue string) string {
- if value == "" {
- value = defaultValue
- }
- return value
-}
-
-var (
- timeout time.Duration
- timeoutHTTP time.Duration
-)
-
-func init() {
- var err error
- timeout, err = time.ParseDuration(timeoutString)
- if err != nil {
- panic(err)
- }
- timeoutHTTP, err = time.ParseDuration(timeoutHTTPClient)
- if err != nil {
- panic(err)
- }
-}
-
-func createDatabase(database string) error {
- cmd := exec.Command("psql", postgresDatabase)
- cmd.Stdin = strings.NewReader(
- fmt.Sprintf("DROP DATABASE IF EXISTS %s; CREATE DATABASE %s;", database, database),
- )
- // Send stdout and stderr to our stderr so that we see error messages from
- // the psql process
- cmd.Stdout = os.Stderr
- cmd.Stderr = os.Stderr
- return cmd.Run()
-}
-
-// runAndReadFromTopic runs a command and waits for a number of messages to be
-// written to a kafka topic. It returns if the command exits, the number of
-// messages is reached or after a timeout. It kills the command before it returns.
-// It returns a list of the messages read from the command on success or an error
-// on failure.
-func runAndReadFromTopic(runCmd *exec.Cmd, readyURL string, doInput func(), topic string, count int, checkQueryAPI func()) ([]string, error) {
- type result struct {
- // data holds all of stdout on success.
- data []byte
- // err is set on failure.
- err error
- }
- done := make(chan result)
- readCmd := exec.Command(
- filepath.Join(kafkaDir, "bin", "kafka-console-consumer.sh"),
- "--bootstrap-server", kafkaURI,
- "--topic", topic,
- "--from-beginning",
- "--max-messages", fmt.Sprintf("%d", count),
- )
- // Send stderr to our stderr so the user can see any error messages.
- readCmd.Stderr = os.Stderr
-
- // Kill both processes before we exit.
- defer func() { runCmd.Process.Kill() }() // nolint: errcheck
- defer func() { readCmd.Process.Kill() }() // nolint: errcheck
-
- // Run the command, read the messages and wait for a timeout in parallel.
- go func() {
- // Read all of stdout.
- defer func() {
- if err := recover(); err != nil {
- if errv, ok := err.(error); ok {
- done <- result{nil, errv}
- } else {
- panic(err)
- }
- }
- }()
- data, err := readCmd.Output()
- checkQueryAPI()
- done <- result{data, err}
- }()
- go func() {
- err := runCmd.Run()
- done <- result{nil, err}
- }()
- go func() {
- time.Sleep(timeout)
- done <- result{nil, fmt.Errorf("Timeout reading %d messages from topic %q", count, topic)}
- }()
-
- // Poll the HTTP listener of the process waiting for it to be ready to receive requests.
- ready := make(chan struct{})
- go func() {
- delay := 10 * time.Millisecond
- for {
- time.Sleep(delay)
- if delay < 100*time.Millisecond {
- delay *= 2
- }
- resp, err := http.Get(readyURL)
- if err != nil {
- continue
- }
- if resp.StatusCode == 200 {
- break
- }
- }
- ready <- struct{}{}
- }()
-
- // Wait for the roomserver to be ready to receive input or for it to crash.
- select {
- case <-ready:
- case r := <-done:
- return nil, r.err
- }
-
- // Write the input now that the server is running.
- doInput()
-
- // Wait for one of the tasks to finsh.
- r := <-done
-
- if r.err != nil {
- return nil, r.err
- }
-
- // The kafka console consumer writes a newline character after each message.
- // So we split on newline characters
- lines := strings.Split(string(r.data), "\n")
- if len(lines) > 0 {
- // Remove the blank line at the end of the data.
- lines = lines[:len(lines)-1]
- }
- return lines, nil
-}
-
-func writeToRoomServer(input []string, roomserverURL string) error {
- var request api.InputRoomEventsRequest
- var response api.InputRoomEventsResponse
- var err error
- request.InputRoomEvents = make([]api.InputRoomEvent, len(input))
- for i := range input {
- if err = json.Unmarshal([]byte(input[i]), &request.InputRoomEvents[i]); err != nil {
- return err
- }
- }
- x, err := inthttp.NewRoomserverClient(roomserverURL, &http.Client{Timeout: timeoutHTTP}, nil)
- if err != nil {
- return err
- }
- x.InputRoomEvents(context.Background(), &request, &response)
- return response.Err()
-}
-
-// testRoomserver is used to run integration tests against a single roomserver.
-// It creates new kafka topics for the input and output of the roomserver.
-// It writes the input messages to the input kafka topic, formatting each message
-// as canonical JSON so that it fits on a single line.
-// It then runs the roomserver and waits for a number of messages to be written
-// to the output topic.
-// Once those messages have been written it runs the checkQueries function passing
-// a api.RoomserverQueryAPI client. The caller can use this function to check the
-// behaviour of the query API.
-func testRoomserver(input []string, wantOutput []string, checkQueries func(api.RoomserverInternalAPI)) {
- dir, err := ioutil.TempDir("", "room-server-test")
- if err != nil {
- panic(err)
- }
-
- cfg, _, err := test.MakeConfig(dir, kafkaURI, testDatabase, "localhost", 10000)
- if err != nil {
- panic(err)
- }
- if err = test.WriteConfig(cfg, dir); err != nil {
- panic(err)
- }
-
- outputTopic := cfg.Global.Kafka.TopicFor(config.TopicOutputRoomEvent)
-
- err = exe.DeleteTopic(outputTopic)
- if err != nil {
- panic(err)
- }
-
- if err = exe.CreateTopic(outputTopic); err != nil {
- panic(err)
- }
-
- if err = createDatabase(testDatabaseName); err != nil {
- panic(err)
- }
-
- cache, err := caching.NewInMemoryLRUCache(false)
- if err != nil {
- panic(err)
- }
-
- doInput := func() {
- fmt.Printf("Roomserver is ready to receive input, sending %d events\n", len(input))
- if err = writeToRoomServer(input, cfg.RoomServerURL()); err != nil {
- panic(err)
- }
- }
-
- cmd := exec.Command(filepath.Join(filepath.Dir(os.Args[0]), "dendrite-room-server"))
-
- // Append the roomserver config to the existing environment.
- // We append to the environment rather than replacing so that any additional
- // postgres and golang environment variables such as PGHOST are passed to
- // the roomserver process.
- cmd.Stderr = os.Stderr
- cmd.Args = []string{"dendrite-room-server", "--config", filepath.Join(dir, test.ConfigFile)}
-
- gotOutput, err := runAndReadFromTopic(cmd, cfg.RoomServerURL()+"/metrics", doInput, outputTopic, len(wantOutput), func() {
- queryAPI, _ := inthttp.NewRoomserverClient("http://"+string(cfg.RoomServer.InternalAPI.Connect), &http.Client{Timeout: timeoutHTTP}, cache)
- checkQueries(queryAPI)
- })
- if err != nil {
- panic(err)
- }
-
- if len(wantOutput) != len(gotOutput) {
- panic(fmt.Errorf("Wanted %d lines of output got %d lines", len(wantOutput), len(gotOutput)))
- }
-
- for i := range wantOutput {
- if !equalJSON(wantOutput[i], gotOutput[i]) {
- panic(fmt.Errorf("Wanted %q at index %d got %q", wantOutput[i], i, gotOutput[i]))
- }
- }
-}
-
-func equalJSON(a, b string) bool {
- canonicalA, err := gomatrixserverlib.CanonicalJSON([]byte(a))
- if err != nil {
- panic(err)
- }
- canonicalB, err := gomatrixserverlib.CanonicalJSON([]byte(b))
- if err != nil {
- panic(err)
- }
- return string(canonicalA) == string(canonicalB)
-}
-
-func main() {
- fmt.Println("==TESTING==", os.Args[0])
-
- input := []string{
- `{
- "auth_event_ids": [],
- "kind": 1,
- "event": {
- "origin": "matrix.org",
- "signatures": {
- "matrix.org": {
- "ed25519:auto": "3kXGwNtdj+zqEXlI8PWLiB76xtrQ7SxcvPuXAEVCTo+QPoBoUvLi1RkHs6O5mDz7UzIowK5bi1seAN4vOh0OBA"
- }
- },
- "origin_server_ts": 1463671337837,
- "sender": "@richvdh:matrix.org",
- "event_id": "$1463671337126266wrSBX:matrix.org",
- "prev_events": [],
- "state_key": "",
- "content": {"creator": "@richvdh:matrix.org"},
- "depth": 1,
- "prev_state": [],
- "room_id": "!HCXfdvrfksxuYnIFiJ:matrix.org",
- "auth_events": [],
- "hashes": {"sha256": "Q05VLC8nztN2tguy+KnHxxhitI95wK9NelnsDaXRqeo"},
- "type": "m.room.create"}
- }`, `{
- "auth_event_ids": ["$1463671337126266wrSBX:matrix.org"],
- "kind": 2,
- "state_event_ids": ["$1463671337126266wrSBX:matrix.org"],
- "event": {
- "origin": "matrix.org",
- "signatures": {
- "matrix.org": {
- "ed25519:auto": "a2b3xXYVPPFeG1sHCU3hmZnAaKqZFgzGZozijRGblG5Y//ewRPAn1A2mCrI2UM5I+0zqr70cNpHgF8bmNFu4BA"
- }
- },
- "origin_server_ts": 1463671339844,
- "sender": "@richvdh:matrix.org",
- "event_id": "$1463671339126270PnVwC:matrix.org",
- "prev_events": [[
- "$1463671337126266wrSBX:matrix.org", {"sha256": "h/VS07u8KlMwT3Ee8JhpkC7sa1WUs0Srgs+l3iBv6c0"}
- ]],
- "membership": "join",
- "state_key": "@richvdh:matrix.org",
- "content": {
- "membership": "join",
- "avatar_url": "mxc://matrix.org/ZafPzsxMJtLaSaJXloBEKiws",
- "displayname": "richvdh"
- },
- "depth": 2,
- "prev_state": [],
- "room_id": "!HCXfdvrfksxuYnIFiJ:matrix.org",
- "auth_events": [[
- "$1463671337126266wrSBX:matrix.org", {"sha256": "h/VS07u8KlMwT3Ee8JhpkC7sa1WUs0Srgs+l3iBv6c0"}
- ]],
- "hashes": {"sha256": "t9t3sZV1Eu0P9Jyrs7pge6UTa1zuTbRdVxeUHnrQVH0"},
- "type": "m.room.member"},
- "has_state": true
- }`,
- }
-
- want := []string{
- `{"type":"new_room_event","new_room_event":{
- "event":{
- "auth_events":[[
- "$1463671337126266wrSBX:matrix.org",{"sha256":"h/VS07u8KlMwT3Ee8JhpkC7sa1WUs0Srgs+l3iBv6c0"}
- ]],
- "content":{
- "avatar_url":"mxc://matrix.org/ZafPzsxMJtLaSaJXloBEKiws",
- "displayname":"richvdh",
- "membership":"join"
- },
- "depth": 2,
- "event_id": "$1463671339126270PnVwC:matrix.org",
- "hashes": {"sha256":"t9t3sZV1Eu0P9Jyrs7pge6UTa1zuTbRdVxeUHnrQVH0"},
- "membership": "join",
- "origin": "matrix.org",
- "origin_server_ts": 1463671339844,
- "prev_events": [[
- "$1463671337126266wrSBX:matrix.org",{"sha256":"h/VS07u8KlMwT3Ee8JhpkC7sa1WUs0Srgs+l3iBv6c0"}
- ]],
- "prev_state":[],
- "room_id":"!HCXfdvrfksxuYnIFiJ:matrix.org",
- "sender":"@richvdh:matrix.org",
- "signatures":{
- "matrix.org":{
- "ed25519:auto":"a2b3xXYVPPFeG1sHCU3hmZnAaKqZFgzGZozijRGblG5Y//ewRPAn1A2mCrI2UM5I+0zqr70cNpHgF8bmNFu4BA"
- }
- },
- "state_key":"@richvdh:matrix.org",
- "type":"m.room.member"
- },
- "state_before_removes_event_ids":["$1463671339126270PnVwC:matrix.org"],
- "state_before_adds_event_ids":null,
- "latest_event_ids":["$1463671339126270PnVwC:matrix.org"],
- "adds_state_event_ids":["$1463671337126266wrSBX:matrix.org", "$1463671339126270PnVwC:matrix.org"],
- "removes_state_event_ids":null,
- "last_sent_event_id":"",
- "send_as_server":"",
- "transaction_id": null
- }}`,
- }
-
- testRoomserver(input, want, func(q api.RoomserverInternalAPI) {
- var response api.QueryLatestEventsAndStateResponse
- if err := q.QueryLatestEventsAndState(
- context.Background(),
- &api.QueryLatestEventsAndStateRequest{
- RoomID: "!HCXfdvrfksxuYnIFiJ:matrix.org",
- StateToFetch: []gomatrixserverlib.StateKeyTuple{
- {EventType: "m.room.member", StateKey: "@richvdh:matrix.org"},
- },
- },
- &response,
- ); err != nil {
- panic(err)
- }
- if !response.RoomExists {
- panic(fmt.Errorf(`Wanted room "!HCXfdvrfksxuYnIFiJ:matrix.org" to exist`))
- }
- if len(response.LatestEvents) != 1 || response.LatestEvents[0].EventID != "$1463671339126270PnVwC:matrix.org" {
- panic(fmt.Errorf(`Wanted "$1463671339126270PnVwC:matrix.org" to be the latest event got %#v`, response.LatestEvents))
- }
- if len(response.StateEvents) != 1 || response.StateEvents[0].EventID() != "$1463671339126270PnVwC:matrix.org" {
- panic(fmt.Errorf(`Wanted "$1463671339126270PnVwC:matrix.org" to be the state event got %#v`, response.StateEvents))
- }
- })
-
- fmt.Println("==PASSED==", os.Args[0])
-}
diff --git a/cmd/syncserver-integration-tests/main.go b/cmd/syncserver-integration-tests/main.go
deleted file mode 100644
index 332bde10..00000000
--- a/cmd/syncserver-integration-tests/main.go
+++ /dev/null
@@ -1,563 +0,0 @@
-// Copyright 2017 Vector Creations Ltd
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "encoding/json"
- "fmt"
- "io/ioutil"
- "net/http"
- "os"
- "os/exec"
- "path/filepath"
- "time"
-
- "github.com/matrix-org/dendrite/internal/test"
- "github.com/matrix-org/dendrite/roomserver/api"
- "github.com/matrix-org/dendrite/setup/config"
- "github.com/matrix-org/gomatrixserverlib"
-)
-
-var (
- // Path to where kafka is installed.
- kafkaDir = test.Defaulting(os.Getenv("KAFKA_DIR"), "kafka")
- // The URI the kafka zookeeper is listening on.
- zookeeperURI = test.Defaulting(os.Getenv("ZOOKEEPER_URI"), "localhost:2181")
- // The URI the kafka server is listening on.
- kafkaURI = test.Defaulting(os.Getenv("KAFKA_URIS"), "localhost:9092")
- // The address the syncserver should listen on.
- syncserverAddr = test.Defaulting(os.Getenv("SYNCSERVER_URI"), "localhost:9876")
- // How long to wait for the syncserver to write the expected output messages.
- // This needs to be high enough to account for the time it takes to create
- // the postgres database tables which can take a while on travis.
- timeoutString = test.Defaulting(os.Getenv("TIMEOUT"), "10s")
- // The name of maintenance database to connect to in order to create the test database.
- postgresDatabase = test.Defaulting(os.Getenv("POSTGRES_DATABASE"), "postgres")
- // Postgres docker container name (for running psql). If not set, psql must be in PATH.
- postgresContainerName = os.Getenv("POSTGRES_CONTAINER")
- // The name of the test database to create.
- testDatabaseName = test.Defaulting(os.Getenv("DATABASE_NAME"), "syncserver_test")
- // The postgres connection config for connecting to the test database.
- testDatabase = test.Defaulting(os.Getenv("DATABASE"), fmt.Sprintf("dbname=%s sslmode=disable binary_parameters=yes", testDatabaseName))
-)
-
-const inputTopic = "syncserverInput"
-const clientTopic = "clientapiserverOutput"
-
-var exe = test.KafkaExecutor{
- ZookeeperURI: zookeeperURI,
- KafkaDirectory: kafkaDir,
- KafkaURI: kafkaURI,
- // Send stdout and stderr to our stderr so that we see error messages from
- // the kafka process.
- OutputWriter: os.Stderr,
-}
-
-var timeout time.Duration
-var clientEventTestData []string
-
-func init() {
- var err error
- timeout, err = time.ParseDuration(timeoutString)
- if err != nil {
- panic(err)
- }
-
- for _, s := range outputRoomEventTestData {
- clientEventTestData = append(clientEventTestData, clientEventJSONForOutputRoomEvent(s))
- }
-}
-
-func createTestUser(database, username, token string) error {
- cmd := exec.Command(
- filepath.Join(filepath.Dir(os.Args[0]), "create-account"),
- "--database", database,
- "--username", username,
- "--token", token,
- )
-
- // Send stdout and stderr to our stderr so that we see error messages from
- // the create-account process
- cmd.Stdout = os.Stderr
- cmd.Stderr = os.Stderr
- return cmd.Run()
-}
-
-// clientEventJSONForOutputRoomEvent parses the given output room event and extracts the 'Event' JSON. It is
-// trimmed to the client format and then canonicalised and returned as a string.
-// Panics if there are any problems.
-func clientEventJSONForOutputRoomEvent(outputRoomEvent string) string {
- var out api.OutputEvent
- if err := json.Unmarshal([]byte(outputRoomEvent), &out); err != nil {
- panic("failed to unmarshal output room event: " + err.Error())
- }
- clientEvs := gomatrixserverlib.ToClientEvents([]*gomatrixserverlib.Event{
- out.NewRoomEvent.Event.Event,
- }, gomatrixserverlib.FormatSync)
- b, err := json.Marshal(clientEvs[0])
- if err != nil {
- panic("failed to marshal client event as json: " + err.Error())
- }
- jsonBytes, err := gomatrixserverlib.CanonicalJSON(b)
- if err != nil {
- panic("failed to turn event json into canonical json: " + err.Error())
- }
- return string(jsonBytes)
-}
-
-// startSyncServer creates the database and config file needed for the sync server to run and
-// then starts the sync server. The Cmd being executed is returned. A channel is also returned,
-// which will have any termination errors sent down it, followed immediately by the channel being closed.
-func startSyncServer() (*exec.Cmd, chan error) {
-
- dir, err := ioutil.TempDir("", "syncapi-server-test")
- if err != nil {
- panic(err)
- }
-
- cfg, _, err := test.MakeConfig(dir, kafkaURI, testDatabase, "localhost", 10000)
- if err != nil {
- panic(err)
- }
- // TODO use the address assigned by the config generator rather than clobbering.
- cfg.Global.ServerName = "localhost"
- cfg.SyncAPI.InternalAPI.Listen = config.HTTPAddress("http://" + syncserverAddr)
- cfg.SyncAPI.InternalAPI.Connect = cfg.SyncAPI.InternalAPI.Listen
-
- if err := test.WriteConfig(cfg, dir); err != nil {
- panic(err)
- }
-
- serverArgs := []string{
- "--config", filepath.Join(dir, test.ConfigFile),
- }
-
- databases := []string{
- testDatabaseName,
- }
-
- test.InitDatabase(
- postgresDatabase,
- postgresContainerName,
- databases,
- )
-
- if err := createTestUser(testDatabase, "alice", "@alice:localhost"); err != nil {
- panic(err)
- }
- if err := createTestUser(testDatabase, "bob", "@bob:localhost"); err != nil {
- panic(err)
- }
- if err := createTestUser(testDatabase, "charlie", "@charlie:localhost"); err != nil {
- panic(err)
- }
-
- cmd, cmdChan := test.CreateBackgroundCommand(
- filepath.Join(filepath.Dir(os.Args[0]), "dendrite-sync-api-server"),
- serverArgs,
- )
-
- return cmd, cmdChan
-}
-
-// prepareKafka creates the topics which will be written to by the tests.
-func prepareKafka() {
- err := exe.DeleteTopic(inputTopic)
- if err != nil {
- panic(err)
- }
-
- if err = exe.CreateTopic(inputTopic); err != nil {
- panic(err)
- }
-
- err = exe.DeleteTopic(clientTopic)
- if err != nil {
- panic(err)
- }
-
- if err = exe.CreateTopic(clientTopic); err != nil {
- panic(err)
- }
-}
-
-func testSyncServer(syncServerCmdChan chan error, userID, since, want string) {
- fmt.Printf("==TESTING== testSyncServer(%s,%s)\n", userID, since)
- sinceQuery := ""
- if since != "" {
- sinceQuery = "&since=" + since
- }
- req, err := http.NewRequest(
- "GET",
- "http://"+syncserverAddr+"/api/_matrix/client/r0/sync?timeout=100&access_token="+userID+sinceQuery,
- nil,
- )
- if err != nil {
- panic(err)
- }
- testReq := &test.Request{
- Req: req,
- WantedStatusCode: 200,
- WantedBody: test.CanonicalJSONInput([]string{want})[0],
- }
- testReq.Run("sync-api", timeout, syncServerCmdChan)
-}
-
-func writeToRoomServerLog(indexes ...int) {
- var roomEvents []string
- for _, i := range indexes {
- roomEvents = append(roomEvents, outputRoomEventTestData[i])
- }
- if err := exe.WriteToTopic(inputTopic, test.CanonicalJSONInput(roomEvents)); err != nil {
- panic(err)
- }
-}
-
-// Runs a battery of sync server tests against test data in testdata.go
-// testdata.go has a list of OutputRoomEvents which will be fed into the kafka log which the sync server will consume.
-// The tests will pause at various points in this list to conduct tests on the /sync responses before continuing.
-// For ease of understanding, the curl commands used to create the OutputRoomEvents are listed along with each write to kafka.
-func main() {
- fmt.Println("==TESTING==", os.Args[0])
- prepareKafka()
- cmd, syncServerCmdChan := startSyncServer()
- // ensure server is dead, only cleaning up so don't care about errors this returns.
- defer cmd.Process.Kill() // nolint: errcheck
-
- // $ curl -XPOST -d '{}' "http://localhost:8009/_matrix/client/r0/createRoom?access_token=@alice:localhost"
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"hello world"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/1?access_token=@alice:localhost"
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"hello world 2"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/2?access_token=@alice:localhost"
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"hello world 3"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/3?access_token=@alice:localhost"
- // $ curl -XPUT -d '{"name":"Custom Room Name"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.name?access_token=@alice:localhost"
- writeToRoomServerLog(
- i0StateRoomCreate, i1StateAliceJoin, i2StatePowerLevels, i3StateJoinRules, i4StateHistoryVisibility,
- i5AliceMsg, i6AliceMsg, i7AliceMsg, i8StateAliceRoomName,
- )
-
- // Make sure initial sync works TODO: prev_batch
- testSyncServer(syncServerCmdChan, "@alice:localhost", "", `{
- "account_data": {
- "events": []
- },
- "next_batch": "9",
- "presence": {
- "events": []
- },
- "rooms": {
- "invite": {},
- "join": {
- "!PjrbIMW2cIiaYF4t:localhost": {
- "account_data": {
- "events": []
- },
- "ephemeral": {
- "events": []
- },
- "state": {
- "events": []
- },
- "timeline": {
- "events": [`+
- clientEventTestData[i0StateRoomCreate]+","+
- clientEventTestData[i1StateAliceJoin]+","+
- clientEventTestData[i2StatePowerLevels]+","+
- clientEventTestData[i3StateJoinRules]+","+
- clientEventTestData[i4StateHistoryVisibility]+","+
- clientEventTestData[i5AliceMsg]+","+
- clientEventTestData[i6AliceMsg]+","+
- clientEventTestData[i7AliceMsg]+","+
- clientEventTestData[i8StateAliceRoomName]+`],
- "limited": true,
- "prev_batch": ""
- }
- }
- },
- "leave": {}
- }
- }`)
- // Make sure alice's rooms don't leak to bob
- testSyncServer(syncServerCmdChan, "@bob:localhost", "", `{
- "account_data": {
- "events": []
- },
- "next_batch": "9",
- "presence": {
- "events": []
- },
- "rooms": {
- "invite": {},
- "join": {},
- "leave": {}
- }
- }`)
- // Make sure polling with an up-to-date token returns nothing new
- testSyncServer(syncServerCmdChan, "@alice:localhost", "9", `{
- "account_data": {
- "events": []
- },
- "next_batch": "9",
- "presence": {
- "events": []
- },
- "rooms": {
- "invite": {},
- "join": {},
- "leave": {}
- }
- }`)
-
- // $ curl -XPUT -d '{"membership":"join"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.member/@bob:localhost?access_token=@bob:localhost"
- writeToRoomServerLog(i9StateBobJoin)
-
- // Make sure alice sees it TODO: prev_batch
- testSyncServer(syncServerCmdChan, "@alice:localhost", "9", `{
- "account_data": {
- "events": []
- },
- "next_batch": "10",
- "presence": {
- "events": []
- },
- "rooms": {
- "invite": {},
- "join": {
- "!PjrbIMW2cIiaYF4t:localhost": {
- "account_data": {
- "events": []
- },
- "ephemeral": {
- "events": []
- },
- "state": {
- "events": []
- },
- "timeline": {
- "limited": false,
- "prev_batch": "",
- "events": [`+clientEventTestData[i9StateBobJoin]+`]
- }
- }
- },
- "leave": {}
- }
- }`)
-
- // Make sure bob sees the room AND all the current room state TODO: history visibility
- testSyncServer(syncServerCmdChan, "@bob:localhost", "9", `{
- "account_data": {
- "events": []
- },
- "next_batch": "10",
- "presence": {
- "events": []
- },
- "rooms": {
- "invite": {},
- "join": {
- "!PjrbIMW2cIiaYF4t:localhost": {
- "account_data": {
- "events": []
- },
- "ephemeral": {
- "events": []
- },
- "state": {
- "events": [`+
- clientEventTestData[i0StateRoomCreate]+","+
- clientEventTestData[i1StateAliceJoin]+","+
- clientEventTestData[i2StatePowerLevels]+","+
- clientEventTestData[i3StateJoinRules]+","+
- clientEventTestData[i4StateHistoryVisibility]+","+
- clientEventTestData[i8StateAliceRoomName]+`]
- },
- "timeline": {
- "limited": false,
- "prev_batch": "",
- "events": [`+
- clientEventTestData[i9StateBobJoin]+`]
- }
- }
- },
- "leave": {}
- }
- }`)
-
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"hello alice"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/1?access_token=@bob:localhost"
- writeToRoomServerLog(i10BobMsg)
-
- // Make sure alice can see everything around the join point for bob TODO: prev_batch
- testSyncServer(syncServerCmdChan, "@alice:localhost", "7", `{
- "account_data": {
- "events": []
- },
- "next_batch": "11",
- "presence": {
- "events": []
- },
- "rooms": {
- "invite": {},
- "join": {
- "!PjrbIMW2cIiaYF4t:localhost": {
- "account_data": {
- "events": []
- },
- "ephemeral": {
- "events": []
- },
- "state": {
- "events": []
- },
- "timeline": {
- "limited": false,
- "prev_batch": "",
- "events": [`+
- clientEventTestData[i7AliceMsg]+","+
- clientEventTestData[i8StateAliceRoomName]+","+
- clientEventTestData[i9StateBobJoin]+","+
- clientEventTestData[i10BobMsg]+`]
- }
- }
- },
- "leave": {}
- }
- }`)
-
- // $ curl -XPUT -d '{"name":"A Different Custom Room Name"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.name?access_token=@alice:localhost"
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"hello bob"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/2?access_token=@alice:localhost"
- // $ curl -XPUT -d '{"membership":"invite"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.member/@charlie:localhost?access_token=@bob:localhost"
- writeToRoomServerLog(i11StateAliceRoomName, i12AliceMsg, i13StateBobInviteCharlie)
-
- // Make sure charlie sees the invite both with and without a ?since= token
- // TODO: Invite state should include the invite event and the room name.
- charlieInviteData := `{
- "account_data": {
- "events": []
- },
- "next_batch": "14",
- "presence": {
- "events": []
- },
- "rooms": {
- "invite": {
- "!PjrbIMW2cIiaYF4t:localhost": {
- "invite_state": {
- "events": []
- }
- }
- },
- "join": {},
- "leave": {}
- }
- }`
- testSyncServer(syncServerCmdChan, "@charlie:localhost", "7", charlieInviteData)
- testSyncServer(syncServerCmdChan, "@charlie:localhost", "", charlieInviteData)
-
- // $ curl -XPUT -d '{"membership":"join"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.member/@charlie:localhost?access_token=@charlie:localhost"
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"not charlie..."}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/3?access_token=@alice:localhost"
- // $ curl -XPUT -d '{"membership":"leave"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.member/@charlie:localhost?access_token=@alice:localhost"
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"why did you kick charlie"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/3?access_token=@bob:localhost"
- writeToRoomServerLog(i14StateCharlieJoin, i15AliceMsg, i16StateAliceKickCharlie, i17BobMsg)
-
- // Check transitions to leave work
- testSyncServer(syncServerCmdChan, "@charlie:localhost", "15", `{
- "account_data": {
- "events": []
- },
- "next_batch": "18",
- "presence": {
- "events": []
- },
- "rooms": {
- "invite": {},
- "join": {},
- "leave": {
- "!PjrbIMW2cIiaYF4t:localhost": {
- "state": {
- "events": []
- },
- "timeline": {
- "limited": false,
- "prev_batch": "",
- "events": [`+
- clientEventTestData[i15AliceMsg]+","+
- clientEventTestData[i16StateAliceKickCharlie]+`]
- }
- }
- }
- }
- }`)
-
- // Test joining and leaving the same room in a single /sync request puts the room in the 'leave' section.
- // TODO: Use an earlier since value to assert that the /sync response doesn't leak messages
- // from before charlie was joined to the room. Currently it does leak because RecentEvents doesn't
- // take membership into account.
- testSyncServer(syncServerCmdChan, "@charlie:localhost", "14", `{
- "account_data": {
- "events": []
- },
- "next_batch": "18",
- "presence": {
- "events": []
- },
- "rooms": {
- "invite": {},
- "join": {},
- "leave": {
- "!PjrbIMW2cIiaYF4t:localhost": {
- "state": {
- "events": []
- },
- "timeline": {
- "limited": false,
- "prev_batch": "",
- "events": [`+
- clientEventTestData[i14StateCharlieJoin]+","+
- clientEventTestData[i15AliceMsg]+","+
- clientEventTestData[i16StateAliceKickCharlie]+`]
- }
- }
- }
- }
- }`)
-
- // $ curl -XPUT -d '{"name":"No Charlies"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.name?access_token=@alice:localhost"
- writeToRoomServerLog(i18StateAliceRoomName)
-
- // Check that users don't see state changes in rooms after they have left
- testSyncServer(syncServerCmdChan, "@charlie:localhost", "17", `{
- "account_data": {
- "events": []
- },
- "next_batch": "19",
- "presence": {
- "events": []
- },
- "rooms": {
- "invite": {},
- "join": {},
- "leave": {}
- }
- }`)
-
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"whatever"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/3?access_token=@bob:localhost"
- // $ curl -XPUT -d '{"membership":"leave"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.member/@bob:localhost?access_token=@bob:localhost"
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"im alone now"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/3?access_token=@alice:localhost"
- // $ curl -XPUT -d '{"membership":"invite"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.member/@bob:localhost?access_token=@alice:localhost"
- // $ curl -XPUT -d '{"membership":"leave"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.member/@bob:localhost?access_token=@bob:localhost"
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"so alone"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/3?access_token=@alice:localhost"
- // $ curl -XPUT -d '{"name":"Everyone welcome"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.name?access_token=@alice:localhost"
- // $ curl -XPUT -d '{"membership":"join"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.member/@charlie:localhost?access_token=@charlie:localhost"
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"hiiiii"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/3?access_token=@charlie:localhost"
-}
diff --git a/cmd/syncserver-integration-tests/testdata.go b/cmd/syncserver-integration-tests/testdata.go
deleted file mode 100644
index 4ff5d1ee..00000000
--- a/cmd/syncserver-integration-tests/testdata.go
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2017 Vector Creations Ltd
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-// nolint: varcheck, deadcode, unused, megacheck
-const (
- i0StateRoomCreate = iota
- i1StateAliceJoin
- i2StatePowerLevels
- i3StateJoinRules
- i4StateHistoryVisibility
- i5AliceMsg
- i6AliceMsg
- i7AliceMsg
- i8StateAliceRoomName
- i9StateBobJoin
- i10BobMsg
- i11StateAliceRoomName
- i12AliceMsg
- i13StateBobInviteCharlie
- i14StateCharlieJoin
- i15AliceMsg
- i16StateAliceKickCharlie
- i17BobMsg
- i18StateAliceRoomName
- i19BobMsg
- i20StateBobLeave
- i21AliceMsg
- i22StateAliceInviteBob
- i23StateBobRejectInvite
- i24AliceMsg
- i25StateAliceRoomName
- i26StateCharlieJoin
- i27CharlieMsg
-)
-
-var outputRoomEventTestData = []string{
- // $ curl -XPOST -d '{}' "http://localhost:8009/_matrix/client/r0/createRoom?access_token=@alice:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[],"content":{"creator":"@alice:localhost"},"depth":1,"event_id":"$xz0fUB8zNMTGFh1W:localhost","hashes":{"sha256":"KKkpxS8NoH0igBbL3J+nJ39MRlmA7QgW4BGL7Fv4ASI"},"origin":"localhost","origin_server_ts":1494411218382,"prev_events":[],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"uZG5Q/Hs2Z611gFlZPdwomomRJKf70xV2FQV+gLWM1XgzkLDRlRF3cBZc9y3CnHKnV/upTcXs7Op2/GmgD3UBw"}},"state_key":"","type":"m.room.create"},"latest_event_ids":["$xz0fUB8zNMTGFh1W:localhost"],"adds_state_event_ids":["$xz0fUB8zNMTGFh1W:localhost"],"last_sent_event_id":""}}`,
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}]],"content":{"membership":"join"},"depth":2,"event_id":"$QTen1vksfcRTpUCk:localhost","hashes":{"sha256":"tTukc9ab1fJfzgc5EMA/UD3swqfl/ic9Y9Zkt4fJo0Q"},"origin":"localhost","origin_server_ts":1494411218385,"prev_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"OPysDn/wT7yHeALXLTcEgR+iaKjv0p7VPuR/Mzvyg2IMAwPUjSOw8SQZlhSioWRtVPUp9VHbhIhJxQaPUg9yBQ"}},"state_key":"@alice:localhost","type":"m.room.member"},"latest_event_ids":["$QTen1vksfcRTpUCk:localhost"],"adds_state_event_ids":["$QTen1vksfcRTpUCk:localhost"],"last_sent_event_id":"$xz0fUB8zNMTGFh1W:localhost"}}`,
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$QTen1vksfcRTpUCk:localhost",{"sha256":"znwhbYzdueh0grYkUX4jgXmP9AjKphzyesMZWMiF4IY"}]],"content":{"ban":50,"events":{"m.room.avatar":50,"m.room.canonical_alias":50,"m.room.history_visibility":100,"m.room.name":50,"m.room.power_levels":100},"events_default":0,"invite":0,"kick":50,"redact":50,"state_default":50,"users":{"@alice:localhost":100},"users_default":0},"depth":3,"event_id":"$RWsxGlfPHAcijTgu:localhost","hashes":{"sha256":"ueZWiL/Q8bagRQGFktpnYJAJV6V6U3QKcUEmWYeyaaM"},"origin":"localhost","origin_server_ts":1494411218385,"prev_events":[["$QTen1vksfcRTpUCk:localhost",{"sha256":"znwhbYzdueh0grYkUX4jgXmP9AjKphzyesMZWMiF4IY"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"hZwWx3lyW61zMYmqLOxLTlfW2CnbjJQsZPLjZFa97TVG4ISz8CixMPsnVAIu5is29UCmiHyP8RvLecJjbLCtAQ"}},"state_key":"","type":"m.room.power_levels"},"latest_event_ids":["$RWsxGlfPHAcijTgu:localhost"],"adds_state_event_ids":["$RWsxGlfPHAcijTgu:localhost"],"last_sent_event_id":"$QTen1vksfcRTpUCk:localhost"}}`,
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}],["$QTen1vksfcRTpUCk:localhost",{"sha256":"znwhbYzdueh0grYkUX4jgXmP9AjKphzyesMZWMiF4IY"}]],"content":{"join_rule":"public"},"depth":4,"event_id":"$2O2DpHB37CuwwJOe:localhost","hashes":{"sha256":"3P3HxAXI8gc094i020EoV/gissYiMVWv8+JAbrakM4E"},"origin":"localhost","origin_server_ts":1494411218386,"prev_events":[["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"L2yZoBbG/6TNsRHz+UtHY0SK4FgrdAYPR1l7RBWaNFbm+k/7kVhnoGlJ9yptpdLJjPMR2InqKXH8BBxRC83BCg"}},"state_key":"","type":"m.room.join_rules"},"latest_event_ids":["$2O2DpHB37CuwwJOe:localhost"],"adds_state_event_ids":["$2O2DpHB37CuwwJOe:localhost"],"last_sent_event_id":"$RWsxGlfPHAcijTgu:localhost"}}`,
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}],["$QTen1vksfcRTpUCk:localhost",{"sha256":"znwhbYzdueh0grYkUX4jgXmP9AjKphzyesMZWMiF4IY"}]],"content":{"history_visibility":"joined"},"depth":5,"event_id":"$5LRiBskVCROnL5WY:localhost","hashes":{"sha256":"341alVufcKSVKLPr9WsJNTnW33QkBTn9eTfVWbyoa0o"},"origin":"localhost","origin_server_ts":1494411218387,"prev_events":[["$2O2DpHB37CuwwJOe:localhost",{"sha256":"ulaRD63dbCyolLTwvInIQpcrtU2c7ex/BHmhpLXAUoE"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"kRyt68cstwYgK8NtYzf0V5CnAbqUO47ixCCWYzRCi0WNstEwUw4XW1GHc8BllQsXwSj+nNv9g/66zZgG0DtxCA"}},"state_key":"","type":"m.room.history_visibility"},"latest_event_ids":["$5LRiBskVCROnL5WY:localhost"],"adds_state_event_ids":["$5LRiBskVCROnL5WY:localhost"],"last_sent_event_id":"$2O2DpHB37CuwwJOe:localhost"}}`,
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"hello world"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/1?access_token=@alice:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$QTen1vksfcRTpUCk:localhost",{"sha256":"znwhbYzdueh0grYkUX4jgXmP9AjKphzyesMZWMiF4IY"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}]],"content":{"body":"hello world","msgtype":"m.text"},"depth":0,"event_id":"$Z8ZJik7ghwzSYTH9:localhost","hashes":{"sha256":"ahN1T5aiSZCzllf0pqNWJkF+x2h2S3kic+40pQ1X6BE"},"origin":"localhost","origin_server_ts":1494411339207,"prev_events":[["$5LRiBskVCROnL5WY:localhost",{"sha256":"3jULNC9b9Q0AhvnDQqpjhbtYwmkioHzPzdTJZvn8vOI"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"ylEpahRwEfGpqk+UCv0IF8YAxmut7w7udgHy3sVDfdJhs/4uJ6EkFEsKLknpXRc1vTIy1etKCBQ63QbCmRC2Bw"}},"type":"m.room.message"},"latest_event_ids":["$Z8ZJik7ghwzSYTH9:localhost"],"last_sent_event_id":"$5LRiBskVCROnL5WY:localhost"}}`,
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"hello world 2"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/2?access_token=@alice:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$QTen1vksfcRTpUCk:localhost",{"sha256":"znwhbYzdueh0grYkUX4jgXmP9AjKphzyesMZWMiF4IY"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}]],"content":{"body":"hello world 2","msgtype":"m.text"},"depth":0,"event_id":"$8382Ah682eL4hxjN:localhost","hashes":{"sha256":"hQElDGSYc6KOdylrbMMm3+LlvUiCKo6S9G9n58/qtns"},"origin":"localhost","origin_server_ts":1494411380282,"prev_events":[["$Z8ZJik7ghwzSYTH9:localhost",{"sha256":"FBDwP+2FeqDENe7AEa3iAFAVKl1/IVq43mCH0uPRn90"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"LFXi6jTG7qn9xzi4rhIiHbkLD+4AZ9Yg7UTS2gqm1gt2lXQsgTYH1wE4Fol2fq4lvGlQVpxhtEr2huAYSbT7DA"}},"type":"m.room.message"},"latest_event_ids":["$8382Ah682eL4hxjN:localhost"],"last_sent_event_id":"$Z8ZJik7ghwzSYTH9:localhost"}}`,
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"hello world 3"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/3?access_token=@alice:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$QTen1vksfcRTpUCk:localhost",{"sha256":"znwhbYzdueh0grYkUX4jgXmP9AjKphzyesMZWMiF4IY"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}]],"content":{"body":"hello world 3","msgtype":"m.text"},"depth":0,"event_id":"$17SfHsvSeTQthSWF:localhost","hashes":{"sha256":"eS6VFQI0l2U8rA8U17jgSHr9lQ73SNSnlnZu+HD0IjE"},"origin":"localhost","origin_server_ts":1494411396560,"prev_events":[["$8382Ah682eL4hxjN:localhost",{"sha256":"c6I/PUY7WnvxQ+oUEp/w2HEEuD3g8Vq7QwPUOSUjuc8"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"dvu9bSHZmX+yZoEqHioK7YDMtLH9kol0DdFqc5aHsbhZe/fKRZpfJMrlf1iXQdXSCMhikvnboPAXN3guiZCUBQ"}},"type":"m.room.message"},"latest_event_ids":["$17SfHsvSeTQthSWF:localhost"],"last_sent_event_id":"$8382Ah682eL4hxjN:localhost"}}`,
- // $ curl -XPUT -d '{"name":"Custom Room Name"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.name?access_token=@alice:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$QTen1vksfcRTpUCk:localhost",{"sha256":"znwhbYzdueh0grYkUX4jgXmP9AjKphzyesMZWMiF4IY"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}]],"content":{"name":"Custom Room Name"},"depth":0,"event_id":"$j7KtuOzM0K15h3Kr:localhost","hashes":{"sha256":"QIKj5Klr50ugll4EjaNUATJmrru4CDp6TvGPv0v15bo"},"origin":"localhost","origin_server_ts":1494411482625,"prev_events":[["$17SfHsvSeTQthSWF:localhost",{"sha256":"iMTefewJ4W5sKQy7osQv4ilJAi7X0NsK791kqEUmYX0"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"WU7lwSWUAk7bsyDnBs128PyXxPZZoD1sN4AiDcvk+W1mDezJbFvWHDWymclxWESlP7TDrFTZEumRWGGCakjyAg"}},"state_key":"","type":"m.room.name"},"latest_event_ids":["$j7KtuOzM0K15h3Kr:localhost"],"adds_state_event_ids":["$j7KtuOzM0K15h3Kr:localhost"],"last_sent_event_id":"$17SfHsvSeTQthSWF:localhost"}}`,
- // $ curl -XPUT -d '{"membership":"join"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.member/@bob:localhost?access_token=@bob:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}],["$2O2DpHB37CuwwJOe:localhost",{"sha256":"ulaRD63dbCyolLTwvInIQpcrtU2c7ex/BHmhpLXAUoE"}]],"content":{"membership":"join"},"depth":0,"event_id":"$wPepDhIla765Odre:localhost","hashes":{"sha256":"KeKqWLvM+LTvyFbwx6y3Y4W5Pj6nBSFUQ6jpkSf1oTE"},"origin":"localhost","origin_server_ts":1494411534290,"prev_events":[["$j7KtuOzM0K15h3Kr:localhost",{"sha256":"oDrWG5/sy1Ea3hYDOSJZRuGKCcjaHQlDYPDn2gB0/L0"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@bob:localhost","signatures":{"localhost":{"ed25519:something":"oVtvjZbWFe+iJhoDvLcQKnFpSYQ94dOodM4gGsx26P6fs2sFJissYwSIqpoxlElCJnmBAgy5iv4JK/5x21R2CQ"}},"state_key":"@bob:localhost","type":"m.room.member"},"latest_event_ids":["$wPepDhIla765Odre:localhost"],"adds_state_event_ids":["$wPepDhIla765Odre:localhost"],"last_sent_event_id":"$j7KtuOzM0K15h3Kr:localhost"}}`,
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"hello alice"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/1?access_token=@bob:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}],["$wPepDhIla765Odre:localhost",{"sha256":"GqUhRiAkRvPrNBDyUxj+emRfK2P8j6iWtvsXDOUltiI"}]],"content":{"body":"hello alice","msgtype":"m.text"},"depth":0,"event_id":"$RHNjeYUvXVZfb93t:localhost","hashes":{"sha256":"Ic1QLxTWFrWt1o31DS93ftrNHkunf4O6ubFvdD4ydNI"},"origin":"localhost","origin_server_ts":1494411593196,"prev_events":[["$wPepDhIla765Odre:localhost",{"sha256":"GqUhRiAkRvPrNBDyUxj+emRfK2P8j6iWtvsXDOUltiI"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@bob:localhost","signatures":{"localhost":{"ed25519:something":"8BHHkiThWwiIZbXCegRjIKNVGIa2kqrZW8VuL7nASfJBORhZ9R9p34UsmhsxVwTs/2/dX7M2ogMB28gIGdLQCg"}},"type":"m.room.message"},"latest_event_ids":["$RHNjeYUvXVZfb93t:localhost"],"last_sent_event_id":"$wPepDhIla765Odre:localhost"}}`,
- // $ curl -XPUT -d '{"name":"A Different Custom Room Name"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.name?access_token=@alice:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$QTen1vksfcRTpUCk:localhost",{"sha256":"znwhbYzdueh0grYkUX4jgXmP9AjKphzyesMZWMiF4IY"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}]],"content":{"name":"A Different Custom Room Name"},"depth":0,"event_id":"$1xoUuqOFjFFJgwA5:localhost","hashes":{"sha256":"2pNnLhoHxNeSUpqxrd3c0kZUA4I+cdWZgYcJ8V3e2tk"},"origin":"localhost","origin_server_ts":1494411643348,"prev_events":[["$RHNjeYUvXVZfb93t:localhost",{"sha256":"LqFmTIzULgUDSf5xM3REObvnsRGLQliWBUf1hEDT4+w"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"gsY4B6TIBdVvLyFAaXw0xez9N5/Cn/ZaJ4z+j9gJU/ZR8j1t3OYlcVQN6uln9JwEU1k20AsGnIqvOaayd+bfCg"}},"state_key":"","type":"m.room.name"},"latest_event_ids":["$1xoUuqOFjFFJgwA5:localhost"],"adds_state_event_ids":["$1xoUuqOFjFFJgwA5:localhost"],"removes_state_event_ids":["$j7KtuOzM0K15h3Kr:localhost"],"last_sent_event_id":"$RHNjeYUvXVZfb93t:localhost"}}`,
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"hello bob"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/2?access_token=@alice:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$QTen1vksfcRTpUCk:localhost",{"sha256":"znwhbYzdueh0grYkUX4jgXmP9AjKphzyesMZWMiF4IY"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}]],"content":{"body":"hello bob","msgtype":"m.text"},"depth":0,"event_id":"$4NBTdIwDxq5fDGpv:localhost","hashes":{"sha256":"msCIESAya8kD7nLCopxkEqrgVuGfrlr9YBIADH5czTA"},"origin":"localhost","origin_server_ts":1494411674630,"prev_events":[["$1xoUuqOFjFFJgwA5:localhost",{"sha256":"ZXj+kY6sqQpf5vsNqvCMSvNoXXKDKxRE4R7+gZD9Tkk"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"bZRT3NxVlfBWw1PxSlKlgfnJixG+NI5H9QmUK2AjECg+l887BZJNCvAK0eD27N8e9V+c2glyXWYje2wexP2CBw"}},"type":"m.room.message"},"latest_event_ids":["$4NBTdIwDxq5fDGpv:localhost"],"last_sent_event_id":"$1xoUuqOFjFFJgwA5:localhost"}}`,
- // $ curl -XPUT -d '{"membership":"invite"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.member/@charlie:localhost?access_token=@bob:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}],["$wPepDhIla765Odre:localhost",{"sha256":"GqUhRiAkRvPrNBDyUxj+emRfK2P8j6iWtvsXDOUltiI"}]],"content":{"membership":"invite"},"depth":0,"event_id":"$zzLHVlHIWPrnE7DI:localhost","hashes":{"sha256":"LKk7tnYJAHsyffbi9CzfdP+TU4KQ5g6YTgYGKjJ7NxU"},"origin":"localhost","origin_server_ts":1494411709192,"prev_events":[["$4NBTdIwDxq5fDGpv:localhost",{"sha256":"EpqmxEoJP93Zb2Nt2fS95SJWTqqIutHm/Ne8OHqp6Ps"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@bob:localhost","signatures":{"localhost":{"ed25519:something":"GdUzkC+7YKl1XDi7kYuD39yi2L/+nv+YrecIQHS+0BLDQqnEj+iRXfNBuZfTk6lUBCJCHXZlk7MnEIjvWDlZCg"}},"state_key":"@charlie:localhost","type":"m.room.member"},"latest_event_ids":["$zzLHVlHIWPrnE7DI:localhost"],"adds_state_event_ids":["$zzLHVlHIWPrnE7DI:localhost"],"last_sent_event_id":"$4NBTdIwDxq5fDGpv:localhost"}}`,
- // $ curl -XPUT -d '{"membership":"join"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.member/@charlie:localhost?access_token=@charlie:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}],["$2O2DpHB37CuwwJOe:localhost",{"sha256":"ulaRD63dbCyolLTwvInIQpcrtU2c7ex/BHmhpLXAUoE"}],["$zzLHVlHIWPrnE7DI:localhost",{"sha256":"Jw28x9W+GoZYw7sEynsi1fcRzqRQiLddolOa/p26PV0"}]],"content":{"membership":"join"},"unsigned":{"prev_content":{"membership":"invite"},"prev_sender":"@bob:localhost","replaces_state":"$zzLHVlHIWPrnE7DI:localhost"},"depth":0,"event_id":"$uJVKyzZi8ZX0kOd9:localhost","hashes":{"sha256":"9ZZs/Cg0ewpBiCB6iFXXYlmW8koFiesCNGFrOLDTolE"},"origin":"localhost","origin_server_ts":1494411745015,"prev_events":[["$zzLHVlHIWPrnE7DI:localhost",{"sha256":"Jw28x9W+GoZYw7sEynsi1fcRzqRQiLddolOa/p26PV0"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@charlie:localhost","signatures":{"localhost":{"ed25519:something":"+TM0gFPM/M3Ji2BjYuTUTgDyCOWlOq8aTMCxLg7EBvS62yPxJ558f13OWWTczUO5aRAt+PvXsMVM/bp8u6c8DQ"}},"state_key":"@charlie:localhost","type":"m.room.member"},"latest_event_ids":["$uJVKyzZi8ZX0kOd9:localhost"],"adds_state_event_ids":["$uJVKyzZi8ZX0kOd9:localhost"],"removes_state_event_ids":["$zzLHVlHIWPrnE7DI:localhost"],"last_sent_event_id":"$zzLHVlHIWPrnE7DI:localhost"}}`,
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"not charlie..."}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/3?access_token=@alice:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$QTen1vksfcRTpUCk:localhost",{"sha256":"znwhbYzdueh0grYkUX4jgXmP9AjKphzyesMZWMiF4IY"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}]],"content":{"body":"not charlie...","msgtype":"m.text"},"depth":0,"event_id":"$Ixfn5WT9ocWTYxfy:localhost","hashes":{"sha256":"hRChdyMQ3AY4jvrPpI8PEX6Taux83Qo5hdSeHlhPxGo"},"origin":"localhost","origin_server_ts":1494411792737,"prev_events":[["$uJVKyzZi8ZX0kOd9:localhost",{"sha256":"BtesLFnHZOREQCeilFM+xvDU/Wdj+nyHMw7IGTh/9gU"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"LC/Zqwu/XdqjmLdTOp/NQaFaE0niSAGgEpa39gCxsnsqEX80P7P5WDn/Kzx6rjWTnhIszrLsnoycqkXQT0Z4DQ"}},"type":"m.room.message"},"latest_event_ids":["$Ixfn5WT9ocWTYxfy:localhost"],"last_sent_event_id":"$uJVKyzZi8ZX0kOd9:localhost"}}`,
- // $ curl -XPUT -d '{"membership":"leave"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.member/@charlie:localhost?access_token=@alice:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$QTen1vksfcRTpUCk:localhost",{"sha256":"znwhbYzdueh0grYkUX4jgXmP9AjKphzyesMZWMiF4IY"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}],["$uJVKyzZi8ZX0kOd9:localhost",{"sha256":"BtesLFnHZOREQCeilFM+xvDU/Wdj+nyHMw7IGTh/9gU"}]],"content":{"membership":"leave"},"unsigned":{"prev_content":{"membership":"join"},"prev_sender":"@charlie:localhost","replaces_state":"$uJVKyzZi8ZX0kOd9:localhost"},"depth":0,"event_id":"$om1F4AI8tCYlHUSp:localhost","hashes":{"sha256":"7JVI0uCxSUyEqDJ+o36/zUIlIZkXVK/R6wkrZGvQXDE"},"origin":"localhost","origin_server_ts":1494411855278,"prev_events":[["$Ixfn5WT9ocWTYxfy:localhost",{"sha256":"hOoPIDQFvvNqQJzA5ggjoQi4v1BOELnhnmwU4UArDOY"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"3sxoDLUPnKuDJgFgS3C647BbiXrozxhhxrZOlFP3KgJKzBYv/ht+Jd2V2iSZOvsv94wgRBf0A/lEcJRIqeLgDA"}},"state_key":"@charlie:localhost","type":"m.room.member"},"latest_event_ids":["$om1F4AI8tCYlHUSp:localhost"],"adds_state_event_ids":["$om1F4AI8tCYlHUSp:localhost"],"removes_state_event_ids":["$uJVKyzZi8ZX0kOd9:localhost"],"last_sent_event_id":"$Ixfn5WT9ocWTYxfy:localhost"}}`,
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"why did you kick charlie"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/3?access_token=@bob:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}],["$wPepDhIla765Odre:localhost",{"sha256":"GqUhRiAkRvPrNBDyUxj+emRfK2P8j6iWtvsXDOUltiI"}]],"content":{"body":"why did you kick charlie","msgtype":"m.text"},"depth":0,"event_id":"$hgao5gTmr3r9TtK2:localhost","hashes":{"sha256":"Aa2ZCrvwjX5xhvkVqIOFUeEGqrnrQZjjNFiZRybjsPY"},"origin":"localhost","origin_server_ts":1494411912809,"prev_events":[["$om1F4AI8tCYlHUSp:localhost",{"sha256":"yVs+CW7AiJrJOYouL8xPIBrtIHAhnbxaegna8MxeCto"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@bob:localhost","signatures":{"localhost":{"ed25519:something":"sGkpbEXGsvAuCvE3wb5E9H5fjCVKpRdWNt6csj1bCB9Fmg4Rg4mvj3TAJ+91DjO8IPsgSxDKdqqRYF0OtcynBA"}},"type":"m.room.message"},"latest_event_ids":["$hgao5gTmr3r9TtK2:localhost"],"last_sent_event_id":"$om1F4AI8tCYlHUSp:localhost"}}`,
- // $ curl -XPUT -d '{"name":"No Charlies"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.name?access_token=@alice:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$QTen1vksfcRTpUCk:localhost",{"sha256":"znwhbYzdueh0grYkUX4jgXmP9AjKphzyesMZWMiF4IY"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}]],"content":{"name":"No Charlies"},"depth":0,"event_id":"$CY4XDoxjbns3a4Pc:localhost","hashes":{"sha256":"chk72pVkp3AGR2FtdC0mORBWS1b9ePnRN4WK3BP0BiI"},"origin":"localhost","origin_server_ts":1494411959114,"prev_events":[["$hgao5gTmr3r9TtK2:localhost",{"sha256":"/4/OG4Q2YalIeBtN76BEPIieBKA/3UFshR9T+WJip4o"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"mapvA3KJYgw5FmzJMhSFa/+JSuNyv2eKAkiGomAeBB7LQ1e9nK9XhW/Fp7a5Z2Sy2ENwHyd3ij7FEGiLOnSIAw"}},"state_key":"","type":"m.room.name"},"latest_event_ids":["$CY4XDoxjbns3a4Pc:localhost"],"adds_state_event_ids":["$CY4XDoxjbns3a4Pc:localhost"],"removes_state_event_ids":["$1xoUuqOFjFFJgwA5:localhost"],"last_sent_event_id":"$hgao5gTmr3r9TtK2:localhost"}}`,
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"whatever"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/3?access_token=@bob:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}],["$wPepDhIla765Odre:localhost",{"sha256":"GqUhRiAkRvPrNBDyUxj+emRfK2P8j6iWtvsXDOUltiI"}]],"content":{"body":"whatever","msgtype":"m.text"},"depth":0,"event_id":"$pl8VBHRPYDmsnDh4:localhost","hashes":{"sha256":"FYqY9+/cepwIxxjfFV3AjOFBXkTlyEI2jep87dUc+SU"},"origin":"localhost","origin_server_ts":1494411988548,"prev_events":[["$CY4XDoxjbns3a4Pc:localhost",{"sha256":"hCoV63fp8eiquVdEefsOqJtLmJhw4wTlRv+wNTS20Ac"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@bob:localhost","signatures":{"localhost":{"ed25519:something":"sQKwRzE59eZyb8rDySo/pVwZXBh0nA5zx+kjEyXglxIQrTre+8Gj3R7Prni+RE3Dq7oWfKYV7QklTLURAaSICQ"}},"type":"m.room.message"},"latest_event_ids":["$pl8VBHRPYDmsnDh4:localhost"],"last_sent_event_id":"$CY4XDoxjbns3a4Pc:localhost"}}`,
- // $ curl -XPUT -d '{"membership":"leave"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.member/@bob:localhost?access_token=@bob:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}],["$wPepDhIla765Odre:localhost",{"sha256":"GqUhRiAkRvPrNBDyUxj+emRfK2P8j6iWtvsXDOUltiI"}]],"content":{"membership":"leave"},"depth":0,"event_id":"$acCW4IgnBo8YD3jw:localhost","hashes":{"sha256":"porP+E2yftBGjfS381+WpZeDM9gZHsM3UydlBcRKBLw"},"origin":"localhost","origin_server_ts":1494412037042,"prev_events":[["$pl8VBHRPYDmsnDh4:localhost",{"sha256":"b+qQ380JDFq7quVU9EbIJ2sbpUKM1LAUNX0ZZUoVMZw"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@bob:localhost","signatures":{"localhost":{"ed25519:something":"kxbjTIC0/UR4cOYUAOTNiUc0SSVIF4BY6Rq6IEgYJemq4jcU2fYqum4mFxIQTDKKXMSRHEoNPDmYMFIJwkrsCg"}},"state_key":"@bob:localhost","type":"m.room.member"},"latest_event_ids":["$acCW4IgnBo8YD3jw:localhost"],"adds_state_event_ids":["$acCW4IgnBo8YD3jw:localhost"],"removes_state_event_ids":["$wPepDhIla765Odre:localhost"],"last_sent_event_id":"$pl8VBHRPYDmsnDh4:localhost"}}`,
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"im alone now"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/3?access_token=@alice:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$QTen1vksfcRTpUCk:localhost",{"sha256":"znwhbYzdueh0grYkUX4jgXmP9AjKphzyesMZWMiF4IY"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}]],"content":{"body":"im alone now","msgtype":"m.text"},"depth":0,"event_id":"$nYdEXrvTDeb7DfkC:localhost","hashes":{"sha256":"qibC5NmlJpSRMBWSWxy1pv73FXymhPDXQFMmGosfsV0"},"origin":"localhost","origin_server_ts":1494412084668,"prev_events":[["$acCW4IgnBo8YD3jw:localhost",{"sha256":"8h3uXoE6pnI9iLnXI6493qJ0HeuRQfenRIu9PcgH72g"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"EHRoZznhXywhYeIn83o4FSFm3No/aOdLQPHQ68YGtNgESWwpuWLkkGVjoISjz3QgXQ06Fl3cHt7nlTaAHpCNAg"}},"type":"m.room.message"},"latest_event_ids":["$nYdEXrvTDeb7DfkC:localhost"],"last_sent_event_id":"$acCW4IgnBo8YD3jw:localhost"}}`,
- // $ curl -XPUT -d '{"membership":"invite"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.member/@bob:localhost?access_token=@alice:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$QTen1vksfcRTpUCk:localhost",{"sha256":"znwhbYzdueh0grYkUX4jgXmP9AjKphzyesMZWMiF4IY"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}],["$acCW4IgnBo8YD3jw:localhost",{"sha256":"8h3uXoE6pnI9iLnXI6493qJ0HeuRQfenRIu9PcgH72g"}]],"content":{"membership":"invite"},"depth":0,"event_id":"$gKNfcXLlWvs2cFad:localhost","hashes":{"sha256":"iYDOUjYkaGSFbVp7TRVFvGJyGMEuBHMQrJ9XqwhzmPI"},"origin":"localhost","origin_server_ts":1494412135845,"prev_events":[["$nYdEXrvTDeb7DfkC:localhost",{"sha256":"83T5Q3+nDvtS0oJTEhHxIw02twBDa1A7QR2bHtnxv1Y"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"ofw009aMJMqVjww9eDXgeTjOQqSlJl/GN/AAb+6mZAPcUI8aVgRlXOSESfhu1ONEuV/yNUycxNXWfMwuvoWsDg"}},"state_key":"@bob:localhost","type":"m.room.member"},"latest_event_ids":["$gKNfcXLlWvs2cFad:localhost"],"adds_state_event_ids":["$gKNfcXLlWvs2cFad:localhost"],"removes_state_event_ids":["$acCW4IgnBo8YD3jw:localhost"],"last_sent_event_id":"$nYdEXrvTDeb7DfkC:localhost"}}`,
- // $ curl -XPUT -d '{"membership":"leave"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.member/@bob:localhost?access_token=@bob:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}],["$gKNfcXLlWvs2cFad:localhost",{"sha256":"/TYIY+L9qjg516Bzl8sadu+Np21KkxE4KdPXALeJ9eE"}]],"content":{"membership":"leave"},"depth":0,"event_id":"$B2q9Tepb6Xc1Rku0:localhost","hashes":{"sha256":"RbHTVdceAEfTALQDZdGrOmakKeTYnChaKjlVuoNUdSY"},"origin":"localhost","origin_server_ts":1494412187614,"prev_events":[["$gKNfcXLlWvs2cFad:localhost",{"sha256":"/TYIY+L9qjg516Bzl8sadu+Np21KkxE4KdPXALeJ9eE"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@bob:localhost","signatures":{"localhost":{"ed25519:something":"dNtUL86j2zUe5+DkfOkil5VujvFZg4FeTjbtcpeF+3E4SUChCAG3lyR6YOAIYBnjtD0/kqT7OcP3pM6vMEp1Aw"}},"state_key":"@bob:localhost","type":"m.room.member"},"latest_event_ids":["$B2q9Tepb6Xc1Rku0:localhost"],"adds_state_event_ids":["$B2q9Tepb6Xc1Rku0:localhost"],"removes_state_event_ids":["$gKNfcXLlWvs2cFad:localhost"],"last_sent_event_id":"$gKNfcXLlWvs2cFad:localhost"}}`,
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"so alone"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/3?access_token=@alice:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$QTen1vksfcRTpUCk:localhost",{"sha256":"znwhbYzdueh0grYkUX4jgXmP9AjKphzyesMZWMiF4IY"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}]],"content":{"body":"so alone","msgtype":"m.text"},"depth":0,"event_id":"$W1nrYHQIbCTTSJOV:localhost","hashes":{"sha256":"uUKSa4U1coDoT3LUcNF25dt+UpUa2pLXzRJ3ljgxXZs"},"origin":"localhost","origin_server_ts":1494412229742,"prev_events":[["$B2q9Tepb6Xc1Rku0:localhost",{"sha256":"0CLru7nGPgyF9AWlZnarCElscSVrXl2MMY2atrz80Uc"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"YlBJyDnE34UhaCB9hirQN5OySfTDoqiBDnNvxomXjU94z4a8g2CLWKjApwd/q/j4HamCUtjgkjJ2um6hNjsVBA"}},"type":"m.room.message"},"latest_event_ids":["$W1nrYHQIbCTTSJOV:localhost"],"last_sent_event_id":"$B2q9Tepb6Xc1Rku0:localhost"}}`,
- // $ curl -XPUT -d '{"name":"Everyone welcome"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.name?access_token=@alice:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$QTen1vksfcRTpUCk:localhost",{"sha256":"znwhbYzdueh0grYkUX4jgXmP9AjKphzyesMZWMiF4IY"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}]],"content":{"name":"Everyone welcome"},"depth":0,"event_id":"$nLzxoBC4A0QRvJ1k:localhost","hashes":{"sha256":"PExCybjaMW1TfgFr57MdIRYJ642FY2jnrdW/tpPOf1Y"},"origin":"localhost","origin_server_ts":1494412294551,"prev_events":[["$W1nrYHQIbCTTSJOV:localhost",{"sha256":"HXk/ACcsiaZ/z1f2aZSIhJF8Ih3BWeh1vp+cV/fwoE0"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@alice:localhost","signatures":{"localhost":{"ed25519:something":"RK09L8sQv78y69PNbOLaX8asq5kp51mbqUuct5gd7ZNmaHKnVds6ew06QEn+gHSDAxqQo2tpcfoajp+yMj1HBw"}},"state_key":"","type":"m.room.name"},"latest_event_ids":["$nLzxoBC4A0QRvJ1k:localhost"],"adds_state_event_ids":["$nLzxoBC4A0QRvJ1k:localhost"],"removes_state_event_ids":["$CY4XDoxjbns3a4Pc:localhost"],"last_sent_event_id":"$W1nrYHQIbCTTSJOV:localhost"}}`,
- // $ curl -XPUT -d '{"membership":"join"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/state/m.room.member/@charlie:localhost?access_token=@charlie:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}],["$2O2DpHB37CuwwJOe:localhost",{"sha256":"ulaRD63dbCyolLTwvInIQpcrtU2c7ex/BHmhpLXAUoE"}],["$om1F4AI8tCYlHUSp:localhost",{"sha256":"yVs+CW7AiJrJOYouL8xPIBrtIHAhnbxaegna8MxeCto"}]],"content":{"membership":"join"},"depth":0,"event_id":"$Zo6P8r9bczF6kctV:localhost","hashes":{"sha256":"R3J2iUWnGxVdmly8ah+Dgb5VbJ2i/e8BLaWM0z9eZKU"},"origin":"localhost","origin_server_ts":1494412338689,"prev_events":[["$nLzxoBC4A0QRvJ1k:localhost",{"sha256":"TDcFaArAXpxIJ1noSubcFqkLXiQTrc1Dw1+kgCtx3XY"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@charlie:localhost","signatures":{"localhost":{"ed25519:something":"tVnjLVoJ9SLlMQIJSK/6zANWaEu8tVVkx3AEJiC3y5JmhPORb3PyG8eE+e/9hC4aJSQL8LGLaJNWXukMpb2SBg"}},"state_key":"@charlie:localhost","type":"m.room.member"},"latest_event_ids":["$Zo6P8r9bczF6kctV:localhost"],"adds_state_event_ids":["$Zo6P8r9bczF6kctV:localhost"],"removes_state_event_ids":["$om1F4AI8tCYlHUSp:localhost"],"last_sent_event_id":"$nLzxoBC4A0QRvJ1k:localhost"}}`,
- // $ curl -XPUT -d '{"msgtype":"m.text","body":"hiiiii"}' "http://localhost:8009/_matrix/client/r0/rooms/%21PjrbIMW2cIiaYF4t:localhost/send/m.room.message/3?access_token=@charlie:localhost"
- `{"type":"new_room_event","new_room_event":{"event":{"auth_events":[["$xz0fUB8zNMTGFh1W:localhost",{"sha256":"F4tTLtltC6f2XKeXq4ZKpMZ5EpditaW+RYQSnYzq3lI"}],["$RWsxGlfPHAcijTgu:localhost",{"sha256":"1zc+86U9vLK1BvTJbeLuYpw9dZqvX2fr8rc3pOF69f8"}],["$Zo6P8r9bczF6kctV:localhost",{"sha256":"mnjt3WTYqwtuyl2Fca+0cgm6moHaNL+W9BqRJTQzdEY"}]],"content":{"body":"hiiiii","msgtype":"m.text"},"depth":0,"event_id":"$YAEvK8u2zkTsjf5P:localhost","hashes":{"sha256":"6hKy61h1tuHjYdfpq2MnaPtGEBAZOUz8FLTtxLwjK5A"},"origin":"localhost","origin_server_ts":1494412375465,"prev_events":[["$Zo6P8r9bczF6kctV:localhost",{"sha256":"mnjt3WTYqwtuyl2Fca+0cgm6moHaNL+W9BqRJTQzdEY"}]],"room_id":"!PjrbIMW2cIiaYF4t:localhost","sender":"@charlie:localhost","signatures":{"localhost":{"ed25519:something":"BsSLaMM5U/YkyvBZ00J/+si9My+wAJZOcBhBeato0oHayiag7FW77ZpSTfADazPdNH62kjB0sdP9CN6vQA7yDg"}},"type":"m.room.message"},"latest_event_ids":["$YAEvK8u2zkTsjf5P:localhost"],"last_sent_event_id":"$Zo6P8r9bczF6kctV:localhost"}}`,
-}