diff options
Diffstat (limited to 'examples/redis-unstable/tests/unit/moduleapi/propagate.tcl')
| -rw-r--r-- | examples/redis-unstable/tests/unit/moduleapi/propagate.tcl | 806 |
1 files changed, 0 insertions, 806 deletions
diff --git a/examples/redis-unstable/tests/unit/moduleapi/propagate.tcl b/examples/redis-unstable/tests/unit/moduleapi/propagate.tcl deleted file mode 100644 index d3d08d9..0000000 --- a/examples/redis-unstable/tests/unit/moduleapi/propagate.tcl +++ /dev/null | |||
| @@ -1,806 +0,0 @@ | |||
| 1 | set testmodule [file normalize tests/modules/propagate.so] | ||
| 2 | set miscmodule [file normalize tests/modules/misc.so] | ||
| 3 | set keyspace_events [file normalize tests/modules/keyspace_events.so] | ||
| 4 | |||
| 5 | tags "modules external:skip" { | ||
| 6 | test {Modules can propagate in async and threaded contexts} { | ||
| 7 | start_server [list overrides [list loadmodule "$testmodule"]] { | ||
| 8 | set replica [srv 0 client] | ||
| 9 | set replica_host [srv 0 host] | ||
| 10 | set replica_port [srv 0 port] | ||
| 11 | $replica module load $keyspace_events | ||
| 12 | start_server [list overrides [list loadmodule "$testmodule"]] { | ||
| 13 | set master [srv 0 client] | ||
| 14 | set master_host [srv 0 host] | ||
| 15 | set master_port [srv 0 port] | ||
| 16 | $master module load $keyspace_events | ||
| 17 | |||
| 18 | # Start the replication process... | ||
| 19 | $replica replicaof $master_host $master_port | ||
| 20 | wait_for_sync $replica | ||
| 21 | after 1000 | ||
| 22 | |||
| 23 | test {module propagates from timer} { | ||
| 24 | set repl [attach_to_replication_stream] | ||
| 25 | |||
| 26 | $master propagate-test.timer | ||
| 27 | |||
| 28 | wait_for_condition 500 10 { | ||
| 29 | [$replica get timer] eq "3" | ||
| 30 | } else { | ||
| 31 | fail "The two counters don't match the expected value." | ||
| 32 | } | ||
| 33 | |||
| 34 | assert_replication_stream $repl { | ||
| 35 | {select *} | ||
| 36 | {incr timer} | ||
| 37 | {incr timer} | ||
| 38 | {incr timer} | ||
| 39 | } | ||
| 40 | close_replication_stream $repl | ||
| 41 | } | ||
| 42 | |||
| 43 | test {module propagation with notifications} { | ||
| 44 | set repl [attach_to_replication_stream] | ||
| 45 | |||
| 46 | $master set x y | ||
| 47 | |||
| 48 | assert_replication_stream $repl { | ||
| 49 | {multi} | ||
| 50 | {select *} | ||
| 51 | {incr notifications} | ||
| 52 | {set x y} | ||
| 53 | {exec} | ||
| 54 | } | ||
| 55 | close_replication_stream $repl | ||
| 56 | } | ||
| 57 | |||
| 58 | test {module propagation with notifications with multi} { | ||
| 59 | set repl [attach_to_replication_stream] | ||
| 60 | |||
| 61 | $master multi | ||
| 62 | $master set x1 y1 | ||
| 63 | $master set x2 y2 | ||
| 64 | $master exec | ||
| 65 | |||
| 66 | assert_replication_stream $repl { | ||
| 67 | {multi} | ||
| 68 | {select *} | ||
| 69 | {incr notifications} | ||
| 70 | {set x1 y1} | ||
| 71 | {incr notifications} | ||
| 72 | {set x2 y2} | ||
| 73 | {exec} | ||
| 74 | } | ||
| 75 | close_replication_stream $repl | ||
| 76 | } | ||
| 77 | |||
| 78 | test {module propagation with notifications with active-expire} { | ||
| 79 | $master debug set-active-expire 1 | ||
| 80 | set repl [attach_to_replication_stream] | ||
| 81 | |||
| 82 | $master set asdf1 1 PX 300 | ||
| 83 | $master set asdf2 2 PX 300 | ||
| 84 | $master set asdf3 3 PX 300 | ||
| 85 | |||
| 86 | wait_for_condition 500 10 { | ||
| 87 | [$replica keys asdf*] eq {} | ||
| 88 | } else { | ||
| 89 | fail "Not all keys have expired" | ||
| 90 | } | ||
| 91 | |||
| 92 | # Note whenever there's double notification: SET with PX issues two separate | ||
| 93 | # notifications: one for "set" and one for "expire" | ||
| 94 | assert_replication_stream $repl { | ||
| 95 | {multi} | ||
| 96 | {select *} | ||
| 97 | {incr notifications} | ||
| 98 | {incr notifications} | ||
| 99 | {set asdf1 1 PXAT *} | ||
| 100 | {exec} | ||
| 101 | {multi} | ||
| 102 | {incr notifications} | ||
| 103 | {incr notifications} | ||
| 104 | {set asdf2 2 PXAT *} | ||
| 105 | {exec} | ||
| 106 | {multi} | ||
| 107 | {incr notifications} | ||
| 108 | {incr notifications} | ||
| 109 | {set asdf3 3 PXAT *} | ||
| 110 | {exec} | ||
| 111 | {multi} | ||
| 112 | {incr notifications} | ||
| 113 | {incr notifications} | ||
| 114 | {incr testkeyspace:expired} | ||
| 115 | {del asdf*} | ||
| 116 | {exec} | ||
| 117 | {multi} | ||
| 118 | {incr notifications} | ||
| 119 | {incr notifications} | ||
| 120 | {incr testkeyspace:expired} | ||
| 121 | {del asdf*} | ||
| 122 | {exec} | ||
| 123 | {multi} | ||
| 124 | {incr notifications} | ||
| 125 | {incr notifications} | ||
| 126 | {incr testkeyspace:expired} | ||
| 127 | {del asdf*} | ||
| 128 | {exec} | ||
| 129 | } | ||
| 130 | close_replication_stream $repl | ||
| 131 | |||
| 132 | $master debug set-active-expire 0 | ||
| 133 | } | ||
| 134 | |||
| 135 | test {module propagation with notifications with eviction case 1} { | ||
| 136 | $master flushall | ||
| 137 | $master set asdf1 1 | ||
| 138 | $master set asdf2 2 | ||
| 139 | $master set asdf3 3 | ||
| 140 | |||
| 141 | $master config set maxmemory-policy allkeys-random | ||
| 142 | $master config set maxmemory 1 | ||
| 143 | |||
| 144 | # Please note the following loop: | ||
| 145 | # We evict a key and send a notification, which does INCR on the "notifications" key, so | ||
| 146 | # that every time we evict any key, "notifications" key exist (it happens inside the | ||
| 147 | # performEvictions loop). So even evicting "notifications" causes INCR on "notifications". | ||
| 148 | # If maxmemory_eviction_tenacity would have been set to 100 this would be an endless loop, but | ||
| 149 | # since the default is 10, at some point the performEvictions loop would end. | ||
| 150 | # Bottom line: "notifications" always exists and we can't really determine the order of evictions | ||
| 151 | # This test is here only for sanity | ||
| 152 | |||
| 153 | # The replica will get the notification with multi exec and we have a generic notification handler | ||
| 154 | # that performs `RedisModule_Call(ctx, "INCR", "c", "multi");` if the notification is inside multi exec. | ||
| 155 | # so we will have 2 keys, "notifications" and "multi". | ||
| 156 | wait_for_condition 500 10 { | ||
| 157 | [$replica dbsize] eq 2 | ||
| 158 | } else { | ||
| 159 | fail "Not all keys have been evicted" | ||
| 160 | } | ||
| 161 | |||
| 162 | $master config set maxmemory 0 | ||
| 163 | $master config set maxmemory-policy noeviction | ||
| 164 | } | ||
| 165 | |||
| 166 | test {module propagation with notifications with eviction case 2} { | ||
| 167 | $master flushall | ||
| 168 | set repl [attach_to_replication_stream] | ||
| 169 | |||
| 170 | $master set asdf1 1 EX 300 | ||
| 171 | $master set asdf2 2 EX 300 | ||
| 172 | $master set asdf3 3 EX 300 | ||
| 173 | |||
| 174 | # Please note we use volatile eviction to prevent the loop described in the test above. | ||
| 175 | # "notifications" is not volatile so it always remains | ||
| 176 | $master config resetstat | ||
| 177 | $master config set maxmemory-policy volatile-ttl | ||
| 178 | $master config set maxmemory 1 | ||
| 179 | |||
| 180 | wait_for_condition 500 10 { | ||
| 181 | [s evicted_keys] eq 3 | ||
| 182 | } else { | ||
| 183 | fail "Not all keys have been evicted" | ||
| 184 | } | ||
| 185 | |||
| 186 | $master config set maxmemory 0 | ||
| 187 | $master config set maxmemory-policy noeviction | ||
| 188 | |||
| 189 | $master set asdf4 4 | ||
| 190 | |||
| 191 | # Note whenever there's double notification: SET with EX issues two separate | ||
| 192 | # notifications: one for "set" and one for "expire" | ||
| 193 | # Note that although CONFIG SET maxmemory is called in this flow (see issue #10014), | ||
| 194 | # eviction will happen and will not induce propagation of the CONFIG command (see #10019). | ||
| 195 | assert_replication_stream $repl { | ||
| 196 | {multi} | ||
| 197 | {select *} | ||
| 198 | {incr notifications} | ||
| 199 | {incr notifications} | ||
| 200 | {set asdf1 1 PXAT *} | ||
| 201 | {exec} | ||
| 202 | {multi} | ||
| 203 | {incr notifications} | ||
| 204 | {incr notifications} | ||
| 205 | {set asdf2 2 PXAT *} | ||
| 206 | {exec} | ||
| 207 | {multi} | ||
| 208 | {incr notifications} | ||
| 209 | {incr notifications} | ||
| 210 | {set asdf3 3 PXAT *} | ||
| 211 | {exec} | ||
| 212 | {multi} | ||
| 213 | {incr notifications} | ||
| 214 | {del asdf*} | ||
| 215 | {exec} | ||
| 216 | {multi} | ||
| 217 | {incr notifications} | ||
| 218 | {del asdf*} | ||
| 219 | {exec} | ||
| 220 | {multi} | ||
| 221 | {incr notifications} | ||
| 222 | {del asdf*} | ||
| 223 | {exec} | ||
| 224 | {multi} | ||
| 225 | {incr notifications} | ||
| 226 | {set asdf4 4} | ||
| 227 | {exec} | ||
| 228 | } | ||
| 229 | close_replication_stream $repl | ||
| 230 | } | ||
| 231 | |||
| 232 | test {module propagation with timer and CONFIG SET maxmemory} { | ||
| 233 | set repl [attach_to_replication_stream] | ||
| 234 | |||
| 235 | $master config resetstat | ||
| 236 | $master config set maxmemory-policy volatile-random | ||
| 237 | |||
| 238 | $master propagate-test.timer-maxmemory | ||
| 239 | |||
| 240 | # Wait until the volatile keys are evicted | ||
| 241 | wait_for_condition 500 10 { | ||
| 242 | [s evicted_keys] eq 2 | ||
| 243 | } else { | ||
| 244 | fail "Not all keys have been evicted" | ||
| 245 | } | ||
| 246 | |||
| 247 | assert_replication_stream $repl { | ||
| 248 | {multi} | ||
| 249 | {select *} | ||
| 250 | {incr notifications} | ||
| 251 | {incr notifications} | ||
| 252 | {set timer-maxmemory-volatile-start 1 PXAT *} | ||
| 253 | {incr timer-maxmemory-middle} | ||
| 254 | {incr notifications} | ||
| 255 | {incr notifications} | ||
| 256 | {set timer-maxmemory-volatile-end 1 PXAT *} | ||
| 257 | {exec} | ||
| 258 | {multi} | ||
| 259 | {incr notifications} | ||
| 260 | {del timer-maxmemory-volatile-*} | ||
| 261 | {exec} | ||
| 262 | {multi} | ||
| 263 | {incr notifications} | ||
| 264 | {del timer-maxmemory-volatile-*} | ||
| 265 | {exec} | ||
| 266 | } | ||
| 267 | close_replication_stream $repl | ||
| 268 | |||
| 269 | $master config set maxmemory 0 | ||
| 270 | $master config set maxmemory-policy noeviction | ||
| 271 | } | ||
| 272 | |||
| 273 | test {module propagation with timer and EVAL} { | ||
| 274 | set repl [attach_to_replication_stream] | ||
| 275 | |||
| 276 | $master propagate-test.timer-eval | ||
| 277 | |||
| 278 | assert_replication_stream $repl { | ||
| 279 | {multi} | ||
| 280 | {select *} | ||
| 281 | {incr notifications} | ||
| 282 | {incrby timer-eval-start 1} | ||
| 283 | {incr notifications} | ||
| 284 | {set foo bar} | ||
| 285 | {incr timer-eval-middle} | ||
| 286 | {incr notifications} | ||
| 287 | {incrby timer-eval-end 1} | ||
| 288 | {exec} | ||
| 289 | } | ||
| 290 | close_replication_stream $repl | ||
| 291 | } | ||
| 292 | |||
| 293 | test {module propagates nested ctx case1} { | ||
| 294 | set repl [attach_to_replication_stream] | ||
| 295 | |||
| 296 | $master propagate-test.timer-nested | ||
| 297 | |||
| 298 | wait_for_condition 500 10 { | ||
| 299 | [$replica get timer-nested-end] eq "1" | ||
| 300 | } else { | ||
| 301 | fail "The two counters don't match the expected value." | ||
| 302 | } | ||
| 303 | |||
| 304 | assert_replication_stream $repl { | ||
| 305 | {multi} | ||
| 306 | {select *} | ||
| 307 | {incrby timer-nested-start 1} | ||
| 308 | {incrby timer-nested-end 1} | ||
| 309 | {exec} | ||
| 310 | } | ||
| 311 | close_replication_stream $repl | ||
| 312 | |||
| 313 | # Note propagate-test.timer-nested just propagates INCRBY, causing an | ||
| 314 | # inconsistency, so we flush | ||
| 315 | $master flushall | ||
| 316 | } | ||
| 317 | |||
| 318 | test {module propagates nested ctx case2} { | ||
| 319 | set repl [attach_to_replication_stream] | ||
| 320 | |||
| 321 | $master propagate-test.timer-nested-repl | ||
| 322 | |||
| 323 | wait_for_condition 500 10 { | ||
| 324 | [$replica get timer-nested-end] eq "1" | ||
| 325 | } else { | ||
| 326 | fail "The two counters don't match the expected value." | ||
| 327 | } | ||
| 328 | |||
| 329 | assert_replication_stream $repl { | ||
| 330 | {multi} | ||
| 331 | {select *} | ||
| 332 | {incrby timer-nested-start 1} | ||
| 333 | {incr notifications} | ||
| 334 | {incr using-call} | ||
| 335 | {incr counter-1} | ||
| 336 | {incr counter-2} | ||
| 337 | {incr counter-3} | ||
| 338 | {incr counter-4} | ||
| 339 | {incr notifications} | ||
| 340 | {incr after-call} | ||
| 341 | {incr notifications} | ||
| 342 | {incr before-call-2} | ||
| 343 | {incr notifications} | ||
| 344 | {incr asdf} | ||
| 345 | {incr notifications} | ||
| 346 | {del asdf} | ||
| 347 | {incr notifications} | ||
| 348 | {incr after-call-2} | ||
| 349 | {incr notifications} | ||
| 350 | {incr timer-nested-middle} | ||
| 351 | {incrby timer-nested-end 1} | ||
| 352 | {exec} | ||
| 353 | } | ||
| 354 | close_replication_stream $repl | ||
| 355 | |||
| 356 | # Note propagate-test.timer-nested-repl just propagates INCRBY, causing an | ||
| 357 | # inconsistency, so we flush | ||
| 358 | $master flushall | ||
| 359 | } | ||
| 360 | |||
| 361 | test {module propagates from thread} { | ||
| 362 | set repl [attach_to_replication_stream] | ||
| 363 | |||
| 364 | $master propagate-test.thread | ||
| 365 | |||
| 366 | wait_for_condition 500 10 { | ||
| 367 | [$replica get a-from-thread] eq "3" | ||
| 368 | } else { | ||
| 369 | fail "The two counters don't match the expected value." | ||
| 370 | } | ||
| 371 | |||
| 372 | assert_replication_stream $repl { | ||
| 373 | {multi} | ||
| 374 | {select *} | ||
| 375 | {incr a-from-thread} | ||
| 376 | {incr notifications} | ||
| 377 | {incr thread-call} | ||
| 378 | {incr b-from-thread} | ||
| 379 | {exec} | ||
| 380 | {multi} | ||
| 381 | {incr a-from-thread} | ||
| 382 | {incr notifications} | ||
| 383 | {incr thread-call} | ||
| 384 | {incr b-from-thread} | ||
| 385 | {exec} | ||
| 386 | {multi} | ||
| 387 | {incr a-from-thread} | ||
| 388 | {incr notifications} | ||
| 389 | {incr thread-call} | ||
| 390 | {incr b-from-thread} | ||
| 391 | {exec} | ||
| 392 | } | ||
| 393 | close_replication_stream $repl | ||
| 394 | } | ||
| 395 | |||
| 396 | test {module propagates from thread with detached ctx} { | ||
| 397 | set repl [attach_to_replication_stream] | ||
| 398 | |||
| 399 | $master propagate-test.detached-thread | ||
| 400 | |||
| 401 | wait_for_condition 500 10 { | ||
| 402 | [$replica get thread-detached-after] eq "1" | ||
| 403 | } else { | ||
| 404 | fail "The key doesn't match the expected value." | ||
| 405 | } | ||
| 406 | |||
| 407 | assert_replication_stream $repl { | ||
| 408 | {multi} | ||
| 409 | {select *} | ||
| 410 | {incr thread-detached-before} | ||
| 411 | {incr notifications} | ||
| 412 | {incr thread-detached-1} | ||
| 413 | {incr notifications} | ||
| 414 | {incr thread-detached-2} | ||
| 415 | {incr thread-detached-after} | ||
| 416 | {exec} | ||
| 417 | } | ||
| 418 | close_replication_stream $repl | ||
| 419 | } | ||
| 420 | |||
| 421 | test {module propagates from command} { | ||
| 422 | set repl [attach_to_replication_stream] | ||
| 423 | |||
| 424 | $master propagate-test.simple | ||
| 425 | $master propagate-test.mixed | ||
| 426 | |||
| 427 | assert_replication_stream $repl { | ||
| 428 | {multi} | ||
| 429 | {select *} | ||
| 430 | {incr counter-1} | ||
| 431 | {incr counter-2} | ||
| 432 | {exec} | ||
| 433 | {multi} | ||
| 434 | {incr notifications} | ||
| 435 | {incr using-call} | ||
| 436 | {incr counter-1} | ||
| 437 | {incr counter-2} | ||
| 438 | {incr notifications} | ||
| 439 | {incr after-call} | ||
| 440 | {exec} | ||
| 441 | } | ||
| 442 | close_replication_stream $repl | ||
| 443 | } | ||
| 444 | |||
| 445 | test {module propagates from EVAL} { | ||
| 446 | set repl [attach_to_replication_stream] | ||
| 447 | |||
| 448 | assert_equal [ $master eval { \ | ||
| 449 | redis.call("propagate-test.simple"); \ | ||
| 450 | redis.call("set", "x", "y"); \ | ||
| 451 | redis.call("propagate-test.mixed"); return "OK" } 0 ] {OK} | ||
| 452 | |||
| 453 | assert_replication_stream $repl { | ||
| 454 | {multi} | ||
| 455 | {select *} | ||
| 456 | {incr counter-1} | ||
| 457 | {incr counter-2} | ||
| 458 | {incr notifications} | ||
| 459 | {set x y} | ||
| 460 | {incr notifications} | ||
| 461 | {incr using-call} | ||
| 462 | {incr counter-1} | ||
| 463 | {incr counter-2} | ||
| 464 | {incr notifications} | ||
| 465 | {incr after-call} | ||
| 466 | {exec} | ||
| 467 | } | ||
| 468 | close_replication_stream $repl | ||
| 469 | } | ||
| 470 | |||
| 471 | test {module propagates from command after good EVAL} { | ||
| 472 | set repl [attach_to_replication_stream] | ||
| 473 | |||
| 474 | assert_equal [ $master eval { return "hello" } 0 ] {hello} | ||
| 475 | $master propagate-test.simple | ||
| 476 | $master propagate-test.mixed | ||
| 477 | |||
| 478 | assert_replication_stream $repl { | ||
| 479 | {multi} | ||
| 480 | {select *} | ||
| 481 | {incr counter-1} | ||
| 482 | {incr counter-2} | ||
| 483 | {exec} | ||
| 484 | {multi} | ||
| 485 | {incr notifications} | ||
| 486 | {incr using-call} | ||
| 487 | {incr counter-1} | ||
| 488 | {incr counter-2} | ||
| 489 | {incr notifications} | ||
| 490 | {incr after-call} | ||
| 491 | {exec} | ||
| 492 | } | ||
| 493 | close_replication_stream $repl | ||
| 494 | } | ||
| 495 | |||
| 496 | test {module propagates from command after bad EVAL} { | ||
| 497 | set repl [attach_to_replication_stream] | ||
| 498 | |||
| 499 | catch { $master eval { return "hello" } -12 } e | ||
| 500 | assert_equal $e {ERR Number of keys can't be negative} | ||
| 501 | $master propagate-test.simple | ||
| 502 | $master propagate-test.mixed | ||
| 503 | |||
| 504 | assert_replication_stream $repl { | ||
| 505 | {multi} | ||
| 506 | {select *} | ||
| 507 | {incr counter-1} | ||
| 508 | {incr counter-2} | ||
| 509 | {exec} | ||
| 510 | {multi} | ||
| 511 | {incr notifications} | ||
| 512 | {incr using-call} | ||
| 513 | {incr counter-1} | ||
| 514 | {incr counter-2} | ||
| 515 | {incr notifications} | ||
| 516 | {incr after-call} | ||
| 517 | {exec} | ||
| 518 | } | ||
| 519 | close_replication_stream $repl | ||
| 520 | } | ||
| 521 | |||
| 522 | test {module propagates from multi-exec} { | ||
| 523 | set repl [attach_to_replication_stream] | ||
| 524 | |||
| 525 | $master multi | ||
| 526 | $master propagate-test.simple | ||
| 527 | $master propagate-test.mixed | ||
| 528 | $master propagate-test.timer-nested-repl | ||
| 529 | $master exec | ||
| 530 | |||
| 531 | wait_for_condition 500 10 { | ||
| 532 | [$replica get timer-nested-end] eq "1" | ||
| 533 | } else { | ||
| 534 | fail "The two counters don't match the expected value." | ||
| 535 | } | ||
| 536 | |||
| 537 | assert_replication_stream $repl { | ||
| 538 | {multi} | ||
| 539 | {select *} | ||
| 540 | {incr counter-1} | ||
| 541 | {incr counter-2} | ||
| 542 | {incr notifications} | ||
| 543 | {incr using-call} | ||
| 544 | {incr counter-1} | ||
| 545 | {incr counter-2} | ||
| 546 | {incr notifications} | ||
| 547 | {incr after-call} | ||
| 548 | {exec} | ||
| 549 | {multi} | ||
| 550 | {incrby timer-nested-start 1} | ||
| 551 | {incr notifications} | ||
| 552 | {incr using-call} | ||
| 553 | {incr counter-1} | ||
| 554 | {incr counter-2} | ||
| 555 | {incr counter-3} | ||
| 556 | {incr counter-4} | ||
| 557 | {incr notifications} | ||
| 558 | {incr after-call} | ||
| 559 | {incr notifications} | ||
| 560 | {incr before-call-2} | ||
| 561 | {incr notifications} | ||
| 562 | {incr asdf} | ||
| 563 | {incr notifications} | ||
| 564 | {del asdf} | ||
| 565 | {incr notifications} | ||
| 566 | {incr after-call-2} | ||
| 567 | {incr notifications} | ||
| 568 | {incr timer-nested-middle} | ||
| 569 | {incrby timer-nested-end 1} | ||
| 570 | {exec} | ||
| 571 | } | ||
| 572 | close_replication_stream $repl | ||
| 573 | |||
| 574 | # Note propagate-test.timer-nested just propagates INCRBY, causing an | ||
| 575 | # inconsistency, so we flush | ||
| 576 | $master flushall | ||
| 577 | } | ||
| 578 | |||
| 579 | test {module RM_Call of expired key propagation} { | ||
| 580 | $master debug set-active-expire 0 | ||
| 581 | |||
| 582 | $master set k1 900 px 100 | ||
| 583 | after 110 | ||
| 584 | |||
| 585 | set repl [attach_to_replication_stream] | ||
| 586 | $master propagate-test.incr k1 | ||
| 587 | |||
| 588 | assert_replication_stream $repl { | ||
| 589 | {multi} | ||
| 590 | {select *} | ||
| 591 | {del k1} | ||
| 592 | {propagate-test.incr k1} | ||
| 593 | {exec} | ||
| 594 | } | ||
| 595 | close_replication_stream $repl | ||
| 596 | |||
| 597 | assert_equal [$master get k1] 1 | ||
| 598 | assert_equal [$master ttl k1] -1 | ||
| 599 | |||
| 600 | wait_for_condition 50 100 { | ||
| 601 | [$replica get k1] eq 1 && | ||
| 602 | [$replica ttl k1] eq -1 | ||
| 603 | } else { | ||
| 604 | fail "failed RM_Call of expired key propagation" | ||
| 605 | } | ||
| 606 | } | ||
| 607 | |||
| 608 | test {module notification on set} { | ||
| 609 | set repl [attach_to_replication_stream] | ||
| 610 | |||
| 611 | $master SADD s foo | ||
| 612 | |||
| 613 | wait_for_condition 500 10 { | ||
| 614 | [$replica SCARD s] eq "1" | ||
| 615 | } else { | ||
| 616 | fail "Failed to wait for set to be replicated" | ||
| 617 | } | ||
| 618 | |||
| 619 | $master SPOP s 1 | ||
| 620 | |||
| 621 | wait_for_condition 500 10 { | ||
| 622 | [$replica SCARD s] eq "0" | ||
| 623 | } else { | ||
| 624 | fail "Failed to wait for set to be replicated" | ||
| 625 | } | ||
| 626 | |||
| 627 | # Currently the `del` command comes after the notification. | ||
| 628 | # When we fix spop to fire notification at the end (like all other commands), | ||
| 629 | # the `del` will come first. | ||
| 630 | assert_replication_stream $repl { | ||
| 631 | {multi} | ||
| 632 | {select *} | ||
| 633 | {incr notifications} | ||
| 634 | {sadd s foo} | ||
| 635 | {exec} | ||
| 636 | {multi} | ||
| 637 | {incr notifications} | ||
| 638 | {incr notifications} | ||
| 639 | {del s} | ||
| 640 | {exec} | ||
| 641 | } | ||
| 642 | close_replication_stream $repl | ||
| 643 | } | ||
| 644 | |||
| 645 | test {module key miss notification do not cause read command to be replicated} { | ||
| 646 | set repl [attach_to_replication_stream] | ||
| 647 | |||
| 648 | $master flushall | ||
| 649 | |||
| 650 | $master get unexisting_key | ||
| 651 | |||
| 652 | wait_for_condition 500 10 { | ||
| 653 | [$replica get missed] eq "1" | ||
| 654 | } else { | ||
| 655 | fail "Failed to wait for set to be replicated" | ||
| 656 | } | ||
| 657 | |||
| 658 | # Test is checking a wrong!!! behavior that causes a read command to be replicated to replica/aof. | ||
| 659 | # We keep the test to verify that such a wrong behavior does not cause any crashes. | ||
| 660 | assert_replication_stream $repl { | ||
| 661 | {select *} | ||
| 662 | {flushall} | ||
| 663 | {multi} | ||
| 664 | {incr notifications} | ||
| 665 | {incr missed} | ||
| 666 | {get unexisting_key} | ||
| 667 | {exec} | ||
| 668 | } | ||
| 669 | |||
| 670 | close_replication_stream $repl | ||
| 671 | } | ||
| 672 | |||
| 673 | test "Unload the module - propagate-test/testkeyspace" { | ||
| 674 | assert_equal {OK} [r module unload propagate-test] | ||
| 675 | assert_equal {OK} [r module unload testkeyspace] | ||
| 676 | } | ||
| 677 | |||
| 678 | assert_equal [s -1 unexpected_error_replies] 0 | ||
| 679 | } | ||
| 680 | } | ||
| 681 | } | ||
| 682 | } | ||
| 683 | |||
| 684 | |||
| 685 | tags "modules aof external:skip" { | ||
| 686 | foreach aofload_type {debug_cmd startup} { | ||
| 687 | test "Modules RM_Replicate replicates MULTI/EXEC correctly: AOF-load type $aofload_type" { | ||
| 688 | start_server [list overrides [list loadmodule "$testmodule"]] { | ||
| 689 | # Enable the AOF | ||
| 690 | r config set appendonly yes | ||
| 691 | r config set auto-aof-rewrite-percentage 0 ; # Disable auto-rewrite. | ||
| 692 | waitForBgrewriteaof r | ||
| 693 | |||
| 694 | r propagate-test.simple | ||
| 695 | r propagate-test.mixed | ||
| 696 | r multi | ||
| 697 | r propagate-test.simple | ||
| 698 | r propagate-test.mixed | ||
| 699 | r exec | ||
| 700 | |||
| 701 | assert_equal [r get counter-1] {} | ||
| 702 | assert_equal [r get counter-2] {} | ||
| 703 | assert_equal [r get using-call] 2 | ||
| 704 | assert_equal [r get after-call] 2 | ||
| 705 | assert_equal [r get notifications] 4 | ||
| 706 | |||
| 707 | # Load the AOF | ||
| 708 | if {$aofload_type == "debug_cmd"} { | ||
| 709 | r debug loadaof | ||
| 710 | } else { | ||
| 711 | r config rewrite | ||
| 712 | restart_server 0 true false | ||
| 713 | wait_done_loading r | ||
| 714 | } | ||
| 715 | |||
| 716 | # This module behaves bad on purpose, it only calls | ||
| 717 | # RM_Replicate for counter-1 and counter-2 so values | ||
| 718 | # after AOF-load are different | ||
| 719 | assert_equal [r get counter-1] 4 | ||
| 720 | assert_equal [r get counter-2] 4 | ||
| 721 | assert_equal [r get using-call] 2 | ||
| 722 | assert_equal [r get after-call] 2 | ||
| 723 | # 4+4+2+2 commands from AOF (just above) + 4 "INCR notifications" from AOF + 4 notifications for these INCRs | ||
| 724 | assert_equal [r get notifications] 20 | ||
| 725 | |||
| 726 | assert_equal {OK} [r module unload propagate-test] | ||
| 727 | assert_equal [s 0 unexpected_error_replies] 0 | ||
| 728 | } | ||
| 729 | } | ||
| 730 | test "Modules RM_Call does not update stats during aof load: AOF-load type $aofload_type" { | ||
| 731 | start_server [list overrides [list loadmodule "$miscmodule"]] { | ||
| 732 | # Enable the AOF | ||
| 733 | r config set appendonly yes | ||
| 734 | r config set auto-aof-rewrite-percentage 0 ; # Disable auto-rewrite. | ||
| 735 | waitForBgrewriteaof r | ||
| 736 | |||
| 737 | r config resetstat | ||
| 738 | r set foo bar | ||
| 739 | r EVAL {return redis.call('SET', KEYS[1], ARGV[1])} 1 foo bar2 | ||
| 740 | r test.rm_call_replicate set foo bar3 | ||
| 741 | r EVAL {return redis.call('test.rm_call_replicate',ARGV[1],KEYS[1],ARGV[2])} 1 foo set bar4 | ||
| 742 | |||
| 743 | r multi | ||
| 744 | r set foo bar5 | ||
| 745 | r EVAL {return redis.call('SET', KEYS[1], ARGV[1])} 1 foo bar6 | ||
| 746 | r test.rm_call_replicate set foo bar7 | ||
| 747 | r EVAL {return redis.call('test.rm_call_replicate',ARGV[1],KEYS[1],ARGV[2])} 1 foo set bar8 | ||
| 748 | r exec | ||
| 749 | |||
| 750 | assert_match {*calls=8,*,rejected_calls=0,failed_calls=0} [cmdrstat set r] | ||
| 751 | |||
| 752 | |||
| 753 | # Load the AOF | ||
| 754 | if {$aofload_type == "debug_cmd"} { | ||
| 755 | r config resetstat | ||
| 756 | r debug loadaof | ||
| 757 | } else { | ||
| 758 | r config rewrite | ||
| 759 | restart_server 0 true false | ||
| 760 | wait_done_loading r | ||
| 761 | } | ||
| 762 | |||
| 763 | assert_no_match {*calls=*} [cmdrstat set r] | ||
| 764 | |||
| 765 | } | ||
| 766 | } | ||
| 767 | } | ||
| 768 | } | ||
| 769 | |||
| 770 | # This test does not really test module functionality, but rather uses a module | ||
| 771 | # command to test Redis replication mechanisms. | ||
| 772 | test {Replicas that was marked as CLIENT_CLOSE_ASAP should not keep the replication backlog from been trimmed} { | ||
| 773 | start_server [list overrides [list loadmodule "$testmodule"] tags {"external:skip"}] { | ||
| 774 | set replica [srv 0 client] | ||
| 775 | start_server [list overrides [list loadmodule "$testmodule"] tags {"external:skip"}] { | ||
| 776 | set master [srv 0 client] | ||
| 777 | set master_host [srv 0 host] | ||
| 778 | set master_port [srv 0 port] | ||
| 779 | $master config set client-output-buffer-limit "replica 10mb 5mb 0" | ||
| 780 | |||
| 781 | # Start the replication process... | ||
| 782 | $replica replicaof $master_host $master_port | ||
| 783 | wait_for_sync $replica | ||
| 784 | |||
| 785 | test {module propagates from timer} { | ||
| 786 | # Replicate large commands to make the replica disconnected. | ||
| 787 | $master write [format_command propagate-test.verbatim 100000 [string repeat "a" 1000]] ;# almost 100mb | ||
| 788 | # Execute this command together with module commands within the same | ||
| 789 | # event loop to prevent periodic cleanup of replication backlog. | ||
| 790 | $master write [format_command info memory] | ||
| 791 | $master flush | ||
| 792 | $master read ;# propagate-test.verbatim | ||
| 793 | set res [$master read] ;# info memory | ||
| 794 | |||
| 795 | # Wait for the replica to be disconnected. | ||
| 796 | wait_for_log_messages 0 {"*flags=S*scheduled to be closed ASAP for overcoming of output buffer limits*"} 0 1500 10 | ||
| 797 | # Due to the replica reaching the soft limit (5MB), memory peaks should not significantly | ||
| 798 | # exceed the replica soft limit. Furthermore, as the replica release its reference to | ||
| 799 | # replication backlog, it should be properly trimmed, the memory usage of replication | ||
| 800 | # backlog should not significantly exceed repl-backlog-size (default 1MB). */ | ||
| 801 | assert_lessthan [getInfoProperty $res used_memory_peak] 20000000;# less than 20mb | ||
| 802 | assert_lessthan [getInfoProperty $res mem_replication_backlog] 2000000;# less than 2mb | ||
| 803 | } | ||
| 804 | } | ||
| 805 | } | ||
| 806 | } | ||
