summaryrefslogtreecommitdiff
path: root/tests/integration/replication.tcl
blob: 5ca6449f4fddb7f5f7586278ad8d984a166a953c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
start_server {tags {"repl"}} {
    start_server {} {
        test {First server should have role slave after SLAVEOF} {
            r -1 slaveof [srv 0 host] [srv 0 port]
            wait_for_condition 50 100 {
                [s -1 role] eq {slave} &&
                [string match {*master_link_status:up*} [r -1 info replication]]
            } else {
                fail "Can't turn the instance into a slave"
            }
        }

        test {BRPOPLPUSH replication, when blocking against empty list} {
            set rd [redis_deferring_client]
            $rd brpoplpush a b 5
            r lpush a foo
            wait_for_condition 50 100 {
                [r debug digest] eq [r -1 debug digest]
            } else {
                fail "Master and slave have different digest: [r debug digest] VS [r -1 debug digest]"
            }
        }

        test {BRPOPLPUSH replication, list exists} {
            set rd [redis_deferring_client]
            r lpush c 1
            r lpush c 2
            r lpush c 3
            $rd brpoplpush c d 5
            after 1000
            assert_equal [r debug digest] [r -1 debug digest]
        }
    }
}

start_server {tags {"repl"}} {
    r set mykey foo
    
    start_server {} {
        test {Second server should have role master at first} {
            s role
        } {master}
        
        test {SLAVEOF should start with link status "down"} {
            r slaveof [srv -1 host] [srv -1 port]
            s master_link_status
        } {down}
        
        test {The role should immediately be changed to "slave"} {
            s role
        } {slave}

        wait_for_sync r
        test {Sync should have transferred keys from master} {
            r get mykey
        } {foo}
        
        test {The link status should be up} {
            s master_link_status
        } {up}
        
        test {SET on the master should immediately propagate} {
            r -1 set mykey bar

            wait_for_condition 500 100 {
                [r  0 get mykey] eq {bar}
            } else {
                fail "SET on master did not propagated on slave"
            }
        }

        test {FLUSHALL should replicate} {
            r -1 flushall
            if {$::valgrind} {after 2000}
            list [r -1 dbsize] [r 0 dbsize]
        } {0 0}
    }
}

proc start_write_load {host port seconds} {
    set tclsh [info nameofexecutable]
    exec $tclsh tests/helpers/gen_write_load.tcl $host $port $seconds &
}

proc stop_write_load {handle} {
    catch {exec /bin/kill -9 $handle}
}

start_server {tags {"repl"}} {
    set master [srv 0 client]
    set master_host [srv 0 host]
    set master_port [srv 0 port]
    set slaves {}
    set load_handle0 [start_write_load $master_host $master_port 3]
    set load_handle1 [start_write_load $master_host $master_port 5]
    set load_handle2 [start_write_load $master_host $master_port 20]
    set load_handle3 [start_write_load $master_host $master_port 8]
    set load_handle4 [start_write_load $master_host $master_port 4]
    start_server {} {
        lappend slaves [srv 0 client]
        start_server {} {
            lappend slaves [srv 0 client]
            start_server {} {
                lappend slaves [srv 0 client]
                test "Connect multiple slaves at the same time (issue #141)" {
                    # Send SALVEOF commands to slaves
                    [lindex $slaves 0] slaveof $master_host $master_port
                    [lindex $slaves 1] slaveof $master_host $master_port
                    [lindex $slaves 2] slaveof $master_host $master_port

                    # Wait for all the three slaves to reach the "online" state
                    set retry 500
                    while {$retry} {
                        set info [r -3 info]
                        if {[string match {*slave0:*,online*slave1:*,online*slave2:*,online*} $info]} {
                            break
                        } else {
                            incr retry -1
                            after 100
                        }
                    }
                    if {$retry == 0} {
                        error "assertion:Slaves not correctly synchronized"
                    }

                    # Stop the write load
                    stop_write_load $load_handle0
                    stop_write_load $load_handle1
                    stop_write_load $load_handle2
                    stop_write_load $load_handle3
                    stop_write_load $load_handle4

                    # Wait that slaves exit the "loading" state
                    wait_for_condition 500 100 {
                        ![string match {*loading:1*} [[lindex $slaves 0] info]] &&
                        ![string match {*loading:1*} [[lindex $slaves 1] info]] &&
                        ![string match {*loading:1*} [[lindex $slaves 2] info]]
                    } else {
                        fail "Slaves still loading data after too much time"
                    }

                    # Make sure that slaves and master have same number of keys
                    wait_for_condition 500 100 {
                        [$master dbsize] == [[lindex $slaves 0] dbsize] &&
                        [$master dbsize] == [[lindex $slaves 1] dbsize] &&
                        [$master dbsize] == [[lindex $slaves 2] dbsize]
                    } else {
                        fail "Different number of keys between masted and slave after too long time."
                    }

                    # Check digests
                    set digest [$master debug digest]
                    set digest0 [[lindex $slaves 0] debug digest]
                    set digest1 [[lindex $slaves 1] debug digest]
                    set digest2 [[lindex $slaves 2] debug digest]
                    assert {$digest ne 0000000000000000000000000000000000000000}
                    assert {$digest eq $digest0}
                    assert {$digest eq $digest1}
                    assert {$digest eq $digest2}
                }
           }
        }
    }
}