engine_fingerprint_signal_test.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package openai
  2. import (
  3. "net/http"
  4. "testing"
  5. "github.com/stretchr/testify/require"
  6. )
  7. // hdr 构造一个 http.Header(键值对)。
  8. func hdr(kv ...string) http.Header {
  9. h := http.Header{}
  10. for i := 0; i+1 < len(kv); i += 2 {
  11. h.Set(kv[i], kv[i+1])
  12. }
  13. return h
  14. }
  15. func TestEvaluateEngineFingerprint_DefaultSeed(t *testing.T) {
  16. sigs := DefaultEngineFingerprintSignals // 仅 x-codex- 前缀 Required
  17. cases := []struct {
  18. name string
  19. h http.Header
  20. body string
  21. want bool
  22. }{
  23. {"R1 真CLI 带x-codex-window-id", hdr("x-codex-window-id", "a1", "session-id", "u1"), ``, true},
  24. {"R2 纯伪装 无指纹", hdr("user-agent", "codex/1"), ``, false},
  25. {"R3 仅body有", hdr(), `{"client_metadata":{"x-codex-window-id":"c3"}}`, false},
  26. {"R4 旧版 仅session_id无x-codex-", hdr("session_id", "u4"), ``, false},
  27. }
  28. for _, tc := range cases {
  29. t.Run(tc.name, func(t *testing.T) {
  30. require.Equal(t, tc.want, EvaluateEngineFingerprint(tc.h, []byte(tc.body), sigs))
  31. })
  32. }
  33. }
  34. func TestEvaluateEngineFingerprint_Rules(t *testing.T) {
  35. exactSession := EngineFingerprintSignal{Type: FingerprintSignalHeaderExact, Match: []string{"session-id", "session_id"}, Required: true}
  36. prefixCodex := EngineFingerprintSignal{Type: FingerprintSignalHeaderPrefix, Match: []string{"x-codex-"}, Required: true}
  37. bodyWin := EngineFingerprintSignal{Type: FingerprintSignalBodyPath, Match: []string{"client_metadata.x-codex-window-id"}, Required: true}
  38. t.Run("行内变体OR: 配置session-id 命中下划线session_id", func(t *testing.T) {
  39. require.True(t, EvaluateEngineFingerprint(hdr("session_id", "x"), nil, []EngineFingerprintSignal{exactSession}))
  40. })
  41. t.Run("跨条AND: 勾x-codex-与session 缺一即拒", func(t *testing.T) {
  42. both := []EngineFingerprintSignal{prefixCodex, exactSession}
  43. require.True(t, EvaluateEngineFingerprint(hdr("x-codex-window-id", "a", "session-id", "b"), nil, both))
  44. require.False(t, EvaluateEngineFingerprint(hdr("session-id", "b"), nil, both)) // 缺 x-codex-
  45. })
  46. t.Run("body_path 命中/ body空", func(t *testing.T) {
  47. require.True(t, EvaluateEngineFingerprint(hdr(), []byte(`{"client_metadata":{"x-codex-window-id":"1"}}`), []EngineFingerprintSignal{bodyWin}))
  48. require.False(t, EvaluateEngineFingerprint(hdr(), nil, []EngineFingerprintSignal{bodyWin}))
  49. })
  50. t.Run("无任何Required → true", func(t *testing.T) {
  51. none := []EngineFingerprintSignal{{Type: FingerprintSignalHeaderPrefix, Match: []string{"x-codex-"}, Required: false}}
  52. require.True(t, EvaluateEngineFingerprint(hdr(), nil, none))
  53. require.True(t, EvaluateEngineFingerprint(hdr(), nil, nil))
  54. })
  55. }
  56. func TestParseAndValidateEngineFingerprintSignals(t *testing.T) {
  57. t.Run("空串=合法空", func(t *testing.T) {
  58. sigs, ok := ParseEngineFingerprintSignals("")
  59. require.True(t, ok)
  60. require.Nil(t, sigs)
  61. require.NoError(t, ValidateEngineFingerprintSignalsJSON(""))
  62. })
  63. t.Run("合法数组", func(t *testing.T) {
  64. raw := `[{"type":"header_prefix","match":["x-codex-"],"required":true}]`
  65. sigs, ok := ParseEngineFingerprintSignals(raw)
  66. require.True(t, ok)
  67. require.Len(t, sigs, 1)
  68. require.NoError(t, ValidateEngineFingerprintSignalsJSON(raw))
  69. })
  70. t.Run("非法JSON", func(t *testing.T) {
  71. _, ok := ParseEngineFingerprintSignals("not json")
  72. require.False(t, ok)
  73. require.Error(t, ValidateEngineFingerprintSignalsJSON("not json"))
  74. })
  75. t.Run("非法type 被校验拒绝", func(t *testing.T) {
  76. require.Error(t, ValidateEngineFingerprintSignalsJSON(`[{"type":"bogus","match":["x"]}]`))
  77. })
  78. t.Run("match全空 被校验拒绝", func(t *testing.T) {
  79. require.Error(t, ValidateEngineFingerprintSignalsJSON(`[{"type":"header_exact","match":["",""]}]`))
  80. })
  81. t.Run("默认种子JSON 可解析且只勾x-codex-", func(t *testing.T) {
  82. sigs, ok := ParseEngineFingerprintSignals(DefaultEngineFingerprintSignalsJSON())
  83. require.True(t, ok)
  84. requiredTypes := []string{}
  85. for _, s := range sigs {
  86. if s.Required {
  87. requiredTypes = append(requiredTypes, s.Type+":"+s.Match[0])
  88. }
  89. }
  90. require.Equal(t, []string{"header_prefix:x-codex-"}, requiredTypes)
  91. })
  92. }