1
0
Fork 0
mirror of https://codeberg.org/forgejo/forgejo.git synced 2025-08-06 17:40:57 +00:00

add files

This commit is contained in:
pat-s 2025-06-25 22:33:30 +02:00
parent 7ab27a7a7f
commit faa2dcdfca
No known key found for this signature in database
GPG key ID: 3C6318841EF78925
20 changed files with 1484 additions and 98 deletions

View file

@ -0,0 +1,393 @@
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package httplib
import (
"crypto/tls"
"net/http"
"net/http/httptest"
"sync"
"testing"
"time"
"forgejo.org/modules/setting"
)
func TestClientPool(t *testing.T) {
// Initialize settings for testing
setting.HTTPClient.MaxIdleConns = 50
setting.HTTPClient.MaxIdleConnsPerHost = 5
setting.HTTPClient.IdleConnTimeout = 60 * time.Second
setting.HTTPClient.DefaultTimeout = 30 * time.Second
pool := GetGlobalClientPool()
// Test getting a client
client1 := pool.GetClient("test")
if client1 == nil {
t.Fatal("Expected non-nil client")
}
// Test getting the same client again (should be cached)
client2 := pool.GetClient("test")
if client1 != client2 {
t.Fatal("Expected same client instance for same key")
}
// Test getting a different client
client3 := pool.GetClient("test2")
if client3 == client1 {
t.Fatal("Expected different client instance for different key")
}
// Test transport configuration
transport := client1.Transport.(*http.Transport)
if transport.MaxIdleConns != setting.HTTPClient.MaxIdleConns {
t.Errorf("Expected MaxIdleConns %d, got %d", setting.HTTPClient.MaxIdleConns, transport.MaxIdleConns)
}
if transport.MaxIdleConnsPerHost != setting.HTTPClient.MaxIdleConnsPerHost {
t.Errorf("Expected MaxIdleConnsPerHost %d, got %d", setting.HTTPClient.MaxIdleConnsPerHost, transport.MaxIdleConnsPerHost)
}
if transport.IdleConnTimeout != setting.HTTPClient.IdleConnTimeout {
t.Errorf("Expected IdleConnTimeout %v, got %v", setting.HTTPClient.IdleConnTimeout, transport.IdleConnTimeout)
}
if client1.Timeout != setting.HTTPClient.DefaultTimeout {
t.Errorf("Expected Timeout %v, got %v", setting.HTTPClient.DefaultTimeout, client1.Timeout)
}
}
func TestClientPoolConcurrentAccess(t *testing.T) {
pool := GetGlobalClientPool()
var wg sync.WaitGroup
clients := make([]*http.Client, 100)
// Test concurrent access to the same client key
for i := 0; i < 100; i++ {
wg.Add(1)
go func(index int) {
defer wg.Done()
clients[index] = pool.GetClient("concurrent_test")
}(i)
}
wg.Wait()
// All clients should be the same instance
firstClient := clients[0]
for i := 1; i < 100; i++ {
if clients[i] != firstClient {
t.Errorf("Expected all clients to be the same instance, but client[%d] is different", i)
}
}
}
func TestClientPoolDifferentKeys(t *testing.T) {
pool := GetGlobalClientPool()
// Test that different keys return different clients
client1 := pool.GetClient("key1")
client2 := pool.GetClient("key2")
client3 := pool.GetClient("key3")
if client1 == client2 || client1 == client3 || client2 == client3 {
t.Fatal("Expected different keys to return different client instances")
}
}
func TestGetClientWithTimeout(t *testing.T) {
pool := GetGlobalClientPool()
customTimeout := 15 * time.Second
client := pool.GetClientWithTimeout("timeout_test", customTimeout)
if client.Timeout != customTimeout {
t.Errorf("Expected timeout %v, got %v", customTimeout, client.Timeout)
}
// Test that the base client is not affected
baseClient := pool.GetClient("timeout_test")
if baseClient.Timeout == customTimeout {
t.Error("Expected base client timeout to be unchanged")
}
}
func TestGetClientWithTLS(t *testing.T) {
pool := GetGlobalClientPool()
baseClient := pool.GetClient("tls_test")
tlsConfig := &tls.Config{InsecureSkipVerify: true}
client := pool.GetClientWithTLS("tls_test", tlsConfig)
if client == baseClient {
t.Fatal("Expected different client instance with TLS config")
}
// Verify TLS config is applied
transport := client.Transport.(*http.Transport)
if transport.TLSClientConfig != tlsConfig {
t.Error("Expected TLS config to be applied to transport")
}
}
func TestGetDefaultClient(t *testing.T) {
client := GetDefaultClient()
if client == nil {
t.Fatal("Expected non-nil default client")
}
// Test that it's the same as getting from pool with "default" key
poolClient := GetGlobalClientPool().GetClient("default")
if client != poolClient {
t.Error("Expected GetDefaultClient to return the same client as pool.GetClient(\"default\")")
}
}
func TestGetWebhookClient(t *testing.T) {
// Set webhook timeout for testing
setting.Webhook.DeliverTimeout = 10
client := GetWebhookClient()
if client == nil {
t.Fatal("Expected non-nil webhook client")
}
expectedTimeout := time.Duration(setting.Webhook.DeliverTimeout) * time.Second
if client.Timeout != expectedTimeout {
t.Errorf("Expected webhook timeout %v, got %v", expectedTimeout, client.Timeout)
}
}
func TestGetLFSClient(t *testing.T) {
client := GetLFSClient()
if client == nil {
t.Fatal("Expected non-nil LFS client")
}
}
func TestGetMigrationClient(t *testing.T) {
client := GetMigrationClient()
if client == nil {
t.Fatal("Expected non-nil migration client")
}
}
func TestClientPoolClose(t *testing.T) {
pool := GetGlobalClientPool()
// Get some clients
client1 := pool.GetClient("close_test1")
client2 := pool.GetClient("close_test2")
if client1 == nil || client2 == nil {
t.Fatal("Expected non-nil clients")
}
// Close the pool
pool.Close()
// Verify clients are still accessible (they should be recreated)
client3 := pool.GetClient("close_test1")
client4 := pool.GetClient("close_test2")
if client3 == nil || client4 == nil {
t.Fatal("Expected clients to be recreated after pool close")
}
}
func TestClientPoolTransportConfiguration(t *testing.T) {
pool := GetGlobalClientPool()
client := pool.GetClient("transport_test")
transport := client.Transport.(*http.Transport)
// Test that all expected transport settings are configured
if transport.MaxIdleConns == 0 {
t.Error("Expected MaxIdleConns to be configured")
}
if transport.MaxIdleConnsPerHost == 0 {
t.Error("Expected MaxIdleConnsPerHost to be configured")
}
if transport.IdleConnTimeout == 0 {
t.Error("Expected IdleConnTimeout to be configured")
}
if transport.TLSHandshakeTimeout == 0 {
t.Error("Expected TLSHandshakeTimeout to be configured")
}
if transport.ExpectContinueTimeout == 0 {
t.Error("Expected ExpectContinueTimeout to be configured")
}
if transport.DialContext == nil {
t.Error("Expected DialContext to be configured")
}
if transport.Proxy == nil {
t.Error("Expected Proxy to be configured")
}
}
func TestClientPoolHTTP2Support(t *testing.T) {
pool := GetGlobalClientPool()
client := pool.GetClient("http2_test")
transport := client.Transport.(*http.Transport)
// Test HTTP/2 support
if !transport.ForceAttemptHTTP2 {
t.Error("Expected ForceAttemptHTTP2 to be enabled")
}
}
func TestClientPoolKeepAliveSettings(t *testing.T) {
pool := GetGlobalClientPool()
client := pool.GetClient("keepalive_test")
transport := client.Transport.(*http.Transport)
// Test that keep-alive is enabled
if transport.DisableKeepAlives {
t.Error("Expected DisableKeepAlives to be false")
}
}
func TestClientPoolWithRealHTTPRequest(t *testing.T) {
// Create a test server
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
}))
defer server.Close()
// Get a client from the pool
client := GetDefaultClient()
// Make a real HTTP request
resp, err := client.Get(server.URL)
if err != nil {
t.Fatalf("Failed to make HTTP request: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Errorf("Expected status 200, got %d", resp.StatusCode)
}
}
func TestClientPoolMultipleRequests(t *testing.T) {
// Create a test server
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
}))
defer server.Close()
// Get a client from the pool
client := GetDefaultClient()
// Make multiple requests to test connection reuse
for i := 0; i < 10; i++ {
resp, err := client.Get(server.URL)
if err != nil {
t.Fatalf("Failed to make HTTP request %d: %v", i, err)
}
resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Errorf("Expected status 200, got %d", resp.StatusCode)
}
}
}
func TestClientPoolTimeoutBehavior(t *testing.T) {
// Create a slow test server
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
time.Sleep(2 * time.Second) // Simulate slow response
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
}))
defer server.Close()
// Get a client with short timeout
client := GetGlobalClientPool().GetClientWithTimeout("timeout_test", 1*time.Second)
// Make a request that should timeout
_, err := client.Get(server.URL)
if err == nil {
t.Error("Expected request to timeout")
}
}
func TestClientPoolTLSConfiguration(t *testing.T) {
// Create a test server with TLS
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
}))
defer server.Close()
// Get a client with TLS config that skips verification
tlsConfig := &tls.Config{InsecureSkipVerify: true}
client := GetGlobalClientPool().GetClientWithTLS("tls_test", tlsConfig)
// Make a request to the TLS server
resp, err := client.Get(server.URL)
if err != nil {
t.Fatalf("Failed to make TLS request: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Errorf("Expected status 200, got %d", resp.StatusCode)
}
}
func TestClientPoolSingletonBehavior(t *testing.T) {
// Test that GetGlobalClientPool always returns the same instance
pool1 := GetGlobalClientPool()
pool2 := GetGlobalClientPool()
if pool1 != pool2 {
t.Fatal("Expected GetGlobalClientPool to return the same instance")
}
}
func TestClientPoolEmptyKey(t *testing.T) {
pool := GetGlobalClientPool()
// Test with empty key
client := pool.GetClient("")
if client == nil {
t.Fatal("Expected non-nil client for empty key")
}
}
func TestClientPoolSpecialCharacters(t *testing.T) {
pool := GetGlobalClientPool()
// Test with special characters in key
specialKeys := []string{
"key with spaces",
"key-with-dashes",
"key_with_underscores",
"key.with.dots",
"key:with:colons",
"key/with/slashes",
"key\\with\\backslashes",
}
for _, key := range specialKeys {
client := pool.GetClient(key)
if client == nil {
t.Errorf("Expected non-nil client for key: %s", key)
}
}
}