1package plugin 2 3import ( 4 "context" 5 "fmt" 6 "regexp" 7 "testing" 8) 9 10func TestGeneratePassword(t *testing.T) { 11 type testCase struct { 12 passConf passwordConf 13 generator passwordGenerator 14 15 passwordAssertion func(t *testing.T, password string) 16 expectErr bool 17 } 18 19 tests := map[string]testCase{ 20 "missing configs": { 21 passConf: passwordConf{ 22 Length: 0, 23 Formatter: "", 24 PasswordPolicy: "", 25 }, 26 generator: nil, 27 28 passwordAssertion: assertNoPassword, 29 expectErr: true, 30 }, 31 "policy failure": { 32 passConf: passwordConf{ 33 PasswordPolicy: "testpolicy", 34 }, 35 generator: makePasswordGenerator("", fmt.Errorf("test error")), 36 passwordAssertion: assertNoPassword, 37 expectErr: true, 38 }, 39 "successful policy": { 40 passConf: passwordConf{ 41 PasswordPolicy: "testpolicy", 42 }, 43 generator: makePasswordGenerator("testpassword", nil), 44 passwordAssertion: assertPassword("testpassword"), 45 expectErr: false, 46 }, 47 "deprecated with no formatter": { 48 passConf: passwordConf{ 49 Length: 50, 50 }, 51 passwordAssertion: assertPasswordRegex( 52 fmt.Sprintf("^%s[a-zA-Z0-9]{%d}$", 53 regexp.QuoteMeta(passwordComplexityPrefix), 54 50-len(passwordComplexityPrefix), 55 ), 56 ), 57 expectErr: false, 58 }, 59 "deprecated with formatter prefix": { 60 passConf: passwordConf{ 61 Length: 50, 62 Formatter: "foobar{{PASSWORD}}", 63 }, 64 passwordAssertion: assertPasswordRegex("^foobar[a-zA-Z0-9]{44}$"), 65 expectErr: false, 66 }, 67 "deprecated with formatter suffix": { 68 passConf: passwordConf{ 69 Length: 50, 70 Formatter: "{{PASSWORD}}foobar", 71 }, 72 passwordAssertion: assertPasswordRegex("^[a-zA-Z0-9]{44}foobar$"), 73 expectErr: false, 74 }, 75 "deprecated with formatter prefix and suffix": { 76 passConf: passwordConf{ 77 Length: 50, 78 Formatter: "foo{{PASSWORD}}bar", 79 }, 80 passwordAssertion: assertPasswordRegex("^foo[a-zA-Z0-9]{44}bar$"), 81 expectErr: false, 82 }, 83 } 84 85 for name, test := range tests { 86 t.Run(name, func(t *testing.T) { 87 password, err := GeneratePassword(context.Background(), test.passConf, test.generator) 88 if test.expectErr && err == nil { 89 t.Fatalf("err expected, got nil") 90 } 91 if !test.expectErr && err != nil { 92 t.Fatalf("no error expected, got: %s", err) 93 } 94 test.passwordAssertion(t, password) 95 }) 96 } 97} 98 99func assertNoPassword(t *testing.T, password string) { 100 t.Helper() 101 if password != "" { 102 t.Fatalf("password should be empty") 103 } 104} 105 106func assertPassword(expectedPassword string) func(*testing.T, string) { 107 return func(t *testing.T, password string) { 108 t.Helper() 109 if password != expectedPassword { 110 t.Fatalf("Expected password %q but was %q", expectedPassword, password) 111 } 112 } 113} 114 115func assertPasswordRegex(rawRegex string) func(*testing.T, string) { 116 re := regexp.MustCompile(rawRegex) 117 return func(t *testing.T, password string) { 118 t.Helper() 119 if !re.MatchString(password) { 120 t.Fatalf("Password %q does not match regexp %q", password, rawRegex) 121 } 122 } 123} 124 125type fakeGenerator struct { 126 password string 127 err error 128} 129 130func (g fakeGenerator) GeneratePasswordFromPolicy(_ context.Context, _ string) (password string, err error) { 131 return g.password, g.err 132} 133 134func makePasswordGenerator(returnedPass string, returnedErr error) passwordGenerator { 135 return fakeGenerator{ 136 password: returnedPass, 137 err: returnedErr, 138 } 139} 140