...

Source file src/github.com/sethvargo/go-password/password/generate_test.go

Documentation: github.com/sethvargo/go-password/password

     1  package password
     2  
     3  import (
     4  	"io"
     5  	"strings"
     6  	"sync/atomic"
     7  	"testing"
     8  )
     9  
    10  type (
    11  	MockReader struct {
    12  		Counter int64
    13  	}
    14  )
    15  
    16  const (
    17  	N = 10000
    18  )
    19  
    20  func (mr *MockReader) Read(data []byte) (int, error) {
    21  	for i := 0; i < len(data); i++ {
    22  		data[i] = byte(atomic.AddInt64(&mr.Counter, 1))
    23  	}
    24  	return len(data), nil
    25  }
    26  
    27  func testHasDuplicates(tb testing.TB, s string) bool {
    28  	found := make(map[rune]struct{}, len(s))
    29  	for _, ch := range s {
    30  		if _, ok := found[ch]; ok {
    31  			return true
    32  		}
    33  		found[ch] = struct{}{}
    34  	}
    35  	return false
    36  }
    37  
    38  func testGeneratorGenerate(t *testing.T, reader io.Reader) {
    39  	t.Parallel()
    40  
    41  	gen, err := NewGenerator(nil)
    42  	if reader != nil {
    43  		gen.reader = reader
    44  	}
    45  	if err != nil {
    46  		t.Fatal(err)
    47  	}
    48  
    49  	t.Run("exceeds_length", func(t *testing.T) {
    50  		t.Parallel()
    51  
    52  		if _, err := gen.Generate(0, 1, 0, false, false); err != ErrExceedsTotalLength {
    53  			t.Errorf("expected %q to be %q", err, ErrExceedsTotalLength)
    54  		}
    55  
    56  		if _, err := gen.Generate(0, 0, 1, false, false); err != ErrExceedsTotalLength {
    57  			t.Errorf("expected %q to be %q", err, ErrExceedsTotalLength)
    58  		}
    59  	})
    60  
    61  	t.Run("exceeds_letters_available", func(t *testing.T) {
    62  		t.Parallel()
    63  
    64  		if _, err := gen.Generate(1000, 0, 0, false, false); err != ErrLettersExceedsAvailable {
    65  			t.Errorf("expected %q to be %q", err, ErrLettersExceedsAvailable)
    66  		}
    67  	})
    68  
    69  	t.Run("exceeds_digits_available", func(t *testing.T) {
    70  		t.Parallel()
    71  
    72  		if _, err := gen.Generate(52, 11, 0, false, false); err != ErrDigitsExceedsAvailable {
    73  			t.Errorf("expected %q to be %q", err, ErrDigitsExceedsAvailable)
    74  		}
    75  	})
    76  
    77  	t.Run("exceeds_symbols_available", func(t *testing.T) {
    78  		t.Parallel()
    79  
    80  		if _, err := gen.Generate(52, 0, 31, false, false); err != ErrSymbolsExceedsAvailable {
    81  			t.Errorf("expected %q to be %q", err, ErrSymbolsExceedsAvailable)
    82  		}
    83  	})
    84  
    85  	t.Run("gen_lowercase", func(t *testing.T) {
    86  		t.Parallel()
    87  
    88  		for i := 0; i < N; i++ {
    89  			res, err := gen.Generate(i%len(LowerLetters), 0, 0, true, true)
    90  			if err != nil {
    91  				t.Error(err)
    92  			}
    93  
    94  			if res != strings.ToLower(res) {
    95  				t.Errorf("%q is not lowercase", res)
    96  			}
    97  		}
    98  	})
    99  
   100  	t.Run("gen_uppercase", func(t *testing.T) {
   101  		t.Parallel()
   102  
   103  		res, err := gen.Generate(1000, 0, 0, false, true)
   104  		if err != nil {
   105  			t.Error(err)
   106  		}
   107  
   108  		if res == strings.ToLower(res) {
   109  			t.Errorf("%q does not include uppercase", res)
   110  		}
   111  	})
   112  
   113  	t.Run("gen_no_repeats", func(t *testing.T) {
   114  		t.Parallel()
   115  
   116  		for i := 0; i < N; i++ {
   117  			res, err := gen.Generate(52, 10, 30, false, false)
   118  			if err != nil {
   119  				t.Error(err)
   120  			}
   121  
   122  			if testHasDuplicates(t, res) {
   123  				t.Errorf("%q should not have duplicates", res)
   124  			}
   125  		}
   126  	})
   127  }
   128  
   129  func TestGeneratorGenerate(t *testing.T) {
   130  	testGeneratorGenerate(t, nil)
   131  }
   132  
   133  func TestGenerator_Reader_Generate(t *testing.T) {
   134  	testGeneratorGenerate(t, &MockReader{})
   135  }
   136  
   137  func testGeneratorGenerateCustom(t *testing.T, reader io.Reader) {
   138  	t.Parallel()
   139  
   140  	gen, err := NewGenerator(&GeneratorInput{
   141  		LowerLetters: "abcde",
   142  		UpperLetters: "ABCDE",
   143  		Symbols:      "!@#$%",
   144  		Digits:       "01234",
   145  		Reader:       reader,
   146  	})
   147  	if err != nil {
   148  		t.Fatal(err)
   149  	}
   150  
   151  	for i := 0; i < N; i++ {
   152  		res, err := gen.Generate(52, 10, 10, false, true)
   153  		if err != nil {
   154  			t.Error(err)
   155  		}
   156  
   157  		if strings.Contains(res, "f") {
   158  			t.Errorf("%q should only contain lower letters abcde", res)
   159  		}
   160  
   161  		if strings.Contains(res, "F") {
   162  			t.Errorf("%q should only contain upper letters ABCDE", res)
   163  		}
   164  
   165  		if strings.Contains(res, "&") {
   166  			t.Errorf("%q should only include symbols !@#$%%", res)
   167  		}
   168  
   169  		if strings.Contains(res, "5") {
   170  			t.Errorf("%q should only contain digits 01234", res)
   171  		}
   172  	}
   173  }
   174  
   175  func TestGeneratorGenerateCustom(t *testing.T) {
   176  	testGeneratorGenerateCustom(t, nil)
   177  }
   178  
   179  func TestGenerator_Reader_Generate_Custom(t *testing.T) {
   180  	testGeneratorGenerateCustom(t, &MockReader{})
   181  }
   182  

View as plain text