diff options
Diffstat (limited to 'pkg/runner/run_context_test.go')
-rw-r--r-- | pkg/runner/run_context_test.go | 705 |
1 files changed, 705 insertions, 0 deletions
diff --git a/pkg/runner/run_context_test.go b/pkg/runner/run_context_test.go new file mode 100644 index 0000000..af0cd4e --- /dev/null +++ b/pkg/runner/run_context_test.go @@ -0,0 +1,705 @@ +package runner + +import ( + "context" + "fmt" + "os" + "regexp" + "runtime" + "sort" + "strings" + "testing" + + "github.com/nektos/act/pkg/exprparser" + "github.com/nektos/act/pkg/model" + + log "github.com/sirupsen/logrus" + assert "github.com/stretchr/testify/assert" + yaml "gopkg.in/yaml.v3" +) + +func TestRunContext_EvalBool(t *testing.T) { + var yml yaml.Node + err := yml.Encode(map[string][]interface{}{ + "os": {"Linux", "Windows"}, + "foo": {"bar", "baz"}, + }) + assert.NoError(t, err) + + rc := &RunContext{ + Config: &Config{ + Workdir: ".", + }, + Env: map[string]string{ + "SOMETHING_TRUE": "true", + "SOMETHING_FALSE": "false", + "SOME_TEXT": "text", + }, + Run: &model.Run{ + JobID: "job1", + Workflow: &model.Workflow{ + Name: "test-workflow", + Jobs: map[string]*model.Job{ + "job1": { + Strategy: &model.Strategy{ + RawMatrix: yml, + }, + }, + }, + }, + }, + Matrix: map[string]interface{}{ + "os": "Linux", + "foo": "bar", + }, + StepResults: map[string]*model.StepResult{ + "id1": { + Conclusion: model.StepStatusSuccess, + Outcome: model.StepStatusFailure, + Outputs: map[string]string{ + "foo": "bar", + }, + }, + }, + } + rc.ExprEval = rc.NewExpressionEvaluator(context.Background()) + + tables := []struct { + in string + out bool + wantErr bool + }{ + // The basic ones + {in: "failure()", out: false}, + {in: "success()", out: true}, + {in: "cancelled()", out: false}, + {in: "always()", out: true}, + // TODO: move to sc.NewExpressionEvaluator(), because "steps" context is not available here + // {in: "steps.id1.conclusion == 'success'", out: true}, + // {in: "steps.id1.conclusion != 'success'", out: false}, + // {in: "steps.id1.outcome == 'failure'", out: true}, + // {in: "steps.id1.outcome != 'failure'", out: false}, + {in: "true", out: true}, + {in: "false", out: false}, + // TODO: This does not throw an error, because the evaluator does not know if the expression is inside ${{ }} or not + // {in: "!true", wantErr: true}, + // {in: "!false", wantErr: true}, + {in: "1 != 0", out: true}, + {in: "1 != 1", out: false}, + {in: "${{ 1 != 0 }}", out: true}, + {in: "${{ 1 != 1 }}", out: false}, + {in: "1 == 0", out: false}, + {in: "1 == 1", out: true}, + {in: "1 > 2", out: false}, + {in: "1 < 2", out: true}, + // And or + {in: "true && false", out: false}, + {in: "true && 1 < 2", out: true}, + {in: "false || 1 < 2", out: true}, + {in: "false || false", out: false}, + // None boolable + {in: "env.UNKNOWN == 'true'", out: false}, + {in: "env.UNKNOWN", out: false}, + // Inline expressions + {in: "env.SOME_TEXT", out: true}, + {in: "env.SOME_TEXT == 'text'", out: true}, + {in: "env.SOMETHING_TRUE == 'true'", out: true}, + {in: "env.SOMETHING_FALSE == 'true'", out: false}, + {in: "env.SOMETHING_TRUE", out: true}, + {in: "env.SOMETHING_FALSE", out: true}, + // TODO: This does not throw an error, because the evaluator does not know if the expression is inside ${{ }} or not + // {in: "!env.SOMETHING_TRUE", wantErr: true}, + // {in: "!env.SOMETHING_FALSE", wantErr: true}, + {in: "${{ !env.SOMETHING_TRUE }}", out: false}, + {in: "${{ !env.SOMETHING_FALSE }}", out: false}, + {in: "${{ ! env.SOMETHING_TRUE }}", out: false}, + {in: "${{ ! env.SOMETHING_FALSE }}", out: false}, + {in: "${{ env.SOMETHING_TRUE }}", out: true}, + {in: "${{ env.SOMETHING_FALSE }}", out: true}, + {in: "${{ !env.SOMETHING_TRUE }}", out: false}, + {in: "${{ !env.SOMETHING_FALSE }}", out: false}, + {in: "${{ !env.SOMETHING_TRUE && true }}", out: false}, + {in: "${{ !env.SOMETHING_FALSE && true }}", out: false}, + {in: "${{ !env.SOMETHING_TRUE || true }}", out: true}, + {in: "${{ !env.SOMETHING_FALSE || false }}", out: false}, + {in: "${{ env.SOMETHING_TRUE && true }}", out: true}, + {in: "${{ env.SOMETHING_FALSE || true }}", out: true}, + {in: "${{ env.SOMETHING_FALSE || false }}", out: true}, + // TODO: This does not throw an error, because the evaluator does not know if the expression is inside ${{ }} or not + // {in: "!env.SOMETHING_TRUE || true", wantErr: true}, + {in: "${{ env.SOMETHING_TRUE == 'true'}}", out: true}, + {in: "${{ env.SOMETHING_FALSE == 'true'}}", out: false}, + {in: "${{ env.SOMETHING_FALSE == 'false'}}", out: true}, + {in: "${{ env.SOMETHING_FALSE }} && ${{ env.SOMETHING_TRUE }}", out: true}, + + // All together now + {in: "false || env.SOMETHING_TRUE == 'true'", out: true}, + {in: "true || env.SOMETHING_FALSE == 'true'", out: true}, + {in: "true && env.SOMETHING_TRUE == 'true'", out: true}, + {in: "false && env.SOMETHING_TRUE == 'true'", out: false}, + {in: "env.SOMETHING_FALSE == 'true' && env.SOMETHING_TRUE == 'true'", out: false}, + {in: "env.SOMETHING_FALSE == 'true' && true", out: false}, + {in: "${{ env.SOMETHING_FALSE == 'true' }} && true", out: true}, + {in: "true && ${{ env.SOMETHING_FALSE == 'true' }}", out: true}, + // Check github context + {in: "github.actor == 'nektos/act'", out: true}, + {in: "github.actor == 'unknown'", out: false}, + {in: "github.job == 'job1'", out: true}, + // The special ACT flag + {in: "${{ env.ACT }}", out: true}, + {in: "${{ !env.ACT }}", out: false}, + // Invalid expressions should be reported + {in: "INVALID_EXPRESSION", wantErr: true}, + } + + updateTestIfWorkflow(t, tables, rc) + for _, table := range tables { + table := table + t.Run(table.in, func(t *testing.T) { + assertObject := assert.New(t) + b, err := EvalBool(context.Background(), rc.ExprEval, table.in, exprparser.DefaultStatusCheckSuccess) + if table.wantErr { + assertObject.Error(err) + } + + assertObject.Equal(table.out, b, fmt.Sprintf("Expected %s to be %v, was %v", table.in, table.out, b)) + }) + } +} + +func updateTestIfWorkflow(t *testing.T, tables []struct { + in string + out bool + wantErr bool +}, rc *RunContext) { + var envs string + keys := make([]string, 0, len(rc.Env)) + for k := range rc.Env { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + envs += fmt.Sprintf(" %s: %s\n", k, rc.Env[k]) + } + // editorconfig-checker-disable + workflow := fmt.Sprintf(` +name: "Test what expressions result in true and false on GitHub" +on: push + +env: +%s + +jobs: + test-ifs-and-buts: + runs-on: ubuntu-latest + steps: +`, envs) + // editorconfig-checker-enable + + for i, table := range tables { + if table.wantErr || strings.HasPrefix(table.in, "github.actor") { + continue + } + expressionPattern := regexp.MustCompile(`\${{\s*(.+?)\s*}}`) + + expr := expressionPattern.ReplaceAllStringFunc(table.in, func(match string) string { + return fmt.Sprintf("€{{ %s }}", expressionPattern.ReplaceAllString(match, "$1")) + }) + echo := fmt.Sprintf(`run: echo "%s should be false, but was evaluated to true;" exit 1;`, table.in) + name := fmt.Sprintf(`"❌ I should not run, expr: %s"`, expr) + if table.out { + echo = `run: echo OK` + name = fmt.Sprintf(`"✅ I should run, expr: %s"`, expr) + } + workflow += fmt.Sprintf("\n - name: %s\n id: step%d\n if: %s\n %s\n", name, i, table.in, echo) + if table.out { + workflow += fmt.Sprintf("\n - name: \"Double checking expr: %s\"\n if: steps.step%d.conclusion == 'skipped'\n run: echo \"%s should have been true, but wasn't\"\n", expr, i, table.in) + } + } + + file, err := os.Create("../../.github/workflows/test-if.yml") + if err != nil { + t.Fatal(err) + } + + _, err = file.WriteString(workflow) + if err != nil { + t.Fatal(err) + } +} + +func TestRunContext_GetBindsAndMounts(t *testing.T) { + rctemplate := &RunContext{ + Name: "TestRCName", + Run: &model.Run{ + Workflow: &model.Workflow{ + Name: "TestWorkflowName", + }, + }, + Config: &Config{ + BindWorkdir: false, + }, + } + + tests := []struct { + windowsPath bool + name string + rc *RunContext + wantbind string + wantmount string + }{ + {false, "/mnt/linux", rctemplate, "/mnt/linux", "/mnt/linux"}, + {false, "/mnt/path with spaces/linux", rctemplate, "/mnt/path with spaces/linux", "/mnt/path with spaces/linux"}, + {true, "C:\\Users\\TestPath\\MyTestPath", rctemplate, "/mnt/c/Users/TestPath/MyTestPath", "/mnt/c/Users/TestPath/MyTestPath"}, + {true, "C:\\Users\\Test Path with Spaces\\MyTestPath", rctemplate, "/mnt/c/Users/Test Path with Spaces/MyTestPath", "/mnt/c/Users/Test Path with Spaces/MyTestPath"}, + {true, "/LinuxPathOnWindowsShouldFail", rctemplate, "", ""}, + } + + isWindows := runtime.GOOS == "windows" + + for _, testcase := range tests { + // pin for scopelint + testcase := testcase + for _, bindWorkDir := range []bool{true, false} { + // pin for scopelint + bindWorkDir := bindWorkDir + testBindSuffix := "" + if bindWorkDir { + testBindSuffix = "Bind" + } + + // Only run windows path tests on windows and non-windows on non-windows + if (isWindows && testcase.windowsPath) || (!isWindows && !testcase.windowsPath) { + t.Run((testcase.name + testBindSuffix), func(t *testing.T) { + config := testcase.rc.Config + config.Workdir = testcase.name + config.BindWorkdir = bindWorkDir + gotbind, gotmount := rctemplate.GetBindsAndMounts() + + // Name binds/mounts are either/or + if config.BindWorkdir { + fullBind := testcase.name + ":" + testcase.wantbind + if runtime.GOOS == "darwin" { + fullBind += ":delegated" + } + assert.Contains(t, gotbind, fullBind) + } else { + mountkey := testcase.rc.jobContainerName() + assert.EqualValues(t, testcase.wantmount, gotmount[mountkey]) + } + }) + } + } + } + + t.Run("ContainerVolumeMountTest", func(t *testing.T) { + tests := []struct { + name string + volumes []string + wantbind string + wantmount map[string]string + }{ + {"BindAnonymousVolume", []string{"/volume"}, "/volume", map[string]string{}}, + {"BindHostFile", []string{"/path/to/file/on/host:/volume"}, "/path/to/file/on/host:/volume", map[string]string{}}, + {"MountExistingVolume", []string{"volume-id:/volume"}, "", map[string]string{"volume-id": "/volume"}}, + } + + for _, testcase := range tests { + t.Run(testcase.name, func(t *testing.T) { + job := &model.Job{} + err := job.RawContainer.Encode(map[string][]string{ + "volumes": testcase.volumes, + }) + assert.NoError(t, err) + + rc := &RunContext{ + Name: "TestRCName", + Run: &model.Run{ + Workflow: &model.Workflow{ + Name: "TestWorkflowName", + }, + }, + Config: &Config{ + BindWorkdir: false, + }, + } + rc.Run.JobID = "job1" + rc.Run.Workflow.Jobs = map[string]*model.Job{"job1": job} + + gotbind, gotmount := rc.GetBindsAndMounts() + + if len(testcase.wantbind) > 0 { + assert.Contains(t, gotbind, testcase.wantbind) + } + + for k, v := range testcase.wantmount { + assert.Contains(t, gotmount, k) + assert.Equal(t, gotmount[k], v) + } + }) + } + }) +} + +func TestGetGitHubContext(t *testing.T) { + log.SetLevel(log.DebugLevel) + + cwd, err := os.Getwd() + assert.Nil(t, err) + + rc := &RunContext{ + Config: &Config{ + EventName: "push", + Workdir: cwd, + }, + Run: &model.Run{ + Workflow: &model.Workflow{ + Name: "GitHubContextTest", + }, + }, + Name: "GitHubContextTest", + CurrentStep: "step", + Matrix: map[string]interface{}{}, + Env: map[string]string{}, + ExtraPath: []string{}, + StepResults: map[string]*model.StepResult{}, + OutputMappings: map[MappableOutput]MappableOutput{}, + } + rc.Run.JobID = "job1" + + ghc := rc.getGithubContext(context.Background()) + + log.Debugf("%v", ghc) + + actor := "nektos/act" + if a := os.Getenv("ACT_ACTOR"); a != "" { + actor = a + } + + repo := "nektos/act" + if r := os.Getenv("ACT_REPOSITORY"); r != "" { + repo = r + } + + owner := "nektos" + if o := os.Getenv("ACT_OWNER"); o != "" { + owner = o + } + + assert.Equal(t, ghc.RunID, "1") + assert.Equal(t, ghc.RunNumber, "1") + assert.Equal(t, ghc.RetentionDays, "0") + assert.Equal(t, ghc.Actor, actor) + assert.Equal(t, ghc.Repository, repo) + assert.Equal(t, ghc.RepositoryOwner, owner) + assert.Equal(t, ghc.RunnerPerflog, "/dev/null") + assert.Equal(t, ghc.Token, rc.Config.Secrets["GITHUB_TOKEN"]) + assert.Equal(t, ghc.Job, "job1") +} + +func TestGetGithubContextRef(t *testing.T) { + table := []struct { + event string + json string + ref string + }{ + {event: "push", json: `{"ref":"0000000000000000000000000000000000000000"}`, ref: "0000000000000000000000000000000000000000"}, + {event: "create", json: `{"ref":"0000000000000000000000000000000000000000"}`, ref: "0000000000000000000000000000000000000000"}, + {event: "workflow_dispatch", json: `{"ref":"0000000000000000000000000000000000000000"}`, ref: "0000000000000000000000000000000000000000"}, + {event: "delete", json: `{"repository":{"default_branch": "main"}}`, ref: "refs/heads/main"}, + {event: "pull_request", json: `{"number":123}`, ref: "refs/pull/123/merge"}, + {event: "pull_request_review", json: `{"number":123}`, ref: "refs/pull/123/merge"}, + {event: "pull_request_review_comment", json: `{"number":123}`, ref: "refs/pull/123/merge"}, + {event: "pull_request_target", json: `{"pull_request":{"base":{"ref": "main"}}}`, ref: "refs/heads/main"}, + {event: "deployment", json: `{"deployment": {"ref": "tag-name"}}`, ref: "tag-name"}, + {event: "deployment_status", json: `{"deployment": {"ref": "tag-name"}}`, ref: "tag-name"}, + {event: "release", json: `{"release": {"tag_name": "tag-name"}}`, ref: "refs/tags/tag-name"}, + } + + for _, data := range table { + data := data + t.Run(data.event, func(t *testing.T) { + rc := &RunContext{ + EventJSON: data.json, + Config: &Config{ + EventName: data.event, + Workdir: "", + }, + Run: &model.Run{ + Workflow: &model.Workflow{ + Name: "GitHubContextTest", + }, + }, + } + + ghc := rc.getGithubContext(context.Background()) + + assert.Equal(t, data.ref, ghc.Ref) + }) + } +} + +func createIfTestRunContext(jobs map[string]*model.Job) *RunContext { + rc := &RunContext{ + Config: &Config{ + Workdir: ".", + Platforms: map[string]string{ + "ubuntu-latest": "ubuntu-latest", + }, + }, + Env: map[string]string{}, + Run: &model.Run{ + JobID: "job1", + Workflow: &model.Workflow{ + Name: "test-workflow", + Jobs: jobs, + }, + }, + } + rc.ExprEval = rc.NewExpressionEvaluator(context.Background()) + + return rc +} + +func createJob(t *testing.T, input string, result string) *model.Job { + var job *model.Job + err := yaml.Unmarshal([]byte(input), &job) + assert.NoError(t, err) + job.Result = result + + return job +} + +func TestRunContextRunsOnPlatformNames(t *testing.T) { + log.SetLevel(log.DebugLevel) + assertObject := assert.New(t) + + rc := createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: ubuntu-latest`, ""), + }) + assertObject.Equal([]string{"ubuntu-latest"}, rc.runsOnPlatformNames(context.Background())) + + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: ${{ 'ubuntu-latest' }}`, ""), + }) + assertObject.Equal([]string{"ubuntu-latest"}, rc.runsOnPlatformNames(context.Background())) + + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: [self-hosted, my-runner]`, ""), + }) + assertObject.Equal([]string{"self-hosted", "my-runner"}, rc.runsOnPlatformNames(context.Background())) + + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: [self-hosted, "${{ 'my-runner' }}"]`, ""), + }) + assertObject.Equal([]string{"self-hosted", "my-runner"}, rc.runsOnPlatformNames(context.Background())) + + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: ${{ fromJSON('["ubuntu-latest"]') }}`, ""), + }) + assertObject.Equal([]string{"ubuntu-latest"}, rc.runsOnPlatformNames(context.Background())) + + // test missing / invalid runs-on + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `name: something`, ""), + }) + assertObject.Equal([]string{}, rc.runsOnPlatformNames(context.Background())) + + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: + mapping: value`, ""), + }) + assertObject.Equal([]string{}, rc.runsOnPlatformNames(context.Background())) + + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: ${{ invalid expression }}`, ""), + }) + assertObject.Equal([]string{}, rc.runsOnPlatformNames(context.Background())) +} + +func TestRunContextIsEnabled(t *testing.T) { + log.SetLevel(log.DebugLevel) + assertObject := assert.New(t) + + // success() + rc := createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: ubuntu-latest +if: success()`, ""), + }) + assertObject.True(rc.isEnabled(context.Background())) + + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: ubuntu-latest`, "failure"), + "job2": createJob(t, `runs-on: ubuntu-latest +needs: [job1] +if: success()`, ""), + }) + rc.Run.JobID = "job2" + assertObject.False(rc.isEnabled(context.Background())) + + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: ubuntu-latest`, "success"), + "job2": createJob(t, `runs-on: ubuntu-latest +needs: [job1] +if: success()`, ""), + }) + rc.Run.JobID = "job2" + assertObject.True(rc.isEnabled(context.Background())) + + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: ubuntu-latest`, "failure"), + "job2": createJob(t, `runs-on: ubuntu-latest +if: success()`, ""), + }) + rc.Run.JobID = "job2" + assertObject.True(rc.isEnabled(context.Background())) + + // failure() + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: ubuntu-latest +if: failure()`, ""), + }) + assertObject.False(rc.isEnabled(context.Background())) + + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: ubuntu-latest`, "failure"), + "job2": createJob(t, `runs-on: ubuntu-latest +needs: [job1] +if: failure()`, ""), + }) + rc.Run.JobID = "job2" + assertObject.True(rc.isEnabled(context.Background())) + + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: ubuntu-latest`, "success"), + "job2": createJob(t, `runs-on: ubuntu-latest +needs: [job1] +if: failure()`, ""), + }) + rc.Run.JobID = "job2" + assertObject.False(rc.isEnabled(context.Background())) + + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: ubuntu-latest`, "failure"), + "job2": createJob(t, `runs-on: ubuntu-latest +if: failure()`, ""), + }) + rc.Run.JobID = "job2" + assertObject.False(rc.isEnabled(context.Background())) + + // always() + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: ubuntu-latest +if: always()`, ""), + }) + assertObject.True(rc.isEnabled(context.Background())) + + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: ubuntu-latest`, "failure"), + "job2": createJob(t, `runs-on: ubuntu-latest +needs: [job1] +if: always()`, ""), + }) + rc.Run.JobID = "job2" + assertObject.True(rc.isEnabled(context.Background())) + + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: ubuntu-latest`, "success"), + "job2": createJob(t, `runs-on: ubuntu-latest +needs: [job1] +if: always()`, ""), + }) + rc.Run.JobID = "job2" + assertObject.True(rc.isEnabled(context.Background())) + + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `runs-on: ubuntu-latest`, "success"), + "job2": createJob(t, `runs-on: ubuntu-latest +if: always()`, ""), + }) + rc.Run.JobID = "job2" + assertObject.True(rc.isEnabled(context.Background())) + + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `uses: ./.github/workflows/reusable.yml`, ""), + }) + assertObject.True(rc.isEnabled(context.Background())) + + rc = createIfTestRunContext(map[string]*model.Job{ + "job1": createJob(t, `uses: ./.github/workflows/reusable.yml +if: false`, ""), + }) + assertObject.False(rc.isEnabled(context.Background())) +} + +func TestRunContextGetEnv(t *testing.T) { + tests := []struct { + description string + rc *RunContext + targetEnv string + want string + }{ + { + description: "Env from Config should overwrite", + rc: &RunContext{ + Config: &Config{ + Env: map[string]string{"OVERWRITTEN": "true"}, + }, + Run: &model.Run{ + Workflow: &model.Workflow{ + Jobs: map[string]*model.Job{"test": {Name: "test"}}, + Env: map[string]string{"OVERWRITTEN": "false"}, + }, + JobID: "test", + }, + }, + targetEnv: "OVERWRITTEN", + want: "true", + }, + { + description: "No overwrite occurs", + rc: &RunContext{ + Config: &Config{ + Env: map[string]string{"SOME_OTHER_VAR": "true"}, + }, + Run: &model.Run{ + Workflow: &model.Workflow{ + Jobs: map[string]*model.Job{"test": {Name: "test"}}, + Env: map[string]string{"OVERWRITTEN": "false"}, + }, + JobID: "test", + }, + }, + targetEnv: "OVERWRITTEN", + want: "false", + }, + } + + for _, test := range tests { + t.Run(test.description, func(t *testing.T) { + envMap := test.rc.GetEnv() + assert.EqualValues(t, test.want, envMap[test.targetEnv]) + }) + } +} + +func Test_createSimpleContainerName(t *testing.T) { + tests := []struct { + parts []string + want string + }{ + { + parts: []string{"a--a", "BB正", "c-C"}, + want: "a-a_BB_c-C", + }, + { + parts: []string{"a-a", "", "-"}, + want: "a-a", + }, + } + for _, tt := range tests { + t.Run(strings.Join(tt.parts, " "), func(t *testing.T) { + assert.Equalf(t, tt.want, createSimpleContainerName(tt.parts...), "createSimpleContainerName(%v)", tt.parts) + }) + } +} |