Received: from mail.netlandish.com (mail.netlandish.com [174.136.98.166]) by code.netlandish.com (Postfix) with ESMTP id 291541EE for <~netlandish/links-dev@lists.code.netlandish.com>; Wed, 12 Nov 2025 13:40:43 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=209.85.128.177; helo=mail-yw1-f177.google.com; envelope-from=peter@netlandish.com; receiver= Authentication-Results: mail.netlandish.com; dkim=pass (1024-bit key; unprotected) header.d=netlandish.com header.i=@netlandish.com header.b=MMRcUifN Received: from mail-yw1-f177.google.com (mail-yw1-f177.google.com [209.85.128.177]) by mail.netlandish.com (Postfix) with ESMTP id F18321D640A for <~netlandish/links-dev@lists.code.netlandish.com>; Wed, 12 Nov 2025 13:42:09 +0000 (UTC) Received: by mail-yw1-f177.google.com with SMTP id 00721157ae682-787be077127so8949697b3.2 for <~netlandish/links-dev@lists.code.netlandish.com>; Wed, 12 Nov 2025 05:42:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=netlandish.com; s=google; t=1762954929; x=1763559729; darn=lists.code.netlandish.com; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=lxT0doDPec+bbnyzeax/vx2j4C3u7XBiwHTTfIaV9yU=; b=MMRcUifNxacwOZPvtZk4QnSBEbwydCL+kS3VAKX2PC+iPErdGR1vpA1tXGlsQVGKG5 dB8Q7nLR1j9pZ1OdJW7q48spg3zikRprCl5GQf9tET/8ThVqhPvQc77V7o88c5qcqbp2 XHsNkzwT74ic9aFVhJ9O7Fc15fniulVBDSdrc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762954929; x=1763559729; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=lxT0doDPec+bbnyzeax/vx2j4C3u7XBiwHTTfIaV9yU=; b=CW4TtCBjcHNMgOVuCpLMBTfUubvZZmj0O9UGSDSR9c76Dk5T4IV4nb7YyT9o4YzCh8 Fdz6OCdt6w/hzvaJeZKP+sglvQy4mydFx7RORR3kbtAToo8c7CAFX2WddG8e5a0PWu/u EzU9A2UMNGg+fuELCA3LEZpuYe/EGfoSGMLno1MkRO3mXMkRfkFVyreD01xleiww2MS6 AqETlXH4xT/8T4C0+J4+XoqX/jsWBljbfRi6xRniekKgNTqgFYVkr2ADJuKiXyuSx03H rZ0mfErNnTXfGPnc18Q/VXf5NInRN6MewhCFuRAoolvQ+n8bTFtQduJmsvYzehB4Ty0V ytug== X-Gm-Message-State: AOJu0Yzds3I3xjFuyGNh5BAQOea4z4TV6LzRD4BQh5r1ey92yadIoQQ7 sm5OW+FU/WvnMuDKm0GUKbCxz/ixH12psiS0N3v0xGTzwFTSXFAusKSHjRkbjj+jbGj1WR/F+xq qIOMdp9k= X-Gm-Gg: ASbGnctx0t2t01z6xqaBS9uOqE9mBhnEPkSOU/DRrDUvNorq1B7NhbA5sIEwg7TkynR 9OVvcyrT1IgV/7Yw3EEwNVfOnEyEnf07Kn0nau86GkREdMrqjkKGjZ7caoe6JG9oRJnnlFfvRA0 XMr7sa2jpF3QDDboGEWGOyQ4eZfLOjhoIkN+rwCJL3dDIEZ+CWol2kEsGHq3W+Ql2w5FyTf9Q3Z vqLWH/qRPaQEYiE40chNapffhEPLTKUDMgM/Me5ahjRogZNFKqOh5P01lpIDHz4Gv4g/b3ukmKl 8Y4BSgyXhC1bCsQqtkYaCHZMo0ggm571/fOF+QoBTJKxZMxaUjBLTaK/cNPiFmNkrMoeXpiS/pi Pd2JmVhPj168+fnoTc9pyNbnUtDWc0Ts2ZjDBCZSSKGN22W+FS9gd5w4tFx9GloOEoRwp2+Ajam i9AUXejvuWXIc= X-Google-Smtp-Source: AGHT+IEnZ1Es9Iqynwi881jRZ+osyJRw3Xy02XIzAJ2UD1ce1AI1WV46fPueFgRGajgnkNFqRGP2xQ== X-Received: by 2002:a05:690c:7444:b0:786:5712:46af with SMTP id 00721157ae682-788135e2fb6mr23538257b3.9.1762954929016; Wed, 12 Nov 2025 05:42:09 -0800 (PST) Received: from localhost ([2803:2d60:1107:87f:e68a:2c54:8a71:5fe9]) by smtp.gmail.com with UTF8SMTPSA id 00721157ae682-787d680aac0sm41874847b3.9.2025.11.12.05.42.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 12 Nov 2025 05:42:08 -0800 (PST) From: Peter Sanchez To: ~netlandish/links-dev@lists.code.netlandish.com Cc: Peter Sanchez Subject: [PATCH links] Removing test as it's not needed. The functionality of `ValidDomain` is covered in another test, which is what we care about. Date: Wed, 12 Nov 2025 07:42:02 -0600 Message-ID: <20251112134204.18527-1-peter@netlandish.com> X-Mailer: git-send-email 2.49.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit --- domain/integration_test.go | 132 ------------------------------------- 1 file changed, 132 deletions(-) diff --git a/domain/integration_test.go b/domain/integration_test.go index a05bb1e..6028118 100644 --- a/domain/integration_test.go +++ b/domain/integration_test.go @@ -4,16 +4,10 @@ import ( "context" "database/sql" "links/models" - "net/http" - "net/http/httptest" "os" "testing" - "time" - "github.com/labstack/echo/v4" - "netlandish.com/x/gobwebs/config" "netlandish.com/x/gobwebs/database" - "netlandish.com/x/gobwebs/server" "netlandish.com/x/gobwebs/timezone" _ "github.com/lib/pq" @@ -48,132 +42,6 @@ func testDB(t *testing.T) *sql.DB { return db } -// TestDomainValidationContextCancellation tests the exact scenario that was causing transaction leaks: -// Domain validation middleware calling ValidDomain() with context cancellation during database lookup -func TestDomainValidationContextCancellation(t *testing.T) { - db := testDB(t) - - // Set up basic test data - create a test domain - // First try to delete any existing test domain - db.Exec("DELETE FROM domains WHERE lookup_name = 'test.example.com'") - - _, err := db.Exec(` - INSERT INTO domains (lookup_name, name, service, status, level, is_active) - VALUES ($1, $2, $3, $4, $5, $6) - `, "test.example.com", "test.example.com", models.DomainServiceLinks, models.DomainStatusApproved, models.DomainLevelSystem, true) - if err != nil { - t.Fatalf("Failed to create test domain: %v", err) - } - - // Clean up after test - defer func() { - db.Exec("DELETE FROM domains WHERE lookup_name = 'test.example.com'") - }() - - // Track connection stats before test - statsBefore := db.Stats() - - // Create Echo server with middleware stack similar to production - e := echo.New() - cfg := &config.Config{Debug: true} - server.New(e, db, cfg).Initialize() - - // Add middleware in same order as production - e.Use( - // Custom context middleware (matches server.DefaultMiddlewareWithConfig) - func(next echo.HandlerFunc) echo.HandlerFunc { - return func(c echo.Context) error { - ctx := &server.Context{Context: c, Server: server.New(e, db, cfg)} - return next(ctx) - } - }, - database.DBIMiddleware(db), // DBI must be first - func(next echo.HandlerFunc) echo.HandlerFunc { // Add timezone context - return func(c echo.Context) error { - ctx := timezone.Context(c.Request().Context(), "UTC") - c.SetRequest(c.Request().WithContext(ctx)) - return next(c) - } - }, - DomainContext(models.DomainServiceLinks), // Domain validation - ) - - // Simple handler that should never be reached due to domain validation failure - e.GET("/test", func(c echo.Context) error { - return c.String(http.StatusOK, "success") - }) - - // Test 1: Context cancellation during domain validation - req := httptest.NewRequest(http.MethodGet, "/test", nil) - req.Host = "test.example.com" // Valid domain that exists in DB - - // Create cancellable context - ctx, cancel := context.WithCancel(req.Context()) - req = req.WithContext(ctx) - rec := httptest.NewRecorder() - - // Start request processing in goroutine - done := make(chan bool) - go func() { - defer func() { done <- true }() - e.ServeHTTP(rec, req) - }() - - // Cancel context immediately to simulate client disconnect - // This should trigger the "context canceled" error in ValidDomain() - cancel() - - // Wait for request to complete - <-done - - // The request should fail (exact status depends on error handling) - if rec.Code == http.StatusOK { - t.Error("Expected request to fail due to context cancellation") - } - - // Wait for cleanup - time.Sleep(300 * time.Millisecond) - - // Verify no connection leak occurred - this is the critical test - statsAfter := db.Stats() - if statsAfter.OpenConnections > statsBefore.OpenConnections { - t.Errorf("Connection leak detected after context cancellation: before=%d, after=%d", - statsBefore.OpenConnections, statsAfter.OpenConnections) - } - - t.Logf("Context cancellation test - Connection stats before: %d, after: %d", - statsBefore.OpenConnections, statsAfter.OpenConnections) - - // Test 2: Multiple rapid cancellations (stress test) - for range 5 { - req := httptest.NewRequest(http.MethodGet, "/test", nil) - req.Host = "test.example.com" - - ctx, cancel := context.WithCancel(req.Context()) - req = req.WithContext(ctx) - rec := httptest.NewRecorder() - - go func() { - e.ServeHTTP(rec, req) - }() - - // Cancel quickly - cancel() - time.Sleep(50 * time.Millisecond) - } - - // Final connection check after stress test - time.Sleep(500 * time.Millisecond) - statsFinal := db.Stats() - - if statsFinal.OpenConnections > statsBefore.OpenConnections+2 { // Allow some tolerance - t.Errorf("Connection leak detected after stress test: before=%d, final=%d", - statsBefore.OpenConnections, statsFinal.OpenConnections) - } - - t.Logf("Stress test complete - Connection stats before: %d, final: %d", - statsBefore.OpenConnections, statsFinal.OpenConnections) -} // TestValidDomainWithContextCancellation tests the ValidDomain function directly func TestValidDomainWithContextCancellation(t *testing.T) { -- 2.49.1