expire.tcl 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. start_server {tags {"expire"}} {
  2. test {EXPIRE - set timeouts multiple times} {
  3. r set x foobar
  4. set v1 [r expire x 5]
  5. set v2 [r ttl x]
  6. set v3 [r expire x 10]
  7. set v4 [r ttl x]
  8. r expire x 2
  9. list $v1 $v2 $v3 $v4
  10. } {1 [45] 1 10}
  11. test {EXPIRE - It should be still possible to read 'x'} {
  12. r get x
  13. } {foobar}
  14. tags {"slow"} {
  15. test {EXPIRE - After 2.1 seconds the key should no longer be here} {
  16. after 2100
  17. list [r get x] [r exists x]
  18. } {{} 0}
  19. }
  20. test {EXPIRE - write on expire should work} {
  21. r del x
  22. r lpush x foo
  23. r expire x 1000
  24. r lpush x bar
  25. r lrange x 0 -1
  26. } {bar foo}
  27. test {EXPIREAT - Check for EXPIRE alike behavior} {
  28. r del x
  29. r set x foo
  30. r expireat x [expr [clock seconds]+15]
  31. r ttl x
  32. } {1[345]}
  33. test {SETEX - Set + Expire combo operation. Check for TTL} {
  34. r setex x 12 test
  35. r ttl x
  36. } {1[012]}
  37. test {SETEX - Check value} {
  38. r get x
  39. } {test}
  40. test {SETEX - Overwrite old key} {
  41. r setex y 1 foo
  42. r get y
  43. } {foo}
  44. tags {"slow"} {
  45. test {SETEX - Wait for the key to expire} {
  46. after 1100
  47. r get y
  48. } {}
  49. }
  50. test {SETEX - Wrong time parameter} {
  51. catch {r setex z -10 foo} e
  52. set _ $e
  53. } {*invalid expire*}
  54. test {PERSIST can undo an EXPIRE} {
  55. r set x foo
  56. r expire x 50
  57. list [r ttl x] [r persist x] [r ttl x] [r get x]
  58. } {50 1 -1 foo}
  59. test {PERSIST returns 0 against non existing or non volatile keys} {
  60. r set x foo
  61. list [r persist foo] [r persist nokeyatall]
  62. } {0 0}
  63. test {EXPIRE precision is now the millisecond} {
  64. # This test is very likely to do a false positive if the
  65. # server is under pressure, so if it does not work give it a few more
  66. # chances.
  67. for {set j 0} {$j < 10} {incr j} {
  68. r del x
  69. r setex x 1 somevalue
  70. after 900
  71. set a [r get x]
  72. after 1100
  73. set b [r get x]
  74. if {$a eq {somevalue} && $b eq {}} break
  75. }
  76. if {$::verbose} {
  77. puts "millisecond expire test attempts: $j"
  78. }
  79. list $a $b
  80. } {somevalue {}}
  81. test {PEXPIRE/PSETEX/PEXPIREAT can set sub-second expires} {
  82. # This test is very likely to do a false positive if the
  83. # server is under pressure, so if it does not work give it a few more
  84. # chances.
  85. for {set j 0} {$j < 30} {incr j} {
  86. r del x
  87. r del y
  88. r del z
  89. r psetex x 100 somevalue
  90. after 80
  91. set a [r get x]
  92. after 120
  93. set b [r get x]
  94. r set x somevalue
  95. r pexpire x 100
  96. after 80
  97. set c [r get x]
  98. after 120
  99. set d [r get x]
  100. r set x somevalue
  101. set now [r time]
  102. r pexpireat x [expr ([lindex $now 0]*1000)+([lindex $now 1]/1000)+200]
  103. after 20
  104. set e [r get x]
  105. after 220
  106. set f [r get x]
  107. if {$a eq {somevalue} && $b eq {} &&
  108. $c eq {somevalue} && $d eq {} &&
  109. $e eq {somevalue} && $f eq {}} break
  110. }
  111. if {$::verbose} {
  112. puts "sub-second expire test attempts: $j"
  113. }
  114. list $a $b $c $d $e $f
  115. } {somevalue {} somevalue {} somevalue {}}
  116. test {TTL returns time to live in seconds} {
  117. r del x
  118. r setex x 10 somevalue
  119. set ttl [r ttl x]
  120. assert {$ttl > 8 && $ttl <= 10}
  121. }
  122. test {PTTL returns time to live in milliseconds} {
  123. r del x
  124. r setex x 1 somevalue
  125. set ttl [r pttl x]
  126. assert {$ttl > 900 && $ttl <= 1000}
  127. }
  128. test {TTL / PTTL / EXPIRETIME / PEXPIRETIME return -1 if key has no expire} {
  129. r del x
  130. r set x hello
  131. list [r ttl x] [r pttl x] [r expiretime x] [r pexpiretime x]
  132. } {-1 -1 -1 -1}
  133. test {TTL / PTTL / EXPIRETIME / PEXPIRETIME return -2 if key does not exit} {
  134. r del x
  135. list [r ttl x] [r pttl x] [r expiretime x] [r pexpiretime x]
  136. } {-2 -2 -2 -2}
  137. test {EXPIRETIME returns absolute expiration time in seconds} {
  138. r del x
  139. set abs_expire [expr [clock seconds] + 100]
  140. r set x somevalue exat $abs_expire
  141. assert_equal [r expiretime x] $abs_expire
  142. }
  143. test {PEXPIRETIME returns absolute expiration time in milliseconds} {
  144. r del x
  145. set abs_expire [expr [clock milliseconds] + 100000]
  146. r set x somevalue pxat $abs_expire
  147. assert_equal [r pexpiretime x] $abs_expire
  148. }
  149. test {Redis should actively expire keys incrementally} {
  150. r flushdb
  151. r psetex key1 500 a
  152. r psetex key2 500 a
  153. r psetex key3 500 a
  154. assert_equal 3 [r dbsize]
  155. # Redis expires random keys ten times every second so we are
  156. # fairly sure that all the three keys should be evicted after
  157. # two seconds.
  158. wait_for_condition 20 100 {
  159. [r dbsize] eq 0
  160. } fail {
  161. "Keys did not actively expire."
  162. }
  163. }
  164. test {Redis should lazy expire keys} {
  165. r flushdb
  166. r debug set-active-expire 0
  167. r psetex key1{t} 500 a
  168. r psetex key2{t} 500 a
  169. r psetex key3{t} 500 a
  170. set size1 [r dbsize]
  171. # Redis expires random keys ten times every second so we are
  172. # fairly sure that all the three keys should be evicted after
  173. # one second.
  174. after 1000
  175. set size2 [r dbsize]
  176. r mget key1{t} key2{t} key3{t}
  177. set size3 [r dbsize]
  178. r debug set-active-expire 1
  179. list $size1 $size2 $size3
  180. } {3 3 0} {needs:debug}
  181. test {EXPIRE should not resurrect keys (issue #1026)} {
  182. r debug set-active-expire 0
  183. r set foo bar
  184. r pexpire foo 500
  185. after 1000
  186. r expire foo 10
  187. r debug set-active-expire 1
  188. r exists foo
  189. } {0} {needs:debug}
  190. test {5 keys in, 5 keys out} {
  191. r flushdb
  192. r set a c
  193. r expire a 5
  194. r set t c
  195. r set e c
  196. r set s c
  197. r set foo b
  198. assert_equal [lsort [r keys *]] {a e foo s t}
  199. r del a ; # Do not leak volatile keys to other tests
  200. }
  201. test {EXPIRE with empty string as TTL should report an error} {
  202. r set foo bar
  203. catch {r expire foo ""} e
  204. set e
  205. } {*not an integer*}
  206. test {SET with EX with big integer should report an error} {
  207. catch {r set foo bar EX 10000000000000000} e
  208. set e
  209. } {ERR invalid expire time in set}
  210. test {SET with EX with smallest integer should report an error} {
  211. catch {r SET foo bar EX -9999999999999999} e
  212. set e
  213. } {ERR invalid expire time in set}
  214. test {GETEX with big integer should report an error} {
  215. r set foo bar
  216. catch {r GETEX foo EX 10000000000000000} e
  217. set e
  218. } {ERR invalid expire time in getex}
  219. test {GETEX with smallest integer should report an error} {
  220. r set foo bar
  221. catch {r GETEX foo EX -9999999999999999} e
  222. set e
  223. } {ERR invalid expire time in getex}
  224. test {EXPIRE with big integer overflows when converted to milliseconds} {
  225. r set foo bar
  226. catch {r EXPIRE foo 10000000000000000} e
  227. set e
  228. } {ERR invalid expire time in expire}
  229. test {PEXPIRE with big integer overflow when basetime is added} {
  230. r set foo bar
  231. catch {r PEXPIRE foo 9223372036854770000} e
  232. set e
  233. } {ERR invalid expire time in pexpire}
  234. test {EXPIRE with big negative integer} {
  235. r set foo bar
  236. catch {r EXPIRE foo -9999999999999999} e
  237. assert_match {ERR invalid expire time in expire} $e
  238. r ttl foo
  239. } {-1}
  240. test {PEXPIREAT with big integer works} {
  241. r set foo bar
  242. r PEXPIREAT foo 9223372036854770000
  243. } {1}
  244. test {PEXPIREAT with big negative integer works} {
  245. r set foo bar
  246. r PEXPIREAT foo -9223372036854770000
  247. r ttl foo
  248. } {-2}
  249. # Start a new server with empty data and AOF file.
  250. start_server {overrides {appendonly {yes} appendfilename {appendonly.aof} appendfsync always} tags {external:skip}} {
  251. test {All time-to-live(TTL) in commands are propagated as absolute timestamp in milliseconds in AOF} {
  252. # This test makes sure that expire times are propagated as absolute
  253. # times to the AOF file and not as relative time, so that when the AOF
  254. # is reloaded the TTLs are not being shifted forward to the future.
  255. # We want the time to logically pass when the server is restarted!
  256. set aof [file join [lindex [r config get dir] 1] [lindex [r config get appendfilename] 1]]
  257. # Apply each TTL-related command to a unique key
  258. # SET commands
  259. r set foo1 bar ex 100
  260. r set foo2 bar px 100000
  261. r set foo3 bar exat [expr [clock seconds]+100]
  262. r set foo4 bar pxat [expr [clock milliseconds]+100000]
  263. r setex foo5 100 bar
  264. r psetex foo6 100000 bar
  265. # EXPIRE-family commands
  266. r set foo7 bar
  267. r expire foo7 100
  268. r set foo8 bar
  269. r pexpire foo8 100000
  270. r set foo9 bar
  271. r expireat foo9 [expr [clock seconds]+100]
  272. r set foo10 bar
  273. r pexpireat foo10 [expr [clock seconds]*1000+100000]
  274. r set foo11 bar
  275. r expireat foo11 [expr [clock seconds]-100]
  276. # GETEX commands
  277. r set foo12 bar
  278. r getex foo12 ex 100
  279. r set foo13 bar
  280. r getex foo13 px 100000
  281. r set foo14 bar
  282. r getex foo14 exat [expr [clock seconds]+100]
  283. r set foo15 bar
  284. r getex foo15 pxat [expr [clock milliseconds]+100000]
  285. # RESTORE commands
  286. r set foo16 bar
  287. set encoded [r dump foo16]
  288. r restore foo17 100000 $encoded
  289. r restore foo18 [expr [clock milliseconds]+100000] $encoded absttl
  290. # Assert that each TTL-relatd command are persisted with absolute timestamps in AOF
  291. assert_aof_content $aof {
  292. {select *}
  293. {set foo1 bar PXAT *}
  294. {set foo2 bar PXAT *}
  295. {set foo3 bar PXAT *}
  296. {set foo4 bar PXAT *}
  297. {set foo5 bar PXAT *}
  298. {set foo6 bar PXAT *}
  299. {set foo7 bar}
  300. {pexpireat foo7 *}
  301. {set foo8 bar}
  302. {pexpireat foo8 *}
  303. {set foo9 bar}
  304. {pexpireat foo9 *}
  305. {set foo10 bar}
  306. {pexpireat foo10 *}
  307. {set foo11 bar}
  308. {del foo11}
  309. {set foo12 bar}
  310. {pexpireat foo12 *}
  311. {set foo13 bar}
  312. {pexpireat foo13 *}
  313. {set foo14 bar}
  314. {pexpireat foo14 *}
  315. {set foo15 bar}
  316. {pexpireat foo15 *}
  317. {set foo16 bar}
  318. {restore foo17 * {*} ABSTTL}
  319. {restore foo18 * {*} absttl}
  320. }
  321. # Remember the absolute TTLs of all the keys
  322. set ttl1 [r pexpiretime foo1]
  323. set ttl2 [r pexpiretime foo2]
  324. set ttl3 [r pexpiretime foo3]
  325. set ttl4 [r pexpiretime foo4]
  326. set ttl5 [r pexpiretime foo5]
  327. set ttl6 [r pexpiretime foo6]
  328. set ttl7 [r pexpiretime foo7]
  329. set ttl8 [r pexpiretime foo8]
  330. set ttl9 [r pexpiretime foo9]
  331. set ttl10 [r pexpiretime foo10]
  332. assert_equal "-2" [r pexpiretime foo11] ; # foo11 is gone
  333. set ttl12 [r pexpiretime foo12]
  334. set ttl13 [r pexpiretime foo13]
  335. set ttl14 [r pexpiretime foo14]
  336. set ttl15 [r pexpiretime foo15]
  337. assert_equal "-1" [r pexpiretime foo16] ; # foo16 has no TTL
  338. set ttl17 [r pexpiretime foo17]
  339. set ttl18 [r pexpiretime foo18]
  340. # Let some time pass and reload data from AOF
  341. after 2000
  342. r debug loadaof
  343. # Assert that relative TTLs are roughly the same
  344. assert_range [r ttl foo1] 90 98
  345. assert_range [r ttl foo2] 90 98
  346. assert_range [r ttl foo3] 90 98
  347. assert_range [r ttl foo4] 90 98
  348. assert_range [r ttl foo5] 90 98
  349. assert_range [r ttl foo6] 90 98
  350. assert_range [r ttl foo7] 90 98
  351. assert_range [r ttl foo8] 90 98
  352. assert_range [r ttl foo9] 90 98
  353. assert_range [r ttl foo10] 90 98
  354. assert_equal [r ttl foo11] "-2" ; # foo11 is gone
  355. assert_range [r ttl foo12] 90 98
  356. assert_range [r ttl foo13] 90 98
  357. assert_range [r ttl foo14] 90 98
  358. assert_range [r ttl foo15] 90 98
  359. assert_equal [r ttl foo16] "-1" ; # foo16 has no TTL
  360. assert_range [r ttl foo17] 90 98
  361. assert_range [r ttl foo18] 90 98
  362. # Assert that all keys have restored the same absolute TTLs from AOF
  363. assert_equal [r pexpiretime foo1] $ttl1
  364. assert_equal [r pexpiretime foo2] $ttl2
  365. assert_equal [r pexpiretime foo3] $ttl3
  366. assert_equal [r pexpiretime foo4] $ttl4
  367. assert_equal [r pexpiretime foo5] $ttl5
  368. assert_equal [r pexpiretime foo6] $ttl6
  369. assert_equal [r pexpiretime foo7] $ttl7
  370. assert_equal [r pexpiretime foo8] $ttl8
  371. assert_equal [r pexpiretime foo9] $ttl9
  372. assert_equal [r pexpiretime foo10] $ttl10
  373. assert_equal [r pexpiretime foo11] "-2" ; # foo11 is gone
  374. assert_equal [r pexpiretime foo12] $ttl12
  375. assert_equal [r pexpiretime foo13] $ttl13
  376. assert_equal [r pexpiretime foo14] $ttl14
  377. assert_equal [r pexpiretime foo15] $ttl15
  378. assert_equal [r pexpiretime foo16] "-1" ; # foo16 has no TTL
  379. assert_equal [r pexpiretime foo17] $ttl17
  380. assert_equal [r pexpiretime foo18] $ttl18
  381. } {} {needs:debug}
  382. }
  383. test {All TTL in commands are propagated as absolute timestamp in replication stream} {
  384. # Make sure that both relative and absolute expire commands are propagated
  385. # as absolute to replicas for two reasons:
  386. # 1) We want to avoid replicas retaining data much longer than primary due
  387. # to replication lag.
  388. # 2) We want to unify the way TTLs are replicated in both RDB and replication
  389. # stream, which is as absolute timestamps.
  390. # See: https://github.com/redis/redis/issues/8433
  391. r flushall ; # Clean up keyspace to avoid interference by keys from other tests
  392. set repl [attach_to_replication_stream]
  393. # SET commands
  394. r set foo1 bar ex 200
  395. r set foo1 bar px 100000
  396. r set foo1 bar exat [expr [clock seconds]+100]
  397. r set foo1 bar pxat [expr [clock milliseconds]+100000]
  398. r setex foo1 100 bar
  399. r psetex foo1 100000 bar
  400. r set foo2 bar
  401. # EXPIRE-family commands
  402. r expire foo2 100
  403. r pexpire foo2 100000
  404. r set foo3 bar
  405. r expireat foo3 [expr [clock seconds]+100]
  406. r pexpireat foo3 [expr [clock seconds]*1000+100000]
  407. r expireat foo3 [expr [clock seconds]-100]
  408. # GETEX-family commands
  409. r set foo4 bar
  410. r getex foo4 ex 200
  411. r getex foo4 px 200000
  412. r getex foo4 exat [expr [clock seconds]+100]
  413. r getex foo4 pxat [expr [clock milliseconds]+100000]
  414. # RESTORE commands
  415. r set foo5 bar
  416. set encoded [r dump foo5]
  417. r restore foo6 100000 $encoded
  418. r restore foo7 [expr [clock milliseconds]+100000] $encoded absttl
  419. assert_replication_stream $repl {
  420. {select *}
  421. {set foo1 bar PXAT *}
  422. {set foo1 bar PXAT *}
  423. {set foo1 bar PXAT *}
  424. {set foo1 bar PXAT *}
  425. {set foo1 bar PXAT *}
  426. {set foo1 bar PXAT *}
  427. {set foo2 bar}
  428. {pexpireat foo2 *}
  429. {pexpireat foo2 *}
  430. {set foo3 bar}
  431. {pexpireat foo3 *}
  432. {pexpireat foo3 *}
  433. {del foo3}
  434. {set foo4 bar}
  435. {pexpireat foo4 *}
  436. {pexpireat foo4 *}
  437. {pexpireat foo4 *}
  438. {pexpireat foo4 *}
  439. {set foo5 bar}
  440. {restore foo6 * {*} ABSTTL}
  441. {restore foo7 * {*} absttl}
  442. }
  443. } {} {needs:repl}
  444. # Start another server to test replication of TTLs
  445. start_server {tags {needs:repl external:skip}} {
  446. # Set the outer layer server as primary
  447. set primary [srv -1 client]
  448. set primary_host [srv -1 host]
  449. set primary_port [srv -1 port]
  450. # Set this inner layer server as replica
  451. set replica [srv 0 client]
  452. test {First server should have role slave after REPLICAOF} {
  453. $replica replicaof $primary_host $primary_port
  454. wait_for_condition 50 100 {
  455. [s 0 role] eq {slave}
  456. } else {
  457. fail "Replication not started."
  458. }
  459. }
  460. test {For all replicated TTL-related commands, absolute expire times are identical on primary and replica} {
  461. # Apply each TTL-related command to a unique key on primary
  462. # SET commands
  463. $primary set foo1 bar ex 100
  464. $primary set foo2 bar px 100000
  465. $primary set foo3 bar exat [expr [clock seconds]+100]
  466. $primary set foo4 bar pxat [expr [clock milliseconds]+100000]
  467. $primary setex foo5 100 bar
  468. $primary psetex foo6 100000 bar
  469. # EXPIRE-family commands
  470. $primary set foo7 bar
  471. $primary expire foo7 100
  472. $primary set foo8 bar
  473. $primary pexpire foo8 100000
  474. $primary set foo9 bar
  475. $primary expireat foo9 [expr [clock seconds]+100]
  476. $primary set foo10 bar
  477. $primary pexpireat foo10 [expr [clock milliseconds]+100000]
  478. # GETEX commands
  479. $primary set foo11 bar
  480. $primary getex foo11 ex 100
  481. $primary set foo12 bar
  482. $primary getex foo12 px 100000
  483. $primary set foo13 bar
  484. $primary getex foo13 exat [expr [clock seconds]+100]
  485. $primary set foo14 bar
  486. $primary getex foo14 pxat [expr [clock milliseconds]+100000]
  487. # RESTORE commands
  488. $primary set foo15 bar
  489. set encoded [$primary dump foo15]
  490. $primary restore foo16 100000 $encoded
  491. $primary restore foo17 [expr [clock milliseconds]+100000] $encoded absttl
  492. # Wait for replica to get the keys and TTLs
  493. assert {[$primary wait 1 0] == 1}
  494. # Verify absolute TTLs are identical on primary and replica for all keys
  495. # This is because TTLs are always replicated as absolute values
  496. foreach key [$primary keys *] {
  497. assert_equal [$primary pexpiretime $key] [$replica pexpiretime $key]
  498. }
  499. }
  500. }
  501. test {SET command will remove expire} {
  502. r set foo bar EX 100
  503. r set foo bar
  504. r ttl foo
  505. } {-1}
  506. test {SET - use KEEPTTL option, TTL should not be removed} {
  507. r set foo bar EX 100
  508. r set foo bar KEEPTTL
  509. set ttl [r ttl foo]
  510. assert {$ttl <= 100 && $ttl > 90}
  511. }
  512. test {SET - use KEEPTTL option, TTL should not be removed after loadaof} {
  513. r config set appendonly yes
  514. r set foo bar EX 100
  515. r set foo bar2 KEEPTTL
  516. after 2000
  517. r debug loadaof
  518. set ttl [r ttl foo]
  519. assert {$ttl <= 98 && $ttl > 90}
  520. } {} {needs:debug}
  521. test {GETEX use of PERSIST option should remove TTL} {
  522. r set foo bar EX 100
  523. r getex foo PERSIST
  524. r ttl foo
  525. } {-1}
  526. test {GETEX use of PERSIST option should remove TTL after loadaof} {
  527. r set foo bar EX 100
  528. r getex foo PERSIST
  529. after 2000
  530. r debug loadaof
  531. r ttl foo
  532. } {-1} {needs:debug}
  533. test {GETEX propagate as to replica as PERSIST, DEL, or nothing} {
  534. set repl [attach_to_replication_stream]
  535. r set foo bar EX 100
  536. r getex foo PERSIST
  537. r getex foo
  538. r getex foo exat [expr [clock seconds]-100]
  539. assert_replication_stream $repl {
  540. {select *}
  541. {set foo bar PXAT *}
  542. {persist foo}
  543. {del foo}
  544. }
  545. } {} {needs:repl}
  546. test {EXPIRE with NX option on a key with ttl} {
  547. r SET foo bar EX 100
  548. assert_equal [r EXPIRE foo 200 NX] 0
  549. assert_range [r TTL foo] 50 100
  550. } {}
  551. test {EXPIRE with NX option on a key without ttl} {
  552. r SET foo bar
  553. assert_equal [r EXPIRE foo 200 NX] 1
  554. assert_range [r TTL foo] 100 200
  555. } {}
  556. test {EXPIRE with XX option on a key with ttl} {
  557. r SET foo bar EX 100
  558. assert_equal [r EXPIRE foo 200 XX] 1
  559. assert_range [r TTL foo] 100 200
  560. } {}
  561. test {EXPIRE with XX option on a key without ttl} {
  562. r SET foo bar
  563. assert_equal [r EXPIRE foo 200 XX] 0
  564. assert_equal [r TTL foo] -1
  565. } {}
  566. test {EXPIRE with GT option on a key with lower ttl} {
  567. r SET foo bar EX 100
  568. assert_equal [r EXPIRE foo 200 GT] 1
  569. assert_range [r TTL foo] 100 200
  570. } {}
  571. test {EXPIRE with GT option on a key with higher ttl} {
  572. r SET foo bar EX 200
  573. assert_equal [r EXPIRE foo 100 GT] 0
  574. assert_range [r TTL foo] 100 200
  575. } {}
  576. test {EXPIRE with GT option on a key without ttl} {
  577. r SET foo bar
  578. assert_equal [r EXPIRE foo 200 GT] 0
  579. assert_equal [r TTL foo] -1
  580. } {}
  581. test {EXPIRE with LT option on a key with higher ttl} {
  582. r SET foo bar EX 100
  583. assert_equal [r EXPIRE foo 200 LT] 0
  584. assert_range [r TTL foo] 50 100
  585. } {}
  586. test {EXPIRE with LT option on a key with lower ttl} {
  587. r SET foo bar EX 200
  588. assert_equal [r EXPIRE foo 100 LT] 1
  589. assert_range [r TTL foo] 50 100
  590. } {}
  591. test {EXPIRE with LT option on a key without ttl} {
  592. r SET foo bar
  593. assert_equal [r EXPIRE foo 100 LT] 1
  594. assert_range [r TTL foo] 50 100
  595. } {}
  596. test {EXPIRE with LT and XX option on a key with ttl} {
  597. r SET foo bar EX 200
  598. assert_equal [r EXPIRE foo 100 LT XX] 1
  599. assert_range [r TTL foo] 50 100
  600. } {}
  601. test {EXPIRE with LT and XX option on a key without ttl} {
  602. r SET foo bar
  603. assert_equal [r EXPIRE foo 200 LT XX] 0
  604. assert_equal [r TTL foo] -1
  605. } {}
  606. test {EXPIRE with conflicting options: LT GT} {
  607. catch {r EXPIRE foo 200 LT GT} e
  608. set e
  609. } {ERR GT and LT options at the same time are not compatible}
  610. test {EXPIRE with conflicting options: NX GT} {
  611. catch {r EXPIRE foo 200 NX GT} e
  612. set e
  613. } {ERR NX and XX, GT or LT options at the same time are not compatible}
  614. test {EXPIRE with conflicting options: NX LT} {
  615. catch {r EXPIRE foo 200 NX LT} e
  616. set e
  617. } {ERR NX and XX, GT or LT options at the same time are not compatible}
  618. test {EXPIRE with conflicting options: NX XX} {
  619. catch {r EXPIRE foo 200 NX XX} e
  620. set e
  621. } {ERR NX and XX, GT or LT options at the same time are not compatible}
  622. test {EXPIRE with unsupported options} {
  623. catch {r EXPIRE foo 200 AB} e
  624. set e
  625. } {ERR Unsupported option AB}
  626. test {EXPIRE with unsupported options} {
  627. catch {r EXPIRE foo 200 XX AB} e
  628. set e
  629. } {ERR Unsupported option AB}
  630. test {EXPIRE with negative expiry} {
  631. r SET foo bar EX 100
  632. assert_equal [r EXPIRE foo -10 LT] 1
  633. assert_equal [r TTL foo] -2
  634. } {}
  635. test {EXPIRE with negative expiry on a non-valitale key} {
  636. r SET foo bar
  637. assert_equal [r EXPIRE foo -10 LT] 1
  638. assert_equal [r TTL foo] -2
  639. } {}
  640. test {EXPIRE with non-existed key} {
  641. assert_equal [r EXPIRE none 100 NX] 0
  642. assert_equal [r EXPIRE none 100 XX] 0
  643. assert_equal [r EXPIRE none 100 GT] 0
  644. assert_equal [r EXPIRE none 100 LT] 0
  645. } {}
  646. }