- Add end-to-end tests for complete workflow validation - Include integration tests for API and database interactions - Add unit tests for all major components and utilities - Include performance tests for payload handling - Add CLI API integration tests - Include Podman container integration tests - Add WebSocket and queue execution tests - Include shell script tests for setup validation Provides comprehensive test coverage ensuring platform reliability and functionality across all components and interactions.
225 lines
5.5 KiB
Go
225 lines
5.5 KiB
Go
package unit
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
tests "github.com/jfraeys/fetch_ml/tests/fixtures"
|
|
)
|
|
|
|
// TestBasicRedisConnection tests basic Redis connectivity
|
|
func TestBasicRedisConnection(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
ctx := context.Background()
|
|
|
|
// Use fixtures for Redis operations
|
|
redisHelper, err := tests.NewRedisHelper("localhost:6379", 12)
|
|
if err != nil {
|
|
t.Skipf("Redis not available, skipping test: %v", err)
|
|
}
|
|
defer func() {
|
|
redisHelper.FlushDB()
|
|
redisHelper.Close()
|
|
}()
|
|
|
|
// Test basic operations
|
|
key := "test:key"
|
|
value := "test_value"
|
|
|
|
// Set
|
|
if err := redisHelper.GetClient().Set(ctx, key, value, time.Hour).Err(); err != nil {
|
|
t.Fatalf("Failed to set value: %v", err)
|
|
}
|
|
|
|
// Get
|
|
result, err := redisHelper.GetClient().Get(ctx, key).Result()
|
|
if err != nil {
|
|
t.Fatalf("Failed to get value: %v", err)
|
|
}
|
|
|
|
if result != value {
|
|
t.Errorf("Expected value '%s', got '%s'", value, result)
|
|
}
|
|
|
|
// Delete
|
|
if err := redisHelper.GetClient().Del(ctx, key).Err(); err != nil {
|
|
t.Fatalf("Failed to delete key: %v", err)
|
|
}
|
|
|
|
// Verify deleted
|
|
_, err = redisHelper.GetClient().Get(ctx, key).Result()
|
|
if err == nil {
|
|
t.Error("Expected error when getting deleted key")
|
|
}
|
|
}
|
|
|
|
// TestTaskQueueBasicOperations tests basic task queue functionality
|
|
func TestTaskQueueBasicOperations(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
|
|
// Use fixtures for Redis operations
|
|
redisHelper, err := tests.NewRedisHelper("localhost:6379", 11)
|
|
if err != nil {
|
|
t.Skipf("Redis not available, skipping test: %v", err)
|
|
}
|
|
defer func() {
|
|
redisHelper.FlushDB()
|
|
redisHelper.Close()
|
|
}()
|
|
|
|
// Create task queue
|
|
taskQueue, err := tests.NewTaskQueue(&tests.Config{
|
|
RedisAddr: "localhost:6379",
|
|
RedisDB: 11,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Failed to create task queue: %v", err)
|
|
}
|
|
defer taskQueue.Close()
|
|
|
|
// Test enqueue
|
|
task, err := taskQueue.EnqueueTask("simple_test", "--epochs 1", 5)
|
|
if err != nil {
|
|
t.Fatalf("Failed to enqueue task: %v", err)
|
|
}
|
|
|
|
if task.ID == "" {
|
|
t.Error("Task ID should not be empty")
|
|
}
|
|
|
|
if task.Status != "queued" {
|
|
t.Errorf("Expected status 'queued', got '%s'", task.Status)
|
|
}
|
|
|
|
// Test get
|
|
retrievedTask, err := taskQueue.GetTask(task.ID)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get task: %v", err)
|
|
}
|
|
|
|
if retrievedTask.ID != task.ID {
|
|
t.Errorf("Expected task ID %s, got %s", task.ID, retrievedTask.ID)
|
|
}
|
|
|
|
// Test get next
|
|
nextTask, err := taskQueue.GetNextTask()
|
|
if err != nil {
|
|
t.Fatalf("Failed to get next task: %v", err)
|
|
}
|
|
|
|
if nextTask == nil {
|
|
t.Fatal("Should have retrieved a task")
|
|
}
|
|
|
|
if nextTask.ID != task.ID {
|
|
t.Errorf("Expected task ID %s, got %s", task.ID, nextTask.ID)
|
|
}
|
|
|
|
// Test update
|
|
now := time.Now()
|
|
nextTask.Status = "running"
|
|
nextTask.StartedAt = &now
|
|
|
|
if err := taskQueue.UpdateTask(nextTask); err != nil {
|
|
t.Fatalf("Failed to update task: %v", err)
|
|
}
|
|
|
|
// Verify update
|
|
updatedTask, err := taskQueue.GetTask(nextTask.ID)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get updated task: %v", err)
|
|
}
|
|
|
|
if updatedTask.Status != "running" {
|
|
t.Errorf("Expected status 'running', got '%s'", updatedTask.Status)
|
|
}
|
|
|
|
if updatedTask.StartedAt == nil {
|
|
t.Error("StartedAt should not be nil")
|
|
}
|
|
|
|
// Test metrics
|
|
if err := taskQueue.RecordMetric("simple_test", "accuracy", 0.95); err != nil {
|
|
t.Fatalf("Failed to record metric: %v", err)
|
|
}
|
|
|
|
metrics, err := taskQueue.GetMetrics("simple_test")
|
|
if err != nil {
|
|
t.Fatalf("Failed to get metrics: %v", err)
|
|
}
|
|
|
|
if metrics["accuracy"] != "0.95" {
|
|
t.Errorf("Expected accuracy '0.95', got '%s'", metrics["accuracy"])
|
|
}
|
|
|
|
t.Log("Basic task queue operations test completed successfully")
|
|
}
|
|
|
|
// TestManageScriptHealthCheck tests the manage.sh health check functionality
|
|
func TestManageScriptHealthCheck(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
|
|
// Use fixtures for manage script operations
|
|
manageScript := "../../tools/manage.sh"
|
|
if _, err := os.Stat(manageScript); os.IsNotExist(err) {
|
|
t.Skipf("manage.sh not found at %s", manageScript)
|
|
}
|
|
|
|
ms := tests.NewManageScript(manageScript)
|
|
|
|
// Test help command to verify health command exists
|
|
output, err := ms.Status()
|
|
if err != nil {
|
|
t.Fatalf("Failed to run manage.sh status: %v", err)
|
|
}
|
|
|
|
if !strings.Contains(output, "Redis") {
|
|
t.Error("manage.sh status should include 'Redis' service status")
|
|
}
|
|
|
|
t.Log("manage.sh status command verification completed")
|
|
}
|
|
|
|
// TestAPIHealthEndpoint tests the actual API health endpoint
|
|
func TestAPIHealthEndpoint(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
|
|
// Create HTTP client with reduced timeout for better performance
|
|
client := &http.Client{
|
|
Timeout: 3 * time.Second, // Reduced from 5 seconds
|
|
}
|
|
|
|
// Test the health endpoint
|
|
req, err := http.NewRequest("GET", "https://localhost:9101/health", nil)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create request: %v", err)
|
|
}
|
|
|
|
// Add required headers
|
|
req.Header.Set("X-API-Key", "password")
|
|
req.Header.Set("X-Forwarded-For", "127.0.0.1")
|
|
|
|
// Make request (skip TLS verification for self-signed certs)
|
|
client.Transport = &http.Transport{
|
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
|
}
|
|
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
// API might not be running, which is okay for this test
|
|
t.Skipf("API not available, skipping health endpoint test: %v", err)
|
|
return
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
t.Errorf("Expected status 200, got %d", resp.StatusCode)
|
|
}
|
|
|
|
t.Log("API health endpoint test completed successfully")
|
|
}
|