deb-orchestrator/internal/e2e/workflow_test.go
2025-08-18 23:45:01 -07:00

234 lines
6.7 KiB
Go

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())
}
})
}