github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/rowcontainer/datum_row_container_test.go (about) 1 // Copyright 2016 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package rowcontainer 12 13 import ( 14 "context" 15 "math" 16 "testing" 17 18 "github.com/cockroachdb/cockroach/pkg/settings/cluster" 19 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 20 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 21 "github.com/cockroachdb/cockroach/pkg/sql/types" 22 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 23 "github.com/cockroachdb/cockroach/pkg/util/mon" 24 ) 25 26 func TestRowContainer(t *testing.T) { 27 defer leaktest.AfterTest(t)() 28 29 for _, numCols := range []int{0, 1, 2, 3, 5, 10, 15} { 30 for _, numRows := range []int{5, 10, 100} { 31 for _, numPops := range []int{0, 1, 2, numRows / 3, numRows / 2} { 32 resCol := make(sqlbase.ResultColumns, numCols) 33 for i := range resCol { 34 resCol[i] = sqlbase.ResultColumn{Typ: types.Int} 35 } 36 st := cluster.MakeTestingClusterSettings() 37 m := mon.MakeUnlimitedMonitor( 38 context.Background(), "test", mon.MemoryResource, nil, nil, math.MaxInt64, st, 39 ) 40 rc := NewRowContainer(m.MakeBoundAccount(), sqlbase.ColTypeInfoFromResCols(resCol), 0) 41 row := make(tree.Datums, numCols) 42 for i := 0; i < numRows; i++ { 43 for j := range row { 44 row[j] = tree.NewDInt(tree.DInt(i*numCols + j)) 45 } 46 if _, err := rc.AddRow(context.Background(), row); err != nil { 47 t.Fatal(err) 48 } 49 } 50 51 for i := 0; i < numPops; i++ { 52 rc.PopFirst() 53 } 54 55 // Given that we just deleted numPops rows, we have numRows - 56 // numPops rows remaining. 57 if rc.Len() != numRows-numPops { 58 t.Fatalf("invalid length, expected %d got %d", numRows-numPops, rc.Len()) 59 } 60 61 // what was previously rc.At(i + numPops) is now rc.At(i). 62 for i := 0; i < rc.Len(); i++ { 63 row := rc.At(i) 64 for j := range row { 65 dint, ok := tree.AsDInt(row[j]) 66 if !ok || int(dint) != (i+numPops)*numCols+j { 67 t.Fatalf("invalid value %+v on row %d, col %d", row[j], i+numPops, j) 68 } 69 } 70 } 71 rc.Close(context.Background()) 72 m.Stop(context.Background()) 73 } 74 } 75 } 76 } 77 78 func TestRowContainerAtOutOfRange(t *testing.T) { 79 defer leaktest.AfterTest(t)() 80 81 ctx := context.Background() 82 st := cluster.MakeTestingClusterSettings() 83 m := mon.MakeUnlimitedMonitor(ctx, "test", mon.MemoryResource, nil, nil, math.MaxInt64, st) 84 defer m.Stop(ctx) 85 86 resCols := sqlbase.ResultColumns{sqlbase.ResultColumn{Typ: types.Int}} 87 rc := NewRowContainer(m.MakeBoundAccount(), sqlbase.ColTypeInfoFromResCols(resCols), 0) 88 defer rc.Close(ctx) 89 90 // Verify that a panic is thrown for out-of-range conditions. 91 for _, i := range []int{-1, 0} { 92 var p interface{} 93 func() { 94 defer func() { 95 p = recover() 96 }() 97 rc.At(i) 98 }() 99 if p == nil { 100 t.Fatalf("%d: expected panic, but found success", i) 101 } 102 } 103 } 104 105 func TestRowContainerZeroCols(t *testing.T) { 106 defer leaktest.AfterTest(t)() 107 108 ctx := context.Background() 109 st := cluster.MakeTestingClusterSettings() 110 m := mon.MakeUnlimitedMonitor(ctx, "test", mon.MemoryResource, nil, nil, math.MaxInt64, st) 111 defer m.Stop(ctx) 112 113 rc := NewRowContainer(m.MakeBoundAccount(), sqlbase.ColTypeInfoFromResCols(nil), 0) 114 defer rc.Close(ctx) 115 116 const numRows = 10 117 for i := 0; i < numRows; i++ { 118 if _, err := rc.AddRow(context.Background(), nil); err != nil { 119 t.Fatal(err) 120 } 121 } 122 if rc.Len() != numRows { 123 t.Fatalf("expected %d rows, but found %d", numRows, rc.Len()) 124 } 125 row := rc.At(0) 126 if row == nil { 127 t.Fatalf("expected non-nil row") 128 } 129 if len(row) != 0 { 130 t.Fatalf("expected empty row") 131 } 132 } 133 134 func BenchmarkRowContainerAt(b *testing.B) { 135 const numCols = 3 136 const numRows = 1024 137 138 st := cluster.MakeTestingClusterSettings() 139 m := mon.MakeUnlimitedMonitor( 140 context.Background(), "test", mon.MemoryResource, nil, nil, math.MaxInt64, st, 141 ) 142 defer m.Stop(context.Background()) 143 144 resCol := make(sqlbase.ResultColumns, numCols) 145 for i := range resCol { 146 resCol[i] = sqlbase.ResultColumn{Typ: types.Int} 147 } 148 149 rc := NewRowContainer(m.MakeBoundAccount(), sqlbase.ColTypeInfoFromResCols(resCol), 0) 150 defer rc.Close(context.Background()) 151 152 row := make(tree.Datums, numCols) 153 for i := 0; i < numRows; i++ { 154 for j := range row { 155 row[j] = tree.NewDInt(tree.DInt(i*numCols + j)) 156 } 157 if _, err := rc.AddRow(context.Background(), row); err != nil { 158 b.Fatal(err) 159 } 160 } 161 162 b.ResetTimer() 163 for i := 0; i < b.N; i++ { 164 _ = rc.At(i & (numRows - 1)) 165 } 166 b.StopTimer() 167 }