1
0
mirror of https://github.com/oauth2-proxy/oauth2-proxy.git synced 2024-11-24 08:52:25 +02:00
oauth2-proxy/validator_test.go
Mike Bland 5f2df7167a Ensure watcher tests don't block during shutdown
These test failures from #93 inspired this change:
https://travis-ci.org/bitly/google_auth_proxy/jobs/62474406
https://travis-ci.org/bitly/google_auth_proxy/jobs/62474407

Both tests exhibited this pattern:
2015/05/13 22:10:54 validating: is xyzzy@example.com valid? false
2015/05/13 22:10:54 watching interrupted on event: "/tmp/test_auth_emails_300880185": CHMOD
2015/05/13 22:10:54 watching resumed for /tmp/test_auth_emails_300880185
2015/05/13 22:10:54 reloading after event: "/tmp/test_auth_emails_300880185": CHMOD
panic: test timed out after 1m0s

[snip]

goroutine 175 [chan send]:
github.com/bitly/google_auth_proxy.(*ValidatorTest).TearDown(0xc2080bc330)
        /home/travis/gopath/src/github.com/bitly/google_auth_proxy/validator_test.go:27 +0x43
github.com/bitly/google_auth_proxy.TestValidatorOverwriteEmailListViaRenameAndReplace(0xc2080f2480)
        /home/travis/gopath/src/github.com/bitly/google_auth_proxy/validator_watcher_test.go:103 +0x3b9

[snip]

goroutine 177 [chan send]:
github.com/bitly/google_auth_proxy.func·017()
        /home/travis/gopath/src/github.com/bitly/google_auth_proxy/validator_test.go:34 +0x41

I realized that the spurious CHMOD events were causing calls to
`func() { updated <- true }` (from validator_test.go:34), which caused
the goroutine running the watcher to block. At the same time,
ValidatorTest.TearDown was blocked by trying to send into the `done` channel.
The solution was to create a flag that ensured only one value was ever sent
into the update channel.
2015-05-13 18:48:39 -04:00

150 lines
3.7 KiB
Go

package main
import (
"io/ioutil"
"os"
"strings"
"testing"
)
type ValidatorTest struct {
auth_email_file *os.File
done chan bool
update_seen bool
}
func NewValidatorTest(t *testing.T) *ValidatorTest {
vt := &ValidatorTest{}
var err error
vt.auth_email_file, err = ioutil.TempFile("", "test_auth_emails_")
if err != nil {
t.Fatal("failed to create temp file: " + err.Error())
}
vt.done = make(chan bool)
return vt
}
func (vt *ValidatorTest) TearDown() {
vt.done <- true
os.Remove(vt.auth_email_file.Name())
}
func (vt *ValidatorTest) NewValidator(domains []string,
updated chan<- bool) func(string) bool {
return newValidatorImpl(domains, vt.auth_email_file.Name(),
vt.done, func() {
if vt.update_seen == false {
updated <- true
vt.update_seen = true
}
})
}
// This will close vt.auth_email_file.
func (vt *ValidatorTest) WriteEmails(t *testing.T, emails []string) {
defer vt.auth_email_file.Close()
vt.auth_email_file.WriteString(strings.Join(emails, "\n"))
if err := vt.auth_email_file.Close(); err != nil {
t.Fatal("failed to close temp file " +
vt.auth_email_file.Name() + ": " + err.Error())
}
}
func TestValidatorEmpty(t *testing.T) {
vt := NewValidatorTest(t)
defer vt.TearDown()
vt.WriteEmails(t, []string(nil))
domains := []string(nil)
validator := vt.NewValidator(domains, nil)
if validator("foo.bar@example.com") {
t.Error("nothing should validate when the email and " +
"domain lists are empty")
}
}
func TestValidatorSingleEmail(t *testing.T) {
vt := NewValidatorTest(t)
defer vt.TearDown()
vt.WriteEmails(t, []string{"foo.bar@example.com"})
domains := []string(nil)
validator := vt.NewValidator(domains, nil)
if !validator("foo.bar@example.com") {
t.Error("email should validate")
}
if validator("baz.quux@example.com") {
t.Error("email from same domain but not in list " +
"should not validate when domain list is empty")
}
}
func TestValidatorSingleDomain(t *testing.T) {
vt := NewValidatorTest(t)
defer vt.TearDown()
vt.WriteEmails(t, []string(nil))
domains := []string{"example.com"}
validator := vt.NewValidator(domains, nil)
if !validator("foo.bar@example.com") {
t.Error("email should validate")
}
if !validator("baz.quux@example.com") {
t.Error("email from same domain should validate")
}
}
func TestValidatorMultipleEmailsMultipleDomains(t *testing.T) {
vt := NewValidatorTest(t)
defer vt.TearDown()
vt.WriteEmails(t, []string{
"xyzzy@example.com",
"plugh@example.com",
})
domains := []string{"example0.com", "example1.com"}
validator := vt.NewValidator(domains, nil)
if !validator("foo.bar@example0.com") {
t.Error("email from first domain should validate")
}
if !validator("baz.quux@example1.com") {
t.Error("email from second domain should validate")
}
if !validator("xyzzy@example.com") {
t.Error("first email in list should validate")
}
if !validator("plugh@example.com") {
t.Error("second email in list should validate")
}
if validator("xyzzy.plugh@example.com") {
t.Error("email not in list that matches no domains " +
"should not validate")
}
}
func TestValidatorComparisonsAreCaseInsensitive(t *testing.T) {
vt := NewValidatorTest(t)
defer vt.TearDown()
vt.WriteEmails(t, []string{"Foo.Bar@Example.Com"})
domains := []string{"Frobozz.Com"}
validator := vt.NewValidator(domains, nil)
if !validator("foo.bar@example.com") {
t.Error("loaded email addresses are not lower-cased")
}
if !validator("Foo.Bar@Example.Com") {
t.Error("validated email addresses are not lower-cased")
}
if !validator("foo.bar@frobozz.com") {
t.Error("loaded domains are not lower-cased")
}
if !validator("foo.bar@Frobozz.Com") {
t.Error("validated domains are not lower-cased")
}
}