github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/flowinfra/stream_data_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 flowinfra 12 13 import ( 14 "context" 15 "fmt" 16 "math/rand" 17 "testing" 18 19 "github.com/cockroachdb/cockroach/pkg/sql/execinfra" 20 "github.com/cockroachdb/cockroach/pkg/sql/execinfrapb" 21 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 22 "github.com/cockroachdb/cockroach/pkg/sql/types" 23 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 24 "github.com/cockroachdb/cockroach/pkg/util/randutil" 25 ) 26 27 // The encoder/decoder don't maintain the ordering between rows and metadata 28 // records. 29 func testGetDecodedRows( 30 tb testing.TB, 31 sd *StreamDecoder, 32 decodedRows sqlbase.EncDatumRows, 33 metas []execinfrapb.ProducerMetadata, 34 ) (sqlbase.EncDatumRows, []execinfrapb.ProducerMetadata) { 35 for { 36 row, meta, err := sd.GetRow(nil /* rowBuf */) 37 if err != nil { 38 tb.Fatal(err) 39 } 40 if row == nil && meta == nil { 41 break 42 } 43 if row != nil { 44 decodedRows = append(decodedRows, row) 45 } else { 46 metas = append(metas, *meta) 47 } 48 } 49 return decodedRows, metas 50 } 51 52 func testRowStream(tb testing.TB, rng *rand.Rand, types []*types.T, records []rowOrMeta) { 53 var se StreamEncoder 54 var sd StreamDecoder 55 56 var decodedRows sqlbase.EncDatumRows 57 var metas []execinfrapb.ProducerMetadata 58 numRows := 0 59 numMeta := 0 60 61 se.Init(types) 62 63 for rowIdx := 0; rowIdx <= len(records); rowIdx++ { 64 if rowIdx < len(records) { 65 if records[rowIdx].row != nil { 66 if err := se.AddRow(records[rowIdx].row); err != nil { 67 tb.Fatal(err) 68 } 69 numRows++ 70 } else { 71 se.AddMetadata(context.Background(), records[rowIdx].meta) 72 numMeta++ 73 } 74 } 75 // "Send" a message every now and then and once at the end. 76 final := (rowIdx == len(records)) 77 if final || (rowIdx > 0 && rng.Intn(10) == 0) { 78 msg := se.FormMessage(context.Background()) 79 // Make a copy of the data buffer. 80 msg.Data.RawBytes = append([]byte(nil), msg.Data.RawBytes...) 81 err := sd.AddMessage(context.Background(), msg) 82 if err != nil { 83 tb.Fatal(err) 84 } 85 decodedRows, metas = testGetDecodedRows(tb, &sd, decodedRows, metas) 86 } 87 } 88 if len(metas) != numMeta { 89 tb.Errorf("expected %d metadata records, got: %d", numMeta, len(metas)) 90 } 91 if len(decodedRows) != numRows { 92 tb.Errorf("expected %d rows, got: %d", numRows, len(decodedRows)) 93 } 94 } 95 96 type rowOrMeta struct { 97 row sqlbase.EncDatumRow 98 meta execinfrapb.ProducerMetadata 99 } 100 101 // TestStreamEncodeDecode generates random streams of EncDatums and passes them 102 // through a StreamEncoder and a StreamDecoder 103 func TestStreamEncodeDecode(t *testing.T) { 104 defer leaktest.AfterTest(t)() 105 rng, _ := randutil.NewPseudoRand() 106 for test := 0; test < 100; test++ { 107 rowLen := rng.Intn(20) 108 types := sqlbase.RandEncodableColumnTypes(rng, rowLen) 109 info := make([]execinfrapb.DatumInfo, rowLen) 110 for i := range info { 111 info[i].Type = types[i] 112 info[i].Encoding = sqlbase.RandDatumEncoding(rng) 113 } 114 numRows := rng.Intn(100) 115 rows := make([]rowOrMeta, numRows) 116 for i := range rows { 117 if rng.Intn(10) != 0 { 118 rows[i].row = make(sqlbase.EncDatumRow, rowLen) 119 for j := range rows[i].row { 120 rows[i].row[j] = sqlbase.DatumToEncDatum(info[j].Type, 121 sqlbase.RandDatum(rng, info[j].Type, true)) 122 } 123 } else { 124 rows[i].meta.Err = fmt.Errorf("test error %d", i) 125 } 126 } 127 testRowStream(t, rng, types, rows) 128 } 129 } 130 131 func TestEmptyStreamEncodeDecode(t *testing.T) { 132 defer leaktest.AfterTest(t)() 133 var se StreamEncoder 134 var sd StreamDecoder 135 msg := se.FormMessage(context.Background()) 136 if err := sd.AddMessage(context.Background(), msg); err != nil { 137 t.Fatal(err) 138 } 139 if msg.Header == nil { 140 t.Errorf("no header in first message") 141 } 142 if row, meta, err := sd.GetRow(nil /* rowBuf */); err != nil { 143 t.Fatal(err) 144 } else if meta != nil || row != nil { 145 t.Errorf("received bogus row %v %v", row, meta) 146 } 147 } 148 149 func BenchmarkStreamEncoder(b *testing.B) { 150 numRows := 1 << 16 151 152 for _, numCols := range []int{1, 4, 16, 64} { 153 b.Run(fmt.Sprintf("rows=%d,cols=%d", numRows, numCols), func(b *testing.B) { 154 b.SetBytes(int64(numRows * numCols * 8)) 155 cols := sqlbase.MakeIntCols(numCols) 156 rows := sqlbase.MakeIntRows(numRows, numCols) 157 input := execinfra.NewRepeatableRowSource(cols, rows) 158 159 b.ResetTimer() 160 ctx := context.Background() 161 162 for i := 0; i < b.N; i++ { 163 b.StopTimer() 164 input.Reset() 165 // Reset the EncDatums' encoded bytes cache. 166 for _, row := range rows { 167 for j := range row { 168 row[j] = sqlbase.EncDatum{ 169 Datum: row[j].Datum, 170 } 171 } 172 } 173 var se StreamEncoder 174 se.Init(cols) 175 b.StartTimer() 176 177 // Add rows to the StreamEncoder until the input source is exhausted. 178 // "Flush" every outboxBufRows. 179 for j := 0; ; j++ { 180 row, _ := input.Next() 181 if row == nil { 182 break 183 } 184 if err := se.AddRow(row); err != nil { 185 b.Fatal(err) 186 } 187 if j%outboxBufRows == 0 { 188 // ignore output 189 se.FormMessage(ctx) 190 } 191 } 192 } 193 }) 194 } 195 } 196 197 func BenchmarkStreamDecoder(b *testing.B) { 198 ctx := context.Background() 199 200 for _, numCols := range []int{1, 4, 16, 64} { 201 b.Run(fmt.Sprintf("cols=%d", numCols), func(b *testing.B) { 202 b.SetBytes(int64(outboxBufRows * numCols * 8)) 203 var se StreamEncoder 204 colTypes := sqlbase.MakeIntCols(numCols) 205 se.Init(colTypes) 206 inRow := sqlbase.MakeIntRows(1, numCols)[0] 207 for i := 0; i < outboxBufRows; i++ { 208 if err := se.AddRow(inRow); err != nil { 209 b.Fatal(err) 210 } 211 } 212 msg := se.FormMessage(ctx) 213 214 for i := 0; i < b.N; i++ { 215 var sd StreamDecoder 216 if err := sd.AddMessage(ctx, msg); err != nil { 217 b.Fatal(err) 218 } 219 for j := 0; j < outboxBufRows; j++ { 220 row, meta, err := sd.GetRow(nil) 221 if err != nil { 222 b.Fatal(err) 223 } 224 if row == nil && meta == nil { 225 break 226 } 227 } 228 } 229 }) 230 } 231 }