github.com/letsencrypt/boulder@v0.20251208.0/ratelimits/source_redis_test.go (about) 1 package ratelimits 2 3 import ( 4 "context" 5 "testing" 6 "time" 7 8 "github.com/letsencrypt/boulder/cmd" 9 "github.com/letsencrypt/boulder/metrics" 10 "github.com/letsencrypt/boulder/test" 11 12 "github.com/jmhodges/clock" 13 "github.com/redis/go-redis/v9" 14 ) 15 16 func newTestRedisSource(clk clock.FakeClock, addrs map[string]string) *RedisSource { 17 CACertFile := "../test/certs/ipki/minica.pem" 18 CertFile := "../test/certs/ipki/localhost/cert.pem" 19 KeyFile := "../test/certs/ipki/localhost/key.pem" 20 tlsConfig := cmd.TLSConfig{ 21 CACertFile: CACertFile, 22 CertFile: CertFile, 23 KeyFile: KeyFile, 24 } 25 tlsConfig2, err := tlsConfig.Load(metrics.NoopRegisterer) 26 if err != nil { 27 panic(err) 28 } 29 30 client := redis.NewRing(&redis.RingOptions{ 31 Addrs: addrs, 32 Username: "boulder", 33 Password: "824968fa490f4ecec1e52d5e34916bdb60d45f8d", 34 TLSConfig: tlsConfig2, 35 }) 36 return NewRedisSource(client, clk, metrics.NoopRegisterer) 37 } 38 39 func newRedisTestLimiter(t *testing.T, clk clock.FakeClock) *Limiter { 40 return newTestLimiter(t, newTestRedisSource(clk, map[string]string{ 41 "shard1": "10.77.77.4:4218", 42 "shard2": "10.77.77.5:4218", 43 }), clk) 44 } 45 46 func TestRedisSource_Ping(t *testing.T) { 47 clk := clock.NewFake() 48 workingSource := newTestRedisSource(clk, map[string]string{ 49 "shard1": "10.77.77.4:4218", 50 "shard2": "10.77.77.5:4218", 51 }) 52 53 err := workingSource.Ping(context.Background()) 54 test.AssertNotError(t, err, "Ping should not error") 55 56 missingFirstShardSource := newTestRedisSource(clk, map[string]string{ 57 "shard1": "10.77.77.4:1337", 58 "shard2": "10.77.77.5:4218", 59 }) 60 61 err = missingFirstShardSource.Ping(context.Background()) 62 test.AssertError(t, err, "Ping should not error") 63 64 missingSecondShardSource := newTestRedisSource(clk, map[string]string{ 65 "shard1": "10.77.77.4:4218", 66 "shard2": "10.77.77.5:1337", 67 }) 68 69 err = missingSecondShardSource.Ping(context.Background()) 70 test.AssertError(t, err, "Ping should not error") 71 } 72 73 func TestRedisSource_BatchSetAndGet(t *testing.T) { 74 clk := clock.NewFake() 75 s := newTestRedisSource(clk, map[string]string{ 76 "shard1": "10.77.77.4:4218", 77 "shard2": "10.77.77.5:4218", 78 }) 79 80 set := map[string]time.Time{ 81 "test1": clk.Now().Add(time.Second), 82 "test2": clk.Now().Add(time.Second * 2), 83 "test3": clk.Now().Add(time.Second * 3), 84 } 85 86 incr := map[string]increment{ 87 "test1": {time.Second, time.Minute}, 88 "test2": {time.Second * 2, time.Minute}, 89 "test3": {time.Second * 3, time.Minute}, 90 } 91 92 err := s.BatchSet(context.Background(), set) 93 test.AssertNotError(t, err, "BatchSet() should not error") 94 95 got, err := s.BatchGet(context.Background(), []string{"test1", "test2", "test3"}) 96 test.AssertNotError(t, err, "BatchGet() should not error") 97 98 for k, v := range set { 99 test.AssertEquals(t, got[k], v) 100 } 101 102 err = s.BatchIncrement(context.Background(), incr) 103 test.AssertNotError(t, err, "BatchIncrement() should not error") 104 105 got, err = s.BatchGet(context.Background(), []string{"test1", "test2", "test3"}) 106 test.AssertNotError(t, err, "BatchGet() should not error") 107 108 for k := range set { 109 test.AssertEquals(t, got[k], set[k].Add(incr[k].cost)) 110 } 111 112 // Test that BatchGet() returns a zero time for a key that does not exist. 113 got, err = s.BatchGet(context.Background(), []string{"test1", "test4", "test3"}) 114 test.AssertNotError(t, err, "BatchGet() should not error when a key isn't found") 115 test.Assert(t, got["test4"].IsZero(), "BatchGet() should return a zero time for a key that does not exist") 116 }