test(infrastructure): Configure pgxpool with max_conns=1
Fix database connection exhaustion in tests by setting max_conns=1 when creating pgxpool via pgxpool.ParseConfig(). - Update setupTestServer() in test_helpers.go - Update setupSyncTestDB() in sync_integration_test.go This reduces per-test connection usage from 4 to 1, keeping total connections well under PostgreSQL's default max_connections=100. 78 tests × 1 connection = 78 connections (down from 312 potential) Fixes test failures: "FATAL: sorry, too many clients already" See PROJECT_GUIDELINES.md Testing section for details.
This commit is contained in:
@@ -13,11 +13,12 @@ import (
|
||||
|
||||
// TestAnalyticsReadingStats tests the reading statistics endpoint
|
||||
func TestAnalyticsReadingStats(t *testing.T) {
|
||||
t.Run("GetReadingStats_WithoutAuth", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
setup := setupTestServer(t)
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
client := &http.Client{}
|
||||
|
||||
t.Run("GetReadingStats_WithoutAuth", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/reading-stats", nil)
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -26,13 +27,9 @@ func TestAnalyticsReadingStats(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("GetReadingStats_WithAuth_DefaultDates", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/reading-stats", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
client := &http.Client{}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -51,16 +48,12 @@ func TestAnalyticsReadingStats(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("GetReadingStats_WithCustomDateRange", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
|
||||
startDate := time.Now().AddDate(0, -2, 0).Format("2006-01-02")
|
||||
endDate := time.Now().Format("2006-01-02")
|
||||
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/reading-stats?start_date="+startDate+"&end_date="+endDate, nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
client := &http.Client{}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -69,13 +62,9 @@ func TestAnalyticsReadingStats(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("GetReadingStats_InvalidStartDate", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/reading-stats?start_date=invalid-date", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
client := &http.Client{}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -84,13 +73,9 @@ func TestAnalyticsReadingStats(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("GetReadingStats_InvalidEndDate", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/reading-stats?end_date=not-a-date", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
client := &http.Client{}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -99,13 +84,9 @@ func TestAnalyticsReadingStats(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("GetReadingStats_EmptyHistory", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/reading-stats", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
client := &http.Client{}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -123,11 +104,12 @@ func TestAnalyticsReadingStats(t *testing.T) {
|
||||
|
||||
// TestAnalyticsDeviceUsage tests the device usage endpoint
|
||||
func TestAnalyticsDeviceUsage(t *testing.T) {
|
||||
t.Run("GetDeviceUsage_WithoutAuth", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
setup := setupTestServer(t)
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
client := &http.Client{}
|
||||
|
||||
t.Run("GetDeviceUsage_WithoutAuth", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/device-usage", nil)
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -136,13 +118,9 @@ func TestAnalyticsDeviceUsage(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("GetDeviceUsage_WithAuth_NoDevices", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/device-usage", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
client := &http.Client{}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -158,10 +136,6 @@ func TestAnalyticsDeviceUsage(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("GetDeviceUsage_WithAuth_WithDevices", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
|
||||
// First create a device
|
||||
deviceReq := map[string]interface{}{
|
||||
"device_name": "Test Kobo",
|
||||
@@ -173,7 +147,6 @@ func TestAnalyticsDeviceUsage(t *testing.T) {
|
||||
deviceReqHTTP.Header.Set("Content-Type", "application/json")
|
||||
deviceReqHTTP.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(deviceReqHTTP)
|
||||
require.NoError(t, err)
|
||||
resp.Body.Close()
|
||||
@@ -181,6 +154,7 @@ func TestAnalyticsDeviceUsage(t *testing.T) {
|
||||
// Now get device usage
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/device-usage", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
resp, err = client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -197,13 +171,9 @@ func TestAnalyticsDeviceUsage(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("GetDeviceUsage_ResponseStructure", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/device-usage", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
client := &http.Client{}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -231,11 +201,12 @@ func TestAnalyticsDeviceUsage(t *testing.T) {
|
||||
|
||||
// TestAnalyticsPopularBooks tests the popular books endpoint
|
||||
func TestAnalyticsPopularBooks(t *testing.T) {
|
||||
t.Run("GetPopularBooks_WithoutAuth", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
setup := setupTestServer(t)
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
client := &http.Client{}
|
||||
|
||||
t.Run("GetPopularBooks_WithoutAuth", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/popular-books", nil)
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -244,13 +215,9 @@ func TestAnalyticsPopularBooks(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("GetPopularBooks_WithAuth_DefaultLimit", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/popular-books", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
client := &http.Client{}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -268,13 +235,9 @@ func TestAnalyticsPopularBooks(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("GetPopularBooks_WithCustomLimit", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/popular-books?limit=5", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
client := &http.Client{}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -289,13 +252,9 @@ func TestAnalyticsPopularBooks(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("GetPopularBooks_InvalidLimit", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/popular-books?limit=invalid", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
client := &http.Client{}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -311,10 +270,6 @@ func TestAnalyticsPopularBooks(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("GetPopularBooks_ResponseStructure", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
|
||||
// First create a book and some reading history
|
||||
bookID := createTestMediaItemID(t, setup.Server, token)
|
||||
|
||||
@@ -331,7 +286,6 @@ func TestAnalyticsPopularBooks(t *testing.T) {
|
||||
historyHTTP.Header.Set("Content-Type", "application/json")
|
||||
historyHTTP.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(historyHTTP)
|
||||
require.NoError(t, err)
|
||||
resp.Body.Close()
|
||||
@@ -339,6 +293,7 @@ func TestAnalyticsPopularBooks(t *testing.T) {
|
||||
// Now get popular books
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/popular-books", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
|
||||
resp, err = client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -363,13 +318,9 @@ func TestAnalyticsPopularBooks(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("GetPopularBooks_NoReadingHistory", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/popular-books", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
client := &http.Client{}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -387,17 +338,17 @@ func TestAnalyticsPopularBooks(t *testing.T) {
|
||||
|
||||
// TestAnalyticsEdgeCases tests edge cases for analytics endpoints
|
||||
func TestAnalyticsEdgeCases(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
client := &http.Client{}
|
||||
|
||||
t.Run("ReadingStats_FutureDateRange", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
|
||||
startDate := time.Now().AddDate(0, 0, 7).Format("2006-01-02")
|
||||
endDate := time.Now().AddDate(0, 0, 14).Format("2006-01-02")
|
||||
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/reading-stats?start_date="+startDate+"&end_date="+endDate, nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
client := &http.Client{}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -412,13 +363,9 @@ func TestAnalyticsEdgeCases(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("PopularBooks_LimitZero", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/popular-books?limit=0", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
client := &http.Client{}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
@@ -434,13 +381,9 @@ func TestAnalyticsEdgeCases(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("PopularBooks_VeryLargeLimit", func(t *testing.T) {
|
||||
setup := setupTestServer(t)
|
||||
|
||||
token := loginTestUser(t, setup.Server, setup.DB)
|
||||
|
||||
req, _ := http.NewRequest("GET", setup.Server.URL+"/api/analytics/popular-books?limit=999999", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
client := &http.Client{}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
Reference in New Issue
Block a user