From c9861ec24ec8bf26efceca61bddff3fbae483882 Mon Sep 17 00:00:00 2001 From: Luke Kingland <58986931+lkingland@users.noreply.github.com> Date: Mon, 3 Oct 2022 12:03:28 -1000 Subject: [PATCH] chore: cmd test cleanup (#1289) All tests which are directory-sensitive now also: - reset viper - use t.Cleanup - use t.TempDir - use a clean XDG_CONFIG_HOME - specify explict name when creating - moves helpers to root_test --- cmd/build_test.go | 12 ++------ cmd/config_test.go | 1 - cmd/create_test.go | 41 ++++++++++++--------------- cmd/delete_test.go | 4 +-- cmd/deploy_test.go | 57 ++++++++++++-------------------------- cmd/invoke_test.go | 7 ++--- cmd/languages_test.go | 10 ++++--- cmd/repository_test.go | 63 ++++++++++-------------------------------- cmd/root_test.go | 63 +++++++++++++++++++++++++++++++++++++++--- cmd/run_test.go | 3 +- cmd/templates_test.go | 19 ++++++++----- repositories_test.go | 28 +++++++++---------- templates_test.go | 4 +-- testing/testing.go | 54 ++++++++++++++---------------------- 14 files changed, 168 insertions(+), 198 deletions(-) diff --git a/cmd/build_test.go b/cmd/build_test.go index 1af0375e..b0d6e3ea 100644 --- a/cmd/build_test.go +++ b/cmd/build_test.go @@ -6,7 +6,6 @@ import ( fn "knative.dev/kn-plugin-func" "knative.dev/kn-plugin-func/mock" - . "knative.dev/kn-plugin-func/testing" ) // TestBuild_ImageFlag ensures that the image flag is used when specified. @@ -15,9 +14,7 @@ func TestBuild_ImageFlag(t *testing.T) { args = []string{"--image", "docker.io/tigerteam/foo"} builder = mock.NewBuilder() ) - - root, cleanup := Mktemp(t) - defer cleanup() + root := fromTempDirectory(t) if err := fn.New().Create(fn.Function{Runtime: "go", Root: root, Registry: TestRegistry}); err != nil { t.Fatal(err) @@ -48,9 +45,7 @@ func TestBuild_ImageFlag(t *testing.T) { // provided (or exist on the function already), and the client has not been // instantiated with a default registry, an ErrRegistryRequired is received. func TestBuild_RegistryOrImageRequired(t *testing.T) { - t.Helper() - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) if err := fn.New().Create(fn.Function{Runtime: "go", Root: root}); err != nil { t.Fatal(err) @@ -106,8 +101,7 @@ func TestBuild_BuilderValidated(t *testing.T) { // - Push not triggered after an unsuccessful build // - Push can be disabled func TestBuild_Push(t *testing.T) { - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) f := fn.Function{ Root: root, diff --git a/cmd/config_test.go b/cmd/config_test.go index 998cb718..b6078dee 100644 --- a/cmd/config_test.go +++ b/cmd/config_test.go @@ -14,7 +14,6 @@ import ( ) func TestListEnvs(t *testing.T) { - mock := newMockLoaderSaver() foo := "foo" bar := "bar" diff --git a/cmd/create_test.go b/cmd/create_test.go index 3cc6f152..c1e21bec 100644 --- a/cmd/create_test.go +++ b/cmd/create_test.go @@ -5,17 +5,16 @@ import ( "path/filepath" "testing" - . "knative.dev/kn-plugin-func/testing" "knative.dev/kn-plugin-func/utils" ) // TestCreate_Execute ensures that an invocation of create with minimal settings // and valid input completes without error; degenerate case. func TestCreate_Execute(t *testing.T) { - defer Fromtemp(t)() + _ = fromTempDirectory(t) cmd := NewCreateCmd(NewClient) - cmd.SetArgs([]string{"--language", "go"}) + cmd.SetArgs([]string{"--language", "go", "myfunc"}) if err := cmd.Execute(); err != nil { t.Fatal(err) @@ -25,10 +24,10 @@ func TestCreate_Execute(t *testing.T) { // TestCreate_NoRuntime ensures that an invocation of create must be // done with a runtime. func TestCreate_NoRuntime(t *testing.T) { - defer Fromtemp(t)() + _ = fromTempDirectory(t) cmd := NewCreateCmd(NewClient) - cmd.SetArgs([]string{}) // Do not use test command args + cmd.SetArgs([]string{"myfunc"}) // Do not use test command args err := cmd.Execute() var e ErrNoRuntime @@ -40,10 +39,10 @@ func TestCreate_NoRuntime(t *testing.T) { // TestCreate_WithNoRuntime ensures that an invocation of create must be // done with one of the valid runtimes only. func TestCreate_WithInvalidRuntime(t *testing.T) { - defer Fromtemp(t)() + _ = fromTempDirectory(t) cmd := NewCreateCmd(NewClient) - cmd.SetArgs([]string{"--language", "invalid"}) + cmd.SetArgs([]string{"--language", "invalid", "myfunc"}) err := cmd.Execute() var e ErrInvalidRuntime @@ -55,10 +54,10 @@ func TestCreate_WithInvalidRuntime(t *testing.T) { // TestCreate_InvalidTemplate ensures that an invocation of create must be // done with one of the valid templates only. func TestCreate_InvalidTemplate(t *testing.T) { - defer Fromtemp(t)() + _ = fromTempDirectory(t) cmd := NewCreateCmd(NewClient) - cmd.SetArgs([]string{"--language", "go", "--template", "invalid"}) + cmd.SetArgs([]string{"--language", "go", "--template", "invalid", "myfunc"}) err := cmd.Execute() var e ErrInvalidTemplate @@ -70,7 +69,7 @@ func TestCreate_InvalidTemplate(t *testing.T) { // TestCreate_ValidatesName ensures that the create command only accepts // DNS-1123 labels for function name. func TestCreate_ValidatesName(t *testing.T) { - defer Fromtemp(t)() + _ = fromTempDirectory(t) // Execute the command with a function name containing invalid characters and // confirm the expected error is returned @@ -87,9 +86,10 @@ func TestCreate_ValidatesName(t *testing.T) { // the expected repositories path, respecting the setting for XDG_CONFIG_PATH // when deriving the default func TestCreateConfig_RepositoriesPath(t *testing.T) { - defer Fromtemp(t)() + _ = fromTempDirectory(t) - // Update XDG_CONFIG_HOME to point to some arbitrary location. + // Update XDG_CONFIG_HOME to point to some arbitrary location which we know + // The above call to fromTempDirectory also updates, but value is not returned. xdgConfigHome := t.TempDir() t.Setenv("XDG_CONFIG_HOME", xdgConfigHome) @@ -97,7 +97,7 @@ func TestCreateConfig_RepositoriesPath(t *testing.T) { expected := filepath.Join(xdgConfigHome, "func", "repositories") cmd := NewCreateCmd(NewClient) - cmd.SetArgs([]string{}) // Do not use test command args + cmd.SetArgs([]string{"myfunc"}) // Do not use test command args cfg, err := newCreateConfig(cmd, []string{}, NewClient) if err != nil { t.Fatal(err) @@ -111,19 +111,12 @@ func TestCreateConfig_RepositoriesPath(t *testing.T) { // TestCreate_ConfigOptional ensures that the system can be used without // any additional configuration being required. func TestCreate_ConfigOptional(t *testing.T) { - // Empty Home - // the func directory, and other static assets will be created here - // if they do not exist. - home, rm := Mktemp(t) - defer rm() - t.Setenv("XDG_CONFIG_HOME", home) + _ = fromTempDirectory(t) + + t.Setenv("XDG_CONFIG_HOME", t.TempDir()) - // Immediately using "create" in a new empty directory should not fail; - // even when this home directory is devoid of config files. - _, rm2 := Mktemp(t) - defer rm2() cmd := NewCreateCmd(NewClient) - cmd.SetArgs([]string{"--language=go"}) + cmd.SetArgs([]string{"--language=go", "myfunc"}) if err := cmd.Execute(); err != nil { t.Fatal(err) } diff --git a/cmd/delete_test.go b/cmd/delete_test.go index bae21c16..da65aa96 100644 --- a/cmd/delete_test.go +++ b/cmd/delete_test.go @@ -6,7 +6,6 @@ import ( fn "knative.dev/kn-plugin-func" "knative.dev/kn-plugin-func/mock" - . "knative.dev/kn-plugin-func/testing" ) // TestDelete_ByName ensures that running delete specifying the name of the @@ -46,8 +45,7 @@ func TestDelete_ByName(t *testing.T) { // TestDelete_ByProject ensures that running delete with a valid project as its // context invokes remove and with the correct name (reads name from func.yaml) func TestDelete_ByProject(t *testing.T) { - // from within a new temporary directory - defer Fromtemp(t)() + _ = fromTempDirectory(t) // Write a func.yaml config which specifies a name funcYaml := `name: bar diff --git a/cmd/deploy_test.go b/cmd/deploy_test.go index 02e6997a..d164837e 100644 --- a/cmd/deploy_test.go +++ b/cmd/deploy_test.go @@ -14,7 +14,6 @@ import ( fn "knative.dev/kn-plugin-func" "knative.dev/kn-plugin-func/builders" "knative.dev/kn-plugin-func/mock" - . "knative.dev/kn-plugin-func/testing" ) const TestRegistry = "example.com/alice" @@ -24,8 +23,7 @@ type commandConstructor func(ClientFactory) *cobra.Command // TestDeploy_Default ensures that running deploy on a valid default Function // (only required options populated; all else default) completes successfully. func TestDeploy_Default(t *testing.T) { - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) // A Function with the minimum required values for deployment populated. f := fn.Function{ @@ -57,8 +55,7 @@ func TestDeploy_RegistryOrImageRequired(t *testing.T) { func testRegistryOrImageRequired(cmdFn commandConstructor, t *testing.T) { t.Helper() - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) if err := fn.New().Create(fn.Function{Runtime: "go", Root: root}); err != nil { t.Fatal(err) @@ -95,8 +92,7 @@ func TestDeploy_ImageAndRegistry(t *testing.T) { func testImageAndRegistry(cmdFn commandConstructor, t *testing.T) { t.Helper() - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) if err := fn.New().Create(fn.Function{Runtime: "go", Root: root}); err != nil { t.Fatal(err) @@ -171,8 +167,7 @@ func TestDeploy_InvalidRegistry(t *testing.T) { func testInvalidRegistry(cmdFn commandConstructor, t *testing.T) { t.Helper() - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) f := fn.Function{ Root: root, @@ -204,8 +199,7 @@ func TestDeploy_RegistryLoads(t *testing.T) { func testRegistryLoads(cmdFn commandConstructor, t *testing.T) { t.Helper() - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) f := fn.Function{ Root: root, @@ -246,11 +240,9 @@ func TestDeploy_BuilderPersists(t *testing.T) { } func testBuilderPersists(cmdFn commandConstructor, t *testing.T) { - t.Setenv("KUBECONFIG", fmt.Sprintf("%s/testdata/kubeconfig_deploy_namespace", cwd())) - t.Helper() - root, rm := Mktemp(t) - defer rm() + t.Setenv("KUBECONFIG", fmt.Sprintf("%s/testdata/kubeconfig_deploy_namespace", cwd())) + root := fromTempDirectory(t) if err := fn.New().Create(fn.Function{Runtime: "go", Root: root}); err != nil { t.Fatal(err) @@ -340,8 +332,7 @@ func TestDeploy_BuilderValidated(t *testing.T) { func testBuilderValidated(cmdFn commandConstructor, t *testing.T) { t.Helper() - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) if err := fn.New().Create(fn.Function{Runtime: "go", Root: root}); err != nil { t.Fatal(err) @@ -406,8 +397,7 @@ func TestDeploy_RemoteBuildURLPermutations(t *testing.T) { // returns a single test function for one possible permutation of the flags. newTestFn := func(remote, build, url string) func(t *testing.T) { return func(t *testing.T) { - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) // Create a new Function in the temp directory if err := fn.New().Create(fn.Function{Runtime: "go", Root: root}); err != nil { @@ -580,8 +570,7 @@ func Test_ImageWithDigestErrors(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Move into a new temp directory - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) // Create a new Function in the temp directory if err := fn.New().Create(fn.Function{Runtime: "go", Root: root}); err != nil { @@ -677,8 +666,7 @@ func Test_namespace(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { t.Helper() - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) // if running with an active kubeconfig if test.context { @@ -736,8 +724,7 @@ Test_namespaceCheck cases were refactored into: // TestDeploy_GitArgsPersist ensures that the git flags, if provided, are // persisted to the Function for subsequent deployments. func TestDeploy_GitArgsPersist(t *testing.T) { - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) var ( url = "https://example.com/user/repo" @@ -778,8 +765,7 @@ func TestDeploy_GitArgsPersist(t *testing.T) { // TestDeploy_GitArgsUsed ensures that any git values provided as flags are used // when invoking a remote deployment. func TestDeploy_GitArgsUsed(t *testing.T) { - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) var ( url = "https://example.com/user/repo" @@ -821,8 +807,7 @@ func TestDeploy_GitArgsUsed(t *testing.T) { // TestDeploy_GitURLBranch ensures that a --git-url which specifies the branch // in the URL is equivalent to providing --git-branch func TestDeploy_GitURLBranch(t *testing.T) { - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) if err := fn.New().Create(fn.Function{Runtime: "go", Root: root}); err != nil { t.Fatal(err) @@ -861,12 +846,8 @@ func TestDeploy_GitURLBranch(t *testing.T) { // TestDeploy_NamespaceDefaults ensures that when not specified, a users's // active kubernetes context is used for the namespace if available. func TestDeploy_NamespaceDefaults(t *testing.T) { - // Set kube context to test context t.Setenv("KUBECONFIG", filepath.Join(cwd(), "testdata", "kubeconfig_deploy_namespace")) - - // from a temp directory - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) // Create a new function if err := fn.New().Create(fn.Function{Runtime: "go", Root: root}); err != nil { @@ -913,8 +894,7 @@ func TestDeploy_NamespaceDefaults(t *testing.T) { // Also implicitly checks that the --namespace flag takes precidence over // the namespace of a previously deployed Function. func TestDeploy_NamespaceUpdateWarning(t *testing.T) { - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) // Create a Function which appears to have been deployed to 'myns' f := fn.Function{ @@ -975,10 +955,7 @@ func TestDeploy_NamespaceUpdateWarning(t *testing.T) { func TestDeploy_NamespaceRedeployWarning(t *testing.T) { // Change profile to one whose current profile is 'test-ns-deploy' t.Setenv("KUBECONFIG", filepath.Join(cwd(), "testdata", "kubeconfig_deploy_namespace")) - - // From within a temp directory - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) // Create a Function which appears to have been deployed to 'myns' f := fn.Function{ diff --git a/cmd/invoke_test.go b/cmd/invoke_test.go index b930487f..85ba00a4 100644 --- a/cmd/invoke_test.go +++ b/cmd/invoke_test.go @@ -12,13 +12,11 @@ import ( fn "knative.dev/kn-plugin-func" "knative.dev/kn-plugin-func/mock" - . "knative.dev/kn-plugin-func/testing" ) // TestInvoke command executes the invocation path. func TestInvoke(t *testing.T) { - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) var invoked int32 @@ -78,8 +76,7 @@ func TestInvoke(t *testing.T) { // TestInvoke_Namespace ensures that invocation uses the Function's namespace // despite the currently active. func TestInvoke_Namespace(t *testing.T) { - root, rm := Mktemp(t) - defer rm() + root := fromTempDirectory(t) // Create a Function in a non-active namespace f := fn.Function{Runtime: "go", Root: root, Deploy: fn.DeploySpec{Namespace: "ns"}} diff --git a/cmd/languages_test.go b/cmd/languages_test.go index 05cddf24..2142ec1f 100644 --- a/cmd/languages_test.go +++ b/cmd/languages_test.go @@ -10,8 +10,9 @@ import ( // all supported languages is to print a plain text list of all the builtin // language runtimes. func TestLanguages_Default(t *testing.T) { - t.Setenv("XDG_CONFIG_HOME", t.TempDir()) // ignore user-added - buf := piped(t) // gather output + _ = fromTempDirectory(t) + + buf := piped(t) // gather output cmd := NewLanguagesCmd(NewClientFactory(func() *fn.Client { return fn.New() })) @@ -35,8 +36,9 @@ typescript` // TestLanguages_JSON ensures that listing languages in --json format returns // builtin languages as a JSON array. func TestLanguages_JSON(t *testing.T) { - t.Setenv("XDG_CONFIG_HOME", t.TempDir()) // ignore user-added - buf := piped(t) // gather output + _ = fromTempDirectory(t) + + buf := piped(t) // gather output cmd := NewLanguagesCmd(NewClientFactory(func() *fn.Client { return fn.New() })) diff --git a/cmd/repository_test.go b/cmd/repository_test.go index af88cebc..3ffc0ba7 100644 --- a/cmd/repository_test.go +++ b/cmd/repository_test.go @@ -1,9 +1,6 @@ package cmd import ( - "io" - "os" - "strings" "testing" . "knative.dev/kn-plugin-func/testing" @@ -13,7 +10,8 @@ import ( // set of repositories by name for builtin repositories, by explicitly // setting the repositories' path to a new path which includes no others. func TestRepository_List(t *testing.T) { - t.Setenv("XDG_CONFIG_HOME", t.TempDir()) + _ = fromTempDirectory(t) + cmd := NewRepositoryListCmd(NewClient) cmd.SetArgs([]string{}) // Do not use test command args @@ -35,7 +33,9 @@ func TestRepository_List(t *testing.T) { // arguments, respects the repositories' path flag, and the expected name is echoed // upon subsequent 'list'. func TestRepository_Add(t *testing.T) { - t.Setenv("XDG_CONFIG_HOME", t.TempDir()) + url := ServeRepo("repository.git", t) + _ = fromTempDirectory(t) + var ( add = NewRepositoryAddCmd(NewClient) list = NewRepositoryListCmd(NewClient) @@ -48,7 +48,7 @@ func TestRepository_Add(t *testing.T) { // add [flags] add.SetArgs([]string{ "newrepo", - TestRepoURI("repository", t), + url, }) // Parse flags and args, performing action @@ -73,7 +73,9 @@ func TestRepository_Add(t *testing.T) { // positional arguments, respects the repositories' path flag, and the name is // reflected as having been renamed upon subsequent 'list'. func TestRepository_Rename(t *testing.T) { - t.Setenv("XDG_CONFIG_HOME", t.TempDir()) + url := ServeRepo("repository.git", t) + _ = fromTempDirectory(t) + var ( add = NewRepositoryAddCmd(NewClient) rename = NewRepositoryRenameCmd(NewClient) @@ -86,7 +88,7 @@ func TestRepository_Rename(t *testing.T) { list.SetArgs([]string{}) // add a repo which will be renamed - add.SetArgs([]string{"newrepo", TestRepoURI("repository", t)}) + add.SetArgs([]string{"newrepo", url}) if err := add.Execute(); err != nil { t.Fatal(err) } @@ -119,7 +121,9 @@ func TestRepository_Rename(t *testing.T) { // its argument, respects the repositories' flag, and the entry is removed upon // subsequent 'list'. func TestRepository_Remove(t *testing.T) { - t.Setenv("XDG_CONFIG_HOME", t.TempDir()) + url := ServeRepo("repository.git", t) + _ = fromTempDirectory(t) + var ( add = NewRepositoryAddCmd(NewClient) remove = NewRepositoryRemoveCmd(NewClient) @@ -132,7 +136,7 @@ func TestRepository_Remove(t *testing.T) { list.SetArgs([]string{}) // add a repo which will be removed - add.SetArgs([]string{"newrepo", TestRepoURI("repository", t)}) + add.SetArgs([]string{"newrepo", url}) if err := add.Execute(); err != nil { t.Fatal(err) } @@ -159,42 +163,3 @@ func TestRepository_Remove(t *testing.T) { t.Fatalf("expected:\n'%v'\ngot:\n'%v'\n", expect, output) } } - -// Helpers -// ------- - -// pipe the output of stdout to a buffer whose value is returned -// from the returned function. Call pipe() to start piping output -// to the buffer, call the returned function to access the data in -// the buffer. -func piped(t *testing.T) func() string { - t.Helper() - var ( - o = os.Stdout - c = make(chan error, 1) - b strings.Builder - ) - - r, w, err := os.Pipe() - if err != nil { - t.Fatal(err) - } - - os.Stdout = w - - go func() { - _, err := io.Copy(&b, r) - r.Close() - c <- err - }() - - return func() string { - os.Stdout = o - w.Close() - err := <-c - if err != nil { - t.Fatal(err) - } - return strings.TrimSpace(b.String()) - } -} diff --git a/cmd/root_test.go b/cmd/root_test.go index 3f7452f0..05619d66 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -3,6 +3,8 @@ package cmd import ( "bytes" "fmt" + "io" + "os" "reflect" "strings" "testing" @@ -37,10 +39,11 @@ func TestRoot_PersistentFlags(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - defer Fromtemp(t)() // from a temp dir, deferred cleanup - cmd := NewCreateCmd(NewClient) // Create a new function - cmd.SetArgs([]string{"--language", "go"}) // providing language (the only required param) - if err := cmd.Execute(); err != nil { // fail on any errors + _ = fromTempDirectory(t) + + cmd := NewCreateCmd(NewClient) // Create a function + cmd.SetArgs([]string{"--language", "go", "myfunc"}) // providing language + if err := cmd.Execute(); err != nil { // fail on any errors t.Fatal(err) } @@ -252,3 +255,55 @@ func TestVerbose(t *testing.T) { }) } } + +// Helpers +// ------- + +// pipe the output of stdout to a buffer whose value is returned +// from the returned function. Call pipe() to start piping output +// to the buffer, call the returned function to access the data in +// the buffer. +func piped(t *testing.T) func() string { + t.Helper() + var ( + o = os.Stdout + c = make(chan error, 1) + b strings.Builder + ) + + r, w, err := os.Pipe() + if err != nil { + t.Fatal(err) + } + + os.Stdout = w + + go func() { + _, err := io.Copy(&b, r) + r.Close() + c <- err + }() + + return func() string { + os.Stdout = o + w.Close() + err := <-c + if err != nil { + t.Fatal(err) + } + return strings.TrimSpace(b.String()) + } +} + +// fromTempDirectory is a cli-specific test helper which +// - creates a temp directory and changes to it as the new working directory +// - creates a temp directory and uses it for XDG_CONFIG_HOME +// - removes temp directories on cleanup +// - resets viper on cleanum (the reason this is "cli-specific") +func fromTempDirectory(t *testing.T) string { + t.Helper() + t.Setenv("XDG_CONFIG_HOME", t.TempDir()) + d, done := Mktemp(t) // creates and CDs to 'tmp' + t.Cleanup(func() { done(); viper.Reset() }) + return d +} diff --git a/cmd/run_test.go b/cmd/run_test.go index 6df60841..04e53ec4 100644 --- a/cmd/run_test.go +++ b/cmd/run_test.go @@ -8,7 +8,6 @@ import ( fn "knative.dev/kn-plugin-func" "knative.dev/kn-plugin-func/mock" - . "knative.dev/kn-plugin-func/testing" ) func TestRun_Run(t *testing.T) { @@ -100,7 +99,7 @@ created: 2009-11-10 23:00:00`, for _, tt := range tests { // run as a sub-test t.Run(tt.name, func(t *testing.T) { - defer Fromtemp(t)() + _ = fromTempDirectory(t) runner := mock.NewRunner() if tt.runError != nil { diff --git a/cmd/templates_test.go b/cmd/templates_test.go index 996dc048..37a447e0 100644 --- a/cmd/templates_test.go +++ b/cmd/templates_test.go @@ -12,8 +12,9 @@ import ( // TestTemplates_Default ensures that the default behavior is listing all // templates for all language runtimes. func TestTemplates_Default(t *testing.T) { - t.Setenv("XDG_CONFIG_HOME", t.TempDir()) // ignore user-added - buf := piped(t) // gather output + _ = fromTempDirectory(t) + + buf := piped(t) // gather output cmd := NewTemplatesCmd(NewClientFactory(func() *fn.Client { return fn.New() })) @@ -45,8 +46,9 @@ typescript http` // TestTemplates_JSON ensures that listing templates respects the --json // output format. func TestTemplates_JSON(t *testing.T) { - t.Setenv("XDG_CONFIG_HOME", t.TempDir()) // ignore user-added - buf := piped(t) // gather output + _ = fromTempDirectory(t) + + buf := piped(t) // gather output cmd := NewTemplatesCmd(NewClientFactory(func() *fn.Client { return fn.New() })) @@ -104,7 +106,8 @@ func TestTemplates_JSON(t *testing.T) { // TestTemplates_ByLanguage ensures that the output is correctly filtered // by language runtime when provided. func TestTemplates_ByLanguage(t *testing.T) { - t.Setenv("XDG_CONFIG_HOME", t.TempDir()) // ignore user-added + _ = fromTempDirectory(t) + cmd := NewTemplatesCmd(NewClientFactory(func() *fn.Client { return fn.New() })) @@ -144,7 +147,8 @@ http` } func TestTemplates_ErrTemplateRepoDoesNotExist(t *testing.T) { - defer t.Setenv("XDG_CONFIG_HOME", t.TempDir()) + _ = fromTempDirectory(t) + cmd := NewTemplatesCmd(NewClientFactory(func() *fn.Client { return fn.New() })) @@ -155,7 +159,8 @@ func TestTemplates_ErrTemplateRepoDoesNotExist(t *testing.T) { } func TestTemplates_WrongRepositoryUrl(t *testing.T) { - defer t.Setenv("XDG_CONFIG_HOME", t.TempDir()) + _ = fromTempDirectory(t) + cmd := NewTemplatesCmd(NewClientFactory(func() *fn.Client { return fn.New() })) diff --git a/repositories_test.go b/repositories_test.go index eefe5da1..9df848bb 100644 --- a/repositories_test.go +++ b/repositories_test.go @@ -18,7 +18,7 @@ import ( // test. Others do eist with specific test requirements that are mutually // exclusive, such as manifest differences, and are specified inline to their // requisite test. -const RepositoriesTestRepo = "repository" +const RepositoriesTestRepo = "repository.git" // TestRepositories_List ensures the base case of listing // repositories without error in the default scenario of builtin only. @@ -69,7 +69,7 @@ func TestRepositories_Get(t *testing.T) { // TestRepositories_All ensures repos are returned from // .All accessor. Tests both builtin and buitlin+extensible cases. func TestRepositories_All(t *testing.T) { - uri := TestRepoURI(RepositoriesTestRepo, t) + uri := ServeRepo(RepositoriesTestRepo, t) root, rm := Mktemp(t) defer rm() @@ -99,15 +99,15 @@ func TestRepositories_All(t *testing.T) { // Assert it now includes both builtin and extended if len(repositories) != 2 || repositories[0].Name != fn.DefaultRepositoryName || - repositories[1].Name != RepositoriesTestRepo { + repositories[1].Name != "repository" { t.Fatal("Repositories list does not pass shallow repository membership check") } } // TestRepositories_Add checks basic adding of a repository by URI. func TestRepositories_Add(t *testing.T) { - uri := TestRepoURI(RepositoriesTestRepo, t) // ./testdata/$RepositoriesTestRepo.git - root, rm := Mktemp(t) // create and cd to a temp dir, returning path. + uri := ServeRepo(RepositoriesTestRepo, t) // ./testdata/$RepositoriesTestRepo.git + root, rm := Mktemp(t) // create and cd to a temp dir, returning path. defer rm() // Instantiate the client using the current temp directory as the @@ -144,7 +144,7 @@ func TestRepositories_AddDeafultName(t *testing.T) { // repo meant to exemplify the simplest use case: a repo with no metadata // that simply contains templates, grouped by runtime. It therefore does // not have a manifest and the default name will therefore be the repo name - uri := TestRepoURI(RepositoriesTestRepo, t) // ./testdata/$RepositoriesTestRepo.git + uri := ServeRepo(RepositoriesTestRepo, t) // ./testdata/$RepositoriesTestRepo.git root, rm := Mktemp(t) defer rm() @@ -156,7 +156,7 @@ func TestRepositories_AddDeafultName(t *testing.T) { } // The name returned should be the repo name - if name != RepositoriesTestRepo { + if name != "repository" { t.Fatalf("expected returned name '%v', got '%v'", RepositoriesTestRepo, name) } @@ -165,7 +165,7 @@ func TestRepositories_AddDeafultName(t *testing.T) { if err != nil { t.Fatal(err) } - expected := []string{"default", RepositoriesTestRepo} + expected := []string{"default", "repository"} if diff := cmp.Diff(expected, rr); diff != "" { t.Error("Repositories differed (-want, +got):", diff) } @@ -179,7 +179,7 @@ func TestRepositories_AddWithManifest(t *testing.T) { // defines a custom language pack and makes full use of the manifest.yaml. // The manifest.yaml is included which specifies things like custom templates // location and (appropos to this test) a default name/ - uri := TestRepoURI("repository-a", t) // ./testdata/repository-a.git + uri := ServeRepo("repository-a", t) // ./testdata/repository-a.git root, rm := Mktemp(t) defer rm() @@ -210,7 +210,7 @@ func TestRepositories_AddWithManifest(t *testing.T) { // TestRepositories_AddExistingErrors ensures that adding a repository that // already exists yields an error. func TestRepositories_AddExistingErrors(t *testing.T) { - uri := TestRepoURI(RepositoriesTestRepo, t) + uri := ServeRepo(RepositoriesTestRepo, t) root, rm := Mktemp(t) // create and cd to a temp dir, returning path. defer rm() @@ -244,7 +244,7 @@ func TestRepositories_AddExistingErrors(t *testing.T) { // TestRepositories_Rename ensures renaming a repository succeeds. func TestRepositories_Rename(t *testing.T) { - uri := TestRepoURI(RepositoriesTestRepo, t) + uri := ServeRepo(RepositoriesTestRepo, t) root, rm := Mktemp(t) // create and cd to a temp dir, returning path. defer rm() @@ -278,8 +278,8 @@ func TestRepositories_Rename(t *testing.T) { // TestRepositories_Remove ensures that removing a repository by name // removes it from the list and FS. func TestRepositories_Remove(t *testing.T) { - uri := TestRepoURI(RepositoriesTestRepo, t) // ./testdata/repository.git - root, rm := Mktemp(t) // create and cd to a temp dir + uri := ServeRepo(RepositoriesTestRepo, t) // ./testdata/repository.git + root, rm := Mktemp(t) // create and cd to a temp dir defer rm() // Instantiate the client using the current temp directory as the @@ -313,7 +313,7 @@ func TestRepositories_Remove(t *testing.T) { // TestRepositories_URL ensures that a repository populates its URL member // from the git repository's origin url (if it is a git repo and exists) func TestRepositories_URL(t *testing.T) { - uri := TestRepoURI(RepositoriesTestRepo, t) + uri := ServeRepo(RepositoriesTestRepo, t) root, rm := Mktemp(t) defer rm() diff --git a/templates_test.go b/templates_test.go index a687436e..2126173d 100644 --- a/templates_test.go +++ b/templates_test.go @@ -163,7 +163,7 @@ func TestTemplates_Remote(t *testing.T) { root := "testdata/testTemplatesRemote" defer Using(t, root)() - url := TestRepoURI(RepositoriesTestRepo, t) + url := ServeRepo(RepositoriesTestRepo, t) // Create a client which explicitly specifies the Git repo at URL // rather than relying on the default internally builtin template repo @@ -328,7 +328,7 @@ func TestTemplates_ModeRemote(t *testing.T) { root := "testdata/testTemplates_ModeRemote" defer Using(t, root)() - url := TestRepoURI(RepositoriesTestRepo, t) + url := ServeRepo(RepositoriesTestRepo, t) client := fn.New( fn.WithRegistry(TestRegistry), diff --git a/testing/testing.go b/testing/testing.go index 2a838216..73fc17e2 100644 --- a/testing/testing.go +++ b/testing/testing.go @@ -82,11 +82,10 @@ func Within(t *testing.T, root string) func() { // errors encountererd fail the current test. func Mktemp(t *testing.T) (string, func()) { t.Helper() - tmp := tempdir(t) + tmp := t.TempDir() owd := pwd(t) cd(t, tmp) return tmp, func() { - os.RemoveAll(tmp) cd(t, owd) } } @@ -97,19 +96,6 @@ func Fromtemp(t *testing.T) func() { return done } -// tempdir creates a new temporary directory and returns its path. -// errors fail the current test. -func tempdir(t *testing.T) string { - // NOTE: Not using t.TempDir() because it is sometimes helpful during - // debugging to skip running the returned deferred cleanup function - // and manually inspect the contents of the test's temp directory. - d, err := os.MkdirTemp("", "dir") - if err != nil { - t.Fatal(err) - } - return d -} - // pwd prints the current working directory. // errors fail the test. func pwd(t *testing.T) string { @@ -129,20 +115,20 @@ func cd(t *testing.T, dir string) { } } -// TestRepoURI starts serving HTTP git server with GIT_PROJECT_ROOT=$(pwd)/testdata -// and returns URL for project named `name` under the git root. -// -// For example TestRepoURI("my-repo", t) returns string that could look like: -// http://localhost:4242/my-repo.git -func TestRepoURI(name string, t *testing.T) string { +// ServeRepositry [name] from ./testdata/[name] returning URL at which +// the named repository is available. +// Must be called before any helpers which change test working directory +// such as fromTempDirectory(t) +func ServeRepo(name string, t *testing.T) string { t.Helper() - wd, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - gitRoot := filepath.Join(wd, "testdata") - hostPort := RunGitServer(t, gitRoot) - return fmt.Sprintf(`http://%s/%s.git`, hostPort, name) + var ( + path = filepath.Join("./testdata", name) + dir = filepath.Dir(path) + abs, _ = filepath.Abs(dir) + repo = filepath.Base(path) + url = RunGitServer(abs, t) + ) + return fmt.Sprintf("%v/%v", url, repo) } // WithExecutable creates an executable of the given name and source in a temp @@ -186,13 +172,13 @@ go.exe run GO_SCRIPT_PATH %* } } -// RunGitServer starts serving git HTTP server and returns its address including port -func RunGitServer(t *testing.T, gitRoot string) (hostPort string) { - l, err := net.Listen("tcp", "localhost:0") +// RunGitServer starts serving git HTTP server and returns its address +func RunGitServer(root string, t *testing.T) (url string) { + l, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatal(err) } - hostPort = l.Addr().String() + url = l.Addr().String() cmd := exec.Command("git", "--exec-path") out, err := cmd.CombinedOutput() @@ -203,7 +189,7 @@ func RunGitServer(t *testing.T, gitRoot string) (hostPort string) { server := &http.Server{ Handler: &cgi.Handler{ Path: filepath.Join(strings.Trim(string(out), "\n"), "git-http-backend"), - Env: []string{"GIT_HTTP_EXPORT_ALL=true", fmt.Sprintf("GIT_PROJECT_ROOT=%s", gitRoot)}, + Env: []string{"GIT_HTTP_EXPORT_ALL=true", fmt.Sprintf("GIT_PROJECT_ROOT=%s", root)}, }, } @@ -218,7 +204,7 @@ func RunGitServer(t *testing.T, gitRoot string) (hostPort string) { server.Close() }) - return hostPort + return "http://" + url } // Cwd returns the current working directory or panic if unable to determine.