github.com/Jeffail/benthos/v3@v3.65.0/lib/input/reader/preserver_test.go (about) 1 package reader 2 3 import ( 4 "errors" 5 "reflect" 6 "sync" 7 "testing" 8 "time" 9 10 "github.com/Jeffail/benthos/v3/lib/message" 11 "github.com/Jeffail/benthos/v3/lib/types" 12 ) 13 14 //------------------------------------------------------------------------------ 15 16 type mockReader struct { 17 msgToSnd types.Message 18 ackRcvd error 19 20 connChan chan error 21 readChan chan error 22 ackChan chan error 23 closeAsyncChan chan struct{} 24 waitForCloseChan chan error 25 } 26 27 func newMockReader() *mockReader { 28 return &mockReader{ 29 connChan: make(chan error), 30 readChan: make(chan error), 31 ackChan: make(chan error), 32 closeAsyncChan: make(chan struct{}), 33 waitForCloseChan: make(chan error), 34 } 35 } 36 37 func (r *mockReader) Connect() error { 38 return <-r.connChan 39 } 40 func (r *mockReader) Read() (types.Message, error) { 41 if err := <-r.readChan; err != nil { 42 return nil, err 43 } 44 return r.msgToSnd, nil 45 } 46 func (r *mockReader) Acknowledge(err error) error { 47 r.ackRcvd = err 48 return <-r.ackChan 49 } 50 func (r *mockReader) CloseAsync() { 51 <-r.closeAsyncChan 52 } 53 func (r *mockReader) WaitForClose(time.Duration) error { 54 return <-r.waitForCloseChan 55 } 56 57 //------------------------------------------------------------------------------ 58 59 func TestPreserverClose(t *testing.T) { 60 t.Parallel() 61 62 readerImpl := newMockReader() 63 pres := NewPreserver(readerImpl) 64 65 exp := errors.New("foo error") 66 67 wg := sync.WaitGroup{} 68 wg.Add(1) 69 70 go func() { 71 if err := pres.Connect(); err != nil { 72 t.Error(err) 73 } 74 pres.CloseAsync() 75 if act := pres.WaitForClose(time.Second); act != exp { 76 t.Errorf("Wrong error returned: %v != %v", act, exp) 77 } 78 wg.Done() 79 }() 80 81 select { 82 case readerImpl.connChan <- nil: 83 case <-time.After(time.Second): 84 t.Error("Timed out") 85 } 86 87 select { 88 case readerImpl.closeAsyncChan <- struct{}{}: 89 case <-time.After(time.Second): 90 t.Error("Timed out") 91 } 92 93 select { 94 case readerImpl.waitForCloseChan <- exp: 95 case <-time.After(time.Second): 96 t.Error("Timed out") 97 } 98 99 wg.Wait() 100 } 101 102 func TestPreserverHappy(t *testing.T) { 103 t.Parallel() 104 105 readerImpl := newMockReader() 106 pres := NewPreserver(readerImpl) 107 108 expParts := [][]byte{ 109 []byte("foo"), 110 } 111 112 go func() { 113 select { 114 case readerImpl.connChan <- nil: 115 case <-time.After(time.Second): 116 t.Error("Timed out") 117 } 118 for _, p := range expParts { 119 readerImpl.msgToSnd = message.New([][]byte{p}) 120 select { 121 case readerImpl.readChan <- nil: 122 case <-time.After(time.Second): 123 t.Error("Timed out") 124 } 125 } 126 }() 127 128 if err := pres.Connect(); err != nil { 129 t.Error(err) 130 } 131 132 for _, exp := range expParts { 133 msg, err := pres.Read() 134 if err != nil { 135 t.Fatal(err) 136 } 137 if act := msg.Get(0).Get(); !reflect.DeepEqual(act, exp) { 138 t.Errorf("Wrong message returned: %v != %v", act, exp) 139 } 140 } 141 } 142 143 func TestPreserverErrorProp(t *testing.T) { 144 t.Parallel() 145 146 readerImpl := newMockReader() 147 pres := NewPreserver(readerImpl) 148 149 expErr := errors.New("foo") 150 151 go func() { 152 select { 153 case readerImpl.connChan <- expErr: 154 case <-time.After(time.Second): 155 t.Error("Timed out") 156 } 157 select { 158 case readerImpl.readChan <- expErr: 159 case <-time.After(time.Second): 160 t.Error("Timed out") 161 } 162 select { 163 case readerImpl.readChan <- nil: 164 case <-time.After(time.Second): 165 t.Error("Timed out") 166 } 167 select { 168 case readerImpl.ackChan <- expErr: 169 case <-time.After(time.Second): 170 t.Error("Timed out") 171 } 172 }() 173 174 if actErr := pres.Connect(); expErr != actErr { 175 t.Errorf("Wrong error returned: %v != %v", actErr, expErr) 176 } 177 if _, actErr := pres.Read(); expErr != actErr { 178 t.Errorf("Wrong error returned: %v != %v", actErr, expErr) 179 } 180 if _, actErr := pres.Read(); actErr != nil { 181 t.Fatal(actErr) 182 } 183 if actErr := pres.Acknowledge(nil); expErr != actErr { 184 t.Errorf("Wrong error returned: %v != %v", actErr, expErr) 185 } 186 } 187 188 //------------------------------------------------------------------------------ 189 190 func TestPreserverBuffer(t *testing.T) { 191 t.Parallel() 192 193 readerImpl := newMockReader() 194 pres := NewPreserver(readerImpl) 195 196 sendMsg := func(content string) { 197 readerImpl.msgToSnd = message.New( 198 [][]byte{[]byte(content)}, 199 ) 200 select { 201 case readerImpl.readChan <- nil: 202 case <-time.After(time.Second): 203 t.Error("Timed out") 204 } 205 } 206 sendAck := func() { 207 select { 208 case readerImpl.ackChan <- nil: 209 case <-time.After(time.Second): 210 t.Error("Timed out") 211 } 212 } 213 214 // Send message normally. 215 exp := "msg 1" 216 exp2 := "msg 2" 217 exp3 := "msg 3" 218 219 go sendMsg(exp) 220 msg, err := pres.Read() 221 if err != nil { 222 t.Fatal(err) 223 } 224 if act := string(msg.Get(0).Get()); exp != act { 225 t.Errorf("Wrong message returned: %v != %v", act, exp) 226 } 227 228 // Prime second message. 229 go sendMsg(exp2) 230 231 // Fail previous message, expecting it to be resent. 232 pres.Acknowledge(errors.New("failed")) 233 msg, err = pres.Read() 234 if err != nil { 235 t.Fatal(err) 236 } 237 if act := string(msg.Get(0).Get()); exp != act { 238 t.Errorf("Wrong message returned: %v != %v", act, exp) 239 } 240 241 // Read the primed message. 242 msg, err = pres.Read() 243 if err != nil { 244 t.Fatal(err) 245 } 246 if act := string(msg.Get(0).Get()); exp2 != act { 247 t.Errorf("Wrong message returned: %v != %v", act, exp2) 248 } 249 250 // Fail both messages, expecting them to be resent. 251 pres.Acknowledge(errors.New("failed again")) 252 253 // Read both messages. 254 msg, err = pres.Read() 255 if err != nil { 256 t.Fatal(err) 257 } 258 if act := string(msg.Get(0).Get()); exp != act { 259 t.Errorf("Wrong message returned: %v != %v", act, exp) 260 } 261 msg, err = pres.Read() 262 if err != nil { 263 t.Fatal(err) 264 } 265 if act := string(msg.Get(0).Get()); exp2 != act { 266 t.Errorf("Wrong message returned: %v != %v", act, exp2) 267 } 268 269 // Prime a new message and also an acknowledgement. 270 go sendMsg(exp3) 271 go sendAck() 272 273 // Ack all messages. 274 pres.Acknowledge(nil) 275 276 msg, err = pres.Read() 277 if err != nil { 278 t.Fatal(err) 279 } 280 if act := string(msg.Get(0).Get()); exp3 != act { 281 t.Errorf("Wrong message returned: %v != %v", act, exp3) 282 } 283 } 284 285 func TestPreserverBufferBatchedAcks(t *testing.T) { 286 t.Parallel() 287 288 readerImpl := newMockReader() 289 pres := NewPreserver(readerImpl) 290 291 sendMsg := func(content string) { 292 readerImpl.msgToSnd = message.New( 293 [][]byte{[]byte(content)}, 294 ) 295 select { 296 case readerImpl.readChan <- nil: 297 case <-time.After(time.Second): 298 t.Error("Timed out") 299 } 300 } 301 sendAck := func() { 302 select { 303 case readerImpl.ackChan <- nil: 304 case <-time.After(time.Second): 305 t.Error("Timed out") 306 } 307 } 308 309 messages := []string{ 310 "msg 1", 311 "msg 2", 312 "msg 3", 313 } 314 315 for _, exp := range messages { 316 go sendMsg(exp) 317 msg, err := pres.Read() 318 if err != nil { 319 t.Fatal(err) 320 } 321 if act := string(msg.Get(0).Get()); exp != act { 322 t.Errorf("Wrong message returned: %v != %v", act, exp) 323 } 324 } 325 326 // Fail all messages, expecting them to be resent. 327 pres.Acknowledge(errors.New("failed again")) 328 329 for _, exp := range messages { 330 // If we ack all messages now, this shouldnt be propagated to underlying 331 // until the resends are completed. 332 pres.Acknowledge(nil) 333 334 msg, err := pres.Read() 335 if err != nil { 336 t.Fatal(err) 337 } 338 if act := string(msg.Get(0).Get()); exp != act { 339 t.Errorf("Wrong message returned: %v != %v", act, exp) 340 } 341 } 342 343 // Ack all messages. 344 go pres.Acknowledge(nil) 345 346 sendAck() 347 } 348 349 //------------------------------------------------------------------------------