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  }