diff --git a/password/generator.go b/password/generator.go index 0171af3..ea2bf86 100644 --- a/password/generator.go +++ b/password/generator.go @@ -68,16 +68,24 @@ func (g *generator) Generate() string { defer g.pool.Put(password) idx := 0 - fillPassword := func(count int, runes []rune) { - for ; count > 0 && idx < len(password); count-- { + fillPassword := func(runes []rune, count int) { + for ; idx < len(password) && count > 0; count-- { password[idx] = runes[g.rng.IntN(len(runes))] idx++ } } - fillPassword(g.minLowerCase, g.charsetCaseLower) - fillPassword(g.minUpperCase, g.charsetCaseUpper) - fillPassword(g.numSymbolsToGenerate(), g.charsetSymbols) - fillPassword(len(password)-idx, g.charsetNonSymbols) + if g.minLowerCase > 0 { + fillPassword(g.charsetCaseLower, g.minLowerCase) + } + if g.minUpperCase > 0 { + fillPassword(g.charsetCaseUpper, g.minUpperCase) + } + if numSymbols := g.numSymbolsToGenerate(); numSymbols > 0 { + fillPassword(g.charsetSymbols, numSymbols) + } + if remainingChars := len(password) - idx; remainingChars > 0 { + fillPassword(g.charsetNonSymbols, remainingChars) + } // shuffle it all g.rng.Shuffle(len(password), func(i, j int) { @@ -119,15 +127,15 @@ func (g *generator) sanitize() (Generator, error) { if g.minUpperCase > g.numChars { return nil, ErrMinUpperCaseTooLong } + if g.minSymbols > 0 && len(g.charsetSymbols) == 0 { + return nil, ErrNoSymbolsInCharset + } if g.minSymbols > g.numChars { return nil, ErrMinSymbolsTooLong } if g.minLowerCase+g.minUpperCase+g.minSymbols > g.numChars { return nil, ErrRequirementsNotMet } - if g.minSymbols > 0 && len(g.charsetSymbols) == 0 { - return nil, ErrNoSymbolsInCharset - } return g, nil } diff --git a/password/generator_test.go b/password/generator_test.go index 9aea4ed..ef4102c 100644 --- a/password/generator_test.go +++ b/password/generator_test.go @@ -2,7 +2,7 @@ package password import ( "fmt" - "strings" + "slices" "testing" "unicode" @@ -42,19 +42,19 @@ func TestGenerator_Generate(t *testing.T) { "uCFmDFDAoLZY", "pMgNoVa9z5Vv", } - sb := strings.Builder{} + var actualPasswords []string for idx := 0; idx < 100; idx++ { password := g.Generate() assert.NotEmpty(t, password) if idx < len(expectedPasswords) { + actualPasswords = append(actualPasswords, password) assert.Equal(t, expectedPasswords[idx], password) - if expectedPasswords[idx] != password { - sb.WriteString(fmt.Sprintf("%#v,\n", password)) - } } } - if sb.Len() > 0 { - fmt.Println(sb.String()) + if !slices.Equal(expectedPasswords, actualPasswords) { + for _, pw := range actualPasswords { + fmt.Printf("%#v,\n", pw) + } } } @@ -81,15 +81,13 @@ func TestGenerator_Generate_WithAMixOfEverything(t *testing.T) { "bVrPjBRC 0 { - fmt.Println(sb.String()) + if !slices.Equal(expectedPasswords, actualPasswords) { + for _, pw := range actualPasswords { + fmt.Printf("%#v,\n", pw) + } } } @@ -126,22 +126,22 @@ func TestGenerator_Generate_WithSymbols(t *testing.T) { "-e3a6cda4#!1", "162e6bb#ee53", } - sb := strings.Builder{} + var actualPasswords []string for idx := 0; idx < 100; idx++ { password := g.Generate() assert.NotEmpty(t, password) if idx < len(expectedPasswords) { + actualPasswords = append(actualPasswords, password) assert.Equal(t, expectedPasswords[idx], password) - if expectedPasswords[idx] != password { - sb.WriteString(fmt.Sprintf("%#v,\n", password)) - } } numSymbols := getNumSymbols(password) assert.True(t, numSymbols >= 0 && numSymbols <= 3, password) } - if sb.Len() > 0 { - fmt.Println(sb.String()) + if !slices.Equal(expectedPasswords, actualPasswords) { + for _, pw := range actualPasswords { + fmt.Printf("%#v,\n", pw) + } } })