openai_cyber_policy_test.go 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. package service
  2. import (
  3. "net/http/httptest"
  4. "testing"
  5. "github.com/gin-gonic/gin"
  6. "github.com/stretchr/testify/require"
  7. )
  8. func TestMarkAndGetOpsCyberPolicy(t *testing.T) {
  9. gin.SetMode(gin.TestMode)
  10. rec := httptest.NewRecorder()
  11. c, _ := gin.CreateTestContext(rec)
  12. require.Nil(t, GetOpsCyberPolicy(c), "no mark initially")
  13. MarkOpsCyberPolicy(c, CyberPolicyMark{
  14. Code: "cyber_policy",
  15. Message: "This request was flagged for cyber policy.",
  16. Body: `{"error":{"code":"cyber_policy"}}`,
  17. UpstreamStatus: 400,
  18. })
  19. got := GetOpsCyberPolicy(c)
  20. require.NotNil(t, got)
  21. require.Equal(t, "cyber_policy", got.Code)
  22. require.Equal(t, 400, got.UpstreamStatus)
  23. }
  24. func TestMarkOpsCyberPolicyFirstWins(t *testing.T) {
  25. gin.SetMode(gin.TestMode)
  26. rec := httptest.NewRecorder()
  27. c, _ := gin.CreateTestContext(rec)
  28. MarkOpsCyberPolicy(c, CyberPolicyMark{Code: "cyber_policy", Message: "first"})
  29. MarkOpsCyberPolicy(c, CyberPolicyMark{Code: "cyber_policy", Message: "second"})
  30. require.Equal(t, "first", GetOpsCyberPolicy(c).Message, "first mark wins, later marks ignored")
  31. }
  32. func TestMarkOpsCyberPolicyNilContext(t *testing.T) {
  33. MarkOpsCyberPolicy(nil, CyberPolicyMark{Code: "cyber_policy"})
  34. require.Nil(t, GetOpsCyberPolicy(nil))
  35. }
  36. // TestClearOpsCyberPolicy_AllowsRemark verifies F1: after Clear, Get returns nil
  37. // and a subsequent Mark takes effect (per-turn lifecycle in WS connections).
  38. func TestClearOpsCyberPolicy_AllowsRemark(t *testing.T) {
  39. gin.SetMode(gin.TestMode)
  40. c, _ := gin.CreateTestContext(httptest.NewRecorder())
  41. MarkOpsCyberPolicy(c, CyberPolicyMark{Message: "first", UpstreamStatus: 200})
  42. require.NotNil(t, GetOpsCyberPolicy(c))
  43. ClearOpsCyberPolicy(c)
  44. require.Nil(t, GetOpsCyberPolicy(c), "mark must be invisible after Clear")
  45. MarkOpsCyberPolicy(c, CyberPolicyMark{Message: "second", UpstreamStatus: 400})
  46. got := GetOpsCyberPolicy(c)
  47. require.NotNil(t, got, "re-mark after Clear must take effect")
  48. require.Equal(t, "second", got.Message)
  49. }
  50. func TestDetectOpenAICyberPolicy(t *testing.T) {
  51. cases := []struct {
  52. name string
  53. payload string
  54. hit bool
  55. msg string
  56. }{
  57. {"top-level error", `{"error":{"code":"cyber_policy","message":"flagged"}}`, true, "flagged"},
  58. {"response-wrapped", `{"response":{"error":{"code":"cyber_policy","message":" bad "}}}`, true, "bad"},
  59. {"case-insensitive", `{"error":{"code":"Cyber_Policy"}}`, true, ""},
  60. {"content_policy not cyber", `{"error":{"code":"content_policy","message":"x"}}`, false, ""},
  61. {"safety message not cyber", `{"error":{"type":"safety_error","message":"high-risk cyber activity"}}`, false, ""},
  62. {"empty", ``, false, ""},
  63. {"upstream_error", `{"error":{"code":"upstream_error"}}`, false, ""},
  64. }
  65. for _, tc := range cases {
  66. t.Run(tc.name, func(t *testing.T) {
  67. hit, code, msg := detectOpenAICyberPolicy([]byte(tc.payload))
  68. require.Equal(t, tc.hit, hit)
  69. if tc.hit {
  70. require.Equal(t, "cyber_policy", code)
  71. require.Equal(t, tc.msg, msg)
  72. }
  73. })
  74. }
  75. }