package claudemask import ( "net/http" "testing" ) func TestValidateNodeEmulation_ValidRequest(t *testing.T) { req, _ := http.NewRequest("POST", "https://api.anthropic.com/v1/messages", nil) // 设置所有必需的 Node.js 头 req.Header.Set("User-Agent", "claude-cli/2.1.88 (external, cli)") req.Header.Set("X-Stainless-Lang", "js") req.Header.Set("X-Stainless-Runtime", "node") req.Header.Set("X-Stainless-Runtime-Version", "v24.3.0") req.Header.Set("X-Stainless-Package-Version", "0.74.0") req.Header.Set("X-Stainless-OS", "MacOS") req.Header.Set("X-Stainless-Arch", "arm64") req.Header.Set("anthropic-version", "2023-06-01") isValid, errors := ValidateNodeEmulation(req) if !isValid { t.Errorf("expected valid emulation, got errors: %v", errors) } if len(errors) > 0 { t.Errorf("expected no errors, got: %v", errors) } } func TestValidateNodeEmulation_MissingHeaders(t *testing.T) { req, _ := http.NewRequest("POST", "https://api.anthropic.com/v1/messages", nil) // 只设置部分头 req.Header.Set("User-Agent", "claude-cli/2.1.88 (external, cli)") isValid, errors := ValidateNodeEmulation(req) if isValid { t.Error("expected invalid emulation due to missing headers") } if len(errors) == 0 { t.Error("expected validation errors") } if len(errors) < 7 { t.Errorf("expected at least 7 missing headers, got %d errors", len(errors)) } } func TestValidateNodeEmulation_InvalidRuntime(t *testing.T) { req, _ := http.NewRequest("POST", "https://api.anthropic.com/v1/messages", nil) // 设置所有必需的头,但 runtime 错误 req.Header.Set("User-Agent", "claude-cli/2.1.88 (external, cli)") req.Header.Set("X-Stainless-Lang", "js") req.Header.Set("X-Stainless-Runtime", "go") // ❌ 应为 "node" req.Header.Set("X-Stainless-Runtime-Version", "v24.3.0") req.Header.Set("X-Stainless-Package-Version", "0.74.0") req.Header.Set("X-Stainless-OS", "MacOS") req.Header.Set("X-Stainless-Arch", "arm64") req.Header.Set("anthropic-version", "2023-06-01") isValid, errs := ValidateNodeEmulation(req) if isValid { t.Error("expected invalid due to runtime=go") } if len(errs) == 0 { t.Error("expected validation error for runtime") } } func TestValidateNodeEmulation_GoClientUA(t *testing.T) { req, _ := http.NewRequest("POST", "https://api.anthropic.com/v1/messages", nil) // User-Agent 包含 Go 指示 req.Header.Set("User-Agent", "Go-http-client/2.0") // ❌ 包含 Go 指示 isValid, _ := ValidateNodeEmulation(req) if isValid { t.Error("expected invalid due to Go-http-client in User-Agent") } } func TestValidateNodeEmulation_MissingUserAgent(t *testing.T) { req, _ := http.NewRequest("POST", "https://api.anthropic.com/v1/messages", nil) // 不设置 User-Agent req.Header.Set("X-Stainless-Lang", "js") req.Header.Set("X-Stainless-Runtime", "node") req.Header.Set("X-Stainless-Runtime-Version", "v24.3.0") req.Header.Set("X-Stainless-Package-Version", "0.74.0") req.Header.Set("X-Stainless-OS", "MacOS") req.Header.Set("X-Stainless-Arch", "arm64") req.Header.Set("anthropic-version", "2023-06-01") isValid, errs := ValidateNodeEmulation(req) if isValid { t.Error("expected invalid due to missing User-Agent") } if len(errs) == 0 { t.Error("expected validation error for missing User-Agent") } } func TestCleanRequest_FixesGoUserAgent(t *testing.T) { req, _ := http.NewRequest("POST", "https://api.anthropic.com/v1/messages", nil) // 设置不正确的 User-Agent req.Header.Set("User-Agent", "Go-http-client/2.0") CleanRequest(req) ua := req.Header.Get("User-Agent") if ua != "claude-cli/2.1.88 (external, cli)" { t.Errorf("expected fixed User-Agent, got: %s", ua) } } func TestCleanRequest_FixesMissingUserAgent(t *testing.T) { req, _ := http.NewRequest("POST", "https://api.anthropic.com/v1/messages", nil) // 不设置 User-Agent CleanRequest(req) ua := req.Header.Get("User-Agent") if ua != "claude-cli/2.1.88 (external, cli)" { t.Errorf("expected User-Agent to be set, got: %s", ua) } } func TestValidateAndClean(t *testing.T) { req, _ := http.NewRequest("POST", "https://api.anthropic.com/v1/messages", nil) // 设置带有 Go 指示的 User-Agent,其他头正确 req.Header.Set("User-Agent", "Go-http-client/2.0") req.Header.Set("X-Stainless-Lang", "js") req.Header.Set("X-Stainless-Runtime", "node") req.Header.Set("X-Stainless-Runtime-Version", "v24.3.0") req.Header.Set("X-Stainless-Package-Version", "0.74.0") req.Header.Set("X-Stainless-OS", "MacOS") req.Header.Set("X-Stainless-Arch", "arm64") req.Header.Set("anthropic-version", "2023-06-01") isValid, errors := ValidateAndClean(req) // 清理后应该有效 if !isValid { t.Errorf("expected valid after cleaning, got errors: %v", errors) } ua := req.Header.Get("User-Agent") if ua != "claude-cli/2.1.88 (external, cli)" { t.Errorf("expected cleaned User-Agent, got: %s", ua) } }