From 9397df30228683f859aef6e6ae171df7f692966b Mon Sep 17 00:00:00 2001 From: Kegan Dougal <7190048+kegsay@users.noreply.github.com> Date: Mon, 30 Sep 2024 16:29:32 +0100 Subject: [PATCH 1/2] Convert remaining Must functions to TestClient --- internal/api/client.go | 118 +++++++++++++++++--------- internal/api/js/js.go | 43 ++++------ internal/api/rust/rust.go | 54 ++++++------ internal/deploy/rpc/client.go | 57 +++---------- internal/deploy/rpc/server.go | 41 ++++----- internal/tests/client_test.go | 14 +-- tests/delayed_requests_test.go | 4 +- tests/device_keys_test.go | 2 +- tests/federation_connectivity_test.go | 12 +-- tests/key_backup_test.go | 4 +- tests/membership_acls_test.go | 22 ++--- tests/one_time_keys_test.go | 6 +- tests/room_keys_test.go | 34 ++++---- tests/rust/notification_test.go | 40 ++++----- tests/to_device_test.go | 20 ++--- 15 files changed, 229 insertions(+), 242 deletions(-) diff --git a/internal/api/client.go b/internal/api/client.go index 7bfc99d..03e521d 100644 --- a/internal/api/client.go +++ b/internal/api/client.go @@ -45,20 +45,18 @@ type Client interface { InviteUser(t ct.TestLike, roomID, userID string) error // SendMessage sends the given text as an encrypted/unencrypted message in the room, depending // if the room is encrypted or not. Returns the event ID of the sent event, so MUST BLOCK until the event has been sent. - SendMessage(t ct.TestLike, roomID, text string) (eventID string) - // TrySendMessage tries to send the message, but can fail. - TrySendMessage(t ct.TestLike, roomID, text string) (eventID string, err error) + // If the event cannot be sent, returns an error. + SendMessage(t ct.TestLike, roomID, text string) (eventID string, err error) // Wait until an event is seen in the given room. The checker functions can be custom or you can use // a pre-defined one like api.CheckEventHasMembership, api.CheckEventHasBody, or api.CheckEventHasEventID. WaitUntilEventInRoom(t ct.TestLike, roomID string, checker func(e Event) bool) Waiter - // Backpaginate in this room by `count` events. - MustBackpaginate(t ct.TestLike, roomID string, count int) - // MustGetEvent will return the client's view of this event, or fail the test if the event cannot be found. - MustGetEvent(t ct.TestLike, roomID, eventID string) Event - // MustBackupKeys will backup E2EE keys, else fail the test. - MustBackupKeys(t ct.TestLike) (recoveryKey string) - // MustLoadBackup will recover E2EE keys from the latest backup, else fail the test. - MustLoadBackup(t ct.TestLike, recoveryKey string) + // Backpaginate in this room by `count` events. Returns an error if there was a problem backpaginating. + // Getting to the beginning of the room is not an error condition. + Backpaginate(t ct.TestLike, roomID string, count int) error + // GetEvent will return the client's view of this event, or returns an error if the event cannot be found. + GetEvent(t ct.TestLike, roomID, eventID string) (*Event, error) + // BackupKeys will backup E2EE keys, else return an error. + BackupKeys(t ct.TestLike) (recoveryKey string, err error) // LoadBackup will recover E2EE keys from the latest backup, else return an error. LoadBackup(t ct.TestLike, recoveryKey string) error // GetNotification gets push notification-like information for the given event. If there is a problem, an error is returned. @@ -96,7 +94,18 @@ type Client interface { // instead composed together by the test rig itself. type TestClient interface { Client + // MustStartSyncing is StartSyncing but fails the test on error. MustStartSyncing(t ct.TestLike) (stopSyncing func()) + // MustLoadBackup is LoadBackup but fails the test on error. + MustLoadBackup(t ct.TestLike, recoveryKey string) + // MustSendMessage is SendMessage but fails the test on error. + MustSendMessage(t ct.TestLike, roomID, text string) (eventID string) + // MustGetEvent is GetEvent but fails the test on error. + MustGetEvent(t ct.TestLike, roomID, eventID string) *Event + // MustBackupKeys is BackupKeys but fails the test on error. + MustBackupKeys(t ct.TestLike) (recoveryKey string) + // MustBackpaginate is Backpaginate but fails the test on error. + MustBackpaginate(t ct.TestLike, roomID string, count int) } // NewTestClient wraps a Client implementation with helper functions which tests can use. @@ -119,6 +128,49 @@ func (c *testClientImpl) MustStartSyncing(t ct.TestLike) (stopSyncing func()) { return stopSyncing } +func (c *testClientImpl) MustLoadBackup(t ct.TestLike, recoveryKey string) { + t.Helper() + err := c.LoadBackup(t, recoveryKey) + if err != nil { + ct.Fatalf(t, "MustLoadBackup: %s", err) + } +} + +func (c *testClientImpl) MustBackupKeys(t ct.TestLike) (recoveryKey string) { + t.Helper() + recoveryKey, err := c.BackupKeys(t) + if err != nil { + ct.Fatalf(t, "MustBackupKeys: %s", err) + } + return recoveryKey +} + +func (c *testClientImpl) MustBackpaginate(t ct.TestLike, roomID string, count int) { + t.Helper() + err := c.Backpaginate(t, roomID, count) + if err != nil { + ct.Fatalf(t, "MustBackpaginate: %s", err) + } +} + +func (c *testClientImpl) MustSendMessage(t ct.TestLike, roomID, text string) (eventID string) { + t.Helper() + eventID, err := c.SendMessage(t, roomID, text) + if err != nil { + ct.Fatalf(t, "MustSendMessage: %s", err) + } + return eventID +} + +func (c *testClientImpl) MustGetEvent(t ct.TestLike, roomID, eventID string) *Event { + t.Helper() + ev, err := c.GetEvent(t, roomID, eventID) + if err != nil { + ct.Fatalf(t, "MustGetEvent: %s", err) + } + return ev +} + type LoggedClient struct { Client } @@ -148,10 +200,10 @@ func (c *LoggedClient) ForceClose(t ct.TestLike) { c.Client.ForceClose(t) } -func (c *LoggedClient) MustGetEvent(t ct.TestLike, roomID, eventID string) Event { +func (c *LoggedClient) GetEvent(t ct.TestLike, roomID, eventID string) (*Event, error) { t.Helper() - c.Logf(t, "%s MustGetEvent(%s, %s)", c.logPrefix(), roomID, eventID) - return c.Client.MustGetEvent(t, roomID, eventID) + c.Logf(t, "%s GetEvent(%s, %s)", c.logPrefix(), roomID, eventID) + return c.Client.GetEvent(t, roomID, eventID) } func (c *LoggedClient) StartSyncing(t ct.TestLike) (stopSyncing func(), err error) { @@ -168,19 +220,11 @@ func (c *LoggedClient) IsRoomEncrypted(t ct.TestLike, roomID string) (bool, erro return c.Client.IsRoomEncrypted(t, roomID) } -func (c *LoggedClient) TrySendMessage(t ct.TestLike, roomID, text string) (eventID string, err error) { - t.Helper() - c.Logf(t, "%s TrySendMessage %s => %s", c.logPrefix(), roomID, text) - eventID, err = c.Client.TrySendMessage(t, roomID, text) - c.Logf(t, "%s TrySendMessage %s => %s", c.logPrefix(), roomID, eventID) - return -} - -func (c *LoggedClient) SendMessage(t ct.TestLike, roomID, text string) (eventID string) { +func (c *LoggedClient) SendMessage(t ct.TestLike, roomID, text string) (eventID string, err error) { t.Helper() c.Logf(t, "%s SendMessage %s => %s", c.logPrefix(), roomID, text) - eventID = c.Client.SendMessage(t, roomID, text) - c.Logf(t, "%s SendMessage %s => %s", c.logPrefix(), roomID, eventID) + eventID, err = c.Client.SendMessage(t, roomID, text) + c.Logf(t, "%s SendMessage %s => %s %s", c.logPrefix(), roomID, eventID, err) return } @@ -190,24 +234,20 @@ func (c *LoggedClient) WaitUntilEventInRoom(t ct.TestLike, roomID string, checke return c.Client.WaitUntilEventInRoom(t, roomID, checker) } -func (c *LoggedClient) MustBackpaginate(t ct.TestLike, roomID string, count int) { +func (c *LoggedClient) Backpaginate(t ct.TestLike, roomID string, count int) error { t.Helper() - c.Logf(t, "%s MustBackpaginate %d %s", c.logPrefix(), count, roomID) - c.Client.MustBackpaginate(t, roomID, count) -} - -func (c *LoggedClient) MustBackupKeys(t ct.TestLike) (recoveryKey string) { - t.Helper() - c.Logf(t, "%s MustBackupKeys", c.logPrefix()) - recoveryKey = c.Client.MustBackupKeys(t) - c.Logf(t, "%s MustBackupKeys => %s", c.logPrefix(), recoveryKey) - return recoveryKey + c.Logf(t, "%s Backpaginate %d %s", c.logPrefix(), count, roomID) + err := c.Client.Backpaginate(t, roomID, count) + c.Logf(t, "%s Backpaginate %d %s => %s", c.logPrefix(), count, roomID, err) + return err } -func (c *LoggedClient) MustLoadBackup(t ct.TestLike, recoveryKey string) { +func (c *LoggedClient) BackupKeys(t ct.TestLike) (recoveryKey string, err error) { t.Helper() - c.Logf(t, "%s MustLoadBackup key=%s", c.logPrefix(), recoveryKey) - c.Client.MustLoadBackup(t, recoveryKey) + c.Logf(t, "%s BackupKeys", c.logPrefix()) + recoveryKey, err = c.Client.BackupKeys(t) + c.Logf(t, "%s BackupKeys => %s %s", c.logPrefix(), recoveryKey, err) + return recoveryKey, err } func (c *LoggedClient) LoadBackup(t ct.TestLike, recoveryKey string) error { diff --git a/internal/api/js/js.go b/internal/api/js/js.go index b421d68..0140843 100644 --- a/internal/api/js/js.go +++ b/internal/api/js/js.go @@ -14,7 +14,6 @@ import ( "github.com/matrix-org/complement-crypto/internal/api" "github.com/matrix-org/complement-crypto/internal/api/js/chrome" "github.com/matrix-org/complement/ct" - "github.com/matrix-org/complement/must" "github.com/tidwall/gjson" ) @@ -509,7 +508,7 @@ func (c *JSClient) InviteUser(t ct.TestLike, roomID, userID string) error { return err } -func (c *JSClient) MustGetEvent(t ct.TestLike, roomID, eventID string) api.Event { +func (c *JSClient) GetEvent(t ct.TestLike, roomID, eventID string) (*api.Event, error) { t.Helper() // serialised output (if encrypted): // { @@ -517,14 +516,17 @@ func (c *JSClient) MustGetEvent(t ct.TestLike, roomID, eventID string) api.Event // decrypted: { event } // } // else just returns { event } - evSerialised := chrome.MustRunAsyncFn[string](t, c.browser.Ctx, fmt.Sprintf(` + evSerialised, err := chrome.RunAsyncFn[string](t, c.browser.Ctx, fmt.Sprintf(` return JSON.stringify(window.__client.getRoom("%s")?.getLiveTimeline()?.getEvents().filter((ev, i) => { console.log("MustGetEvent["+i+"] => " + ev.getId()+ " " + JSON.stringify(ev.toJSON())); return ev.getId() === "%s"; })[0].toJSON()); `, roomID, eventID)) + if err != nil { + return nil, fmt.Errorf("failed to get event %s: %s", eventID, err) + } if !gjson.Valid(*evSerialised) { - ct.Fatalf(t, "MustGetEvent(%s, %s) %s (js): invalid event, got %s", roomID, eventID, c.userID, *evSerialised) + return nil, fmt.Errorf("invalid event %s, got %s", eventID, *evSerialised) } result := gjson.Parse(*evSerialised) decryptedEvent := result.Get("decrypted") @@ -533,7 +535,7 @@ func (c *JSClient) MustGetEvent(t ct.TestLike, roomID, eventID string) api.Event } encryptedEvent := result.Get("encrypted") //fmt.Printf("DECRYPTED: %s\nENCRYPTED: %s\n\n", decryptedEvent.Raw, encryptedEvent.Raw) - ev := api.Event{ + ev := &api.Event{ ID: decryptedEvent.Get("event_id").Str, Text: decryptedEvent.Get("content.body").Str, Sender: decryptedEvent.Get("sender").Str, @@ -546,7 +548,7 @@ func (c *JSClient) MustGetEvent(t ct.TestLike, roomID, eventID string) api.Event ev.FailedToDecrypt = true } - return ev + return ev, nil } // StartSyncing to begin syncing from sync v2 / sliding sync. @@ -602,16 +604,7 @@ func (c *JSClient) IsRoomEncrypted(t ct.TestLike, roomID string) (bool, error) { return *isEncrypted, nil } -// SendMessage sends the given text as an m.room.message with msgtype:m.text into the given -// room. -func (c *JSClient) SendMessage(t ct.TestLike, roomID, text string) (eventID string) { - t.Helper() - eventID, err := c.TrySendMessage(t, roomID, text) - must.NotError(t, "failed to sendMessage", err) - return eventID -} - -func (c *JSClient) TrySendMessage(t ct.TestLike, roomID, text string) (eventID string, err error) { +func (c *JSClient) SendMessage(t ct.TestLike, roomID, text string) (eventID string, err error) { t.Helper() res, err := chrome.RunAsyncFn[map[string]interface{}](t, c.browser.Ctx, fmt.Sprintf(` return await window.__client.sendMessage("%s", { @@ -624,16 +617,17 @@ func (c *JSClient) TrySendMessage(t ct.TestLike, roomID, text string) (eventID s return (*res)["event_id"].(string), nil } -func (c *JSClient) MustBackpaginate(t ct.TestLike, roomID string, count int) { +func (c *JSClient) Backpaginate(t ct.TestLike, roomID string, count int) error { t.Helper() - chrome.MustRunAsyncFn[chrome.Void](t, c.browser.Ctx, fmt.Sprintf( + _, err := chrome.RunAsyncFn[chrome.Void](t, c.browser.Ctx, fmt.Sprintf( `await window.__client.scrollback(window.__client.getRoom("%s"), %d);`, roomID, count, )) + return err } -func (c *JSClient) MustBackupKeys(t ct.TestLike) (recoveryKey string) { +func (c *JSClient) BackupKeys(t ct.TestLike) (recoveryKey string, err error) { t.Helper() - key := chrome.MustRunAsyncFn[string](t, c.browser.Ctx, ` + key, err := chrome.RunAsyncFn[string](t, c.browser.Ctx, ` // we need to ensure that we have a recovery key first, though we don't actually care about it..? const recoveryKey = await window.__client.getCrypto().createRecoveryKeyFromPassphrase(); // now use said key to make backups @@ -645,15 +639,14 @@ func (c *JSClient) MustBackupKeys(t ct.TestLike) (recoveryKey string) { // now we can enable key backups await window.__client.getCrypto().checkKeyBackupAndEnable(); return recoveryKey.encodedPrivateKey;`) + if err != nil { + return "", fmt.Errorf("error enabling key backup: %s", err) + } // the backup loop which sends keys will wait between 0-10s before uploading keys... // See https://github.com/matrix-org/matrix-js-sdk/blob/49624d5d7308e772ebee84322886a39d2e866869/src/rust-crypto/backup.ts#L319 // Ideally this would be configurable.. time.Sleep(11 * time.Second) - return *key -} - -func (c *JSClient) MustLoadBackup(t ct.TestLike, recoveryKey string) { - must.NotError(t, "failed to load backup", c.LoadBackup(t, recoveryKey)) + return *key, nil } func (c *JSClient) LoadBackup(t ct.TestLike, recoveryKey string) error { diff --git a/internal/api/rust/rust.go b/internal/api/rust/rust.go index bd3cf1f..b4ceea0 100644 --- a/internal/api/rust/rust.go +++ b/internal/api/rust/rust.go @@ -309,18 +309,18 @@ func (c *RustClient) Close(t ct.TestLike) { } } -func (c *RustClient) MustGetEvent(t ct.TestLike, roomID, eventID string) api.Event { +func (c *RustClient) GetEvent(t ct.TestLike, roomID, eventID string) (*api.Event, error) { t.Helper() room := c.findRoom(t, roomID) timelineItem, err := mustGetTimeline(t, room).GetEventTimelineItemByEventId(eventID) if err != nil { - ct.Fatalf(t, "MustGetEvent(rust) %s (%s, %s): %s", c.userID, roomID, eventID, err) + return nil, fmt.Errorf("failed to GetEventTimelineItemByEventId(%s): %s", eventID, err) } ev := eventTimelineItemToEvent(timelineItem) if ev == nil { - ct.Fatalf(t, "MustGetEvent(rust) %s (%s, %s): found timeline item but failed to convert it to an Event", c.userID, roomID, eventID) + return nil, fmt.Errorf("found timeline item %s but failed to convert it to an Event", eventID) } - return *ev + return ev, nil } // StartSyncing to begin syncing from sync v2 / sliding sync. @@ -453,33 +453,40 @@ func (c *RustClient) IsRoomEncrypted(t ct.TestLike, roomID string) (bool, error) return r.IsEncrypted() } -func (c *RustClient) MustBackupKeys(t ct.TestLike) (recoveryKey string) { +func (c *RustClient) BackupKeys(t ct.TestLike) (recoveryKey string, err error) { t.Helper() genericListener := newGenericStateListener[matrix_sdk_ffi.EnableRecoveryProgress]() var listener matrix_sdk_ffi.EnableRecoveryProgressListener = genericListener e := c.FFIClient.Encryption() defer e.Destroy() - recoveryKey, err := e.EnableRecovery(true, nil, listener) - must.NotError(t, "Encryption.EnableRecovery", err) + recoveryKey, err = e.EnableRecovery(true, nil, listener) + if err != nil { + return "", fmt.Errorf("EnableRecovery: %s", err) + } + var lastState string for !genericListener.isClosed.Load() { select { case s := <-genericListener.ch: switch x := s.(type) { case matrix_sdk_ffi.EnableRecoveryProgressCreatingBackup: t.Logf("MustBackupKeys: state=CreatingBackup") + lastState = "CreatingBackup" case matrix_sdk_ffi.EnableRecoveryProgressBackingUp: t.Logf("MustBackupKeys: state=BackingUp %v/%v", x.BackedUpCount, x.TotalCount) + lastState = fmt.Sprintf("BackingUp %v/%v", x.BackedUpCount, x.TotalCount) case matrix_sdk_ffi.EnableRecoveryProgressCreatingRecoveryKey: t.Logf("MustBackupKeys: state=CreatingRecoveryKey") + lastState = "CreatingRecoveryKey" case matrix_sdk_ffi.EnableRecoveryProgressDone: t.Logf("MustBackupKeys: state=Done") + lastState = "Done" genericListener.Close() // break the loop } case <-time.After(5 * time.Second): - ct.Fatalf(t, "timed out enabling backup keys") + return "", fmt.Errorf("timed out enabling backup keys: last state: %s", lastState) } } - return recoveryKey + return recoveryKey, nil } func (c *RustClient) LoadBackup(t ct.TestLike, recoveryKey string) error { @@ -489,11 +496,6 @@ func (c *RustClient) LoadBackup(t ct.TestLike, recoveryKey string) error { return e.Recover(recoveryKey) } -func (c *RustClient) MustLoadBackup(t ct.TestLike, recoveryKey string) { - t.Helper() - c.LoadBackup(t, recoveryKey) -} - func (c *RustClient) WaitUntilEventInRoom(t ct.TestLike, roomID string, checker func(api.Event) bool) api.Waiter { t.Helper() c.ensureListening(t, roomID) @@ -508,18 +510,7 @@ func (c *RustClient) Type() api.ClientTypeLang { return api.ClientTypeRust } -// SendMessage sends the given text as an m.room.message with msgtype:m.text into the given -// room. Returns the event ID of the sent event. -func (c *RustClient) SendMessage(t ct.TestLike, roomID, text string) (eventID string) { - t.Helper() - eventID, err := c.TrySendMessage(t, roomID, text) - if err != nil { - ct.Fatalf(t, err.Error()) - } - return eventID -} - -func (c *RustClient) TrySendMessage(t ct.TestLike, roomID, text string) (eventID string, err error) { +func (c *RustClient) SendMessage(t ct.TestLike, roomID, text string) (eventID string, err error) { t.Helper() var isChannelClosed atomic.Bool ch := make(chan bool) @@ -579,12 +570,17 @@ func (c *RustClient) InviteUser(t ct.TestLike, roomID, userID string) error { return r.InviteUserById(userID) } -func (c *RustClient) MustBackpaginate(t ct.TestLike, roomID string, count int) { +func (c *RustClient) Backpaginate(t ct.TestLike, roomID string, count int) error { t.Helper() r := c.findRoom(t, roomID) - must.NotEqual(t, r, nil, "unknown room") + if r == nil { + return fmt.Errorf("Backpaginate: cannot find room %s", roomID) + } _, err := mustGetTimeline(t, r).PaginateBackwards(uint16(count)) - must.NotError(t, "failed to backpaginate", err) + if err != nil { + return fmt.Errorf("cannot PaginateBackwards in %s: %s", roomID, err) + } + return nil } func (c *RustClient) UserID() string { diff --git a/internal/deploy/rpc/client.go b/internal/deploy/rpc/client.go index 02ab2fa..82f0da8 100644 --- a/internal/deploy/rpc/client.go +++ b/internal/deploy/rpc/client.go @@ -244,23 +244,9 @@ func (c *RPCClient) IsRoomEncrypted(t ct.TestLike, roomID string) (bool, error) return isEncrypted, err } -// SendMessage sends the given text as an m.room.message with msgtype:m.text into the given -// room. Returns the event ID of the sent event, so MUST BLOCK until the event has been sent. -func (c *RPCClient) SendMessage(t ct.TestLike, roomID, text string) (eventID string) { - err := c.client.Call("Server.SendMessage", RPCSendMessage{ - TestName: t.Name(), - RoomID: roomID, - Text: text, - }, &eventID) - if err != nil { - t.Fatalf("RPCClient.SendMessage: %s", err) - } - return -} - -// TrySendMessage tries to send the message, but can fail. -func (c *RPCClient) TrySendMessage(t ct.TestLike, roomID, text string) (eventID string, err error) { - err = c.client.Call("Server.TrySendMessage", RPCSendMessage{ +// SendMessage tries to send the message, but can fail. +func (c *RPCClient) SendMessage(t ct.TestLike, roomID, text string) (eventID string, err error) { + err = c.client.Call("Server.SendMessage", RPCSendMessage{ TestName: t.Name(), RoomID: roomID, Text: text, @@ -287,50 +273,33 @@ func (c *RPCClient) WaitUntilEventInRoom(t ct.TestLike, roomID string, checker f } // Backpaginate in this room by `count` events. -func (c *RPCClient) MustBackpaginate(t ct.TestLike, roomID string, count int) { +func (c *RPCClient) Backpaginate(t ct.TestLike, roomID string, count int) error { var void int - err := c.client.Call("Server.MustBackpaginate", RPCBackpaginate{ + err := c.client.Call("Server.Backpaginate", RPCBackpaginate{ TestName: t.Name(), RoomID: roomID, Count: count, }, &void) - if err != nil { - t.Fatalf("RPCClient.MustBackpaginate: %s", err) - } + return err } -// MustGetEvent will return the client's view of this event, or fail the test if the event cannot be found. -func (c *RPCClient) MustGetEvent(t ct.TestLike, roomID, eventID string) api.Event { +// GetEvent will return the client's view of this event, or return an error if the event cannot be found. +func (c *RPCClient) GetEvent(t ct.TestLike, roomID, eventID string) (*api.Event, error) { var ev api.Event - err := c.client.Call("Server.MustGetEvent", RPCGetEvent{ + err := c.client.Call("Server.GetEvent", RPCGetEvent{ TestName: t.Name(), RoomID: roomID, EventID: eventID, }, &ev) - if err != nil { - t.Fatalf("RPCClient.MustGetEvent: %s", err) - } - return ev + return &ev, err } -// MustBackupKeys will backup E2EE keys, else fail the test. -func (c *RPCClient) MustBackupKeys(t ct.TestLike) (recoveryKey string) { - err := c.client.Call("Server.MustBackupKeys", 0, &recoveryKey) - if err != nil { - t.Fatalf("RPCClient.MustBackupKeys: %v", err) - } +// BackupKeys will backup E2EE keys, else return an error. +func (c *RPCClient) BackupKeys(t ct.TestLike) (recoveryKey string, err error) { + err = c.client.Call("Server.BackupKeys", 0, &recoveryKey) return } -// MustLoadBackup will recover E2EE keys from the latest backup, else fail the test. -func (c *RPCClient) MustLoadBackup(t ct.TestLike, recoveryKey string) { - var void int - err := c.client.Call("Server.MustLoadBackup", recoveryKey, &void) - if err != nil { - t.Fatalf("RPCClient.MustLoadBackup: %v", err) - } -} - // LoadBackup will recover E2EE keys from the latest backup, else return an error. func (c *RPCClient) LoadBackup(t ct.TestLike, recoveryKey string) error { var void int diff --git a/internal/deploy/rpc/server.go b/internal/deploy/rpc/server.go index 0e363d3..cc85e0c 100644 --- a/internal/deploy/rpc/server.go +++ b/internal/deploy/rpc/server.go @@ -145,15 +145,9 @@ type RPCSendMessage struct { } func (s *Server) SendMessage(msg RPCSendMessage, eventID *string) error { - defer s.keepAlive() - *eventID = s.activeClient.SendMessage(&api.MockT{TestName: msg.TestName}, msg.RoomID, msg.Text) - return nil -} - -func (s *Server) TrySendMessage(msg RPCSendMessage, eventID *string) error { defer s.keepAlive() var err error - *eventID, err = s.activeClient.TrySendMessage(&api.MockT{TestName: msg.TestName}, msg.RoomID, msg.Text) + *eventID, err = s.activeClient.SendMessage(&api.MockT{TestName: msg.TestName}, msg.RoomID, msg.Text) if err != nil { return err } @@ -228,10 +222,8 @@ func (s *Server) WaiterStart(input RPCWait, void *int) error { func (s *Server) WaiterPoll(waiterID int, eventsToCheck *[]api.Event) error { defer s.keepAlive() - fmt.Println("Acquiring lock") s.waitersMu.Lock() defer s.waitersMu.Unlock() - fmt.Println("Acquired!") w := s.waiters[waiterID] if w == nil { return fmt.Errorf("unknown waiter id %d", waiterID) @@ -255,10 +247,9 @@ type RPCBackpaginate struct { Count int } -func (s *Server) MustBackpaginate(input RPCBackpaginate, void *int) error { +func (s *Server) Backpaginate(input RPCBackpaginate, void *int) error { defer s.keepAlive() - s.activeClient.MustBackpaginate(&api.MockT{TestName: input.TestName}, input.RoomID, input.Count) - return nil + return s.activeClient.Backpaginate(&api.MockT{TestName: input.TestName}, input.RoomID, input.Count) } type RPCGetEvent struct { @@ -267,18 +258,23 @@ type RPCGetEvent struct { EventID string } -// MustGetEvent will return the client's view of this event, or fail the test if the event cannot be found. -func (s *Server) MustGetEvent(input RPCGetEvent, output *api.Event) error { +// GetEvent will return the client's view of this event, or returns an error if the event cannot be found. +func (s *Server) GetEvent(input RPCGetEvent, output *api.Event) error { defer s.keepAlive() - *output = s.activeClient.MustGetEvent(&api.MockT{TestName: input.TestName}, input.RoomID, input.EventID) + ev, err := s.activeClient.GetEvent(&api.MockT{TestName: input.TestName}, input.RoomID, input.EventID) + if err != nil { + return err + } + *output = *ev return nil } -// MustBackupKeys will backup E2EE keys, else fail the test. -func (s *Server) MustBackupKeys(testName string, recoveryKey *string) error { +// BackupKeys will backup E2EE keys, else fail the test. +func (s *Server) BackupKeys(testName string, recoveryKey *string) error { defer s.keepAlive() - *recoveryKey = s.activeClient.MustBackupKeys(&api.MockT{TestName: testName}) - return nil + var err error + *recoveryKey, err = s.activeClient.BackupKeys(&api.MockT{TestName: testName}) + return err } type RPCGetNotification struct { @@ -296,13 +292,6 @@ func (s *Server) GetNotification(input RPCGetNotification, output *api.Notificat return err } -// MustLoadBackup will recover E2EE keys from the latest backup, else fail the test. -func (s *Server) MustLoadBackup(recoveryKey string, void *int) error { - defer s.keepAlive() - s.activeClient.MustLoadBackup(&api.MockT{}, recoveryKey) - return nil -} - func (s *Server) LoadBackup(recoveryKey string, void *int) error { defer s.keepAlive() return s.activeClient.LoadBackup(&api.MockT{}, recoveryKey) diff --git a/internal/tests/client_test.go b/internal/tests/client_test.go index c000301..9441633 100644 --- a/internal/tests/client_test.go +++ b/internal/tests/client_test.go @@ -201,18 +201,18 @@ func TestSendingEvents(t *testing.T) { roomID := csapi.MustCreateRoom(t, map[string]interface{}{}) stopSyncing := client.MustStartSyncing(t) defer stopSyncing() - eventID := client.SendMessage(t, roomID, "Test Message") + eventID := client.MustSendMessage(t, roomID, "Test Message") event := client.MustGetEvent(t, roomID, eventID) must.Equal(t, event.Text, "Test Message", "event text mismatch") - eventID2, err := client.TrySendMessage(t, roomID, "Another Test Message") - must.NotError(t, "TrySendMessage failed", err) + eventID2, err := client.SendMessage(t, roomID, "Another Test Message") + must.NotError(t, "SendMessage failed", err) event2 := client.MustGetEvent(t, roomID, eventID2) must.Equal(t, event2.Text, "Another Test Message", "event text mismatch") // sending to a bogus room should error but not fail the test - invalidEventID, err := client.TrySendMessage(t, "!foo:hs1", "This should not work") - t.Logf("TrySendMessage -> %v", err) - must.NotEqual(t, err, nil, "TrySendMessage returned no error when it should have") - must.Equal(t, invalidEventID, "", "TrySendMessage returned an event ID when it should have returned an error") + invalidEventID, err := client.SendMessage(t, "!foo:hs1", "This should not work") + t.Logf("SendMessage -> %v", err) + must.NotEqual(t, err, nil, "SendMessage returned no error when it should have") + must.Equal(t, invalidEventID, "", "SendMessage returned an event ID when it should have returned an error") }) } diff --git a/tests/delayed_requests_test.go b/tests/delayed_requests_test.go index 4720084..167cb4a 100644 --- a/tests/delayed_requests_test.go +++ b/tests/delayed_requests_test.go @@ -36,7 +36,7 @@ func TestDelayedInviteResponse(t *testing.T) { tc.WithAliceAndBobSyncing(t, func(alice, bob api.TestClient) { // we send a message first so clients which lazily call /members can do so now. // if we don't do this, the client won't rely on /sync for the member list so won't fail. - alice.SendMessage(t, roomID, "dummy message to make /members call") + alice.MustSendMessage(t, roomID, "dummy message to make /members call") config := tc.Deployment.MITM().Configure(t) serverHasInvite := helpers.NewWaiter() @@ -67,7 +67,7 @@ func TestDelayedInviteResponse(t *testing.T) { // once the server got the invite, send a message serverHasInvite.Waitf(t, 3*time.Second, "did not intercept invite") t.Logf("intercepted invite; sending message") - eventID := alice.SendMessage(t, roomID, "hello world!") + eventID := alice.MustSendMessage(t, roomID, "hello world!") // bob joins, ensure he can decrypt the message. tc.Bob.JoinRoom(t, roomID, []string{clientType.HS}) diff --git a/tests/device_keys_test.go b/tests/device_keys_test.go index 9ada72a..e8d3717 100644 --- a/tests/device_keys_test.go +++ b/tests/device_keys_test.go @@ -43,7 +43,7 @@ func TestFailedDeviceKeyDownloadRetries(t *testing.T) { tc.WithAliceAndBobSyncing(t, func(alice, bob api.TestClient) { // When Alice sends a message - alice.SendMessage(t, roomID, "checking whether we can send a message") + alice.MustSendMessage(t, roomID, "checking whether we can send a message") // Then Bob should receive it bob.WaitUntilEventInRoom( diff --git a/tests/federation_connectivity_test.go b/tests/federation_connectivity_test.go index e72958e..d961fda 100644 --- a/tests/federation_connectivity_test.go +++ b/tests/federation_connectivity_test.go @@ -39,7 +39,7 @@ func TestNewUserCannotGetKeysForOfflineServer(t *testing.T) { // ensure encrypted messaging works wantMsgBody := "Hello world" waiter := bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - evID := alice.SendMessage(t, roomID, wantMsgBody) + evID := alice.MustSendMessage(t, roomID, wantMsgBody) t.Logf("bob (%s) waiting for event %s", bob.Type(), evID) waiter.Waitf(t, 5*time.Second, "bob did not see alice's message '%s'", wantMsgBody) @@ -59,7 +59,7 @@ func TestNewUserCannotGetKeysForOfflineServer(t *testing.T) { // send a message: bob won't be able to decrypt this, but alice will. wantUndecryptableMsgBody := "Bob can't see this because his server is down" waiter = alice.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantUndecryptableMsgBody)) - undecryptableEventID := charlie.SendMessage(t, roomID, wantUndecryptableMsgBody) + undecryptableEventID := charlie.MustSendMessage(t, roomID, wantUndecryptableMsgBody) t.Logf("alice (%s) waiting for event %s", alice.Type(), undecryptableEventID) waiter.Waitf(t, 5*time.Second, "alice did not see charlie's messages '%s'", wantUndecryptableMsgBody) @@ -77,7 +77,7 @@ func TestNewUserCannotGetKeysForOfflineServer(t *testing.T) { // send another message, bob should be able to decrypt it. wantMsgBody = "Bob can see this because his server is now back online" waiter = bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - evID = charlie.SendMessage(t, roomID, wantMsgBody) + evID = charlie.MustSendMessage(t, roomID, wantMsgBody) t.Logf("bob (%s) waiting for event %s", bob.Type(), evID) waiter.Waitf(t, 7*time.Second, "bob did not see charlie's message '%s'", wantMsgBody) @@ -123,11 +123,11 @@ func TestExistingSessionCannotGetKeysForOfflineServer(t *testing.T) { // ensure encrypted messaging works in rooms ab,bc wantMsgBody := "Hello world" waiter := bob.WaitUntilEventInRoom(t, roomIDab, api.CheckEventHasBody(wantMsgBody)) - evID := alice.SendMessage(t, roomIDab, wantMsgBody) + evID := alice.MustSendMessage(t, roomIDab, wantMsgBody) t.Logf("bob (%s) waiting for event %s", bob.Type(), evID) waiter.Waitf(t, 5*time.Second, "bob did not see alice's message: '%s'", wantMsgBody) waiter = bob.WaitUntilEventInRoom(t, roomIDbc, api.CheckEventHasBody(wantMsgBody)) - evID = charlie.SendMessage(t, roomIDbc, wantMsgBody) + evID = charlie.MustSendMessage(t, roomIDbc, wantMsgBody) t.Logf("bob (%s) waiting for event %s", bob.Type(), evID) waiter.Waitf(t, 5*time.Second, "bob did not see charlie's message: '%s'", wantMsgBody) @@ -145,7 +145,7 @@ func TestExistingSessionCannotGetKeysForOfflineServer(t *testing.T) { // are per-device, not per-room. wantDecryptableMsgBody := "Bob can see this even though his server is down as we had a session already" waiter = alice.WaitUntilEventInRoom(t, roomIDab, api.CheckEventHasBody(wantDecryptableMsgBody)) - decryptableEventID := charlie.SendMessage(t, roomIDab, wantDecryptableMsgBody) + decryptableEventID := charlie.MustSendMessage(t, roomIDab, wantDecryptableMsgBody) t.Logf("alice (%s) waiting for event %s", alice.Type(), decryptableEventID) waiter.Waitf(t, 5*time.Second, "alice did not see charlie's message: '%s'", wantDecryptableMsgBody) diff --git a/tests/key_backup_test.go b/tests/key_backup_test.go index 62c9c43..fce2bad 100644 --- a/tests/key_backup_test.go +++ b/tests/key_backup_test.go @@ -39,7 +39,7 @@ func TestCanBackupKeys(t *testing.T) { tc.WithAliceSyncing(t, func(backupCreator api.TestClient) { body := "An encrypted message" waiter := backupCreator.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(body)) - evID := backupCreator.SendMessage(t, roomID, body) + evID := backupCreator.MustSendMessage(t, roomID, body) t.Logf("backupCreator (%s) waiting for event %s", backupCreator.Type(), evID) waiter.Waitf(t, 5*time.Second, "backup creator did not see own message %s", evID) @@ -101,7 +101,7 @@ func TestBackupWrongRecoveryKeyFails(t *testing.T) { tc.WithAliceSyncing(t, func(backupCreator api.TestClient) { body := "An encrypted message" waiter := backupCreator.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(body)) - evID := backupCreator.SendMessage(t, roomID, body) + evID := backupCreator.MustSendMessage(t, roomID, body) t.Logf("backupCreator (%s) waiting for event %s", backupCreator.Type(), evID) waiter.Waitf(t, 5*time.Second, "backup creator did not see own message %s", evID) diff --git a/tests/membership_acls_test.go b/tests/membership_acls_test.go index a7dd54c..8d39edd 100644 --- a/tests/membership_acls_test.go +++ b/tests/membership_acls_test.go @@ -48,7 +48,7 @@ func TestAliceBobEncryptionWorks(t *testing.T) { t.Logf("bob room encrypted = %v", isEncrypted) waiter := bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - evID := alice.SendMessage(t, roomID, wantMsgBody) + evID := alice.MustSendMessage(t, roomID, wantMsgBody) // Bob receives the message t.Logf("bob (%s) waiting for event %s", bob.Type(), evID) @@ -84,7 +84,7 @@ func TestCanDecryptMessagesAfterInviteButBeforeJoin(t *testing.T) { must.Equal(t, isEncrypted, true, "room is not encrypted when it should be") // Alice sends the message whilst Bob is still invited. - alice.SendMessage(t, roomID, wantMsgBody) + alice.MustSendMessage(t, roomID, wantMsgBody) // Bob joins the room (via Complement, but it shouldn't matter) tc.Bob.MustJoinRoom(t, roomID, []string{clientTypeA.HS}) @@ -98,7 +98,7 @@ func TestCanDecryptMessagesAfterInviteButBeforeJoin(t *testing.T) { // This also checks that subsequent messages are decryptable. sentinelBody := "Sentinel" waiter := bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(sentinelBody)) - alice.SendMessage(t, roomID, sentinelBody) + alice.MustSendMessage(t, roomID, sentinelBody) waiter.Waitf(t, 5*time.Second, "bob did not see alice's message") // Explicitly ask for a pagination, rather than assuming the SDK will return events @@ -126,7 +126,7 @@ func TestBobCanSeeButNotDecryptHistoryInPublicRoom(t *testing.T) { // Alice sends a message which Bob should not be able to decrypt beforeJoinBody := "Before Bob joins" waiter := alice.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(beforeJoinBody)) - evID := alice.SendMessage(t, roomID, beforeJoinBody) + evID := alice.MustSendMessage(t, roomID, beforeJoinBody) t.Logf("alice (%s) waiting for event %s", alice.Type(), evID) waiter.Waitf(t, 5*time.Second, "alice did not see own message") @@ -167,7 +167,7 @@ func TestOnRejoinBobCanSeeButNotDecryptHistoryInPublicRoom(t *testing.T) { // Alice sends a message which Bob should be able to decrypt. bothJoinedBody := "Alice and Bob in a room" waiter := bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(bothJoinedBody)) - evID := alice.SendMessage(t, roomID, bothJoinedBody) + evID := alice.MustSendMessage(t, roomID, bothJoinedBody) t.Logf("bob (%s) waiting for event %s", bob.Type(), evID) waiter.Waitf(t, 5*time.Second, "bob did not see alice's message") @@ -179,7 +179,7 @@ func TestOnRejoinBobCanSeeButNotDecryptHistoryInPublicRoom(t *testing.T) { // now alice sends another message, which should use a key that bob does not have. Wait for the remote echo to come back. onlyAliceBody := "Only me on my lonesome" waiter = alice.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(onlyAliceBody)) - evID = alice.SendMessage(t, roomID, onlyAliceBody) + evID = alice.MustSendMessage(t, roomID, onlyAliceBody) t.Logf("alice (%s) waiting for event %s", alice.Type(), evID) waiter.Waitf(t, 5*time.Second, "alice did not see own message") @@ -201,7 +201,7 @@ func TestOnRejoinBobCanSeeButNotDecryptHistoryInPublicRoom(t *testing.T) { time.Sleep(time.Second) // let alice realise bob is back in the room // bob should be able to decrypt subsequent messages bothJoinedBody = "Alice and Bob in a room again" - evID = alice.SendMessage(t, roomID, bothJoinedBody) + evID = alice.MustSendMessage(t, roomID, bothJoinedBody) time.Sleep(time.Second) // TODO: use a Waiter; currently this is broken as it seems like listeners get detached on leave? ev = bob.MustGetEvent(t, roomID, evID) must.Equal(t, ev.Text, bothJoinedBody, "event was not decrypted correctly") */ @@ -226,7 +226,7 @@ func TestOnNewDeviceBobCanSeeButNotDecryptHistoryInPublicRoom(t *testing.T) { // Alice sends a message which Bob should be able to decrypt. onlyFirstDeviceBody := "Alice and Bob in a room" waiter := bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(onlyFirstDeviceBody)) - evID := alice.SendMessage(t, roomID, onlyFirstDeviceBody) + evID := alice.MustSendMessage(t, roomID, onlyFirstDeviceBody) t.Logf("bob (%s) waiting for event %s", bob.Type(), evID) waiter.Waitf(t, 5*time.Second, "bob did not see alice's message") @@ -244,7 +244,7 @@ func TestOnNewDeviceBobCanSeeButNotDecryptHistoryInPublicRoom(t *testing.T) { // now alice sends another message, which bob's new device should be able to decrypt. decryptableBody := "Bob's new device can decrypt this" waiter = bob2.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(decryptableBody)) - evID = alice.SendMessage(t, roomID, decryptableBody) + evID = alice.MustSendMessage(t, roomID, decryptableBody) t.Logf("bob2 (%s) waiting for event %s", bob2.Type(), evID) waiter.Waitf(t, 5*time.Second, "bob2 did not see alice's message") }) @@ -258,7 +258,7 @@ func TestOnNewDeviceBobCanSeeButNotDecryptHistoryInPublicRoom(t *testing.T) { // by bob's other logged in device though. undecryptableBody := "Bob's logged out device won't be able to decrypt this" waiter = bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(undecryptableBody)) - evID = alice.SendMessage(t, roomID, undecryptableBody) + evID = alice.MustSendMessage(t, roomID, undecryptableBody) t.Logf("bob (%s) waiting for event %s", bob.Type(), evID) waiter.Waitf(t, 5*time.Second, "bob did not see alice's event %s", evID) @@ -287,7 +287,7 @@ func TestChangingDeviceAfterInviteReEncrypts(t *testing.T) { tc.Alice.MustInviteRoom(t, roomID, tc.Bob.UserID) time.Sleep(time.Second) // let device keys propagate body := "Alice should re-encrypt this message for bob's new device" - evID := alice.SendMessage(t, roomID, body) + evID := alice.MustSendMessage(t, roomID, body) // now Bob logs in on a different device and accepts the invite. The different device should be able to decrypt the message. csapiBob2 := tc.MustRegisterNewDevice(t, tc.Bob, "NEW_DEVICE") diff --git a/tests/one_time_keys_test.go b/tests/one_time_keys_test.go index 6bac656..e51c919 100644 --- a/tests/one_time_keys_test.go +++ b/tests/one_time_keys_test.go @@ -136,8 +136,8 @@ func TestFallbackKeyIsUsedIfOneTimeKeysRunOut(t *testing.T) { charlie.WaitUntilEventInRoom(t, roomID, api.CheckEventHasMembership(alice.UserID(), "join")).Waitf(t, 5*time.Second, "charlie did not see alice's join") bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasMembership(alice.UserID(), "join")).Waitf(t, 5*time.Second, "bob did not see alice's join") alice.WaitUntilEventInRoom(t, roomID, api.CheckEventHasMembership(alice.UserID(), "join")).Waitf(t, 5*time.Second, "alice did not see own join") - bob.SendMessage(t, roomID, "Hello world!") - charlie.SendMessage(t, roomID, "Goodbye world!") + bob.MustSendMessage(t, roomID, "Hello world!") + charlie.MustSendMessage(t, roomID, "Goodbye world!") waiter = alice.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody("Hello world!")) // ensure that /keys/upload is actually blocked (OTK count should be 0) res, _ := tc.Alice.MustSync(t, client.SyncReq{}) @@ -239,7 +239,7 @@ func TestFailedKeysClaimRetries(t *testing.T) { // JS SDK won't retry the /keys/claim automatically. Try sending another event to kick it. counter := 0 for !stopPoking.Load() && counter < 10 { - bob.TrySendMessage(t, roomID, "poke msg") + bob.SendMessage(t, roomID, "poke msg") counter++ time.Sleep(100 * time.Millisecond * time.Duration(counter+1)) } diff --git a/tests/room_keys_test.go b/tests/room_keys_test.go index baa5f80..7e39c68 100644 --- a/tests/room_keys_test.go +++ b/tests/room_keys_test.go @@ -64,7 +64,7 @@ func TestRoomKeyIsCycledOnDeviceLogout(t *testing.T) { wantMsgBody := "Test Message" waiter := bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) waiter2 := alice2.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - alice.SendMessage(t, roomID, wantMsgBody) + alice.MustSendMessage(t, roomID, wantMsgBody) waiter.Waitf(t, 5*time.Second, "bob did not see alice's message") waiter2.Waitf(t, 5*time.Second, "alice2 did not see alice's message") alice2StopSyncing() @@ -82,7 +82,7 @@ func TestRoomKeyIsCycledOnDeviceLogout(t *testing.T) { // now send another message from Alice, who should negotiate a new room key wantMsgBody = "Another Test Message" waiter = bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - alice.SendMessage(t, roomID, wantMsgBody) + alice.MustSendMessage(t, roomID, wantMsgBody) waiter.Waitf(t, 5*time.Second, "bob did not see alice's new message") // we should have seen a /sendToDevice call by now. If we didn't, this implies we didn't cycle @@ -122,7 +122,7 @@ func TestRoomKeyIsCycledAfterEnoughMessages(t *testing.T) { for i := 0; i < 4; i++ { wantMsgBody := fmt.Sprintf("Before we hit the threshold %d", i) waiter := bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - alice.SendMessage(t, roomID, wantMsgBody) + alice.MustSendMessage(t, roomID, wantMsgBody) waiter.Waitf(t, 5*time.Second, "bob did not see alice's message '%s'", wantMsgBody) } @@ -138,12 +138,12 @@ func TestRoomKeyIsCycledAfterEnoughMessages(t *testing.T) { // of these approaches will pass the test. wantMsgBody := "This one hits the threshold" waiter := bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - alice.SendMessage(t, roomID, wantMsgBody) + alice.MustSendMessage(t, roomID, wantMsgBody) waiter.Waitf(t, 5*time.Second, "bob did not see alice's message '%s'", wantMsgBody) wantMsgBody = "After the threshold" waiter = bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - alice.SendMessage(t, roomID, wantMsgBody) + alice.MustSendMessage(t, roomID, wantMsgBody) waiter.Waitf(t, 5*time.Second, "bob did not see alice's message '%s'", wantMsgBody) // Then we did send out new keys @@ -196,7 +196,7 @@ func TestRoomKeyIsCycledAfterEnoughTime(t *testing.T) { // don't get a false positive. wantMsgBody := "Before we start" waiter := bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - alice.SendMessage(t, roomID, wantMsgBody) + alice.MustSendMessage(t, roomID, wantMsgBody) waiter.Waitf(t, 5*time.Second, "Did not see 'before we start' event in the room") // Sniff calls to /sendToDevice to ensure we see the new room key being sent. @@ -204,7 +204,7 @@ func TestRoomKeyIsCycledAfterEnoughTime(t *testing.T) { // Send a message to ensure the room is working, and any timer is set up wantMsgBody := "Before the time expires" waiter := bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - alice.SendMessage(t, roomID, wantMsgBody) + alice.MustSendMessage(t, roomID, wantMsgBody) waiter.Waitf(t, 5*time.Second, "Did not see 'before the time expires' event in the room") // When we wait 1+period seconds @@ -213,7 +213,7 @@ func TestRoomKeyIsCycledAfterEnoughTime(t *testing.T) { // And send another message wantMsgBody = "After the time expires" waiter = bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - alice.SendMessage(t, roomID, wantMsgBody) + alice.MustSendMessage(t, roomID, wantMsgBody) waiter.Waitf(t, 5*time.Second, "Did not see 'after the time expires' event in the room") pc.Recv(t, "did not see /sendToDevice after waiting rotation_period_ms milliseconds") @@ -242,7 +242,7 @@ func TestRoomKeyIsCycledOnMemberLeaving(t *testing.T) { wantMsgBody := "Test Message" waiter := bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) waiter2 := charlie.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - alice.SendMessage(t, roomID, wantMsgBody) + alice.MustSendMessage(t, roomID, wantMsgBody) waiter.Waitf(t, 5*time.Second, "bob did not see alice's message") waiter2.Waitf(t, 5*time.Second, "charlie did not see alice's message") @@ -258,7 +258,7 @@ func TestRoomKeyIsCycledOnMemberLeaving(t *testing.T) { // now send another message from Alice, who should negotiate a new room key wantMsgBody = "Another Test Message" waiter = bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - alice.SendMessage(t, roomID, wantMsgBody) + alice.MustSendMessage(t, roomID, wantMsgBody) waiter.Waitf(t, 5*time.Second, "bob did not see alice's message") // we should have seen a /sendToDevice call by now. If we didn't, this implies we didn't cycle @@ -285,7 +285,7 @@ func TestRoomKeyIsNotCycled(t *testing.T) { // check the room works wantMsgBody := "Test Message" waiter := bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - alice.SendMessage(t, roomID, wantMsgBody) + alice.MustSendMessage(t, roomID, wantMsgBody) waiter.Waitf(t, 5*time.Second, "bob did not see alice's message") t.Run("on display name change", func(t *testing.T) { // we don't know when the new room key will be sent, it could be sent as soon as the device list update @@ -304,7 +304,7 @@ func TestRoomKeyIsNotCycled(t *testing.T) { // now send another message from Alice, who should negotiate a new room key wantMsgBody = "Another Test Message" waiter = bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - alice.SendMessage(t, roomID, wantMsgBody) + alice.MustSendMessage(t, roomID, wantMsgBody) waiter.Waitf(t, 5*time.Second, "bob did not see alice's message") got := pc.TryRecv(t) @@ -338,7 +338,7 @@ func TestRoomKeyIsNotCycled(t *testing.T) { // now send another message from Alice, who should negotiate a new room key wantMsgBody = "Yet Another Test Message" waiter = bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - alice.SendMessage(t, roomID, wantMsgBody) + alice.MustSendMessage(t, roomID, wantMsgBody) waiter.Waitf(t, 5*time.Second, "bob did not see alice's message") // we should have seen a /sendToDevice call by now. If we didn't, this implies we didn't cycle @@ -417,7 +417,7 @@ func testRoomKeyIsNotCycledOnClientRestartRust(t *testing.T, clientType api.Clie }, Multiprocess: true, }, func(remoteAlice api.TestClient) { - eventID := remoteAlice.SendMessage(t, roomID, wantMsgBody) + eventID := remoteAlice.MustSendMessage(t, roomID, wantMsgBody) waiter := remoteAlice.WaitUntilEventInRoom(t, roomID, api.CheckEventHasEventID(eventID)) waiter.Waitf(t, 5*time.Second, "client did not see event %s", eventID) }) @@ -446,7 +446,7 @@ func testRoomKeyIsNotCycledOnClientRestartRust(t *testing.T, clientType api.Clie // now send another message from Alice, who should NOT negotiate a new room key wantMsgBody = "Another Test Message" waiter = bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - alice.SendMessage(t, roomID, wantMsgBody) + alice.MustSendMessage(t, roomID, wantMsgBody) waiter.Waitf(t, 5*time.Second, "bob did not see alice's message") // we should have seen a /sendToDevice call by now. If we didn't, this implies we didn't cycle @@ -484,7 +484,7 @@ func testRoomKeyIsNotCycledOnClientRestartJS(t *testing.T, clientType api.Client // check the room works wantMsgBody := "Test Message" waiter := bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - alice.SendMessage(t, roomID, wantMsgBody) + alice.MustSendMessage(t, roomID, wantMsgBody) waiter.Waitf(t, 5*time.Second, "bob did not see alice's message") // we're going to sniff calls to /sendToDevice to ensure we do NOT see a new room key being sent. @@ -500,7 +500,7 @@ func testRoomKeyIsNotCycledOnClientRestartJS(t *testing.T, clientType api.Client // now send another message from Alice, who should NOT send another new room key wantMsgBody = "Another Test Message" waiter = bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsgBody)) - alice.SendMessage(t, roomID, wantMsgBody) + alice.MustSendMessage(t, roomID, wantMsgBody) waiter.Waitf(t, 5*time.Second, "bob did not see alice's message") }) diff --git a/tests/rust/notification_test.go b/tests/rust/notification_test.go index 47bf815..57dc33c 100644 --- a/tests/rust/notification_test.go +++ b/tests/rust/notification_test.go @@ -70,7 +70,7 @@ func testNSEReceive(t *testing.T, numMsgsBefore, numMsgsAfter int) { alice.Logf(t, "syncing and sending dummy message to ensure e2ee keys are uploaded") stopSyncing := alice.MustStartSyncing(t) alice.WaitUntilEventInRoom(t, roomID, api.CheckEventHasMembership(tc.Bob.UserID, "join")).Waitf(t, 5*time.Second, "did not see bob's join") - alice.SendMessage(t, roomID, "test message to ensure E2EE keys are uploaded") + alice.MustSendMessage(t, roomID, "test message to ensure E2EE keys are uploaded") accessToken := alice.Opts().AccessToken // app is "backgrounded" so we tidy things up @@ -122,14 +122,14 @@ func TestNSEReceiveForNonPreKeyMessage(t *testing.T) { // let bob realise alice exists and claims keys time.Sleep(time.Second) // Send a message as Bob, this will contain ensure an Olm session is set up already before we do NSE work - bob.SendMessage(t, roomID, "initial message") + bob.MustSendMessage(t, roomID, "initial message") alice.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody("initial message")).Waitf(t, 5*time.Second, "alice did not see bob's initial message") // Alice goes into the background accessToken := alice.Opts().AccessToken stopSyncing() alice.Close(t) // Bob sends another message which the NSE process will get - eventID := bob.SendMessage(t, roomID, "for nse") + eventID := bob.MustSendMessage(t, roomID, "for nse") bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasEventID(eventID)).Waitf(t, 5*time.Second, "bob did not see his own message") // now make the "NSE" process and get bob's message client := tc.MustCreateClient(t, &cc.ClientCreationRequest{ @@ -180,7 +180,7 @@ func TestMultiprocessNSE(t *testing.T) { time.Sleep(time.Second) for i := 0; i < numPreBackgroundMsgs; i++ { msg := fmt.Sprintf("numPreBackgroundMsgs %d", i) - bob.SendMessage(t, roomID, msg) + bob.MustSendMessage(t, roomID, msg) alice.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(msg)).Waitf(t, 5*time.Second, "alice did not see '%s'", msg) } @@ -251,7 +251,7 @@ func TestMultiprocessNSE(t *testing.T) { nseAlice.Close(t) } msg := fmt.Sprintf("numPostNSEMsgs %d", i) - eventID := bob.SendMessage(t, roomID, msg) + eventID := bob.MustSendMessage(t, roomID, msg) eventTimeline = append(eventTimeline, eventID) t.Logf("event %s => '%s'", eventID, msg) if restartNSE { // a new NSE process is created as a result of bob's message @@ -277,7 +277,7 @@ func TestMultiprocessNSE(t *testing.T) { startAliceSyncing() } if aliceSendsMsg { // this will cause the main app to update the crypto store - sentEventID := alice.SendMessage(t, roomID, "dummy") + sentEventID := alice.MustSendMessage(t, roomID, "dummy") eventTimeline = append(eventTimeline, sentEventID) } if !nseOpensFirst { @@ -384,7 +384,7 @@ func TestMultiprocessNSEBackupKeyMacError(t *testing.T) { }) // this should login already as we provided an access token msg := "first message" - eventID := bob.SendMessage(t, roomID, msg) + eventID := bob.MustSendMessage(t, roomID, msg) eventTimeline = append(eventTimeline, eventID) t.Logf("first event %s => '%s'", eventID, msg) checkNSECanDecryptEvent(nseAlice, roomID, eventID, msg) @@ -395,7 +395,7 @@ func TestMultiprocessNSEBackupKeyMacError(t *testing.T) { // send final message msg = "final message" - eventID = bob.SendMessage(t, roomID, msg) + eventID = bob.MustSendMessage(t, roomID, msg) eventTimeline = append(eventTimeline, eventID) t.Logf("final event %s => '%s'", eventID, msg) @@ -456,7 +456,7 @@ func TestMultiprocessNSEOlmSessionWedge(t *testing.T) { // let bob realise alice exists and claims keys time.Sleep(time.Second) msg := "pre message" - bob.SendMessage(t, roomID, msg) + bob.MustSendMessage(t, roomID, msg) alice.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(msg)).Waitf(t, 5*time.Second, "alice did not see '%s'", msg) stopAliceSyncing := func() { @@ -510,7 +510,7 @@ func TestMultiprocessNSEOlmSessionWedge(t *testing.T) { stopAliceSyncing() msg = fmt.Sprintf("test message %d", 1) - eventID := bob.SendMessage(t, roomID, msg) + eventID := bob.MustSendMessage(t, roomID, msg) t.Logf("event %s => '%s'", eventID, msg) // both the nse process and the app process should be able to decrypt the event. @@ -519,12 +519,12 @@ func TestMultiprocessNSEOlmSessionWedge(t *testing.T) { t.Logf("restarting alice") nseAlice.Logf(t, "post checkNSECanDecryptEvent") startAliceSyncing() - alice.SendMessage(t, roomID, "dummy") + alice.MustSendMessage(t, roomID, "dummy") // iteration 2 stopAliceSyncing() msg = fmt.Sprintf("test message %d", 2) - eventID = bob.SendMessage(t, roomID, msg) + eventID = bob.MustSendMessage(t, roomID, msg) t.Logf("event %s => '%s'", eventID, msg) // both the nse process and the app process should be able to decrypt the event. @@ -532,7 +532,7 @@ func TestMultiprocessNSEOlmSessionWedge(t *testing.T) { checkNSECanDecryptEvent(nseAlice, roomID, eventID, msg) t.Logf("restarting alice") startAliceSyncing() - alice.SendMessage(t, roomID, "dummy") + alice.MustSendMessage(t, roomID, "dummy") nseAlice.Close(t) stopAliceSyncing() @@ -600,7 +600,7 @@ func TestNotificationClientDupeOTKUpload(t *testing.T) { tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: tc.Bob, }, func(bob api.TestClient) { - eventID := bob.SendMessage(t, roomID, "Hello world!") + eventID := bob.MustSendMessage(t, roomID, "Hello world!") // create a NotificationClient in the same process to fetch this "push notification". // It might make the NotificationClient upload a OTK as it would have seen 1 has been used. // The NotificationClient and main Client must talk to each other to ensure they use the same key. @@ -651,7 +651,7 @@ func TestMultiprocessInitialE2EESyncDoesntDropDeviceListUpdates(t *testing.T) { }, func(alice api.TestClient) { // ensure bob has queried keys from alice by sending a message. msg := "pre message" - bob.SendMessage(t, roomID, msg) + bob.MustSendMessage(t, roomID, msg) alice.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(msg)).Waitf(t, 5*time.Second, "alice did not see '%s'", msg) stopBobSyncing := func() { @@ -704,7 +704,7 @@ func TestMultiprocessInitialE2EESyncDoesntDropDeviceListUpdates(t *testing.T) { // wait for device keys to sync up time.Sleep(time.Second) // alice[1] sends a message, this is unimportant other than to grab the event ID for the push process - pushEventID := alice.SendMessage(t, roomID, "pre message 2") + pushEventID := alice.MustSendMessage(t, roomID, "pre message 2") // Bob's push process receives Alice[1]'s message. // This /should/ make Bob aware of Alice[2]. notif, err := nseBob.GetNotification(t, roomID, pushEventID) @@ -718,7 +718,7 @@ func TestMultiprocessInitialE2EESyncDoesntDropDeviceListUpdates(t *testing.T) { time.Sleep(time.Second) // Bob sends a message. wantMsg := "can alice's new device decrypt this?" - bob.SendMessage(t, roomID, wantMsg) + bob.MustSendMessage(t, roomID, wantMsg) alice2.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(wantMsg)).Waitf(t, 5*time.Second, "alice[2] did not see '%s'", wantMsg) }) }) @@ -752,13 +752,13 @@ func bobSendsMessage(t *testing.T, tc *cc.TestContext, roomID, text string, msgs User: tc.Bob, }, func(bob api.TestClient) { for i := 0; i < msgsBefore; i++ { - bob.SendMessage(t, roomID, fmt.Sprintf("msg before %d", i)) + bob.MustSendMessage(t, roomID, fmt.Sprintf("msg before %d", i)) } bob.Logf(t, "sending push notification message as bob") - pushNotifEventID = bob.SendMessage(t, roomID, text) + pushNotifEventID = bob.MustSendMessage(t, roomID, text) bob.Logf(t, "sent push notification message as bob => %s", pushNotifEventID) for i := 0; i < msgsAfter; i++ { - bob.SendMessage(t, roomID, fmt.Sprintf("msg after %d", i)) + bob.MustSendMessage(t, roomID, fmt.Sprintf("msg after %d", i)) } }) return pushNotifEventID diff --git a/tests/to_device_test.go b/tests/to_device_test.go index 56a852d..bb9cff6 100644 --- a/tests/to_device_test.go +++ b/tests/to_device_test.go @@ -38,18 +38,18 @@ func TestClientRetriesSendToDevice(t *testing.T) { }, ResponseCallback: callback.SendError(0, http.StatusGatewayTimeout), }, func() { - evID, err = alice.TrySendMessage(t, roomID, wantMsgBody) + evID, err = alice.SendMessage(t, roomID, wantMsgBody) if err != nil { // we allow clients to fail the send if they cannot call /sendToDevice - t.Logf("TrySendMessage: %s", err) + t.Logf("SendMessage: %s", err) } if evID != "" { - t.Logf("TrySendMessage: => %s", evID) + t.Logf("SendMessage: => %s", evID) } }) if err != nil { // retry now we have connectivity - evID = alice.SendMessage(t, roomID, wantMsgBody) + evID = alice.MustSendMessage(t, roomID, wantMsgBody) } // Bob receives the message @@ -89,7 +89,7 @@ func TestUnprocessedToDeviceMessagesArentLostOnRestart(t *testing.T) { // we will close this in the test, no defer bobStopSyncing := bob.MustStartSyncing(t) // check the room works - alice.SendMessage(t, roomID, "Hello World!") + alice.MustSendMessage(t, roomID, "Hello World!") bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody("Hello World!")).Waitf(t, 2*time.Second, "bob did not see event with body 'Hello World!'") // stop bob's client, but grab the access token first so we can re-use it bobOpts := bob.Opts() @@ -113,7 +113,7 @@ func TestUnprocessedToDeviceMessagesArentLostOnRestart(t *testing.T) { t.Logf("to-device msgs sent") // send a message as alice to make a new room key - eventID := alice.SendMessage(t, roomID, "Kick to make a new room key!") + eventID := alice.MustSendMessage(t, roomID, "Kick to make a new room key!") // client specific impls to handle restarts. switch clientType.Lang { @@ -315,7 +315,7 @@ func TestToDeviceMessagesAreBatched(t *testing.T) { return nil }, }, func() { - alice.SendMessage(t, roomID, "this should cause to-device msgs to be sent") + alice.MustSendMessage(t, roomID, "this should cause to-device msgs to be sent") time.Sleep(time.Second) waiter.Waitf(t, 5*time.Second, "did not see /sendToDevice") }) @@ -348,7 +348,7 @@ func TestToDeviceMessagesArentLostWhenKeysQueryFails(t *testing.T) { tc.WithAliceAndBobSyncing(t, func(alice, bob api.TestClient) { msg := "hello world" msg2 := "new device message from alice" - alice.SendMessage(t, roomID, msg) + alice.MustSendMessage(t, roomID, msg) bob.WaitUntilEventInRoom(t, roomID, api.CheckEventHasBody(msg)).Waitf(t, 5*time.Second, "bob failed to see message from alice") // Block /keys/query requests waiter := helpers.NewWaiter() @@ -375,7 +375,7 @@ func TestToDeviceMessagesArentLostWhenKeysQueryFails(t *testing.T) { time.Sleep(time.Second) // Alice sends a message on the new device. - eventID = alice2.SendMessage(t, roomID, msg2) + eventID = alice2.MustSendMessage(t, roomID, msg2) waiter.Waitf(t, 3*time.Second, "did not see /keys/query") time.Sleep(3 * time.Second) // let Bob retry /keys/query @@ -473,7 +473,7 @@ func TestToDeviceMessagesAreProcessedInOrder(t *testing.T) { for i := 0; i < numMsgsPerClient; i++ { for _, c := range clients { body := fmt.Sprintf("Message %d", i+1) - eventID := c.SendMessage(t, roomID, body) + eventID := c.MustSendMessage(t, roomID, body) timelineEvents = append(timelineEvents, struct { ID string Body string From bad61788ff18e84f2f7d2da93ada89c2b4e2834e Mon Sep 17 00:00:00 2001 From: Kegan Dougal <7190048+kegsay@users.noreply.github.com> Date: Tue, 1 Oct 2024 09:15:12 +0100 Subject: [PATCH 2/2] ensure single line logging to stop syntax errors on multilined error args --- internal/api/js/js.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/api/js/js.go b/internal/api/js/js.go index 0140843..bb2afed 100644 --- a/internal/api/js/js.go +++ b/internal/api/js/js.go @@ -679,8 +679,9 @@ func (c *JSClient) WaitUntilEventInRoom(t ct.TestLike, roomID string, checker fu func (c *JSClient) Logf(t ct.TestLike, format string, args ...interface{}) { t.Helper() formatted := fmt.Sprintf(t.Name()+": "+format, args...) + firstLine := strings.Split(formatted, "\n")[0] if c.browser.Ctx.Err() == nil { // don't log on dead browsers - chrome.MustRunAsyncFn[chrome.Void](t, c.browser.Ctx, fmt.Sprintf(`console.log("%s");`, strings.Replace(formatted, `"`, `\"`, -1))) + chrome.MustRunAsyncFn[chrome.Void](t, c.browser.Ctx, fmt.Sprintf(`console.log("%s");`, strings.Replace(firstLine, `"`, `\"`, -1))) t.Logf(format, args...) } }