fetch_ml/tests/integration/jupyter_experiment_test.go
Jeremie Fraeys 7305e2bc21
test: add comprehensive test coverage and command improvements
- Add logs and debug end-to-end tests
- Add test helper utilities
- Improve test fixtures and templates
- Update API server and config lint commands
- Add multi-user database initialization
2026-02-16 20:38:15 -05:00

210 lines
6.2 KiB
Go

package tests
import (
"context"
"log/slog"
"os"
"path/filepath"
"testing"
"time"
"github.com/jfraeys/fetch_ml/internal/experiment"
"github.com/jfraeys/fetch_ml/internal/jupyter"
"github.com/jfraeys/fetch_ml/internal/logging"
)
func TestJupyterExperimentIntegration(t *testing.T) {
// Setup test environment
tempDir, err := os.MkdirTemp("", "TestJupyterExperimentIntegration")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer func() {
if err := os.RemoveAll(tempDir); err != nil {
t.Logf("Warning: failed to cleanup temp dir: %v", err)
}
}()
// Initialize experiment manager
expManager := experiment.NewManager(filepath.Join(tempDir, "experiments"))
if err := expManager.Initialize(); err != nil {
t.Fatalf("Failed to initialize experiment manager: %v", err)
}
// Initialize Jupyter service manager with clean state
serviceConfig := &jupyter.ServiceConfig{
DefaultImage: "test-image",
DefaultPort: 8888,
DefaultWorkspace: tempDir,
MaxServices: 5,
DefaultResources: jupyter.ResourceConfig{
MemoryLimit: "1G",
CPULimit: "1",
GPUDevices: nil,
},
}
logger := logging.NewLogger(slog.LevelInfo, false)
serviceManager, err := jupyter.NewServiceManager(logger, serviceConfig)
if err != nil {
t.Fatalf("Failed to create service manager: %v", err)
}
defer func() {
if err := serviceManager.Close(context.Background()); err != nil {
t.Logf("Warning: failed to close service manager: %v", err)
}
}()
// Clear any existing metadata to ensure test isolation
if err := serviceManager.ClearAllMetadata(); err != nil {
t.Fatalf("Failed to clear metadata: %v", err)
}
// Test 1: Create workspace
workspacePath := filepath.Join(tempDir, "test_workspace")
if err := os.MkdirAll(workspacePath, 0750); err != nil {
t.Fatalf("Failed to create workspace: %v", err)
}
// Create sample files in workspace
notebookContent := `{
"cells": [{"cell_type": "code", "source": ["print('Hello Jupyter!')"]}],
"metadata": {"kernelspec": {"name": "python3"}},
"nbformat": 4
}`
if err := os.WriteFile(filepath.Join(workspacePath, "test.ipynb"), []byte(notebookContent), 0600); err != nil {
t.Fatalf("Failed to create notebook: %v", err)
}
// Test 2: Create experiment
experimentID := "test_experiment_123"
if err := expManager.CreateExperiment(experimentID); err != nil {
t.Fatalf("Failed to create experiment: %v", err)
}
// Write experiment metadata
metadata := &experiment.Metadata{
CommitID: experimentID,
Timestamp: time.Now().Unix(),
JobName: "test_job",
User: "test_user",
}
if err := expManager.WriteMetadata(metadata); err != nil {
t.Fatalf("Failed to write experiment metadata: %v", err)
}
// Test 3: Link workspace with experiment
serviceID := "test_service_456"
if err := serviceManager.LinkWorkspaceWithExperiment(workspacePath, experimentID, serviceID); err != nil {
t.Fatalf("Failed to link workspace with experiment: %v", err)
}
// Test 4: Verify workspace metadata
workspaceMeta, err := serviceManager.GetWorkspaceMetadata(workspacePath)
if err != nil {
t.Fatalf("Failed to get workspace metadata: %v", err)
}
if workspaceMeta.ExperimentID != experimentID {
t.Errorf("Expected experiment ID %s, got %s", experimentID, workspaceMeta.ExperimentID)
}
if workspaceMeta.ServiceID != serviceID {
t.Errorf("Expected service ID %s, got %s", serviceID, workspaceMeta.ServiceID)
}
// Test 5: Sync workspace with experiment
ctx := context.Background()
if err := serviceManager.SyncWorkspaceWithExperiment(ctx, workspacePath, experimentID, "push"); err != nil {
t.Fatalf("Failed to sync workspace: %v", err)
}
// Verify sync timestamp updated
syncedMeta, err := serviceManager.GetWorkspaceMetadata(workspacePath)
if err != nil {
t.Fatalf("Failed to get workspace metadata after sync: %v", err)
}
if syncedMeta.LastSync.IsZero() {
t.Error("Expected last sync time to be set after sync")
}
// Test 6: List linked workspaces
linkedWorkspaces := serviceManager.ListLinkedWorkspaces()
if len(linkedWorkspaces) != 1 {
t.Errorf("Expected 1 linked workspace, got %d", len(linkedWorkspaces))
}
if linkedWorkspaces[0].ExperimentID != experimentID {
t.Errorf("Expected experiment ID %s, got %s", experimentID, linkedWorkspaces[0].ExperimentID)
}
// Test 7: Get workspaces for experiment
workspacesForExp := serviceManager.GetWorkspacesForExperiment(experimentID)
if len(workspacesForExp) != 1 {
t.Errorf("Expected 1 workspace for experiment, got %d", len(workspacesForExp))
}
if workspacesForExp[0].WorkspacePath != workspacePath {
t.Errorf("Expected workspace path %s, got %s", workspacePath, workspacesForExp[0].WorkspacePath)
}
// Test 8: Set auto-sync
if err := serviceManager.SetAutoSync(workspacePath, true, 15*time.Minute); err != nil {
t.Fatalf("Failed to set auto-sync: %v", err)
}
// Verify auto-sync settings
autoSyncMeta, err := serviceManager.GetWorkspaceMetadata(workspacePath)
if err != nil {
t.Fatalf("Failed to get workspace metadata after auto-sync: %v", err)
}
if !autoSyncMeta.AutoSync {
t.Error("Expected auto-sync to be enabled")
}
if autoSyncMeta.SyncInterval != 15*time.Minute {
t.Errorf("Expected sync interval 15m, got %v", autoSyncMeta.SyncInterval)
}
// Test 9: Add tags
if err := serviceManager.AddTag(workspacePath, "test"); err != nil {
t.Fatalf("Failed to add tag: %v", err)
}
// Verify tag added
taggedMeta, err := serviceManager.GetWorkspaceMetadata(workspacePath)
if err != nil {
t.Fatalf("Failed to get workspace metadata after adding tag: %v", err)
}
foundTag := false
for _, tag := range taggedMeta.Tags {
if tag == "test" {
foundTag = true
break
}
}
if !foundTag {
t.Error("Expected 'test' tag to be found")
}
// Test 10: Unlink workspace
if err := serviceManager.UnlinkWorkspace(workspacePath); err != nil {
t.Fatalf("Failed to unlink workspace: %v", err)
}
// Verify workspace is unlinked
_, err = serviceManager.GetWorkspaceMetadata(workspacePath)
if err == nil {
t.Error("Expected workspace to be unlinked")
}
// Test 11: Verify no linked workspaces
linkedWorkspaces = serviceManager.ListLinkedWorkspaces()
if len(linkedWorkspaces) != 0 {
t.Errorf("Expected 0 linked workspaces after unlink, got %d", len(linkedWorkspaces))
}
}