github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/colexec/ordered_synchronizer_test.go (about)

     1  // Copyright 2019 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 colexec
    12  
    13  import (
    14  	"context"
    15  	"math/rand"
    16  	"sort"
    17  	"testing"
    18  
    19  	"github.com/cockroachdb/cockroach/pkg/col/coldata"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/colexecbase"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    22  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    23  	"github.com/cockroachdb/cockroach/pkg/util/encoding"
    24  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    25  	"github.com/stretchr/testify/require"
    26  )
    27  
    28  // Adapted from the same-named test in the rowflow package.
    29  func TestOrderedSync(t *testing.T) {
    30  	defer leaktest.AfterTest(t)()
    31  	testCases := []struct {
    32  		sources  []tuples
    33  		ordering sqlbase.ColumnOrdering
    34  		expected tuples
    35  	}{
    36  		{
    37  			sources: []tuples{
    38  				{
    39  					{0, 1, 4},
    40  					{0, 1, 2},
    41  					{0, 2, 3},
    42  					{1, 1, 3},
    43  				},
    44  				{
    45  					{1, 0, 4},
    46  				},
    47  				{
    48  					{0, 0, 0},
    49  					{4, 4, 4},
    50  				},
    51  			},
    52  			ordering: sqlbase.ColumnOrdering{
    53  				{ColIdx: 0, Direction: encoding.Ascending},
    54  				{ColIdx: 1, Direction: encoding.Ascending},
    55  			},
    56  			expected: tuples{
    57  				{0, 0, 0},
    58  				{0, 1, 4},
    59  				{0, 1, 2},
    60  				{0, 2, 3},
    61  				{1, 0, 4},
    62  				{1, 1, 3},
    63  				{4, 4, 4},
    64  			},
    65  		},
    66  		{
    67  			sources: []tuples{
    68  				{
    69  					{1, 0, 4},
    70  				},
    71  				{
    72  					{3, 4, 1},
    73  					{4, 4, 4},
    74  					{3, 2, 0},
    75  				},
    76  				{
    77  					{4, 4, 5},
    78  					{3, 3, 0},
    79  					{0, 0, 0},
    80  				},
    81  			},
    82  			ordering: sqlbase.ColumnOrdering{
    83  				{ColIdx: 1, Direction: encoding.Descending},
    84  				{ColIdx: 0, Direction: encoding.Ascending},
    85  				{ColIdx: 2, Direction: encoding.Ascending},
    86  			},
    87  			expected: tuples{
    88  				{3, 4, 1},
    89  				{4, 4, 4},
    90  				{4, 4, 5},
    91  				{3, 3, 0},
    92  				{3, 2, 0},
    93  				{0, 0, 0},
    94  				{1, 0, 4},
    95  			},
    96  		},
    97  		{
    98  			sources: []tuples{
    99  				{
   100  					{-1},
   101  				},
   102  				{
   103  					{1},
   104  				},
   105  				{
   106  					{nil},
   107  				},
   108  			},
   109  			ordering: sqlbase.ColumnOrdering{
   110  				{ColIdx: 0, Direction: encoding.Ascending},
   111  			},
   112  			expected: tuples{
   113  				{nil},
   114  				{-1},
   115  				{1},
   116  			},
   117  		},
   118  		{
   119  			sources: []tuples{
   120  				{
   121  					{-1},
   122  				},
   123  				{
   124  					{1},
   125  				},
   126  				{
   127  					{nil},
   128  				},
   129  			},
   130  			ordering: sqlbase.ColumnOrdering{
   131  				{ColIdx: 0, Direction: encoding.Descending},
   132  			},
   133  			expected: tuples{
   134  				{1},
   135  				{-1},
   136  				{nil},
   137  			},
   138  		},
   139  	}
   140  	for _, tc := range testCases {
   141  		numCols := len(tc.sources[0][0])
   142  		typs := make([]*types.T, numCols)
   143  		for i := range typs {
   144  			typs[i] = types.Int
   145  		}
   146  		runTests(t, tc.sources, tc.expected, orderedVerifier, func(inputs []colexecbase.Operator) (colexecbase.Operator, error) {
   147  			return NewOrderedSynchronizer(testAllocator, inputs, typs, tc.ordering)
   148  		})
   149  	}
   150  }
   151  
   152  func TestOrderedSyncRandomInput(t *testing.T) {
   153  	defer leaktest.AfterTest(t)()
   154  	numInputs := 3
   155  	inputLen := 1024
   156  	batchSize := 16
   157  	if batchSize > coldata.BatchSize() {
   158  		batchSize = coldata.BatchSize()
   159  	}
   160  	typs := []*types.T{types.Int}
   161  
   162  	// Generate a random slice of sorted ints.
   163  	randInts := make([]int, inputLen)
   164  	for i := range randInts {
   165  		randInts[i] = rand.Int()
   166  	}
   167  	sort.Ints(randInts)
   168  
   169  	// Randomly distribute them among the inputs.
   170  	expected := make(tuples, inputLen)
   171  	sources := make([]tuples, numInputs)
   172  	for i := range expected {
   173  		t := tuple{randInts[i]}
   174  		expected[i] = t
   175  		sourceIdx := rand.Int() % 3
   176  		if i < numInputs {
   177  			// Make sure each input has at least one row.
   178  			sourceIdx = i
   179  		}
   180  		sources[sourceIdx] = append(sources[sourceIdx], t)
   181  	}
   182  	inputs := make([]colexecbase.Operator, numInputs)
   183  	for i := range inputs {
   184  		inputs[i] = newOpTestInput(batchSize, sources[i], typs)
   185  	}
   186  	ordering := sqlbase.ColumnOrdering{{ColIdx: 0, Direction: encoding.Ascending}}
   187  	op, err := NewOrderedSynchronizer(testAllocator, inputs, typs, ordering)
   188  	require.NoError(t, err)
   189  	op.Init()
   190  	out := newOpTestOutput(op, expected)
   191  	if err := out.Verify(); err != nil {
   192  		t.Error(err)
   193  	}
   194  }
   195  
   196  func BenchmarkOrderedSynchronizer(b *testing.B) {
   197  	ctx := context.Background()
   198  
   199  	numInputs := int64(3)
   200  	typs := []*types.T{types.Int}
   201  	batches := make([]coldata.Batch, numInputs)
   202  	for i := range batches {
   203  		batches[i] = testAllocator.NewMemBatch(typs)
   204  		batches[i].SetLength(coldata.BatchSize())
   205  	}
   206  	for i := int64(0); i < int64(coldata.BatchSize())*numInputs; i++ {
   207  		batch := batches[i%numInputs]
   208  		batch.ColVec(0).Int64()[i/numInputs] = i
   209  	}
   210  
   211  	inputs := make([]colexecbase.Operator, len(batches))
   212  	for i := range batches {
   213  		inputs[i] = colexecbase.NewRepeatableBatchSource(testAllocator, batches[i], typs)
   214  	}
   215  
   216  	ordering := sqlbase.ColumnOrdering{{ColIdx: 0, Direction: encoding.Ascending}}
   217  	op, err := NewOrderedSynchronizer(testAllocator, inputs, typs, ordering)
   218  	require.NoError(b, err)
   219  	op.Init()
   220  
   221  	b.SetBytes(8 * int64(coldata.BatchSize()) * numInputs)
   222  	b.ResetTimer()
   223  	for i := 0; i < b.N; i++ {
   224  		op.Next(ctx)
   225  	}
   226  }