diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 4344253..3f5bebc 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -120,5 +120,4 @@ jobs: with: name: Logs - ${{ job.status }} path: | - ./tests/rust_sdk_logs* - ./tests/*.log + ./tests/logs/* diff --git a/go.mod b/go.mod index 0ecc884..c8e715b 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/chromedp/cdproto v0.0.0-20231025043423-5615e204d422 github.com/chromedp/chromedp v0.9.3 github.com/docker/go-connections v0.4.0 - github.com/matrix-org/complement v0.0.0-20231121123151-a43fb99237ed + github.com/matrix-org/complement v0.0.0-20240117130049-f24331b29b64 github.com/testcontainers/testcontainers-go v0.26.0 github.com/tidwall/gjson v1.16.0 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 @@ -58,10 +58,10 @@ require ( github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect - golang.org/x/crypto v0.14.0 // indirect + golang.org/x/crypto v0.17.0 // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect + golang.org/x/sys v0.15.0 // indirect golang.org/x/tools v0.13.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect google.golang.org/grpc v1.57.1 // indirect diff --git a/go.sum b/go.sum index b04d4f5..bf073c0 100644 --- a/go.sum +++ b/go.sum @@ -85,6 +85,10 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/matrix-org/complement v0.0.0-20231121123151-a43fb99237ed h1:sGEyUnlj9tNYzAvIq9P/7pTQCQz+KwnQltLvOxuNA10= github.com/matrix-org/complement v0.0.0-20231121123151-a43fb99237ed/go.mod h1:MpFg8YqIgcfReuwX5x0HyIsxkekKyUvbXxY6ey9LeE0= +github.com/matrix-org/complement v0.0.0-20240117124104-5ecb086412c1 h1:YryEz+vrdtun3l0qqggeB75sJ0WyEJmXzE2zxMrzhqs= +github.com/matrix-org/complement v0.0.0-20240117124104-5ecb086412c1/go.mod h1:GMCwbgMOudedB86u1c5+nfQS1L31sFHZ9/YzTYqWyjU= +github.com/matrix-org/complement v0.0.0-20240117130049-f24331b29b64 h1:dBvjM8idvlfkgyCeimfSxZTXdE85wdfJfGIEPq4GAu8= +github.com/matrix-org/complement v0.0.0-20240117130049-f24331b29b64/go.mod h1:GMCwbgMOudedB86u1c5+nfQS1L31sFHZ9/YzTYqWyjU= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= github.com/matrix-org/gomatrixserverlib v0.0.0-20230921171121-0466775328c7 h1:NhPNNFLHwdDb/upeicBh1GkxX/sFinEp5HF1WBqPtiY= @@ -168,6 +172,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -206,6 +212,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/internal/api/client.go b/internal/api/client.go index 4432e70..54d51fc 100644 --- a/internal/api/client.go +++ b/internal/api/client.go @@ -5,6 +5,7 @@ import ( "time" "github.com/matrix-org/complement/client" + "github.com/matrix-org/complement/ct" ) type ClientTypeLang string @@ -26,41 +27,41 @@ type Client interface { // Specifically, we need to shut off existing browsers and any FFI bindings. // If we get callbacks/events after this point, tests may panic if the callbacks // log messages. - Close(t Test) + Close(t ct.TestLike) // Remove any persistent storage, if it was enabled. - DeletePersistentStorage(t Test) - Login(t Test, opts ClientCreationOpts) error + DeletePersistentStorage(t ct.TestLike) + 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 Test) (stopSyncing func()) + 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. // Returns an error if there was a problem syncing. - StartSyncing(t Test) (stopSyncing func(), err error) + StartSyncing(t ct.TestLike) (stopSyncing func(), err error) // IsRoomEncrypted returns true if the room is encrypted. May return an error e.g if you // provide a bogus room ID. - IsRoomEncrypted(t Test, roomID string) (bool, error) + IsRoomEncrypted(t ct.TestLike, roomID string) (bool, error) // 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. - SendMessage(t Test, roomID, text string) (eventID string) + SendMessage(t ct.TestLike, roomID, text string) (eventID string) // TrySendMessage tries to send the message, but can fail. - TrySendMessage(t Test, roomID, text string) (eventID string, err error) + TrySendMessage(t ct.TestLike, roomID, text string) (eventID string, err error) // Wait until an event with the given body is seen. Not all impls expose event IDs // hence needing to use body as a proxy. - WaitUntilEventInRoom(t Test, roomID string, checker func(e Event) bool) Waiter + WaitUntilEventInRoom(t ct.TestLike, roomID string, checker func(e Event) bool) Waiter // Backpaginate in this room by `count` events. - MustBackpaginate(t Test, roomID string, count int) + 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 Test, roomID, eventID string) Event + MustGetEvent(t ct.TestLike, roomID, eventID string) Event // MustBackupKeys will backup E2EE keys, else fail the test. - MustBackupKeys(t Test) (recoveryKey string) + MustBackupKeys(t ct.TestLike) (recoveryKey string) // MustLoadBackup will recover E2EE keys from the latest backup, else fail the test. - MustLoadBackup(t Test, recoveryKey string) + MustLoadBackup(t ct.TestLike, recoveryKey string) // Log something to stdout and the underlying client log file - Logf(t Test, format string, args ...interface{}) + Logf(t ct.TestLike, format string, args ...interface{}) // The user for this client UserID() string Type() ClientTypeLang @@ -70,19 +71,19 @@ type LoggedClient struct { Client } -func (c *LoggedClient) Login(t Test, opts ClientCreationOpts) error { +func (c *LoggedClient) Login(t ct.TestLike, opts ClientCreationOpts) error { t.Helper() c.Logf(t, "%s Login %+v", c.logPrefix(), opts) return c.Client.Login(t, opts) } -func (c *LoggedClient) Close(t Test) { +func (c *LoggedClient) Close(t ct.TestLike) { t.Helper() c.Logf(t, "%s Close", c.logPrefix()) c.Client.Close(t) } -func (c *LoggedClient) MustStartSyncing(t Test) (stopSyncing func()) { +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) @@ -90,7 +91,7 @@ func (c *LoggedClient) MustStartSyncing(t Test) (stopSyncing func()) { return } -func (c *LoggedClient) StartSyncing(t Test) (stopSyncing func(), err error) { +func (c *LoggedClient) StartSyncing(t ct.TestLike) (stopSyncing func(), err error) { t.Helper() c.Logf(t, "%s StartSyncing starting to sync", c.logPrefix()) stopSyncing, err = c.Client.StartSyncing(t) @@ -98,13 +99,13 @@ func (c *LoggedClient) StartSyncing(t Test) (stopSyncing func(), err error) { return } -func (c *LoggedClient) IsRoomEncrypted(t Test, roomID string) (bool, error) { +func (c *LoggedClient) IsRoomEncrypted(t ct.TestLike, roomID string) (bool, error) { t.Helper() c.Logf(t, "%s IsRoomEncrypted %s", c.logPrefix(), roomID) return c.Client.IsRoomEncrypted(t, roomID) } -func (c *LoggedClient) TrySendMessage(t Test, roomID, text string) (eventID string, err error) { +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) @@ -112,7 +113,7 @@ func (c *LoggedClient) TrySendMessage(t Test, roomID, text string) (eventID stri return } -func (c *LoggedClient) SendMessage(t Test, roomID, text string) (eventID string) { +func (c *LoggedClient) SendMessage(t ct.TestLike, roomID, text string) (eventID string) { t.Helper() c.Logf(t, "%s SendMessage %s => %s", c.logPrefix(), roomID, text) eventID = c.Client.SendMessage(t, roomID, text) @@ -120,19 +121,19 @@ func (c *LoggedClient) SendMessage(t Test, roomID, text string) (eventID string) return } -func (c *LoggedClient) WaitUntilEventInRoom(t Test, roomID string, checker func(e Event) bool) Waiter { +func (c *LoggedClient) WaitUntilEventInRoom(t ct.TestLike, roomID string, checker func(e Event) bool) Waiter { t.Helper() c.Logf(t, "%s WaitUntilEventInRoom %s", c.logPrefix(), roomID) return c.Client.WaitUntilEventInRoom(t, roomID, checker) } -func (c *LoggedClient) MustBackpaginate(t Test, roomID string, count int) { +func (c *LoggedClient) MustBackpaginate(t ct.TestLike, roomID string, count int) { t.Helper() c.Logf(t, "%s MustBackpaginate %d %s", c.logPrefix(), count, roomID) c.Client.MustBackpaginate(t, roomID, count) } -func (c *LoggedClient) MustBackupKeys(t Test) (recoveryKey string) { +func (c *LoggedClient) MustBackupKeys(t ct.TestLike) (recoveryKey string) { t.Helper() c.Logf(t, "%s MustBackupKeys", c.logPrefix()) recoveryKey = c.Client.MustBackupKeys(t) @@ -140,13 +141,13 @@ func (c *LoggedClient) MustBackupKeys(t Test) (recoveryKey string) { return recoveryKey } -func (c *LoggedClient) MustLoadBackup(t Test, recoveryKey string) { +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) } -func (c *LoggedClient) DeletePersistentStorage(t Test) { +func (c *LoggedClient) DeletePersistentStorage(t ct.TestLike) { t.Helper() c.Logf(t, "%s DeletePersistentStorage", c.logPrefix()) c.Client.DeletePersistentStorage(t) @@ -196,7 +197,7 @@ type Event struct { } type Waiter interface { - Wait(t Test, s time.Duration) + Wait(t ct.TestLike, s time.Duration) } func CheckEventHasBody(body string) func(e Event) bool { diff --git a/internal/api/js/chrome/chrome.go b/internal/api/js/chrome/chrome.go index d113ff4..9b0009c 100644 --- a/internal/api/js/chrome/chrome.go +++ b/internal/api/js/chrome/chrome.go @@ -19,7 +19,7 @@ import ( "github.com/chromedp/cdproto/runtime" "github.com/chromedp/chromedp" - "github.com/matrix-org/complement-crypto/internal/api" + "github.com/matrix-org/complement/ct" ) //go:embed dist @@ -36,7 +36,7 @@ type Void *runtime.RemoteObject // // result, err := RunAsyncFn[string](t, ctx, "return await getSomeString()") // void, err := RunAsyncFn[chrome.Void](t, ctx, "doSomething(); await doSomethingElse();") -func RunAsyncFn[T any](t api.Test, ctx context.Context, js string) (*T, error) { +func RunAsyncFn[T any](t ct.TestLike, ctx context.Context, js string) (*T, error) { t.Helper() out := new(T) err := chromedp.Run(ctx, @@ -55,11 +55,11 @@ func RunAsyncFn[T any](t api.Test, ctx context.Context, js string) (*T, error) { // Run an anonymous async iffe in the browser. Set the type parameter to a basic data type // which can be returned as JSON e.g string, map[string]any, []string. If you do not want // to return anything, use chrome.Void -func MustRunAsyncFn[T any](t api.Test, ctx context.Context, js string) *T { +func MustRunAsyncFn[T any](t ct.TestLike, ctx context.Context, js string) *T { t.Helper() result, err := RunAsyncFn[T](t, ctx, js) if err != nil { - api.Fatalf(t, "MustRunAsyncFn: %s", err) + ct.Fatalf(t, "MustRunAsyncFn: %s", err) } return result } @@ -86,7 +86,6 @@ func RunHeadless(onConsoleLog func(s string), requiresPersistance bool, listenPo opts = append(opts, chromedp.UserDataDir(userDir), ) - fmt.Println(userDir) } allocCtx, allocCancel := chromedp.NewExecAllocator(context.Background(), opts...) diff --git a/internal/api/js/js.go b/internal/api/js/js.go index c100924..66af677 100644 --- a/internal/api/js/js.go +++ b/internal/api/js/js.go @@ -12,6 +12,8 @@ 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" ) @@ -56,7 +58,7 @@ type JSClient struct { userID string } -func NewJSClient(t api.Test, opts api.ClientCreationOpts) (api.Client, error) { +func NewJSClient(t ct.TestLike, opts api.ClientCreationOpts) (api.Client, error) { jsc := &JSClient{ listeners: make(map[int32]func(roomID string, ev api.Event)), userID: opts.UserID, @@ -116,7 +118,7 @@ func NewJSClient(t api.Test, opts api.ClientCreationOpts) (api.Client, error) { portStr := u.Port() port, err := strconv.Atoi(portStr) if portStr == "" || err != nil { - api.Fatalf(t, "failed to extract port from base url %s", browser.BaseURL) + ct.Fatalf(t, "failed to extract port from base url %s", browser.BaseURL) } userDeviceToPort[portKey] = port t.Logf("user=%s device=%s will be served from %s due to persistent storage", opts.UserID, opts.DeviceID, browser.BaseURL) @@ -160,7 +162,7 @@ func NewJSClient(t api.Test, opts api.ClientCreationOpts) (api.Client, error) { return &api.LoggedClient{Client: jsc}, nil } -func (c *JSClient) Login(t api.Test, opts api.ClientCreationOpts) error { +func (c *JSClient) Login(t ct.TestLike, opts api.ClientCreationOpts) error { deviceID := "undefined" if opts.DeviceID != "" { deviceID = `"` + opts.DeviceID + `"` @@ -186,7 +188,7 @@ func (c *JSClient) Login(t api.Test, opts api.ClientCreationOpts) error { return nil } -func (c *JSClient) DeletePersistentStorage(t api.Test) { +func (c *JSClient) DeletePersistentStorage(t ct.TestLike) { t.Helper() chrome.MustRunAsyncFn[chrome.Void](t, c.browser.Ctx, fmt.Sprintf(` window.localStorage.clear(); @@ -220,7 +222,7 @@ func (c *JSClient) DeletePersistentStorage(t api.Test) { // Specifically, we need to shut off existing browsers and any FFI bindings. // If we get callbacks/events after this point, tests may panic if the callbacks // log messages. -func (c *JSClient) Close(t api.Test) { +func (c *JSClient) Close(t ct.TestLike) { chrome.MustRunAsyncFn[chrome.Void](t, c.browser.Ctx, ` const databases = await indexedDB.databases(); console.log("====CLOSE======= idb " + JSON.stringify(databases)); @@ -234,7 +236,7 @@ func (c *JSClient) UserID() string { return c.userID } -func (c *JSClient) MustGetEvent(t api.Test, roomID, eventID string) api.Event { +func (c *JSClient) MustGetEvent(t ct.TestLike, roomID, eventID string) api.Event { t.Helper() // serialised output (if encrypted): // { @@ -249,7 +251,7 @@ func (c *JSClient) MustGetEvent(t api.Test, roomID, eventID string) api.Event { })[0].toJSON()); `, roomID, eventID)) if !gjson.Valid(*evSerialised) { - api.Fatalf(t, "MustGetEvent(%s, %s) %s (js): invalid event, got %s", roomID, eventID, c.userID, *evSerialised) + ct.Fatalf(t, "MustGetEvent(%s, %s) %s (js): invalid event, got %s", roomID, eventID, c.userID, *evSerialised) } result := gjson.Parse(*evSerialised) decryptedEvent := result.Get("decrypted") @@ -274,16 +276,16 @@ func (c *JSClient) MustGetEvent(t api.Test, roomID, eventID string) api.Event { return ev } -func (c *JSClient) MustStartSyncing(t api.Test) (stopSyncing func()) { +func (c *JSClient) MustStartSyncing(t ct.TestLike) (stopSyncing func()) { t.Helper() stopSyncing, err := c.StartSyncing(t) - api.MustNotError(t, "StartSyncing", err) + must.NotError(t, "StartSyncing", err) return stopSyncing } // StartSyncing to begin syncing from sync v2 / sliding sync. // Tests should call stopSyncing() at the end of the test. -func (c *JSClient) StartSyncing(t api.Test) (stopSyncing func(), err error) { +func (c *JSClient) StartSyncing(t ct.TestLike) (stopSyncing func(), err error) { t.Helper() _, err = chrome.RunAsyncFn[chrome.Void](t, c.browser.Ctx, fmt.Sprintf(` var fn; @@ -323,7 +325,7 @@ func (c *JSClient) StartSyncing(t api.Test) (stopSyncing func(), err error) { // IsRoomEncrypted returns true if the room is encrypted. May return an error e.g if you // provide a bogus room ID. -func (c *JSClient) IsRoomEncrypted(t api.Test, roomID string) (bool, error) { +func (c *JSClient) IsRoomEncrypted(t ct.TestLike, roomID string) (bool, error) { t.Helper() isEncrypted, err := chrome.RunAsyncFn[bool]( t, c.browser.Ctx, fmt.Sprintf(`return window.__client.isRoomEncrypted("%s")`, roomID), @@ -336,14 +338,14 @@ func (c *JSClient) IsRoomEncrypted(t api.Test, roomID string) (bool, error) { // SendMessage sends the given text as an m.room.message with msgtype:m.text into the given // room. -func (c *JSClient) SendMessage(t api.Test, roomID, text string) (eventID string) { +func (c *JSClient) SendMessage(t ct.TestLike, roomID, text string) (eventID string) { t.Helper() eventID, err := c.TrySendMessage(t, roomID, text) - api.MustNotError(t, "failed to sendMessage", err) + must.NotError(t, "failed to sendMessage", err) return eventID } -func (c *JSClient) TrySendMessage(t api.Test, roomID, text string) (eventID string, err error) { +func (c *JSClient) TrySendMessage(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", { @@ -356,14 +358,14 @@ func (c *JSClient) TrySendMessage(t api.Test, roomID, text string) (eventID stri return (*res)["event_id"].(string), nil } -func (c *JSClient) MustBackpaginate(t api.Test, roomID string, count int) { +func (c *JSClient) MustBackpaginate(t ct.TestLike, roomID string, count int) { t.Helper() chrome.MustRunAsyncFn[chrome.Void](t, c.browser.Ctx, fmt.Sprintf( `await window.__client.scrollback(window.__client.getRoom("%s"), %d);`, roomID, count, )) } -func (c *JSClient) MustBackupKeys(t api.Test) (recoveryKey string) { +func (c *JSClient) MustBackupKeys(t ct.TestLike) (recoveryKey string) { t.Helper() key := chrome.MustRunAsyncFn[string](t, c.browser.Ctx, ` // we need to ensure that we have a recovery key first, though we don't actually care about it..? @@ -384,7 +386,7 @@ func (c *JSClient) MustBackupKeys(t api.Test) (recoveryKey string) { return *key } -func (c *JSClient) MustLoadBackup(t api.Test, recoveryKey string) { +func (c *JSClient) MustLoadBackup(t ct.TestLike, recoveryKey string) { chrome.MustRunAsyncFn[chrome.Void](t, c.browser.Ctx, fmt.Sprintf(` // we assume the recovery key is the private key for the default key id so // figure out what that key id is. @@ -401,7 +403,7 @@ func (c *JSClient) MustLoadBackup(t api.Test, recoveryKey string) { recoveryKey)) } -func (c *JSClient) WaitUntilEventInRoom(t api.Test, roomID string, checker func(e api.Event) bool) api.Waiter { +func (c *JSClient) WaitUntilEventInRoom(t ct.TestLike, roomID string, checker func(e api.Event) bool) api.Waiter { t.Helper() return &jsTimelineWaiter{ roomID: roomID, @@ -410,7 +412,7 @@ func (c *JSClient) WaitUntilEventInRoom(t api.Test, roomID string, checker func( } } -func (c *JSClient) Logf(t api.Test, format string, args ...interface{}) { +func (c *JSClient) Logf(t ct.TestLike, format string, args ...interface{}) { t.Helper() formatted := fmt.Sprintf(t.Name()+": "+format, args...) if c.browser.Ctx.Err() == nil { // don't log on dead browsers @@ -437,7 +439,7 @@ type jsTimelineWaiter struct { client *JSClient } -func (w *jsTimelineWaiter) Wait(t api.Test, s time.Duration) { +func (w *jsTimelineWaiter) Wait(t ct.TestLike, s time.Duration) { t.Helper() updates := make(chan bool, 3) cancel := w.client.listenForUpdates(func(roomID string, ev api.Event) { @@ -462,11 +464,11 @@ func (w *jsTimelineWaiter) Wait(t api.Test, s time.Duration) { for { timeLeft := s - time.Since(start) if timeLeft <= 0 { - api.Fatalf(t, "%s (js): Wait[%s]: timed out", w.client.userID, w.roomID) + ct.Fatalf(t, "%s (js): Wait[%s]: timed out", w.client.userID, w.roomID) } select { case <-time.After(timeLeft): - api.Fatalf(t, "%s (js): Wait[%s]: timed out", w.client.userID, w.roomID) + ct.Fatalf(t, "%s (js): Wait[%s]: timed out", w.client.userID, w.roomID) case <-updates: return } diff --git a/internal/api/rust/rust.go b/internal/api/rust/rust.go index deb7f5f..e62f711 100644 --- a/internal/api/rust/rust.go +++ b/internal/api/rust/rust.go @@ -10,6 +10,8 @@ import ( "github.com/matrix-org/complement-crypto/internal/api" "github.com/matrix-org/complement-crypto/rust/matrix_sdk_ffi" + "github.com/matrix-org/complement/ct" + "github.com/matrix-org/complement/must" "golang.org/x/exp/slices" ) @@ -18,7 +20,7 @@ func init() { WriteToStdoutOrSystem: false, Filter: "debug", WriteToFiles: &matrix_sdk_ffi.TracingFileConfiguration{ - Path: ".", + Path: "./logs", FilePrefix: "rust_sdk_logs", }, }) @@ -43,7 +45,7 @@ type RustClient struct { persistentStoragePath string } -func NewRustClient(t api.Test, opts api.ClientCreationOpts, ssURL string) (api.Client, error) { +func NewRustClient(t ct.TestLike, opts api.ClientCreationOpts, ssURL string) (api.Client, error) { t.Logf("NewRustClient[%s][%s] creating...", opts.UserID, opts.DeviceID) matrix_sdk_ffi.LogEvent("rust.go", &zero, matrix_sdk_ffi.LogLevelInfo, t.Name(), fmt.Sprintf("NewRustClient[%s][%s] creating...", opts.UserID, opts.DeviceID)) ab := matrix_sdk_ffi.NewClientBuilder().HomeserverUrl(opts.BaseURL).SlidingSyncProxy(&ssURL) @@ -71,7 +73,7 @@ func NewRustClient(t api.Test, opts api.ClientCreationOpts, ssURL string) (api.C return &api.LoggedClient{Client: c}, nil } -func (c *RustClient) Login(t api.Test, opts api.ClientCreationOpts) error { +func (c *RustClient) Login(t ct.TestLike, opts api.ClientCreationOpts) error { var deviceID *string if opts.DeviceID != "" { deviceID = &opts.DeviceID @@ -83,17 +85,17 @@ func (c *RustClient) Login(t api.Test, opts api.ClientCreationOpts) error { return nil } -func (c *RustClient) DeletePersistentStorage(t api.Test) { +func (c *RustClient) DeletePersistentStorage(t ct.TestLike) { t.Helper() if c.persistentStoragePath != "" { err := os.RemoveAll(c.persistentStoragePath) if err != nil { - api.Fatalf(t, "DeletePersistentStorage: %s", err) + ct.Fatalf(t, "DeletePersistentStorage: %s", err) } } } -func (c *RustClient) Close(t api.Test) { +func (c *RustClient) Close(t ct.TestLike) { t.Helper() c.roomsMu.Lock() for _, rri := range c.rooms { @@ -106,30 +108,30 @@ func (c *RustClient) Close(t api.Test) { c.FFIClient.Destroy() } -func (c *RustClient) MustGetEvent(t api.Test, roomID, eventID string) api.Event { +func (c *RustClient) MustGetEvent(t ct.TestLike, roomID, eventID string) api.Event { t.Helper() room := c.findRoom(t, roomID) timelineItem, err := room.Timeline().GetEventTimelineItemByEventId(eventID) if err != nil { - api.Fatalf(t, "MustGetEvent(rust) %s (%s, %s): %s", c.userID, roomID, eventID, err) + ct.Fatalf(t, "MustGetEvent(rust) %s (%s, %s): %s", c.userID, roomID, eventID, err) } ev := eventTimelineItemToEvent(timelineItem) if ev == nil { - api.Fatalf(t, "MustGetEvent(rust) %s (%s, %s): found timeline item but failed to convert it to an Event", c.userID, roomID, eventID) + ct.Fatalf(t, "MustGetEvent(rust) %s (%s, %s): found timeline item but failed to convert it to an Event", c.userID, roomID, eventID) } return *ev } -func (c *RustClient) MustStartSyncing(t api.Test) (stopSyncing func()) { +func (c *RustClient) MustStartSyncing(t ct.TestLike) (stopSyncing func()) { t.Helper() stopSyncing, err := c.StartSyncing(t) - api.MustNotError(t, "StartSyncing", err) + must.NotError(t, "StartSyncing", err) return stopSyncing } // StartSyncing to begin syncing from sync v2 / sliding sync. // Tests should call stopSyncing() at the end of the test. -func (c *RustClient) StartSyncing(t api.Test) (stopSyncing func(), err error) { +func (c *RustClient) StartSyncing(t ct.TestLike) (stopSyncing func(), err error) { t.Helper() syncService, err := c.FFIClient.SyncService().Finish() if err != nil { @@ -174,7 +176,7 @@ func (c *RustClient) StartSyncing(t api.Test) (stopSyncing func(), err error) { // IsRoomEncrypted returns true if the room is encrypted. May return an error e.g if you // provide a bogus room ID. -func (c *RustClient) IsRoomEncrypted(t api.Test, roomID string) (bool, error) { +func (c *RustClient) IsRoomEncrypted(t ct.TestLike, roomID string) (bool, error) { t.Helper() r := c.findRoom(t, roomID) if r == nil { @@ -184,7 +186,7 @@ func (c *RustClient) IsRoomEncrypted(t api.Test, roomID string) (bool, error) { return r.IsEncrypted() } -func (c *RustClient) MustBackupKeys(t api.Test) (recoveryKey string) { +func (c *RustClient) MustBackupKeys(t ct.TestLike) (recoveryKey string) { t.Helper() genericListener := newGenericStateListener[matrix_sdk_ffi.EnableRecoveryProgress]() var listener matrix_sdk_ffi.EnableRecoveryProgressListener = genericListener @@ -202,16 +204,16 @@ func (c *RustClient) MustBackupKeys(t api.Test) (recoveryKey string) { genericListener.Close() // break the loop } } - api.MustNotError(t, "Encryption.EnableRecovery", err) + must.NotError(t, "Encryption.EnableRecovery", err) return recoveryKey } -func (c *RustClient) MustLoadBackup(t api.Test, recoveryKey string) { +func (c *RustClient) MustLoadBackup(t ct.TestLike, recoveryKey string) { t.Helper() - api.MustNotError(t, "Recover", c.FFIClient.Encryption().Recover(recoveryKey)) + must.NotError(t, "Recover", c.FFIClient.Encryption().Recover(recoveryKey)) } -func (c *RustClient) WaitUntilEventInRoom(t api.Test, roomID string, checker func(api.Event) bool) api.Waiter { +func (c *RustClient) WaitUntilEventInRoom(t ct.TestLike, roomID string, checker func(api.Event) bool) api.Waiter { t.Helper() c.ensureListening(t, roomID) return &timelineWaiter{ @@ -227,16 +229,16 @@ func (c *RustClient) Type() api.ClientTypeLang { // 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 api.Test, roomID, text string) (eventID string) { +func (c *RustClient) SendMessage(t ct.TestLike, roomID, text string) (eventID string) { t.Helper() eventID, err := c.TrySendMessage(t, roomID, text) if err != nil { - api.Fatalf(t, err.Error()) + ct.Fatalf(t, err.Error()) } return eventID } -func (c *RustClient) TrySendMessage(t api.Test, roomID, text string) (eventID string, err error) { +func (c *RustClient) TrySendMessage(t ct.TestLike, roomID, text string) (eventID string, err error) { t.Helper() ch := make(chan bool) // we need a timeline listener before we can send messages, AND that listener must be attached to the @@ -268,11 +270,11 @@ func (c *RustClient) TrySendMessage(t api.Test, roomID, text string) (eventID st } } -func (c *RustClient) MustBackpaginate(t api.Test, roomID string, count int) { +func (c *RustClient) MustBackpaginate(t ct.TestLike, roomID string, count int) { t.Helper() r := c.findRoom(t, roomID) - api.MustNotEqual(t, r, nil, "unknown room") - api.MustNotError(t, "failed to backpaginate", r.Timeline().PaginateBackwards(matrix_sdk_ffi.PaginationOptionsSimpleRequest{ + must.NotEqual(t, r, nil, "unknown room") + must.NotError(t, "failed to backpaginate", r.Timeline().PaginateBackwards(matrix_sdk_ffi.PaginationOptionsSimpleRequest{ EventLimit: uint16(count), })) } @@ -293,7 +295,7 @@ func (c *RustClient) findRoomInMap(roomID string) *matrix_sdk_ffi.Room { } // findRoom returns the room, waiting up to 5s for it to appear -func (c *RustClient) findRoom(t api.Test, roomID string) *matrix_sdk_ffi.Room { +func (c *RustClient) findRoom(t ct.TestLike, roomID string) *matrix_sdk_ffi.Room { t.Helper() room := c.findRoomInMap(roomID) if room != nil { @@ -334,20 +336,20 @@ func (c *RustClient) findRoom(t api.Test, roomID string) *matrix_sdk_ffi.Room { return nil } -func (c *RustClient) Logf(t api.Test, format string, args ...interface{}) { +func (c *RustClient) Logf(t ct.TestLike, format string, args ...interface{}) { t.Helper() c.logToFile(t, format, args...) t.Logf(format, args...) } -func (c *RustClient) logToFile(t api.Test, format string, args ...interface{}) { +func (c *RustClient) logToFile(t ct.TestLike, format string, args ...interface{}) { matrix_sdk_ffi.LogEvent("rust.go", &zero, matrix_sdk_ffi.LogLevelInfo, t.Name(), fmt.Sprintf(format, args...)) } -func (c *RustClient) ensureListening(t api.Test, roomID string) *matrix_sdk_ffi.Room { +func (c *RustClient) ensureListening(t ct.TestLike, roomID string) *matrix_sdk_ffi.Room { t.Helper() r := c.findRoom(t, roomID) - api.MustNotEqual(t, r, nil, fmt.Sprintf("room %s does not exist", roomID)) + must.NotEqual(t, r, nil, fmt.Sprintf("room %s does not exist", roomID)) info := c.rooms[roomID] if info.stream != nil { @@ -449,7 +451,7 @@ type timelineWaiter struct { client *RustClient } -func (w *timelineWaiter) Wait(t api.Test, s time.Duration) { +func (w *timelineWaiter) Wait(t ct.TestLike, s time.Duration) { t.Helper() checkForEvent := func() bool { @@ -494,11 +496,11 @@ func (w *timelineWaiter) Wait(t api.Test, s time.Duration) { for { timeLeft := s - time.Since(start) if timeLeft <= 0 { - api.Fatalf(t, "%s (rust): Wait[%s]: timed out", w.client.userID, w.roomID) + ct.Fatalf(t, "%s (rust): Wait[%s]: timed out", w.client.userID, w.roomID) } select { case <-time.After(timeLeft): - api.Fatalf(t, "%s (rust): Wait[%s]: timed out", w.client.userID, w.roomID) + ct.Fatalf(t, "%s (rust): Wait[%s]: timed out", w.client.userID, w.roomID) case <-updates: return } diff --git a/internal/api/test.go b/internal/api/test.go index 7bffff1..08c90f8 100644 --- a/internal/api/test.go +++ b/internal/api/test.go @@ -11,6 +11,9 @@ func (t *MockT) Helper() {} func (t *MockT) Logf(f string, args ...any) { fmt.Printf(f, args...) } +func (t *MockT) Skipf(f string, args ...any) { + fmt.Printf(f, args...) +} func (t *MockT) Errorf(f string, args ...any) { fmt.Printf(f, args...) } @@ -18,48 +21,8 @@ func (t *MockT) Fatalf(f string, args ...any) { fmt.Printf(f, args...) os.Exit(1) } -func (t *MockT) Name() string { return "inline_script" } - -type Test interface { - Logf(f string, args ...any) - Errorf(f string, args ...any) - Fatalf(f string, args ...any) - Helper() - Name() string -} - -// TODO move to must package when it accepts an interface - -// NotError will ensure `err` is nil else terminate the test with `msg`. -func MustNotError(t Test, msg string, err error) { - t.Helper() - if err != nil { - Fatalf(t, "must.NotError: %s -> %s", msg, err) - } -} - -// NotEqual ensures that got!=want else logs an error. -// The 'msg' is displayed with the error to provide extra context. -func MustNotEqual[V comparable](t Test, got, want V, msg string) { - t.Helper() - if got == want { - Errorf(t, "NotEqual %s: got '%v', want '%v'", msg, got, want) - } -} - -const ansiRedForeground = "\x1b[31m" -const ansiResetForeground = "\x1b[39m" - -// Errorf is a wrapper around t.Errorf which prints the failing error message in red. -func Errorf(t Test, format string, args ...any) { - t.Helper() - format = ansiRedForeground + format + ansiResetForeground - t.Errorf(format, args...) -} - -// Fatalf is a wrapper around t.Fatalf which prints the failing error message in red. -func Fatalf(t Test, format string, args ...any) { - t.Helper() - format = ansiRedForeground + format + ansiResetForeground - t.Fatalf(format, args...) +func (t *MockT) Error(args ...any) { + t.Errorf("Error:", args...) } +func (t *MockT) Name() string { return "inline_script" } +func (t *MockT) Failed() bool { return false } diff --git a/internal/config/config.go b/internal/config/config.go index 7088832..880b2db 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -13,7 +13,7 @@ import ( type ComplementCrypto struct { // Name: COMPLEMENT_CRYPTO_WRITE_CONTAINER_LOGS // Default: 0 - // Description: If 1, writes container logs to ./tests. Useful as a debugging tool. + // Description: If 1, writes container logs to ./tests/logs. Useful as a debugging tool. WriteContainerLogs bool // Name: COMPLEMENT_CRYPTO_TEST_CLIENT_MATRIX diff --git a/internal/deploy/callback_addon.go b/internal/deploy/callback_addon.go index a585389..d498866 100644 --- a/internal/deploy/callback_addon.go +++ b/internal/deploy/callback_addon.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "github.com/matrix-org/complement-crypto/internal/api" + "github.com/matrix-org/complement/ct" "github.com/matrix-org/complement/must" ) @@ -27,7 +27,7 @@ func NewCallbackServer(t *testing.T, cb func(CallbackData)) (callbackURL string, mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { var data CallbackData if err := json.NewDecoder(r.Body).Decode(&data); err != nil { - api.Errorf(t, "error decoding json: %s", err) + ct.Errorf(t, "error decoding json: %s", err) w.WriteHeader(500) return } diff --git a/internal/deploy/deploy.go b/internal/deploy/deploy.go index 93c6d39..45f2c1e 100644 --- a/internal/deploy/deploy.go +++ b/internal/deploy/deploy.go @@ -18,9 +18,11 @@ import ( "testing" "time" + "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/go-connections/nat" "github.com/matrix-org/complement" + "github.com/matrix-org/complement-crypto/internal/api" "github.com/matrix-org/complement/must" testcontainers "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" @@ -95,13 +97,53 @@ func (d *SlidingSyncDeployment) ReverseProxyURLForHS(hsName string) string { } func (d *SlidingSyncDeployment) Teardown(writeLogs bool) { - if d.slidingSync != nil { - if writeLogs { - err := writeContainerLogs(d.slidingSync, "container-sliding-sync.log") + if writeLogs { + containers := map[string]testcontainers.Container{ + "container-sliding-sync.log": d.slidingSync, + "container-mitmproxy.log": d.reverseProxy, + } + for filename, c := range containers { + if c == nil { + continue + } + logs, err := c.Logs(context.Background()) + if err != nil { + log.Printf("failed to get logs for file %s: %s", filename, err) + continue + } + err = writeContainerLogs(logs, "container-sliding-sync.log") if err != nil { - log.Printf("failed to write sliding sync logs: %s", err) + log.Printf("failed to write logs to %s: %s", filename, err) + } + } + // and HSes.. + dockerClient, err := testcontainers.NewDockerClientWithOpts(context.Background()) + if err != nil { + log.Printf("failed to write HS container logs, failed to make docker client: %s", err) + } else { + filenameToContainerID := map[string]string{ + "container-hs1.log": d.Deployment.ContainerID(&api.MockT{}, "hs1"), + "container-hs2.log": d.Deployment.ContainerID(&api.MockT{}, "hs2"), + } + for filename, containerID := range filenameToContainerID { + logs, err := dockerClient.ContainerLogs(context.Background(), containerID, types.ContainerLogsOptions{ + ShowStdout: true, + ShowStderr: true, + Follow: false, + }) + if err != nil { + log.Printf("failed to get logs for container %s: %s", containerID, err) + continue + } + err = writeContainerLogs(logs, filename) + if err != nil { + log.Printf("failed to write logs to %s: %s", filename, err) + } } } + } + + if d.slidingSync != nil { if err := d.slidingSync.Terminate(context.Background()); err != nil { log.Fatalf("failed to stop sliding sync: %s", err) } @@ -112,12 +154,6 @@ func (d *SlidingSyncDeployment) Teardown(writeLogs bool) { } } if d.reverseProxy != nil { - if writeLogs { - err := writeContainerLogs(d.reverseProxy, "container-mitmproxy.log") - if err != nil { - log.Printf("failed to write sliding sync logs: %s", err) - } - } if err := d.reverseProxy.Terminate(context.Background()); err != nil { log.Fatalf("failed to stop reverse proxy: %s", err) } @@ -300,16 +336,12 @@ func externalURL(t *testing.T, c testcontainers.Container, exposedPort string) s return fmt.Sprintf("http://%s:%s", host, mappedPort.Port()) } -func writeContainerLogs(container testcontainers.Container, filename string) error { - w, err := os.Create(filename) +func writeContainerLogs(readCloser io.ReadCloser, filename string) error { + w, err := os.Create("./logs/" + filename) if err != nil { return fmt.Errorf("os.Create: %s", err) } - reader, err := container.Logs(context.Background()) - if err != nil { - return fmt.Errorf("container.Logs: %s", err) - } - _, err = io.Copy(w, reader) + _, err = io.Copy(w, readCloser) if err != nil { return fmt.Errorf("io.Copy: %s", err) } diff --git a/internal/rp/controller.go b/internal/rp/controller.go deleted file mode 100644 index 4b0a640..0000000 --- a/internal/rp/controller.go +++ /dev/null @@ -1,18 +0,0 @@ -package rp - -import ( - "testing" -) - -type ReverseProxyController struct { -} - -func NewReverseProxyController() *ReverseProxyController { - return &ReverseProxyController{} -} - -// InterceptResponses will interecept responses between the homeserver and client and modify them according to the ResponseTransformer. -// The RequestMatchers are applied IN THE ORDER GIVEN. All request matchers MUST matcher before the response is intercepted. -func (c *ReverseProxyController) InterceptResponses(t *testing.T, rt ResponseTransformer, matchers ...RequestMatcher) (stop func()) { - return -} diff --git a/internal/rp/opts.go b/internal/rp/opts.go deleted file mode 100644 index 6b2cfb5..0000000 --- a/internal/rp/opts.go +++ /dev/null @@ -1,72 +0,0 @@ -package rp - -import ( - "fmt" - "io" - "net/http" - "strings" - "testing" - "time" - - "github.com/tidwall/gjson" -) - -type RequestMatcher func(*http.Request) bool -type ResponseTransformer func(*http.Response) *http.Response - -func RespondWithError(statusCode int, body string) ResponseTransformer { - return nil -} - -func WithUserInfo(t *testing.T, hsURL, userID, deviceID string) RequestMatcher { - c := &http.Client{ - Timeout: 10 * time.Second, - } - accessToken := "" - return func(req *http.Request) bool { - if accessToken == "" { - // figure out who this is - whoami, err := http.NewRequest("GET", fmt.Sprintf("%s/_matrix/client/v3/account/whoami", hsURL), nil) - if err != nil { - t.Errorf("WithUserInfo: failed to create /whoami request: %s", err) // should be unreachable - } - // discard all errors and just don't set the access token. We expect to see some errors here - // as we will be hitting hsURL for users not on that HS. - res, _ := c.Do(whoami) - if res.StatusCode == 200 { - body, err := io.ReadAll(res.Body) - if err != nil { - t.Errorf("WithUserInfo: failed to read /whoami response: %s", err) - } - res.Body.Close() - if !gjson.ValidBytes(body) { - t.Errorf("WithUserInfo: /whoami response is not JSON: %s", string(body)) - } - bodyJSON := gjson.ParseBytes(body) - if userID == bodyJSON.Get("user_id").Str && deviceID == bodyJSON.Get("device_id").Str { - accessToken = strings.TrimPrefix(req.Header.Get("Authorization"), "Bearer ") - t.Logf("WithUserInfo: identified user with token %s", accessToken) - } - } - } - if strings.TrimPrefix(req.Header.Get("Authorization"), "Bearer ") == accessToken { - return true - } - return false // some other user - } -} - -func WithPathSuffix(path string) RequestMatcher { - return func(req *http.Request) bool { - return strings.HasSuffix(req.URL.Path, path) - } -} - -func WithRepititions(num int) RequestMatcher { - seen := 0 - return func(req *http.Request) bool { - allowed := seen < num - seen++ - return allowed - } -} diff --git a/tests/client_connectivity_test.go b/tests/client_connectivity_test.go index 82bbd71..fb4e6a5 100644 --- a/tests/client_connectivity_test.go +++ b/tests/client_connectivity_test.go @@ -11,6 +11,7 @@ import ( "github.com/matrix-org/complement-crypto/internal/api" "github.com/matrix-org/complement-crypto/internal/deploy" templates "github.com/matrix-org/complement-crypto/tests/go_templates" + "github.com/matrix-org/complement/ct" "github.com/matrix-org/complement/helpers" "github.com/matrix-org/complement/must" ) @@ -110,7 +111,7 @@ func TestSigkillBeforeKeysUploadResponseJS(t *testing.T) { if terminated.Load() { // make sure the 2nd upload 200 OKs if cd.ResponseCode != 200 { - api.Errorf(t, "2nd /keys/upload did not 200 OK => got %v", cd.ResponseCode) + ct.Errorf(t, "2nd /keys/upload did not 200 OK => got %v", cd.ResponseCode) } seenSecondKeysUploadWaiter.Finish() return diff --git a/tests/go_templates/templates.go b/tests/go_templates/templates.go index ebc8701..b9200f3 100644 --- a/tests/go_templates/templates.go +++ b/tests/go_templates/templates.go @@ -6,26 +6,26 @@ import ( "path/filepath" "text/template" - "github.com/matrix-org/complement-crypto/internal/api" + "github.com/matrix-org/complement/ct" ) // PrepareGoScript takes a template filename from `./tests/templates` and injects the templateData given // as a Go template. It then runs the file through `go build` and prepares a command to run the resulting // binary. Returns the prepared command and a close function to delete the script and binary. The script // will not execute until you call cmd.Start() or cmd.Run(). -func PrepareGoScript(t api.Test, templatePath string, templateData any) (*exec.Cmd, func()) { +func PrepareGoScript(t ct.TestLike, templatePath string, templateData any) (*exec.Cmd, func()) { _, templateFilename := filepath.Split(templatePath) tmpl, err := template.New(templateFilename).ParseFiles("./go_templates/" + templatePath) if err != nil { - api.Fatalf(t, "failed to parse template %s : %s", templateFilename, err) + ct.Fatalf(t, "failed to parse template %s : %s", templateFilename, err) } scriptFile, err := os.CreateTemp("./go_templates", "script_*.go") if err != nil { - api.Fatalf(t, "failed to open temporary file: %s", err) + ct.Fatalf(t, "failed to open temporary file: %s", err) } defer scriptFile.Close() if err = tmpl.ExecuteTemplate(scriptFile, templateFilename, templateData); err != nil { - api.Fatalf(t, "failed to execute template to file: %s", err) + ct.Fatalf(t, "failed to execute template to file: %s", err) } // TODO: should we build output to the random number? // e.g go build -o ./templates/script ./templates/script_3523965439.go diff --git a/tests/logs/README.md b/tests/logs/README.md new file mode 100644 index 0000000..0225c91 --- /dev/null +++ b/tests/logs/README.md @@ -0,0 +1 @@ +Logs from Rust SDK and JS SDK will be stored in this location. If `COMPLEMENT_CRYPTO_WRITE_CONTAINER_LOGS` is set, container logs are also stored here. \ No newline at end of file diff --git a/tests/main_test.go b/tests/main_test.go index 779ffe0..7c4d882 100644 --- a/tests/main_test.go +++ b/tests/main_test.go @@ -25,7 +25,7 @@ var ( func TestMain(m *testing.M) { complementCryptoConfig = config.NewComplementCryptoConfigFromEnvVars() ssMutex = &sync.Mutex{} - js.SetupJSLogs("js_sdk.log") // rust sdk logs on its own + js.SetupJSLogs("./logs/js_sdk.log") // rust sdk logs on its own complement.TestMainWithCleanup(m, "crypto", func() { // always teardown even if panicking ssMutex.Lock() if ssDeployment != nil {