github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/colexec/top/top_test.go (about)

     1  // Copyright 2021 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 top
    16  
    17  import (
    18  	"bytes"
    19  	"testing"
    20  
    21  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    22  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    23  	"github.com/matrixorigin/matrixone/pkg/container/types"
    24  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    25  	"github.com/matrixorigin/matrixone/pkg/sql/colexec/value_scan"
    26  	"github.com/matrixorigin/matrixone/pkg/testutil"
    27  	"github.com/matrixorigin/matrixone/pkg/vm"
    28  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  const (
    33  	Rows          = 10     // default rows
    34  	BenchmarkRows = 100000 // default rows for benchmark
    35  )
    36  
    37  // add unit tests for cases
    38  type topTestCase struct {
    39  	arg   *Argument
    40  	types []types.Type
    41  	proc  *process.Process
    42  }
    43  
    44  var (
    45  	tcs []topTestCase
    46  )
    47  
    48  func init() {
    49  	tcs = []topTestCase{
    50  		newTestCase(mpool.MustNewZero(), []types.Type{types.T_int8.ToType()}, 3, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 0}}),
    51  		newTestCase(mpool.MustNewZero(), []types.Type{types.T_int8.ToType()}, 3, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 2}}),
    52  		newTestCase(mpool.MustNewZero(), []types.Type{types.T_int8.ToType(), types.T_int64.ToType()}, 3, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 2}, {Expr: newExpression(1), Flag: 0}}),
    53  	}
    54  }
    55  
    56  func TestString(t *testing.T) {
    57  	buf := new(bytes.Buffer)
    58  	for _, tc := range tcs {
    59  		tc.arg.String(buf)
    60  	}
    61  }
    62  
    63  func TestPrepare(t *testing.T) {
    64  	for _, tc := range tcs {
    65  		err := tc.arg.Prepare(tc.proc)
    66  		require.NoError(t, err)
    67  	}
    68  }
    69  
    70  func TestTop(t *testing.T) {
    71  	for _, tc := range tcs {
    72  		err := tc.arg.Prepare(tc.proc)
    73  		require.NoError(t, err)
    74  
    75  		bats := []*batch.Batch{
    76  			newBatch(tc.types, tc.proc, Rows),
    77  			newBatch(tc.types, tc.proc, Rows),
    78  			batch.EmptyBatch,
    79  		}
    80  		resetChildren(tc.arg, bats)
    81  		_, _ = tc.arg.Call(tc.proc)
    82  		tc.proc.FreeVectors()
    83  		tc.arg.Free(tc.proc, false, nil)
    84  		tc.arg.GetChildren(0).Free(tc.proc, false, nil)
    85  		require.Equal(t, int64(0), tc.proc.Mp().CurrNB())
    86  	}
    87  }
    88  
    89  func BenchmarkTop(b *testing.B) {
    90  	for i := 0; i < b.N; i++ {
    91  		tcs = []topTestCase{
    92  			newTestCase(mpool.MustNewZero(), []types.Type{types.T_int8.ToType()}, 3, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 0}}),
    93  			newTestCase(mpool.MustNewZero(), []types.Type{types.T_int8.ToType()}, 3, []*plan.OrderBySpec{{Expr: newExpression(0), Flag: 2}}),
    94  		}
    95  		t := new(testing.T)
    96  		for _, tc := range tcs {
    97  			err := tc.arg.Prepare(tc.proc)
    98  			require.NoError(t, err)
    99  
   100  			bats := []*batch.Batch{
   101  				newBatch(tc.types, tc.proc, BenchmarkRows),
   102  				newBatch(tc.types, tc.proc, BenchmarkRows),
   103  				batch.EmptyBatch,
   104  			}
   105  			resetChildren(tc.arg, bats)
   106  			_, _ = tc.arg.Call(tc.proc)
   107  			tc.arg.Free(tc.proc, false, nil)
   108  			tc.arg.GetChildren(0).Free(tc.proc, false, nil)
   109  		}
   110  	}
   111  }
   112  
   113  func newTestCase(m *mpool.MPool, ts []types.Type, limit int64, fs []*plan.OrderBySpec) topTestCase {
   114  	return topTestCase{
   115  		types: ts,
   116  		proc:  testutil.NewProcessWithMPool(m),
   117  		arg: &Argument{
   118  			Fs:    fs,
   119  			Limit: limit,
   120  			OperatorBase: vm.OperatorBase{
   121  				OperatorInfo: vm.OperatorInfo{
   122  					Idx:     0,
   123  					IsFirst: false,
   124  					IsLast:  false,
   125  				},
   126  			},
   127  		},
   128  	}
   129  }
   130  
   131  func newExpression(pos int32) *plan.Expr {
   132  	return &plan.Expr{
   133  		Expr: &plan.Expr_Col{
   134  			Col: &plan.ColRef{
   135  				ColPos: pos,
   136  			},
   137  		},
   138  		Typ: plan.Type{},
   139  	}
   140  }
   141  
   142  // create a new block based on the type information
   143  func newBatch(ts []types.Type, proc *process.Process, rows int64) *batch.Batch {
   144  	return testutil.NewBatch(ts, false, int(rows), proc.Mp())
   145  }
   146  
   147  func resetChildren(arg *Argument, bats []*batch.Batch) {
   148  	arg.SetChildren(
   149  		[]vm.Operator{
   150  			&value_scan.Argument{
   151  				Batchs: bats,
   152  			},
   153  		})
   154  }