From ef330e1eeee9c4b404d397912198cefc432ef137 Mon Sep 17 00:00:00 2001 From: Florian Geckeler <43751896+fgeckeler@users.noreply.github.com> Date: Thu, 27 Feb 2020 12:11:22 +0100 Subject: [PATCH] Move mock capabilities to pkg/mock/runner and adapt all tests --- cmd/abapEnvironmentPullGitRepo_test.go | 11 +- cmd/cloudFoundryDeleteService_test.go | 39 +++--- cmd/detectExecuteScan.go | 2 +- cmd/detectExecuteScan_test.go | 11 +- cmd/interfaces.go | 4 +- cmd/karmaExecuteTests.go | 4 +- cmd/karmaExecuteTests_test.go | 15 +-- cmd/kubernetesDeploy.go | 6 +- cmd/kubernetesDeploy_test.go | 53 ++++---- cmd/mtaBuild.go | 2 +- cmd/mtaBuild_test.go | 55 ++++---- cmd/piper_test.go | 167 ++----------------------- cmd/xsDeploy_test.go | 41 +++--- integration/integration_api_test.go | 2 +- integration/integration_cli_test.go | 2 +- pkg/command/command.go | 8 +- pkg/mock/runner.go | 159 +++++++++++++++++++++++ 17 files changed, 297 insertions(+), 284 deletions(-) create mode 100644 pkg/mock/runner.go diff --git a/cmd/abapEnvironmentPullGitRepo_test.go b/cmd/abapEnvironmentPullGitRepo_test.go index a16b4d364..31f013c68 100644 --- a/cmd/abapEnvironmentPullGitRepo_test.go +++ b/cmd/abapEnvironmentPullGitRepo_test.go @@ -2,6 +2,7 @@ package cmd import ( "bytes" + "github.com/SAP/jenkins-library/pkg/mock" "io" "io/ioutil" "net/http" @@ -120,11 +121,11 @@ func TestGetAbapCommunicationArrangementInfo(t *testing.T) { Password: "testPassword", } - execRunner := execMockRunner{} + execRunner := mock.ExecMockRunner{} getAbapCommunicationArrangementInfo(config, &execRunner) - assert.Equal(t, "cf", execRunner.calls[0].exec, "Wrong command") - assert.Equal(t, []string{"login", "-a", "https://api.endpoint.com", "-u", "testUser", "-p", "testPassword", "-o", "testOrg", "-s", "testSpace"}, execRunner.calls[0].params, "Wrong parameters") + assert.Equal(t, "cf", execRunner.Calls[0].Exec, "Wrong command") + assert.Equal(t, []string{"login", "-a", "https://api.endpoint.com", "-u", "testUser", "-p", "testPassword", "-o", "testOrg", "-s", "testSpace"}, execRunner.Calls[0].Params, "Wrong parameters") }) t.Run("Test cf cli command: params missing", func(t *testing.T) { @@ -138,7 +139,7 @@ func TestGetAbapCommunicationArrangementInfo(t *testing.T) { Password: "testPassword", } - execRunner := execMockRunner{} + execRunner := mock.ExecMockRunner{} var _, err = getAbapCommunicationArrangementInfo(config, &execRunner) assert.Equal(t, "Parameters missing. Please provide EITHER the Host of the ABAP server OR the Cloud Foundry ApiEndpoint, Organization, Space, Service Instance and a corresponding Service Key for the Communication Scenario SAP_COM_0510", err.Error(), "Expected error message") @@ -151,7 +152,7 @@ func TestGetAbapCommunicationArrangementInfo(t *testing.T) { Password: "testPassword", } - execRunner := execMockRunner{} + execRunner := mock.ExecMockRunner{} var _, err = getAbapCommunicationArrangementInfo(config, &execRunner) assert.Equal(t, "Parameters missing. Please provide EITHER the Host of the ABAP server OR the Cloud Foundry ApiEndpoint, Organization, Space, Service Instance and a corresponding Service Key for the Communication Scenario SAP_COM_0510", err.Error(), "Expected error message") diff --git a/cmd/cloudFoundryDeleteService_test.go b/cmd/cloudFoundryDeleteService_test.go index bd7a015bb..3310d26c9 100644 --- a/cmd/cloudFoundryDeleteService_test.go +++ b/cmd/cloudFoundryDeleteService_test.go @@ -1,12 +1,13 @@ package cmd import ( + "github.com/SAP/jenkins-library/pkg/mock" "github.com/stretchr/testify/assert" "testing" ) func TestCloudFoundryDeleteService(t *testing.T) { - execRunner := execMockRunner{} + execRunner := mock.ExecMockRunner{} t.Run("CF Login: success case", func(t *testing.T) { config := cloudFoundryDeleteServiceOptions{ @@ -18,35 +19,35 @@ func TestCloudFoundryDeleteService(t *testing.T) { } error := cloudFoundryLogin(config, &execRunner) if error == nil { - assert.Equal(t, "cf", execRunner.calls[0].exec) - assert.Equal(t, "login", execRunner.calls[0].params[0]) - assert.Equal(t, "-a", execRunner.calls[0].params[1]) - assert.Equal(t, "https://api.endpoint.com", execRunner.calls[0].params[2]) - assert.Equal(t, "-o", execRunner.calls[0].params[3]) - assert.Equal(t, "testOrg", execRunner.calls[0].params[4]) - assert.Equal(t, "-s", execRunner.calls[0].params[5]) - assert.Equal(t, "testSpace", execRunner.calls[0].params[6]) - assert.Equal(t, "-u", execRunner.calls[0].params[7]) - assert.Equal(t, "testUser", execRunner.calls[0].params[8]) - assert.Equal(t, "-p", execRunner.calls[0].params[9]) - assert.Equal(t, "testPassword", execRunner.calls[0].params[10]) + assert.Equal(t, "cf", execRunner.Calls[0].Exec) + assert.Equal(t, "login", execRunner.Calls[0].Params[0]) + assert.Equal(t, "-a", execRunner.Calls[0].Params[1]) + assert.Equal(t, "https://api.endpoint.com", execRunner.Calls[0].Params[2]) + assert.Equal(t, "-o", execRunner.Calls[0].Params[3]) + assert.Equal(t, "testOrg", execRunner.Calls[0].Params[4]) + assert.Equal(t, "-s", execRunner.Calls[0].Params[5]) + assert.Equal(t, "testSpace", execRunner.Calls[0].Params[6]) + assert.Equal(t, "-u", execRunner.Calls[0].Params[7]) + assert.Equal(t, "testUser", execRunner.Calls[0].Params[8]) + assert.Equal(t, "-p", execRunner.Calls[0].Params[9]) + assert.Equal(t, "testPassword", execRunner.Calls[0].Params[10]) } }) t.Run("CF Delete Service: Success case", func(t *testing.T) { ServiceName := "testInstance" error := cloudFoundryDeleteServiceFunction(ServiceName, &execRunner) if error == nil { - assert.Equal(t, "cf", execRunner.calls[1].exec) - assert.Equal(t, "delete-service", execRunner.calls[1].params[0]) - assert.Equal(t, "testInstance", execRunner.calls[1].params[1]) - assert.Equal(t, "-f", execRunner.calls[1].params[2]) + assert.Equal(t, "cf", execRunner.Calls[1].Exec) + assert.Equal(t, "delete-service", execRunner.Calls[1].Params[0]) + assert.Equal(t, "testInstance", execRunner.Calls[1].Params[1]) + assert.Equal(t, "-f", execRunner.Calls[1].Params[2]) } }) t.Run("CF Logout: Success case", func(t *testing.T) { error := cloudFoundryLogout(&execRunner) if error == nil { - assert.Equal(t, "cf", execRunner.calls[2].exec) - assert.Equal(t, "logout", execRunner.calls[2].params[0]) + assert.Equal(t, "cf", execRunner.Calls[2].Exec) + assert.Equal(t, "logout", execRunner.Calls[2].Params[0]) } }) t.Run("CF Delete Service: Error case", func(t *testing.T) { diff --git a/cmd/detectExecuteScan.go b/cmd/detectExecuteScan.go index b954331e6..e592509e5 100644 --- a/cmd/detectExecuteScan.go +++ b/cmd/detectExecuteScan.go @@ -24,7 +24,7 @@ func runDetect(config detectExecuteScanOptions, command shellRunner) { args = addDetectArgs(args, config) script := strings.Join(args, " ") - command.Dir(".") + command.SetDir(".") err := command.RunShell("/bin/bash", script) if err != nil { diff --git a/cmd/detectExecuteScan_test.go b/cmd/detectExecuteScan_test.go index 8a24c84e3..09db9d16e 100644 --- a/cmd/detectExecuteScan_test.go +++ b/cmd/detectExecuteScan_test.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "github.com/SAP/jenkins-library/pkg/mock" "testing" "github.com/SAP/jenkins-library/pkg/log" @@ -11,20 +12,20 @@ import ( func TestRunDetect(t *testing.T) { t.Run("success case", func(t *testing.T) { - s := shellMockRunner{} + s := mock.ShellMockRunner{} runDetect(detectExecuteScanOptions{}, &s) - assert.Equal(t, ".", s.dir, "Wrong execution directory used") - assert.Equal(t, "/bin/bash", s.shell[0], "Bash shell expected") + assert.Equal(t, ".", s.Dir, "Wrong execution directory used") + assert.Equal(t, "/bin/bash", s.Shell[0], "Bash shell expected") expectedScript := "bash <(curl -s https://detect.synopsys.com/detect.sh) --blackduck.url= --blackduck.api.token= --detect.project.name= --detect.project.version.name= --detect.code.location.name=" - assert.Equal(t, expectedScript, s.calls[0]) + assert.Equal(t, expectedScript, s.Calls[0]) }) t.Run("failure case", func(t *testing.T) { var hasFailed bool log.Entry().Logger.ExitFunc = func(int) { hasFailed = true } - s := shellMockRunner{shouldFailOnCommand: map[string]error{"bash <(curl -s https://detect.synopsys.com/detect.sh) --blackduck.url= --blackduck.api.token= --detect.project.name= --detect.project.version.name= --detect.code.location.name=": fmt.Errorf("Test Error")}} + s := mock.ShellMockRunner{ShouldFailOnCommand: map[string]error{"bash <(curl -s https://detect.synopsys.com/detect.sh) --blackduck.url= --blackduck.api.token= --detect.project.name= --detect.project.version.name= --detect.code.location.name=": fmt.Errorf("Test Error")}} runDetect(detectExecuteScanOptions{}, &s) assert.True(t, hasFailed, "expected command to exit with fatal") }) diff --git a/cmd/interfaces.go b/cmd/interfaces.go index 4b55cdfce..09802e264 100644 --- a/cmd/interfaces.go +++ b/cmd/interfaces.go @@ -5,7 +5,7 @@ import ( ) type runner interface { - Dir(d string) + SetDir(d string) Stdout(out io.Writer) Stderr(err io.Writer) } @@ -17,7 +17,7 @@ type execRunner interface { type envExecRunner interface { execRunner - Env(e []string) + SetEnv(e []string) } type shellRunner interface { diff --git a/cmd/karmaExecuteTests.go b/cmd/karmaExecuteTests.go index e59a4880c..dd3c02787 100644 --- a/cmd/karmaExecuteTests.go +++ b/cmd/karmaExecuteTests.go @@ -19,7 +19,7 @@ func karmaExecuteTests(config karmaExecuteTestsOptions, telemetryData *telemetry func runKarma(config karmaExecuteTestsOptions, command execRunner) { installCommandTokens := tokenize(config.InstallCommand) - command.Dir(config.ModulePath) + command.SetDir(config.ModulePath) err := command.RunExecutable(installCommandTokens[0], installCommandTokens[1:]...) if err != nil { log.Entry(). @@ -29,7 +29,7 @@ func runKarma(config karmaExecuteTestsOptions, command execRunner) { } runCommandTokens := tokenize(config.RunCommand) - command.Dir(config.ModulePath) + command.SetDir(config.ModulePath) err = command.RunExecutable(runCommandTokens[0], runCommandTokens[1:]...) if err != nil { log.Entry(). diff --git a/cmd/karmaExecuteTests_test.go b/cmd/karmaExecuteTests_test.go index b6784c898..d5e10cec3 100644 --- a/cmd/karmaExecuteTests_test.go +++ b/cmd/karmaExecuteTests_test.go @@ -2,6 +2,7 @@ package cmd import ( "errors" + "github.com/SAP/jenkins-library/pkg/mock" "testing" "github.com/SAP/jenkins-library/pkg/log" @@ -12,14 +13,14 @@ func TestRunKarma(t *testing.T) { t.Run("success case", func(t *testing.T) { opts := karmaExecuteTestsOptions{ModulePath: "./test", InstallCommand: "npm install test", RunCommand: "npm run test"} - e := execMockRunner{} + e := mock.ExecMockRunner{} runKarma(opts, &e) - assert.Equal(t, e.dir[0], "./test", "install command dir incorrect") - assert.Equal(t, e.calls[0], execCall{exec: "npm", params: []string{"install", "test"}}, "install command/params incorrect") + assert.Equal(t, e.Dir[0], "./test", "install command dir incorrect") + assert.Equal(t, e.Calls[0], mock.ExecCall{Exec: "npm", Params: []string{"install", "test"}}, "install command/params incorrect") - assert.Equal(t, e.dir[1], "./test", "run command dir incorrect") - assert.Equal(t, e.calls[1], execCall{exec: "npm", params: []string{"run", "test"}}, "run command/params incorrect") + assert.Equal(t, e.Dir[1], "./test", "run command dir incorrect") + assert.Equal(t, e.Calls[1], mock.ExecCall{Exec: "npm", Params: []string{"run", "test"}}, "run command/params incorrect") }) @@ -29,7 +30,7 @@ func TestRunKarma(t *testing.T) { opts := karmaExecuteTestsOptions{ModulePath: "./test", InstallCommand: "fail install test", RunCommand: "npm run test"} - e := execMockRunner{shouldFailOnCommand: map[string]error{"fail install test": errors.New("error case")}} + e := mock.ExecMockRunner{ShouldFailOnCommand: map[string]error{"fail install test": errors.New("error case")}} runKarma(opts, &e) assert.True(t, hasFailed, "expected command to exit with fatal") }) @@ -40,7 +41,7 @@ func TestRunKarma(t *testing.T) { opts := karmaExecuteTestsOptions{ModulePath: "./test", InstallCommand: "npm install test", RunCommand: "npm run test"} - e := execMockRunner{shouldFailOnCommand: map[string]error{"npm install test": errors.New("error case")}} + e := mock.ExecMockRunner{ShouldFailOnCommand: map[string]error{"npm install test": errors.New("error case")}} runKarma(opts, &e) assert.True(t, hasFailed, "expected command to exit with fatal") }) diff --git a/cmd/kubernetesDeploy.go b/cmd/kubernetesDeploy.go index 76158d496..5f28a9f5a 100644 --- a/cmd/kubernetesDeploy.go +++ b/cmd/kubernetesDeploy.go @@ -51,8 +51,8 @@ func runHelmDeploy(config kubernetesDeployOptions, command envExecRunner, stdout if len(config.TillerNamespace) > 0 { helmEnv = append(helmEnv, fmt.Sprintf("TILLER_NAMESPACE=%v", config.TillerNamespace)) } - log.Entry().Debugf("Helm Env: %v", helmEnv) - command.Env(helmEnv) + log.Entry().Debugf("Helm SetEnv: %v", helmEnv) + command.SetEnv(helmEnv) command.Stdout(stdout) initParams := []string{"init", "--client-only"} @@ -144,7 +144,7 @@ func runKubectlDeploy(config kubernetesDeployOptions, command envExecRunner) { if len(config.KubeConfig) > 0 { log.Entry().Info("Using KUBECONFIG environment for authentication.") kubeEnv := []string{fmt.Sprintf("KUBECONFIG=%v", config.KubeConfig)} - command.Env(kubeEnv) + command.SetEnv(kubeEnv) if len(config.KubeContext) > 0 { kubeParams = append(kubeParams, fmt.Sprintf("--context=%v", config.KubeContext)) } diff --git a/cmd/kubernetesDeploy_test.go b/cmd/kubernetesDeploy_test.go index 4f6f76a93..b885a6c65 100644 --- a/cmd/kubernetesDeploy_test.go +++ b/cmd/kubernetesDeploy_test.go @@ -3,6 +3,7 @@ package cmd import ( "bytes" "fmt" + "github.com/SAP/jenkins-library/pkg/mock" "io/ioutil" "os" "path/filepath" @@ -31,8 +32,8 @@ func TestRunKubernetesDeploy(t *testing.T) { dockerConfigJSON := `{"kind": "Secret","data":{".dockerconfigjson": "ThisIsOurBase64EncodedSecret=="}}` - e := execMockRunner{ - stdoutReturn: map[string]string{ + e := mock.ExecMockRunner{ + StdoutReturn: map[string]string{ "kubectl --insecure-skip-tls-verify=true create secret docker-registry regsecret --docker-server=my.registry:55555 --docker-username=registryUser --docker-password=******** --dry-run=true --output=json": dockerConfigJSON, }, } @@ -41,13 +42,13 @@ func TestRunKubernetesDeploy(t *testing.T) { runKubernetesDeploy(opts, &e, &stdout) - assert.Equal(t, "helm", e.calls[0].exec, "Wrong init command") - assert.Equal(t, []string{"init", "--client-only"}, e.calls[0].params, "Wrong init parameters") + assert.Equal(t, "helm", e.Calls[0].Exec, "Wrong init command") + assert.Equal(t, []string{"init", "--client-only"}, e.Calls[0].Params, "Wrong init parameters") - assert.Equal(t, "kubectl", e.calls[1].exec, "Wrong secret creation command") - assert.Equal(t, []string{"--insecure-skip-tls-verify=true", "create", "secret", "docker-registry", "regsecret", "--docker-server=my.registry:55555", "--docker-username=registryUser", "--docker-password=********", "--dry-run=true", "--output=json"}, e.calls[1].params, "Wrong secret creation parameters") + assert.Equal(t, "kubectl", e.Calls[1].Exec, "Wrong secret creation command") + assert.Equal(t, []string{"--insecure-skip-tls-verify=true", "create", "secret", "docker-registry", "regsecret", "--docker-server=my.registry:55555", "--docker-username=registryUser", "--docker-password=********", "--dry-run=true", "--output=json"}, e.Calls[1].Params, "Wrong secret creation parameters") - assert.Equal(t, "helm", e.calls[2].exec, "Wrong upgrade command") + assert.Equal(t, "helm", e.Calls[2].Exec, "Wrong upgrade command") assert.Equal(t, []string{ "upgrade", "deploymentName", @@ -65,7 +66,7 @@ func TestRunKubernetesDeploy(t *testing.T) { "testCluster", "--testParam", "testValue", - }, e.calls[2].params, "Wrong upgrade parameters") + }, e.Calls[2].Params, "Wrong upgrade parameters") }) t.Run("test kubectl - create secret/kubeconfig", func(t *testing.T) { @@ -96,17 +97,17 @@ spec: ioutil.WriteFile(opts.AppTemplate, []byte(kubeYaml), 0755) - e := execMockRunner{ - shouldFailOnCommand: map[string]error{ + e := mock.ExecMockRunner{ + ShouldFailOnCommand: map[string]error{ "kubectl --insecure-skip-tls-verify=true --namespace=deploymentNamespace --context=testCluster get secret regSecret": fmt.Errorf("secret not found"), }, } var stdout bytes.Buffer runKubernetesDeploy(opts, &e, &stdout) - assert.Equal(t, e.env[0], []string{"KUBECONFIG=This is my kubeconfig"}) + assert.Equal(t, e.Env[0], []string{"KUBECONFIG=This is my kubeconfig"}) - assert.Equal(t, "kubectl", e.calls[0].exec, "Wrong secret lookup command") + assert.Equal(t, "kubectl", e.Calls[0].Exec, "Wrong secret lookup command") assert.Equal(t, []string{ "--insecure-skip-tls-verify=true", fmt.Sprintf("--namespace=%v", opts.Namespace), @@ -114,9 +115,9 @@ spec: "get", "secret", opts.ContainerRegistrySecret, - }, e.calls[0].params, "kubectl parameters incorrect") + }, e.Calls[0].Params, "kubectl parameters incorrect") - assert.Equal(t, "kubectl", e.calls[1].exec, "Wrong secret create command") + assert.Equal(t, "kubectl", e.Calls[1].Exec, "Wrong secret create command") assert.Equal(t, []string{ "--insecure-skip-tls-verify=true", fmt.Sprintf("--namespace=%v", opts.Namespace), @@ -128,9 +129,9 @@ spec: "--docker-server=my.registry:55555", fmt.Sprintf("--docker-username=%v", opts.ContainerRegistryUser), fmt.Sprintf("--docker-password=%v", opts.ContainerRegistryPassword), - }, e.calls[1].params, "kubectl parameters incorrect") + }, e.Calls[1].Params, "kubectl parameters incorrect") - assert.Equal(t, "kubectl", e.calls[2].exec, "Wrong apply command") + assert.Equal(t, "kubectl", e.Calls[2].Exec, "Wrong apply command") assert.Equal(t, []string{ "--insecure-skip-tls-verify=true", fmt.Sprintf("--namespace=%v", opts.Namespace), @@ -140,7 +141,7 @@ spec: opts.AppTemplate, "--testParam", "testValue", - }, e.calls[2].params, "kubectl parameters incorrect") + }, e.Calls[2].Params, "kubectl parameters incorrect") appTemplate, err := ioutil.ReadFile(opts.AppTemplate) assert.Contains(t, string(appTemplate), "my.registry:55555/path/to/Image:latest") @@ -166,28 +167,28 @@ spec: ioutil.WriteFile(opts.AppTemplate, []byte("testYaml"), 0755) - e := execMockRunner{} + e := mock.ExecMockRunner{} var stdout bytes.Buffer runKubernetesDeploy(opts, &e, &stdout) - assert.Equal(t, "kubectl", e.calls[0].exec, "Wrong secret lookup command") + assert.Equal(t, "kubectl", e.Calls[0].Exec, "Wrong secret lookup command") assert.Equal(t, []string{ "--insecure-skip-tls-verify=true", fmt.Sprintf("--namespace=%v", opts.Namespace), "get", "secret", opts.ContainerRegistrySecret, - }, e.calls[0].params, "kubectl parameters incorrect") + }, e.Calls[0].Params, "kubectl parameters incorrect") - assert.Equal(t, "kubectl", e.calls[1].exec, "Wrong apply command") + assert.Equal(t, "kubectl", e.Calls[1].Exec, "Wrong apply command") assert.Equal(t, []string{ "--insecure-skip-tls-verify=true", fmt.Sprintf("--namespace=%v", opts.Namespace), "apply", "--filename", opts.AppTemplate, - }, e.calls[1].params, "kubectl parameters incorrect") + }, e.Calls[1].Params, "kubectl parameters incorrect") }) t.Run("test kubectl - token only", func(t *testing.T) { @@ -210,13 +211,13 @@ spec: ioutil.WriteFile(opts.AppTemplate, []byte("testYaml"), 0755) - e := execMockRunner{ - shouldFailOnCommand: map[string]error{}, + e := mock.ExecMockRunner{ + ShouldFailOnCommand: map[string]error{}, } var stdout bytes.Buffer runKubernetesDeploy(opts, &e, &stdout) - assert.Equal(t, "kubectl", e.calls[0].exec, "Wrong apply command") + assert.Equal(t, "kubectl", e.Calls[0].Exec, "Wrong apply command") assert.Equal(t, []string{ "--insecure-skip-tls-verify=true", fmt.Sprintf("--namespace=%v", opts.Namespace), @@ -225,7 +226,7 @@ spec: "apply", "--filename", opts.AppTemplate, - }, e.calls[0].params, "kubectl parameters incorrect") + }, e.Calls[0].Params, "kubectl parameters incorrect") }) } diff --git a/cmd/mtaBuild.go b/cmd/mtaBuild.go index 9119ef7d1..e4d1951d7 100644 --- a/cmd/mtaBuild.go +++ b/cmd/mtaBuild.go @@ -197,7 +197,7 @@ func addNpmBinToPath(e envExecRunner) error { if len(oldPath) > 0 { path = path + ":" + oldPath } - e.Env(append(os.Environ(), "PATH="+path)) + e.SetEnv(append(os.Environ(), "PATH="+path)) return nil } diff --git a/cmd/mtaBuild_test.go b/cmd/mtaBuild_test.go index cb346910b..95a5da667 100644 --- a/cmd/mtaBuild_test.go +++ b/cmd/mtaBuild_test.go @@ -3,6 +3,7 @@ package cmd import ( piperhttp "github.com/SAP/jenkins-library/pkg/http" "github.com/SAP/jenkins-library/pkg/maven" + "github.com/SAP/jenkins-library/pkg/mock" "github.com/SAP/jenkins-library/pkg/piperutils" "github.com/stretchr/testify/assert" "gopkg.in/yaml.v2" @@ -17,7 +18,7 @@ func TestMarBuild(t *testing.T) { t.Run("Application name not set", func(t *testing.T) { - e := execMockRunner{} + e := mock.ExecMockRunner{} options := mtaBuildOptions{} @@ -32,7 +33,7 @@ func TestMarBuild(t *testing.T) { t.Run("Provide default npm registry", func(t *testing.T) { - e := execMockRunner{} + e := mock.ExecMockRunner{} options := mtaBuildOptions{ApplicationName: "myApp", MtaBuildTool: "classic", BuildTarget: "CF", DefaultNpmRegistry: "https://example.org/npm", MtarName: "myName"} @@ -44,15 +45,15 @@ func TestMarBuild(t *testing.T) { assert.Nil(t, err) - if assert.Len(t, e.calls, 2) { // the second (unchecked) entry is the mta call - assert.Equal(t, "npm", e.calls[0].exec) - assert.Equal(t, []string{"config", "set", "registry", "https://example.org/npm"}, e.calls[0].params) + if assert.Len(t, e.Calls, 2) { // the second (unchecked) entry is the mta call + assert.Equal(t, "npm", e.Calls[0].Exec) + assert.Equal(t, []string{"config", "set", "registry", "https://example.org/npm"}, e.Calls[0].Params) } }) t.Run("Package json does not exist", func(t *testing.T) { - e := execMockRunner{} + e := mock.ExecMockRunner{} options := mtaBuildOptions{ApplicationName: "myApp"} @@ -68,7 +69,7 @@ func TestMarBuild(t *testing.T) { t.Run("Write yaml file", func(t *testing.T) { - e := execMockRunner{} + e := mock.ExecMockRunner{} options := mtaBuildOptions{ApplicationName: "myApp", MtaBuildTool: "classic", BuildTarget: "CF", MtarName: "myName"} @@ -107,7 +108,7 @@ func TestMarBuild(t *testing.T) { t.Run("Dont write mta yaml file when already present no timestamp placeholder", func(t *testing.T) { - e := execMockRunner{} + e := mock.ExecMockRunner{} options := mtaBuildOptions{ApplicationName: "myApp", MtaBuildTool: "classic", BuildTarget: "CF"} @@ -123,7 +124,7 @@ func TestMarBuild(t *testing.T) { t.Run("Write mta yaml file when already present with timestamp placeholder", func(t *testing.T) { - e := execMockRunner{} + e := mock.ExecMockRunner{} options := mtaBuildOptions{ApplicationName: "myApp", MtaBuildTool: "classic", BuildTarget: "CF"} @@ -139,7 +140,7 @@ func TestMarBuild(t *testing.T) { t.Run("Test mta build classic toolset", func(t *testing.T) { - e := execMockRunner{} + e := mock.ExecMockRunner{} options := mtaBuildOptions{ApplicationName: "myApp", MtaBuildTool: "classic", BuildTarget: "CF", MtarName: "myName"} @@ -153,9 +154,9 @@ func TestMarBuild(t *testing.T) { assert.Nil(t, err) - if assert.Len(t, e.calls, 1) { - assert.Equal(t, "java", e.calls[0].exec) - assert.Equal(t, []string{"-jar", "mta.jar", "--mtar", "myName.mtar", "--build-target=CF", "build"}, e.calls[0].params) + if assert.Len(t, e.Calls, 1) { + assert.Equal(t, "java", e.Calls[0].Exec) + assert.Equal(t, []string{"-jar", "mta.jar", "--mtar", "myName.mtar", "--build-target=CF", "build"}, e.Calls[0].Params) } assert.Equal(t, "myName.mtar", cpe.mtarFilePath) @@ -163,7 +164,7 @@ func TestMarBuild(t *testing.T) { t.Run("Test mta build classic toolset, mtarName from already existing mta.yaml", func(t *testing.T) { - e := execMockRunner{} + e := mock.ExecMockRunner{} options := mtaBuildOptions{ApplicationName: "myApp", MtaBuildTool: "classic", BuildTarget: "CF"} @@ -178,15 +179,15 @@ func TestMarBuild(t *testing.T) { assert.Nil(t, err) - if assert.Len(t, e.calls, 1) { - assert.Equal(t, "java", e.calls[0].exec) - assert.Equal(t, []string{"-jar", "mta.jar", "--mtar", "myNameFromMtar.mtar", "--build-target=CF", "build"}, e.calls[0].params) + if assert.Len(t, e.Calls, 1) { + assert.Equal(t, "java", e.Calls[0].Exec) + assert.Equal(t, []string{"-jar", "mta.jar", "--mtar", "myNameFromMtar.mtar", "--build-target=CF", "build"}, e.Calls[0].Params) } }) t.Run("Test mta build classic toolset with configured mta jar", func(t *testing.T) { - e := execMockRunner{} + e := mock.ExecMockRunner{} options := mtaBuildOptions{ApplicationName: "myApp", MtaBuildTool: "classic", BuildTarget: "CF", MtaJarLocation: "/opt/sap/mta/lib/mta.jar", MtarName: "myName"} @@ -198,15 +199,15 @@ func TestMarBuild(t *testing.T) { assert.Nil(t, err) - if assert.Len(t, e.calls, 1) { - assert.Equal(t, "java", e.calls[0].exec) - assert.Equal(t, []string{"-jar", "/opt/sap/mta/lib/mta.jar", "--mtar", "myName.mtar", "--build-target=CF", "build"}, e.calls[0].params) + if assert.Len(t, e.Calls, 1) { + assert.Equal(t, "java", e.Calls[0].Exec) + assert.Equal(t, []string{"-jar", "/opt/sap/mta/lib/mta.jar", "--mtar", "myName.mtar", "--build-target=CF", "build"}, e.Calls[0].Params) } }) t.Run("Mta build mbt toolset", func(t *testing.T) { - e := execMockRunner{} + e := mock.ExecMockRunner{} cpe.mtarFilePath = "" @@ -220,9 +221,9 @@ func TestMarBuild(t *testing.T) { assert.Nil(t, err) - if assert.Len(t, e.calls, 1) { - assert.Equal(t, "mbt", e.calls[0].exec) - assert.Equal(t, []string{"build", "--mtar", "myName.mtar", "--platform", "CF", "--target", "./"}, e.calls[0].params) + if assert.Len(t, e.Calls, 1) { + assert.Equal(t, "mbt", e.Calls[0].Exec) + assert.Equal(t, []string{"build", "--mtar", "myName.mtar", "--platform", "CF", "--target", "./"}, e.Calls[0].Params) } assert.Equal(t, "myName.mtar", cpe.mtarFilePath) }) @@ -257,7 +258,7 @@ func TestMarBuild(t *testing.T) { settingsFileType = -1 }() - e := execMockRunner{} + e := mock.ExecMockRunner{} options := mtaBuildOptions{ApplicationName: "myApp", GlobalSettingsFile: "/opt/maven/settings.xml", MtaBuildTool: "cloudMbt", Platform: "CF", MtarName: "myName"} @@ -276,7 +277,7 @@ func TestMarBuild(t *testing.T) { settingsFileType = -1 }() - e := execMockRunner{} + e := mock.ExecMockRunner{} options := mtaBuildOptions{ApplicationName: "myApp", ProjectSettingsFile: "/my/project/settings.xml", MtaBuildTool: "cloudMbt", Platform: "CF", MtarName: "myName"} diff --git a/cmd/piper_test.go b/cmd/piper_test.go index c5299b96a..117b26978 100644 --- a/cmd/piper_test.go +++ b/cmd/piper_test.go @@ -2,171 +2,18 @@ package cmd import ( "fmt" - "io" "io/ioutil" "os" "path/filepath" - "regexp" - "strings" "testing" "github.com/SAP/jenkins-library/pkg/config" + "github.com/SAP/jenkins-library/pkg/mock" "github.com/spf13/cobra" flag "github.com/spf13/pflag" "github.com/stretchr/testify/assert" ) -type execMockRunner struct { - dir []string - env [][]string - calls []execCall - stdout io.Writer - stderr io.Writer - stdoutReturn map[string]string - shouldFailOnCommand map[string]error -} - -type execCall struct { - exec string - params []string -} - -type shellMockRunner struct { - dir string - env [][]string - calls []string - shell []string - stdout io.Writer - stderr io.Writer - stdoutReturn map[string]string - shouldFailOnCommand map[string]error -} - -func (m *execMockRunner) Dir(d string) { - m.dir = append(m.dir, d) -} - -func (m *execMockRunner) Env(e []string) { - m.env = append(m.env, e) -} - -func (m *execMockRunner) RunExecutable(e string, p ...string) error { - - exec := execCall{exec: e, params: p} - m.calls = append(m.calls, exec) - - c := strings.Join(append([]string{e}, p...), " ") - - return handleCall(c, m.stdoutReturn, m.shouldFailOnCommand, m.stdout) -} - -func (m *execMockRunner) Stdout(out io.Writer) { - m.stdout = out -} - -func (m *execMockRunner) Stderr(err io.Writer) { - m.stderr = err -} - -func (m *shellMockRunner) Dir(d string) { - m.dir = d -} - -func (m *shellMockRunner) Env(e []string) { - m.env = append(m.env, e) -} - -func (m *shellMockRunner) RunShell(s string, c string) error { - - m.shell = append(m.shell, s) - m.calls = append(m.calls, c) - - return handleCall(c, m.stdoutReturn, m.shouldFailOnCommand, m.stdout) -} - -func handleCall(call string, stdoutReturn map[string]string, shouldFailOnCommand map[string]error, stdout io.Writer) error { - - if stdoutReturn != nil { - for k, v := range stdoutReturn { - - found := k == call - - if !found { - - r, e := regexp.Compile(k) - if e != nil { - return e - // we don't distinguish here between an error returned - // since it was configured or returning this error here - // indicating an invalid regex. Anyway: when running the - // test we will see it ... - } - if r.MatchString(call) { - found = true - - } - } - - if found { - stdout.Write([]byte(v)) - } - } - } - - if shouldFailOnCommand != nil { - for k, v := range shouldFailOnCommand { - - found := k == call - - if !found { - r, e := regexp.Compile(k) - if e != nil { - return e - // we don't distinguish here between an error returned - // since it was configured or returning this error here - // indicating an invalid regex. Anyway: when running the - // test we will see it ... - } - if r.MatchString(call) { - found = true - - } - } - - if found { - return v - } - } - } - - return nil -} - -func (m *shellMockRunner) Stdout(out io.Writer) { - m.stdout = out -} - -func (m *shellMockRunner) Stderr(err io.Writer) { - m.stderr = err -} - -type stepOptions struct { - TestParam string `json:"testParam,omitempty"` -} - -func openFileMock(name string) (io.ReadCloser, error) { - var r string - switch name { - case "testDefaults.yml": - r = "general:\n testParam: testValue" - case "testDefaultsInvalid.yml": - r = "invalid yaml" - default: - r = "" - } - return ioutil.NopCloser(strings.NewReader(r)), nil -} - func TestAddRootFlags(t *testing.T) { var testRootCmd = &cobra.Command{Use: "test", Short: "This is just a test"} addRootFlags(testRootCmd) @@ -189,7 +36,7 @@ func TestPrepareConfig(t *testing.T) { stepConfigJSONBak := GeneralConfig.StepConfigJSON GeneralConfig.StepConfigJSON = `{"testParam": "testValueJSON"}` defer func() { GeneralConfig.StepConfigJSON = stepConfigJSONBak }() - testOptions := stepOptions{} + testOptions := mock.StepOptions{} var testCmd = &cobra.Command{Use: "test", Short: "This is just a test"} testCmd.Flags().StringVar(&testOptions.TestParam, "testParam", "", "test usage") metadata := config.StepData{ @@ -202,13 +49,13 @@ func TestPrepareConfig(t *testing.T) { }, } - PrepareConfig(testCmd, &metadata, "testStep", &testOptions, openFileMock) + PrepareConfig(testCmd, &metadata, "testStep", &testOptions, mock.OpenFileMock) assert.Equal(t, "testValueJSON", testOptions.TestParam, "wrong value retrieved from config") }) t.Run("using config files", func(t *testing.T) { t.Run("success case", func(t *testing.T) { - testOptions := stepOptions{} + testOptions := mock.StepOptions{} var testCmd = &cobra.Command{Use: "test", Short: "This is just a test"} testCmd.Flags().StringVar(&testOptions.TestParam, "testParam", "", "test usage") metadata := config.StepData{ @@ -221,7 +68,7 @@ func TestPrepareConfig(t *testing.T) { }, } - err := PrepareConfig(testCmd, &metadata, "testStep", &testOptions, openFileMock) + err := PrepareConfig(testCmd, &metadata, "testStep", &testOptions, mock.OpenFileMock) assert.NoError(t, err, "no error expected but error occured") //assert config @@ -237,11 +84,11 @@ func TestPrepareConfig(t *testing.T) { t.Run("error case", func(t *testing.T) { GeneralConfig.DefaultConfig = []string{"testDefaultsInvalid.yml"} - testOptions := stepOptions{} + testOptions := mock.StepOptions{} var testCmd = &cobra.Command{Use: "test", Short: "This is just a test"} metadata := config.StepData{} - err := PrepareConfig(testCmd, &metadata, "testStep", &testOptions, openFileMock) + err := PrepareConfig(testCmd, &metadata, "testStep", &testOptions, mock.OpenFileMock) assert.Error(t, err, "error expected but none occured") }) }) diff --git a/cmd/xsDeploy_test.go b/cmd/xsDeploy_test.go index cbf17317a..c7fa92cf4 100644 --- a/cmd/xsDeploy_test.go +++ b/cmd/xsDeploy_test.go @@ -4,6 +4,7 @@ import ( "bytes" "errors" "fmt" + "github.com/SAP/jenkins-library/pkg/mock" "github.com/stretchr/testify/assert" "io" "io/ioutil" @@ -54,7 +55,7 @@ func TestDeploy(t *testing.T) { OperationIDLogPattern: `^.*xs bg-deploy -i (.*) -a.*$`, } - s := shellMockRunner{} + s := mock.ShellMockRunner{} var removedFiles []string @@ -72,7 +73,7 @@ func TestDeploy(t *testing.T) { defer func() { fileUtilsMock.copiedFiles = nil removedFiles = nil - s.calls = nil + s.Calls = nil stdout = "" }() @@ -97,10 +98,10 @@ func TestDeploy(t *testing.T) { t.Run("Standard checks", func(t *testing.T) { // Contains --> we do not check for the shebang - assert.Contains(t, s.calls[0], "xs login -a https://example.org:12345 -u me -p 'secretPassword' -o myOrg -s mySpace --skip-ssl-validation") - assert.Contains(t, s.calls[1], "xs deploy dummy.mtar --dummy-deploy-opts") - assert.Contains(t, s.calls[2], "xs logout") - assert.Len(t, s.calls, 3) + assert.Contains(t, s.Calls[0], "xs login -a https://example.org:12345 -u me -p 'secretPassword' -o myOrg -s mySpace --skip-ssl-validation") + assert.Contains(t, s.Calls[1], "xs deploy dummy.mtar --dummy-deploy-opts") + assert.Contains(t, s.Calls[2], "xs logout") + assert.Len(t, s.Calls, 3) // xs session file needs to be removed at end during a normal deployment assert.Len(t, removedFiles, 1) @@ -127,7 +128,7 @@ func TestDeploy(t *testing.T) { defer func() { fileUtilsMock.copiedFiles = nil removedFiles = nil - s.calls = nil + s.Calls = nil }() oldMtaPath := myXsDeployOptions.MtaPath @@ -148,7 +149,7 @@ func TestDeploy(t *testing.T) { defer func() { fileUtilsMock.copiedFiles = nil removedFiles = nil - s.calls = nil + s.Calls = nil }() myXsDeployOptions.Action = "RETRY" @@ -165,11 +166,11 @@ func TestDeploy(t *testing.T) { defer func() { fileUtilsMock.copiedFiles = nil removedFiles = nil - s.calls = nil - s.shouldFailOnCommand = nil + s.Calls = nil + s.ShouldFailOnCommand = nil }() - s.shouldFailOnCommand = map[string]error{"#!/bin/bash\nxs login -a https://example.org:12345 -u me -p 'secretPassword' -o myOrg -s mySpace --skip-ssl-validation\n": errors.New("Error from underlying process")} + s.ShouldFailOnCommand = map[string]error{"#!/bin/bash\nxs login -a https://example.org:12345 -u me -p 'secretPassword' -o myOrg -s mySpace --skip-ssl-validation\n": errors.New("Error from underlying process")} e := runXsDeploy(myXsDeployOptions, &s, &fileUtilsMock, fRemove, ioutil.Discard) checkErr(t, e, "Error from underlying process") @@ -180,7 +181,7 @@ func TestDeploy(t *testing.T) { defer func() { fileUtilsMock.copiedFiles = nil removedFiles = nil - s.calls = nil + s.Calls = nil }() oldMode := myXsDeployOptions.Mode @@ -194,9 +195,9 @@ func TestDeploy(t *testing.T) { e := runXsDeploy(myXsDeployOptions, &s, &fileUtilsMock, fRemove, ioutil.Discard) checkErr(t, e, "") - assert.Contains(t, s.calls[0], "xs login") - assert.Contains(t, s.calls[1], "xs bg-deploy dummy.mtar --dummy-deploy-opts") - assert.Len(t, s.calls, 2) // There are two entries --> no logout in this case. + assert.Contains(t, s.Calls[0], "xs login") + assert.Contains(t, s.Calls[1], "xs bg-deploy dummy.mtar --dummy-deploy-opts") + assert.Len(t, s.Calls, 2) // There are two entries --> no logout in this case. }) t.Run("BG deploy abort succeeds", func(t *testing.T) { @@ -204,7 +205,7 @@ func TestDeploy(t *testing.T) { defer func() { fileUtilsMock.copiedFiles = nil removedFiles = nil - s.calls = nil + s.Calls = nil }() oldMode := myXsDeployOptions.Mode @@ -223,9 +224,9 @@ func TestDeploy(t *testing.T) { e := runXsDeploy(myXsDeployOptions, &s, &fileUtilsMock, fRemove, ioutil.Discard) checkErr(t, e, "") - assert.Contains(t, s.calls[0], "xs bg-deploy -i 12345 -a abort") - assert.Contains(t, s.calls[1], "xs logout") - assert.Len(t, s.calls, 2) // There is no login --> we have two calls + assert.Contains(t, s.Calls[0], "xs bg-deploy -i 12345 -a abort") + assert.Contains(t, s.Calls[1], "xs logout") + assert.Len(t, s.Calls, 2) // There is no login --> we have two calls }) t.Run("BG deploy abort fails due to missing operationId", func(t *testing.T) { @@ -233,7 +234,7 @@ func TestDeploy(t *testing.T) { defer func() { fileUtilsMock.copiedFiles = nil removedFiles = nil - s.calls = nil + s.Calls = nil }() oldMode := myXsDeployOptions.Mode diff --git a/integration/integration_api_test.go b/integration/integration_api_test.go index 03bd41c64..df44d2456 100644 --- a/integration/integration_api_test.go +++ b/integration/integration_api_test.go @@ -40,7 +40,7 @@ func TestPiperGithubPublishRelease(t *testing.T) { piperenv.SetResourceParameter(filepath.Join(dir, ".pipeline"), "commonPipelineEnvironment", "artifactVersion", now.Format("20060102150405")) cmd := command.Command{} - cmd.Dir(dir) + cmd.SetDir(dir) piperOptions := []string{ "githubPublishRelease", diff --git a/integration/integration_cli_test.go b/integration/integration_cli_test.go index eb6df1d65..1a7209501 100644 --- a/integration/integration_cli_test.go +++ b/integration/integration_cli_test.go @@ -102,7 +102,7 @@ cd /test assert.Equal(t, 0, code) } -// Dir copies a directory +// copyDir copies a directory func copyDir(source string, target string) error { var err error var fileInfo []os.FileInfo diff --git a/pkg/command/command.go b/pkg/command/command.go index 6eb8c6ace..ef9c442a7 100644 --- a/pkg/command/command.go +++ b/pkg/command/command.go @@ -19,13 +19,13 @@ type Command struct { env []string } -// Dir sets the working directory for the execution -func (c *Command) Dir(d string) { +// SetDir sets the working directory for the execution +func (c *Command) SetDir(d string) { c.dir = d } -// Env sets explicit environment variables to be used for execution -func (c *Command) Env(e []string) { +// SetEnv sets explicit environment variables to be used for execution +func (c *Command) SetEnv(e []string) { c.env = e } diff --git a/pkg/mock/runner.go b/pkg/mock/runner.go new file mode 100644 index 000000000..780a6477e --- /dev/null +++ b/pkg/mock/runner.go @@ -0,0 +1,159 @@ +package mock + +import ( + "io" + "io/ioutil" + "regexp" + "strings" +) + +type ExecMockRunner struct { + Dir []string + Env [][]string + Calls []ExecCall + stdout io.Writer + stderr io.Writer + StdoutReturn map[string]string + ShouldFailOnCommand map[string]error +} + +type ExecCall struct { + Exec string + Params []string +} + +type ShellMockRunner struct { + Dir string + Env [][]string + Calls []string + Shell []string + stdout io.Writer + stderr io.Writer + StdoutReturn map[string]string + ShouldFailOnCommand map[string]error +} + +func (m *ExecMockRunner) SetDir(d string) { + m.Dir = append(m.Dir, d) +} + +func (m *ExecMockRunner) SetEnv(e []string) { + m.Env = append(m.Env, e) +} + +func (m *ExecMockRunner) RunExecutable(e string, p ...string) error { + + exec := ExecCall{Exec: e, Params: p} + m.Calls = append(m.Calls, exec) + + c := strings.Join(append([]string{e}, p...), " ") + + return handleCall(c, m.StdoutReturn, m.ShouldFailOnCommand, m.stdout) +} + +func (m *ExecMockRunner) Stdout(out io.Writer) { + m.stdout = out +} + +func (m *ExecMockRunner) Stderr(err io.Writer) { + m.stderr = err +} + +func (m *ShellMockRunner) SetDir(d string) { + m.Dir = d +} + +func (m *ShellMockRunner) AddToEnv(e []string) { + m.Env = append(m.Env, e) +} + +func (m *ShellMockRunner) RunShell(s string, c string) error { + + m.Shell = append(m.Shell, s) + m.Calls = append(m.Calls, c) + + return handleCall(c, m.StdoutReturn, m.ShouldFailOnCommand, m.stdout) +} + +func handleCall(call string, stdoutReturn map[string]string, shouldFailOnCommand map[string]error, stdout io.Writer) error { + + if stdoutReturn != nil { + for k, v := range stdoutReturn { + + found := k == call + + if !found { + + r, e := regexp.Compile(k) + if e != nil { + return e + // we don't distinguish here between an error returned + // since it was configured or returning this error here + // indicating an invalid regex. Anyway: when running the + // test we will see it ... + } + if r.MatchString(call) { + found = true + + } + } + + if found { + stdout.Write([]byte(v)) + } + } + } + + if shouldFailOnCommand != nil { + for k, v := range shouldFailOnCommand { + + found := k == call + + if !found { + r, e := regexp.Compile(k) + if e != nil { + return e + // we don't distinguish here between an error returned + // since it was configured or returning this error here + // indicating an invalid regex. Anyway: when running the + // test we will see it ... + } + if r.MatchString(call) { + found = true + + } + } + + if found { + return v + } + } + } + + return nil +} + +func (m *ShellMockRunner) Stdout(out io.Writer) { + m.stdout = out +} + +func (m *ShellMockRunner) Stderr(err io.Writer) { + m.stderr = err +} + +type StepOptions struct { + TestParam string `json:"testParam,omitempty"` +} + +func OpenFileMock(name string) (io.ReadCloser, error) { + var r string + switch name { + case "testDefaults.yml": + r = "general:\n testParam: testValue" + case "testDefaultsInvalid.yml": + r = "invalid yaml" + default: + r = "" + } + return ioutil.NopCloser(strings.NewReader(r)), nil +}