@@ -364,6 +364,47 @@ TEST_F(HSetFamilyTest, HSetEx) {
364
364
resp = Run ({" HGET" , " k" , " field4" });
365
365
EXPECT_THAT (resp,
366
366
" value" ); // HSETEX with NX option; old expiration time was NOT replaced by a new one
367
+
368
+ // KEEPTTL related asserts
369
+ EXPECT_THAT (Run ({" HSETEX" , " k" , long_time, " kttlfield" , " value" }), IntArg (1 ));
370
+ EXPECT_EQ (Run ({" HGET" , " k" , " kttlfield" }), " value" );
371
+ EXPECT_EQ (CheckedInt ({" FIELDTTL" , " k" , " kttlfield" }), 100 );
372
+
373
+ // KEEPTTL resets value of kttlfield, but preserves its TTL. afield is added with TTL=1
374
+ EXPECT_THAT (Run ({" HSETEX" , " k" , " KEEPTTL" , " 1" , " kttlfield" , " resetvalue" , " afield" , " aval" }),
375
+ IntArg (1 ));
376
+ EXPECT_EQ (CheckedInt ({" FIELDTTL" , " k" , " kttlfield" }), 100 );
377
+ EXPECT_EQ (Run ({" FIELDTTL" , " k" , " afield" }).GetInt (), 1 );
378
+ EXPECT_EQ (Run ({" HGET" , " k" , " afield" }), " aval" );
379
+ // make afield expire
380
+ AdvanceTime (1000 );
381
+ EXPECT_THAT (Run ({" HGET" , " k" , " afield" }), ArgType (RespExpr::NIL));
382
+
383
+ // kttlfield is still present although with updated value
384
+ EXPECT_EQ (Run ({" HGET" , " k" , " kttlfield" }), " resetvalue" );
385
+ EXPECT_EQ (Run ({" FIELDTTL" , " k" , " kttlfield" }).GetInt (), 99 );
386
+
387
+ // If NX is supplied, with or without KEEPTTL neither expiry nor value is updated
388
+ EXPECT_THAT (Run ({" HSETEX" , " k" , " NX" , " KEEPTTL" , " 1" , " kttlfield" , " value" }), IntArg (0 ));
389
+
390
+ // No updates
391
+ EXPECT_EQ (Run ({" HGET" , " k" , " kttlfield" }), " resetvalue" );
392
+ EXPECT_EQ (Run ({" FIELDTTL" , " k" , " kttlfield" }).GetInt (), 99 );
393
+
394
+ EXPECT_THAT (Run ({" HSETEX" , " k" , " NX" , " 1" , " kttlfield" , " value" }), IntArg (0 ));
395
+ // No updates
396
+ EXPECT_EQ (Run ({" HGET" , " k" , " kttlfield" }), " resetvalue" );
397
+ EXPECT_EQ (Run ({" FIELDTTL" , " k" , " kttlfield" }).GetInt (), 99 );
398
+
399
+ // Invalid TTL handling
400
+ EXPECT_THAT (Run ({" HSETEX" , " k" , " NX" , " zero" , " kttlfield" , " value" }),
401
+ ErrArg (" ERR value is not an integer or out of range" ));
402
+
403
+ // Exercise the code path where a field is added without TTL, but then we set a new expiration AND
404
+ // provide KEEPTTL. Since there was no old expiry, the new TTL should be applied.
405
+ EXPECT_EQ (Run ({" HSET" , " k" , " nottl" , " val" }), 1 );
406
+ EXPECT_EQ (Run ({" HSETEX" , " k" , " KEEPTTL" , long_time, " nottl" , " newval" }), 0 );
407
+ EXPECT_EQ (Run ({" FIELDTTL" , " k" , " nottl" }).GetInt (), 100 );
367
408
}
368
409
369
410
TEST_F (HSetFamilyTest, TriggerConvertToStrMap) {
0 commit comments