diff --git a/boil/randomize/random.go b/boil/randomize/random.go new file mode 100644 index 0000000..27395c6 --- /dev/null +++ b/boil/randomize/random.go @@ -0,0 +1,121 @@ +package randomize + +import ( + "crypto/md5" + "fmt" + "math/rand" +) + +const alphabetAll = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +const alphabetLowerAlpha = "abcdefghijklmnopqrstuvwxyz" + +func randStr(s *Seed, ln int) string { + str := make([]byte, ln) + for i := 0; i < ln; i++ { + str[i] = byte(alphabetAll[s.nextInt()%len(alphabetAll)]) + } + + return string(str) +} + +func randByteSlice(s *Seed, ln int) []byte { + str := make([]byte, ln) + for i := 0; i < ln; i++ { + str[i] = byte(s.nextInt() % 256) + } + + return str +} + +func randPoint() string { + a := rand.Intn(100) + b := a + 1 + return fmt.Sprintf("(%d,%d)", a, b) +} + +func randBox() string { + a := rand.Intn(100) + b := a + 1 + c := a + 2 + d := a + 3 + return fmt.Sprintf("(%d,%d),(%d,%d)", a, b, c, d) +} + +func randCircle() string { + a, b, c := rand.Intn(100), rand.Intn(100), rand.Intn(100) + return fmt.Sprintf("((%d,%d),%d)", a, b, c) +} + +func randNetAddr() string { + return fmt.Sprintf( + "%d.%d.%d.%d", + rand.Intn(254)+1, + rand.Intn(254)+1, + rand.Intn(254)+1, + rand.Intn(254)+1, + ) +} + +func randMacAddr() string { + buf := make([]byte, 6) + _, err := rand.Read(buf) + if err != nil { + panic(err) + } + + // Set the local bit + buf[0] |= 2 + return fmt.Sprintf( + "%02x:%02x:%02x:%02x:%02x:%02x", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], + ) +} + +func randLsn() string { + a := rand.Int63n(9000000) + b := rand.Int63n(9000000) + return fmt.Sprintf("%d/%d", a, b) +} + +func randTxID() string { + // Order of integers is relevant + a := rand.Intn(200) + 100 + b := a + 100 + c := a + d := a + 50 + return fmt.Sprintf("%d:%d:%d,%d", a, b, c, d) +} + +func randMoney(s *Seed) string { + return fmt.Sprintf("%d.00", s.nextInt()) +} + +// StableDBName takes a database name in, and generates +// a random string using the database name as the rand Seed. +// getDBNameHash is used to generate unique test database names. +func StableDBName(input string) string { + return randStrFromSource(stableSource(input), 40) +} + +// stableSource takes an input value, and produces a random +// seed from it that will produce very few collisions in +// a 40 character random string made from a different alphabet. +func stableSource(input string) *rand.Rand { + sum := md5.Sum([]byte(input)) + var seed int64 + for i, byt := range sum { + seed ^= int64(byt) << uint((i*4)%64) + } + return rand.New(rand.NewSource(seed)) +} + +func randStrFromSource(r *rand.Rand, length int) string { + ln := len(alphabetLowerAlpha) + + output := make([]rune, length) + for i := 0; i < length; i++ { + output[i] = rune(alphabetLowerAlpha[r.Intn(ln)]) + } + + return string(output) +} diff --git a/boil/randomize/random_test.go b/boil/randomize/random_test.go new file mode 100644 index 0000000..ee910ce --- /dev/null +++ b/boil/randomize/random_test.go @@ -0,0 +1,19 @@ +package randomize + +import "testing" + +func TestStableDBName(t *testing.T) { + t.Parallel() + + db := "awesomedb" + + one, two := StableDBName(db), StableDBName(db) + + if len(one) != 40 { + t.Error("want 40 characters:", len(one), one) + } + + if one != two { + t.Error("it should always produce the same value") + } +} diff --git a/boil/randomize/randomize.go b/boil/randomize/randomize.go index 2277ef2..e12193e 100644 --- a/boil/randomize/randomize.go +++ b/boil/randomize/randomize.go @@ -4,7 +4,6 @@ package randomize import ( "database/sql" "fmt" - "math/rand" "reflect" "regexp" "sort" @@ -572,86 +571,3 @@ func getVariableRandValue(s *Seed, kind reflect.Kind, typ reflect.Type) interfac return nil } - -const alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - -func randStr(s *Seed, ln int) string { - str := make([]byte, ln) - for i := 0; i < ln; i++ { - str[i] = byte(alphabet[s.nextInt()%len(alphabet)]) - } - - return string(str) -} - -func randByteSlice(s *Seed, ln int) []byte { - str := make([]byte, ln) - for i := 0; i < ln; i++ { - str[i] = byte(s.nextInt() % 256) - } - - return str -} - -func randPoint() string { - a := rand.Intn(100) - b := a + 1 - return fmt.Sprintf("(%d,%d)", a, b) -} - -func randBox() string { - a := rand.Intn(100) - b := a + 1 - c := a + 2 - d := a + 3 - return fmt.Sprintf("(%d,%d),(%d,%d)", a, b, c, d) -} - -func randCircle() string { - a, b, c := rand.Intn(100), rand.Intn(100), rand.Intn(100) - return fmt.Sprintf("((%d,%d),%d)", a, b, c) -} - -func randNetAddr() string { - return fmt.Sprintf( - "%d.%d.%d.%d", - rand.Intn(254)+1, - rand.Intn(254)+1, - rand.Intn(254)+1, - rand.Intn(254)+1, - ) -} - -func randMacAddr() string { - buf := make([]byte, 6) - _, err := rand.Read(buf) - if err != nil { - panic(err) - } - - // Set the local bit - buf[0] |= 2 - return fmt.Sprintf( - "%02x:%02x:%02x:%02x:%02x:%02x", - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], - ) -} - -func randLsn() string { - a := rand.Int63n(9000000) - b := rand.Int63n(9000000) - return fmt.Sprintf("%d/%d", a, b) -} - -func randTxID() string { - // Order of integers is relevant - a := rand.Intn(200) + 100 - b := a + 100 - c := a - d := a + 50 - return fmt.Sprintf("%d:%d:%d,%d", a, b, c, d) -} - -func randMoney(s *Seed) string { - return fmt.Sprintf("%d.00", s.nextInt()) -}