aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortalis <talis@il.ibm.com>2019-02-28 14:59:24 +0200
committertalis <talis@il.ibm.com>2019-02-28 14:59:24 +0200
commit63b66ddfe0ddd512d239ead433bc6124ae02a56b (patch)
treefd98dd66d4b2100ee7d8dde630e10d4c1348fdc5
parentcaad4a112366c90c62a8957be036ead8040f6602 (diff)
downloadgoogle-uuid-63b66ddfe0ddd512d239ead433bc6124ae02a56b.tar.gz
reused version4 NewRandom() and added better testing
-rw-r--r--uuid_source.go30
-rw-r--r--uuid_source_test.go42
-rw-r--r--uuid_test.go21
-rw-r--r--version4.go7
4 files changed, 85 insertions, 15 deletions
diff --git a/uuid_source.go b/uuid_source.go
index 211b052..83a569c 100644
--- a/uuid_source.go
+++ b/uuid_source.go
@@ -5,10 +5,18 @@ import (
"crypto/rand"
)
+// A UuidSource holds a random number generator and generates UUIDs using it as its source.
+//
+// It is useful when a process need its own random number generator,
+// e.g. when running some processes concurrently.
type UuidSource struct {
rander io.Reader
}
+// Creates a new UuidSource which holds its own random number generator.
+//
+// Calling NewSource with nil sets the random number generator to a default
+// generator.
func NewSource(r io.Reader) UuidSource {
var uuidSource UuidSource
uuidSource.SetRand(r)
@@ -16,6 +24,12 @@ func NewSource(r io.Reader) UuidSource {
}
+// SetRand sets the random number generator of the UuidSource to r, which implements io.Reader.
+// If r.Read returns an error when the package requests random data then
+// a panic will be issued.
+//
+// Calling SetRand with nil sets the random number generator to a default
+// generator.
func (uuidSource *UuidSource) SetRand(r io.Reader) {
if r == nil {
uuidSource.rander = rand.Reader
@@ -24,17 +38,17 @@ func (uuidSource *UuidSource) SetRand(r io.Reader) {
uuidSource.rander = r
}
+// NewRandom returns a Random (Version 4) UUID based on the random number generator in the UuidSource.
+//
+// See more detailed explanation here: https://godoc.org/github.com/google/uuid#NewRandom
func (uuidSource UuidSource) NewRandom() (UUID, error) {
- var uuid UUID
- _, err := io.ReadFull(uuidSource.rander, uuid[:])
- if err != nil {
- return Nil, err
- }
- uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
- uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
- return uuid, nil
+ return newRandom(uuidSource.rander)
}
+// New creates a new random UUID based on the random number generator in the UuidSource or panics. New is equivalent to
+// the expression
+//
+// uuid.Must(uuid.NewRandom())
func (uuidSource UuidSource) New() UUID {
return Must(uuidSource.NewRandom())
}
diff --git a/uuid_source_test.go b/uuid_source_test.go
index 646e605..762146d 100644
--- a/uuid_source_test.go
+++ b/uuid_source_test.go
@@ -7,23 +7,53 @@ import (
)
func TestUuidSources(t *testing.T) {
+
+ // Two identical sources, should give same sequence
currentTime := time.Now().UnixNano()
uuidSourceA := NewSource(rand.New(rand.NewSource(currentTime)))
uuidSourceB := NewSource(rand.New(rand.NewSource(currentTime)))
for i := 0; i < 10; i++ {
- if uuidSourceA.New().String() != uuidSourceB.New().String() {
- t.Error("Uuid values are not reproducaible!")
+ uuid1 := uuidSourceA.New()
+ uuid2 := uuidSourceB.New()
+ if uuid1 != uuid2 {
+ t.Errorf("expected duplicates, got %q and %q", uuid1, uuid2)
}
}
- uuidSourceA = NewSource(rand.New(rand.NewSource(123)))
- uuidSourceB = NewSource(rand.New(rand.NewSource(456)))
+ // Set rander with nil, each source will be random
+ uuidSourceA.SetRand(nil)
+ uuidSourceB.SetRand(nil)
+
+ for i := 0; i < 10; i++ {
+ uuid1 := uuidSourceA.New()
+ uuid2 := uuidSourceB.New()
+ if uuid1 == uuid2 {
+ t.Errorf("unexpected duplicates, got %q", uuid1)
+ }
+ }
+ // Set rander to rand source with same seed, should give same sequence
+ uuidSourceA.SetRand(rand.New(rand.NewSource(123)))
+ uuidSourceB.SetRand(rand.New(rand.NewSource(123)))
+
+ for i := 0; i < 10; i++ {
+ uuid1 := uuidSourceA.New()
+ uuid2 := uuidSourceB.New()
+ if uuid1 != uuid2 {
+ t.Errorf("expected duplicates, got %q and %q", uuid1, uuid2)
+ }
+ }
+
+ // Set rander to rand source with different seeds, should not give same sequence
+ uuidSourceA.SetRand(rand.New(rand.NewSource(456)))
+ uuidSourceB.SetRand(rand.New(rand.NewSource(789)))
for i := 0; i < 10; i++ {
- if uuidSourceA.New().String() == uuidSourceB.New().String() {
- t.Error("Uuid values should not match!")
+ uuid1 := uuidSourceA.New()
+ uuid2 := uuidSourceB.New()
+ if uuid1 == uuid2 {
+ t.Errorf("unexpected duplicates, got %q", uuid1)
}
}
diff --git a/uuid_test.go b/uuid_test.go
index e7876f1..ff17ff3 100644
--- a/uuid_test.go
+++ b/uuid_test.go
@@ -13,6 +13,8 @@ import (
"testing"
"time"
"unsafe"
+
+ "math/rand"
)
type test struct {
@@ -479,6 +481,25 @@ func TestBadRand(t *testing.T) {
}
}
+func TestSetRand(t *testing.T) {
+ SetRand(rand.New(rand.NewSource(456)))
+ uuid1 := New()
+ uuid2 := New()
+
+ SetRand(rand.New(rand.NewSource(456)))
+ uuid3 := New()
+ uuid4 := New()
+
+ if uuid1 != uuid3 {
+ t.Errorf("expected duplicates, got %q and %q", uuid1, uuid3)
+ }
+ if uuid2 != uuid4 {
+ t.Errorf("expected duplicates, got %q and %q", uuid2, uuid4)
+ }
+
+
+}
+
var asString = "f47ac10b-58cc-0372-8567-0e02b2c3d479"
var asBytes = []byte(asString)
diff --git a/version4.go b/version4.go
index 84af91c..66acd62 100644
--- a/version4.go
+++ b/version4.go
@@ -27,8 +27,12 @@ func New() UUID {
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
// year and having one duplicate.
func NewRandom() (UUID, error) {
+ return newRandom(rander)
+}
+
+func newRandom(r io.Reader) (UUID, error) {
var uuid UUID
- _, err := io.ReadFull(rander, uuid[:])
+ _, err := io.ReadFull(r, uuid[:])
if err != nil {
return Nil, err
}
@@ -36,3 +40,4 @@ func NewRandom() (UUID, error) {
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
return uuid, nil
}
+