added logout

This commit is contained in:
2026-01-24 15:23:28 +11:00
parent c780050f8e
commit 9497c17c30
14 changed files with 327 additions and 191 deletions

View File

@@ -27,12 +27,26 @@ func testLogger(t *testing.T) *hlog.Logger {
return logger
}
// testConfig creates a test config for testing
func testConfig() *Config {
return &Config{
ClientID: "test-client-id",
ClientSecret: "test-client-secret",
OAuthScopes: "identify+email",
RedirectPath: "/oauth/callback",
}
}
func TestNewRateLimitedClient(t *testing.T) {
logger := testLogger(t)
client := NewRateLimitedClient(logger)
cfg := testConfig()
client, err := NewAPIClient(cfg, logger, "trusted-host.example.com")
if err != nil {
t.Fatalf("NewAPIClient returned error: %v", err)
}
if client == nil {
t.Fatal("NewRateLimitedClient returned nil")
t.Fatal("NewAPIClient returned nil")
}
if client.client == nil {
t.Error("client.client is nil")
@@ -43,11 +57,21 @@ func TestNewRateLimitedClient(t *testing.T) {
if client.buckets == nil {
t.Error("client.buckets map is nil")
}
if client.cfg == nil {
t.Error("client.cfg is nil")
}
if client.trustedHost != "trusted-host.example.com" {
t.Errorf("expected trustedHost='trusted-host.example.com', got '%s'", client.trustedHost)
}
}
func TestAPIClient_Do_Success(t *testing.T) {
logger := testLogger(t)
client := NewRateLimitedClient(logger)
cfg := testConfig()
client, err := NewAPIClient(cfg, logger, "trusted-host.example.com")
if err != nil {
t.Fatalf("NewAPIClient returned error: %v", err)
}
// Mock server that returns success with rate limit headers
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -93,7 +117,11 @@ func TestAPIClient_Do_Success(t *testing.T) {
func TestAPIClient_Do_RateLimitRetrySuccess(t *testing.T) {
logger := testLogger(t)
client := NewRateLimitedClient(logger)
cfg := testConfig()
client, err := NewAPIClient(cfg, logger, "trusted-host.example.com")
if err != nil {
t.Fatalf("NewAPIClient returned error: %v", err)
}
attemptCount := 0
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -149,7 +177,11 @@ func TestAPIClient_Do_RateLimitRetrySuccess(t *testing.T) {
func TestAPIClient_Do_RateLimitRetryFails(t *testing.T) {
logger := testLogger(t)
client := NewRateLimitedClient(logger)
cfg := testConfig()
client, err := NewAPIClient(cfg, logger, "trusted-host.example.com")
if err != nil {
t.Fatalf("NewAPIClient returned error: %v", err)
}
attemptCount := 0
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -187,7 +219,11 @@ func TestAPIClient_Do_RateLimitRetryFails(t *testing.T) {
func TestAPIClient_Do_RateLimitTooLong(t *testing.T) {
logger := testLogger(t)
client := NewRateLimitedClient(logger)
cfg := testConfig()
client, err := NewAPIClient(cfg, logger, "trusted-host.example.com")
if err != nil {
t.Fatalf("NewAPIClient returned error: %v", err)
}
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Retry-After", "60") // 60 seconds > 30s cap
@@ -224,7 +260,11 @@ func TestAPIClient_Do_RateLimitTooLong(t *testing.T) {
func TestAPIClient_Do_NoRetryAfterHeader(t *testing.T) {
logger := testLogger(t)
client := NewRateLimitedClient(logger)
cfg := testConfig()
client, err := NewAPIClient(cfg, logger, "trusted-host.example.com")
if err != nil {
t.Fatalf("NewAPIClient returned error: %v", err)
}
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Return 429 but NO Retry-After header
@@ -254,7 +294,11 @@ func TestAPIClient_Do_NoRetryAfterHeader(t *testing.T) {
func TestAPIClient_UpdateRateLimit(t *testing.T) {
logger := testLogger(t)
client := NewRateLimitedClient(logger)
cfg := testConfig()
client, err := NewAPIClient(cfg, logger, "trusted-host.example.com")
if err != nil {
t.Fatalf("NewAPIClient returned error: %v", err)
}
headers := http.Header{}
headers.Set("X-RateLimit-Bucket", "global")
@@ -291,7 +335,11 @@ func TestAPIClient_UpdateRateLimit(t *testing.T) {
func TestAPIClient_WaitIfNeeded(t *testing.T) {
logger := testLogger(t)
client := NewRateLimitedClient(logger)
cfg := testConfig()
client, err := NewAPIClient(cfg, logger, "trusted-host.example.com")
if err != nil {
t.Fatalf("NewAPIClient returned error: %v", err)
}
// Set up a bucket with 0 remaining and reset in future
bucket := "test-bucket"
@@ -305,7 +353,7 @@ func TestAPIClient_WaitIfNeeded(t *testing.T) {
client.mu.Unlock()
start := time.Now()
err := client.waitIfNeeded(bucket)
err = client.waitIfNeeded(bucket)
elapsed := time.Since(start)
if err != nil {
@@ -323,7 +371,11 @@ func TestAPIClient_WaitIfNeeded(t *testing.T) {
func TestAPIClient_WaitIfNeeded_NoWait(t *testing.T) {
logger := testLogger(t)
client := NewRateLimitedClient(logger)
cfg := testConfig()
client, err := NewAPIClient(cfg, logger, "trusted-host.example.com")
if err != nil {
t.Fatalf("NewAPIClient returned error: %v", err)
}
// Set up a bucket with remaining requests
bucket := "test-bucket"
@@ -337,7 +389,7 @@ func TestAPIClient_WaitIfNeeded_NoWait(t *testing.T) {
client.mu.Unlock()
start := time.Now()
err := client.waitIfNeeded(bucket)
err = client.waitIfNeeded(bucket)
elapsed := time.Since(start)
if err != nil {
@@ -352,7 +404,11 @@ func TestAPIClient_WaitIfNeeded_NoWait(t *testing.T) {
func TestAPIClient_Do_Concurrent(t *testing.T) {
logger := testLogger(t)
client := NewRateLimitedClient(logger)
cfg := testConfig()
client, err := NewAPIClient(cfg, logger, "trusted-host.example.com")
if err != nil {
t.Fatalf("NewAPIClient returned error: %v", err)
}
requestCount := 0
var mu sync.Mutex
@@ -376,24 +432,22 @@ func TestAPIClient_Do_Concurrent(t *testing.T) {
var wg sync.WaitGroup
errors := make(chan error, 10)
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for range 10 {
wg.Go(
func() {
req, err := http.NewRequest("GET", server.URL+"/test", nil)
if err != nil {
errors <- err
return
}
req, err := http.NewRequest("GET", server.URL+"/test", nil)
if err != nil {
errors <- err
return
}
resp, err := client.Do(req)
if err != nil {
errors <- err
return
}
resp.Body.Close()
}()
resp, err := client.Do(req)
if err != nil {
errors <- err
return
}
resp.Body.Close()
})
}
wg.Wait()
@@ -430,7 +484,11 @@ func TestAPIClient_Do_Concurrent(t *testing.T) {
func TestAPIClient_ParseRetryAfter(t *testing.T) {
logger := testLogger(t)
client := NewRateLimitedClient(logger)
cfg := testConfig()
client, err := NewAPIClient(cfg, logger, "trusted-host.example.com")
if err != nil {
t.Fatalf("NewAPIClient returned error: %v", err)
}
tests := []struct {
name string