github.com/hdt3213/godis@v1.2.9/database/replication_slave_test.go (about) 1 package database 2 3 import ( 4 "bytes" 5 "github.com/hdt3213/godis/aof" 6 "github.com/hdt3213/godis/config" 7 "github.com/hdt3213/godis/lib/utils" 8 "github.com/hdt3213/godis/redis/client" 9 "github.com/hdt3213/godis/redis/connection" 10 "github.com/hdt3213/godis/redis/protocol" 11 "github.com/hdt3213/godis/redis/protocol/asserts" 12 "io/ioutil" 13 "os" 14 "path" 15 "testing" 16 "time" 17 ) 18 19 func TestReplicationSlaveSide(t *testing.T) { 20 tmpDir, err := ioutil.TempDir("", "godis") 21 if err != nil { 22 t.Error(err) 23 return 24 } 25 aofFilename := path.Join(tmpDir, "a.aof") 26 defer func() { 27 _ = os.Remove(aofFilename) 28 }() 29 config.Properties = &config.ServerProperties{ 30 Databases: 16, 31 AppendOnly: true, 32 AppendFilename: aofFilename, 33 } 34 conn := connection.NewFakeConn() 35 server := mockServer() 36 masterCli, err := client.MakeClient("127.0.0.1:6379") 37 if err != nil { 38 t.Error(err) 39 return 40 } 41 aofHandler, err := NewPersister(server, config.Properties.AppendFilename, true, aof.FsyncNo) 42 if err != nil { 43 t.Error(err) 44 return 45 } 46 server.bindPersister(aofHandler) 47 server.Exec(conn, utils.ToCmdLine("set", "zz", "zz")) 48 masterCli.Start() 49 50 // sync with master 51 ret := masterCli.Send(utils.ToCmdLine("set", "1", "1")) 52 asserts.AssertStatusReply(t, ret, "OK") 53 ret = server.Exec(conn, utils.ToCmdLine("SLAVEOF", "127.0.0.1", "6379")) 54 asserts.AssertStatusReply(t, ret, "OK") 55 success := false 56 for i := 0; i < 30; i++ { 57 // wait for sync 58 time.Sleep(time.Second) 59 ret = server.Exec(conn, utils.ToCmdLine("GET", "1")) 60 bulkRet, ok := ret.(*protocol.BulkReply) 61 if ok { 62 if bytes.Equal(bulkRet.Arg, []byte("1")) { 63 success = true 64 break 65 } 66 } 67 } 68 if !success { 69 t.Error("sync failed") 70 return 71 } 72 73 // receive aof 74 ret = masterCli.Send(utils.ToCmdLine("set", "1", "2")) 75 asserts.AssertStatusReply(t, ret, "OK") 76 success = false 77 for i := 0; i < 10; i++ { 78 // wait for sync 79 time.Sleep(time.Second) 80 ret = server.Exec(conn, utils.ToCmdLine("GET", "1")) 81 bulkRet, ok := ret.(*protocol.BulkReply) 82 if ok { 83 if bytes.Equal(bulkRet.Arg, []byte("2")) { 84 success = true 85 break 86 } 87 } 88 } 89 if !success { 90 t.Error("sync failed") 91 return 92 } 93 err = server.slaveStatus.sendAck2Master() 94 if err != nil { 95 t.Error(err) 96 return 97 } 98 time.Sleep(3 * time.Second) 99 100 // test reconnect 101 config.Properties.ReplTimeout = 1 102 _ = server.slaveStatus.masterConn.Close() 103 server.slaveStatus.lastRecvTime = time.Now().Add(-time.Hour) // mock timeout 104 server.slaveCron() 105 time.Sleep(3 * time.Second) 106 ret = masterCli.Send(utils.ToCmdLine("set", "1", "3")) 107 asserts.AssertStatusReply(t, ret, "OK") 108 success = false 109 for i := 0; i < 10; i++ { 110 // wait for sync 111 time.Sleep(time.Second) 112 ret = server.Exec(conn, utils.ToCmdLine("GET", "1")) 113 bulkRet, ok := ret.(*protocol.BulkReply) 114 if ok { 115 if bytes.Equal(bulkRet.Arg, []byte("3")) { 116 success = true 117 break 118 } 119 } 120 } 121 if !success { 122 t.Error("sync failed") 123 return 124 } 125 126 // test slave of no one 127 ret = server.Exec(conn, utils.ToCmdLine("SLAVEOF", "NO", "ONE")) 128 asserts.AssertStatusReply(t, ret, "OK") 129 ret = masterCli.Send(utils.ToCmdLine("set", "1", "4")) 130 asserts.AssertStatusReply(t, ret, "OK") 131 ret = server.Exec(conn, utils.ToCmdLine("GET", "1")) 132 asserts.AssertBulkReply(t, ret, "3") 133 ret = server.Exec(conn, utils.ToCmdLine("SLAVEOF", "127.0.0.1", "6379")) 134 asserts.AssertStatusReply(t, ret, "OK") 135 success = false 136 for i := 0; i < 30; i++ { 137 // wait for sync 138 time.Sleep(time.Second) 139 ret = server.Exec(conn, utils.ToCmdLine("GET", "1")) 140 bulkRet, ok := ret.(*protocol.BulkReply) 141 if ok { 142 if bytes.Equal(bulkRet.Arg, []byte("4")) { 143 success = true 144 break 145 } 146 } 147 } 148 if !success { 149 t.Error("sync failed") 150 return 151 } 152 153 // check slave aof file 154 aofLoader := MakeAuxiliaryServer() 155 aofHandler2, err := NewPersister(aofLoader, config.Properties.AppendFilename, true, aof.FsyncNo) 156 aofLoader.bindPersister(aofHandler2) 157 ret = aofLoader.Exec(conn, utils.ToCmdLine("get", "zz")) 158 asserts.AssertNullBulk(t, ret) 159 ret = aofLoader.Exec(conn, utils.ToCmdLine("get", "1")) 160 asserts.AssertBulkReply(t, ret, "4") 161 162 err = server.slaveStatus.close() 163 if err != nil { 164 t.Error("cannot close") 165 } 166 }