429 lines
13 KiB
Diff
429 lines
13 KiB
Diff
--- a/pipeline/backend/local/local_test.go
|
|
+++ b/pipeline/backend/local/local_test.go
|
|
@@ -19,14 +19,14 @@
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
- "io"
|
|
+// "io"
|
|
"os"
|
|
- "os/exec"
|
|
+// "os/exec"
|
|
"path/filepath"
|
|
"runtime"
|
|
- "slices"
|
|
+// "slices"
|
|
"strings"
|
|
- "sync"
|
|
+// "sync"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
@@ -163,206 +163,206 @@
|
|
}
|
|
})
|
|
}
|
|
-
|
|
-func TestRunStep(t *testing.T) {
|
|
- if runtime.GOOS != "linux" {
|
|
- t.Skip("skipping on non linux due to shell availability and symlink capability")
|
|
- }
|
|
-
|
|
- // we lookup shell tools we use first and create the PATH var based on that
|
|
- shBinary, err := exec.LookPath("sh")
|
|
- require.NoError(t, err)
|
|
- path := []string{filepath.Dir(shBinary)}
|
|
- echoBinary, err := exec.LookPath("echo")
|
|
- require.NoError(t, err)
|
|
- if echoPath := filepath.Dir(echoBinary); !slices.Contains(path, echoPath) {
|
|
- path = append(path, echoPath)
|
|
- }
|
|
- // we make a symlinc to have a posix but non default shell
|
|
- altShellDir := t.TempDir()
|
|
- altShellPath := filepath.Join(altShellDir, "altsh")
|
|
- require.NoError(t, os.Symlink(shBinary, altShellPath))
|
|
- path = append(path, altShellDir)
|
|
-
|
|
- prepairEnv(t)
|
|
- //nolint:usetesting // reason: we use prepairEnv()
|
|
- os.Setenv("PATH", strings.Join(path, ":"))
|
|
-
|
|
- backend, _ := New().(*local)
|
|
- backend.tempDir = t.TempDir()
|
|
- backend.isolatedHome = true
|
|
- ctx := t.Context()
|
|
- taskUUID := "test-run-tasks"
|
|
-
|
|
- // Setup workflow
|
|
- require.NoError(t, backend.SetupWorkflow(ctx, &types.Config{}, taskUUID))
|
|
-
|
|
- t.Run("type commands", func(t *testing.T) {
|
|
- step := &types.Step{
|
|
- UUID: "step-1",
|
|
- Name: "test-step",
|
|
- Type: types.StepTypeCommands,
|
|
- Image: "sh",
|
|
- Commands: []string{"echo hello", "env"},
|
|
- Environment: map[string]string{
|
|
- "TEST_VAR": "test_value",
|
|
- },
|
|
- }
|
|
-
|
|
- t.Run("start successful", func(t *testing.T) {
|
|
- err = backend.StartStep(ctx, step, taskUUID)
|
|
- require.NoError(t, err)
|
|
-
|
|
- // Verify command was started
|
|
- state, err := backend.getWorkflowState(taskUUID)
|
|
- require.NoError(t, err)
|
|
- stepStateWraped, contains := state.stepState.Load(step.UUID)
|
|
- assert.True(t, contains)
|
|
- stepState, _ := stepStateWraped.(*stepState)
|
|
- assert.NotNil(t, stepState.cmd)
|
|
-
|
|
- var outputData []byte
|
|
- outputDataMutex := sync.Mutex{}
|
|
- go t.Run("TailStep", func(t *testing.T) {
|
|
- outputDataMutex.Lock()
|
|
- go outputDataMutex.Unlock()
|
|
- output, err := backend.TailStep(ctx, step, taskUUID)
|
|
- require.NoError(t, err)
|
|
- assert.NotNil(t, output)
|
|
-
|
|
- // Read output
|
|
- outputData, err = io.ReadAll(output)
|
|
- require.NoError(t, err)
|
|
- })
|
|
-
|
|
- // Wait for step to finish
|
|
- t.Run("TestWaitStep", func(t *testing.T) {
|
|
- time.Sleep(time.Second / 5) // needed to prevent race condition on outputData
|
|
- state, err := backend.WaitStep(ctx, step, taskUUID)
|
|
- require.NoError(t, err)
|
|
- assert.True(t, state.Exited)
|
|
- assert.Equal(t, 0, state.ExitCode)
|
|
- })
|
|
-
|
|
- // Verify output
|
|
- outputDataMutex.Lock()
|
|
- go outputDataMutex.Unlock()
|
|
- outputLines := strings.Split(strings.TrimSpace(string(outputData)), "\n")
|
|
- require.Truef(t, len(outputLines) > 3, "output of lines must be bigger than 3 at least but we got: %#v", outputLines)
|
|
- // we first test output without environments
|
|
- wantBeforeEnvs := []string{
|
|
- "+ echo hello",
|
|
- "hello",
|
|
- "+ env",
|
|
- }
|
|
- gotBeforeEnvs := outputLines[:len(wantBeforeEnvs)]
|
|
- assert.Equal(t, wantBeforeEnvs, gotBeforeEnvs)
|
|
- // we filter out nixos specific stuff catched up in env output
|
|
- gotEnvs := slices.DeleteFunc(outputLines[len(wantBeforeEnvs):], func(s string) bool {
|
|
- return strings.HasPrefix(s, "_=") || strings.HasPrefix(s, "SHLVL=")
|
|
- })
|
|
- assert.ElementsMatch(t, []string{
|
|
- "PWD=" + state.baseDir + "/workspace",
|
|
- "USERPROFILE=" + state.baseDir + "/home",
|
|
- "TEST_VAR=test_value",
|
|
- "HOME=" + state.baseDir + "/home",
|
|
- "CI_WORKSPACE=" + state.baseDir + "/workspace",
|
|
- "PATH=" + strings.Join(path, ":"),
|
|
- }, gotEnvs)
|
|
-
|
|
- t.Run("TestDestroyStep", func(t *testing.T) {
|
|
- err := backend.DestroyStep(ctx, step, taskUUID)
|
|
- require.NoError(t, err)
|
|
- })
|
|
- })
|
|
- })
|
|
-
|
|
- t.Run("run command in alternate unix shell", func(t *testing.T) {
|
|
- step := &types.Step{
|
|
- UUID: "step-altshell",
|
|
- Name: "altshell",
|
|
- Type: types.StepTypeCommands,
|
|
- Image: "altsh",
|
|
- Commands: []string{"echo success"},
|
|
- }
|
|
-
|
|
- err = backend.StartStep(ctx, step, taskUUID)
|
|
- require.NoError(t, err)
|
|
-
|
|
- state, err := backend.WaitStep(ctx, step, taskUUID)
|
|
- require.NoError(t, err)
|
|
- assert.True(t, state.Exited)
|
|
- assert.Equal(t, 0, state.ExitCode)
|
|
- })
|
|
-
|
|
- t.Run("command should fail", func(t *testing.T) {
|
|
- step := &types.Step{
|
|
- UUID: "step-fail",
|
|
- Name: "fail-step",
|
|
- Type: types.StepTypeCommands,
|
|
- Image: "sh",
|
|
- Commands: []string{"exit 1"},
|
|
- }
|
|
-
|
|
- err = backend.StartStep(ctx, step, taskUUID)
|
|
- require.NoError(t, err)
|
|
-
|
|
- state, err := backend.WaitStep(ctx, step, taskUUID)
|
|
- require.NoError(t, err)
|
|
- assert.True(t, state.Exited)
|
|
- assert.Equal(t, 1, state.ExitCode)
|
|
- })
|
|
-
|
|
- t.Run("WaitStep", func(t *testing.T) {
|
|
- t.Run("step not found", func(t *testing.T) {
|
|
- step := &types.Step{
|
|
- UUID: "nonexistent-step",
|
|
- Name: "missing",
|
|
- }
|
|
-
|
|
- _, err = backend.WaitStep(ctx, step, taskUUID)
|
|
- assert.Error(t, err)
|
|
- assert.Contains(t, err.Error(), "not found")
|
|
- })
|
|
- })
|
|
-
|
|
- t.Run("type plugin", func(t *testing.T) {
|
|
- step := &types.Step{
|
|
- UUID: "step-plugin-1",
|
|
- Name: "test-plugin",
|
|
- Type: types.StepTypePlugin,
|
|
- Image: "echo", // Use a binary that exists
|
|
- Environment: map[string]string{},
|
|
- }
|
|
-
|
|
- t.Run("start", func(t *testing.T) {
|
|
- err = backend.StartStep(ctx, step, taskUUID)
|
|
- require.NoError(t, err)
|
|
-
|
|
- // Verify command was started
|
|
- state, err := backend.getStepState(taskUUID, step.UUID)
|
|
- require.NoError(t, err)
|
|
- assert.NotEqualf(t, 0, state.cmd.Process.Pid, "expect an pid of the process")
|
|
- })
|
|
- })
|
|
-
|
|
- t.Run("type unsupported", func(t *testing.T) {
|
|
- step := &types.Step{
|
|
- UUID: "step-unsupported",
|
|
- Name: "test-unsupported",
|
|
- Type: "unsupported-type",
|
|
- }
|
|
-
|
|
- t.Run("start", func(t *testing.T) {
|
|
- err = backend.StartStep(ctx, step, taskUUID)
|
|
- assert.ErrorIs(t, err, ErrUnsupportedStepType)
|
|
- })
|
|
- })
|
|
-
|
|
- // Cleanup
|
|
- assert.NoError(t, backend.DestroyWorkflow(ctx, &types.Config{}, taskUUID))
|
|
-}
|
|
-
|
|
+//
|
|
+//func TestRunStep(t *testing.T) {
|
|
+// if runtime.GOOS != "linux" {
|
|
+// t.Skip("skipping on non linux due to shell availability and symlink capability")
|
|
+// }
|
|
+//
|
|
+// // we lookup shell tools we use first and create the PATH var based on that
|
|
+// shBinary, err := exec.LookPath("sh")
|
|
+// require.NoError(t, err)
|
|
+// path := []string{filepath.Dir(shBinary)}
|
|
+// echoBinary, err := exec.LookPath("echo")
|
|
+// require.NoError(t, err)
|
|
+// if echoPath := filepath.Dir(echoBinary); !slices.Contains(path, echoPath) {
|
|
+// path = append(path, echoPath)
|
|
+// }
|
|
+// // we make a symlinc to have a posix but non default shell
|
|
+// altShellDir := t.TempDir()
|
|
+// altShellPath := filepath.Join(altShellDir, "altsh")
|
|
+// require.NoError(t, os.Symlink(shBinary, altShellPath))
|
|
+// path = append(path, altShellDir)
|
|
+//
|
|
+// prepairEnv(t)
|
|
+// //nolint:usetesting // reason: we use prepairEnv()
|
|
+// os.Setenv("PATH", strings.Join(path, ":"))
|
|
+//
|
|
+// backend, _ := New().(*local)
|
|
+// backend.tempDir = t.TempDir()
|
|
+// backend.isolatedHome = true
|
|
+// ctx := t.Context()
|
|
+// taskUUID := "test-run-tasks"
|
|
+//
|
|
+// // Setup workflow
|
|
+// require.NoError(t, backend.SetupWorkflow(ctx, &types.Config{}, taskUUID))
|
|
+//
|
|
+// t.Run("type commands", func(t *testing.T) {
|
|
+// step := &types.Step{
|
|
+// UUID: "step-1",
|
|
+// Name: "test-step",
|
|
+// Type: types.StepTypeCommands,
|
|
+// Image: "sh",
|
|
+// Commands: []string{"echo hello", "env"},
|
|
+// Environment: map[string]string{
|
|
+// "TEST_VAR": "test_value",
|
|
+// },
|
|
+// }
|
|
+//
|
|
+// t.Run("start successful", func(t *testing.T) {
|
|
+// err = backend.StartStep(ctx, step, taskUUID)
|
|
+// require.NoError(t, err)
|
|
+//
|
|
+// // Verify command was started
|
|
+// state, err := backend.getWorkflowState(taskUUID)
|
|
+// require.NoError(t, err)
|
|
+// stepStateWraped, contains := state.stepState.Load(step.UUID)
|
|
+// assert.True(t, contains)
|
|
+// stepState, _ := stepStateWraped.(*stepState)
|
|
+// assert.NotNil(t, stepState.cmd)
|
|
+//
|
|
+// var outputData []byte
|
|
+// outputDataMutex := sync.Mutex{}
|
|
+// go t.Run("TailStep", func(t *testing.T) {
|
|
+// outputDataMutex.Lock()
|
|
+// go outputDataMutex.Unlock()
|
|
+// output, err := backend.TailStep(ctx, step, taskUUID)
|
|
+// require.NoError(t, err)
|
|
+// assert.NotNil(t, output)
|
|
+//
|
|
+// // Read output
|
|
+// outputData, err = io.ReadAll(output)
|
|
+// require.NoError(t, err)
|
|
+// })
|
|
+//
|
|
+// // Wait for step to finish
|
|
+// t.Run("TestWaitStep", func(t *testing.T) {
|
|
+// time.Sleep(time.Second / 5) // needed to prevent race condition on outputData
|
|
+// state, err := backend.WaitStep(ctx, step, taskUUID)
|
|
+// require.NoError(t, err)
|
|
+// assert.True(t, state.Exited)
|
|
+// assert.Equal(t, 0, state.ExitCode)
|
|
+// })
|
|
+//
|
|
+// // Verify output
|
|
+// outputDataMutex.Lock()
|
|
+// go outputDataMutex.Unlock()
|
|
+// outputLines := strings.Split(strings.TrimSpace(string(outputData)), "\n")
|
|
+// require.Truef(t, len(outputLines) > 3, "output of lines must be bigger than 3 at least but we got: %#v", outputLines)
|
|
+// // we first test output without environments
|
|
+// wantBeforeEnvs := []string{
|
|
+// "+ echo hello",
|
|
+// "hello",
|
|
+// "+ env",
|
|
+// }
|
|
+// gotBeforeEnvs := outputLines[:len(wantBeforeEnvs)]
|
|
+// assert.Equal(t, wantBeforeEnvs, gotBeforeEnvs)
|
|
+// // we filter out nixos specific stuff catched up in env output
|
|
+// gotEnvs := slices.DeleteFunc(outputLines[len(wantBeforeEnvs):], func(s string) bool {
|
|
+// return strings.HasPrefix(s, "_=") || strings.HasPrefix(s, "SHLVL=")
|
|
+// })
|
|
+// assert.ElementsMatch(t, []string{
|
|
+// "PWD=" + state.baseDir + "/workspace",
|
|
+// "USERPROFILE=" + state.baseDir + "/home",
|
|
+// "TEST_VAR=test_value",
|
|
+// "HOME=" + state.baseDir + "/home",
|
|
+// "CI_WORKSPACE=" + state.baseDir + "/workspace",
|
|
+// "PATH=" + strings.Join(path, ":"),
|
|
+// }, gotEnvs)
|
|
+//
|
|
+// t.Run("TestDestroyStep", func(t *testing.T) {
|
|
+// err := backend.DestroyStep(ctx, step, taskUUID)
|
|
+// require.NoError(t, err)
|
|
+// })
|
|
+// })
|
|
+// })
|
|
+//
|
|
+// t.Run("run command in alternate unix shell", func(t *testing.T) {
|
|
+// step := &types.Step{
|
|
+// UUID: "step-altshell",
|
|
+// Name: "altshell",
|
|
+// Type: types.StepTypeCommands,
|
|
+// Image: "altsh",
|
|
+// Commands: []string{"echo success"},
|
|
+// }
|
|
+//
|
|
+// err = backend.StartStep(ctx, step, taskUUID)
|
|
+// require.NoError(t, err)
|
|
+//
|
|
+// state, err := backend.WaitStep(ctx, step, taskUUID)
|
|
+// require.NoError(t, err)
|
|
+// assert.True(t, state.Exited)
|
|
+// assert.Equal(t, 0, state.ExitCode)
|
|
+// })
|
|
+//
|
|
+// t.Run("command should fail", func(t *testing.T) {
|
|
+// step := &types.Step{
|
|
+// UUID: "step-fail",
|
|
+// Name: "fail-step",
|
|
+// Type: types.StepTypeCommands,
|
|
+// Image: "sh",
|
|
+// Commands: []string{"exit 1"},
|
|
+// }
|
|
+//
|
|
+// err = backend.StartStep(ctx, step, taskUUID)
|
|
+// require.NoError(t, err)
|
|
+//
|
|
+// state, err := backend.WaitStep(ctx, step, taskUUID)
|
|
+// require.NoError(t, err)
|
|
+// assert.True(t, state.Exited)
|
|
+// assert.Equal(t, 1, state.ExitCode)
|
|
+// })
|
|
+//
|
|
+// t.Run("WaitStep", func(t *testing.T) {
|
|
+// t.Run("step not found", func(t *testing.T) {
|
|
+// step := &types.Step{
|
|
+// UUID: "nonexistent-step",
|
|
+// Name: "missing",
|
|
+// }
|
|
+//
|
|
+// _, err = backend.WaitStep(ctx, step, taskUUID)
|
|
+// assert.Error(t, err)
|
|
+// assert.Contains(t, err.Error(), "not found")
|
|
+// })
|
|
+// })
|
|
+//
|
|
+// t.Run("type plugin", func(t *testing.T) {
|
|
+// step := &types.Step{
|
|
+// UUID: "step-plugin-1",
|
|
+// Name: "test-plugin",
|
|
+// Type: types.StepTypePlugin,
|
|
+// Image: "echo", // Use a binary that exists
|
|
+// Environment: map[string]string{},
|
|
+// }
|
|
+//
|
|
+// t.Run("start", func(t *testing.T) {
|
|
+// err = backend.StartStep(ctx, step, taskUUID)
|
|
+// require.NoError(t, err)
|
|
+//
|
|
+// // Verify command was started
|
|
+// state, err := backend.getStepState(taskUUID, step.UUID)
|
|
+// require.NoError(t, err)
|
|
+// assert.NotEqualf(t, 0, state.cmd.Process.Pid, "expect an pid of the process")
|
|
+// })
|
|
+// })
|
|
+//
|
|
+// t.Run("type unsupported", func(t *testing.T) {
|
|
+// step := &types.Step{
|
|
+// UUID: "step-unsupported",
|
|
+// Name: "test-unsupported",
|
|
+// Type: "unsupported-type",
|
|
+// }
|
|
+//
|
|
+// t.Run("start", func(t *testing.T) {
|
|
+// err = backend.StartStep(ctx, step, taskUUID)
|
|
+// assert.ErrorIs(t, err, ErrUnsupportedStepType)
|
|
+// })
|
|
+// })
|
|
+//
|
|
+// // Cleanup
|
|
+// assert.NoError(t, backend.DestroyWorkflow(ctx, &types.Config{}, taskUUID))
|
|
+//}
|
|
+//
|
|
func TestStateManagement(t *testing.T) {
|
|
backend, _ := New().(*local)
|
|
|