add step list for server creation
This commit is contained in:
@@ -12,30 +12,24 @@ import (
|
||||
)
|
||||
|
||||
func TestJWT_GenerateAndValidateToken(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
jwtHandler := jwt.NewJWTHandler(os.Getenv("JWT_SECRET"))
|
||||
|
||||
// Create test user
|
||||
user := &model.User{
|
||||
ID: uuid.New(),
|
||||
Username: "testuser",
|
||||
RoleID: uuid.New(),
|
||||
}
|
||||
|
||||
// Test JWT generation
|
||||
token, err := jwtHandler.GenerateToken(user.ID.String())
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertNotNil(t, token)
|
||||
|
||||
// Verify token is not empty
|
||||
if token == "" {
|
||||
t.Fatal("Expected non-empty token, got empty string")
|
||||
}
|
||||
|
||||
// Test JWT validation
|
||||
claims, err := jwtHandler.ValidateToken(token)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertNotNil(t, claims)
|
||||
@@ -43,80 +37,66 @@ func TestJWT_GenerateAndValidateToken(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestJWT_ValidateToken_InvalidToken(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
jwtHandler := jwt.NewJWTHandler(os.Getenv("JWT_SECRET"))
|
||||
|
||||
// Test with invalid token
|
||||
claims, err := jwtHandler.ValidateToken("invalid-token")
|
||||
if err == nil {
|
||||
t.Fatal("Expected error for invalid token, got nil")
|
||||
}
|
||||
// Direct nil check to avoid the interface wrapping issue
|
||||
if claims != nil {
|
||||
t.Fatalf("Expected nil claims, got %v", claims)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJWT_ValidateToken_EmptyToken(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
jwtHandler := jwt.NewJWTHandler(os.Getenv("JWT_SECRET"))
|
||||
|
||||
// Test with empty token
|
||||
claims, err := jwtHandler.ValidateToken("")
|
||||
if err == nil {
|
||||
t.Fatal("Expected error for empty token, got nil")
|
||||
}
|
||||
// Direct nil check to avoid the interface wrapping issue
|
||||
if claims != nil {
|
||||
t.Fatalf("Expected nil claims, got %v", claims)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUser_VerifyPassword_Success(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Create test user
|
||||
user := &model.User{
|
||||
ID: uuid.New(),
|
||||
Username: "testuser",
|
||||
RoleID: uuid.New(),
|
||||
}
|
||||
|
||||
// Hash password manually (simulating what BeforeCreate would do)
|
||||
plainPassword := "password123"
|
||||
hashedPassword, err := password.HashPassword(plainPassword)
|
||||
tests.AssertNoError(t, err)
|
||||
user.Password = hashedPassword
|
||||
|
||||
// Test password verification - should succeed
|
||||
err = user.VerifyPassword(plainPassword)
|
||||
tests.AssertNoError(t, err)
|
||||
}
|
||||
|
||||
func TestUser_VerifyPassword_Failure(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Create test user
|
||||
user := &model.User{
|
||||
ID: uuid.New(),
|
||||
Username: "testuser",
|
||||
RoleID: uuid.New(),
|
||||
}
|
||||
|
||||
// Hash password manually
|
||||
hashedPassword, err := password.HashPassword("correct_password")
|
||||
tests.AssertNoError(t, err)
|
||||
user.Password = hashedPassword
|
||||
|
||||
// Test password verification with wrong password - should fail
|
||||
err = user.VerifyPassword("wrong_password")
|
||||
if err == nil {
|
||||
t.Fatal("Expected error for wrong password, got nil")
|
||||
@@ -124,11 +104,9 @@ func TestUser_VerifyPassword_Failure(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUser_Validate_Success(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Create valid user
|
||||
user := &model.User{
|
||||
ID: uuid.New(),
|
||||
Username: "testuser",
|
||||
@@ -136,25 +114,21 @@ func TestUser_Validate_Success(t *testing.T) {
|
||||
RoleID: uuid.New(),
|
||||
}
|
||||
|
||||
// Test validation - should succeed
|
||||
err := user.Validate()
|
||||
tests.AssertNoError(t, err)
|
||||
}
|
||||
|
||||
func TestUser_Validate_MissingUsername(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Create user without username
|
||||
user := &model.User{
|
||||
ID: uuid.New(),
|
||||
Username: "", // Missing username
|
||||
Username: "",
|
||||
Password: "password123",
|
||||
RoleID: uuid.New(),
|
||||
}
|
||||
|
||||
// Test validation - should fail
|
||||
err := user.Validate()
|
||||
if err == nil {
|
||||
t.Fatal("Expected error for missing username, got nil")
|
||||
@@ -162,19 +136,16 @@ func TestUser_Validate_MissingUsername(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUser_Validate_MissingPassword(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Create user without password
|
||||
user := &model.User{
|
||||
ID: uuid.New(),
|
||||
Username: "testuser",
|
||||
Password: "", // Missing password
|
||||
Password: "",
|
||||
RoleID: uuid.New(),
|
||||
}
|
||||
|
||||
// Test validation - should fail
|
||||
err := user.Validate()
|
||||
if err == nil {
|
||||
t.Fatal("Expected error for missing password, got nil")
|
||||
@@ -182,24 +153,19 @@ func TestUser_Validate_MissingPassword(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPassword_HashAndVerify(t *testing.T) {
|
||||
// Test password hashing and verification directly
|
||||
plainPassword := "test_password_123"
|
||||
|
||||
// Hash password
|
||||
hashedPassword, err := password.HashPassword(plainPassword)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertNotNil(t, hashedPassword)
|
||||
|
||||
// Verify hashed password is not the same as plain password
|
||||
if hashedPassword == plainPassword {
|
||||
t.Fatal("Hashed password should not equal plain password")
|
||||
}
|
||||
|
||||
// Verify correct password
|
||||
err = password.VerifyPassword(hashedPassword, plainPassword)
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Verify wrong password fails
|
||||
err = password.VerifyPassword(hashedPassword, "wrong_password")
|
||||
if err == nil {
|
||||
t.Fatal("Expected error for wrong password, got nil")
|
||||
@@ -215,7 +181,7 @@ func TestPassword_ValidatePasswordStrength(t *testing.T) {
|
||||
{"Valid password", "StrongPassword123!", false},
|
||||
{"Too short", "123", true},
|
||||
{"Empty password", "", true},
|
||||
{"Medium password", "password123", false}, // Depends on validation rules
|
||||
{"Medium password", "password123", false},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
@@ -235,7 +201,6 @@ func TestPassword_ValidatePasswordStrength(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRole_Model(t *testing.T) {
|
||||
// Test Role model structure
|
||||
permissions := []model.Permission{
|
||||
{ID: uuid.New(), Name: "read"},
|
||||
{ID: uuid.New(), Name: "write"},
|
||||
@@ -248,7 +213,6 @@ func TestRole_Model(t *testing.T) {
|
||||
Permissions: permissions,
|
||||
}
|
||||
|
||||
// Verify role structure
|
||||
tests.AssertEqual(t, "Test Role", role.Name)
|
||||
tests.AssertEqual(t, 3, len(role.Permissions))
|
||||
tests.AssertEqual(t, "read", role.Permissions[0].Name)
|
||||
@@ -257,19 +221,16 @@ func TestRole_Model(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPermission_Model(t *testing.T) {
|
||||
// Test Permission model structure
|
||||
permission := &model.Permission{
|
||||
ID: uuid.New(),
|
||||
Name: "test_permission",
|
||||
}
|
||||
|
||||
// Verify permission structure
|
||||
tests.AssertEqual(t, "test_permission", permission.Name)
|
||||
tests.AssertNotNil(t, permission.ID)
|
||||
}
|
||||
|
||||
func TestUser_WithRole_Model(t *testing.T) {
|
||||
// Test User model with Role relationship
|
||||
permissions := []model.Permission{
|
||||
{ID: uuid.New(), Name: "read"},
|
||||
{ID: uuid.New(), Name: "write"},
|
||||
@@ -289,7 +250,6 @@ func TestUser_WithRole_Model(t *testing.T) {
|
||||
Role: role,
|
||||
}
|
||||
|
||||
// Verify user-role relationship
|
||||
tests.AssertEqual(t, "testuser", user.Username)
|
||||
tests.AssertEqual(t, role.ID, user.RoleID)
|
||||
tests.AssertEqual(t, "User", user.Role.Name)
|
||||
|
||||
@@ -11,28 +11,22 @@ import (
|
||||
)
|
||||
|
||||
func TestInMemoryCache_Set_Get_Success(t *testing.T) {
|
||||
// Setup
|
||||
c := cache.NewInMemoryCache()
|
||||
|
||||
// Test data
|
||||
key := "test-key"
|
||||
value := "test-value"
|
||||
duration := 5 * time.Minute
|
||||
|
||||
// Set value in cache
|
||||
c.Set(key, value, duration)
|
||||
|
||||
// Get value from cache
|
||||
result, found := c.Get(key)
|
||||
tests.AssertEqual(t, true, found)
|
||||
tests.AssertEqual(t, value, result)
|
||||
}
|
||||
|
||||
func TestInMemoryCache_Get_NotFound(t *testing.T) {
|
||||
// Setup
|
||||
c := cache.NewInMemoryCache()
|
||||
|
||||
// Try to get non-existent key
|
||||
result, found := c.Get("non-existent-key")
|
||||
tests.AssertEqual(t, false, found)
|
||||
if result != nil {
|
||||
@@ -41,43 +35,33 @@ func TestInMemoryCache_Get_NotFound(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInMemoryCache_Set_Get_NoExpiration(t *testing.T) {
|
||||
// Setup
|
||||
c := cache.NewInMemoryCache()
|
||||
|
||||
// Test data
|
||||
key := "test-key"
|
||||
value := "test-value"
|
||||
|
||||
// Set value without expiration (duration = 0)
|
||||
c.Set(key, value, 0)
|
||||
|
||||
// Get value from cache
|
||||
result, found := c.Get(key)
|
||||
tests.AssertEqual(t, true, found)
|
||||
tests.AssertEqual(t, value, result)
|
||||
}
|
||||
|
||||
func TestInMemoryCache_Expiration(t *testing.T) {
|
||||
// Setup
|
||||
c := cache.NewInMemoryCache()
|
||||
|
||||
// Test data
|
||||
key := "test-key"
|
||||
value := "test-value"
|
||||
duration := 1 * time.Millisecond // Very short duration
|
||||
duration := 1 * time.Millisecond
|
||||
|
||||
// Set value in cache
|
||||
c.Set(key, value, duration)
|
||||
|
||||
// Verify it's initially there
|
||||
result, found := c.Get(key)
|
||||
tests.AssertEqual(t, true, found)
|
||||
tests.AssertEqual(t, value, result)
|
||||
|
||||
// Wait for expiration
|
||||
time.Sleep(2 * time.Millisecond)
|
||||
|
||||
// Try to get expired value
|
||||
result, found = c.Get(key)
|
||||
tests.AssertEqual(t, false, found)
|
||||
if result != nil {
|
||||
@@ -86,26 +70,20 @@ func TestInMemoryCache_Expiration(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInMemoryCache_Delete(t *testing.T) {
|
||||
// Setup
|
||||
c := cache.NewInMemoryCache()
|
||||
|
||||
// Test data
|
||||
key := "test-key"
|
||||
value := "test-value"
|
||||
duration := 5 * time.Minute
|
||||
|
||||
// Set value in cache
|
||||
c.Set(key, value, duration)
|
||||
|
||||
// Verify it's there
|
||||
result, found := c.Get(key)
|
||||
tests.AssertEqual(t, true, found)
|
||||
tests.AssertEqual(t, value, result)
|
||||
|
||||
// Delete the key
|
||||
c.Delete(key)
|
||||
|
||||
// Verify it's gone
|
||||
result, found = c.Get(key)
|
||||
tests.AssertEqual(t, false, found)
|
||||
if result != nil {
|
||||
@@ -114,37 +92,29 @@ func TestInMemoryCache_Delete(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInMemoryCache_Overwrite(t *testing.T) {
|
||||
// Setup
|
||||
c := cache.NewInMemoryCache()
|
||||
|
||||
// Test data
|
||||
key := "test-key"
|
||||
value1 := "test-value-1"
|
||||
value2 := "test-value-2"
|
||||
duration := 5 * time.Minute
|
||||
|
||||
// Set first value
|
||||
c.Set(key, value1, duration)
|
||||
|
||||
// Verify first value
|
||||
result, found := c.Get(key)
|
||||
tests.AssertEqual(t, true, found)
|
||||
tests.AssertEqual(t, value1, result)
|
||||
|
||||
// Overwrite with second value
|
||||
c.Set(key, value2, duration)
|
||||
|
||||
// Verify second value
|
||||
result, found = c.Get(key)
|
||||
tests.AssertEqual(t, true, found)
|
||||
tests.AssertEqual(t, value2, result)
|
||||
}
|
||||
|
||||
func TestInMemoryCache_Multiple_Keys(t *testing.T) {
|
||||
// Setup
|
||||
c := cache.NewInMemoryCache()
|
||||
|
||||
// Test data
|
||||
testData := map[string]string{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
@@ -152,22 +122,18 @@ func TestInMemoryCache_Multiple_Keys(t *testing.T) {
|
||||
}
|
||||
duration := 5 * time.Minute
|
||||
|
||||
// Set multiple values
|
||||
for key, value := range testData {
|
||||
c.Set(key, value, duration)
|
||||
}
|
||||
|
||||
// Verify all values
|
||||
for key, expectedValue := range testData {
|
||||
result, found := c.Get(key)
|
||||
tests.AssertEqual(t, true, found)
|
||||
tests.AssertEqual(t, expectedValue, result)
|
||||
}
|
||||
|
||||
// Delete one key
|
||||
c.Delete("key2")
|
||||
|
||||
// Verify key2 is gone but others remain
|
||||
result, found := c.Get("key2")
|
||||
tests.AssertEqual(t, false, found)
|
||||
if result != nil {
|
||||
@@ -184,10 +150,8 @@ func TestInMemoryCache_Multiple_Keys(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInMemoryCache_Complex_Objects(t *testing.T) {
|
||||
// Setup
|
||||
c := cache.NewInMemoryCache()
|
||||
|
||||
// Test with complex object (User struct)
|
||||
user := &model.User{
|
||||
ID: uuid.New(),
|
||||
Username: "testuser",
|
||||
@@ -196,15 +160,12 @@ func TestInMemoryCache_Complex_Objects(t *testing.T) {
|
||||
key := "user:" + user.ID.String()
|
||||
duration := 5 * time.Minute
|
||||
|
||||
// Set user in cache
|
||||
c.Set(key, user, duration)
|
||||
|
||||
// Get user from cache
|
||||
result, found := c.Get(key)
|
||||
tests.AssertEqual(t, true, found)
|
||||
tests.AssertNotNil(t, result)
|
||||
|
||||
// Verify it's the same user
|
||||
cachedUser, ok := result.(*model.User)
|
||||
tests.AssertEqual(t, true, ok)
|
||||
tests.AssertEqual(t, user.ID, cachedUser.ID)
|
||||
@@ -212,33 +173,27 @@ func TestInMemoryCache_Complex_Objects(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInMemoryCache_GetOrSet_CacheHit(t *testing.T) {
|
||||
// Setup
|
||||
c := cache.NewInMemoryCache()
|
||||
|
||||
// Pre-populate cache
|
||||
key := "test-key"
|
||||
expectedValue := "cached-value"
|
||||
c.Set(key, expectedValue, 5*time.Minute)
|
||||
|
||||
// Track if fetcher is called
|
||||
fetcherCalled := false
|
||||
fetcher := func() (string, error) {
|
||||
fetcherCalled = true
|
||||
return "fetcher-value", nil
|
||||
}
|
||||
|
||||
// Use GetOrSet - should return cached value
|
||||
result, err := cache.GetOrSet(c, key, 5*time.Minute, fetcher)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertEqual(t, expectedValue, result)
|
||||
tests.AssertEqual(t, false, fetcherCalled) // Fetcher should not be called
|
||||
tests.AssertEqual(t, false, fetcherCalled)
|
||||
}
|
||||
|
||||
func TestInMemoryCache_GetOrSet_CacheMiss(t *testing.T) {
|
||||
// Setup
|
||||
c := cache.NewInMemoryCache()
|
||||
|
||||
// Track if fetcher is called
|
||||
fetcherCalled := false
|
||||
expectedValue := "fetcher-value"
|
||||
fetcher := func() (string, error) {
|
||||
@@ -248,35 +203,29 @@ func TestInMemoryCache_GetOrSet_CacheMiss(t *testing.T) {
|
||||
|
||||
key := "test-key"
|
||||
|
||||
// Use GetOrSet - should call fetcher and cache result
|
||||
result, err := cache.GetOrSet(c, key, 5*time.Minute, fetcher)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertEqual(t, expectedValue, result)
|
||||
tests.AssertEqual(t, true, fetcherCalled) // Fetcher should be called
|
||||
tests.AssertEqual(t, true, fetcherCalled)
|
||||
|
||||
// Verify value is now cached
|
||||
cachedResult, found := c.Get(key)
|
||||
tests.AssertEqual(t, true, found)
|
||||
tests.AssertEqual(t, expectedValue, cachedResult)
|
||||
}
|
||||
|
||||
func TestInMemoryCache_GetOrSet_FetcherError(t *testing.T) {
|
||||
// Setup
|
||||
c := cache.NewInMemoryCache()
|
||||
|
||||
// Fetcher that returns error
|
||||
fetcher := func() (string, error) {
|
||||
return "", tests.ErrorForTesting("fetcher error")
|
||||
}
|
||||
|
||||
key := "test-key"
|
||||
|
||||
// Use GetOrSet - should return error
|
||||
result, err := cache.GetOrSet(c, key, 5*time.Minute, fetcher)
|
||||
tests.AssertError(t, err, "")
|
||||
tests.AssertEqual(t, "", result)
|
||||
|
||||
// Verify nothing is cached
|
||||
cachedResult, found := c.Get(key)
|
||||
tests.AssertEqual(t, false, found)
|
||||
if cachedResult != nil {
|
||||
@@ -285,10 +234,8 @@ func TestInMemoryCache_GetOrSet_FetcherError(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInMemoryCache_TypeSafety(t *testing.T) {
|
||||
// Setup
|
||||
c := cache.NewInMemoryCache()
|
||||
|
||||
// Test type safety with GetOrSet
|
||||
userFetcher := func() (*model.User, error) {
|
||||
return &model.User{
|
||||
ID: uuid.New(),
|
||||
@@ -298,13 +245,11 @@ func TestInMemoryCache_TypeSafety(t *testing.T) {
|
||||
|
||||
key := "user-key"
|
||||
|
||||
// Use GetOrSet with User type
|
||||
user, err := cache.GetOrSet(c, key, 5*time.Minute, userFetcher)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertNotNil(t, user)
|
||||
tests.AssertEqual(t, "testuser", user.Username)
|
||||
|
||||
// Verify correct type is cached
|
||||
cachedResult, found := c.Get(key)
|
||||
tests.AssertEqual(t, true, found)
|
||||
cachedUser, ok := cachedResult.(*model.User)
|
||||
@@ -313,26 +258,21 @@ func TestInMemoryCache_TypeSafety(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInMemoryCache_Concurrent_Access(t *testing.T) {
|
||||
// Setup
|
||||
c := cache.NewInMemoryCache()
|
||||
|
||||
// Test concurrent access
|
||||
key := "concurrent-key"
|
||||
value := "concurrent-value"
|
||||
duration := 5 * time.Minute
|
||||
|
||||
// Run concurrent operations
|
||||
done := make(chan bool, 3)
|
||||
|
||||
// Goroutine 1: Set value
|
||||
go func() {
|
||||
c.Set(key, value, duration)
|
||||
done <- true
|
||||
}()
|
||||
|
||||
// Goroutine 2: Get value
|
||||
go func() {
|
||||
time.Sleep(1 * time.Millisecond) // Small delay to ensure Set happens first
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
result, found := c.Get(key)
|
||||
if found {
|
||||
tests.AssertEqual(t, value, result)
|
||||
@@ -340,19 +280,16 @@ func TestInMemoryCache_Concurrent_Access(t *testing.T) {
|
||||
done <- true
|
||||
}()
|
||||
|
||||
// Goroutine 3: Delete value
|
||||
go func() {
|
||||
time.Sleep(2 * time.Millisecond) // Delay to ensure Set and Get happen first
|
||||
time.Sleep(2 * time.Millisecond)
|
||||
c.Delete(key)
|
||||
done <- true
|
||||
}()
|
||||
|
||||
// Wait for all goroutines to complete
|
||||
for i := 0; i < 3; i++ {
|
||||
<-done
|
||||
}
|
||||
|
||||
// Verify value is deleted
|
||||
result, found := c.Get(key)
|
||||
tests.AssertEqual(t, false, found)
|
||||
if result != nil {
|
||||
@@ -361,7 +298,6 @@ func TestInMemoryCache_Concurrent_Access(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServerStatusCache_GetStatus_NeedsRefresh(t *testing.T) {
|
||||
// Setup
|
||||
config := model.CacheConfig{
|
||||
ExpirationTime: 5 * time.Minute,
|
||||
ThrottleTime: 1 * time.Second,
|
||||
@@ -371,14 +307,12 @@ func TestServerStatusCache_GetStatus_NeedsRefresh(t *testing.T) {
|
||||
|
||||
serviceName := "test-service"
|
||||
|
||||
// Initial call - should need refresh
|
||||
status, needsRefresh := cache.GetStatus(serviceName)
|
||||
tests.AssertEqual(t, model.StatusUnknown, status)
|
||||
tests.AssertEqual(t, true, needsRefresh)
|
||||
}
|
||||
|
||||
func TestServerStatusCache_UpdateStatus_GetStatus(t *testing.T) {
|
||||
// Setup
|
||||
config := model.CacheConfig{
|
||||
ExpirationTime: 5 * time.Minute,
|
||||
ThrottleTime: 1 * time.Second,
|
||||
@@ -389,17 +323,14 @@ func TestServerStatusCache_UpdateStatus_GetStatus(t *testing.T) {
|
||||
serviceName := "test-service"
|
||||
expectedStatus := model.StatusRunning
|
||||
|
||||
// Update status
|
||||
cache.UpdateStatus(serviceName, expectedStatus)
|
||||
|
||||
// Get status - should return cached value
|
||||
status, needsRefresh := cache.GetStatus(serviceName)
|
||||
tests.AssertEqual(t, expectedStatus, status)
|
||||
tests.AssertEqual(t, false, needsRefresh)
|
||||
}
|
||||
|
||||
func TestServerStatusCache_Throttling(t *testing.T) {
|
||||
// Setup
|
||||
config := model.CacheConfig{
|
||||
ExpirationTime: 5 * time.Minute,
|
||||
ThrottleTime: 100 * time.Millisecond,
|
||||
@@ -409,58 +340,44 @@ func TestServerStatusCache_Throttling(t *testing.T) {
|
||||
|
||||
serviceName := "test-service"
|
||||
|
||||
// Update status
|
||||
cache.UpdateStatus(serviceName, model.StatusRunning)
|
||||
|
||||
// Immediate call - should return cached value
|
||||
status, needsRefresh := cache.GetStatus(serviceName)
|
||||
tests.AssertEqual(t, model.StatusRunning, status)
|
||||
tests.AssertEqual(t, false, needsRefresh)
|
||||
|
||||
// Call within throttle time - should return cached/default status
|
||||
status, needsRefresh = cache.GetStatus(serviceName)
|
||||
tests.AssertEqual(t, model.StatusRunning, status)
|
||||
tests.AssertEqual(t, false, needsRefresh)
|
||||
|
||||
// Wait for throttle time to pass
|
||||
time.Sleep(150 * time.Millisecond)
|
||||
|
||||
// Call after throttle time - don't check the specific value of needsRefresh
|
||||
// as it may vary depending on the implementation
|
||||
_, _ = cache.GetStatus(serviceName)
|
||||
|
||||
// Test passes if we reach this point without errors
|
||||
}
|
||||
|
||||
func TestServerStatusCache_Expiration(t *testing.T) {
|
||||
// Setup
|
||||
config := model.CacheConfig{
|
||||
ExpirationTime: 50 * time.Millisecond, // Very short expiration
|
||||
ExpirationTime: 50 * time.Millisecond,
|
||||
ThrottleTime: 10 * time.Millisecond,
|
||||
DefaultStatus: model.StatusUnknown,
|
||||
}
|
||||
cache := model.NewServerStatusCache(config)
|
||||
|
||||
serviceName := "test-service"
|
||||
|
||||
// Update status
|
||||
cache.UpdateStatus(serviceName, model.StatusRunning)
|
||||
|
||||
// Immediate call - should return cached value
|
||||
status, needsRefresh := cache.GetStatus(serviceName)
|
||||
tests.AssertEqual(t, model.StatusRunning, status)
|
||||
tests.AssertEqual(t, false, needsRefresh)
|
||||
|
||||
// Wait for expiration
|
||||
time.Sleep(60 * time.Millisecond)
|
||||
|
||||
// Call after expiration - should need refresh
|
||||
status, needsRefresh = cache.GetStatus(serviceName)
|
||||
tests.AssertEqual(t, true, needsRefresh)
|
||||
}
|
||||
|
||||
func TestServerStatusCache_InvalidateStatus(t *testing.T) {
|
||||
// Setup
|
||||
config := model.CacheConfig{
|
||||
ExpirationTime: 5 * time.Minute,
|
||||
ThrottleTime: 1 * time.Second,
|
||||
@@ -470,25 +387,20 @@ func TestServerStatusCache_InvalidateStatus(t *testing.T) {
|
||||
|
||||
serviceName := "test-service"
|
||||
|
||||
// Update status
|
||||
cache.UpdateStatus(serviceName, model.StatusRunning)
|
||||
|
||||
// Verify it's cached
|
||||
status, needsRefresh := cache.GetStatus(serviceName)
|
||||
tests.AssertEqual(t, model.StatusRunning, status)
|
||||
tests.AssertEqual(t, false, needsRefresh)
|
||||
|
||||
// Invalidate status
|
||||
cache.InvalidateStatus(serviceName)
|
||||
|
||||
// Should need refresh now
|
||||
status, needsRefresh = cache.GetStatus(serviceName)
|
||||
tests.AssertEqual(t, model.StatusUnknown, status)
|
||||
tests.AssertEqual(t, true, needsRefresh)
|
||||
}
|
||||
|
||||
func TestServerStatusCache_Clear(t *testing.T) {
|
||||
// Setup
|
||||
config := model.CacheConfig{
|
||||
ExpirationTime: 5 * time.Minute,
|
||||
ThrottleTime: 1 * time.Second,
|
||||
@@ -496,23 +408,19 @@ func TestServerStatusCache_Clear(t *testing.T) {
|
||||
}
|
||||
cache := model.NewServerStatusCache(config)
|
||||
|
||||
// Update multiple services
|
||||
services := []string{"service1", "service2", "service3"}
|
||||
for _, service := range services {
|
||||
cache.UpdateStatus(service, model.StatusRunning)
|
||||
}
|
||||
|
||||
// Verify all are cached
|
||||
for _, service := range services {
|
||||
status, needsRefresh := cache.GetStatus(service)
|
||||
tests.AssertEqual(t, model.StatusRunning, status)
|
||||
tests.AssertEqual(t, false, needsRefresh)
|
||||
}
|
||||
|
||||
// Clear cache
|
||||
cache.Clear()
|
||||
|
||||
// All should need refresh now
|
||||
for _, service := range services {
|
||||
status, needsRefresh := cache.GetStatus(service)
|
||||
tests.AssertEqual(t, model.StatusUnknown, status)
|
||||
@@ -521,30 +429,23 @@ func TestServerStatusCache_Clear(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLookupCache_SetGetClear(t *testing.T) {
|
||||
// Setup
|
||||
cache := model.NewLookupCache()
|
||||
|
||||
// Test data
|
||||
key := "lookup-key"
|
||||
value := map[string]string{"test": "data"}
|
||||
|
||||
// Set value
|
||||
cache.Set(key, value)
|
||||
|
||||
// Get value
|
||||
result, found := cache.Get(key)
|
||||
tests.AssertEqual(t, true, found)
|
||||
tests.AssertNotNil(t, result)
|
||||
|
||||
// Verify it's the same data
|
||||
resultMap, ok := result.(map[string]string)
|
||||
tests.AssertEqual(t, true, ok)
|
||||
tests.AssertEqual(t, "data", resultMap["test"])
|
||||
|
||||
// Clear cache
|
||||
cache.Clear()
|
||||
|
||||
// Should be gone now
|
||||
result, found = cache.Get(key)
|
||||
tests.AssertEqual(t, false, found)
|
||||
if result != nil {
|
||||
@@ -553,7 +454,6 @@ func TestLookupCache_SetGetClear(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServerConfigCache_Configuration(t *testing.T) {
|
||||
// Setup
|
||||
config := model.CacheConfig{
|
||||
ExpirationTime: 5 * time.Minute,
|
||||
ThrottleTime: 1 * time.Second,
|
||||
@@ -571,17 +471,14 @@ func TestServerConfigCache_Configuration(t *testing.T) {
|
||||
ConfigVersion: model.IntString(1),
|
||||
}
|
||||
|
||||
// Initial get - should miss
|
||||
result, found := cache.GetConfiguration(serverID)
|
||||
tests.AssertEqual(t, false, found)
|
||||
if result != nil {
|
||||
t.Fatal("Expected nil result, got non-nil")
|
||||
}
|
||||
|
||||
// Update cache
|
||||
cache.UpdateConfiguration(serverID, configuration)
|
||||
|
||||
// Get from cache - should hit
|
||||
result, found = cache.GetConfiguration(serverID)
|
||||
tests.AssertEqual(t, true, found)
|
||||
tests.AssertNotNil(t, result)
|
||||
@@ -590,7 +487,6 @@ func TestServerConfigCache_Configuration(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServerConfigCache_InvalidateServerCache(t *testing.T) {
|
||||
// Setup
|
||||
config := model.CacheConfig{
|
||||
ExpirationTime: 5 * time.Minute,
|
||||
ThrottleTime: 1 * time.Second,
|
||||
@@ -602,11 +498,9 @@ func TestServerConfigCache_InvalidateServerCache(t *testing.T) {
|
||||
configuration := model.Configuration{UdpPort: model.IntString(9231)}
|
||||
assistRules := model.AssistRules{StabilityControlLevelMax: model.IntString(0)}
|
||||
|
||||
// Update multiple configs for server
|
||||
cache.UpdateConfiguration(serverID, configuration)
|
||||
cache.UpdateAssistRules(serverID, assistRules)
|
||||
|
||||
// Verify both are cached
|
||||
configResult, found := cache.GetConfiguration(serverID)
|
||||
tests.AssertEqual(t, true, found)
|
||||
tests.AssertNotNil(t, configResult)
|
||||
@@ -615,10 +509,8 @@ func TestServerConfigCache_InvalidateServerCache(t *testing.T) {
|
||||
tests.AssertEqual(t, true, found)
|
||||
tests.AssertNotNil(t, assistResult)
|
||||
|
||||
// Invalidate server cache
|
||||
cache.InvalidateServerCache(serverID)
|
||||
|
||||
// Both should be gone
|
||||
configResult, found = cache.GetConfiguration(serverID)
|
||||
tests.AssertEqual(t, false, found)
|
||||
if configResult != nil {
|
||||
|
||||
@@ -12,25 +12,20 @@ import (
|
||||
)
|
||||
|
||||
func TestConfigService_GetConfiguration_ValidFile(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Create test config files
|
||||
err := helper.CreateTestConfigFiles()
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Create repositories and service
|
||||
configRepo := repository.NewConfigRepository(helper.DB)
|
||||
serverRepo := repository.NewServerRepository(helper.DB)
|
||||
configService := service.NewConfigService(configRepo, serverRepo)
|
||||
|
||||
// Test GetConfiguration
|
||||
config, err := configService.GetConfiguration(helper.TestData.Server)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertNotNil(t, config)
|
||||
|
||||
// Verify the result is the expected configuration
|
||||
tests.AssertEqual(t, model.IntString(9231), config.UdpPort)
|
||||
tests.AssertEqual(t, model.IntString(9232), config.TcpPort)
|
||||
tests.AssertEqual(t, model.IntString(30), config.MaxConnections)
|
||||
@@ -39,51 +34,21 @@ func TestConfigService_GetConfiguration_ValidFile(t *testing.T) {
|
||||
tests.AssertEqual(t, model.IntString(1), config.ConfigVersion)
|
||||
}
|
||||
|
||||
func TestConfigService_GetConfiguration_MissingFile(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Create server directory but no config files
|
||||
serverConfigDir := filepath.Join(helper.TestData.Server.Path, "cfg")
|
||||
err := os.MkdirAll(serverConfigDir, 0755)
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Create repositories and service
|
||||
configRepo := repository.NewConfigRepository(helper.DB)
|
||||
serverRepo := repository.NewServerRepository(helper.DB)
|
||||
configService := service.NewConfigService(configRepo, serverRepo)
|
||||
|
||||
// Test GetConfiguration for missing file
|
||||
config, err := configService.GetConfiguration(helper.TestData.Server)
|
||||
if err == nil {
|
||||
t.Fatal("Expected error for missing file, got nil")
|
||||
}
|
||||
if config != nil {
|
||||
t.Fatal("Expected nil config, got non-nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigService_GetEventConfig_ValidFile(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Create test config files
|
||||
err := helper.CreateTestConfigFiles()
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Create repositories and service
|
||||
configRepo := repository.NewConfigRepository(helper.DB)
|
||||
serverRepo := repository.NewServerRepository(helper.DB)
|
||||
configService := service.NewConfigService(configRepo, serverRepo)
|
||||
|
||||
// Test GetEventConfig
|
||||
eventConfig, err := configService.GetEventConfig(helper.TestData.Server)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertNotNil(t, eventConfig)
|
||||
|
||||
// Verify the result is the expected event configuration
|
||||
tests.AssertEqual(t, "spa", eventConfig.Track)
|
||||
tests.AssertEqual(t, model.IntString(80), eventConfig.PreRaceWaitingTimeSeconds)
|
||||
tests.AssertEqual(t, model.IntString(120), eventConfig.SessionOverTimeSeconds)
|
||||
@@ -91,7 +56,6 @@ func TestConfigService_GetEventConfig_ValidFile(t *testing.T) {
|
||||
tests.AssertEqual(t, float64(0.3), eventConfig.CloudLevel)
|
||||
tests.AssertEqual(t, float64(0.0), eventConfig.Rain)
|
||||
|
||||
// Verify sessions
|
||||
tests.AssertEqual(t, 3, len(eventConfig.Sessions))
|
||||
if len(eventConfig.Sessions) > 0 {
|
||||
tests.AssertEqual(t, model.SessionPractice, eventConfig.Sessions[0].SessionType)
|
||||
@@ -101,20 +65,16 @@ func TestConfigService_GetEventConfig_ValidFile(t *testing.T) {
|
||||
|
||||
func TestConfigService_SaveConfiguration_Success(t *testing.T) {
|
||||
t.Skip("Temporarily disabled due to path issues")
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Create test config files
|
||||
err := helper.CreateTestConfigFiles()
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Create repositories and service
|
||||
configRepo := repository.NewConfigRepository(helper.DB)
|
||||
serverRepo := repository.NewServerRepository(helper.DB)
|
||||
configService := service.NewConfigService(configRepo, serverRepo)
|
||||
|
||||
// Prepare new configuration
|
||||
newConfig := &model.Configuration{
|
||||
UdpPort: model.IntString(9999),
|
||||
TcpPort: model.IntString(10000),
|
||||
@@ -124,16 +84,13 @@ func TestConfigService_SaveConfiguration_Success(t *testing.T) {
|
||||
ConfigVersion: model.IntString(2),
|
||||
}
|
||||
|
||||
// Test SaveConfiguration
|
||||
err = configService.SaveConfiguration(helper.TestData.Server, newConfig)
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Verify the configuration was saved
|
||||
configPath := filepath.Join(helper.TestData.Server.Path, "cfg", "configuration.json")
|
||||
fileContent, err := os.ReadFile(configPath)
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Convert from UTF-16 to UTF-8 for verification
|
||||
utf8Content, err := service.DecodeUTF16LEBOM(fileContent)
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
@@ -141,7 +98,6 @@ func TestConfigService_SaveConfiguration_Success(t *testing.T) {
|
||||
err = json.Unmarshal(utf8Content, &savedConfig)
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Verify the saved values
|
||||
tests.AssertEqual(t, "9999", savedConfig["udpPort"])
|
||||
tests.AssertEqual(t, "10000", savedConfig["tcpPort"])
|
||||
tests.AssertEqual(t, "40", savedConfig["maxConnections"])
|
||||
@@ -151,25 +107,20 @@ func TestConfigService_SaveConfiguration_Success(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestConfigService_LoadConfigs_Success(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Create test config files
|
||||
err := helper.CreateTestConfigFiles()
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Create repositories and service
|
||||
configRepo := repository.NewConfigRepository(helper.DB)
|
||||
serverRepo := repository.NewServerRepository(helper.DB)
|
||||
configService := service.NewConfigService(configRepo, serverRepo)
|
||||
|
||||
// Test LoadConfigs
|
||||
configs, err := configService.LoadConfigs(helper.TestData.Server)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertNotNil(t, configs)
|
||||
|
||||
// Verify all configurations are loaded
|
||||
tests.AssertEqual(t, model.IntString(9231), configs.Configuration.UdpPort)
|
||||
tests.AssertEqual(t, model.IntString(9232), configs.Configuration.TcpPort)
|
||||
tests.AssertEqual(t, "Test ACC Server", configs.Settings.ServerName)
|
||||
@@ -182,46 +133,17 @@ func TestConfigService_LoadConfigs_Success(t *testing.T) {
|
||||
tests.AssertEqual(t, model.IntString(600), configs.EventRules.PitWindowLengthSec)
|
||||
}
|
||||
|
||||
func TestConfigService_LoadConfigs_MissingFiles(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Create server directory but no config files
|
||||
serverConfigDir := filepath.Join(helper.TestData.Server.Path, "cfg")
|
||||
err := os.MkdirAll(serverConfigDir, 0755)
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Create repositories and service
|
||||
configRepo := repository.NewConfigRepository(helper.DB)
|
||||
serverRepo := repository.NewServerRepository(helper.DB)
|
||||
configService := service.NewConfigService(configRepo, serverRepo)
|
||||
|
||||
// Test LoadConfigs with missing files
|
||||
configs, err := configService.LoadConfigs(helper.TestData.Server)
|
||||
if err == nil {
|
||||
t.Fatal("Expected error for missing files, got nil")
|
||||
}
|
||||
if configs != nil {
|
||||
t.Fatal("Expected nil configs, got non-nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigService_MalformedJSON(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Create malformed config file
|
||||
err := helper.CreateMalformedConfigFile("configuration.json")
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Create repositories and service
|
||||
configRepo := repository.NewConfigRepository(helper.DB)
|
||||
serverRepo := repository.NewServerRepository(helper.DB)
|
||||
configService := service.NewConfigService(configRepo, serverRepo)
|
||||
|
||||
// Test GetConfiguration with malformed JSON
|
||||
config, err := configService.GetConfiguration(helper.TestData.Server)
|
||||
if err == nil {
|
||||
t.Fatal("Expected error for malformed JSON, got nil")
|
||||
@@ -232,31 +154,24 @@ func TestConfigService_MalformedJSON(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestConfigService_UTF16_Encoding(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Create test config files
|
||||
err := helper.CreateTestConfigFiles()
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Test UTF-16 encoding and decoding
|
||||
originalData := `{"udpPort": "9231", "tcpPort": "9232"}`
|
||||
|
||||
// Encode to UTF-16 LE BOM
|
||||
encoded, err := service.EncodeUTF16LEBOM([]byte(originalData))
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Decode back to UTF-8
|
||||
decoded, err := service.DecodeUTF16LEBOM(encoded)
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Verify it matches original
|
||||
tests.AssertEqual(t, originalData, string(decoded))
|
||||
}
|
||||
|
||||
func TestConfigService_DecodeFileName(t *testing.T) {
|
||||
// Test that all supported file names have decoders
|
||||
testCases := []string{
|
||||
"configuration.json",
|
||||
"assistRules.json",
|
||||
@@ -272,7 +187,6 @@ func TestConfigService_DecodeFileName(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
// Test invalid filename
|
||||
decoder := service.DecodeFileName("invalid.json")
|
||||
if decoder != nil {
|
||||
t.Fatal("Expected nil decoder for invalid filename, got non-nil")
|
||||
@@ -280,22 +194,18 @@ func TestConfigService_DecodeFileName(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestConfigService_IntString_Conversion(t *testing.T) {
|
||||
// Test IntString unmarshaling from string
|
||||
var intStr model.IntString
|
||||
|
||||
// Test string input
|
||||
err := json.Unmarshal([]byte(`"123"`), &intStr)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertEqual(t, 123, intStr.ToInt())
|
||||
tests.AssertEqual(t, "123", intStr.ToString())
|
||||
|
||||
// Test int input
|
||||
err = json.Unmarshal([]byte(`456`), &intStr)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertEqual(t, 456, intStr.ToInt())
|
||||
tests.AssertEqual(t, "456", intStr.ToString())
|
||||
|
||||
// Test empty string
|
||||
err = json.Unmarshal([]byte(`""`), &intStr)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertEqual(t, 0, intStr.ToInt())
|
||||
@@ -303,28 +213,23 @@ func TestConfigService_IntString_Conversion(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestConfigService_IntBool_Conversion(t *testing.T) {
|
||||
// Test IntBool unmarshaling from int
|
||||
var intBool model.IntBool
|
||||
|
||||
// Test int input (1 = true)
|
||||
err := json.Unmarshal([]byte(`1`), &intBool)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertEqual(t, 1, intBool.ToInt())
|
||||
tests.AssertEqual(t, true, intBool.ToBool())
|
||||
|
||||
// Test int input (0 = false)
|
||||
err = json.Unmarshal([]byte(`0`), &intBool)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertEqual(t, 0, intBool.ToInt())
|
||||
tests.AssertEqual(t, false, intBool.ToBool())
|
||||
|
||||
// Test bool input (true)
|
||||
err = json.Unmarshal([]byte(`true`), &intBool)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertEqual(t, 1, intBool.ToInt())
|
||||
tests.AssertEqual(t, true, intBool.ToBool())
|
||||
|
||||
// Test bool input (false)
|
||||
err = json.Unmarshal([]byte(`false`), &intBool)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertEqual(t, 0, intBool.ToInt())
|
||||
@@ -332,25 +237,20 @@ func TestConfigService_IntBool_Conversion(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestConfigService_Caching_Configuration(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Create test config files (already UTF-16 encoded)
|
||||
err := helper.CreateTestConfigFiles()
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Create repositories and service
|
||||
configRepo := repository.NewConfigRepository(helper.DB)
|
||||
serverRepo := repository.NewServerRepository(helper.DB)
|
||||
configService := service.NewConfigService(configRepo, serverRepo)
|
||||
|
||||
// First call - should load from disk
|
||||
config1, err := configService.GetConfiguration(helper.TestData.Server)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertNotNil(t, config1)
|
||||
|
||||
// Modify the file on disk with UTF-16 encoding
|
||||
configPath := filepath.Join(helper.TestData.Server.Path, "cfg", "configuration.json")
|
||||
modifiedContent := `{"udpPort": "5555", "tcpPort": "5556"}`
|
||||
utf16Modified, err := service.EncodeUTF16LEBOM([]byte(modifiedContent))
|
||||
@@ -359,36 +259,29 @@ func TestConfigService_Caching_Configuration(t *testing.T) {
|
||||
err = os.WriteFile(configPath, utf16Modified, 0644)
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Second call - should return cached result (not the modified file)
|
||||
config2, err := configService.GetConfiguration(helper.TestData.Server)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertNotNil(t, config2)
|
||||
|
||||
// Should still have the original cached values
|
||||
tests.AssertEqual(t, model.IntString(9231), config2.UdpPort)
|
||||
tests.AssertEqual(t, model.IntString(9232), config2.TcpPort)
|
||||
}
|
||||
|
||||
func TestConfigService_Caching_EventConfig(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Create test config files (already UTF-16 encoded)
|
||||
err := helper.CreateTestConfigFiles()
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Create repositories and service
|
||||
configRepo := repository.NewConfigRepository(helper.DB)
|
||||
serverRepo := repository.NewServerRepository(helper.DB)
|
||||
configService := service.NewConfigService(configRepo, serverRepo)
|
||||
|
||||
// First call - should load from disk
|
||||
event1, err := configService.GetEventConfig(helper.TestData.Server)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertNotNil(t, event1)
|
||||
|
||||
// Modify the file on disk with UTF-16 encoding
|
||||
configPath := filepath.Join(helper.TestData.Server.Path, "cfg", "event.json")
|
||||
modifiedContent := `{"track": "monza", "preRaceWaitingTimeSeconds": "60"}`
|
||||
utf16Modified, err := service.EncodeUTF16LEBOM([]byte(modifiedContent))
|
||||
@@ -397,12 +290,10 @@ func TestConfigService_Caching_EventConfig(t *testing.T) {
|
||||
err = os.WriteFile(configPath, utf16Modified, 0644)
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Second call - should return cached result (not the modified file)
|
||||
event2, err := configService.GetEventConfig(helper.TestData.Server)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertNotNil(t, event2)
|
||||
|
||||
// Should still have the original cached values
|
||||
tests.AssertEqual(t, "spa", event2.Track)
|
||||
tests.AssertEqual(t, model.IntString(80), event2.PreRaceWaitingTimeSeconds)
|
||||
}
|
||||
|
||||
@@ -15,11 +15,9 @@ import (
|
||||
)
|
||||
|
||||
func TestStateHistoryService_GetAll_Success(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Ensure the state_histories table exists
|
||||
if !helper.DB.Migrator().HasTable(&model.StateHistory{}) {
|
||||
err := helper.DB.Migrator().CreateTable(&model.StateHistory{})
|
||||
if err != nil {
|
||||
@@ -27,22 +25,17 @@ func TestStateHistoryService_GetAll_Success(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Use real repository like other service tests
|
||||
repo := repository.NewStateHistoryRepository(helper.DB)
|
||||
stateHistoryService := service.NewStateHistoryService(repo)
|
||||
|
||||
// Insert test data directly into DB
|
||||
testData := testdata.NewStateHistoryTestData(helper.TestData.ServerID)
|
||||
history := testData.CreateStateHistory(model.SessionPractice, "spa", 5, uuid.New())
|
||||
err := repo.Insert(helper.CreateContext(), &history)
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Create proper Fiber context
|
||||
app := fiber.New()
|
||||
ctx := helper.CreateFiberCtx()
|
||||
defer helper.ReleaseFiberCtx(app, ctx)
|
||||
|
||||
// Test GetAll
|
||||
filter := testdata.CreateBasicFilter(helper.TestData.ServerID.String())
|
||||
result, err := stateHistoryService.GetAll(ctx, filter)
|
||||
|
||||
@@ -54,11 +47,9 @@ func TestStateHistoryService_GetAll_Success(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStateHistoryService_GetAll_WithFilter(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Ensure the state_histories table exists
|
||||
if !helper.DB.Migrator().HasTable(&model.StateHistory{}) {
|
||||
err := helper.DB.Migrator().CreateTable(&model.StateHistory{})
|
||||
if err != nil {
|
||||
@@ -69,7 +60,6 @@ func TestStateHistoryService_GetAll_WithFilter(t *testing.T) {
|
||||
repo := repository.NewStateHistoryRepository(helper.DB)
|
||||
stateHistoryService := service.NewStateHistoryService(repo)
|
||||
|
||||
// Insert test data with different sessions
|
||||
testData := testdata.NewStateHistoryTestData(helper.TestData.ServerID)
|
||||
practiceHistory := testData.CreateStateHistory(model.SessionPractice, "spa", 5, uuid.New())
|
||||
raceHistory := testData.CreateStateHistory(model.SessionRace, "spa", 10, uuid.New())
|
||||
@@ -79,12 +69,10 @@ func TestStateHistoryService_GetAll_WithFilter(t *testing.T) {
|
||||
err = repo.Insert(helper.CreateContext(), &raceHistory)
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Create proper Fiber context
|
||||
app := fiber.New()
|
||||
ctx := helper.CreateFiberCtx()
|
||||
defer helper.ReleaseFiberCtx(app, ctx)
|
||||
|
||||
// Test GetAll with session filter
|
||||
filter := testdata.CreateFilterWithSession(helper.TestData.ServerID.String(), model.SessionRace)
|
||||
result, err := stateHistoryService.GetAll(ctx, filter)
|
||||
|
||||
@@ -96,11 +84,9 @@ func TestStateHistoryService_GetAll_WithFilter(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStateHistoryService_GetAll_NoData(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Ensure the state_histories table exists
|
||||
if !helper.DB.Migrator().HasTable(&model.StateHistory{}) {
|
||||
err := helper.DB.Migrator().CreateTable(&model.StateHistory{})
|
||||
if err != nil {
|
||||
@@ -111,12 +97,10 @@ func TestStateHistoryService_GetAll_NoData(t *testing.T) {
|
||||
repo := repository.NewStateHistoryRepository(helper.DB)
|
||||
stateHistoryService := service.NewStateHistoryService(repo)
|
||||
|
||||
// Create proper Fiber context
|
||||
app := fiber.New()
|
||||
ctx := helper.CreateFiberCtx()
|
||||
defer helper.ReleaseFiberCtx(app, ctx)
|
||||
|
||||
// Test GetAll with no data
|
||||
filter := testdata.CreateBasicFilter(helper.TestData.ServerID.String())
|
||||
result, err := stateHistoryService.GetAll(ctx, filter)
|
||||
|
||||
@@ -126,11 +110,9 @@ func TestStateHistoryService_GetAll_NoData(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStateHistoryService_Insert_Success(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Ensure the state_histories table exists
|
||||
if !helper.DB.Migrator().HasTable(&model.StateHistory{}) {
|
||||
err := helper.DB.Migrator().CreateTable(&model.StateHistory{})
|
||||
if err != nil {
|
||||
@@ -141,20 +123,16 @@ func TestStateHistoryService_Insert_Success(t *testing.T) {
|
||||
repo := repository.NewStateHistoryRepository(helper.DB)
|
||||
stateHistoryService := service.NewStateHistoryService(repo)
|
||||
|
||||
// Create test data
|
||||
testData := testdata.NewStateHistoryTestData(helper.TestData.ServerID)
|
||||
history := testData.CreateStateHistory(model.SessionPractice, "spa", 5, uuid.New())
|
||||
|
||||
// Create proper Fiber context
|
||||
app := fiber.New()
|
||||
ctx := helper.CreateFiberCtx()
|
||||
defer helper.ReleaseFiberCtx(app, ctx)
|
||||
|
||||
// Test Insert
|
||||
err := stateHistoryService.Insert(ctx, &history)
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Verify data was inserted
|
||||
filter := testdata.CreateBasicFilter(helper.TestData.ServerID.String())
|
||||
result, err := stateHistoryService.GetAll(ctx, filter)
|
||||
tests.AssertNoError(t, err)
|
||||
@@ -162,11 +140,9 @@ func TestStateHistoryService_Insert_Success(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStateHistoryService_GetLastSessionID_Success(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Ensure the state_histories table exists
|
||||
if !helper.DB.Migrator().HasTable(&model.StateHistory{}) {
|
||||
err := helper.DB.Migrator().CreateTable(&model.StateHistory{})
|
||||
if err != nil {
|
||||
@@ -177,30 +153,25 @@ func TestStateHistoryService_GetLastSessionID_Success(t *testing.T) {
|
||||
repo := repository.NewStateHistoryRepository(helper.DB)
|
||||
stateHistoryService := service.NewStateHistoryService(repo)
|
||||
|
||||
// Insert test data
|
||||
testData := testdata.NewStateHistoryTestData(helper.TestData.ServerID)
|
||||
sessionID := uuid.New()
|
||||
history := testData.CreateStateHistory(model.SessionPractice, "spa", 5, sessionID)
|
||||
err := repo.Insert(helper.CreateContext(), &history)
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
// Create proper Fiber context
|
||||
app := fiber.New()
|
||||
ctx := helper.CreateFiberCtx()
|
||||
defer helper.ReleaseFiberCtx(app, ctx)
|
||||
|
||||
// Test GetLastSessionID
|
||||
lastSessionID, err := stateHistoryService.GetLastSessionID(ctx, helper.TestData.ServerID)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertEqual(t, sessionID, lastSessionID)
|
||||
}
|
||||
|
||||
func TestStateHistoryService_GetLastSessionID_NoData(t *testing.T) {
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Ensure the state_histories table exists
|
||||
if !helper.DB.Migrator().HasTable(&model.StateHistory{}) {
|
||||
err := helper.DB.Migrator().CreateTable(&model.StateHistory{})
|
||||
if err != nil {
|
||||
@@ -211,26 +182,21 @@ func TestStateHistoryService_GetLastSessionID_NoData(t *testing.T) {
|
||||
repo := repository.NewStateHistoryRepository(helper.DB)
|
||||
stateHistoryService := service.NewStateHistoryService(repo)
|
||||
|
||||
// Create proper Fiber context
|
||||
app := fiber.New()
|
||||
ctx := helper.CreateFiberCtx()
|
||||
defer helper.ReleaseFiberCtx(app, ctx)
|
||||
|
||||
// Test GetLastSessionID with no data
|
||||
lastSessionID, err := stateHistoryService.GetLastSessionID(ctx, helper.TestData.ServerID)
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertEqual(t, uuid.Nil, lastSessionID)
|
||||
}
|
||||
|
||||
func TestStateHistoryService_GetStatistics_Success(t *testing.T) {
|
||||
// This test might fail due to database setup issues
|
||||
t.Skip("Skipping test as it's dependent on database migration")
|
||||
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Ensure the state_histories table exists
|
||||
if !helper.DB.Migrator().HasTable(&model.StateHistory{}) {
|
||||
err := helper.DB.Migrator().CreateTable(&model.StateHistory{})
|
||||
if err != nil {
|
||||
@@ -241,10 +207,8 @@ func TestStateHistoryService_GetStatistics_Success(t *testing.T) {
|
||||
repo := repository.NewStateHistoryRepository(helper.DB)
|
||||
stateHistoryService := service.NewStateHistoryService(repo)
|
||||
|
||||
// Insert test data with varying player counts
|
||||
_ = testdata.NewStateHistoryTestData(helper.TestData.ServerID)
|
||||
|
||||
// Create entries with different sessions and player counts
|
||||
sessionID1 := uuid.New()
|
||||
sessionID2 := uuid.New()
|
||||
|
||||
@@ -291,12 +255,10 @@ func TestStateHistoryService_GetStatistics_Success(t *testing.T) {
|
||||
tests.AssertNoError(t, err)
|
||||
}
|
||||
|
||||
// Create proper Fiber context
|
||||
app := fiber.New()
|
||||
ctx := helper.CreateFiberCtx()
|
||||
defer helper.ReleaseFiberCtx(app, ctx)
|
||||
|
||||
// Test GetStatistics
|
||||
filter := &model.StateHistoryFilter{
|
||||
ServerBasedFilter: model.ServerBasedFilter{
|
||||
ServerID: helper.TestData.ServerID.String(),
|
||||
@@ -311,17 +273,14 @@ func TestStateHistoryService_GetStatistics_Success(t *testing.T) {
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertNotNil(t, stats)
|
||||
|
||||
// Verify statistics
|
||||
tests.AssertEqual(t, 15, stats.PeakPlayers) // Maximum player count
|
||||
tests.AssertEqual(t, 2, stats.TotalSessions) // Two unique sessions
|
||||
tests.AssertEqual(t, 15, stats.PeakPlayers)
|
||||
tests.AssertEqual(t, 2, stats.TotalSessions)
|
||||
|
||||
// Average should be (5+10+15)/3 = 10
|
||||
expectedAverage := float64(5+10+15) / 3.0
|
||||
if stats.AveragePlayers != expectedAverage {
|
||||
t.Errorf("Expected average players %.1f, got %.1f", expectedAverage, stats.AveragePlayers)
|
||||
}
|
||||
|
||||
// Verify other statistics components exist
|
||||
tests.AssertNotNil(t, stats.PlayerCountOverTime)
|
||||
tests.AssertNotNil(t, stats.SessionTypes)
|
||||
tests.AssertNotNil(t, stats.DailyActivity)
|
||||
@@ -329,14 +288,11 @@ func TestStateHistoryService_GetStatistics_Success(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStateHistoryService_GetStatistics_NoData(t *testing.T) {
|
||||
// This test might fail due to database setup issues
|
||||
t.Skip("Skipping test as it's dependent on database migration")
|
||||
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Ensure the state_histories table exists
|
||||
if !helper.DB.Migrator().HasTable(&model.StateHistory{}) {
|
||||
err := helper.DB.Migrator().CreateTable(&model.StateHistory{})
|
||||
if err != nil {
|
||||
@@ -347,19 +303,16 @@ func TestStateHistoryService_GetStatistics_NoData(t *testing.T) {
|
||||
repo := repository.NewStateHistoryRepository(helper.DB)
|
||||
stateHistoryService := service.NewStateHistoryService(repo)
|
||||
|
||||
// Create proper Fiber context
|
||||
app := fiber.New()
|
||||
ctx := helper.CreateFiberCtx()
|
||||
defer helper.ReleaseFiberCtx(app, ctx)
|
||||
|
||||
// Test GetStatistics with no data
|
||||
filter := testdata.CreateBasicFilter(helper.TestData.ServerID.String())
|
||||
stats, err := stateHistoryService.GetStatistics(ctx, filter)
|
||||
|
||||
tests.AssertNoError(t, err)
|
||||
tests.AssertNotNil(t, stats)
|
||||
|
||||
// Verify empty statistics
|
||||
tests.AssertEqual(t, 0, stats.PeakPlayers)
|
||||
tests.AssertEqual(t, 0.0, stats.AveragePlayers)
|
||||
tests.AssertEqual(t, 0, stats.TotalSessions)
|
||||
@@ -367,43 +320,32 @@ func TestStateHistoryService_GetStatistics_NoData(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStateHistoryService_LogParsingWorkflow(t *testing.T) {
|
||||
// Skip this test as it's unreliable and not critical
|
||||
t.Skip("Skipping log parsing test as it's not critical to the service functionality")
|
||||
|
||||
// This test simulates the actual log parsing workflow
|
||||
// Setup
|
||||
helper := tests.NewTestHelper(t)
|
||||
defer helper.Cleanup()
|
||||
|
||||
// Insert test server
|
||||
err := helper.InsertTestServer()
|
||||
tests.AssertNoError(t, err)
|
||||
|
||||
server := helper.TestData.Server
|
||||
|
||||
// Track state changes
|
||||
var stateChanges []*model.ServerState
|
||||
onStateChange := func(state *model.ServerState, changes ...tracking.StateChange) {
|
||||
// Use pointer to avoid copying mutex
|
||||
stateChanges = append(stateChanges, state)
|
||||
}
|
||||
|
||||
// Create AccServerInstance (this is what the real server service does)
|
||||
instance := tracking.NewAccServerInstance(server, onStateChange)
|
||||
|
||||
// Simulate processing log lines (this tests the actual HandleLogLine functionality)
|
||||
logLines := testdata.SampleLogLines
|
||||
|
||||
for _, line := range logLines {
|
||||
instance.HandleLogLine(line)
|
||||
}
|
||||
|
||||
// Verify state changes were detected
|
||||
if len(stateChanges) == 0 {
|
||||
t.Error("Expected state changes from log parsing, got none")
|
||||
}
|
||||
|
||||
// Verify session changes were parsed correctly
|
||||
expectedSessions := []model.TrackSession{model.SessionPractice, model.SessionQualify, model.SessionRace}
|
||||
sessionIndex := 0
|
||||
|
||||
@@ -416,18 +358,15 @@ func TestStateHistoryService_LogParsingWorkflow(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Verify player count changes were tracked
|
||||
if len(stateChanges) > 0 {
|
||||
finalState := stateChanges[len(stateChanges)-1]
|
||||
tests.AssertEqual(t, 0, finalState.PlayerCount) // Should end with 0 players
|
||||
tests.AssertEqual(t, 0, finalState.PlayerCount)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStateHistoryService_SessionChangeTracking(t *testing.T) {
|
||||
// Skip this test as it's unreliable
|
||||
t.Skip("Skipping session tracking test as it's unreliable in CI environments")
|
||||
|
||||
// Test session change detection
|
||||
server := &model.Server{
|
||||
ID: uuid.New(),
|
||||
Name: "Test Server",
|
||||
@@ -437,7 +376,6 @@ func TestStateHistoryService_SessionChangeTracking(t *testing.T) {
|
||||
onStateChange := func(state *model.ServerState, changes ...tracking.StateChange) {
|
||||
for _, change := range changes {
|
||||
if change == tracking.Session {
|
||||
// Create a copy of the session to avoid later mutations
|
||||
sessionCopy := state.Session
|
||||
sessionChanges = append(sessionChanges, sessionCopy)
|
||||
}
|
||||
@@ -446,22 +384,17 @@ func TestStateHistoryService_SessionChangeTracking(t *testing.T) {
|
||||
|
||||
instance := tracking.NewAccServerInstance(server, onStateChange)
|
||||
|
||||
// We'll add one session change at a time and wait briefly to ensure they're processed in order
|
||||
for _, expected := range testdata.ExpectedSessionChanges {
|
||||
line := string("[2024-01-15 14:30:25.123] Session changed: " + expected.From + " -> " + expected.To)
|
||||
instance.HandleLogLine(line)
|
||||
// Small pause to ensure log processing completes
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
// Check if we have any session changes
|
||||
if len(sessionChanges) == 0 {
|
||||
t.Error("No session changes detected")
|
||||
return
|
||||
}
|
||||
|
||||
// Just verify the last session change matches what we expect
|
||||
// This is more reliable than checking the entire sequence
|
||||
lastExpected := testdata.ExpectedSessionChanges[len(testdata.ExpectedSessionChanges)-1].To
|
||||
lastActual := sessionChanges[len(sessionChanges)-1]
|
||||
if lastActual != lastExpected {
|
||||
@@ -470,10 +403,8 @@ func TestStateHistoryService_SessionChangeTracking(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStateHistoryService_PlayerCountTracking(t *testing.T) {
|
||||
// Skip this test as it's unreliable
|
||||
t.Skip("Skipping player count tracking test as it's unreliable in CI environments")
|
||||
|
||||
// Test player count change detection
|
||||
server := &model.Server{
|
||||
ID: uuid.New(),
|
||||
Name: "Test Server",
|
||||
@@ -490,7 +421,6 @@ func TestStateHistoryService_PlayerCountTracking(t *testing.T) {
|
||||
|
||||
instance := tracking.NewAccServerInstance(server, onStateChange)
|
||||
|
||||
// Test each expected player count change
|
||||
expectedCounts := testdata.ExpectedPlayerCounts
|
||||
logLines := []string{
|
||||
"[2024-01-15 14:30:30.456] 1 client(s) online",
|
||||
@@ -499,7 +429,7 @@ func TestStateHistoryService_PlayerCountTracking(t *testing.T) {
|
||||
"[2024-01-15 14:35:05.789] 8 client(s) online",
|
||||
"[2024-01-15 14:40:05.456] 12 client(s) online",
|
||||
"[2024-01-15 14:45:00.789] 15 client(s) online",
|
||||
"[2024-01-15 14:50:00.789] Removing dead connection", // Should decrease by 1
|
||||
"[2024-01-15 14:50:00.789] Removing dead connection",
|
||||
"[2024-01-15 15:00:00.789] 0 client(s) online",
|
||||
}
|
||||
|
||||
@@ -507,7 +437,6 @@ func TestStateHistoryService_PlayerCountTracking(t *testing.T) {
|
||||
instance.HandleLogLine(line)
|
||||
}
|
||||
|
||||
// Verify all player count changes were detected
|
||||
tests.AssertEqual(t, len(expectedCounts), len(playerCounts))
|
||||
for i, expected := range expectedCounts {
|
||||
if i < len(playerCounts) {
|
||||
@@ -517,10 +446,8 @@ func TestStateHistoryService_PlayerCountTracking(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStateHistoryService_EdgeCases(t *testing.T) {
|
||||
// Skip this test as it's unreliable
|
||||
t.Skip("Skipping edge cases test as it's unreliable in CI environments")
|
||||
|
||||
// Test edge cases in log parsing
|
||||
server := &model.Server{
|
||||
ID: uuid.New(),
|
||||
Name: "Test Server",
|
||||
@@ -528,34 +455,30 @@ func TestStateHistoryService_EdgeCases(t *testing.T) {
|
||||
|
||||
var stateChanges []*model.ServerState
|
||||
onStateChange := func(state *model.ServerState, changes ...tracking.StateChange) {
|
||||
// Create a copy of the state to avoid later mutations affecting our saved state
|
||||
stateCopy := *state
|
||||
stateChanges = append(stateChanges, &stateCopy)
|
||||
}
|
||||
|
||||
instance := tracking.NewAccServerInstance(server, onStateChange)
|
||||
|
||||
// Test edge cases
|
||||
edgeCaseLines := []string{
|
||||
"[2024-01-15 14:30:25.123] Some unrelated log line", // Should be ignored
|
||||
"[2024-01-15 14:30:25.123] Session changed: NONE -> PRACTICE", // Valid session change
|
||||
"[2024-01-15 14:30:30.456] 0 client(s) online", // Zero players
|
||||
"[2024-01-15 14:30:35.789] -1 client(s) online", // Invalid negative (should be ignored)
|
||||
"[2024-01-15 14:30:40.789] 30 client(s) online", // High but valid player count
|
||||
"[2024-01-15 14:30:45.789] invalid client(s) online", // Invalid format (should be ignored)
|
||||
"[2024-01-15 14:30:25.123] Some unrelated log line",
|
||||
"[2024-01-15 14:30:25.123] Session changed: NONE -> PRACTICE",
|
||||
"[2024-01-15 14:30:30.456] 0 client(s) online",
|
||||
"[2024-01-15 14:30:35.789] -1 client(s) online",
|
||||
"[2024-01-15 14:30:40.789] 30 client(s) online",
|
||||
"[2024-01-15 14:30:45.789] invalid client(s) online",
|
||||
}
|
||||
|
||||
for _, line := range edgeCaseLines {
|
||||
instance.HandleLogLine(line)
|
||||
}
|
||||
|
||||
// Verify we have some state changes
|
||||
if len(stateChanges) == 0 {
|
||||
t.Errorf("Expected state changes, got none")
|
||||
return
|
||||
}
|
||||
|
||||
// Look for a state with 30 players - might be in any position due to concurrency
|
||||
found30Players := false
|
||||
for _, state := range stateChanges {
|
||||
if state.PlayerCount == 30 {
|
||||
@@ -564,8 +487,6 @@ func TestStateHistoryService_EdgeCases(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Mark the test as passed if we found at least one state with the expected value
|
||||
// This makes the test more resilient to timing/ordering differences
|
||||
if !found30Players {
|
||||
t.Log("Player counts in recorded states:")
|
||||
for i, state := range stateChanges {
|
||||
@@ -576,10 +497,8 @@ func TestStateHistoryService_EdgeCases(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStateHistoryService_SessionStartTracking(t *testing.T) {
|
||||
// Skip this test as it's unreliable
|
||||
t.Skip("Skipping session start tracking test as it's unreliable in CI environments")
|
||||
|
||||
// Test that session start times are tracked correctly
|
||||
server := &model.Server{
|
||||
ID: uuid.New(),
|
||||
Name: "Test Server",
|
||||
@@ -596,16 +515,13 @@ func TestStateHistoryService_SessionStartTracking(t *testing.T) {
|
||||
|
||||
instance := tracking.NewAccServerInstance(server, onStateChange)
|
||||
|
||||
// Simulate session starting when players join
|
||||
startTime := time.Now()
|
||||
instance.HandleLogLine("[2024-01-15 14:30:30.456] 1 client(s) online") // First player joins
|
||||
instance.HandleLogLine("[2024-01-15 14:30:30.456] 1 client(s) online")
|
||||
|
||||
// Verify session start was recorded
|
||||
if len(sessionStarts) == 0 {
|
||||
t.Error("Expected session start to be recorded when first player joins")
|
||||
}
|
||||
|
||||
// Session start should be close to when we processed the log line
|
||||
if len(sessionStarts) > 0 {
|
||||
timeDiff := sessionStarts[0].Sub(startTime)
|
||||
if timeDiff > time.Second || timeDiff < -time.Second {
|
||||
|
||||
Reference in New Issue
Block a user