diff --git a/generators.go b/generators.go index fabf650..c7ad4e8 100644 --- a/generators.go +++ b/generators.go @@ -1,6 +1,9 @@ package nomino -import "errors" +import ( + "errors" + "math/rand" +) // Generator is a function that returns the "random" portion of the returned filename. // Technically, it doesn't necessarily need to be random, and could be based on time, or a counter, @@ -45,3 +48,20 @@ func MultiGeneratorInOrder(gens ...Generator) Generator { return st, err } } + +// MultiGeneratorRandomOrder allows the use of multiple generators. Each new invokation will use one of the generators randomly. +// If none are passed, the generator will always return ErrMissingGenerators. +func MultiGeneratorRandomOrder(gens ...Generator) Generator { + if len(gens) == 0 { + return missingGen + } + + if len(gens) == 1 { + return gens[0] + } + + return func(c *Config) (string, error) { + idx := rand.Int() % len(gens) + return gens[idx](c) + } +} diff --git a/generators_examples_test.go b/generators_examples_test.go index 31951f5..5efc4d8 100644 --- a/generators_examples_test.go +++ b/generators_examples_test.go @@ -7,18 +7,14 @@ import ( ) func ExampleWithGenerator_customGenerator() { - gen := func(*nomino.Config) (string, error) { + var gen nomino.Generator = func(*nomino.Config) (string, error) { return "hello", nil } - option := nomino.WithGenerator(gen) - str, _ := nomino.Make(nomino.NewConfig(option)) + str, _ := gen.Make() fmt.Println(str) - str, _ = nomino.Make(nomino.NewConfig( - option, - nomino.WithoutExtension(), - )) + str, _ = gen.Make(nomino.WithoutExtension()) fmt.Println(str) // Output: @@ -47,15 +43,14 @@ func ExampleMultiGeneratorInOrder() { return "goodbye", nil } gen := nomino.MultiGeneratorInOrder(gen1, gen2) - option := nomino.WithGenerator(gen) - str, _ := nomino.Make(nomino.NewConfig(option)) + str, _ := gen.Make() fmt.Println(str) - str, _ = nomino.Make(nomino.NewConfig(option)) + str, _ = gen.Make() fmt.Println(str) - str, _ = nomino.Make(nomino.NewConfig(option)) + str, _ = gen.Make() fmt.Println(str) // Output: @@ -63,3 +58,22 @@ func ExampleMultiGeneratorInOrder() { // goodbye.txt // hello.txt } + +func ExampleMultiGeneratorRandomOrder() { + gen1 := func(*nomino.Config) (string, error) { + return "hello", nil + } + gen2 := func(*nomino.Config) (string, error) { + return "goodbye", nil + } + gen := nomino.MultiGeneratorRandomOrder(gen1, gen2) + + str, _ := gen.Make() + fmt.Println(str) + + str, _ = gen.Make() + fmt.Println(str) + + str, _ = gen.Make() + fmt.Println(str) +} diff --git a/generators_test.go b/generators_test.go index 997d87c..f8a81fa 100644 --- a/generators_test.go +++ b/generators_test.go @@ -16,26 +16,34 @@ func TestWithGenerator(t *testing.T) { assert.Equal(t, "abc", st) } +const ( + out1 string = "abc" + out2 string = "def" +) + +var ( + outs = []string{out1, out2} + err1 = errors.New("oops") + gen1 Generator = func(*Config) (string, error) { return out1, nil } + gen2 Generator = func(*Config) (string, error) { return out2, nil } + gen3 Generator = func(*Config) (string, error) { return "", err1 } + gens = []Generator{gen1, gen2, gen3} +) + func TestMultiGeneratorInOrder(t *testing.T) { - st1 := "abc" - st2 := "def" - er1 := errors.New("oops") - g1 := func(*Config) (string, error) { return st1, nil } - g2 := func(*Config) (string, error) { return st2, nil } - g3 := func(*Config) (string, error) { return "", er1 } - g := MultiGeneratorInOrder(g1, g2, g3) + g := MultiGeneratorInOrder(gens...) st, err := g(nil) assert.NoError(t, err) - assert.Equal(t, st1, st) + assert.Equal(t, out1, st) st, err = g(nil) assert.NoError(t, err) - assert.Equal(t, st2, st) + assert.Equal(t, out2, st) st, err = g(nil) assert.Zero(t, st) - assert.ErrorIs(t, err, er1) + assert.ErrorIs(t, err, err1) st, err = g(nil) assert.NoError(t, err) - assert.Equal(t, st1, st) + assert.Equal(t, out1, st) } func TestMultiGeneratorInOrderOne(t *testing.T) { @@ -60,3 +68,39 @@ func TestMultiGeneratorInOrderMissing(t *testing.T) { assert.Zero(t, st) assert.ErrorIs(t, err, ErrMissingGenerators) } + +func TestMultiGeneratorRandomOrder(t *testing.T) { + g := MultiGeneratorRandomOrder(gens...) + for i := 0; i < 4; i++ { + st, err := g(nil) + if err != nil { + assert.Zero(t, st) + assert.ErrorIs(t, err, err1) + } else { + assert.Contains(t, outs, st) + } + } +} + +func TestMultiGeneratorRandomOrderOne(t *testing.T) { + st1 := "abc" + g1 := func(*Config) (string, error) { return st1, nil } + g := MultiGeneratorRandomOrder(g1) + + st, err := g(nil) + assert.NoError(t, err) + assert.Equal(t, st1, st) + st, err = g(nil) + assert.NoError(t, err) + assert.Equal(t, st1, st) +} + +func TestMultiGeneratorRandomOrderMissing(t *testing.T) { + g := MultiGeneratorRandomOrder() + st, err := g(nil) + assert.Zero(t, st) + assert.ErrorIs(t, err, ErrMissingGenerators) + st, err = g(nil) + assert.Zero(t, st) + assert.ErrorIs(t, err, ErrMissingGenerators) +}