From 174acd729c640f1576a319ce4b37a291b7c758dd Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Wed, 18 Jan 2023 11:01:52 -0500 Subject: [PATCH 1/6] Add a test using a sync token for relations. --- tests/csapi/room_relations_test.go | 86 ++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/tests/csapi/room_relations_test.go b/tests/csapi/room_relations_test.go index 4119924b..ed15f738 100644 --- a/tests/csapi/room_relations_test.go +++ b/tests/csapi/room_relations_test.go @@ -205,3 +205,89 @@ func TestRelationsPagination(t *testing.T) { }, }) } + +func TestRelationsPaginationSync(t *testing.T) { + deployment := Deploy(t, b.BlueprintAlice) + defer deployment.Destroy(t) + + alice := deployment.Client(t, "hs1", "@alice:hs1") + roomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) + _, token := alice.MustSync(t, client.SyncReq{}) + + res := alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-1"}, client.WithJSONBody(t, map[string]interface{}{ + "msgtype": "m.text", + "body": "root", + })) + rootEventID := client.GetJSONFieldStr(t, client.ParseJSON(t, res), "event_id") + + // Create some related events. + event_id := "" + for i := 0; i < 5; i++ { + res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", fmt.Sprintf("txn-%d", 2+i)}, client.WithJSONBody(t, map[string]interface{}{ + "msgtype": "m.text", + "body": fmt.Sprintf("reply %d", i), + "m.relates_to": map[string]interface{}{ + "event_id": rootEventID, + "rel_type": "m.thread", + }, + })) + event_id = client.GetJSONFieldStr(t, client.ParseJSON(t, res), "event_id") + } + + // Sync and keep the token. + nextBatch := alice.MustSyncUntil(t, client.SyncReq{Since: token}, client.SyncTimelineHas(roomID, func(r gjson.Result) bool { + return r.Get("event_id").Str == event_id + })) + + // Create more related events. + event_ids := [5]string{} + for i := 0; i < 5; i++ { + res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", fmt.Sprintf("txn-%d", 2+i)}, client.WithJSONBody(t, map[string]interface{}{ + "msgtype": "m.text", + "body": fmt.Sprintf("reply %d", i), + "m.relates_to": map[string]interface{}{ + "event_id": rootEventID, + "rel_type": "m.thread", + }, + })) + event_ids[i] = client.GetJSONFieldStr(t, client.ParseJSON(t, res), "event_id") + } + + // sync until the server has processed it + alice.MustSyncUntil(t, client.SyncReq{Since: token}, client.SyncTimelineHas(roomID, func(r gjson.Result) bool { + return r.Get("event_id").Str == event_ids[4] + })) + + // Fetch the first page since the last sync. + queryParams := url.Values{} + queryParams.Set("limit", "3") + queryParams.Set("to", nextBatch) + queryParams.Set("dir", "f") + res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}, client.WithQueries(queryParams)) + body := must.MatchResponse(t, res, match.HTTPResponse{ + StatusCode: http.StatusOK, + JSON: []match.JSON{ + match.JSONCheckOff("chunk", []interface{}{ + event_ids[0], event_ids[1], event_ids[2], + }, func(r gjson.Result) interface{} { + return r.Get("event_id").Str + }, nil, + ), + }, + }) + + // Fetch the next page. + queryParams.Set("from", client.GetJSONFieldStr(t, body, "next_batch")) + res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}, client.WithQueries(queryParams)) + must.MatchResponse(t, res, match.HTTPResponse{ + StatusCode: http.StatusOK, + JSON: []match.JSON{ + match.JSONCheckOff("chunk", []interface{}{ + event_ids[3], event_ids[4], + }, func(r gjson.Result) interface{} { + return r.Get("event_id").Str + }, nil, + ), + }, + }) +} From 454a60a83077d25b753e0f7b9e74f738695e8cfa Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Wed, 18 Jan 2023 11:34:06 -0500 Subject: [PATCH 2/6] Broken on dendrite. --- tests/csapi/room_relations_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/csapi/room_relations_test.go b/tests/csapi/room_relations_test.go index ed15f738..5f7b9ca7 100644 --- a/tests/csapi/room_relations_test.go +++ b/tests/csapi/room_relations_test.go @@ -12,6 +12,7 @@ import ( "github.com/matrix-org/complement/internal/client" "github.com/matrix-org/complement/internal/match" "github.com/matrix-org/complement/internal/must" + "github.com/matrix-org/complement/runtime" ) func TestRelations(t *testing.T) { @@ -207,6 +208,8 @@ func TestRelationsPagination(t *testing.T) { } func TestRelationsPaginationSync(t *testing.T) { + runtime.SkipIf(t, runtime.Dendrite) // FIXME: https://github.com/matrix-org/dendrite/issues/2944 + deployment := Deploy(t, b.BlueprintAlice) defer deployment.Destroy(t) From 0b9ce9b4545ae7b3d13c5242ee306380eee511c8 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 27 Jan 2023 08:59:55 -0500 Subject: [PATCH 3/6] Run gofmt --- tests/csapi/room_relations_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/csapi/room_relations_test.go b/tests/csapi/room_relations_test.go index 5f7b9ca7..b702c34c 100644 --- a/tests/csapi/room_relations_test.go +++ b/tests/csapi/room_relations_test.go @@ -208,7 +208,7 @@ func TestRelationsPagination(t *testing.T) { } func TestRelationsPaginationSync(t *testing.T) { - runtime.SkipIf(t, runtime.Dendrite) // FIXME: https://github.com/matrix-org/dendrite/issues/2944 + runtime.SkipIf(t, runtime.Dendrite) // FIXME: https://github.com/matrix-org/dendrite/issues/2944 deployment := Deploy(t, b.BlueprintAlice) defer deployment.Destroy(t) From f5ef0093ef646198b83339098ed7892fd4e3254f Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 27 Jan 2023 09:07:00 -0500 Subject: [PATCH 4/6] Fix transactions. --- tests/csapi/room_relations_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/csapi/room_relations_test.go b/tests/csapi/room_relations_test.go index b702c34c..27314824 100644 --- a/tests/csapi/room_relations_test.go +++ b/tests/csapi/room_relations_test.go @@ -226,7 +226,7 @@ func TestRelationsPaginationSync(t *testing.T) { // Create some related events. event_id := "" for i := 0; i < 5; i++ { - res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", fmt.Sprintf("txn-%d", 2+i)}, client.WithJSONBody(t, map[string]interface{}{ + res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", fmt.Sprintf("txn-%d", 1+i)}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": fmt.Sprintf("reply %d", i), "m.relates_to": map[string]interface{}{ @@ -245,7 +245,7 @@ func TestRelationsPaginationSync(t *testing.T) { // Create more related events. event_ids := [5]string{} for i := 0; i < 5; i++ { - res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", fmt.Sprintf("txn-%d", 2+i)}, client.WithJSONBody(t, map[string]interface{}{ + res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", fmt.Sprintf("txn-%d", 6+i)}, client.WithJSONBody(t, map[string]interface{}{ "msgtype": "m.text", "body": fmt.Sprintf("reply %d", i), "m.relates_to": map[string]interface{}{ @@ -264,7 +264,7 @@ func TestRelationsPaginationSync(t *testing.T) { // Fetch the first page since the last sync. queryParams := url.Values{} queryParams.Set("limit", "3") - queryParams.Set("to", nextBatch) + queryParams.Set("from", nextBatch) queryParams.Set("dir", "f") res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}, client.WithQueries(queryParams)) body := must.MatchResponse(t, res, match.HTTPResponse{ From 41826f4b4ee08e4b1cca38ad2ddb821596dbee18 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 27 Jan 2023 10:06:33 -0500 Subject: [PATCH 5/6] Use helpers. --- tests/csapi/room_relations_test.go | 57 +++++++++++++++++------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/tests/csapi/room_relations_test.go b/tests/csapi/room_relations_test.go index 27314824..d8daa68e 100644 --- a/tests/csapi/room_relations_test.go +++ b/tests/csapi/room_relations_test.go @@ -217,24 +217,30 @@ func TestRelationsPaginationSync(t *testing.T) { roomID := alice.CreateRoom(t, map[string]interface{}{"preset": "public_chat"}) _, token := alice.MustSync(t, client.SyncReq{}) - res := alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", "txn-1"}, client.WithJSONBody(t, map[string]interface{}{ - "msgtype": "m.text", - "body": "root", - })) - rootEventID := client.GetJSONFieldStr(t, client.ParseJSON(t, res), "event_id") + rootEventID := alice.SendEventUnsynced(t, roomID, b.Event{ + Type: "m.room.message", + Content: map[string]interface{}{ + "msgtype": "m.text", + "body": "root", + }, + Sender: alice.UserID, + }) // Create some related events. event_id := "" for i := 0; i < 5; i++ { - res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", fmt.Sprintf("txn-%d", 1+i)}, client.WithJSONBody(t, map[string]interface{}{ - "msgtype": "m.text", - "body": fmt.Sprintf("reply %d", i), - "m.relates_to": map[string]interface{}{ - "event_id": rootEventID, - "rel_type": "m.thread", + event_id = alice.SendEventUnsynced(t, roomID, b.Event{ + Type: "m.room.message", + Content: map[string]interface{}{ + "msgtype": "m.text", + "body": fmt.Sprintf("reply %d", i), + "m.relates_to": map[string]interface{}{ + "event_id": rootEventID, + "rel_type": "m.thread", + }, }, - })) - event_id = client.GetJSONFieldStr(t, client.ParseJSON(t, res), "event_id") + Sender: alice.UserID, + }) } // Sync and keep the token. @@ -245,28 +251,29 @@ func TestRelationsPaginationSync(t *testing.T) { // Create more related events. event_ids := [5]string{} for i := 0; i < 5; i++ { - res = alice.MustDoFunc(t, "PUT", []string{"_matrix", "client", "v3", "rooms", roomID, "send", "m.room.message", fmt.Sprintf("txn-%d", 6+i)}, client.WithJSONBody(t, map[string]interface{}{ - "msgtype": "m.text", - "body": fmt.Sprintf("reply %d", i), - "m.relates_to": map[string]interface{}{ - "event_id": rootEventID, - "rel_type": "m.thread", + event_ids[i] = alice.SendEventUnsynced(t, roomID, b.Event{ + Type: "m.room.message", + Content: map[string]interface{}{ + "msgtype": "m.text", + "body": fmt.Sprintf("reply %d", i), + "m.relates_to": map[string]interface{}{ + "event_id": rootEventID, + "rel_type": "m.thread", + }, }, - })) - event_ids[i] = client.GetJSONFieldStr(t, client.ParseJSON(t, res), "event_id") + Sender: alice.UserID, + }) } // sync until the server has processed it - alice.MustSyncUntil(t, client.SyncReq{Since: token}, client.SyncTimelineHas(roomID, func(r gjson.Result) bool { - return r.Get("event_id").Str == event_ids[4] - })) + alice.MustSyncUntil(t, client.SyncReq{Since: token}, client.SyncTimelineHasEventID(roomID, event_ids[4])) // Fetch the first page since the last sync. queryParams := url.Values{} queryParams.Set("limit", "3") queryParams.Set("from", nextBatch) queryParams.Set("dir", "f") - res = alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}, client.WithQueries(queryParams)) + res := alice.MustDoFunc(t, "GET", []string{"_matrix", "client", "v1", "rooms", roomID, "relations", rootEventID}, client.WithQueries(queryParams)) body := must.MatchResponse(t, res, match.HTTPResponse{ StatusCode: http.StatusOK, JSON: []match.JSON{ From 531cafcb43db51ca6812794099280c2b0a5ec359 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 27 Jan 2023 12:08:38 -0500 Subject: [PATCH 6/6] Unique message bodies. --- tests/csapi/room_relations_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/csapi/room_relations_test.go b/tests/csapi/room_relations_test.go index d8daa68e..2ca85433 100644 --- a/tests/csapi/room_relations_test.go +++ b/tests/csapi/room_relations_test.go @@ -233,7 +233,7 @@ func TestRelationsPaginationSync(t *testing.T) { Type: "m.room.message", Content: map[string]interface{}{ "msgtype": "m.text", - "body": fmt.Sprintf("reply %d", i), + "body": fmt.Sprintf("reply %d before sync token", i), "m.relates_to": map[string]interface{}{ "event_id": rootEventID, "rel_type": "m.thread", @@ -255,7 +255,7 @@ func TestRelationsPaginationSync(t *testing.T) { Type: "m.room.message", Content: map[string]interface{}{ "msgtype": "m.text", - "body": fmt.Sprintf("reply %d", i), + "body": fmt.Sprintf("reply %d after sync token", i), "m.relates_to": map[string]interface{}{ "event_id": rootEventID, "rel_type": "m.thread",