package builder
import (
"errors"
"reflect"
"testing"
"github.com/fsouza/go-dockerclient"
)
type FakeDocker struct {
pushImageFunc func(opts docker.PushImageOptions, auth docker.AuthConfiguration) error
buildImageFunc func(opts docker.BuildImageOptions) error
removeImageFunc func(name string) error
buildImageCalled bool
pushImageCalled bool
removeImageCalled bool
errPushImage error
callLog []methodCall
}
type methodCall struct {
methodName string
args []interface{}
}
func NewFakeDockerClient() *FakeDocker {
return &FakeDocker{}
}
var fooBarRunTimes = 0
func fakePushImageFunc(opts docker.PushImageOptions, auth docker.AuthConfiguration) error {
switch opts.Tag {
case "tag_test_succ_foo_bar":
return nil
case "tag_test_err_exist_foo_bar":
fooBarRunTimes++
return errors.New(RetriableErrors[0])
case "tag_test_err_no_exist_foo_bar":
return errors.New("no_exist_err_foo_bar")
}
return nil
}
func (d *FakeDocker) BuildImage(opts docker.BuildImageOptions) error {
if d.buildImageFunc != nil {
return d.buildImageFunc(opts)
}
return nil
}
func (d *FakeDocker) PushImage(opts docker.PushImageOptions, auth docker.AuthConfiguration) error {
d.pushImageCalled = true
if d.pushImageFunc != nil {
return d.pushImageFunc(opts, auth)
}
return d.errPushImage
}
func (d *FakeDocker) RemoveImage(name string) error {
if d.removeImageFunc != nil {
return d.removeImageFunc(name)
}
return nil
}
func (d *FakeDocker) CreateContainer(opts docker.CreateContainerOptions) (*docker.Container, error) {
return &docker.Container{}, nil
}
func (d *FakeDocker) DownloadFromContainer(id string, opts docker.DownloadFromContainerOptions) error {
return nil
}
func (d *FakeDocker) PullImage(opts docker.PullImageOptions, auth docker.AuthConfiguration) error {
return nil
}
func (d *FakeDocker) RemoveContainer(opts docker.RemoveContainerOptions) error {
return nil
}
func (d *FakeDocker) InspectImage(name string) (*docker.Image, error) {
return &docker.Image{}, nil
}
func (d *FakeDocker) StartContainer(id string, hostConfig *docker.HostConfig) error {
return nil
}
func (d *FakeDocker) WaitContainer(id string) (int, error) {
return 0, nil
}
func (d *FakeDocker) Logs(opts docker.LogsOptions) error {
return nil
}
func (d *FakeDocker) TagImage(name string, opts docker.TagImageOptions) error {
d.callLog = append(d.callLog, methodCall{"TagImage", []interface{}{name, opts}})
return nil
}
func TestDockerPush(t *testing.T) {
verifyFunc := func(opts docker.PushImageOptions, auth docker.AuthConfiguration) error {
if opts.Name != "test/image" {
t.Errorf("Unexpected image name: %s", opts.Name)
}
return nil
}
fd := &FakeDocker{pushImageFunc: verifyFunc}
pushImage(fd, "test/image", docker.AuthConfiguration{})
}
func TestTagImage(t *testing.T) {
tests := []struct {
old, new, newRepo, newTag string
}{
{"test/image", "new/image:tag", "new/image", "tag"},
{"test/image:1.0", "new-name", "new-name", ""},
}
for _, tt := range tests {
dockerClient := &FakeDocker{}
tagImage(dockerClient, tt.old, tt.new)
got := dockerClient.callLog
tagOpts := docker.TagImageOptions{
Repo: tt.newRepo,
Tag: tt.newTag,
Force: true,
}
want := []methodCall{
{"TagImage", []interface{}{tt.old, tagOpts}},
}
if !reflect.DeepEqual(got, want) {
t.Errorf("dockerClient called with %#v, want %#v", got, want)
}
}
}
func TestPushImage(t *testing.T) {
var testImageName string
bakRetryCount := DefaultPushRetryCount
bakRetryDelay := DefaultPushRetryDelay
fakeDocker := NewFakeDockerClient()
fakeDocker.pushImageFunc = fakePushImageFunc
testAuth := docker.AuthConfiguration{
Username: "usernname_foo_bar",
Password: "password_foo_bar",
Email: "email_foo_bar",
ServerAddress: "serveraddress_foo_bar",
}
//make test quickly, and recover the value after testing
DefaultPushRetryCount = 2
defer func() { DefaultPushRetryCount = bakRetryCount }()
DefaultPushRetryDelay = 1
defer func() { DefaultPushRetryDelay = bakRetryDelay }()
//expect succ
testImageName = "repo_foo_bar:tag_test_succ_foo_bar"
if err := pushImage(fakeDocker, testImageName, testAuth); err != nil {
t.Errorf("Unexpect push image : %v, want succ", err)
}
//expect fail
testImageName = "repo_foo_bar:tag_test_err_exist_foo_bar"
err := pushImage(fakeDocker, testImageName, testAuth)
if err == nil {
t.Errorf("Unexpect push image : %v, want error", err)
}
//expect run 3 times
if fooBarRunTimes != (DefaultPushRetryCount + 1) {
t.Errorf("Unexpect run times : %d, we expect run three times", fooBarRunTimes)
}
//expect fail
testImageName = "repo_foo_bar:tag_test_err_no_exist_foo_bar"
if err := pushImage(fakeDocker, testImageName, testAuth); err == nil {
t.Errorf("Unexpect push image : %v, want error", err)
}
defer func() { fooBarRunTimes = 0 }()
}