github.com/Jeffail/benthos/v3@v3.65.0/internal/component/processor/processor_v2_test.go (about)

     1  package processor
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"sync"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/Jeffail/benthos/v3/lib/message"
    11  	"github.com/Jeffail/benthos/v3/lib/metrics"
    12  	"github.com/Jeffail/benthos/v3/lib/processor"
    13  	"github.com/Jeffail/benthos/v3/lib/types"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  type fnProcessor struct {
    19  	fn     func(context.Context, types.Part) ([]types.Part, error)
    20  	closed bool
    21  
    22  	sync.Mutex
    23  }
    24  
    25  func (p *fnProcessor) Process(ctx context.Context, msg types.Part) ([]types.Part, error) {
    26  	return p.fn(ctx, msg)
    27  }
    28  
    29  func (p *fnProcessor) Close(ctx context.Context) error {
    30  	p.Lock()
    31  	p.closed = true
    32  	p.Unlock()
    33  	return nil
    34  }
    35  
    36  func TestProcessorAirGapShutdown(t *testing.T) {
    37  	rp := &fnProcessor{}
    38  	agrp := NewV2ToV1Processor("foo", rp, metrics.Noop())
    39  
    40  	err := agrp.WaitForClose(time.Millisecond * 5)
    41  	assert.EqualError(t, err, "action timed out")
    42  	rp.Lock()
    43  	assert.False(t, rp.closed)
    44  	rp.Unlock()
    45  
    46  	agrp.CloseAsync()
    47  	err = agrp.WaitForClose(time.Millisecond * 5)
    48  	assert.NoError(t, err)
    49  	rp.Lock()
    50  	assert.True(t, rp.closed)
    51  	rp.Unlock()
    52  }
    53  
    54  func TestProcessorAirGapOneToOne(t *testing.T) {
    55  	agrp := NewV2ToV1Processor("foo", &fnProcessor{
    56  		fn: func(c context.Context, m types.Part) ([]types.Part, error) {
    57  			if b := m.Get(); string(b) != "unchanged" {
    58  				return nil, errors.New("nope")
    59  			}
    60  			newPart := m.Copy()
    61  			newPart.Set([]byte("changed"))
    62  			return []types.Part{newPart}, nil
    63  		},
    64  	}, metrics.Noop())
    65  
    66  	msg := message.New([][]byte{[]byte("unchanged")})
    67  	msgs, res := agrp.ProcessMessage(msg)
    68  	require.Nil(t, res)
    69  	require.Len(t, msgs, 1)
    70  	assert.Equal(t, 1, msgs[0].Len())
    71  	assert.Equal(t, "changed", string(msgs[0].Get(0).Get()))
    72  	assert.Equal(t, "unchanged", string(msg.Get(0).Get()))
    73  }
    74  
    75  func TestProcessorAirGapOneToError(t *testing.T) {
    76  	agrp := NewV2ToV1Processor("foo", &fnProcessor{
    77  		fn: func(c context.Context, m types.Part) ([]types.Part, error) {
    78  			_, err := m.JSON()
    79  			return nil, err
    80  		},
    81  	}, metrics.Noop())
    82  
    83  	msg := message.New([][]byte{[]byte("not a structured doc")})
    84  	msgs, res := agrp.ProcessMessage(msg)
    85  	require.Nil(t, res)
    86  	require.Len(t, msgs, 1)
    87  	assert.Equal(t, 1, msgs[0].Len())
    88  	assert.Equal(t, "not a structured doc", string(msgs[0].Get(0).Get()))
    89  	assert.Equal(t, "not a structured doc", string(msgs[0].Get(0).Get()))
    90  	assert.Equal(t, "invalid character 'o' in literal null (expecting 'u')", processor.GetFail(msgs[0].Get(0)))
    91  }
    92  
    93  func TestProcessorAirGapOneToMany(t *testing.T) {
    94  	agrp := NewV2ToV1Processor("foo", &fnProcessor{
    95  		fn: func(c context.Context, m types.Part) ([]types.Part, error) {
    96  			if b := m.Get(); string(b) != "unchanged" {
    97  				return nil, errors.New("nope")
    98  			}
    99  			first := m.Copy()
   100  			second := m.Copy()
   101  			third := m.Copy()
   102  			first.Set([]byte("changed 1"))
   103  			second.Set([]byte("changed 2"))
   104  			third.Set([]byte("changed 3"))
   105  			return []types.Part{first, second, third}, nil
   106  		},
   107  	}, metrics.Noop())
   108  
   109  	msg := message.New([][]byte{[]byte("unchanged")})
   110  	msgs, res := agrp.ProcessMessage(msg)
   111  	require.Nil(t, res)
   112  	require.Len(t, msgs, 1)
   113  	assert.Equal(t, 3, msgs[0].Len())
   114  	assert.Equal(t, "changed 1", string(msgs[0].Get(0).Get()))
   115  	assert.Equal(t, "changed 2", string(msgs[0].Get(1).Get()))
   116  	assert.Equal(t, "changed 3", string(msgs[0].Get(2).Get()))
   117  	assert.Equal(t, "unchanged", string(msg.Get(0).Get()))
   118  }
   119  
   120  //------------------------------------------------------------------------------
   121  
   122  type fnBatchProcessor struct {
   123  	fn     func(context.Context, []types.Part) ([][]types.Part, error)
   124  	closed bool
   125  }
   126  
   127  func (p *fnBatchProcessor) ProcessBatch(ctx context.Context, msg []types.Part) ([][]types.Part, error) {
   128  	return p.fn(ctx, msg)
   129  }
   130  
   131  func (p *fnBatchProcessor) Close(ctx context.Context) error {
   132  	p.closed = true
   133  	return nil
   134  }
   135  
   136  func TestBatchProcessorAirGapShutdown(t *testing.T) {
   137  	rp := &fnBatchProcessor{}
   138  	agrp := NewV2BatchedToV1Processor("foo", rp, metrics.Noop())
   139  
   140  	err := agrp.WaitForClose(time.Millisecond * 5)
   141  	assert.EqualError(t, err, "action timed out")
   142  	assert.False(t, rp.closed)
   143  
   144  	agrp.CloseAsync()
   145  	err = agrp.WaitForClose(time.Millisecond * 5)
   146  	assert.NoError(t, err)
   147  	assert.True(t, rp.closed)
   148  }
   149  
   150  func TestBatchProcessorAirGapOneToOne(t *testing.T) {
   151  	agrp := NewV2BatchedToV1Processor("foo", &fnBatchProcessor{
   152  		fn: func(c context.Context, msgs []types.Part) ([][]types.Part, error) {
   153  			if b := msgs[0].Get(); string(b) != "unchanged" {
   154  				return nil, errors.New("nope")
   155  			}
   156  			newMsg := msgs[0].Copy()
   157  			newMsg.Set([]byte("changed"))
   158  			return [][]types.Part{{newMsg}}, nil
   159  		},
   160  	}, metrics.Noop())
   161  
   162  	msg := message.New([][]byte{[]byte("unchanged")})
   163  	msgs, res := agrp.ProcessMessage(msg)
   164  	require.Nil(t, res)
   165  	require.Len(t, msgs, 1)
   166  	assert.Equal(t, 1, msgs[0].Len())
   167  	assert.Equal(t, "changed", string(msgs[0].Get(0).Get()))
   168  	assert.Equal(t, "unchanged", string(msg.Get(0).Get()))
   169  }
   170  
   171  func TestBatchProcessorAirGapOneToError(t *testing.T) {
   172  	agrp := NewV2BatchedToV1Processor("foo", &fnBatchProcessor{
   173  		fn: func(c context.Context, msgs []types.Part) ([][]types.Part, error) {
   174  			_, err := msgs[0].JSON()
   175  			return nil, err
   176  		},
   177  	}, metrics.Noop())
   178  
   179  	msg := message.New([][]byte{[]byte("not a structured doc")})
   180  	msgs, res := agrp.ProcessMessage(msg)
   181  	require.Nil(t, res)
   182  	require.Len(t, msgs, 1)
   183  	assert.Equal(t, 1, msgs[0].Len())
   184  	assert.Equal(t, "not a structured doc", string(msgs[0].Get(0).Get()))
   185  	assert.Equal(t, "not a structured doc", string(msgs[0].Get(0).Get()))
   186  	assert.Equal(t, "invalid character 'o' in literal null (expecting 'u')", processor.GetFail(msgs[0].Get(0)))
   187  }
   188  
   189  func TestBatchProcessorAirGapOneToMany(t *testing.T) {
   190  	agrp := NewV2BatchedToV1Processor("foo", &fnBatchProcessor{
   191  		fn: func(c context.Context, msgs []types.Part) ([][]types.Part, error) {
   192  			if b := msgs[0].Get(); string(b) != "unchanged" {
   193  				return nil, errors.New("nope")
   194  			}
   195  			first := msgs[0].Copy()
   196  			second := msgs[0].Copy()
   197  			third := msgs[0].Copy()
   198  			first.Set([]byte("changed 1"))
   199  			second.Set([]byte("changed 2"))
   200  			third.Set([]byte("changed 3"))
   201  			return [][]types.Part{{first, second}, {third}}, nil
   202  		},
   203  	}, metrics.Noop())
   204  
   205  	msg := message.New([][]byte{[]byte("unchanged")})
   206  	msgs, res := agrp.ProcessMessage(msg)
   207  	require.Nil(t, res)
   208  	require.Len(t, msgs, 2)
   209  	assert.Equal(t, "unchanged", string(msg.Get(0).Get()))
   210  
   211  	assert.Equal(t, 2, msgs[0].Len())
   212  	assert.Equal(t, "changed 1", string(msgs[0].Get(0).Get()))
   213  	assert.Equal(t, "changed 2", string(msgs[0].Get(1).Get()))
   214  
   215  	assert.Equal(t, 1, msgs[1].Len())
   216  	assert.Equal(t, "changed 3", string(msgs[1].Get(0).Get()))
   217  }