package creds import ( "errors" "testing" "github.com/stretchr/testify/assert" ) type testCredHelper struct { fillErr error approveErr error rejectErr error fill []Creds approve []Creds reject []Creds } func newTestCredHelper() *testCredHelper { return &testCredHelper{ fill: make([]Creds, 0), approve: make([]Creds, 0), reject: make([]Creds, 0), } } func (h *testCredHelper) Fill(input Creds) (Creds, error) { h.fill = append(h.fill, input) return input, h.fillErr } func (h *testCredHelper) Approve(creds Creds) error { h.approve = append(h.approve, creds) return h.approveErr } func (h *testCredHelper) Reject(creds Creds) error { h.reject = append(h.reject, creds) return h.rejectErr } func TestCredHelperSetNoErrors(t *testing.T) { cache := NewCredentialCacher() helper1 := newTestCredHelper() helper2 := newTestCredHelper() helpers := NewCredentialHelpers([]CredentialHelper{cache, helper1, helper2}) creds := Creds{"protocol": []string{"https"}, "host": []string{"example.com"}} out, err := helpers.Fill(creds) assert.Nil(t, err) assert.Equal(t, creds, out) assert.Equal(t, 1, len(helper1.fill)) assert.Equal(t, 0, len(helper2.fill)) // calling Fill() with empty cache out, err = helpers.Fill(creds) assert.Nil(t, err) assert.Equal(t, creds, out) assert.Equal(t, 2, len(helper1.fill)) assert.Equal(t, 0, len(helper2.fill)) credsWithPass := Creds{ "protocol": []string{"https"}, "host": []string{"example.com"}, "username": []string{"foo"}, "password": []string{"bar"}, } assert.Nil(t, helpers.Approve(credsWithPass)) assert.Equal(t, 1, len(helper1.approve)) assert.Equal(t, 0, len(helper2.approve)) // calling Approve() again is cached assert.Nil(t, helpers.Approve(credsWithPass)) assert.Equal(t, 1, len(helper1.approve)) assert.Equal(t, 0, len(helper2.approve)) // access cache for i := 0; i < 3; i++ { out, err = helpers.Fill(creds) assert.Nil(t, err) assert.Equal(t, credsWithPass, out) assert.Equal(t, 2, len(helper1.fill)) assert.Equal(t, 0, len(helper2.fill)) } assert.Nil(t, helpers.Reject(creds)) assert.Equal(t, 1, len(helper1.reject)) assert.Equal(t, 0, len(helper2.reject)) // Reject() is never cached assert.Nil(t, helpers.Reject(creds)) assert.Equal(t, 2, len(helper1.reject)) assert.Equal(t, 0, len(helper2.reject)) // calling Fill() with empty cache out, err = helpers.Fill(creds) assert.Nil(t, err) assert.Equal(t, creds, out) assert.Equal(t, 3, len(helper1.fill)) assert.Equal(t, 0, len(helper2.fill)) } func TestCredHelperSetFillError(t *testing.T) { cache := NewCredentialCacher() helper1 := newTestCredHelper() helper2 := newTestCredHelper() helpers := NewCredentialHelpers([]CredentialHelper{cache, helper1, helper2}) creds := Creds{"protocol": []string{"https"}, "host": []string{"example.com"}} helper1.fillErr = errors.New("boom") out, err := helpers.Fill(creds) assert.Nil(t, err) assert.Equal(t, creds, out) assert.Equal(t, 1, len(helper1.fill)) assert.Equal(t, 1, len(helper2.fill)) assert.Nil(t, helpers.Approve(creds)) assert.Equal(t, 0, len(helper1.approve)) assert.Equal(t, 1, len(helper2.approve)) // Fill() with cache for i := 0; i < 3; i++ { out, err = helpers.Fill(creds) assert.Nil(t, err) assert.Equal(t, creds, out) assert.Equal(t, 1, len(helper1.fill)) assert.Equal(t, 1, len(helper2.fill)) } assert.Nil(t, helpers.Reject(creds)) assert.Equal(t, 0, len(helper1.reject)) assert.Equal(t, 1, len(helper2.reject)) // Fill() with empty cache out, err = helpers.Fill(creds) assert.Nil(t, err) assert.Equal(t, creds, out) assert.Equal(t, 1, len(helper1.fill)) // still skipped assert.Equal(t, 2, len(helper2.fill)) } func TestCredHelperSetApproveError(t *testing.T) { cache := NewCredentialCacher() helper1 := newTestCredHelper() helper2 := newTestCredHelper() helpers := NewCredentialHelpers([]CredentialHelper{cache, helper1, helper2}) creds := Creds{"protocol": []string{"https"}, "host": []string{"example.com"}} approveErr := errors.New("boom") helper1.approveErr = approveErr out, err := helpers.Fill(creds) assert.Nil(t, err) assert.Equal(t, creds, out) assert.Equal(t, 1, len(helper1.fill)) assert.Equal(t, 0, len(helper2.fill)) assert.Equal(t, approveErr, helpers.Approve(creds)) assert.Equal(t, 1, len(helper1.approve)) assert.Equal(t, 0, len(helper2.approve)) // cache is never set out, err = helpers.Fill(creds) assert.Nil(t, err) assert.Equal(t, creds, out) assert.Equal(t, 2, len(helper1.fill)) assert.Equal(t, 0, len(helper2.fill)) assert.Nil(t, helpers.Reject(creds)) assert.Equal(t, 1, len(helper1.reject)) assert.Equal(t, 0, len(helper2.reject)) } func TestCredHelperSetFillAndApproveError(t *testing.T) { cache := NewCredentialCacher() helper1 := newTestCredHelper() helper2 := newTestCredHelper() helpers := NewCredentialHelpers([]CredentialHelper{cache, helper1, helper2}) creds := Creds{"protocol": []string{"https"}, "host": []string{"example.com"}} credErr := errors.New("boom") helper1.fillErr = credErr helper2.approveErr = credErr out, err := helpers.Fill(creds) assert.Nil(t, err) assert.Equal(t, creds, out) assert.Equal(t, 1, len(helper1.fill)) assert.Equal(t, 1, len(helper2.fill)) assert.Equal(t, credErr, helpers.Approve(creds)) assert.Equal(t, 0, len(helper1.approve)) // skipped assert.Equal(t, 0, len(helper1.reject)) // skipped assert.Equal(t, 1, len(helper2.approve)) // never approved, so cache is empty out, err = helpers.Fill(creds) assert.Nil(t, err) assert.Equal(t, creds, out) assert.Equal(t, 1, len(helper1.fill)) // still skipped assert.Equal(t, 2, len(helper2.fill)) } func TestCredHelperSetRejectError(t *testing.T) { cache := NewCredentialCacher() helper1 := newTestCredHelper() helper2 := newTestCredHelper() helpers := NewCredentialHelpers([]CredentialHelper{cache, helper1, helper2}) creds := Creds{"protocol": []string{"https"}, "host": []string{"example.com"}} rejectErr := errors.New("boom") helper1.rejectErr = rejectErr out, err := helpers.Fill(creds) assert.Nil(t, err) assert.Equal(t, creds, out) assert.Equal(t, 1, len(helper1.fill)) assert.Equal(t, 0, len(helper2.fill)) assert.Nil(t, helpers.Approve(creds)) assert.Equal(t, 1, len(helper1.approve)) assert.Equal(t, 0, len(helper2.approve)) // Fill() with cache out, err = helpers.Fill(creds) assert.Nil(t, err) assert.Equal(t, creds, out) assert.Equal(t, 1, len(helper1.fill)) assert.Equal(t, 0, len(helper2.fill)) assert.Equal(t, rejectErr, helpers.Reject(creds)) assert.Equal(t, 1, len(helper1.reject)) assert.Equal(t, 0, len(helper2.reject)) // failed Reject() still clears cache out, err = helpers.Fill(creds) assert.Nil(t, err) assert.Equal(t, creds, out) assert.Equal(t, 2, len(helper1.fill)) assert.Equal(t, 0, len(helper2.fill)) } func TestCredHelperSetAllFillErrors(t *testing.T) { cache := NewCredentialCacher() helper1 := newTestCredHelper() helper2 := newTestCredHelper() helpers := NewCredentialHelpers([]CredentialHelper{cache, helper1, helper2}) creds := Creds{"protocol": []string{"https"}, "host": []string{"example.com"}} helper1.fillErr = errors.New("boom 1") helper2.fillErr = errors.New("boom 2") out, err := helpers.Fill(creds) if assert.NotNil(t, err) { assert.Equal(t, "credential fill errors:\nboom 1\nboom 2", err.Error()) } assert.Nil(t, out) assert.Equal(t, 1, len(helper1.fill)) assert.Equal(t, 1, len(helper2.fill)) err = helpers.Approve(creds) if assert.NotNil(t, err) { assert.Equal(t, "no valid credential helpers to approve", err.Error()) } assert.Equal(t, 0, len(helper1.approve)) assert.Equal(t, 0, len(helper2.approve)) err = helpers.Reject(creds) if assert.NotNil(t, err) { assert.Equal(t, "no valid credential helpers to reject", err.Error()) } assert.Equal(t, 0, len(helper1.reject)) assert.Equal(t, 0, len(helper2.reject)) }