openai_ws_client_test.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package service
  2. import (
  3. "fmt"
  4. "net/http"
  5. "testing"
  6. "time"
  7. "github.com/stretchr/testify/require"
  8. )
  9. func TestCoderOpenAIWSClientDialer_ProxyHTTPClientReuse(t *testing.T) {
  10. dialer := newDefaultOpenAIWSClientDialer()
  11. impl, ok := dialer.(*coderOpenAIWSClientDialer)
  12. require.True(t, ok)
  13. c1, err := impl.proxyHTTPClient("http://127.0.0.1:8080")
  14. require.NoError(t, err)
  15. c2, err := impl.proxyHTTPClient("http://127.0.0.1:8080")
  16. require.NoError(t, err)
  17. require.Same(t, c1, c2, "同一代理地址应复用同一个 HTTP 客户端")
  18. c3, err := impl.proxyHTTPClient("http://127.0.0.1:8081")
  19. require.NoError(t, err)
  20. require.NotSame(t, c1, c3, "不同代理地址应分离客户端")
  21. }
  22. func TestCoderOpenAIWSClientDialer_ProxyHTTPClientInvalidURL(t *testing.T) {
  23. dialer := newDefaultOpenAIWSClientDialer()
  24. impl, ok := dialer.(*coderOpenAIWSClientDialer)
  25. require.True(t, ok)
  26. _, err := impl.proxyHTTPClient("://bad")
  27. require.Error(t, err)
  28. }
  29. func TestCoderOpenAIWSClientDialer_TransportMetricsSnapshot(t *testing.T) {
  30. dialer := newDefaultOpenAIWSClientDialer()
  31. impl, ok := dialer.(*coderOpenAIWSClientDialer)
  32. require.True(t, ok)
  33. _, err := impl.proxyHTTPClient("http://127.0.0.1:18080")
  34. require.NoError(t, err)
  35. _, err = impl.proxyHTTPClient("http://127.0.0.1:18080")
  36. require.NoError(t, err)
  37. _, err = impl.proxyHTTPClient("http://127.0.0.1:18081")
  38. require.NoError(t, err)
  39. snapshot := impl.SnapshotTransportMetrics()
  40. require.Equal(t, int64(1), snapshot.ProxyClientCacheHits)
  41. require.Equal(t, int64(2), snapshot.ProxyClientCacheMisses)
  42. require.InDelta(t, 1.0/3.0, snapshot.TransportReuseRatio, 0.0001)
  43. }
  44. func TestCoderOpenAIWSClientDialer_ProxyClientCacheCapacity(t *testing.T) {
  45. dialer := newDefaultOpenAIWSClientDialer()
  46. impl, ok := dialer.(*coderOpenAIWSClientDialer)
  47. require.True(t, ok)
  48. total := openAIWSProxyClientCacheMaxEntries + 32
  49. for i := 0; i < total; i++ {
  50. _, err := impl.proxyHTTPClient(fmt.Sprintf("http://127.0.0.1:%d", 20000+i))
  51. require.NoError(t, err)
  52. }
  53. impl.proxyMu.Lock()
  54. cacheSize := len(impl.proxyClients)
  55. impl.proxyMu.Unlock()
  56. require.LessOrEqual(t, cacheSize, openAIWSProxyClientCacheMaxEntries, "代理客户端缓存应受容量上限约束")
  57. }
  58. func TestCoderOpenAIWSClientDialer_ProxyClientCacheIdleTTL(t *testing.T) {
  59. dialer := newDefaultOpenAIWSClientDialer()
  60. impl, ok := dialer.(*coderOpenAIWSClientDialer)
  61. require.True(t, ok)
  62. oldProxy := "http://127.0.0.1:28080"
  63. _, err := impl.proxyHTTPClient(oldProxy)
  64. require.NoError(t, err)
  65. impl.proxyMu.Lock()
  66. oldEntry := impl.proxyClients[oldProxy]
  67. require.NotNil(t, oldEntry)
  68. oldEntry.lastUsedUnixNano = time.Now().Add(-openAIWSProxyClientCacheIdleTTL - time.Minute).UnixNano()
  69. impl.proxyMu.Unlock()
  70. // 触发一次新的代理获取,驱动 TTL 清理。
  71. _, err = impl.proxyHTTPClient("http://127.0.0.1:28081")
  72. require.NoError(t, err)
  73. impl.proxyMu.Lock()
  74. _, exists := impl.proxyClients[oldProxy]
  75. impl.proxyMu.Unlock()
  76. require.False(t, exists, "超过空闲 TTL 的代理客户端应被回收")
  77. }
  78. func TestCoderOpenAIWSClientDialer_ProxyTransportTLSHandshakeTimeout(t *testing.T) {
  79. dialer := newDefaultOpenAIWSClientDialer()
  80. impl, ok := dialer.(*coderOpenAIWSClientDialer)
  81. require.True(t, ok)
  82. client, err := impl.proxyHTTPClient("http://127.0.0.1:38080")
  83. require.NoError(t, err)
  84. require.NotNil(t, client)
  85. transport, ok := client.Transport.(*http.Transport)
  86. require.True(t, ok)
  87. require.NotNil(t, transport)
  88. require.Equal(t, 10*time.Second, transport.TLSHandshakeTimeout)
  89. }
  90. func TestCoderOpenAIWSClientConn_DoesNotSupportIdlePingWithoutReader(t *testing.T) {
  91. require.False(t, (&coderOpenAIWSClientConn{}).SupportsIdlePingWithoutReader())
  92. }