github.com/matrixorigin/matrixone@v0.7.0/pkg/hakeeper/checkers/logservice/check_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 "fmt" 19 "testing" 20 "time" 21 22 "github.com/matrixorigin/matrixone/pkg/common/runtime" 23 "github.com/matrixorigin/matrixone/pkg/hakeeper" 24 "github.com/matrixorigin/matrixone/pkg/hakeeper/checkers/util" 25 "github.com/matrixorigin/matrixone/pkg/hakeeper/operator" 26 "github.com/matrixorigin/matrixone/pkg/logutil" 27 pb "github.com/matrixorigin/matrixone/pkg/pb/logservice" 28 "github.com/matrixorigin/matrixone/pkg/pb/metadata" 29 "github.com/stretchr/testify/assert" 30 ) 31 32 func TestMain(m *testing.M) { 33 logutil.SetupMOLogger(&logutil.LogConfig{ 34 Level: "debug", 35 Format: "console", 36 }) 37 38 runtime.SetupProcessLevelRuntime(runtime.NewRuntime(metadata.ServiceType_LOG, "test", logutil.GetGlobalLogger())) 39 m.Run() 40 } 41 42 var expiredTick = uint64(hakeeper.DefaultLogStoreTimeout / time.Second * hakeeper.DefaultTickPerSecond) 43 44 func TestCheck(t *testing.T) { 45 cases := []struct { 46 desc string 47 cluster pb.ClusterInfo 48 infos pb.LogState 49 removing map[uint64][]uint64 50 adding map[uint64][]uint64 51 currentTick uint64 52 expected []*operator.Operator 53 }{ 54 { 55 desc: "normal case", 56 cluster: pb.ClusterInfo{ 57 LogShards: []metadata.LogShardRecord{{ 58 ShardID: 1, 59 NumberOfReplicas: 3, 60 }}, 61 }, 62 infos: pb.LogState{ 63 Shards: map[uint64]pb.LogShardInfo{1: { 64 ShardID: 1, 65 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 66 Epoch: 1, 67 LeaderID: 1, 68 Term: 1, 69 }}, 70 Stores: map[string]pb.LogStoreInfo{"a": { 71 Tick: 0, 72 Replicas: []pb.LogReplicaInfo{{ 73 LogShardInfo: pb.LogShardInfo{ 74 ShardID: 1, 75 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 76 Epoch: 1, 77 LeaderID: 1, 78 Term: 1, 79 }, ReplicaID: 1}}}, 80 "b": { 81 Tick: 0, 82 Replicas: []pb.LogReplicaInfo{{ 83 LogShardInfo: pb.LogShardInfo{ 84 ShardID: 1, 85 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 86 Epoch: 1, 87 LeaderID: 1, 88 Term: 1, 89 }, ReplicaID: 2}}}, 90 "c": { 91 Tick: 0, 92 Replicas: []pb.LogReplicaInfo{{ 93 LogShardInfo: pb.LogShardInfo{ 94 ShardID: 1, 95 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 96 Epoch: 1, 97 LeaderID: 1, 98 Term: 1, 99 }, ReplicaID: 3}}}, 100 }, 101 }, 102 removing: nil, 103 adding: nil, 104 currentTick: 0, 105 expected: nil, 106 }, 107 { 108 desc: "store \"a\" expired", 109 cluster: pb.ClusterInfo{ 110 LogShards: []metadata.LogShardRecord{{ 111 ShardID: 1, 112 NumberOfReplicas: 3, 113 }}, 114 }, 115 infos: pb.LogState{ 116 Shards: map[uint64]pb.LogShardInfo{1: { 117 ShardID: 1, 118 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 119 Epoch: 1, 120 LeaderID: 1, 121 Term: 1, 122 }}, 123 Stores: map[string]pb.LogStoreInfo{ 124 "a": { 125 Tick: 0, 126 Replicas: []pb.LogReplicaInfo{{ 127 LogShardInfo: pb.LogShardInfo{ 128 ShardID: 1, 129 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 130 Epoch: 1, 131 LeaderID: 1, 132 Term: 1, 133 }, ReplicaID: 1}}}, 134 "b": { 135 Tick: expiredTick + 1, 136 Replicas: []pb.LogReplicaInfo{{ 137 LogShardInfo: pb.LogShardInfo{ 138 ShardID: 1, 139 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 140 Epoch: 1, 141 LeaderID: 1, 142 Term: 1, 143 }, ReplicaID: 2}}}, 144 "c": { 145 Tick: expiredTick + 1, 146 Replicas: []pb.LogReplicaInfo{{ 147 LogShardInfo: pb.LogShardInfo{ 148 ShardID: 1, 149 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 150 Epoch: 1, 151 LeaderID: 1, 152 Term: 1, 153 }, ReplicaID: 3}}}, 154 "d": { 155 Tick: expiredTick + 1, 156 }, 157 }, 158 }, 159 removing: nil, 160 adding: nil, 161 currentTick: expiredTick + 1, 162 expected: []*operator.Operator{ 163 operator.NewOperator("", 1, 1, 164 operator.RemoveLogService{ 165 Target: "b", 166 Replica: operator.Replica{ 167 UUID: "a", 168 ShardID: 1, 169 ReplicaID: 1, 170 Epoch: 1}, 171 }), 172 }, 173 }, 174 { 175 desc: "shard 1 has only 2 replicas, which expected as 3", 176 cluster: pb.ClusterInfo{ 177 LogShards: []metadata.LogShardRecord{{ 178 ShardID: 1, 179 NumberOfReplicas: 3, 180 }}, 181 }, 182 infos: pb.LogState{ 183 Shards: map[uint64]pb.LogShardInfo{1: { 184 ShardID: 1, 185 Replicas: map[uint64]string{1: "a", 2: "b"}, 186 Epoch: 1, 187 LeaderID: 1, 188 Term: 1, 189 }}, 190 Stores: map[string]pb.LogStoreInfo{"a": { 191 Tick: 0, 192 Replicas: []pb.LogReplicaInfo{{ 193 LogShardInfo: pb.LogShardInfo{ 194 ShardID: 1, 195 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 196 Epoch: 1, 197 LeaderID: 1, 198 Term: 1, 199 }, ReplicaID: 1}}}, 200 "b": { 201 Tick: 0, 202 Replicas: []pb.LogReplicaInfo{{ 203 LogShardInfo: pb.LogShardInfo{ 204 ShardID: 1, 205 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 206 Epoch: 1, 207 LeaderID: 1, 208 Term: 1, 209 }, ReplicaID: 2}}}, 210 "c": {Tick: 0, Replicas: []pb.LogReplicaInfo{}}, 211 }, 212 }, 213 removing: nil, 214 adding: nil, 215 currentTick: 0, 216 expected: []*operator.Operator{operator.NewOperator("adding 1:4(at epoch 1) to c", 1, 217 1, operator.AddLogService{ 218 Target: "a", 219 Replica: operator.Replica{ 220 UUID: "c", 221 ShardID: 1, 222 ReplicaID: 4, 223 Epoch: 1, 224 }, 225 })}, 226 }, 227 { 228 desc: "replica 3 on store c is not started", 229 cluster: pb.ClusterInfo{ 230 LogShards: []metadata.LogShardRecord{{ 231 ShardID: 1, 232 NumberOfReplicas: 3, 233 }}, 234 }, 235 infos: pb.LogState{ 236 Shards: map[uint64]pb.LogShardInfo{1: { 237 ShardID: 1, 238 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 239 Epoch: 1, 240 LeaderID: 1, 241 Term: 1, 242 }}, 243 Stores: map[string]pb.LogStoreInfo{"a": { 244 Tick: 0, 245 Replicas: []pb.LogReplicaInfo{{ 246 LogShardInfo: pb.LogShardInfo{ 247 ShardID: 1, 248 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 249 Epoch: 1, 250 LeaderID: 1, 251 Term: 1, 252 }, ReplicaID: 1}}}, 253 "b": { 254 Tick: 0, 255 Replicas: []pb.LogReplicaInfo{{ 256 LogShardInfo: pb.LogShardInfo{ 257 ShardID: 1, 258 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 259 Epoch: 1, 260 LeaderID: 1, 261 Term: 1, 262 }, ReplicaID: 2}}}, 263 "c": { 264 Tick: 0, 265 Replicas: []pb.LogReplicaInfo{}}, 266 }, 267 }, 268 removing: nil, 269 adding: nil, 270 currentTick: 0, 271 expected: []*operator.Operator{operator.NewOperator("", 1, 272 1, operator.StartLogService{ 273 Replica: operator.Replica{ 274 UUID: "c", 275 ShardID: 1, 276 ReplicaID: 3}, 277 })}, 278 }, 279 { 280 desc: "store \"a\" expired and is processing", 281 cluster: pb.ClusterInfo{ 282 LogShards: []metadata.LogShardRecord{{ 283 ShardID: 1, 284 NumberOfReplicas: 3, 285 }}, 286 }, 287 infos: pb.LogState{ 288 Shards: map[uint64]pb.LogShardInfo{1: { 289 ShardID: 1, 290 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 291 Epoch: 1, 292 LeaderID: 1, 293 Term: 1, 294 }}, 295 Stores: map[string]pb.LogStoreInfo{"a": { 296 Tick: 0, 297 Replicas: []pb.LogReplicaInfo{{ 298 LogShardInfo: pb.LogShardInfo{ 299 ShardID: 1, 300 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 301 Epoch: 1, 302 LeaderID: 1, 303 Term: 1, 304 }, ReplicaID: 1}}}, 305 "b": { 306 Tick: expiredTick + 1, 307 Replicas: []pb.LogReplicaInfo{{ 308 LogShardInfo: pb.LogShardInfo{ 309 ShardID: 1, 310 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 311 Epoch: 1, 312 LeaderID: 1, 313 Term: 1, 314 }, ReplicaID: 2}}}, 315 "c": { 316 Tick: expiredTick + 1, 317 Replicas: []pb.LogReplicaInfo{{ 318 LogShardInfo: pb.LogShardInfo{ 319 ShardID: 1, 320 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 321 Epoch: 1, 322 LeaderID: 1, 323 Term: 1, 324 }, ReplicaID: 3}}}, 325 }, 326 }, 327 removing: map[uint64][]uint64{1: {1}}, 328 adding: nil, 329 currentTick: expiredTick + 1, 330 expected: []*operator.Operator{}, 331 }, 332 } 333 334 for i, c := range cases { 335 fmt.Printf("case %v: %s\n", i, c.desc) 336 alloc := util.NewTestIDAllocator(3) 337 cfg := hakeeper.Config{} 338 cfg.Fill() 339 executing := operator.ExecutingReplicas{ 340 Adding: c.adding, 341 Removing: c.removing, 342 } 343 operators := Check(alloc, cfg, c.cluster, c.infos, executing, pb.TaskTableUser{}, c.currentTick) 344 345 assert.Equal(t, len(c.expected), len(operators)) 346 for j, op := range operators { 347 assert.Equal(t, len(c.expected[j].OpSteps()), len(op.OpSteps())) 348 for k, step := range op.OpSteps() { 349 assert.Equal(t, c.expected[j].OpSteps()[k], step) 350 } 351 } 352 } 353 }