fetch_ml/tests/e2e/podman_integration_test.go
Jeremie Fraeys c980167041 test: implement comprehensive test suite with multiple test types
- Add end-to-end tests for complete workflow validation
- Include integration tests for API and database interactions
- Add unit tests for all major components and utilities
- Include performance tests for payload handling
- Add CLI API integration tests
- Include Podman container integration tests
- Add WebSocket and queue execution tests
- Include shell script tests for setup validation

Provides comprehensive test coverage ensuring platform reliability
and functionality across all components and interactions.
2025-12-04 16:55:13 -05:00

168 lines
5.1 KiB
Go

package tests
import (
"context"
"os"
"os/exec"
"path/filepath"
"testing"
"time"
tests "github.com/jfraeys/fetch_ml/tests/fixtures"
)
// TestPodmanIntegration tests podman workflow with examples
func TestPodmanIntegration(t *testing.T) {
if testing.Short() {
t.Skip("Skipping podman integration test in short mode")
}
// Check if podman is available
if _, err := exec.LookPath("podman"); err != nil {
t.Skip("Podman not available, skipping integration test")
}
// Check if podman daemon is running
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
podmanCheck := exec.CommandContext(ctx, "podman", "info")
if err := podmanCheck.Run(); err != nil {
t.Skip("Podman daemon not running, skipping integration test")
}
// Determine project root (two levels up from tests/e2e)
projectRoot, err := filepath.Abs(filepath.Join("..", ".."))
if err != nil {
t.Fatalf("Failed to resolve project root: %v", err)
}
// Test build
t.Run("BuildContainer", func(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
cmd := exec.CommandContext(ctx, "podman", "build",
"-f", filepath.Join("podman", "secure-ml-runner.podfile"),
"-t", "secure-ml-runner:test",
"podman")
cmd.Dir = projectRoot
t.Logf("Building container with command: %v", cmd)
t.Logf("Current directory: %s", cmd.Dir)
output, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("Failed to build container: %v\nOutput: %s", err, string(output))
}
t.Logf("Container build successful")
})
// Test execution with examples
t.Run("ExecuteExample", func(t *testing.T) {
// Use fixtures for examples directory operations
examplesDir := tests.NewExamplesDir(filepath.Join("..", "fixtures", "examples"))
project := "standard_ml_project"
// Create temporary workspace
tempDir := t.TempDir()
workspaceDir := filepath.Join(tempDir, "workspace")
resultsDir := filepath.Join(tempDir, "results")
// Ensure workspace and results directories exist
if err := os.MkdirAll(workspaceDir, 0755); err != nil {
t.Fatalf("Failed to create workspace directory: %v", err)
}
if err := os.MkdirAll(resultsDir, 0755); err != nil {
t.Fatalf("Failed to create results directory: %v", err)
}
// Copy example to workspace using fixtures
dstDir := filepath.Join(workspaceDir, project)
if err := examplesDir.CopyProject(project, dstDir); err != nil {
t.Fatalf("Failed to copy example project: %v (dst: %s)", err, dstDir)
}
// Run container with example
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
// Pass script arguments via --args flag
// The --args flag collects all remaining arguments after it
cmd := exec.CommandContext(ctx, "podman", "run", "--rm",
"--security-opt", "no-new-privileges",
"--cap-drop", "ALL",
"--memory", "2g",
"--cpus", "1",
"--userns", "keep-id",
"-v", workspaceDir+":/workspace:rw",
"-v", resultsDir+":/workspace/results:rw",
"secure-ml-runner:test",
"--workspace", "/workspace/"+project,
"--requirements", "/workspace/"+project+"/requirements.txt",
"--script", "/workspace/"+project+"/train.py",
"--args", "--epochs", "1", "--output_dir", "/workspace/results")
cmd.Dir = ".." // Run from project root
output, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("Failed to execute example in container: %v\nOutput: %s", err, string(output))
}
// Check results
resultsFile := filepath.Join(resultsDir, "results.json")
if _, err := os.Stat(resultsFile); os.IsNotExist(err) {
t.Errorf("Expected results.json not found in output")
}
t.Logf("Container execution successful")
})
}
// TestPodmanExamplesSync tests the sync functionality using temp directories
func TestPodmanExamplesSync(t *testing.T) {
// Use temporary directory to avoid modifying actual workspace
tempDir := t.TempDir()
tempWorkspace := filepath.Join(tempDir, "workspace")
// Use fixtures for examples directory operations
examplesDir := tests.NewExamplesDir(filepath.Join("..", "fixtures", "examples"))
// Create temporary workspace
if err := os.MkdirAll(tempWorkspace, 0755); err != nil {
t.Fatalf("Failed to create temp workspace: %v", err)
}
// Get all example projects using fixtures
projects, err := examplesDir.ListProjects()
if err != nil {
t.Fatalf("Failed to read examples directory: %v", err)
}
for _, projectName := range projects {
dstDir := filepath.Join(tempWorkspace, projectName)
t.Run("Sync_"+projectName, func(t *testing.T) {
// Remove existing destination
os.RemoveAll(dstDir)
// Copy project using fixtures
if err := examplesDir.CopyProject(projectName, dstDir); err != nil {
t.Fatalf("Failed to copy %s to test workspace: %v", projectName, err)
}
// Verify copy
requiredFiles := []string{"train.py", "requirements.txt", "README.md"}
for _, file := range requiredFiles {
dstFile := filepath.Join(dstDir, file)
if _, err := os.Stat(dstFile); os.IsNotExist(err) {
t.Errorf("Missing file %s in copied project %s", file, projectName)
}
}
t.Logf("Successfully synced %s to temp workspace", projectName)
})
}
}