diff --git a/cryptorandomstringutils.go b/cryptorandomstringutils.go index 177dd86..8dbd924 100644 --- a/cryptorandomstringutils.go +++ b/cryptorandomstringutils.go @@ -21,7 +21,6 @@ import ( "fmt" "math" "math/big" - "regexp" "unicode" ) @@ -99,27 +98,7 @@ Returns: error - an error stemming from an invalid parameter within underlying function, CryptoRandom(...) */ func CryptoRandomAlphaNumeric(count int) (string, error) { - if count == 0 { - return "", nil - } - RandomString, err := CryptoRandom(count, 0, 0, true, true) - if err != nil { - return "", fmt.Errorf("Error: %s", err) - } - match, err := regexp.MatchString("([0-9]+)", RandomString) - if err != nil { - panic(err) - } - - if !match { - //Get the position between 0 and the length of the string-1 to insert a random number - position := getCryptoRandomInt(count) - //Insert a random number between [0-9] in the position - RandomString = RandomString[:position] + string('0' + getCryptoRandomInt(10)) + RandomString[position + 1:] - return RandomString, err - } - return RandomString, err - + return CryptoRandom(count, 0, 0, true, true) } /* @@ -204,7 +183,7 @@ func CryptoRandom(count int, start int, end int, letters bool, numbers bool, cha if chars == nil { ch = rune(getCryptoRandomInt(gap) + int64(start)) } else { - ch = chars[getCryptoRandomInt(gap) + int64(start)] + ch = chars[getCryptoRandomInt(gap)+int64(start)] } if letters && unicode.IsLetter(ch) || numbers && unicode.IsDigit(ch) || !letters && !numbers { diff --git a/cryptorandomstringutils_test.go b/cryptorandomstringutils_test.go index c8c1622..fc1d7a6 100644 --- a/cryptorandomstringutils_test.go +++ b/cryptorandomstringutils_test.go @@ -1,6 +1,8 @@ package goutils import ( + "regexp" + "strconv" "testing" "unicode/utf8" ) @@ -74,3 +76,37 @@ func TestCryptoRandomAlphaNumeric(t *testing.T) { } } } + +func TestCryptoRandAlphaNumeric_FuzzOnlyNumeric(t *testing.T) { + + // Testing for a reported regression in which some versions produced + // a predictably small set of chars. + iters := 1000 + charlen := 0 + for i := 0; i < 16; i++ { + numOnly := 0 + charlen++ + for i := 0; i < iters; i++ { + out, err := CryptoRandomAlphaNumeric(charlen) + if err != nil { + t.Fatal("func failed to produce a random thinger") + } + if _, err := strconv.Atoi(out); err == nil { + numOnly++ + } + + m, err := regexp.MatchString("^[0-9a-zA-Z]+$", out) + if err != nil { + t.Fatal(err) + } + if !m { + t.Fatal("Character is not alphanum") + } + } + + if numOnly == iters { + t.Fatalf("Got %d numeric-only random sequences", numOnly) + } + } + +} diff --git a/randomstringutils.go b/randomstringutils.go index 1364e0c..2726702 100644 --- a/randomstringutils.go +++ b/randomstringutils.go @@ -20,7 +20,6 @@ import ( "fmt" "math" "math/rand" - "regexp" "time" "unicode" ) @@ -75,12 +74,10 @@ func RandomNumeric(count int) (string, error) { /* RandomAlphabetic creates a random string whose length is the number of characters specified. -Characters will be chosen from the set of alpha-numeric characters as indicated by the arguments. +Characters will be chosen from the set of alphabetic characters. Parameters: count - the length of random string to create - letters - if true, generated string may include alphabetic characters - numbers - if true, generated string may include numeric characters Returns: string - the random string @@ -102,24 +99,7 @@ Returns: error - an error stemming from an invalid parameter within underlying function, RandomSeed(...) */ func RandomAlphaNumeric(count int) (string, error) { - RandomString, err := Random(count, 0, 0, true, true) - if err != nil { - return "", fmt.Errorf("Error: %s", err) - } - match, err := regexp.MatchString("([0-9]+)", RandomString) - if err != nil { - panic(err) - } - - if !match { - //Get the position between 0 and the length of the string-1 to insert a random number - position := rand.Intn(count) - //Insert a random number between [0-9] in the position - RandomString = RandomString[:position] + string('0'+rand.Intn(10)) + RandomString[position+1:] - return RandomString, err - } - return RandomString, err - + return Random(count, 0, 0, true, true) } /* diff --git a/randomstringutils_test.go b/randomstringutils_test.go index b990654..f8dd294 100644 --- a/randomstringutils_test.go +++ b/randomstringutils_test.go @@ -3,6 +3,8 @@ package goutils import ( "fmt" "math/rand" + "regexp" + "strconv" "testing" ) @@ -76,3 +78,37 @@ func ExampleRandomSeed() { // H_I;E // 2b2ca } + +func TestRandAlphaNumeric_FuzzOnlyNumeric(t *testing.T) { + + // Testing for a reported regression in which some versions produced + // a predictably small set of chars. + iters := 1000 + charlen := 0 + for i := 0; i < 16; i++ { + numOnly := 0 + charlen++ + for i := 0; i < iters; i++ { + out, err := RandomAlphaNumeric(charlen) + if err != nil { + t.Fatal("func failed to produce a random thinger") + } + if _, err := strconv.Atoi(out); err == nil { + numOnly++ + } + + m, err := regexp.MatchString("^[0-9a-zA-Z]+$", out) + if err != nil { + t.Fatal(err) + } + if !m { + t.Fatal("Character is not alphanum") + } + } + + if numOnly == iters { + t.Fatalf("Got %d numeric-only random sequences", numOnly) + } + } + +}