summaryrefslogtreecommitdiffstats
path: root/pkg/runner/step_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/runner/step_test.go')
-rw-r--r--pkg/runner/step_test.go346
1 files changed, 346 insertions, 0 deletions
diff --git a/pkg/runner/step_test.go b/pkg/runner/step_test.go
new file mode 100644
index 0000000..d08a129
--- /dev/null
+++ b/pkg/runner/step_test.go
@@ -0,0 +1,346 @@
+package runner
+
+import (
+ "context"
+ "testing"
+
+ "github.com/nektos/act/pkg/common"
+ "github.com/nektos/act/pkg/model"
+ log "github.com/sirupsen/logrus"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+ yaml "gopkg.in/yaml.v3"
+)
+
+func TestMergeIntoMap(t *testing.T) {
+ table := []struct {
+ name string
+ target map[string]string
+ maps []map[string]string
+ expected map[string]string
+ }{
+ {
+ name: "testEmptyMap",
+ target: map[string]string{},
+ maps: []map[string]string{},
+ expected: map[string]string{},
+ },
+ {
+ name: "testMergeIntoEmptyMap",
+ target: map[string]string{},
+ maps: []map[string]string{
+ {
+ "key1": "value1",
+ "key2": "value2",
+ }, {
+ "key2": "overridden",
+ "key3": "value3",
+ },
+ },
+ expected: map[string]string{
+ "key1": "value1",
+ "key2": "overridden",
+ "key3": "value3",
+ },
+ },
+ {
+ name: "testMergeIntoExistingMap",
+ target: map[string]string{
+ "key1": "value1",
+ "key2": "value2",
+ },
+ maps: []map[string]string{
+ {
+ "key1": "overridden",
+ },
+ },
+ expected: map[string]string{
+ "key1": "overridden",
+ "key2": "value2",
+ },
+ },
+ }
+
+ for _, tt := range table {
+ t.Run(tt.name, func(t *testing.T) {
+ mergeIntoMapCaseSensitive(tt.target, tt.maps...)
+ assert.Equal(t, tt.expected, tt.target)
+ mergeIntoMapCaseInsensitive(tt.target, tt.maps...)
+ assert.Equal(t, tt.expected, tt.target)
+ })
+ }
+}
+
+type stepMock struct {
+ mock.Mock
+ step
+}
+
+func (sm *stepMock) pre() common.Executor {
+ args := sm.Called()
+ return args.Get(0).(func(context.Context) error)
+}
+
+func (sm *stepMock) main() common.Executor {
+ args := sm.Called()
+ return args.Get(0).(func(context.Context) error)
+}
+
+func (sm *stepMock) post() common.Executor {
+ args := sm.Called()
+ return args.Get(0).(func(context.Context) error)
+}
+
+func (sm *stepMock) getRunContext() *RunContext {
+ args := sm.Called()
+ return args.Get(0).(*RunContext)
+}
+
+func (sm *stepMock) getGithubContext(ctx context.Context) *model.GithubContext {
+ args := sm.Called()
+ return args.Get(0).(*RunContext).getGithubContext(ctx)
+}
+
+func (sm *stepMock) getStepModel() *model.Step {
+ args := sm.Called()
+ return args.Get(0).(*model.Step)
+}
+
+func (sm *stepMock) getEnv() *map[string]string {
+ args := sm.Called()
+ return args.Get(0).(*map[string]string)
+}
+
+func TestSetupEnv(t *testing.T) {
+ cm := &containerMock{}
+ sm := &stepMock{}
+
+ rc := &RunContext{
+ Config: &Config{
+ Env: map[string]string{
+ "GITHUB_RUN_ID": "runId",
+ },
+ },
+ Run: &model.Run{
+ JobID: "1",
+ Workflow: &model.Workflow{
+ Jobs: map[string]*model.Job{
+ "1": {
+ Env: yaml.Node{
+ Value: "JOB_KEY: jobvalue",
+ },
+ },
+ },
+ },
+ },
+ Env: map[string]string{
+ "RC_KEY": "rcvalue",
+ },
+ JobContainer: cm,
+ }
+ step := &model.Step{
+ With: map[string]string{
+ "STEP_WITH": "with-value",
+ },
+ }
+ env := map[string]string{}
+
+ sm.On("getRunContext").Return(rc)
+ sm.On("getGithubContext").Return(rc)
+ sm.On("getStepModel").Return(step)
+ sm.On("getEnv").Return(&env)
+
+ err := setupEnv(context.Background(), sm)
+ assert.Nil(t, err)
+
+ // These are commit or system specific
+ delete((env), "GITHUB_REF")
+ delete((env), "GITHUB_REF_NAME")
+ delete((env), "GITHUB_REF_TYPE")
+ delete((env), "GITHUB_SHA")
+ delete((env), "GITHUB_WORKSPACE")
+ delete((env), "GITHUB_REPOSITORY")
+ delete((env), "GITHUB_REPOSITORY_OWNER")
+ delete((env), "GITHUB_ACTOR")
+
+ assert.Equal(t, map[string]string{
+ "ACT": "true",
+ "CI": "true",
+ "GITHUB_ACTION": "",
+ "GITHUB_ACTIONS": "true",
+ "GITHUB_ACTION_PATH": "",
+ "GITHUB_ACTION_REF": "",
+ "GITHUB_ACTION_REPOSITORY": "",
+ "GITHUB_API_URL": "https:///api/v3",
+ "GITHUB_BASE_REF": "",
+ "GITHUB_EVENT_NAME": "",
+ "GITHUB_EVENT_PATH": "/var/run/act/workflow/event.json",
+ "GITHUB_GRAPHQL_URL": "https:///api/graphql",
+ "GITHUB_HEAD_REF": "",
+ "GITHUB_JOB": "1",
+ "GITHUB_RETENTION_DAYS": "0",
+ "GITHUB_RUN_ID": "runId",
+ "GITHUB_RUN_NUMBER": "1",
+ "GITHUB_SERVER_URL": "https://",
+ "GITHUB_TOKEN": "",
+ "GITHUB_WORKFLOW": "",
+ "INPUT_STEP_WITH": "with-value",
+ "RC_KEY": "rcvalue",
+ "RUNNER_PERFLOG": "/dev/null",
+ "RUNNER_TRACKING_ID": "",
+ }, env)
+
+ cm.AssertExpectations(t)
+}
+
+func TestIsStepEnabled(t *testing.T) {
+ createTestStep := func(t *testing.T, input string) step {
+ var step *model.Step
+ err := yaml.Unmarshal([]byte(input), &step)
+ assert.NoError(t, err)
+
+ return &stepRun{
+ RunContext: &RunContext{
+ Config: &Config{
+ Workdir: ".",
+ Platforms: map[string]string{
+ "ubuntu-latest": "ubuntu-latest",
+ },
+ },
+ StepResults: map[string]*model.StepResult{},
+ Env: map[string]string{},
+ Run: &model.Run{
+ JobID: "job1",
+ Workflow: &model.Workflow{
+ Name: "workflow1",
+ Jobs: map[string]*model.Job{
+ "job1": createJob(t, `runs-on: ubuntu-latest`, ""),
+ },
+ },
+ },
+ },
+ Step: step,
+ }
+ }
+
+ log.SetLevel(log.DebugLevel)
+ assertObject := assert.New(t)
+
+ // success()
+ step := createTestStep(t, "if: success()")
+ assertObject.True(isStepEnabled(context.Background(), step.getIfExpression(context.Background(), stepStageMain), step, stepStageMain))
+
+ step = createTestStep(t, "if: success()")
+ step.getRunContext().StepResults["a"] = &model.StepResult{
+ Conclusion: model.StepStatusSuccess,
+ }
+ assertObject.True(isStepEnabled(context.Background(), step.getStepModel().If.Value, step, stepStageMain))
+
+ step = createTestStep(t, "if: success()")
+ step.getRunContext().StepResults["a"] = &model.StepResult{
+ Conclusion: model.StepStatusFailure,
+ }
+ assertObject.False(isStepEnabled(context.Background(), step.getStepModel().If.Value, step, stepStageMain))
+
+ // failure()
+ step = createTestStep(t, "if: failure()")
+ assertObject.False(isStepEnabled(context.Background(), step.getStepModel().If.Value, step, stepStageMain))
+
+ step = createTestStep(t, "if: failure()")
+ step.getRunContext().StepResults["a"] = &model.StepResult{
+ Conclusion: model.StepStatusSuccess,
+ }
+ assertObject.False(isStepEnabled(context.Background(), step.getStepModel().If.Value, step, stepStageMain))
+
+ step = createTestStep(t, "if: failure()")
+ step.getRunContext().StepResults["a"] = &model.StepResult{
+ Conclusion: model.StepStatusFailure,
+ }
+ assertObject.True(isStepEnabled(context.Background(), step.getStepModel().If.Value, step, stepStageMain))
+
+ // always()
+ step = createTestStep(t, "if: always()")
+ assertObject.True(isStepEnabled(context.Background(), step.getStepModel().If.Value, step, stepStageMain))
+
+ step = createTestStep(t, "if: always()")
+ step.getRunContext().StepResults["a"] = &model.StepResult{
+ Conclusion: model.StepStatusSuccess,
+ }
+ assertObject.True(isStepEnabled(context.Background(), step.getStepModel().If.Value, step, stepStageMain))
+
+ step = createTestStep(t, "if: always()")
+ step.getRunContext().StepResults["a"] = &model.StepResult{
+ Conclusion: model.StepStatusFailure,
+ }
+ assertObject.True(isStepEnabled(context.Background(), step.getStepModel().If.Value, step, stepStageMain))
+}
+
+func TestIsContinueOnError(t *testing.T) {
+ createTestStep := func(t *testing.T, input string) step {
+ var step *model.Step
+ err := yaml.Unmarshal([]byte(input), &step)
+ assert.NoError(t, err)
+
+ return &stepRun{
+ RunContext: &RunContext{
+ Config: &Config{
+ Workdir: ".",
+ Platforms: map[string]string{
+ "ubuntu-latest": "ubuntu-latest",
+ },
+ },
+ StepResults: map[string]*model.StepResult{},
+ Env: map[string]string{},
+ Run: &model.Run{
+ JobID: "job1",
+ Workflow: &model.Workflow{
+ Name: "workflow1",
+ Jobs: map[string]*model.Job{
+ "job1": createJob(t, `runs-on: ubuntu-latest`, ""),
+ },
+ },
+ },
+ },
+ Step: step,
+ }
+ }
+
+ log.SetLevel(log.DebugLevel)
+ assertObject := assert.New(t)
+
+ // absent
+ step := createTestStep(t, "name: test")
+ continueOnError, err := isContinueOnError(context.Background(), step.getStepModel().RawContinueOnError, step, stepStageMain)
+ assertObject.False(continueOnError)
+ assertObject.Nil(err)
+
+ // explcit true
+ step = createTestStep(t, "continue-on-error: true")
+ continueOnError, err = isContinueOnError(context.Background(), step.getStepModel().RawContinueOnError, step, stepStageMain)
+ assertObject.True(continueOnError)
+ assertObject.Nil(err)
+
+ // explicit false
+ step = createTestStep(t, "continue-on-error: false")
+ continueOnError, err = isContinueOnError(context.Background(), step.getStepModel().RawContinueOnError, step, stepStageMain)
+ assertObject.False(continueOnError)
+ assertObject.Nil(err)
+
+ // expression true
+ step = createTestStep(t, "continue-on-error: ${{ 'test' == 'test' }}")
+ continueOnError, err = isContinueOnError(context.Background(), step.getStepModel().RawContinueOnError, step, stepStageMain)
+ assertObject.True(continueOnError)
+ assertObject.Nil(err)
+
+ // expression false
+ step = createTestStep(t, "continue-on-error: ${{ 'test' != 'test' }}")
+ continueOnError, err = isContinueOnError(context.Background(), step.getStepModel().RawContinueOnError, step, stepStageMain)
+ assertObject.False(continueOnError)
+ assertObject.Nil(err)
+
+ // expression parse error
+ step = createTestStep(t, "continue-on-error: ${{ 'test' != test }}")
+ continueOnError, err = isContinueOnError(context.Background(), step.getStepModel().RawContinueOnError, step, stepStageMain)
+ assertObject.False(continueOnError)
+ assertObject.NotNil(err)
+}