From e690225b5215928672939835bfcacabb57ce7b38 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Wed, 10 Aug 2022 16:04:28 -0500 Subject: [PATCH 1/6] WIP: /messages tests --- internal/b/perf_many_messages.go | 11 +++++- tests/federation_room_messages_test.go | 53 ++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 tests/federation_room_messages_test.go diff --git a/internal/b/perf_many_messages.go b/internal/b/perf_many_messages.go index 77d7360b..853bb31c 100644 --- a/internal/b/perf_many_messages.go +++ b/internal/b/perf_many_messages.go @@ -45,7 +45,16 @@ var BlueprintPerfManyMessages = MustValidate(Blueprint{ }, Sender: "@bob", }, - }, manyMessages([]string{"@alice", "@bob"}, 7000)...), + }, manyMessages([]string{"@alice", "@bob"}, 200)...), + }, + }, + }, + { + Name: "hs2", + Users: []User{ + { + Localpart: "@charlie", + DisplayName: "Charlie", }, }, }, diff --git a/tests/federation_room_messages_test.go b/tests/federation_room_messages_test.go new file mode 100644 index 00000000..214af887 --- /dev/null +++ b/tests/federation_room_messages_test.go @@ -0,0 +1,53 @@ +package tests + +import ( + "net/url" + "testing" + "time" + + "github.com/matrix-org/complement/internal/b" + "github.com/matrix-org/complement/internal/client" + "github.com/sirupsen/logrus" +) + +func TestMessagesOverFederation(t *testing.T) { + deployment := Deploy(t, b.BlueprintPerfManyMessages) + defer deployment.Destroy(t) + defer time.Sleep(30 * time.Second) + + alice := deployment.Client(t, "hs1", "@alice:hs1") + + remoteCharlie := deployment.Client(t, "hs2", "@charlie:hs2") + + t.Run("parallel", func(t *testing.T) { + t.Run("asdf", func(t *testing.T) { + t.Parallel() + + syncResult, _ := alice.MustSync(t, client.SyncReq{}) + joinedRooms := syncResult.Get("rooms.join|@keys") + roomWithManyMessages := joinedRooms.Get("0").String() + + // logrus.WithFields(logrus.Fields{ + // "joinedRooms": joinedRooms, + // "roomWithManyMessages": roomWithManyMessages, + // }).Error("asdf") + + remoteCharlie.JoinRoom(t, roomWithManyMessages, []string{"hs1"}) + + messagesRes := remoteCharlie.MustDoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomWithManyMessages, "messages"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ + "dir": []string{"b"}, + "limit": []string{"100"}, + })) + messagesResBody := client.ParseJSON(t, messagesRes) + eventIDs := client.GetJSONFieldStringArray(t, messagesResBody, "chunk") + + logrus.WithFields(logrus.Fields{ + "joinedRooms": joinedRooms, + "roomWithManyMessages": roomWithManyMessages, + "eventIDs": eventIDs, + }).Error("asdf") + + time.Sleep(5 * time.Second) + }) + }) +} From 737a944dade609c02ccc92fd5a78b0fd6d5cc64c Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Thu, 11 Aug 2022 10:28:26 -0500 Subject: [PATCH 2/6] Bigger room and state --- internal/b/blueprints.go | 44 ++++++++++++++++++++++++++ internal/b/perf_e2ee_room.go | 19 ----------- internal/b/perf_many_messages.go | 36 ++++++++++++++------- internal/docker/builder.go | 5 ++- tests/federation_room_messages_test.go | 1 - 5 files changed, 72 insertions(+), 33 deletions(-) diff --git a/internal/b/blueprints.go b/internal/b/blueprints.go index 365d419c..57a20283 100644 --- a/internal/b/blueprints.go +++ b/internal/b/blueprints.go @@ -236,3 +236,47 @@ func manyMessages(senders []string, count int) []Event { } return evs } + +func manJoinEvents(homeserver string, users []User) []Event { + evs := make([]Event, len(users)) + for i := 0; i < len(users); i++ { + user := users[i] + evs[i] = Event{ + Type: "m.room.member", + StateKey: Ptr(fmt.Sprintf("%s:%s", user.Localpart, homeserver)), + Content: map[string]interface{}{ + "membership": "join", + }, + Sender: user.Localpart, + } + } + return evs +} + +func manyUsers(count int) []User { + users := make([]User, count) + + for i := 0; i < count; i++ { + localPart := fmt.Sprintf("@user_%d", i) + displayName := fmt.Sprintf("User %d", i) + deviceID := fmt.Sprintf("USERDEVICE%d", i) + + users[i] = User{ + Localpart: localPart, + DisplayName: displayName, + OneTimeKeys: 50, + DeviceID: Ptr(deviceID), + } + } + + return users +} + +func getSendersFromUsers(users []User) []string { + senders := make([]string, len(users)) + for i := 0; i < len(users); i++ { + senders[i] = users[i].Localpart + } + + return senders +} diff --git a/internal/b/perf_e2ee_room.go b/internal/b/perf_e2ee_room.go index ae171b22..8f2acf46 100644 --- a/internal/b/perf_e2ee_room.go +++ b/internal/b/perf_e2ee_room.go @@ -83,22 +83,3 @@ func memberships(count int) []Event { return events } - -func manyUsers(count int) []User { - users := make([]User, count) - - for i := 0; i < count; i++ { - localPart := fmt.Sprintf("@alice_%d", i) - displayName := fmt.Sprintf("Alice %d", i) - deviceID := fmt.Sprintf("ALICEDEVICE%d", i) - - users[i] = User{ - Localpart: localPart, - DisplayName: displayName, - OneTimeKeys: 50, - DeviceID: Ptr(deviceID), - } - } - - return users -} diff --git a/internal/b/perf_many_messages.go b/internal/b/perf_many_messages.go index 853bb31c..ad1764bc 100644 --- a/internal/b/perf_many_messages.go +++ b/internal/b/perf_many_messages.go @@ -14,13 +14,34 @@ package b +var manyUsersList = manyUsers(500) + +func makeEvents(homeserver string) []Event { + events := []Event{ + { + Type: "m.room.member", + StateKey: Ptr("@bob:hs1"), + Content: map[string]interface{}{ + "membership": "join", + }, + Sender: "@bob", + }, + } + events = append(events, manJoinEvents(homeserver, manyUsersList)...) + events = append(events, manyMessages(getSendersFromUsers(manyUsersList), 1000)...) + + //fmt.Printf("events made %d events=%+v", len(events), events) + + return events +} + // BlueprintPerfManyMessages contains a homeserver with 2 users, who are joined to the same room with thousands of messages. var BlueprintPerfManyMessages = MustValidate(Blueprint{ Name: "perf_many_messages", Homeservers: []Homeserver{ { Name: "hs1", - Users: []User{ + Users: append([]User{ { Localpart: "@alice", DisplayName: "Alice", @@ -29,23 +50,14 @@ var BlueprintPerfManyMessages = MustValidate(Blueprint{ Localpart: "@bob", DisplayName: "Bob", }, - }, + }, manyUsersList...), Rooms: []Room{ { CreateRoom: map[string]interface{}{ "preset": "public_chat", }, Creator: "@alice", - Events: append([]Event{ - Event{ - Type: "m.room.member", - StateKey: Ptr("@bob:hs1"), - Content: map[string]interface{}{ - "membership": "join", - }, - Sender: "@bob", - }, - }, manyMessages([]string{"@alice", "@bob"}, 200)...), + Events: makeEvents("hs1"), }, }, }, diff --git a/internal/docker/builder.go b/internal/docker/builder.go index 28b5bde0..1392918f 100644 --- a/internal/docker/builder.go +++ b/internal/docker/builder.go @@ -181,7 +181,10 @@ func (d *Builder) ConstructBlueprintIfNotExist(bprint b.Blueprint) error { return fmt.Errorf("ConstructBlueprintIfNotExist(%s): failed to ImageList: %w", bprint.Name, err) } if len(images) == 0 { - d.ConstructBlueprint(bprint) + err := d.ConstructBlueprint(bprint) + if err != nil { + return fmt.Errorf("ConstructBlueprintIfNotExist(%s): failed to build image: %w", bprint.Name, err) + } } return nil } diff --git a/tests/federation_room_messages_test.go b/tests/federation_room_messages_test.go index 214af887..1b011d73 100644 --- a/tests/federation_room_messages_test.go +++ b/tests/federation_room_messages_test.go @@ -13,7 +13,6 @@ import ( func TestMessagesOverFederation(t *testing.T) { deployment := Deploy(t, b.BlueprintPerfManyMessages) defer deployment.Destroy(t) - defer time.Sleep(30 * time.Second) alice := deployment.Client(t, "hs1", "@alice:hs1") From 856bbd0d1dabf45605d399958d1e4a846bd0035d Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Fri, 12 Aug 2022 09:42:23 -0500 Subject: [PATCH 3/6] Be able to keep certain homeservers from a blueprint ``` TEST_ONLY_IGNORE_POETRY_LOCKFILE=1 TEST_ONLY_SKIP_DEP_HASH_VERIFICATION=1 COMPLEMENT_DEBUG=1 COMPLEMENT_KEEP_BLUEPRINTS="fed.perf_many_messages.hs1" COMPLEMENT_ALWAYS_PRINT_SERVER_LOGS=1 COMPLEMENT_DIR=../complement ./scripts-dev/complement.sh -run TestMessagesOverFederation -p 1 ``` --- internal/b/perf_many_messages.go | 4 ++-- internal/docker/builder.go | 37 +++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/internal/b/perf_many_messages.go b/internal/b/perf_many_messages.go index ad1764bc..b2e60594 100644 --- a/internal/b/perf_many_messages.go +++ b/internal/b/perf_many_messages.go @@ -14,7 +14,7 @@ package b -var manyUsersList = manyUsers(500) +var manyUsersList = manyUsers(1000) func makeEvents(homeserver string) []Event { events := []Event{ @@ -28,7 +28,7 @@ func makeEvents(homeserver string) []Event { }, } events = append(events, manJoinEvents(homeserver, manyUsersList)...) - events = append(events, manyMessages(getSendersFromUsers(manyUsersList), 1000)...) + events = append(events, manyMessages(getSendersFromUsers(manyUsersList), 1400)...) //fmt.Printf("events made %d events=%+v", len(events), events) diff --git a/internal/docker/builder.go b/internal/docker/builder.go index bb0c93c2..7908a7c8 100644 --- a/internal/docker/builder.go +++ b/internal/docker/builder.go @@ -124,16 +124,17 @@ func (d *Builder) removeImages() error { d.log("Not cleaning up image with tags: %v", img.RepoTags) continue } - bprintName := img.Labels["complement_blueprint"] + //bprintName := img.Labels["complement_blueprint"] + contextStr := img.Labels[complementLabel] keep := false for _, keepBprint := range d.Config.KeepBlueprints { - if bprintName == keepBprint { + if contextStr == keepBprint { keep = true break } } if keep { - d.log("Keeping image created from blueprint %s", bprintName) + d.log("Keeping image created from blueprint %s", contextStr) continue } _, err = d.Docker.ImageRemove(context.Background(), img.ID, types.ImageRemoveOptions{ @@ -180,8 +181,24 @@ func (d *Builder) ConstructBlueprintIfNotExist(bprint b.Blueprint) error { if err != nil { return fmt.Errorf("ConstructBlueprintIfNotExist(%s): failed to ImageList: %w", bprint.Name, err) } - if len(images) == 0 { - err = d.ConstructBlueprint(bprint) + + var missingHomeservers []b.Homeserver + for _, homeserver := range bprint.Homeservers { + found := false + for _, image := range images { + if image.Labels["complement_hs_name"] == homeserver.Name { + found = true + break + } + } + + if !found { + missingHomeservers = append(missingHomeservers, homeserver) + } + } + + if len(images) < len(bprint.Homeservers) { + err = d.ConstructBlueprint(bprint, missingHomeservers) if err != nil { return fmt.Errorf("ConstructBlueprintIfNotExist(%s): failed to ConstructBlueprint: %w", bprint.Name, err) } @@ -189,8 +206,8 @@ func (d *Builder) ConstructBlueprintIfNotExist(bprint b.Blueprint) error { return nil } -func (d *Builder) ConstructBlueprint(bprint b.Blueprint) error { - errs := d.construct(bprint) +func (d *Builder) ConstructBlueprint(bprint b.Blueprint, homeserversToConstruct []b.Homeserver) error { + errs := d.construct(bprint, homeserversToConstruct) if len(errs) > 0 { for _, err := range errs { d.log("could not construct blueprint: %s", err) @@ -237,7 +254,7 @@ func (d *Builder) ConstructBlueprint(bprint b.Blueprint) error { } // construct all Homeservers sequentially then commits them -func (d *Builder) construct(bprint b.Blueprint) (errs []error) { +func (d *Builder) construct(bprint b.Blueprint, homeserversToConstruct []b.Homeserver) (errs []error) { d.log("Constructing blueprint '%s'", bprint.Name) networkID, err := createNetworkIfNotExists(d.Docker, d.Config.PackageNamespace, bprint.Name) @@ -246,8 +263,8 @@ func (d *Builder) construct(bprint b.Blueprint) (errs []error) { } runner := instruction.NewRunner(bprint.Name, d.Config.BestEffort, d.Config.DebugLoggingEnabled) - results := make([]result, len(bprint.Homeservers)) - for i, hs := range bprint.Homeservers { + results := make([]result, len(homeserversToConstruct)) + for i, hs := range homeserversToConstruct { res := d.constructHomeserver(bprint.Name, runner, hs, networkID) if res.err != nil { errs = append(errs, res.err) From 8aae43faa934a6d38ce2990bca778f744591c449 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Mon, 22 Aug 2022 15:14:29 -0500 Subject: [PATCH 4/6] Ask for more than 100 so we can see how much backfill gives (answer 100) --- tests/federation_room_messages_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/federation_room_messages_test.go b/tests/federation_room_messages_test.go index 1b011d73..2fb30530 100644 --- a/tests/federation_room_messages_test.go +++ b/tests/federation_room_messages_test.go @@ -35,7 +35,7 @@ func TestMessagesOverFederation(t *testing.T) { messagesRes := remoteCharlie.MustDoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomWithManyMessages, "messages"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ "dir": []string{"b"}, - "limit": []string{"100"}, + "limit": []string{"500"}, })) messagesResBody := client.ParseJSON(t, messagesRes) eventIDs := client.GetJSONFieldStringArray(t, messagesResBody, "chunk") @@ -43,6 +43,7 @@ func TestMessagesOverFederation(t *testing.T) { logrus.WithFields(logrus.Fields{ "joinedRooms": joinedRooms, "roomWithManyMessages": roomWithManyMessages, + "eventIDsLength": len(eventIDs), "eventIDs": eventIDs, }).Error("asdf") From bb60b9fc533275105d5896ee7630e3b9a9433f55 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 6 Jun 2023 23:01:55 -0500 Subject: [PATCH 5/6] Sprinkle in some state to make it harder --- internal/b/blueprints.go | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/internal/b/blueprints.go b/internal/b/blueprints.go index 46662035..6cebf7bb 100644 --- a/internal/b/blueprints.go +++ b/internal/b/blueprints.go @@ -227,13 +227,26 @@ func manyMessages(senders []string, count int) []Event { evs := make([]Event, count) for i := 0; i < len(evs); i++ { sender := senders[i%len(senders)] - evs[i] = Event{ - Type: "m.room.message", - Content: map[string]interface{}{ - "body": "Hello world " + strconv.Itoa(i), - "msgtype": "m.text", - }, - Sender: sender, + + // Sprinkle in some state every so often to make it harder for the HS + if i%10 == 0 { + evs[i] = Event{ + Type: "m.room.topic", + StateKey: Ptr(""), + Content: map[string]interface{}{ + "topic": "Room topic " + strconv.Itoa(i), + }, + Sender: "@alice", + } + } else { + evs[i] = Event{ + Type: "m.room.message", + Content: map[string]interface{}{ + "body": "Hello world " + strconv.Itoa(i), + "msgtype": "m.text", + }, + Sender: sender, + } } } return evs From da9d2d052d5730604f247fd6277e5f9a1a4c714d Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Wed, 14 Jun 2023 01:21:40 -0500 Subject: [PATCH 6/6] Lesser test --- internal/b/perf_many_messages.go | 4 ++-- tests/federation_room_messages_test.go | 18 +++++++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/internal/b/perf_many_messages.go b/internal/b/perf_many_messages.go index b2e60594..697c211b 100644 --- a/internal/b/perf_many_messages.go +++ b/internal/b/perf_many_messages.go @@ -14,7 +14,7 @@ package b -var manyUsersList = manyUsers(1000) +var manyUsersList = manyUsers(20) func makeEvents(homeserver string) []Event { events := []Event{ @@ -28,7 +28,7 @@ func makeEvents(homeserver string) []Event { }, } events = append(events, manJoinEvents(homeserver, manyUsersList)...) - events = append(events, manyMessages(getSendersFromUsers(manyUsersList), 1400)...) + events = append(events, manyMessages(getSendersFromUsers(manyUsersList), 300)...) //fmt.Printf("events made %d events=%+v", len(events), events) diff --git a/tests/federation_room_messages_test.go b/tests/federation_room_messages_test.go index 2fb30530..036c1b4f 100644 --- a/tests/federation_room_messages_test.go +++ b/tests/federation_room_messages_test.go @@ -35,10 +35,11 @@ func TestMessagesOverFederation(t *testing.T) { messagesRes := remoteCharlie.MustDoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomWithManyMessages, "messages"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ "dir": []string{"b"}, - "limit": []string{"500"}, + "limit": []string{"100"}, })) messagesResBody := client.ParseJSON(t, messagesRes) eventIDs := client.GetJSONFieldStringArray(t, messagesResBody, "chunk") + // end := client.GetJSONFieldStringArray(t, messagesResBody, "end") logrus.WithFields(logrus.Fields{ "joinedRooms": joinedRooms, @@ -47,6 +48,21 @@ func TestMessagesOverFederation(t *testing.T) { "eventIDs": eventIDs, }).Error("asdf") + // messagesRes2 := remoteCharlie.MustDoFunc(t, "GET", []string{"_matrix", "client", "r0", "rooms", roomWithManyMessages, "messages"}, client.WithContentType("application/json"), client.WithQueries(url.Values{ + // "dir": []string{"b"}, + // "from": end, + // "limit": []string{"500"}, + // })) + // messagesResBody2 := client.ParseJSON(t, messagesRes2) + // eventIDs2 := client.GetJSONFieldStringArray(t, messagesResBody2, "chunk") + + // logrus.WithFields(logrus.Fields{ + // "joinedRooms": joinedRooms, + // "roomWithManyMessages": roomWithManyMessages, + // "eventIDsLength": len(eventIDs2), + // "eventIDs": eventIDs2, + // }).Error("asdf2") + time.Sleep(5 * time.Second) }) })