From 129f96a1f3711896d86e652da06d4d95caa9b9b6 Mon Sep 17 00:00:00 2001 From: Alexander Pykavy Date: Mon, 4 Aug 2025 17:58:01 +0200 Subject: [PATCH 1/2] Fix deleting a running task --- tests/helper/task.go | 20 ++++++++++++---- tests/worker/stop_task_test.go | 43 ++++++++++++++++++++++++++++++++++ tests/worker/task_logs_test.go | 2 +- worker/worker.go | 3 +-- 4 files changed, 61 insertions(+), 7 deletions(-) diff --git a/tests/helper/task.go b/tests/helper/task.go index 2f1420c..c54edc5 100644 --- a/tests/helper/task.go +++ b/tests/helper/task.go @@ -16,18 +16,30 @@ import ( ) var ( - HostsFilePath string - NoFileErrorMessage string + HostsFilePath string + NoFileErrMessage string + SignalKilledErrMessage string ) func init() { switch runtime.GOOS { case "windows": HostsFilePath = "$env:windir/System32/drivers/etc/hosts" - NoFileErrorMessage = "Cannot find path (\\r\\n)*'.+%s' because (\\r\\n)*it (\\r\\n)*does (\\r\\n)*not (\\r\\n)*exist." + NoFileErrMessage = "Cannot find path (\\r\\n)*'.+%s' because (\\r\\n)*it (\\r\\n)*does (\\r\\n)*not (\\r\\n)*exist." + SignalKilledErrMessage = "exit status 1" case "linux": HostsFilePath = "/etc/hosts" - NoFileErrorMessage = "%s: No such file or directory" + NoFileErrMessage = "%s: No such file or directory" + SignalKilledErrMessage = "signal: killed" + } +} + +func PingTask(name, host string) task.Task { + return task.Task{ + ID: uuid.New(), + Name: name, + Executable: "ping", + Args: []string{host, "-n", "20"}, } } diff --git a/tests/worker/stop_task_test.go b/tests/worker/stop_task_test.go index d95afe6..7d55c2f 100644 --- a/tests/worker/stop_task_test.go +++ b/tests/worker/stop_task_test.go @@ -7,7 +7,9 @@ import ( "fmt" "net/http" "net/http/httptest" + "sync" "testing" + "time" "github.com/google/uuid" "github.com/stretchr/testify/assert" @@ -53,3 +55,44 @@ func TestStopTask__ShouldStopCompletedTask(t *testing.T) { assert.Empty(t, responseRecorder.Body, "Response body should be empty") assert.Empty(t, api.Worker.Tasks, "Tasks map should be empty") } + +func TestStopTask__ShouldStopRunningTask(t *testing.T) { + api := &worker.Api{ + Worker: &worker.Worker{ + Tasks: make(map[uuid.UUID]*task.Task), + }, + } + testTask := helper.PingTask("ping-task", "127.0.0.1") + + // 1 - Create a task + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + + createRequest := helper.NewTaskPostRequest(testTask) + createResponseRecorder := httptest.NewRecorder() + + api.HandleCreateTask(createResponseRecorder, createRequest) + + assert.Equal(t, http.StatusInternalServerError, createResponseRecorder.Code, "Response status code should be 500 Internal Server Error") + assert.Equal(t, fmt.Sprintf("Error when executing the task: %s", helper.SignalKilledErrMessage), createResponseRecorder.Body.String(), "Response body should contain error message") + assert.Empty(t, api.Worker.Tasks, "Tasks map should be empty") + }() + + time.Sleep(1 * time.Second) + + assert.Equal(t, 1, len(api.Worker.Tasks), "Tasks map should contain 1 task") + + // 2 - Delete a task + deleteRequest := helper.NewTaskDeleteRequest(testTask.ID) + deleteResponseRecorder := httptest.NewRecorder() + + api.HandleDeleteTask(deleteResponseRecorder, deleteRequest) + + assert.Equal(t, http.StatusNoContent, deleteResponseRecorder.Code, "Response status code should be 204 No Content") + assert.Empty(t, deleteResponseRecorder.Body, "Response body should be empty") + assert.Empty(t, api.Worker.Tasks, "Tasks map should be empty") + + wg.Wait() +} diff --git a/tests/worker/task_logs_test.go b/tests/worker/task_logs_test.go index 37f6e73..a180e7d 100644 --- a/tests/worker/task_logs_test.go +++ b/tests/worker/task_logs_test.go @@ -33,7 +33,7 @@ func TestTaskLogs__PrintFile(t *testing.T) { path: "non-existing-file.txt", responseStatus: http.StatusInternalServerError, responseBody: "Error when executing the task: exit status 1", - stdoutRegexp: fmt.Sprintf(helper.NoFileErrorMessage, "non-existing-file.txt"), + stdoutRegexp: fmt.Sprintf(helper.NoFileErrMessage, "non-existing-file.txt"), }, } diff --git a/worker/worker.go b/worker/worker.go index b37139a..7a71194 100644 --- a/worker/worker.go +++ b/worker/worker.go @@ -24,6 +24,7 @@ func (w *Worker) GetTask(id uuid.UUID) *task.Task { func (w *Worker) StartTask(t task.Task) error { t.Cmd = exec.Command(t.Executable, t.Args...) + w.Tasks[t.ID] = &t stdout, err := t.Cmd.CombinedOutput() os.Stdout.Write(stdout) @@ -31,8 +32,6 @@ func (w *Worker) StartTask(t task.Task) error { return err } - w.Tasks[t.ID] = &t - return nil } From bc4e919e6b6c92cd44b608b2db91986a33a21cb7 Mon Sep 17 00:00:00 2001 From: Alexander Pykavy Date: Tue, 5 Aug 2025 07:43:50 +0200 Subject: [PATCH 2/2] Run tests on both Windows & Linux --- .github/workflows/worker-tests.yaml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/worker-tests.yaml b/.github/workflows/worker-tests.yaml index 9439adf..269bbac 100644 --- a/.github/workflows/worker-tests.yaml +++ b/.github/workflows/worker-tests.yaml @@ -8,7 +8,16 @@ on: jobs: worker_tests: - runs-on: ubuntu-latest + strategy: + matrix: + os: [Linux, Windows] + include: + - os: Linux + pool: ubuntu-latest + - os: Windows + pool: windows-latest + name: Run tests on ${{ matrix.os }} + runs-on: ${{ matrix.pool }} steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 @@ -17,6 +26,7 @@ jobs: go-version: "1.23.6" - name: Build worker Docker image + if: ${{ matrix.os != 'Windows' }} run: | docker compose build