@@ -7,7 +7,9 @@ package redis
77
88import (
99 "context"
10+ "strconv"
1011 "testing"
12+ "time"
1113
1214 "github.com/agrea/ptr"
1315 miniredis "github.com/alicebob/miniredis/v2"
@@ -90,6 +92,47 @@ func TestParseEtag(t *testing.T) {
9092 })
9193}
9294
95+ func TestParseTTL (t * testing.T ) {
96+ store := NewRedisStateStore (logger .NewLogger ("test" ))
97+ t .Run ("TTL Not an integer" , func (t * testing.T ) {
98+ ttlInSeconds := "not an integer"
99+ ttl := store .parseTTL (& state.SetRequest {
100+ Metadata : map [string ]string {
101+ "ttlInSeconds" : ttlInSeconds ,
102+ },
103+ })
104+ assert .Equal (t , ttl , 0 )
105+ })
106+ t .Run ("TTL specified with wrong key" , func (t * testing.T ) {
107+ ttlInSeconds := 12345
108+ ttl := store .parseTTL (& state.SetRequest {
109+ Metadata : map [string ]string {
110+ "expirationTime" : strconv .Itoa (ttlInSeconds ),
111+ },
112+ })
113+ assert .Equal (t , ttl , 0 )
114+ })
115+ t .Run ("TTL is a number" , func (t * testing.T ) {
116+ ttlInSeconds := 12345
117+ ttl := store .parseTTL (& state.SetRequest {
118+ Metadata : map [string ]string {
119+ "ttlInSeconds" : strconv .Itoa (ttlInSeconds ),
120+ },
121+ })
122+ assert .Equal (t , ttl , ttlInSeconds )
123+ })
124+
125+ t .Run ("TTL never expires" , func (t * testing.T ) {
126+ ttlInSeconds := - 1
127+ ttl := store .parseTTL (& state.SetRequest {
128+ Metadata : map [string ]string {
129+ "ttlInSeconds" : strconv .Itoa (ttlInSeconds ),
130+ },
131+ })
132+ assert .Equal (t , ttl , ttlInSeconds )
133+ })
134+ }
135+
93136func TestParseConnectedSlavs (t * testing.T ) {
94137 store := NewRedisStateStore (logger .NewLogger ("test" ))
95138
@@ -126,13 +169,35 @@ func TestTransactionalUpsert(t *testing.T) {
126169 ss .ctx , ss .cancel = context .WithCancel (context .Background ())
127170
128171 err := ss .Multi (& state.TransactionalStateRequest {
129- Operations : []state.TransactionalStateOperation {{
130- Operation : state .Upsert ,
131- Request : state.SetRequest {
132- Key : "weapon" ,
133- Value : "deathstar" ,
172+ Operations : []state.TransactionalStateOperation {
173+ {
174+ Operation : state .Upsert ,
175+ Request : state.SetRequest {
176+ Key : "weapon" ,
177+ Value : "deathstar" ,
178+ },
134179 },
135- }},
180+ {
181+ Operation : state .Upsert ,
182+ Request : state.SetRequest {
183+ Key : "weapon2" ,
184+ Value : "deathstar2" ,
185+ Metadata : map [string ]string {
186+ "ttlInSeconds" : "123" ,
187+ },
188+ },
189+ },
190+ {
191+ Operation : state .Upsert ,
192+ Request : state.SetRequest {
193+ Key : "weapon3" ,
194+ Value : "deathstar3" ,
195+ Metadata : map [string ]string {
196+ "ttlInSeconds" : "-1" ,
197+ },
198+ },
199+ },
200+ },
136201 })
137202 assert .Equal (t , nil , err )
138203
@@ -144,6 +209,18 @@ func TestTransactionalUpsert(t *testing.T) {
144209 assert .Equal (t , nil , err )
145210 assert .Equal (t , ptr .String ("1" ), version )
146211 assert .Equal (t , `"deathstar"` , data )
212+
213+ res , err = c .Do (context .Background (), "TTL" , "weapon" ).Result ()
214+ assert .Equal (t , nil , err )
215+ assert .Equal (t , int64 (- 1 ), res )
216+
217+ res , err = c .Do (context .Background (), "TTL" , "weapon2" ).Result ()
218+ assert .Equal (t , nil , err )
219+ assert .Equal (t , int64 (123 ), res )
220+
221+ res , err = c .Do (context .Background (), "TTL" , "weapon3" ).Result ()
222+ assert .Equal (t , nil , err )
223+ assert .Equal (t , int64 (- 1 ), res )
147224}
148225
149226func TestTransactionalDelete (t * testing.T ) {
@@ -201,6 +278,76 @@ func TestPing(t *testing.T) {
201278 assert .Error (t , err )
202279}
203280
281+ func TestSetRequestWithTTL (t * testing.T ) {
282+ s , c := setupMiniredis ()
283+ defer s .Close ()
284+
285+ ss := & StateStore {
286+ client : c ,
287+ json : jsoniter .ConfigFastest ,
288+ logger : logger .NewLogger ("test" ),
289+ }
290+ ss .ctx , ss .cancel = context .WithCancel (context .Background ())
291+
292+ t .Run ("TTL specified" , func (t * testing.T ) {
293+ ttlInSeconds := 100
294+ ss .Set (& state.SetRequest {
295+ Key : "weapon100" ,
296+ Value : "deathstar100" ,
297+ Metadata : map [string ]string {
298+ "ttlInSeconds" : strconv .Itoa (ttlInSeconds ),
299+ },
300+ })
301+
302+ ttl , _ := ss .client .TTL (ss .ctx , "weapon100" ).Result ()
303+
304+ assert .Equal (t , time .Duration (ttlInSeconds )* time .Second , ttl )
305+ })
306+
307+ t .Run ("TTL not specified" , func (t * testing.T ) {
308+ ss .Set (& state.SetRequest {
309+ Key : "weapon200" ,
310+ Value : "deathstar200" ,
311+ })
312+
313+ ttl , _ := ss .client .TTL (ss .ctx , "weapon200" ).Result ()
314+
315+ assert .Equal (t , time .Duration (- 1 ), ttl )
316+ })
317+
318+ t .Run ("TTL Changed for Existing Key" , func (t * testing.T ) {
319+ ss .Set (& state.SetRequest {
320+ Key : "weapon300" ,
321+ Value : "deathstar300" ,
322+ })
323+ ttl , _ := ss .client .TTL (ss .ctx , "weapon300" ).Result ()
324+ assert .Equal (t , time .Duration (- 1 ), ttl )
325+
326+ // make the key no longer persistent
327+ ttlInSeconds := 123
328+ ss .Set (& state.SetRequest {
329+ Key : "weapon300" ,
330+ Value : "deathstar300" ,
331+ Metadata : map [string ]string {
332+ "ttlInSeconds" : strconv .Itoa (ttlInSeconds ),
333+ },
334+ })
335+ ttl , _ = ss .client .TTL (ss .ctx , "weapon300" ).Result ()
336+ assert .Equal (t , time .Duration (ttlInSeconds )* time .Second , ttl )
337+
338+ // make the key persistent again
339+ ss .Set (& state.SetRequest {
340+ Key : "weapon300" ,
341+ Value : "deathstar301" ,
342+ Metadata : map [string ]string {
343+ "ttlInSeconds" : strconv .Itoa (- 1 ),
344+ },
345+ })
346+ ttl , _ = ss .client .TTL (ss .ctx , "weapon300" ).Result ()
347+ assert .Equal (t , time .Duration (- 1 ), ttl )
348+ })
349+ }
350+
204351func TestTransactionalDeleteNoEtag (t * testing.T ) {
205352 s , c := setupMiniredis ()
206353 defer s .Close ()
0 commit comments