github.com/Jeffail/benthos/v3@v3.65.0/lib/buffer/parallel_wrapper_test.go (about)

     1  package buffer
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/Jeffail/benthos/v3/lib/buffer/parallel"
     8  	"github.com/Jeffail/benthos/v3/lib/log"
     9  	"github.com/Jeffail/benthos/v3/lib/message"
    10  	"github.com/Jeffail/benthos/v3/lib/metrics"
    11  	"github.com/Jeffail/benthos/v3/lib/response"
    12  	"github.com/Jeffail/benthos/v3/lib/types"
    13  )
    14  
    15  //------------------------------------------------------------------------------
    16  
    17  func TestParallelMemoryBuffer(t *testing.T) {
    18  	var incr, total uint8 = 100, 50
    19  
    20  	tChan := make(chan types.Transaction)
    21  	resChan := make(chan types.Response)
    22  
    23  	conf := NewConfig()
    24  	b := NewParallelWrapper(
    25  		conf, parallel.NewMemory(int(incr)*int(total)),
    26  		log.Noop(), metrics.Noop(),
    27  	)
    28  	if err := b.Consume(tChan); err != nil {
    29  		t.Fatal(err)
    30  	}
    31  
    32  	var i uint8
    33  
    34  	// Check correct flow no blocking
    35  	for ; i < total; i++ {
    36  		msgBytes := make([][]byte, 1)
    37  		msgBytes[0] = make([]byte, int(incr))
    38  		msgBytes[0][0] = i
    39  
    40  		select {
    41  		// Send to buffer
    42  		case tChan <- types.NewTransaction(message.New(msgBytes), resChan):
    43  		case <-time.After(time.Second):
    44  			t.Errorf("Timed out waiting for unbuffered message %v send", i)
    45  			return
    46  		}
    47  
    48  		// Instant response from buffer
    49  		select {
    50  		case res := <-resChan:
    51  			if res.Error() != nil {
    52  				t.Error(res.Error())
    53  			}
    54  		case <-time.After(time.Second):
    55  			t.Errorf("Timed out waiting for unbuffered message %v response", i)
    56  			return
    57  		}
    58  
    59  		// Receive on output
    60  		var outTr types.Transaction
    61  		select {
    62  		case outTr = <-b.TransactionChan():
    63  			if actual := outTr.Payload.Get(0).Get()[0]; actual != i {
    64  				t.Errorf("Wrong order receipt of unbuffered message receive: %v != %v", actual, i)
    65  			}
    66  		case <-time.After(time.Second):
    67  			t.Errorf("Timed out waiting for unbuffered message %v read", i)
    68  			return
    69  		}
    70  
    71  		// Response from output
    72  		select {
    73  		case outTr.ResponseChan <- response.NewAck():
    74  		case <-time.After(time.Second):
    75  			t.Errorf("Timed out waiting for unbuffered response send back %v", i)
    76  			return
    77  		}
    78  	}
    79  
    80  	for i = 0; i < total; i++ {
    81  		msgBytes := make([][]byte, 1)
    82  		msgBytes[0] = make([]byte, int(incr))
    83  		msgBytes[0][0] = i
    84  
    85  		select {
    86  		case tChan <- types.NewTransaction(message.New(msgBytes), resChan):
    87  		case <-time.After(time.Second):
    88  			t.Errorf("Timed out waiting for buffered message %v send", i)
    89  			return
    90  		}
    91  		select {
    92  		case res := <-resChan:
    93  			if res.Error() != nil {
    94  				t.Error(res.Error())
    95  			}
    96  		case <-time.After(time.Second):
    97  			t.Errorf("Timed out waiting for buffered message %v response", i)
    98  			return
    99  		}
   100  	}
   101  
   102  	// Should have reached limit here
   103  	msgBytes := make([][]byte, 1)
   104  	msgBytes[0] = make([]byte, int(incr))
   105  
   106  	select {
   107  	case tChan <- types.NewTransaction(message.New(msgBytes), resChan):
   108  	case <-time.After(time.Second):
   109  		t.Errorf("Timed out waiting for final buffered message send")
   110  		return
   111  	}
   112  
   113  	// Response should block until buffer is relieved
   114  	select {
   115  	case res := <-resChan:
   116  		if res.Error() != nil {
   117  			t.Error(res.Error())
   118  		} else {
   119  			t.Errorf("Overflowed response returned before timeout")
   120  		}
   121  		return
   122  	case <-time.After(100 * time.Millisecond):
   123  	}
   124  
   125  	var outTr types.Transaction
   126  
   127  	// Extract last message
   128  	select {
   129  	case outTr = <-b.TransactionChan():
   130  		if actual := outTr.Payload.Get(0).Get()[0]; actual != 0 {
   131  			t.Errorf("Wrong order receipt of buffered message receive: %v != %v", actual, 0)
   132  		}
   133  		outTr.ResponseChan <- response.NewAck()
   134  	case <-time.After(time.Second):
   135  		t.Errorf("Timed out waiting for final buffered message read")
   136  		return
   137  	}
   138  
   139  	// Response from the last attempt should no longer be blocking
   140  	select {
   141  	case res := <-resChan:
   142  		if res.Error() != nil {
   143  			t.Error(res.Error())
   144  		}
   145  	case <-time.After(100 * time.Millisecond):
   146  		t.Errorf("Final buffered response blocked")
   147  	}
   148  
   149  	// Extract all other messages
   150  	for i = 1; i < total; i++ {
   151  		select {
   152  		case outTr = <-b.TransactionChan():
   153  			if actual := outTr.Payload.Get(0).Get()[0]; actual != i {
   154  				t.Errorf("Wrong order receipt of buffered message: %v != %v", actual, i)
   155  			}
   156  		case <-time.After(time.Second):
   157  			t.Errorf("Timed out waiting for buffered message %v read", i)
   158  			return
   159  		}
   160  
   161  		select {
   162  		case outTr.ResponseChan <- response.NewAck():
   163  		case <-time.After(time.Second):
   164  			t.Errorf("Timed out waiting for buffered response send back %v", i)
   165  			return
   166  		}
   167  	}
   168  
   169  	// Get final message
   170  	select {
   171  	case outTr = <-b.TransactionChan():
   172  	case <-time.After(time.Second):
   173  		t.Errorf("Timed out waiting for buffered message %v read", i)
   174  		return
   175  	}
   176  
   177  	select {
   178  	case outTr.ResponseChan <- response.NewAck():
   179  	case <-time.After(time.Second):
   180  		t.Errorf("Timed out waiting for buffered response send back %v", i)
   181  		return
   182  	}
   183  
   184  	b.CloseAsync()
   185  	b.WaitForClose(time.Second)
   186  
   187  	close(resChan)
   188  	close(tChan)
   189  }
   190  
   191  func TestParallelBufferClosing(t *testing.T) {
   192  	var incr, total uint8 = 100, 5
   193  
   194  	tChan := make(chan types.Transaction)
   195  	resChan := make(chan types.Response)
   196  
   197  	conf := NewConfig()
   198  	b := NewParallelWrapper(
   199  		conf, parallel.NewMemory(int(incr)*int(total)),
   200  		log.Noop(), metrics.Noop(),
   201  	)
   202  	if err := b.Consume(tChan); err != nil {
   203  		t.Fatal(err)
   204  	}
   205  
   206  	var i uint8
   207  
   208  	// Populate buffer with some messages
   209  	for i = 0; i < total; i++ {
   210  		msgBytes := make([][]byte, 1)
   211  		msgBytes[0] = make([]byte, int(incr))
   212  		msgBytes[0][0] = i
   213  
   214  		select {
   215  		case tChan <- types.NewTransaction(message.New(msgBytes), resChan):
   216  		case <-time.After(time.Second):
   217  			t.Errorf("Timed out waiting for buffered message %v send", i)
   218  			return
   219  		}
   220  		select {
   221  		case res := <-resChan:
   222  			if res.Error() != nil {
   223  				t.Error(res.Error())
   224  			}
   225  		case <-time.After(time.Second):
   226  			t.Errorf("Timed out waiting for buffered message %v response", i)
   227  			return
   228  		}
   229  	}
   230  
   231  	// Close input, this should prompt the stack buffer to CloseOnceEmpty().
   232  	close(tChan)
   233  
   234  	// Receive all of those messages from the buffer
   235  	for i = 0; i < total; i++ {
   236  		select {
   237  		case val := <-b.TransactionChan():
   238  			if actual := val.Payload.Get(0).Get()[0]; actual != i {
   239  				t.Errorf("Wrong order receipt of buffered message receive: %v != %v", actual, i)
   240  			}
   241  			val.ResponseChan <- response.NewAck()
   242  		case <-time.After(time.Second):
   243  			t.Errorf("Timed out waiting for final buffered message read")
   244  			return
   245  		}
   246  	}
   247  
   248  	// The buffer should now be closed, therefore so should our read channel.
   249  	select {
   250  	case _, open := <-b.TransactionChan():
   251  		if open {
   252  			t.Error("Reader channel still open after clearing buffer")
   253  		}
   254  	case <-time.After(time.Second):
   255  		t.Errorf("Timed out waiting for final buffered message read")
   256  		return
   257  	}
   258  
   259  	// Should already be shut down.
   260  	b.WaitForClose(time.Second)
   261  }
   262  
   263  func BenchmarkParallelMem(b *testing.B) {
   264  	tChan := make(chan types.Transaction)
   265  	resChan := make(chan types.Response)
   266  
   267  	conf := NewConfig()
   268  	buffer := NewParallelWrapper(
   269  		conf, parallel.NewMemory(50000000),
   270  		log.Noop(), metrics.Noop(),
   271  	)
   272  	if err := buffer.Consume(tChan); err != nil {
   273  		b.Fatal(err)
   274  	}
   275  
   276  	contents := [][]byte{
   277  		make([]byte, 1024*1024*1),
   278  	}
   279  
   280  	b.ReportAllocs()
   281  	b.ResetTimer()
   282  	for i := 0; i < b.N; i++ {
   283  		select {
   284  		case tChan <- types.NewTransaction(message.New(contents), resChan):
   285  		case <-time.After(time.Second):
   286  			b.Errorf("Timed out waiting for buffered message %v send", i)
   287  			return
   288  		}
   289  		select {
   290  		case res := <-resChan:
   291  			if res.Error() != nil {
   292  				b.Error(res.Error())
   293  			}
   294  		case <-time.After(time.Second):
   295  			b.Errorf("Timed out waiting for buffered message %v response", i)
   296  			return
   297  		}
   298  
   299  		select {
   300  		case val := <-buffer.TransactionChan():
   301  			val.ResponseChan <- response.NewAck()
   302  		case <-time.After(time.Second):
   303  			b.Errorf("Timed out waiting for final buffered message read")
   304  			return
   305  		}
   306  	}
   307  	b.StopTimer()
   308  
   309  	buffer.CloseAsync()
   310  	buffer.WaitForClose(time.Second)
   311  }
   312  
   313  //------------------------------------------------------------------------------