From 50bd0658d6265ecdc665c06b2dd1a7b8f2f76147 Mon Sep 17 00:00:00 2001 From: Eric Wollesen Date: Fri, 4 Oct 2024 11:16:17 -0600 Subject: [PATCH 1/8] add a comment to declare the goal --- service/service/DEPRECATED_service.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/service/service/DEPRECATED_service.go b/service/service/DEPRECATED_service.go index 5240c8f40e..b3a64b0d33 100644 --- a/service/service/DEPRECATED_service.go +++ b/service/service/DEPRECATED_service.go @@ -14,6 +14,10 @@ type DEPRECATEDService struct { authClient *authClient.Client } +// NewDEPRECATEDService is only used by the data service. Let's see if we can figure out how +// to finally deprecate it. What replaces it? Well, the platform/service/service.Service of +// course, which you can find in service/service/service.go. There's a YO DAWG meme in there +// somewhere. func NewDEPRECATEDService() *DEPRECATEDService { return &DEPRECATEDService{ Application: application.New(), From acf2d47743438255f3edc91d2cd3dd25fd55bd9e Mon Sep 17 00:00:00 2001 From: Eric Wollesen Date: Fri, 4 Oct 2024 11:18:03 -0600 Subject: [PATCH 2/8] run the deprecated service contemporarily with the new service code --- data/service/service/standard.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/data/service/service/standard.go b/data/service/service/standard.go index 80911f4b20..bb32b09cd8 100644 --- a/data/service/service/standard.go +++ b/data/service/service/standard.go @@ -5,12 +5,12 @@ import ( "log" "os" - "github.com/tidepool-org/platform/clinics" - "github.com/IBM/sarama" + eventsCommon "github.com/tidepool-org/go-common/events" "github.com/tidepool-org/platform/application" + "github.com/tidepool-org/platform/clinics" dataDeduplicatorDeduplicator "github.com/tidepool-org/platform/data/deduplicator/deduplicator" dataDeduplicatorFactory "github.com/tidepool-org/platform/data/deduplicator/factory" dataEvents "github.com/tidepool-org/platform/data/events" @@ -34,7 +34,8 @@ import ( ) type Standard struct { - *service.DEPRECATEDService + *service.Service + deprecatedService *service.DEPRECATEDService metricClient *metricClient.Client permissionClient *permissionClient.Client dataDeduplicatorFactory *dataDeduplicatorFactory.Factory @@ -51,12 +52,16 @@ type Standard struct { func NewStandard() *Standard { return &Standard{ - DEPRECATEDService: service.NewDEPRECATEDService(), + deprecatedService: service.NewDEPRECATEDService(), + Service: service.New(), } } func (s *Standard) Initialize(provider application.Provider) error { - if err := s.DEPRECATEDService.Initialize(provider); err != nil { + if err := s.deprecatedService.Initialize(provider); err != nil { + return err + } + if err := s.Service.Initialize(provider); err != nil { return err } @@ -128,7 +133,8 @@ func (s *Standard) Terminate() { s.permissionClient = nil s.metricClient = nil - s.DEPRECATEDService.Terminate() + s.Service.Terminate() + s.deprecatedService.Terminate() } func (s *Standard) Run() error { From 1c523f8167899942e529d8564a4122524ee249a6 Mon Sep 17 00:00:00 2001 From: Eric Wollesen Date: Fri, 4 Oct 2024 11:20:45 -0600 Subject: [PATCH 3/8] remove the deprecated service --- data/service/service/standard.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/data/service/service/standard.go b/data/service/service/standard.go index bb32b09cd8..7e6d40a925 100644 --- a/data/service/service/standard.go +++ b/data/service/service/standard.go @@ -35,7 +35,6 @@ import ( type Standard struct { *service.Service - deprecatedService *service.DEPRECATEDService metricClient *metricClient.Client permissionClient *permissionClient.Client dataDeduplicatorFactory *dataDeduplicatorFactory.Factory @@ -52,15 +51,11 @@ type Standard struct { func NewStandard() *Standard { return &Standard{ - deprecatedService: service.NewDEPRECATEDService(), - Service: service.New(), + Service: service.New(), } } func (s *Standard) Initialize(provider application.Provider) error { - if err := s.deprecatedService.Initialize(provider); err != nil { - return err - } if err := s.Service.Initialize(provider); err != nil { return err } @@ -133,8 +128,7 @@ func (s *Standard) Terminate() { s.permissionClient = nil s.metricClient = nil - s.Service.Terminate() - s.deprecatedService.Terminate() + s.Terminate() } func (s *Standard) Run() error { From 71f63c4a66fd28b9a694eb7d0f69cbda884af850 Mon Sep 17 00:00:00 2001 From: Eric Wollesen Date: Fri, 4 Oct 2024 11:42:50 -0600 Subject: [PATCH 4/8] minimal modifications of the deprecated service tests, to test the new service The AuthClient test removal is the only thing I find in any way controversial here. That test requests the auth client, then calls a method on it, to ensure that it returns what is expected. However, since the new service doesn't initialize that auth client itself, rather, it's just returning whatever is passed to it via a setter, there's no point in testing this here. --- data/service/service/client_test.go | 8 -- data/service/service/service_suite_test.go | 11 --- data/service/service/standard_test.go | 8 -- service/service/DEPRECATED_service.go | 97 ---------------------- service/service/DEPRECATED_service_test.go | 28 +++---- 5 files changed, 14 insertions(+), 138 deletions(-) delete mode 100644 data/service/service/client_test.go delete mode 100644 data/service/service/service_suite_test.go delete mode 100644 data/service/service/standard_test.go delete mode 100644 service/service/DEPRECATED_service.go diff --git a/data/service/service/client_test.go b/data/service/service/client_test.go deleted file mode 100644 index 9a8a94e85d..0000000000 --- a/data/service/service/client_test.go +++ /dev/null @@ -1,8 +0,0 @@ -package service_test - -import ( - . "github.com/onsi/ginkgo/v2" -) - -var _ = Describe("Client", func() { -}) diff --git a/data/service/service/service_suite_test.go b/data/service/service/service_suite_test.go deleted file mode 100644 index f257c20c7d..0000000000 --- a/data/service/service/service_suite_test.go +++ /dev/null @@ -1,11 +0,0 @@ -package service_test - -import ( - "testing" - - "github.com/tidepool-org/platform/test" -) - -func TestSuite(t *testing.T) { - test.Test(t) -} diff --git a/data/service/service/standard_test.go b/data/service/service/standard_test.go deleted file mode 100644 index 0f13ddfc85..0000000000 --- a/data/service/service/standard_test.go +++ /dev/null @@ -1,8 +0,0 @@ -package service_test - -import ( - . "github.com/onsi/ginkgo/v2" -) - -var _ = Describe("Standard", func() { -}) diff --git a/service/service/DEPRECATED_service.go b/service/service/DEPRECATED_service.go deleted file mode 100644 index b3a64b0d33..0000000000 --- a/service/service/DEPRECATED_service.go +++ /dev/null @@ -1,97 +0,0 @@ -package service - -import ( - "github.com/tidepool-org/platform/application" - "github.com/tidepool-org/platform/auth" - authClient "github.com/tidepool-org/platform/auth/client" - "github.com/tidepool-org/platform/errors" - "github.com/tidepool-org/platform/platform" -) - -type DEPRECATEDService struct { - *application.Application - secret string - authClient *authClient.Client -} - -// NewDEPRECATEDService is only used by the data service. Let's see if we can figure out how -// to finally deprecate it. What replaces it? Well, the platform/service/service.Service of -// course, which you can find in service/service/service.go. There's a YO DAWG meme in there -// somewhere. -func NewDEPRECATEDService() *DEPRECATEDService { - return &DEPRECATEDService{ - Application: application.New(), - } -} - -func (d *DEPRECATEDService) Initialize(provider application.Provider) error { - if err := d.Application.Initialize(provider); err != nil { - return err - } - - if err := d.initializeSecret(); err != nil { - return err - } - return d.initializeAuthClient() -} - -func (d *DEPRECATEDService) Terminate() { - if d.authClient != nil { - d.authClient.Close() - d.authClient = nil - } - d.secret = "" - - d.Application.Terminate() -} - -func (d *DEPRECATEDService) Secret() string { - return d.secret -} - -func (d *DEPRECATEDService) AuthClient() auth.Client { - return d.authClient -} - -func (d *DEPRECATEDService) initializeSecret() error { - d.Logger().Debug("Initializing secret") - - secret := d.ConfigReporter().GetWithDefault("secret", "") - if secret == "" { - return errors.New("secret is missing") - } - d.secret = secret - - return nil -} - -func (d *DEPRECATEDService) initializeAuthClient() error { - d.Logger().Debug("Loading auth client config") - - cfg := authClient.NewConfig() - cfg.UserAgent = d.UserAgent() - cfg.ExternalConfig.UserAgent = d.UserAgent() - reporter := d.ConfigReporter().WithScopes("auth", "client") - ext := authClient.NewExternalConfigReporterLoader(reporter.WithScopes("external")) - plt := platform.NewConfigReporterLoader(reporter) - loader := authClient.NewConfigLoader(ext, plt) - if err := cfg.Load(loader); err != nil { - return errors.Wrap(err, "unable to load auth client config") - } - - d.Logger().Debug("Creating auth client") - - clnt, err := authClient.NewClient(cfg, platform.AuthorizeAsService, d.Name(), d.Logger()) - if err != nil { - return errors.Wrap(err, "unable to create auth client") - } - d.authClient = clnt - - d.Logger().Debug("Starting auth client") - - if err = d.authClient.Start(); err != nil { - return errors.Wrap(err, "unable to start auth client") - } - - return nil -} diff --git a/service/service/DEPRECATED_service_test.go b/service/service/DEPRECATED_service_test.go index 95e148f7be..7d972fc766 100644 --- a/service/service/DEPRECATED_service_test.go +++ b/service/service/DEPRECATED_service_test.go @@ -11,23 +11,26 @@ import ( authTest "github.com/tidepool-org/platform/auth/test" configTest "github.com/tidepool-org/platform/config/test" serviceService "github.com/tidepool-org/platform/service/service" + testHttp "github.com/tidepool-org/platform/test/http" ) var _ = Describe("DEPRECATEDService", func() { Context("NewDEPRECATEDService", func() { It("returns successfully", func() { - Expect(serviceService.NewDEPRECATEDService()).ToNot(BeNil()) + Expect(serviceService.New()).ToNot(BeNil()) }) }) Context("with started server, config reporter, and new service", func() { var provider *applicationTest.Provider - var svc *serviceService.DEPRECATEDService + //var svc *serviceService.DEPRECATEDService + var svc *serviceService.Service var serverSecret string var sessionToken string var server *Server var authClientConfig map[string]interface{} var serviceConfig map[string]interface{} + var serverConfig map[string]interface{} BeforeEach(func() { provider = applicationTest.NewProviderWithDefaults() @@ -54,15 +57,20 @@ var _ = Describe("DEPRECATEDService", func() { "server_session_token_secret": serverSecret, }, } + serverConfig = map[string]interface{}{ + "address": testHttp.NewAddress(), + "tls": "false", + } serviceConfig = map[string]interface{}{ "secret": authTest.NewServiceSecret(), + "server": serverConfig, "auth": map[string]interface{}{ "client": authClientConfig, }, } (*provider.ConfigReporterOutput).(*configTest.Reporter).Config = serviceConfig - svc = serviceService.NewDEPRECATEDService() + svc = serviceService.New() Expect(svc).ToNot(BeNil()) }) @@ -88,9 +96,9 @@ var _ = Describe("DEPRECATEDService", func() { Expect(svc.Initialize(provider)).To(MatchError("secret is missing")) }) - It("returns an error when the auth client cannot be initialized", func() { - delete(authClientConfig, "address") - Expect(svc.Initialize(provider)).To(MatchError("unable to create auth client; config is invalid; address is missing")) + It("returns an error when the server cannot be initialized", func() { + delete(serverConfig, "address") + Expect(svc.Initialize(provider)).To(MatchError("unable to create server; config is invalid; address is missing")) }) It("returns successfully", func() { @@ -114,14 +122,6 @@ var _ = Describe("DEPRECATEDService", func() { Expect(svc.Secret()).To(Equal(serviceConfig["secret"])) }) }) - - Context("AuthClient", func() { - It("returns successfully with server token", func() { - authClient := svc.AuthClient() - Expect(authClient).ToNot(BeNil()) - Eventually(authClient.ServerSessionToken).Should(Equal(sessionToken)) - }) - }) }) }) }) From bbb7a49889cd0613b3d55529cd7bbc141f26ed35 Mon Sep 17 00:00:00 2001 From: Eric Wollesen Date: Fri, 4 Oct 2024 14:38:26 -0600 Subject: [PATCH 5/8] restore the deprecated service tests, applied to Authenticated The previous commit did drop one test, because it didn't apply to the new Service. That test does apply to Authenticated however. This commit restores that test, which checks that the configuration passed to the service via the config reporter is able to successfully initialize an authentication client. --- data/service/service/standard.go | 6 +- service/service/authenticated_test.go | 80 +++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/data/service/service/standard.go b/data/service/service/standard.go index 7e6d40a925..2eaec45300 100644 --- a/data/service/service/standard.go +++ b/data/service/service/standard.go @@ -34,7 +34,7 @@ import ( ) type Standard struct { - *service.Service + *service.Authenticated metricClient *metricClient.Client permissionClient *permissionClient.Client dataDeduplicatorFactory *dataDeduplicatorFactory.Factory @@ -51,7 +51,7 @@ type Standard struct { func NewStandard() *Standard { return &Standard{ - Service: service.New(), + Authenticated: service.NewAuthenticated(), } } @@ -128,7 +128,7 @@ func (s *Standard) Terminate() { s.permissionClient = nil s.metricClient = nil - s.Terminate() + s.Authenticated.Terminate() } func (s *Standard) Run() error { diff --git a/service/service/authenticated_test.go b/service/service/authenticated_test.go index 21c74ce196..9617b59173 100644 --- a/service/service/authenticated_test.go +++ b/service/service/authenticated_test.go @@ -1,8 +1,88 @@ package service_test import ( + "net/http" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + . "github.com/onsi/gomega/ghttp" + + applicationTest "github.com/tidepool-org/platform/application/test" + authTest "github.com/tidepool-org/platform/auth/test" + configTest "github.com/tidepool-org/platform/config/test" + serviceService "github.com/tidepool-org/platform/service/service" ) var _ = Describe("Authenticated", func() { + + var provider *applicationTest.Provider + var svc *serviceService.Authenticated + var serverSecret string + var sessionToken string + var authClientConfig map[string]interface{} + var serviceConfig map[string]interface{} + var serverConfig map[string]interface{} + var testServer *Server + + BeforeEach(func() { + provider = applicationTest.NewProviderWithDefaults() + + serverSecret = authTest.NewServiceSecret() + sessionToken = authTest.NewSessionToken() + + testServer = NewServer() + testServer.AppendHandlers( + CombineHandlers( + VerifyRequest("POST", "/auth/serverlogin"), + VerifyHeaderKV("X-Tidepool-Server-Name", *provider.NameOutput), + VerifyHeaderKV("X-Tidepool-Server-Secret", serverSecret), + VerifyBody(nil), + RespondWith(http.StatusOK, nil, http.Header{"X-Tidepool-Session-Token": []string{sessionToken}})), + ) + + authClientConfig = map[string]interface{}{ + "address": testServer.URL(), + "server_token_secret": authTest.NewServiceSecret(), + "external": map[string]interface{}{ + "address": testServer.URL(), + "server_session_token_secret": serverSecret, + }, + } + serverConfig = map[string]interface{}{ + "address": testServer.URL(), + "tls": "false", + } + serviceConfig = map[string]interface{}{ + "secret": authTest.NewServiceSecret(), + "server": serverConfig, + "auth": map[string]interface{}{ + "client": authClientConfig, + }, + } + (*provider.ConfigReporterOutput).(*configTest.Reporter).Config = serviceConfig + + svc = serviceService.NewAuthenticated() + Expect(svc).ToNot(BeNil()) + + Expect(svc.Initialize(provider)).To(Succeed()) + }) + + AfterEach(func() { + if svc != nil { + svc.Terminate() + } + provider.AssertOutputsEmpty() + }) + + It("returns the secret", func() { + Expect(svc.Secret()).To(Equal(serviceConfig["secret"])) + }) + + Context("AuthClient", func() { + It("returns successfully with server token", func() { + authClient := svc.AuthClient() + Expect(authClient).ToNot(BeNil()) + Eventually(authClient.ServerSessionToken).Should(Equal(sessionToken)) + }) + }) }) From 87e2501536d0536fdc593670215b73e71da2cbbb Mon Sep 17 00:00:00 2001 From: Eric Wollesen Date: Fri, 4 Oct 2024 14:51:13 -0600 Subject: [PATCH 6/8] remove duplicated/replaced tests I believe there is no loss in test coverage through this action. I manually compared the old tests and new tests to see that they covered the same concepts. Most of them were duplicates to begin with. The one that wasn't duplicated already, was moved to authenticated_test.go in a previous commit. Since the deprecated service is no more, these tests are no longer necessary. They had already be retro-fitted to test the replacement service.Service anyway, where they all passed. --- service/service/DEPRECATED_service_test.go | 128 --------------------- 1 file changed, 128 deletions(-) delete mode 100644 service/service/DEPRECATED_service_test.go diff --git a/service/service/DEPRECATED_service_test.go b/service/service/DEPRECATED_service_test.go deleted file mode 100644 index 7d972fc766..0000000000 --- a/service/service/DEPRECATED_service_test.go +++ /dev/null @@ -1,128 +0,0 @@ -package service_test - -import ( - "net/http" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - . "github.com/onsi/gomega/ghttp" - - applicationTest "github.com/tidepool-org/platform/application/test" - authTest "github.com/tidepool-org/platform/auth/test" - configTest "github.com/tidepool-org/platform/config/test" - serviceService "github.com/tidepool-org/platform/service/service" - testHttp "github.com/tidepool-org/platform/test/http" -) - -var _ = Describe("DEPRECATEDService", func() { - Context("NewDEPRECATEDService", func() { - It("returns successfully", func() { - Expect(serviceService.New()).ToNot(BeNil()) - }) - }) - - Context("with started server, config reporter, and new service", func() { - var provider *applicationTest.Provider - //var svc *serviceService.DEPRECATEDService - var svc *serviceService.Service - var serverSecret string - var sessionToken string - var server *Server - var authClientConfig map[string]interface{} - var serviceConfig map[string]interface{} - var serverConfig map[string]interface{} - - BeforeEach(func() { - provider = applicationTest.NewProviderWithDefaults() - - serverSecret = authTest.NewServiceSecret() - sessionToken = authTest.NewSessionToken() - - server = NewServer() - Expect(server).ToNot(BeNil()) - server.AppendHandlers( - CombineHandlers( - VerifyRequest("POST", "/auth/serverlogin"), - VerifyHeaderKV("X-Tidepool-Server-Name", *provider.NameOutput), - VerifyHeaderKV("X-Tidepool-Server-Secret", serverSecret), - VerifyBody(nil), - RespondWith(http.StatusOK, nil, http.Header{"X-Tidepool-Session-Token": []string{sessionToken}})), - ) - - authClientConfig = map[string]interface{}{ - "address": server.URL(), - "server_token_secret": authTest.NewServiceSecret(), - "external": map[string]interface{}{ - "address": server.URL(), - "server_session_token_secret": serverSecret, - }, - } - serverConfig = map[string]interface{}{ - "address": testHttp.NewAddress(), - "tls": "false", - } - serviceConfig = map[string]interface{}{ - "secret": authTest.NewServiceSecret(), - "server": serverConfig, - "auth": map[string]interface{}{ - "client": authClientConfig, - }, - } - (*provider.ConfigReporterOutput).(*configTest.Reporter).Config = serviceConfig - - svc = serviceService.New() - Expect(svc).ToNot(BeNil()) - }) - - AfterEach(func() { - if server != nil { - server.Close() - } - provider.AssertOutputsEmpty() - }) - - Context("with Terminate after", func() { - AfterEach(func() { - svc.Terminate() - }) - - Context("Initialize", func() { - It("returns an error when the provider is missing", func() { - Expect(svc.Initialize(nil)).To(MatchError("provider is missing")) - }) - - It("returns an error when the secret is missing", func() { - delete(serviceConfig, "secret") - Expect(svc.Initialize(provider)).To(MatchError("secret is missing")) - }) - - It("returns an error when the server cannot be initialized", func() { - delete(serverConfig, "address") - Expect(svc.Initialize(provider)).To(MatchError("unable to create server; config is invalid; address is missing")) - }) - - It("returns successfully", func() { - Expect(svc.Initialize(provider)).To(Succeed()) - }) - }) - - Context("with Initialize before", func() { - BeforeEach(func() { - Expect(svc.Initialize(provider)).To(Succeed()) - }) - - Context("Terminate", func() { - It("returns successfully", func() { - svc.Terminate() - }) - }) - - Context("Secret", func() { - It("returns the secret", func() { - Expect(svc.Secret()).To(Equal(serviceConfig["secret"])) - }) - }) - }) - }) - }) -}) From 180cc9ab958d88de8829fe492fc6f08f4d224c64 Mon Sep 17 00:00:00 2001 From: Eric Wollesen Date: Mon, 25 Nov 2024 08:12:32 -0700 Subject: [PATCH 7/8] initialize the authentication client --- data/service/service/standard.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/data/service/service/standard.go b/data/service/service/standard.go index 2eaec45300..c22dc93792 100644 --- a/data/service/service/standard.go +++ b/data/service/service/standard.go @@ -59,6 +59,9 @@ func (s *Standard) Initialize(provider application.Provider) error { if err := s.Service.Initialize(provider); err != nil { return err } + if err := s.Authenticated.Initialize(provider); err != nil { + return err + } if err := s.initializeMetricClient(); err != nil { return err From 04e96e00703f096d121a425c091977200e47f471 Mon Sep 17 00:00:00 2001 From: Eric Wollesen Date: Mon, 25 Nov 2024 09:36:56 -0700 Subject: [PATCH 8/8] add a test for auth client initialization --- data/service/service/standard_test.go | 95 +++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 data/service/service/standard_test.go diff --git a/data/service/service/standard_test.go b/data/service/service/standard_test.go new file mode 100644 index 0000000000..55ce32f251 --- /dev/null +++ b/data/service/service/standard_test.go @@ -0,0 +1,95 @@ +package service + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/tidepool-org/platform/application" + netTest "github.com/tidepool-org/platform/net/test" + "github.com/tidepool-org/platform/test" +) + +func TestAuthClientIsInitialized(t *testing.T) { + tt := newStandardTest(t) + tt.Setenv("SECRET", "something secret") + tt.Setenv("SERVER_ADDRESS", "somehost") + tt.SetenvToFilePath("SERVER_TLS_CERTIFICATE_FILE", "contents") + tt.SetenvToFilePath("SERVER_TLS_KEY_FILE", "contents") + tt.Setenv("AUTH_CLIENT_ADDRESS", "something secret") + tt.Setenv("AUTH_CLIENT_EXTERNAL_ADDRESS", "something secret") + tt.Setenv("AUTH_CLIENT_SERVICE_SECRET", "something secret") + tt.Setenv("AUTH_CLIENT_EXTERNAL_SERVICE_SECRET", "something secret") + tt.Setenv("AUTH_CLIENT_SERVER_SESSION_TOKEN_SECRET", "something secret") + tt.Setenv("AUTH_CLIENT_EXTERNAL_SERVER_SESSION_TOKEN_SECRET", "something secret") + tt.Setenv("METRIC_CLIENT_ADDRESS", "something secret") + tt.Setenv("PERMISSION_CLIENT_ADDRESS", "something secret") + tt.Setenv("DEPRECATED_DATA_STORE_DATABASE", "test_data_database") + tt.Setenv("SYNC_TASK_STORE_DATABASE", "test_sync_task_database") + // These have no prefixes + t.Setenv("KAFKA_BROKERS", "somehost") + t.Setenv("KAFKA_TOPIC_PREFIX", "somehost") + t.Setenv("KAFKA_REQUIRE_SSL", "false") + t.Setenv("KAFKA_VERSION", "2.5.0") + + std := NewStandard() + err := std.Initialize(tt.Provider) + if err != nil { + t.Errorf("expected successful initialization, got %s", err) + } +} + +type standardTest struct { + Prefix string + Name string + Scopes []string + Provider application.Provider + + t testing.TB + tempDir string +} + +func newStandardTest(t *testing.T) *standardTest { + prefix := test.RandomStringFromRangeAndCharset(4, 8, test.CharsetUppercase) + name := test.RandomStringFromRangeAndCharset(4, 8, test.CharsetAlphaNumeric) + scopes := test.RandomStringArrayFromRangeAndCharset(0, 2, test.CharsetAlphaNumeric) + + t.Setenv(fmt.Sprintf("%s_LOGGER_LEVEL", prefix), "error") + oldName := os.Args[0] + os.Args[0] = name + t.Cleanup(func() { os.Args[0] = oldName }) + + application.VersionBase = netTest.RandomSemanticVersion() + application.VersionFullCommit = test.RandomStringFromRangeAndCharset(40, 40, test.CharsetHexidecimalLowercase) + application.VersionShortCommit = application.VersionFullCommit[0:8] + + provider, err := application.NewProvider(prefix, scopes...) + if err != nil { + t.Fatalf("unable to initialize provider") + } + + return &standardTest{ + Prefix: prefix, + Name: name, + Scopes: scopes, + Provider: provider, + + t: t, + tempDir: t.TempDir(), + } +} + +func (t *standardTest) Setenv(keySuffix, value string) { + baseKey := strings.Join(append([]string{t.Prefix, t.Name}, t.Scopes...), "_") + t.t.Setenv(strings.ToUpper(baseKey+"_"+keySuffix), value) +} + +func (t *standardTest) SetenvToFilePath(keySuffix, contents string) { + filename := filepath.Join(t.tempDir, keySuffix) + if err := os.WriteFile(filename, []byte(contents), 0600); err != nil { + t.t.Fatalf("opening tempfile %q: %s", filename, err) + } + t.Setenv(keySuffix, filename) +}