git-lfs/creds/creds_test.go
brian m. carlson c752dcdf51
Move credential handling to its own package
In a future commit, we're going to be accessing credential handling from
multiple packages.  To avoid an import loop, move credential handling
into its own package.  Update all the callers of the credential handling
code to use a qualified name.

Where there is a local variable called "creds", which would conflict
with our package name, rename it "cred" instead.
2018-09-24 15:09:22 +00:00

267 lines
7.6 KiB
Go

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": "https", "host": "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": "https", "host": "example.com", "username": "foo", "password": "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": "https", "host": "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": "https", "host": "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": "https", "host": "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": "https", "host": "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": "https", "host": "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))
}