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 }() }