Skip to content
This repository has been archived by the owner on Dec 8, 2022. It is now read-only.

feat: added random source customization #137

Merged
merged 2 commits into from Jul 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion address.go
@@ -1,7 +1,6 @@
package faker

import (
"math/rand"
"reflect"
)

Expand Down
1 change: 0 additions & 1 deletion datetime.go
Expand Up @@ -2,7 +2,6 @@ package faker

import (
"fmt"
"math/rand"
"reflect"
"time"
)
Expand Down
11 changes: 9 additions & 2 deletions faker.go
Expand Up @@ -3,9 +3,10 @@ package faker
// Faker is a simple fake data generator for your own struct.
// Save your time, and Fake your data for your testing now.
import (
cryptorand "crypto/rand"
"errors"
"fmt"
"math/rand"
mathrand "math/rand"
"reflect"
"regexp"
"strconv"
Expand Down Expand Up @@ -263,10 +264,16 @@ var (
)

func init() {
rand.Seed(time.Now().UnixNano())
rand = mathrand.New(NewSafeSource(mathrand.NewSource(time.Now().UnixNano())))
crypto = cryptorand.Reader
}

func init() {
findLangReg, _ = regexp.Compile("lang=[a-z]{3}")
findLenReg, _ = regexp.Compile(`len=\d+`)
findSliceLenReg, _ = regexp.Compile(`slice_len=\d+`)

randNameFlag = rand.Intn(100) // for person
}

// ResetUnique is used to forget generated unique values.
Expand Down
5 changes: 2 additions & 3 deletions faker_test.go
Expand Up @@ -2,7 +2,7 @@ package faker

import (
"fmt"
"math/rand"
mathrand "math/rand"
"reflect"
"strings"
"testing"
Expand Down Expand Up @@ -1066,8 +1066,7 @@ func TestExtend(t *testing.T) {
a := Sample{}
sliceLen := 10
err := AddProvider("myint", func(v reflect.Value) (interface{}, error) {
s1 := rand.NewSource(time.Now().UnixNano())
r1 := rand.New(s1)
r1 := mathrand.New(NewSafeSource(mathrand.NewSource(time.Now().UnixNano())))
r := make([]MyInt, sliceLen)
for i := range r {
r[i] = MyInt(r1.Intn(100))
Expand Down
1 change: 0 additions & 1 deletion internet.go
Expand Up @@ -2,7 +2,6 @@ package faker

import (
"fmt"
"math/rand"
"net"
"reflect"
"strings"
Expand Down
1 change: 0 additions & 1 deletion lorem.go
Expand Up @@ -2,7 +2,6 @@ package faker

import (
"fmt"
"math/rand"
"reflect"
"strings"
)
Expand Down
1 change: 0 additions & 1 deletion payment.go
@@ -1,7 +1,6 @@
package faker

import (
"math/rand"
"reflect"
"strconv"
"strings"
Expand Down
4 changes: 2 additions & 2 deletions person.go
Expand Up @@ -2,7 +2,6 @@ package faker

import (
"fmt"
"math/rand"
"reflect"
)

Expand Down Expand Up @@ -107,7 +106,8 @@ var lastNames = []string{
"Ullrich", "Upton", "Vandervort", "Veum", "Volkman", "Von", "VonRueden", "Waelchi", "Walker", "Walsh", "Walter", "Ward", "Waters", "Watsica", "Weber", "Wehner", "Weimann", "Weissnat", "Welch", "West", "White", "Wiegand", "Wilderman", "Wilkinson", "Will", "Williamson", "Willms", "Windler", "Wintheiser", "Wisoky", "Wisozk", "Witting", "Wiza", "Wolf", "Wolff", "Wuckert", "Wunsch", "Wyman",
"Yost", "Yundt", "Zboncak", "Zemlak", "Ziemann", "Zieme", "Zulauf",
}
var randNameFlag = rand.Intn(100)

var randNameFlag int

var genders = []string{"Male", "Female", "Prefer to skip"}

Expand Down
1 change: 0 additions & 1 deletion phone.go
Expand Up @@ -2,7 +2,6 @@ package faker

import (
"fmt"
"math/rand"
"reflect"
"strings"

Expand Down
1 change: 0 additions & 1 deletion price.go
Expand Up @@ -3,7 +3,6 @@ package faker
import (
"fmt"
"math"
"math/rand"
"reflect"
)

Expand Down
49 changes: 49 additions & 0 deletions random_source.go
@@ -0,0 +1,49 @@
package faker

import (
"io"
mathrand "math/rand"
"sync"
)

var (
rand *mathrand.Rand
crypto io.Reader
)

type safeSource struct {
mx sync.Mutex
mathrand.Source
}

func (s *safeSource) Int63() int64 {
s.mx.Lock()
defer s.mx.Unlock()

return s.Source.Int63()
}

// NewSafeSource wraps an unsafe rand.Source with a mutex to guard the random source
// against concurrent access.
func NewSafeSource(in mathrand.Source) mathrand.Source {
return &safeSource{
Source: in,
}
}

// SetRandomSource sets a new random source at the package level.
//
// To use a concurrent-safe source, you may wrap it with NewSafeSource,
// e.g. SetRandomSource(NewSafeSource(mysource)).
//
// The default is the global, concurrent-safe source provided by math/rand.
func SetRandomSource(in mathrand.Source) {
rand = mathrand.New(in)
}

// SetCryptoSource sets a new reader for functions using a cryptographically-safe random generator (e.g. UUID).
//
// The default is the global source provided by crypto/rand.
func SetCryptoSource(in io.Reader) {
crypto = in
}
25 changes: 25 additions & 0 deletions random_source_test.go
@@ -0,0 +1,25 @@
package faker

import (
cryptorand "crypto/rand"
"io"
mathrand "math/rand"
"testing"
"time"
)

func TestSetRandomSource(t *testing.T) {
SetRandomSource(NewSafeSource(mathrand.NewSource(time.Now().UnixNano())))

_ = rand.Int31n(100)
}

func TestSetCryptoSource(t *testing.T) {
SetCryptoSource(cryptorand.Reader)

buf := make([]byte, 10)
_, err := io.ReadFull(crypto, buf)
if err != nil {
t.Error("Expected Not Error, But Got: ", err)
}
}
1 change: 0 additions & 1 deletion tag_argument_extractor.go
Expand Up @@ -2,7 +2,6 @@ package faker

import (
"fmt"
"math/rand"
"strconv"
"strings"
)
Expand Down
3 changes: 1 addition & 2 deletions uuid.go
@@ -1,7 +1,6 @@
package faker

import (
"crypto/rand"
"fmt"
"io"
"reflect"
Expand Down Expand Up @@ -32,7 +31,7 @@ type UUID struct{}
// createUUID returns a 16 byte slice with random values
func createUUID() ([]byte, error) {
b := make([]byte, 16)
_, err := io.ReadFull(rand.Reader, b)
_, err := io.ReadFull(crypto, b)
if err != nil {
return b, err
}
Expand Down