Update comprehensive test coverage: - E2E tests with scheduler integration - Integration tests with tenant isolation - Unit tests with security assertions - Security tests with audit validation - Audit verification tests - Auth tests with tenant scoping - Config validation tests - Container security tests - Worker tests with scheduler mock - Environment pool tests - Load tests with distributed patterns - Test fixtures with scheduler support - Update go.mod/go.sum with new dependencies
213 lines
5.6 KiB
Go
213 lines
5.6 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/jfraeys/fetch_ml/internal/config"
|
|
)
|
|
|
|
// MockValidator implements the Validator interface for testing
|
|
type MockValidator struct {
|
|
errorMsg string
|
|
shouldFail bool
|
|
}
|
|
|
|
func (m *MockValidator) Validate() error {
|
|
if m.shouldFail {
|
|
return fmt.Errorf("validation error: %s", m.errorMsg)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func TestValidateConfig(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
|
|
// Test with valid validator
|
|
validValidator := &MockValidator{shouldFail: false}
|
|
err := config.ValidateConfig(validValidator)
|
|
if err != nil {
|
|
t.Errorf("Expected no error for valid validator, got %v", err)
|
|
}
|
|
|
|
// Test with invalid validator
|
|
invalidValidator := &MockValidator{shouldFail: true, errorMsg: "validation failed"}
|
|
err = config.ValidateConfig(invalidValidator)
|
|
if err == nil {
|
|
t.Error("Expected error for invalid validator")
|
|
}
|
|
if err.Error() != "validation error: validation failed" {
|
|
t.Errorf("Expected error message 'validation error: validation failed', got %s", err.Error())
|
|
}
|
|
}
|
|
|
|
func TestValidatePort(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
|
|
// Test valid ports
|
|
validPorts := []int{1, 22, 80, 443, 6379, 65535}
|
|
for _, port := range validPorts {
|
|
err := config.ValidatePort(port)
|
|
if err != nil {
|
|
t.Errorf("Expected no error for valid port %d, got %v", port, err)
|
|
}
|
|
}
|
|
|
|
// Test invalid ports
|
|
invalidPorts := []int{0, -1, 65536, 100000}
|
|
for _, port := range invalidPorts {
|
|
err := config.ValidatePort(port)
|
|
if err == nil {
|
|
t.Errorf("Expected error for invalid port %d", port)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestValidateDirectory(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
|
|
// Test empty path
|
|
err := config.ValidateDirectory("")
|
|
if err == nil {
|
|
t.Error("Expected error for empty path")
|
|
}
|
|
|
|
// Test non-existent directory
|
|
err = config.ValidateDirectory("/nonexistent/directory")
|
|
if err == nil {
|
|
t.Error("Expected error for non-existent directory")
|
|
}
|
|
|
|
// Test existing directory
|
|
tempDir := t.TempDir()
|
|
err = config.ValidateDirectory(tempDir)
|
|
if err != nil {
|
|
t.Errorf("Expected no error for existing directory %s, got %v", tempDir, err)
|
|
}
|
|
|
|
// Test file instead of directory
|
|
tempFile := filepath.Join(tempDir, "test_file")
|
|
err = os.WriteFile(tempFile, []byte("test"), 0600)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create test file: %v", err)
|
|
}
|
|
|
|
err = config.ValidateDirectory(tempFile)
|
|
if err == nil {
|
|
t.Error("Expected error for file path")
|
|
}
|
|
|
|
// Test directory with environment variable expansion
|
|
// Reuse the tempDir path so validation succeeds after expansion
|
|
_ = os.Setenv("TEST_DIR", tempDir)
|
|
defer func() { _ = os.Unsetenv("TEST_DIR") }()
|
|
|
|
err = config.ValidateDirectory("$TEST_DIR")
|
|
if err != nil {
|
|
t.Errorf("Expected no error for expanded directory path, got %v", err)
|
|
}
|
|
|
|
// Test directory with tilde expansion (if home directory is available)
|
|
home, err := os.UserHomeDir()
|
|
if err == nil {
|
|
// Create a test directory in home
|
|
testHomeDir := filepath.Join(home, "test_fetch_ml")
|
|
err = os.MkdirAll(testHomeDir, 0750)
|
|
if err == nil {
|
|
defer func() { _ = os.RemoveAll(tempDir) }()
|
|
|
|
err = config.ValidateDirectory("~/test_fetch_ml")
|
|
if err != nil {
|
|
t.Errorf("Expected no error for tilde expanded path, got %v", err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestValidateRedisAddr(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
|
|
// Test valid Redis addresses
|
|
validAddrs := []string{
|
|
"localhost:6379",
|
|
"127.0.0.1:6379",
|
|
"redis.example.com:6379",
|
|
"10.0.0.1:6380",
|
|
"[::1]:6379", // IPv6
|
|
}
|
|
|
|
for _, addr := range validAddrs {
|
|
err := config.ValidateRedisAddr(addr)
|
|
if err != nil {
|
|
t.Errorf("Expected no error for valid Redis address %s, got %v", addr, err)
|
|
}
|
|
}
|
|
|
|
// Test invalid Redis addresses
|
|
invalidAddrs := []string{
|
|
"", // empty
|
|
"localhost", // missing port
|
|
":6379", // missing host
|
|
"localhost:", // missing port number
|
|
"localhost:abc", // non-numeric port
|
|
"localhost:-1", // negative port
|
|
"localhost:0", // port too low
|
|
"localhost:65536", // port too high
|
|
"localhost:999999", // port way too high
|
|
"multiple:colons:6379", // too many colons
|
|
}
|
|
|
|
for _, addr := range invalidAddrs {
|
|
err := config.ValidateRedisAddr(addr)
|
|
if err == nil {
|
|
t.Errorf("Expected error for invalid Redis address %s", addr)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestValidateRedisAddrEdgeCases(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
|
|
// Test edge case ports
|
|
edgeCases := []struct {
|
|
addr string
|
|
shouldErr bool
|
|
}{
|
|
{"localhost:1", false}, // minimum valid port
|
|
{"localhost:65535", false}, // maximum valid port
|
|
{"localhost:0", true}, // below minimum
|
|
{"localhost:65536", true}, // above maximum
|
|
}
|
|
|
|
for _, tc := range edgeCases {
|
|
err := config.ValidateRedisAddr(tc.addr)
|
|
if tc.shouldErr && err == nil {
|
|
t.Errorf("Expected error for Redis address %s", tc.addr)
|
|
}
|
|
if !tc.shouldErr && err != nil {
|
|
t.Errorf("Expected no error for Redis address %s, got %v", tc.addr, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestValidatorInterface(t *testing.T) {
|
|
t.Parallel() // Enable parallel execution
|
|
|
|
// Test that our mock properly implements the interface
|
|
var _ config.Validator = &MockValidator{}
|
|
|
|
// Test that the interface works as expected
|
|
validator := &MockValidator{shouldFail: false}
|
|
err := validator.Validate()
|
|
if err != nil {
|
|
t.Errorf("MockValidator should not fail when shouldFail is false")
|
|
}
|
|
|
|
validator = &MockValidator{shouldFail: true, errorMsg: "test error"}
|
|
err = validator.Validate()
|
|
if err == nil {
|
|
t.Error("MockValidator should fail when shouldFail is true")
|
|
}
|
|
}
|