WIP: use complement libraries

This commit is contained in:
Kegan Dougal 2023-10-11 12:23:46 +01:00
parent 4d8cbb2709
commit 37aa1469a5
23 changed files with 531 additions and 1228 deletions

16
go.mod
View File

@ -9,12 +9,13 @@ require (
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0
github.com/jmoiron/sqlx v1.3.3 github.com/jmoiron/sqlx v1.3.3
github.com/lib/pq v1.10.9 github.com/lib/pq v1.10.9
github.com/matrix-org/gomatrixserverlib v0.0.0-20230822143230-740f742d6993 github.com/matrix-org/complement v0.0.0-20231010122615-008239d3b6e7
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4 github.com/matrix-org/gomatrixserverlib v0.0.0-20230921171121-0466775328c7
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66
github.com/pressly/goose/v3 v3.14.0 github.com/pressly/goose/v3 v3.14.0
github.com/prometheus/client_golang v1.13.0 github.com/prometheus/client_golang v1.13.0
github.com/rs/zerolog v1.29.0 github.com/rs/zerolog v1.29.0
github.com/tidwall/gjson v1.14.3 github.com/tidwall/gjson v1.16.0
github.com/tidwall/sjson v1.2.5 github.com/tidwall/sjson v1.2.5
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0
go.opentelemetry.io/contrib/propagators/jaeger v1.18.0 go.opentelemetry.io/contrib/propagators/jaeger v1.18.0
@ -34,6 +35,7 @@ require (
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect github.com/golang/protobuf v1.5.3 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.17.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.17.0 // indirect
github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-isatty v0.0.19 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
@ -43,17 +45,19 @@ require (
github.com/rs/xid v1.4.0 // indirect github.com/rs/xid v1.4.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect
github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect github.com/tidwall/pretty v1.2.1 // indirect
github.com/x448/float16 v0.8.4 // indirect github.com/x448/float16 v0.8.4 // indirect
go.opentelemetry.io/otel/metric v1.18.0 // indirect go.opentelemetry.io/otel/metric v1.18.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect
golang.org/x/crypto v0.12.0 // indirect golang.org/x/crypto v0.13.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/net v0.14.0 // indirect golang.org/x/net v0.14.0 // indirect
golang.org/x/sync v0.3.0 // indirect golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.12.0 // indirect golang.org/x/sys v0.12.0 // indirect
golang.org/x/text v0.12.0 // indirect golang.org/x/text v0.13.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/grpc v1.58.0 // indirect google.golang.org/grpc v1.58.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect google.golang.org/protobuf v1.31.0 // indirect
maunium.net/go/mautrix v0.11.0 // indirect
) )

39
go.sum
View File

@ -153,6 +153,7 @@ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.17.0 h1:Rme6CE1aUTyV9WmrEPyGf1V+7W3iQzZ1DZkKnT6z9B0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.17.0 h1:Rme6CE1aUTyV9WmrEPyGf1V+7W3iQzZ1DZkKnT6z9B0=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.17.0/go.mod h1:Hbb13e3/WtqQ8U5hLGkek9gJvBLasHuPFI0UEGfnQ10= github.com/grpc-ecosystem/grpc-gateway/v2 v2.17.0/go.mod h1:Hbb13e3/WtqQ8U5hLGkek9gJvBLasHuPFI0UEGfnQ10=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@ -178,11 +179,14 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16 h1:ZtO5uywdd5dLDCud4r0r55eP4j9FuUNpl60Gmntcop4= github.com/matrix-org/complement v0.0.0-20231010122615-008239d3b6e7 h1:lamc87j5ig2mNEi5Qqd+ZeIpmLdKtvYgZ3HDSPG0DrI=
github.com/matrix-org/gomatrixserverlib v0.0.0-20230822143230-740f742d6993 h1:88wDfSsqSFyeCnTha8vfK9XJUbNjNXdEZAieOjbBzos= github.com/matrix-org/complement v0.0.0-20231010122615-008239d3b6e7/go.mod h1:GCJVyag4p1Qj/WJUmBLlRtRHd04ALFNJkhzOcM/BvgA=
github.com/matrix-org/gomatrixserverlib v0.0.0-20230822143230-740f742d6993/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U=
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4 h1:eCEHXWDv9Rm335MSuB49mFUK44bwZPFSDde3ORE3syk= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4/go.mod h1:vVQlW/emklohkZnOPwD3LrZUBqdfsbiyO3p1lNV8F6U= github.com/matrix-org/gomatrixserverlib v0.0.0-20230921171121-0466775328c7 h1:NhPNNFLHwdDb/upeicBh1GkxX/sFinEp5HF1WBqPtiY=
github.com/matrix-org/gomatrixserverlib v0.0.0-20230921171121-0466775328c7/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU=
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y=
github.com/matrix-org/util v0.0.0-20221111132719-399730281e66/go.mod h1:iBI1foelCqA09JJgPV0FYz4qA5dUXYOxMi57FxKBdd4=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
@ -190,10 +194,11 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.13 h1:1tj15ngiFfcZzii7yd82foL+ks+ouQcj8j/TPq3fk1I=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
@ -254,12 +259,13 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw= github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg=
github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
@ -299,8 +305,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -311,6 +317,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -443,8 +451,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -490,7 +498,7 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20210112230658-8b4aab62c064/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210112230658-8b4aab62c064/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -584,6 +592,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@ -601,6 +610,8 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo= lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo=
maunium.net/go/mautrix v0.11.0 h1:B1FBHcvE4Mud+AC+zgNQQOw0JxSVrt40watCejhVA7w=
maunium.net/go/mautrix v0.11.0/go.mod h1:K29EcHwsNg6r7fMfwvi0GHQ9o5wSjqB9+Q8RjCIQEjA=
modernc.org/cc/v3 v3.41.0 h1:QoR1Sn3YWlmA1T4vLaKZfawdVtSiGx8H+cEojbC7v1Q= modernc.org/cc/v3 v3.41.0 h1:QoR1Sn3YWlmA1T4vLaKZfawdVtSiGx8H+cEojbC7v1Q=
modernc.org/ccgo/v3 v3.16.14 h1:af6KNtFgsVmnDYrWk3PQCS9XT6BXe7o3ZFJKkIKvXNQ= modernc.org/ccgo/v3 v3.16.14 h1:af6KNtFgsVmnDYrWk3PQCS9XT6BXe7o3ZFJKkIKvXNQ=
modernc.org/libc v1.24.1 h1:uvJSeCKL/AgzBo2yYIPPTy82v21KgGnizcGYfBHaNuM= modernc.org/libc v1.24.1 h1:uvJSeCKL/AgzBo2yYIPPTy82v21KgGnizcGYfBHaNuM=

View File

@ -19,8 +19,8 @@ func TestAccountDataRespectsExtensionScope(t *testing.T) {
// Want at least one test of the initial sync behaviour (which hits `ProcessInitial`) // Want at least one test of the initial sync behaviour (which hits `ProcessInitial`)
// separate to the incremental sync behaviour (hits `AppendLive`) // separate to the incremental sync behaviour (hits `AppendLive`)
t.Log("Alice creates rooms 1 and 2.") t.Log("Alice creates rooms 1 and 2.")
room1 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 1"}) room1 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 1"})
room2 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 2"}) room2 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 2"})
t.Logf("room1=%s room2=%s", room1, room2) t.Logf("room1=%s room2=%s", room1, room2)
t.Log("Alice uploads account data for both rooms, plus global account data.") t.Log("Alice uploads account data for both rooms, plus global account data.")
@ -216,7 +216,7 @@ func TestAccountDataDoesntDupe(t *testing.T) {
// sync response with bytes.Equal. // sync response with bytes.Equal.
func putGlobalAccountData(t *testing.T, client *CSAPI, eventType string, content map[string]interface{}) json.RawMessage { func putGlobalAccountData(t *testing.T, client *CSAPI, eventType string, content map[string]interface{}) json.RawMessage {
t.Helper() t.Helper()
client.SetGlobalAccountData(t, eventType, content) client.MustSetGlobalAccountData(t, eventType, content)
serialised := testutils.NewAccountData(t, eventType, content) serialised := testutils.NewAccountData(t, eventType, content)
return serialised return serialised
} }
@ -224,7 +224,7 @@ func putGlobalAccountData(t *testing.T, client *CSAPI, eventType string, content
// putRoomAccountData is like putGlobalAccountData, but for room-specific account data. // putRoomAccountData is like putGlobalAccountData, but for room-specific account data.
func putRoomAccountData(t *testing.T, client *CSAPI, roomID, eventType string, content map[string]interface{}) json.RawMessage { func putRoomAccountData(t *testing.T, client *CSAPI, roomID, eventType string, content map[string]interface{}) json.RawMessage {
t.Helper() t.Helper()
client.SetRoomAccountData(t, roomID, eventType, content) client.MustSetRoomAccountData(t, roomID, eventType, content)
serialised := testutils.NewAccountData(t, eventType, content) serialised := testutils.NewAccountData(t, eventType, content)
return serialised return serialised
} }

File diff suppressed because it is too large Load Diff

View File

@ -9,13 +9,15 @@ import (
"testing" "testing"
"time" "time"
"github.com/matrix-org/complement/b"
"github.com/matrix-org/complement/client"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils/m" "github.com/matrix-org/sliding-sync/testutils/m"
) )
func TestInvalidTokenReturnsMUnknownTokenError(t *testing.T) { func TestInvalidTokenReturnsMUnknownTokenError(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
roomID := alice.CreateRoom(t, map[string]interface{}{}) roomID := alice.MustCreateRoom(t, map[string]interface{}{})
// normal sliding sync // normal sliding sync
alice.SlidingSync(t, sync3.Request{ alice.SlidingSync(t, sync3.Request{
ConnID: "A", ConnID: "A",
@ -26,15 +28,15 @@ func TestInvalidTokenReturnsMUnknownTokenError(t *testing.T) {
}, },
}) })
// invalidate the access token // invalidate the access token
alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "logout"}) alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "logout"})
// let the proxy realise the token is expired and tell downstream // let the proxy realise the token is expired and tell downstream
time.Sleep(time.Second) time.Sleep(time.Second)
var invalidResponses []*http.Response var invalidResponses []*http.Response
// using the same token now returns a 401 with M_UNKNOWN_TOKEN // using the same token now returns a 401 with M_UNKNOWN_TOKEN
httpRes := alice.DoFunc(t, "POST", []string{"_matrix", "client", "unstable", "org.matrix.msc3575", "sync"}, WithQueries(url.Values{ httpRes := alice.Do(t, "POST", []string{"_matrix", "client", "unstable", "org.matrix.msc3575", "sync"}, client.WithQueries(url.Values{
"timeout": []string{"500"}, "timeout": []string{"500"},
}), WithJSONBody(t, sync3.Request{ }), client.WithJSONBody(t, sync3.Request{
ConnID: "A", ConnID: "A",
RoomSubscriptions: map[string]sync3.RoomSubscription{ RoomSubscriptions: map[string]sync3.RoomSubscription{
roomID: { roomID: {
@ -45,9 +47,9 @@ func TestInvalidTokenReturnsMUnknownTokenError(t *testing.T) {
invalidResponses = append(invalidResponses, httpRes) invalidResponses = append(invalidResponses, httpRes)
// using a bogus access token returns a 401 with M_UNKNOWN_TOKEN // using a bogus access token returns a 401 with M_UNKNOWN_TOKEN
alice.AccessToken = "flibble_wibble" alice.AccessToken = "flibble_wibble"
httpRes = alice.DoFunc(t, "POST", []string{"_matrix", "client", "unstable", "org.matrix.msc3575", "sync"}, WithQueries(url.Values{ httpRes = alice.Do(t, "POST", []string{"_matrix", "client", "unstable", "org.matrix.msc3575", "sync"}, client.WithQueries(url.Values{
"timeout": []string{"500"}, "timeout": []string{"500"},
}), WithJSONBody(t, sync3.Request{ }), client.WithJSONBody(t, sync3.Request{
ConnID: "A", ConnID: "A",
RoomSubscriptions: map[string]sync3.RoomSubscription{ RoomSubscriptions: map[string]sync3.RoomSubscription{
roomID: { roomID: {
@ -84,7 +86,7 @@ func TestInvalidTokenReturnsMUnknownTokenError(t *testing.T) {
// Test that you can have multiple connections with the same device, and they work independently. // Test that you can have multiple connections with the same device, and they work independently.
func TestMultipleConns(t *testing.T) { func TestMultipleConns(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
roomID := alice.CreateRoom(t, map[string]interface{}{}) roomID := alice.MustCreateRoom(t, map[string]interface{}{})
resA := alice.SlidingSync(t, sync3.Request{ resA := alice.SlidingSync(t, sync3.Request{
ConnID: "A", ConnID: "A",
@ -111,7 +113,7 @@ func TestMultipleConns(t *testing.T) {
}, },
}) })
eventID := alice.SendEventSynced(t, roomID, Event{ eventID := alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.name", Type: "m.room.name",
StateKey: ptr(""), StateKey: ptr(""),
Content: map[string]interface{}{"name": "pub"}, Content: map[string]interface{}{"name": "pub"},

View File

@ -2,9 +2,11 @@ package syncv3_test
import ( import (
"fmt" "fmt"
"testing"
"github.com/matrix-org/complement/b"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils/m" "github.com/matrix-org/sliding-sync/testutils/m"
"testing"
) )
// Test that state changes "missed" by a poller are injected back into the room when a // Test that state changes "missed" by a poller are injected back into the room when a
@ -15,10 +17,10 @@ func TestGappyState(t *testing.T) {
t.Log("Alice creates a room") t.Log("Alice creates a room")
firstRoomName := "Romeo Oscar Oscar Mike" firstRoomName := "Romeo Oscar Oscar Mike"
roomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": firstRoomName}) roomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": firstRoomName})
t.Log("Alice sends a message into that room") t.Log("Alice sends a message into that room")
firstMessageID := alice.SendEventSynced(t, roomID, Event{ firstMessageID := alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
@ -50,19 +52,23 @@ func TestGappyState(t *testing.T) {
) )
t.Log("Alice logs out of her first device.") t.Log("Alice logs out of her first device.")
alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "logout"}) alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "logout"})
t.Log("Alice logs in again on her second device.") t.Log("Alice logs in again on her second device.")
alice.Login(t, "password", "device2") alice.Login(t, "password", "device2")
t.Log("Alice changes the room name while the proxy isn't polling.") t.Log("Alice changes the room name while the proxy isn't polling.")
nameContent := map[string]interface{}{"name": "potato"} nameContent := map[string]interface{}{"name": "potato"}
alice.SetState(t, roomID, "m.room.name", "", nameContent) alice.Unsafe_SendEventUnsynced(t, roomID, b.Event{
Type: "m.room.name",
StateKey: ptr(""),
Content: nameContent,
})
t.Log("Alice sends lots of message events (more than the poller will request in a timeline.") t.Log("Alice sends lots of message events (more than the poller will request in a timeline.")
var latestMessageID string var latestMessageID string
for i := 0; i < 51; i++ { for i := 0; i < 51; i++ {
latestMessageID = alice.SendEventUnsynced(t, roomID, Event{ latestMessageID = alice.Unsafe_SendEventUnsynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",

View File

@ -2,9 +2,11 @@ package syncv3_test
import ( import (
"fmt" "fmt"
"testing"
"github.com/matrix-org/complement/b"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils/m" "github.com/matrix-org/sliding-sync/testutils/m"
"testing"
) )
func TestInvitesFromIgnoredUsersOmitted(t *testing.T) { func TestInvitesFromIgnoredUsersOmitted(t *testing.T) {
@ -13,16 +15,16 @@ func TestInvitesFromIgnoredUsersOmitted(t *testing.T) {
nigel := registerNamedUser(t, "nigel") nigel := registerNamedUser(t, "nigel")
t.Log("Nigel create two public rooms. Bob joins both.") t.Log("Nigel create two public rooms. Bob joins both.")
room1 := nigel.CreateRoom(t, map[string]any{"preset": "public_chat", "name": "room 1"}) room1 := nigel.MustCreateRoom(t, map[string]any{"preset": "public_chat", "name": "room 1"})
room2 := nigel.CreateRoom(t, map[string]any{"preset": "public_chat", "name": "room 2"}) room2 := nigel.MustCreateRoom(t, map[string]any{"preset": "public_chat", "name": "room 2"})
bob.JoinRoom(t, room1, nil) bob.JoinRoom(t, room1, nil)
bob.JoinRoom(t, room2, nil) bob.JoinRoom(t, room2, nil)
t.Log("Alice makes a room for dumping sentinel messages.") t.Log("Alice makes a room for dumping sentinel messages.")
aliceRoom := alice.CreateRoom(t, map[string]any{"preset": "private_chat"}) aliceRoom := alice.MustCreateRoom(t, map[string]any{"preset": "private_chat"})
t.Log("Alice ignores Nigel.") t.Log("Alice ignores Nigel.")
alice.SetGlobalAccountData(t, "m.ignored_user_list", map[string]any{ alice.MustSetGlobalAccountData(t, "m.ignored_user_list", map[string]any{
"ignored_users": map[string]any{ "ignored_users": map[string]any{
nigel.UserID: map[string]any{}, nigel.UserID: map[string]any{},
}, },
@ -35,7 +37,7 @@ func TestInvitesFromIgnoredUsersOmitted(t *testing.T) {
bob.SlidingSyncUntilMembership(t, "", room1, alice, "invite") bob.SlidingSyncUntilMembership(t, "", room1, alice, "invite")
t.Log("Alice sends a sentinel message in her private room.") t.Log("Alice sends a sentinel message in her private room.")
sentinel := alice.SendEventSynced(t, aliceRoom, Event{ sentinel := alice.SendEventSynced(t, aliceRoom, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]any{ Content: map[string]any{
"body": "Hello, world!", "body": "Hello, world!",
@ -69,7 +71,7 @@ func TestInvitesFromIgnoredUsersOmitted(t *testing.T) {
bob.SlidingSyncUntilMembership(t, "", room1, alice, "invite") bob.SlidingSyncUntilMembership(t, "", room1, alice, "invite")
t.Log("Alice sends a sentinel message in her private room.") t.Log("Alice sends a sentinel message in her private room.")
sentinel = alice.SendEventSynced(t, aliceRoom, Event{ sentinel = alice.SendEventSynced(t, aliceRoom, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]any{ Content: map[string]any{
"body": "Hello, world, again", "body": "Hello, world, again",

View File

@ -3,6 +3,7 @@ package syncv3_test
import ( import (
"testing" "testing"
"github.com/matrix-org/complement/b"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils/m" "github.com/matrix-org/sliding-sync/testutils/m"
) )
@ -14,12 +15,12 @@ func TestLazyLoading(t *testing.T) {
sentinel := registerNewUser(t) // dummy user to ensure that the proxy has processed sent events sentinel := registerNewUser(t) // dummy user to ensure that the proxy has processed sent events
// all 3 join the room and say something // all 3 join the room and say something
roomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) roomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat"})
bob.JoinRoom(t, roomID, nil) bob.JoinRoom(t, roomID, nil)
charlie.JoinRoom(t, roomID, nil) charlie.JoinRoom(t, roomID, nil)
sentinel.JoinRoom(t, roomID, nil) sentinel.JoinRoom(t, roomID, nil)
alice.SendEventSynced(t, roomID, Event{ alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"body": "Hello world", "body": "Hello world",
@ -27,7 +28,7 @@ func TestLazyLoading(t *testing.T) {
}, },
}) })
bob.SendEventSynced(t, roomID, Event{ bob.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"body": "Hello world", "body": "Hello world",
@ -35,7 +36,7 @@ func TestLazyLoading(t *testing.T) {
}, },
}) })
lastEventID := charlie.SendEventSynced(t, roomID, Event{ lastEventID := charlie.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"body": "Hello world", "body": "Hello world",
@ -142,7 +143,7 @@ func TestLazyLoading(t *testing.T) {
})) }))
// alice now sends a message // alice now sends a message
aliceEventID := alice.SendEventSynced(t, roomID, Event{Type: "m.room.message", Content: map[string]interface{}{"body": "hello", "msgtype": "m.text"}}) aliceEventID := alice.SendEventSynced(t, roomID, b.Event{Type: "m.room.message", Content: map[string]interface{}{"body": "hello", "msgtype": "m.text"}})
sentinel.SlidingSyncUntilEventID(t, "", roomID, aliceEventID) sentinel.SlidingSyncUntilEventID(t, "", roomID, aliceEventID)
// bob, who didn't previously get alice's m.room.member event, should now see this // bob, who didn't previously get alice's m.room.member event, should now see this
@ -161,7 +162,7 @@ func TestLazyLoading(t *testing.T) {
})) }))
// alice sends another message // alice sends another message
aliceEventID2 := alice.SendEventSynced(t, roomID, Event{Type: "m.room.message", Content: map[string]interface{}{"body": "hello2", "msgtype": "m.text"}}) aliceEventID2 := alice.SendEventSynced(t, roomID, b.Event{Type: "m.room.message", Content: map[string]interface{}{"body": "hello2", "msgtype": "m.text"}})
sentinel.SlidingSyncUntilEventID(t, "", roomID, aliceEventID2) sentinel.SlidingSyncUntilEventID(t, "", roomID, aliceEventID2)
// bob, who had just got alice's m.room.member event, shouldn't see it again. // bob, who had just got alice's m.room.member event, shouldn't see it again.

View File

@ -2,12 +2,14 @@ package syncv3_test
import ( import (
"fmt" "fmt"
"github.com/matrix-org/sliding-sync/sync3/extensions"
"github.com/tidwall/gjson"
"sync" "sync"
"testing" "testing"
"time" "time"
"github.com/matrix-org/complement/b"
"github.com/matrix-org/sliding-sync/sync3/extensions"
"github.com/tidwall/gjson"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils/m" "github.com/matrix-org/sliding-sync/testutils/m"
) )
@ -20,13 +22,13 @@ func TestMultipleLists(t *testing.T) {
var encryptedRoomIDs []string var encryptedRoomIDs []string
var unencryptedRoomIDs []string var unencryptedRoomIDs []string
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
unencryptedRoomID := alice.CreateRoom(t, map[string]interface{}{ unencryptedRoomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
unencryptedRoomIDs = append([]string{unencryptedRoomID}, unencryptedRoomIDs...) // push in array unencryptedRoomIDs = append([]string{unencryptedRoomID}, unencryptedRoomIDs...) // push in array
encryptedRoomID := alice.CreateRoom(t, map[string]interface{}{ encryptedRoomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
"initial_state": []Event{ "initial_state": []b.Event{
NewEncryptionEvent(), NewEncryptionEvent(),
}, },
}) })
@ -164,11 +166,11 @@ func TestMultipleListsDMUpdate(t *testing.T) {
// make 5 group rooms and make 5 DMs rooms. Room 0 is most recent to ease checks // make 5 group rooms and make 5 DMs rooms. Room 0 is most recent to ease checks
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
dmUserID := fmt.Sprintf("@dm_%d:synapse", i) // TODO: domain brittle dmUserID := fmt.Sprintf("@dm_%d:synapse", i) // TODO: domain brittle
groupRoomID := alice.CreateRoom(t, map[string]interface{}{ groupRoomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
groupRoomIDs = append([]string{groupRoomID}, groupRoomIDs...) // push in array groupRoomIDs = append([]string{groupRoomID}, groupRoomIDs...) // push in array
dmRoomID := alice.CreateRoom(t, map[string]interface{}{ dmRoomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "trusted_private_chat", "preset": "trusted_private_chat",
"is_direct": true, "is_direct": true,
"invite": []string{dmUserID}, "invite": []string{dmUserID},
@ -178,7 +180,7 @@ func TestMultipleListsDMUpdate(t *testing.T) {
time.Sleep(time.Millisecond) // ensure timestamp changes time.Sleep(time.Millisecond) // ensure timestamp changes
} }
// set the account data // set the account data
alice.SetGlobalAccountData(t, "m.direct", dmContent) alice.MustSetGlobalAccountData(t, "m.direct", dmContent)
// request 2 lists, one set DM, one set no DM // request 2 lists, one set DM, one set no DM
res := alice.SlidingSync(t, sync3.Request{ res := alice.SlidingSync(t, sync3.Request{
@ -222,7 +224,7 @@ func TestMultipleListsDMUpdate(t *testing.T) {
})) }))
// now bring the last DM room to the top with a notif // now bring the last DM room to the top with a notif
pingEventID := alice.SendEventSynced(t, dmRoomIDs[len(dmRoomIDs)-1], Event{ pingEventID := alice.SendEventSynced(t, dmRoomIDs[len(dmRoomIDs)-1], b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{"body": "ping", "msgtype": "m.text"}, Content: map[string]interface{}{"body": "ping", "msgtype": "m.text"},
}) })
@ -269,7 +271,7 @@ func TestNewListMidConnection(t *testing.T) {
var roomIDs []string var roomIDs []string
// make rooms // make rooms
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
roomID := alice.CreateRoom(t, map[string]interface{}{ roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
roomIDs = append([]string{roomID}, roomIDs...) // push in array roomIDs = append([]string{roomID}, roomIDs...) // push in array
@ -319,7 +321,7 @@ func TestMultipleOverlappingLists(t *testing.T) {
"preset": "private_chat", "preset": "private_chat",
} }
if isEncrypted { if isEncrypted {
createContent["initial_state"] = []Event{ createContent["initial_state"] = []b.Event{
NewEncryptionEvent(), NewEncryptionEvent(),
} }
} }
@ -327,7 +329,7 @@ func TestMultipleOverlappingLists(t *testing.T) {
createContent["is_direct"] = true createContent["is_direct"] = true
createContent["invite"] = []string{dmUserID} createContent["invite"] = []string{dmUserID}
} }
roomID := alice.CreateRoom(t, createContent) roomID := alice.MustCreateRoom(t, createContent)
time.Sleep(time.Millisecond) time.Sleep(time.Millisecond)
if isDM { if isDM {
var roomIDs []string var roomIDs []string
@ -346,7 +348,7 @@ func TestMultipleOverlappingLists(t *testing.T) {
// set the account data // set the account data
t.Logf("DM rooms: %v", dmRoomIDs) t.Logf("DM rooms: %v", dmRoomIDs)
t.Logf("Encrypted rooms: %v", encryptedRoomIDs) t.Logf("Encrypted rooms: %v", encryptedRoomIDs)
alice.SetGlobalAccountData(t, "m.direct", dmContent) alice.MustSetGlobalAccountData(t, "m.direct", dmContent)
// seed the proxy: so we can get timeline correctly as it uses limit:1 initially. // seed the proxy: so we can get timeline correctly as it uses limit:1 initially.
alice.SlidingSync(t, sync3.Request{}) alice.SlidingSync(t, sync3.Request{})
@ -357,7 +359,7 @@ func TestMultipleOverlappingLists(t *testing.T) {
// - This ping message (always) // - This ping message (always)
roomToEventID := make(map[string]string, len(allRoomIDs)) roomToEventID := make(map[string]string, len(allRoomIDs))
for i := len(allRoomIDs) - 1; i >= 0; i-- { for i := len(allRoomIDs) - 1; i >= 0; i-- {
roomToEventID[allRoomIDs[i]] = alice.SendEventSynced(t, allRoomIDs[i], Event{ roomToEventID[allRoomIDs[i]] = alice.SendEventSynced(t, allRoomIDs[i], b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{"body": "ping", "msgtype": "m.text"}, Content: map[string]interface{}{"body": "ping", "msgtype": "m.text"},
}) })
@ -539,7 +541,7 @@ func TestNot500OnNewRooms(t *testing.T) {
}, },
}, },
}) })
alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat"})
alice.SlidingSync(t, sync3.Request{ alice.SlidingSync(t, sync3.Request{
Lists: map[string]sync3.RequestList{ Lists: map[string]sync3.RequestList{
"a": { "a": {
@ -556,7 +558,7 @@ func TestNot500OnNewRooms(t *testing.T) {
}, },
}, },
}, WithPos(res.Pos)) }, WithPos(res.Pos))
alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat"})
// should not 500 // should not 500
alice.SlidingSync(t, sync3.Request{ alice.SlidingSync(t, sync3.Request{
Lists: map[string]sync3.RequestList{ Lists: map[string]sync3.RequestList{
@ -594,7 +596,7 @@ func TestNewRoomNameCalculations(t *testing.T) {
go func() { go func() {
for i := range ch { for i := range ch {
roomName := fmt.Sprintf("room %d", i) roomName := fmt.Sprintf("room %d", i)
roomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": roomName}) roomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": roomName})
roomIDToName.Store(roomID, roomName) roomIDToName.Store(roomID, roomName)
} }
}() }()
@ -698,7 +700,7 @@ func TestChangeSortOrder(t *testing.T) {
} }
for i, name := range roomNames { for i, name := range roomNames {
roomIDs[i] = alice.CreateRoom(t, map[string]interface{}{ roomIDs[i] = alice.MustCreateRoom(t, map[string]interface{}{
"name": name, "name": name,
}) })
// we cannot guarantee we will see the right state yet, so just keep track of the room names // we cannot guarantee we will see the right state yet, so just keep track of the room names
@ -739,7 +741,7 @@ func TestShrinkRange(t *testing.T) {
var roomIDs []string // most recent first var roomIDs []string // most recent first
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
time.Sleep(time.Millisecond) // ensure creation timestamp changes time.Sleep(time.Millisecond) // ensure creation timestamp changes
roomIDs = append([]string{alice.CreateRoom(t, map[string]interface{}{ roomIDs = append([]string{alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
"name": fmt.Sprintf("Room %d", i), "name": fmt.Sprintf("Room %d", i),
})}, roomIDs...) })}, roomIDs...)
@ -775,7 +777,7 @@ func TestExpandRange(t *testing.T) {
var roomIDs []string // most recent first var roomIDs []string // most recent first
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
time.Sleep(time.Millisecond) // ensure creation timestamp changes time.Sleep(time.Millisecond) // ensure creation timestamp changes
roomIDs = append([]string{alice.CreateRoom(t, map[string]interface{}{ roomIDs = append([]string{alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
"name": fmt.Sprintf("Room %d", i), "name": fmt.Sprintf("Room %d", i),
})}, roomIDs...) })}, roomIDs...)
@ -809,7 +811,7 @@ func TestMultipleSameList(t *testing.T) {
var roomIDs []string // most recent first var roomIDs []string // most recent first
for i := 0; i < 16; i++ { for i := 0; i < 16; i++ {
time.Sleep(time.Millisecond) // ensure creation timestamp changes time.Sleep(time.Millisecond) // ensure creation timestamp changes
roomIDs = append([]string{alice.CreateRoom(t, map[string]interface{}{ roomIDs = append([]string{alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
"name": fmt.Sprintf("Room %d", i), "name": fmt.Sprintf("Room %d", i),
})}, roomIDs...) })}, roomIDs...)
@ -865,14 +867,14 @@ func TestBumpEventTypesHandling(t *testing.T) {
charlie := registerNamedUser(t, "charlie") charlie := registerNamedUser(t, "charlie")
t.Log("Alice creates two rooms") t.Log("Alice creates two rooms")
room1 := alice.CreateRoom( room1 := alice.MustCreateRoom(
t, t,
map[string]interface{}{ map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
"name": "room1", "name": "room1",
}, },
) )
room2 := alice.CreateRoom( room2 := alice.MustCreateRoom(
t, t,
map[string]interface{}{ map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
@ -885,14 +887,14 @@ func TestBumpEventTypesHandling(t *testing.T) {
bob.JoinRoom(t, room2, nil) bob.JoinRoom(t, room2, nil)
t.Log("Bob sends a message in room 2 then room 1.") t.Log("Bob sends a message in room 2 then room 1.")
bob.SendEventSynced(t, room2, Event{ bob.SendEventSynced(t, room2, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"body": "Hi room 2", "body": "Hi room 2",
"msgtype": "m.text", "msgtype": "m.text",
}, },
}) })
bob.SendEventSynced(t, room1, Event{ bob.SendEventSynced(t, room1, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"body": "Hello world", "body": "Hello world",
@ -1017,18 +1019,18 @@ func TestBumpEventTypesInOverlappingLists(t *testing.T) {
bob := registerNamedUser(t, "bob") bob := registerNamedUser(t, "bob")
t.Log("Alice creates four rooms") t.Log("Alice creates four rooms")
room1 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room1"}) room1 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room1"})
room2 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room2"}) room2 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room2"})
room3 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room3"}) room3 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room3"})
room4 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room4"}) room4 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room4"})
t.Log("Alice writes a message in all four rooms.") t.Log("Alice writes a message in all four rooms.")
// Note: all lists bump on messages, so this will ensure the recency order is sensible. // Note: all lists bump on messages, so this will ensure the recency order is sensible.
helloWorld := map[string]interface{}{"body": "Hello world", "msgtype": "m.text"} helloWorld := map[string]interface{}{"body": "Hello world", "msgtype": "m.text"}
alice.SendEventUnsynced(t, room1, Event{Type: "m.room.message", Content: helloWorld}) alice.Unsafe_SendEventUnsynced(t, room1, b.Event{Type: "m.room.message", Content: helloWorld})
alice.SendEventUnsynced(t, room2, Event{Type: "m.room.message", Content: helloWorld}) alice.Unsafe_SendEventUnsynced(t, room2, b.Event{Type: "m.room.message", Content: helloWorld})
alice.SendEventUnsynced(t, room3, Event{Type: "m.room.message", Content: helloWorld}) alice.Unsafe_SendEventUnsynced(t, room3, b.Event{Type: "m.room.message", Content: helloWorld})
alice.SendEventSynced(t, room4, Event{Type: "m.room.message", Content: helloWorld}) alice.SendEventSynced(t, room4, b.Event{Type: "m.room.message", Content: helloWorld})
t.Log("Alice requests a sync with three lists: one bumping on messages, a second bumping on messages and memberships, and a third bumping on all events.") t.Log("Alice requests a sync with three lists: one bumping on messages, a second bumping on messages and memberships, and a third bumping on all events.")
const listMsg = "message" const listMsg = "message"
@ -1093,7 +1095,11 @@ func TestBumpEventTypesInOverlappingLists(t *testing.T) {
})) }))
t.Log("Alice sets a room topic in room 3, and syncs until she sees the topic.") t.Log("Alice sets a room topic in room 3, and syncs until she sees the topic.")
topicEventID := alice.SetState(t, room3, "m.room.topic", "", map[string]interface{}{"topic": "spicy meatballs"}) topicEventID := alice.Unsafe_SendEventUnsynced(t, room3, b.Event{
Type: "m.room.topic",
StateKey: ptr(""),
Content: map[string]interface{}{"topic": "spicy meatballs"},
})
res = alice.SlidingSyncUntilEventID(t, res.Pos, room3, topicEventID) res = alice.SlidingSyncUntilEventID(t, res.Pos, room3, topicEventID)
t.Logf("Alice sees room3 bump in the %s list only", listAll) t.Logf("Alice sees room3 bump in the %s list only", listAll)
@ -1104,7 +1110,7 @@ func TestBumpEventTypesInOverlappingLists(t *testing.T) {
})) }))
t.Logf("Alice sends a message in room 2, and syncs until she sees it.") t.Logf("Alice sends a message in room 2, and syncs until she sees it.")
msgEventID := alice.SendEventUnsynced(t, room2, Event{Type: "m.room.message", Content: helloWorld}) msgEventID := alice.Unsafe_SendEventUnsynced(t, room2, b.Event{Type: "m.room.message", Content: helloWorld})
res = alice.SlidingSyncUntilEventID(t, res.Pos, room2, msgEventID) res = alice.SlidingSyncUntilEventID(t, res.Pos, room2, msgEventID)
t.Logf("Alice sees room2 bump in all lists") t.Logf("Alice sees room2 bump in all lists")
@ -1121,25 +1127,33 @@ func TestBumpEventTypesDoesntLeakOnNewConnAfterJoin(t *testing.T) {
bob := registerNamedUser(t, "bob") bob := registerNamedUser(t, "bob")
t.Log("Alice creates a room and sends a secret state event.") t.Log("Alice creates a room and sends a secret state event.")
room1 := alice.CreateRoom( room1 := alice.MustCreateRoom(
t, t,
map[string]interface{}{ map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
"name": "room1", "name": "room1",
}, },
) )
alice.SetState(t, room1, "secret", "", map[string]interface{}{}) alice.Unsafe_SendEventUnsynced(t, room1, b.Event{
Type: "secret",
StateKey: ptr(""),
Content: map[string]interface{}{},
})
t.Log("Bob creates a room and sends a secret state event.") t.Log("Bob creates a room and sends a secret state event.")
time.Sleep(1 * time.Millisecond) time.Sleep(1 * time.Millisecond)
room2 := bob.CreateRoom( room2 := bob.MustCreateRoom(
t, t,
map[string]interface{}{ map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
"name": "room1", "name": "room1",
}, },
) )
bob.SetState(t, room2, "secret", "", map[string]interface{}{}) bob.Unsafe_SendEventUnsynced(t, room2, b.Event{
Type: "secret",
StateKey: ptr(""),
Content: map[string]interface{}{},
})
t.Log("Alice invites Bob, who accepts.") t.Log("Alice invites Bob, who accepts.")
alice.InviteRoom(t, room1, bob.UserID) alice.InviteRoom(t, room1, bob.UserID)
@ -1184,25 +1198,33 @@ func TestBumpEventTypesDoesntLeakOnNewConnAfterInvite(t *testing.T) {
bob := registerNamedUser(t, "bob") bob := registerNamedUser(t, "bob")
t.Log("Alice creates a room and sends a secret state event.") t.Log("Alice creates a room and sends a secret state event.")
room1 := alice.CreateRoom( room1 := alice.MustCreateRoom(
t, t,
map[string]interface{}{ map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
"name": "room1", "name": "room1",
}, },
) )
alice.SetState(t, room1, "secret", "", map[string]interface{}{}) alice.Unsafe_SendEventUnsynced(t, room1, b.Event{
Type: "secret",
StateKey: ptr(""),
Content: map[string]interface{}{},
})
t.Log("Bob creates a room and sends a secret state event.") t.Log("Bob creates a room and sends a secret state event.")
time.Sleep(1 * time.Millisecond) time.Sleep(1 * time.Millisecond)
room2 := bob.CreateRoom( room2 := bob.MustCreateRoom(
t, t,
map[string]interface{}{ map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
"name": "room1", "name": "room1",
}, },
) )
bob.SetState(t, room2, "secret", "", map[string]interface{}{}) bob.Unsafe_SendEventUnsynced(t, room2, b.Event{
Type: "secret",
StateKey: ptr(""),
Content: map[string]interface{}{},
})
t.Log("Alice invites Bob, who does not respond.") t.Log("Alice invites Bob, who does not respond.")
alice.InviteRoom(t, room1, bob.UserID) alice.InviteRoom(t, room1, bob.UserID)
@ -1245,9 +1267,9 @@ func TestRangeOutsideTotalRooms(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
t.Log("Alice makes three public rooms.") t.Log("Alice makes three public rooms.")
room0 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "A"}) room0 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "A"})
room1 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "B"}) room1 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "B"})
room2 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "C"}) room2 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "C"})
t.Log("Alice initial syncs, requesting room ranges [0, 1] and [8, 9]") t.Log("Alice initial syncs, requesting room ranges [0, 1] and [8, 9]")
syncRes := alice.SlidingSync(t, sync3.Request{ syncRes := alice.SlidingSync(t, sync3.Request{
@ -1331,24 +1353,24 @@ func TestAvatarFieldInRoomResponse(t *testing.T) {
chris.SetAvatar(t, chrisAvatar) chris.SetAvatar(t, chrisAvatar)
t.Log("Alice makes a public room, a DM with herself, a DM with Bob, a DM with Chris, and a group-DM with Bob and Chris.") t.Log("Alice makes a public room, a DM with herself, a DM with Bob, a DM with Chris, and a group-DM with Bob and Chris.")
public := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) public := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat"})
// TODO: you can create a DM with yourself e.g. as below. It probably ought to have // TODO: you can create a DM with yourself e.g. as below. It probably ought to have
// your own face as an avatar. // your own face as an avatar.
// dmAlice := alice.CreateRoom(t, map[string]interface{}{ // dmAlice := alice.MustCreateRoom(t, map[string]interface{}{
// "preset": "trusted_private_chat", // "preset": "trusted_private_chat",
// "is_direct": true, // "is_direct": true,
// }) // })
dmBob := alice.CreateRoom(t, map[string]interface{}{ dmBob := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "trusted_private_chat", "preset": "trusted_private_chat",
"is_direct": true, "is_direct": true,
"invite": []string{bob.UserID}, "invite": []string{bob.UserID},
}) })
dmChris := alice.CreateRoom(t, map[string]interface{}{ dmChris := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "trusted_private_chat", "preset": "trusted_private_chat",
"is_direct": true, "is_direct": true,
"invite": []string{chris.UserID}, "invite": []string{chris.UserID},
}) })
dmBobChris := alice.CreateRoom(t, map[string]interface{}{ dmBobChris := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "trusted_private_chat", "preset": "trusted_private_chat",
"is_direct": true, "is_direct": true,
"invite": []string{bob.UserID, chris.UserID}, "invite": []string{bob.UserID, chris.UserID},
@ -1380,7 +1402,7 @@ func TestAvatarFieldInRoomResponse(t *testing.T) {
t.Run("Avatar not resent on message", func(t *testing.T) { t.Run("Avatar not resent on message", func(t *testing.T) {
t.Log("Bob sends a sentinel message.") t.Log("Bob sends a sentinel message.")
sentinel := bob.SendEventSynced(t, dmBob, Event{ sentinel := bob.SendEventSynced(t, dmBob, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"body": "Hello world", "body": "Hello world",
@ -1497,8 +1519,12 @@ func TestAvatarFieldInRoomResponse(t *testing.T) {
t.Run("Explicit avatar propagates in non-DM room", func(t *testing.T) { t.Run("Explicit avatar propagates in non-DM room", func(t *testing.T) {
t.Log("Alice sets an avatar for the public room.") t.Log("Alice sets an avatar for the public room.")
publicAvatar := uploadAvatar(alice, "public.png") publicAvatar := uploadAvatar(alice, "public.png")
alice.SetState(t, public, "m.room.avatar", "", map[string]interface{}{ alice.Unsafe_SendEventUnsynced(t, public, b.Event{
"url": publicAvatar, Type: "m.room.avatar",
StateKey: ptr(""),
Content: map[string]interface{}{
"url": publicAvatar,
},
}) })
t.Log("Alice syncs until she sees that avatar.") t.Log("Alice syncs until she sees that avatar.")
res = alice.SlidingSyncUntil( res = alice.SlidingSyncUntil(
@ -1512,8 +1538,12 @@ func TestAvatarFieldInRoomResponse(t *testing.T) {
t.Log("Alice changes the avatar for the public room.") t.Log("Alice changes the avatar for the public room.")
publicAvatar2 := uploadAvatar(alice, "public2.png") publicAvatar2 := uploadAvatar(alice, "public2.png")
alice.SetState(t, public, "m.room.avatar", "", map[string]interface{}{ alice.Unsafe_SendEventUnsynced(t, public, b.Event{
"url": publicAvatar2, Type: "m.room.avatar",
StateKey: ptr(""),
Content: map[string]interface{}{
"url": publicAvatar2,
},
}) })
t.Log("Alice syncs until she sees that avatar.") t.Log("Alice syncs until she sees that avatar.")
res = alice.SlidingSyncUntil( res = alice.SlidingSyncUntil(
@ -1526,7 +1556,11 @@ func TestAvatarFieldInRoomResponse(t *testing.T) {
) )
t.Log("Alice removes the avatar for the public room.") t.Log("Alice removes the avatar for the public room.")
alice.SetState(t, public, "m.room.avatar", "", map[string]interface{}{}) alice.Unsafe_SendEventUnsynced(t, public, b.Event{
Type: "m.room.avatar",
StateKey: ptr(""),
Content: map[string]interface{}{},
})
t.Log("Alice syncs until she sees that avatar vanish.") t.Log("Alice syncs until she sees that avatar vanish.")
res = alice.SlidingSyncUntil( res = alice.SlidingSyncUntil(
t, t,
@ -1559,8 +1593,12 @@ func TestAvatarFieldInRoomResponse(t *testing.T) {
t.Log("Chris gives their DM a bespoke avatar.") t.Log("Chris gives their DM a bespoke avatar.")
dmAvatar := uploadAvatar(chris, "dm.png") dmAvatar := uploadAvatar(chris, "dm.png")
chris.SetState(t, dmChris, "m.room.avatar", "", map[string]interface{}{ chris.Unsafe_SendEventUnsynced(t, dmChris, b.Event{
"url": dmAvatar, Type: "m.room.avatar",
StateKey: ptr(""),
Content: map[string]interface{}{
"url": dmAvatar,
},
}) })
t.Log("Alice syncs until she sees that avatar.") t.Log("Alice syncs until she sees that avatar.")
@ -1586,15 +1624,23 @@ func TestAvatarFieldInRoomResponse(t *testing.T) {
t.Log("Chris updates the DM's avatar.") t.Log("Chris updates the DM's avatar.")
dmAvatar2 := uploadAvatar(chris, "dm2.png") dmAvatar2 := uploadAvatar(chris, "dm2.png")
chris.SetState(t, dmChris, "m.room.avatar", "", map[string]interface{}{ chris.Unsafe_SendEventUnsynced(t, dmChris, b.Event{
"url": dmAvatar2, Type: "m.room.avatar",
StateKey: ptr(""),
Content: map[string]interface{}{
"url": dmAvatar2,
},
}) })
t.Log("Alice syncs until she sees that avatar.") t.Log("Alice syncs until she sees that avatar.")
res = alice.SlidingSyncUntil(t, res.Pos, sync3.Request{}, m.MatchRoomSubscription(dmChris, m.MatchRoomAvatar(dmAvatar2))) res = alice.SlidingSyncUntil(t, res.Pos, sync3.Request{}, m.MatchRoomSubscription(dmChris, m.MatchRoomAvatar(dmAvatar2)))
t.Log("Chris removes the DM's avatar.") t.Log("Chris removes the DM's avatar.")
chris.SetState(t, dmChris, "m.room.avatar", "", map[string]interface{}{}) chris.Unsafe_SendEventUnsynced(t, dmChris, b.Event{
Type: "m.room.avatar",
StateKey: ptr(""),
Content: map[string]interface{}{},
})
t.Log("Alice syncs until the DM avatar returns to Chris's most recent avatar.") t.Log("Alice syncs until the DM avatar returns to Chris's most recent avatar.")
res = alice.SlidingSyncUntil(t, res.Pos, sync3.Request{}, m.MatchRoomSubscription(dmChris, m.MatchRoomAvatar(chris.AvatarURL))) res = alice.SlidingSyncUntil(t, res.Pos, sync3.Request{}, m.MatchRoomSubscription(dmChris, m.MatchRoomAvatar(chris.AvatarURL)))
@ -1603,7 +1649,7 @@ func TestAvatarFieldInRoomResponse(t *testing.T) {
t.Run("Changing DM flag", func(t *testing.T) { t.Run("Changing DM flag", func(t *testing.T) {
t.Skip("TODO: unimplemented") t.Skip("TODO: unimplemented")
t.Log("Alice clears the DM flag on Bob's room.") t.Log("Alice clears the DM flag on Bob's room.")
alice.SetGlobalAccountData(t, "m.direct", map[string]interface{}{ alice.MustSetGlobalAccountData(t, "m.direct", map[string]interface{}{
"content": map[string][]string{ "content": map[string][]string{
bob.UserID: {}, // no dmBob here bob.UserID: {}, // no dmBob here
chris.UserID: {dmChris, dmBobChris}, chris.UserID: {dmChris, dmBobChris},
@ -1636,7 +1682,7 @@ func TestAvatarFieldInRoomResponse(t *testing.T) {
})) }))
t.Log("Alice sets the DM flag on Bob's room.") t.Log("Alice sets the DM flag on Bob's room.")
alice.SetGlobalAccountData(t, "m.direct", map[string]interface{}{ alice.MustSetGlobalAccountData(t, "m.direct", map[string]interface{}{
"content": map[string][]string{ "content": map[string][]string{
bob.UserID: {dmBob}, // dmBob reinstated bob.UserID: {dmBob}, // dmBob reinstated
chris.UserID: {dmChris, dmBobChris}, chris.UserID: {dmChris, dmBobChris},
@ -1672,7 +1718,7 @@ func TestAvatarFieldInRoomResponse(t *testing.T) {
t.Run("See avatar when invited", func(t *testing.T) { t.Run("See avatar when invited", func(t *testing.T) {
t.Log("Chris invites Alice to a DM.") t.Log("Chris invites Alice to a DM.")
dmInvited := chris.CreateRoom(t, map[string]interface{}{ dmInvited := chris.MustCreateRoom(t, map[string]interface{}{
"preset": "trusted_private_chat", "preset": "trusted_private_chat",
"is_direct": true, "is_direct": true,
"invite": []string{alice.UserID}, "invite": []string{alice.UserID},

View File

@ -3,7 +3,6 @@ package syncv3_test
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/url"
"os" "os"
"reflect" "reflect"
"sort" "sort"
@ -12,6 +11,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/matrix-org/complement/client"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils/m" "github.com/matrix-org/sliding-sync/testutils/m"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
@ -33,13 +33,6 @@ func TestMain(m *testing.M) {
os.Exit(exitCode) os.Exit(exitCode)
} }
func WithPos(pos string) RequestOpt {
return WithQueries(url.Values{
"pos": []string{pos},
"timeout": []string{"500"}, // 0.5s
})
}
func assertEventsEqual(t *testing.T, wantList []Event, gotList []json.RawMessage) { func assertEventsEqual(t *testing.T, wantList []Event, gotList []json.RawMessage) {
t.Helper() t.Helper()
err := eventsEqual(wantList, gotList) err := eventsEqual(wantList, gotList)
@ -212,11 +205,13 @@ func registerNewUser(t *testing.T) *CSAPI {
func registerNamedUser(t *testing.T, localpartPrefix string) *CSAPI { func registerNamedUser(t *testing.T, localpartPrefix string) *CSAPI {
// create user // create user
localpart := fmt.Sprintf("%s-%d-%d", localpartPrefix, time.Now().Unix(), atomic.AddUint64(&userCounter, 1)) localpart := fmt.Sprintf("%s-%d-%d", localpartPrefix, time.Now().Unix(), atomic.AddUint64(&userCounter, 1))
httpClient := NewLoggedClient(t, "localhost", nil) httpClient := client.NewLoggedClient(t, "localhost", nil)
client := &CSAPI{ client := &CSAPI{
Client: httpClient, CSAPI: &client.CSAPI{
BaseURL: homeserverBaseURL, Client: httpClient,
SyncUntilTimeout: 3 * time.Second, BaseURL: homeserverBaseURL,
SyncUntilTimeout: 3 * time.Second,
},
} }
client.UserID, client.AccessToken, client.DeviceID = client.RegisterUser(t, localpart, "password") client.UserID, client.AccessToken, client.DeviceID = client.RegisterUser(t, localpart, "password")

View File

@ -5,6 +5,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/matrix-org/complement/b"
"github.com/matrix-org/complement/client"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils/m" "github.com/matrix-org/sliding-sync/testutils/m"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
@ -15,19 +17,19 @@ func TestRoomStateTransitions(t *testing.T) {
bob := registerNewUser(t) bob := registerNewUser(t)
// make 4 rooms and set bob's membership state in each to a different value. // make 4 rooms and set bob's membership state in each to a different value.
joinRoomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) joinRoomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat"})
bob.JoinRoom(t, joinRoomID, nil) bob.JoinRoom(t, joinRoomID, nil)
kickRoomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) kickRoomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat"})
bob.JoinRoom(t, kickRoomID, nil) bob.JoinRoom(t, kickRoomID, nil)
alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", kickRoomID, "kick"}, WithJSONBody(t, map[string]interface{}{ alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", kickRoomID, "kick"}, client.WithJSONBody(t, map[string]interface{}{
"user_id": bob.UserID, "user_id": bob.UserID,
})) }))
banRoomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) banRoomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat"})
bob.JoinRoom(t, banRoomID, nil) bob.JoinRoom(t, banRoomID, nil)
alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", banRoomID, "ban"}, WithJSONBody(t, map[string]interface{}{ alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", banRoomID, "ban"}, client.WithJSONBody(t, map[string]interface{}{
"user_id": bob.UserID, "user_id": bob.UserID,
})) }))
inviteRoomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) inviteRoomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat"})
alice.InviteRoom(t, inviteRoomID, bob.UserID) alice.InviteRoom(t, inviteRoomID, bob.UserID)
// seed the proxy with Alice data // seed the proxy with Alice data
@ -134,9 +136,9 @@ func TestInviteRejection(t *testing.T) {
// ensure that invite state correctly propagates. One room will already be in 'invite' state // ensure that invite state correctly propagates. One room will already be in 'invite' state
// prior to the first proxy sync, whereas the 2nd will transition. // prior to the first proxy sync, whereas the 2nd will transition.
firstInviteRoomID := alice.CreateRoom(t, map[string]interface{}{"preset": "private_chat", "name": "First"}) firstInviteRoomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "private_chat", "name": "First"})
alice.InviteRoom(t, firstInviteRoomID, bob.UserID) alice.InviteRoom(t, firstInviteRoomID, bob.UserID)
secondInviteRoomID := alice.CreateRoom(t, map[string]interface{}{"preset": "private_chat", "name": "Second"}) secondInviteRoomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "private_chat", "name": "Second"})
t.Logf("TestInviteRejection first %s second %s", firstInviteRoomID, secondInviteRoomID) t.Logf("TestInviteRejection first %s second %s", firstInviteRoomID, secondInviteRoomID)
// sync as bob, we should see 1 invite // sync as bob, we should see 1 invite
@ -169,10 +171,10 @@ func TestInviteRejection(t *testing.T) {
}, },
})) }))
_, since := bob.MustSync(t, SyncReq{}) _, since := bob.MustSync(t, client.SyncReq{})
// now invite bob // now invite bob
alice.InviteRoom(t, secondInviteRoomID, bob.UserID) alice.InviteRoom(t, secondInviteRoomID, bob.UserID)
since = bob.MustSyncUntil(t, SyncReq{Since: since}, SyncInvitedTo(bob.UserID, secondInviteRoomID)) since = bob.MustSyncUntil(t, client.SyncReq{Since: since}, client.SyncInvitedTo(bob.UserID, secondInviteRoomID))
res = bob.SlidingSync(t, sync3.Request{ res = bob.SlidingSync(t, sync3.Request{
Lists: map[string]sync3.RequestList{ Lists: map[string]sync3.RequestList{
@ -203,7 +205,7 @@ func TestInviteRejection(t *testing.T) {
bob.LeaveRoom(t, firstInviteRoomID) bob.LeaveRoom(t, firstInviteRoomID)
bob.LeaveRoom(t, secondInviteRoomID) bob.LeaveRoom(t, secondInviteRoomID)
bob.MustSyncUntil(t, SyncReq{Since: since}, SyncLeftFrom(bob.UserID, secondInviteRoomID)) bob.MustSyncUntil(t, client.SyncReq{Since: since}, client.SyncLeftFrom(bob.UserID, secondInviteRoomID))
// TODO: proxy needs to have processed this event enough for it to be waiting for us // TODO: proxy needs to have processed this event enough for it to be waiting for us
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
@ -241,9 +243,9 @@ func TestInviteAcceptance(t *testing.T) {
// ensure that invite state correctly propagates. One room will already be in 'invite' state // ensure that invite state correctly propagates. One room will already be in 'invite' state
// prior to the first proxy sync, whereas the 2nd will transition. // prior to the first proxy sync, whereas the 2nd will transition.
t.Logf("Alice creates two rooms and invites Bob to the first.") t.Logf("Alice creates two rooms and invites Bob to the first.")
firstInviteRoomID := alice.CreateRoom(t, map[string]interface{}{"preset": "private_chat", "name": "First"}) firstInviteRoomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "private_chat", "name": "First"})
alice.InviteRoom(t, firstInviteRoomID, bob.UserID) alice.InviteRoom(t, firstInviteRoomID, bob.UserID)
secondInviteRoomID := alice.CreateRoom(t, map[string]interface{}{"preset": "private_chat", "name": "Second"}) secondInviteRoomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "private_chat", "name": "Second"})
t.Logf("first %s second %s", firstInviteRoomID, secondInviteRoomID) t.Logf("first %s second %s", firstInviteRoomID, secondInviteRoomID)
t.Log("Sync as Bob, requesting invites only. He should see 1 invite") t.Log("Sync as Bob, requesting invites only. He should see 1 invite")
@ -353,7 +355,7 @@ func TestInviteRejectionTwice(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
bob := registerNewUser(t) bob := registerNewUser(t)
roomName := "It's-a-me-invitio" roomName := "It's-a-me-invitio"
inviteRoomID := alice.CreateRoom(t, map[string]interface{}{"preset": "private_chat", "name": roomName}) inviteRoomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "private_chat", "name": roomName})
t.Logf("TestInviteRejectionTwice room %s", inviteRoomID) t.Logf("TestInviteRejectionTwice room %s", inviteRoomID)
// sync as bob, we see no invites yet. // sync as bob, we see no invites yet.
@ -406,7 +408,7 @@ func TestLeavingRoomReturnsOneEvent(t *testing.T) {
for _, aliceSyncing := range []bool{false, true} { for _, aliceSyncing := range []bool{false, true} {
t.Run(fmt.Sprintf("leaving a room returns one leave event (multiple poller=%v)", aliceSyncing), func(t *testing.T) { t.Run(fmt.Sprintf("leaving a room returns one leave event (multiple poller=%v)", aliceSyncing), func(t *testing.T) {
inviteRoomID := alice.CreateRoom(t, map[string]interface{}{"preset": "private_chat", "name": roomName}) inviteRoomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "private_chat", "name": roomName})
t.Logf("TestLeavingRoomReturnsOneEvent room %s", inviteRoomID) t.Logf("TestLeavingRoomReturnsOneEvent room %s", inviteRoomID)
if aliceSyncing { if aliceSyncing {
@ -476,7 +478,7 @@ func TestRejectingInviteReturnsOneEvent(t *testing.T) {
for _, aliceSyncing := range []bool{false, true} { for _, aliceSyncing := range []bool{false, true} {
t.Run(fmt.Sprintf("rejecting an invite returns one leave event (multiple poller=%v)", aliceSyncing), func(t *testing.T) { t.Run(fmt.Sprintf("rejecting an invite returns one leave event (multiple poller=%v)", aliceSyncing), func(t *testing.T) {
inviteRoomID := alice.CreateRoom(t, map[string]interface{}{"preset": "private_chat", "name": roomName}) inviteRoomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "private_chat", "name": roomName})
t.Logf("TestRejectingInviteReturnsOneEvent room %s", inviteRoomID) t.Logf("TestRejectingInviteReturnsOneEvent room %s", inviteRoomID)
if aliceSyncing { if aliceSyncing {
@ -542,7 +544,7 @@ func TestHeroesOnMembershipChanges(t *testing.T) {
t.Run("nameless room uses heroes to calculate roomname", func(t *testing.T) { t.Run("nameless room uses heroes to calculate roomname", func(t *testing.T) {
// create a room without a name, to ensure we calculate the room name based on // create a room without a name, to ensure we calculate the room name based on
// room heroes // room heroes
roomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) roomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat"})
bob.JoinRoom(t, roomID, []string{}) bob.JoinRoom(t, roomID, []string{})
@ -571,7 +573,7 @@ func TestHeroesOnMembershipChanges(t *testing.T) {
} }
// Send a message, the heroes shouldn't change // Send a message, the heroes shouldn't change
msgEv := bob.SendEventSynced(t, roomID, Event{ msgEv := bob.SendEventSynced(t, roomID, b.Event{
Type: "m.room.roomID", Type: "m.room.roomID",
Content: map[string]interface{}{"body": "Hello world", "msgtype": "m.text"}, Content: map[string]interface{}{"body": "Hello world", "msgtype": "m.text"},
}) })
@ -593,7 +595,7 @@ func TestHeroesOnMembershipChanges(t *testing.T) {
}) })
t.Run("named rooms don't have heroes", func(t *testing.T) { t.Run("named rooms don't have heroes", func(t *testing.T) {
namedRoomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "my room without heroes"}) namedRoomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "my room without heroes"})
// this makes sure that even if bob is joined, we don't return any heroes // this makes sure that even if bob is joined, we don't return any heroes
bob.JoinRoom(t, namedRoomID, []string{}) bob.JoinRoom(t, namedRoomID, []string{})
@ -604,14 +606,18 @@ func TestHeroesOnMembershipChanges(t *testing.T) {
}) })
t.Run("rooms with aliases don't have heroes", func(t *testing.T) { t.Run("rooms with aliases don't have heroes", func(t *testing.T) {
aliasRoomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) aliasRoomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat"})
alias := fmt.Sprintf("#%s-%d:%s", t.Name(), time.Now().Unix(), alice.Domain) alias := fmt.Sprintf("#%s-%d:%s", t.Name(), time.Now().Unix(), alice.Domain)
alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "directory", "room", alias}, alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "directory", "room", alias},
WithJSONBody(t, map[string]any{"room_id": aliasRoomID}), client.WithJSONBody(t, map[string]any{"room_id": aliasRoomID}),
) )
alice.SetState(t, aliasRoomID, "m.room.canonical_alias", "", map[string]any{ alice.Unsafe_SendEventUnsynced(t, aliasRoomID, b.Event{
"alias": alias, Type: "m.room.canonical_alias",
StateKey: ptr(""),
Content: map[string]any{
"alias": alias,
},
}) })
bob.JoinRoom(t, aliasRoomID, []string{}) bob.JoinRoom(t, aliasRoomID, []string{})
@ -623,7 +629,7 @@ func TestHeroesOnMembershipChanges(t *testing.T) {
}) })
t.Run("can set heroes=true on room subscriptions", func(t *testing.T) { t.Run("can set heroes=true on room subscriptions", func(t *testing.T) {
subRoomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) subRoomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat"})
bob.JoinRoom(t, subRoomID, []string{}) bob.JoinRoom(t, subRoomID, []string{})
res := alice.SlidingSyncUntilMembership(t, "", subRoomID, bob, "join") res := alice.SlidingSyncUntilMembership(t, "", subRoomID, bob, "join")
@ -636,7 +642,7 @@ func TestHeroesOnMembershipChanges(t *testing.T) {
}) })
t.Run("can set heroes=true in lists", func(t *testing.T) { t.Run("can set heroes=true in lists", func(t *testing.T) {
listRoomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) listRoomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat"})
bob.JoinRoom(t, listRoomID, []string{}) bob.JoinRoom(t, listRoomID, []string{})
res := alice.SlidingSyncUntil(t, "", sync3.Request{ res := alice.SlidingSyncUntil(t, "", sync3.Request{
@ -683,9 +689,9 @@ func TestMemberCounts(t *testing.T) {
bob := registerNewUser(t) bob := registerNewUser(t)
charlie := registerNewUser(t) charlie := registerNewUser(t)
firstRoomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "First"}) firstRoomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "First"})
alice.InviteRoom(t, firstRoomID, bob.UserID) alice.InviteRoom(t, firstRoomID, bob.UserID)
secondRoomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "Second"}) secondRoomID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "Second"})
alice.InviteRoom(t, secondRoomID, bob.UserID) alice.InviteRoom(t, secondRoomID, bob.UserID)
charlie.JoinRoom(t, secondRoomID, nil) charlie.JoinRoom(t, secondRoomID, nil)
t.Logf("first %s second %s", firstRoomID, secondRoomID) t.Logf("first %s second %s", firstRoomID, secondRoomID)
@ -758,7 +764,7 @@ func TestMemberCounts(t *testing.T) {
})) }))
// sending a message shouldn't update the count as it wastes bandwidth // sending a message shouldn't update the count as it wastes bandwidth
charlie.SendEventSynced(t, secondRoomID, Event{ charlie.SendEventSynced(t, secondRoomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{"body": "ping", "msgtype": "m.text"}, Content: map[string]interface{}{"body": "ping", "msgtype": "m.text"},
}) })
@ -779,7 +785,7 @@ func TestMemberCounts(t *testing.T) {
// leaving a room should update the count // leaving a room should update the count
charlie.LeaveRoom(t, secondRoomID) charlie.LeaveRoom(t, secondRoomID)
bob.MustSyncUntil(t, SyncReq{}, SyncLeftFrom(charlie.UserID, secondRoomID)) bob.MustSyncUntil(t, client.SyncReq{}, client.SyncLeftFrom(charlie.UserID, secondRoomID))
res = bob.SlidingSync(t, sync3.Request{ res = bob.SlidingSync(t, sync3.Request{
Lists: map[string]sync3.RequestList{ Lists: map[string]sync3.RequestList{

View File

@ -5,6 +5,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/matrix-org/complement/b"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils/m" "github.com/matrix-org/sliding-sync/testutils/m"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
@ -13,11 +14,11 @@ import (
func TestNumLive(t *testing.T) { func TestNumLive(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
bob := registerNewUser(t) bob := registerNewUser(t)
roomID := alice.CreateRoom(t, map[string]interface{}{ roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
bob.JoinRoom(t, roomID, nil) bob.JoinRoom(t, roomID, nil)
eventID := alice.SendEventSynced(t, roomID, Event{ eventID := alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
@ -43,7 +44,7 @@ func TestNumLive(t *testing.T) {
)) ))
// live event -> 1 num live // live event -> 1 num live
eventID2 := alice.SendEventSynced(t, roomID, Event{ eventID2 := alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
@ -72,11 +73,11 @@ func TestNumLive(t *testing.T) {
)) ))
// now the big one -> 3 rooms, ask for top 2, bump 3rd room to top twice -> num_live=2 // now the big one -> 3 rooms, ask for top 2, bump 3rd room to top twice -> num_live=2
roomID2 := alice.CreateRoom(t, map[string]interface{}{ roomID2 := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
bob.JoinRoom(t, roomID2, nil) bob.JoinRoom(t, roomID2, nil)
roomID3 := alice.CreateRoom(t, map[string]interface{}{ roomID3 := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
bob.JoinRoom(t, roomID3, nil) bob.JoinRoom(t, roomID3, nil)
@ -98,14 +99,14 @@ func TestNumLive(t *testing.T) {
m.MatchV3SyncOp(0, 1, []string{roomID3, roomID2}), m.MatchV3SyncOp(0, 1, []string{roomID3, roomID2}),
))) )))
// now send 2 live events into roomID to bump it to the top // now send 2 live events into roomID to bump it to the top
eventID3 := alice.SendEventSynced(t, roomID, Event{ eventID3 := alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
"body": "bump 1", "body": "bump 1",
}, },
}) })
eventID4 := alice.SendEventSynced(t, roomID, Event{ eventID4 := alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
@ -138,12 +139,12 @@ func TestNumLive(t *testing.T) {
func TestReqParamStarvation(t *testing.T) { func TestReqParamStarvation(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
bob := registerNewUser(t) bob := registerNewUser(t)
roomID := alice.CreateRoom(t, map[string]interface{}{ roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
numOtherRooms := 10 numOtherRooms := 10
for i := 0; i < numOtherRooms; i++ { for i := 0; i < numOtherRooms; i++ {
bob.CreateRoom(t, map[string]interface{}{ bob.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
} }
@ -172,7 +173,7 @@ func TestReqParamStarvation(t *testing.T) {
// We do this for the first few /syncs and don't dictate which response they should arrive // We do this for the first few /syncs and don't dictate which response they should arrive
// in, as we do not know and cannot force the proxy to deliver the event in a particular response. // in, as we do not know and cannot force the proxy to deliver the event in a particular response.
if i < 3 { if i < 3 {
eventID := alice.SendEventSynced(t, roomID, Event{ eventID := alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",

View File

@ -3,17 +3,21 @@ package syncv3_test
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"net/url" "net/url"
"testing" "testing"
"github.com/matrix-org/complement/b"
"github.com/matrix-org/complement/client"
"github.com/matrix-org/complement/must"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
) )
func TestPrevBatch(t *testing.T) { func TestPrevBatch(t *testing.T) {
client := registerNewUser(t) cli := registerNewUser(t)
// create room // create room
roomID := client.CreateRoom(t, map[string]interface{}{}) roomID := cli.MustCreateRoom(t, map[string]interface{}{})
var timeline []Event var timeline []Event
// send messages // send messages
for i := 0; i < 30; i++ { for i := 0; i < 30; i++ {
@ -24,12 +28,15 @@ func TestPrevBatch(t *testing.T) {
"msgtype": "m.text", "msgtype": "m.text",
}, },
} }
ev.ID = client.SendEventSynced(t, roomID, ev) ev.ID = cli.SendEventSynced(t, roomID, b.Event{
Type: ev.Type,
Content: ev.Content,
})
timeline = append(timeline, ev) timeline = append(timeline, ev)
} }
// hit proxy // hit proxy
res := client.SlidingSync(t, sync3.Request{ res := cli.SlidingSync(t, sync3.Request{
Lists: map[string]sync3.RequestList{ Lists: map[string]sync3.RequestList{
"a": { "a": {
Ranges: sync3.SliceRanges{[2]int64{0, 10}}, Ranges: sync3.SliceRanges{[2]int64{0, 10}},
@ -49,13 +56,22 @@ func TestPrevBatch(t *testing.T) {
assertEventsEqual(t, []Event{timeline[len(timeline)-1]}, room.Timeline) assertEventsEqual(t, []Event{timeline[len(timeline)-1]}, room.Timeline)
// hit /messages with prev_batch token // hit /messages with prev_batch token
msgRes := client.MustDoFunc(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, WithQueries(url.Values{ msgRes := cli.MustDo(t, "GET", []string{"_matrix", "client", "v3", "rooms", roomID, "messages"}, client.WithQueries(url.Values{
"dir": []string{"b"}, "dir": []string{"b"},
"from": []string{room.PrevBatch}, "from": []string{room.PrevBatch},
"limit": []string{"10"}, "limit": []string{"10"},
})) }))
body, err := io.ReadAll(msgRes.Body)
msgRes.Body.Close()
must.NotError(t, "failed to read response body", err)
type MessagesBatch struct {
Chunk []json.RawMessage `json:"chunk"`
Start string `json:"start"`
End string `json:"end"`
}
var msgBody MessagesBatch var msgBody MessagesBatch
if err := json.Unmarshal(ParseJSON(t, msgRes), &msgBody); err != nil { if err := json.Unmarshal(body, &msgBody); err != nil {
t.Fatalf("failed to unmarshal /messages response: %v", err) t.Fatalf("failed to unmarshal /messages response: %v", err)
} }
// reverse it // reverse it

View File

@ -5,6 +5,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/matrix-org/complement/b"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/sync3/extensions" "github.com/matrix-org/sliding-sync/sync3/extensions"
"github.com/matrix-org/sliding-sync/testutils/m" "github.com/matrix-org/sliding-sync/testutils/m"
@ -14,11 +15,11 @@ import (
func TestReceipts(t *testing.T) { func TestReceipts(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
bob := registerNewUser(t) bob := registerNewUser(t)
roomID := alice.CreateRoom(t, map[string]interface{}{ roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
bob.JoinRoom(t, roomID, nil) bob.JoinRoom(t, roomID, nil)
eventID := alice.SendEventSynced(t, roomID, Event{ eventID := alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
@ -73,13 +74,13 @@ func TestReceiptsLazy(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
bob := registerNewUser(t) bob := registerNewUser(t)
charlie := registerNewUser(t) charlie := registerNewUser(t)
roomID := alice.CreateRoom(t, map[string]interface{}{ roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
bob.JoinRoom(t, roomID, nil) bob.JoinRoom(t, roomID, nil)
charlie.JoinRoom(t, roomID, nil) charlie.JoinRoom(t, roomID, nil)
alice.SlidingSync(t, sync3.Request{}) // proxy begins tracking alice.SlidingSync(t, sync3.Request{}) // proxy begins tracking
eventID := alice.SendEventSynced(t, roomID, Event{ eventID := alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
@ -94,7 +95,7 @@ func TestReceiptsLazy(t *testing.T) {
// alice sends 5 new events, bob and alice ACK the last event // alice sends 5 new events, bob and alice ACK the last event
var fifthEventID string var fifthEventID string
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
fifthEventID = alice.SendEventSynced(t, roomID, Event{ fifthEventID = alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
@ -108,7 +109,7 @@ func TestReceiptsLazy(t *testing.T) {
// alice sends another 5 events and ACKs nothing // alice sends another 5 events and ACKs nothing
var lastEventID string var lastEventID string
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
lastEventID = alice.SendEventSynced(t, roomID, Event{ lastEventID = alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
@ -171,12 +172,12 @@ func TestReceiptsLazy(t *testing.T) {
func TestReceiptsPrivate(t *testing.T) { func TestReceiptsPrivate(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
bob := registerNewUser(t) bob := registerNewUser(t)
roomID := alice.CreateRoom(t, map[string]interface{}{ roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
bob.JoinRoom(t, roomID, nil) bob.JoinRoom(t, roomID, nil)
eventID := alice.SendEventSynced(t, roomID, Event{ eventID := alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
@ -231,10 +232,10 @@ func TestReceiptsRespectsExtensionScope(t *testing.T) {
var syncResp *sync3.Response var syncResp *sync3.Response
t.Log("Alice creates four rooms.") t.Log("Alice creates four rooms.")
room1 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 1"}) room1 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 1"})
room2 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 2"}) room2 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 2"})
room3 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 3"}) room3 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 3"})
room4 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 4"}) room4 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 4"})
t.Logf("room1=%s room2=%s room3=%s room4=%s", room1, room2, room3, room4) t.Logf("room1=%s room2=%s room3=%s room4=%s", room1, room2, room3, room4)
t.Log("Bob joins those rooms.") t.Log("Bob joins those rooms.")
@ -244,7 +245,7 @@ func TestReceiptsRespectsExtensionScope(t *testing.T) {
bob.JoinRoom(t, room4, nil) bob.JoinRoom(t, room4, nil)
t.Log("Alice posts a message to each room") t.Log("Alice posts a message to each room")
messageEvent := Event{ messageEvent := b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
@ -323,8 +324,8 @@ func TestReceiptsOnRoomsOnly(t *testing.T) {
bob := registerNamedUser(t, "bob") bob := registerNamedUser(t, "bob")
t.Log("Alice creates two rooms.") t.Log("Alice creates two rooms.")
room1 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 1"}) room1 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 1"})
room2 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 2"}) room2 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 2"})
t.Logf("room1=%s room2=%s", room1, room2) t.Logf("room1=%s room2=%s", room1, room2)
t.Log("Bob joins those rooms.") t.Log("Bob joins those rooms.")
@ -332,7 +333,7 @@ func TestReceiptsOnRoomsOnly(t *testing.T) {
bob.JoinRoom(t, room2, nil) bob.JoinRoom(t, room2, nil)
t.Log("Alice posts a message to each room") t.Log("Alice posts a message to each room")
messageEvent := Event{ messageEvent := b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",

View File

@ -5,6 +5,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/matrix-org/complement/b"
"github.com/matrix-org/complement/client"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils/m" "github.com/matrix-org/sliding-sync/testutils/m"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
@ -12,9 +14,9 @@ import (
func TestRedactionsAreRedactedWherePossible(t *testing.T) { func TestRedactionsAreRedactedWherePossible(t *testing.T) {
alice := registerNamedUser(t, "alice") alice := registerNamedUser(t, "alice")
room := alice.CreateRoom(t, map[string]any{"preset": "public_chat"}) room := alice.MustCreateRoom(t, map[string]any{"preset": "public_chat"})
eventID := alice.SendEventSynced(t, room, Event{ eventID := alice.SendEventSynced(t, room, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
@ -40,7 +42,7 @@ func TestRedactionsAreRedactedWherePossible(t *testing.T) {
})) }))
// redact the event // redact the event
redactionEventID := alice.RedactEvent(t, room, eventID) redactionEventID := alice.MustSendRedaction(t, room, map[string]interface{}{}, eventID)
// see the redaction // see the redaction
alice.SlidingSyncUntilEventID(t, res.Pos, room, redactionEventID) alice.SlidingSyncUntilEventID(t, res.Pos, room, redactionEventID)
@ -83,21 +85,29 @@ func TestRedactingRoomStateIsReflectedInNextSync(t *testing.T) {
bob := registerNamedUser(t, "bob") bob := registerNamedUser(t, "bob")
t.Log("Alice creates a room, then sets a room alias and name.") t.Log("Alice creates a room, then sets a room alias and name.")
room := alice.CreateRoom(t, map[string]any{ room := alice.MustCreateRoom(t, map[string]any{
"preset": "public_chat", "preset": "public_chat",
}) })
alias := fmt.Sprintf("#%s-%d:%s", t.Name(), time.Now().Unix(), alice.Domain) alias := fmt.Sprintf("#%s-%d:%s", t.Name(), time.Now().Unix(), alice.Domain)
alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "directory", "room", alias}, alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "directory", "room", alias},
WithJSONBody(t, map[string]any{"room_id": room}), client.WithJSONBody(t, map[string]any{"room_id": room}),
) )
aliasID := alice.SetState(t, room, "m.room.canonical_alias", "", map[string]any{ aliasID := alice.Unsafe_SendEventUnsynced(t, room, b.Event{
"alias": alias, Type: "m.room.canonical_alias",
StateKey: ptr(""),
Content: map[string]interface{}{
"alias": alias,
},
}) })
const naughty = "naughty room for naughty people" const naughty = "naughty room for naughty people"
nameID := alice.SetState(t, room, "m.room.name", "", map[string]any{ nameID := alice.Unsafe_SendEventUnsynced(t, room, b.Event{
"name": naughty, Type: "m.room.name",
StateKey: ptr(""),
Content: map[string]interface{}{
"name": naughty,
},
}) })
t.Log("Alice sliding syncs, subscribing to that room explicitly.") t.Log("Alice sliding syncs, subscribing to that room explicitly.")
@ -113,7 +123,7 @@ func TestRedactingRoomStateIsReflectedInNextSync(t *testing.T) {
m.MatchResponse(t, res, m.MatchRoomSubscription(room, m.MatchRoomName(naughty))) m.MatchResponse(t, res, m.MatchRoomSubscription(room, m.MatchRoomName(naughty)))
t.Log("Alice redacts the room name.") t.Log("Alice redacts the room name.")
redactionID := alice.RedactEvent(t, room, nameID) redactionID := alice.MustSendRedaction(t, room, map[string]interface{}{}, nameID)
t.Log("Alice syncs until she sees her redaction.") t.Log("Alice syncs until she sees her redaction.")
res = alice.SlidingSyncUntil(t, res.Pos, sync3.Request{}, m.MatchRoomSubscription( res = alice.SlidingSyncUntil(t, res.Pos, sync3.Request{}, m.MatchRoomSubscription(
@ -126,15 +136,19 @@ func TestRedactingRoomStateIsReflectedInNextSync(t *testing.T) {
t.Log("Alice sets a room avatar.") t.Log("Alice sets a room avatar.")
avatarURL := alice.UploadContent(t, smallPNG, "avatar.png", "image/png") avatarURL := alice.UploadContent(t, smallPNG, "avatar.png", "image/png")
avatarID := alice.SetState(t, room, "m.room.avatar", "", map[string]interface{}{ avatarID := alice.Unsafe_SendEventUnsynced(t, room, b.Event{
"url": avatarURL, Type: "m.room.avatar",
StateKey: ptr(""),
Content: map[string]interface{}{
"url": avatarURL,
},
}) })
t.Log("Alice waits to see the avatar.") t.Log("Alice waits to see the avatar.")
res = alice.SlidingSyncUntil(t, res.Pos, sync3.Request{}, m.MatchRoomSubscription(room, m.MatchRoomAvatar(avatarURL))) res = alice.SlidingSyncUntil(t, res.Pos, sync3.Request{}, m.MatchRoomSubscription(room, m.MatchRoomAvatar(avatarURL)))
t.Log("Alice redacts the avatar.") t.Log("Alice redacts the avatar.")
redactionID = alice.RedactEvent(t, room, avatarID) redactionID = alice.MustSendRedaction(t, room, map[string]interface{}{}, avatarID)
t.Log("Alice sees the avatar revert to blank.") t.Log("Alice sees the avatar revert to blank.")
res = alice.SlidingSyncUntil(t, res.Pos, sync3.Request{}, m.MatchRoomSubscription(room, m.MatchRoomUnsetAvatar())) res = alice.SlidingSyncUntil(t, res.Pos, sync3.Request{}, m.MatchRoomSubscription(room, m.MatchRoomUnsetAvatar()))
@ -160,13 +174,13 @@ func TestRedactingRoomStateIsReflectedInNextSync(t *testing.T) {
bobJoinID := gjson.GetBytes(timeline[len(timeline)-1], "event_id").Str bobJoinID := gjson.GetBytes(timeline[len(timeline)-1], "event_id").Str
t.Log("Alice redacts the alias.") t.Log("Alice redacts the alias.")
redactionID = alice.RedactEvent(t, room, aliasID) redactionID = alice.MustSendRedaction(t, room, map[string]interface{}{}, aliasID)
t.Log("Alice sees the room name reset to Bob's display name.") t.Log("Alice sees the room name reset to Bob's display name.")
res = alice.SlidingSyncUntil(t, res.Pos, sync3.Request{}, m.MatchRoomSubscription(room, m.MatchRoomName(bobDisplayName))) res = alice.SlidingSyncUntil(t, res.Pos, sync3.Request{}, m.MatchRoomSubscription(room, m.MatchRoomName(bobDisplayName)))
t.Log("Bob redacts his membership") t.Log("Bob redacts his membership")
redactionID = bob.RedactEvent(t, room, bobJoinID) redactionID = bob.MustSendRedaction(t, room, map[string]interface{}{}, bobJoinID)
t.Log("Alice sees the room name reset to Bob's username.") t.Log("Alice sees the room name reset to Bob's username.")
res = alice.SlidingSyncUntil(t, res.Pos, sync3.Request{}, m.MatchRoomSubscription(room, m.MatchRoomName(bob.UserID))) res = alice.SlidingSyncUntil(t, res.Pos, sync3.Request{}, m.MatchRoomSubscription(room, m.MatchRoomName(bob.UserID)))

View File

@ -5,6 +5,8 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/matrix-org/complement/b"
"github.com/matrix-org/complement/client"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils/m" "github.com/matrix-org/sliding-sync/testutils/m"
) )
@ -26,7 +28,7 @@ func TestSecurityLiveStreamEventLeftLeak(t *testing.T) {
eve := registerNewUser(t) eve := registerNewUser(t)
// Alice and Eve in the room // Alice and Eve in the room
roomID := alice.CreateRoom(t, map[string]interface{}{ roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
eve.JoinRoom(t, roomID, nil) eve.JoinRoom(t, roomID, nil)
@ -62,12 +64,12 @@ func TestSecurityLiveStreamEventLeftLeak(t *testing.T) {
))) )))
// kick Eve // kick Eve
alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "kick"}, WithJSONBody(t, map[string]interface{}{ alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "kick"}, client.WithJSONBody(t, map[string]interface{}{
"user_id": eve.UserID, "user_id": eve.UserID,
})) }))
// send message as Alice, note it shouldn't go down Eve's v2 stream // send message as Alice, note it shouldn't go down Eve's v2 stream
sensitiveEventID := alice.SendEventSynced(t, roomID, Event{ sensitiveEventID := alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.name", Type: "m.room.name",
StateKey: ptr(""), StateKey: ptr(""),
Content: map[string]interface{}{ Content: map[string]interface{}{
@ -157,12 +159,12 @@ func TestSecurityRoomSubscriptionLeak(t *testing.T) {
eve := registerNewUser(t) eve := registerNewUser(t)
// Alice in the room // Alice in the room
alicePrivateRoomID := alice.CreateRoom(t, map[string]interface{}{ alicePrivateRoomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "private_chat", "preset": "private_chat",
}) })
// Eve is in an unrelated room // Eve is in an unrelated room
eveUnrelatedRoomID := eve.CreateRoom(t, map[string]interface{}{ eveUnrelatedRoomID := eve.MustCreateRoom(t, map[string]interface{}{
"preset": "private_chat", "preset": "private_chat",
}) })
@ -194,7 +196,7 @@ func TestSecurityRoomSubscriptionLeak(t *testing.T) {
})) }))
// Assert that live updates still don't feed through to Eve // Assert that live updates still don't feed through to Eve
alice.SendEventSynced(t, alicePrivateRoomID, Event{ alice.SendEventSynced(t, alicePrivateRoomID, b.Event{
Type: "m.room.name", Type: "m.room.name",
StateKey: ptr(""), StateKey: ptr(""),
Content: map[string]interface{}{ Content: map[string]interface{}{
@ -226,16 +228,16 @@ func TestSecuritySpaceDataLeak(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
eve := registerNewUser(t) eve := registerNewUser(t)
roomA := alice.CreateRoom(t, map[string]interface{}{ roomA := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
"creation_content": map[string]string{ "creation_content": map[string]string{
"type": "m.space", "type": "m.space",
}, },
}) })
roomB := alice.CreateRoom(t, map[string]interface{}{ roomB := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "private_chat", "preset": "private_chat",
}) })
alice.SendEventSynced(t, roomA, Event{ alice.SendEventSynced(t, roomA, b.Event{
Type: "m.space.child", Type: "m.space.child",
StateKey: &roomB, StateKey: &roomB,
Content: map[string]interface{}{ Content: map[string]interface{}{
@ -273,17 +275,17 @@ func TestSecuritySpaceMetadataLeak(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
eve := registerNewUser(t) eve := registerNewUser(t)
roomA := alice.CreateRoom(t, map[string]interface{}{ roomA := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
"creation_content": map[string]string{ "creation_content": map[string]string{
"type": "m.space", "type": "m.space",
}, },
}) })
roomB := alice.CreateRoom(t, map[string]interface{}{ roomB := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
// Alice has a space A -> B // Alice has a space A -> B
alice.SendEventSynced(t, roomA, Event{ alice.SendEventSynced(t, roomA, b.Event{
Type: "m.space.child", Type: "m.space.child",
StateKey: &roomB, StateKey: &roomB,
Content: map[string]interface{}{ Content: map[string]interface{}{
@ -294,14 +296,14 @@ func TestSecuritySpaceMetadataLeak(t *testing.T) {
alice.SlidingSync(t, sync3.Request{}) alice.SlidingSync(t, sync3.Request{})
// now Eve also has a space... C -> B // now Eve also has a space... C -> B
roomC := eve.CreateRoom(t, map[string]interface{}{ roomC := eve.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
"creation_content": map[string]string{ "creation_content": map[string]string{
"type": "m.space", "type": "m.space",
}, },
}) })
eve.JoinRoom(t, roomB, nil) eve.JoinRoom(t, roomB, nil)
eve.SendEventSynced(t, roomC, Event{ eve.SendEventSynced(t, roomC, b.Event{
Type: "m.space.child", Type: "m.space.child",
StateKey: &roomB, StateKey: &roomB,
Content: map[string]interface{}{ Content: map[string]interface{}{

View File

@ -4,6 +4,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/matrix-org/complement/b"
"github.com/matrix-org/complement/client"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils/m" "github.com/matrix-org/sliding-sync/testutils/m"
) )
@ -21,46 +23,46 @@ import (
// spaces[A,B] => B,C,E // spaces[A,B] => B,C,E
func TestSpacesFilter(t *testing.T) { func TestSpacesFilter(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
parentA := alice.CreateRoom(t, map[string]interface{}{ parentA := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
"creation_content": map[string]string{ "creation_content": map[string]string{
"type": "m.space", "type": "m.space",
}, },
}) })
parentD := alice.CreateRoom(t, map[string]interface{}{ parentD := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
"creation_content": map[string]string{ "creation_content": map[string]string{
"type": "m.space", "type": "m.space",
}, },
}) })
roomB := alice.CreateRoom(t, map[string]interface{}{ roomB := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
roomC := alice.CreateRoom(t, map[string]interface{}{ roomC := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
roomE := alice.CreateRoom(t, map[string]interface{}{ roomE := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
roomF := alice.CreateRoom(t, map[string]interface{}{ roomF := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
t.Logf("A: %s B: %s C: %s D: %s E: %s F: %s", parentA, roomB, roomC, parentD, roomE, roomF) t.Logf("A: %s B: %s C: %s D: %s E: %s F: %s", parentA, roomB, roomC, parentD, roomE, roomF)
alice.SendEventSynced(t, parentA, Event{ alice.SendEventSynced(t, parentA, b.Event{
Type: "m.space.child", Type: "m.space.child",
StateKey: &roomB, StateKey: &roomB,
Content: map[string]interface{}{ Content: map[string]interface{}{
"via": []string{"example.com"}, "via": []string{"example.com"},
}, },
}) })
alice.SendEventSynced(t, parentA, Event{ alice.SendEventSynced(t, parentA, b.Event{
Type: "m.space.child", Type: "m.space.child",
StateKey: &roomC, StateKey: &roomC,
Content: map[string]interface{}{ Content: map[string]interface{}{
"via": []string{"example.com"}, "via": []string{"example.com"},
}, },
}) })
alice.SendEventSynced(t, parentD, Event{ alice.SendEventSynced(t, parentD, b.Event{
Type: "m.space.child", Type: "m.space.child",
StateKey: &roomE, StateKey: &roomE,
Content: map[string]interface{}{ Content: map[string]interface{}{
@ -71,7 +73,7 @@ func TestSpacesFilter(t *testing.T) {
doSpacesListRequest := func(spaces []string, pos *string, listMatchers ...m.ListMatcher) *sync3.Response { doSpacesListRequest := func(spaces []string, pos *string, listMatchers ...m.ListMatcher) *sync3.Response {
t.Helper() t.Helper()
var opts []RequestOpt var opts []client.RequestOpt
if pos != nil { if pos != nil {
opts = append(opts, WithPos(*pos)) opts = append(opts, WithPos(*pos))
} }
@ -116,7 +118,7 @@ func TestSpacesFilter(t *testing.T) {
} }
// now move F into D and re-query D // now move F into D and re-query D
alice.SendEventSynced(t, parentD, Event{ alice.SendEventSynced(t, parentD, b.Event{
Type: "m.space.child", Type: "m.space.child",
StateKey: &roomF, StateKey: &roomF,
Content: map[string]interface{}{ Content: map[string]interface{}{
@ -127,7 +129,7 @@ func TestSpacesFilter(t *testing.T) {
doInitialSpacesListRequest([]string{parentD}, []string{roomF, roomE}) doInitialSpacesListRequest([]string{parentD}, []string{roomF, roomE})
// now remove B and re-query A // now remove B and re-query A
alice.SendEventSynced(t, parentA, Event{ alice.SendEventSynced(t, parentA, b.Event{
Type: "m.space.child", Type: "m.space.child",
StateKey: &roomB, StateKey: &roomB,
Content: map[string]interface{}{}, Content: map[string]interface{}{},
@ -136,7 +138,7 @@ func TestSpacesFilter(t *testing.T) {
res := doInitialSpacesListRequest([]string{parentA}, []string{roomC}) res := doInitialSpacesListRequest([]string{parentA}, []string{roomC})
// now live stream an update to ensure it gets added // now live stream an update to ensure it gets added
alice.SendEventSynced(t, parentA, Event{ alice.SendEventSynced(t, parentA, b.Event{
Type: "m.space.child", Type: "m.space.child",
StateKey: &roomB, StateKey: &roomB,
Content: map[string]interface{}{ Content: map[string]interface{}{
@ -165,14 +167,14 @@ func TestSpacesFilter(t *testing.T) {
func TestSpacesFilterInvite(t *testing.T) { func TestSpacesFilterInvite(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
bob := registerNewUser(t) bob := registerNewUser(t)
spaceRoomID := alice.CreateRoom(t, map[string]interface{}{ spaceRoomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
"name": "Space Room", "name": "Space Room",
"creation_content": map[string]string{ "creation_content": map[string]string{
"type": "m.space", "type": "m.space",
}, },
}) })
normalRoomID := alice.CreateRoom(t, map[string]interface{}{ normalRoomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
"name": "Normal Room", "name": "Normal Room",
}) })
@ -205,7 +207,7 @@ func TestAddingUnknownChildToSpace(t *testing.T) {
bob := registerNewUser(t) bob := registerNewUser(t)
t.Log("Alice creates a space and invites Bob.") t.Log("Alice creates a space and invites Bob.")
parentID := alice.CreateRoom(t, map[string]interface{}{ parentID := alice.MustCreateRoom(t, map[string]interface{}{
"type": "m.space", "type": "m.space",
"invite": []string{bob.UserID}, "invite": []string{bob.UserID},
}) })
@ -226,9 +228,13 @@ func TestAddingUnknownChildToSpace(t *testing.T) {
}) })
t.Log("Alice creates a room and marks it as a child of the space.") t.Log("Alice creates a room and marks it as a child of the space.")
childID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) childID := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat"})
childEventID := alice.SetState(t, parentID, "m.space.child", childID, map[string]interface{}{ childEventID := alice.Unsafe_SendEventUnsynced(t, parentID, b.Event{
"via": []string{"localhost"}, Type: "m.space.child",
StateKey: ptr(childID),
Content: map[string]interface{}{
"via": []string{"localhost"},
},
}) })
t.Log("Bob syncs until he sees the m.space.child event in the space.") t.Log("Bob syncs until he sees the m.space.child event in the space.")

View File

@ -4,6 +4,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/matrix-org/complement/b"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils/m" "github.com/matrix-org/sliding-sync/testutils/m"
) )
@ -13,7 +14,7 @@ func TestTimestamp(t *testing.T) {
bob := registerNewUser(t) bob := registerNewUser(t)
charlie := registerNewUser(t) charlie := registerNewUser(t)
roomID := alice.CreateRoom(t, map[string]interface{}{ roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
@ -67,7 +68,7 @@ func TestTimestamp(t *testing.T) {
// Send an event which should NOT bump Bobs timestamp, because it is not listed it // Send an event which should NOT bump Bobs timestamp, because it is not listed it
// any BumpEventTypes // any BumpEventTypes
emptyStateKey := "" emptyStateKey := ""
eventID := alice.SendEventSynced(t, roomID, Event{ eventID := alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.topic", Type: "m.room.topic",
StateKey: &emptyStateKey, StateKey: &emptyStateKey,
Content: map[string]interface{}{ Content: map[string]interface{}{
@ -85,7 +86,7 @@ func TestTimestamp(t *testing.T) {
expectedTs = gotTs expectedTs = gotTs
// Now send a message which bumps the timestamp in myFirstList // Now send a message which bumps the timestamp in myFirstList
eventID = alice.SendEventSynced(t, roomID, Event{ eventID = alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
@ -102,7 +103,7 @@ func TestTimestamp(t *testing.T) {
expectedTs = gotTs expectedTs = gotTs
// Now send a message which bumps the timestamp in mySecondList // Now send a message which bumps the timestamp in mySecondList
eventID = alice.SendEventSynced(t, roomID, Event{ eventID = alice.SendEventSynced(t, roomID, b.Event{
Type: "m.reaction", Type: "m.reaction",
Content: map[string]interface{}{ Content: map[string]interface{}{
"m.relates.to": map[string]interface{}{ "m.relates.to": map[string]interface{}{
@ -122,7 +123,7 @@ func TestTimestamp(t *testing.T) {
expectedTs = bobTimestampReaction expectedTs = bobTimestampReaction
// Send another event which should NOT bump Bobs timestamp // Send another event which should NOT bump Bobs timestamp
eventID = alice.SendEventSynced(t, roomID, Event{ eventID = alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.name", Type: "m.room.name",
StateKey: &emptyStateKey, StateKey: &emptyStateKey,
Content: map[string]interface{}{ Content: map[string]interface{}{

View File

@ -17,7 +17,11 @@ import (
func TestToDeviceDeliveryInitialLogin(t *testing.T) { func TestToDeviceDeliveryInitialLogin(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
bob := registerNewUser(t) bob := registerNewUser(t)
bob.SendToDevice(t, "m.dummy", alice.UserID, alice.DeviceID, map[string]interface{}{}) bob.SendToDeviceMessages(t, "m.dummy", map[string]map[string]map[string]interface{}{
alice.UserID: map[string]map[string]interface{}{
alice.DeviceID: map[string]interface{}{},
},
})
// loop until we see the event // loop until we see the event
loopUntilToDeviceEvent(t, alice, nil, "", "m.dummy", bob.UserID) loopUntilToDeviceEvent(t, alice, nil, "", "m.dummy", bob.UserID)
} }
@ -33,7 +37,11 @@ func TestToDeviceDeliveryStream(t *testing.T) {
}, },
}, },
}) })
bob.SendToDevice(t, "m.dummy", alice.UserID, alice.DeviceID, map[string]interface{}{}) bob.SendToDeviceMessages(t, "m.dummy", map[string]map[string]map[string]interface{}{
alice.UserID: map[string]map[string]interface{}{
alice.DeviceID: map[string]interface{}{},
},
})
// loop until we see the event // loop until we see the event
loopUntilToDeviceEvent(t, alice, res, res.Extensions.ToDevice.NextBatch, "m.dummy", bob.UserID) loopUntilToDeviceEvent(t, alice, res, res.Extensions.ToDevice.NextBatch, "m.dummy", bob.UserID)
@ -52,7 +60,11 @@ func TestToDeviceDeliveryReconnect(t *testing.T) {
}, },
}, },
}) })
bob.SendToDevice(t, "m.dummy", alice.UserID, alice.DeviceID, map[string]interface{}{}) bob.SendToDeviceMessages(t, "m.dummy", map[string]map[string]map[string]interface{}{
alice.UserID: map[string]map[string]interface{}{
alice.DeviceID: map[string]interface{}{},
},
})
// loop until we see the event // loop until we see the event
loopUntilToDeviceEvent(t, alice, nil, "", "m.dummy", bob.UserID) loopUntilToDeviceEvent(t, alice, nil, "", "m.dummy", bob.UserID)
} }
@ -65,18 +77,30 @@ func TestToDeviceDropStaleKeyRequestsInitial(t *testing.T) {
// send a few dummy messages, cancelling each other // send a few dummy messages, cancelling each other
for i := 0; i < sendMessages; i++ { for i := 0; i < sendMessages; i++ {
reqID := util.RandomString(8) reqID := util.RandomString(8)
bob.SendToDevice(t, "m.room_key_request", alice.UserID, alice.DeviceID, map[string]interface{}{ bob.SendToDeviceMessages(t, "m.room_key_request", map[string]map[string]map[string]interface{}{
"request_id": reqID, alice.UserID: map[string]map[string]interface{}{
"action": "request", alice.DeviceID: map[string]interface{}{
"requesting_device_id": "mydevice", "request_id": reqID,
"action": "request",
"requesting_device_id": "mydevice",
},
},
}) })
bob.SendToDevice(t, "m.room_key_request", alice.UserID, alice.DeviceID, map[string]interface{}{ bob.SendToDeviceMessages(t, "m.room_key_request", map[string]map[string]map[string]interface{}{
"request_id": reqID, alice.UserID: map[string]map[string]interface{}{
"action": "request_cancellation", alice.DeviceID: map[string]interface{}{
"requesting_device_id": "mydevice", "request_id": reqID,
"action": "request_cancellation",
"requesting_device_id": "mydevice",
},
},
}) })
} }
bob.SendToDevice(t, "sentinel", alice.UserID, alice.DeviceID, map[string]interface{}{}) bob.SendToDeviceMessages(t, "sentinel", map[string]map[string]map[string]interface{}{
alice.UserID: map[string]map[string]interface{}{
alice.DeviceID: map[string]interface{}{},
},
})
// Loop until we have the sentinel event, the rest should cancel out. // Loop until we have the sentinel event, the rest should cancel out.
gotMessages, _ := loopUntilToDeviceEvent(t, alice, nil, "", "sentinel", bob.UserID) gotMessages, _ := loopUntilToDeviceEvent(t, alice, nil, "", "sentinel", bob.UserID)
wantCount := 1 wantCount := 1
@ -89,10 +113,14 @@ func TestToDeviceDropStaleKeyRequestsStreamNoDelete(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
bob := registerNewUser(t) bob := registerNewUser(t)
bob.SendToDevice(t, "m.room_key_request", alice.UserID, alice.DeviceID, map[string]interface{}{ bob.SendToDeviceMessages(t, "m.room_key_request", map[string]map[string]map[string]interface{}{
"request_id": "A", alice.UserID: map[string]map[string]interface{}{
"action": "request", alice.DeviceID: map[string]interface{}{
"requesting_device_id": "mydevice", "request_id": "A",
"action": "request",
"requesting_device_id": "mydevice",
},
},
}) })
msgs1, res := loopUntilToDeviceEvent(t, alice, nil, "", "m.room_key_request", bob.UserID) msgs1, res := loopUntilToDeviceEvent(t, alice, nil, "", "m.room_key_request", bob.UserID)
if len(msgs1) != 1 { if len(msgs1) != 1 {
@ -100,10 +128,14 @@ func TestToDeviceDropStaleKeyRequestsStreamNoDelete(t *testing.T) {
} }
// now send a cancellation: we should not delete the cancellation // now send a cancellation: we should not delete the cancellation
bob.SendToDevice(t, "m.room_key_request", alice.UserID, alice.DeviceID, map[string]interface{}{ bob.SendToDeviceMessages(t, "m.room_key_request", map[string]map[string]map[string]interface{}{
"request_id": "A", alice.UserID: map[string]map[string]interface{}{
"action": "request_cancellation", alice.DeviceID: map[string]interface{}{
"requesting_device_id": "mydevice", "request_id": "A",
"action": "request_cancellation",
"requesting_device_id": "mydevice",
},
},
}) })
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
msgs2, _ := loopUntilToDeviceEvent(t, alice, res, res.Extensions.ToDevice.NextBatch, "m.room_key_request", bob.UserID) msgs2, _ := loopUntilToDeviceEvent(t, alice, res, res.Extensions.ToDevice.NextBatch, "m.room_key_request", bob.UserID)

View File

@ -6,6 +6,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/matrix-org/complement/b"
"github.com/matrix-org/complement/client"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils/m" "github.com/matrix-org/sliding-sync/testutils/m"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
@ -14,7 +16,7 @@ import (
// tests that if we upgrade a room it is removed from the list. If we request old rooms it should be included. // tests that if we upgrade a room it is removed from the list. If we request old rooms it should be included.
func TestIncludeOldRooms(t *testing.T) { func TestIncludeOldRooms(t *testing.T) {
client := registerNewUser(t) client := registerNewUser(t)
roomID := client.CreateRoom(t, map[string]interface{}{}) roomID := client.MustCreateRoom(t, map[string]interface{}{})
res := client.SlidingSync(t, sync3.Request{ res := client.SlidingSync(t, sync3.Request{
Lists: map[string]sync3.RequestList{ Lists: map[string]sync3.RequestList{
@ -158,23 +160,23 @@ func TestIncludeOldRoomsLongChain(t *testing.T) {
// seed the server with this client, we need to do this so the proxy has timeline history to // seed the server with this client, we need to do this so the proxy has timeline history to
// return so we can assert events appear in the right rooms // return so we can assert events appear in the right rooms
res := client.SlidingSync(t, sync3.Request{}) res := client.SlidingSync(t, sync3.Request{})
roomA := client.CreateRoom(t, map[string]interface{}{}) roomA := client.MustCreateRoom(t, map[string]interface{}{})
client.SendEventSynced(t, roomA, Event{ client.SendEventSynced(t, roomA, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{"body": "A", "msgtype": "m.text"}, Content: map[string]interface{}{"body": "A", "msgtype": "m.text"},
}) })
roomB := upgradeRoom(t, client, roomA) roomB := upgradeRoom(t, client, roomA)
eventB := client.SendEventSynced(t, roomB, Event{ eventB := client.SendEventSynced(t, roomB, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{"body": "B", "msgtype": "m.text"}, Content: map[string]interface{}{"body": "B", "msgtype": "m.text"},
}) })
roomC := upgradeRoom(t, client, roomB) roomC := upgradeRoom(t, client, roomB)
client.SendEventSynced(t, roomC, Event{ client.SendEventSynced(t, roomC, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{"body": "C", "msgtype": "m.text"}, Content: map[string]interface{}{"body": "C", "msgtype": "m.text"},
}) })
roomD := upgradeRoom(t, client, roomC) roomD := upgradeRoom(t, client, roomC)
eventD := client.SendEventSynced(t, roomD, Event{ eventD := client.SendEventSynced(t, roomD, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{"body": "D", "msgtype": "m.text"}, Content: map[string]interface{}{"body": "D", "msgtype": "m.text"},
}) })
@ -266,7 +268,7 @@ func TestIncludeOldRoomsLongChain(t *testing.T) {
// test that if you have a list version and direct sub version of include_old_rooms, they get unioned correctly. // test that if you have a list version and direct sub version of include_old_rooms, they get unioned correctly.
func TestIncludeOldRoomsSubscriptionUnion(t *testing.T) { func TestIncludeOldRoomsSubscriptionUnion(t *testing.T) {
client := registerNewUser(t) client := registerNewUser(t)
roomA := client.CreateRoom(t, map[string]interface{}{}) roomA := client.MustCreateRoom(t, map[string]interface{}{})
roomB := upgradeRoom(t, client, roomA) roomB := upgradeRoom(t, client, roomA)
// should union to timeline_limit=2, req_state=create+member+tombstone // should union to timeline_limit=2, req_state=create+member+tombstone
@ -322,8 +324,8 @@ func TestIncludeOldRoomsSubscriptionUnion(t *testing.T) {
})) }))
} }
func upgradeRoom(t *testing.T, client *CSAPI, roomID string) (newRoomID string) { func upgradeRoom(t *testing.T, c *CSAPI, roomID string) (newRoomID string) {
upgradeRes := client.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "upgrade"}, WithJSONBody(t, map[string]interface{}{ upgradeRes := c.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "upgrade"}, client.WithJSONBody(t, map[string]interface{}{
"new_version": "9", "new_version": "9",
})) }))
var body map[string]interface{} var body map[string]interface{}

View File

@ -5,23 +5,24 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/matrix-org/complement/client"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils/m" "github.com/matrix-org/sliding-sync/testutils/m"
) )
func TestTransactionIDsAppear(t *testing.T) { func TestTransactionIDsAppear(t *testing.T) {
client := registerNewUser(t) c := registerNewUser(t)
roomID := client.CreateRoom(t, map[string]interface{}{}) roomID := c.MustCreateRoom(t, map[string]interface{}{})
sendRes := client.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "foobar"}, sendRes := c.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "foobar"},
WithJSONBody(t, map[string]interface{}{ client.WithJSONBody(t, map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
"body": "Hello World!", "body": "Hello World!",
})) }))
body := ParseJSON(t, sendRes) body := client.ParseJSON(t, sendRes)
eventID := GetJSONFieldStr(t, body, "event_id") eventID := client.GetJSONFieldStr(t, body, "event_id")
// ensure initial syncs include the txn id // ensure initial syncs include the txn id
res := client.SlidingSync(t, sync3.Request{ res := c.SlidingSync(t, sync3.Request{
Lists: map[string]sync3.RequestList{ Lists: map[string]sync3.RequestList{
"a": { "a": {
Ranges: [][2]int64{{0, 10}}, Ranges: [][2]int64{{0, 10}},
@ -40,15 +41,15 @@ func TestTransactionIDsAppear(t *testing.T) {
})) }))
// now live stream another event and ensure that too has a txn ID // now live stream another event and ensure that too has a txn ID
sendRes = client.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "foobar2"}, sendRes = c.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "foobar2"},
WithJSONBody(t, map[string]interface{}{ client.WithJSONBody(t, map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
"body": "Hello World 2!", "body": "Hello World 2!",
})) }))
body = ParseJSON(t, sendRes) body = client.ParseJSON(t, sendRes)
eventID = GetJSONFieldStr(t, body, "event_id") eventID = client.GetJSONFieldStr(t, body, "event_id")
res = client.SlidingSyncUntilEvent(t, res.Pos, sync3.Request{}, roomID, Event{ID: eventID}) res = c.SlidingSyncUntilEvent(t, res.Pos, sync3.Request{}, roomID, Event{ID: eventID})
m.MatchResponse(t, res, m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{ m.MatchResponse(t, res, m.MatchRoomSubscriptionsStrict(map[string][]m.RoomMatcher{
roomID: { roomID: {
matchTransactionID(t, eventID, "foobar2"), matchTransactionID(t, eventID, "foobar2"),
@ -64,7 +65,7 @@ func TestTransactionIDsAppearWithMultiplePollers(t *testing.T) {
alice := registerNamedUser(t, "alice") alice := registerNamedUser(t, "alice")
t.Log("Alice creates a room and syncs until she sees it.") t.Log("Alice creates a room and syncs until she sees it.")
roomID := alice.CreateRoom(t, map[string]interface{}{}) roomID := alice.MustCreateRoom(t, map[string]interface{}{})
res := alice.SlidingSync(t, sync3.Request{ res := alice.SlidingSync(t, sync3.Request{
Lists: map[string]sync3.RequestList{ Lists: map[string]sync3.RequestList{
"a": { "a": {
@ -95,13 +96,13 @@ func TestTransactionIDsAppearWithMultiplePollers(t *testing.T) {
t.Log("Alice sends a message with a transaction ID.") t.Log("Alice sends a message with a transaction ID.")
const txnID = "foobar" const txnID = "foobar"
sendRes := alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", txnID}, sendRes := alice.MustDo(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", txnID},
WithJSONBody(t, map[string]interface{}{ client.WithJSONBody(t, map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
"body": "Hello, world!", "body": "Hello, world!",
})) }))
body := ParseJSON(t, sendRes) body := client.ParseJSON(t, sendRes)
eventID := GetJSONFieldStr(t, body, "event_id") eventID := client.GetJSONFieldStr(t, body, "event_id")
t.Log("Alice syncs on her main devices until she sees her message.") t.Log("Alice syncs on her main devices until she sees her message.")
res = alice.SlidingSyncUntilEventID(t, res.Pos, roomID, eventID) res = alice.SlidingSyncUntilEventID(t, res.Pos, roomID, eventID)

View File

@ -8,6 +8,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/matrix-org/complement/b"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/sync3/extensions" "github.com/matrix-org/sliding-sync/sync3/extensions"
"github.com/matrix-org/sliding-sync/testutils/m" "github.com/matrix-org/sliding-sync/testutils/m"
@ -17,7 +18,7 @@ import (
func TestTyping(t *testing.T) { func TestTyping(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
bob := registerNewUser(t) bob := registerNewUser(t)
roomID := alice.CreateRoom(t, map[string]interface{}{ roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
bob.JoinRoom(t, roomID, nil) bob.JoinRoom(t, roomID, nil)
@ -65,7 +66,7 @@ func TestTyping(t *testing.T) {
m.MatchResponse(t, res, m.MatchTyping(roomID, []string{bob.UserID, alice.UserID})) m.MatchResponse(t, res, m.MatchTyping(roomID, []string{bob.UserID, alice.UserID}))
// make sure if you type in a room not returned in the window it does not go through // make sure if you type in a room not returned in the window it does not go through
roomID2 := alice.CreateRoom(t, map[string]interface{}{ roomID2 := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
bob.JoinRoom(t, roomID2, nil) bob.JoinRoom(t, roomID2, nil)
@ -108,7 +109,7 @@ func TestTyping(t *testing.T) {
func TestTypingNoUpdate(t *testing.T) { func TestTypingNoUpdate(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
bob := registerNewUser(t) bob := registerNewUser(t)
roomID := alice.CreateRoom(t, map[string]interface{}{ roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
bob.JoinRoom(t, roomID, nil) bob.JoinRoom(t, roomID, nil)
@ -136,19 +137,19 @@ func TestTypingNoUpdate(t *testing.T) {
func TestTypingLazyLoad(t *testing.T) { func TestTypingLazyLoad(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
bob := registerNewUser(t) bob := registerNewUser(t)
roomID := alice.CreateRoom(t, map[string]interface{}{ roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
bob.JoinRoom(t, roomID, nil) bob.JoinRoom(t, roomID, nil)
alice.SendEventSynced(t, roomID, Event{ alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"body": "hello world!", "body": "hello world!",
"msgtype": "m.text", "msgtype": "m.text",
}, },
}) })
alice.SendEventSynced(t, roomID, Event{ alice.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"body": "hello world!", "body": "hello world!",
@ -202,8 +203,8 @@ func TestTypingRespectsExtensionScope(t *testing.T) {
// separate to the incremental sync behaviour (hits `AppendLive`) // separate to the incremental sync behaviour (hits `AppendLive`)
t.Run("Can limit by room in an initial sync", func(t *testing.T) { t.Run("Can limit by room in an initial sync", func(t *testing.T) {
t.Log("Alice creates rooms 1 and 2. Bob joins both.") t.Log("Alice creates rooms 1 and 2. Bob joins both.")
room1 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 1"}) room1 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 1"})
room2 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 2"}) room2 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 2"})
bob.JoinRoom(t, room1, nil) bob.JoinRoom(t, room1, nil)
bob.JoinRoom(t, room2, nil) bob.JoinRoom(t, room2, nil)
t.Logf("room1=%s room2=%s", room1, room2) t.Logf("room1=%s room2=%s", room1, room2)
@ -244,8 +245,8 @@ func TestTypingRespectsExtensionScope(t *testing.T) {
t.Run("Can limit by list in an incremental sync", func(t *testing.T) { t.Run("Can limit by list in an incremental sync", func(t *testing.T) {
t.Log("Alice creates rooms 3 and 4. Bob joins both.") t.Log("Alice creates rooms 3 and 4. Bob joins both.")
room3 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 3"}) room3 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 3"})
room4 := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 4"}) room4 := alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": "room 4"})
bob.JoinRoom(t, room3, nil) bob.JoinRoom(t, room3, nil)
bob.JoinRoom(t, room4, nil) bob.JoinRoom(t, room4, nil)
t.Logf("room3=%s room4=%s", room3, room4) t.Logf("room3=%s room4=%s", room3, room4)
@ -300,7 +301,7 @@ func TestTypingRespectsExtensionScopeWithOmittedFields(t *testing.T) {
t.Log("Alice creates four rooms. Bob joins each one.") t.Log("Alice creates four rooms. Bob joins each one.")
rooms := make([]string, 4) rooms := make([]string, 4)
for i := 0; i < len(rooms); i++ { for i := 0; i < len(rooms); i++ {
rooms[i] = alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": fmt.Sprintf("room %d", i)}) rooms[i] = alice.MustCreateRoom(t, map[string]interface{}{"preset": "public_chat", "name": fmt.Sprintf("room %d", i)})
bob.JoinRoom(t, rooms[i], nil) bob.JoinRoom(t, rooms[i], nil)
} }
t.Logf("rooms = %v", rooms) t.Logf("rooms = %v", rooms)
@ -356,7 +357,7 @@ func TestTypingRespectsExtensionScopeWithOmittedFields(t *testing.T) {
} }
t.Log("Bob sends a sentinel message.") t.Log("Bob sends a sentinel message.")
// Use room 2 because Alice explicitly subscribes to it // Use room 2 because Alice explicitly subscribes to it
bobMsg := bob.SendEventSynced(t, rooms[2], Event{ bobMsg := bob.SendEventSynced(t, rooms[2], b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
@ -388,7 +389,7 @@ func TestTypingRespectsExtensionScopeWithOmittedFields(t *testing.T) {
bob.SendTyping(t, room, true, 5000) bob.SendTyping(t, room, true, 5000)
} }
t.Log("Bob sends a sentinel message.") t.Log("Bob sends a sentinel message.")
bobMsg = bob.SendEventSynced(t, rooms[2], Event{ bobMsg = bob.SendEventSynced(t, rooms[2], b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
@ -396,7 +397,6 @@ func TestTypingRespectsExtensionScopeWithOmittedFields(t *testing.T) {
}, },
}) })
t.Log("Alice now requests typing notifications in all windows, and explicitly in rooms 0 and 3.") t.Log("Alice now requests typing notifications in all windows, and explicitly in rooms 0 and 3.")
t.Log("Alice incremental syncs until she sees Bob's latest sentinel. She should see no ops.") t.Log("Alice incremental syncs until she sees Bob's latest sentinel. She should see no ops.")
seenTyping := map[int]int{} seenTyping := map[int]int{}

View File

@ -4,6 +4,8 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/matrix-org/complement/b"
"github.com/matrix-org/complement/client"
"github.com/matrix-org/sliding-sync/sync3" "github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/testutils/m" "github.com/matrix-org/sliding-sync/testutils/m"
) )
@ -11,11 +13,11 @@ import (
func TestUnreadCountsUpdate(t *testing.T) { func TestUnreadCountsUpdate(t *testing.T) {
alice := registerNewUser(t) alice := registerNewUser(t)
bob := registerNewUser(t) bob := registerNewUser(t)
roomID := alice.CreateRoom(t, map[string]interface{}{ roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat", "preset": "public_chat",
}) })
bob.JoinRoom(t, roomID, nil) bob.JoinRoom(t, roomID, nil)
eventID := bob.SendEventSynced(t, roomID, Event{ eventID := bob.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message", Type: "m.room.message",
Content: map[string]interface{}{ Content: map[string]interface{}{
"msgtype": "m.text", "msgtype": "m.text",
@ -35,7 +37,7 @@ func TestUnreadCountsUpdate(t *testing.T) {
m.MatchRoomNotificationCount(1), m.MatchRoomNotificationCount(1),
}, },
})) }))
alice.MustDoFunc(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "read_markers"}, WithJSONBody(t, map[string]interface{}{ alice.MustDo(t, "POST", []string{"_matrix", "client", "v3", "rooms", roomID, "read_markers"}, client.WithJSONBody(t, map[string]interface{}{
"m.fully_read": eventID, "m.fully_read": eventID,
"m.read": eventID, "m.read": eventID,
})) }))