diff --git a/fuzz.go b/fuzz.go index 3c1ba51..049d7db 100644 --- a/fuzz.go +++ b/fuzz.go @@ -471,15 +471,19 @@ func randBool(r *rand.Rand) bool { return false } +type int63nPicker interface { + Int63n(int64) int64 +} + type charRange struct { first, last rune } // choose returns a random unicode character from the given range, using the // given randomness source. -func (r *charRange) choose(rand *rand.Rand) rune { - count := int64(r.last - r.first) - return r.first + rune(rand.Int63n(count)) +func (cr charRange) choose(r int63nPicker) rune { + count := int64(cr.last - cr.first + 1) + return cr.first + rune(r.Int63n(count)) } var unicodeRanges = []charRange{ diff --git a/fuzz_test.go b/fuzz_test.go index b98ba63..963ea59 100644 --- a/fuzz_test.go +++ b/fuzz_test.go @@ -17,6 +17,7 @@ limitations under the License. package fuzz import ( + "math/rand" "reflect" "regexp" "testing" @@ -512,3 +513,43 @@ func TestFuzz_SkipPattern(t *testing.T) { return 5, true }) } + +type int63mode int + +const ( + modeRandom int63mode = iota + modeFirst + modeLast +) + +type customInt63 struct { + mode int63mode +} + +func (c customInt63) Int63n(n int64) int64 { + switch c.mode { + case modeFirst: return 0 + case modeLast: return n-1 + default: return rand.Int63n(n) + } +} + +func Test_charRange_choose(t *testing.T) { + lowercaseLetters := charRange{'a', 'z'} + + t.Run("Picks first", func(t *testing.T) { + r := customInt63{mode: modeFirst} + letter := lowercaseLetters.choose(r) + if letter != 'a' { + t.Errorf("Expected a, got %v", letter) + } + }) + + t.Run("Picks last", func(t *testing.T) { + r := customInt63{mode: modeLast} + letter := lowercaseLetters.choose(r) + if letter != 'z' { + t.Errorf("Expected z, got %v", letter) + } + }) +}