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

Commit

Permalink
feat: added random source customization (#137)
Browse files Browse the repository at this point in the history
* added random source customization

Signed-off-by: Frederic BIDON <fredbi@yahoo.com>

* added unit tests

Signed-off-by: Frederic BIDON <fredbi@yahoo.com>
  • Loading branch information
fredbi committed Jul 1, 2021
1 parent 74585ae commit 7460bf3
Show file tree
Hide file tree
Showing 14 changed files with 88 additions and 17 deletions.
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

0 comments on commit 7460bf3

Please sign in to comment.