diff --git a/internal/api/client.go b/internal/api/client.go index 36797e6..03e521d 100644 --- a/internal/api/client.go +++ b/internal/api/client.go @@ -33,11 +33,6 @@ type Client interface { // uploaded to the server. Failure to block will result in flakey tests as other users may not // encrypt for this Client due to not detecting keys for the Client. Login(t ct.TestLike, opts ClientCreationOpts) error - // MustStartSyncing to begin syncing from sync v2 / sliding sync. - // Tests should call stopSyncing() at the end of the test. - // MUST BLOCK until the initial sync is complete. - // Fails the test if there was a problem syncing. - MustStartSyncing(t ct.TestLike) (stopSyncing func()) // StartSyncing to begin syncing from sync v2 / sliding sync. // Tests should call stopSyncing() at the end of the test. // MUST BLOCK until the initial sync is complete. @@ -50,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,9 +89,86 @@ type Client interface { Opts() ClientCreationOpts } -type Notification struct { - Event - HasMentions *bool +// TestClient is a Client with extra helper functions added to make writing tests easier. +// Client implementations are not expected to implement these helper functions, and are +// 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. +func NewTestClient(c Client) TestClient { + return &testClientImpl{ + Client: c, + } +} + +type testClientImpl struct { + Client +} + +func (c *testClientImpl) MustStartSyncing(t ct.TestLike) (stopSyncing func()) { + t.Helper() + stopSyncing, err := c.StartSyncing(t) + if err != nil { + ct.Fatalf(t, "MustStartSyncing: %s", err) + } + 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 { @@ -130,18 +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) -} - -func (c *LoggedClient) MustStartSyncing(t ct.TestLike) (stopSyncing func()) { - t.Helper() - c.Logf(t, "%s MustStartSyncing starting to sync", c.logPrefix()) - stopSyncing = c.Client.MustStartSyncing(t) - c.Logf(t, "%s MustStartSyncing now syncing", c.logPrefix()) - return + 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) { @@ -158,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 } @@ -180,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) + 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) MustBackupKeys(t ct.TestLike) (recoveryKey string) { +func (c *LoggedClient) BackupKeys(t ct.TestLike) (recoveryKey string, err error) { 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 -} - -func (c *LoggedClient) MustLoadBackup(t ct.TestLike, recoveryKey string) { - 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 { @@ -216,6 +266,11 @@ func (c *LoggedClient) logPrefix() string { return fmt.Sprintf("[%s](%s)", c.UserID(), c.Type()) } +type Notification struct { + Event + HasMentions *bool +} + // ClientCreationOpts are options to use when creating crypto clients. // // This contains a mixture of generic options which can be used across any client, and specific diff --git a/internal/api/js/js.go b/internal/api/js/js.go index 5ae0294..bb2afed 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,14 +548,7 @@ func (c *JSClient) MustGetEvent(t ct.TestLike, roomID, eventID string) api.Event ev.FailedToDecrypt = true } - return ev -} - -func (c *JSClient) MustStartSyncing(t ct.TestLike) (stopSyncing func()) { - t.Helper() - stopSyncing, err := c.StartSyncing(t) - must.NotError(t, "StartSyncing", err) - return stopSyncing + return ev, nil } // StartSyncing to begin syncing from sync v2 / sliding sync. @@ -609,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", { @@ -631,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 @@ -652,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 { @@ -693,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...) } } diff --git a/internal/api/rust/rust.go b/internal/api/rust/rust.go index 44db503..b4ceea0 100644 --- a/internal/api/rust/rust.go +++ b/internal/api/rust/rust.go @@ -309,25 +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 -} - -func (c *RustClient) MustStartSyncing(t ct.TestLike) (stopSyncing func()) { - t.Helper() - stopSyncing, err := c.StartSyncing(t) - must.NotError(t, "StartSyncing", err) - return stopSyncing + return ev, nil } // StartSyncing to begin syncing from sync v2 / sliding sync. @@ -460,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 { @@ -496,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) @@ -515,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) @@ -586,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/cc/test_context.go b/internal/cc/test_context.go index 169b356..8711215 100644 --- a/internal/cc/test_context.go +++ b/internal/cc/test_context.go @@ -70,9 +70,9 @@ func (c *TestContext) RegisterNewUser(t *testing.T, clientType api.ClientType, l // // The callback function is invoked after this, and cleanup functions are called on your behalf when the // callback function ends. -func (c *TestContext) WithClientSyncing(t *testing.T, req *ClientCreationRequest, callback func(cli api.Client)) { +func (c *TestContext) WithClientSyncing(t *testing.T, req *ClientCreationRequest, callback func(cli api.TestClient)) { t.Helper() - c.WithClientsSyncing(t, []*ClientCreationRequest{req}, func(clients []api.Client) { + c.WithClientsSyncing(t, []*ClientCreationRequest{req}, func(clients []api.TestClient) { callback(clients[0]) }) } @@ -87,9 +87,9 @@ func (c *TestContext) WithClientSyncing(t *testing.T, req *ClientCreationRequest // // The callback function is invoked after this, and cleanup functions are called on your behalf when the // callback function ends. -func (c *TestContext) WithClientsSyncing(t *testing.T, reqs []*ClientCreationRequest, callback func(clients []api.Client)) { +func (c *TestContext) WithClientsSyncing(t *testing.T, reqs []*ClientCreationRequest, callback func(clients []api.TestClient)) { t.Helper() - cryptoClients := make([]api.Client, len(reqs)) + cryptoClients := make([]api.TestClient, len(reqs)) // Login all clients BEFORE starting any of their sync loops. // We do this because Login will send device list updates and cause clients to upload OTKs/device keys. // We want to make sure ALL these keys are on the server before any test client syncs otherwise it @@ -107,18 +107,18 @@ func (c *TestContext) WithClientsSyncing(t *testing.T, reqs []*ClientCreationReq } // mustCreateMultiprocessClient creates a new RPC process and instructs it to create a client given by the client creation options. -func (c *TestContext) mustCreateMultiprocessClient(t *testing.T, req *ClientCreationRequest) api.Client { +func (c *TestContext) mustCreateMultiprocessClient(t *testing.T, req *ClientCreationRequest) api.TestClient { t.Helper() if c.RPCBinaryPath == "" { t.Skipf("RPC binary path not provided, skipping multiprocess test. To run this test, set COMPLEMENT_CRYPTO_RPC_BINARY") - return nil + return api.NewTestClient(nil) } ctxPrefix := fmt.Sprintf("%d", c.RPCInstance.Add(1)) remoteBindings, err := rpc.NewLanguageBindings(c.RPCBinaryPath, req.User.ClientType.Lang, ctxPrefix) if err != nil { t.Fatalf("Failed to create new RPC language bindings: %s", err) } - return remoteBindings.MustCreateClient(t, req.Opts) + return api.NewTestClient(remoteBindings.MustCreateClient(t, req.Opts)) } // WithAliceSyncing is a helper function which creates a rust/js client and automatically logs in Alice and starts @@ -126,7 +126,7 @@ func (c *TestContext) mustCreateMultiprocessClient(t *testing.T, req *ClientCrea // // The callback function is invoked after this, and cleanup functions are called on your behalf when the // callback function ends. -func (c *TestContext) WithAliceSyncing(t *testing.T, callback func(alice api.Client)) { +func (c *TestContext) WithAliceSyncing(t *testing.T, callback func(alice api.TestClient)) { t.Helper() must.NotEqual(t, c.Alice, nil, "No Alice defined. Call CreateTestContext() with at least 1 api.ClientType.") c.WithClientSyncing(t, &ClientCreationRequest{ @@ -139,7 +139,7 @@ func (c *TestContext) WithAliceSyncing(t *testing.T, callback func(alice api.Cli // // The callback function is invoked after this, and cleanup functions are called on your behalf when the // callback function ends. -func (c *TestContext) WithAliceAndBobSyncing(t *testing.T, callback func(alice, bob api.Client)) { +func (c *TestContext) WithAliceAndBobSyncing(t *testing.T, callback func(alice, bob api.TestClient)) { t.Helper() must.NotEqual(t, c.Bob, nil, "No Bob defined. Call CreateTestContext() with at least 2 api.ClientTypes.") c.WithClientsSyncing(t, []*ClientCreationRequest{ @@ -149,7 +149,7 @@ func (c *TestContext) WithAliceAndBobSyncing(t *testing.T, callback func(alice, { User: c.Bob, }, - }, func(clients []api.Client) { + }, func(clients []api.TestClient) { callback(clients[0], clients[1]) }) } @@ -159,7 +159,7 @@ func (c *TestContext) WithAliceAndBobSyncing(t *testing.T, callback func(alice, // // The callback function is invoked after this, and cleanup functions are called on your behalf when the // callback function ends. -func (c *TestContext) WithAliceBobAndCharlieSyncing(t *testing.T, callback func(alice, bob, charlie api.Client)) { +func (c *TestContext) WithAliceBobAndCharlieSyncing(t *testing.T, callback func(alice, bob, charlie api.TestClient)) { t.Helper() must.NotEqual(t, c.Charlie, nil, "No Charlie defined. Call CreateTestContext() with at least 3 api.ClientTypes.") c.WithClientsSyncing(t, []*ClientCreationRequest{ @@ -172,7 +172,7 @@ func (c *TestContext) WithAliceBobAndCharlieSyncing(t *testing.T, callback func( { User: c.Charlie, }, - }, func(clients []api.Client) { + }, func(clients []api.TestClient) { callback(clients[0], clients[1], clients[2]) }) } @@ -288,7 +288,7 @@ func (c *TestContext) MustRegisterNewDevice(t *testing.T, user *User, newDeviceI } // MustLoginClient is the same as MustCreateClient but also logs in the client. -func (c *TestContext) MustLoginClient(t *testing.T, req *ClientCreationRequest) api.Client { +func (c *TestContext) MustLoginClient(t *testing.T, req *ClientCreationRequest) api.TestClient { t.Helper() client := c.MustCreateClient(t, req) must.NotError(t, "failed to login client", client.Login(t, client.Opts())) @@ -297,7 +297,7 @@ func (c *TestContext) MustLoginClient(t *testing.T, req *ClientCreationRequest) // MustCreateClient creates an api.Client from an existing Complement client and the specified client type. Additional options // can be set to configure the client beyond that of the Complement client e.g to add persistent storage. -func (c *TestContext) MustCreateClient(t *testing.T, req *ClientCreationRequest) api.Client { +func (c *TestContext) MustCreateClient(t *testing.T, req *ClientCreationRequest) api.TestClient { t.Helper() if req.User == nil { ct.Fatalf(t, "MustCreateClient: ClientCreationRequest missing 'user', register one with RegisterNewUser or use an existing one.") @@ -318,11 +318,11 @@ func (c *TestContext) MustCreateClient(t *testing.T, req *ClientCreationRequest) // mustCreateClient creates an api.Client with the specified language/server, else fails the test. // // Options can be provided to configure clients, such as enabling persistent storage. -func mustCreateClient(t *testing.T, clientType api.ClientType, cfg api.ClientCreationOpts) api.Client { +func mustCreateClient(t *testing.T, clientType api.ClientType, cfg api.ClientCreationOpts) api.TestClient { bindings := langs.GetLanguageBindings(clientType.Lang) if bindings == nil { t.Fatalf("unknown language: %s", clientType.Lang) } c := bindings.MustCreateClient(t, cfg) - return c + return api.NewTestClient(c) } diff --git a/internal/deploy/rpc/client.go b/internal/deploy/rpc/client.go index 2f07061..82f0da8 100644 --- a/internal/deploy/rpc/client.go +++ b/internal/deploy/rpc/client.go @@ -218,24 +218,6 @@ func (c *RPCClient) Login(t ct.TestLike, opts api.ClientCreationOpts) error { return err } -// MustStartSyncing to begin syncing from sync v2 / sliding sync. -// Tests should call stopSyncing() at the end of the test. -// MUST BLOCK until the initial sync is complete. -// Fails the test if there was a problem syncing. -func (c *RPCClient) MustStartSyncing(t ct.TestLike) (stopSyncing func()) { - var void int - err := c.client.Call("Server.MustStartSyncing", t.Name(), &void) - if err != nil { - t.Fatalf("RPCClient.MustStartSyncing: %s", err) - } - return func() { - err := c.client.Call("Server.StopSyncing", t.Name(), &void) - if err != nil { - t.Fatalf("RPCClient.StopSyncing: %s", err) - } - } -} - // StartSyncing to begin syncing from sync v2 / sliding sync. // Tests should call stopSyncing() at the end of the test. // MUST BLOCK until the initial sync is complete. @@ -262,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, @@ -305,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 1c83d14..cc85e0c 100644 --- a/internal/deploy/rpc/server.go +++ b/internal/deploy/rpc/server.go @@ -111,12 +111,6 @@ func (s *Server) Login(opts api.ClientCreationOpts, void *int) error { return s.activeClient.Login(&api.MockT{}, opts) } -func (s *Server) MustStartSyncing(testName string, void *int) error { - defer s.keepAlive() - s.stopSyncing = s.activeClient.MustStartSyncing(&api.MockT{TestName: testName}) - return nil -} - func (s *Server) StartSyncing(testName string, void *int) error { defer s.keepAlive() stopSyncing, err := s.activeClient.StartSyncing(&api.MockT{TestName: testName}) @@ -151,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 } @@ -234,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) @@ -261,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 { @@ -273,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 { @@ -302,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 72502d9..9441633 100644 --- a/internal/tests/client_test.go +++ b/internal/tests/client_test.go @@ -29,7 +29,7 @@ var ( ssDeployment *deploy.SlidingSyncDeployment // aka functions which make clients, and we don't care about the language. // Tests just loop through this array for each client impl. - clientFactories []func(t *testing.T, cfg api.ClientCreationOpts) api.Client + clientFactories []func(t *testing.T, cfg api.ClientCreationOpts) api.TestClient ) func Deploy(t *testing.T) *deploy.SlidingSyncDeployment { @@ -47,30 +47,30 @@ func Deploy(t *testing.T) *deploy.SlidingSyncDeployment { } func TestMain(m *testing.M) { - rustClientCreator := func(t *testing.T, cfg api.ClientCreationOpts) api.Client { + rustClientCreator := func(t *testing.T, cfg api.ClientCreationOpts) api.TestClient { client, err := rust.NewRustClient(t, cfg) if err != nil { t.Fatalf("NewRustClient: %s", err) } - return client + return api.NewTestClient(client) } - jsClientCreator := func(t *testing.T, cfg api.ClientCreationOpts) api.Client { + jsClientCreator := func(t *testing.T, cfg api.ClientCreationOpts) api.TestClient { client, err := js.NewJSClient(t, cfg) if err != nil { t.Fatalf("NewJSClient: %s", err) } - return client + return api.NewTestClient(client) } clientFactories = append(clientFactories, rustClientCreator, jsClientCreator) rpcBinary := os.Getenv("COMPLEMENT_CRYPTO_RPC_BINARY") if rpcBinary != "" { - clientFactories = append(clientFactories, func(t *testing.T, cfg api.ClientCreationOpts) api.Client { + clientFactories = append(clientFactories, func(t *testing.T, cfg api.ClientCreationOpts) api.TestClient { remoteBindings, err := rpc.NewLanguageBindings(rpcBinary, api.ClientTypeRust, "") if err != nil { log.Fatal(err) } - return remoteBindings.MustCreateClient(t, cfg) + return api.NewTestClient(remoteBindings.MustCreateClient(t, cfg)) }) } rust.SetupLogs("rust_sdk_logs") @@ -104,7 +104,7 @@ func TestReceiveTimeline(t *testing.T) { } // test that if we start syncing with a room full of events, we see those events. - ForEachClient(t, "existing_events", deployment, func(t *testing.T, client api.Client, csapi *client.CSAPI) { + ForEachClient(t, "existing_events", deployment, func(t *testing.T, client api.TestClient, csapi *client.CSAPI) { must.NotError(t, "Failed to login", client.Login(t, client.Opts())) roomID, eventIDs := createAndSendEvents(t, csapi) time.Sleep(time.Second) // give time for everything to settle server-side e.g sliding sync proxy @@ -132,7 +132,7 @@ func TestReceiveTimeline(t *testing.T) { }) // test that if we are already syncing and then see a room live stream full of events, we see those events. - ForEachClient(t, "live_events", deployment, func(t *testing.T, client api.Client, csapi *client.CSAPI) { + ForEachClient(t, "live_events", deployment, func(t *testing.T, client api.TestClient, csapi *client.CSAPI) { must.NotError(t, "Failed to login", client.Login(t, client.Opts())) stopSyncing := client.MustStartSyncing(t) defer stopSyncing() @@ -171,7 +171,7 @@ func TestReceiveTimeline(t *testing.T) { func TestCanWaitUntilEventInRoomBeforeRoomIsKnown(t *testing.T) { deployment := Deploy(t) - ForEachClient(t, "", deployment, func(t *testing.T, client api.Client, csapi *client.CSAPI) { + ForEachClient(t, "", deployment, func(t *testing.T, client api.TestClient, csapi *client.CSAPI) { roomID := csapi.MustCreateRoom(t, map[string]interface{}{}) eventID := csapi.SendEventSynced(t, roomID, b.Event{ Type: "m.room.message", @@ -196,28 +196,28 @@ func TestCanWaitUntilEventInRoomBeforeRoomIsKnown(t *testing.T) { func TestSendingEvents(t *testing.T) { deployment := Deploy(t) - ForEachClient(t, "", deployment, func(t *testing.T, client api.Client, csapi *client.CSAPI) { + ForEachClient(t, "", deployment, func(t *testing.T, client api.TestClient, csapi *client.CSAPI) { must.NotError(t, "Failed to login", client.Login(t, client.Opts())) 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") }) } // run a subtest for each client factory -func ForEachClient(t *testing.T, name string, deployment *deploy.SlidingSyncDeployment, fn func(t *testing.T, client api.Client, csapi *client.CSAPI)) { +func ForEachClient(t *testing.T, name string, deployment *deploy.SlidingSyncDeployment, fn func(t *testing.T, client api.TestClient, csapi *client.CSAPI)) { for _, createClient := range clientFactories { csapiAlice := deployment.Register(t, "hs1", helpers.RegistrationOpts{ LocalpartSuffix: "client", diff --git a/tests/delayed_requests_test.go b/tests/delayed_requests_test.go index 4ff5f26..167cb4a 100644 --- a/tests/delayed_requests_test.go +++ b/tests/delayed_requests_test.go @@ -33,10 +33,10 @@ func TestDelayedInviteResponse(t *testing.T) { Instance().ForEachClientType(t, func(t *testing.T, clientType api.ClientType) { tc := Instance().CreateTestContext(t, clientType, clientType) roomID := tc.CreateNewEncryptedRoom(t, tc.Alice) - tc.WithAliceAndBobSyncing(t, func(alice, bob api.Client) { + 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 b18ad08..e8d3717 100644 --- a/tests/device_keys_test.go +++ b/tests/device_keys_test.go @@ -41,9 +41,9 @@ func TestFailedDeviceKeyDownloadRetries(t *testing.T) { roomID := tc.CreateNewEncryptedRoom(t, tc.Alice, cc.EncRoomOptions.Invite([]string{tc.Bob.UserID})) tc.Bob.MustJoinRoom(t, roomID, []string{"hs1"}) - tc.WithAliceAndBobSyncing(t, func(alice, bob api.Client) { + 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 4b6b624..d961fda 100644 --- a/tests/federation_connectivity_test.go +++ b/tests/federation_connectivity_test.go @@ -32,14 +32,14 @@ func TestNewUserCannotGetKeysForOfflineServer(t *testing.T) { t.Logf("%s joining room %s", tc.Bob.UserID, roomID) tc.Bob.MustJoinRoom(t, roomID, []string{"hs1"}) - tc.WithAliceAndBobSyncing(t, func(alice, bob api.Client) { + tc.WithAliceAndBobSyncing(t, func(alice, bob api.TestClient) { // let clients sync device keys time.Sleep(time.Second) // 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) @@ -50,7 +50,7 @@ func TestNewUserCannotGetKeysForOfflineServer(t *testing.T) { tc.Alice.MustInviteRoom(t, roomID, tc.Charlie.UserID) tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: tc.Charlie, - }, func(charlie api.Client) { + }, func(charlie api.TestClient) { tc.Charlie.MustJoinRoom(t, roomID, []string{"hs1"}) // let charlie sync device keys... and fail to get bob's keys! @@ -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) @@ -116,18 +116,18 @@ func TestExistingSessionCannotGetKeysForOfflineServer(t *testing.T) { tc.Bob.MustJoinRoom(t, roomIDab, []string{"hs1"}) tc.Bob.MustJoinRoom(t, roomIDbc, []string{"hs1"}) - tc.WithAliceBobAndCharlieSyncing(t, func(alice, bob, charlie api.Client) { + tc.WithAliceBobAndCharlieSyncing(t, func(alice, bob, charlie api.TestClient) { // let clients sync device keys time.Sleep(time.Second) // 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 d267f3c..fce2bad 100644 --- a/tests/key_backup_test.go +++ b/tests/key_backup_test.go @@ -36,10 +36,10 @@ func TestCanBackupKeys(t *testing.T) { // SDK testing below // ----------------- - tc.WithAliceSyncing(t, func(backupCreator api.Client) { + 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) @@ -98,10 +98,10 @@ func TestBackupWrongRecoveryKeyFails(t *testing.T) { // SDK testing below // ----------------- - tc.WithAliceSyncing(t, func(backupCreator api.Client) { + 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 42a1cb9..8d39edd 100644 --- a/tests/membership_acls_test.go +++ b/tests/membership_acls_test.go @@ -35,7 +35,7 @@ func TestAliceBobEncryptionWorks(t *testing.T) { // SDK testing below // ----------------- - tc.WithAliceAndBobSyncing(t, func(alice, bob api.Client) { + tc.WithAliceAndBobSyncing(t, func(alice, bob api.TestClient) { wantMsgBody := "Hello world" // Check the room is in fact encrypted @@ -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) @@ -75,7 +75,7 @@ func TestCanDecryptMessagesAfterInviteButBeforeJoin(t *testing.T) { // SDK testing below // ----------------- - tc.WithAliceAndBobSyncing(t, func(alice, bob api.Client) { + tc.WithAliceAndBobSyncing(t, func(alice, bob api.TestClient) { wantMsgBody := "Message sent when bob is invited not joined" // Check the room is in fact encrypted @@ -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 @@ -122,11 +122,11 @@ func TestBobCanSeeButNotDecryptHistoryInPublicRoom(t *testing.T) { // SDK testing below // ----------------- - tc.WithAliceAndBobSyncing(t, func(alice, bob api.Client) { + tc.WithAliceAndBobSyncing(t, func(alice, bob api.TestClient) { // 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") @@ -163,11 +163,11 @@ func TestOnRejoinBobCanSeeButNotDecryptHistoryInPublicRoom(t *testing.T) { // SDK testing below // ----------------- - tc.WithAliceAndBobSyncing(t, func(alice, bob api.Client) { + tc.WithAliceAndBobSyncing(t, func(alice, bob api.TestClient) { // 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") */ @@ -222,11 +222,11 @@ func TestOnNewDeviceBobCanSeeButNotDecryptHistoryInPublicRoom(t *testing.T) { // SDK testing below // ----------------- - tc.WithAliceAndBobSyncing(t, func(alice, bob api.Client) { + tc.WithAliceAndBobSyncing(t, func(alice, bob api.TestClient) { // 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") @@ -234,7 +234,7 @@ func TestOnNewDeviceBobCanSeeButNotDecryptHistoryInPublicRoom(t *testing.T) { csapiBob2 := tc.MustRegisterNewDevice(t, tc.Bob, "NEW_DEVICE") tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: csapiBob2, - }, func(bob2 api.Client) { + }, func(bob2 api.TestClient) { time.Sleep(time.Second) // let device keys propagate to alice bob2.MustBackpaginate(t, roomID, 5) // ensure the older event is there time.Sleep(time.Second) @@ -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,14 +258,14 @@ 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) // now bob logs in again tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: csapiBob2, - }, func(bob2 api.Client) { + }, func(bob2 api.TestClient) { time.Sleep(time.Second) // let device keys propagate to alice undecryptableEvent := bob2.MustGetEvent(t, roomID, evID) must.Equal(t, undecryptableEvent.FailedToDecrypt, true, "bob's new device was able to decrypt a message sent after he had logged out") @@ -282,18 +282,18 @@ func TestChangingDeviceAfterInviteReEncrypts(t *testing.T) { // shared history visibility roomID := tc.CreateNewEncryptedRoom(t, tc.Alice, cc.EncRoomOptions.PresetPublicChat()) - tc.WithAliceAndBobSyncing(t, func(alice, bob api.Client) { + tc.WithAliceAndBobSyncing(t, func(alice, bob api.TestClient) { // Alice invites Bob and then she sends an event 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") tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: csapiBob2, - }, func(bob2 api.Client) { + }, func(bob2 api.TestClient) { time.Sleep(time.Second) // let device keys propagate tc.Bob.MustJoinRoom(t, roomID, []string{clientTypeA.HS}) diff --git a/tests/one_time_keys_test.go b/tests/one_time_keys_test.go index 6e5605a..e51c919 100644 --- a/tests/one_time_keys_test.go +++ b/tests/one_time_keys_test.go @@ -95,7 +95,7 @@ func TestFallbackKeyIsUsedIfOneTimeKeysRunOut(t *testing.T) { // ================= // Upload OTKs and a fallback - tc.WithAliceBobAndCharlieSyncing(t, func(alice, bob, charlie api.Client) { + tc.WithAliceBobAndCharlieSyncing(t, func(alice, bob, charlie api.TestClient) { // we need to send _something_ to cause /sync v2 to return a long poll response, as fallback // keys don't wake up /sync v2. If we don't do this, rust SDK fails to realise it needs to upload a fallback // key because SS doesn't tell it, because Synapse doesn't tell SS that the fallback key was used. @@ -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{}) @@ -169,7 +169,7 @@ func TestFailedOneTimeKeyUploadRetries(t *testing.T) { }, RequestCallback: callback.SendError(2, http.StatusGatewayTimeout), }, func() { - tc.WithAliceSyncing(t, func(alice api.Client) { + tc.WithAliceSyncing(t, func(alice api.TestClient) { tc.Bob.MustDo(t, "POST", []string{ "_matrix", "client", "v3", "keys", "claim", }, client.WithJSONBody(t, map[string]any{ @@ -208,7 +208,7 @@ func TestFailedKeysClaimRetries(t *testing.T) { Instance().ForEachClientType(t, func(t *testing.T, clientType api.ClientType) { tc := Instance().CreateTestContext(t, clientType, clientType) // both clients start syncing to upload OTKs - tc.WithAliceAndBobSyncing(t, func(alice, bob api.Client) { + tc.WithAliceAndBobSyncing(t, func(alice, bob api.TestClient) { var stopPoking atomic.Bool waiter := helpers.NewWaiter() // make a room which will link the 2 users together when @@ -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 c7284b2..7e39c68 100644 --- a/tests/room_keys_test.go +++ b/tests/room_keys_test.go @@ -57,14 +57,14 @@ func TestRoomKeyIsCycledOnDeviceLogout(t *testing.T) { User: csapiAlice2, }) defer alice2.Close(t) - tc.WithAliceAndBobSyncing(t, func(alice, bob api.Client) { + tc.WithAliceAndBobSyncing(t, func(alice, bob api.TestClient) { alice2StopSyncing := alice2.MustStartSyncing(t) alice.WaitUntilEventInRoom(t, roomID, api.CheckEventHasMembership(tc.Bob.UserID, "join")).Waitf(t, 5*time.Second, "alice did not see own join") // check the room works 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 @@ -117,12 +117,12 @@ func TestRoomKeyIsCycledAfterEnoughMessages(t *testing.T) { ) tc.Bob.MustJoinRoom(t, roomID, []string{clientTypeA.HS}) - tc.WithAliceAndBobSyncing(t, func(alice, bob api.Client) { + tc.WithAliceAndBobSyncing(t, func(alice, bob api.TestClient) { // And some messages were sent, but not enough to trigger resending 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 @@ -191,12 +191,12 @@ func TestRoomKeyIsCycledAfterEnoughTime(t *testing.T) { ) tc.Bob.MustJoinRoom(t, roomID, []string{clientTypeA.HS}) - tc.WithAliceAndBobSyncing(t, func(alice, bob api.Client) { + tc.WithAliceAndBobSyncing(t, func(alice, bob api.TestClient) { // Before we start, ensure some keys have already been sent, so we // 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") @@ -226,7 +226,7 @@ func TestRoomKeyIsCycledOnMemberLeaving(t *testing.T) { Instance().ClientTypeMatrix(t, func(t *testing.T, clientTypeA, clientTypeB api.ClientType) { tc := Instance().CreateTestContext(t, clientTypeA, clientTypeB, clientTypeB) // Alice, Bob and Charlie are in a room. - tc.WithAliceBobAndCharlieSyncing(t, func(alice, bob, charlie api.Client) { + tc.WithAliceBobAndCharlieSyncing(t, func(alice, bob, charlie api.TestClient) { // do setup code after all clients are syncing to ensure that if Alice asks for Charlie's keys on receipt of the // join event, then Charlie has already uploaded keys. roomID := tc.CreateNewEncryptedRoom( @@ -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 @@ -281,11 +281,11 @@ func TestRoomKeyIsNotCycled(t *testing.T) { tc.Bob.MustJoinRoom(t, roomID, []string{clientTypeA.HS}) // Alice, Bob are in a room. - tc.WithAliceAndBobSyncing(t, func(alice, bob api.Client) { + tc.WithAliceAndBobSyncing(t, func(alice, bob api.TestClient) { // 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 @@ -407,7 +407,7 @@ func testRoomKeyIsNotCycledOnClientRestartRust(t *testing.T, clientType api.Clie tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: tc.Bob, - }, func(bob api.Client) { + }, func(bob api.TestClient) { wantMsgBody := "test from another process" // send a message as Alice in a different process tc.WithClientSyncing(t, &cc.ClientCreationRequest{ @@ -416,8 +416,8 @@ func testRoomKeyIsNotCycledOnClientRestartRust(t *testing.T, clientType api.Clie PersistentStorage: true, }, Multiprocess: true, - }, func(remoteAlice api.Client) { - eventID := remoteAlice.SendMessage(t, roomID, wantMsgBody) + }, func(remoteAlice api.TestClient) { + 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 @@ -480,11 +480,11 @@ func testRoomKeyIsNotCycledOnClientRestartJS(t *testing.T, clientType api.Client // no alice.close here as we'll close it in the test mid-way tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: tc.Bob, - }, func(bob api.Client) { + }, func(bob api.TestClient) { // 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. @@ -496,11 +496,11 @@ func testRoomKeyIsNotCycledOnClientRestartJS(t *testing.T, clientType api.Client tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: tc.Alice, Opts: alice.Opts(), - }, func(alice api.Client) { + }, func(alice api.TestClient) { // 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 f791322..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 @@ -118,18 +118,18 @@ func TestNSEReceiveForNonPreKeyMessage(t *testing.T) { // Bob sends a message to alice tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: tc.Bob, - }, func(bob api.Client) { + }, func(bob api.TestClient) { // 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{ @@ -175,12 +175,12 @@ func TestMultiprocessNSE(t *testing.T) { // Bob sends a message to alice tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: tc.Bob, - }, func(bob api.Client) { + }, func(bob api.TestClient) { // let bob realise alice exists and claims keys 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 { @@ -336,7 +336,7 @@ func TestMultiprocessNSEBackupKeyMacError(t *testing.T) { // Bob sends a message to alice tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: tc.Bob, - }, func(bob api.Client) { + }, func(bob api.TestClient) { // let bob realise alice exists and claims keys time.Sleep(time.Second) @@ -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) @@ -452,11 +452,11 @@ func TestMultiprocessNSEOlmSessionWedge(t *testing.T) { // Bob sends a message to alice tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: tc.Bob, - }, func(bob api.Client) { + }, func(bob api.TestClient) { // 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() @@ -599,8 +599,8 @@ func TestNotificationClientDupeOTKUpload(t *testing.T) { // The main app will see this in /sync and then try to upload another OTK, which we will tarpit. tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: tc.Bob, - }, func(bob api.Client) { - eventID := bob.SendMessage(t, roomID, "Hello world!") + }, func(bob api.TestClient) { + 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. @@ -648,10 +648,10 @@ func TestMultiprocessInitialE2EESyncDoesntDropDeviceListUpdates(t *testing.T) { // Bob sends a message to Alice tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: tc.Alice, - }, func(alice api.Client) { + }, 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() { @@ -700,11 +700,11 @@ func TestMultiprocessInitialE2EESyncDoesntDropDeviceListUpdates(t *testing.T) { csapiAlice2 := tc.MustRegisterNewDevice(t, tc.Alice, "NEW_DEVICE") tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: csapiAlice2, - }, func(alice2 api.Client) { + }, func(alice2 api.TestClient) { // 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) }) }) @@ -750,15 +750,15 @@ func bobSendsMessage(t *testing.T, tc *cc.TestContext, roomID, text string, msgs pushNotifEventID := "" tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: tc.Bob, - }, func(bob api.Client) { + }, 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 102b6d3..bb9cff6 100644 --- a/tests/to_device_test.go +++ b/tests/to_device_test.go @@ -22,7 +22,7 @@ func TestClientRetriesSendToDevice(t *testing.T) { tc := Instance().CreateTestContext(t, clientTypeA, clientTypeB) roomID := tc.CreateNewEncryptedRoom(t, tc.Alice, cc.EncRoomOptions.PresetPublicChat()) tc.Bob.MustJoinRoom(t, roomID, []string{clientTypeA.HS}) - tc.WithAliceAndBobSyncing(t, func(alice, bob api.Client) { + tc.WithAliceAndBobSyncing(t, func(alice, bob api.TestClient) { // lets device keys be exchanged time.Sleep(time.Second) @@ -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 @@ -85,11 +85,11 @@ func TestUnprocessedToDeviceMessagesArentLostOnRestart(t *testing.T) { PersistentStorage: true, }, }) - tc.WithAliceSyncing(t, func(alice api.Client) { + tc.WithAliceSyncing(t, func(alice api.TestClient) { // 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 { @@ -178,7 +178,7 @@ func testUnprocessedToDeviceMessagesArentLostOnRestartRust(t *testing.T, tc *cc. Opts: api.ClientCreationOpts{ PersistentStorage: true, }, - }, func(bob api.Client) { + }, func(bob api.TestClient) { // we can't rely on MustStartSyncing returning to know that the room key has been received, as // in rust we just wait for RoomListLoadingStateLoaded which is a separate connection to the // encryption loop. @@ -242,7 +242,7 @@ func testUnprocessedToDeviceMessagesArentLostOnRestartJS(t *testing.T, tc *cc.Te Opts: api.ClientCreationOpts{ PersistentStorage: true, }, - }, func(bob api.Client) { + }, func(bob api.TestClient) { // include a grace period like rust, no specific reason beyond consistency. time.Sleep(time.Second) ev := bob.MustGetEvent(t, roomID, eventID) @@ -282,7 +282,7 @@ func TestToDeviceMessagesAreBatched(t *testing.T) { clientUnderTest.Close(t) } waiter := helpers.NewWaiter() - tc.WithAliceSyncing(t, func(alice api.Client) { + tc.WithAliceSyncing(t, func(alice api.TestClient) { // intercept /sendToDevice and check we are sending 100 messages per request tc.Deployment.MITM().Configure(t).WithIntercept(mitm.InterceptOpts{ Filter: mitm.FilterParams{ @@ -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") }) @@ -345,10 +345,10 @@ func TestToDeviceMessagesArentLostWhenKeysQueryFails(t *testing.T) { // get a normal E2EE room set up roomID := tc.CreateNewEncryptedRoom(t, tc.Alice, cc.EncRoomOptions.Invite([]string{tc.Bob.UserID})) tc.Bob.MustJoinRoom(t, roomID, []string{clientType.HS}) - tc.WithAliceAndBobSyncing(t, func(alice, bob api.Client) { + 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() @@ -370,12 +370,12 @@ func TestToDeviceMessagesArentLostWhenKeysQueryFails(t *testing.T) { csapiAlice2 := tc.MustRegisterNewDevice(t, tc.Alice, "OTHER_DEVICE") tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: csapiAlice2, - }, func(alice2 api.Client) { + }, func(alice2 api.TestClient) { // we don't know how long it will take for the device list update to be processed, so wait 1s 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 @@ -429,7 +429,7 @@ func TestToDeviceMessagesAreProcessedInOrder(t *testing.T) { ID string Body string }{} - tc.WithAliceSyncing(t, func(alice api.Client) { + tc.WithAliceSyncing(t, func(alice api.TestClient) { callbackFn := func(cd callback.Data) *callback.Response { // try v2 sync then SS toDeviceEvents := gjson.ParseBytes(cd.ResponseBody).Get("to_device.events").Array() @@ -469,11 +469,11 @@ func TestToDeviceMessagesAreProcessedInOrder(t *testing.T) { creationReqs[i].User.MustJoinRoom(t, roomID, []string{clientType.HS}) } // send 30 messages as each user (interleaved) - tc.WithClientsSyncing(t, creationReqs, func(clients []api.Client) { + tc.WithClientsSyncing(t, creationReqs, func(clients []api.TestClient) { 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 diff --git a/tests/verification_test.go b/tests/verification_test.go index d437795..e1d6f74 100644 --- a/tests/verification_test.go +++ b/tests/verification_test.go @@ -67,13 +67,13 @@ func TestVerificationSAS(t *testing.T) { ClientType: verifieeClientType, } - tc.WithAliceSyncing(t, func(verifier api.Client) { + tc.WithAliceSyncing(t, func(verifier api.TestClient) { tc.WithClientSyncing(t, &cc.ClientCreationRequest{ User: verifieeUser, Opts: api.ClientCreationOpts{ DeviceID: "OTHER_DEVICE", }, - }, func(verifiee api.Client) { + }, func(verifiee api.TestClient) { status := &verificationStatus{ mu: &sync.Mutex{}, }