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 }