github.com/matrixorigin/matrixone@v1.2.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 users pb.TaskTableUser 50 removing map[uint64][]uint64 51 adding map[uint64][]uint64 52 currentTick uint64 53 expected []*operator.Operator 54 }{ 55 { 56 desc: "normal case", 57 cluster: pb.ClusterInfo{ 58 LogShards: []metadata.LogShardRecord{{ 59 ShardID: 1, 60 NumberOfReplicas: 3, 61 }}, 62 }, 63 infos: pb.LogState{ 64 Shards: map[uint64]pb.LogShardInfo{1: { 65 ShardID: 1, 66 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 67 Epoch: 1, 68 LeaderID: 1, 69 Term: 1, 70 }}, 71 Stores: map[string]pb.LogStoreInfo{"a": { 72 Tick: 0, 73 Replicas: []pb.LogReplicaInfo{{ 74 LogShardInfo: pb.LogShardInfo{ 75 ShardID: 1, 76 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 77 Epoch: 1, 78 LeaderID: 1, 79 Term: 1, 80 }, ReplicaID: 1}}}, 81 "b": { 82 Tick: 0, 83 Replicas: []pb.LogReplicaInfo{{ 84 LogShardInfo: pb.LogShardInfo{ 85 ShardID: 1, 86 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 87 Epoch: 1, 88 LeaderID: 1, 89 Term: 1, 90 }, ReplicaID: 2}}}, 91 "c": { 92 Tick: 0, 93 Replicas: []pb.LogReplicaInfo{{ 94 LogShardInfo: pb.LogShardInfo{ 95 ShardID: 1, 96 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 97 Epoch: 1, 98 LeaderID: 1, 99 Term: 1, 100 }, ReplicaID: 3}}}, 101 }, 102 }, 103 removing: nil, 104 adding: nil, 105 currentTick: 0, 106 expected: nil, 107 }, 108 { 109 desc: "store \"a\" expired", 110 cluster: pb.ClusterInfo{ 111 LogShards: []metadata.LogShardRecord{{ 112 ShardID: 1, 113 NumberOfReplicas: 3, 114 }}, 115 }, 116 infos: pb.LogState{ 117 Shards: map[uint64]pb.LogShardInfo{1: { 118 ShardID: 1, 119 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 120 Epoch: 1, 121 LeaderID: 1, 122 Term: 1, 123 }}, 124 Stores: map[string]pb.LogStoreInfo{ 125 "a": { 126 Tick: 0, 127 Replicas: []pb.LogReplicaInfo{{ 128 LogShardInfo: pb.LogShardInfo{ 129 ShardID: 1, 130 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 131 Epoch: 1, 132 LeaderID: 1, 133 Term: 1, 134 }, ReplicaID: 1}}}, 135 "b": { 136 Tick: expiredTick + 1, 137 Replicas: []pb.LogReplicaInfo{{ 138 LogShardInfo: pb.LogShardInfo{ 139 ShardID: 1, 140 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 141 Epoch: 1, 142 LeaderID: 1, 143 Term: 1, 144 }, ReplicaID: 2}}}, 145 "c": { 146 Tick: expiredTick + 1, 147 Replicas: []pb.LogReplicaInfo{{ 148 LogShardInfo: pb.LogShardInfo{ 149 ShardID: 1, 150 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 151 Epoch: 1, 152 LeaderID: 1, 153 Term: 1, 154 }, ReplicaID: 3}}}, 155 "d": { 156 Tick: expiredTick + 1, 157 }, 158 }, 159 }, 160 removing: nil, 161 adding: nil, 162 currentTick: expiredTick + 1, 163 expected: []*operator.Operator{ 164 operator.NewOperator("", 1, 1, 165 operator.RemoveLogService{ 166 Target: "b", 167 Replica: operator.Replica{ 168 UUID: "a", 169 ShardID: 1, 170 ReplicaID: 1, 171 Epoch: 1}, 172 }), 173 }, 174 }, 175 { 176 desc: "shard 1 has only 2 replicas, which expected as 3", 177 cluster: pb.ClusterInfo{ 178 LogShards: []metadata.LogShardRecord{{ 179 ShardID: 1, 180 NumberOfReplicas: 3, 181 }}, 182 }, 183 infos: pb.LogState{ 184 Shards: map[uint64]pb.LogShardInfo{1: { 185 ShardID: 1, 186 Replicas: map[uint64]string{1: "a", 2: "b"}, 187 Epoch: 1, 188 LeaderID: 1, 189 Term: 1, 190 }}, 191 Stores: map[string]pb.LogStoreInfo{"a": { 192 Tick: 0, 193 Replicas: []pb.LogReplicaInfo{{ 194 LogShardInfo: pb.LogShardInfo{ 195 ShardID: 1, 196 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 197 Epoch: 1, 198 LeaderID: 1, 199 Term: 1, 200 }, ReplicaID: 1}}}, 201 "b": { 202 Tick: 0, 203 Replicas: []pb.LogReplicaInfo{{ 204 LogShardInfo: pb.LogShardInfo{ 205 ShardID: 1, 206 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 207 Epoch: 1, 208 LeaderID: 1, 209 Term: 1, 210 }, ReplicaID: 2}}}, 211 "c": {Tick: 0, Replicas: []pb.LogReplicaInfo{}}, 212 }, 213 }, 214 removing: nil, 215 adding: nil, 216 currentTick: 0, 217 expected: []*operator.Operator{operator.NewOperator("adding 1:4(at epoch 1) to c", 1, 218 1, operator.AddLogService{ 219 Target: "a", 220 Replica: operator.Replica{ 221 UUID: "c", 222 ShardID: 1, 223 ReplicaID: 4, 224 Epoch: 1, 225 }, 226 })}, 227 }, 228 { 229 desc: "replica 3 on store c is not started", 230 cluster: pb.ClusterInfo{ 231 LogShards: []metadata.LogShardRecord{{ 232 ShardID: 1, 233 NumberOfReplicas: 3, 234 }}, 235 }, 236 infos: pb.LogState{ 237 Shards: map[uint64]pb.LogShardInfo{1: { 238 ShardID: 1, 239 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 240 Epoch: 1, 241 LeaderID: 1, 242 Term: 1, 243 }}, 244 Stores: map[string]pb.LogStoreInfo{"a": { 245 Tick: 0, 246 Replicas: []pb.LogReplicaInfo{{ 247 LogShardInfo: pb.LogShardInfo{ 248 ShardID: 1, 249 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 250 Epoch: 1, 251 LeaderID: 1, 252 Term: 1, 253 }, ReplicaID: 1}}}, 254 "b": { 255 Tick: 0, 256 Replicas: []pb.LogReplicaInfo{{ 257 LogShardInfo: pb.LogShardInfo{ 258 ShardID: 1, 259 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 260 Epoch: 1, 261 LeaderID: 1, 262 Term: 1, 263 }, ReplicaID: 2}}}, 264 "c": { 265 Tick: 0, 266 Replicas: []pb.LogReplicaInfo{}}, 267 }, 268 }, 269 removing: nil, 270 adding: nil, 271 currentTick: 0, 272 expected: []*operator.Operator{operator.NewOperator("", 1, 273 1, operator.StartLogService{ 274 Replica: operator.Replica{ 275 UUID: "c", 276 ShardID: 1, 277 ReplicaID: 3}, 278 })}, 279 }, 280 { 281 desc: "store \"a\" expired and is processing", 282 cluster: pb.ClusterInfo{ 283 LogShards: []metadata.LogShardRecord{{ 284 ShardID: 1, 285 NumberOfReplicas: 3, 286 }}, 287 }, 288 infos: pb.LogState{ 289 Shards: map[uint64]pb.LogShardInfo{1: { 290 ShardID: 1, 291 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 292 Epoch: 1, 293 LeaderID: 1, 294 Term: 1, 295 }}, 296 Stores: map[string]pb.LogStoreInfo{"a": { 297 Tick: 0, 298 Replicas: []pb.LogReplicaInfo{{ 299 LogShardInfo: pb.LogShardInfo{ 300 ShardID: 1, 301 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 302 Epoch: 1, 303 LeaderID: 1, 304 Term: 1, 305 }, ReplicaID: 1}}}, 306 "b": { 307 Tick: expiredTick + 1, 308 Replicas: []pb.LogReplicaInfo{{ 309 LogShardInfo: pb.LogShardInfo{ 310 ShardID: 1, 311 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 312 Epoch: 1, 313 LeaderID: 1, 314 Term: 1, 315 }, ReplicaID: 2}}}, 316 "c": { 317 Tick: expiredTick + 1, 318 Replicas: []pb.LogReplicaInfo{{ 319 LogShardInfo: pb.LogShardInfo{ 320 ShardID: 1, 321 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 322 Epoch: 1, 323 LeaderID: 1, 324 Term: 1, 325 }, ReplicaID: 3}}}, 326 }, 327 }, 328 removing: map[uint64][]uint64{1: {1}}, 329 adding: nil, 330 currentTick: expiredTick + 1, 331 expected: []*operator.Operator{}, 332 }, 333 { 334 desc: "no more stores but need to create task service", 335 cluster: pb.ClusterInfo{ 336 TNShards: []metadata.TNShardRecord{{ 337 ShardID: 1, 338 LogShardID: 1, 339 }}, 340 LogShards: []metadata.LogShardRecord{{ 341 ShardID: 1, 342 NumberOfReplicas: 3, 343 }}, 344 }, 345 infos: pb.LogState{ 346 Shards: map[uint64]pb.LogShardInfo{1: { 347 ShardID: 1, 348 Replicas: map[uint64]string{ 349 1: "a", 350 2: "b", 351 3: "c", 352 }, 353 Epoch: 1, 354 LeaderID: 1, 355 Term: 1, 356 }}, 357 Stores: map[string]pb.LogStoreInfo{ 358 "a": { 359 Tick: 0, 360 Replicas: []pb.LogReplicaInfo{{ 361 LogShardInfo: pb.LogShardInfo{ 362 ShardID: 1, 363 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 364 Epoch: 1, 365 LeaderID: 1, 366 Term: 1, 367 }, 368 ReplicaID: 1, 369 }}, 370 TaskServiceCreated: true, 371 }, 372 "b": { 373 Tick: expiredTick + 1, 374 Replicas: []pb.LogReplicaInfo{{ 375 LogShardInfo: pb.LogShardInfo{ 376 ShardID: 1, 377 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 378 Epoch: 1, 379 LeaderID: 1, 380 Term: 1, 381 }, 382 }}, 383 TaskServiceCreated: true, 384 }, 385 "c": { 386 Tick: expiredTick + 1, 387 Replicas: []pb.LogReplicaInfo{{ 388 LogShardInfo: pb.LogShardInfo{ 389 ShardID: 1, 390 Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"}, 391 Epoch: 1, 392 LeaderID: 1, 393 Term: 1, 394 }, 395 }}, 396 TaskServiceCreated: false, 397 }, 398 }, 399 }, 400 users: pb.TaskTableUser{Username: "abc"}, 401 removing: nil, 402 adding: nil, 403 currentTick: 0, 404 expected: []*operator.Operator{operator.NewOperator("", 1, 405 1, operator.CreateTaskService{ 406 StoreID: "c", 407 TaskUser: pb.TaskTableUser{Username: "abc"}, 408 })}, 409 }, 410 } 411 412 for i, c := range cases { 413 fmt.Printf("case %v: %s\n", i, c.desc) 414 alloc := util.NewTestIDAllocator(3) 415 cfg := hakeeper.Config{} 416 cfg.Fill() 417 executing := operator.ExecutingReplicas{ 418 Adding: c.adding, 419 Removing: c.removing, 420 } 421 operators := Check(alloc, cfg, c.cluster, c.infos, executing, c.users, c.currentTick) 422 423 assert.Equal(t, len(c.expected), len(operators)) 424 for j, op := range operators { 425 assert.Equal(t, len(c.expected[j].OpSteps()), len(op.OpSteps())) 426 for k, step := range op.OpSteps() { 427 assert.Equal(t, c.expected[j].OpSteps()[k], step) 428 } 429 } 430 } 431 }