github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/colexec/hashbuild/build_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 hashbuild 16 17 import ( 18 "bytes" 19 "context" 20 "testing" 21 22 "github.com/matrixorigin/matrixone/pkg/common/hashmap" 23 "github.com/matrixorigin/matrixone/pkg/common/mpool" 24 "github.com/matrixorigin/matrixone/pkg/container/batch" 25 "github.com/matrixorigin/matrixone/pkg/container/types" 26 "github.com/matrixorigin/matrixone/pkg/pb/plan" 27 "github.com/matrixorigin/matrixone/pkg/testutil" 28 "github.com/matrixorigin/matrixone/pkg/vm" 29 "github.com/matrixorigin/matrixone/pkg/vm/process" 30 "github.com/stretchr/testify/require" 31 ) 32 33 const ( 34 Rows = 10 // default rows 35 BenchmarkRows = 100000 // default rows for benchmark 36 ) 37 38 // add unit tests for cases 39 type buildTestCase struct { 40 arg *Argument 41 flgs []bool // flgs[i] == true: nullable 42 types []types.Type 43 proc *process.Process 44 cancel context.CancelFunc 45 } 46 47 var ( 48 tcs []buildTestCase 49 ) 50 51 func init() { 52 tcs = []buildTestCase{ 53 newTestCase([]bool{false}, []types.Type{types.T_int8.ToType()}, 54 []*plan.Expr{ 55 newExpr(0, types.T_int8.ToType()), 56 }), 57 newTestCase([]bool{true}, []types.Type{types.T_int8.ToType()}, 58 []*plan.Expr{ 59 newExpr(0, types.T_int8.ToType()), 60 }), 61 } 62 } 63 64 func TestString(t *testing.T) { 65 buf := new(bytes.Buffer) 66 for _, tc := range tcs { 67 tc.arg.String(buf) 68 } 69 } 70 71 func TestBuild(t *testing.T) { 72 for _, tc := range tcs[:1] { 73 err := tc.arg.Prepare(tc.proc) 74 require.NoError(t, err) 75 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(tc.types, tc.proc, Rows) 76 tc.proc.Reg.MergeReceivers[0].Ch <- batch.EmptyBatch 77 tc.proc.Reg.MergeReceivers[0].Ch <- nil 78 for { 79 ok, err := tc.arg.Call(tc.proc) 80 require.NoError(t, err) 81 require.Equal(t, false, ok.Status == vm.ExecStop) 82 mp := ok.Batch.AuxData.(*hashmap.JoinMap) 83 tc.proc.Reg.MergeReceivers[0].Ch <- nil 84 mp.Free() 85 ok.Batch.Clean(tc.proc.Mp()) 86 break 87 } 88 tc.proc.Reg.MergeReceivers[0].Ch <- nil 89 tc.arg.Free(tc.proc, false, nil) 90 tc.proc.FreeVectors() 91 require.Equal(t, int64(0), tc.proc.Mp().CurrNB()) 92 } 93 } 94 95 func BenchmarkBuild(b *testing.B) { 96 for i := 0; i < b.N; i++ { 97 tcs = []buildTestCase{ 98 newTestCase([]bool{false}, []types.Type{types.T_int8.ToType()}, 99 []*plan.Expr{ 100 newExpr(0, types.T_int8.ToType()), 101 }), 102 } 103 t := new(testing.T) 104 for _, tc := range tcs { 105 err := tc.arg.Prepare(tc.proc) 106 require.NoError(t, err) 107 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(tc.types, tc.proc, Rows) 108 tc.proc.Reg.MergeReceivers[0].Ch <- batch.EmptyBatch 109 tc.proc.Reg.MergeReceivers[0].Ch <- nil 110 for { 111 ok, err := tc.arg.Call(tc.proc) 112 require.NoError(t, err) 113 require.Equal(t, true, ok) 114 mp := ok.Batch.AuxData.(*hashmap.JoinMap) 115 tc.proc.Reg.MergeReceivers[0].Ch <- nil 116 mp.Free() 117 ok.Batch.Clean(tc.proc.Mp()) 118 break 119 } 120 } 121 } 122 } 123 124 func newExpr(pos int32, typ types.Type) *plan.Expr { 125 return &plan.Expr{ 126 Typ: plan.Type{ 127 Id: int32(typ.Oid), 128 Width: typ.Width, 129 Scale: typ.Scale, 130 }, 131 Expr: &plan.Expr_Col{ 132 Col: &plan.ColRef{ 133 ColPos: pos, 134 }, 135 }, 136 } 137 } 138 139 func newTestCase(flgs []bool, ts []types.Type, cs []*plan.Expr) buildTestCase { 140 proc := testutil.NewProcessWithMPool(mpool.MustNewZero()) 141 proc.Reg.MergeReceivers = make([]*process.WaitRegister, 1) 142 ctx, cancel := context.WithCancel(context.Background()) 143 proc.Reg.MergeReceivers[0] = &process.WaitRegister{ 144 Ctx: ctx, 145 Ch: make(chan *batch.Batch, 10), 146 } 147 return buildTestCase{ 148 types: ts, 149 flgs: flgs, 150 proc: proc, 151 cancel: cancel, 152 arg: &Argument{ 153 Typs: ts, 154 Conditions: cs, 155 NeedHashMap: true, 156 OperatorBase: vm.OperatorBase{ 157 OperatorInfo: vm.OperatorInfo{ 158 Idx: 0, 159 IsFirst: false, 160 IsLast: false, 161 }, 162 }, 163 }, 164 } 165 } 166 167 // create a new block based on the type information, flgs[i] == ture: has null 168 func newBatch(ts []types.Type, proc *process.Process, rows int64) *batch.Batch { 169 return testutil.NewBatch(ts, false, int(rows), proc.Mp()) 170 }