mirror of
https://github.com/ultravioletrs/cocos.git
synced 2026-06-23 04:10:25 +00:00
c1cbcec851
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: Introduce Go-based CoRIM generation and deprecate Rust attestation policy scripts. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Update dependencies and refactor attestation policy handling Signed-off-by: Sammy Oina <sammyoina@gmail.com> * refactor: Migrate attestation verification to use CoRIM and remove deprecated policy handling and EAT verification tests. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * Removed the `tdx` and `sev-snp` attestation policy scripts and their build configurations, along with related build and installation steps from the main Makefile. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * chore: Remove Rust CI workflow and Cargo Dependabot configuration, and enhance Go test setup for attestation policy paths. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * refactor: Use WriteString instead of Write([]byte) for writing policy file content in test. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Refactor `ca-bundle` command to fetch bundles by product string using a configurable HTTP getter with improved error handling, and simplify `attestation_policy` command usage. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * fix: ignore return value of cmd.Help() Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Implement CoRIM generation for Azure and GCP attestation policies and add a CLI command to download and verify GCP OVMF files. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Upgrade Python virtual environment setup to include setuptools and wheel, append computation ID to Docker container names, and improve test robustness with error assertions and conditional skips for runtime tests. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * test: Enhance attestation verification tests, including CoRIM integration and specific platform types like Azure SNP, vTPM, TDX, and IGVM. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Add comprehensive test cases for `VerifyWithCoRIM` including success and measurement mismatch, and refine reference value validation. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Add Azure and TDX attestation verification tests and abstract external service dependencies for improved testability. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Add new test cases for Azure measurement extraction, EAT platform types, IGVM measurement stopping, vTPM CoRIM verification, and GCP OVMF download CLI. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * test: enhance CLI CoRIM generation and ATLS certificate verification tests, and refactor the Azure MAA client to use an interface. Signed-off-by: Sammy Oina <sammyoina@gmail.com> --------- Signed-off-by: Sammy Oina <sammyoina@gmail.com>
284 lines
7.7 KiB
Go
284 lines
7.7 KiB
Go
// Copyright (c) Ultraviolet
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
package service
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"log/slog"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
pb "github.com/ultravioletrs/cocos/agent/runner"
|
|
)
|
|
|
|
// MockEventService is a mock implementation of events.Service.
|
|
type MockEventService struct {
|
|
events []interface{}
|
|
}
|
|
|
|
func (m *MockEventService) SendEvent(cmpID, event, status string, details json.RawMessage) {
|
|
m.events = append(m.events, map[string]interface{}{
|
|
"cmpID": cmpID,
|
|
"event": event,
|
|
"status": status,
|
|
"details": details,
|
|
})
|
|
}
|
|
|
|
// TestNewRunnerService tests the creation of a new runner service.
|
|
func TestNewRunnerService(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
eventSvc := &MockEventService{}
|
|
|
|
rs := New(logger, eventSvc)
|
|
require.NotNil(t, rs)
|
|
assert.NotNil(t, rs.logger)
|
|
assert.NotNil(t, rs.eventSvc)
|
|
assert.Nil(t, rs.currentAlgo)
|
|
}
|
|
|
|
// TestRunWithBinaryAlgorithm tests running a binary algorithm.
|
|
func TestRunWithBinaryAlgorithm(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
eventSvc := &MockEventService{}
|
|
rs := New(logger, eventSvc)
|
|
|
|
req := &pb.RunRequest{
|
|
ComputationId: "test-1",
|
|
AlgoType: "bin",
|
|
Algorithm: []byte("#!/bin/bash\necho 'test'"),
|
|
Args: []string{"arg1", "arg2"},
|
|
}
|
|
|
|
resp, err := rs.Run(context.Background(), req)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
assert.Empty(t, resp.Error)
|
|
assert.Equal(t, "test-1", resp.ComputationId)
|
|
}
|
|
|
|
// TestRunWithPythonAlgorithm tests running a Python algorithm.
|
|
func TestRunWithPythonAlgorithm(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
eventSvc := &MockEventService{}
|
|
rs := New(logger, eventSvc)
|
|
|
|
req := &pb.RunRequest{
|
|
ComputationId: "test-python",
|
|
AlgoType: "python",
|
|
Algorithm: []byte("print('hello')"),
|
|
Args: []string{},
|
|
Requirements: []byte("numpy==2.2.0"),
|
|
}
|
|
|
|
resp, err := rs.Run(context.Background(), req)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
assert.Empty(t, resp.Error)
|
|
assert.Equal(t, "test-python", resp.ComputationId)
|
|
}
|
|
|
|
// TestRunWithPythonAlgorithmNoRequirements tests running Python without requirements.
|
|
func TestRunWithPythonAlgorithmNoRequirements(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
eventSvc := &MockEventService{}
|
|
rs := New(logger, eventSvc)
|
|
|
|
req := &pb.RunRequest{
|
|
ComputationId: "test-python-noreq",
|
|
AlgoType: "python",
|
|
Algorithm: []byte("print('hello')"),
|
|
Args: []string{},
|
|
}
|
|
|
|
resp, err := rs.Run(context.Background(), req)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
assert.Empty(t, resp.Error)
|
|
assert.Equal(t, "test-python-noreq", resp.ComputationId)
|
|
}
|
|
|
|
// TestRunWithWasmAlgorithm tests running a WASM algorithm.
|
|
func TestRunWithWasmAlgorithm(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
eventSvc := &MockEventService{}
|
|
rs := New(logger, eventSvc)
|
|
|
|
req := &pb.RunRequest{
|
|
ComputationId: "test-wasm",
|
|
AlgoType: "wasm",
|
|
Algorithm: []byte{0x00, 0x61, 0x73, 0x6d},
|
|
Args: []string{},
|
|
}
|
|
|
|
resp, err := rs.Run(context.Background(), req)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
if resp.Error != "" {
|
|
assert.Contains(t, resp.Error, "wasmedge")
|
|
t.Skip("wasmedge not found, skipping test")
|
|
}
|
|
assert.Equal(t, "test-wasm", resp.ComputationId)
|
|
}
|
|
|
|
// TestRunWithDockerAlgorithm tests running a Docker algorithm.
|
|
func TestRunWithDockerAlgorithm(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
eventSvc := &MockEventService{}
|
|
rs := New(logger, eventSvc)
|
|
|
|
req := &pb.RunRequest{
|
|
ComputationId: "test-docker",
|
|
AlgoType: "docker",
|
|
Algorithm: []byte("FROM ubuntu:latest\nRUN echo 'test'"),
|
|
Args: []string{},
|
|
}
|
|
|
|
resp, err := rs.Run(context.Background(), req)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
if resp.Error != "" {
|
|
assert.Contains(t, resp.Error, "Docker")
|
|
t.Skip("Docker issue, skipping test")
|
|
}
|
|
assert.Equal(t, "test-docker", resp.ComputationId)
|
|
}
|
|
|
|
// TestRunWithUnsupportedAlgorithmType tests running with unsupported algorithm type.
|
|
func TestRunWithUnsupportedAlgorithmType(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
eventSvc := &MockEventService{}
|
|
rs := New(logger, eventSvc)
|
|
|
|
req := &pb.RunRequest{
|
|
ComputationId: "test-unsupported",
|
|
AlgoType: "unsupported",
|
|
Algorithm: []byte("test"),
|
|
Args: []string{},
|
|
}
|
|
|
|
resp, err := rs.Run(context.Background(), req)
|
|
require.Error(t, err)
|
|
require.Nil(t, resp)
|
|
}
|
|
|
|
// TestRunAlreadyRunning tests running computation when one is already running.
|
|
func TestRunAlreadyRunning(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
eventSvc := &MockEventService{}
|
|
rs := New(logger, eventSvc)
|
|
|
|
// Use a long-running bash script
|
|
req := &pb.RunRequest{
|
|
ComputationId: "test-running",
|
|
AlgoType: "bin",
|
|
Algorithm: []byte("#!/bin/bash\nsleep 30"),
|
|
Args: []string{},
|
|
}
|
|
|
|
// Start first computation (will run for 30 seconds)
|
|
go func() {
|
|
_, _ = rs.Run(context.Background(), req)
|
|
}()
|
|
|
|
// Give it time to start
|
|
time.Sleep(500 * time.Millisecond)
|
|
|
|
// Try to run another immediately - should fail
|
|
resp, err := rs.Run(context.Background(), req)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
assert.Equal(t, "computation already running", resp.Error)
|
|
}
|
|
|
|
// TestStopWhenRunning tests stopping a running computation.
|
|
func TestStopWhenRunning(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
eventSvc := &MockEventService{}
|
|
rs := New(logger, eventSvc)
|
|
|
|
req := &pb.RunRequest{
|
|
ComputationId: "test-stop",
|
|
AlgoType: "bin",
|
|
Algorithm: []byte("#!/bin/bash\nsleep 10"),
|
|
Args: []string{},
|
|
}
|
|
|
|
_, err := rs.Run(context.Background(), req)
|
|
require.NoError(t, err)
|
|
|
|
stopReq := &pb.StopRequest{
|
|
ComputationId: "test-stop",
|
|
}
|
|
|
|
stopResp, err := rs.Stop(context.Background(), stopReq)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, stopResp)
|
|
}
|
|
|
|
// TestStopWhenNotRunning tests stopping when no computation is running.
|
|
func TestStopWhenNotRunning(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
eventSvc := &MockEventService{}
|
|
rs := New(logger, eventSvc)
|
|
|
|
stopReq := &pb.StopRequest{
|
|
ComputationId: "test-not-running",
|
|
}
|
|
|
|
stopResp, err := rs.Stop(context.Background(), stopReq)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, stopResp)
|
|
}
|
|
|
|
// TestConcurrentRun tests that concurrent runs are properly serialized.
|
|
func TestConcurrentRun(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
eventSvc := &MockEventService{}
|
|
rs := New(logger, eventSvc)
|
|
|
|
req := &pb.RunRequest{
|
|
ComputationId: "test-concurrent",
|
|
AlgoType: "bin",
|
|
Algorithm: []byte("#!/bin/bash\nsleep 15"),
|
|
Args: []string{},
|
|
}
|
|
|
|
// Start first run in goroutine (will run for 15 seconds)
|
|
go func() {
|
|
_, _ = rs.Run(context.Background(), req)
|
|
}()
|
|
|
|
// Give it time to actually start
|
|
time.Sleep(500 * time.Millisecond)
|
|
|
|
// Concurrent attempt should fail
|
|
resp2, err := rs.Run(context.Background(), req)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "computation already running", resp2.Error)
|
|
}
|
|
|
|
// TestRunWithMultipleArgs tests running with multiple arguments.
|
|
func TestRunWithMultipleArgs(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
eventSvc := &MockEventService{}
|
|
rs := New(logger, eventSvc)
|
|
|
|
req := &pb.RunRequest{
|
|
ComputationId: "test-multi-args",
|
|
AlgoType: "bin",
|
|
Algorithm: []byte("#!/bin/bash\necho $@"),
|
|
Args: []string{"arg1", "arg2", "arg3", "arg4"},
|
|
}
|
|
|
|
resp, err := rs.Run(context.Background(), req)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, resp)
|
|
assert.Empty(t, resp.Error)
|
|
assert.Equal(t, "test-multi-args", resp.ComputationId)
|
|
}
|