1start_server {tags {"repl"}} {
2    set A [srv 0 client]
3    set A_host [srv 0 host]
4    set A_port [srv 0 port]
5    start_server {} {
6        set B [srv 0 client]
7        set B_host [srv 0 host]
8        set B_port [srv 0 port]
9
10        test {Set instance A as slave of B} {
11            $A slaveof $B_host $B_port
12            wait_for_condition 50 100 {
13                [lindex [$A role] 0] eq {slave} &&
14                [string match {*master_link_status:up*} [$A info replication]]
15            } else {
16                fail "Can't turn the instance into a slave"
17            }
18        }
19
20        test {BRPOPLPUSH replication, when blocking against empty list} {
21            set rd [redis_deferring_client]
22            $rd brpoplpush a b 5
23            r lpush a foo
24            wait_for_condition 50 100 {
25                [$A debug digest] eq [$B debug digest]
26            } else {
27                fail "Master and slave have different digest: [$A debug digest] VS [$B debug digest]"
28            }
29        }
30
31        test {BRPOPLPUSH replication, list exists} {
32            set rd [redis_deferring_client]
33            r lpush c 1
34            r lpush c 2
35            r lpush c 3
36            $rd brpoplpush c d 5
37            after 1000
38            assert_equal [$A debug digest] [$B debug digest]
39        }
40
41        test {BLPOP followed by role change, issue #2473} {
42            set rd [redis_deferring_client]
43            $rd blpop foo 0 ; # Block while B is a master
44
45            # Turn B into master of A
46            $A slaveof no one
47            $B slaveof $A_host $A_port
48            wait_for_condition 50 100 {
49                [lindex [$B role] 0] eq {slave} &&
50                [string match {*master_link_status:up*} [$B info replication]]
51            } else {
52                fail "Can't turn the instance into a slave"
53            }
54
55            # Push elements into the "foo" list of the new slave.
56            # If the client is still attached to the instance, we'll get
57            # a desync between the two instances.
58            $A rpush foo a b c
59            after 100
60
61            wait_for_condition 50 100 {
62                [$A debug digest] eq [$B debug digest] &&
63                [$A lrange foo 0 -1] eq {a b c} &&
64                [$B lrange foo 0 -1] eq {a b c}
65            } else {
66                fail "Master and slave have different digest: [$A debug digest] VS [$B debug digest]"
67            }
68        }
69    }
70}
71
72start_server {tags {"repl"}} {
73    r set mykey foo
74
75    start_server {} {
76        test {Second server should have role master at first} {
77            s role
78        } {master}
79
80        test {SLAVEOF should start with link status "down"} {
81            r slaveof [srv -1 host] [srv -1 port]
82            s master_link_status
83        } {down}
84
85        test {The role should immediately be changed to "slave"} {
86            s role
87        } {slave}
88
89        wait_for_sync r
90        test {Sync should have transferred keys from master} {
91            r get mykey
92        } {foo}
93
94        test {The link status should be up} {
95            s master_link_status
96        } {up}
97
98        test {SET on the master should immediately propagate} {
99            r -1 set mykey bar
100
101            wait_for_condition 500 100 {
102                [r  0 get mykey] eq {bar}
103            } else {
104                fail "SET on master did not propagated on slave"
105            }
106        }
107
108        test {FLUSHALL should replicate} {
109            r -1 flushall
110            if {$::valgrind} {after 2000}
111            list [r -1 dbsize] [r 0 dbsize]
112        } {0 0}
113
114        test {ROLE in master reports master with a slave} {
115            set res [r -1 role]
116            lassign $res role offset slaves
117            assert {$role eq {master}}
118            assert {$offset > 0}
119            assert {[llength $slaves] == 1}
120            lassign [lindex $slaves 0] master_host master_port slave_offset
121            assert {$slave_offset <= $offset}
122        }
123
124        test {ROLE in slave reports slave in connected state} {
125            set res [r role]
126            lassign $res role master_host master_port slave_state slave_offset
127            assert {$role eq {slave}}
128            assert {$slave_state eq {connected}}
129        }
130    }
131}
132
133foreach dl {no yes} {
134    start_server {tags {"repl"}} {
135        set master [srv 0 client]
136        $master config set repl-diskless-sync $dl
137        set master_host [srv 0 host]
138        set master_port [srv 0 port]
139        set slaves {}
140        set load_handle0 [start_write_load $master_host $master_port 3]
141        set load_handle1 [start_write_load $master_host $master_port 5]
142        set load_handle2 [start_write_load $master_host $master_port 20]
143        set load_handle3 [start_write_load $master_host $master_port 8]
144        set load_handle4 [start_write_load $master_host $master_port 4]
145        start_server {} {
146            lappend slaves [srv 0 client]
147            start_server {} {
148                lappend slaves [srv 0 client]
149                start_server {} {
150                    lappend slaves [srv 0 client]
151                    test "Connect multiple slaves at the same time (issue #141), diskless=$dl" {
152                        # Send SLAVEOF commands to slaves
153                        [lindex $slaves 0] slaveof $master_host $master_port
154                        [lindex $slaves 1] slaveof $master_host $master_port
155                        [lindex $slaves 2] slaveof $master_host $master_port
156
157                        # Wait for all the three slaves to reach the "online"
158                        # state from the POV of the master.
159                        set retry 500
160                        while {$retry} {
161                            set info [r -3 info]
162                            if {[string match {*slave0:*state=online*slave1:*state=online*slave2:*state=online*} $info]} {
163                                break
164                            } else {
165                                incr retry -1
166                                after 100
167                            }
168                        }
169                        if {$retry == 0} {
170                            error "assertion:Slaves not correctly synchronized"
171                        }
172
173                        # Wait that slaves acknowledge they are online so
174                        # we are sure that DBSIZE and DEBUG DIGEST will not
175                        # fail because of timing issues.
176                        wait_for_condition 500 100 {
177                            [lindex [[lindex $slaves 0] role] 3] eq {connected} &&
178                            [lindex [[lindex $slaves 1] role] 3] eq {connected} &&
179                            [lindex [[lindex $slaves 2] role] 3] eq {connected}
180                        } else {
181                            fail "Slaves still not connected after some time"
182                        }
183
184                        # Stop the write load
185                        stop_write_load $load_handle0
186                        stop_write_load $load_handle1
187                        stop_write_load $load_handle2
188                        stop_write_load $load_handle3
189                        stop_write_load $load_handle4
190
191                        # Make sure that slaves and master have same
192                        # number of keys
193                        wait_for_condition 500 100 {
194                            [$master dbsize] == [[lindex $slaves 0] dbsize] &&
195                            [$master dbsize] == [[lindex $slaves 1] dbsize] &&
196                            [$master dbsize] == [[lindex $slaves 2] dbsize]
197                        } else {
198                            fail "Different number of keys between masted and slave after too long time."
199                        }
200
201                        # Check digests
202                        set digest [$master debug digest]
203                        set digest0 [[lindex $slaves 0] debug digest]
204                        set digest1 [[lindex $slaves 1] debug digest]
205                        set digest2 [[lindex $slaves 2] debug digest]
206                        assert {$digest ne 0000000000000000000000000000000000000000}
207                        assert {$digest eq $digest0}
208                        assert {$digest eq $digest1}
209                        assert {$digest eq $digest2}
210                    }
211               }
212            }
213        }
214    }
215}
216