- windsurf_gateway_service: 添加上游延迟/TTFT/错误上下文记录 - endpoint: DeriveUpstreamEndpoint 添加 PlatformWindsurf 分支 - ops_error_logger: guessPlatformFromPath 添加 /windsurf/ 识别
303 lines
7.4 KiB
Go
303 lines
7.4 KiB
Go
package windsurf
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
)
|
|
|
|
func TestProxyKey(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expected string
|
|
}{
|
|
{"empty string", "", "default"},
|
|
{"whitespace only", " ", "default"},
|
|
{"simple http proxy", "http://1.2.3.4:8080", "px_1_2_3_4_8080"},
|
|
{"https proxy", "https://proxy.example.com:3128", "px_proxy_example_com_3128"},
|
|
{"socks5 proxy", "socks5://10.0.0.1:1080", "px_10_0_0_1_1080"},
|
|
{"proxy with auth", "http://user:pass@1.2.3.4:8080", "px_1_2_3_4_8080_user"},
|
|
{"different auth same host", "http://other:secret@1.2.3.4:8080", "px_1_2_3_4_8080_other"},
|
|
{"no port", "http://proxy.local", "px_proxy_local"},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := proxyKey(tt.input)
|
|
if got != tt.expected {
|
|
t.Errorf("proxyKey(%q) = %q, want %q", tt.input, got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestProxyKeyDifferentAuthGetsDifferentKey(t *testing.T) {
|
|
k1 := proxyKey("http://alice:pw1@host:8080")
|
|
k2 := proxyKey("http://bob:pw2@host:8080")
|
|
if k1 == k2 {
|
|
t.Errorf("different credentials on same host should produce different keys: %q vs %q", k1, k2)
|
|
}
|
|
}
|
|
|
|
func TestRedactProxyURL(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
want string
|
|
}{
|
|
{"empty", "", "none"},
|
|
{"no auth", "http://1.2.3.4:8080", "http://1.2.3.4:8080"},
|
|
{"with auth stripped", "http://user:secret@1.2.3.4:8080", "http://1.2.3.4:8080"},
|
|
{"invalid url", "://bad", "<invalid>"},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := redactProxyURL(tt.input)
|
|
if got != tt.want {
|
|
t.Errorf("redactProxyURL(%q) = %q, want %q", tt.input, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsPortInUse(t *testing.T) {
|
|
if isPortInUse(59999) {
|
|
t.Skip("port 59999 unexpectedly in use")
|
|
}
|
|
}
|
|
|
|
func TestWriteVarint(t *testing.T) {
|
|
tests := []struct {
|
|
val uint64
|
|
expect []byte
|
|
}{
|
|
{0, []byte{0}},
|
|
{1, []byte{1}},
|
|
{127, []byte{127}},
|
|
{128, []byte{0x80, 0x01}},
|
|
{300, []byte{0xAC, 0x02}},
|
|
}
|
|
for _, tt := range tests {
|
|
got := writeVarint(tt.val)
|
|
if len(got) != len(tt.expect) {
|
|
t.Errorf("writeVarint(%d) len=%d, want %d", tt.val, len(got), len(tt.expect))
|
|
continue
|
|
}
|
|
for i := range got {
|
|
if got[i] != tt.expect[i] {
|
|
t.Errorf("writeVarint(%d)[%d] = 0x%02x, want 0x%02x", tt.val, i, got[i], tt.expect[i])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestReadVarintRoundtrip(t *testing.T) {
|
|
values := []uint64{0, 1, 127, 128, 300, 16384, 1<<32 - 1}
|
|
for _, v := range values {
|
|
encoded := writeVarint(v)
|
|
decoded, pos, ok := ReadVarint(encoded, 0)
|
|
if !ok {
|
|
t.Errorf("ReadVarint failed for %d", v)
|
|
continue
|
|
}
|
|
if decoded != v {
|
|
t.Errorf("ReadVarint roundtrip: got %d, want %d", decoded, v)
|
|
}
|
|
if pos != len(encoded) {
|
|
t.Errorf("ReadVarint pos=%d, want %d", pos, len(encoded))
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEncodeStringField(t *testing.T) {
|
|
data := encodeStringField(1, "hello")
|
|
tag, pos, ok := ReadVarint(data, 0)
|
|
if !ok || tag != (1<<3|2) {
|
|
t.Fatalf("bad tag: %d ok=%v", tag, ok)
|
|
}
|
|
length, pos, ok := ReadVarint(data, pos)
|
|
if !ok || length != 5 {
|
|
t.Fatalf("bad length: %d ok=%v", length, ok)
|
|
}
|
|
if string(data[pos:pos+int(length)]) != "hello" {
|
|
t.Fatalf("payload mismatch")
|
|
}
|
|
}
|
|
|
|
func TestEncodeVarintField(t *testing.T) {
|
|
data := encodeVarintField(3, 42)
|
|
tag, pos, ok := ReadVarint(data, 0)
|
|
if !ok || tag != (3<<3|0) {
|
|
t.Fatalf("bad tag: %d ok=%v", tag, ok)
|
|
}
|
|
val, _, ok := ReadVarint(data, pos)
|
|
if !ok || val != 42 {
|
|
t.Fatalf("bad value: %d ok=%v", val, ok)
|
|
}
|
|
}
|
|
|
|
func TestParseStringField1(t *testing.T) {
|
|
data := encodeStringField(1, "cascade-123")
|
|
got, err := parseStringField1(data)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got != "cascade-123" {
|
|
t.Fatalf("got %q, want %q", got, "cascade-123")
|
|
}
|
|
}
|
|
|
|
func TestParseStringField1WithOtherFields(t *testing.T) {
|
|
var data []byte
|
|
data = append(data, encodeVarintField(2, 99)...)
|
|
data = append(data, encodeStringField(1, "target")...)
|
|
data = append(data, encodeStringField(3, "noise")...)
|
|
got, err := parseStringField1(data)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got != "target" {
|
|
t.Fatalf("got %q, want %q", got, "target")
|
|
}
|
|
}
|
|
|
|
func TestParseVarintField2(t *testing.T) {
|
|
var data []byte
|
|
data = append(data, encodeVarintField(1, 10)...)
|
|
data = append(data, encodeVarintField(2, 42)...)
|
|
got, err := parseVarintField2(data)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got != 42 {
|
|
t.Fatalf("got %d, want 42", got)
|
|
}
|
|
}
|
|
|
|
func TestResolveModelEnum(t *testing.T) {
|
|
if v := resolveModelEnum("MODEL_CLAUDE_4_SONNET"); v != 281 {
|
|
t.Errorf("got %d, want 281", v)
|
|
}
|
|
if v := resolveModelEnum("NONEXISTENT"); v != 0 {
|
|
t.Errorf("got %d, want 0", v)
|
|
}
|
|
}
|
|
|
|
func TestIsPanelStateNotFound(t *testing.T) {
|
|
tests := []struct {
|
|
msg string
|
|
want bool
|
|
}{
|
|
{"gRPC status 5: panel state not found for session abc", true},
|
|
{"NOT_FOUND: panel xyz is missing", true},
|
|
{"connection refused", false},
|
|
{"", false},
|
|
}
|
|
for _, tt := range tests {
|
|
var err error
|
|
if tt.msg != "" {
|
|
err = fmt.Errorf("%s", tt.msg)
|
|
}
|
|
got := isPanelStateNotFound(err)
|
|
if got != tt.want {
|
|
t.Errorf("isPanelStateNotFound(%q) = %v, want %v", tt.msg, got, tt.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGenerateUUID(t *testing.T) {
|
|
u := generateUUID()
|
|
if len(u) != 36 {
|
|
t.Fatalf("UUID length = %d, want 36", len(u))
|
|
}
|
|
if u[8] != '-' || u[13] != '-' || u[18] != '-' || u[23] != '-' {
|
|
t.Fatalf("UUID format wrong: %s", u)
|
|
}
|
|
if u[14] != '4' {
|
|
t.Fatalf("UUID version not 4: %s", u)
|
|
}
|
|
u2 := generateUUID()
|
|
if u == u2 {
|
|
t.Fatal("two UUIDs should not be equal")
|
|
}
|
|
}
|
|
|
|
func TestBuildMetadata(t *testing.T) {
|
|
meta := buildMetadata("test-token-123", "session-abc")
|
|
got, err := parseStringField1(meta)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got != AppName {
|
|
t.Errorf("field 1 (ide_name) = %q, want %q", got, AppName)
|
|
}
|
|
}
|
|
|
|
func TestBuildCascadeConfig(t *testing.T) {
|
|
cfg := buildCascadeConfig("MODEL_CLAUDE_4_SONNET", 281, "")
|
|
if len(cfg) == 0 {
|
|
t.Fatal("buildCascadeConfig returned empty")
|
|
}
|
|
}
|
|
|
|
func TestStripGRPCFrame(t *testing.T) {
|
|
payload := []byte("hello world")
|
|
frame := make([]byte, 5+len(payload))
|
|
frame[0] = 0
|
|
frame[1] = 0
|
|
frame[2] = 0
|
|
frame[3] = 0
|
|
frame[4] = byte(len(payload))
|
|
copy(frame[5:], payload)
|
|
got := stripGRPCFrame(frame)
|
|
if string(got) != "hello world" {
|
|
t.Fatalf("got %q, want %q", got, "hello world")
|
|
}
|
|
}
|
|
|
|
func TestStripGRPCFrameShortData(t *testing.T) {
|
|
got := stripGRPCFrame([]byte{0, 0})
|
|
if string(got) != string([]byte{0, 0}) {
|
|
t.Fatal("short data should be returned as-is")
|
|
}
|
|
}
|
|
|
|
func TestNewLSPoolDefaults(t *testing.T) {
|
|
pool := NewLSPool(LSPoolConfig{}, nil)
|
|
if pool.config.Binary == "" {
|
|
t.Error("default binary should not be empty")
|
|
}
|
|
if pool.config.BasePort != DefaultLSPort {
|
|
t.Errorf("default port = %d, want %d", pool.config.BasePort, DefaultLSPort)
|
|
}
|
|
if pool.config.CSRFToken != DefaultCSRF {
|
|
t.Errorf("default CSRF = %q, want %q", pool.config.CSRFToken, DefaultCSRF)
|
|
}
|
|
}
|
|
|
|
func TestLSPoolGetNonExistent(t *testing.T) {
|
|
pool := NewLSPool(LSPoolConfig{}, nil)
|
|
if e := pool.Get("http://nonexistent:9999"); e != nil {
|
|
t.Error("Get on empty pool should return nil")
|
|
}
|
|
}
|
|
|
|
func TestLSPoolStatus(t *testing.T) {
|
|
pool := NewLSPool(LSPoolConfig{}, nil)
|
|
s := pool.Status()
|
|
if s.Running {
|
|
t.Error("empty pool should not be running")
|
|
}
|
|
if len(s.Instances) != 0 {
|
|
t.Error("empty pool should have no instances")
|
|
}
|
|
}
|
|
|
|
func TestLSPoolShutdownEmpty(t *testing.T) {
|
|
pool := NewLSPool(LSPoolConfig{}, nil)
|
|
pool.Shutdown()
|
|
s := pool.Status()
|
|
if s.Running {
|
|
t.Error("shutdown pool should not be running")
|
|
}
|
|
}
|