- 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
210 lines
6.2 KiB
Go
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))
|
|
}
|
|
}
|