github.com/matrixorigin/matrixone@v1.2.0/pkg/pb/logservice/logservice_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 "testing" 19 20 "github.com/matrixorigin/matrixone/pkg/pb/metadata" 21 "github.com/stretchr/testify/assert" 22 ) 23 24 func TestLogRecord(t *testing.T) { 25 r := LogRecord{ 26 Data: make([]byte, 32), 27 } 28 assert.Equal(t, 32-HeaderSize-8, len(r.Payload())) 29 r.ResizePayload(2) 30 assert.Equal(t, HeaderSize+8+2, len(r.Data)) 31 assert.Equal(t, 2, len(r.Payload())) 32 } 33 34 func TestCNStateUpdate(t *testing.T) { 35 state := CNState{Stores: map[string]CNStoreInfo{}} 36 37 hb1 := CNStoreHeartbeat{UUID: "cn-a", ServiceAddress: "addr-a", Role: metadata.CNRole_AP} 38 tick1 := uint64(100) 39 40 state.Update(hb1, tick1) 41 assert.Equal(t, state.Stores[hb1.UUID], CNStoreInfo{ 42 Tick: tick1, 43 ServiceAddress: hb1.ServiceAddress, 44 Role: metadata.CNRole_AP, 45 WorkState: metadata.WorkState_Working, 46 Labels: map[string]metadata.LabelList{}, 47 UpTime: state.Stores[hb1.UUID].UpTime, 48 }) 49 50 hb2 := CNStoreHeartbeat{UUID: "cn-b", ServiceAddress: "addr-b", Role: metadata.CNRole_TP} 51 tick2 := uint64(200) 52 53 state.Update(hb2, tick2) 54 assert.Equal(t, state.Stores[hb2.UUID], CNStoreInfo{ 55 Tick: tick2, 56 ServiceAddress: hb2.ServiceAddress, 57 Role: metadata.CNRole_TP, 58 WorkState: metadata.WorkState_Working, 59 Labels: map[string]metadata.LabelList{}, 60 UpTime: state.Stores[hb2.UUID].UpTime, 61 }) 62 63 hb3 := CNStoreHeartbeat{UUID: "cn-a", ServiceAddress: "addr-a", Role: metadata.CNRole_TP} 64 tick3 := uint64(300) 65 66 state.Update(hb3, tick3) 67 assert.Equal(t, state.Stores[hb3.UUID], CNStoreInfo{ 68 Tick: tick3, 69 ServiceAddress: hb3.ServiceAddress, 70 Role: metadata.CNRole_TP, 71 WorkState: metadata.WorkState_Working, 72 Labels: map[string]metadata.LabelList{}, 73 UpTime: state.Stores[hb3.UUID].UpTime, 74 }) 75 } 76 77 func TestTNStateUpdate(t *testing.T) { 78 state := TNState{Stores: map[string]TNStoreInfo{}} 79 80 hb1 := TNStoreHeartbeat{ 81 UUID: "dn-a", 82 ServiceAddress: "addr-a", 83 Shards: []TNShardInfo{{ 84 ShardID: 1, 85 ReplicaID: 1, 86 }}, 87 LogtailServerAddress: "addr-0", 88 } 89 tick1 := uint64(100) 90 91 state.Update(hb1, tick1) 92 assert.Equal(t, state.Stores["dn-a"], TNStoreInfo{ 93 Tick: tick1, 94 ServiceAddress: hb1.ServiceAddress, 95 Shards: hb1.Shards, 96 LogtailServerAddress: hb1.LogtailServerAddress, 97 }) 98 99 hb2 := TNStoreHeartbeat{ 100 UUID: "dn-a", 101 ServiceAddress: "addr-a", 102 Shards: []TNShardInfo{ 103 {ShardID: 1, ReplicaID: 1}, 104 {ShardID: 2, ReplicaID: 1}}, 105 LogtailServerAddress: "addr-0", 106 } 107 tick2 := uint64(200) 108 109 state.Update(hb2, tick2) 110 assert.Equal(t, state.Stores[hb2.UUID], TNStoreInfo{ 111 Tick: tick2, 112 ServiceAddress: hb2.ServiceAddress, 113 Shards: hb2.Shards, 114 LogtailServerAddress: "addr-0", 115 }) 116 } 117 118 func TestLogStateUpdateStores(t *testing.T) { 119 defer func() { 120 if r := recover(); r == nil { 121 t.Errorf("The code did not panic") 122 } 123 }() 124 125 state := LogState{ 126 Shards: map[uint64]LogShardInfo{}, 127 Stores: map[string]LogStoreInfo{}, 128 } 129 130 hb1 := LogStoreHeartbeat{ 131 UUID: "log-a", 132 RaftAddress: "raft-a", 133 ServiceAddress: "addr-a", 134 GossipAddress: "gossip-a", 135 Replicas: []LogReplicaInfo{{ 136 LogShardInfo: LogShardInfo{ 137 ShardID: 1, 138 Replicas: map[uint64]string{1: "log-a"}, 139 Epoch: 1, 140 LeaderID: 1, 141 Term: 1, 142 }, 143 ReplicaID: 1, 144 }}, 145 } 146 tick1 := uint64(100) 147 state.Update(hb1, tick1) 148 assert.Equal(t, state.Stores[hb1.UUID], LogStoreInfo{ 149 Tick: tick1, 150 RaftAddress: hb1.RaftAddress, 151 ServiceAddress: hb1.ServiceAddress, 152 GossipAddress: hb1.GossipAddress, 153 Replicas: hb1.Replicas, 154 }) 155 156 hb2 := LogStoreHeartbeat{ 157 UUID: "log-a", 158 RaftAddress: "raft-a", 159 ServiceAddress: "addr-a", 160 GossipAddress: "gossip-a", 161 Replicas: []LogReplicaInfo{{ 162 LogShardInfo: LogShardInfo{ 163 ShardID: 1, 164 Replicas: map[uint64]string{1: "log-a", 2: "log-b"}, 165 Epoch: 2, 166 LeaderID: 1, 167 Term: 2, 168 }, 169 ReplicaID: 1, 170 }}, 171 } 172 tick2 := uint64(200) 173 state.Update(hb2, tick2) 174 assert.Equal(t, state.Stores[hb2.UUID], LogStoreInfo{ 175 Tick: tick2, 176 RaftAddress: hb2.RaftAddress, 177 ServiceAddress: hb2.ServiceAddress, 178 GossipAddress: hb2.GossipAddress, 179 Replicas: hb2.Replicas, 180 }) 181 182 hb3 := LogStoreHeartbeat{ 183 UUID: "log-a", 184 RaftAddress: "raft-a", 185 ServiceAddress: "addr-a", 186 GossipAddress: "gossip-a", 187 Replicas: []LogReplicaInfo{{ 188 LogShardInfo: LogShardInfo{ 189 ShardID: 1, 190 Replicas: map[uint64]string{1: "log-a"}, 191 Epoch: 2, 192 LeaderID: 1, 193 Term: 2, 194 }, 195 ReplicaID: 1, 196 }}, 197 } 198 tick3 := uint64(200) 199 200 // should panic() 201 state.Update(hb3, tick3) 202 } 203 204 func TestLogString(t *testing.T) { 205 cases := []struct { 206 desc string 207 208 command ScheduleCommand 209 expected string 210 }{ 211 { 212 desc: "add log replica", 213 command: ScheduleCommand{ 214 UUID: "storeA", 215 Bootstrapping: false, 216 ConfigChange: &ConfigChange{ 217 Replica: Replica{ 218 UUID: "storeB", 219 ShardID: 1, 220 ReplicaID: 4, 221 Epoch: 1, 222 LogShardID: 0, 223 }, 224 ChangeType: AddReplica, 225 InitialMembers: nil, 226 }, 227 ServiceType: LogService, 228 ShutdownStore: nil, 229 }, 230 expected: "L/Add storeA storeB:1:4:1", 231 }, 232 { 233 desc: "remove log replica", 234 command: ScheduleCommand{ 235 UUID: "storeA", 236 Bootstrapping: false, 237 ConfigChange: &ConfigChange{ 238 Replica: Replica{ 239 UUID: "storeB", 240 ShardID: 1, 241 ReplicaID: 4, 242 Epoch: 1, 243 LogShardID: 0, 244 }, 245 ChangeType: RemoveReplica, 246 InitialMembers: nil, 247 }, 248 ServiceType: LogService, 249 ShutdownStore: nil, 250 }, 251 expected: "L/Remove storeA storeB:1:4:1", 252 }, 253 { 254 desc: "remove log replica", 255 command: ScheduleCommand{ 256 UUID: "storeA", 257 Bootstrapping: false, 258 ConfigChange: &ConfigChange{ 259 Replica: Replica{ 260 UUID: "storeA", 261 ShardID: 1, 262 ReplicaID: 4, 263 Epoch: 1, 264 LogShardID: 0, 265 }, 266 ChangeType: StartReplica, 267 InitialMembers: nil, 268 }, 269 ServiceType: LogService, 270 ShutdownStore: nil, 271 }, 272 expected: "L/Start storeA storeA:1:4:1", 273 }, 274 { 275 desc: "remove log replica", 276 command: ScheduleCommand{ 277 UUID: "storeA", 278 Bootstrapping: false, 279 ConfigChange: &ConfigChange{ 280 Replica: Replica{ 281 UUID: "storeA", 282 ShardID: 1, 283 ReplicaID: 4, 284 Epoch: 1, 285 LogShardID: 0, 286 }, 287 ChangeType: StartReplica, 288 InitialMembers: nil, 289 }, 290 ServiceType: TNService, 291 ShutdownStore: nil, 292 }, 293 expected: "D/Start storeA storeA:1:4:1", 294 }, 295 { 296 desc: "remove log replica", 297 command: ScheduleCommand{ 298 UUID: "storeA", 299 Bootstrapping: false, 300 ServiceType: LogService, 301 ShutdownStore: &ShutdownStore{ 302 StoreID: "storeA", 303 }, 304 }, 305 expected: "L/shutdown storeA", 306 }, 307 { 308 desc: "kill zombie", 309 command: ScheduleCommand{ 310 UUID: "storeA", 311 Bootstrapping: false, 312 ConfigChange: &ConfigChange{ 313 Replica: Replica{ 314 UUID: "storeA", 315 ShardID: 1, 316 }, 317 ChangeType: KillZombie, 318 }, 319 ServiceType: LogService, 320 }, 321 expected: "L/Kill storeA storeA:1:0:0", 322 }, 323 { 324 desc: "bootstrapping", 325 command: ScheduleCommand{ 326 UUID: "storeA", 327 Bootstrapping: true, 328 ConfigChange: &ConfigChange{ 329 Replica: Replica{ 330 UUID: "storeA", 331 ShardID: 1, 332 ReplicaID: 1, 333 }, 334 ChangeType: StartReplica, 335 InitialMembers: map[uint64]string{1: "storeA123", 2: "storeB", 3: "storeC"}, 336 }, 337 ServiceType: LogService, 338 }, 339 expected: "L/Start storeA storeA:1:1:0 [1:storeA123 2:storeB 3:storeC]", 340 }, 341 } 342 343 for _, c := range cases { 344 output := c.command.LogString() 345 assert.Equal(t, c.expected, output) 346 } 347 } 348 349 func TestCNLabelUpdate(t *testing.T) { 350 state := CNState{Stores: map[string]CNStoreInfo{}} 351 352 label := CNStoreLabel{ 353 UUID: "cn-1", 354 Labels: map[string]metadata.LabelList{ 355 "account": { 356 Labels: []string{"a1", "a2"}, 357 }, 358 "role": { 359 Labels: []string{"r1"}, 360 }, 361 }, 362 } 363 364 state.UpdateLabel(label) 365 // No heartbeat yet, nothing happens. 366 assert.Equal(t, state.Stores[label.UUID], CNStoreInfo{}) 367 368 // Add CN store to HAKeeper. 369 hb1 := CNStoreHeartbeat{UUID: "cn-1", ServiceAddress: "addr-a", Role: metadata.CNRole_AP} 370 tick1 := uint64(100) 371 372 state.Update(hb1, tick1) 373 assert.Equal(t, state.Stores[hb1.UUID], CNStoreInfo{ 374 Tick: tick1, 375 ServiceAddress: hb1.ServiceAddress, 376 Role: metadata.CNRole_AP, 377 WorkState: metadata.WorkState_Working, 378 Labels: map[string]metadata.LabelList{}, 379 UpTime: state.Stores[hb1.UUID].UpTime, 380 }) 381 382 label = CNStoreLabel{ 383 UUID: "cn-1", 384 Labels: map[string]metadata.LabelList{ 385 "account": { 386 Labels: []string{"a1", "a2"}, 387 }, 388 "role": { 389 Labels: []string{"r1"}, 390 }, 391 }, 392 } 393 394 state.UpdateLabel(label) 395 assert.Equal(t, state.Stores[label.UUID], CNStoreInfo{ 396 Tick: tick1, 397 ServiceAddress: hb1.ServiceAddress, 398 Role: metadata.CNRole_AP, 399 WorkState: metadata.WorkState_Working, 400 Labels: map[string]metadata.LabelList{ 401 "account": { 402 Labels: []string{"a1", "a2"}, 403 }, 404 "role": { 405 Labels: []string{"r1"}, 406 }, 407 }, 408 UpTime: state.Stores[label.UUID].UpTime, 409 }) 410 411 label = CNStoreLabel{ 412 UUID: "cn-1", 413 Labels: map[string]metadata.LabelList{ 414 "role": { 415 Labels: []string{"r1"}, 416 }, 417 }, 418 } 419 420 state.UpdateLabel(label) 421 assert.Equal(t, state.Stores[label.UUID], CNStoreInfo{ 422 Tick: tick1, 423 ServiceAddress: hb1.ServiceAddress, 424 Role: metadata.CNRole_AP, 425 WorkState: metadata.WorkState_Working, 426 Labels: map[string]metadata.LabelList{ 427 "role": { 428 Labels: []string{"r1"}, 429 }, 430 }, 431 UpTime: state.Stores[label.UUID].UpTime, 432 }) 433 } 434 435 func TestCNWorkStateUpdate(t *testing.T) { 436 state := CNState{Stores: map[string]CNStoreInfo{}} 437 438 workState := CNWorkState{ 439 UUID: "cn-1", 440 State: metadata.WorkState_Working, 441 } 442 state.UpdateWorkState(workState) 443 // No heartbeat yet, nothing happens. 444 assert.Equal(t, state.Stores[workState.UUID], CNStoreInfo{}) 445 446 // Add CN store to HAKeeper. 447 hb1 := CNStoreHeartbeat{UUID: "cn-1", ServiceAddress: "addr-a", Role: metadata.CNRole_AP} 448 tick1 := uint64(100) 449 450 state.Update(hb1, tick1) 451 assert.Equal(t, state.Stores[hb1.UUID], CNStoreInfo{ 452 Tick: tick1, 453 ServiceAddress: hb1.ServiceAddress, 454 Role: metadata.CNRole_AP, 455 WorkState: metadata.WorkState_Working, 456 Labels: map[string]metadata.LabelList{}, 457 UpTime: state.Stores[hb1.UUID].UpTime, 458 }) 459 460 workState = CNWorkState{ 461 UUID: "cn-1", 462 State: metadata.WorkState_Draining, 463 } 464 465 state.UpdateWorkState(workState) 466 assert.Equal(t, state.Stores[workState.UUID], CNStoreInfo{ 467 Tick: tick1, 468 ServiceAddress: hb1.ServiceAddress, 469 Role: metadata.CNRole_AP, 470 WorkState: metadata.WorkState_Draining, 471 Labels: map[string]metadata.LabelList{}, 472 UpTime: state.Stores[workState.UUID].UpTime, 473 }) 474 475 workState = CNWorkState{ 476 UUID: "cn-1", 477 State: metadata.WorkState_Working, 478 } 479 480 state.UpdateWorkState(workState) 481 assert.Equal(t, state.Stores[workState.UUID], CNStoreInfo{ 482 Tick: tick1, 483 ServiceAddress: hb1.ServiceAddress, 484 Role: metadata.CNRole_AP, 485 WorkState: metadata.WorkState_Working, 486 Labels: map[string]metadata.LabelList{}, 487 UpTime: state.Stores[workState.UUID].UpTime, 488 }) 489 } 490 491 func TestCNStateLabelPatch(t *testing.T) { 492 state := CNState{Stores: map[string]CNStoreInfo{}} 493 494 stateLabel := CNStateLabel{ 495 UUID: "cn-1", 496 State: metadata.WorkState_Working, 497 Labels: map[string]metadata.LabelList{ 498 "account": { 499 Labels: []string{"a1", "a2"}, 500 }, 501 "role": { 502 Labels: []string{"r1"}, 503 }, 504 }, 505 } 506 state.PatchCNStore(stateLabel) 507 // No heartbeat yet, nothing happens. 508 assert.Equal(t, state.Stores[stateLabel.UUID], CNStoreInfo{}) 509 510 // Add CN store to HAKeeper. 511 hb1 := CNStoreHeartbeat{UUID: "cn-1", ServiceAddress: "addr-a", Role: metadata.CNRole_AP} 512 tick1 := uint64(100) 513 514 state.Update(hb1, tick1) 515 assert.Equal(t, state.Stores[hb1.UUID], CNStoreInfo{ 516 Tick: tick1, 517 ServiceAddress: hb1.ServiceAddress, 518 Role: metadata.CNRole_AP, 519 WorkState: metadata.WorkState_Working, 520 Labels: map[string]metadata.LabelList{}, 521 UpTime: state.Stores[hb1.UUID].UpTime, 522 }) 523 524 stateLabel = CNStateLabel{ 525 UUID: "cn-1", 526 State: metadata.WorkState_Draining, 527 Labels: map[string]metadata.LabelList{ 528 "account": { 529 Labels: []string{"a1", "a2"}, 530 }, 531 "role": { 532 Labels: []string{"r1"}, 533 }, 534 }, 535 } 536 state.PatchCNStore(stateLabel) 537 assert.Equal(t, state.Stores[stateLabel.UUID], CNStoreInfo{ 538 Tick: tick1, 539 ServiceAddress: hb1.ServiceAddress, 540 Role: metadata.CNRole_AP, 541 WorkState: metadata.WorkState_Draining, 542 Labels: map[string]metadata.LabelList{ 543 "account": { 544 Labels: []string{"a1", "a2"}, 545 }, 546 "role": { 547 Labels: []string{"r1"}, 548 }, 549 }, 550 UpTime: state.Stores[stateLabel.UUID].UpTime, 551 }) 552 553 stateLabel = CNStateLabel{ 554 UUID: "cn-1", 555 State: metadata.WorkState_Drained, 556 } 557 state.PatchCNStore(stateLabel) 558 assert.Equal(t, state.Stores[stateLabel.UUID], CNStoreInfo{ 559 Tick: tick1, 560 ServiceAddress: hb1.ServiceAddress, 561 Role: metadata.CNRole_AP, 562 WorkState: metadata.WorkState_Drained, 563 Labels: map[string]metadata.LabelList{ 564 "account": { 565 Labels: []string{"a1", "a2"}, 566 }, 567 "role": { 568 Labels: []string{"r1"}, 569 }, 570 }, 571 UpTime: state.Stores[stateLabel.UUID].UpTime, 572 }) 573 574 stateLabel = CNStateLabel{ 575 UUID: "cn-1", 576 Labels: map[string]metadata.LabelList{ 577 "role": { 578 Labels: []string{"r1"}, 579 }, 580 }, 581 } 582 state.PatchCNStore(stateLabel) 583 assert.Equal(t, state.Stores[stateLabel.UUID], CNStoreInfo{ 584 Tick: tick1, 585 ServiceAddress: hb1.ServiceAddress, 586 Role: metadata.CNRole_AP, 587 WorkState: metadata.WorkState_Working, 588 Labels: map[string]metadata.LabelList{ 589 "role": { 590 Labels: []string{"r1"}, 591 }, 592 }, 593 UpTime: state.Stores[stateLabel.UUID].UpTime, 594 }) 595 } 596 597 func TestProxyStateUpdate(t *testing.T) { 598 state := ProxyState{Stores: map[string]ProxyStore{}} 599 600 hb1 := ProxyHeartbeat{ 601 UUID: "proxy-1", 602 ListenAddress: "addr-a", 603 } 604 tick1 := uint64(100) 605 606 state.Update(hb1, tick1) 607 assert.Equal(t, state.Stores[hb1.UUID], ProxyStore{ 608 UUID: hb1.UUID, 609 Tick: tick1, 610 ListenAddress: hb1.ListenAddress, 611 }) 612 613 hb2 := ProxyHeartbeat{ 614 UUID: "proxy-1", 615 ListenAddress: "addr-a", 616 } 617 tick2 := uint64(200) 618 619 state.Update(hb2, tick2) 620 assert.Equal(t, state.Stores[hb2.UUID], ProxyStore{ 621 UUID: hb1.UUID, 622 Tick: tick2, 623 ListenAddress: hb1.ListenAddress, 624 }) 625 }