github.com/thanos-io/thanos@v0.32.5/pkg/cacheutil/redis_client_test.go (about)

     1  // Copyright (c) The Thanos Authors.
     2  // Licensed under the Apache License 2.0.
     3  
     4  package cacheutil
     5  
     6  import (
     7  	"context"
     8  	"os"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/alicebob/miniredis/v2"
    13  	"github.com/efficientgo/core/testutil"
    14  	"github.com/go-kit/log"
    15  	"github.com/prometheus/client_golang/prometheus"
    16  )
    17  
    18  func TestRedisClient(t *testing.T) {
    19  	// Init some data to conveniently define test cases later one.
    20  	key1 := "key1"
    21  	key2 := "key2"
    22  	key3 := "key3"
    23  	value1 := []byte{1}
    24  	value2 := []byte{2}
    25  	value3 := []byte{3}
    26  
    27  	type args struct {
    28  		data      map[string][]byte
    29  		fetchKeys []string
    30  	}
    31  	type want struct {
    32  		hits map[string][]byte
    33  	}
    34  	tests := []struct {
    35  		name string
    36  		args args
    37  		want want
    38  	}{
    39  		{
    40  			name: "all hit",
    41  			args: args{
    42  				data: map[string][]byte{
    43  					key1: value1,
    44  					key2: value2,
    45  					key3: value3,
    46  				},
    47  				fetchKeys: []string{key1, key2, key3},
    48  			},
    49  			want: want{
    50  				hits: map[string][]byte{
    51  					key1: value1,
    52  					key2: value2,
    53  					key3: value3,
    54  				},
    55  			},
    56  		},
    57  		{
    58  			name: "partial hit",
    59  			args: args{
    60  				data: map[string][]byte{
    61  					key1: value1,
    62  					key2: value2,
    63  				},
    64  				fetchKeys: []string{key1, key2, key3},
    65  			},
    66  			want: want{
    67  				hits: map[string][]byte{
    68  					key1: value1,
    69  					key2: value2,
    70  				},
    71  			},
    72  		},
    73  		{
    74  			name: "not hit",
    75  			args: args{
    76  				data:      map[string][]byte{},
    77  				fetchKeys: []string{key1, key2, key3},
    78  			},
    79  			want: want{
    80  				hits: map[string][]byte{},
    81  			},
    82  		},
    83  	}
    84  	s, err := miniredis.Run()
    85  	if err != nil {
    86  		testutil.Ok(t, err)
    87  	}
    88  	defer s.Close()
    89  	redisConfigs := []struct {
    90  		name        string
    91  		redisConfig func() RedisClientConfig
    92  	}{
    93  		{
    94  			name: "MaxConcurrency>0",
    95  			redisConfig: func() RedisClientConfig {
    96  				cfg := DefaultRedisClientConfig
    97  				cfg.Addr = s.Addr()
    98  				cfg.MaxGetMultiConcurrency = 2
    99  				cfg.GetMultiBatchSize = 2
   100  				cfg.MaxSetMultiConcurrency = 2
   101  				cfg.SetMultiBatchSize = 2
   102  				return cfg
   103  			},
   104  		},
   105  		{
   106  			name: "MaxConcurrency=0",
   107  			redisConfig: func() RedisClientConfig {
   108  				cfg := DefaultRedisClientConfig
   109  				cfg.Addr = s.Addr()
   110  				cfg.MaxGetMultiConcurrency = 0
   111  				cfg.GetMultiBatchSize = 0
   112  				cfg.MaxSetMultiConcurrency = 0
   113  				cfg.SetMultiBatchSize = 0
   114  				return cfg
   115  			},
   116  		},
   117  	}
   118  	for _, tt := range tests {
   119  		t.Run(tt.name, func(t *testing.T) {
   120  			for _, redisConfig := range redisConfigs {
   121  				t.Run(tt.name+redisConfig.name, func(t *testing.T) {
   122  					logger := log.NewLogfmtLogger(os.Stderr)
   123  					reg := prometheus.NewRegistry()
   124  					c, err := NewRedisClientWithConfig(logger, t.Name(), redisConfig.redisConfig(), reg)
   125  					if err != nil {
   126  						testutil.Ok(t, err)
   127  					}
   128  					defer c.Stop()
   129  					defer s.FlushAll()
   130  					ctx := context.Background()
   131  					c.SetMulti(tt.args.data, time.Hour)
   132  					hits := c.GetMulti(ctx, tt.args.fetchKeys)
   133  					testutil.Equals(t, tt.want.hits, hits)
   134  				})
   135  			}
   136  		})
   137  	}
   138  }
   139  
   140  func TestValidateRedisConfig(t *testing.T) {
   141  	tests := []struct {
   142  		name       string
   143  		config     func() RedisClientConfig
   144  		expect_err bool // func(*testing.T, interface{}, error)
   145  	}{
   146  		{
   147  			name: "simpleConfig",
   148  			config: func() RedisClientConfig {
   149  				cfg := DefaultRedisClientConfig
   150  				cfg.Addr = "127.0.0.1:6789"
   151  				cfg.Username = "user"
   152  				cfg.Password = "1234"
   153  				return cfg
   154  			},
   155  			expect_err: false,
   156  		},
   157  		{
   158  			name: "tlsConfigDefaults",
   159  			config: func() RedisClientConfig {
   160  				cfg := DefaultRedisClientConfig
   161  				cfg.Addr = "127.0.0.1:6789"
   162  				cfg.Username = "user"
   163  				cfg.Password = "1234"
   164  				cfg.TLSEnabled = true
   165  				return cfg
   166  			},
   167  			expect_err: false,
   168  		},
   169  		{
   170  			name: "tlsClientCertConfig",
   171  			config: func() RedisClientConfig {
   172  				cfg := DefaultRedisClientConfig
   173  				cfg.Addr = "127.0.0.1:6789"
   174  				cfg.Username = "user"
   175  				cfg.Password = "1234"
   176  				cfg.TLSEnabled = true
   177  				cfg.TLSConfig = TLSConfig{
   178  					CertFile: "cert/client.pem",
   179  					KeyFile:  "cert/client.key",
   180  				}
   181  				return cfg
   182  			},
   183  			expect_err: false,
   184  		},
   185  		{
   186  			name: "tlsInvalidClientCertConfig",
   187  			config: func() RedisClientConfig {
   188  				cfg := DefaultRedisClientConfig
   189  				cfg.Addr = "127.0.0.1:6789"
   190  				cfg.Username = "user"
   191  				cfg.Password = "1234"
   192  				cfg.TLSEnabled = true
   193  				cfg.TLSConfig = TLSConfig{
   194  					CertFile: "cert/client.pem",
   195  				}
   196  				return cfg
   197  			},
   198  			expect_err: true,
   199  		},
   200  	}
   201  
   202  	for _, tt := range tests {
   203  		t.Run(tt.name, func(t *testing.T) {
   204  			cfg := tt.config()
   205  
   206  			if tt.expect_err {
   207  				testutil.NotOk(t, cfg.validate())
   208  			} else {
   209  				testutil.Ok(t, cfg.validate())
   210  			}
   211  		})
   212  	}
   213  
   214  }
   215  
   216  func TestMultipleRedisClient(t *testing.T) {
   217  	s, err := miniredis.Run()
   218  	if err != nil {
   219  		testutil.Ok(t, err)
   220  	}
   221  	defer s.Close()
   222  	cfg := DefaultRedisClientConfig
   223  	cfg.Addr = s.Addr()
   224  	logger := log.NewLogfmtLogger(os.Stderr)
   225  	reg := prometheus.NewRegistry()
   226  	cl, err := NewRedisClientWithConfig(logger, "test1", cfg, reg)
   227  	testutil.Ok(t, err)
   228  	t.Cleanup(cl.Stop)
   229  	cl, err = NewRedisClientWithConfig(logger, "test2", cfg, reg)
   230  	testutil.Ok(t, err)
   231  	t.Cleanup(cl.Stop)
   232  }