234 lines
6.7 KiB
Go
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())
|
|
}
|
|
})
|
|
}
|