github.com/MetalBlockchain/metalgo@v1.11.9/utils/sampler/uniform_test.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package sampler 5 6 import ( 7 "fmt" 8 "math" 9 "slices" 10 "testing" 11 12 "github.com/stretchr/testify/require" 13 ) 14 15 var ( 16 uniformSamplers = []struct { 17 name string 18 sampler Uniform 19 }{ 20 { 21 name: "replacer", 22 sampler: &uniformReplacer{ 23 rng: globalRNG, 24 }, 25 }, 26 { 27 name: "resampler", 28 sampler: &uniformResample{ 29 rng: globalRNG, 30 }, 31 }, 32 { 33 name: "best", 34 sampler: NewBestUniform(30), 35 }, 36 } 37 uniformTests = []struct { 38 name string 39 test func(*testing.T, Uniform) 40 }{ 41 { 42 name: "can sample large values", 43 test: UniformInitializeMaxUint64Test, 44 }, 45 { 46 name: "out of range", 47 test: UniformOutOfRangeTest, 48 }, 49 { 50 name: "empty", 51 test: UniformEmptyTest, 52 }, 53 { 54 name: "singleton", 55 test: UniformSingletonTest, 56 }, 57 { 58 name: "distribution", 59 test: UniformDistributionTest, 60 }, 61 { 62 name: "over sample", 63 test: UniformOverSampleTest, 64 }, 65 { 66 name: "lazily sample", 67 test: UniformLazilySample, 68 }, 69 } 70 ) 71 72 func TestAllUniform(t *testing.T) { 73 for _, s := range uniformSamplers { 74 for _, test := range uniformTests { 75 t.Run(fmt.Sprintf("sampler %s test %s", s.name, test.name), func(t *testing.T) { 76 test.test(t, s.sampler) 77 }) 78 } 79 } 80 } 81 82 func UniformInitializeMaxUint64Test(t *testing.T, s Uniform) { 83 s.Initialize(math.MaxUint64) 84 85 for { 86 val, hasNext := s.Next() 87 require.True(t, hasNext) 88 89 if val > math.MaxInt64 { 90 break 91 } 92 } 93 } 94 95 func UniformOutOfRangeTest(t *testing.T, s Uniform) { 96 s.Initialize(0) 97 98 _, ok := s.Sample(1) 99 require.False(t, ok) 100 } 101 102 func UniformEmptyTest(t *testing.T, s Uniform) { 103 require := require.New(t) 104 105 s.Initialize(1) 106 107 val, ok := s.Sample(0) 108 require.True(ok) 109 require.Empty(val) 110 } 111 112 func UniformSingletonTest(t *testing.T, s Uniform) { 113 require := require.New(t) 114 115 s.Initialize(1) 116 117 val, ok := s.Sample(1) 118 require.True(ok) 119 require.Equal([]uint64{0}, val) 120 } 121 122 func UniformDistributionTest(t *testing.T, s Uniform) { 123 require := require.New(t) 124 125 s.Initialize(3) 126 127 val, ok := s.Sample(3) 128 require.True(ok) 129 130 slices.Sort(val) 131 require.Equal([]uint64{0, 1, 2}, val) 132 } 133 134 func UniformOverSampleTest(t *testing.T, s Uniform) { 135 s.Initialize(3) 136 137 _, ok := s.Sample(4) 138 require.False(t, ok) 139 } 140 141 func UniformLazilySample(t *testing.T, s Uniform) { 142 require := require.New(t) 143 144 s.Initialize(3) 145 146 for j := 0; j < 2; j++ { 147 sampled := map[uint64]bool{} 148 for i := 0; i < 3; i++ { 149 val, hasNext := s.Next() 150 require.True(hasNext) 151 require.False(sampled[val]) 152 153 sampled[val] = true 154 } 155 156 _, hasNext := s.Next() 157 require.False(hasNext) 158 159 s.Reset() 160 } 161 }