- 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.
228 lines
5.7 KiB
Go
228 lines
5.7 KiB
Go
package tests
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"slices"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/jfraeys/fetch_ml/internal/network"
|
|
)
|
|
|
|
func TestSSHClient_ExecContext(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
client, err := network.NewSSHClient("", "", "", 0, "")
|
|
if err != nil {
|
|
t.Fatalf("NewSSHClient failed: %v", err)
|
|
}
|
|
defer client.Close()
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) // Reduced from 5 seconds
|
|
defer cancel()
|
|
|
|
out, err := client.ExecContext(ctx, "echo 'test'")
|
|
if err != nil {
|
|
t.Errorf("ExecContext failed: %v", err)
|
|
}
|
|
|
|
if out != "test\n" {
|
|
t.Errorf("Expected 'test\\n', got %q", out)
|
|
}
|
|
}
|
|
|
|
func TestSSHClient_RemoteExists(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
client, err := network.NewSSHClient("", "", "", 0, "")
|
|
if err != nil {
|
|
t.Fatalf("NewSSHClient failed: %v", err)
|
|
}
|
|
defer client.Close()
|
|
|
|
dir := t.TempDir()
|
|
file := filepath.Join(dir, "exists.txt")
|
|
if writeErr := os.WriteFile(file, []byte("data"), 0o644); writeErr != nil {
|
|
t.Fatalf("failed to create temp file: %v", writeErr)
|
|
}
|
|
|
|
if !client.RemoteExists(file) {
|
|
t.Fatal("expected RemoteExists to return true for existing file")
|
|
}
|
|
|
|
missing := filepath.Join(dir, "missing.txt")
|
|
if client.RemoteExists(missing) {
|
|
t.Fatal("expected RemoteExists to return false for missing file")
|
|
}
|
|
}
|
|
|
|
func TestSSHClient_GetFileSizeError(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
client, err := network.NewSSHClient("", "", "", 0, "")
|
|
if err != nil {
|
|
t.Fatalf("NewSSHClient failed: %v", err)
|
|
}
|
|
defer client.Close()
|
|
|
|
if _, err := client.GetFileSize("/path/that/does/not/exist"); err == nil {
|
|
t.Fatal("expected GetFileSize to error for missing path")
|
|
}
|
|
}
|
|
|
|
func TestSSHClient_TailFileMissingReturnsEmpty(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
client, err := network.NewSSHClient("", "", "", 0, "")
|
|
if err != nil {
|
|
t.Fatalf("NewSSHClient failed: %v", err)
|
|
}
|
|
defer client.Close()
|
|
|
|
if out := client.TailFile("/path/that/does/not/exist", 5); out != "" {
|
|
t.Fatalf("expected empty TailFile output for missing file, got %q", out)
|
|
}
|
|
}
|
|
|
|
func TestSSHClient_ExecContextCancellationDuringRun(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
client, err := network.NewSSHClient("", "", "", 0, "")
|
|
if err != nil {
|
|
t.Fatalf("NewSSHClient failed: %v", err)
|
|
}
|
|
defer client.Close()
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
done := make(chan error, 1)
|
|
go func() {
|
|
_, runErr := client.ExecContext(ctx, "sleep 5")
|
|
done <- runErr
|
|
}()
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
cancel()
|
|
|
|
select {
|
|
case err := <-done:
|
|
if err == nil {
|
|
t.Fatal("expected cancellation error, got nil")
|
|
}
|
|
if !errors.Is(err, context.Canceled) && !strings.Contains(err.Error(), "signal: killed") {
|
|
t.Fatalf("expected context cancellation or killed signal, got %v", err)
|
|
}
|
|
case <-time.After(2 * time.Second):
|
|
t.Fatal("ExecContext did not return after cancellation")
|
|
}
|
|
}
|
|
|
|
func TestSSHClient_ContextCancellation(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
client, _ := network.NewSSHClient("", "", "", 0, "")
|
|
defer client.Close()
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel() // Cancel immediately
|
|
|
|
_, err := client.ExecContext(ctx, "sleep 10")
|
|
if err == nil {
|
|
t.Error("Expected error from cancelled context")
|
|
}
|
|
|
|
// Check that it's a context cancellation error
|
|
if !strings.Contains(err.Error(), "context canceled") {
|
|
t.Errorf("Expected context cancellation error, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestSSHClient_LocalMode(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
client, err := network.NewSSHClient("", "", "", 0, "")
|
|
if err != nil {
|
|
t.Fatalf("NewSSHClient failed: %v", err)
|
|
}
|
|
defer client.Close()
|
|
|
|
// Test basic command
|
|
out, err := client.Exec("pwd")
|
|
if err != nil {
|
|
t.Errorf("Exec failed: %v", err)
|
|
}
|
|
|
|
if out == "" {
|
|
t.Error("Expected non-empty output from pwd")
|
|
}
|
|
}
|
|
|
|
func TestSSHClient_FileExists(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
client, err := network.NewSSHClient("", "", "", 0, "")
|
|
if err != nil {
|
|
t.Fatalf("NewSSHClient failed: %v", err)
|
|
}
|
|
defer client.Close()
|
|
|
|
// Test existing file
|
|
if !client.FileExists("/etc/passwd") {
|
|
t.Error("FileExists should return true for /etc/passwd")
|
|
}
|
|
|
|
// Test non-existing file
|
|
if client.FileExists("/non/existing/file") {
|
|
t.Error("FileExists should return false for non-existing file")
|
|
}
|
|
}
|
|
|
|
func TestSSHClient_GetFileSize(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
client, err := network.NewSSHClient("", "", "", 0, "")
|
|
if err != nil {
|
|
t.Fatalf("NewSSHClient failed: %v", err)
|
|
}
|
|
defer client.Close()
|
|
|
|
size, err := client.GetFileSize("/etc/passwd")
|
|
if err != nil {
|
|
t.Errorf("GetFileSize failed: %v", err)
|
|
}
|
|
|
|
if size <= 0 {
|
|
t.Errorf("Expected positive size for /etc/passwd, got %d", size)
|
|
}
|
|
}
|
|
|
|
func TestSSHClient_ListDir(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
client, err := network.NewSSHClient("", "", "", 0, "")
|
|
if err != nil {
|
|
t.Fatalf("NewSSHClient failed: %v", err)
|
|
}
|
|
defer client.Close()
|
|
|
|
entries := client.ListDir("/etc")
|
|
if entries == nil {
|
|
t.Error("ListDir should return non-nil slice")
|
|
}
|
|
|
|
if !slices.Contains(entries, "passwd") {
|
|
t.Error("ListDir should include 'passwd' in /etc directory")
|
|
}
|
|
}
|
|
|
|
func TestSSHClient_TailFile(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
client, err := network.NewSSHClient("", "", "", 0, "")
|
|
if err != nil {
|
|
t.Fatalf("NewSSHClient failed: %v", err)
|
|
}
|
|
defer client.Close()
|
|
|
|
content := client.TailFile("/etc/passwd", 5)
|
|
if content == "" {
|
|
t.Error("TailFile should return non-empty content")
|
|
}
|
|
|
|
lines := len(strings.Split(strings.TrimSpace(content), "\n"))
|
|
if lines > 5 {
|
|
t.Errorf("Expected at most 5 lines, got %d", lines)
|
|
}
|
|
}
|