Merge branch 'master' into neilalexander/nats
This commit is contained in:
commit
8f40e8fd5e
|
@ -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"))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -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)
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.8 MiB |
|
@ -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])
|
|
||||||
}
|
|
|
@ -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"
|
|
||||||
}
|
|
|
@ -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"}}`,
|
|
||||||
}
|
|
Loading…
Reference in a new issue