package e2e import ( "testing" "github.com/debian/deb-orchestrator/internal/database" "github.com/debian/deb-orchestrator/internal/models" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // TestCompleteBuildWorkflow tests the complete build workflow func TestCompleteBuildWorkflow(t *testing.T) { service := database.NewMockService() require.NotNil(t, service) // Step 1: Register a build host hostReq := models.HostRequest{ Name: "e2e-build-host", Arch: "amd64", Channel: "stable", Capacity: 5, Hostname: "192.168.1.200", Port: 22, Capabilities: map[string]interface{}{"build": true}, } host := models.NewHost(hostReq) err := service.CreateHost(host) require.NoError(t, err) // Step 2: Create a build task taskReq := models.TaskRequest{ Method: "build", Args: []string{"test-package"}, Priority: 1, Arch: "amd64", Channel: "stable", } task := models.NewTask(taskReq) err = service.CreateTask(task) require.NoError(t, err) // Step 3: Complete the workflow err = service.AssignTask(task.ID, host.ID) require.NoError(t, err) err = service.StartTask(task.ID) require.NoError(t, err) err = service.CompleteTask(task.ID, "Build completed successfully") require.NoError(t, err) // Verify final state retrievedTask, err := service.GetTaskByID(task.ID) require.NoError(t, err) assert.Equal(t, models.TaskStateCompleted, retrievedTask.State) assert.Equal(t, host.ID, retrievedTask.HostID) } // TestHostFailoverWorkflow tests the failover and recovery workflow func TestHostFailoverWorkflow(t *testing.T) { service := database.NewMockService() require.NotNil(t, service) t.Run("Host Failure and Task Recovery", func(t *testing.T) { // Create two hosts host1 := models.NewHost(models.HostRequest{ Name: "primary-host", Arch: "amd64", Channel: "stable", Capacity: 3, Hostname: "192.168.1.100", Port: 22, Capabilities: map[string]interface{}{"build": true}, }) err := service.CreateHost(host1) require.NoError(t, err) host2 := models.NewHost(models.HostRequest{ Name: "backup-host", Arch: "amd64", Channel: "stable", Capacity: 3, Hostname: "192.168.1.101", Port: 22, Capabilities: map[string]interface{}{"build": true}, }) err = service.CreateHost(host2) require.NoError(t, err) // Create and assign tasks to primary host task1 := models.NewTask(models.TaskRequest{ Method: "build", Args: []string{"package1"}, Priority: 1, Arch: "amd64", Channel: "stable", }) err = service.CreateTask(task1) require.NoError(t, err) task2 := models.NewTask(models.TaskRequest{ Method: "build", Args: []string{"package2"}, Priority: 1, Arch: "amd64", Channel: "stable", }) err = service.CreateTask(task2) require.NoError(t, err) // Assign tasks to primary host err = service.AssignTask(task1.ID, host1.ID) require.NoError(t, err) err = service.AssignTask(task2.ID, host1.ID) require.NoError(t, err) // Start tasks err = service.StartTask(task1.ID) require.NoError(t, err) err = service.StartTask(task2.ID) require.NoError(t, err) // Simulate primary host failure by marking it as offline err = service.UpdateHostState(host1.ID, models.HostStateOffline) require.NoError(t, err) // Verify tasks are in running state but host is offline retrievedTask1, err := service.GetTaskByID(task1.ID) require.NoError(t, err) assert.Equal(t, models.TaskStateRunning, retrievedTask1.State) retrievedHost1, err := service.GetHostByID(host1.ID) require.NoError(t, err) assert.Equal(t, models.HostStateOffline, retrievedHost1.State) // Simulate task recovery by reassigning to backup host err = service.AssignTask(task1.ID, host2.ID) require.NoError(t, err) err = service.AssignTask(task2.ID, host2.ID) require.NoError(t, err) // Complete tasks on backup host err = service.CompleteTask(task1.ID, "Build completed on backup host") require.NoError(t, err) err = service.CompleteTask(task2.ID, "Build completed on backup host") require.NoError(t, err) // Verify tasks completed successfully finalTask1, err := service.GetTaskByID(task1.ID) require.NoError(t, err) assert.Equal(t, models.TaskStateCompleted, finalTask1.State) assert.Equal(t, host2.ID, finalTask1.HostID) finalTask2, err := service.GetTaskByID(task2.ID) require.NoError(t, err) assert.Equal(t, models.TaskStateCompleted, finalTask2.State) assert.Equal(t, host2.ID, finalTask2.HostID) }) } // TestSystemStability tests system stability under load func TestSystemStability(t *testing.T) { service := database.NewMockService() require.NotNil(t, service) t.Run("High Load Stability", func(t *testing.T) { const numOperations = 100 // Create hosts hosts := make([]*models.Host, 5) for i := 0; i < 5; i++ { hostReq := models.HostRequest{ Name: fmt.Sprintf("stability-host-%d", i), Arch: "amd64", Channel: "stable", Capacity: 10, Hostname: fmt.Sprintf("192.168.1.%d", 300+i), Port: 22, Capabilities: map[string]interface{}{"build": true}, } host := models.NewHost(hostReq) err := service.CreateHost(host) require.NoError(t, err) hosts[i] = host } // Create and process many tasks start := time.Now() for i := 0; i < numOperations; i++ { taskReq := models.TaskRequest{ Method: "build", Args: []string{fmt.Sprintf("stability-package-%d", i)}, Priority: i % 3, Arch: "amd64", Channel: "stable", } task := models.NewTask(taskReq) err := service.CreateTask(task) require.NoError(t, err) // Assign to random host hostIndex := i % len(hosts) err = service.AssignTask(task.ID, hosts[hostIndex].ID) require.NoError(t, err) // Start and complete immediately err = service.StartTask(task.ID) require.NoError(t, err) err = service.CompleteTask(task.ID, "Stability test completed") require.NoError(t, err) } duration := time.Since(start) // Performance assertions assert.Less(t, duration, 5*time.Second, "High load operations should complete within 5 seconds") avgTime := duration / numOperations assert.Less(t, avgTime, 50*time.Millisecond, "Average operation time should be under 50ms") t.Logf("Processed %d operations in %v (avg: %v per operation)", numOperations, duration, avgTime) // Verify system integrity stats, err := service.GetTaskStats() require.NoError(t, err) assert.GreaterOrEqual(t, stats.(map[string]int)["total_tasks"], numOperations) // Verify all hosts are available for _, host := range hosts { retrievedHost, err := service.GetHostByID(host.ID) require.NoError(t, err) assert.True(t, retrievedHost.IsAvailable()) } }) }