package integration import ( "context" "fmt" "os" "testing" "time" _ "github.com/lib/pq" "github.com/atlasos/calypso/internal/common/config" "github.com/atlasos/calypso/internal/common/database" "github.com/atlasos/calypso/internal/common/logger" "github.com/google/uuid" ) // TestDB holds the test database connection var TestDB *database.DB var TestConfig *config.Config var TestLogger *logger.Logger // SetupTestDB initializes a test database connection func SetupTestDB(t *testing.T) *database.DB { if TestDB != nil { return TestDB } // Get test database configuration from environment dbHost := getEnv("TEST_DB_HOST", "localhost") dbPort := getEnvInt("TEST_DB_PORT", 5432) dbUser := getEnv("TEST_DB_USER", "calypso") dbPassword := getEnv("TEST_DB_PASSWORD", "calypso123") dbName := getEnv("TEST_DB_NAME", "calypso_test") cfg := &config.Config{ Database: config.DatabaseConfig{ Host: dbHost, Port: dbPort, User: dbUser, Password: dbPassword, Database: dbName, SSLMode: "disable", MaxConnections: 10, MaxIdleConns: 5, ConnMaxLifetime: 5 * time.Minute, }, } db, err := database.NewConnection(cfg.Database) if err != nil { t.Fatalf("Failed to connect to test database: %v", err) } // Run migrations ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if err := database.RunMigrations(ctx, db); err != nil { t.Fatalf("Failed to run migrations: %v", err) } TestDB = db TestConfig = cfg if TestLogger == nil { TestLogger = logger.NewLogger("test") } return db } // CleanupTestDB cleans up test data func CleanupTestDB(t *testing.T) { if TestDB == nil { return } ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() // Clean up test data (but keep schema) tables := []string{ "sessions", "audit_log", "tasks", "alerts", "user_roles", "role_permissions", "users", "scst_initiators", "scst_luns", "scst_targets", "disk_repositories", "physical_disks", "virtual_tapes", "virtual_tape_drives", "virtual_tape_libraries", "physical_tape_slots", "physical_tape_drives", "physical_tape_libraries", } for _, table := range tables { query := fmt.Sprintf("TRUNCATE TABLE %s CASCADE", table) if _, err := TestDB.ExecContext(ctx, query); err != nil { // Ignore errors for tables that don't exist t.Logf("Warning: Failed to truncate %s: %v", table, err) } } } // CreateTestUser creates a test user in the database func CreateTestUser(t *testing.T, username, email, passwordHash string, isAdmin bool) string { userID := uuid.New().String() query := ` INSERT INTO users (id, username, email, password_hash, full_name, is_active) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id ` var id string err := TestDB.QueryRow(query, userID, username, email, passwordHash, "Test User", true).Scan(&id) if err != nil { t.Fatalf("Failed to create test user: %v", err) } // Assign admin role if requested if isAdmin { roleQuery := ` INSERT INTO user_roles (user_id, role_id) SELECT $1, id FROM roles WHERE name = 'admin' ` if _, err := TestDB.Exec(roleQuery, id); err != nil { t.Fatalf("Failed to assign admin role: %v", err) } } else { // Assign operator role for non-admin users (gives monitoring:read permission) roleQuery := ` INSERT INTO user_roles (user_id, role_id) SELECT $1, id FROM roles WHERE name = 'operator' ` if _, err := TestDB.Exec(roleQuery, id); err != nil { // Operator role might not exist, try readonly roleQuery = ` INSERT INTO user_roles (user_id, role_id) SELECT $1, id FROM roles WHERE name = 'readonly' ` if _, err := TestDB.Exec(roleQuery, id); err != nil { t.Logf("Warning: Failed to assign role: %v", err) } } } return id } // Helper functions func getEnv(key, defaultValue string) string { if v := os.Getenv(key); v != "" { return v } return defaultValue } func getEnvInt(key string, defaultValue int) int { if v := os.Getenv(key); v != "" { var result int if _, err := fmt.Sscanf(v, "%d", &result); err == nil { return result } } return defaultValue }