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  }