github.com/Jeffail/benthos/v3@v3.65.0/lib/processor/redis_test.go (about)

     1  package processor
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"net/url"
     7  	"reflect"
     8  	"regexp"
     9  	"sort"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/Jeffail/benthos/v3/lib/log"
    15  	"github.com/Jeffail/benthos/v3/lib/message"
    16  	"github.com/Jeffail/benthos/v3/lib/metrics"
    17  	"github.com/go-redis/redis/v7"
    18  	"github.com/ory/dockertest/v3"
    19  	"github.com/stretchr/testify/assert"
    20  	"github.com/stretchr/testify/require"
    21  )
    22  
    23  func TestRedisIntegration(t *testing.T) {
    24  	if m := flag.Lookup("test.run").Value.String(); m == "" || regexp.MustCompile(strings.Split(m, "/")[0]).FindString(t.Name()) == "" {
    25  		t.Skip("Skipping as execution was not requested explicitly using go test -run ^TestIntegration$")
    26  	}
    27  
    28  	if testing.Short() {
    29  		t.Skip("Skipping integration test in short mode")
    30  	}
    31  
    32  	pool, err := dockertest.NewPool("")
    33  	if err != nil {
    34  		t.Skipf("Could not connect to docker: %s", err)
    35  	}
    36  	pool.MaxWait = time.Second * 30
    37  
    38  	resource, err := pool.Run("redis", "latest", nil)
    39  	if err != nil {
    40  		t.Fatalf("Could not start resource: %s", err)
    41  	}
    42  
    43  	urlStr := fmt.Sprintf("tcp://localhost:%v", resource.GetPort("6379/tcp"))
    44  	uri, err := url.Parse(urlStr)
    45  	if err != nil {
    46  		t.Fatal(err)
    47  	}
    48  
    49  	client := redis.NewClient(&redis.Options{
    50  		Addr:    uri.Host,
    51  		Network: uri.Scheme,
    52  	})
    53  
    54  	if err = pool.Retry(func() error {
    55  		return client.Ping().Err()
    56  	}); err != nil {
    57  		t.Fatalf("Could not connect to docker resource: %s", err)
    58  	}
    59  
    60  	defer func() {
    61  		if err = pool.Purge(resource); err != nil {
    62  			t.Logf("Failed to clean up docker resource: %v", err)
    63  		}
    64  	}()
    65  
    66  	defer client.Close()
    67  
    68  	t.Run("testRedisKeys", func(t *testing.T) {
    69  		testRedisKeys(t, client, urlStr)
    70  	})
    71  	t.Run("testRedisSAdd", func(t *testing.T) {
    72  		testRedisSAdd(t, client, urlStr)
    73  	})
    74  	t.Run("testRedisSCard", func(t *testing.T) {
    75  		testRedisSCard(t, client, urlStr)
    76  	})
    77  	t.Run("testRedisIncrby", func(t *testing.T) {
    78  		testRedisIncrby(t, client, urlStr)
    79  	})
    80  }
    81  
    82  func testRedisKeys(t *testing.T, client *redis.Client, url string) {
    83  	conf := NewConfig()
    84  	conf.Type = TypeRedis
    85  	conf.Redis.URL = url
    86  	conf.Redis.Operator = "keys"
    87  	conf.Redis.Key = "foo*"
    88  
    89  	r, err := NewRedis(conf, nil, log.Noop(), metrics.Noop())
    90  	require.NoError(t, err)
    91  
    92  	for _, key := range []string{
    93  		"bar1", "bar2", "fooa", "foob", "baz1", "fooc",
    94  	} {
    95  		_, err := client.Set(key, "hello world", 0).Result()
    96  		require.NoError(t, err)
    97  	}
    98  
    99  	msg := message.New([][]byte{[]byte(`ignore me please`)})
   100  
   101  	resMsgs, response := r.ProcessMessage(msg)
   102  	if !assert.Nil(t, response) {
   103  		require.NoError(t, response.Error())
   104  	}
   105  
   106  	require.Len(t, resMsgs, 1)
   107  	require.Equal(t, 1, resMsgs[0].Len())
   108  
   109  	exp := []string{"fooa", "foob", "fooc"}
   110  
   111  	actI, err := resMsgs[0].Get(0).JSON()
   112  	require.NoError(t, err)
   113  
   114  	actS, ok := actI.([]interface{})
   115  	require.True(t, ok)
   116  
   117  	actStrs := make([]string, 0, len(actS))
   118  	for _, v := range actS {
   119  		actStrs = append(actStrs, v.(string))
   120  	}
   121  	sort.Strings(actStrs)
   122  
   123  	assert.Equal(t, exp, actStrs)
   124  }
   125  
   126  func testRedisSAdd(t *testing.T, client *redis.Client, url string) {
   127  	conf := NewConfig()
   128  	conf.Type = TypeRedis
   129  	conf.Redis.URL = url
   130  	conf.Redis.Operator = "sadd"
   131  	conf.Redis.Key = "${! meta(\"key\") }"
   132  
   133  	r, err := NewRedis(conf, nil, log.Noop(), metrics.Noop())
   134  	if err != nil {
   135  		t.Fatal(err)
   136  	}
   137  
   138  	msg := message.New([][]byte{
   139  		[]byte(`foo`),
   140  		[]byte(`bar`),
   141  		[]byte(`bar`),
   142  		[]byte(`baz`),
   143  		[]byte(`buz`),
   144  		[]byte(`bev`),
   145  	})
   146  	msg.Get(0).Metadata().Set("key", "foo1")
   147  	msg.Get(1).Metadata().Set("key", "foo1")
   148  	msg.Get(2).Metadata().Set("key", "foo1")
   149  	msg.Get(3).Metadata().Set("key", "foo2")
   150  	msg.Get(4).Metadata().Set("key", "foo2")
   151  	msg.Get(5).Metadata().Set("key", "foo2")
   152  
   153  	resMsgs, response := r.ProcessMessage(msg)
   154  	if response != nil {
   155  		if response.Error() != nil {
   156  			t.Fatal(response.Error())
   157  		}
   158  		t.Fatal("Expected nil response")
   159  	}
   160  	if len(resMsgs) != 1 {
   161  		t.Fatalf("Wrong resulting msgs: %v != %v", len(resMsgs), 1)
   162  	}
   163  
   164  	exp := [][]byte{
   165  		[]byte(`1`),
   166  		[]byte(`1`),
   167  		[]byte(`0`),
   168  		[]byte(`1`),
   169  		[]byte(`1`),
   170  		[]byte(`1`),
   171  	}
   172  	if act := message.GetAllBytes(resMsgs[0]); !reflect.DeepEqual(exp, act) {
   173  		t.Fatalf("Wrong result: %s != %s", act, exp)
   174  	}
   175  
   176  	res, err := client.SCard("foo1").Result()
   177  	if err != nil {
   178  		t.Fatal(err)
   179  	}
   180  	if exp, act := 2, int(res); exp != act {
   181  		t.Errorf("Wrong cardinality of set 1: %v != %v", act, exp)
   182  	}
   183  	res, err = client.SCard("foo2").Result()
   184  	if err != nil {
   185  		t.Fatal(err)
   186  	}
   187  	if exp, act := 3, int(res); exp != act {
   188  		t.Errorf("Wrong cardinality of set 2: %v != %v", act, exp)
   189  	}
   190  }
   191  
   192  func testRedisSCard(t *testing.T, client *redis.Client, url string) {
   193  	// WARNING: Relies on testRedisSAdd succeeding.
   194  	conf := NewConfig()
   195  	conf.Type = TypeRedis
   196  	conf.Redis.URL = url
   197  	conf.Redis.Operator = "scard"
   198  	conf.Redis.Key = "${!content()}"
   199  
   200  	r, err := NewRedis(conf, nil, log.Noop(), metrics.Noop())
   201  	if err != nil {
   202  		t.Fatal(err)
   203  	}
   204  
   205  	msg := message.New([][]byte{
   206  		[]byte(`doesntexist`),
   207  		[]byte(`foo1`),
   208  		[]byte(`foo2`),
   209  	})
   210  
   211  	resMsgs, response := r.ProcessMessage(msg)
   212  	if response != nil {
   213  		if response.Error() != nil {
   214  			t.Fatal(response.Error())
   215  		}
   216  		t.Fatal("Expected nil response")
   217  	}
   218  	if len(resMsgs) != 1 {
   219  		t.Fatalf("Wrong resulting msgs: %v != %v", len(resMsgs), 1)
   220  	}
   221  
   222  	exp := [][]byte{
   223  		[]byte(`0`),
   224  		[]byte(`2`),
   225  		[]byte(`3`),
   226  	}
   227  	if act := message.GetAllBytes(resMsgs[0]); !reflect.DeepEqual(exp, act) {
   228  		t.Fatalf("Wrong result: %s != %s", act, exp)
   229  	}
   230  }
   231  
   232  func testRedisIncrby(t *testing.T, client *redis.Client, url string) {
   233  	conf := NewConfig()
   234  	conf.Type = TypeRedis
   235  	conf.Redis.URL = url
   236  	conf.Redis.Operator = "incrby"
   237  	conf.Redis.Key = "incrby"
   238  
   239  	r, err := NewRedis(conf, nil, log.Noop(), metrics.Noop())
   240  	if err != nil {
   241  		t.Fatal(err)
   242  	}
   243  
   244  	msg := message.New([][]byte{
   245  		[]byte(`2`),
   246  		[]byte(`1`),
   247  		[]byte(`5`),
   248  		[]byte(`-10`),
   249  		[]byte(`0`),
   250  	})
   251  	resMsgs, response := r.ProcessMessage(msg)
   252  	if response != nil {
   253  		if response.Error() != nil {
   254  			t.Fatal(response.Error())
   255  		}
   256  		t.Fatal("Expected nil response")
   257  	}
   258  
   259  	exp := [][]byte{
   260  		[]byte(`2`),
   261  		[]byte(`3`),
   262  		[]byte(`8`),
   263  		[]byte(`-2`),
   264  		[]byte(`-2`),
   265  	}
   266  	if act := message.GetAllBytes(resMsgs[0]); !reflect.DeepEqual(exp, act) {
   267  		t.Fatalf("Wrong result: %s != %s", act, exp)
   268  	}
   269  
   270  }