github.com/Jeffail/benthos/v3@v3.65.0/lib/input/reader/async_bundle_unacks_test.go (about)

     1  package reader
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"reflect"
     7  	"sync"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/Jeffail/benthos/v3/lib/message"
    12  	"github.com/Jeffail/benthos/v3/lib/response"
    13  	"github.com/Jeffail/benthos/v3/lib/types"
    14  )
    15  
    16  //------------------------------------------------------------------------------
    17  
    18  func TestAsyncBundleUnacksClose(t *testing.T) {
    19  	t.Parallel()
    20  
    21  	ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
    22  	defer cancel()
    23  
    24  	readerImpl := newMockAsyncReader()
    25  	pres := NewAsyncBundleUnacks(readerImpl)
    26  
    27  	exp := errors.New("foo error")
    28  
    29  	wg := sync.WaitGroup{}
    30  	wg.Add(1)
    31  
    32  	go func() {
    33  		if err := pres.ConnectWithContext(ctx); err != nil {
    34  			t.Error(err)
    35  		}
    36  		pres.CloseAsync()
    37  		if act := pres.WaitForClose(time.Second); act != exp {
    38  			t.Errorf("Wrong error returned: %v != %v", act, exp)
    39  		}
    40  		wg.Done()
    41  	}()
    42  
    43  	select {
    44  	case readerImpl.connChan <- nil:
    45  	case <-time.After(time.Second):
    46  		t.Error("Timed out")
    47  	}
    48  
    49  	select {
    50  	case readerImpl.closeAsyncChan <- struct{}{}:
    51  	case <-time.After(time.Second):
    52  		t.Error("Timed out")
    53  	}
    54  
    55  	select {
    56  	case readerImpl.waitForCloseChan <- exp:
    57  	case <-time.After(time.Second):
    58  		t.Error("Timed out")
    59  	}
    60  
    61  	wg.Wait()
    62  }
    63  
    64  func TestAsyncBundleUnacksBasic(t *testing.T) {
    65  	t.Parallel()
    66  
    67  	ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
    68  	defer cancel()
    69  
    70  	readerImpl := newMockAsyncReader()
    71  	pres := NewAsyncBundleUnacks(readerImpl)
    72  
    73  	expMsgs := [][]byte{
    74  		[]byte("foo"),
    75  		[]byte("bar"),
    76  	}
    77  
    78  	go func() {
    79  		select {
    80  		case readerImpl.connChan <- nil:
    81  		case <-time.After(time.Second):
    82  			t.Error("Timed out")
    83  		}
    84  		for _, p := range expMsgs {
    85  			readerImpl.msgsToSnd = []types.Message{message.New([][]byte{p})}
    86  			select {
    87  			case readerImpl.readChan <- nil:
    88  			case <-time.After(time.Second):
    89  				t.Error("Timed out")
    90  			}
    91  			select {
    92  			case readerImpl.ackChan <- nil:
    93  			case <-time.After(time.Second):
    94  				t.Error("Timed out")
    95  			}
    96  		}
    97  	}()
    98  
    99  	if err := pres.ConnectWithContext(ctx); err != nil {
   100  		t.Error(err)
   101  	}
   102  
   103  	msg, ackFn, err := pres.ReadWithContext(ctx)
   104  	if err != nil {
   105  		t.Fatal(err)
   106  	}
   107  	if act, exp := msg.Get(0).Get(), expMsgs[0]; !reflect.DeepEqual(act, exp) {
   108  		t.Errorf("Wrong message returned: %s != %s", act, exp)
   109  	}
   110  	if err := ackFn(ctx, response.NewAck()); err != nil {
   111  		t.Error(err)
   112  	}
   113  
   114  	msg, ackFn, err = pres.ReadWithContext(ctx)
   115  	if err != nil {
   116  		t.Fatal(err)
   117  	}
   118  	if act, exp := msg.Get(0).Get(), expMsgs[1]; !reflect.DeepEqual(act, exp) {
   119  		t.Errorf("Wrong message returned: %s != %s", act, exp)
   120  	}
   121  	if err := ackFn(ctx, response.NewAck()); err != nil {
   122  		t.Error(err)
   123  	}
   124  
   125  	if exp, act := []error{nil, nil}, readerImpl.ackRcvd; !reflect.DeepEqual(exp, act) {
   126  		t.Errorf("Wrong acks returned: %v != %v", act, exp)
   127  	}
   128  }
   129  
   130  func TestAsyncBundleUnacksHappy(t *testing.T) {
   131  	t.Parallel()
   132  
   133  	ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
   134  	defer cancel()
   135  
   136  	readerImpl := newMockAsyncReader()
   137  	pres := NewAsyncBundleUnacks(readerImpl)
   138  
   139  	expMsgs := [][]byte{
   140  		[]byte("foo"),
   141  		[]byte("bar"),
   142  	}
   143  	for _, p := range expMsgs {
   144  		readerImpl.msgsToSnd = append(readerImpl.msgsToSnd, message.New([][]byte{p}))
   145  	}
   146  
   147  	go func() {
   148  		select {
   149  		case readerImpl.connChan <- nil:
   150  		case <-time.After(time.Second):
   151  			t.Error("Timed out")
   152  		}
   153  		for range expMsgs {
   154  			select {
   155  			case readerImpl.readChan <- nil:
   156  			case <-time.After(time.Second):
   157  				t.Error("Timed out")
   158  			}
   159  		}
   160  		for range expMsgs {
   161  			select {
   162  			case readerImpl.ackChan <- nil:
   163  			case <-time.After(time.Second):
   164  				t.Error("Timed out")
   165  			}
   166  		}
   167  	}()
   168  
   169  	if err := pres.ConnectWithContext(ctx); err != nil {
   170  		t.Error(err)
   171  	}
   172  
   173  	msg, ackFn, err := pres.ReadWithContext(ctx)
   174  	if err != nil {
   175  		t.Fatal(err)
   176  	}
   177  	if act, exp := msg.Get(0).Get(), expMsgs[0]; !reflect.DeepEqual(act, exp) {
   178  		t.Errorf("Wrong message returned: %s != %s", act, exp)
   179  	}
   180  	if err := ackFn(ctx, response.NewUnack()); err != nil {
   181  		t.Error(err)
   182  	}
   183  
   184  	msg, ackFn, err = pres.ReadWithContext(ctx)
   185  	if err != nil {
   186  		t.Fatal(err)
   187  	}
   188  	if act, exp := msg.Get(0).Get(), expMsgs[1]; !reflect.DeepEqual(act, exp) {
   189  		t.Errorf("Wrong message returned: %s != %s", act, exp)
   190  	}
   191  	if err := ackFn(ctx, response.NewAck()); err != nil {
   192  		t.Error(err)
   193  	}
   194  
   195  	if exp, act := []error{nil, nil}, readerImpl.ackRcvd; !reflect.DeepEqual(exp, act) {
   196  		t.Errorf("Wrong acks returned: %v != %v", act, exp)
   197  	}
   198  }
   199  
   200  func TestAsyncBundleUnacksSad(t *testing.T) {
   201  	t.Parallel()
   202  
   203  	ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
   204  	defer cancel()
   205  
   206  	readerImpl := newMockAsyncReader()
   207  	pres := NewAsyncBundleUnacks(readerImpl)
   208  
   209  	expMsgs := [][]byte{
   210  		[]byte("foo"),
   211  		[]byte("bar"),
   212  	}
   213  	for _, p := range expMsgs {
   214  		readerImpl.msgsToSnd = append(readerImpl.msgsToSnd, message.New([][]byte{p}))
   215  	}
   216  
   217  	go func() {
   218  		select {
   219  		case readerImpl.connChan <- nil:
   220  		case <-time.After(time.Second):
   221  			t.Error("Timed out")
   222  		}
   223  		for range expMsgs {
   224  			select {
   225  			case readerImpl.readChan <- nil:
   226  			case <-time.After(time.Second):
   227  				t.Error("Timed out")
   228  			}
   229  		}
   230  		for range expMsgs {
   231  			select {
   232  			case readerImpl.ackChan <- nil:
   233  			case <-time.After(time.Second):
   234  				t.Error("Timed out")
   235  			}
   236  		}
   237  	}()
   238  
   239  	if err := pres.ConnectWithContext(ctx); err != nil {
   240  		t.Error(err)
   241  	}
   242  
   243  	msg, ackFn, err := pres.ReadWithContext(ctx)
   244  	if err != nil {
   245  		t.Fatal(err)
   246  	}
   247  	if act, exp := msg.Get(0).Get(), expMsgs[0]; !reflect.DeepEqual(act, exp) {
   248  		t.Errorf("Wrong message returned: %s != %s", act, exp)
   249  	}
   250  	if err := ackFn(ctx, response.NewUnack()); err != nil {
   251  		t.Error(err)
   252  	}
   253  
   254  	errTest := errors.New("test error")
   255  
   256  	msg, ackFn, err = pres.ReadWithContext(ctx)
   257  	if err != nil {
   258  		t.Fatal(err)
   259  	}
   260  	if act, exp := msg.Get(0).Get(), expMsgs[1]; !reflect.DeepEqual(act, exp) {
   261  		t.Errorf("Wrong message returned: %s != %s", act, exp)
   262  	}
   263  	if err := ackFn(ctx, response.NewError(errTest)); err != nil {
   264  		t.Error(err)
   265  	}
   266  
   267  	if exp, act := []error{errTest, errTest}, readerImpl.ackRcvd; !reflect.DeepEqual(exp, act) {
   268  		t.Errorf("Wrong acks returned: %v != %v", act, exp)
   269  	}
   270  }
   271  
   272  func TestAsyncBundleUnacksSadTwo(t *testing.T) {
   273  	t.Parallel()
   274  
   275  	ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
   276  	defer cancel()
   277  
   278  	readerImpl := newMockAsyncReader()
   279  	pres := NewAsyncBundleUnacks(readerImpl)
   280  
   281  	expMsgs := [][]byte{
   282  		[]byte("foo"),
   283  		[]byte("bar"),
   284  	}
   285  	for _, p := range expMsgs {
   286  		readerImpl.msgsToSnd = append(readerImpl.msgsToSnd, message.New([][]byte{p}))
   287  	}
   288  
   289  	errFirstAck := errors.New("error returned by first ack")
   290  	errSecondAck := errors.New("error returned by second ack")
   291  
   292  	go func() {
   293  		select {
   294  		case readerImpl.connChan <- nil:
   295  		case <-time.After(time.Second):
   296  			t.Error("Timed out")
   297  		}
   298  		for range expMsgs {
   299  			select {
   300  			case readerImpl.readChan <- nil:
   301  			case <-time.After(time.Second):
   302  				t.Error("Timed out")
   303  			}
   304  		}
   305  		select {
   306  		case readerImpl.ackChan <- errFirstAck:
   307  		case <-time.After(time.Second):
   308  			t.Error("Timed out")
   309  		}
   310  		select {
   311  		case readerImpl.ackChan <- errSecondAck:
   312  		case <-time.After(time.Second):
   313  			t.Error("Timed out")
   314  		}
   315  	}()
   316  
   317  	if err := pres.ConnectWithContext(ctx); err != nil {
   318  		t.Error(err)
   319  	}
   320  
   321  	msg, ackFn, err := pres.ReadWithContext(ctx)
   322  	if err != nil {
   323  		t.Fatal(err)
   324  	}
   325  	if act, exp := msg.Get(0).Get(), expMsgs[0]; !reflect.DeepEqual(act, exp) {
   326  		t.Errorf("Wrong message returned: %s != %s", act, exp)
   327  	}
   328  	if err := ackFn(ctx, response.NewUnack()); err != nil {
   329  		t.Error(err)
   330  	}
   331  
   332  	errTest := errors.New("test error")
   333  
   334  	msg, ackFn, err = pres.ReadWithContext(ctx)
   335  	if err != nil {
   336  		t.Fatal(err)
   337  	}
   338  	if act, exp := msg.Get(0).Get(), expMsgs[1]; !reflect.DeepEqual(act, exp) {
   339  		t.Errorf("Wrong message returned: %s != %s", act, exp)
   340  	}
   341  	if act, exp := ackFn(ctx, response.NewError(errTest)).Error(), "failed to send grouped acknowledgements: [error returned by first ack error returned by second ack]"; act != exp {
   342  		t.Errorf("Wrong error returned: %v != %v", act, exp)
   343  	}
   344  
   345  	if exp, act := []error{errTest, errTest}, readerImpl.ackRcvd; !reflect.DeepEqual(exp, act) {
   346  		t.Errorf("Wrong acks returned: %v != %v", act, exp)
   347  	}
   348  }
   349  
   350  func TestAsyncBundleUnacksSadThree(t *testing.T) {
   351  	t.Parallel()
   352  
   353  	ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
   354  	defer cancel()
   355  
   356  	readerImpl := newMockAsyncReader()
   357  	pres := NewAsyncBundleUnacks(readerImpl)
   358  
   359  	expMsgs := [][]byte{
   360  		[]byte("foo"),
   361  		[]byte("bar"),
   362  	}
   363  	for _, p := range expMsgs {
   364  		readerImpl.msgsToSnd = append(readerImpl.msgsToSnd, message.New([][]byte{p}))
   365  	}
   366  
   367  	errFirstAck := errors.New("error returned by first ack")
   368  
   369  	go func() {
   370  		select {
   371  		case readerImpl.connChan <- nil:
   372  		case <-time.After(time.Second):
   373  			t.Error("Timed out")
   374  		}
   375  		for range expMsgs {
   376  			select {
   377  			case readerImpl.readChan <- nil:
   378  			case <-time.After(time.Second):
   379  				t.Error("Timed out")
   380  			}
   381  		}
   382  		select {
   383  		case readerImpl.ackChan <- nil:
   384  		case <-time.After(time.Second):
   385  			t.Error("Timed out")
   386  		}
   387  		select {
   388  		case readerImpl.ackChan <- errFirstAck:
   389  		case <-time.After(time.Second):
   390  			t.Error("Timed out")
   391  		}
   392  	}()
   393  
   394  	if err := pres.ConnectWithContext(ctx); err != nil {
   395  		t.Error(err)
   396  	}
   397  
   398  	msg, ackFn, err := pres.ReadWithContext(ctx)
   399  	if err != nil {
   400  		t.Fatal(err)
   401  	}
   402  	if act, exp := msg.Get(0).Get(), expMsgs[0]; !reflect.DeepEqual(act, exp) {
   403  		t.Errorf("Wrong message returned: %s != %s", act, exp)
   404  	}
   405  	if err := ackFn(ctx, response.NewUnack()); err != nil {
   406  		t.Error(err)
   407  	}
   408  
   409  	errTest := errors.New("test error")
   410  
   411  	msg, ackFn, err = pres.ReadWithContext(ctx)
   412  	if err != nil {
   413  		t.Fatal(err)
   414  	}
   415  	if act, exp := msg.Get(0).Get(), expMsgs[1]; !reflect.DeepEqual(act, exp) {
   416  		t.Errorf("Wrong message returned: %s != %s", act, exp)
   417  	}
   418  	if act, exp := ackFn(ctx, response.NewError(errTest)).Error(), "error returned by first ack"; act != exp {
   419  		t.Errorf("Wrong error returned: %v != %v", act, exp)
   420  	}
   421  
   422  	if exp, act := []error{errTest, errTest}, readerImpl.ackRcvd; !reflect.DeepEqual(exp, act) {
   423  		t.Errorf("Wrong acks returned: %v != %v", act, exp)
   424  	}
   425  }
   426  
   427  //------------------------------------------------------------------------------