fetch_ml/tests/unit/config/paths_test.go
Jeremie Fraeys ea15af1833 Fix multi-user authentication and clean up debug code
- Fix YAML tags in auth config struct (json -> yaml)
- Update CLI configs to use pre-hashed API keys
- Remove double hashing in WebSocket client
- Fix port mapping (9102 -> 9103) in CLI commands
- Update permission keys to use jobs:read, jobs:create, etc.
- Clean up all debug logging from CLI and server
- All user roles now authenticate correctly:
  * Admin: Can queue jobs and see all jobs
  * Researcher: Can queue jobs and see own jobs
  * Analyst: Can see status (read-only access)

Multi-user authentication is now fully functional.
2025-12-06 12:35:32 -05:00

215 lines
6.1 KiB
Go

package config
import (
"os"
"path/filepath"
"strings"
"testing"
"github.com/jfraeys/fetch_ml/internal/config"
)
func TestExpandPath(t *testing.T) {
t.Parallel() // Enable parallel execution
// Test empty path
result := config.ExpandPath("")
if result != "" {
t.Errorf("Expected empty string for empty input, got %s", result)
}
// Test normal path (no expansion)
result = config.ExpandPath("/some/path")
if result != "/some/path" {
t.Errorf("Expected /some/path, got %s", result)
}
// Test environment variable expansion
_ = os.Setenv("TEST_VAR", "test_value")
defer func() { _ = os.Unsetenv("XDG_CONFIG_HOME") }()
result = config.ExpandPath("/path/$TEST_VAR/file")
expected := "/path/test_value/file"
if result != expected {
t.Errorf("Expected %s, got %s", expected, result)
}
// Test tilde expansion (if home directory is available)
home, err := os.UserHomeDir()
if err == nil {
result = config.ExpandPath("~/test")
expected := filepath.Join(home, "test")
if result != expected {
t.Errorf("Expected %s, got %s", expected, result)
}
}
// Test combination of tilde and env vars
if err == nil {
// To ensure consistent tilde expansion for this test, temporarily set HOME
tempHomeDir := t.TempDir()
_ = os.Setenv("HOME", tempHomeDir)
defer func() { _ = os.Unsetenv("HOME") }() // Clean up HOME env var
_ = os.Setenv("TEST_DIR", "mydir")
defer func() { _ = os.Unsetenv("TEST_DIR") }()
result = config.ExpandPath("~/$TEST_DIR/file")
// The expected path should use the temporarily set HOME
expected := filepath.Join(tempHomeDir, "mydir", "file")
if result != expected {
t.Errorf("Expected %s, got %s", expected, result)
}
}
}
func TestResolveConfigPath(t *testing.T) {
t.Parallel() // Enable parallel execution
// Create a temporary directory for testing
tempDir := t.TempDir()
// Test with absolute path that exists
configFile := filepath.Join(tempDir, "config.yaml")
err := os.WriteFile(configFile, []byte("test: config"), 0600)
if err != nil {
t.Fatalf("Failed to create test config file: %v", err)
}
result, err := config.ResolveConfigPath(configFile)
if err != nil {
t.Errorf("Expected no error for existing absolute path, got %v", err)
}
if result != config.ExpandPath(configFile) {
t.Errorf("Expected %s, got %s", config.ExpandPath(configFile), result)
}
// Test with relative path that doesn't exist
_, err = config.ResolveConfigPath("nonexistent.yaml")
if err == nil {
t.Error("Expected error for non-existent config file")
}
// Test with relative path that exists in current directory
relativeConfig := "relative_config.yaml"
err = os.WriteFile(relativeConfig, []byte("test: config"), 0600)
if err != nil {
t.Fatalf("Failed to create relative config file: %v", err)
}
defer func() { _ = os.Remove(relativeConfig) }()
result, err = config.ResolveConfigPath(relativeConfig)
if err != nil {
t.Errorf("Expected no error for existing relative path, got %v", err)
}
if result != config.ExpandPath(relativeConfig) {
t.Errorf("Expected %s, got %s", config.ExpandPath(relativeConfig), result)
}
// Test with relative path that exists in configs subdirectory
configsDir := filepath.Join(tempDir, "configs")
err = os.MkdirAll(configsDir, 0750)
if err != nil {
t.Fatalf("Failed to create configs directory: %v", err)
}
configInConfigs := filepath.Join(configsDir, "config.yaml")
err = os.WriteFile(configInConfigs, []byte("test: config"), 0600)
if err != nil {
t.Fatalf("Failed to create config in configs directory: %v", err)
}
// Change to temp directory to test relative path resolution
originalWd, err := os.Getwd()
if err != nil {
t.Fatalf("Failed to get current working directory: %v", err)
}
defer func() { _ = os.Chdir(originalWd) }()
err = os.Chdir(tempDir)
if err != nil {
t.Fatalf("Failed to change to temp directory: %v", err)
}
result, err = config.ResolveConfigPath("config.yaml")
if err != nil {
t.Errorf("Expected no error for config in configs subdirectory, got %v", err)
}
// The result should be the expanded path to the config file
if !strings.Contains(result, "config.yaml") {
t.Errorf("Expected result to contain config.yaml, got %s", result)
}
}
func TestNewJobPaths(t *testing.T) {
t.Parallel() // Enable parallel execution
basePath := "/test/base"
jobPaths := config.NewJobPaths(basePath)
if jobPaths.BasePath != basePath {
t.Errorf("Expected BasePath %s, got %s", basePath, jobPaths.BasePath)
}
}
func TestJobPathsMethods(t *testing.T) {
t.Parallel() // Enable parallel execution
basePath := "/test/base"
jobPaths := config.NewJobPaths(basePath)
// Test all path methods
tests := []struct {
name string
method func() string
expected string
}{
{"PendingPath", jobPaths.PendingPath, "/test/base/pending"},
{"RunningPath", jobPaths.RunningPath, "/test/base/running"},
{"FinishedPath", jobPaths.FinishedPath, "/test/base/finished"},
{"FailedPath", jobPaths.FailedPath, "/test/base/failed"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := tt.method()
if result != tt.expected {
t.Errorf("Expected %s, got %s", tt.expected, result)
}
})
}
}
func TestJobPathsWithComplexBase(t *testing.T) {
t.Parallel() // Enable parallel execution
basePath := "/very/complex/base/path/with/subdirs"
jobPaths := config.NewJobPaths(basePath)
expectedPending := filepath.Join(basePath, "pending")
if jobPaths.PendingPath() != expectedPending {
t.Errorf("Expected %s, got %s", expectedPending, jobPaths.PendingPath())
}
expectedRunning := filepath.Join(basePath, "running")
if jobPaths.RunningPath() != expectedRunning {
t.Errorf("Expected %s, got %s", expectedRunning, jobPaths.RunningPath())
}
}
func TestJobPathsEmptyBase(t *testing.T) {
t.Parallel() // Enable parallel execution
jobPaths := config.NewJobPaths("")
// Should still work with empty base path
expectedPending := "pending"
if jobPaths.PendingPath() != expectedPending {
t.Errorf("Expected %s, got %s", expectedPending, jobPaths.PendingPath())
}
expectedRunning := "running"
if jobPaths.RunningPath() != expectedRunning {
t.Errorf("Expected %s, got %s", expectedRunning, jobPaths.RunningPath())
}
}