@@ -5,6 +5,8 @@ import (
55 "os"
66 "strings"
77 "testing"
8+
9+ . "github.com/onsi/gomega"
810)
911
1012type ValidatorTest struct {
@@ -59,118 +61,50 @@ func (vt *ValidatorTest) WriteEmails(t *testing.T, emails []string) {
5961 }
6062}
6163
62−func TestValidatorEmpty(t *testing.T) {
63− vt := NewValidatorTest(t)
64− defer vt.TearDown()
65−
66− vt.WriteEmails(t, []string(nil))
67− domains := []string(nil)
68− validator := vt.NewValidator(domains, nil)
69−
70− if validator("foo.bar@example.com") {
71− t.Error("nothing should validate when the email and " +
72− "domain lists are empty")
73− }
74−}
75−
76−func TestValidatorSingleEmail(t *testing.T) {
77− vt := NewValidatorTest(t)
78− defer vt.TearDown()
79−
80− vt.WriteEmails(t, []string{"foo.bar@example.com"})
81− domains := []string(nil)
82− validator := vt.NewValidator(domains, nil)
83−
84− if !validator("foo.bar@example.com") {
85− t.Error("email should validate")
86− }
87− if validator("baz.quux@example.com") {
88− t.Error("email from same domain but not in list " +
89− "should not validate when domain list is empty")
90− }
91−}
92−
93−func TestValidatorSingleDomain(t *testing.T) {
94− vt := NewValidatorTest(t)
95− defer vt.TearDown()
96−
97− vt.WriteEmails(t, []string(nil))
98− domains := []string{"example.com"}
99− validator := vt.NewValidator(domains, nil)
100−
101− if !validator("foo.bar@example.com") {
102− t.Error("email should validate")
103− }
104− if !validator("baz.quux@example.com") {
105− t.Error("email from same domain should validate")
106− }
107−}
108−
109−func TestValidatorMultipleEmailsMultipleDomains(t *testing.T) {
110− vt := NewValidatorTest(t)
111− defer vt.TearDown()
112−
113− vt.WriteEmails(t, []string{
114− "xyzzy@example.com",
115− "plugh@example.com",
116− })
117− domains := []string{"example0.com", "example1.com"}
118− validator := vt.NewValidator(domains, nil)
119−
120− if !validator("foo.bar@example0.com") {
121− t.Error("email from first domain should validate")
122− }
123− if !validator("baz.quux@example1.com") {
124− t.Error("email from second domain should validate")
125− }
126− if !validator("xyzzy@example.com") {
127− t.Error("first email in list should validate")
128− }
129− if !validator("plugh@example.com") {
130− t.Error("second email in list should validate")
131− }
132− if validator("xyzzy.plugh@example.com") {
133− t.Error("email not in list that matches no domains " +
134− "should not validate")
135− }
136−}
137−
138−func TestValidatorComparisonsAreCaseInsensitive(t *testing.T) {
139− vt := NewValidatorTest(t)
140− defer vt.TearDown()
141−
142− vt.WriteEmails(t, []string{"Foo.Bar@Example.Com"})
143− domains := []string{"Frobozz.Com"}
144− validator := vt.NewValidator(domains, nil)
145−
146− if !validator("foo.bar@example.com") {
147− t.Error("loaded email addresses are not lower-cased")
148− }
149− if !validator("Foo.Bar@Example.Com") {
150− t.Error("validated email addresses are not lower-cased")
151− }
152− if !validator("foo.bar@frobozz.com") {
153− t.Error("loaded domains are not lower-cased")
154− }
155− if !validator("foo.bar@Frobozz.Com") {
156− t.Error("validated domains are not lower-cased")
64+func TestValidatorOverwriteEmailListDirectly(t *testing.T) {
65+ testCasesPreUpdate := []struct {
66+ name string
67+ email string
68+ expectedAuthZ bool
69+ }{
70+ {
71+ name: "FirstEmailInList",
72+ email: "xyzzy@example.com",
73+ expectedAuthZ: true,
74+ },
75+ {
76+ name: "SecondEmailInList",
77+ email: "plugh@example.com",
78+ expectedAuthZ: true,
79+ },
80+ {
81+ name: "EmailNotInListThatMatchesNoDomains",
82+ email: "xyzzy.plugh@example.com",
83+ expectedAuthZ: false,
84+ },
15785 }
158−}
159−
160−func TestValidatorIgnoreSpacesInAuthEmails(t *testing.T) {
161− vt := NewValidatorTest(t)
162− defer vt.TearDown()
163−
164− vt.WriteEmails(t, []string{" foo.bar@example.com "})
165− domains := []string(nil)
166− validator := vt.NewValidator(domains, nil)
167−
168− if !validator("foo.bar@example.com") {
169− t.Error("email should validate")
86+ testCasesPostUpdate := []struct {
87+ name string
88+ email string
89+ expectedAuthZ bool
90+ }{
91+ {
92+ name: "email removed from list",
93+ email: "xyzzy@example.com",
94+ expectedAuthZ: false,
95+ },
96+ {
97+ name: "email retained in list",
98+ email: "plugh@example.com",
99+ expectedAuthZ: true,
100+ },
101+ {
102+ name: "email added to list",
103+ email: "xyzzy.plugh@example.com",
104+ expectedAuthZ: true,
105+ },
170106 }
171−}
172107
173−func TestValidatorOverwriteEmailListDirectly(t *testing.T) {
174108 vt := NewValidatorTest(t)
175109 defer vt.TearDown()
176110
@@ -178,19 +112,15 @@ func TestValidatorOverwriteEmailListDirectly(t *testing.T) {
178112 "xyzzy@example.com",
179113 "plugh@example.com",
180114 })
181− domains := []string(nil)
182115 updated := make(chan bool)
183− validator := vt.NewValidator(domains, updated)
116+ validator := vt.NewValidator([]string(nil), updated)
184117
185− if !validator("xyzzy@example.com") {
186− t.Error("first email in list should validate")
187− }
188− if !validator("plugh@example.com") {
189− t.Error("second email in list should validate")
190− }
191− if validator("xyzzy.plugh@example.com") {
192− t.Error("email not in list that matches no domains " +
193− "should not validate")
118+ for _, tc := range testCasesPreUpdate {
119+ t.Run(tc.name, func(t *testing.T) {
120+ g := NewWithT(t)
121+ authorized := validator(tc.email)
122+ g.Expect(authorized).To(Equal(tc.expectedAuthZ))
123+ })
194124 }
195125
196126 vt.WriteEmails(t, []string{
@@ -199,13 +129,259 @@ func TestValidatorOverwriteEmailListDirectly(t *testing.T) {
199129 })
200130 <-updated
201131
202− if validator("xyzzy@example.com") {
203− t.Error("email removed from list should not validate")
132+ for _, tc := range testCasesPostUpdate {
133+ t.Run(tc.name, func(t *testing.T) {
134+ g := NewWithT(t)
135+ authorized := validator(tc.email)
136+ g.Expect(authorized).To(Equal(tc.expectedAuthZ))
137+ })
204138 }
205− if !validator("plugh@example.com") {
206− t.Error("email retained in list should validate")
139+}
140+
141+func TestValidatorCases(t *testing.T) {
142+ testCases := []struct {
143+ name string
144+ allowedEmails []string
145+ allowedDomains []string
146+ email string
147+ expectedAuthZ bool
148+ }{
149+ {
150+ name: "EmailNotInCorrect1stSubDomainsNotInEmails",
151+ allowedEmails: []string{"xyzzy@example.com", "plugh@example.com"},
152+ allowedDomains: []string{".example0.com", ".example1.com"},
153+ email: "foo.bar@example0.com",
154+ expectedAuthZ: false,
155+ },
156+ {
157+ name: "EmailInFirstDomain",
158+ allowedEmails: []string{"xyzzy@example.com", "plugh@example.com"},
159+ allowedDomains: []string{".example0.com", ".example1.com"},
160+ email: "foo@bar.example0.com",
161+ expectedAuthZ: true,
162+ },
163+ {
164+ name: "EmailNotInCorrect2ndSubDomainsNotInEmails",
165+ allowedEmails: []string{"xyzzy@example.com", "plugh@example.com"},
166+ allowedDomains: []string{".example0.com", ".example1.com"},
167+ email: "baz.quux@example1.com",
168+ expectedAuthZ: false,
169+ },
170+ {
171+ name: "EmailInSecondDomain",
172+ allowedEmails: []string{"xyzzy@example.com", "plugh@example.com"},
173+ allowedDomains: []string{".example0.com", ".example1.com"},
174+ email: "baz@quux.example1.com",
175+ expectedAuthZ: true,
176+ },
177+ {
178+ name: "EmailInFirstEmailList",
179+ allowedEmails: []string{"xyzzy@example.com", "plugh@example.com"},
180+ allowedDomains: []string{".example0.com", ".example1.com"},
181+ email: "xyzzy@example.com",
182+ expectedAuthZ: true,
183+ },
184+ {
185+ name: "EmailNotInDomainsNotInEmails",
186+ allowedEmails: []string{"xyzzy@example.com", "plugh@example.com"},
187+ allowedDomains: []string{".example0.com", ".example1.com"},
188+ email: "xyzzy.plugh@example.com",
189+ expectedAuthZ: false,
190+ },
191+ {
192+ name: "EmailInLastEmailList",
193+ allowedEmails: []string{"xyzzy@example.com", "plugh@example.com"},
194+ allowedDomains: []string{".example0.com", ".example1.com"},
195+ email: "plugh@example.com",
196+ expectedAuthZ: true,
197+ },
198+ {
199+ name: "EmailIn1stSubdomain",
200+ allowedEmails: nil,
201+ allowedDomains: []string{"us.example.com", "de.example.com", "example.com"},
202+ email: "xyzzy@us.example.com",
203+ expectedAuthZ: true,
204+ },
205+ {
206+ name: "EmailIn2ndSubdomain",
207+ allowedEmails: nil,
208+ allowedDomains: []string{"us.example.com", "de.example.com", "example.com"},
209+ email: "xyzzy@de.example.com",
210+ expectedAuthZ: true,
211+ },
212+ {
213+ name: "EmailNotInAnySubdomain",
214+ allowedEmails: nil,
215+ allowedDomains: []string{"us.example.com", "de.example.com", "example.com"},
216+ email: "global@au.example.com",
217+ expectedAuthZ: false,
218+ },
219+ {
220+ name: "EmailInLastSubdomain",
221+ allowedEmails: nil,
222+ allowedDomains: []string{"us.example.com", "de.example.com", "example.com"},
223+ email: "xyzzy@example.com",
224+ expectedAuthZ: true,
225+ },
226+ {
227+ name: "EmailDomainNotCompletelyMatch",
228+ allowedEmails: nil,
229+ allowedDomains: []string{".example.com", ".example1.com"},
230+ email: "something@fooexample.com",
231+ expectedAuthZ: false,
232+ },
233+ {
234+ name: "HackerExtraDomainPrefix1",
235+ allowedEmails: nil,
236+ allowedDomains: []string{".mycompany.com"},
237+ email: "something@evilhackmycompany.com",
238+ expectedAuthZ: false,
239+ },
240+ {
241+ name: "HackerExtraDomainPrefix2",
242+ allowedEmails: nil,
243+ allowedDomains: []string{".mycompany.com"},
244+ email: "something@ext.evilhackmycompany.com",
245+ expectedAuthZ: false,
246+ },
247+ {
248+ name: "EmptyDomainAndEmailList",
249+ allowedEmails: []string(nil),
250+ allowedDomains: []string(nil),
251+ email: "foo.bar@example.com",
252+ expectedAuthZ: false,
253+ },
254+ {
255+ name: "EmailMatchWithAllowedEmails",
256+ email: "foo.bar@example.com",
257+ allowedEmails: []string{"foo.bar@example.com"},
258+ allowedDomains: []string{"example.com"},
259+ expectedAuthZ: true,
260+ },
261+ {
262+ name: "EmailFromSameDomainButNotInList",
263+ email: "baz.quux@example.com",
264+ allowedEmails: []string{"foo.bar@example.com"},
265+ allowedDomains: []string(nil),
266+ expectedAuthZ: false,
267+ },
268+ {
269+ name: "EmailMatchOnDomain",
270+ email: "foo.bar@example.com",
271+ allowedEmails: []string(nil),
272+ allowedDomains: []string{"example.com"},
273+ expectedAuthZ: true,
274+ },
275+ {
276+ name: "EmailMatchOnDomain2",
277+ email: "baz.quux@example.com",
278+ allowedEmails: []string(nil),
279+ allowedDomains: []string{"example.com"},
280+ expectedAuthZ: true,
281+ },
282+ {
283+ name: "EmailFromFirstDomainShouldValidate",
284+ email: "foo.bar@example0.com",
285+ allowedEmails: []string{"Foo.Bar@Example.Com"},
286+ allowedDomains: []string{"example0.com", "example1.com"},
287+ expectedAuthZ: true,
288+ },
289+ {
290+ name: "EmailFromSecondDomainShouldValidate",
291+ email: "baz.quux@example1.com",
292+ allowedEmails: []string{"Foo.Bar@Example.Com"},
293+ allowedDomains: []string{"example0.com", "example1.com"},
294+ expectedAuthZ: true,
295+ },
296+ {
297+ name: "FirstEmailInListShouldValidate",
298+ email: "xyzzy@example.com",
299+ allowedEmails: []string{"xyzzy@example.com", "plugh@example.com"},
300+ allowedDomains: []string{"example0.com", "example1.com"},
301+ expectedAuthZ: true,
302+ },
303+ {
304+ name: "SecondEmailInListShouldValidate",
305+ email: "plugh@example.com",
306+ allowedEmails: []string{"xyzzy@example.com", "plugh@example.com"},
307+ allowedDomains: []string{"example0.com", "example1.com"},
308+ expectedAuthZ: true,
309+ },
310+ {
311+ name: "EmailNotInListThatMatchesNoDomains ",
312+ email: "xyzzy.plugh@example.com",
313+ allowedEmails: []string{"xyzzy@example.com", "plugh@example.com"},
314+ allowedDomains: []string{"example0.com", "example1.com"},
315+ expectedAuthZ: false,
316+ },
317+ {
318+ name: "LoadedEmailAddressesAreNotLowerCased",
319+ email: "foo.bar@example.com",
320+ allowedEmails: []string{"Foo.Bar@Example.Com"},
321+ allowedDomains: []string{"Frobozz.Com"},
322+ expectedAuthZ: true,
323+ },
324+ {
325+ name: "ValidatedEmailAddressesAreNotLowerCased",
326+ email: "Foo.Bar@Example.Com",
327+ allowedEmails: []string{"Foo.Bar@Example.Com"},
328+ allowedDomains: []string{"Frobozz.Com"},
329+ expectedAuthZ: true,
330+ },
331+ {
332+ name: "LoadedDomainsAreNotLowerCased",
333+ email: "foo.bar@frobozz.com",
334+ allowedEmails: []string{"Foo.Bar@Example.Com"},
335+ allowedDomains: []string{"Frobozz.Com"},
336+ expectedAuthZ: true,
337+ },
338+ {
339+ name: "ValidatedDomainsAreNotLowerCased",
340+ email: "foo.bar@Frobozz.Com",
341+ allowedEmails: []string{"Foo.Bar@Example.Com"},
342+ allowedDomains: []string{"Frobozz.Com"},
343+ expectedAuthZ: true,
344+ },
345+ {
346+ name: "IgnoreSpacesInAuthEmails",
347+ email: "foo.bar@example.com",
348+ allowedEmails: []string{" foo.bar@example.com "},
349+ allowedDomains: []string(nil),
350+ expectedAuthZ: true,
351+ },
352+ {
353+ name: "IgnorePrefixSpacesInAuthEmails",
354+ email: "foo.bar@example.com",
355+ allowedEmails: []string{" foo.bar@example.com"},
356+ allowedDomains: []string(nil),
357+ expectedAuthZ: true,
358+ },
359+ {
360+ name: "CheckForEqualityNotSuffix",
361+ email: "foo@evilcompany.com",
362+ allowedEmails: []string(nil),
363+ allowedDomains: []string{".company.com"},
364+ expectedAuthZ: false,
365+ },
366+ {
367+ name: "CheckForEqualityNotSuffix2",
368+ email: "foo@evilcompany.com",
369+ allowedEmails: []string(nil),
370+ allowedDomains: []string{"company.com"},
371+ expectedAuthZ: false,
372+ },
207373 }
208− if !validator("xyzzy.plugh@example.com") {
209− t.Error("email added to list should validate")
374+
375+ for _, tc := range testCases {
376+ t.Run(tc.name, func(t *testing.T) {
377+ vt := NewValidatorTest(t)
378+ defer vt.TearDown()
379+
380+ g := NewWithT(t)
381+ vt.WriteEmails(t, tc.allowedEmails)
382+ validator := vt.NewValidator(tc.allowedDomains, nil)
383+ authorized := validator(tc.email)
384+ g.Expect(authorized).To(Equal(tc.expectedAuthZ))
385+ })
210386 }
211387}