github.com/matrixorigin/matrixone@v1.2.0/pkg/logservice/rsm_test.go (about) 1 // Copyright 2021 - 2022 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package logservice 16 17 import ( 18 "bytes" 19 "testing" 20 21 sm "github.com/lni/dragonboat/v4/statemachine" 22 "github.com/stretchr/testify/assert" 23 24 pb "github.com/matrixorigin/matrixone/pkg/pb/logservice" 25 ) 26 27 func TestGetLeaseHistory(t *testing.T) { 28 tsm := newStateMachine(1, 2).(*stateMachine) 29 tsm.state.LeaseHistory[100] = 1000 30 tsm.state.LeaseHistory[200] = 2000 31 tsm.state.LeaseHistory[300] = 3000 32 lease, index := tsm.getLeaseHistory(150) 33 assert.Equal(t, uint64(1000), lease) 34 assert.Equal(t, uint64(100), index) 35 36 lease, index = tsm.getLeaseHistory(200) 37 assert.Equal(t, uint64(1000), lease) 38 assert.Equal(t, uint64(100), index) 39 40 lease, index = tsm.getLeaseHistory(100) 41 assert.Equal(t, uint64(0), lease) 42 assert.Equal(t, uint64(0), index) 43 44 lease, index = tsm.getLeaseHistory(400) 45 assert.Equal(t, uint64(3000), lease) 46 assert.Equal(t, uint64(300), index) 47 } 48 49 func TestTruncateLeaseHistory(t *testing.T) { 50 getSM := func() *stateMachine { 51 tsm := newStateMachine(1, 2).(*stateMachine) 52 tsm.state.LeaseHistory[100] = 1000 53 tsm.state.LeaseHistory[200] = 2000 54 tsm.state.LeaseHistory[300] = 3000 55 return tsm 56 } 57 58 tsm := getSM() 59 tsm.truncateLeaseHistory(105) 60 assert.Equal(t, 3, len(tsm.state.LeaseHistory)) 61 tsm.truncateLeaseHistory(200) 62 assert.Equal(t, 3, len(tsm.state.LeaseHistory)) 63 tsm.truncateLeaseHistory(201) 64 assert.Equal(t, 2, len(tsm.state.LeaseHistory)) 65 _, ok1 := tsm.state.LeaseHistory[200] 66 _, ok2 := tsm.state.LeaseHistory[300] 67 assert.True(t, ok1) 68 assert.True(t, ok2) 69 70 tsm = getSM() 71 tsm.truncateLeaseHistory(300) 72 assert.Equal(t, 2, len(tsm.state.LeaseHistory)) 73 _, ok := tsm.state.LeaseHistory[100] 74 assert.False(t, ok) 75 76 tsm = getSM() 77 tsm.truncateLeaseHistory(301) 78 assert.Equal(t, 1, len(tsm.state.LeaseHistory)) 79 _, ok = tsm.state.LeaseHistory[300] 80 assert.True(t, ok) 81 } 82 83 func TestGetSetLeaseHolderCmd(t *testing.T) { 84 cmd := getSetLeaseHolderCmd(100) 85 assert.True(t, isSetLeaseHolderUpdate(cmd)) 86 cmd2 := getSetTruncatedLsnCmd(200) 87 assert.False(t, isSetLeaseHolderUpdate(cmd2)) 88 } 89 90 func TestIsUserUpdate(t *testing.T) { 91 cmd := make([]byte, headerSize+8+1) 92 binaryEnc.PutUint32(cmd, uint32(pb.UserEntryUpdate)) 93 assert.True(t, isUserUpdate(cmd)) 94 cmd2 := getSetLeaseHolderCmd(1234) 95 cmd3 := getSetTruncatedLsnCmd(200) 96 assert.False(t, isUserUpdate(cmd2)) 97 assert.False(t, isUserUpdate(cmd3)) 98 } 99 100 func TestNewStateMachine(t *testing.T) { 101 tsm := newStateMachine(100, 200).(*stateMachine) 102 assert.Equal(t, uint64(100), tsm.shardID) 103 assert.Equal(t, uint64(200), tsm.replicaID) 104 } 105 106 func TestStateMachineCanBeClosed(t *testing.T) { 107 tsm := newStateMachine(100, 200) 108 assert.Nil(t, tsm.Close()) 109 } 110 111 func TestTNLeaseHolderCanBeUpdated(t *testing.T) { 112 cmd := getSetLeaseHolderCmd(500) 113 tsm := newStateMachine(1, 2).(*stateMachine) 114 assert.Equal(t, uint64(0), tsm.state.LeaseHolderID) 115 e := sm.Entry{Cmd: cmd, Index: 100} 116 result, err := tsm.Update(e) 117 assert.Equal(t, sm.Result{}, result) 118 assert.Nil(t, err) 119 assert.Equal(t, uint64(500), tsm.state.LeaseHolderID) 120 assert.Equal(t, 1, len(tsm.state.LeaseHistory)) 121 v, ok := tsm.state.LeaseHistory[100] 122 assert.True(t, ok) 123 assert.Equal(t, uint64(500), v) 124 125 cmd = getSetLeaseHolderCmd(1000) 126 e = sm.Entry{Cmd: cmd, Index: 200} 127 result, err = tsm.Update(e) 128 assert.Equal(t, sm.Result{}, result) 129 assert.Nil(t, err) 130 assert.Equal(t, uint64(1000), tsm.state.LeaseHolderID) 131 assert.Equal(t, 2, len(tsm.state.LeaseHistory)) 132 v, ok = tsm.state.LeaseHistory[200] 133 assert.True(t, ok) 134 assert.Equal(t, uint64(1000), v) 135 136 cmd = getSetTruncatedLsnCmd(110) 137 e = sm.Entry{Cmd: cmd} 138 result, err = tsm.Update(e) 139 assert.Equal(t, sm.Result{}, result) 140 assert.Nil(t, err) 141 // first lease history record won't be truncated 142 assert.Equal(t, 2, len(tsm.state.LeaseHistory)) 143 } 144 145 func TestTruncatedIndexCanBeUpdated(t *testing.T) { 146 cmd := getSetTruncatedLsnCmd(200) 147 tsm := newStateMachine(1, 2).(*stateMachine) 148 e := sm.Entry{Cmd: cmd} 149 result, err := tsm.Update(e) 150 assert.Equal(t, sm.Result{}, result) 151 assert.Nil(t, err) 152 153 cmd2 := getSetTruncatedLsnCmd(220) 154 e2 := sm.Entry{Cmd: cmd2} 155 result, err = tsm.Update(e2) 156 assert.Equal(t, sm.Result{}, result) 157 assert.Nil(t, err) 158 159 cmd3 := getSetTruncatedLsnCmd(100) 160 e3 := sm.Entry{Cmd: cmd3} 161 result, err = tsm.Update(e3) 162 assert.Equal(t, sm.Result{Value: 220}, result) 163 assert.Nil(t, err) 164 } 165 166 func TestStateMachineUserUpdate(t *testing.T) { 167 cmd := make([]byte, headerSize+8+1) 168 binaryEnc.PutUint32(cmd, uint32(pb.UserEntryUpdate)) 169 binaryEnc.PutUint64(cmd[headerSize:], uint64(1234)) 170 171 tsm := newStateMachine(1, 2).(*stateMachine) 172 tsm.state.LeaseHolderID = 1234 173 e := sm.Entry{Index: 100, Cmd: cmd} 174 result, err := tsm.Update(e) 175 assert.Nil(t, err) 176 assert.Equal(t, e.Index, result.Value) 177 assert.Nil(t, result.Data) 178 179 tsm.state.LeaseHolderID = 2345 180 e = sm.Entry{Cmd: cmd} 181 result, err = tsm.Update(e) 182 assert.Nil(t, err) 183 assert.Equal(t, uint64(0), result.Value) 184 assert.NotNil(t, result.Data) 185 assert.Equal(t, tsm.state.LeaseHolderID, binaryEnc.Uint64(result.Data)) 186 } 187 188 func TestTsoUpdate(t *testing.T) { 189 tsm := newStateMachine(1, 2).(*stateMachine) 190 tsm.state.Tso = 200 191 cmd := getTsoUpdateCmd(100) 192 result, err := tsm.Update(sm.Entry{Cmd: cmd}) 193 assert.NoError(t, err) 194 assert.Equal(t, uint64(200), result.Value) 195 assert.Equal(t, uint64(300), tsm.state.Tso) 196 } 197 198 func TestStateMachineSnapshot(t *testing.T) { 199 buf := bytes.NewBuffer(nil) 200 tsm := newStateMachine(1, 2).(*stateMachine) 201 tsm.state.LeaseHolderID = 123456 202 tsm.state.TruncatedLsn = 456789 203 assert.Nil(t, tsm.SaveSnapshot(buf, nil, nil)) 204 205 tsm2 := newStateMachine(3, 4).(*stateMachine) 206 assert.Nil(t, tsm2.RecoverFromSnapshot(buf, nil, nil)) 207 assert.Equal(t, tsm.state.LeaseHolderID, tsm2.state.LeaseHolderID) 208 assert.Equal(t, tsm.state.TruncatedLsn, tsm2.state.TruncatedLsn) 209 assert.Equal(t, uint64(3), tsm2.shardID) 210 assert.Equal(t, uint64(4), tsm2.replicaID) 211 } 212 213 func TestStateMachineLookup(t *testing.T) { 214 tsm := newStateMachine(1, 2).(*stateMachine) 215 tsm.state.Index = 1234 216 tsm.state.LeaseHolderID = 123456 217 tsm.state.TruncatedLsn = 456789 218 v, err := tsm.Lookup(leaseHolderIDQuery{}) 219 assert.Nil(t, err) 220 assert.Equal(t, tsm.state.LeaseHolderID, v.(uint64)) 221 222 v2, err := tsm.Lookup(truncatedLsnQuery{}) 223 assert.Nil(t, err) 224 assert.Equal(t, tsm.state.TruncatedLsn, v2.(uint64)) 225 226 v3, err := tsm.Lookup(indexQuery{}) 227 assert.Nil(t, err) 228 assert.Equal(t, tsm.state.Index, v3.(uint64)) 229 } 230 231 func TestStateMachineLookupPanicOnUnexpectedInputValue(t *testing.T) { 232 defer func() { 233 if r := recover(); r == nil { 234 t.Fatalf("failed to panic") 235 } 236 }() 237 tsm := newStateMachine(1, 2).(*stateMachine) 238 _, err := tsm.Lookup(uint16(1234)) 239 assert.NoError(t, err) 240 } 241 242 func TestStateMachineLookupPanicOnUnexpectedInputType(t *testing.T) { 243 defer func() { 244 if r := recover(); r == nil { 245 t.Fatalf("failed to panic") 246 } 247 }() 248 tsm := newStateMachine(1, 2).(*stateMachine) 249 _, err := tsm.Lookup(uint64(1234)) 250 assert.NoError(t, err) 251 }