ingress_reject_access_sampler_test.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. package middleware
  2. import (
  3. "net/http"
  4. "net/http/httptest"
  5. "sync"
  6. "sync/atomic"
  7. "testing"
  8. "time"
  9. "github.com/Wei-Shaw/sub2api/internal/pkg/logger"
  10. "github.com/gin-gonic/gin"
  11. "github.com/stretchr/testify/require"
  12. )
  13. func TestIngressRejectAccessSamplerConcurrentGlobalLimit(t *testing.T) {
  14. sampler := newIngressRejectAccessSampler(10, time.Hour, time.Minute)
  15. now := time.Now()
  16. var allowed atomic.Int64
  17. var wg sync.WaitGroup
  18. for i := 0; i < 200; i++ {
  19. wg.Add(1)
  20. go func() {
  21. defer wg.Done()
  22. if ok, _ := sampler.allow(now); ok {
  23. allowed.Add(1)
  24. }
  25. }()
  26. }
  27. wg.Wait()
  28. require.Equal(t, int64(10), allowed.Load())
  29. }
  30. func TestLoggerIngressRejectSamplingIsBoundedAndSummarySkipsOpsSink(t *testing.T) {
  31. gin.SetMode(gin.TestMode)
  32. original := globalIngressRejectAccessSampler
  33. globalIngressRejectAccessSampler = newIngressRejectAccessSampler(2, time.Hour, time.Hour)
  34. t.Cleanup(func() { globalIngressRejectAccessSampler = original })
  35. sink := initMiddlewareTestLogger(t)
  36. router := gin.New()
  37. router.Use(Logger())
  38. router.GET("/v1/messages", func(c *gin.Context) {
  39. MarkIngressRejected(c, IngressRejectInvalidAPIKey)
  40. c.Status(http.StatusUnauthorized)
  41. })
  42. for i := 0; i < 20; i++ {
  43. router.ServeHTTP(httptest.NewRecorder(), httptest.NewRequest(http.MethodGet, "/v1/messages", nil))
  44. }
  45. var accessEvents, summaries int
  46. for _, event := range sink.list() {
  47. switch event.Message {
  48. case "http request completed":
  49. accessEvents++
  50. case "ingress rejection access logs dropped":
  51. summaries++
  52. if skipped, _ := event.Fields[logger.OpsSystemLogSkipField].(bool); !skipped {
  53. t.Fatalf("dropped summary must skip ops system log sink")
  54. }
  55. }
  56. }
  57. require.Equal(t, 2, accessEvents)
  58. require.Equal(t, 1, summaries)
  59. }
  60. func TestIngressRejectAccessSamplerDroppedSummaryIsLowFrequency(t *testing.T) {
  61. sampler := newIngressRejectAccessSampler(1, time.Hour, time.Second)
  62. now := time.Now()
  63. allowed, summary := sampler.allow(now)
  64. require.True(t, allowed)
  65. require.Zero(t, summary)
  66. allowed, summary = sampler.allow(now.Add(100 * time.Millisecond))
  67. require.False(t, allowed)
  68. require.Equal(t, uint64(1), summary)
  69. allowed, summary = sampler.allow(now.Add(200 * time.Millisecond))
  70. require.False(t, allowed)
  71. require.Zero(t, summary)
  72. allowed, summary = sampler.allow(now.Add(2 * time.Second))
  73. require.False(t, allowed)
  74. require.Equal(t, uint64(2), summary)
  75. }