github.com/whoyao/protocol@v0.0.0-20230519045905-2d8ace718ca5/webhook/webhook_test.go (about) 1 package webhook 2 3 import ( 4 "context" 5 "net" 6 "net/http" 7 "sync" 8 "testing" 9 "time" 10 11 "github.com/stretchr/testify/require" 12 "go.uber.org/atomic" 13 14 "github.com/whoyao/protocol/auth" 15 "github.com/whoyao/protocol/livekit" 16 ) 17 18 const ( 19 apiKey = "mykey" 20 apiSecret = "mysecret" 21 testAddr = ":8765" 22 testUrl = "http://localhost:8765" 23 webhookCheckInterval = 100 * time.Millisecond 24 ) 25 26 var authProvider = auth.NewSimpleKeyProvider( 27 apiKey, apiSecret, 28 ) 29 30 func TestWebHook(t *testing.T) { 31 s := newServer(testAddr) 32 require.NoError(t, s.Start()) 33 defer s.Stop() 34 35 notifier := NewDefaultNotifier(apiKey, apiSecret, []string{testUrl}) 36 37 t.Run("test event payload", func(t *testing.T) { 38 event := &livekit.WebhookEvent{ 39 Event: EventTrackPublished, 40 Participant: &livekit.ParticipantInfo{ 41 Identity: "test", 42 }, 43 Track: &livekit.TrackInfo{ 44 Sid: "TR_abcde", 45 }, 46 } 47 48 wg := sync.WaitGroup{} 49 wg.Add(1) 50 s.handler = func(r *http.Request) { 51 defer wg.Done() 52 decodedEvent, err := ReceiveWebhookEvent(r, authProvider) 53 require.NoError(t, err) 54 55 require.EqualValues(t, event, decodedEvent) 56 } 57 require.NoError(t, notifier.QueueNotify(context.Background(), event)) 58 wg.Wait() 59 }) 60 61 } 62 63 func TestURLNotifierDropped(t *testing.T) { 64 s := newServer(testAddr) 65 require.NoError(t, s.Start()) 66 defer s.Stop() 67 68 urlNotifier := newTestNotifier() 69 defer urlNotifier.Stop(true) 70 totalDropped := atomic.Int32{} 71 totalReceived := atomic.Int32{} 72 s.handler = func(r *http.Request) { 73 decodedEvent, err := ReceiveWebhookEvent(r, authProvider) 74 require.NoError(t, err) 75 totalReceived.Inc() 76 totalDropped.Add(decodedEvent.NumDropped) 77 } 78 // send multiple notifications 79 for i := 0; i < 10; i++ { 80 _ = urlNotifier.QueueNotify(&livekit.WebhookEvent{Event: EventRoomStarted}) 81 _ = urlNotifier.QueueNotify(&livekit.WebhookEvent{Event: EventParticipantJoined}) 82 _ = urlNotifier.QueueNotify(&livekit.WebhookEvent{Event: EventRoomFinished}) 83 } 84 85 time.Sleep(webhookCheckInterval) 86 87 require.Equal(t, int32(30), totalDropped.Load()+totalReceived.Load()) 88 // at least one request dropped 89 require.Less(t, int32(0), totalDropped.Load()) 90 } 91 92 func TestURLNotifierLifecycle(t *testing.T) { 93 s := newServer(testAddr) 94 require.NoError(t, s.Start()) 95 defer s.Stop() 96 97 t.Run("start/stop without use", func(t *testing.T) { 98 urlNotifier := newTestNotifier() 99 urlNotifier.Stop(false) 100 }) 101 102 t.Run("stop allowing to drain", func(t *testing.T) { 103 urlNotifier := newTestNotifier() 104 numCalled := atomic.Int32{} 105 s.handler = func(r *http.Request) { 106 numCalled.Inc() 107 } 108 for i := 0; i < 10; i++ { 109 _ = urlNotifier.QueueNotify(&livekit.WebhookEvent{Event: EventRoomStarted}) 110 _ = urlNotifier.QueueNotify(&livekit.WebhookEvent{Event: EventRoomFinished}) 111 } 112 urlNotifier.Stop(false) 113 require.Eventually(t, func() bool { return numCalled.Load() == 20 }, 5*time.Second, webhookCheckInterval) 114 }) 115 116 t.Run("force stop", func(t *testing.T) { 117 urlNotifier := newTestNotifier() 118 numCalled := atomic.Int32{} 119 s.handler = func(r *http.Request) { 120 numCalled.Inc() 121 } 122 for i := 0; i < 10; i++ { 123 _ = urlNotifier.QueueNotify(&livekit.WebhookEvent{Event: EventRoomStarted}) 124 _ = urlNotifier.QueueNotify(&livekit.WebhookEvent{Event: EventRoomFinished}) 125 } 126 urlNotifier.Stop(true) 127 time.Sleep(time.Second) 128 require.Greater(t, int32(20), numCalled.Load()) 129 }) 130 } 131 132 func newTestNotifier() *URLNotifier { 133 return NewURLNotifier(URLNotifierParams{ 134 QueueSize: 20, 135 URL: testUrl, 136 APIKey: apiKey, 137 APISecret: apiSecret, 138 }) 139 } 140 141 type testServer struct { 142 handler func(r *http.Request) 143 server *http.Server 144 } 145 146 func newServer(addr string) *testServer { 147 s := &testServer{} 148 s.server = &http.Server{ 149 Addr: addr, 150 Handler: s, 151 } 152 return s 153 } 154 155 func (s *testServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { 156 if s.handler != nil { 157 s.handler(r) 158 } 159 } 160 161 func (s *testServer) Start() error { 162 l, err := net.Listen("tcp", s.server.Addr) 163 if err != nil { 164 return err 165 } 166 go s.server.Serve(l) 167 return nil 168 } 169 170 func (s *testServer) Stop() { 171 _ = s.server.Shutdown(context.Background()) 172 }