github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/stats/row_sampling_test.go (about) 1 // Copyright 2017 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 stats 12 13 import ( 14 "context" 15 "fmt" 16 "reflect" 17 "sort" 18 "testing" 19 20 "github.com/cockroachdb/cockroach/pkg/settings/cluster" 21 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 22 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 23 "github.com/cockroachdb/cockroach/pkg/sql/types" 24 "github.com/cockroachdb/cockroach/pkg/util" 25 "github.com/cockroachdb/cockroach/pkg/util/randutil" 26 ) 27 28 // runSampleTest feeds rows with the given ranks through a reservoir 29 // of a given size and verifies the results are correct. 30 func runSampleTest(t *testing.T, evalCtx *tree.EvalContext, numSamples int, ranks []int) { 31 ctx := context.Background() 32 var sr SampleReservoir 33 sr.Init(numSamples, []*types.T{types.Int}, nil /* memAcc */, util.MakeFastIntSet(0)) 34 for _, r := range ranks { 35 d := sqlbase.DatumToEncDatum(types.Int, tree.NewDInt(tree.DInt(r))) 36 if err := sr.SampleRow(ctx, evalCtx, sqlbase.EncDatumRow{d}, uint64(r)); err != nil { 37 t.Errorf("%v", err) 38 } 39 } 40 samples := sr.Get() 41 sampledRanks := make([]int, len(samples)) 42 43 // Verify that the row and the ranks weren't mishandled. 44 for i, s := range samples { 45 if *s.Row[0].Datum.(*tree.DInt) != tree.DInt(s.Rank) { 46 t.Fatalf( 47 "mismatch between row %s and rank %d", 48 s.Row.String([]*types.T{types.Int}), s.Rank, 49 ) 50 } 51 sampledRanks[i] = int(s.Rank) 52 } 53 54 // Verify the top ranks made it. 55 sort.Ints(sampledRanks) 56 expected := append([]int(nil), ranks...) 57 sort.Ints(expected) 58 if len(expected) > numSamples { 59 expected = expected[:numSamples] 60 } 61 if !reflect.DeepEqual(expected, sampledRanks) { 62 t.Errorf("invalid ranks: %v vs %v", sampledRanks, expected) 63 } 64 } 65 66 func TestSampleReservoir(t *testing.T) { 67 evalCtx := tree.MakeTestingEvalContext(cluster.MakeTestingClusterSettings()) 68 for _, n := range []int{10, 100, 1000, 10000} { 69 rng, _ := randutil.NewPseudoRand() 70 ranks := make([]int, n) 71 for i := range ranks { 72 ranks[i] = rng.Int() 73 } 74 for _, k := range []int{1, 5, 10, 100} { 75 t.Run(fmt.Sprintf("%d/%d", n, k), func(t *testing.T) { 76 runSampleTest(t, &evalCtx, k, ranks) 77 }) 78 } 79 } 80 } 81 82 func TestTruncateDatum(t *testing.T) { 83 evalCtx := tree.MakeTestingEvalContext(cluster.MakeTestingClusterSettings()) 84 runTest := func(d, expected tree.Datum) { 85 actual := truncateDatum(&evalCtx, d, 10 /* maxBytes */) 86 if actual.Compare(&evalCtx, expected) != 0 { 87 t.Fatalf("expected %s but found %s", expected.String(), actual.String()) 88 } 89 } 90 91 original1, err := tree.ParseDBitArray("0110110101111100001100110110101111100001100110110101111" + 92 "10000110011011010111110000110011011010111110000110011011010111110000110") 93 if err != nil { 94 t.Fatal(err) 95 } 96 expected1, err := tree.ParseDBitArray("0110110101111100001100110110101111100001100110110101111" + 97 "1000011001101101011111000") 98 if err != nil { 99 t.Fatal(err) 100 } 101 runTest(original1, expected1) 102 103 original2 := tree.DBytes("deadbeef1234567890") 104 expected2 := tree.DBytes("deadbeef12") 105 runTest(&original2, &expected2) 106 107 original3 := tree.DString("Hello 世界") 108 expected3 := tree.DString("Hello 世") 109 runTest(&original3, &expected3) 110 111 original4, err := tree.NewDCollatedString(`IT was lovely summer weather in the country, and the golden 112 corn, the green oats, and the haystacks piled up in the meadows looked beautiful`, 113 "en_US", &tree.CollationEnvironment{}) 114 if err != nil { 115 t.Fatal(err) 116 } 117 expected4, err := tree.NewDCollatedString("IT was lov", "en_US", &tree.CollationEnvironment{}) 118 if err != nil { 119 t.Fatal(err) 120 } 121 runTest(original4, expected4) 122 }