github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/colexec/product/product_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 product 16 17 import ( 18 "bytes" 19 "context" 20 "testing" 21 22 "github.com/matrixorigin/matrixone/pkg/common/mpool" 23 "github.com/matrixorigin/matrixone/pkg/container/batch" 24 "github.com/matrixorigin/matrixone/pkg/container/types" 25 "github.com/matrixorigin/matrixone/pkg/sql/colexec" 26 "github.com/matrixorigin/matrixone/pkg/sql/colexec/hashbuild" 27 "github.com/matrixorigin/matrixone/pkg/testutil" 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 productTestCase struct { 39 arg *Argument 40 flgs []bool // flgs[i] == true: nullable 41 types []types.Type 42 proc *process.Process 43 cancel context.CancelFunc 44 barg *hashbuild.Argument 45 } 46 47 var ( 48 tcs []productTestCase 49 ) 50 51 func init() { 52 tcs = []productTestCase{ 53 newTestCase([]bool{false}, []types.Type{{Oid: types.T_int8}}, []colexec.ResultPos{colexec.NewResultPos(0, 0), colexec.NewResultPos(1, 0)}), 54 newTestCase([]bool{true}, []types.Type{{Oid: types.T_int8}}, []colexec.ResultPos{colexec.NewResultPos(0, 0), colexec.NewResultPos(1, 0)}), 55 } 56 } 57 58 func TestString(t *testing.T) { 59 buf := new(bytes.Buffer) 60 for _, tc := range tcs { 61 String(tc.arg, buf) 62 } 63 } 64 65 func TestPrepare(t *testing.T) { 66 for _, tc := range tcs { 67 err := Prepare(tc.proc, tc.arg) 68 require.NoError(t, err) 69 } 70 } 71 72 func TestProduct(t *testing.T) { 73 for _, tc := range tcs { 74 bat := hashBuild(t, tc) 75 err := Prepare(tc.proc, tc.arg) 76 require.NoError(t, err) 77 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 78 tc.proc.Reg.MergeReceivers[0].Ch <- &batch.Batch{} 79 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 80 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 81 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 82 tc.proc.Reg.MergeReceivers[0].Ch <- nil 83 tc.proc.Reg.MergeReceivers[1].Ch <- bat 84 for { 85 if ok, err := Call(0, tc.proc, tc.arg, false, false); ok || err != nil { 86 break 87 } 88 tc.proc.Reg.InputBatch.Clean(tc.proc.Mp()) 89 } 90 require.Equal(t, int64(0), tc.proc.Mp().CurrNB()) 91 } 92 } 93 94 func BenchmarkProduct(b *testing.B) { 95 for i := 0; i < b.N; i++ { 96 tcs = []productTestCase{ 97 newTestCase([]bool{false}, []types.Type{{Oid: types.T_int8}}, []colexec.ResultPos{colexec.NewResultPos(0, 0), colexec.NewResultPos(1, 0)}), 98 newTestCase([]bool{true}, []types.Type{{Oid: types.T_int8}}, []colexec.ResultPos{colexec.NewResultPos(0, 0), colexec.NewResultPos(1, 0)}), 99 } 100 t := new(testing.T) 101 for _, tc := range tcs { 102 bat := hashBuild(t, tc) 103 err := Prepare(tc.proc, tc.arg) 104 require.NoError(t, err) 105 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 106 tc.proc.Reg.MergeReceivers[0].Ch <- &batch.Batch{} 107 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 108 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 109 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 110 tc.proc.Reg.MergeReceivers[0].Ch <- nil 111 tc.proc.Reg.MergeReceivers[1].Ch <- bat 112 for { 113 if ok, err := Call(0, tc.proc, tc.arg, false, false); ok || err != nil { 114 break 115 } 116 tc.proc.Reg.InputBatch.Clean(tc.proc.Mp()) 117 } 118 } 119 } 120 } 121 122 func newTestCase(flgs []bool, ts []types.Type, rp []colexec.ResultPos) productTestCase { 123 proc := testutil.NewProcessWithMPool(mpool.MustNewZero()) 124 proc.Reg.MergeReceivers = make([]*process.WaitRegister, 2) 125 ctx, cancel := context.WithCancel(context.Background()) 126 proc.Reg.MergeReceivers[0] = &process.WaitRegister{ 127 Ctx: ctx, 128 Ch: make(chan *batch.Batch, 10), 129 } 130 proc.Reg.MergeReceivers[1] = &process.WaitRegister{ 131 Ctx: ctx, 132 Ch: make(chan *batch.Batch, 4), 133 } 134 return productTestCase{ 135 types: ts, 136 flgs: flgs, 137 proc: proc, 138 cancel: cancel, 139 arg: &Argument{ 140 Typs: ts, 141 Result: rp, 142 }, 143 barg: &hashbuild.Argument{ 144 Typs: ts, 145 }, 146 } 147 } 148 149 func hashBuild(t *testing.T, tc productTestCase) *batch.Batch { 150 err := hashbuild.Prepare(tc.proc, tc.barg) 151 require.NoError(t, err) 152 tc.proc.Reg.MergeReceivers[0].Ch <- newBatch(t, tc.flgs, tc.types, tc.proc, Rows) 153 tc.proc.Reg.MergeReceivers[0].Ch <- nil 154 ok, err := hashbuild.Call(0, tc.proc, tc.barg, false, false) 155 require.NoError(t, err) 156 require.Equal(t, true, ok) 157 return tc.proc.Reg.InputBatch 158 } 159 160 // create a new block based on the type information, flgs[i] == ture: has null 161 func newBatch(t *testing.T, flgs []bool, ts []types.Type, proc *process.Process, rows int64) *batch.Batch { 162 return testutil.NewBatch(ts, false, int(rows), proc.Mp()) 163 }