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  //------------------------------------------------------------------------------