github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/pkg/notifier/notifier_test.go (about) 1 // Copyright 2022 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package notifier 15 16 import ( 17 "context" 18 "math" 19 "sync" 20 "testing" 21 "time" 22 23 "github.com/stretchr/testify/require" 24 ) 25 26 func TestNotifierBasics(t *testing.T) { 27 n := NewNotifier[int]() 28 defer n.Close() 29 30 const ( 31 numReceivers = 10 32 numEvents = 10000 33 finEv = math.MaxInt 34 ) 35 var wg sync.WaitGroup 36 37 for i := 0; i < numReceivers; i++ { 38 wg.Add(1) 39 go func() { 40 defer wg.Done() 41 42 r := n.NewReceiver() 43 defer r.Close() 44 45 var ev, lastEv int 46 for { 47 ev = <-r.C 48 49 if ev == finEv { 50 return 51 } 52 53 if lastEv != 0 { 54 require.Equal(t, lastEv+1, ev) 55 } 56 lastEv = ev 57 } 58 }() 59 } 60 61 for i := 1; i <= numEvents; i++ { 62 n.Notify(i) 63 } 64 65 n.Notify(finEv) 66 err := n.Flush(context.Background()) 67 require.NoError(t, err) 68 69 wg.Wait() 70 } 71 72 func TestNotifierClose(t *testing.T) { 73 n := NewNotifier[int]() 74 defer n.Close() 75 76 const ( 77 numReceivers = 1000 78 ) 79 var wg sync.WaitGroup 80 81 for i := 0; i < numReceivers; i++ { 82 wg.Add(1) 83 go func() { 84 defer wg.Done() 85 86 r := n.NewReceiver() 87 defer r.Close() 88 89 _, ok := <-r.C 90 require.False(t, ok) 91 }() 92 } 93 94 time.Sleep(1 * time.Second) 95 n.Close() 96 97 wg.Wait() 98 } 99 100 func TestReceiverClose(t *testing.T) { 101 n := NewNotifier[int]() 102 r := n.NewReceiver() 103 104 // Send enough events to make sure the receiver channel is full. 105 for i := 0; i < 64; i++ { 106 n.Notify(i) 107 } 108 time.Sleep(time.Second) 109 110 // Closing the receiver shouldn't be blocked, although we don't consume the events. 111 doneCh := make(chan struct{}) 112 go func() { 113 r.Close() 114 close(doneCh) 115 }() 116 select { 117 case <-doneCh: 118 case <-time.After(time.Second): 119 t.Fatal("receiver.Close() is blocked") 120 } 121 n.Close() 122 } 123 124 func TestFlushWithClosedNotifier(t *testing.T) { 125 t.Parallel() 126 127 n := NewNotifier[int]() 128 n.Notify(1) 129 n.Close() 130 err := n.Flush(context.Background()) 131 require.Nil(t, err) 132 }