github.com/Jeffail/benthos/v3@v3.65.0/lib/output/writer/sqs_test.go (about)

     1  package writer
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"testing"
     8  
     9  	"github.com/Jeffail/benthos/v3/lib/log"
    10  	"github.com/Jeffail/benthos/v3/lib/message"
    11  	"github.com/Jeffail/benthos/v3/lib/metrics"
    12  	"github.com/Jeffail/benthos/v3/lib/types"
    13  	"github.com/aws/aws-sdk-go/aws"
    14  	"github.com/aws/aws-sdk-go/service/sqs"
    15  	"github.com/aws/aws-sdk-go/service/sqs/sqsiface"
    16  	"github.com/stretchr/testify/assert"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  func TestSQSHeaderCheck(t *testing.T) {
    21  	type testCase struct {
    22  		k, v     string
    23  		expected bool
    24  	}
    25  
    26  	tests := []testCase{
    27  		{
    28  			k: "foo", v: "bar",
    29  			expected: true,
    30  		},
    31  		{
    32  			k: "foo.bar", v: "bar.baz",
    33  			expected: true,
    34  		},
    35  		{
    36  			k: "foo_bar", v: "bar_baz",
    37  			expected: true,
    38  		},
    39  		{
    40  			k: "foo-bar", v: "bar-baz",
    41  			expected: true,
    42  		},
    43  		{
    44  			k: ".foo", v: "bar",
    45  			expected: false,
    46  		},
    47  		{
    48  			k: "foo", v: ".bar",
    49  			expected: true,
    50  		},
    51  		{
    52  			k: "f..oo", v: "bar",
    53  			expected: false,
    54  		},
    55  		{
    56  			k: "foo", v: "ba..r",
    57  			expected: true,
    58  		},
    59  		{
    60  			k: "aws.foo", v: "bar",
    61  			expected: false,
    62  		},
    63  		{
    64  			k: "amazon.foo", v: "bar",
    65  			expected: false,
    66  		},
    67  		{
    68  			k: "foo.", v: "bar",
    69  			expected: false,
    70  		},
    71  		{
    72  			k: "foo", v: "bar.",
    73  			expected: true,
    74  		},
    75  		{
    76  			k: "fo$o", v: "bar",
    77  			expected: false,
    78  		},
    79  		{
    80  			k: "foo", v: "ba$r",
    81  			expected: true,
    82  		},
    83  		{
    84  			k: "foo_with_10_numbers", v: "bar",
    85  			expected: true,
    86  		},
    87  		{
    88  			k: "foo", v: "bar_with_10_numbers and a space",
    89  			expected: true,
    90  		},
    91  		{
    92  			k: "foo with space", v: "bar",
    93  			expected: false,
    94  		},
    95  		{
    96  			k: "iso_date", v: "1997-07-16T19:20:30.45+01:00",
    97  			expected: true,
    98  		},
    99  		{
   100  			k: "has_a_char_in_the_valid_range", v: "#x9 | #xA | #xD | #x20 to #xD7FF | #xE000 to #xFFFD | #x10000 to #x10FFFF - Ѱ",
   101  			expected: true,
   102  		},
   103  	}
   104  
   105  	for i, test := range tests {
   106  		if act, exp := isValidSQSAttribute(test.k, test.v), test.expected; act != exp {
   107  			t.Errorf("Unexpected result for test '%v': %v != %v", i, act, exp)
   108  		}
   109  	}
   110  }
   111  
   112  type mockSqs struct {
   113  	sqsiface.SQSAPI
   114  	fn func(*sqs.SendMessageBatchInput) (*sqs.SendMessageBatchOutput, error)
   115  }
   116  
   117  func (m *mockSqs) SendMessageBatch(input *sqs.SendMessageBatchInput) (*sqs.SendMessageBatchOutput, error) {
   118  	return m.fn(input)
   119  }
   120  
   121  type inMsg struct {
   122  	id      string
   123  	content string
   124  }
   125  type inEntries []inMsg
   126  
   127  func TestSQSRetries(t *testing.T) {
   128  	tCtx := context.Background()
   129  
   130  	conf := NewAmazonSQSConfig()
   131  	w, err := NewAmazonSQSV2(conf, types.NoopMgr(), log.Noop(), metrics.Noop())
   132  	require.NoError(t, err)
   133  
   134  	var in []inEntries
   135  	var out []*sqs.SendMessageBatchOutput
   136  	w.sqs = &mockSqs{
   137  		fn: func(smbi *sqs.SendMessageBatchInput) (*sqs.SendMessageBatchOutput, error) {
   138  			var e inEntries
   139  			for _, entry := range smbi.Entries {
   140  				e = append(e, inMsg{
   141  					id:      *entry.Id,
   142  					content: *entry.MessageBody,
   143  				})
   144  			}
   145  			in = append(in, e)
   146  
   147  			if len(out) == 0 {
   148  				return nil, errors.New("ran out of mock outputs")
   149  			}
   150  			outBatch := out[0]
   151  			out = out[1:]
   152  			return outBatch, nil
   153  		},
   154  	}
   155  
   156  	out = []*sqs.SendMessageBatchOutput{
   157  		{
   158  			Failed: []*sqs.BatchResultErrorEntry{
   159  				{
   160  					Code:        aws.String("xx"),
   161  					Id:          aws.String("1"),
   162  					Message:     aws.String("test error"),
   163  					SenderFault: aws.Bool(false),
   164  				},
   165  			},
   166  		},
   167  		{},
   168  	}
   169  
   170  	inMsg := message.New([][]byte{
   171  		[]byte("hello world 1"),
   172  		[]byte("hello world 2"),
   173  		[]byte("hello world 3"),
   174  	})
   175  	require.NoError(t, w.WriteWithContext(tCtx, inMsg))
   176  
   177  	assert.Equal(t, []inEntries{
   178  		{
   179  			{id: "0", content: "hello world 1"},
   180  			{id: "1", content: "hello world 2"},
   181  			{id: "2", content: "hello world 3"},
   182  		},
   183  		{
   184  			{id: "1", content: "hello world 2"},
   185  		},
   186  	}, in)
   187  }
   188  
   189  func TestSQSSendLimit(t *testing.T) {
   190  	tCtx := context.Background()
   191  
   192  	conf := NewAmazonSQSConfig()
   193  	w, err := NewAmazonSQSV2(conf, types.NoopMgr(), log.Noop(), metrics.Noop())
   194  	require.NoError(t, err)
   195  
   196  	var in []inEntries
   197  	var out []*sqs.SendMessageBatchOutput
   198  	w.sqs = &mockSqs{
   199  		fn: func(smbi *sqs.SendMessageBatchInput) (*sqs.SendMessageBatchOutput, error) {
   200  			var e inEntries
   201  			for _, entry := range smbi.Entries {
   202  				e = append(e, inMsg{
   203  					id:      *entry.Id,
   204  					content: *entry.MessageBody,
   205  				})
   206  			}
   207  			in = append(in, e)
   208  
   209  			if len(out) == 0 {
   210  				return nil, errors.New("ran out of mock outputs")
   211  			}
   212  			outBatch := out[0]
   213  			out = out[1:]
   214  			return outBatch, nil
   215  		},
   216  	}
   217  
   218  	out = []*sqs.SendMessageBatchOutput{
   219  		{}, {},
   220  	}
   221  
   222  	inMsg := message.New(nil)
   223  	for i := 0; i < 15; i++ {
   224  		inMsg.Append(message.NewPart([]byte(fmt.Sprintf("hello world %v", i+1))))
   225  	}
   226  	require.NoError(t, w.WriteWithContext(tCtx, inMsg))
   227  
   228  	assert.Equal(t, []inEntries{
   229  		{
   230  			{id: "0", content: "hello world 1"},
   231  			{id: "1", content: "hello world 2"},
   232  			{id: "2", content: "hello world 3"},
   233  			{id: "3", content: "hello world 4"},
   234  			{id: "4", content: "hello world 5"},
   235  			{id: "5", content: "hello world 6"},
   236  			{id: "6", content: "hello world 7"},
   237  			{id: "7", content: "hello world 8"},
   238  			{id: "8", content: "hello world 9"},
   239  			{id: "9", content: "hello world 10"},
   240  		},
   241  		{
   242  			{id: "10", content: "hello world 11"},
   243  			{id: "11", content: "hello world 12"},
   244  			{id: "12", content: "hello world 13"},
   245  			{id: "13", content: "hello world 14"},
   246  			{id: "14", content: "hello world 15"},
   247  		},
   248  	}, in)
   249  }