Skip to content

Instantly share code, notes, and snippets.

@srfrog
Created January 17, 2020 19:38
Show Gist options
  • Save srfrog/90101cb8d485e200117fabdd2fa9d2ae to your computer and use it in GitHub Desktop.
Save srfrog/90101cb8d485e200117fabdd2fa9d2ae to your computer and use it in GitHub Desktop.
Random string generation
package randstr_test
import (
"crypto/rand"
weak "math/rand"
"testing"
"time"
)
const (
randChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
randCharsLen = len(randChars)
)
// RandStringWeak uses a time-based pseudo random generated string.
// This func is fine for tests and limited use values.
func RandStringWeak(n int, t time.Time) string {
src := weak.NewSource(t.UTC().UnixNano())
b := make([]byte, n)
for i := range b {
b[i] = randChars[src.Int63()%int64(randCharsLen)]
}
return string(b)
}
// RandString returns a random string using a crptographically secure RNG source.
// It will panic if n < 0. If n==0 it will return an empty string.
// This func may block if there isn't enough entrophy in the RNG source.
func RandString(n int) string {
bs := make([]byte, n)
if _, err := rand.Read(bs); err != nil {
return ""
}
for i, b := range bs {
bs[i] = randChars[int(b)%randCharsLen]
}
return string(bs)
}
func TestRandStr(t *testing.T) {
var tests = []struct {
name string
len int
}{
{name: "len=0", len: 0},
{name: "len=1", len: 1},
{name: "len=2", len: 2},
{name: "len=3", len: 3},
{name: "len=4", len: 4},
{name: "len=8", len: 8},
{name: "len=16", len: 16},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
out := RandString(tc.len)
t.Logf("%s\n", out)
if len(out) != tc.len {
t.Errorf("RandString() = %v, got %v want %v", out, len(out), tc.len)
}
})
}
}
func TestRandStrWeak(t *testing.T) {
var tests = []struct {
name string
len int
}{
{name: "len=0", len: 0},
{name: "len=1", len: 1},
{name: "len=2", len: 2},
{name: "len=3", len: 3},
{name: "len=4", len: 4},
{name: "len=8", len: 8},
{name: "len=16", len: 16},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
out := RandStringWeak(tc.len, time.Now())
t.Logf("%s\n", out)
if len(out) != tc.len {
t.Errorf("RandStringWeak() = %v, got %v want %v", out, len(out), tc.len)
}
})
}
}
func BenchmarkRandString(b *testing.B) {
for i := 0; i < b.N; i++ {
RandString(10)
}
}
func BenchmarkRandStringWeak(b *testing.B) {
for i := 0; i < b.N; i++ {
RandStringWeak(10, time.Now())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment