aboutsummaryrefslogtreecommitdiff
path: root/examples/redis-unstable/tests/unit/moduleapi/testrdb.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'examples/redis-unstable/tests/unit/moduleapi/testrdb.tcl')
-rw-r--r--examples/redis-unstable/tests/unit/moduleapi/testrdb.tcl311
1 files changed, 311 insertions, 0 deletions
diff --git a/examples/redis-unstable/tests/unit/moduleapi/testrdb.tcl b/examples/redis-unstable/tests/unit/moduleapi/testrdb.tcl
new file mode 100644
index 0000000..e44cf42
--- /dev/null
+++ b/examples/redis-unstable/tests/unit/moduleapi/testrdb.tcl
@@ -0,0 +1,311 @@
1# This module can be configure with multiple options given as flags on module load time
2# 0 - not aux fields will be declared (this is the default)
3# 1 << 0 - use aux_save2 api
4# 1 << 1 - call aux callback before key space
5# 1 << 2 - call aux callback after key space
6# 1 << 3 - do not save data on aux callback
7set testmodule [file normalize tests/modules/testrdb.so]
8
9tags "modules external:skip" {
10 test {modules are able to persist types} {
11 start_server [list overrides [list loadmodule "$testmodule"]] {
12 r testrdb.set.key key1 value1
13 assert_equal "value1" [r testrdb.get.key key1]
14 r debug reload
15 assert_equal "value1" [r testrdb.get.key key1]
16 }
17 }
18
19 test {modules global are lost without aux} {
20 set server_path [tmpdir "server.module-testrdb"]
21 start_server [list overrides [list loadmodule "$testmodule" "dir" $server_path] keep_persistence true] {
22 r testrdb.set.before global1
23 assert_equal "global1" [r testrdb.get.before]
24 }
25 start_server [list overrides [list loadmodule "$testmodule" "dir" $server_path]] {
26 assert_equal "" [r testrdb.get.before]
27 }
28 }
29
30 test {aux that saves no data are not saved to the rdb when aux_save2 is used} {
31 set server_path [tmpdir "server.module-testrdb"]
32 puts $server_path
33 # 15 == 1111 - use aux_save2 before and after key space without data
34 start_server [list overrides [list loadmodule "$testmodule 15" "dir" $server_path] keep_persistence true] {
35 r set x 1
36 r save
37 }
38 start_server [list overrides [list "dir" $server_path] keep_persistence true] {
39 # make sure server started successfully without the module.
40 assert_equal {1} [r get x]
41 }
42 }
43
44 test {aux that saves no data are saved to the rdb when aux_save is used} {
45 set server_path [tmpdir "server.module-testrdb"]
46 puts $server_path
47 # 14 == 1110 - use aux_save before and after key space without data
48 start_server [list overrides [list loadmodule "$testmodule 14" "dir" $server_path] keep_persistence true] {
49 r set x 1
50 r save
51 }
52 start_server [list overrides [list loadmodule "$testmodule 14" "dir" $server_path] keep_persistence true] {
53 # make sure server started successfully and aux_save was called twice.
54 assert_equal {1} [r get x]
55 assert_equal {2} [r testrdb.get.n_aux_load_called]
56 }
57 }
58
59 foreach test_case {6 7} {
60 # 6 == 0110 - use aux_save before and after key space with data
61 # 7 == 0111 - use aux_save2 before and after key space with data
62 test {modules are able to persist globals before and after} {
63 set server_path [tmpdir "server.module-testrdb"]
64 start_server [list overrides [list loadmodule "$testmodule $test_case" "dir" $server_path "save" "900 1"] keep_persistence true] {
65 r testrdb.set.before global1
66 r testrdb.set.after global2
67 assert_equal "global1" [r testrdb.get.before]
68 assert_equal "global2" [r testrdb.get.after]
69 }
70 start_server [list overrides [list loadmodule "$testmodule $test_case" "dir" $server_path "save" "900 1"]] {
71 assert_equal "global1" [r testrdb.get.before]
72 assert_equal "global2" [r testrdb.get.after]
73 }
74
75 }
76 }
77
78 foreach test_case {4 5} {
79 # 4 == 0100 - use aux_save after key space with data
80 # 5 == 0101 - use aux_save2 after key space with data
81 test {modules are able to persist globals just after} {
82 set server_path [tmpdir "server.module-testrdb"]
83 start_server [list overrides [list loadmodule "$testmodule $test_case" "dir" $server_path "save" "900 1"] keep_persistence true] {
84 r testrdb.set.after global2
85 assert_equal "global2" [r testrdb.get.after]
86 }
87 start_server [list overrides [list loadmodule "$testmodule $test_case" "dir" $server_path "save" "900 1"]] {
88 assert_equal "global2" [r testrdb.get.after]
89 }
90 }
91 }
92
93 test {Verify module options info} {
94 start_server [list overrides [list loadmodule "$testmodule"]] {
95 assert_match "*\[handle-io-errors|handle-repl-async-load\]*" [r info modules]
96 }
97 }
98
99 tags {repl} {
100 test {diskless loading short read with module} {
101 start_server [list overrides [list loadmodule "$testmodule"]] {
102 set replica [srv 0 client]
103 set replica_host [srv 0 host]
104 set replica_port [srv 0 port]
105 start_server [list overrides [list loadmodule "$testmodule"]] {
106 set master [srv 0 client]
107 set master_host [srv 0 host]
108 set master_port [srv 0 port]
109
110 # Set master and replica to use diskless replication
111 $master config set repl-diskless-sync yes
112 $master config set rdbcompression no
113 $replica config set repl-diskless-load swapdb
114 $master config set hz 500
115 $replica config set hz 500
116 $master config set dynamic-hz no
117 $replica config set dynamic-hz no
118 set start [clock clicks -milliseconds]
119 # Generate small keys
120 for {set k 0} {$k < 20000} {incr k} {
121 r testrdb.set.key keysmall$k [string repeat A [expr {int(rand()*100)}]]
122 }
123 # Generate larger keys
124 for {set k 0} {$k < 30} {incr k} {
125 r testrdb.set.key key$k [string repeat A [expr {int(rand()*1000000)}]]
126 }
127
128 if {$::verbose} {
129 set end [clock clicks -milliseconds]
130 set duration [expr $end - $start]
131 puts "filling took $duration ms (TODO: use pipeline)"
132 set start [clock clicks -milliseconds]
133 }
134
135 # Start the replication process...
136 set loglines [count_log_lines -1]
137 $master config set repl-diskless-sync-delay 0
138 $replica replicaof $master_host $master_port
139
140 # kill the replication at various points
141 set attempts 100
142 if {$::accurate} { set attempts 500 }
143 for {set i 0} {$i < $attempts} {incr i} {
144 # wait for the replica to start reading the rdb
145 # using the log file since the replica only responds to INFO once in 2mb
146 set res [wait_for_log_messages -1 {"*Loading DB in memory*"} $loglines 2000 1]
147 set loglines [lindex $res 1]
148
149 # add some additional random sleep so that we kill the master on a different place each time
150 after [expr {int(rand()*50)}]
151
152 # kill the replica connection on the master
153 set killed [$master client kill type replica]
154
155 set res [wait_for_log_messages -1 {"*Internal error in RDB*" "*Finished with success*" "*Successful partial resynchronization*"} $loglines 500 10]
156 if {$::verbose} { puts $res }
157 set log_text [lindex $res 0]
158 set loglines [lindex $res 1]
159 if {![string match "*Internal error in RDB*" $log_text]} {
160 # force the replica to try another full sync
161 $master multi
162 $master client kill type replica
163 $master set asdf asdf
164 # fill replication backlog with new content
165 $master config set repl-backlog-size 16384
166 for {set keyid 0} {$keyid < 10} {incr keyid} {
167 $master set "$keyid string_$keyid" [string repeat A 16384]
168 }
169 $master exec
170 }
171
172 # wait for loading to stop (fail)
173 # After a loading successfully, next loop will enter `async_loading`
174 wait_for_condition 1000 1 {
175 [s -1 async_loading] eq 0 &&
176 [s -1 loading] eq 0
177 } else {
178 fail "Replica didn't disconnect"
179 }
180 }
181 if {$::verbose} {
182 set end [clock clicks -milliseconds]
183 set duration [expr $end - $start]
184 puts "test took $duration ms"
185 }
186 # enable fast shutdown
187 $master config set rdb-key-save-delay 0
188 }
189 }
190 }
191
192 # Module events for diskless load swapdb when async_loading (matching master replid)
193 foreach test_case {6 7} {
194 # 6 == 0110 - use aux_save before and after key space with data
195 # 7 == 0111 - use aux_save2 before and after key space with data
196 foreach testType {Successful Aborted} {
197 start_server [list overrides [list loadmodule "$testmodule $test_case"] tags [list external:skip]] {
198 set replica [srv 0 client]
199 set replica_host [srv 0 host]
200 set replica_port [srv 0 port]
201 set replica_log [srv 0 stdout]
202 start_server [list overrides [list loadmodule "$testmodule $test_case"]] {
203 set master [srv 0 client]
204 set master_host [srv 0 host]
205 set master_port [srv 0 port]
206
207 set start [clock clicks -milliseconds]
208
209 # Set master and replica to use diskless replication on swapdb mode
210 $master config set repl-diskless-sync yes
211 $master config set repl-diskless-sync-delay 0
212 $master config set save ""
213 $replica config set repl-diskless-load swapdb
214 $replica config set save ""
215
216 # Initial sync to have matching replids between master and replica
217 $replica replicaof $master_host $master_port
218
219 # Let replica finish initial sync with master
220 wait_for_condition 100 100 {
221 [s -1 master_link_status] eq "up"
222 } else {
223 fail "Master <-> Replica didn't finish sync"
224 }
225
226 # Set global values on module so we can check if module event callbacks will pick it up correctly
227 $master testrdb.set.before value1_master
228 $replica testrdb.set.before value1_replica
229
230 # Put different data sets on the master and replica
231 # We need to put large keys on the master since the replica replies to info only once in 2mb
232 $replica debug populate 200 slave 10
233 $master debug populate 1000 master 100000
234 $master config set rdbcompression no
235
236 # Force the replica to try another full sync (this time it will have matching master replid)
237 $master multi
238 $master client kill type replica
239 # Fill replication backlog with new content
240 $master config set repl-backlog-size 16384
241 for {set keyid 0} {$keyid < 10} {incr keyid} {
242 $master set "$keyid string_$keyid" [string repeat A 16384]
243 }
244 $master exec
245
246 switch $testType {
247 "Aborted" {
248 # Set master with a slow rdb generation, so that we can easily intercept loading
249 # 10ms per key, with 1000 keys is 10 seconds
250 $master config set rdb-key-save-delay 10000
251
252 test {Diskless load swapdb RedisModuleEvent_ReplAsyncLoad handling: during loading, can keep module variable same as before} {
253 # Wait for the replica to start reading the rdb and module for acknowledgement
254 # We wanna abort only after the temp db was populated by REDISMODULE_AUX_BEFORE_RDB
255 wait_for_condition 100 100 {
256 [s -1 async_loading] eq 1 && [$replica testrdb.async_loading.get.before] eq "value1_master"
257 } else {
258 fail "Module didn't receive or react to REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_STARTED"
259 }
260
261 assert_equal [$replica dbsize] 200
262 assert_equal value1_replica [$replica testrdb.get.before]
263 }
264
265 # Make sure that next sync will not start immediately so that we can catch the replica in between syncs
266 $master config set repl-diskless-sync-delay 5
267
268 # Kill the replica connection on the master
269 set killed [$master client kill type replica]
270
271 test {Diskless load swapdb RedisModuleEvent_ReplAsyncLoad handling: when loading aborted, can keep module variable same as before} {
272 # Wait for loading to stop (fail) and module for acknowledgement
273 wait_for_condition 100 100 {
274 [s -1 async_loading] eq 0 && [$replica testrdb.async_loading.get.before] eq ""
275 } else {
276 fail "Module didn't receive or react to REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_ABORTED"
277 }
278
279 assert_equal [$replica dbsize] 200
280 assert_equal value1_replica [$replica testrdb.get.before]
281 }
282
283 # Speed up shutdown
284 $master config set rdb-key-save-delay 0
285 }
286 "Successful" {
287 # Let replica finish sync with master
288 wait_for_condition 100 100 {
289 [s -1 master_link_status] eq "up"
290 } else {
291 fail "Master <-> Replica didn't finish sync"
292 }
293
294 test {Diskless load swapdb RedisModuleEvent_ReplAsyncLoad handling: after db loaded, can set module variable with new value} {
295 assert_equal [$replica dbsize] 1010
296 assert_equal value1_master [$replica testrdb.get.before]
297 }
298 }
299 }
300
301 if {$::verbose} {
302 set end [clock clicks -milliseconds]
303 set duration [expr $end - $start]
304 puts "test took $duration ms"
305 }
306 }
307 }
308 }
309 }
310 }
311}