func TestHashRouter(t *testing.T) { defer leaktest.AfterTest(t)() const numCols = 6 const numRows = 200 rng, _ := randutil.NewPseudoRand() alloc := &sqlbase.DatumAlloc{} // Generate tables of possible values for each column; we have fewer possible // values than rows to guarantee many occurrences of each value. vals := sqlbase.RandEncDatumSlices(rng, numCols, numRows/10) testCases := []struct { hashColumns []uint32 numBuckets int }{ {[]uint32{0}, 2}, {[]uint32{3}, 4}, {[]uint32{1, 3}, 4}, {[]uint32{5, 2}, 3}, {[]uint32{0, 1, 2, 3, 4}, 5}, } for _, tc := range testCases { bufs := make([]*RowBuffer, tc.numBuckets) recvs := make([]RowReceiver, tc.numBuckets) for i := 0; i < tc.numBuckets; i++ { bufs[i] = &RowBuffer{} recvs[i] = bufs[i] } hr, err := makeHashRouter(tc.hashColumns, recvs) if err != nil { t.Fatal(err) } for i := 0; i < numRows; i++ { row := make(sqlbase.EncDatumRow, numCols) for j := 0; j < numCols; j++ { row[j] = vals[j][rng.Intn(len(vals[j]))] } ok := hr.PushRow(row) if !ok { t.Fatalf("PushRow returned false") } } hr.Close(nil) for bIdx, b := range bufs { if !b.closed { t.Errorf("bucket not closed") } if b.err != nil { t.Error(b.err) } for _, row := range b.rows { // Verify there are no rows that // - have the same values with this row on all the hashColumns, and // - ended up in a different bucket for b2Idx, b2 := range bufs { if b2Idx == bIdx { continue } for _, row2 := range b2.rows { equal := true for _, c := range tc.hashColumns { cmp, err := row[c].Compare(alloc, &row2[c]) if err != nil { t.Fatal(err) } if cmp != 0 { equal = false break } } if equal { t.Errorf("rows %s and %s in different buckets", row, row2) } } } } } } }
func TestMirrorRouter(t *testing.T) { defer leaktest.AfterTest(t)() const numCols = 6 const numRows = 20 rng, _ := randutil.NewPseudoRand() alloc := &sqlbase.DatumAlloc{} vals := sqlbase.RandEncDatumSlices(rng, numCols, numRows) for numBuckets := 1; numBuckets <= 3; numBuckets++ { bufs := make([]*RowBuffer, numBuckets) recvs := make([]RowReceiver, numBuckets) for i := 0; i < numBuckets; i++ { bufs[i] = &RowBuffer{} recvs[i] = bufs[i] } mr, err := makeMirrorRouter(recvs) if err != nil { t.Fatal(err) } for i := 0; i < numRows; i++ { row := make(sqlbase.EncDatumRow, numCols) for j := 0; j < numCols; j++ { row[j] = vals[j][rng.Intn(len(vals[j]))] } ok := mr.PushRow(row) if !ok { t.Fatalf("PushRow returned false") } } mr.Close(nil) // Verify each row is sent to each of the output streams. for bIdx, b := range bufs { if len(b.rows) != len(bufs[0].rows) { t.Errorf("buckets %d and %d have different number of rows", 0, bIdx) } if !b.closed { t.Errorf("bucket not closed") } if b.err != nil { t.Error(b.err) } if bIdx == 0 { continue } // Verify that the i-th row is the same across all buffers. for i, row := range b.rows { row2 := bufs[0].rows[i] equal := true for j, c := range row { cmp, err := c.Compare(alloc, &row2[j]) if err != nil { t.Fatal(err) } if cmp != 0 { equal = false break } } if !equal { t.Errorf("rows %s and %s found in one bucket and not the other", row, row2) } } } } }