Skip to content
Permalink
Browse files
randbp: Add min length arg to GenerateRandomString
Currently GenerateRandomString could generate empty strings. In some
cases we want to avoid empty strings, so add min length arg to control
that.

Also convert its args into a struct. As a result this is a breaking
change.

Also add an example to GenerateRandomString.
  • Loading branch information
fishy committed Aug 31, 2020
1 parent fb7a64d commit dfb983ddbbcd3410dd0164a154d2596934311e63
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 5 deletions.
@@ -20,6 +20,7 @@ go_test(
srcs = [
"rand_test.go",
"sample_test.go",
"string_example_test.go",
],
embed = [":go_default_library"],
)
@@ -11,12 +11,42 @@ import (
// GenerateRandomString.
const Base64Runes = `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_+/=`

// GenerateRandomString generates a random string with length [0, maxLength),
// and all characters limited to runes.
// RandomStringArgs defines the args used by GenerateRandomString.
type RandomStringArgs struct {
// Required. If MaxLength <= MinLength it will cause panic.
MaxLength int

// Optional. Default is 0, which means it could generate empty strings.
// If MinLength < 0 or MinLength >= MaxLength it will cause panic.
MinLength int

// Optional. If nil randbp.R will be used instead.
R *rand.Rand

// Optional. If empty []rune(randbp.Base64Runes) will be used instead.
Runes []rune
}

// The common interface between *math/rand.Rand and randbp.Rand used in
// GenerateRandomString.
type intner interface {
Intn(n int) int
}

// GenerateRandomString generates a random string with length
// [MinLength, MaxLength), and all characters limited to Runes.
//
// It could be used to help implement testing/quick.Generator interface.
func GenerateRandomString(r *rand.Rand, maxLength int, runes []rune) string {
n := r.Intn(maxLength)
func GenerateRandomString(args RandomStringArgs) string {
var r intner = args.R
if r == nil {
r = R
}
runes := args.Runes
if len(runes) == 0 {
runes = []rune(Base64Runes)
}
n := r.Intn(args.MaxLength-args.MinLength) + args.MinLength
ret := make([]rune, n)
for i := range ret {
ret[i] = runes[r.Intn(len(runes))]
@@ -0,0 +1,62 @@
package randbp_test

import (
"math/rand"
"reflect"
"testing"
"testing/quick"

"github.com/reddit/baseplate.go/randbp"
)

const (
MinLength = 1
MaxLength = 20
)

type RandomString string

func (RandomString) Generate(r *rand.Rand, _ int) reflect.Value {
return reflect.ValueOf(RandomString(randbp.GenerateRandomString(
randbp.RandomStringArgs{
R: r,
MinLength: MinLength,
MaxLength: MaxLength,
},
)))
}

var _ quick.Generator = RandomString("")

// In real code the function name should be TestRandomString,
// but using that name here will break the example.
func RandomStringTest(t *testing.T) {
f := func(input RandomString) bool {
s := string(input)
if len(s) < MinLength {
t.Errorf(
"Expected random string to have a minimal length of %d, got %q",
MinLength,
s,
)
}
if len(s) >= MaxLength {
t.Errorf(
"Expected random string to have a maximum length of %d, got %q",
MaxLength,
s,
)
}
return !t.Failed()
}
if err := quick.Check(f, nil); err != nil {
t.Error(err)
}
}

// This example demonstrates how to use GenerateRandomString in your tests with
// testing/quick package.
func ExampleGenerateRandomString() {
// Nothing really here.
// The real example is on the other functions/types above,
}
@@ -171,7 +171,10 @@ const maxNameLength = 20

func (randomName) Generate(r *rand.Rand, _ int) reflect.Value {
return reflect.ValueOf(randomName(
randbp.GenerateRandomString(r, maxNameLength, []rune(randbp.Base64Runes)),
randbp.GenerateRandomString(randbp.RandomStringArgs{
R: r,
MaxLength: maxNameLength,
}),
))
}

0 comments on commit dfb983d

Please sign in to comment.