mirror of
https://github.com/ultravioletrs/cocos.git
synced 2026-06-23 04:10:25 +00:00
b44780df95
CI / lint (push) Has been cancelled
CI / test (agent) (push) Has been cancelled
CI / test (cli) (push) Has been cancelled
CI / test (cmd) (push) Has been cancelled
CI / test (internal) (push) Has been cancelled
CI / test (manager, true) (push) Has been cancelled
CI / test (pkg) (push) Has been cancelled
CI / upload-coverage (push) Has been cancelled
* feat: Enhance OCI image extraction to return algorithm and requirements paths, and add deferred cleanup for temporary files. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: implement deterministic zipping and enhance checksum verification for resources Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Update component build sources, add gRPC health checks to the CVM server, and refine algorithm argument handling and documentation. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * docs: Update remote resources testing guide with `sudo` for KBS, algorithm result saving, `requirements.txt`, and `algo-args` for RVPS. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * refactor: Explicitly ignore `stderr.Write` return values and add minor whitespace in tests. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * test: add comprehensive error path and edge case tests for file, zip, OCI, and agent components. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Add mutexes for thread-safe algorithm execution and expand recognized data file extensions to include common archive formats. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Add OCI extraction tests for Python algorithms and multi-layer datasets, refactor algorithm execution for testability, and enhance algorithm stop and error handling tests. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * test: Add error assertions to OCI extraction test helpers and remove an unused mock exec command. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * test: Improve error handling test coverage for algorithm execution and OCI resource extraction. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * fix: Improve algorithm process termination, enhance computation error handling, and add concurrency safety to agent service. Signed-off-by: Sammy Oina <sammyoina@gmail.com> --------- Signed-off-by: Sammy Oina <sammyoina@gmail.com>
180 lines
4.0 KiB
Go
180 lines
4.0 KiB
Go
// Copyright (c) Ultraviolet
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
package wasm
|
|
|
|
import (
|
|
"log/slog"
|
|
"os"
|
|
"os/exec"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/ultravioletrs/cocos/agent/algorithm/logging"
|
|
"github.com/ultravioletrs/cocos/agent/events/mocks"
|
|
)
|
|
|
|
const testWasm = "test.wasm"
|
|
|
|
func TestNewAlgorithm(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
eventsSvc := new(mocks.Service)
|
|
algoFile := testWasm
|
|
args := []string{"arg1", "arg2"}
|
|
|
|
algo := NewAlgorithm(logger, eventsSvc, args, algoFile, "")
|
|
|
|
w, ok := algo.(*wasm)
|
|
if !ok {
|
|
t.Fatalf("NewAlgorithm did not return a *wasm")
|
|
}
|
|
|
|
if w.algoFile != algoFile {
|
|
t.Errorf("Expected algoFile to be %s, got %s", algoFile, w.algoFile)
|
|
}
|
|
|
|
if len(w.args) != len(args) {
|
|
t.Errorf("Expected %d args, got %d", len(args), len(w.args))
|
|
}
|
|
|
|
_, ok = w.stderr.(*logging.Stderr)
|
|
if !ok {
|
|
t.Errorf("Expected stderr to be *algorithm.Stderr")
|
|
}
|
|
|
|
_, ok = w.stdout.(*logging.Stdout)
|
|
if !ok {
|
|
t.Errorf("Expected stdout to be *algorithm.Stdout")
|
|
}
|
|
}
|
|
|
|
func TestRunError(t *testing.T) {
|
|
// Mock exec.Command to return an error
|
|
execCommand = mockExecCommandError
|
|
defer func() { execCommand = exec.Command }()
|
|
|
|
algoFile := testWasm
|
|
args := []string{"arg1", "arg2"}
|
|
|
|
w := &wasm{
|
|
algoFile: algoFile,
|
|
args: args,
|
|
stderr: os.Stderr, // Use real stderr or io.Discard
|
|
stdout: os.Stdout,
|
|
}
|
|
|
|
err := w.Run()
|
|
|
|
if err == nil {
|
|
t.Errorf("Run() should have returned an error")
|
|
}
|
|
}
|
|
|
|
func mockExecCommand(command string, args ...string) *exec.Cmd {
|
|
cs := []string{"-test.run=TestHelperProcess", "--", command}
|
|
cs = append(cs, args...)
|
|
cmd := exec.Command(os.Args[0], cs...)
|
|
cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
|
|
return cmd
|
|
}
|
|
|
|
func mockExecCommandError(command string, args ...string) *exec.Cmd {
|
|
cmd := mockExecCommand(command, args...)
|
|
cmd.Env = append(cmd.Env, "GO_WANT_HELPER_PROCESS_ERROR=1")
|
|
return cmd
|
|
}
|
|
|
|
func TestStop(t *testing.T) {
|
|
t.Run("stop nil cmd", func(t *testing.T) {
|
|
w := &wasm{}
|
|
err := w.Stop()
|
|
if err != nil {
|
|
t.Errorf("Expected nil error, got %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("stop with running process", func(t *testing.T) {
|
|
oldExecCommand := execCommand
|
|
execCommand = mockExecCommand
|
|
defer func() { execCommand = oldExecCommand }()
|
|
|
|
w := &wasm{
|
|
algoFile: testWasm,
|
|
stdout: os.Stdout,
|
|
stderr: os.Stderr,
|
|
}
|
|
|
|
// We need to simulate a running process.
|
|
// mockExecCommand returns a command that runs TestHelperProcess.
|
|
// If we don't call Wait(), it keeps running? No, TestHelperProcess exits immediately.
|
|
// Let's modify TestHelperProcess to sleep if an env var is set.
|
|
|
|
w.cmd = mockExecCommand("sleep", "10")
|
|
w.cmd.Env = append(w.cmd.Env, "GO_WANT_HELPER_PROCESS_SLEEP=1")
|
|
if err := w.cmd.Start(); err != nil {
|
|
t.Fatalf("Failed to start command: %v", err)
|
|
}
|
|
|
|
err := w.Stop()
|
|
if err != nil {
|
|
t.Errorf("Expected nil error, got %v", err)
|
|
}
|
|
_ = w.cmd.Wait()
|
|
})
|
|
}
|
|
|
|
func TestStopAlreadyExited(t *testing.T) {
|
|
oldExecCommand := execCommand
|
|
execCommand = mockExecCommand
|
|
defer func() { execCommand = oldExecCommand }()
|
|
|
|
w := &wasm{
|
|
algoFile: testWasm,
|
|
stdout: os.Stdout,
|
|
stderr: os.Stderr,
|
|
}
|
|
|
|
w.cmd = mockExecCommand("true")
|
|
if err := w.cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to run command: %v", err)
|
|
}
|
|
|
|
err := w.Stop()
|
|
if err != nil {
|
|
t.Errorf("Expected nil error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestRunSuccess(t *testing.T) {
|
|
oldExecCommand := execCommand
|
|
execCommand = mockExecCommand
|
|
defer func() { execCommand = oldExecCommand }()
|
|
|
|
algoFile := testWasm
|
|
args := []string{"arg1", "arg2"}
|
|
|
|
w := &wasm{
|
|
algoFile: algoFile,
|
|
args: args,
|
|
stderr: os.Stderr,
|
|
stdout: os.Stdout,
|
|
}
|
|
|
|
err := w.Run()
|
|
if err != nil {
|
|
t.Errorf("Run() returned unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestHelperProcess(t *testing.T) {
|
|
if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
|
|
return
|
|
}
|
|
if os.Getenv("GO_WANT_HELPER_PROCESS_SLEEP") == "1" {
|
|
time.Sleep(10 * time.Second)
|
|
}
|
|
if os.Getenv("GO_WANT_HELPER_PROCESS_ERROR") == "1" {
|
|
os.Exit(1)
|
|
}
|
|
os.Exit(0)
|
|
}
|