diff --git a/tests/driver/driver.go b/tests/driver/driver.go new file mode 100644 index 0000000..dea9e9e --- /dev/null +++ b/tests/driver/driver.go @@ -0,0 +1,6 @@ +package driver + +type Driver interface { + // WithAuth sets the authentication context to be used by this driver. + WithAuth() +} diff --git a/tests/driver/http.go b/tests/driver/http.go index cb27c3a..fe022cc 100644 --- a/tests/driver/http.go +++ b/tests/driver/http.go @@ -2,6 +2,7 @@ package driver import ( "bytes" + "context" "encoding/json" "fmt" "io" @@ -44,7 +45,7 @@ func (driver *HTTPDriver) newRequest(method, url string, body io.Reader) (*http. return req, nil } -func (driver *HTTPDriver) ResolvePURL(domain string, name string) (*url.URL, error) { +func (driver *HTTPDriver) ResolvePURL(_ context.Context, domain string, name string) (*url.URL, error) { req, err := driver.newRequest(http.MethodGet, fmt.Sprintf("%s/r/%s/%s", driver.BasePath, domain, name), nil) if err != nil { return nil, err @@ -72,7 +73,7 @@ func (driver *HTTPDriver) ResolvePURL(domain string, name string) (*url.URL, err return loc, nil } -func (driver *HTTPDriver) SavePURL(purl *dsl.PURL) (string, error) { +func (driver *HTTPDriver) SavePURL(_ context.Context, purl *dsl.PURL) (string, error) { body := bytes.NewBuffer([]byte{}) err := json.NewEncoder(body).Encode(map[string]string{ "target": purl.Target.String(), @@ -107,7 +108,7 @@ func (driver *HTTPDriver) SavePURL(purl *dsl.PURL) (string, error) { return r.Path, nil } -func (driver *HTTPDriver) CreateDomain(name string) error { +func (driver *HTTPDriver) CreateDomain(_ context.Context, name string) error { req, err := driver.newRequest(http.MethodPost, fmt.Sprintf("%s/a/domains/%s", driver.BasePath, name), nil) if err != nil { return err diff --git a/tests/dsl/apis.go b/tests/dsl/apis.go index f07354a..82b16dc 100644 --- a/tests/dsl/apis.go +++ b/tests/dsl/apis.go @@ -1,22 +1,25 @@ package dsl -import "net/url" +import ( + "context" + "net/url" +) // AdminAPI defines admin features of the application. type AdminAPI interface { - CreateDomain(name string) error + CreateDomain(ctx context.Context, name string) error // SavePURL creates a new or updates an existing purl. // // If no error occurred the returned string is the path (without host) of the created PURL. - SavePURL(purl *PURL) (string, error) + SavePURL(ctx context.Context, purl *PURL) (string, error) } // ResolveAPI defines features for PURL resolution. type ResolveAPI interface { // ResolvePURL resolves the PURL identified by domain and name, returning // the target of the resolved PURL. - ResolvePURL(domain string, name string) (*url.URL, error) + ResolvePURL(ctx context.Context, domain string, name string) (*url.URL, error) } // API aggregates all apis. diff --git a/tests/dsl/given.go b/tests/dsl/given.go index 44ad9bc..cd45f35 100644 --- a/tests/dsl/given.go +++ b/tests/dsl/given.go @@ -1,6 +1,7 @@ package dsl import ( + "context" "testing" "github.com/fabiante/persurl/app" @@ -11,8 +12,8 @@ import ( // GivenExistingPURL ensures that a PURL is known to the application. // // This is done by simply creating it. -func GivenExistingPURL(t *testing.T, service AdminAPI, purl *PURL) { - path, err := service.SavePURL(purl) +func GivenExistingPURL(ctx context.Context, t *testing.T, service AdminAPI, purl *PURL) { + path, err := service.SavePURL(ctx, purl) require.NoError(t, err, "saving purl failed") require.NotEmpty(t, path) } @@ -20,13 +21,13 @@ func GivenExistingPURL(t *testing.T, service AdminAPI, purl *PURL) { // GivenExistingDomain ensures that a Domain is known to the application. // // This currently is a no-op since domains can't explicitly be created. -func GivenExistingDomain(t *testing.T, service AdminAPI, domain string) { - err := service.CreateDomain(domain) +func GivenExistingDomain(ctx context.Context, t *testing.T, service AdminAPI, domain string) { + err := service.CreateDomain(ctx, domain) require.NoError(t, err, "creating domain failed") } // GivenSomeUser creates a user and returns the key for it. -func GivenSomeUser(t *testing.T, userService *app.UserService) *models.UserKey { +func GivenSomeUser(_ context.Context, t *testing.T, userService *app.UserService) *models.UserKey { user, err := userService.CreateUser("test@local.com") require.NoError(t, err) diff --git a/tests/http_load_test.go b/tests/http_load_test.go index 2b9a1e0..47033c9 100644 --- a/tests/http_load_test.go +++ b/tests/http_load_test.go @@ -1,6 +1,7 @@ package tests import ( + "context" "net/http" "net/http/httptest" "testing" @@ -17,6 +18,8 @@ import ( ) func TestLoadWithHTTPDriver(t *testing.T) { + ctx := context.TODO() + conf := config.Get() if !conf.TestLoad { @@ -35,7 +38,7 @@ func TestLoadWithHTTPDriver(t *testing.T) { service := app.NewService(database.Gorm) userService := app.NewUserService(database.Gorm) - key := dsl.GivenSomeUser(t, userService) + key := dsl.GivenSomeUser(ctx, t, userService) server := api.NewServer(service, service, userService) api.SetupRouting(handler, server) diff --git a/tests/http_test.go b/tests/http_test.go index c006de4..3da76d5 100644 --- a/tests/http_test.go +++ b/tests/http_test.go @@ -1,6 +1,7 @@ package tests import ( + "context" "net/http" "net/http/httptest" "testing" @@ -17,6 +18,7 @@ import ( ) func TestWithHTTPDriver(t *testing.T) { + ctx := context.TODO() gin.SetMode(gin.TestMode) handler := gin.Default() @@ -29,7 +31,7 @@ func TestWithHTTPDriver(t *testing.T) { service := app.NewService(database.Gorm) userService := app.NewUserService(database.Gorm) - key := dsl.GivenSomeUser(t, userService) + key := dsl.GivenSomeUser(ctx, t, userService) server := api.NewServer(service, service, userService) api.SetupRouting(handler, server) diff --git a/tests/load/agent_create.go b/tests/load/agent_create.go index 772076d..7846f1b 100644 --- a/tests/load/agent_create.go +++ b/tests/load/agent_create.go @@ -1,6 +1,7 @@ package load import ( + "context" "fmt" "net/url" "sync" @@ -31,13 +32,15 @@ func NewCreateAgent(id int, domain string, createInterval time.Duration, API dsl // // Run ensures that the agent's Domain exists before starting to create PURLs. // -// The agent runs until a message is sent to the done channel. It will then decrement the given wait group. +// The agent runs until the given context is cancelled. It will then decrement the given wait group. // // You should use this method in a dedicated goroutine as this is a blocking function. -func (a *CreateAgent) Run(t *testing.T, done <-chan struct{}, wg *sync.WaitGroup) { +func (a *CreateAgent) Run(t *testing.T, ctx context.Context, wg *sync.WaitGroup) { defer wg.Done() - dsl.GivenExistingDomain(t, a.API, a.Domain) + done := ctx.Done() + + dsl.GivenExistingDomain(ctx, t, a.API, a.Domain) target, _ := url.Parse("https://google.com") i := 0 @@ -45,7 +48,7 @@ func (a *CreateAgent) Run(t *testing.T, done <-chan struct{}, wg *sync.WaitGroup for { name := fmt.Sprintf("purl-%d", i) - path, err := a.API.SavePURL(dsl.NewPURL(a.Domain, name, target)) + path, err := a.API.SavePURL(ctx, dsl.NewPURL(a.Domain, name, target)) require.NoError(t, err) require.NotEmpty(t, path) diff --git a/tests/specs/admin.go b/tests/specs/admin.go index 7d04838..75707fc 100644 --- a/tests/specs/admin.go +++ b/tests/specs/admin.go @@ -1,6 +1,7 @@ package specs import ( + "context" "fmt" "testing" @@ -17,6 +18,8 @@ func TestAdministration(t *testing.T, admin dsl.AdminAPI) { } func testPurlAdmin(t *testing.T, admin dsl.AdminAPI) { + ctx := context.TODO() + t.Run("can't create invalid PURL", func(t *testing.T) { invalid := []*dsl.PURL{ // empty @@ -33,11 +36,11 @@ func testPurlAdmin(t *testing.T, admin dsl.AdminAPI) { dsl.NewPURL("valid", "`", mustParseURL("example.com")), } - dsl.GivenExistingDomain(t, admin, "valid") + dsl.GivenExistingDomain(ctx, t, admin, "valid") for i, purl := range invalid { t.Run(fmt.Sprintf("invalid[%d]", i), func(t *testing.T) { - _, err := admin.SavePURL(purl) + _, err := admin.SavePURL(ctx, purl) require.Error(t, err) //require.ErrorIs(t, err, app.ErrBadRequest) // TODO: Some tests cause a 404 with the http driver. }) @@ -48,13 +51,13 @@ func testPurlAdmin(t *testing.T, admin dsl.AdminAPI) { domain := "this-domain-does-not-exist-it-should-not" purl := dsl.NewPURL(domain, "my-name3456334654645663456", mustParseURL("https://google.com")) - _, err := admin.SavePURL(purl) + _, err := admin.SavePURL(ctx, purl) require.ErrorIs(t, err, app.ErrBadRequest) }) t.Run("can create new PURL", func(t *testing.T) { domain := "my-domain-123456" - dsl.GivenExistingDomain(t, admin, domain) + dsl.GivenExistingDomain(ctx, t, admin, domain) validPurls := []*dsl.PURL{ dsl.NewPURL(domain, "my-name3456345663456", mustParseURL("https://google.com")), @@ -64,7 +67,7 @@ func testPurlAdmin(t *testing.T, admin dsl.AdminAPI) { for i, purl := range validPurls { t.Run(fmt.Sprintf("valid[%d]", i), func(t *testing.T) { // TODO: Assert non-existence of purl to be created - path, err := admin.SavePURL(purl) + path, err := admin.SavePURL(ctx, purl) require.NoError(t, err, "creating purl failed") require.NotEmpty(t, path) }) @@ -75,13 +78,13 @@ func testPurlAdmin(t *testing.T, admin dsl.AdminAPI) { domain := "my-domain-123456789" purl := dsl.NewPURL(domain, "my-name3458904562454564565467", mustParseURL("https://google.com")) - dsl.GivenExistingDomain(t, admin, domain) - dsl.GivenExistingPURL(t, admin, purl) + dsl.GivenExistingDomain(ctx, t, admin, domain) + dsl.GivenExistingPURL(ctx, t, admin, purl) // modify purl's name - updating the target would be the usual case but that is harder to assert. purl.Name = "my-new-name-updated" - path, err := admin.SavePURL(purl) + path, err := admin.SavePURL(ctx, purl) require.NoError(t, err, "updating existing purl failed") require.NotEmpty(t, path) require.Contains(t, path, "my-new-name-updated") @@ -89,6 +92,8 @@ func testPurlAdmin(t *testing.T, admin dsl.AdminAPI) { } func testDomainAdmin(t *testing.T, admin dsl.AdminAPI) { + ctx := context.TODO() + t.Run("can't create invalid domain", func(t *testing.T) { invalid := []string{ // empty @@ -107,7 +112,7 @@ func testDomainAdmin(t *testing.T, admin dsl.AdminAPI) { for i, domain := range invalid { t.Run(fmt.Sprintf("invalid[%d]", i), func(t *testing.T) { - err := admin.CreateDomain(domain) + err := admin.CreateDomain(ctx, domain) require.Error(t, err) //require.ErrorIs(t, err, app.ErrBadRequest) // TODO: Some tests cause a 404 with the http driver. }) @@ -122,7 +127,7 @@ func testDomainAdmin(t *testing.T, admin dsl.AdminAPI) { for i, v := range valid { t.Run(fmt.Sprintf("valid[%d]", i), func(*testing.T) { - err := admin.CreateDomain(v) + err := admin.CreateDomain(ctx, v) require.NoError(t, err) }) } @@ -130,8 +135,8 @@ func testDomainAdmin(t *testing.T, admin dsl.AdminAPI) { t.Run("can't create duplicate domain", func(t *testing.T) { domain := "should-exist-once-4357824758wr47895645" - dsl.GivenExistingDomain(t, admin, domain) - err := admin.CreateDomain("should-exist-once-4357824758wr47895645") + dsl.GivenExistingDomain(ctx, t, admin, domain) + err := admin.CreateDomain(ctx, "should-exist-once-4357824758wr47895645") require.Error(t, err) require.ErrorIs(t, err, app.ErrBadRequest) }) diff --git a/tests/specs/load.go b/tests/specs/load.go index f058092..80ccd0a 100644 --- a/tests/specs/load.go +++ b/tests/specs/load.go @@ -64,13 +64,12 @@ func TestLoad(t *testing.T, api dsl.API) { for i, test := range tests { t.Run(fmt.Sprintf("tests[%d] create:%d", i, test.CreateAgents), func(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) - done := ctx.Done() wg := &sync.WaitGroup{} for j := 0; j < test.CreateAgents; j++ { agent := load.NewCreateAgent(j, fmt.Sprintf("agent-%d-%d", i, j), test.CreateInterval, api) wg.Add(1) - go agent.Run(t, done, wg) + go agent.Run(t, ctx, wg) } time.Sleep(test.Duration) diff --git a/tests/specs/resolve.go b/tests/specs/resolve.go index a2c3efb..59d4a92 100644 --- a/tests/specs/resolve.go +++ b/tests/specs/resolve.go @@ -1,6 +1,7 @@ package specs import ( + "context" "testing" "github.com/fabiante/persurl/app" @@ -9,12 +10,14 @@ import ( ) func TestResolver(t *testing.T, resolver dsl.API) { + ctx := context.TODO() + t.Run("resolver", func(t *testing.T) { t.Run("does not resolve non-existent domain", func(t *testing.T) { domain := "something-very-stupid-9873214356" name := "should-not-exist" - purl, err := resolver.ResolvePURL(domain, name) + purl, err := resolver.ResolvePURL(ctx, domain, name) require.Error(t, err) require.ErrorIs(t, err, app.ErrNotFound) require.Nil(t, purl) @@ -24,9 +27,9 @@ func TestResolver(t *testing.T, resolver dsl.API) { domain := "something-very-stupid-34563456" name := "should-not-exist" - dsl.GivenExistingDomain(t, resolver, domain) + dsl.GivenExistingDomain(ctx, t, resolver, domain) - purl, err := resolver.ResolvePURL(domain, name) + purl, err := resolver.ResolvePURL(ctx, domain, name) require.Error(t, err) require.ErrorIs(t, err, app.ErrNotFound) require.Nil(t, purl) @@ -36,10 +39,10 @@ func TestResolver(t *testing.T, resolver dsl.API) { domain := "my-domain" name := "my-name" - dsl.GivenExistingDomain(t, resolver, domain) - dsl.GivenExistingPURL(t, resolver, dsl.NewPURL(domain, name, mustParseURL("https://google.com"))) + dsl.GivenExistingDomain(ctx, t, resolver, domain) + dsl.GivenExistingPURL(ctx, t, resolver, dsl.NewPURL(domain, name, mustParseURL("https://google.com"))) - purl, err := resolver.ResolvePURL(domain, name) + purl, err := resolver.ResolvePURL(ctx, domain, name) require.NoError(t, err) require.NotNil(t, purl) })