chore: 并入 iotlcm-upstream-proxy 历史到 upstream-proxy/(原提交 44209ec)

This commit is contained in:
MiFaZhan
2026-11-02 13:28:02 +08:00
117 changed files with 8690 additions and 0 deletions
@@ -0,0 +1,97 @@
package upstreamimpl
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/gogf/gf/v2/frame/g"
)
func TestGatewayTimeoutAllowsDelayedHeaders(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
time.Sleep(40 * time.Millisecond)
_, _ = w.Write([]byte(`{"code":0,"data":[]}`))
}))
defer server.Close()
client := g.Client()
other := g.Client()
original := other.Transport.(*http.Transport)
original.ResponseHeaderTimeout = time.Millisecond
client.Transport.(*http.Transport).ResponseHeaderTimeout = time.Millisecond
configureGatewayTimeout(context.Background(), client, "/sim/change/sim-apn", 1, time.Second)
response, err := client.Post(context.Background(), server.URL, nil)
if err != nil {
t.Fatal(err)
}
defer response.Close()
if original.ResponseHeaderTimeout != time.Millisecond {
t.Fatal("修改了共享Transport")
}
}
func TestNonAPNGatewayTimeoutPreservesHeaderBudget(t *testing.T) {
client := g.Client()
transport := client.Transport.(*http.Transport)
transport.ResponseHeaderTimeout = 17 * time.Second
configureGatewayTimeout(context.Background(), client, "/sim/query/test", 2, 3*time.Second)
if client.Client.Timeout != 6*time.Second || transport.ResponseHeaderTimeout != 6*time.Second {
t.Fatalf("非APN响应头预算必须与请求预算一致:request=%s header=%s", client.Client.Timeout, transport.ResponseHeaderTimeout)
}
}
// TestNonAPNBatchExpandsHeaderBudget 覆盖批量停复机等非 APN 路径:
// 50 张卡按单卡预算放大后,响应头等待不能继续停留在 gclient 的 30 秒默认值。
func TestNonAPNBatchExpandsHeaderBudget(t *testing.T) {
client := g.Client()
transport := client.Transport.(*http.Transport)
transport.ResponseHeaderTimeout = 30 * time.Second
applyGatewayTimeout(client, "/sim/change/sim-status", 50, 10*time.Second, defaultDataServiceTimeout, defaultGatewayBatchTimeout)
if client.Client.Timeout != 500*time.Second {
t.Fatalf("请求预算=%s,期望500s", client.Client.Timeout)
}
if transport.ResponseHeaderTimeout != client.Client.Timeout {
t.Fatalf("响应头预算=%s与请求预算不一致", transport.ResponseHeaderTimeout)
}
}
// TestNonAPNBatchRespectsBatchTimeoutCap 保证异常上游不会无限占用连接:
// 超出批量上限时按上限截断,且响应头预算同步截断。
func TestNonAPNBatchRespectsBatchTimeoutCap(t *testing.T) {
client := g.Client()
transport := client.Transport.(*http.Transport)
applyGatewayTimeout(client, "/sim/query/usage", 1000, 10*time.Second, defaultDataServiceTimeout, defaultGatewayBatchTimeout)
if client.Client.Timeout != defaultGatewayBatchTimeout {
t.Fatalf("请求预算=%s,期望批量上限%s", client.Client.Timeout, defaultGatewayBatchTimeout)
}
if transport.ResponseHeaderTimeout != defaultGatewayBatchTimeout {
t.Fatalf("响应头预算=%s,期望批量上限%s", transport.ResponseHeaderTimeout, defaultGatewayBatchTimeout)
}
}
// TestNonAPNSingleCardKeepsPerCardBudget 保证单卡请求不被放大成批量预算。
func TestNonAPNSingleCardKeepsPerCardBudget(t *testing.T) {
for _, count := range []int{0, 1} {
client := g.Client()
transport := client.Transport.(*http.Transport)
applyGatewayTimeout(client, "/sim/query/test", count, 10*time.Second, defaultDataServiceTimeout, defaultGatewayBatchTimeout)
if client.Client.Timeout != 10*time.Second || transport.ResponseHeaderTimeout != 10*time.Second {
t.Fatalf("count=%d request=%s header=%s", count, client.Client.Timeout, transport.ResponseHeaderTimeout)
}
}
}
func TestDataServiceTimeoutOverridesCardBudget(t *testing.T) {
for _, count := range []int{0, 1, 100} {
client := g.Client()
configureGatewayTimeout(context.Background(), client, "/sim/change/sim-apn", count, time.Millisecond)
if client.Client.Timeout != 210*time.Second {
t.Fatalf("count=%d timeout=%s", count, client.Client.Timeout)
}
if client.Transport.(*http.Transport).ResponseHeaderTimeout != client.Client.Timeout {
t.Fatal("响应头预算不一致")
}
}
}