github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/colexec/table_function/system_view_test.go (about) 1 // Copyright 2023 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 table_function 16 17 import ( 18 "context" 19 "fmt" 20 "reflect" 21 "testing" 22 "time" 23 24 "github.com/golang/mock/gomock" 25 "github.com/matrixorigin/matrixone/pkg/clusterservice" 26 "github.com/matrixorigin/matrixone/pkg/common/mpool" 27 "github.com/matrixorigin/matrixone/pkg/container/vector" 28 "github.com/matrixorigin/matrixone/pkg/logservice" 29 "github.com/matrixorigin/matrixone/pkg/pb/lock" 30 pb "github.com/matrixorigin/matrixone/pkg/pb/logservice" 31 "github.com/matrixorigin/matrixone/pkg/pb/metadata" 32 "github.com/matrixorigin/matrixone/pkg/pb/query" 33 "github.com/matrixorigin/matrixone/pkg/queryservice" 34 qclient "github.com/matrixorigin/matrixone/pkg/queryservice/client" 35 "github.com/matrixorigin/matrixone/pkg/vm" 36 "github.com/matrixorigin/matrixone/pkg/vm/process" 37 "github.com/prashantv/gostub" 38 "github.com/stretchr/testify/assert" 39 ) 40 41 var _ queryservice.QueryService = &mockQueryService{} 42 43 type mockQueryService struct { 44 } 45 46 func (m *mockQueryService) SetReleaseFunc(_ *query.Response, _ func()) { 47 } 48 49 func (m *mockQueryService) SendMessage(ctx context.Context, address string, req *query.Request) (*query.Response, error) { 50 return nil, nil 51 } 52 53 func (m *mockQueryService) NewRequest(method query.CmdMethod) *query.Request { 54 req := &query.Request{ 55 CmdMethod: method, 56 } 57 switch method { 58 case query.CmdMethod_GetCacheInfo: 59 req.GetCacheInfoRequest = &query.GetCacheInfoRequest{} 60 case query.CmdMethod_GetTxnInfo: 61 req.GetTxnInfoRequest = &query.GetTxnInfoRequest{} 62 case query.CmdMethod_GetLockInfo: 63 req.GetLockInfoRequest = &query.GetLockInfoRequest{} 64 default: 65 panic(fmt.Sprintf("usp method:%s", method.String())) 66 } 67 return req 68 } 69 70 func (m *mockQueryService) Release(response *query.Response) { 71 } 72 73 func (m *mockQueryService) Start() error { 74 return nil 75 } 76 77 func (m *mockQueryService) Close() error { 78 return nil 79 } 80 81 func (m *mockQueryService) AddHandleFunc(method query.CmdMethod, h func(context.Context, *query.Request, *query.Response) error, async bool) { 82 } 83 84 func (m *mockQueryService) AddReleaseFunc(method query.CmdMethod, f func()) { 85 } 86 87 func (m *mockQueryService) ServiceID() string { 88 return "mock_query_service" 89 } 90 91 func Test_gettingInfo(t *testing.T) { 92 ctrl := gomock.NewController(t) 93 defer ctrl.Finish() 94 95 wantCacheInfo := &query.CacheInfo{ 96 NodeType: "cache_node", 97 NodeId: "cache_node_id", 98 CacheType: "mock_cache", 99 } 100 101 wantTxnInfo := &query.TxnInfo{ 102 CreateAt: time.Time{}, 103 Meta: nil, 104 UserTxn: true, 105 WaitLocks: nil, 106 } 107 108 wantLockInfo := &query.LockInfo{ 109 TableId: 1000, 110 Keys: nil, 111 LockMode: lock.LockMode_Exclusive, 112 IsRangeLock: true, 113 Holders: nil, 114 Waiters: nil, 115 } 116 117 selectStubs := gostub.Stub(&selectSuperTenant, 118 func(selector clusterservice.Selector, 119 username string, 120 filter func(string) bool, 121 appendFn func(service *metadata.CNService)) { 122 if appendFn != nil { 123 appendFn(&metadata.CNService{ 124 QueryAddress: "127.0.0.1:6060", 125 }) 126 } 127 }) 128 defer selectStubs.Reset() 129 130 listTnStubs := gostub.Stub(&listTnService, func(appendFn func(service *metadata.TNService)) { 131 }) 132 defer listTnStubs.Reset() 133 134 requestMultipleCnStubs := gostub.Stub(&requestMultipleCn, 135 func(ctx context.Context, 136 nodes []string, 137 qt qclient.QueryClient, 138 genRequest func() *query.Request, 139 handleValidResponse func(string, *query.Response), 140 handleInvalidResponse func(string)) error { 141 req := genRequest() 142 fmt.Println(">>>>>", *req) 143 resp := &query.Response{ 144 CmdMethod: req.CmdMethod, 145 } 146 switch req.CmdMethod { 147 case query.CmdMethod_GetCacheInfo: 148 resp.GetCacheInfoResponse = &query.GetCacheInfoResponse{ 149 CacheInfoList: []*query.CacheInfo{ 150 wantCacheInfo, 151 }, 152 } 153 case query.CmdMethod_GetTxnInfo: 154 resp.GetTxnInfoResponse = &query.GetTxnInfoResponse{ 155 TxnInfoList: []*query.TxnInfo{ 156 wantTxnInfo, 157 }, 158 } 159 case query.CmdMethod_GetLockInfo: 160 resp.GetLockInfoResponse = &query.GetLockInfoResponse{ 161 CnId: "xxx", 162 LockInfoList: []*query.LockInfo{ 163 wantLockInfo, 164 }, 165 } 166 default: 167 panic(fmt.Sprintf("usp method %v", req.CmdMethod.String())) 168 } 169 170 fmt.Println(">>>>>", *resp) 171 handleValidResponse("", resp) 172 return nil 173 }) 174 defer requestMultipleCnStubs.Reset() 175 176 mp, err := mpool.NewMPool("ut_pool", 0, mpool.NoFixed) 177 if err != nil { 178 assert.NoError(t, err) 179 } 180 defer mpool.DeleteMPool(mp) 181 182 testProc := process.New(context.Background(), mp, nil, nil, nil, nil, &mockQueryService{}, nil, nil, nil) 183 184 type args struct { 185 proc *process.Process 186 } 187 //////test get cache status 188 tests := []struct { 189 name string 190 args args 191 want []*query.GetCacheInfoResponse 192 wantErr bool 193 }{ 194 { 195 name: "t1", 196 args: args{ 197 proc: testProc, 198 }, 199 want: []*query.GetCacheInfoResponse{ 200 { 201 CacheInfoList: []*query.CacheInfo{ 202 wantCacheInfo, 203 }, 204 }, 205 }, 206 wantErr: false, 207 }, 208 } 209 for _, tt := range tests { 210 t.Run(tt.name, func(t *testing.T) { 211 got, err := getCacheStats(tt.args.proc) 212 if (err != nil) != tt.wantErr { 213 t.Errorf("getCacheStats() error = %v, wantErr %v", err, tt.wantErr) 214 return 215 } 216 if !reflect.DeepEqual(got, tt.want) { 217 t.Errorf("getCacheStats() got = %v, want %v", got, tt.want) 218 } 219 }) 220 } 221 222 /////test get txns info 223 tests1 := []struct { 224 name string 225 args args 226 want []*query.GetTxnInfoResponse 227 wantErr bool 228 }{ 229 { 230 name: "t2", 231 args: args{ 232 proc: testProc, 233 }, 234 want: []*query.GetTxnInfoResponse{ 235 { 236 TxnInfoList: []*query.TxnInfo{ 237 wantTxnInfo, 238 }, 239 }, 240 }, 241 wantErr: false, 242 }, 243 } 244 for _, tt := range tests1 { 245 t.Run(tt.name, func(t *testing.T) { 246 got, err := getTxns(tt.args.proc) 247 if (err != nil) != tt.wantErr { 248 t.Errorf("getCacheStats() error = %v, wantErr %v", err, tt.wantErr) 249 return 250 } 251 if !reflect.DeepEqual(got, tt.want) { 252 t.Errorf("getCacheStats() got = %v, want %v", got, tt.want) 253 } 254 }) 255 } 256 257 /////test get locks info 258 tests2 := []struct { 259 name string 260 args args 261 want []*query.GetLockInfoResponse 262 wantErr bool 263 }{ 264 { 265 name: "t3", 266 args: args{ 267 proc: testProc, 268 }, 269 want: []*query.GetLockInfoResponse{ 270 { 271 CnId: "xxx", 272 LockInfoList: []*query.LockInfo{ 273 wantLockInfo, 274 }, 275 }, 276 }, 277 wantErr: false, 278 }, 279 } 280 for _, tt := range tests2 { 281 t.Run(tt.name, func(t *testing.T) { 282 got, err := getLocks(tt.args.proc) 283 if (err != nil) != tt.wantErr { 284 t.Errorf("getCacheStats() error = %v, wantErr %v", err, tt.wantErr) 285 return 286 } 287 if !reflect.DeepEqual(got, tt.want) { 288 t.Errorf("getCacheStats() got = %v, want %v", got, tt.want) 289 } 290 }) 291 } 292 293 /////test moCacheCall 294 295 type argsx struct { 296 in0 int 297 proc *process.Process 298 arg *Argument 299 } 300 tests4 := []struct { 301 name string 302 args argsx 303 want bool 304 wantErr bool 305 }{ 306 { 307 name: "", 308 args: argsx{ 309 proc: testProc, 310 arg: &Argument{ 311 ctr: &container{ 312 state: dataProducing, 313 executorsForArgs: nil, 314 }, 315 Rets: nil, 316 Args: nil, 317 Attrs: []string{ 318 "type", 319 "used", 320 "hit_ratio", 321 }, 322 Params: nil, 323 FuncName: "", 324 retSchema: nil, 325 }, 326 }, 327 want: false, 328 wantErr: false, 329 }, 330 } 331 for _, tt := range tests4 { 332 t.Run(tt.name, func(t *testing.T) { 333 result := vm.NewCallResult() 334 got, err := moCacheCall(tt.args.in0, tt.args.proc, tt.args.arg, &result) 335 if (err != nil) != tt.wantErr { 336 t.Errorf("moCacheCall() error = %v, wantErr %v", err, tt.wantErr) 337 return 338 } 339 if got != tt.want { 340 t.Errorf("moCacheCall() got = %v, want %v", got, tt.want) 341 } 342 bat := result.Batch 343 344 assert.Equal(t, len(bat.Attrs), 3) 345 assert.Equal(t, bat.Attrs[0], "type") 346 assert.Equal(t, bat.Attrs[1], "used") 347 assert.Equal(t, bat.Attrs[2], "hit_ratio") 348 349 assert.Equal(t, vector.MustStrCol(bat.GetVector(0))[0], "mock_cache") 350 assert.Equal(t, vector.MustFixedCol[uint64](bat.GetVector(1))[0], uint64(0)) 351 352 }) 353 } 354 355 ///// test moTransactionsCall 356 357 tests5 := []struct { 358 name string 359 args argsx 360 want bool 361 wantErr assert.ErrorAssertionFunc 362 }{ 363 { 364 name: "", 365 args: argsx{ 366 proc: testProc, 367 arg: &Argument{ 368 ctr: &container{ 369 state: dataProducing, 370 executorsForArgs: nil, 371 }, 372 Rets: nil, 373 Args: nil, 374 Attrs: []string{ 375 "user_txn", 376 }, 377 Params: nil, 378 FuncName: "", 379 retSchema: nil, 380 }, 381 }, 382 want: false, 383 wantErr: func(assert.TestingT, error, ...interface{}) bool { 384 385 return true 386 }, 387 }, 388 } 389 for _, tt := range tests5 { 390 t.Run(tt.name, func(t *testing.T) { 391 result := vm.NewCallResult() 392 got, err := moTransactionsCall(tt.args.in0, tt.args.proc, tt.args.arg, &result) 393 if !tt.wantErr(t, err, fmt.Sprintf("moTransactionsCall(%v, %v, %v)", tt.args.in0, tt.args.proc, tt.args.arg)) { 394 return 395 } 396 assert.Equalf(t, tt.want, got, "moTransactionsCall(%v, %v, %v)", tt.args.in0, tt.args.proc, tt.args.arg) 397 bat := result.Batch 398 399 assert.Equal(t, len(bat.Attrs), 1) 400 assert.Equal(t, bat.Attrs[0], "user_txn") 401 402 assert.Equal(t, vector.MustStrCol(bat.GetVector(0))[0], "true") 403 }) 404 } 405 406 ///// test moLocksCall 407 408 tests6 := []struct { 409 name string 410 args argsx 411 want bool 412 wantErr assert.ErrorAssertionFunc 413 }{ 414 { 415 name: "", 416 args: argsx{ 417 proc: testProc, 418 arg: &Argument{ 419 ctr: &container{ 420 state: dataProducing, 421 executorsForArgs: nil, 422 }, 423 Rets: nil, 424 Args: nil, 425 Attrs: []string{ 426 "table_id", 427 "lock_key", 428 "lock_mode", 429 }, 430 Params: nil, 431 FuncName: "", 432 retSchema: nil, 433 }, 434 }, 435 want: false, 436 wantErr: func(assert.TestingT, error, ...interface{}) bool { 437 438 return true 439 }, 440 }, 441 } 442 for _, tt := range tests6 { 443 t.Run(tt.name, func(t *testing.T) { 444 result := vm.NewCallResult() 445 got, err := moLocksCall(tt.args.in0, tt.args.proc, tt.args.arg, &result) 446 if !tt.wantErr(t, err, fmt.Sprintf("moLocksCall(%v, %v, %v)", tt.args.in0, tt.args.proc, tt.args.arg)) { 447 return 448 } 449 assert.Equalf(t, tt.want, got, "moLocksCall(%v, %v, %v)", tt.args.in0, tt.args.proc, tt.args.arg) 450 bat := result.Batch 451 assert.Equal(t, len(bat.Attrs), 3) 452 assert.Equal(t, bat.Attrs[0], "table_id") 453 assert.Equal(t, bat.Attrs[1], "lock_key") 454 assert.Equal(t, bat.Attrs[2], "lock_mode") 455 456 assert.Equal(t, vector.MustStrCol(bat.GetVector(0))[0], "1000") 457 assert.Equal(t, vector.MustStrCol(bat.GetVector(1))[0], "range") 458 assert.Equal(t, vector.MustStrCol(bat.GetVector(2))[0], "Exclusive") 459 }) 460 } 461 } 462 463 var _ logservice.CNHAKeeperClient = &mockHKClient{} 464 465 type mockHKClient struct { 466 } 467 468 func (m *mockHKClient) Close() error { 469 return nil 470 } 471 472 func (m *mockHKClient) AllocateID(ctx context.Context) (uint64, error) { 473 return 0, nil 474 } 475 476 func (m *mockHKClient) AllocateIDByKey(ctx context.Context, key string) (uint64, error) { 477 return 0, nil 478 } 479 480 func (m *mockHKClient) AllocateIDByKeyWithBatch(ctx context.Context, key string, batch uint64) (uint64, error) { 481 return 0, nil 482 } 483 484 func (m *mockHKClient) GetClusterDetails(ctx context.Context) (pb.ClusterDetails, error) { 485 cd := pb.ClusterDetails{ 486 CNStores: []pb.CNStore{ 487 { 488 ConfigData: &pb.ConfigData{ 489 Content: map[string]*pb.ConfigItem{ 490 "xxxx": { 491 Name: "xxxx", 492 CurrentValue: "123", 493 DefaultValue: "0", 494 }, 495 }, 496 }, 497 }, 498 }, 499 TNStores: []pb.TNStore{ 500 { 501 ConfigData: &pb.ConfigData{ 502 Content: map[string]*pb.ConfigItem{ 503 "xxxx": { 504 Name: "xxxx", 505 CurrentValue: "123", 506 DefaultValue: "0", 507 }, 508 }, 509 }, 510 }, 511 }, 512 LogStores: []pb.LogStore{ 513 { 514 ConfigData: &pb.ConfigData{ 515 Content: map[string]*pb.ConfigItem{ 516 "xxxx": { 517 Name: "xxxx", 518 CurrentValue: "123", 519 DefaultValue: "0", 520 }, 521 }, 522 }, 523 }, 524 }, 525 ProxyStores: []pb.ProxyStore{ 526 { 527 ConfigData: &pb.ConfigData{ 528 Content: map[string]*pb.ConfigItem{ 529 "xxxx": { 530 Name: "xxxx", 531 CurrentValue: "123", 532 DefaultValue: "0", 533 }, 534 }, 535 }, 536 }, 537 }, 538 } 539 540 return cd, nil 541 } 542 543 func (m *mockHKClient) GetClusterState(ctx context.Context) (pb.CheckerState, error) { 544 return pb.CheckerState{}, nil 545 } 546 547 func (m *mockHKClient) GetBackupData(ctx context.Context) ([]byte, error) { 548 return nil, nil 549 } 550 551 func (m *mockHKClient) SendCNHeartbeat(ctx context.Context, hb pb.CNStoreHeartbeat) (pb.CommandBatch, error) { 552 return pb.CommandBatch{}, nil 553 } 554 555 func Test_moConfigurationsCall(t *testing.T) { 556 mp, err := mpool.NewMPool("ut_pool", 0, mpool.NoFixed) 557 if err != nil { 558 assert.NoError(t, err) 559 } 560 defer mpool.DeleteMPool(mp) 561 testProc := process.New(context.Background(), mp, nil, nil, nil, nil, &mockQueryService{}, &mockHKClient{}, nil, nil) 562 563 type args struct { 564 in0 int 565 proc *process.Process 566 arg *Argument 567 } 568 tests := []struct { 569 name string 570 args args 571 want bool 572 wantErr assert.ErrorAssertionFunc 573 }{ 574 { 575 name: "t1", 576 args: args{ 577 proc: testProc, 578 arg: &Argument{ 579 ctr: &container{ 580 state: dataProducing, 581 executorsForArgs: nil, 582 }, 583 Rets: nil, 584 Args: nil, 585 Attrs: []string{ 586 "name", 587 "current_value", 588 "default_value", 589 }, 590 Params: nil, 591 FuncName: "", 592 retSchema: nil, 593 }, 594 }, 595 want: false, 596 wantErr: func(t assert.TestingT, err error, i ...interface{}) bool { 597 return true 598 }, 599 }, 600 } 601 for _, tt := range tests { 602 t.Run(tt.name, func(t *testing.T) { 603 result := vm.NewCallResult() 604 got, err := moConfigurationsCall(tt.args.in0, tt.args.proc, tt.args.arg, &result) 605 if !tt.wantErr(t, err, fmt.Sprintf("moConfigurationsCall(%v, %v, %v)", tt.args.in0, tt.args.proc, tt.args.arg)) { 606 return 607 } 608 assert.Equalf(t, tt.want, got, "moConfigurationsCall(%v, %v, %v)", tt.args.in0, tt.args.proc, tt.args.arg) 609 bat := result.Batch 610 assert.Equal(t, len(bat.Attrs), 3) 611 assert.Equal(t, bat.Attrs[0], "name") 612 assert.Equal(t, bat.Attrs[1], "current_value") 613 assert.Equal(t, bat.Attrs[2], "default_value") 614 615 for i := 0; i < 4; i++ { 616 assert.Equal(t, vector.MustStrCol(bat.GetVector(0))[i], "xxxx") 617 assert.Equal(t, vector.MustStrCol(bat.GetVector(1))[i], "123") 618 assert.Equal(t, vector.MustStrCol(bat.GetVector(2))[i], "0") 619 } 620 }) 621 } 622 }