From 5fee13587945e96f2702e58c6873a42b9a7a1342 Mon Sep 17 00:00:00 2001 From: Matija Lesar Date: Fri, 25 Feb 2022 09:49:30 +0100 Subject: [PATCH 1/2] Added generator options so that default values can be changed --- generator.go | 48 +++++++++++++---- generator_test.go | 128 ++++++++++++++++++++-------------------------- go.mod | 3 ++ 3 files changed, 95 insertions(+), 84 deletions(-) create mode 100644 go.mod diff --git a/generator.go b/generator.go index 38bf685..c7d5d38 100644 --- a/generator.go +++ b/generator.go @@ -39,7 +39,7 @@ import ( // UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970). const epochStart = 122192928000000000 -type epochFunc func() time.Time +type EpochFunc func() time.Time // HWAddrFunc is the function type used to provide hardware (MAC) addresses. type HWAddrFunc func() (net.HardwareAddr, error) @@ -126,7 +126,7 @@ type Gen struct { rand io.Reader - epochFunc epochFunc + epochFunc EpochFunc hwAddrFunc HWAddrFunc lastTime uint64 clockSequence uint16 @@ -137,13 +137,43 @@ type Gen struct { v7ClockSequence uint16 } +type GenOption func(*Gen) + // interface check -- build will fail if *Gen doesn't satisfy Generator var _ Generator = (*Gen)(nil) -// NewGen returns a new instance of Gen with some default values set. Most -// people should use this. -func NewGen() *Gen { - return NewGenWithHWAF(defaultHWAddrFunc) +// NewGen returns a new instance of Gen with default values if no options are +// passed. +func NewGen(opts ...GenOption) *Gen { + gen := &Gen{ + epochFunc: time.Now, + hwAddrFunc: defaultHWAddrFunc, + rand: rand.Reader, + } + + for _, opt := range opts { + opt(gen) + } + + return gen +} + +func WithHWAddrFunc(hwaf HWAddrFunc) GenOption { + return func(gen *Gen) { + gen.hwAddrFunc = hwaf + } +} + +func WithEpochFunc(epochf EpochFunc) GenOption { + return func(gen *Gen) { + gen.epochFunc = epochf + } +} + +func WithRandomReader(reader io.Reader) GenOption { + return func(gen *Gen) { + gen.rand = reader + } } // NewGenWithHWAF builds a new UUID generator with the HWAddrFunc provided. Most @@ -158,11 +188,7 @@ func NewGen() *Gen { // MAC address being used, you'll need to create a new generator using this // function. func NewGenWithHWAF(hwaf HWAddrFunc) *Gen { - return &Gen{ - epochFunc: time.Now, - hwAddrFunc: hwaf, - rand: rand.Reader, - } + return NewGen(WithHWAddrFunc(hwaf)) } // NewV1 returns a UUID based on the current timestamp and MAC address. diff --git a/generator_test.go b/generator_test.go index eaf8203..044399c 100644 --- a/generator_test.go +++ b/generator_test.go @@ -107,13 +107,11 @@ func testNewV1DifferentAcrossCalls(t *testing.T) { } func testNewV1StaleEpoch(t *testing.T) { - g := &Gen{ - epochFunc: func() time.Time { + g := NewGen( + WithEpochFunc(func() time.Time { return time.Unix(0, 0) - }, - hwAddrFunc: defaultHWAddrFunc, - rand: rand.Reader, - } + }), + ) u1, err := g.NewV1() if err != nil { t.Fatal(err) @@ -128,13 +126,11 @@ func testNewV1StaleEpoch(t *testing.T) { } func testNewV1FaultyRand(t *testing.T) { - g := &Gen{ - epochFunc: time.Now, - hwAddrFunc: defaultHWAddrFunc, - rand: &faultyReader{ + g := NewGen( + WithRandomReader(&faultyReader{ readToFail: 0, // fail immediately - }, - } + }), + ) u, err := g.NewV1() if err == nil { t.Fatalf("got %v, want error", u) @@ -145,13 +141,11 @@ func testNewV1FaultyRand(t *testing.T) { } func testNewV1MissingNetwork(t *testing.T) { - g := &Gen{ - epochFunc: time.Now, - hwAddrFunc: func() (net.HardwareAddr, error) { + g := NewGen( + WithHWAddrFunc(func() (net.HardwareAddr, error) { return []byte{}, fmt.Errorf("uuid: no hw address found") - }, - rand: rand.Reader, - } + }), + ) _, err := g.NewV1() if err != nil { t.Errorf("did not handle missing network interfaces: %v", err) @@ -159,15 +153,14 @@ func testNewV1MissingNetwork(t *testing.T) { } func testNewV1MissingNetworkFaultyRand(t *testing.T) { - g := &Gen{ - epochFunc: time.Now, - hwAddrFunc: func() (net.HardwareAddr, error) { + g := NewGen( + WithHWAddrFunc(func() (net.HardwareAddr, error) { return []byte{}, fmt.Errorf("uuid: no hw address found") - }, - rand: &faultyReader{ + }), + WithRandomReader(&faultyReader{ readToFail: 1, - }, - } + }), + ) u, err := g.NewV1() if err == nil { t.Errorf("did not error on faulty reader and missing network, got %v", u) @@ -252,13 +245,11 @@ func testNewV4DifferentAcrossCalls(t *testing.T) { } func testNewV4FaultyRand(t *testing.T) { - g := &Gen{ - epochFunc: time.Now, - hwAddrFunc: defaultHWAddrFunc, - rand: &faultyReader{ + g := NewGen( + WithRandomReader(&faultyReader{ readToFail: 0, // fail immediately - }, - } + }), + ) u, err := g.NewV4() if err == nil { t.Errorf("got %v, nil error", u) @@ -266,13 +257,14 @@ func testNewV4FaultyRand(t *testing.T) { } func testNewV4ShortRandomRead(t *testing.T) { - g := &Gen{ - epochFunc: time.Now, - hwAddrFunc: func() (net.HardwareAddr, error) { + g := NewGen( + WithHWAddrFunc(func() (net.HardwareAddr, error) { return []byte{}, fmt.Errorf("uuid: no hw address found") - }, - rand: bytes.NewReader([]byte{42}), - } + }), + WithRandomReader(&faultyReader{ + readToFail: 0, // fail immediately + }), + ) u, err := g.NewV4() if err == nil { t.Errorf("got %v, nil error", u) @@ -359,13 +351,11 @@ func testNewV6DifferentAcrossCalls(t *testing.T) { } func testNewV6StaleEpoch(t *testing.T) { - g := &Gen{ - epochFunc: func() time.Time { + g := NewGen( + WithEpochFunc(func() time.Time { return time.Unix(0, 0) - }, - hwAddrFunc: defaultHWAddrFunc, - rand: rand.Reader, - } + }), + ) u1, err := g.NewV6() if err != nil { t.Fatal(err) @@ -381,13 +371,11 @@ func testNewV6StaleEpoch(t *testing.T) { func testNewV6FaultyRand(t *testing.T) { t.Run("randomData", func(t *testing.T) { - g := &Gen{ - epochFunc: time.Now, - hwAddrFunc: defaultHWAddrFunc, - rand: &faultyReader{ + g := NewGen( + WithRandomReader(&faultyReader{ readToFail: 0, // fail immediately - }, - } + }), + ) u, err := g.NewV6() if err == nil { t.Fatalf("got %v, want error", u) @@ -398,13 +386,11 @@ func testNewV6FaultyRand(t *testing.T) { }) t.Run("clockSequence", func(t *testing.T) { - g := &Gen{ - epochFunc: time.Now, - hwAddrFunc: defaultHWAddrFunc, - rand: &faultyReader{ + g := NewGen( + WithRandomReader(&faultyReader{ readToFail: 1, // fail immediately - }, - } + }), + ) u, err := g.NewV6() if err == nil { t.Fatalf("got %v, want error", u) @@ -416,10 +402,9 @@ func testNewV6FaultyRand(t *testing.T) { } func testNewV6ShortRandomRead(t *testing.T) { - g := &Gen{ - epochFunc: time.Now, - rand: bytes.NewReader([]byte{42}), - } + g := NewGen( + WithRandomReader(bytes.NewReader([]byte{42})), + ) u, err := g.NewV6() if err == nil { t.Errorf("got %v, nil error", u) @@ -554,12 +539,11 @@ func makeTestNewV7DifferentAcrossCalls(p Precision) func(t *testing.T) { func makeTestNewV7StaleEpoch(p Precision) func(t *testing.T) { return func(t *testing.T) { - g := &Gen{ - epochFunc: func() time.Time { + g := NewGen( + WithEpochFunc(func() time.Time { return time.Unix(0, 0) - }, - rand: rand.Reader, - } + }), + ) u1, err := g.NewV7(p) if err != nil { t.Fatal(err) @@ -576,12 +560,11 @@ func makeTestNewV7StaleEpoch(p Precision) func(t *testing.T) { func makeTestNewV7FaultyRand(p Precision) func(t *testing.T) { return func(t *testing.T) { - g := &Gen{ - epochFunc: time.Now, - rand: &faultyReader{ + g := NewGen( + WithRandomReader(&faultyReader{ readToFail: 0, // fail immediately - }, - } + }), + ) u, err := g.NewV7(p) if err == nil { t.Errorf("got %v, nil error", u) @@ -591,10 +574,9 @@ func makeTestNewV7FaultyRand(p Precision) func(t *testing.T) { func makeTestNewV7ShortRandomRead(p Precision) func(t *testing.T) { return func(t *testing.T) { - g := &Gen{ - epochFunc: time.Now, - rand: bytes.NewReader([]byte{42}), - } + g := NewGen( + WithRandomReader(bytes.NewReader([]byte{42})), + ) u, err := g.NewV7(p) if err == nil { t.Errorf("got %v, nil error", u) diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..7a94d52 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/mlesar/uuid + +go 1.17 From b037f1baf7e1f0d418abda4a982b7b152d46c4a9 Mon Sep 17 00:00:00 2001 From: Matija Lesar Date: Fri, 25 Feb 2022 09:50:34 +0100 Subject: [PATCH 2/2] Removed go.mod --- go.mod | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 go.mod diff --git a/go.mod b/go.mod deleted file mode 100644 index 7a94d52..0000000 --- a/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/mlesar/uuid - -go 1.17