mirror of
https://github.com/lukaszraczylo/graphql-monitoring-proxy.git
synced 2026-10-18 06:17:56 +00:00
improvements mid may 2025 (#24)
* General improvements and bug fixes. * Improve tests coverage. * fixup! Improve tests coverage. * Update README.md with latest changes. * Fix the uint32 * Resolve issue with race condition for logging. * fixup! Merge remote-tracking branch 'origin/main' into improvements-mid-apr-2025 * Fix the test of the rate limiter * Add default ratelimit.json file * Update dependencies. * Significant refactor. * fixup! Significant refactor. * fixup! Merge remote-tracking branch 'origin/main' into improvements-mid-apr-2025 * fixup! fixup! Merge remote-tracking branch 'origin/main' into improvements-mid-apr-2025 * fixup! fixup! fixup! Merge remote-tracking branch 'origin/main' into improvements-mid-apr-2025 * fixup! fixup! fixup! fixup! fixup! Merge remote-tracking branch 'origin/main' into improvements-mid-apr-2025 * fixup! fixup! fixup! fixup! fixup! fixup! Merge remote-tracking branch 'origin/main' into improvements-mid-apr-2025 * fixup! fixup! fixup! fixup! fixup! fixup! fixup! Merge remote-tracking branch 'origin/main' into improvements-mid-apr-2025 * fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! Merge remote-tracking branch 'origin/main' into improvements-mid-apr-2025 * fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! Merge remote-tracking branch 'origin/main' into improvements-mid-apr-2025 * fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! Merge remote-tracking branch 'origin/main' into improvements-mid-apr-2025
This commit is contained in:
+88
-79
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -14,6 +15,7 @@ import (
|
||||
"github.com/gofrs/flock"
|
||||
libpack_cache "github.com/lukaszraczylo/graphql-monitoring-proxy/cache"
|
||||
libpack_logger "github.com/lukaszraczylo/graphql-monitoring-proxy/logging"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
@@ -38,24 +40,24 @@ func (suite *Tests) Test_apiBanUser() {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := app.Test(req)
|
||||
assert.NoError(err)
|
||||
assert.Equal(200, resp.StatusCode)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Equal(suite.T(), 200, resp.StatusCode)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
assert.NoError(err)
|
||||
assert.Contains(string(body), "OK: user banned")
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Contains(suite.T(), string(body), "OK: user banned")
|
||||
|
||||
// Verify user was added to banned users map
|
||||
bannedUsersIDsMutex.RLock()
|
||||
reason, exists := bannedUsersIDs["test-user-123"]
|
||||
bannedUsersIDsMutex.RUnlock()
|
||||
|
||||
assert.True(exists)
|
||||
assert.Equal("testing", reason)
|
||||
assert.True(suite.T(), exists)
|
||||
assert.Equal(suite.T(), "testing", reason)
|
||||
|
||||
// Verify file was created
|
||||
_, err = os.Stat(cfg.Api.BannedUsersFile)
|
||||
assert.NoError(err)
|
||||
assert.NoError(suite.T(), err)
|
||||
})
|
||||
|
||||
// Test missing user_id
|
||||
@@ -65,12 +67,12 @@ func (suite *Tests) Test_apiBanUser() {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := app.Test(req)
|
||||
assert.NoError(err)
|
||||
assert.Equal(400, resp.StatusCode)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Equal(suite.T(), 400, resp.StatusCode)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
assert.NoError(err)
|
||||
assert.Contains(string(body), "user_id and reason are required")
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Contains(suite.T(), string(body), "user_id and reason are required")
|
||||
})
|
||||
|
||||
// Test missing reason
|
||||
@@ -80,12 +82,12 @@ func (suite *Tests) Test_apiBanUser() {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := app.Test(req)
|
||||
assert.NoError(err)
|
||||
assert.Equal(400, resp.StatusCode)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Equal(suite.T(), 400, resp.StatusCode)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
assert.NoError(err)
|
||||
assert.Contains(string(body), "user_id and reason are required")
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Contains(suite.T(), string(body), "user_id and reason are required")
|
||||
})
|
||||
|
||||
// Test invalid JSON
|
||||
@@ -95,17 +97,17 @@ func (suite *Tests) Test_apiBanUser() {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := app.Test(req)
|
||||
assert.NoError(err)
|
||||
assert.Equal(400, resp.StatusCode)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Equal(suite.T(), 400, resp.StatusCode)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
assert.NoError(err)
|
||||
assert.Contains(string(body), "Invalid request payload")
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Contains(suite.T(), string(body), "Invalid request payload")
|
||||
})
|
||||
|
||||
// Cleanup
|
||||
os.Remove(cfg.Api.BannedUsersFile)
|
||||
os.Remove(fmt.Sprintf("%s.lock", cfg.Api.BannedUsersFile))
|
||||
_ = os.Remove(cfg.Api.BannedUsersFile)
|
||||
_ = os.Remove(fmt.Sprintf("%s.lock", cfg.Api.BannedUsersFile))
|
||||
}
|
||||
|
||||
func (suite *Tests) Test_apiUnbanUser() {
|
||||
@@ -130,19 +132,19 @@ func (suite *Tests) Test_apiUnbanUser() {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := app.Test(req)
|
||||
assert.NoError(err)
|
||||
assert.Equal(200, resp.StatusCode)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Equal(suite.T(), 200, resp.StatusCode)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
assert.NoError(err)
|
||||
assert.Contains(string(body), "OK: user unbanned")
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Contains(suite.T(), string(body), "OK: user unbanned")
|
||||
|
||||
// Verify user was removed from banned users map
|
||||
bannedUsersIDsMutex.RLock()
|
||||
_, exists := bannedUsersIDs["test-user-123"]
|
||||
bannedUsersIDsMutex.RUnlock()
|
||||
|
||||
assert.False(exists)
|
||||
assert.False(suite.T(), exists)
|
||||
})
|
||||
|
||||
// Test missing user_id
|
||||
@@ -152,12 +154,12 @@ func (suite *Tests) Test_apiUnbanUser() {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := app.Test(req)
|
||||
assert.NoError(err)
|
||||
assert.Equal(400, resp.StatusCode)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Equal(suite.T(), 400, resp.StatusCode)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
assert.NoError(err)
|
||||
assert.Contains(string(body), "user_id is required")
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Contains(suite.T(), string(body), "user_id is required")
|
||||
})
|
||||
|
||||
// Test invalid JSON
|
||||
@@ -167,17 +169,17 @@ func (suite *Tests) Test_apiUnbanUser() {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := app.Test(req)
|
||||
assert.NoError(err)
|
||||
assert.Equal(400, resp.StatusCode)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Equal(suite.T(), 400, resp.StatusCode)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
assert.NoError(err)
|
||||
assert.Contains(string(body), "Invalid request payload")
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Contains(suite.T(), string(body), "Invalid request payload")
|
||||
})
|
||||
|
||||
// Cleanup
|
||||
os.Remove(cfg.Api.BannedUsersFile)
|
||||
os.Remove(fmt.Sprintf("%s.lock", cfg.Api.BannedUsersFile))
|
||||
_ = os.Remove(cfg.Api.BannedUsersFile)
|
||||
_ = os.Remove(fmt.Sprintf("%s.lock", cfg.Api.BannedUsersFile))
|
||||
}
|
||||
|
||||
func (suite *Tests) Test_apiClearCache() {
|
||||
@@ -205,16 +207,16 @@ func (suite *Tests) Test_apiClearCache() {
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/cache-clear", nil)
|
||||
|
||||
resp, err := app.Test(req)
|
||||
assert.NoError(err)
|
||||
assert.Equal(200, resp.StatusCode)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Equal(suite.T(), 200, resp.StatusCode)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
assert.NoError(err)
|
||||
assert.Contains(string(body), "OK: cache cleared")
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Contains(suite.T(), string(body), "OK: cache cleared")
|
||||
|
||||
// Verify cache was cleared
|
||||
stats := libpack_cache.GetCacheStats()
|
||||
assert.Equal(int64(0), stats.CachedQueries)
|
||||
assert.Equal(suite.T(), int64(0), stats.CachedQueries)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -245,16 +247,16 @@ func (suite *Tests) Test_apiCacheStats() {
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/cache-stats", nil)
|
||||
|
||||
resp, err := app.Test(req)
|
||||
assert.NoError(err)
|
||||
assert.Equal(200, resp.StatusCode)
|
||||
assert.NoError(suite.T(), err)
|
||||
assert.Equal(suite.T(), 200, resp.StatusCode)
|
||||
|
||||
var stats libpack_cache.CacheStats
|
||||
err = json.NewDecoder(resp.Body).Decode(&stats)
|
||||
assert.NoError(err)
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
assert.Equal(int64(2), stats.CachedQueries)
|
||||
assert.Equal(int64(1), stats.CacheHits)
|
||||
assert.Equal(int64(1), stats.CacheMisses)
|
||||
assert.Equal(suite.T(), int64(2), stats.CachedQueries)
|
||||
assert.Equal(suite.T(), int64(1), stats.CacheHits)
|
||||
assert.Equal(suite.T(), int64(1), stats.CacheMisses)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -274,8 +276,8 @@ func (suite *Tests) Test_checkIfUserIsBanned() {
|
||||
bannedUsersIDs = make(map[string]string)
|
||||
|
||||
isBanned := checkIfUserIsBanned(ctx, "non-banned-user")
|
||||
assert.False(isBanned)
|
||||
assert.Equal(200, ctx.Response().StatusCode())
|
||||
assert.False(suite.T(), isBanned)
|
||||
assert.Equal(suite.T(), 200, ctx.Response().StatusCode())
|
||||
})
|
||||
|
||||
// Test with banned user
|
||||
@@ -284,8 +286,8 @@ func (suite *Tests) Test_checkIfUserIsBanned() {
|
||||
bannedUsersIDs["banned-user"] = "testing"
|
||||
|
||||
isBanned := checkIfUserIsBanned(ctx, "banned-user")
|
||||
assert.True(isBanned)
|
||||
assert.Equal(403, ctx.Response().StatusCode())
|
||||
assert.True(suite.T(), isBanned)
|
||||
assert.Equal(suite.T(), 403, ctx.Response().StatusCode())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -299,17 +301,17 @@ func (suite *Tests) Test_loadBannedUsers() {
|
||||
// Test with non-existent file (should create it)
|
||||
suite.Run("non-existent file", func() {
|
||||
// Remove file if it exists
|
||||
os.Remove(cfg.Api.BannedUsersFile)
|
||||
_ = os.Remove(cfg.Api.BannedUsersFile)
|
||||
|
||||
bannedUsersIDs = make(map[string]string)
|
||||
loadBannedUsers()
|
||||
|
||||
// Verify file was created
|
||||
_, err := os.Stat(cfg.Api.BannedUsersFile)
|
||||
assert.NoError(err)
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
// Verify banned users map is empty
|
||||
assert.Equal(0, len(bannedUsersIDs))
|
||||
assert.Equal(suite.T(), 0, len(bannedUsersIDs))
|
||||
})
|
||||
|
||||
// Test with existing file
|
||||
@@ -320,34 +322,34 @@ func (suite *Tests) Test_loadBannedUsers() {
|
||||
"test-user-2": "reason 2",
|
||||
}
|
||||
data, _ := json.Marshal(testData)
|
||||
err := os.WriteFile(cfg.Api.BannedUsersFile, data, 0644)
|
||||
assert.NoError(err)
|
||||
err := os.WriteFile(cfg.Api.BannedUsersFile, data, 0o644)
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
bannedUsersIDs = make(map[string]string)
|
||||
loadBannedUsers()
|
||||
|
||||
// Verify banned users map was loaded
|
||||
assert.Equal(2, len(bannedUsersIDs))
|
||||
assert.Equal("reason 1", bannedUsersIDs["test-user-1"])
|
||||
assert.Equal("reason 2", bannedUsersIDs["test-user-2"])
|
||||
assert.Equal(suite.T(), 2, len(bannedUsersIDs))
|
||||
assert.Equal(suite.T(), "reason 1", bannedUsersIDs["test-user-1"])
|
||||
assert.Equal(suite.T(), "reason 2", bannedUsersIDs["test-user-2"])
|
||||
})
|
||||
|
||||
// Test with invalid JSON
|
||||
suite.Run("invalid JSON", func() {
|
||||
// Create file with invalid JSON
|
||||
err := os.WriteFile(cfg.Api.BannedUsersFile, []byte("{invalid json}"), 0644)
|
||||
assert.NoError(err)
|
||||
err := os.WriteFile(cfg.Api.BannedUsersFile, []byte("{invalid json}"), 0o644)
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
bannedUsersIDs = make(map[string]string)
|
||||
loadBannedUsers()
|
||||
|
||||
// Verify banned users map is empty (load failed)
|
||||
assert.Equal(0, len(bannedUsersIDs))
|
||||
assert.Equal(suite.T(), 0, len(bannedUsersIDs))
|
||||
})
|
||||
|
||||
// Cleanup
|
||||
os.Remove(cfg.Api.BannedUsersFile)
|
||||
os.Remove(fmt.Sprintf("%s.lock", cfg.Api.BannedUsersFile))
|
||||
_ = os.Remove(cfg.Api.BannedUsersFile)
|
||||
_ = os.Remove(fmt.Sprintf("%s.lock", cfg.Api.BannedUsersFile))
|
||||
}
|
||||
|
||||
func (suite *Tests) Test_storeBannedUsers() {
|
||||
@@ -366,24 +368,24 @@ func (suite *Tests) Test_storeBannedUsers() {
|
||||
}
|
||||
|
||||
err := storeBannedUsers()
|
||||
assert.NoError(err)
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
// Verify file was created with correct content
|
||||
data, err := os.ReadFile(cfg.Api.BannedUsersFile)
|
||||
assert.NoError(err)
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
var loadedData map[string]string
|
||||
err = json.Unmarshal(data, &loadedData)
|
||||
assert.NoError(err)
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
assert.Equal(2, len(loadedData))
|
||||
assert.Equal("reason 1", loadedData["test-user-1"])
|
||||
assert.Equal("reason 2", loadedData["test-user-2"])
|
||||
assert.Equal(suite.T(), 2, len(loadedData))
|
||||
assert.Equal(suite.T(), "reason 1", loadedData["test-user-1"])
|
||||
assert.Equal(suite.T(), "reason 2", loadedData["test-user-2"])
|
||||
})
|
||||
|
||||
// Cleanup
|
||||
os.Remove(cfg.Api.BannedUsersFile)
|
||||
os.Remove(fmt.Sprintf("%s.lock", cfg.Api.BannedUsersFile))
|
||||
_ = os.Remove(cfg.Api.BannedUsersFile)
|
||||
_ = os.Remove(fmt.Sprintf("%s.lock", cfg.Api.BannedUsersFile))
|
||||
}
|
||||
|
||||
func (suite *Tests) Test_lockFile() {
|
||||
@@ -398,13 +400,16 @@ func (suite *Tests) Test_lockFile() {
|
||||
fileLock := flock.New(lockPath)
|
||||
|
||||
err := lockFile(fileLock)
|
||||
assert.NoError(err)
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
// Verify file is locked
|
||||
assert.True(fileLock.Locked())
|
||||
assert.True(suite.T(), fileLock.Locked())
|
||||
|
||||
// Cleanup
|
||||
fileLock.Unlock()
|
||||
if err := fileLock.Unlock(); err != nil {
|
||||
// In test context, we can use assert to check the error
|
||||
assert.NoError(suite.T(), err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -420,13 +425,16 @@ func (suite *Tests) Test_lockFileRead() {
|
||||
fileLock := flock.New(lockPath)
|
||||
|
||||
err := lockFileRead(fileLock)
|
||||
assert.NoError(err)
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
// Verify file is locked - use RLocked() instead of Locked()
|
||||
assert.True(fileLock.RLocked())
|
||||
assert.True(suite.T(), fileLock.RLocked())
|
||||
|
||||
// Cleanup
|
||||
fileLock.Unlock()
|
||||
if err := fileLock.Unlock(); err != nil {
|
||||
// In test context, we can use assert to check the error
|
||||
assert.NoError(suite.T(), err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -438,6 +446,7 @@ func (suite *Tests) Test_enableApi() {
|
||||
cfg.Server.EnableApi = false
|
||||
|
||||
// This should return immediately without error
|
||||
enableApi()
|
||||
ctx := context.Background()
|
||||
enableApi(ctx)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user