tracking.tcl 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. start_server {tags {"tracking network"}} {
  2. # Create a deferred client we'll use to redirect invalidation
  3. # messages to.
  4. set rd_redirection [redis_deferring_client]
  5. $rd_redirection client id
  6. set redir_id [$rd_redirection read]
  7. $rd_redirection subscribe __redis__:invalidate
  8. $rd_redirection read ; # Consume the SUBSCRIBE reply.
  9. # Create another client that's not used as a redirection client
  10. # We should always keep this client's buffer clean
  11. set rd [redis_deferring_client]
  12. # Client to be used for SET and GET commands
  13. # We don't read this client's buffer
  14. set rd_sg [redis_client]
  15. proc clean_all {} {
  16. uplevel {
  17. # We should make r TRACKING off first. If r is in RESP3,
  18. # r FLUSH ALL will send us tracking-redir-broken or other
  19. # info which will not be consumed.
  20. r CLIENT TRACKING off
  21. $rd QUIT
  22. $rd_redirection QUIT
  23. set rd [redis_deferring_client]
  24. set rd_redirection [redis_deferring_client]
  25. $rd_redirection client id
  26. set redir_id [$rd_redirection read]
  27. $rd_redirection subscribe __redis__:invalidate
  28. $rd_redirection read ; # Consume the SUBSCRIBE reply.
  29. r FLUSHALL
  30. r HELLO 2
  31. r config set tracking-table-max-keys 1000000
  32. }
  33. }
  34. test {Clients are able to enable tracking and redirect it} {
  35. r CLIENT TRACKING on REDIRECT $redir_id
  36. } {*OK}
  37. test {The other connection is able to get invalidations} {
  38. r SET a{t} 1
  39. r SET b{t} 1
  40. r GET a{t}
  41. r INCR b{t} ; # This key should not be notified, since it wasn't fetched.
  42. r INCR a{t}
  43. set keys [lindex [$rd_redirection read] 2]
  44. assert {[llength $keys] == 1}
  45. assert {[lindex $keys 0] eq {a{t}}}
  46. }
  47. test {The client is now able to disable tracking} {
  48. # Make sure to add a few more keys in the tracking list
  49. # so that we can check for leaks, as a side effect.
  50. r MGET a{t} b{t} c{t} d{t} e{t} f{t} g{t}
  51. r CLIENT TRACKING off
  52. } {*OK}
  53. test {Clients can enable the BCAST mode with the empty prefix} {
  54. r CLIENT TRACKING on BCAST REDIRECT $redir_id
  55. } {*OK*}
  56. test {The connection gets invalidation messages about all the keys} {
  57. r MSET a{t} 1 b{t} 2 c{t} 3
  58. set keys [lsort [lindex [$rd_redirection read] 2]]
  59. assert {$keys eq {a{t} b{t} c{t}}}
  60. }
  61. test {Clients can enable the BCAST mode with prefixes} {
  62. r CLIENT TRACKING off
  63. r CLIENT TRACKING on BCAST REDIRECT $redir_id PREFIX a: PREFIX b:
  64. r MULTI
  65. r INCR a:1{t}
  66. r INCR a:2{t}
  67. r INCR b:1{t}
  68. r INCR b:2{t}
  69. # we should not get this key
  70. r INCR c:1{t}
  71. r EXEC
  72. # Because of the internals, we know we are going to receive
  73. # two separated notifications for the two different prefixes.
  74. set keys1 [lsort [lindex [$rd_redirection read] 2]]
  75. set keys2 [lsort [lindex [$rd_redirection read] 2]]
  76. set keys [lsort [list {*}$keys1 {*}$keys2]]
  77. assert {$keys eq {a:1{t} a:2{t} b:1{t} b:2{t}}}
  78. }
  79. test {Adding prefixes to BCAST mode works} {
  80. r CLIENT TRACKING on BCAST REDIRECT $redir_id PREFIX c:
  81. r INCR c:1234
  82. set keys [lsort [lindex [$rd_redirection read] 2]]
  83. assert {$keys eq {c:1234}}
  84. }
  85. test {Tracking NOLOOP mode in standard mode works} {
  86. r CLIENT TRACKING off
  87. r CLIENT TRACKING on REDIRECT $redir_id NOLOOP
  88. r MGET otherkey1{t} loopkey{t} otherkey2{t}
  89. $rd_sg SET otherkey1{t} 1; # We should get this
  90. r SET loopkey{t} 1 ; # We should not get this
  91. $rd_sg SET otherkey2{t} 1; # We should get this
  92. # Because of the internals, we know we are going to receive
  93. # two separated notifications for the two different keys.
  94. set keys1 [lsort [lindex [$rd_redirection read] 2]]
  95. set keys2 [lsort [lindex [$rd_redirection read] 2]]
  96. set keys [lsort [list {*}$keys1 {*}$keys2]]
  97. assert {$keys eq {otherkey1{t} otherkey2{t}}}
  98. }
  99. test {Tracking NOLOOP mode in BCAST mode works} {
  100. r CLIENT TRACKING off
  101. r CLIENT TRACKING on BCAST REDIRECT $redir_id NOLOOP
  102. $rd_sg SET otherkey1 1; # We should get this
  103. r SET loopkey 1 ; # We should not get this
  104. $rd_sg SET otherkey2 1; # We should get this
  105. # Because $rd_sg send command synchronously, we know we are
  106. # going to receive two separated notifications.
  107. set keys1 [lsort [lindex [$rd_redirection read] 2]]
  108. set keys2 [lsort [lindex [$rd_redirection read] 2]]
  109. set keys [lsort [list {*}$keys1 {*}$keys2]]
  110. assert {$keys eq {otherkey1 otherkey2}}
  111. }
  112. test {Tracking gets notification of expired keys} {
  113. r CLIENT TRACKING off
  114. r CLIENT TRACKING on BCAST REDIRECT $redir_id NOLOOP
  115. r SET mykey myval px 1
  116. r SET mykeyotherkey myval ; # We should not get it
  117. after 1000
  118. set keys [lsort [lindex [$rd_redirection read] 2]]
  119. assert {$keys eq {mykey}}
  120. }
  121. test {Tracking gets notification of lazy expired keys} {
  122. r CLIENT TRACKING off
  123. r CLIENT TRACKING on BCAST REDIRECT $redir_id NOLOOP
  124. # Use multi-exec to expose a race where the key gets an two invalidations
  125. # in the same event loop, once by the client so filtered by NOLOOP, and
  126. # the second one by the lazy expire
  127. r MULTI
  128. r SET mykey{t} myval px 1
  129. r SET mykeyotherkey{t} myval ; # We should not get it
  130. r DEBUG SLEEP 0.1
  131. r GET mykey{t}
  132. r EXEC
  133. set keys [lsort [lindex [$rd_redirection read] 2]]
  134. assert {$keys eq {mykey{t}}}
  135. } {} {needs:debug}
  136. test {HELLO 3 reply is correct} {
  137. set reply [r HELLO 3]
  138. assert_equal [dict get $reply proto] 3
  139. }
  140. test {HELLO without protover} {
  141. set reply [r HELLO 3]
  142. assert_equal [dict get $reply proto] 3
  143. set reply [r HELLO]
  144. assert_equal [dict get $reply proto] 3
  145. set reply [r HELLO 2]
  146. assert_equal [dict get $reply proto] 2
  147. set reply [r HELLO]
  148. assert_equal [dict get $reply proto] 2
  149. # restore RESP3 for next test
  150. r HELLO 3
  151. }
  152. test {RESP3 based basic invalidation} {
  153. r CLIENT TRACKING off
  154. r CLIENT TRACKING on
  155. $rd_sg SET key1 1
  156. r GET key1
  157. $rd_sg SET key1 2
  158. r read
  159. } {invalidate key1}
  160. test {RESP3 tracking redirection} {
  161. r CLIENT TRACKING off
  162. r CLIENT TRACKING on REDIRECT $redir_id
  163. $rd_sg SET key1 1
  164. r GET key1
  165. $rd_sg SET key1 2
  166. set res [lindex [$rd_redirection read] 2]
  167. assert {$res eq {key1}}
  168. }
  169. test {Invalidations of previous keys can be redirected after switching to RESP3} {
  170. r HELLO 2
  171. $rd_sg SET key1 1
  172. r GET key1
  173. r HELLO 3
  174. $rd_sg SET key1 2
  175. set res [lindex [$rd_redirection read] 2]
  176. assert {$res eq {key1}}
  177. }
  178. test {Invalidations of new keys can be redirected after switching to RESP3} {
  179. r HELLO 3
  180. $rd_sg SET key1 1
  181. r GET key1
  182. $rd_sg SET key1 2
  183. set res [lindex [$rd_redirection read] 2]
  184. assert {$res eq {key1}}
  185. }
  186. test {RESP3 Client gets tracking-redir-broken push message after cached key changed when rediretion client is terminated} {
  187. r CLIENT TRACKING on REDIRECT $redir_id
  188. $rd_sg SET key1 1
  189. r GET key1
  190. $rd_redirection QUIT
  191. assert_equal OK [$rd_redirection read]
  192. $rd_sg SET key1 2
  193. set MAX_TRIES 100
  194. set res -1
  195. for {set i 0} {$i <= $MAX_TRIES && $res < 0} {incr i} {
  196. set res [lsearch -exact [r PING] "tracking-redir-broken"]
  197. }
  198. assert {$res >= 0}
  199. # Consume PING reply
  200. assert_equal PONG [r read]
  201. # Reinstantiating after QUIT
  202. set rd_redirection [redis_deferring_client]
  203. $rd_redirection CLIENT ID
  204. set redir_id [$rd_redirection read]
  205. $rd_redirection SUBSCRIBE __redis__:invalidate
  206. $rd_redirection read ; # Consume the SUBSCRIBE reply
  207. }
  208. test {Different clients can redirect to the same connection} {
  209. r CLIENT TRACKING on REDIRECT $redir_id
  210. $rd CLIENT TRACKING on REDIRECT $redir_id
  211. assert_equal OK [$rd read] ; # Consume the TRACKING reply
  212. $rd_sg MSET key1{t} 1 key2{t} 1
  213. r GET key1{t}
  214. $rd GET key2{t}
  215. assert_equal 1 [$rd read] ; # Consume the GET reply
  216. $rd_sg INCR key1{t}
  217. $rd_sg INCR key2{t}
  218. set res1 [lindex [$rd_redirection read] 2]
  219. set res2 [lindex [$rd_redirection read] 2]
  220. assert {$res1 eq {key1{t}}}
  221. assert {$res2 eq {key2{t}}}
  222. }
  223. test {Different clients using different protocols can track the same key} {
  224. $rd HELLO 3
  225. set reply [$rd read] ; # Consume the HELLO reply
  226. assert_equal 3 [dict get $reply proto]
  227. $rd CLIENT TRACKING on
  228. assert_equal OK [$rd read] ; # Consume the TRACKING reply
  229. $rd_sg set key1 1
  230. r GET key1
  231. $rd GET key1
  232. assert_equal 1 [$rd read] ; # Consume the GET reply
  233. $rd_sg INCR key1
  234. set res1 [lindex [$rd_redirection read] 2]
  235. $rd PING ; # Non redirecting client has to talk to the server in order to get invalidation message
  236. set res2 [lindex [split [$rd read] " "] 1]
  237. assert_equal PONG [$rd read] ; # Consume the PING reply, which comes together with the invalidation message
  238. assert {$res1 eq {key1}}
  239. assert {$res2 eq {key1}}
  240. }
  241. test {No invalidation message when using OPTIN option} {
  242. r CLIENT TRACKING on OPTIN REDIRECT $redir_id
  243. $rd_sg SET key1 1
  244. r GET key1 ; # This key should not be notified, since OPTIN is on and CLIENT CACHING yes wasn't called
  245. $rd_sg SET key1 2
  246. # Preparing some message to consume on $rd_redirection so we don't get blocked
  247. r CLIENT TRACKING off
  248. r CLIENT TRACKING on REDIRECT $redir_id
  249. $rd_sg SET key2 1
  250. r GET key2 ; # This key should be notified
  251. $rd_sg SET key2 2
  252. set res [lindex [$rd_redirection read] 2]
  253. assert {$res eq {key2}}
  254. }
  255. test {Invalidation message sent when using OPTIN option with CLIENT CACHING yes} {
  256. r CLIENT TRACKING on OPTIN REDIRECT $redir_id
  257. $rd_sg SET key1 3
  258. r CLIENT CACHING yes
  259. r GET key1
  260. $rd_sg SET key1 4
  261. set res [lindex [$rd_redirection read] 2]
  262. assert {$res eq {key1}}
  263. }
  264. test {Invalidation message sent when using OPTOUT option} {
  265. r CLIENT TRACKING off
  266. r CLIENT TRACKING on OPTOUT REDIRECT $redir_id
  267. $rd_sg SET key1 1
  268. r GET key1
  269. $rd_sg SET key1 2
  270. set res [lindex [$rd_redirection read] 2]
  271. assert {$res eq {key1}}
  272. }
  273. test {No invalidation message when using OPTOUT option with CLIENT CACHING no} {
  274. $rd_sg SET key1 1
  275. r CLIENT CACHING no
  276. r GET key1 ; # This key should not be notified, since OPTOUT is on and CLIENT CACHING no was called
  277. $rd_sg SET key1 2
  278. # Preparing some message to consume on $rd_redirection so we don't get blocked
  279. $rd_sg SET key2 1
  280. r GET key2 ; # This key should be notified
  281. $rd_sg SET key2 2
  282. set res [lindex [$rd_redirection read] 2]
  283. assert {$res eq {key2}}
  284. }
  285. test {Able to redirect to a RESP3 client} {
  286. $rd_redirection UNSUBSCRIBE __redis__:invalidate ; # Need to unsub first before we can do HELLO 3
  287. set res [$rd_redirection read] ; # Consume the UNSUBSCRIBE reply
  288. assert_equal {__redis__:invalidate} [lindex $res 1]
  289. $rd_redirection HELLO 3
  290. set res [$rd_redirection read] ; # Consume the HELLO reply
  291. assert_equal [dict get $reply proto] 3
  292. $rd_redirection SUBSCRIBE __redis__:invalidate
  293. set res [$rd_redirection read] ; # Consume the SUBSCRIBE reply
  294. assert_equal {__redis__:invalidate} [lindex $res 1]
  295. r CLIENT TRACKING on REDIRECT $redir_id
  296. $rd_sg SET key1 1
  297. r GET key1
  298. $rd_sg INCR key1
  299. set res [lindex [$rd_redirection read] 1]
  300. assert {$res eq {key1}}
  301. $rd_redirection HELLO 2
  302. set res [$rd_redirection read] ; # Consume the HELLO reply
  303. assert_equal [dict get $res proto] 2
  304. }
  305. test {After switching from normal tracking to BCAST mode, no invalidation message is produced for pre-BCAST keys} {
  306. r CLIENT TRACKING off
  307. r HELLO 3
  308. r CLIENT TRACKING on
  309. $rd_sg SET key1 1
  310. r GET key1
  311. r CLIENT TRACKING off
  312. r CLIENT TRACKING on BCAST
  313. $rd_sg INCR key1
  314. set inv_msg [r PING]
  315. set ping_reply [r read]
  316. assert {$inv_msg eq {invalidate key1}}
  317. assert {$ping_reply eq {PONG}}
  318. }
  319. test {BCAST with prefix collisions throw errors} {
  320. set r [redis_client]
  321. catch {$r CLIENT TRACKING ON BCAST PREFIX FOOBAR PREFIX FOO} output
  322. assert_match {ERR Prefix 'FOOBAR'*'FOO'*} $output
  323. catch {$r CLIENT TRACKING ON BCAST PREFIX FOO PREFIX FOOBAR} output
  324. assert_match {ERR Prefix 'FOO'*'FOOBAR'*} $output
  325. $r CLIENT TRACKING ON BCAST PREFIX FOO PREFIX BAR
  326. catch {$r CLIENT TRACKING ON BCAST PREFIX FO} output
  327. assert_match {ERR Prefix 'FO'*'FOO'*} $output
  328. catch {$r CLIENT TRACKING ON BCAST PREFIX BARB} output
  329. assert_match {ERR Prefix 'BARB'*'BAR'*} $output
  330. $r CLIENT TRACKING OFF
  331. }
  332. test {hdel deliver invlidate message after response in the same connection} {
  333. r CLIENT TRACKING off
  334. r HELLO 3
  335. r CLIENT TRACKING on
  336. r HSET myhash f 1
  337. r HGET myhash f
  338. set res [r HDEL myhash f]
  339. assert_equal $res 1
  340. set res [r read]
  341. assert_equal $res {invalidate myhash}
  342. }
  343. test {Tracking invalidation message is not interleaved with multiple keys response} {
  344. r CLIENT TRACKING off
  345. r HELLO 3
  346. r CLIENT TRACKING on
  347. # We need disable active expire, so we can trigger lazy expire
  348. r DEBUG SET-ACTIVE-EXPIRE 0
  349. r MULTI
  350. r MSET x{t} 1 y{t} 2
  351. r PEXPIRE y{t} 100
  352. r GET y{t}
  353. r EXEC
  354. after 110
  355. # Read expired key y{t}, generate invalidate message about this key
  356. set res [r MGET x{t} y{t}]
  357. assert_equal $res {1 {}}
  358. # Consume the invalidate message which is after command response
  359. set res [r read]
  360. assert_equal $res {invalidate y{t}}
  361. r DEBUG SET-ACTIVE-EXPIRE 1
  362. } {OK} {needs:debug}
  363. test {Tracking invalidation message is not interleaved with transaction response} {
  364. r CLIENT TRACKING off
  365. r HELLO 3
  366. r CLIENT TRACKING on
  367. r MSET a{t} 1 b{t} 2
  368. r GET a{t}
  369. # Start a transaction, make a{t} generate an invalidate message
  370. r MULTI
  371. r INCR a{t}
  372. r GET b{t}
  373. set res [r EXEC]
  374. assert_equal $res {2 2}
  375. set res [r read]
  376. # Consume the invalidate message which is after command response
  377. assert_equal $res {invalidate a{t}}
  378. }
  379. test {Tracking invalidation message of eviction keys should be before response} {
  380. # Get the current memory limit and calculate a new limit.
  381. r CLIENT TRACKING off
  382. r HELLO 3
  383. r CLIENT TRACKING on
  384. # make the previous test is really done before sampling used_memory
  385. wait_lazyfree_done r
  386. set used [s used_memory]
  387. set limit [expr {$used+100*1024}]
  388. set old_policy [lindex [r config get maxmemory-policy] 1]
  389. r config set maxmemory $limit
  390. # We set policy volatile-random, so only keys with ttl will be evicted
  391. r config set maxmemory-policy volatile-random
  392. # Add a volatile key and tracking it.
  393. r setex volatile-key 10000 x
  394. r get volatile-key
  395. # We use SETBIT here, so we can set a big key and get the used_memory
  396. # bigger than maxmemory. Next command will evict volatile keys. We
  397. # can't use SET, as SET uses big input buffer, so it will fail.
  398. r setbit big-key 1000000 0
  399. # volatile-key is evicted before response.
  400. set res [r getbit big-key 0]
  401. assert_equal $res {invalidate volatile-key}
  402. set res [r read]
  403. assert_equal $res 0
  404. r config set maxmemory-policy $old_policy
  405. r config set maxmemory 0
  406. }
  407. test {Unblocked BLMOVE gets notification after response} {
  408. r RPUSH list2{t} a
  409. $rd HELLO 3
  410. $rd read
  411. $rd CLIENT TRACKING on
  412. $rd read
  413. # Tracking key list2{t}
  414. $rd LRANGE list2{t} 0 -1
  415. $rd read
  416. # We block on list1{t}
  417. $rd BLMOVE list1{t} list2{t} left left 0
  418. wait_for_blocked_clients_count 1
  419. # unblock $rd, list2{t} gets element and generate invalidation message
  420. r rpush list1{t} foo
  421. assert_equal [$rd read] {foo}
  422. assert_equal [$rd read] {invalidate list2{t}}
  423. }
  424. test {Tracking gets notification on tracking table key eviction} {
  425. r CLIENT TRACKING off
  426. r CLIENT TRACKING on REDIRECT $redir_id NOLOOP
  427. r MSET key1{t} 1 key2{t} 2
  428. # Let the server track the two keys for us
  429. r MGET key1{t} key2{t}
  430. # Force the eviction of all the keys but one:
  431. r config set tracking-table-max-keys 1
  432. # Note that we may have other keys in the table for this client,
  433. # since we disabled/enabled tracking multiple time with the same
  434. # ID, and tracking does not do ID cleanups for performance reasons.
  435. # So we check that eventually we'll receive one or the other key,
  436. # otherwise the test will die for timeout.
  437. while 1 {
  438. set keys [lindex [$rd_redirection read] 2]
  439. if {$keys eq {key1{t}} || $keys eq {key2{t}}} break
  440. }
  441. # We should receive an expire notification for one of
  442. # the two keys (only one must remain)
  443. assert {$keys eq {key1{t}} || $keys eq {key2{t}}}
  444. }
  445. test {Invalidation message received for flushall} {
  446. clean_all
  447. r CLIENT TRACKING on REDIRECT $redir_id
  448. $rd_sg SET key1 1
  449. r GET key1
  450. $rd_sg FLUSHALL
  451. set msg [$rd_redirection read]
  452. assert {[lindex msg 2] eq {} }
  453. }
  454. test {Invalidation message received for flushdb} {
  455. clean_all
  456. r CLIENT TRACKING on REDIRECT $redir_id
  457. $rd_sg SET key1 1
  458. r GET key1
  459. $rd_sg FLUSHDB
  460. set msg [$rd_redirection read]
  461. assert {[lindex msg 2] eq {} }
  462. }
  463. test {Test ASYNC flushall} {
  464. clean_all
  465. r CLIENT TRACKING on REDIRECT $redir_id
  466. r GET key1
  467. r GET key2
  468. assert_equal [s 0 tracking_total_keys] 2
  469. $rd_sg FLUSHALL ASYNC
  470. assert_equal [s 0 tracking_total_keys] 0
  471. assert_equal [lindex [$rd_redirection read] 2] {}
  472. }
  473. # Keys are defined to be evicted 100 at a time by default.
  474. # If after eviction the number of keys still surpasses the limit
  475. # defined in tracking-table-max-keys, we increases eviction
  476. # effort to 200, and then 300, etc.
  477. # This test tests this effort incrementation.
  478. test {Server is able to evacuate enough keys when num of keys surpasses limit by more than defined initial effort} {
  479. clean_all
  480. set NUM_OF_KEYS_TO_TEST 250
  481. set TRACKING_TABLE_MAX_KEYS 1
  482. r CLIENT TRACKING on REDIRECT $redir_id
  483. for {set i 0} {$i < $NUM_OF_KEYS_TO_TEST} {incr i} {
  484. $rd_sg SET key$i $i
  485. r GET key$i
  486. }
  487. r config set tracking-table-max-keys $TRACKING_TABLE_MAX_KEYS
  488. # If not enough keys are evicted, we won't get enough invalidation
  489. # messages, and "$rd_redirection read" will block.
  490. # If too many keys are evicted, we will get too many invalidation
  491. # messages, and the assert will fail.
  492. for {set i 0} {$i < $NUM_OF_KEYS_TO_TEST - $TRACKING_TABLE_MAX_KEYS} {incr i} {
  493. $rd_redirection read
  494. }
  495. $rd_redirection PING
  496. assert {[$rd_redirection read] eq {pong {}}}
  497. }
  498. test {Tracking info is correct} {
  499. clean_all
  500. r CLIENT TRACKING on REDIRECT $redir_id
  501. $rd_sg SET key1 1
  502. $rd_sg SET key2 2
  503. r GET key1
  504. r GET key2
  505. $rd CLIENT TRACKING on BCAST PREFIX prefix:
  506. assert [string match *OK* [$rd read]]
  507. $rd_sg SET prefix:key1 1
  508. $rd_sg SET prefix:key2 2
  509. set info [r info]
  510. regexp "\r\ntracking_total_items:(.*?)\r\n" $info _ total_items
  511. regexp "\r\ntracking_total_keys:(.*?)\r\n" $info _ total_keys
  512. regexp "\r\ntracking_total_prefixes:(.*?)\r\n" $info _ total_prefixes
  513. regexp "\r\ntracking_clients:(.*?)\r\n" $info _ tracking_clients
  514. assert {$total_items == 2}
  515. assert {$total_keys == 2}
  516. assert {$total_prefixes == 1}
  517. assert {$tracking_clients == 2}
  518. }
  519. test {CLIENT GETREDIR provides correct client id} {
  520. set res [r CLIENT GETREDIR]
  521. assert_equal $redir_id $res
  522. r CLIENT TRACKING off
  523. set res [r CLIENT GETREDIR]
  524. assert_equal -1 $res
  525. r CLIENT TRACKING on
  526. set res [r CLIENT GETREDIR]
  527. assert_equal 0 $res
  528. }
  529. test {CLIENT TRACKINGINFO provides reasonable results when tracking off} {
  530. r CLIENT TRACKING off
  531. set res [r client trackinginfo]
  532. set flags [dict get $res flags]
  533. assert_equal {off} $flags
  534. set redirect [dict get $res redirect]
  535. assert_equal {-1} $redirect
  536. set prefixes [dict get $res prefixes]
  537. assert_equal {} $prefixes
  538. }
  539. test {CLIENT TRACKINGINFO provides reasonable results when tracking on} {
  540. r CLIENT TRACKING on
  541. set res [r client trackinginfo]
  542. set flags [dict get $res flags]
  543. assert_equal {on} $flags
  544. set redirect [dict get $res redirect]
  545. assert_equal {0} $redirect
  546. set prefixes [dict get $res prefixes]
  547. assert_equal {} $prefixes
  548. }
  549. test {CLIENT TRACKINGINFO provides reasonable results when tracking on with options} {
  550. r CLIENT TRACKING on REDIRECT $redir_id noloop
  551. set res [r client trackinginfo]
  552. set flags [dict get $res flags]
  553. assert_equal {on noloop} $flags
  554. set redirect [dict get $res redirect]
  555. assert_equal $redir_id $redirect
  556. set prefixes [dict get $res prefixes]
  557. assert_equal {} $prefixes
  558. }
  559. test {CLIENT TRACKINGINFO provides reasonable results when tracking optin} {
  560. r CLIENT TRACKING off
  561. r CLIENT TRACKING on optin
  562. set res [r client trackinginfo]
  563. set flags [dict get $res flags]
  564. assert_equal {on optin} $flags
  565. set redirect [dict get $res redirect]
  566. assert_equal {0} $redirect
  567. set prefixes [dict get $res prefixes]
  568. assert_equal {} $prefixes
  569. r CLIENT CACHING yes
  570. set res [r client trackinginfo]
  571. set flags [dict get $res flags]
  572. assert_equal {on optin caching-yes} $flags
  573. }
  574. test {CLIENT TRACKINGINFO provides reasonable results when tracking optout} {
  575. r CLIENT TRACKING off
  576. r CLIENT TRACKING on optout
  577. set res [r client trackinginfo]
  578. set flags [dict get $res flags]
  579. assert_equal {on optout} $flags
  580. set redirect [dict get $res redirect]
  581. assert_equal {0} $redirect
  582. set prefixes [dict get $res prefixes]
  583. assert_equal {} $prefixes
  584. r CLIENT CACHING no
  585. set res [r client trackinginfo]
  586. set flags [dict get $res flags]
  587. assert_equal {on optout caching-no} $flags
  588. }
  589. test {CLIENT TRACKINGINFO provides reasonable results when tracking bcast mode} {
  590. r CLIENT TRACKING off
  591. r CLIENT TRACKING on BCAST PREFIX foo PREFIX bar
  592. set res [r client trackinginfo]
  593. set flags [dict get $res flags]
  594. assert_equal {on bcast} $flags
  595. set redirect [dict get $res redirect]
  596. assert_equal {0} $redirect
  597. set prefixes [lsort [dict get $res prefixes]]
  598. assert_equal {bar foo} $prefixes
  599. r CLIENT TRACKING off
  600. r CLIENT TRACKING on BCAST
  601. set res [r client trackinginfo]
  602. set prefixes [dict get $res prefixes]
  603. assert_equal {{}} $prefixes
  604. }
  605. test {CLIENT TRACKINGINFO provides reasonable results when tracking redir broken} {
  606. clean_all
  607. r HELLO 3
  608. r CLIENT TRACKING on REDIRECT $redir_id
  609. $rd_sg SET key1 1
  610. r GET key1
  611. $rd_redirection QUIT
  612. assert_equal OK [$rd_redirection read]
  613. $rd_sg SET key1 2
  614. set res [lsearch -exact [r read] "tracking-redir-broken"]
  615. assert {$res >= 0}
  616. set res [r client trackinginfo]
  617. set flags [dict get $res flags]
  618. assert_equal {on broken_redirect} $flags
  619. set redirect [dict get $res redirect]
  620. assert_equal $redir_id $redirect
  621. set prefixes [dict get $res prefixes]
  622. assert_equal {} $prefixes
  623. }
  624. $rd_redirection close
  625. $rd close
  626. }