From 0e35eaa96f77a737f9508e880c01b4bbbb1341f6 Mon Sep 17 00:00:00 2001 From: kegsay Date: Mon, 9 Oct 2023 14:19:53 +0100 Subject: [PATCH] Move Deploy and Waiter to pubic packages (#662) --- helpers/test_package.go | 81 ++++++++++++++++ helpers/waiter.go | 60 ++++++++++++ tests/csapi/main_test.go | 91 ++--------------- tests/csapi/url_preview_test.go | 2 +- tests/federation_event_auth_test.go | 3 +- tests/federation_redaction_test.go | 3 +- ...federation_room_get_missing_events_test.go | 5 +- tests/federation_room_invite_test.go | 7 +- ...federation_room_join_partial_state_test.go | 19 ++-- tests/federation_room_send_test.go | 3 +- tests/knocking_test.go | 5 +- tests/main_test.go | 97 ++----------------- tests/msc2836_test.go | 3 +- 13 files changed, 182 insertions(+), 197 deletions(-) create mode 100644 helpers/test_package.go create mode 100644 helpers/waiter.go diff --git a/helpers/test_package.go b/helpers/test_package.go new file mode 100644 index 00000000..e8c91464 --- /dev/null +++ b/helpers/test_package.go @@ -0,0 +1,81 @@ +package helpers + +import ( + "context" + "fmt" + "log" + "sync/atomic" + "testing" + "time" + + "github.com/matrix-org/complement/b" + "github.com/matrix-org/complement/internal/config" + "github.com/matrix-org/complement/internal/docker" + "github.com/sirupsen/logrus" +) + +// TestPackage represents the configuration for a package of tests. A package of tests +// are all tests in the same Go package (directory). +type TestPackage struct { + // the config used for this package. + Config *config.Complement + // the builder we'll use to make containers + complementBuilder *docker.Builder + // a counter to stop tests from allocating the same container name + namespaceCounter uint64 +} + +// NewTestPackage creates a new test package which can be used to deploy containers for all tests +// in a single package. This should be called from `TestMain` which is the Go-provided entry point +// before any tests run. After the tests have run, call `TestPackage.Cleanup`. Tests can deploy +// containers by calling `TestPackage.Deploy`. +func NewTestPackage(pkgNamespace string) (*TestPackage, error) { + cfg := config.NewConfigFromEnvVars(pkgNamespace, "") + log.Printf("config: %+v", cfg) + builder, err := docker.NewBuilder(cfg) + if err != nil { + return nil, fmt.Errorf("failed to make docker builder: %w", err) + } + // remove any old images/containers/networks in case we died horribly before + builder.Cleanup() + + // we use GMSL which uses logrus by default. We don't want those logs in our test output unless they are Serious. + logrus.SetLevel(logrus.ErrorLevel) + + return &TestPackage{ + complementBuilder: builder, + namespaceCounter: 0, + Config: cfg, + }, nil +} + +func (tp *TestPackage) Cleanup() { + tp.complementBuilder.Cleanup() +} + +// Deploy will deploy the given blueprint or terminate the test. +// It will construct the blueprint if it doesn't already exist in the docker image cache. +// This function is the main setup function for all tests as it provides a deployment with +// which tests can interact with. +func (tp *TestPackage) Deploy(t *testing.T, blueprint b.Blueprint) *docker.Deployment { + t.Helper() + timeStartBlueprint := time.Now() + if tp.complementBuilder == nil { + t.Fatalf("complementBuilder not set, did you forget to call TestMain?") + } + if err := tp.complementBuilder.ConstructBlueprintIfNotExist(blueprint); err != nil { + t.Fatalf("Deploy: Failed to construct blueprint: %s", err) + } + namespace := fmt.Sprintf("%d", atomic.AddUint64(&tp.namespaceCounter, 1)) + d, err := docker.NewDeployer(namespace, tp.complementBuilder.Config) + if err != nil { + t.Fatalf("Deploy: NewDeployer returned error %s", err) + } + timeStartDeploy := time.Now() + dep, err := d.Deploy(context.Background(), blueprint.Name) + if err != nil { + t.Fatalf("Deploy: Deploy returned error %s", err) + } + t.Logf("Deploy times: %v blueprints, %v containers", timeStartDeploy.Sub(timeStartBlueprint), time.Since(timeStartDeploy)) + return dep +} diff --git a/helpers/waiter.go b/helpers/waiter.go new file mode 100644 index 00000000..c528afd8 --- /dev/null +++ b/helpers/waiter.go @@ -0,0 +1,60 @@ +package helpers + +import ( + "fmt" + "sync" + "testing" + "time" +) + +// Waiter is a simple primitive to wait for a signal asynchronously. It is preferred +// over other sync primitives due to having more sensible defaults such as built-in timeouts +// if the signal does not appear and ability to signal more than once without panicking. +type Waiter struct { + mu sync.Mutex + ch chan bool + closed bool +} + +// NewWaiter returns a generic struct which can be waited on until `Waiter.Finish` is called. +// A Waiter is similar to a `sync.WaitGroup` of size 1, but without the ability to underflow and +// with built-in timeouts. +func NewWaiter() *Waiter { + return &Waiter{ + ch: make(chan bool), + mu: sync.Mutex{}, + } +} + +// Wait blocks until Finish() is called or until the timeout is reached. +// If the timeout is reached, the test is failed. +func (w *Waiter) Wait(t *testing.T, timeout time.Duration) { + t.Helper() + w.Waitf(t, timeout, "Wait") +} + +// Waitf blocks until Finish() is called or until the timeout is reached. +// If the timeout is reached, the test is failed with the given error message. +func (w *Waiter) Waitf(t *testing.T, timeout time.Duration, errFormat string, args ...interface{}) { + t.Helper() + select { + case <-w.ch: + return + case <-time.After(timeout): + errmsg := fmt.Sprintf(errFormat, args...) + t.Fatalf("%s: timed out after %f seconds.", errmsg, timeout.Seconds()) + } +} + +// Finish will cause all goroutines waiting via Wait to stop waiting and return. +// Once this function has been called, subsequent calls to Wait will return immediately. +// To begin waiting again, make a new Waiter. +func (w *Waiter) Finish() { + w.mu.Lock() + defer w.mu.Unlock() + if w.closed { + return + } + w.closed = true + close(w.ch) +} diff --git a/tests/csapi/main_test.go b/tests/csapi/main_test.go index f0eae339..56b48fdf 100644 --- a/tests/csapi/main_test.go +++ b/tests/csapi/main_test.go @@ -1,48 +1,30 @@ package csapi_tests import ( - "context" "fmt" - "log" "os" - "sync" - "sync/atomic" "testing" - "time" - - "github.com/sirupsen/logrus" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/config" + "github.com/matrix-org/complement/helpers" "github.com/matrix-org/complement/internal/docker" ) -var namespaceCounter uint64 - -// persist the complement builder which is set when the tests start via TestMain -var complementBuilder *docker.Builder +var testPackage *helpers.TestPackage // TestMain is the main entry point for Complement. // // It will clean up any old containers/images/networks from the previous run, then run the tests, then clean up // again. No blueprints are made at this point as they are lazily made on demand. func TestMain(m *testing.M) { - cfg := config.NewConfigFromEnvVars("csapi", "") - log.Printf("config: %+v", cfg) - builder, err := docker.NewBuilder(cfg) + var err error + testPackage, err = helpers.NewTestPackage("csapi") if err != nil { fmt.Printf("Error: %s", err) os.Exit(1) } - complementBuilder = builder - // remove any old images/containers/networks in case we died horribly before - builder.Cleanup() - - // we use GMSL which uses logrus by default. We don't want those logs in our test output unless they are Serious. - logrus.SetLevel(logrus.ErrorLevel) - exitCode := m.Run() - builder.Cleanup() + testPackage.Cleanup() os.Exit(exitCode) } @@ -52,66 +34,5 @@ func TestMain(m *testing.M) { // which tests can interact with. func Deploy(t *testing.T, blueprint b.Blueprint) *docker.Deployment { t.Helper() - timeStartBlueprint := time.Now() - if complementBuilder == nil { - t.Fatalf("complementBuilder not set, did you forget to call TestMain?") - } - if err := complementBuilder.ConstructBlueprintIfNotExist(blueprint); err != nil { - t.Fatalf("Deploy: Failed to construct blueprint: %s", err) - } - namespace := fmt.Sprintf("%d", atomic.AddUint64(&namespaceCounter, 1)) - d, err := docker.NewDeployer(namespace, complementBuilder.Config) - if err != nil { - t.Fatalf("Deploy: NewDeployer returned error %s", err) - } - timeStartDeploy := time.Now() - dep, err := d.Deploy(context.Background(), blueprint.Name) - if err != nil { - t.Fatalf("Deploy: Deploy returned error %s", err) - } - t.Logf("Deploy times: %v blueprints, %v containers", timeStartDeploy.Sub(timeStartBlueprint), time.Since(timeStartDeploy)) - return dep -} - -// nolint:unused -type Waiter struct { - mu sync.Mutex - ch chan bool - closed bool -} - -// NewWaiter returns a generic struct which can be waited on until `Waiter.Finish` is called. -// A Waiter is similar to a `sync.WaitGroup` of size 1, but without the ability to underflow and -// with built-in timeouts. -// nolint:unused -func NewWaiter() *Waiter { - return &Waiter{ - ch: make(chan bool), - mu: sync.Mutex{}, - } -} - -// Wait blocks until Finish() is called or until the timeout is reached. -// If the timeout is reached, the test is failed. -func (w *Waiter) Wait(t *testing.T, timeout time.Duration) { - t.Helper() - select { - case <-w.ch: - return - case <-time.After(timeout): - t.Fatalf("Wait: timed out after %f seconds.", timeout.Seconds()) - } -} - -// Finish will cause all goroutines waiting via Wait to stop waiting and return. -// Once this function has been called, subsequent calls to Wait will return immediately. -// To begin waiting again, make a new Waiter. -func (w *Waiter) Finish() { - w.mu.Lock() - defer w.mu.Unlock() - if w.closed { - return - } - w.closed = true - close(w.ch) + return testPackage.Deploy(t, blueprint) } diff --git a/tests/csapi/url_preview_test.go b/tests/csapi/url_preview_test.go index f9bd85f9..9da55313 100644 --- a/tests/csapi/url_preview_test.go +++ b/tests/csapi/url_preview_test.go @@ -44,7 +44,7 @@ func TestUrlPreview(t *testing.T) { deployment := Deploy(t, b.BlueprintAlice) defer deployment.Destroy(t) - webServer := web.NewServer(t, complementBuilder.Config, func(router *mux.Router) { + webServer := web.NewServer(t, testPackage.Config, func(router *mux.Router) { router.HandleFunc("/test.png", func(w http.ResponseWriter, req *http.Request) { t.Log("/test.png fetched") diff --git a/tests/federation_event_auth_test.go b/tests/federation_event_auth_test.go index 6404cadb..1f449149 100644 --- a/tests/federation_event_auth_test.go +++ b/tests/federation_event_auth_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/matrix-org/complement/b" + "github.com/matrix-org/complement/helpers" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/must" "github.com/matrix-org/gomatrixserverlib/spec" @@ -34,7 +35,7 @@ func TestEventAuth(t *testing.T) { // create a remote homeserver which will make the /event_auth request var joinRuleEvent gomatrixserverlib.PDU - waiter := NewWaiter() + waiter := helpers.NewWaiter() srv := federation.NewServer(t, deployment, federation.HandleKeyRequests(), federation.HandleMakeSendJoinRequests(), diff --git a/tests/federation_redaction_test.go b/tests/federation_redaction_test.go index 00a86c87..0a82fff6 100644 --- a/tests/federation_redaction_test.go +++ b/tests/federation_redaction_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/matrix-org/complement/b" + "github.com/matrix-org/complement/helpers" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/must" "github.com/matrix-org/complement/runtime" @@ -20,7 +21,7 @@ func TestFederationRedactSendsWithoutEvent(t *testing.T) { alice := deployment.Client(t, "hs1", "@alice:hs1") - waiter := NewWaiter() + waiter := helpers.NewWaiter() wantEventType := "m.room.redaction" // create a remote homeserver diff --git a/tests/federation_room_get_missing_events_test.go b/tests/federation_room_get_missing_events_test.go index e93d0f70..42e2ae33 100644 --- a/tests/federation_room_get_missing_events_test.go +++ b/tests/federation_room_get_missing_events_test.go @@ -16,6 +16,7 @@ import ( "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/client" + "github.com/matrix-org/complement/helpers" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/match" "github.com/matrix-org/complement/must" @@ -246,7 +247,7 @@ func TestOutboundFederationIgnoresMissingEventWithBadJSONForRoomVersion6(t *test }) room.AddEvent(sentEvent) - waiter := NewWaiter() + waiter := helpers.NewWaiter() onGetMissingEvents = func(w http.ResponseWriter, req *http.Request) { defer waiter.Finish() must.MatchRequest(t, req, match.HTTPRequest{ @@ -300,7 +301,7 @@ func TestOutboundFederationIgnoresMissingEventWithBadJSONForRoomVersion6(t *test }) room.AddEvent(message3) - waiter = NewWaiter() + waiter = helpers.NewWaiter() onGetMissingEvents = func(w http.ResponseWriter, req *http.Request) { must.MatchRequest(t, req, match.HTTPRequest{ JSON: []match.JSON{ diff --git a/tests/federation_room_invite_test.go b/tests/federation_room_invite_test.go index a08152c0..daa0668b 100644 --- a/tests/federation_room_invite_test.go +++ b/tests/federation_room_invite_test.go @@ -7,6 +7,7 @@ import ( "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/complement/b" + "github.com/matrix-org/complement/helpers" "github.com/matrix-org/complement/internal/federation" ) @@ -22,7 +23,7 @@ func TestFederationRejectInvite(t *testing.T) { charlie := deployment.Client(t, "hs2", "@charlie:hs2") // we'll awaken this Waiter when we receive a membership event for Charlie - var waiter *Waiter + var waiter *helpers.Waiter srv := federation.NewServer(t, deployment, federation.HandleKeyRequests(), @@ -47,13 +48,13 @@ func TestFederationRejectInvite(t *testing.T) { room := srv.MustJoinRoom(t, deployment, "hs1", roomID, delia) // Alice invites Charlie; Delia should see the invite - waiter = NewWaiter() + waiter = helpers.NewWaiter() alice.InviteRoom(t, roomID, charlie.UserID) waiter.Wait(t, 5*time.Second) room.MustHaveMembershipForUser(t, charlie.UserID, "invite") // Charlie rejects the invite; Delia should see the rejection. - waiter = NewWaiter() + waiter = helpers.NewWaiter() charlie.LeaveRoom(t, roomID) waiter.Wait(t, 5*time.Second) room.MustHaveMembershipForUser(t, charlie.UserID, "leave") diff --git a/tests/federation_room_join_partial_state_test.go b/tests/federation_room_join_partial_state_test.go index 8f83164d..1b9f818e 100644 --- a/tests/federation_room_join_partial_state_test.go +++ b/tests/federation_room_join_partial_state_test.go @@ -20,6 +20,7 @@ import ( "testing" "time" + "github.com/matrix-org/complement/helpers" "github.com/matrix-org/complement/runtime" "github.com/gorilla/mux" @@ -1230,8 +1231,8 @@ func TestPartialStateJoin(t *testing.T) { // we expect a /state_ids request from hs2 after it joins the room // we will respond to the request with garbage - fedStateIdsRequestReceivedWaiter := NewWaiter() - fedStateIdsSendResponseWaiter := NewWaiter() + fedStateIdsRequestReceivedWaiter := helpers.NewWaiter() + fedStateIdsSendResponseWaiter := helpers.NewWaiter() server.Mux().Handle( fmt.Sprintf("/_matrix/federation/v1/state_ids/%s", roomID), http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { @@ -3549,7 +3550,7 @@ func TestPartialStateJoin(t *testing.T) { client.SyncJoinedTo(alice.UserID, serverRoom.RoomID), ) - leaveCompleted := NewWaiter() + leaveCompleted := helpers.NewWaiter() t.Log("Alice starts a leave request") server.AddPDUHandler(func(e gomatrixserverlib.PDU) bool { return true }) go func() { @@ -4232,8 +4233,8 @@ type partialStateJoinResult struct { Server *server ServerRoom *federation.ServerRoom User *client.CSAPI - fedStateIdsRequestReceivedWaiter *Waiter - fedStateIdsSendResponseWaiter *Waiter + fedStateIdsRequestReceivedWaiter *helpers.Waiter + fedStateIdsSendResponseWaiter *helpers.Waiter } // beginPartialStateJoin has a test user attempt to join the given room. @@ -4258,8 +4259,8 @@ func beginPartialStateJoin(t *testing.T, server *server, serverRoom *federation. }() // some things for orchestration - result.fedStateIdsRequestReceivedWaiter = NewWaiter() - result.fedStateIdsSendResponseWaiter = NewWaiter() + result.fedStateIdsRequestReceivedWaiter = helpers.NewWaiter() + result.fedStateIdsSendResponseWaiter = helpers.NewWaiter() // register a handler for /state_ids requests for the most recent event, // which finishes fedStateIdsRequestReceivedWaiter, then @@ -4359,7 +4360,7 @@ func (psj *partialStateJoinResult) FinishStateRequest() { func handleStateIdsRequests( t *testing.T, srv *server, serverRoom *federation.ServerRoom, eventID string, roomState []gomatrixserverlib.PDU, - requestReceivedWaiter *Waiter, sendResponseWaiter *Waiter, + requestReceivedWaiter *helpers.Waiter, sendResponseWaiter *helpers.Waiter, ) { srv.Mux().NewRoute().Methods("GET").Path( fmt.Sprintf("/_matrix/federation/v1/state_ids/%s", serverRoom.RoomID), @@ -4399,7 +4400,7 @@ func handleStateIdsRequests( func handleStateRequests( t *testing.T, srv *server, serverRoom *federation.ServerRoom, eventID string, roomState []gomatrixserverlib.PDU, - requestReceivedWaiter *Waiter, sendResponseWaiter *Waiter, + requestReceivedWaiter *helpers.Waiter, sendResponseWaiter *helpers.Waiter, ) { srv.Mux().NewRoute().Methods("GET").Path( fmt.Sprintf("/_matrix/federation/v1/state/%s", serverRoom.RoomID), diff --git a/tests/federation_room_send_test.go b/tests/federation_room_send_test.go index 85568798..f399b981 100644 --- a/tests/federation_room_send_test.go +++ b/tests/federation_room_send_test.go @@ -7,6 +7,7 @@ import ( "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/complement/b" + "github.com/matrix-org/complement/helpers" "github.com/matrix-org/complement/internal/federation" ) @@ -23,7 +24,7 @@ func TestOutboundFederationSend(t *testing.T) { alice := deployment.Client(t, "hs1", "@alice:hs1") - waiter := NewWaiter() + waiter := helpers.NewWaiter() wantEventType := "m.room.message" // create a remote homeserver diff --git a/tests/knocking_test.go b/tests/knocking_test.go index 372cdc60..9784bf12 100644 --- a/tests/knocking_test.go +++ b/tests/knocking_test.go @@ -21,6 +21,7 @@ import ( "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/client" + "github.com/matrix-org/complement/helpers" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/match" "github.com/matrix-org/complement/must" @@ -54,7 +55,7 @@ func doTestKnocking(t *testing.T, roomVersion string, joinRule string) { charlie := deployment.Client(t, "hs2", charlieUserID) // Create a server to observe - inviteWaiter := NewWaiter() + inviteWaiter := helpers.NewWaiter() srv := federation.NewServer(t, deployment, federation.HandleKeyRequests(), federation.HandleInviteRequests(func(ev gomatrixserverlib.PDU) { @@ -90,7 +91,7 @@ func doTestKnocking(t *testing.T, roomVersion string, joinRule string) { "private_chat", // Set to private in order to get an invite-only room roomVersion, }) - inviteWaiter = NewWaiter() + inviteWaiter = helpers.NewWaiter() alice.InviteRoom(t, roomIDTwo, david) inviteWaiter.Wait(t, 5*time.Second) serverRoomTwo := srv.MustJoinRoom(t, deployment, "hs1", roomIDTwo, david) diff --git a/tests/main_test.go b/tests/main_test.go index 8d5a88e9..201f672b 100644 --- a/tests/main_test.go +++ b/tests/main_test.go @@ -1,48 +1,30 @@ package tests import ( - "context" "fmt" - "log" "os" - "sync" - "sync/atomic" "testing" - "time" - - "github.com/sirupsen/logrus" "github.com/matrix-org/complement/b" - "github.com/matrix-org/complement/internal/config" + "github.com/matrix-org/complement/helpers" "github.com/matrix-org/complement/internal/docker" ) -var namespaceCounter uint64 - -// persist the complement builder which is set when the tests start via TestMain -var complementBuilder *docker.Builder +var testPackage *helpers.TestPackage // TestMain is the main entry point for Complement. // // It will clean up any old containers/images/networks from the previous run, then run the tests, then clean up // again. No blueprints are made at this point as they are lazily made on demand. func TestMain(m *testing.M) { - cfg := config.NewConfigFromEnvVars("fed", "") - log.Printf("config: %+v", cfg) - builder, err := docker.NewBuilder(cfg) + var err error + testPackage, err = helpers.NewTestPackage("fed") if err != nil { fmt.Printf("Error: %s", err) os.Exit(1) } - complementBuilder = builder - // remove any old images/containers/networks in case we died horribly before - builder.Cleanup() - - // we use GMSL which uses logrus by default. We don't want those logs in our test output unless they are Serious. - logrus.SetLevel(logrus.ErrorLevel) - exitCode := m.Run() - builder.Cleanup() + testPackage.Cleanup() os.Exit(exitCode) } @@ -52,72 +34,5 @@ func TestMain(m *testing.M) { // which tests can interact with. func Deploy(t *testing.T, blueprint b.Blueprint) *docker.Deployment { t.Helper() - timeStartBlueprint := time.Now() - if complementBuilder == nil { - t.Fatalf("complementBuilder not set, did you forget to call TestMain?") - } - if err := complementBuilder.ConstructBlueprintIfNotExist(blueprint); err != nil { - t.Fatalf("Deploy: Failed to construct blueprint: %s", err) - } - namespace := fmt.Sprintf("%d", atomic.AddUint64(&namespaceCounter, 1)) - d, err := docker.NewDeployer(namespace, complementBuilder.Config) - if err != nil { - t.Fatalf("Deploy: NewDeployer returned error %s", err) - } - timeStartDeploy := time.Now() - dep, err := d.Deploy(context.Background(), blueprint.Name) - if err != nil { - t.Fatalf("Deploy: Deploy returned error %s", err) - } - t.Logf("Deploy times: %v blueprints, %v containers", timeStartDeploy.Sub(timeStartBlueprint), time.Since(timeStartDeploy)) - return dep -} - -type Waiter struct { - mu sync.Mutex - ch chan bool - closed bool -} - -// NewWaiter returns a generic struct which can be waited on until `Waiter.Finish` is called. -// A Waiter is similar to a `sync.WaitGroup` of size 1, but without the ability to underflow and -// with built-in timeouts. -func NewWaiter() *Waiter { - return &Waiter{ - ch: make(chan bool), - mu: sync.Mutex{}, - } -} - -// Wait blocks until Finish() is called or until the timeout is reached. -// If the timeout is reached, the test is failed. -func (w *Waiter) Wait(t *testing.T, timeout time.Duration) { - t.Helper() - w.Waitf(t, timeout, "Wait") -} - -// Waitf blocks until Finish() is called or until the timeout is reached. -// If the timeout is reached, the test is failed with the given error message. -func (w *Waiter) Waitf(t *testing.T, timeout time.Duration, errFormat string, args ...interface{}) { - t.Helper() - select { - case <-w.ch: - return - case <-time.After(timeout): - errmsg := fmt.Sprintf(errFormat, args...) - t.Fatalf("%s: timed out after %f seconds.", errmsg, timeout.Seconds()) - } -} - -// Finish will cause all goroutines waiting via Wait to stop waiting and return. -// Once this function has been called, subsequent calls to Wait will return immediately. -// To begin waiting again, make a new Waiter. -func (w *Waiter) Finish() { - w.mu.Lock() - defer w.mu.Unlock() - if w.closed { - return - } - w.closed = true - close(w.ch) + return testPackage.Deploy(t, blueprint) } diff --git a/tests/msc2836_test.go b/tests/msc2836_test.go index 582d3392..fa1402b7 100644 --- a/tests/msc2836_test.go +++ b/tests/msc2836_test.go @@ -21,6 +21,7 @@ import ( "github.com/matrix-org/complement/b" "github.com/matrix-org/complement/client" + "github.com/matrix-org/complement/helpers" "github.com/matrix-org/complement/internal/federation" "github.com/matrix-org/complement/match" "github.com/matrix-org/complement/must" @@ -266,7 +267,7 @@ func TestFederatedEventRelationships(t *testing.T) { t.Logf("D: %s", eventD.EventID()) // we expect to be called with event D, and will return D,C,B,A - waiter := NewWaiter() + waiter := helpers.NewWaiter() srv.Mux().HandleFunc("/_matrix/federation/unstable/event_relationships", func(w http.ResponseWriter, req *http.Request) { defer waiter.Finish() must.MatchRequest(t, req, match.HTTPRequest{