예제 #1
0
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)
						}
					}
				}
			}
		}
	}
}
예제 #2
0
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)
				}
			}
		}
	}
}