From d33013e84e5e3f4de9505f8c4fd37c7b79db0646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lker=20G=C3=B6ktu=C4=9F=20=C3=96zt=C3=BCrk?= Date: Sun, 29 Jul 2018 11:04:32 +0300 Subject: [PATCH 01/22] introduce Container type --- container/build.go | 8 +-- container/build_test.go | 12 +++-- container/client.go | 67 ------------------------ container/client_test.go | 39 -------------- container/container.go | 87 +++++++++++++++++++++++++++++--- container/container_test.go | 53 ++++++++++++++----- container/network.go | 28 +++------- container/network_test.go | 44 ++++++++++------ container/service.go | 68 ++++++++++--------------- container/service_test.go | 80 ++++++++++++++++++++--------- container/shared_network.go | 42 ++++++++------- container/shared_network_test.go | 22 ++++---- container/task.go | 12 ++--- container/task_test.go | 15 +++--- container/wait.go | 6 +-- container/wait_test.go | 22 +++++--- 16 files changed, 315 insertions(+), 290 deletions(-) delete mode 100644 container/client.go diff --git a/container/build.go b/container/build.go index e020c939e..f992dca6c 100644 --- a/container/build.go +++ b/container/build.go @@ -20,7 +20,7 @@ type BuildResponse struct { } // Build builds a docker image. -func Build(path string) (tag string, err error) { +func (c *Container) Build(path string) (tag string, err error) { excludeFilesBytes, _ := ioutil.ReadFile(filepath.Join(path, ".mesgignore")) excludeFiles := strings.Fields(string(excludeFilesBytes)) buildContext, err := archive.TarWithOptions(path, &archive.TarOptions{ @@ -31,11 +31,7 @@ func Build(path string) (tag string, err error) { return "", err } defer buildContext.Close() - client, err := Client() - if err != nil { - return "", err - } - response, err := client.ImageBuild(context.Background(), buildContext, types.ImageBuildOptions{ + response, err := c.client.ImageBuild(context.Background(), buildContext, types.ImageBuildOptions{ Remove: true, ForceRemove: true, SuppressOutput: true, diff --git a/container/build_test.go b/container/build_test.go index d02456f9c..b8e248f4f 100644 --- a/container/build_test.go +++ b/container/build_test.go @@ -10,19 +10,25 @@ import ( ) func TestBuild(t *testing.T) { - tag, err := Build("test/") + c, err := New() + assert.Nil(t, err) + tag, err := c.Build("test/") assert.Nil(t, err) assert.NotEqual(t, "", tag) } func TestBuildNotWorking(t *testing.T) { - tag, err := Build("test-not-valid/") + c, err := New() + assert.Nil(t, err) + tag, err := c.Build("test-not-valid/") assert.NotNil(t, err) assert.Equal(t, "", tag) } func TestBuildWrongPath(t *testing.T) { - _, err := Build("testss/") + c, err := New() + assert.Nil(t, err) + _, err = c.Build("testss/") assert.NotNil(t, err) } diff --git a/container/client.go b/container/client.go deleted file mode 100644 index 5d600cb67..000000000 --- a/container/client.go +++ /dev/null @@ -1,67 +0,0 @@ -package container - -import ( - "context" - "sync" - - "github.com/docker/docker/api/types/swarm" - docker "github.com/docker/docker/client" -) - -var sharedNetworkNamespace = []string{"shared"} - -var clientInstance *docker.Client -var mu sync.Mutex - -// Client creates a ready to use docker client. -func Client() (client *docker.Client, err error) { - mu.Lock() - defer mu.Unlock() - if clientInstance != nil { - client = clientInstance - return - } - client, err = createClient() - if err != nil { - return - } - err = createSwarmIfNeeded(client) - if err != nil { - return - } - err = createSharedNetworkIfNeeded(client) - if err != nil { - return - } - clientInstance = client - return -} - -func resetClient() { - mu.Lock() - defer mu.Unlock() - clientInstance = nil -} - -func createClient() (*docker.Client, error) { - client, err := docker.NewEnvClient() - if err != nil { - return nil, err - } - client.NegotiateAPIVersion(context.Background()) - return client, nil -} - -func createSwarmIfNeeded(client *docker.Client) error { - info, err := client.Info(context.Background()) - if err != nil { - return err - } - if info.Swarm.NodeID != "" { - return nil - } - _, err = client.SwarmInit(context.Background(), swarm.InitRequest{ - ListenAddr: "0.0.0.0:2377", // https://docs.docker.com/engine/reference/commandline/swarm_init/#usage - }) - return err -} diff --git a/container/client_test.go b/container/client_test.go index fa8978b54..7bc5eff94 100644 --- a/container/client_test.go +++ b/container/client_test.go @@ -1,44 +1,5 @@ package container -import ( - "testing" - - "github.com/stvp/assert" -) - -func TestClient(t *testing.T) { - client, err := Client() - assert.Nil(t, err) - assert.NotNil(t, client) -} - -func TestClientIsTheSame(t *testing.T) { - client, err := Client() - assert.Nil(t, err) - assert.NotNil(t, client) - client2, err := Client() - assert.Nil(t, err) - assert.NotNil(t, client2) - assert.Equal(t, client, client2) -} - -func TestClientNotIsTheSame(t *testing.T) { - client, err := Client() - assert.Nil(t, err) - assert.NotNil(t, client) - resetClient() - client2, err := Client() - assert.Nil(t, err) - assert.NotNil(t, client2) - assert.NotEqual(t, client, client2) -} - -func TestCreateSwarmIfNeeded(t *testing.T) { - client, _ := createClient() - err := createSwarmIfNeeded(client) - assert.Nil(t, err) -} - // TODO: this tests break other tests on my machine // func TestCreateSwarm(t *testing.T) { // leaveSwarm() diff --git a/container/container.go b/container/container.go index eaf40bceb..fb95b406b 100644 --- a/container/container.go +++ b/container/container.go @@ -2,19 +2,90 @@ package container import ( "context" + "net/http" + "time" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/swarm" docker "github.com/docker/docker/client" ) -// FindContainer returns a docker container. -func FindContainer(namespace []string) (types.ContainerJSON, error) { - client, err := Client() +// Container provides functionaliets for Docker containers for MESG. +type Container struct { + // client is a Docker client. + client *docker.Client + clientOptions []func(*docker.Client) error + + // callTimeout is the timeout value for Docker API calls. + callTimeout time.Duration +} + +// Option is a configuration func for Container. +type Option func(*Container) + +// New creates a new Container with given options. +func New(options ...Option) (*Container, error) { + c := &Container{ + callTimeout: time.Second * 10, + clientOptions: []func(*docker.Client) error{ + docker.FromEnv, + }, + } + for _, option := range options { + option(c) + } + var err error + c.client, err = docker.NewClientWithOpts(c.clientOptions...) if err != nil { - return types.ContainerJSON{}, err + return c, err + } + c.negotiateAPIVersion() + if err := c.createSwarmIfNeeded(); err != nil { + return c, err + } + return c, c.createSharedNetworkIfNeeded() +} + +// HTTPClientOption creates a new Option with given client for Container. +func HTTPClientOption(client *http.Client) Option { + return func(c *Container) { + c.clientOptions = append(c.clientOptions, docker.WithHTTPClient(client)) + } +} + +// TimeoutOption creates a new Option with given d http call timeout for Container. +func TimeoutOption(d time.Duration) Option { + return func(c *Container) { + c.callTimeout = d } - containers, err := client.ContainerList(context.Background(), types.ContainerListOptions{ +} + +func (c *Container) negotiateAPIVersion() { + ctx, cancel := context.WithTimeout(context.Background(), c.callTimeout) + defer cancel() + c.client.NegotiateAPIVersion(ctx) +} + +func (c *Container) createSwarmIfNeeded() error { + ctx, cancel := context.WithTimeout(context.Background(), c.callTimeout) + defer cancel() + info, err := c.client.Info(ctx) + if err != nil { + return err + } + if info.Swarm.NodeID != "" { + return nil + } + _, err = c.client.SwarmInit(context.Background(), swarm.InitRequest{ + ListenAddr: "0.0.0.0:2377", // https://docs.docker.com/engine/reference/commandline/swarm_init/#usage + }) + return err +} + +// FindContainer returns a docker container. +func (c *Container) FindContainer(namespace []string) (types.ContainerJSON, error) { + containers, err := c.client.ContainerList(context.Background(), types.ContainerListOptions{ Filters: filters.NewArgs(filters.KeyValuePair{ Key: "label", Value: "com.docker.stack.namespace=" + Namespace(namespace), @@ -28,13 +99,13 @@ func FindContainer(namespace []string) (types.ContainerJSON, error) { if len(containers) == 1 { containerID = containers[0].ID } - return client.ContainerInspect(context.Background(), containerID) + return c.client.ContainerInspect(context.Background(), containerID) } // Status returns the status of a docker container. -func Status(namespace []string) (StatusType, error) { +func (c *Container) Status(namespace []string) (StatusType, error) { status := STOPPED - container, err := FindContainer(namespace) + container, err := c.FindContainer(namespace) if docker.IsErrNotFound(err) { return status, nil } diff --git a/container/container_test.go b/container/container_test.go index c0e729c2d..7d789864e 100644 --- a/container/container_test.go +++ b/container/container_test.go @@ -6,53 +6,78 @@ import ( "github.com/stvp/assert" ) +func TestContainer(t *testing.T) { + c, err := New() + assert.Nil(t, err) + assert.NotNil(t, c) +} + +func TestCreateSwarmIfNeeded(t *testing.T) { + c, err := New() + assert.Nil(t, err) + err = c.createSwarmIfNeeded() + assert.Nil(t, err) +} + func TestFindContainerNotExisting(t *testing.T) { - _, err := FindContainer([]string{"TestFindContainerNotExisting"}) + c, err := New() + assert.Nil(t, err) + _, err = c.FindContainer([]string{"TestFindContainerNotExisting"}) assert.NotNil(t, err) } func TestFindContainer(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestFindContainer"} startTestService(namespace) - defer StopService(namespace) - waitForStatus(namespace, RUNNING) - container, err := FindContainer(namespace) + defer c.StopService(namespace) + c.waitForStatus(namespace, RUNNING) + container, err := c.FindContainer(namespace) assert.Nil(t, err) assert.NotEqual(t, "", container.ID) } func TestFindContainerStopped(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestFindContainerStopped"} startTestService(namespace) - StopService(namespace) - _, err := FindContainer(namespace) + c.StopService(namespace) + _, err = c.FindContainer(namespace) assert.NotNil(t, err) } func TestContainerStatusNeverStarted(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestContainerStatusNeverStarted"} - status, err := Status(namespace) + status, err := c.Status(namespace) assert.Nil(t, err) assert.Equal(t, status, STOPPED) } func TestContainerStatusRunning(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestContainerStatusRunning"} startTestService(namespace) - defer StopService(namespace) - waitForStatus(namespace, RUNNING) - status, err := Status(namespace) + defer c.StopService(namespace) + c.waitForStatus(namespace, RUNNING) + status, err := c.Status(namespace) assert.Nil(t, err) assert.Equal(t, status, RUNNING) } func TestContainerStatusStopped(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestContainerStatusStopped"} startTestService(namespace) - waitForStatus(namespace, RUNNING) - StopService(namespace) - waitForStatus(namespace, STOPPED) - status, err := Status(namespace) + c.waitForStatus(namespace, RUNNING) + c.StopService(namespace) + c.waitForStatus(namespace, STOPPED) + status, err := c.Status(namespace) assert.Nil(t, err) assert.Equal(t, status, STOPPED) } diff --git a/container/network.go b/container/network.go index cbc8c6a70..b7cbcfff4 100644 --- a/container/network.go +++ b/container/network.go @@ -8,8 +8,8 @@ import ( ) // CreateNetwork creates a Docker Network with a namespace. -func CreateNetwork(namespace []string) (id string, err error) { - network, err := FindNetwork(namespace) +func (c *Container) CreateNetwork(namespace []string) (id string, err error) { + network, err := c.FindNetwork(namespace) if err != nil && !docker.IsErrNotFound(err) { return "", err } @@ -17,11 +17,7 @@ func CreateNetwork(namespace []string) (id string, err error) { return network.ID, nil } namespaceFlat := Namespace(namespace) - client, err := Client() - if err != nil { - return "", err - } - response, err := client.NetworkCreate(context.Background(), namespaceFlat, types.NetworkCreate{ + response, err := c.client.NetworkCreate(context.Background(), namespaceFlat, types.NetworkCreate{ CheckDuplicate: true, // Cannot have 2 network with the same name Driver: "overlay", Labels: map[string]string{ @@ -35,26 +31,18 @@ func CreateNetwork(namespace []string) (id string, err error) { } // DeleteNetwork deletes a Docker Network associated with a namespace. -func DeleteNetwork(namespace []string) error { - network, err := FindNetwork(namespace) +func (c *Container) DeleteNetwork(namespace []string) error { + network, err := c.FindNetwork(namespace) if docker.IsErrNotFound(err) { return nil } if err != nil { return err } - client, err := Client() - if err != nil { - return err - } - return client.NetworkRemove(context.Background(), network.ID) + return c.client.NetworkRemove(context.Background(), network.ID) } // FindNetwork finds a Docker Network by a namespace. If no network is found, an error is returned. -func FindNetwork(namespace []string) (types.NetworkResource, error) { - client, err := Client() - if err != nil { - return types.NetworkResource{}, err - } - return client.NetworkInspect(context.Background(), Namespace(namespace), types.NetworkInspectOptions{}) +func (c *Container) FindNetwork(namespace []string) (types.NetworkResource, error) { + return c.client.NetworkInspect(context.Background(), Namespace(namespace), types.NetworkInspectOptions{}) } diff --git a/container/network_test.go b/container/network_test.go index 427a8ce61..d7059d0ec 100644 --- a/container/network_test.go +++ b/container/network_test.go @@ -7,47 +7,61 @@ import ( ) func TestCreateNetwork(t *testing.T) { - networkID, err := CreateNetwork([]string{"TestCreateNetwork"}) - defer DeleteNetwork([]string{"TestCreateNetwork"}) + c, err := New() + assert.Nil(t, err) + networkID, err := c.CreateNetwork([]string{"TestCreateNetwork"}) + defer c.DeleteNetwork([]string{"TestCreateNetwork"}) assert.Nil(t, err) assert.NotEqual(t, "", networkID) } func TestCreateAlreadyExistingNetwork(t *testing.T) { - CreateNetwork([]string{"TestCreateAlreadyExistingNetwork"}) - networkID, err := CreateNetwork([]string{"TestCreateAlreadyExistingNetwork"}) - defer DeleteNetwork([]string{"TestCreateAlreadyExistingNetwork"}) + c, err := New() + assert.Nil(t, err) + c.CreateNetwork([]string{"TestCreateAlreadyExistingNetwork"}) + networkID, err := c.CreateNetwork([]string{"TestCreateAlreadyExistingNetwork"}) + defer c.DeleteNetwork([]string{"TestCreateAlreadyExistingNetwork"}) assert.Nil(t, err) assert.NotEqual(t, "", networkID) } func TestDeleteNetwork(t *testing.T) { - CreateNetwork([]string{"TestDeleteNetwork"}) - err := DeleteNetwork([]string{"TestDeleteNetwork"}) + c, err := New() + assert.Nil(t, err) + c.CreateNetwork([]string{"TestDeleteNetwork"}) + err = c.DeleteNetwork([]string{"TestDeleteNetwork"}) assert.Nil(t, err) } func TestDeleteNotExistingNetwork(t *testing.T) { - err := DeleteNetwork([]string{"TestDeleteNotExistingNetwork"}) + c, err := New() + assert.Nil(t, err) + err = c.DeleteNetwork([]string{"TestDeleteNotExistingNetwork"}) assert.Nil(t, err) } func TestFindNetwork(t *testing.T) { - CreateNetwork([]string{"TestFindNetwork"}) - defer DeleteNetwork([]string{"TestFindNetwork"}) - network, err := FindNetwork([]string{"TestFindNetwork"}) + c, err := New() + assert.Nil(t, err) + c.CreateNetwork([]string{"TestFindNetwork"}) + defer c.DeleteNetwork([]string{"TestFindNetwork"}) + network, err := c.FindNetwork([]string{"TestFindNetwork"}) assert.Nil(t, err) assert.NotEqual(t, "", network.ID) } func TestFindNotExistingNetwork(t *testing.T) { - _, err := FindNetwork([]string{"TestFindNotExistingNetwork"}) + c, err := New() + assert.Nil(t, err) + _, err = c.FindNetwork([]string{"TestFindNotExistingNetwork"}) assert.NotNil(t, err) } func TestFindDeletedNetwork(t *testing.T) { - CreateNetwork([]string{"TestFindDeletedNetwork"}) - DeleteNetwork([]string{"TestFindDeletedNetwork"}) - _, err := FindNetwork([]string{"TestFindDeletedNetwork"}) + c, err := New() + assert.Nil(t, err) + c.CreateNetwork([]string{"TestFindDeletedNetwork"}) + c.DeleteNetwork([]string{"TestFindDeletedNetwork"}) + _, err = c.FindNetwork([]string{"TestFindDeletedNetwork"}) assert.NotNil(t, err) } diff --git a/container/service.go b/container/service.go index 8d78df07f..3fb197ec6 100644 --- a/container/service.go +++ b/container/service.go @@ -11,12 +11,8 @@ import ( ) // ListServices returns existing docker services matching a specific label name. -func ListServices(label string) ([]swarm.Service, error) { - client, err := Client() - if err != nil { - return nil, err - } - return client.ServiceList(context.Background(), types.ServiceListOptions{ +func (c *Container) ListServices(label string) ([]swarm.Service, error) { + return c.client.ServiceList(context.Background(), types.ServiceListOptions{ Filters: filters.NewArgs(filters.KeyValuePair{ Key: "label", Value: label, @@ -25,48 +21,40 @@ func ListServices(label string) ([]swarm.Service, error) { } // FindService returns the Docker Service or an error if not found. -func FindService(namespace []string) (swarm.Service, error) { - client, err := Client() - if err != nil { - return swarm.Service{}, err - } - service, _, err := client.ServiceInspectWithRaw(context.Background(), Namespace(namespace), types.ServiceInspectOptions{}) +func (c *Container) FindService(namespace []string) (swarm.Service, error) { + service, _, err := c.client.ServiceInspectWithRaw( + context.Background(), + Namespace(namespace), + types.ServiceInspectOptions{}, + ) return service, err } // StartService starts a docker service. -func StartService(options ServiceOptions) (id string, err error) { - client, err := Client() - if err != nil { - return "", err - } +func (c *Container) StartService(options ServiceOptions) (serviceID string, err error) { service := options.toSwarmServiceSpec() - response, err := client.ServiceCreate(context.Background(), service, types.ServiceCreateOptions{}) + response, err := c.client.ServiceCreate(context.Background(), service, types.ServiceCreateOptions{}) if err != nil { return "", err } - return response.ID, waitForStatus(options.Namespace, RUNNING) + return response.ID, c.waitForStatus(options.Namespace, RUNNING) } // StopService stops a docker service. -func StopService(namespace []string) error { - status, err := ServiceStatus(namespace) +func (c *Container) StopService(namespace []string) (err error) { + status, err := c.ServiceStatus(namespace) if err != nil || status == STOPPED { return err } - client, err := Client() - if err != nil { - return err - } - if err := client.ServiceRemove(context.Background(), Namespace(namespace)); err != nil { + if err := c.client.ServiceRemove(context.Background(), Namespace(namespace)); err != nil { return err } - return waitForStatus(namespace, STOPPED) + return c.waitForStatus(namespace, STOPPED) } // ServiceStatus returns the status of the Docker Swarm Servicer. -func ServiceStatus(namespace []string) (StatusType, error) { - _, err := FindService(namespace) +func (c *Container) ServiceStatus(namespace []string) (StatusType, error) { + _, err := c.FindService(namespace) if docker.IsErrNotFound(err) { return STOPPED, nil } @@ -77,15 +65,15 @@ func ServiceStatus(namespace []string) (StatusType, error) { } // ServiceLogs returns the logs of a service. -func ServiceLogs(namespace []string) (io.ReadCloser, error) { - client, err := Client() - if err != nil { - return nil, err - } - return client.ServiceLogs(context.Background(), Namespace(namespace), types.ContainerLogsOptions{ - ShowStdout: true, - ShowStderr: true, - Timestamps: false, - Follow: true, - }) +func (c *Container) ServiceLogs(namespace []string) (io.ReadCloser, error) { + return c.client.ServiceLogs( + context.Background(), + Namespace(namespace), + types.ContainerLogsOptions{ + ShowStdout: true, + ShowStderr: true, + Timestamps: false, + Follow: true, + }, + ) } diff --git a/container/service_test.go b/container/service_test.go index 3e6ec66b4..ee3c7eee7 100644 --- a/container/service_test.go +++ b/container/service_test.go @@ -7,132 +7,162 @@ import ( ) func startTestService(name []string) (string, error) { - return StartService(ServiceOptions{ + c, err := New() + if err != nil { + return "", err + } + return c.StartService(ServiceOptions{ Image: "nginx", Namespace: name, }) } func TestStartService(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestStartService"} serviceID, err := startTestService(namespace) - defer StopService(namespace) + defer c.StopService(namespace) assert.Nil(t, err) assert.NotEqual(t, "", serviceID) } func TestStartService2Times(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestStartService2Times"} startTestService(namespace) - defer StopService(namespace) + defer c.StopService(namespace) serviceID, err := startTestService(namespace) assert.NotNil(t, err) assert.Equal(t, "", serviceID) } func TestStopService(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestStopService"} startTestService(namespace) - err := StopService(namespace) + err = c.StopService(namespace) assert.Nil(t, err) } func TestStopNotExistingService(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestStopNotExistingService"} - err := StopService(namespace) + err = c.StopService(namespace) assert.Nil(t, err) } func TestServiceStatusNeverStarted(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestServiceStatusNeverStarted"} - status, err := ServiceStatus(namespace) + status, err := c.ServiceStatus(namespace) assert.Nil(t, err) assert.NotEqual(t, RUNNING, status) assert.Equal(t, STOPPED, status) } func TestServiceStatusRunning(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestServiceStatusRunning"} startTestService(namespace) - defer StopService(namespace) - status, err := ServiceStatus(namespace) + defer c.StopService(namespace) + status, err := c.ServiceStatus(namespace) assert.Nil(t, err) assert.Equal(t, status, RUNNING) assert.NotEqual(t, status, STOPPED) } func TestServiceStatusStopped(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestServiceStatusStopped"} startTestService(namespace) - StopService(namespace) - status, err := ServiceStatus(namespace) + c.StopService(namespace) + status, err := c.ServiceStatus(namespace) assert.Nil(t, err) assert.Equal(t, status, STOPPED) assert.NotEqual(t, status, RUNNING) } func TestFindServiceNotExisting(t *testing.T) { - _, err := FindService([]string{"TestFindServiceNotExisting"}) + c, err := New() + assert.Nil(t, err) + _, err = c.FindService([]string{"TestFindServiceNotExisting"}) assert.NotNil(t, err) } func TestFindService(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestFindService"} startTestService(namespace) - defer StopService(namespace) - service, err := FindService(namespace) + defer c.StopService(namespace) + service, err := c.FindService(namespace) assert.Nil(t, err) assert.NotEqual(t, "", service.ID) } func TestFindServiceCloseName(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestFindServiceCloseName", "name"} namespace1 := []string{"TestFindServiceCloseName", "name2"} startTestService(namespace) - defer StopService(namespace) + defer c.StopService(namespace) startTestService(namespace1) - defer StopService(namespace1) - service, err := FindService(namespace) + defer c.StopService(namespace1) + service, err := c.FindService(namespace) assert.Nil(t, err) assert.NotEqual(t, "", service.ID) } func TestFindServiceStopped(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestFindServiceStopped"} startTestService(namespace) - StopService(namespace) - _, err := FindService(namespace) + c.StopService(namespace) + _, err = c.FindService(namespace) assert.NotNil(t, err) } func TestListServices(t *testing.T) { - StartService(ServiceOptions{ + c, err := New() + assert.Nil(t, err) + c.StartService(ServiceOptions{ Image: "nginx", Namespace: []string{"TestListServices"}, Labels: map[string]string{ "label_name": "value_1", }, }) - StartService(ServiceOptions{ + c.StartService(ServiceOptions{ Image: "nginx", Namespace: []string{"TestListServiceswithValue2"}, Labels: map[string]string{ "label_name_2": "value_2", }, }) - defer StopService([]string{"TestListServices"}) - defer StopService([]string{"TestListServiceswithValue2"}) - services, err := ListServices("label_name") + defer c.StopService([]string{"TestListServices"}) + defer c.StopService([]string{"TestListServiceswithValue2"}) + services, err := c.ListServices("label_name") assert.Nil(t, err) assert.Equal(t, 1, len(services)) assert.Equal(t, Namespace([]string{"TestListServices"}), services[0].Spec.Name) } func TestServiceLogs(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestServiceLogs"} startTestService(namespace) - defer StopService(namespace) - reader, err := ServiceLogs(namespace) + defer c.StopService(namespace) + reader, err := c.ServiceLogs(namespace) assert.Nil(t, err) assert.NotNil(t, reader) } diff --git a/container/shared_network.go b/container/shared_network.go index be72b67c2..fdd04ad97 100644 --- a/container/shared_network.go +++ b/container/shared_network.go @@ -7,17 +7,32 @@ import ( docker "github.com/docker/docker/client" ) -func createSharedNetworkIfNeeded(client *docker.Client) error { - network, err := sharedNetwork(client) +var sharedNetworkNamespace = []string{"shared"} + +// SharedNetworkID returns the ID of the shared network. +func (c *Container) SharedNetworkID() (networkID string, err error) { + network, err := c.sharedNetwork() + if err != nil { + return "", err + } + return network.ID, nil +} + +func (c *Container) createSharedNetworkIfNeeded() error { + network, err := c.sharedNetwork() if err != nil && !docker.IsErrNotFound(err) { return err } if network.ID != "" { return nil } - // Create the new network needed to run containers + + ctx, cancel := context.WithTimeout(context.Background(), c.callTimeout) + defer cancel() + + // Create the new network needed to run containers. namespace := Namespace(sharedNetworkNamespace) - _, err = client.NetworkCreate(context.Background(), namespace, types.NetworkCreate{ + _, err = c.client.NetworkCreate(ctx, namespace, types.NetworkCreate{ CheckDuplicate: true, Driver: "overlay", Labels: map[string]string{ @@ -28,19 +43,8 @@ func createSharedNetworkIfNeeded(client *docker.Client) error { } // sharedNetwork returns the shared network created to connect services and MESG Core. -func sharedNetwork(client *docker.Client) (types.NetworkResource, error) { - return client.NetworkInspect(context.Background(), Namespace(sharedNetworkNamespace), types.NetworkInspectOptions{}) -} - -// SharedNetworkID returns the ID of the shared network. -func SharedNetworkID() (string, error) { - client, err := Client() - if err != nil { - return "", err - } - network, err := sharedNetwork(client) - if err != nil { - return "", err - } - return network.ID, nil +func (c *Container) sharedNetwork() (network types.NetworkResource, err error) { + ctx, cancel := context.WithTimeout(context.Background(), c.callTimeout) + defer cancel() + return c.client.NetworkInspect(ctx, Namespace(sharedNetworkNamespace), types.NetworkInspectOptions{}) } diff --git a/container/shared_network_test.go b/container/shared_network_test.go index 228e93d14..8dc164640 100644 --- a/container/shared_network_test.go +++ b/container/shared_network_test.go @@ -8,33 +8,37 @@ import ( "github.com/stvp/assert" ) -func removeSharedNetworkIfExist(client *docker.Client) error { - if _, err := sharedNetwork(client); err != nil { +func removeSharedNetworkIfExist(c *Container) error { + if _, err := c.sharedNetwork(); err != nil { if docker.IsErrNotFound(err) { return nil } return err } - return client.NetworkRemove(context.Background(), Namespace(sharedNetworkNamespace)) + return c.client.NetworkRemove(context.Background(), Namespace(sharedNetworkNamespace)) } func TestCreateSharedNetworkIfNeeded(t *testing.T) { - client, _ := createClient() - err := removeSharedNetworkIfExist(client) + c, err := New() assert.Nil(t, err) - err = createSharedNetworkIfNeeded(client) + err = removeSharedNetworkIfExist(c) + assert.Nil(t, err) + err = c.createSharedNetworkIfNeeded() assert.Nil(t, err) } func TestSharedNetwork(t *testing.T) { - client, _ := Client() - network, err := sharedNetwork(client) + c, err := New() + assert.Nil(t, err) + network, err := c.sharedNetwork() assert.Nil(t, err) assert.NotEqual(t, "", network.ID) } func TestSharedNetworkID(t *testing.T) { - networkID, err := SharedNetworkID() + c, err := New() + assert.Nil(t, err) + networkID, err := c.SharedNetworkID() assert.Nil(t, err) assert.NotEqual(t, "", networkID) } diff --git a/container/task.go b/container/task.go index 4690fea2e..1b3460ee4 100644 --- a/container/task.go +++ b/container/task.go @@ -9,12 +9,8 @@ import ( ) // ListTasks returns all the docker tasks. -func ListTasks(namespace []string) ([]swarm.Task, error) { - client, err := Client() - if err != nil { - return nil, err - } - return client.TaskList(context.Background(), types.TaskListOptions{ +func (c *Container) ListTasks(namespace []string) ([]swarm.Task, error) { + return c.client.TaskList(context.Background(), types.TaskListOptions{ Filters: filters.NewArgs(filters.KeyValuePair{ Key: "label", Value: "com.docker.stack.namespace=" + Namespace(namespace), @@ -23,8 +19,8 @@ func ListTasks(namespace []string) ([]swarm.Task, error) { } // TasksError returns the error of matching tasks. -func TasksError(namespace []string) ([]string, error) { - tasks, err := ListTasks(namespace) +func (c *Container) TasksError(namespace []string) ([]string, error) { + tasks, err := c.ListTasks(namespace) if err != nil { return nil, err } diff --git a/container/task_test.go b/container/task_test.go index 8a5aaf185..1e0d3d99c 100644 --- a/container/task_test.go +++ b/container/task_test.go @@ -8,26 +8,29 @@ import ( ) func TestListTasks(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestListTasks"} startTestService(namespace) - defer StopService(namespace) - tasks, err := ListTasks(namespace) + defer c.StopService(namespace) + tasks, err := c.ListTasks(namespace) assert.Nil(t, err) assert.NotNil(t, tasks) assert.Equal(t, 1, len(tasks)) } func TestTasksError(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestTasksError"} - StartService(ServiceOptions{ + c.StartService(ServiceOptions{ Image: "fiifioewifewiewfifewijopwjeokpfeo", Namespace: namespace, }) - defer StopService(namespace) + defer c.StopService(namespace) var errors []string - var err error for { - errors, err = TasksError(namespace) + errors, err = c.TasksError(namespace) if err != nil || len(errors) > 0 { break } diff --git a/container/wait.go b/container/wait.go index 20347ea34..45dd3ae4c 100644 --- a/container/wait.go +++ b/container/wait.go @@ -7,16 +7,16 @@ import ( ) // waitForStatus waits for the container to have the provided status. Returns error as soon as possible. -func waitForStatus(namespace []string, status StatusType) error { +func (c *Container) waitForStatus(namespace []string, status StatusType) (err error) { for { - tasksErrors, err := TasksError(namespace) + tasksErrors, err := c.TasksError(namespace) if err != nil { return err } if len(tasksErrors) > 0 { return errors.New(strings.Join(tasksErrors, ", ")) } - currentStatus, err := Status(namespace) + currentStatus, err := c.Status(namespace) if err != nil || currentStatus == status { return err } diff --git a/container/wait_test.go b/container/wait_test.go index ebc88d99a..d039318b3 100644 --- a/container/wait_test.go +++ b/container/wait_test.go @@ -7,30 +7,36 @@ import ( ) func TestWaitForStatusRunning(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestWaitForStatusRunning"} startTestService(namespace) - defer StopService(namespace) - err := waitForStatus(namespace, RUNNING) + defer c.StopService(namespace) + err = c.waitForStatus(namespace, RUNNING) assert.Nil(t, err) } func TestWaitForStatusStopped(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestWaitForStatusStopped"} startTestService(namespace) - waitForStatus(namespace, RUNNING) - StopService(namespace) - err := waitForStatus(namespace, STOPPED) + c.waitForStatus(namespace, RUNNING) + c.StopService(namespace) + err = c.waitForStatus(namespace, STOPPED) assert.Nil(t, err) } func TestWaitForStatusTaskError(t *testing.T) { + c, err := New() + assert.Nil(t, err) namespace := []string{"TestWaitForStatusTaskError"} - StartService(ServiceOptions{ + c.StartService(ServiceOptions{ Image: "awgdaywudaywudwa", Namespace: namespace, }) - defer StopService(namespace) - err := waitForStatus(namespace, RUNNING) + defer c.StopService(namespace) + err = c.waitForStatus(namespace, RUNNING) assert.NotNil(t, err) assert.Equal(t, "No such image: awgdaywudaywudwa:latest", err.Error()) } From ca06278393e8bc89dc500f251f7c140b539ab8fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lker=20G=C3=B6ktu=C4=9F=20=C3=96zt=C3=BCrk?= Date: Tue, 31 Jul 2018 11:41:11 +0300 Subject: [PATCH 02/22] container: improve tests & introduce dockertest package * move integration tests to their own files called with _integration_test.go * add dockertest package to easily test methods that calls Docker API --- ...uild_test.go => build_integration_test.go} | 14 +-- container/container.go | 21 ++--- ..._test.go => container_integration_test.go} | 25 ++--- container/dockertest/client.go | 91 +++++++++++++++++++ container/dockertest/testing.go | 68 ++++++++++++++ ...rk_test.go => network_integration_test.go} | 16 ++-- ...ce_test.go => service_integration_test.go} | 28 +++--- ....go => shared_network_integration_test.go} | 8 +- ...{task_test.go => task_integration_test.go} | 6 +- ...{wait_test.go => wait_integration_test.go} | 8 +- 10 files changed, 224 insertions(+), 61 deletions(-) rename container/{build_test.go => build_integration_test.go} (75%) rename container/{container_test.go => container_integration_test.go} (76%) create mode 100644 container/dockertest/client.go create mode 100644 container/dockertest/testing.go rename container/{network_test.go => network_integration_test.go} (78%) rename container/{service_test.go => service_integration_test.go} (83%) rename container/{shared_network_test.go => shared_network_integration_test.go} (80%) rename container/{task_test.go => task_integration_test.go} (88%) rename container/{wait_test.go => wait_integration_test.go} (81%) diff --git a/container/build_test.go b/container/build_integration_test.go similarity index 75% rename from container/build_test.go rename to container/build_integration_test.go index b8e248f4f..d114627f9 100644 --- a/container/build_test.go +++ b/container/build_integration_test.go @@ -1,3 +1,5 @@ +// +build integration + package container import ( @@ -9,7 +11,7 @@ import ( "github.com/stvp/assert" ) -func TestBuild(t *testing.T) { +func TestIntegrationBuild(t *testing.T) { c, err := New() assert.Nil(t, err) tag, err := c.Build("test/") @@ -17,7 +19,7 @@ func TestBuild(t *testing.T) { assert.NotEqual(t, "", tag) } -func TestBuildNotWorking(t *testing.T) { +func TestIntegrationBuildNotWorking(t *testing.T) { c, err := New() assert.Nil(t, err) tag, err := c.Build("test-not-valid/") @@ -25,14 +27,14 @@ func TestBuildNotWorking(t *testing.T) { assert.Equal(t, "", tag) } -func TestBuildWrongPath(t *testing.T) { +func TestIntegrationBuildWrongPath(t *testing.T) { c, err := New() assert.Nil(t, err) _, err = c.Build("testss/") assert.NotNil(t, err) } -func TestParseBuildResponseInvalidJSON(t *testing.T) { +func TestIntegrationParseBuildResponseInvalidJSON(t *testing.T) { body := ioutil.NopCloser(strings.NewReader("invalidJSON")) response := types.ImageBuildResponse{ Body: body, @@ -41,7 +43,7 @@ func TestParseBuildResponseInvalidJSON(t *testing.T) { assert.NotNil(t, err) } -func TestParseBuildResponse(t *testing.T) { +func TestIntegrationParseBuildResponse(t *testing.T) { body := ioutil.NopCloser(strings.NewReader("{\"stream\":\"ok\"}")) response := types.ImageBuildResponse{ Body: body, @@ -51,7 +53,7 @@ func TestParseBuildResponse(t *testing.T) { assert.Equal(t, tag, "ok") } -func TestParseBuildResponseWithNewLine(t *testing.T) { +func TestIntegrationParseBuildResponseWithNewLine(t *testing.T) { body := ioutil.NopCloser(strings.NewReader("{\"stream\":\"ok\\n\"}")) response := types.ImageBuildResponse{ Body: body, diff --git a/container/container.go b/container/container.go index fb95b406b..c5f6fd87c 100644 --- a/container/container.go +++ b/container/container.go @@ -2,7 +2,6 @@ package container import ( "context" - "net/http" "time" "github.com/docker/docker/api/types" @@ -14,8 +13,7 @@ import ( // Container provides functionaliets for Docker containers for MESG. type Container struct { // client is a Docker client. - client *docker.Client - clientOptions []func(*docker.Client) error + client docker.CommonAPIClient // callTimeout is the timeout value for Docker API calls. callTimeout time.Duration @@ -28,17 +26,16 @@ type Option func(*Container) func New(options ...Option) (*Container, error) { c := &Container{ callTimeout: time.Second * 10, - clientOptions: []func(*docker.Client) error{ - docker.FromEnv, - }, } for _, option := range options { option(c) } var err error - c.client, err = docker.NewClientWithOpts(c.clientOptions...) - if err != nil { - return c, err + if c.client == nil { + c.client, err = docker.NewClientWithOpts(docker.FromEnv) + if err != nil { + return c, err + } } c.negotiateAPIVersion() if err := c.createSwarmIfNeeded(); err != nil { @@ -47,10 +44,10 @@ func New(options ...Option) (*Container, error) { return c, c.createSharedNetworkIfNeeded() } -// HTTPClientOption creates a new Option with given client for Container. -func HTTPClientOption(client *http.Client) Option { +// ClientOption creates a new Option with given docker client for Container. +func ClientOption(client docker.CommonAPIClient) Option { return func(c *Container) { - c.clientOptions = append(c.clientOptions, docker.WithHTTPClient(client)) + c.client = client } } diff --git a/container/container_test.go b/container/container_integration_test.go similarity index 76% rename from container/container_test.go rename to container/container_integration_test.go index 7d789864e..7b2dd5bf6 100644 --- a/container/container_test.go +++ b/container/container_integration_test.go @@ -1,3 +1,5 @@ +// +build integration + package container import ( @@ -6,27 +8,20 @@ import ( "github.com/stvp/assert" ) -func TestContainer(t *testing.T) { - c, err := New() - assert.Nil(t, err) - assert.NotNil(t, c) -} - -func TestCreateSwarmIfNeeded(t *testing.T) { +func TestIntegrationCreateSwarmIfNeeded(t *testing.T) { c, err := New() assert.Nil(t, err) - err = c.createSwarmIfNeeded() - assert.Nil(t, err) + assert.Nil(t, c.createSwarmIfNeeded()) } -func TestFindContainerNotExisting(t *testing.T) { +func TestIntegrationFindContainerNotExisting(t *testing.T) { c, err := New() assert.Nil(t, err) _, err = c.FindContainer([]string{"TestFindContainerNotExisting"}) assert.NotNil(t, err) } -func TestFindContainer(t *testing.T) { +func TestIntegrationFindContainer(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestFindContainer"} @@ -38,7 +33,7 @@ func TestFindContainer(t *testing.T) { assert.NotEqual(t, "", container.ID) } -func TestFindContainerStopped(t *testing.T) { +func TestIntegrationFindContainerStopped(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestFindContainerStopped"} @@ -48,7 +43,7 @@ func TestFindContainerStopped(t *testing.T) { assert.NotNil(t, err) } -func TestContainerStatusNeverStarted(t *testing.T) { +func TestIntegrationContainerStatusNeverStarted(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestContainerStatusNeverStarted"} @@ -57,7 +52,7 @@ func TestContainerStatusNeverStarted(t *testing.T) { assert.Equal(t, status, STOPPED) } -func TestContainerStatusRunning(t *testing.T) { +func TestIntegrationContainerStatusRunning(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestContainerStatusRunning"} @@ -69,7 +64,7 @@ func TestContainerStatusRunning(t *testing.T) { assert.Equal(t, status, RUNNING) } -func TestContainerStatusStopped(t *testing.T) { +func TestIntegrationContainerStatusStopped(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestContainerStatusStopped"} diff --git a/container/dockertest/client.go b/container/dockertest/client.go new file mode 100644 index 000000000..611c6eabe --- /dev/null +++ b/container/dockertest/client.go @@ -0,0 +1,91 @@ +package dockertest + +import ( + "context" + "errors" + "sync" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/swarm" + docker "github.com/docker/docker/client" +) + +var ( + ErrContainerDoesNotExists = errors.New("containers does not exists") +) + +type client struct { + // a placeholder for unimplemented methods. + docker.CommonAPIClient + + lastNegotiateAPIVersion chan struct{} + lastSwarmInit chan swarm.InitRequest + lastNetworkCreate chan NetworkCreate + lastInfo chan types.Info + lastContainerList chan types.ContainerListOptions + lastContainerInspect chan string + + m sync.RWMutex + + info types.Info + infoErr error + + containers []types.Container + containerInspect types.ContainerJSON +} + +func newClient() *client { + return &client{ + lastNegotiateAPIVersion: make(chan struct{}, 1), + lastSwarmInit: make(chan swarm.InitRequest, 1), + lastNetworkCreate: make(chan NetworkCreate, 1), + lastInfo: make(chan types.Info, 1), + lastContainerList: make(chan types.ContainerListOptions, 1), + lastContainerInspect: make(chan string, 1), + } +} + +func (c *client) NegotiateAPIVersion(ctx context.Context) { + c.lastNegotiateAPIVersion <- struct{}{} +} + +func (c *client) NetworkInspect(ctx context.Context, network string, + options types.NetworkInspectOptions) (types.NetworkResource, error) { + return types.NetworkResource{}, nil +} + +type NetworkCreate struct { + Name string + Options types.NetworkCreate +} + +func (c *client) NetworkCreate(ctx context.Context, name string, + options types.NetworkCreate) (types.NetworkCreateResponse, error) { + c.lastNetworkCreate <- NetworkCreate{name, options} + return types.NetworkCreateResponse{}, nil +} + +func (c *client) SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error) { + c.lastSwarmInit <- req + return "", nil +} + +func (c *client) Info(context.Context) (types.Info, error) { + c.m.RLock() + defer c.m.RUnlock() + return c.info, c.infoErr +} + +func (c *client) ContainerList(ctx context.Context, + options types.ContainerListOptions) ([]types.Container, error) { + c.lastContainerList <- options + if len(c.containers) > 0 { + return c.containers, nil + } + return c.containers, ErrContainerDoesNotExists +} + +func (c *client) ContainerInspect(ctx context.Context, container string) (types.ContainerJSON, error) { + c.lastContainerInspect <- container + return c.containerInspect, nil +} diff --git a/container/dockertest/testing.go b/container/dockertest/testing.go new file mode 100644 index 000000000..cd4dcc525 --- /dev/null +++ b/container/dockertest/testing.go @@ -0,0 +1,68 @@ +// Package dockertest provides functionalities for mocking and faking the Docker API. +package dockertest + +import ( + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/swarm" +) + +type Testing struct { + client *client +} + +func New() *Testing { + t := &Testing{ + client: newClient(), + } + return t +} + +func (t *Testing) Client() *client { + return t.client +} + +func (t *Testing) ProvideContainer(container types.Container) { + t.client.m.Lock() + defer t.client.m.Unlock() + t.client.containers = append(t.client.containers, container) +} + +func (t *Testing) ProvideContainerInspect(container types.ContainerJSON) { + t.client.containerInspect = container +} + +func (t *Testing) LastContainerList() chan types.ContainerListOptions { + return t.client.lastContainerList +} + +func (t *Testing) LastContainerInspect() chan string { + return t.client.lastContainerInspect +} + +func (t *Testing) LastSwarmInit() chan swarm.InitRequest { + return t.client.lastSwarmInit +} + +func (t *Testing) LastNetworkCreate() chan NetworkCreate { + return t.client.lastNetworkCreate +} + +type SystemInfo struct { + Info types.Info + Err error +} + +func (t *Testing) LastInfo() types.Info { + return <-t.client.lastInfo +} + +func (t *Testing) ProvideInfo(info types.Info, err error) { + t.client.m.Lock() + defer t.client.m.Unlock() + t.client.info = info + t.client.infoErr = err +} + +func (t *Testing) LastNegotiateAPIVersion() chan struct{} { + return t.client.lastNegotiateAPIVersion +} diff --git a/container/network_test.go b/container/network_integration_test.go similarity index 78% rename from container/network_test.go rename to container/network_integration_test.go index d7059d0ec..49c9e660f 100644 --- a/container/network_test.go +++ b/container/network_integration_test.go @@ -1,3 +1,5 @@ +// +build integration + package container import ( @@ -6,7 +8,7 @@ import ( "github.com/stvp/assert" ) -func TestCreateNetwork(t *testing.T) { +func TestIntegrationCreateNetwork(t *testing.T) { c, err := New() assert.Nil(t, err) networkID, err := c.CreateNetwork([]string{"TestCreateNetwork"}) @@ -15,7 +17,7 @@ func TestCreateNetwork(t *testing.T) { assert.NotEqual(t, "", networkID) } -func TestCreateAlreadyExistingNetwork(t *testing.T) { +func TestIntegrationCreateAlreadyExistingNetwork(t *testing.T) { c, err := New() assert.Nil(t, err) c.CreateNetwork([]string{"TestCreateAlreadyExistingNetwork"}) @@ -25,7 +27,7 @@ func TestCreateAlreadyExistingNetwork(t *testing.T) { assert.NotEqual(t, "", networkID) } -func TestDeleteNetwork(t *testing.T) { +func TestIntegrationDeleteNetwork(t *testing.T) { c, err := New() assert.Nil(t, err) c.CreateNetwork([]string{"TestDeleteNetwork"}) @@ -33,14 +35,14 @@ func TestDeleteNetwork(t *testing.T) { assert.Nil(t, err) } -func TestDeleteNotExistingNetwork(t *testing.T) { +func TestIntegrationDeleteNotExistingNetwork(t *testing.T) { c, err := New() assert.Nil(t, err) err = c.DeleteNetwork([]string{"TestDeleteNotExistingNetwork"}) assert.Nil(t, err) } -func TestFindNetwork(t *testing.T) { +func TestIntegrationFindNetwork(t *testing.T) { c, err := New() assert.Nil(t, err) c.CreateNetwork([]string{"TestFindNetwork"}) @@ -50,14 +52,14 @@ func TestFindNetwork(t *testing.T) { assert.NotEqual(t, "", network.ID) } -func TestFindNotExistingNetwork(t *testing.T) { +func TestIntegrationFindNotExistingNetwork(t *testing.T) { c, err := New() assert.Nil(t, err) _, err = c.FindNetwork([]string{"TestFindNotExistingNetwork"}) assert.NotNil(t, err) } -func TestFindDeletedNetwork(t *testing.T) { +func TestIntegrationFindDeletedNetwork(t *testing.T) { c, err := New() assert.Nil(t, err) c.CreateNetwork([]string{"TestFindDeletedNetwork"}) diff --git a/container/service_test.go b/container/service_integration_test.go similarity index 83% rename from container/service_test.go rename to container/service_integration_test.go index ee3c7eee7..7f016d388 100644 --- a/container/service_test.go +++ b/container/service_integration_test.go @@ -1,3 +1,5 @@ +// +build integration + package container import ( @@ -17,7 +19,7 @@ func startTestService(name []string) (string, error) { }) } -func TestStartService(t *testing.T) { +func TestIntegrationStartService(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestStartService"} @@ -27,7 +29,7 @@ func TestStartService(t *testing.T) { assert.NotEqual(t, "", serviceID) } -func TestStartService2Times(t *testing.T) { +func TestIntegrationStartService2Times(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestStartService2Times"} @@ -38,7 +40,7 @@ func TestStartService2Times(t *testing.T) { assert.Equal(t, "", serviceID) } -func TestStopService(t *testing.T) { +func TestIntegrationStopService(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestStopService"} @@ -47,7 +49,7 @@ func TestStopService(t *testing.T) { assert.Nil(t, err) } -func TestStopNotExistingService(t *testing.T) { +func TestIntegrationStopNotExistingService(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestStopNotExistingService"} @@ -55,7 +57,7 @@ func TestStopNotExistingService(t *testing.T) { assert.Nil(t, err) } -func TestServiceStatusNeverStarted(t *testing.T) { +func TestIntegrationServiceStatusNeverStarted(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestServiceStatusNeverStarted"} @@ -65,7 +67,7 @@ func TestServiceStatusNeverStarted(t *testing.T) { assert.Equal(t, STOPPED, status) } -func TestServiceStatusRunning(t *testing.T) { +func TestIntegrationServiceStatusRunning(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestServiceStatusRunning"} @@ -77,7 +79,7 @@ func TestServiceStatusRunning(t *testing.T) { assert.NotEqual(t, status, STOPPED) } -func TestServiceStatusStopped(t *testing.T) { +func TestIntegrationServiceStatusStopped(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestServiceStatusStopped"} @@ -89,14 +91,14 @@ func TestServiceStatusStopped(t *testing.T) { assert.NotEqual(t, status, RUNNING) } -func TestFindServiceNotExisting(t *testing.T) { +func TestIntegrationFindServiceNotExisting(t *testing.T) { c, err := New() assert.Nil(t, err) _, err = c.FindService([]string{"TestFindServiceNotExisting"}) assert.NotNil(t, err) } -func TestFindService(t *testing.T) { +func TestIntegrationFindService(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestFindService"} @@ -107,7 +109,7 @@ func TestFindService(t *testing.T) { assert.NotEqual(t, "", service.ID) } -func TestFindServiceCloseName(t *testing.T) { +func TestIntegrationFindServiceCloseName(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestFindServiceCloseName", "name"} @@ -121,7 +123,7 @@ func TestFindServiceCloseName(t *testing.T) { assert.NotEqual(t, "", service.ID) } -func TestFindServiceStopped(t *testing.T) { +func TestIntegrationFindServiceStopped(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestFindServiceStopped"} @@ -131,7 +133,7 @@ func TestFindServiceStopped(t *testing.T) { assert.NotNil(t, err) } -func TestListServices(t *testing.T) { +func TestIntegrationListServices(t *testing.T) { c, err := New() assert.Nil(t, err) c.StartService(ServiceOptions{ @@ -156,7 +158,7 @@ func TestListServices(t *testing.T) { assert.Equal(t, Namespace([]string{"TestListServices"}), services[0].Spec.Name) } -func TestServiceLogs(t *testing.T) { +func TestIntegrationServiceLogs(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestServiceLogs"} diff --git a/container/shared_network_test.go b/container/shared_network_integration_test.go similarity index 80% rename from container/shared_network_test.go rename to container/shared_network_integration_test.go index 8dc164640..b00699f15 100644 --- a/container/shared_network_test.go +++ b/container/shared_network_integration_test.go @@ -1,3 +1,5 @@ +// +build integration + package container import ( @@ -18,7 +20,7 @@ func removeSharedNetworkIfExist(c *Container) error { return c.client.NetworkRemove(context.Background(), Namespace(sharedNetworkNamespace)) } -func TestCreateSharedNetworkIfNeeded(t *testing.T) { +func TestIntegrationCreateSharedNetworkIfNeeded(t *testing.T) { c, err := New() assert.Nil(t, err) err = removeSharedNetworkIfExist(c) @@ -27,7 +29,7 @@ func TestCreateSharedNetworkIfNeeded(t *testing.T) { assert.Nil(t, err) } -func TestSharedNetwork(t *testing.T) { +func TestIntegrationSharedNetwork(t *testing.T) { c, err := New() assert.Nil(t, err) network, err := c.sharedNetwork() @@ -35,7 +37,7 @@ func TestSharedNetwork(t *testing.T) { assert.NotEqual(t, "", network.ID) } -func TestSharedNetworkID(t *testing.T) { +func TestIntegrationSharedNetworkID(t *testing.T) { c, err := New() assert.Nil(t, err) networkID, err := c.SharedNetworkID() diff --git a/container/task_test.go b/container/task_integration_test.go similarity index 88% rename from container/task_test.go rename to container/task_integration_test.go index 1e0d3d99c..9e0129bc9 100644 --- a/container/task_test.go +++ b/container/task_integration_test.go @@ -1,3 +1,5 @@ +// +build integration + package container import ( @@ -7,7 +9,7 @@ import ( "github.com/stvp/assert" ) -func TestListTasks(t *testing.T) { +func TestIntegrationListTasks(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestListTasks"} @@ -19,7 +21,7 @@ func TestListTasks(t *testing.T) { assert.Equal(t, 1, len(tasks)) } -func TestTasksError(t *testing.T) { +func TestIntegrationTasksError(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestTasksError"} diff --git a/container/wait_test.go b/container/wait_integration_test.go similarity index 81% rename from container/wait_test.go rename to container/wait_integration_test.go index d039318b3..3f6af97b1 100644 --- a/container/wait_test.go +++ b/container/wait_integration_test.go @@ -1,3 +1,5 @@ +// +build integration + package container import ( @@ -6,7 +8,7 @@ import ( "github.com/stvp/assert" ) -func TestWaitForStatusRunning(t *testing.T) { +func TestIntegrationWaitForStatusRunning(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestWaitForStatusRunning"} @@ -16,7 +18,7 @@ func TestWaitForStatusRunning(t *testing.T) { assert.Nil(t, err) } -func TestWaitForStatusStopped(t *testing.T) { +func TestIntegrationWaitForStatusStopped(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestWaitForStatusStopped"} @@ -27,7 +29,7 @@ func TestWaitForStatusStopped(t *testing.T) { assert.Nil(t, err) } -func TestWaitForStatusTaskError(t *testing.T) { +func TestIntegrationWaitForStatusTaskError(t *testing.T) { c, err := New() assert.Nil(t, err) namespace := []string{"TestWaitForStatusTaskError"} From 7d18549ac99b0aba0d88edfc682f031141aa9608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lker=20G=C3=B6ktu=C4=9F=20=C3=96zt=C3=BCrk?= Date: Tue, 31 Jul 2018 11:43:53 +0300 Subject: [PATCH 03/22] container: prepare for unit testing, add some unit tests to container.go --- container/build_test.go | 1 + container/container_test.go | 97 ++++++++++++++++++++++++++++++++ container/network_test.go | 1 + container/service_test.go | 1 + container/shared_network_test.go | 1 + container/task_test.go | 1 + 6 files changed, 102 insertions(+) create mode 100644 container/build_test.go create mode 100644 container/container_test.go create mode 100644 container/network_test.go create mode 100644 container/service_test.go create mode 100644 container/shared_network_test.go create mode 100644 container/task_test.go diff --git a/container/build_test.go b/container/build_test.go new file mode 100644 index 000000000..92b957153 --- /dev/null +++ b/container/build_test.go @@ -0,0 +1 @@ +package container diff --git a/container/container_test.go b/container/container_test.go new file mode 100644 index 000000000..9fe92882d --- /dev/null +++ b/container/container_test.go @@ -0,0 +1,97 @@ +package container + +import ( + "testing" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/swarm" + + "github.com/mesg-foundation/core/container/dockertest" + "github.com/stvp/assert" +) + +func TestNew(t *testing.T) { + dt := dockertest.New() + c, err := New(ClientOption(dt.Client())) + assert.Nil(t, err) + assert.NotNil(t, c) + + select { + case <-dt.LastNegotiateAPIVersion(): + default: + t.Fatal("should negotiate api version") + } + + assert.Equal(t, "0.0.0.0:2377", (<-dt.LastSwarmInit()).ListenAddr) + + ln := <-dt.LastNetworkCreate() + assert.Equal(t, "mesg-shared", ln.Name) + assert.Equal(t, types.NetworkCreate{ + CheckDuplicate: true, + Driver: "overlay", + Labels: map[string]string{ + "com.docker.stack.namespace": ln.Name, + }, + }, ln.Options) +} + +func TestNewWithExistingNode(t *testing.T) { + dt := dockertest.New() + dt.ProvideInfo(types.Info{Swarm: swarm.Info{NodeID: "1"}}, nil) + + c, err := New(ClientOption(dt.Client())) + assert.Nil(t, err) + assert.NotNil(t, c) + + select { + case <-dt.LastSwarmInit(): + t.Fail() + default: + } +} + +func TestFindContainerNotExisting(t *testing.T) { + namespace := []string{"TestFindContainerNotExisting"} + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + _, err := c.FindContainer(namespace) + assert.Equal(t, dockertest.ErrContainerDoesNotExists, err) + + assert.Equal(t, types.ContainerListOptions{ + Filters: filters.NewArgs(filters.KeyValuePair{ + Key: "label", + Value: "com.docker.stack.namespace=" + Namespace(namespace), + }), + Limit: 1, + }, <-dt.LastContainerList()) +} + +func TestFindContainer(t *testing.T) { + namespace := []string{"TestFindContainer"} + containerID := "1" + containerData := types.Container{ID: containerID} + containerJSONData := types.ContainerJSON{ContainerJSONBase: &types.ContainerJSONBase{ID: containerID}} + + dt := dockertest.New() + dt.ProvideContainer(containerData) + dt.ProvideContainerInspect(containerJSONData) + + c, _ := New(ClientOption(dt.Client())) + + container, err := c.FindContainer(namespace) + assert.Nil(t, err) + assert.Equal(t, containerJSONData.ID, container.ID) + + assert.Equal(t, types.ContainerListOptions{ + Filters: filters.NewArgs(filters.KeyValuePair{ + Key: "label", + Value: "com.docker.stack.namespace=" + Namespace(namespace), + }), + Limit: 1, + }, <-dt.LastContainerList()) + + assert.Equal(t, containerID, <-dt.LastContainerInspect()) +} diff --git a/container/network_test.go b/container/network_test.go new file mode 100644 index 000000000..92b957153 --- /dev/null +++ b/container/network_test.go @@ -0,0 +1 @@ +package container diff --git a/container/service_test.go b/container/service_test.go new file mode 100644 index 000000000..92b957153 --- /dev/null +++ b/container/service_test.go @@ -0,0 +1 @@ +package container diff --git a/container/shared_network_test.go b/container/shared_network_test.go new file mode 100644 index 000000000..92b957153 --- /dev/null +++ b/container/shared_network_test.go @@ -0,0 +1 @@ +package container diff --git a/container/task_test.go b/container/task_test.go new file mode 100644 index 000000000..92b957153 --- /dev/null +++ b/container/task_test.go @@ -0,0 +1 @@ +package container From c44a964dafb1c8b4e9fd1815a90e946aee029cab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=CC=87lker=20Go=CC=88ktug=CC=86=20O=CC=88ztu=CC=88rk?= Date: Sun, 5 Aug 2018 14:56:47 +0300 Subject: [PATCH 04/22] add more unit tests for container package & extend dockertest API * add more unit tests to container_test.go, build_test.go, network_test.go * extend dockertest API accordingly --- container/build_integration_test.go | 32 ------ container/build_test.go | 89 ++++++++++++++++ container/container_test.go | 61 ++++++++++- container/dockertest/client.go | 50 +++++++-- container/dockertest/error.go | 22 ++++ container/dockertest/testing.go | 30 ++++++ container/network_test.go | 159 ++++++++++++++++++++++++++++ 7 files changed, 401 insertions(+), 42 deletions(-) create mode 100644 container/dockertest/error.go diff --git a/container/build_integration_test.go b/container/build_integration_test.go index d114627f9..290619581 100644 --- a/container/build_integration_test.go +++ b/container/build_integration_test.go @@ -3,11 +3,8 @@ package container import ( - "io/ioutil" - "strings" "testing" - "github.com/docker/docker/api/types" "github.com/stvp/assert" ) @@ -33,32 +30,3 @@ func TestIntegrationBuildWrongPath(t *testing.T) { _, err = c.Build("testss/") assert.NotNil(t, err) } - -func TestIntegrationParseBuildResponseInvalidJSON(t *testing.T) { - body := ioutil.NopCloser(strings.NewReader("invalidJSON")) - response := types.ImageBuildResponse{ - Body: body, - } - _, err := parseBuildResponse(response) - assert.NotNil(t, err) -} - -func TestIntegrationParseBuildResponse(t *testing.T) { - body := ioutil.NopCloser(strings.NewReader("{\"stream\":\"ok\"}")) - response := types.ImageBuildResponse{ - Body: body, - } - tag, err := parseBuildResponse(response) - assert.Nil(t, err) - assert.Equal(t, tag, "ok") -} - -func TestIntegrationParseBuildResponseWithNewLine(t *testing.T) { - body := ioutil.NopCloser(strings.NewReader("{\"stream\":\"ok\\n\"}")) - response := types.ImageBuildResponse{ - Body: body, - } - tag, err := parseBuildResponse(response) - assert.Nil(t, err) - assert.Equal(t, tag, "ok") -} diff --git a/container/build_test.go b/container/build_test.go index 92b957153..789365eac 100644 --- a/container/build_test.go +++ b/container/build_test.go @@ -1 +1,90 @@ package container + +import ( + "fmt" + "io/ioutil" + "strings" + "testing" + + "github.com/docker/docker/api/types" + "github.com/mesg-foundation/core/container/dockertest" + "github.com/stvp/assert" +) + +func TestBuild(t *testing.T) { + path := "test/" + tag := "sha256:1f6359c933421f53a7ef9e417bfa51b1c313c54878fdeb16de827f427e16d836" + + dt := dockertest.New() + dt.ProvideImageBuild(ioutil.NopCloser(strings.NewReader( + fmt.Sprintf(`{"stream":"%s\n"}`, tag), + ))) + + c, _ := New(ClientOption(dt.Client())) + + tag1, err := c.Build(path) + assert.Nil(t, err) + assert.Equal(t, tag, tag1) + + li := <-dt.LastImageBuild() + assert.True(t, len(li.FileData) > 0) + assert.Equal(t, types.ImageBuildOptions{ + Remove: true, + ForceRemove: true, + SuppressOutput: true, + }, li.Options) +} + +func TestBuildNotWorking(t *testing.T) { + path := "test-not-valid/" + + dt := dockertest.New() + dt.ProvideImageBuild(ioutil.NopCloser(strings.NewReader(` +{"stream":"Step 1/2 : FROM notExistingImage"} +{"stream":"\n"} +{"errorDetail":{"message":"invalid reference format: repository name must be lowercase"},"error":"invalid reference format: repository name must be lowercase"}`))) + + c, _ := New(ClientOption(dt.Client())) + + tag, err := c.Build(path) + assert.Equal(t, "Image build failed. invalid reference format: repository name must be lowercase", err.Error()) + assert.Equal(t, "", tag) +} + +func TestBuildWrongPath(t *testing.T) { + dt := dockertest.New() + dt.ProvideImageBuild(ioutil.NopCloser(strings.NewReader(""))) + + c, _ := New(ClientOption(dt.Client())) + _, err := c.Build("testss/") + assert.Equal(t, "Could not parse container build response", err.Error()) +} + +func TestParseBuildResponseInvalidJSON(t *testing.T) { + body := ioutil.NopCloser(strings.NewReader("invalidJSON")) + response := types.ImageBuildResponse{ + Body: body, + } + _, err := parseBuildResponse(response) + assert.NotNil(t, err) +} + +func TestParseBuildResponse(t *testing.T) { + body := ioutil.NopCloser(strings.NewReader("{\"stream\":\"ok\"}")) + response := types.ImageBuildResponse{ + Body: body, + } + tag, err := parseBuildResponse(response) + assert.Nil(t, err) + assert.Equal(t, tag, "ok") +} + +func TestParseBuildResponseWithNewLine(t *testing.T) { + body := ioutil.NopCloser(strings.NewReader("{\"stream\":\"ok\\n\"}")) + response := types.ImageBuildResponse{ + Body: body, + } + tag, err := parseBuildResponse(response) + assert.Nil(t, err) + assert.Equal(t, tag, "ok") +} diff --git a/container/container_test.go b/container/container_test.go index 9fe92882d..a8bc2fa71 100644 --- a/container/container_test.go +++ b/container/container_test.go @@ -51,8 +51,8 @@ func TestNewWithExistingNode(t *testing.T) { } } -func TestFindContainerNotExisting(t *testing.T) { - namespace := []string{"TestFindContainerNotExisting"} +func TestFindContainerNonExistent(t *testing.T) { + namespace := []string{"namespace"} dt := dockertest.New() c, _ := New(ClientOption(dt.Client())) @@ -73,7 +73,11 @@ func TestFindContainer(t *testing.T) { namespace := []string{"TestFindContainer"} containerID := "1" containerData := types.Container{ID: containerID} - containerJSONData := types.ContainerJSON{ContainerJSONBase: &types.ContainerJSONBase{ID: containerID}} + containerJSONData := types.ContainerJSON{ + ContainerJSONBase: &types.ContainerJSONBase{ + ID: containerID, + }, + } dt := dockertest.New() dt.ProvideContainer(containerData) @@ -95,3 +99,54 @@ func TestFindContainer(t *testing.T) { assert.Equal(t, containerID, <-dt.LastContainerInspect()) } + +func TestNonExistentContainerStatus(t *testing.T) { + namespace := []string{"namespace"} + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + status, err := c.Status(namespace) + assert.Equal(t, err, dockertest.ErrContainerDoesNotExists) + assert.Equal(t, STOPPED, status) +} + +func TestExistentContainerStatus(t *testing.T) { + namespace := []string{"namespace"} + containerID := "1" + containerData := types.Container{ID: containerID} + containerJSONData := types.ContainerJSON{ + ContainerJSONBase: &types.ContainerJSONBase{ + ID: containerID, + State: &types.ContainerState{}, + }, + } + + dt := dockertest.New() + dt.ProvideContainer(containerData) + dt.ProvideContainerInspect(containerJSONData) + + c, _ := New(ClientOption(dt.Client())) + status, err := c.Status(namespace) + assert.Nil(t, err) + assert.Equal(t, STOPPED, status) +} + +func TestExistentContainerRunningStatus(t *testing.T) { + namespace := []string{"namespace"} + containerID := "1" + containerData := types.Container{ID: containerID} + containerJSONData := types.ContainerJSON{ + ContainerJSONBase: &types.ContainerJSONBase{ + ID: containerID, + State: &types.ContainerState{Running: true}, + }, + } + + dt := dockertest.New() + dt.ProvideContainer(containerData) + dt.ProvideContainerInspect(containerJSONData) + + c, _ := New(ClientOption(dt.Client())) + status, err := c.Status(namespace) + assert.Nil(t, err) + assert.Equal(t, RUNNING, status) +} diff --git a/container/dockertest/client.go b/container/dockertest/client.go index 611c6eabe..5ed9e4c9a 100644 --- a/container/dockertest/client.go +++ b/container/dockertest/client.go @@ -2,7 +2,8 @@ package dockertest import ( "context" - "errors" + "io" + "io/ioutil" "sync" "github.com/docker/docker/api/types" @@ -10,10 +11,6 @@ import ( docker "github.com/docker/docker/client" ) -var ( - ErrContainerDoesNotExists = errors.New("containers does not exists") -) - type client struct { // a placeholder for unimplemented methods. docker.CommonAPIClient @@ -24,6 +21,9 @@ type client struct { lastInfo chan types.Info lastContainerList chan types.ContainerListOptions lastContainerInspect chan string + lastImageBuild chan ImageBuild + lastNetworkInspect chan NetworkInspect + lastNetworkRemove chan string m sync.RWMutex @@ -32,6 +32,14 @@ type client struct { containers []types.Container containerInspect types.ContainerJSON + + imageBuild types.ImageBuildResponse + + networkInspect types.NetworkResource + networkInspectErr error + + networkCreate types.NetworkCreateResponse + networkCreateErr error } func newClient() *client { @@ -42,6 +50,9 @@ func newClient() *client { lastInfo: make(chan types.Info, 1), lastContainerList: make(chan types.ContainerListOptions, 1), lastContainerInspect: make(chan string, 1), + lastImageBuild: make(chan ImageBuild, 1), + lastNetworkInspect: make(chan NetworkInspect, 1), + lastNetworkRemove: make(chan string, 1), } } @@ -49,9 +60,15 @@ func (c *client) NegotiateAPIVersion(ctx context.Context) { c.lastNegotiateAPIVersion <- struct{}{} } +type NetworkInspect struct { + Network string + Options types.NetworkInspectOptions +} + func (c *client) NetworkInspect(ctx context.Context, network string, options types.NetworkInspectOptions) (types.NetworkResource, error) { - return types.NetworkResource{}, nil + c.lastNetworkInspect <- NetworkInspect{network, options} + return c.networkInspect, c.networkInspectErr } type NetworkCreate struct { @@ -62,7 +79,7 @@ type NetworkCreate struct { func (c *client) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) { c.lastNetworkCreate <- NetworkCreate{name, options} - return types.NetworkCreateResponse{}, nil + return c.networkCreate, c.networkCreateErr } func (c *client) SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error) { @@ -89,3 +106,22 @@ func (c *client) ContainerInspect(ctx context.Context, container string) (types. c.lastContainerInspect <- container return c.containerInspect, nil } + +type ImageBuild struct { + FileData []byte + Options types.ImageBuildOptions +} + +func (c *client) ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) { + bytes, err := ioutil.ReadAll(context) + if err != nil { + return types.ImageBuildResponse{}, err + } + c.lastImageBuild <- ImageBuild{bytes, options} + return c.imageBuild, nil +} + +func (c *client) NetworkRemove(ctx context.Context, network string) error { + c.lastNetworkRemove <- network + return nil +} diff --git a/container/dockertest/error.go b/container/dockertest/error.go new file mode 100644 index 000000000..78d21022b --- /dev/null +++ b/container/dockertest/error.go @@ -0,0 +1,22 @@ +package dockertest + +import "errors" + +var ( + ErrContainerDoesNotExists = errors.New("containers does not exists") +) + +type NotFoundErr struct { +} + +func NewNotFoundErr() NotFoundErr { + return NotFoundErr{} +} + +func (e NotFoundErr) NotFound() bool { + return true +} + +func (e NotFoundErr) Error() string { + return "not found" +} diff --git a/container/dockertest/testing.go b/container/dockertest/testing.go index cd4dcc525..4892d36ce 100644 --- a/container/dockertest/testing.go +++ b/container/dockertest/testing.go @@ -2,6 +2,8 @@ package dockertest import ( + "io" + "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/swarm" ) @@ -47,6 +49,12 @@ func (t *Testing) LastNetworkCreate() chan NetworkCreate { return t.client.lastNetworkCreate } +func (t *Testing) LastNetworkInspect() chan NetworkInspect { + t.client.networkInspect = types.NetworkResource{} + t.client.networkInspectErr = nil + return t.client.lastNetworkInspect +} + type SystemInfo struct { Info types.Info Err error @@ -66,3 +74,25 @@ func (t *Testing) ProvideInfo(info types.Info, err error) { func (t *Testing) LastNegotiateAPIVersion() chan struct{} { return t.client.lastNegotiateAPIVersion } + +func (t *Testing) LastImageBuild() chan ImageBuild { + return t.client.lastImageBuild +} + +func (t *Testing) ProvideImageBuild(rc io.ReadCloser) { + t.client.imageBuild = types.ImageBuildResponse{Body: rc} +} + +func (t *Testing) ProvideNetworkInspect(response types.NetworkResource, err error) { + t.client.networkInspect = response + t.client.networkInspectErr = err +} + +func (t *Testing) ProvideNetwork(response types.NetworkCreateResponse, err error) { + t.client.networkCreate = response + t.client.networkCreateErr = err +} + +func (t *Testing) LastNetworkRemove() chan string { + return t.client.lastNetworkRemove +} diff --git a/container/network_test.go b/container/network_test.go index 92b957153..b502a6dbc 100644 --- a/container/network_test.go +++ b/container/network_test.go @@ -1 +1,160 @@ package container + +import ( + "errors" + "testing" + + "github.com/docker/docker/api/types" + "github.com/mesg-foundation/core/container/dockertest" + "github.com/stvp/assert" +) + +func TestCreateNetwork(t *testing.T) { + namespace := []string{"namespace"} + id := "id" + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + // discard network requests made from New. + <-dt.LastNetworkInspect() + <-dt.LastNetworkCreate() + + dt.ProvideNetwork(types.NetworkCreateResponse{ID: id}, nil) + dt.ProvideNetworkInspect(types.NetworkResource{}, nil) + + networkID, err := c.CreateNetwork(namespace) + assert.Nil(t, err) + assert.Equal(t, id, networkID) + + li := <-dt.LastNetworkCreate() + assert.Equal(t, Namespace(namespace), li.Name) + assert.Equal(t, types.NetworkCreate{ + CheckDuplicate: true, + Driver: "overlay", + Labels: map[string]string{ + "com.docker.stack.namespace": Namespace(namespace), + }, + }, li.Options) +} + +func TestCreateAlreadyExistingNetwork(t *testing.T) { + namespace := []string{"namespace"} + id := "id" + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + // discard network requests made from New. + <-dt.LastNetworkInspect() + <-dt.LastNetworkCreate() + + dt.ProvideNetworkInspect(types.NetworkResource{ID: id}, nil) + + networkID, err := c.CreateNetwork(namespace) + assert.Nil(t, err) + assert.Equal(t, id, networkID) + + li := <-dt.LastNetworkInspect() + assert.Equal(t, Namespace(namespace), li.Network) + assert.Equal(t, types.NetworkInspectOptions{}, li.Options) +} + +func TestDeleteNetwork(t *testing.T) { + namespace := []string{"namespace"} + id := "id" + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + // discard network requests made from New. + <-dt.LastNetworkInspect() + <-dt.LastNetworkCreate() + + dt.ProvideNetworkInspect(types.NetworkResource{ID: id}, nil) + + assert.Nil(t, c.DeleteNetwork(namespace)) + + li := <-dt.LastNetworkInspect() + assert.Equal(t, Namespace(namespace), li.Network) + assert.Equal(t, types.NetworkInspectOptions{}, li.Options) + + assert.Equal(t, id, <-dt.LastNetworkRemove()) +} + +func TestDeleteNotExistingNetwork(t *testing.T) { + namespace := []string{"namespace"} + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + // discard network requests made from New. + <-dt.LastNetworkInspect() + <-dt.LastNetworkCreate() + + dt.ProvideNetworkInspect(types.NetworkResource{}, dockertest.NewNotFoundErr()) + + assert.Nil(t, c.DeleteNetwork(namespace)) + + select { + case <-dt.LastNetworkRemove(): + t.Error("should not remove non existent network") + default: + } +} + +var errNetworkDelete = errors.New("network delete") + +func TestDeleteNetworkError(t *testing.T) { + namespace := []string{"namespace"} + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + // discard network requests made from New. + <-dt.LastNetworkInspect() + <-dt.LastNetworkCreate() + + dt.ProvideNetworkInspect(types.NetworkResource{}, errNetworkDelete) + + assert.NotNil(t, c.DeleteNetwork(namespace)) +} + +func TestFindNetwork(t *testing.T) { + namespace := []string{"namespace"} + id := "id" + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + // discard network requests made from New. + <-dt.LastNetworkInspect() + <-dt.LastNetworkCreate() + + dt.ProvideNetworkInspect(types.NetworkResource{ID: id}, nil) + + network, err := c.FindNetwork(namespace) + assert.Nil(t, err) + assert.Equal(t, id, network.ID) + + li := <-dt.LastNetworkInspect() + assert.Equal(t, Namespace(namespace), li.Network) + assert.Equal(t, types.NetworkInspectOptions{}, li.Options) +} + +func TestFindNotExistingNetwork(t *testing.T) { + namespace := []string{"namespace"} + notFoundErr := dockertest.NewNotFoundErr() + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + // discard network requests made from New. + <-dt.LastNetworkInspect() + <-dt.LastNetworkCreate() + + dt.ProvideNetworkInspect(types.NetworkResource{}, notFoundErr) + + _, err := c.FindNetwork(namespace) + assert.Equal(t, notFoundErr, err) +} From ce23fd086503abff80bf217bd03a959ed64e43a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=CC=87lker=20Go=CC=88ktug=CC=86=20O=CC=88ztu=CC=88rk?= Date: Sun, 5 Aug 2018 15:14:48 +0300 Subject: [PATCH 05/22] make non Newable packages compatible with container package --- cmd/service/utils.go | 15 ++++++++++++++- daemon/init.go | 18 ++++++++++++++++++ daemon/logs.go | 4 +--- daemon/start.go | 4 ++-- daemon/start_test.go | 4 ++-- daemon/status.go | 2 +- daemon/stop.go | 2 +- service/init.go | 18 ++++++++++++++++++ service/logs.go | 4 +--- service/start.go | 6 +++--- service/start_test.go | 10 +++++----- service/status.go | 4 ++-- service/stop.go | 4 ++-- service/stop_test.go | 6 +++--- 14 files changed, 73 insertions(+), 28 deletions(-) create mode 100644 daemon/init.go create mode 100644 service/init.go diff --git a/cmd/service/utils.go b/cmd/service/utils.go index cc80ea32d..13092598f 100644 --- a/cmd/service/utils.go +++ b/cmd/service/utils.go @@ -3,6 +3,7 @@ package service import ( "fmt" "io/ioutil" + "log" "net/url" "os" @@ -20,6 +21,18 @@ import ( "gopkg.in/src-d/go-git.v4/plumbing" ) +// TODO(ilgooz): remove this after service package made Newable. +var defaultContainer *container.Container + +// TODO(ilgooz): remove this after service package made Newable. +func init() { + c, err := container.New() + if err != nil { + log.Fatal(err) + } + defaultContainer = c +} + func cli() core.CoreClient { connection, err := grpc.Dial(viper.GetString(config.APIClientTarget), grpc.WithInsecure()) utils.HandleError(err) @@ -100,7 +113,7 @@ func createTempFolder() (path string, err error) { func buildDockerImage(path string) (imageHash string, err error) { utils.ShowSpinnerForFunc(utils.SpinnerOptions{Text: "Building image..."}, func() { - imageHash, err = container.Build(path) + imageHash, err = defaultContainer.Build(path) }) return } diff --git a/daemon/init.go b/daemon/init.go new file mode 100644 index 000000000..a707f94ac --- /dev/null +++ b/daemon/init.go @@ -0,0 +1,18 @@ +// TODO(ilgooz): remove this file after service package made Newable. +package daemon + +import ( + "log" + + "github.com/mesg-foundation/core/container" +) + +var defaultContainer *container.Container + +func init() { + c, err := container.New() + if err != nil { + log.Fatal(err) + } + defaultContainer = c +} diff --git a/daemon/logs.go b/daemon/logs.go index 2c161ca71..77e362781 100644 --- a/daemon/logs.go +++ b/daemon/logs.go @@ -2,11 +2,9 @@ package daemon import ( "io" - - "github.com/mesg-foundation/core/container" ) // Logs returns the core's docker service logs. func Logs() (io.ReadCloser, error) { - return container.ServiceLogs(Namespace()) + return defaultContainer.ServiceLogs(Namespace()) } diff --git a/daemon/start.go b/daemon/start.go index b1e61f3df..b16ef3f3c 100644 --- a/daemon/start.go +++ b/daemon/start.go @@ -18,11 +18,11 @@ func Start() (serviceID string, err error) { if err != nil { return "", err } - return container.StartService(spec) + return defaultContainer.StartService(spec) } func serviceSpec() (spec container.ServiceOptions, err error) { - sharedNetworkID, err := container.SharedNetworkID() + sharedNetworkID, err := defaultContainer.SharedNetworkID() if err != nil { return container.ServiceOptions{}, err } diff --git a/daemon/start_test.go b/daemon/start_test.go index 254ad7a85..dbddaa9e7 100644 --- a/daemon/start_test.go +++ b/daemon/start_test.go @@ -19,11 +19,11 @@ func startForTest() { if status == container.RUNNING { return } - sharedNetworkID, err := container.SharedNetworkID() + sharedNetworkID, err := defaultContainer.SharedNetworkID() if err != nil { panic(err) } - _, err = container.StartService(container.ServiceOptions{ + _, err = defaultContainer.StartService(container.ServiceOptions{ Namespace: Namespace(), Image: "nginx", NetworksID: []string{sharedNetworkID}, diff --git a/daemon/status.go b/daemon/status.go index a3b71c4fb..ab91d4c6d 100644 --- a/daemon/status.go +++ b/daemon/status.go @@ -6,5 +6,5 @@ import ( // Status returns the Status of the docker service of the daemon. func Status() (container.StatusType, error) { - return container.ServiceStatus(Namespace()) //TODO: should it be containerStatus? + return defaultContainer.ServiceStatus(Namespace()) //TODO: should it be containerStatus? } diff --git a/daemon/stop.go b/daemon/stop.go index ed36a6837..246b32aac 100644 --- a/daemon/stop.go +++ b/daemon/stop.go @@ -10,5 +10,5 @@ func Stop() error { if err != nil || status == container.STOPPED { return err } - return container.StopService(Namespace()) + return defaultContainer.StopService(Namespace()) } diff --git a/service/init.go b/service/init.go new file mode 100644 index 000000000..d3156cc1c --- /dev/null +++ b/service/init.go @@ -0,0 +1,18 @@ +// TODO(ilgooz): remove this file after service package made Newable. +package service + +import ( + "log" + + "github.com/mesg-foundation/core/container" +) + +var defaultContainer *container.Container + +func init() { + c, err := container.New() + if err != nil { + log.Fatal(err) + } + defaultContainer = c +} diff --git a/service/logs.go b/service/logs.go index 34531f57d..c9a12d0cf 100644 --- a/service/logs.go +++ b/service/logs.go @@ -2,8 +2,6 @@ package service import ( "io" - - "github.com/mesg-foundation/core/container" ) // Logs returns the service's docker service logs. Optionally only shows the logs of a given dependency. @@ -12,7 +10,7 @@ func (service *Service) Logs(onlyForDependency string) ([]io.ReadCloser, error) for _, dep := range service.DependenciesFromService() { if onlyForDependency == "" || onlyForDependency == "*" || onlyForDependency == dep.Name { var reader io.ReadCloser - reader, err := container.ServiceLogs(dep.namespace()) + reader, err := defaultContainer.ServiceLogs(dep.namespace()) if err != nil { return readers, err } diff --git a/service/start.go b/service/start.go index 5227a6173..07887cd66 100644 --- a/service/start.go +++ b/service/start.go @@ -26,7 +26,7 @@ func (service *Service) Start() (serviceIDs []string, err error) { return nil, err } } - networkID, err := container.CreateNetwork(service.namespace()) + networkID, err := defaultContainer.CreateNetwork(service.namespace()) if err != nil { return nil, err } @@ -66,7 +66,7 @@ func (dependency *DependencyFromService) Start(networkID string) (containerServi if service == nil { return "", errors.New("Service is nil") } - sharedNetworkID, err := container.SharedNetworkID() + sharedNetworkID, err := defaultContainer.SharedNetworkID() if err != nil { return "", err } @@ -74,7 +74,7 @@ func (dependency *DependencyFromService) Start(networkID string) (containerServi if err != nil { return "", err } - return container.StartService(container.ServiceOptions{ + return defaultContainer.StartService(container.ServiceOptions{ Namespace: dependency.namespace(), Labels: map[string]string{ "mesg.service": service.Name, diff --git a/service/start_test.go b/service/start_test.go index 445caed46..105b669cf 100644 --- a/service/start_test.go +++ b/service/start_test.go @@ -63,8 +63,8 @@ func TestStartWith2Dependencies(t *testing.T) { assert.Nil(t, err) assert.Equal(t, 2, len(servicesID)) deps := service.DependenciesFromService() - container1, _ := container.FindContainer(deps[0].namespace()) - container2, _ := container.FindContainer(deps[1].namespace()) + container1, _ := defaultContainer.FindContainer(deps[0].namespace()) + container2, _ := defaultContainer.FindContainer(deps[1].namespace()) assert.Equal(t, "nginx:latest", container1.Config.Image) assert.Equal(t, "alpine:latest", container2.Config.Image) } @@ -120,8 +120,8 @@ func TestStartDependency(t *testing.T) { }, }, } - networkID, err := container.CreateNetwork(service.namespace()) - defer container.DeleteNetwork(service.namespace()) + networkID, err := defaultContainer.CreateNetwork(service.namespace()) + defer defaultContainer.DeleteNetwork(service.namespace()) dep := service.DependenciesFromService()[0] serviceID, err := dep.Start(networkID) defer dep.Stop() @@ -142,7 +142,7 @@ func TestNetworkCreated(t *testing.T) { } service.Start() defer service.Stop() - network, err := container.FindNetwork(service.namespace()) + network, err := defaultContainer.FindNetwork(service.namespace()) assert.Nil(t, err) assert.NotEqual(t, "", network.ID) } diff --git a/service/status.go b/service/status.go index bbf826c18..9836f8135 100644 --- a/service/status.go +++ b/service/status.go @@ -37,13 +37,13 @@ func (service *Service) Status() (StatusType, error) { // Status returns StatusType of dependency's container. func (dependency *DependencyFromService) Status() (container.StatusType, error) { - return container.ServiceStatus(dependency.namespace()) + return defaultContainer.ServiceStatus(dependency.namespace()) } // ListRunning returns all the running services.2 // TODO: should move to another file func ListRunning() ([]string, error) { - services, err := container.ListServices("mesg.hash") + services, err := defaultContainer.ListServices("mesg.hash") if err != nil { return nil, err } diff --git a/service/stop.go b/service/stop.go index da6cac97b..4b75ff877 100644 --- a/service/stop.go +++ b/service/stop.go @@ -16,7 +16,7 @@ func (service *Service) Stop() error { if err := service.StopDependencies(); err != nil { return err } - return container.DeleteNetwork(service.namespace()) + return defaultContainer.DeleteNetwork(service.namespace()) } // StopDependencies stops all dependencies. @@ -46,5 +46,5 @@ func (dependency *DependencyFromService) Stop() error { if err != nil || status == container.STOPPED { return err } - return container.StopService(dependency.namespace()) + return defaultContainer.StopService(dependency.namespace()) } diff --git a/service/stop_test.go b/service/stop_test.go index b93d32981..07ca1a44f 100644 --- a/service/stop_test.go +++ b/service/stop_test.go @@ -48,8 +48,8 @@ func TestStopDependency(t *testing.T) { }, }, } - networkID, err := container.CreateNetwork(service.namespace()) - defer container.DeleteNetwork(service.namespace()) + networkID, err := defaultContainer.CreateNetwork(service.namespace()) + defer defaultContainer.DeleteNetwork(service.namespace()) dep := service.DependenciesFromService()[0] dep.Start(networkID) err = dep.Stop() @@ -70,6 +70,6 @@ func TestNetworkDeleted(t *testing.T) { service.Start() service.Stop() time.Sleep(5 * time.Second) - _, err := container.FindNetwork(service.namespace()) + _, err := defaultContainer.FindNetwork(service.namespace()) assert.NotNil(t, err) } From 97d88654d4be197b0fb523c1fc1ec54998bddc8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=CC=87lker=20Go=CC=88ktug=CC=86=20O=CC=88ztu=CC=88rk?= Date: Sun, 5 Aug 2018 21:02:14 +0300 Subject: [PATCH 06/22] add more unit tests for container package & extend dockertest API * add unit tests to service_test,go, shared_network_test.go, task_test.go, wait_test.go * extend dockertest API accordingly * small fixes --- container/container_test.go | 4 +- container/dockertest/client.go | 116 ++++++++++++++++--- container/dockertest/testing.go | 65 +++++++++++ container/service_test.go | 191 +++++++++++++++++++++++++++++++ container/shared_network_test.go | 93 +++++++++++++++ container/task_test.go | 66 +++++++++++ container/wait_test.go | 77 +++++++++++++ daemon/init.go | 2 +- 8 files changed, 592 insertions(+), 22 deletions(-) create mode 100644 container/wait_test.go diff --git a/container/container_test.go b/container/container_test.go index a8bc2fa71..591c1ee30 100644 --- a/container/container_test.go +++ b/container/container_test.go @@ -58,7 +58,7 @@ func TestFindContainerNonExistent(t *testing.T) { c, _ := New(ClientOption(dt.Client())) _, err := c.FindContainer(namespace) - assert.Equal(t, dockertest.ErrContainerDoesNotExists, err) + assert.Equal(t, dockertest.NotFoundErr{}, err) assert.Equal(t, types.ContainerListOptions{ Filters: filters.NewArgs(filters.KeyValuePair{ @@ -105,7 +105,7 @@ func TestNonExistentContainerStatus(t *testing.T) { dt := dockertest.New() c, _ := New(ClientOption(dt.Client())) status, err := c.Status(namespace) - assert.Equal(t, err, dockertest.ErrContainerDoesNotExists) + assert.Nil(t, err) assert.Equal(t, STOPPED, status) } diff --git a/container/dockertest/client.go b/container/dockertest/client.go index 5ed9e4c9a..e4bc10469 100644 --- a/container/dockertest/client.go +++ b/container/dockertest/client.go @@ -15,15 +15,21 @@ type client struct { // a placeholder for unimplemented methods. docker.CommonAPIClient - lastNegotiateAPIVersion chan struct{} - lastSwarmInit chan swarm.InitRequest - lastNetworkCreate chan NetworkCreate - lastInfo chan types.Info - lastContainerList chan types.ContainerListOptions - lastContainerInspect chan string - lastImageBuild chan ImageBuild - lastNetworkInspect chan NetworkInspect - lastNetworkRemove chan string + lastNegotiateAPIVersion chan struct{} + lastSwarmInit chan swarm.InitRequest + lastNetworkCreate chan NetworkCreate + lastInfo chan types.Info + lastContainerList chan types.ContainerListOptions + lastContainerInspect chan string + lastImageBuild chan ImageBuild + lastNetworkInspect chan NetworkInspect + lastNetworkRemove chan string + lastTaskList chan types.TaskListOptions + lastServiceCreate chan ServiceCreate + lastServiceList chan types.ServiceListOptions + lastServiceInspectWithRaw chan ServiceInspectWithRaw + lastServiceRemove chan string + lastServiceLogs chan ServiceLogs m sync.RWMutex @@ -40,19 +46,43 @@ type client struct { networkCreate types.NetworkCreateResponse networkCreateErr error + + tasklist []swarm.Task + tasklistErr error + + serviceCreate types.ServiceCreateResponse + serviceCreateErr error + + serviceList []swarm.Service + serviceListErr error + + serviceInspectWithRaw swarm.Service + serviceInspectWithRawBytes []byte + serviceInspectWithRawErr error + + serviceRemoveErr error + + serviceLogs io.ReadCloser + serviceLogsErr error } func newClient() *client { return &client{ - lastNegotiateAPIVersion: make(chan struct{}, 1), - lastSwarmInit: make(chan swarm.InitRequest, 1), - lastNetworkCreate: make(chan NetworkCreate, 1), - lastInfo: make(chan types.Info, 1), - lastContainerList: make(chan types.ContainerListOptions, 1), - lastContainerInspect: make(chan string, 1), - lastImageBuild: make(chan ImageBuild, 1), - lastNetworkInspect: make(chan NetworkInspect, 1), - lastNetworkRemove: make(chan string, 1), + lastNegotiateAPIVersion: make(chan struct{}, 1), + lastSwarmInit: make(chan swarm.InitRequest, 1), + lastNetworkCreate: make(chan NetworkCreate, 1), + lastInfo: make(chan types.Info, 1), + lastContainerList: make(chan types.ContainerListOptions, 1), + lastContainerInspect: make(chan string, 1), + lastImageBuild: make(chan ImageBuild, 1), + lastNetworkInspect: make(chan NetworkInspect, 1), + lastNetworkRemove: make(chan string, 1), + lastTaskList: make(chan types.TaskListOptions, 1), + lastServiceCreate: make(chan ServiceCreate, 1), + lastServiceList: make(chan types.ServiceListOptions, 1), + lastServiceInspectWithRaw: make(chan ServiceInspectWithRaw, 1), + lastServiceRemove: make(chan string, 1), + lastServiceLogs: make(chan ServiceLogs, 1), } } @@ -99,7 +129,7 @@ func (c *client) ContainerList(ctx context.Context, if len(c.containers) > 0 { return c.containers, nil } - return c.containers, ErrContainerDoesNotExists + return c.containers, NotFoundErr{} } func (c *client) ContainerInspect(ctx context.Context, container string) (types.ContainerJSON, error) { @@ -125,3 +155,51 @@ func (c *client) NetworkRemove(ctx context.Context, network string) error { c.lastNetworkRemove <- network return nil } + +func (c *client) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) { + c.lastTaskList <- options + return c.tasklist, c.tasklistErr +} + +type ServiceCreate struct { + Service swarm.ServiceSpec + Options types.ServiceCreateOptions +} + +func (c *client) ServiceCreate(ctx context.Context, + service swarm.ServiceSpec, options types.ServiceCreateOptions) (types.ServiceCreateResponse, error) { + c.lastServiceCreate <- ServiceCreate{service, options} + return c.serviceCreate, c.serviceCreateErr +} + +func (c *client) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) { + c.lastServiceList <- options + return c.serviceList, c.serviceListErr +} + +type ServiceInspectWithRaw struct { + ServiceID string + Options types.ServiceInspectOptions +} + +func (c *client) ServiceInspectWithRaw(ctx context.Context, serviceID string, + options types.ServiceInspectOptions) (swarm.Service, []byte, error) { + c.lastServiceInspectWithRaw <- ServiceInspectWithRaw{serviceID, options} + return c.serviceInspectWithRaw, c.serviceInspectWithRawBytes, c.serviceInspectWithRawErr +} + +func (c *client) ServiceRemove(ctx context.Context, serviceID string) error { + c.lastServiceRemove <- serviceID + return c.serviceRemoveErr +} + +type ServiceLogs struct { + ServiceID string + Options types.ContainerLogsOptions +} + +func (c *client) ServiceLogs(ctx context.Context, + serviceID string, options types.ContainerLogsOptions) (io.ReadCloser, error) { + c.lastServiceLogs <- ServiceLogs{serviceID, options} + return c.serviceLogs, c.serviceLogsErr +} diff --git a/container/dockertest/testing.go b/container/dockertest/testing.go index 4892d36ce..4728b2c20 100644 --- a/container/dockertest/testing.go +++ b/container/dockertest/testing.go @@ -96,3 +96,68 @@ func (t *Testing) ProvideNetwork(response types.NetworkCreateResponse, err error func (t *Testing) LastNetworkRemove() chan string { return t.client.lastNetworkRemove } + +func (t *Testing) LastTaskList() chan types.TaskListOptions { + return t.client.lastTaskList +} + +func (t *Testing) ProvideTaskList(tasks []swarm.Task, err error) { + t.client.tasklist = tasks + t.client.tasklistErr = err +} + +func (t *Testing) LastServiceCreate() chan ServiceCreate { + return t.client.lastServiceCreate +} + +func (t *Testing) ProvideServiceCreate(response types.ServiceCreateResponse, err error) { + // TODO(ilgooz) do the same shortcurt(calling needed Provides) made here + // on other needed places too. + containerData := types.Container{} + containerJSONData := types.ContainerJSON{ + ContainerJSONBase: &types.ContainerJSONBase{ + State: &types.ContainerState{Running: true}, + }, + } + t.ProvideContainer(containerData) + t.ProvideContainerInspect(containerJSONData) + + t.client.serviceCreate = response + t.client.serviceCreateErr = err +} + +func (t *Testing) LastServiceList() chan types.ServiceListOptions { + return t.client.lastServiceList +} + +func (t *Testing) ProvideServiceList(list []swarm.Service, err error) { + t.client.serviceList = list + t.client.serviceListErr = err +} + +func (t *Testing) LastServiceInspectWithRaw() chan ServiceInspectWithRaw { + return t.client.lastServiceInspectWithRaw +} + +func (t *Testing) ProvideServiceInspectWithRaw(service swarm.Service, data []byte, err error) { + t.client.serviceInspectWithRaw = service + t.client.serviceInspectWithRawBytes = data + t.client.serviceInspectWithRawErr = err +} + +func (t *Testing) LastServiceRemove() chan string { + return t.client.lastServiceRemove +} + +func (t *Testing) ProvideServiceRemove(err error) { + t.client.serviceRemoveErr = err +} + +func (t *Testing) LastServiceLogs() chan ServiceLogs { + return t.client.lastServiceLogs +} + +func (t *Testing) ProvideServiceLogs(rc io.ReadCloser, err error) { + t.client.serviceLogs = rc + t.client.serviceLogsErr = err +} diff --git a/container/service_test.go b/container/service_test.go index 92b957153..9101ee596 100644 --- a/container/service_test.go +++ b/container/service_test.go @@ -1 +1,192 @@ package container + +import ( + "io/ioutil" + "strings" + "testing" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/swarm" + "github.com/mesg-foundation/core/container/dockertest" + "github.com/stvp/assert" +) + +func TestStartService(t *testing.T) { + namespace := []string{"namespace"} + containerID := "id" + options := ServiceOptions{ + Image: "nginx", + Namespace: namespace, + } + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + dt.ProvideServiceCreate(types.ServiceCreateResponse{ID: containerID}, nil) + + id, err := c.StartService(options) + assert.Nil(t, err) + assert.Equal(t, containerID, id) + + ls := <-dt.LastServiceCreate() + assert.Equal(t, options.toSwarmServiceSpec(), ls.Service) + assert.Equal(t, types.ServiceCreateOptions{}, ls.Options) +} + +func TestStopService(t *testing.T) { + namespace := []string{"namespace"} + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + assert.Nil(t, c.StopService(namespace)) + + li := <-dt.LastServiceInspectWithRaw() + assert.Equal(t, Namespace(namespace), li.ServiceID) + assert.Equal(t, types.ServiceInspectOptions{}, li.Options) + + assert.Equal(t, Namespace(namespace), <-dt.LastServiceRemove()) +} + +func TestStopNotExistingService(t *testing.T) { + namespace := []string{"namespace"} + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + dt.ProvideServiceInspectWithRaw(swarm.Service{}, nil, dockertest.NotFoundErr{}) + + assert.Nil(t, c.StopService(namespace)) + + li := <-dt.LastServiceInspectWithRaw() + assert.Equal(t, Namespace(namespace), li.ServiceID) + assert.Equal(t, types.ServiceInspectOptions{}, li.Options) + + select { + case <-dt.LastServiceRemove(): + t.Error("should not remove non existent service") + default: + } +} + +func TestServiceStatusNeverStarted(t *testing.T) { + namespace := []string{"namespace"} + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + dt.ProvideServiceInspectWithRaw(swarm.Service{}, nil, dockertest.NotFoundErr{}) + + status, err := c.ServiceStatus(namespace) + assert.Nil(t, err) + assert.Equal(t, STOPPED, status) + + li := <-dt.LastServiceInspectWithRaw() + assert.Equal(t, Namespace(namespace), li.ServiceID) + assert.Equal(t, types.ServiceInspectOptions{}, li.Options) +} + +func TestIntegrationServiceStatusRunning(t *testing.T) { + namespace := []string{"namespace"} + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + status, err := c.ServiceStatus(namespace) + assert.Nil(t, err) + assert.Equal(t, RUNNING, status) + + li := <-dt.LastServiceInspectWithRaw() + assert.Equal(t, Namespace(namespace), li.ServiceID) + assert.Equal(t, types.ServiceInspectOptions{}, li.Options) +} + +func TestFindService(t *testing.T) { + namespace := []string{"namespace"} + swarmService := swarm.Service{ID: "1"} + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + dt.ProvideServiceInspectWithRaw(swarmService, nil, nil) + + service, err := c.FindService(namespace) + assert.Nil(t, err) + assert.Equal(t, swarmService.ID, service.ID) + + li := <-dt.LastServiceInspectWithRaw() + assert.Equal(t, Namespace(namespace), li.ServiceID) + assert.Equal(t, types.ServiceInspectOptions{}, li.Options) +} + +func TestFindServiceNotExisting(t *testing.T) { + namespace := []string{"namespace"} + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + dt.ProvideServiceInspectWithRaw(swarm.Service{}, nil, dockertest.NotFoundErr{}) + + _, err := c.FindService(namespace) + assert.Equal(t, dockertest.NotFoundErr{}, err) + + li := <-dt.LastServiceInspectWithRaw() + assert.Equal(t, Namespace(namespace), li.ServiceID) + assert.Equal(t, types.ServiceInspectOptions{}, li.Options) +} + +func TestListServices(t *testing.T) { + namespace := []string{"namespace"} + label := "1" + swarmServices := []swarm.Service{ + {Spec: swarm.ServiceSpec{Annotations: swarm.Annotations{Name: Namespace(namespace)}}}, + {Spec: swarm.ServiceSpec{Annotations: swarm.Annotations{Name: Namespace(namespace)}}}, + } + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + dt.ProvideServiceList(swarmServices, nil) + + services, err := c.ListServices(label) + assert.Nil(t, err) + assert.Equal(t, 2, len(services)) + assert.Equal(t, Namespace(namespace), services[0].Spec.Name) + assert.Equal(t, Namespace(namespace), services[1].Spec.Name) + + assert.Equal(t, types.ServiceListOptions{ + Filters: filters.NewArgs(filters.KeyValuePair{ + Key: "label", + Value: label, + }), + }, <-dt.LastServiceList()) +} + +func TestServiceLogs(t *testing.T) { + namespace := []string{"namespace"} + data := "mesg" + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + dt.ProvideServiceLogs(ioutil.NopCloser(strings.NewReader(data)), nil) + + reader, err := c.ServiceLogs(namespace) + assert.Nil(t, err) + + defer reader.Close() + bytes, err := ioutil.ReadAll(reader) + assert.Nil(t, err) + assert.Equal(t, data, string(bytes)) + + ll := <-dt.LastServiceLogs() + + assert.Equal(t, Namespace(namespace), ll.ServiceID) + assert.Equal(t, types.ContainerLogsOptions{ + ShowStdout: true, + ShowStderr: true, + Timestamps: false, + Follow: true, + }, ll.Options) +} diff --git a/container/shared_network_test.go b/container/shared_network_test.go index 92b957153..a7e7b09ae 100644 --- a/container/shared_network_test.go +++ b/container/shared_network_test.go @@ -1 +1,94 @@ package container + +import ( + "testing" + + "github.com/docker/docker/api/types" + "github.com/mesg-foundation/core/container/dockertest" + "github.com/stvp/assert" +) + +func TestSharedNetwork(t *testing.T) { + id := "id" + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + // discard network requests made from New. + <-dt.LastNetworkInspect() + <-dt.LastNetworkCreate() + + dt.ProvideNetworkInspect(types.NetworkResource{ID: id}, nil) + + network, err := c.sharedNetwork() + assert.Nil(t, err) + assert.Equal(t, id, network.ID) + + li := <-dt.LastNetworkInspect() + assert.Equal(t, Namespace(sharedNetworkNamespace), li.Network) + assert.Equal(t, types.NetworkInspectOptions{}, li.Options) +} + +func TestCreateSharedNetworkIfNeeded(t *testing.T) { + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + // discard network requests made from New. + <-dt.LastNetworkInspect() + <-dt.LastNetworkCreate() + + dt.ProvideNetworkInspect(types.NetworkResource{}, nil) + + assert.Nil(t, c.createSharedNetworkIfNeeded()) + + lc := <-dt.LastNetworkCreate() + assert.Equal(t, Namespace(sharedNetworkNamespace), lc.Name) + assert.Equal(t, types.NetworkCreate{ + CheckDuplicate: true, + Driver: "overlay", + Labels: map[string]string{ + "com.docker.stack.namespace": Namespace(sharedNetworkNamespace), + }, + }, lc.Options) +} + +func TestCreateSharedNetworkIfNeededExists(t *testing.T) { + id := "id" + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + // discard network requests made from New. + <-dt.LastNetworkInspect() + <-dt.LastNetworkCreate() + + dt.ProvideNetworkInspect(types.NetworkResource{ID: id}, nil) + + assert.Nil(t, c.createSharedNetworkIfNeeded()) + + select { + case <-dt.LastNetworkCreate(): + t.Error("should not create network") + default: + } +} + +func TestIntegrationSharedNetworkID(t *testing.T) { + id := "1" + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + // discard network requests made from New. + <-dt.LastNetworkInspect() + <-dt.LastNetworkCreate() + + dt.ProvideNetworkInspect(types.NetworkResource{ID: id}, nil) + + network, err := c.SharedNetworkID() + assert.Nil(t, err) + assert.Equal(t, network, id) + + li := <-dt.LastNetworkInspect() + assert.Equal(t, Namespace(sharedNetworkNamespace), li.Network) + assert.Equal(t, types.NetworkInspectOptions{}, li.Options) +} diff --git a/container/task_test.go b/container/task_test.go index 92b957153..9487b765a 100644 --- a/container/task_test.go +++ b/container/task_test.go @@ -1 +1,67 @@ package container + +import ( + "errors" + "testing" + + "github.com/docker/docker/api/types/swarm" + "github.com/mesg-foundation/core/container/dockertest" + "github.com/stvp/assert" +) + +func TestListTasks(t *testing.T) { + namespace := []string{"namespace"} + tasks := []swarm.Task{ + {ID: "1"}, + {ID: "2"}, + } + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + dt.ProvideTaskList(tasks, nil) + + tasks1, err := c.ListTasks(namespace) + assert.Nil(t, err) + assert.Equal(t, tasks, tasks1) + assert.Equal(t, len(tasks), len(tasks1)) +} + +var errTaskList = errors.New("task list") + +func TestListTasksError(t *testing.T) { + namespace := []string{"namespace"} + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + dt.ProvideTaskList(nil, errTaskList) + + _, err := c.ListTasks(namespace) + assert.Equal(t, errTaskList, err) +} + +func TestTasksError(t *testing.T) { + namespace := []string{"namespace"} + tasks := []swarm.Task{ + { + ID: "1", + Status: swarm.TaskStatus{Err: "1-err"}, + }, + { + ID: "1", + Status: swarm.TaskStatus{Err: "2-err"}, + }, + } + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + dt.ProvideTaskList(tasks, nil) + + errors, err := c.TasksError(namespace) + assert.Nil(t, err) + assert.Equal(t, len(tasks), len(errors)) + assert.Equal(t, tasks[0].Status.Err, errors[0]) + assert.Equal(t, tasks[1].Status.Err, errors[1]) +} diff --git a/container/wait_test.go b/container/wait_test.go new file mode 100644 index 000000000..a359d6c27 --- /dev/null +++ b/container/wait_test.go @@ -0,0 +1,77 @@ +package container + +import ( + "testing" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/swarm" + "github.com/mesg-foundation/core/container/dockertest" + "github.com/stvp/assert" +) + +func TestWaitForStatusRunning(t *testing.T) { + namespace := []string{"namespace"} + containerID := "1" + containerData := types.Container{ID: containerID} + containerJSONData := types.ContainerJSON{ + ContainerJSONBase: &types.ContainerJSONBase{ + ID: containerID, + State: &types.ContainerState{Running: true}, + }, + } + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + dt.ProvideContainer(containerData) + dt.ProvideContainerInspect(containerJSONData) + + assert.Nil(t, c.waitForStatus(namespace, RUNNING)) +} + +func TestWaitForStatusStopped(t *testing.T) { + namespace := []string{"namespace"} + containerID := "1" + containerData := types.Container{ID: containerID} + containerJSONData := types.ContainerJSON{ + ContainerJSONBase: &types.ContainerJSONBase{ + ID: containerID, + State: &types.ContainerState{}, + }, + } + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + dt.ProvideContainer(containerData) + dt.ProvideContainerInspect(containerJSONData) + + assert.Nil(t, c.waitForStatus(namespace, STOPPED)) +} + +func TestWaitForStatusTaskError(t *testing.T) { + namespace := []string{"namespace"} + tasks := []swarm.Task{ + { + ID: "1", + Status: swarm.TaskStatus{Err: "1-err"}, + }, + { + ID: "1", + Status: swarm.TaskStatus{Err: "2-err"}, + }, + } + + dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + + dt.ProvideTaskList(tasks, nil) + + assert.Equal(t, "1-err, 2-err", c.waitForStatus(namespace, RUNNING).Error()) + + select { + case <-dt.LastContainerList(): + t.Error("container list shouldn't be called") + default: + } +} diff --git a/daemon/init.go b/daemon/init.go index a707f94ac..cb6c92dfd 100644 --- a/daemon/init.go +++ b/daemon/init.go @@ -1,4 +1,4 @@ -// TODO(ilgooz): remove this file after service package made Newable. +// TODO(ilgooz): remove this file after daemon package made Newable. package daemon import ( From 8b3d615ac9c895cc98c9ce6d6e65c1493fb99d8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=CC=87lker=20Go=CC=88ktug=CC=86=20O=CC=88ztu=CC=88rk?= Date: Mon, 6 Aug 2018 14:57:12 +0300 Subject: [PATCH 07/22] refactor container/dockertest * update container tests accordingly --- container/container_test.go | 44 ++-- container/dockertest/client.go | 349 ++++++++++++++++++------------ container/dockertest/error.go | 17 +- container/dockertest/requests.go | 86 ++++++++ container/dockertest/responses.go | 80 +++++++ container/dockertest/testing.go | 181 ++++++++-------- container/network_test.go | 11 +- container/service_test.go | 13 +- container/task_test.go | 9 + container/wait_test.go | 16 +- 10 files changed, 538 insertions(+), 268 deletions(-) create mode 100644 container/dockertest/requests.go create mode 100644 container/dockertest/responses.go diff --git a/container/container_test.go b/container/container_test.go index 591c1ee30..0077085a5 100644 --- a/container/container_test.go +++ b/container/container_test.go @@ -23,7 +23,13 @@ func TestNew(t *testing.T) { t.Fatal("should negotiate api version") } - assert.Equal(t, "0.0.0.0:2377", (<-dt.LastSwarmInit()).ListenAddr) + select { + case <-dt.LastInfo(): + default: + t.Error("should fetch info") + } + + assert.Equal(t, "0.0.0.0:2377", (<-dt.LastSwarmInit()).Request.ListenAddr) ln := <-dt.LastNetworkCreate() assert.Equal(t, "mesg-shared", ln.Name) @@ -57,6 +63,8 @@ func TestFindContainerNonExistent(t *testing.T) { dt := dockertest.New() c, _ := New(ClientOption(dt.Client())) + dt.ProvideContainerList(nil, dockertest.NotFoundErr{}) + _, err := c.FindContainer(namespace) assert.Equal(t, dockertest.NotFoundErr{}, err) @@ -66,13 +74,15 @@ func TestFindContainerNonExistent(t *testing.T) { Value: "com.docker.stack.namespace=" + Namespace(namespace), }), Limit: 1, - }, <-dt.LastContainerList()) + }, (<-dt.LastContainerList()).Options) } func TestFindContainer(t *testing.T) { namespace := []string{"TestFindContainer"} containerID := "1" - containerData := types.Container{ID: containerID} + containerData := []types.Container{ + {ID: containerID}, + } containerJSONData := types.ContainerJSON{ ContainerJSONBase: &types.ContainerJSONBase{ ID: containerID, @@ -80,8 +90,8 @@ func TestFindContainer(t *testing.T) { } dt := dockertest.New() - dt.ProvideContainer(containerData) - dt.ProvideContainerInspect(containerJSONData) + dt.ProvideContainerList(containerData, nil) + dt.ProvideContainerInspect(containerJSONData, nil) c, _ := New(ClientOption(dt.Client())) @@ -95,15 +105,19 @@ func TestFindContainer(t *testing.T) { Value: "com.docker.stack.namespace=" + Namespace(namespace), }), Limit: 1, - }, <-dt.LastContainerList()) + }, (<-dt.LastContainerList()).Options) - assert.Equal(t, containerID, <-dt.LastContainerInspect()) + assert.Equal(t, containerID, (<-dt.LastContainerInspect()).Container) } func TestNonExistentContainerStatus(t *testing.T) { namespace := []string{"namespace"} + dt := dockertest.New() c, _ := New(ClientOption(dt.Client())) + + dt.ProvideContainerList(nil, dockertest.NotFoundErr{}) + status, err := c.Status(namespace) assert.Nil(t, err) assert.Equal(t, STOPPED, status) @@ -112,7 +126,9 @@ func TestNonExistentContainerStatus(t *testing.T) { func TestExistentContainerStatus(t *testing.T) { namespace := []string{"namespace"} containerID := "1" - containerData := types.Container{ID: containerID} + containerData := []types.Container{ + {ID: containerID}, + } containerJSONData := types.ContainerJSON{ ContainerJSONBase: &types.ContainerJSONBase{ ID: containerID, @@ -121,8 +137,8 @@ func TestExistentContainerStatus(t *testing.T) { } dt := dockertest.New() - dt.ProvideContainer(containerData) - dt.ProvideContainerInspect(containerJSONData) + dt.ProvideContainerList(containerData, nil) + dt.ProvideContainerInspect(containerJSONData, nil) c, _ := New(ClientOption(dt.Client())) status, err := c.Status(namespace) @@ -133,7 +149,9 @@ func TestExistentContainerStatus(t *testing.T) { func TestExistentContainerRunningStatus(t *testing.T) { namespace := []string{"namespace"} containerID := "1" - containerData := types.Container{ID: containerID} + containerData := []types.Container{ + {ID: containerID}, + } containerJSONData := types.ContainerJSON{ ContainerJSONBase: &types.ContainerJSONBase{ ID: containerID, @@ -142,8 +160,8 @@ func TestExistentContainerRunningStatus(t *testing.T) { } dt := dockertest.New() - dt.ProvideContainer(containerData) - dt.ProvideContainerInspect(containerJSONData) + dt.ProvideContainerList(containerData, nil) + dt.ProvideContainerInspect(containerJSONData, nil) c, _ := New(ClientOption(dt.Client())) status, err := c.Status(namespace) diff --git a/container/dockertest/client.go b/container/dockertest/client.go index e4bc10469..4332e4eb9 100644 --- a/container/dockertest/client.go +++ b/container/dockertest/client.go @@ -4,202 +4,265 @@ import ( "context" "io" "io/ioutil" - "sync" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/swarm" docker "github.com/docker/docker/client" ) -type client struct { +// Client satisfies docker.CommonAPIClient for mocking. +type Client struct { + requests *requests + responses *responses + // a placeholder for unimplemented methods. docker.CommonAPIClient +} - lastNegotiateAPIVersion chan struct{} - lastSwarmInit chan swarm.InitRequest - lastNetworkCreate chan NetworkCreate - lastInfo chan types.Info - lastContainerList chan types.ContainerListOptions - lastContainerInspect chan string - lastImageBuild chan ImageBuild - lastNetworkInspect chan NetworkInspect - lastNetworkRemove chan string - lastTaskList chan types.TaskListOptions - lastServiceCreate chan ServiceCreate - lastServiceList chan types.ServiceListOptions - lastServiceInspectWithRaw chan ServiceInspectWithRaw - lastServiceRemove chan string - lastServiceLogs chan ServiceLogs - - m sync.RWMutex - - info types.Info - infoErr error - - containers []types.Container - containerInspect types.ContainerJSON - - imageBuild types.ImageBuildResponse - - networkInspect types.NetworkResource - networkInspectErr error - - networkCreate types.NetworkCreateResponse - networkCreateErr error - - tasklist []swarm.Task - tasklistErr error - - serviceCreate types.ServiceCreateResponse - serviceCreateErr error - - serviceList []swarm.Service - serviceListErr error - - serviceInspectWithRaw swarm.Service - serviceInspectWithRawBytes []byte - serviceInspectWithRawErr error - - serviceRemoveErr error - - serviceLogs io.ReadCloser - serviceLogsErr error -} - -func newClient() *client { - return &client{ - lastNegotiateAPIVersion: make(chan struct{}, 1), - lastSwarmInit: make(chan swarm.InitRequest, 1), - lastNetworkCreate: make(chan NetworkCreate, 1), - lastInfo: make(chan types.Info, 1), - lastContainerList: make(chan types.ContainerListOptions, 1), - lastContainerInspect: make(chan string, 1), - lastImageBuild: make(chan ImageBuild, 1), - lastNetworkInspect: make(chan NetworkInspect, 1), - lastNetworkRemove: make(chan string, 1), - lastTaskList: make(chan types.TaskListOptions, 1), - lastServiceCreate: make(chan ServiceCreate, 1), - lastServiceList: make(chan types.ServiceListOptions, 1), - lastServiceInspectWithRaw: make(chan ServiceInspectWithRaw, 1), - lastServiceRemove: make(chan string, 1), - lastServiceLogs: make(chan ServiceLogs, 1), - } +// requests holds request channels that holds call arguments of Docker client methods. +// Each call to a Docker client method piped to its request chan so multiple +// call to a same method can be received by reading its chan multiple times. +// Inspecting call arguments can be made by listening chan returned by LastX methods of *Testing. +type requests struct { + negotiateAPIVersion chan NegotiateAPIVersionRequest + swarmInit chan SwarmInitRequest + networkCreate chan NetworkCreateRequest + info chan InfoRequest + containerList chan ContainerListRequest + containerInspect chan ContainerInspectRequest + imageBuild chan ImageBuildRequest + networkInspect chan NetworkInspectRequest + networkRemove chan NetworkRemoveRequest + taskList chan TaskListRequest + serviceCreate chan ServiceCreateRequest + serviceList chan ServiceListRequest + serviceInspectWithRaw chan ServiceInspectWithRawRequest + serviceRemove chan ServiceRemoveRequest + serviceLogs chan ServiceLogsRequest } -func (c *client) NegotiateAPIVersion(ctx context.Context) { - c.lastNegotiateAPIVersion <- struct{}{} +// responses holds response channels that holds 'faked' return values of Docker client methods. +// To fake a Docker client method's response send fake return values to it's +// response channel. This is done via ProvideX methods of *Testing. +// We use channels here instead of setting values on the struct in case of a need for returning +// conditional responses depending on method paramaters in future to deal with parallel calls to +// same client methods. +type responses struct { + info chan infoResponse + imageBuild chan imageBuildResponse + networkInspect chan networkInspectResponse + networkCreate chan networkCreateResponse + taskList chan taskListResponse + serviceCreate chan serviceCreateResponse + serviceList chan serviceListResponse + serviceInspectWithRaw chan serviceInspectWithRawResponse + serviceRemove chan serviceRemoveResponse + serviceLogs chan serviceLogsResponse + contanerInspect chan containerInspectResponse + containerList chan containerListResponse } -type NetworkInspect struct { - Network string - Options types.NetworkInspectOptions +// newClient returns a new mock Client for Docker. +func newClient() *Client { + return &Client{ + // buffered channels helps with writing tests in synchronous syntax while using + // LastX methods of Testing. + requests: &requests{ + negotiateAPIVersion: make(chan NegotiateAPIVersionRequest, 1), + swarmInit: make(chan SwarmInitRequest, 1), + networkCreate: make(chan NetworkCreateRequest, 1), + info: make(chan InfoRequest, 1), + containerList: make(chan ContainerListRequest, 1), + containerInspect: make(chan ContainerInspectRequest, 1), + imageBuild: make(chan ImageBuildRequest, 1), + networkInspect: make(chan NetworkInspectRequest, 1), + networkRemove: make(chan NetworkRemoveRequest, 1), + taskList: make(chan TaskListRequest, 1), + serviceCreate: make(chan ServiceCreateRequest, 1), + serviceList: make(chan ServiceListRequest, 1), + serviceInspectWithRaw: make(chan ServiceInspectWithRawRequest, 1), + serviceRemove: make(chan ServiceRemoveRequest, 1), + serviceLogs: make(chan ServiceLogsRequest, 1), + }, + + // buffered channels helps with writing tests in synchronous syntax while using + // ProvideX methods of Testing. + responses: &responses{ + info: make(chan infoResponse, 1), + imageBuild: make(chan imageBuildResponse, 1), + networkInspect: make(chan networkInspectResponse, 1), + networkCreate: make(chan networkCreateResponse, 1), + taskList: make(chan taskListResponse, 1), + serviceCreate: make(chan serviceCreateResponse, 1), + serviceList: make(chan serviceListResponse, 1), + serviceInspectWithRaw: make(chan serviceInspectWithRawResponse, 1), + serviceRemove: make(chan serviceRemoveResponse, 1), + serviceLogs: make(chan serviceLogsResponse, 1), + contanerInspect: make(chan containerInspectResponse, 1), + containerList: make(chan containerListResponse, 1), + }, + } } -func (c *client) NetworkInspect(ctx context.Context, network string, - options types.NetworkInspectOptions) (types.NetworkResource, error) { - c.lastNetworkInspect <- NetworkInspect{network, options} - return c.networkInspect, c.networkInspectErr +// note that select: default statements are a short cut of returning zero value responses +// instead of a explicit need to call Provide methods with zero values. + +// NegotiateAPIVersion is the mock version of the actual method. +func (c *Client) NegotiateAPIVersion(ctx context.Context) { + c.requests.negotiateAPIVersion <- NegotiateAPIVersionRequest{} } -type NetworkCreate struct { - Name string - Options types.NetworkCreate +// NetworkInspect is the mock version of the actual method. +func (c *Client) NetworkInspect(ctx context.Context, network string, + options types.NetworkInspectOptions) (types.NetworkResource, error) { + c.requests.networkInspect <- NetworkInspectRequest{network, options} + select { + case resp := <-c.responses.networkInspect: + return resp.resource, resp.err + default: + return types.NetworkResource{}, nil + } } -func (c *client) NetworkCreate(ctx context.Context, name string, +// NetworkCreate is the mock version of the actual method. +func (c *Client) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) { - c.lastNetworkCreate <- NetworkCreate{name, options} - return c.networkCreate, c.networkCreateErr + c.requests.networkCreate <- NetworkCreateRequest{name, options} + select { + case resp := <-c.responses.networkCreate: + return resp.response, resp.err + default: + return types.NetworkCreateResponse{}, nil + } } -func (c *client) SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error) { - c.lastSwarmInit <- req +// SwarmInit is the mock version of the actual method. +func (c *Client) SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error) { + c.requests.swarmInit <- SwarmInitRequest{req} return "", nil } -func (c *client) Info(context.Context) (types.Info, error) { - c.m.RLock() - defer c.m.RUnlock() - return c.info, c.infoErr +// Info is the mock version of the actual method. +func (c *Client) Info(context.Context) (types.Info, error) { + c.requests.info <- InfoRequest{} + select { + case resp := <-c.responses.info: + return resp.info, resp.err + default: + return types.Info{}, nil + } } -func (c *client) ContainerList(ctx context.Context, +// ContainerList is the mock version of the actual method. +func (c *Client) ContainerList(ctx context.Context, options types.ContainerListOptions) ([]types.Container, error) { - c.lastContainerList <- options - if len(c.containers) > 0 { - return c.containers, nil + c.requests.containerList <- ContainerListRequest{options} + select { + case resp := <-c.responses.containerList: + return resp.containers, resp.err + default: + return nil, nil } - return c.containers, NotFoundErr{} } -func (c *client) ContainerInspect(ctx context.Context, container string) (types.ContainerJSON, error) { - c.lastContainerInspect <- container - return c.containerInspect, nil -} - -type ImageBuild struct { - FileData []byte - Options types.ImageBuildOptions +// ContainerInspect is the mock version of the actual method. +func (c *Client) ContainerInspect(ctx context.Context, container string) (types.ContainerJSON, error) { + c.requests.containerInspect <- ContainerInspectRequest{container} + select { + case resp := <-c.responses.contanerInspect: + return resp.json, resp.err + default: + return types.ContainerJSON{}, nil + } } -func (c *client) ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) { +// ImageBuild is the mock version of the actual method. +func (c *Client) ImageBuild(ctx context.Context, context io.Reader, + options types.ImageBuildOptions) (types.ImageBuildResponse, error) { bytes, err := ioutil.ReadAll(context) if err != nil { return types.ImageBuildResponse{}, err } - c.lastImageBuild <- ImageBuild{bytes, options} - return c.imageBuild, nil + c.requests.imageBuild <- ImageBuildRequest{bytes, options} + select { + case resp := <-c.responses.imageBuild: + return resp.response, resp.err + default: + return types.ImageBuildResponse{}, nil + } } -func (c *client) NetworkRemove(ctx context.Context, network string) error { - c.lastNetworkRemove <- network +// NetworkRemove is the mock version of the actual method. +func (c *Client) NetworkRemove(ctx context.Context, network string) error { + c.requests.networkRemove <- NetworkRemoveRequest{network} return nil } -func (c *client) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) { - c.lastTaskList <- options - return c.tasklist, c.tasklistErr -} - -type ServiceCreate struct { - Service swarm.ServiceSpec - Options types.ServiceCreateOptions +// TaskList is the mock version of the actual method. +func (c *Client) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) { + c.requests.taskList <- TaskListRequest{options} + select { + case resp := <-c.responses.taskList: + return resp.tasks, resp.err + default: + return nil, nil + } } -func (c *client) ServiceCreate(ctx context.Context, +// ServiceCreate is the mock version of the actual method. +func (c *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options types.ServiceCreateOptions) (types.ServiceCreateResponse, error) { - c.lastServiceCreate <- ServiceCreate{service, options} - return c.serviceCreate, c.serviceCreateErr -} - -func (c *client) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) { - c.lastServiceList <- options - return c.serviceList, c.serviceListErr + c.requests.serviceCreate <- ServiceCreateRequest{service, options} + select { + case resp := <-c.responses.serviceCreate: + return resp.response, resp.err + default: + return types.ServiceCreateResponse{}, nil + } } -type ServiceInspectWithRaw struct { - ServiceID string - Options types.ServiceInspectOptions +// ServiceList is the mock version of the actual method. +func (c *Client) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) { + c.requests.serviceList <- ServiceListRequest{options} + select { + case resp := <-c.responses.serviceList: + return resp.services, resp.err + default: + return nil, nil + } } -func (c *client) ServiceInspectWithRaw(ctx context.Context, serviceID string, +// ServiceInspectWithRaw is the mock version of the actual method. +func (c *Client) ServiceInspectWithRaw(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) { - c.lastServiceInspectWithRaw <- ServiceInspectWithRaw{serviceID, options} - return c.serviceInspectWithRaw, c.serviceInspectWithRawBytes, c.serviceInspectWithRawErr -} - -func (c *client) ServiceRemove(ctx context.Context, serviceID string) error { - c.lastServiceRemove <- serviceID - return c.serviceRemoveErr + c.requests.serviceInspectWithRaw <- ServiceInspectWithRawRequest{serviceID, options} + select { + case resp := <-c.responses.serviceInspectWithRaw: + return resp.service, resp.data, resp.err + default: + return swarm.Service{}, nil, nil + } } -type ServiceLogs struct { - ServiceID string - Options types.ContainerLogsOptions +// ServiceRemove is the mock version of the actual method. +func (c *Client) ServiceRemove(ctx context.Context, serviceID string) error { + c.requests.serviceRemove <- ServiceRemoveRequest{serviceID} + select { + case resp := <-c.responses.serviceRemove: + return resp.err + default: + return nil + } } -func (c *client) ServiceLogs(ctx context.Context, +// ServiceLogs is the mock version of the actual method. +func (c *Client) ServiceLogs(ctx context.Context, serviceID string, options types.ContainerLogsOptions) (io.ReadCloser, error) { - c.lastServiceLogs <- ServiceLogs{serviceID, options} - return c.serviceLogs, c.serviceLogsErr + c.requests.serviceLogs <- ServiceLogsRequest{serviceID, options} + select { + case resp := <-c.responses.serviceLogs: + return resp.rc, resp.err + default: + return nil, nil + } } diff --git a/container/dockertest/error.go b/container/dockertest/error.go index 78d21022b..3dcdf245b 100644 --- a/container/dockertest/error.go +++ b/container/dockertest/error.go @@ -1,22 +1,15 @@ package dockertest -import "errors" - -var ( - ErrContainerDoesNotExists = errors.New("containers does not exists") -) - -type NotFoundErr struct { -} - -func NewNotFoundErr() NotFoundErr { - return NotFoundErr{} -} +// NotFoundErr satisfies docker client's NotFoundErr interface. +// docker.IsErrNotFound(err) will return true with NotFoundErr. +type NotFoundErr struct{} +// NotFound indicates that this error is a not found error. func (e NotFoundErr) NotFound() bool { return true } +// Error returns the string representation of error. func (e NotFoundErr) Error() string { return "not found" } diff --git a/container/dockertest/requests.go b/container/dockertest/requests.go new file mode 100644 index 000000000..92974ad18 --- /dev/null +++ b/container/dockertest/requests.go @@ -0,0 +1,86 @@ +package dockertest + +import ( + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/swarm" +) + +// NetworkCreateRequest holds call arguments of *Client.NetworkCreate. +type NetworkCreateRequest struct { + Name string + Options types.NetworkCreate +} + +// ImageBuildRequest holds call arguments of *Client.ImageBuild. +type ImageBuildRequest struct { + FileData []byte + Options types.ImageBuildOptions +} + +// NetworkInspectRequest holds call arguments of *Client.NetworkInspect. +type NetworkInspectRequest struct { + Network string + Options types.NetworkInspectOptions +} + +// ServiceCreateRequest holds call arguments of *Client.ServiceCreate. +type ServiceCreateRequest struct { + Service swarm.ServiceSpec + Options types.ServiceCreateOptions +} + +// ServiceInspectWithRawRequest holds call arguments of *Client.ServiceInspectWithRaw. +type ServiceInspectWithRawRequest struct { + ServiceID string + Options types.ServiceInspectOptions +} + +// ServiceLogsRequest holds call arguments of *Client.ServiceLogs. +type ServiceLogsRequest struct { + ServiceID string + Options types.ContainerLogsOptions +} + +// NegotiateAPIVersionRequest holds call arguments of *Client.NegotiateAPIVersion. +type NegotiateAPIVersionRequest struct { +} + +// SwarmInitRequest holds call arguments of *Client.SwarmInit. +type SwarmInitRequest struct { + Request swarm.InitRequest +} + +// InfoRequest holds call arguments of *Client.Info. +type InfoRequest struct { + Info types.Info +} + +// ContainerListRequest holds call arguments of *Client.ContainerList. +type ContainerListRequest struct { + Options types.ContainerListOptions +} + +// ContainerInspectRequest holds call arguments of *Client.ContainerInspect. +type ContainerInspectRequest struct { + Container string +} + +// NetworkRemoveRequest holds call arguments of *Client.NetworkRemove. +type NetworkRemoveRequest struct { + Network string +} + +// TaskListRequest holds call arguments of *Client.TaskList. +type TaskListRequest struct { + Options types.TaskListOptions +} + +// ServiceListRequest holds call arguments of *Client.ServiceList. +type ServiceListRequest struct { + Options types.ServiceListOptions +} + +// ServiceRemoveRequest holds call arguments of *Client.ServiceRemove. +type ServiceRemoveRequest struct { + ServiceID string +} diff --git a/container/dockertest/responses.go b/container/dockertest/responses.go new file mode 100644 index 000000000..087af8121 --- /dev/null +++ b/container/dockertest/responses.go @@ -0,0 +1,80 @@ +package dockertest + +import ( + "io" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/swarm" +) + +// serviceLogsResponse holds fake return values of *Client.ServiceLogs. +type serviceLogsResponse struct { + rc io.ReadCloser + err error +} + +// serviceRemoveResponse holds fake return values of *Client.ServiceRemove. +type serviceRemoveResponse struct { + err error +} + +// serviceInspectWithRawResponse holds fake return values of *Client.ServiceInspectWithRaw. +type serviceInspectWithRawResponse struct { + service swarm.Service + data []byte + err error +} + +// serviceListResponse holds fake return values of *Client.ServiceList. +type serviceListResponse struct { + services []swarm.Service + err error +} + +// serviceCreateResponse holds fake return values of *Client.ServiceCreate. +type serviceCreateResponse struct { + response types.ServiceCreateResponse + err error +} + +// taskListResponse holds fake return values of *Client.TaskList. +type taskListResponse struct { + tasks []swarm.Task + err error +} + +// networkCreateResponse holds fake return values of *Client.NetworkCreate. +type networkCreateResponse struct { + response types.NetworkCreateResponse + err error +} + +// networkInspectResponse holds fake return values of *Client.NetworkInspect. +type networkInspectResponse struct { + resource types.NetworkResource + err error +} + +// imageBuildResponse holds fake return values of *Client.ImageBuild. +type imageBuildResponse struct { + response types.ImageBuildResponse + err error +} + +// infoResponse holds fake return values of *Client.Info. +type infoResponse struct { + info types.Info + err error +} + +// containerListResponse holds fake return values of *Client.ContainerList. +type containerListResponse struct { + containers []types.Container + err error +} + +// containerInspectResponse holds fake return values of *Client.ContainerInspect. +type containerInspectResponse struct { + json types.ContainerJSON + err error +} diff --git a/container/dockertest/testing.go b/container/dockertest/testing.go index 4728b2c20..f88b3e9c8 100644 --- a/container/dockertest/testing.go +++ b/container/dockertest/testing.go @@ -8,10 +8,12 @@ import ( "github.com/docker/docker/api/types/swarm" ) +// Testing provides functionalities to fake Docker API calls and responses. type Testing struct { - client *client + client *Client } +// New creates a new Testing. func New() *Testing { t := &Testing{ client: newClient(), @@ -19,145 +21,152 @@ func New() *Testing { return t } -func (t *Testing) Client() *client { +// Client returns a new mock client compatible with Docker's +// docker.CommonAPIClient interface. +func (t *Testing) Client() *Client { return t.client } -func (t *Testing) ProvideContainer(container types.Container) { - t.client.m.Lock() - defer t.client.m.Unlock() - t.client.containers = append(t.client.containers, container) +// ProvideInfo sets fake return values for the next call to *Client.Into. +func (t *Testing) ProvideInfo(info types.Info, err error) { + t.client.responses.info <- infoResponse{info, err} } -func (t *Testing) ProvideContainerInspect(container types.ContainerJSON) { - t.client.containerInspect = container +// ProvideContainerList sets fake return values for the next call to *Client.ContainerList. +func (t *Testing) ProvideContainerList(containers []types.Container, err error) { + t.client.responses.containerList <- containerListResponse{containers, err} } -func (t *Testing) LastContainerList() chan types.ContainerListOptions { - return t.client.lastContainerList +// ProvideContainerInspect sets fake return values for the next call to *Client.ContainerInspect. +func (t *Testing) ProvideContainerInspect(json types.ContainerJSON, err error) { + t.client.responses.contanerInspect <- containerInspectResponse{json, err} } -func (t *Testing) LastContainerInspect() chan string { - return t.client.lastContainerInspect +// ProvideImageBuild sets fake return values for the next call to *Client.ImageBuild. +func (t *Testing) ProvideImageBuild(rc io.ReadCloser) { + t.client.responses.imageBuild <- imageBuildResponse{types.ImageBuildResponse{Body: rc}, nil} } -func (t *Testing) LastSwarmInit() chan swarm.InitRequest { - return t.client.lastSwarmInit +// ProvideNetworkInspect sets fake return values for the next call to *Client.NetworkInspect. +func (t *Testing) ProvideNetworkInspect(resource types.NetworkResource, err error) { + t.client.responses.networkInspect <- networkInspectResponse{resource, err} } -func (t *Testing) LastNetworkCreate() chan NetworkCreate { - return t.client.lastNetworkCreate +// ProvideNetworkCreate sets fake return values for the next call to *Client.NetworkCreate. +func (t *Testing) ProvideNetworkCreate(response types.NetworkCreateResponse, err error) { + t.client.responses.networkCreate <- networkCreateResponse{response, err} } -func (t *Testing) LastNetworkInspect() chan NetworkInspect { - t.client.networkInspect = types.NetworkResource{} - t.client.networkInspectErr = nil - return t.client.lastNetworkInspect +// ProvideServiceList sets fake return values for the next call to *Client.ServiceList. +func (t *Testing) ProvideServiceList(services []swarm.Service, err error) { + t.client.responses.serviceList <- serviceListResponse{services, err} } -type SystemInfo struct { - Info types.Info - Err error +// ProvideServiceInspectWithRaw sets fake return values for the next call to *Client.ServiceInspectWithRaw. +func (t *Testing) ProvideServiceInspectWithRaw(service swarm.Service, data []byte, err error) { + t.client.responses.serviceInspectWithRaw <- serviceInspectWithRawResponse{service, data, err} } -func (t *Testing) LastInfo() types.Info { - return <-t.client.lastInfo +// ProvideServiceLogs sets fake return values for the next call to *Client.ServiceLogs. +func (t *Testing) ProvideServiceLogs(rc io.ReadCloser, err error) { + t.client.responses.serviceLogs <- serviceLogsResponse{rc, err} } -func (t *Testing) ProvideInfo(info types.Info, err error) { - t.client.m.Lock() - defer t.client.m.Unlock() - t.client.info = info - t.client.infoErr = err +// ProvideTaskList sets fake return values for the next call to *Client.TaskList. +func (t *Testing) ProvideTaskList(tasks []swarm.Task, err error) { + t.client.responses.taskList <- taskListResponse{tasks, err} } -func (t *Testing) LastNegotiateAPIVersion() chan struct{} { - return t.client.lastNegotiateAPIVersion -} +// ProvideServiceCreate sets fake return values for the next call to *Client.ServiceCreate. +func (t *Testing) ProvideServiceCreate(response types.ServiceCreateResponse, err error) { + // TODO(ilgooz) do the same shortcurt(calling needed Provides) made here + // on other needed places too. + t.ProvideContainerList([]types.Container{}, nil) + t.ProvideContainerInspect(types.ContainerJSON{ + ContainerJSONBase: &types.ContainerJSONBase{ + State: &types.ContainerState{Running: true}, + }, + }, nil) -func (t *Testing) LastImageBuild() chan ImageBuild { - return t.client.lastImageBuild + t.client.responses.serviceCreate <- serviceCreateResponse{response, err} } -func (t *Testing) ProvideImageBuild(rc io.ReadCloser) { - t.client.imageBuild = types.ImageBuildResponse{Body: rc} +// ProvideServiceRemove sets fake return values for the next call to *Client.ServiceRemove. +func (t *Testing) ProvideServiceRemove(err error) { + t.client.responses.serviceRemove <- serviceRemoveResponse{err} } -func (t *Testing) ProvideNetworkInspect(response types.NetworkResource, err error) { - t.client.networkInspect = response - t.client.networkInspectErr = err +// LastContainerList returns a channel that receives call arguments of last *Client.ContainerList. +func (t *Testing) LastContainerList() <-chan ContainerListRequest { + return t.client.requests.containerList } -func (t *Testing) ProvideNetwork(response types.NetworkCreateResponse, err error) { - t.client.networkCreate = response - t.client.networkCreateErr = err +// LastContainerInspect returns a channel that receives call arguments of last *Client.ContainerInspect. +func (t *Testing) LastContainerInspect() <-chan ContainerInspectRequest { + return t.client.requests.containerInspect } -func (t *Testing) LastNetworkRemove() chan string { - return t.client.lastNetworkRemove +// LastSwarmInit returns a channel that receives call arguments of last *Client.SwarmInit. +func (t *Testing) LastSwarmInit() <-chan SwarmInitRequest { + return t.client.requests.swarmInit } -func (t *Testing) LastTaskList() chan types.TaskListOptions { - return t.client.lastTaskList +// LastNetworkCreate returns a channel that receives call arguments of last *Client.NetworkCreate. +func (t *Testing) LastNetworkCreate() <-chan NetworkCreateRequest { + return t.client.requests.networkCreate } -func (t *Testing) ProvideTaskList(tasks []swarm.Task, err error) { - t.client.tasklist = tasks - t.client.tasklistErr = err +// LastNetworkInspect returns a channel that receives call arguments of last *Client.NetworkInspect. +func (t *Testing) LastNetworkInspect() <-chan NetworkInspectRequest { + return t.client.requests.networkInspect } -func (t *Testing) LastServiceCreate() chan ServiceCreate { - return t.client.lastServiceCreate +// LastInfo returns a channel that receives call arguments of last *Client.Info. +func (t *Testing) LastInfo() <-chan InfoRequest { + return t.client.requests.info } -func (t *Testing) ProvideServiceCreate(response types.ServiceCreateResponse, err error) { - // TODO(ilgooz) do the same shortcurt(calling needed Provides) made here - // on other needed places too. - containerData := types.Container{} - containerJSONData := types.ContainerJSON{ - ContainerJSONBase: &types.ContainerJSONBase{ - State: &types.ContainerState{Running: true}, - }, - } - t.ProvideContainer(containerData) - t.ProvideContainerInspect(containerJSONData) - - t.client.serviceCreate = response - t.client.serviceCreateErr = err +// LastNegotiateAPIVersion returns a channel that receives call arguments of last *Client.NegotiateAPIVersion. +func (t *Testing) LastNegotiateAPIVersion() <-chan NegotiateAPIVersionRequest { + return t.client.requests.negotiateAPIVersion } -func (t *Testing) LastServiceList() chan types.ServiceListOptions { - return t.client.lastServiceList +// LastImageBuild returns a channel that receives call arguments of last *Client.ImageBuild. +func (t *Testing) LastImageBuild() <-chan ImageBuildRequest { + return t.client.requests.imageBuild } -func (t *Testing) ProvideServiceList(list []swarm.Service, err error) { - t.client.serviceList = list - t.client.serviceListErr = err +// LastNetworkRemove returns a channel that receives call arguments of last *Client.NetworkRemove. +func (t *Testing) LastNetworkRemove() <-chan NetworkRemoveRequest { + return t.client.requests.networkRemove } -func (t *Testing) LastServiceInspectWithRaw() chan ServiceInspectWithRaw { - return t.client.lastServiceInspectWithRaw +// LastTaskList returns a channel that receives call arguments of last *Client.TaskList. +func (t *Testing) LastTaskList() <-chan TaskListRequest { + return t.client.requests.taskList } -func (t *Testing) ProvideServiceInspectWithRaw(service swarm.Service, data []byte, err error) { - t.client.serviceInspectWithRaw = service - t.client.serviceInspectWithRawBytes = data - t.client.serviceInspectWithRawErr = err +// LastServiceCreate returns a channel that receives call arguments of last *Client.ServiceCreate. +func (t *Testing) LastServiceCreate() <-chan ServiceCreateRequest { + return t.client.requests.serviceCreate } -func (t *Testing) LastServiceRemove() chan string { - return t.client.lastServiceRemove +// LastServiceList returns a channel that receives call arguments of last *Client.ServiceList. +func (t *Testing) LastServiceList() <-chan ServiceListRequest { + return t.client.requests.serviceList } -func (t *Testing) ProvideServiceRemove(err error) { - t.client.serviceRemoveErr = err +// LastServiceInspectWithRaw returns a channel that receives call arguments of last *Client.ServiceInspectWithRaw. +func (t *Testing) LastServiceInspectWithRaw() <-chan ServiceInspectWithRawRequest { + return t.client.requests.serviceInspectWithRaw } -func (t *Testing) LastServiceLogs() chan ServiceLogs { - return t.client.lastServiceLogs +// LastServiceRemove returns a channel that receives call arguments of last *Client.ServiceRemove. +func (t *Testing) LastServiceRemove() <-chan ServiceRemoveRequest { + return t.client.requests.serviceRemove } -func (t *Testing) ProvideServiceLogs(rc io.ReadCloser, err error) { - t.client.serviceLogs = rc - t.client.serviceLogsErr = err +// LastServiceLogs returns a channel that receives call arguments of last *Client.ServiceLogs. +func (t *Testing) LastServiceLogs() <-chan ServiceLogsRequest { + return t.client.requests.serviceLogs } diff --git a/container/network_test.go b/container/network_test.go index b502a6dbc..afe109031 100644 --- a/container/network_test.go +++ b/container/network_test.go @@ -20,7 +20,7 @@ func TestCreateNetwork(t *testing.T) { <-dt.LastNetworkInspect() <-dt.LastNetworkCreate() - dt.ProvideNetwork(types.NetworkCreateResponse{ID: id}, nil) + dt.ProvideNetworkCreate(types.NetworkCreateResponse{ID: id}, nil) dt.ProvideNetworkInspect(types.NetworkResource{}, nil) networkID, err := c.CreateNetwork(namespace) @@ -79,7 +79,7 @@ func TestDeleteNetwork(t *testing.T) { assert.Equal(t, Namespace(namespace), li.Network) assert.Equal(t, types.NetworkInspectOptions{}, li.Options) - assert.Equal(t, id, <-dt.LastNetworkRemove()) + assert.Equal(t, id, (<-dt.LastNetworkRemove()).Network) } func TestDeleteNotExistingNetwork(t *testing.T) { @@ -92,7 +92,7 @@ func TestDeleteNotExistingNetwork(t *testing.T) { <-dt.LastNetworkInspect() <-dt.LastNetworkCreate() - dt.ProvideNetworkInspect(types.NetworkResource{}, dockertest.NewNotFoundErr()) + dt.ProvideNetworkInspect(types.NetworkResource{}, dockertest.NotFoundErr{}) assert.Nil(t, c.DeleteNetwork(namespace)) @@ -144,7 +144,6 @@ func TestFindNetwork(t *testing.T) { func TestFindNotExistingNetwork(t *testing.T) { namespace := []string{"namespace"} - notFoundErr := dockertest.NewNotFoundErr() dt := dockertest.New() c, _ := New(ClientOption(dt.Client())) @@ -153,8 +152,8 @@ func TestFindNotExistingNetwork(t *testing.T) { <-dt.LastNetworkInspect() <-dt.LastNetworkCreate() - dt.ProvideNetworkInspect(types.NetworkResource{}, notFoundErr) + dt.ProvideNetworkInspect(types.NetworkResource{}, dockertest.NotFoundErr{}) _, err := c.FindNetwork(namespace) - assert.Equal(t, notFoundErr, err) + assert.Equal(t, dockertest.NotFoundErr{}, err) } diff --git a/container/service_test.go b/container/service_test.go index 9101ee596..c26dabb57 100644 --- a/container/service_test.go +++ b/container/service_test.go @@ -36,17 +36,26 @@ func TestStartService(t *testing.T) { func TestStopService(t *testing.T) { namespace := []string{"namespace"} + containerData := []types.Container{} + containerJSONData := types.ContainerJSON{ + ContainerJSONBase: &types.ContainerJSONBase{ + State: &types.ContainerState{}, + }, + } dt := dockertest.New() c, _ := New(ClientOption(dt.Client())) + dt.ProvideContainerList(containerData, nil) + dt.ProvideContainerInspect(containerJSONData, nil) + assert.Nil(t, c.StopService(namespace)) li := <-dt.LastServiceInspectWithRaw() assert.Equal(t, Namespace(namespace), li.ServiceID) assert.Equal(t, types.ServiceInspectOptions{}, li.Options) - assert.Equal(t, Namespace(namespace), <-dt.LastServiceRemove()) + assert.Equal(t, Namespace(namespace), (<-dt.LastServiceRemove()).ServiceID) } func TestStopNotExistingService(t *testing.T) { @@ -160,7 +169,7 @@ func TestListServices(t *testing.T) { Key: "label", Value: label, }), - }, <-dt.LastServiceList()) + }, (<-dt.LastServiceList()).Options) } func TestServiceLogs(t *testing.T) { diff --git a/container/task_test.go b/container/task_test.go index 9487b765a..4270d08e5 100644 --- a/container/task_test.go +++ b/container/task_test.go @@ -4,6 +4,8 @@ import ( "errors" "testing" + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/swarm" "github.com/mesg-foundation/core/container/dockertest" "github.com/stvp/assert" @@ -25,6 +27,13 @@ func TestListTasks(t *testing.T) { assert.Nil(t, err) assert.Equal(t, tasks, tasks1) assert.Equal(t, len(tasks), len(tasks1)) + + assert.Equal(t, types.TaskListOptions{ + Filters: filters.NewArgs(filters.KeyValuePair{ + Key: "label", + Value: "com.docker.stack.namespace=" + Namespace(namespace), + }), + }, (<-dt.LastTaskList()).Options) } var errTaskList = errors.New("task list") diff --git a/container/wait_test.go b/container/wait_test.go index a359d6c27..1174622be 100644 --- a/container/wait_test.go +++ b/container/wait_test.go @@ -12,7 +12,9 @@ import ( func TestWaitForStatusRunning(t *testing.T) { namespace := []string{"namespace"} containerID := "1" - containerData := types.Container{ID: containerID} + containerData := []types.Container{ + {ID: containerID}, + } containerJSONData := types.ContainerJSON{ ContainerJSONBase: &types.ContainerJSONBase{ ID: containerID, @@ -23,8 +25,8 @@ func TestWaitForStatusRunning(t *testing.T) { dt := dockertest.New() c, _ := New(ClientOption(dt.Client())) - dt.ProvideContainer(containerData) - dt.ProvideContainerInspect(containerJSONData) + dt.ProvideContainerList(containerData, nil) + dt.ProvideContainerInspect(containerJSONData, nil) assert.Nil(t, c.waitForStatus(namespace, RUNNING)) } @@ -32,7 +34,9 @@ func TestWaitForStatusRunning(t *testing.T) { func TestWaitForStatusStopped(t *testing.T) { namespace := []string{"namespace"} containerID := "1" - containerData := types.Container{ID: containerID} + containerData := []types.Container{ + {ID: containerID}, + } containerJSONData := types.ContainerJSON{ ContainerJSONBase: &types.ContainerJSONBase{ ID: containerID, @@ -43,8 +47,8 @@ func TestWaitForStatusStopped(t *testing.T) { dt := dockertest.New() c, _ := New(ClientOption(dt.Client())) - dt.ProvideContainer(containerData) - dt.ProvideContainerInspect(containerJSONData) + dt.ProvideContainerList(containerData, nil) + dt.ProvideContainerInspect(containerJSONData, nil) assert.Nil(t, c.waitForStatus(namespace, STOPPED)) } From 3c19b098f68c41f92d349342fb255b00dbaae312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=CC=87lker=20Go=CC=88ktug=CC=86=20O=CC=88ztu=CC=88rk?= Date: Tue, 7 Aug 2018 08:36:07 +0300 Subject: [PATCH 08/22] container: use contexts WithTimeout for Docker API calls --- container/build.go | 4 +++- container/container.go | 12 +++++++++--- container/network.go | 12 +++++++++--- container/service.go | 24 +++++++++++++++--------- container/task.go | 4 +++- 5 files changed, 39 insertions(+), 17 deletions(-) diff --git a/container/build.go b/container/build.go index f992dca6c..c64d3f464 100644 --- a/container/build.go +++ b/container/build.go @@ -31,7 +31,9 @@ func (c *Container) Build(path string) (tag string, err error) { return "", err } defer buildContext.Close() - response, err := c.client.ImageBuild(context.Background(), buildContext, types.ImageBuildOptions{ + ctx, cancel := context.WithTimeout(context.Background(), c.callTimeout) + defer cancel() + response, err := c.client.ImageBuild(ctx, buildContext, types.ImageBuildOptions{ Remove: true, ForceRemove: true, SuppressOutput: true, diff --git a/container/container.go b/container/container.go index c5f6fd87c..e92e90938 100644 --- a/container/container.go +++ b/container/container.go @@ -74,7 +74,9 @@ func (c *Container) createSwarmIfNeeded() error { if info.Swarm.NodeID != "" { return nil } - _, err = c.client.SwarmInit(context.Background(), swarm.InitRequest{ + ctx, cancel = context.WithTimeout(context.Background(), c.callTimeout) + defer cancel() + _, err = c.client.SwarmInit(ctx, swarm.InitRequest{ ListenAddr: "0.0.0.0:2377", // https://docs.docker.com/engine/reference/commandline/swarm_init/#usage }) return err @@ -82,7 +84,9 @@ func (c *Container) createSwarmIfNeeded() error { // FindContainer returns a docker container. func (c *Container) FindContainer(namespace []string) (types.ContainerJSON, error) { - containers, err := c.client.ContainerList(context.Background(), types.ContainerListOptions{ + ctx, cancel := context.WithTimeout(context.Background(), c.callTimeout) + defer cancel() + containers, err := c.client.ContainerList(ctx, types.ContainerListOptions{ Filters: filters.NewArgs(filters.KeyValuePair{ Key: "label", Value: "com.docker.stack.namespace=" + Namespace(namespace), @@ -96,7 +100,9 @@ func (c *Container) FindContainer(namespace []string) (types.ContainerJSON, erro if len(containers) == 1 { containerID = containers[0].ID } - return c.client.ContainerInspect(context.Background(), containerID) + ctx, cancel = context.WithTimeout(context.Background(), c.callTimeout) + defer cancel() + return c.client.ContainerInspect(ctx, containerID) } // Status returns the status of a docker container. diff --git a/container/network.go b/container/network.go index b7cbcfff4..14d61f7d7 100644 --- a/container/network.go +++ b/container/network.go @@ -17,7 +17,9 @@ func (c *Container) CreateNetwork(namespace []string) (id string, err error) { return network.ID, nil } namespaceFlat := Namespace(namespace) - response, err := c.client.NetworkCreate(context.Background(), namespaceFlat, types.NetworkCreate{ + ctx, cancel := context.WithTimeout(context.Background(), c.callTimeout) + defer cancel() + response, err := c.client.NetworkCreate(ctx, namespaceFlat, types.NetworkCreate{ CheckDuplicate: true, // Cannot have 2 network with the same name Driver: "overlay", Labels: map[string]string{ @@ -39,10 +41,14 @@ func (c *Container) DeleteNetwork(namespace []string) error { if err != nil { return err } - return c.client.NetworkRemove(context.Background(), network.ID) + ctx, cancel := context.WithTimeout(context.Background(), c.callTimeout) + defer cancel() + return c.client.NetworkRemove(ctx, network.ID) } // FindNetwork finds a Docker Network by a namespace. If no network is found, an error is returned. func (c *Container) FindNetwork(namespace []string) (types.NetworkResource, error) { - return c.client.NetworkInspect(context.Background(), Namespace(namespace), types.NetworkInspectOptions{}) + ctx, cancel := context.WithTimeout(context.Background(), c.callTimeout) + defer cancel() + return c.client.NetworkInspect(ctx, Namespace(namespace), types.NetworkInspectOptions{}) } diff --git a/container/service.go b/container/service.go index 3fb197ec6..9029fc47d 100644 --- a/container/service.go +++ b/container/service.go @@ -12,7 +12,9 @@ import ( // ListServices returns existing docker services matching a specific label name. func (c *Container) ListServices(label string) ([]swarm.Service, error) { - return c.client.ServiceList(context.Background(), types.ServiceListOptions{ + ctx, cancel := context.WithTimeout(context.Background(), c.callTimeout) + defer cancel() + return c.client.ServiceList(ctx, types.ServiceListOptions{ Filters: filters.NewArgs(filters.KeyValuePair{ Key: "label", Value: label, @@ -22,9 +24,9 @@ func (c *Container) ListServices(label string) ([]swarm.Service, error) { // FindService returns the Docker Service or an error if not found. func (c *Container) FindService(namespace []string) (swarm.Service, error) { - service, _, err := c.client.ServiceInspectWithRaw( - context.Background(), - Namespace(namespace), + ctx, cancel := context.WithTimeout(context.Background(), c.callTimeout) + defer cancel() + service, _, err := c.client.ServiceInspectWithRaw(ctx, Namespace(namespace), types.ServiceInspectOptions{}, ) return service, err @@ -33,7 +35,9 @@ func (c *Container) FindService(namespace []string) (swarm.Service, error) { // StartService starts a docker service. func (c *Container) StartService(options ServiceOptions) (serviceID string, err error) { service := options.toSwarmServiceSpec() - response, err := c.client.ServiceCreate(context.Background(), service, types.ServiceCreateOptions{}) + ctx, cancel := context.WithTimeout(context.Background(), c.callTimeout) + defer cancel() + response, err := c.client.ServiceCreate(ctx, service, types.ServiceCreateOptions{}) if err != nil { return "", err } @@ -46,7 +50,9 @@ func (c *Container) StopService(namespace []string) (err error) { if err != nil || status == STOPPED { return err } - if err := c.client.ServiceRemove(context.Background(), Namespace(namespace)); err != nil { + ctx, cancel := context.WithTimeout(context.Background(), c.callTimeout) + defer cancel() + if err := c.client.ServiceRemove(ctx, Namespace(namespace)); err != nil { return err } return c.waitForStatus(namespace, STOPPED) @@ -66,9 +72,9 @@ func (c *Container) ServiceStatus(namespace []string) (StatusType, error) { // ServiceLogs returns the logs of a service. func (c *Container) ServiceLogs(namespace []string) (io.ReadCloser, error) { - return c.client.ServiceLogs( - context.Background(), - Namespace(namespace), + ctx, cancel := context.WithTimeout(context.Background(), c.callTimeout) + defer cancel() + return c.client.ServiceLogs(ctx, Namespace(namespace), types.ContainerLogsOptions{ ShowStdout: true, ShowStderr: true, diff --git a/container/task.go b/container/task.go index 1b3460ee4..ff2ab32ed 100644 --- a/container/task.go +++ b/container/task.go @@ -10,7 +10,9 @@ import ( // ListTasks returns all the docker tasks. func (c *Container) ListTasks(namespace []string) ([]swarm.Task, error) { - return c.client.TaskList(context.Background(), types.TaskListOptions{ + ctx, cancel := context.WithTimeout(context.Background(), c.callTimeout) + defer cancel() + return c.client.TaskList(ctx, types.TaskListOptions{ Filters: filters.NewArgs(filters.KeyValuePair{ Key: "label", Value: "com.docker.stack.namespace=" + Namespace(namespace), From 8e9b76732b6a67549a63f57163d803acd5453912 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=CC=87lker=20Go=CC=88ktug=CC=86=20O=CC=88ztu=CC=88rk?= Date: Tue, 7 Aug 2018 09:29:16 +0300 Subject: [PATCH 09/22] improve comments in container and container/dockertest packages --- container/container.go | 6 +++--- container/dockertest/client.go | 16 ++++++++-------- container/dockertest/testing.go | 30 +++++++++++++++--------------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/container/container.go b/container/container.go index e92e90938..087012d34 100644 --- a/container/container.go +++ b/container/container.go @@ -10,7 +10,7 @@ import ( docker "github.com/docker/docker/client" ) -// Container provides functionaliets for Docker containers for MESG. +// Container provides high level interactions with Docker API for MESG. type Container struct { // client is a Docker client. client docker.CommonAPIClient @@ -44,14 +44,14 @@ func New(options ...Option) (*Container, error) { return c, c.createSharedNetworkIfNeeded() } -// ClientOption creates a new Option with given docker client for Container. +// ClientOption receives a client which will be used to interact with Docker API. func ClientOption(client docker.CommonAPIClient) Option { return func(c *Container) { c.client = client } } -// TimeoutOption creates a new Option with given d http call timeout for Container. +// TimeoutOption receives d which will be set as a timeout value for Docker API calls. func TimeoutOption(d time.Duration) Option { return func(c *Container) { c.callTimeout = d diff --git a/container/dockertest/client.go b/container/dockertest/client.go index 4332e4eb9..375afadd2 100644 --- a/container/dockertest/client.go +++ b/container/dockertest/client.go @@ -19,9 +19,9 @@ type Client struct { docker.CommonAPIClient } -// requests holds request channels that holds call arguments of Docker client methods. -// Each call to a Docker client method piped to its request chan so multiple -// call to a same method can be received by reading its chan multiple times. +// requests encapsulates request channels that keeps call arguments of Docker client methods. +// Each call to a Docker client method piped to its request channel so multiple +// call to a same method can be inspected by reading its channel multiple times. // Inspecting call arguments can be made by listening chan returned by LastX methods of *Testing. type requests struct { negotiateAPIVersion chan NegotiateAPIVersionRequest @@ -41,12 +41,12 @@ type requests struct { serviceLogs chan ServiceLogsRequest } -// responses holds response channels that holds 'faked' return values of Docker client methods. +// responses encapsulates response channels that holds 'faked' return values of Docker client methods. // To fake a Docker client method's response send fake return values to it's -// response channel. This is done via ProvideX methods of *Testing. +// response channel. This can be made by calling ProvideX methods of *Testing. // We use channels here instead of setting values on the struct in case of a need for returning -// conditional responses depending on method paramaters in future to deal with parallel calls to -// same client methods. +// conditional responses depending on request paramaters in future to deal with parallel calls made +// to same client methods. type responses struct { info chan infoResponse imageBuild chan imageBuildResponse @@ -105,7 +105,7 @@ func newClient() *Client { } // note that select: default statements are a short cut of returning zero value responses -// instead of a explicit need to call Provide methods with zero values. +// instead of an explicit need to call Provide methods with zero values. // NegotiateAPIVersion is the mock version of the actual method. func (c *Client) NegotiateAPIVersion(ctx context.Context) { diff --git a/container/dockertest/testing.go b/container/dockertest/testing.go index f88b3e9c8..7c683503e 100644 --- a/container/dockertest/testing.go +++ b/container/dockertest/testing.go @@ -96,77 +96,77 @@ func (t *Testing) ProvideServiceRemove(err error) { t.client.responses.serviceRemove <- serviceRemoveResponse{err} } -// LastContainerList returns a channel that receives call arguments of last *Client.ContainerList. +// LastContainerList returns a channel that receives call arguments of last *Client.ContainerList call. func (t *Testing) LastContainerList() <-chan ContainerListRequest { return t.client.requests.containerList } -// LastContainerInspect returns a channel that receives call arguments of last *Client.ContainerInspect. +// LastContainerInspect returns a channel that receives call arguments of last *Client.ContainerInspect call. func (t *Testing) LastContainerInspect() <-chan ContainerInspectRequest { return t.client.requests.containerInspect } -// LastSwarmInit returns a channel that receives call arguments of last *Client.SwarmInit. +// LastSwarmInit returns a channel that receives call arguments of last *Client.SwarmInit call. func (t *Testing) LastSwarmInit() <-chan SwarmInitRequest { return t.client.requests.swarmInit } -// LastNetworkCreate returns a channel that receives call arguments of last *Client.NetworkCreate. +// LastNetworkCreate returns a channel that receives call arguments of last *Client.NetworkCreate call. func (t *Testing) LastNetworkCreate() <-chan NetworkCreateRequest { return t.client.requests.networkCreate } -// LastNetworkInspect returns a channel that receives call arguments of last *Client.NetworkInspect. +// LastNetworkInspect returns a channel that receives call arguments of last *Client.NetworkInspect call. func (t *Testing) LastNetworkInspect() <-chan NetworkInspectRequest { return t.client.requests.networkInspect } -// LastInfo returns a channel that receives call arguments of last *Client.Info. +// LastInfo returns a channel that receives call arguments of last *Client.Info call. func (t *Testing) LastInfo() <-chan InfoRequest { return t.client.requests.info } -// LastNegotiateAPIVersion returns a channel that receives call arguments of last *Client.NegotiateAPIVersion. +// LastNegotiateAPIVersion returns a channel that receives call arguments of last *Client.NegotiateAPIVersion call. func (t *Testing) LastNegotiateAPIVersion() <-chan NegotiateAPIVersionRequest { return t.client.requests.negotiateAPIVersion } -// LastImageBuild returns a channel that receives call arguments of last *Client.ImageBuild. +// LastImageBuild returns a channel that receives call arguments of last *Client.ImageBuild call. func (t *Testing) LastImageBuild() <-chan ImageBuildRequest { return t.client.requests.imageBuild } -// LastNetworkRemove returns a channel that receives call arguments of last *Client.NetworkRemove. +// LastNetworkRemove returns a channel that receives call arguments of last *Client.NetworkRemove call. func (t *Testing) LastNetworkRemove() <-chan NetworkRemoveRequest { return t.client.requests.networkRemove } -// LastTaskList returns a channel that receives call arguments of last *Client.TaskList. +// LastTaskList returns a channel that receives call arguments of last *Client.TaskList call. func (t *Testing) LastTaskList() <-chan TaskListRequest { return t.client.requests.taskList } -// LastServiceCreate returns a channel that receives call arguments of last *Client.ServiceCreate. +// LastServiceCreate returns a channel that receives call arguments of last *Client.ServiceCreate call. func (t *Testing) LastServiceCreate() <-chan ServiceCreateRequest { return t.client.requests.serviceCreate } -// LastServiceList returns a channel that receives call arguments of last *Client.ServiceList. +// LastServiceList returns a channel that receives call arguments of last *Client.ServiceList call. func (t *Testing) LastServiceList() <-chan ServiceListRequest { return t.client.requests.serviceList } -// LastServiceInspectWithRaw returns a channel that receives call arguments of last *Client.ServiceInspectWithRaw. +// LastServiceInspectWithRaw returns a channel that receives call arguments of last *Client.ServiceInspectWithRaw call. func (t *Testing) LastServiceInspectWithRaw() <-chan ServiceInspectWithRawRequest { return t.client.requests.serviceInspectWithRaw } -// LastServiceRemove returns a channel that receives call arguments of last *Client.ServiceRemove. +// LastServiceRemove returns a channel that receives call arguments of last *Client.ServiceRemove call. func (t *Testing) LastServiceRemove() <-chan ServiceRemoveRequest { return t.client.requests.serviceRemove } -// LastServiceLogs returns a channel that receives call arguments of last *Client.ServiceLogs. +// LastServiceLogs returns a channel that receives call arguments of last *Client.ServiceLogs call. func (t *Testing) LastServiceLogs() <-chan ServiceLogsRequest { return t.client.requests.serviceLogs } From 8e2d2778e3b113f1f52e4d23c271c9cac6ec7675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=CC=87lker=20Go=CC=88ktug=CC=86=20O=CC=88ztu=CC=88rk?= Date: Tue, 7 Aug 2018 12:21:32 +0300 Subject: [PATCH 10/22] container: minor improvements on tests --- container/build_test.go | 11 ++++++----- container/container_test.go | 18 ++++++++++++++---- container/network_test.go | 6 ++++++ container/service_test.go | 10 +++++----- 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/container/build_test.go b/container/build_test.go index 789365eac..fdd9913b3 100644 --- a/container/build_test.go +++ b/container/build_test.go @@ -16,12 +16,12 @@ func TestBuild(t *testing.T) { tag := "sha256:1f6359c933421f53a7ef9e417bfa51b1c313c54878fdeb16de827f427e16d836" dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + dt.ProvideImageBuild(ioutil.NopCloser(strings.NewReader( fmt.Sprintf(`{"stream":"%s\n"}`, tag), ))) - c, _ := New(ClientOption(dt.Client())) - tag1, err := c.Build(path) assert.Nil(t, err) assert.Equal(t, tag, tag1) @@ -39,13 +39,13 @@ func TestBuildNotWorking(t *testing.T) { path := "test-not-valid/" dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + dt.ProvideImageBuild(ioutil.NopCloser(strings.NewReader(` {"stream":"Step 1/2 : FROM notExistingImage"} {"stream":"\n"} {"errorDetail":{"message":"invalid reference format: repository name must be lowercase"},"error":"invalid reference format: repository name must be lowercase"}`))) - c, _ := New(ClientOption(dt.Client())) - tag, err := c.Build(path) assert.Equal(t, "Image build failed. invalid reference format: repository name must be lowercase", err.Error()) assert.Equal(t, "", tag) @@ -53,9 +53,10 @@ func TestBuildNotWorking(t *testing.T) { func TestBuildWrongPath(t *testing.T) { dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + dt.ProvideImageBuild(ioutil.NopCloser(strings.NewReader(""))) - c, _ := New(ClientOption(dt.Client())) _, err := c.Build("testss/") assert.Equal(t, "Could not parse container build response", err.Error()) } diff --git a/container/container_test.go b/container/container_test.go index 0077085a5..6cbbcd21a 100644 --- a/container/container_test.go +++ b/container/container_test.go @@ -90,11 +90,11 @@ func TestFindContainer(t *testing.T) { } dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + dt.ProvideContainerList(containerData, nil) dt.ProvideContainerInspect(containerJSONData, nil) - c, _ := New(ClientOption(dt.Client())) - container, err := c.FindContainer(namespace) assert.Nil(t, err) assert.Equal(t, containerJSONData.ID, container.ID) @@ -121,6 +121,14 @@ func TestNonExistentContainerStatus(t *testing.T) { status, err := c.Status(namespace) assert.Nil(t, err) assert.Equal(t, STOPPED, status) + + assert.Equal(t, types.ContainerListOptions{ + Filters: filters.NewArgs(filters.KeyValuePair{ + Key: "label", + Value: "com.docker.stack.namespace=" + Namespace(namespace), + }), + Limit: 1, + }, (<-dt.LastContainerList()).Options) } func TestExistentContainerStatus(t *testing.T) { @@ -137,10 +145,11 @@ func TestExistentContainerStatus(t *testing.T) { } dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + dt.ProvideContainerList(containerData, nil) dt.ProvideContainerInspect(containerJSONData, nil) - c, _ := New(ClientOption(dt.Client())) status, err := c.Status(namespace) assert.Nil(t, err) assert.Equal(t, STOPPED, status) @@ -160,10 +169,11 @@ func TestExistentContainerRunningStatus(t *testing.T) { } dt := dockertest.New() + c, _ := New(ClientOption(dt.Client())) + dt.ProvideContainerList(containerData, nil) dt.ProvideContainerInspect(containerJSONData, nil) - c, _ := New(ClientOption(dt.Client())) status, err := c.Status(namespace) assert.Nil(t, err) assert.Equal(t, RUNNING, status) diff --git a/container/network_test.go b/container/network_test.go index afe109031..53a644702 100644 --- a/container/network_test.go +++ b/container/network_test.go @@ -58,6 +58,12 @@ func TestCreateAlreadyExistingNetwork(t *testing.T) { li := <-dt.LastNetworkInspect() assert.Equal(t, Namespace(namespace), li.Network) assert.Equal(t, types.NetworkInspectOptions{}, li.Options) + + select { + case <-dt.LastNetworkCreate(): + t.Error("should not create existing network") + default: + } } func TestDeleteNetwork(t *testing.T) { diff --git a/container/service_test.go b/container/service_test.go index c26dabb57..a9761a1ae 100644 --- a/container/service_test.go +++ b/container/service_test.go @@ -96,7 +96,7 @@ func TestServiceStatusNeverStarted(t *testing.T) { assert.Equal(t, types.ServiceInspectOptions{}, li.Options) } -func TestIntegrationServiceStatusRunning(t *testing.T) { +func TestServiceStatusRunning(t *testing.T) { namespace := []string{"namespace"} dt := dockertest.New() @@ -147,10 +147,11 @@ func TestFindServiceNotExisting(t *testing.T) { func TestListServices(t *testing.T) { namespace := []string{"namespace"} + namespace1 := []string{"namespace"} label := "1" swarmServices := []swarm.Service{ {Spec: swarm.ServiceSpec{Annotations: swarm.Annotations{Name: Namespace(namespace)}}}, - {Spec: swarm.ServiceSpec{Annotations: swarm.Annotations{Name: Namespace(namespace)}}}, + {Spec: swarm.ServiceSpec{Annotations: swarm.Annotations{Name: Namespace(namespace1)}}}, } dt := dockertest.New() @@ -162,7 +163,7 @@ func TestListServices(t *testing.T) { assert.Nil(t, err) assert.Equal(t, 2, len(services)) assert.Equal(t, Namespace(namespace), services[0].Spec.Name) - assert.Equal(t, Namespace(namespace), services[1].Spec.Name) + assert.Equal(t, Namespace(namespace1), services[1].Spec.Name) assert.Equal(t, types.ServiceListOptions{ Filters: filters.NewArgs(filters.KeyValuePair{ @@ -183,14 +184,13 @@ func TestServiceLogs(t *testing.T) { reader, err := c.ServiceLogs(namespace) assert.Nil(t, err) - defer reader.Close() + bytes, err := ioutil.ReadAll(reader) assert.Nil(t, err) assert.Equal(t, data, string(bytes)) ll := <-dt.LastServiceLogs() - assert.Equal(t, Namespace(namespace), ll.ServiceID) assert.Equal(t, types.ContainerLogsOptions{ ShowStdout: true, From 3ed65890601b779dac7618793ae22bf22a7cfc13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=CC=87lker=20Go=CC=88ktug=CC=86=20O=CC=88ztu=CC=88rk?= Date: Tue, 7 Aug 2018 16:21:38 +0300 Subject: [PATCH 11/22] add tests for container/dockertest, closes #341 --- container/build_test.go | 6 +- container/dockertest/error.go | 2 +- container/dockertest/error_test.go | 14 ++ container/dockertest/requests.go | 1 - container/dockertest/testing.go | 4 +- container/dockertest/testing_test.go | 265 +++++++++++++++++++++++++++ container/service_test.go | 8 +- 7 files changed, 289 insertions(+), 11 deletions(-) create mode 100644 container/dockertest/error_test.go create mode 100644 container/dockertest/testing_test.go diff --git a/container/build_test.go b/container/build_test.go index fdd9913b3..9740242b9 100644 --- a/container/build_test.go +++ b/container/build_test.go @@ -20,7 +20,7 @@ func TestBuild(t *testing.T) { dt.ProvideImageBuild(ioutil.NopCloser(strings.NewReader( fmt.Sprintf(`{"stream":"%s\n"}`, tag), - ))) + )), nil) tag1, err := c.Build(path) assert.Nil(t, err) @@ -44,7 +44,7 @@ func TestBuildNotWorking(t *testing.T) { dt.ProvideImageBuild(ioutil.NopCloser(strings.NewReader(` {"stream":"Step 1/2 : FROM notExistingImage"} {"stream":"\n"} -{"errorDetail":{"message":"invalid reference format: repository name must be lowercase"},"error":"invalid reference format: repository name must be lowercase"}`))) +{"errorDetail":{"message":"invalid reference format: repository name must be lowercase"},"error":"invalid reference format: repository name must be lowercase"}`)), nil) tag, err := c.Build(path) assert.Equal(t, "Image build failed. invalid reference format: repository name must be lowercase", err.Error()) @@ -55,7 +55,7 @@ func TestBuildWrongPath(t *testing.T) { dt := dockertest.New() c, _ := New(ClientOption(dt.Client())) - dt.ProvideImageBuild(ioutil.NopCloser(strings.NewReader(""))) + dt.ProvideImageBuild(ioutil.NopCloser(strings.NewReader("")), nil) _, err := c.Build("testss/") assert.Equal(t, "Could not parse container build response", err.Error()) diff --git a/container/dockertest/error.go b/container/dockertest/error.go index 3dcdf245b..f15df7822 100644 --- a/container/dockertest/error.go +++ b/container/dockertest/error.go @@ -1,6 +1,6 @@ package dockertest -// NotFoundErr satisfies docker client's NotFoundErr interface. +// NotFoundErr satisfies docker client's notFound interface. // docker.IsErrNotFound(err) will return true with NotFoundErr. type NotFoundErr struct{} diff --git a/container/dockertest/error_test.go b/container/dockertest/error_test.go new file mode 100644 index 000000000..c56145c81 --- /dev/null +++ b/container/dockertest/error_test.go @@ -0,0 +1,14 @@ +package dockertest + +import ( + "testing" + + "github.com/stvp/assert" +) + +// TestNotFoundErr makes sure NotFoundErr to implement docker client's notFound interface. +func TestNotFoundErr(t *testing.T) { + err := NotFoundErr{} + assert.True(t, err.NotFound()) + assert.Equal(t, "not found", err.Error()) +} diff --git a/container/dockertest/requests.go b/container/dockertest/requests.go index 92974ad18..d665d99ef 100644 --- a/container/dockertest/requests.go +++ b/container/dockertest/requests.go @@ -52,7 +52,6 @@ type SwarmInitRequest struct { // InfoRequest holds call arguments of *Client.Info. type InfoRequest struct { - Info types.Info } // ContainerListRequest holds call arguments of *Client.ContainerList. diff --git a/container/dockertest/testing.go b/container/dockertest/testing.go index 7c683503e..bb22b6018 100644 --- a/container/dockertest/testing.go +++ b/container/dockertest/testing.go @@ -43,8 +43,8 @@ func (t *Testing) ProvideContainerInspect(json types.ContainerJSON, err error) { } // ProvideImageBuild sets fake return values for the next call to *Client.ImageBuild. -func (t *Testing) ProvideImageBuild(rc io.ReadCloser) { - t.client.responses.imageBuild <- imageBuildResponse{types.ImageBuildResponse{Body: rc}, nil} +func (t *Testing) ProvideImageBuild(rc io.ReadCloser, err error) { + t.client.responses.imageBuild <- imageBuildResponse{types.ImageBuildResponse{Body: rc}, err} } // ProvideNetworkInspect sets fake return values for the next call to *Client.NetworkInspect. diff --git a/container/dockertest/testing_test.go b/container/dockertest/testing_test.go new file mode 100644 index 000000000..f5c028ed4 --- /dev/null +++ b/container/dockertest/testing_test.go @@ -0,0 +1,265 @@ +package dockertest + +import ( + "bytes" + "context" + "errors" + "io/ioutil" + "testing" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/swarm" + "github.com/stvp/assert" +) + +var errGeneric = errors.New("titan of the errors") + +func TestNew(t *testing.T) { + dt := New() + assert.NotNil(t, dt) +} + +func TestClient(t *testing.T) { + dt := New() + assert.NotNil(t, dt.Client()) +} + +func TestNegotiateAPIVersion(t *testing.T) { + dt := New() + dt.Client().NegotiateAPIVersion(context.Background()) + + select { + case <-dt.LastNegotiateAPIVersion(): + default: + t.Error("last call to *Client.NegotiateAPIVersion should be observable") + } +} + +func TestNetworkInspect(t *testing.T) { + resource := types.NetworkResource{ID: "1"} + network := "2" + options := types.NetworkInspectOptions{Verbose: true} + + dt := New() + dt.ProvideNetworkInspect(resource, errGeneric) + + resource1, err := dt.Client().NetworkInspect(context.Background(), network, options) + assert.Equal(t, errGeneric, err) + assert.Equal(t, resource, resource1) + + ll := <-dt.LastNetworkInspect() + assert.Equal(t, network, ll.Network) + assert.Equal(t, options, ll.Options) +} + +func TestNetworkCreate(t *testing.T) { + response := types.NetworkCreateResponse{ID: "1"} + name := "2" + options := types.NetworkCreate{CheckDuplicate: true} + + dt := New() + dt.ProvideNetworkCreate(response, errGeneric) + + response1, err := dt.Client().NetworkCreate(context.Background(), name, options) + assert.Equal(t, errGeneric, err) + assert.Equal(t, response, response1) + + ll := <-dt.LastNetworkCreate() + assert.Equal(t, name, ll.Name) + assert.Equal(t, options, ll.Options) +} + +func TestSwarmInit(t *testing.T) { + request := swarm.InitRequest{ForceNewCluster: true} + + dt := New() + + data, err := dt.Client().SwarmInit(context.Background(), request) + assert.Nil(t, err) + assert.Equal(t, "", data) + + assert.Equal(t, request, (<-dt.LastSwarmInit()).Request) +} + +func TestInfo(t *testing.T) { + info := types.Info{ID: "1"} + + dt := New() + dt.ProvideInfo(info, errGeneric) + + info1, err := dt.Client().Info(context.Background()) + assert.Equal(t, errGeneric, err) + assert.Equal(t, info, info1) + + select { + case <-dt.LastInfo(): + default: + t.Error("last call to *Client.Info should be observable") + } +} + +func TestContainerList(t *testing.T) { + containers := []types.Container{{ID: "1"}, {ID: "2"}} + options := types.ContainerListOptions{Quiet: true} + + dt := New() + dt.ProvideContainerList(containers, errGeneric) + + containers1, err := dt.Client().ContainerList(context.Background(), options) + assert.Equal(t, errGeneric, err) + assert.Equal(t, containers, containers1) + + ll := <-dt.LastContainerList() + assert.Equal(t, options, ll.Options) +} + +func TestContainerInspect(t *testing.T) { + container := "1" + containerJSON := types.ContainerJSON{ContainerJSONBase: &types.ContainerJSONBase{ID: "2"}} + + dt := New() + dt.ProvideContainerInspect(containerJSON, errGeneric) + + containerJSON1, err := dt.Client().ContainerInspect(context.Background(), container) + assert.Equal(t, errGeneric, err) + assert.Equal(t, containerJSON, containerJSON1) + + ll := <-dt.LastContainerInspect() + assert.Equal(t, container, ll.Container) +} + +func TestImageBuild(t *testing.T) { + options := types.ImageBuildOptions{SuppressOutput: true} + response := []byte{1, 2} + request := []byte{3} + + dt := New() + dt.ProvideImageBuild(ioutil.NopCloser(bytes.NewReader(response)), errGeneric) + + resp, err := dt.Client().ImageBuild(context.Background(), + ioutil.NopCloser(bytes.NewReader(request)), options) + assert.Equal(t, errGeneric, err) + defer resp.Body.Close() + + respData, err := ioutil.ReadAll(resp.Body) + assert.Nil(t, err) + assert.Equal(t, response, respData) + + ll := <-dt.LastImageBuild() + assert.Equal(t, options, ll.Options) + assert.Equal(t, request, ll.FileData) +} + +func TestNetworkRemove(t *testing.T) { + network := "1" + dt := New() + assert.Nil(t, dt.Client().NetworkRemove(context.Background(), network)) + assert.Equal(t, network, (<-dt.LastNetworkRemove()).Network) +} + +func TestTaskList(t *testing.T) { + tasks := []swarm.Task{{ID: "1"}, {ID: "2"}} + options := types.TaskListOptions{ + Filters: filters.NewArgs(filters.KeyValuePair{ + Key: "1", + }), + } + + dt := New() + dt.ProvideTaskList(tasks, errGeneric) + + tasks1, err := dt.Client().TaskList(context.Background(), options) + assert.Equal(t, errGeneric, err) + assert.Equal(t, tasks, tasks1) + + assert.Equal(t, options, (<-dt.LastTaskList()).Options) +} + +func TestServiceCreate(t *testing.T) { + response := types.ServiceCreateResponse{ID: "1"} + service := swarm.ServiceSpec{Annotations: swarm.Annotations{Name: "1"}} + options := types.ServiceCreateOptions{QueryRegistry: true} + + dt := New() + dt.ProvideServiceCreate(response, errGeneric) + + response1, err := dt.Client().ServiceCreate(context.Background(), service, options) + assert.Equal(t, errGeneric, err) + assert.Equal(t, response, response1) + + ll := <-dt.LastServiceCreate() + assert.Equal(t, service, ll.Service) + assert.Equal(t, options, ll.Options) +} + +func TestServiceList(t *testing.T) { + services := []swarm.Service{{ID: "1"}, {ID: "2"}} + options := types.ServiceListOptions{ + Filters: filters.NewArgs(filters.KeyValuePair{ + Key: "label", + }), + } + + dt := New() + dt.ProvideServiceList(services, errGeneric) + + services1, err := dt.Client().ServiceList(context.Background(), options) + assert.Equal(t, errGeneric, err) + assert.Equal(t, services, services1) + + ll := <-dt.LastServiceList() + assert.Equal(t, options, ll.Options) +} + +func TestServiceInspectWithRaw(t *testing.T) { + serviceID := "1" + options := types.ServiceInspectOptions{InsertDefaults: true} + service := swarm.Service{ID: "1"} + data := []byte{1, 2} + + dt := New() + dt.ProvideServiceInspectWithRaw(service, data, errGeneric) + + service1, data1, err := dt.Client().ServiceInspectWithRaw(context.Background(), serviceID, options) + assert.Equal(t, errGeneric, err) + assert.Equal(t, service, service1) + assert.Equal(t, data, data1) + + ll := <-dt.LastServiceInspectWithRaw() + assert.Equal(t, serviceID, ll.ServiceID) + assert.Equal(t, options, ll.Options) +} + +func TestServiceRemove(t *testing.T) { + serviceID := "1" + + dt := New() + dt.ProvideServiceRemove(errGeneric) + + assert.Equal(t, errGeneric, dt.Client().ServiceRemove(context.Background(), serviceID)) + + ll := <-dt.LastServiceRemove() + assert.Equal(t, serviceID, ll.ServiceID) +} + +func TestServiceLogs(t *testing.T) { + serviceID := "1" + data := []byte{1, 2} + options := types.ContainerLogsOptions{ShowStdout: true} + + dt := New() + dt.ProvideServiceLogs(ioutil.NopCloser(bytes.NewReader(data)), errGeneric) + + rc, err := dt.Client().ServiceLogs(context.Background(), serviceID, options) + assert.Equal(t, errGeneric, err) + defer rc.Close() + + data1, err := ioutil.ReadAll(rc) + assert.Nil(t, err) + assert.Equal(t, data, data1) + + ll := <-dt.LastServiceLogs() + assert.Equal(t, serviceID, ll.ServiceID) + assert.Equal(t, options, ll.Options) +} diff --git a/container/service_test.go b/container/service_test.go index a9761a1ae..5f06c98b9 100644 --- a/container/service_test.go +++ b/container/service_test.go @@ -1,8 +1,8 @@ package container import ( + "bytes" "io/ioutil" - "strings" "testing" "github.com/docker/docker/api/types" @@ -175,12 +175,12 @@ func TestListServices(t *testing.T) { func TestServiceLogs(t *testing.T) { namespace := []string{"namespace"} - data := "mesg" + data := []byte{1, 2} dt := dockertest.New() c, _ := New(ClientOption(dt.Client())) - dt.ProvideServiceLogs(ioutil.NopCloser(strings.NewReader(data)), nil) + dt.ProvideServiceLogs(ioutil.NopCloser(bytes.NewReader(data)), nil) reader, err := c.ServiceLogs(namespace) assert.Nil(t, err) @@ -188,7 +188,7 @@ func TestServiceLogs(t *testing.T) { bytes, err := ioutil.ReadAll(reader) assert.Nil(t, err) - assert.Equal(t, data, string(bytes)) + assert.Equal(t, data, bytes) ll := <-dt.LastServiceLogs() assert.Equal(t, Namespace(namespace), ll.ServiceID) From c6c680d3e23366bcb38d1fb05faf91e1f32c3dc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=CC=87lker=20Go=CC=88ktug=CC=86=20O=CC=88ztu=CC=88rk?= Date: Wed, 8 Aug 2018 19:01:29 +0300 Subject: [PATCH 12/22] fix typo on dockertest --- container/dockertest/client.go | 6 +++--- container/dockertest/testing.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/container/dockertest/client.go b/container/dockertest/client.go index 375afadd2..240cb0305 100644 --- a/container/dockertest/client.go +++ b/container/dockertest/client.go @@ -58,7 +58,7 @@ type responses struct { serviceInspectWithRaw chan serviceInspectWithRawResponse serviceRemove chan serviceRemoveResponse serviceLogs chan serviceLogsResponse - contanerInspect chan containerInspectResponse + containerInspect chan containerInspectResponse containerList chan containerListResponse } @@ -98,7 +98,7 @@ func newClient() *Client { serviceInspectWithRaw: make(chan serviceInspectWithRawResponse, 1), serviceRemove: make(chan serviceRemoveResponse, 1), serviceLogs: make(chan serviceLogsResponse, 1), - contanerInspect: make(chan containerInspectResponse, 1), + containerInspect: make(chan containerInspectResponse, 1), containerList: make(chan containerListResponse, 1), }, } @@ -169,7 +169,7 @@ func (c *Client) ContainerList(ctx context.Context, func (c *Client) ContainerInspect(ctx context.Context, container string) (types.ContainerJSON, error) { c.requests.containerInspect <- ContainerInspectRequest{container} select { - case resp := <-c.responses.contanerInspect: + case resp := <-c.responses.containerInspect: return resp.json, resp.err default: return types.ContainerJSON{}, nil diff --git a/container/dockertest/testing.go b/container/dockertest/testing.go index bb22b6018..b928e72b6 100644 --- a/container/dockertest/testing.go +++ b/container/dockertest/testing.go @@ -39,7 +39,7 @@ func (t *Testing) ProvideContainerList(containers []types.Container, err error) // ProvideContainerInspect sets fake return values for the next call to *Client.ContainerInspect. func (t *Testing) ProvideContainerInspect(json types.ContainerJSON, err error) { - t.client.responses.contanerInspect <- containerInspectResponse{json, err} + t.client.responses.containerInspect <- containerInspectResponse{json, err} } // ProvideImageBuild sets fake return values for the next call to *Client.ImageBuild. From 2c7175d4dd998018b6d4c7fab5abdc0feb6ed2ad Mon Sep 17 00:00:00 2001 From: krhubert Date: Thu, 9 Aug 2018 11:03:29 +0200 Subject: [PATCH 13/22] Pass data using flag to the service execute command (#344) * Support data flag in service execute cmd * Add Cast method to Service * Update docs and changelog * Non-zero exit on error * Cast Object from JSON --- CHANGELOG.md | 1 + cmd/service/execute.go | 54 ++++++--- cmd/utils/error.go | 2 +- docs/cli/mesg-core_service_execute.md | 7 +- service/cast.go | 79 +++++++++++++ service/cast_test.go | 98 ++++++++++++++++ service/error.go | 10 ++ utils/xpflag/string_to_string.go | 70 ++++++++++++ utils/xpflag/string_to_string_test.go | 154 ++++++++++++++++++++++++++ 9 files changed, 455 insertions(+), 20 deletions(-) create mode 100644 service/cast.go create mode 100644 service/cast_test.go create mode 100644 utils/xpflag/string_to_string.go create mode 100644 utils/xpflag/string_to_string_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b07bab48..3cfce00ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - (#303) Add command `service dev` that build and run the service with the logs - (#303) Add command `service execute` that execute a task on a service - (#316) Delete service when stoping the `service dev` command to avoid to keep all the versions of the services. +- (#344) Add `service execute --data` flag to pass arguments as key=value. #### Removed - (#303) Deprecate command `service test` in favor of `service dev` and `service execute` diff --git a/cmd/service/execute.go b/cmd/service/execute.go index c28352f7d..59677d86e 100644 --- a/cmd/service/execute.go +++ b/cmd/service/execute.go @@ -2,6 +2,8 @@ package service import ( "context" + "encoding/json" + "errors" "fmt" "io/ioutil" "os" @@ -11,32 +13,44 @@ import ( "github.com/mesg-foundation/core/api/core" "github.com/mesg-foundation/core/cmd/utils" "github.com/mesg-foundation/core/service" + "github.com/mesg-foundation/core/utils/xpflag" "github.com/spf13/cobra" survey "gopkg.in/AlecAivazis/survey.v1" ) -var executions []*core.ResultData +var executeData map[string]string // Execute a task from a service var Execute = &cobra.Command{ Use: "execute", Short: "Execute a task of a service", Example: `mesg-core service execute SERVICE_ID`, - Args: cobra.MinimumNArgs(1), + Args: cobra.ExactArgs(1), + PreRun: executePreRun, Run: executeHandler, DisableAutoGenTag: true, } func init() { Execute.Flags().StringP("task", "t", "", "Run the given task") + Execute.Flags().VarP(xpflag.NewStringToStringValue(&executeData, nil), "data", "d", "data required to run the task") Execute.Flags().StringP("json", "j", "", "Path to a JSON file containing the data required to run the task") } +func executePreRun(cmd *cobra.Command, args []string) { + if cmd.Flag("data").Changed && cmd.Flag("json").Changed { + utils.HandleError(errors.New("You can specify only one of '--data' or '--json' options")) + } +} + func executeHandler(cmd *cobra.Command, args []string) { serviceID := args[0] - taskKey := getTaskKey(cmd, serviceID) - json := getJSON(cmd) - taskData, err := readJSONFile(json) + serviceReply, err := cli().GetService(context.Background(), &core.GetServiceRequest{ + ServiceID: serviceID, + }) + utils.HandleError(err) + taskKey := getTaskKey(cmd, serviceReply.Service) + taskData, err := getData(cmd, taskKey, serviceReply.Service) utils.HandleError(err) stream, err := cli().ListenResult(context.Background(), &core.ListenResultRequest{ @@ -79,16 +93,12 @@ func taskKeysFromService(s *service.Service) []string { return taskKeys } -func getTaskKey(cmd *cobra.Command, serviceID string) string { +func getTaskKey(cmd *cobra.Command, s *service.Service) string { taskKey := cmd.Flag("task").Value.String() if taskKey == "" { - serviceReply, err := cli().GetService(context.Background(), &core.GetServiceRequest{ - ServiceID: serviceID, - }) - utils.HandleError(err) if survey.AskOne(&survey.Select{ Message: "Select the task to execute", - Options: taskKeysFromService(serviceReply.Service), + Options: taskKeysFromService(s), }, &taskKey, nil) != nil { os.Exit(0) } @@ -96,14 +106,26 @@ func getTaskKey(cmd *cobra.Command, serviceID string) string { return taskKey } -func getJSON(cmd *cobra.Command) string { - json := cmd.Flag("json").Value.String() - if json == "" { - if survey.AskOne(&survey.Input{Message: "Enter the filepath to the inputs"}, &json, nil) != nil { +func getData(cmd *cobra.Command, taskKey string, s *service.Service) (string, error) { + data := cmd.Flag("data").Value.String() + jsonFile := cmd.Flag("json").Value.String() + + if data != "" { + castData, err := s.Cast(taskKey, executeData) + if err != nil { + return "", err + } + + b, err := json.Marshal(castData) + return string(b), err + } + + if jsonFile == "" { + if survey.AskOne(&survey.Input{Message: "Enter the filepath to the inputs"}, &jsonFile, nil) != nil { os.Exit(0) } } - return json + return readJSONFile(jsonFile) } func readJSONFile(path string) (string, error) { diff --git a/cmd/utils/error.go b/cmd/utils/error.go index a8297350a..54940c585 100644 --- a/cmd/utils/error.go +++ b/cmd/utils/error.go @@ -21,7 +21,7 @@ const ( func HandleError(err error) { if err != nil { fmt.Println(errorMessage(err)) - os.Exit(0) + os.Exit(1) } } diff --git a/docs/cli/mesg-core_service_execute.md b/docs/cli/mesg-core_service_execute.md index f045864b2..d1fbec7f0 100644 --- a/docs/cli/mesg-core_service_execute.md +++ b/docs/cli/mesg-core_service_execute.md @@ -19,9 +19,10 @@ mesg-core service execute SERVICE_ID ### Options ``` - -h, --help help for execute - -j, --json string Path to a JSON file containing the data required to run the task - -t, --task string Run the given task + -d, --data key=value data required to run the task + -h, --help help for execute + -j, --json string Path to a JSON file containing the data required to run the task + -t, --task string Run the given task ``` ### SEE ALSO diff --git a/service/cast.go b/service/cast.go new file mode 100644 index 000000000..bbcc453cb --- /dev/null +++ b/service/cast.go @@ -0,0 +1,79 @@ +package service + +import ( + "encoding/json" + "fmt" + "strconv" +) + +type caster func(value string) (interface{}, error) + +func castString(value string) (interface{}, error) { + return value, nil +} +func castNumber(value string) (interface{}, error) { + i, err := strconv.ParseInt(value, 10, 64) + if err == nil { + return i, nil + } + f, err := strconv.ParseFloat(value, 64) + if err != nil { + return nil, fmt.Errorf("input %q is not a Number type", value) + } + return f, nil +} +func castBoolean(value string) (interface{}, error) { + b, err := strconv.ParseBool(value) + if err != nil { + return nil, fmt.Errorf("input %q is not a Boolean type", value) + } + return b, nil +} +func castObject(value string) (interface{}, error) { + var v interface{} + if err := json.Unmarshal([]byte(value), &v); err != nil { + return nil, fmt.Errorf("input %q is not a Object type", value) + } + return v, nil +} + +var casters = map[string]caster{ + "String": castString, + "Number": castNumber, + "Boolean": castBoolean, + "Object": castObject, +} + +// Cast converts map[string]string to map[string]interface{} based on defined types in the service tasks map. +func (s *Service) Cast(taskKey string, taskData map[string]string) (map[string]interface{}, error) { + task, ok := s.Tasks[taskKey] + if !ok { + return nil, &TaskNotFoundError{Service: s, TaskKey: taskKey} + } + + m := make(map[string]interface{}, len(taskData)) + for key, value := range taskData { + inputType, ok := task.Inputs[key] + if !ok { + return nil, &InputNotFoundError{Service: s, InputKey: key} + } + + newValue, err := s.cast(value, inputType.Type) + if err != nil { + return nil, fmt.Errorf("Task %q - %s", taskKey, err) + } + if newValue != nil { + m[key] = newValue + } + } + return m, nil +} + +// cast converts single value based on its type. +func (s *Service) cast(value, inputType string) (interface{}, error) { + c, ok := casters[inputType] + if !ok { + return nil, fmt.Errorf("input %q - invalid type", value) + } + return c(value) +} diff --git a/service/cast_test.go b/service/cast_test.go new file mode 100644 index 000000000..5128dfc92 --- /dev/null +++ b/service/cast_test.go @@ -0,0 +1,98 @@ +package service + +import ( + "testing" + + "github.com/stvp/assert" +) + +func TestServiceCast(t *testing.T) { + var tests = []struct { + service *Service + data map[string]string + expected map[string]interface{} + expectErr bool + }{ + { + createTestServcieWithInputs(nil), + map[string]string{}, + map[string]interface{}{}, + false, + }, + { + createTestServcieWithInputs(map[string]string{ + "a": "String", + "b": "Number", + "c": "Number", + "d": "Boolean", + }), + map[string]string{ + "a": "_", + "b": "1", + "c": "1.1", + "d": "true", + }, + map[string]interface{}{ + "a": "_", + "b": int64(1), + "c": 1.1, + "d": true, + }, + false, + }, + { + createTestServcieWithInputs(map[string]string{"a": "String"}), + map[string]string{"b": "_"}, + map[string]interface{}{}, + true, + }, + { + createTestServcieWithInputs(map[string]string{"a": "Number"}), + map[string]string{"a": "_"}, + map[string]interface{}{}, + true, + }, + { + createTestServcieWithInputs(map[string]string{"a": "Boolean"}), + map[string]string{"a": "_"}, + map[string]interface{}{}, + true, + }, + { + createTestServcieWithInputs(map[string]string{"a": "Object"}), + map[string]string{"a": `{"b":1}`}, + map[string]interface{}{"a": map[string]interface{}{"b": float64(1)}}, + false, + }, + } + + for _, tt := range tests { + got, err := tt.service.Cast("test", tt.data) + if tt.expectErr { + assert.NotNil(t, err) + } else { + assert.Equal(t, len(tt.expected), len(got), "maps len are not equal") + assert.Equal(t, tt.expected, got, "maps are not equal") + } + } + + // test if non-existing key returns error + _, err := tests[0].service.Cast("_", nil) + assert.NotNil(t, err) +} + +// creates test service with given inputs name and type under "test" task key. +func createTestServcieWithInputs(inputs map[string]string) *Service { + s := &Service{ + Tasks: map[string]*Task{ + "test": { + Inputs: make(map[string]*Parameter), + }, + }, + } + + for name, itype := range inputs { + s.Tasks["test"].Inputs[name] = &Parameter{Type: itype} + } + return s +} diff --git a/service/error.go b/service/error.go index 7152dd9a3..614ef8d3e 100644 --- a/service/error.go +++ b/service/error.go @@ -50,6 +50,16 @@ func (e *InvalidTaskInputError) Error() string { return errorString } +// InputNotFoundError is an error when a service doesn't contains a specific input. +type InputNotFoundError struct { + Service *Service + InputKey string +} + +func (e *InputNotFoundError) Error() string { + return "Input '" + e.InputKey + "' not found in service '" + e.Service.Name + "'" +} + // OutputNotFoundError is an error when a service doesn't contain a specific output. type OutputNotFoundError struct { Service *Service diff --git a/utils/xpflag/string_to_string.go b/utils/xpflag/string_to_string.go new file mode 100644 index 000000000..cbfe3518c --- /dev/null +++ b/utils/xpflag/string_to_string.go @@ -0,0 +1,70 @@ +package xpflag + +import ( + "bytes" + "fmt" + "strings" +) + +// StringToStringValue flag. +type StringToStringValue struct { + value *map[string]string + separator string + changed bool +} + +// NewStringToStringValue creates new flag with init map, default value and comma separator. +func NewStringToStringValue(p *map[string]string, value map[string]string) *StringToStringValue { + s := new(StringToStringValue) + s.separator = "," + s.value = p + *s.value = value + return s +} + +// SetSeparator changes separator. +func (s *StringToStringValue) SetSeparator(separator string) { + s.separator = separator +} + +// Set value in format: a=1,b=2 +func (s *StringToStringValue) Set(val string) error { + ss := strings.Split(val, s.separator) + out := make(map[string]string, len(ss)) + for _, pair := range ss { + kv := strings.SplitN(pair, "=", 2) + if len(kv) != 2 { + return fmt.Errorf("%s must be formatted as key=value", pair) + } + out[kv[0]] = kv[1] + } + if !s.changed { + *s.value = out + } else { + for k, v := range out { + (*s.value)[k] = v + } + } + s.changed = true + return nil +} + +// Type returns type of value. +func (s *StringToStringValue) Type() string { + return "key=value" +} + +func (s *StringToStringValue) String() string { + var buf bytes.Buffer + i := 0 + for k, v := range *s.value { + if i > 0 { + buf.WriteString(s.separator) + } + buf.WriteString(k) + buf.WriteRune('=') + buf.WriteString(v) + i++ + } + return buf.String() +} diff --git a/utils/xpflag/string_to_string_test.go b/utils/xpflag/string_to_string_test.go new file mode 100644 index 000000000..ca088917d --- /dev/null +++ b/utils/xpflag/string_to_string_test.go @@ -0,0 +1,154 @@ +package xpflag + +import ( + "bytes" + "fmt" + "testing" + + "github.com/spf13/pflag" +) + +func setUpS2SFlagSet(s2sp *map[string]string) *pflag.FlagSet { + f := pflag.NewFlagSet("test", pflag.ContinueOnError) + f.Var(NewStringToStringValue(s2sp, nil), "s2s", "Command separated ls2st!") + return f +} +func setUpS2SFlagSetWithDefault(s2sp *map[string]string) *pflag.FlagSet { + f := pflag.NewFlagSet("test", pflag.ContinueOnError) + f.Var(NewStringToStringValue(s2sp, map[string]string{"a": "1", "b": "2"}), "s2s", "Command separated ls2st!") + return f +} +func createS2SFlag(vals map[string]string) string { + var buf bytes.Buffer + i := 0 + for k, v := range vals { + if i > 0 { + buf.WriteRune(',') + } + buf.WriteString(k) + buf.WriteRune('=') + buf.WriteString(v) + i++ + } + return buf.String() +} +func TestEmptyS2S(t *testing.T) { + var s2s map[string]string + f := setUpS2SFlagSet(&s2s) + err := f.Parse([]string{}) + if err != nil { + t.Fatal("expected no error; got", err) + } + s2sf := f.Lookup("s2s") + if f == nil { + t.Fatal("s2s flag not found") + } + getS2S, ok := s2sf.Value.(*StringToStringValue) + if !ok { + t.Fatal("s2s flag wrong value type") + } + if len(*getS2S.value) != 0 { + t.Fatalf("got s2s %v with len=%d but expected length=0", getS2S, len(*getS2S.value)) + } +} +func TestS2S(t *testing.T) { + var s2s map[string]string + f := setUpS2SFlagSet(&s2s) + vals := map[string]string{"a": "1", "b": "2", "d": "4", "c": "3"} + arg := fmt.Sprintf("--s2s=%s", createS2SFlag(vals)) + err := f.Parse([]string{arg}) + if err != nil { + t.Fatal("expected no error; got", err) + } + for k, v := range s2s { + if vals[k] != v { + t.Fatalf("expected s2s[%s] to be %s but got: %s", k, vals[k], v) + } + } + s2sf := f.Lookup("s2s") + if f == nil { + t.Fatal("s2s flag not found") + } + getS2S, ok := s2sf.Value.(*StringToStringValue) + if !ok { + t.Fatal("s2s flag wrong value type") + } + for k, v := range *getS2S.value { + if vals[k] != v { + t.Fatalf("expected s2s[%s] to be %s but got: %s", k, vals[k], v) + } + } +} +func TestS2SDefault(t *testing.T) { + var s2s map[string]string + f := setUpS2SFlagSetWithDefault(&s2s) + vals := map[string]string{"a": "1", "b": "2"} + err := f.Parse([]string{}) + if err != nil { + t.Fatal("expected no error; got", err) + } + for k, v := range s2s { + if vals[k] != v { + t.Fatalf("expected s2s[%s] to be %s but got: %s", k, vals[k], v) + } + } + s2sf := f.Lookup("s2s") + if f == nil { + t.Fatal("s2s flag not found") + } + getS2S, ok := s2sf.Value.(*StringToStringValue) + if !ok { + t.Fatal("s2s flag wrong value type") + } + for k, v := range *getS2S.value { + if vals[k] != v { + t.Fatalf("expected s2s[%s] to be %s but got: %s", k, vals[k], v) + } + } +} +func TestS2SWithDefault(t *testing.T) { + var s2s map[string]string + f := setUpS2SFlagSetWithDefault(&s2s) + vals := map[string]string{"a": "1", "b": "2"} + arg := fmt.Sprintf("--s2s=%s", createS2SFlag(vals)) + err := f.Parse([]string{arg}) + if err != nil { + t.Fatal("expected no error; got", err) + } + for k, v := range s2s { + if vals[k] != v { + t.Fatalf("expected s2s[%s] to be %s but got: %s", k, vals[k], v) + } + } + s2sf := f.Lookup("s2s") + if f == nil { + t.Fatal("s2s flag not found") + } + getS2S, ok := s2sf.Value.(*StringToStringValue) + if !ok { + t.Fatal("s2s flag wrong value type") + } + for k, v := range *getS2S.value { + if vals[k] != v { + t.Fatalf("expected s2s[%s] to be %s but got: %s", k, vals[k], v) + } + } +} +func TestS2SCalledTwice(t *testing.T) { + var s2s map[string]string + f := setUpS2SFlagSet(&s2s) + in := []string{"a=1,b=2", "b=3"} + expected := map[string]string{"a": "1", "b": "3"} + argfmt := "--s2s=%s" + arg1 := fmt.Sprintf(argfmt, in[0]) + arg2 := fmt.Sprintf(argfmt, in[1]) + err := f.Parse([]string{arg1, arg2}) + if err != nil { + t.Fatal("expected no error; got", err) + } + for i, v := range s2s { + if expected[i] != v { + t.Fatalf("expected s2s[%s] to be %s but got: %s", i, expected[i], v) + } + } +} From 2e57ad647d560d56fb436eeb9fdc786e7afa27ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=CC=87lker=20Go=CC=88ktug=CC=86=20O=CC=88ztu=CC=88rk?= Date: Thu, 9 Aug 2018 17:05:18 +0300 Subject: [PATCH 14/22] fix goroutine leaks on stream handlers of api package stream handlers now quits on a stream.Send() error or when the context is done. pubsub package is updated to support Unsubscriptions otherwise Publishes would get stuck while sending to channels that never listen. --- api/core/listen_event.go | 31 +++++++++++++++++++++---------- api/core/listen_result.go | 35 +++++++++++++++++++++++------------ api/service/listen_task.go | 31 +++++++++++++++++++++---------- pubsub/pubsub.go | 12 ++++++++++++ pubsub/pubsub_test.go | 10 ++++++++++ 5 files changed, 87 insertions(+), 32 deletions(-) diff --git a/api/core/listen_event.go b/api/core/listen_event.go index 79f248d9d..253da2c6a 100644 --- a/api/core/listen_event.go +++ b/api/core/listen_event.go @@ -20,18 +20,29 @@ func (s *Server) ListenEvent(request *ListenEventRequest, stream Core_ListenEven if err := validateEventKey(&service, request.EventFilter); err != nil { return err } - subscription := pubsub.Subscribe(service.EventSubscriptionChannel()) - for data := range subscription { - event := data.(*event.Event) - if isSubscribedEvent(request, event) { - eventData, _ := json.Marshal(event.Data) - stream.Send(&EventData{ - EventKey: event.Key, - EventData: string(eventData), - }) + + ctx := stream.Context() + channel := service.EventSubscriptionChannel() + subscription := pubsub.Subscribe(channel) + defer pubsub.Unsubscribe(channel, subscription) + + for { + select { + case <-ctx.Done(): + return ctx.Err() + case data := <-subscription: + event := data.(*event.Event) + if isSubscribedEvent(request, event) { + eventData, _ := json.Marshal(event.Data) + if err := stream.Send(&EventData{ + EventKey: event.Key, + EventData: string(eventData), + }); err != nil { + return err + } + } } } - return nil } func validateEventKey(service *service.Service, eventKey string) error { diff --git a/api/core/listen_result.go b/api/core/listen_result.go index 19da3f31f..c7defab7a 100644 --- a/api/core/listen_result.go +++ b/api/core/listen_result.go @@ -23,20 +23,31 @@ func (s *Server) ListenResult(request *ListenResultRequest, stream Core_ListenRe if err := validateOutputKey(&service, request.TaskFilter, request.OutputFilter); err != nil { return err } - subscription := pubsub.Subscribe(service.ResultSubscriptionChannel()) - for data := range subscription { - execution := data.(*execution.Execution) - if isSubscribedTask(request, execution) && isSubscribedOutput(request, execution) { - outputs, _ := json.Marshal(execution.OutputData) - stream.Send(&ResultData{ - ExecutionID: execution.ID, - TaskKey: execution.Task, - OutputKey: execution.Output, - OutputData: string(outputs), - }) + + ctx := stream.Context() + channel := service.ResultSubscriptionChannel() + subscription := pubsub.Subscribe(channel) + defer pubsub.Unsubscribe(channel, subscription) + + for { + select { + case <-ctx.Done(): + return ctx.Err() + case data := <-subscription: + execution := data.(*execution.Execution) + if isSubscribedTask(request, execution) && isSubscribedOutput(request, execution) { + outputs, _ := json.Marshal(execution.OutputData) + if err := stream.Send(&ResultData{ + ExecutionID: execution.ID, + TaskKey: execution.Task, + OutputKey: execution.Output, + OutputData: string(outputs), + }); err != nil { + return err + } + } } } - return nil } func validateTaskKey(service *service.Service, taskKey string) error { diff --git a/api/service/listen_task.go b/api/service/listen_task.go index 4143aad78..62d49d484 100644 --- a/api/service/listen_task.go +++ b/api/service/listen_task.go @@ -14,15 +14,26 @@ func (s *Server) ListenTask(request *ListenTaskRequest, stream Service_ListenTas if err != nil { return err } - subscription := pubsub.Subscribe(service.TaskSubscriptionChannel()) - for data := range subscription { - execution := data.(*execution.Execution) - inputs, _ := json.Marshal(execution.Inputs) - stream.Send(&TaskData{ - ExecutionID: execution.ID, - TaskKey: execution.Task, - InputData: string(inputs), - }) + + ctx := stream.Context() + channel := service.TaskSubscriptionChannel() + subscription := pubsub.Subscribe(channel) + defer pubsub.Unsubscribe(channel, subscription) + + for { + select { + case <-ctx.Done(): + return ctx.Err() + case data := <-subscription: + execution := data.(*execution.Execution) + inputs, _ := json.Marshal(execution.Inputs) + if err := stream.Send(&TaskData{ + ExecutionID: execution.ID, + TaskKey: execution.Task, + InputData: string(inputs), + }); err != nil { + return err + } + } } - return nil } diff --git a/pubsub/pubsub.go b/pubsub/pubsub.go index 12e3ed112..a353c7a6d 100644 --- a/pubsub/pubsub.go +++ b/pubsub/pubsub.go @@ -34,3 +34,15 @@ func Subscribe(channel string) chan Message { mu.Unlock() return listener } + +// Unsubscribe unsubscribes a subscription for listening channel. +func Unsubscribe(channel string, subscription chan Message) { + mu.Lock() + defer mu.Unlock() + for i, s := range listeners[channel] { + if s == subscription { + listeners[channel] = append(listeners[channel][:i], listeners[channel][i+1:]...) + return + } + } +} diff --git a/pubsub/pubsub_test.go b/pubsub/pubsub_test.go index bc568d004..75b0c1cbb 100644 --- a/pubsub/pubsub_test.go +++ b/pubsub/pubsub_test.go @@ -45,3 +45,13 @@ func TestSubscribeMultipleTimes(t *testing.T) { Subscribe(key) assert.Equal(t, len(listeners[key]), 2) } + +func TestUnsubscribe(t *testing.T) { + key := "TestUnsubscribe" + channel := Subscribe(key) + channel1 := Subscribe(key) + Unsubscribe(key, channel) + assert.Equal(t, len(listeners[key]), 1) + Unsubscribe(key, channel1) + assert.Equal(t, len(listeners[key]), 0) +} From 1baa37cb95fecbb89027ed89e8d5c3790bb4940d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=CC=87lker=20Go=CC=88ktug=CC=86=20O=CC=88ztu=CC=88rk?= Date: Mon, 13 Aug 2018 08:33:15 +0300 Subject: [PATCH 15/22] optimizations and small refactor on pubsub package --- CHANGELOG.md | 1 + pubsub/pubsub.go | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cfce00ed..6cb3f5bf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - (#303) Deprecate command `service test` in favor of `service dev` and `service execute` #### Fixed +- (#358) Fix gorutinue leaks on api package handlers where gRPC streams are used. Handlers were blocking forever because of not respecting to context cancellation and stream.Send() errors. ## [v1.0.0] diff --git a/pubsub/pubsub.go b/pubsub/pubsub.go index a353c7a6d..4276762bd 100644 --- a/pubsub/pubsub.go +++ b/pubsub/pubsub.go @@ -15,32 +15,34 @@ type Message interface{} // Publish publishes a message to a channel. func Publish(channel string, data Message) { mu.Lock() + defer mu.Unlock() for _, listener := range listeners[channel] { - if listener != nil { - listener <- data - } + listener <- data } - mu.Unlock() } // Subscribe subscribes to the channel and returns listener for it. func Subscribe(channel string) chan Message { - listener := make(chan Message) mu.Lock() + defer mu.Unlock() + listener := make(chan Message) if listeners[channel] == nil { listeners[channel] = make([]chan Message, 0) } listeners[channel] = append(listeners[channel], listener) - mu.Unlock() return listener } -// Unsubscribe unsubscribes a subscription for listening channel. -func Unsubscribe(channel string, subscription chan Message) { +// Unsubscribe unsubscribes a listener from listening channel. +func Unsubscribe(channel string, listener chan Message) { mu.Lock() defer mu.Unlock() - for i, s := range listeners[channel] { - if s == subscription { + if len(listeners[channel]) == 1 { + listeners[channel] = nil + return + } + for i, l := range listeners[channel] { + if l == listener { listeners[channel] = append(listeners[channel][:i], listeners[channel][i+1:]...) return } From b7875dec1e1c3ca4a949c35725e4777061210a59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=CC=87lker=20Go=CC=88ktug=CC=86=20O=CC=88ztu=CC=88rk?= Date: Mon, 13 Aug 2018 09:24:47 +0300 Subject: [PATCH 16/22] api/core: fix codeclimate issue: return statements exceeds 4 allowed --- api/core/listen_result.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/api/core/listen_result.go b/api/core/listen_result.go index c7defab7a..a6cac8b00 100644 --- a/api/core/listen_result.go +++ b/api/core/listen_result.go @@ -17,10 +17,7 @@ func (s *Server) ListenResult(request *ListenResultRequest, stream Core_ListenRe if err != nil { return err } - if err := validateTaskKey(&service, request.TaskFilter); err != nil { - return err - } - if err := validateOutputKey(&service, request.TaskFilter, request.OutputFilter); err != nil { + if err := validateTask(&service, request); err != nil { return err } @@ -50,6 +47,13 @@ func (s *Server) ListenResult(request *ListenResultRequest, stream Core_ListenRe } } +func validateTask(service *service.Service, request *ListenResultRequest) error { + if err := validateTaskKey(service, request.TaskFilter); err != nil { + return err + } + return validateOutputKey(service, request.TaskFilter, request.OutputFilter) +} + func validateTaskKey(service *service.Service, taskKey string) error { if taskKey == "" || taskKey == "*" { return nil From 22d83a40687ddcc456c52acbb75f7c318964bf97 Mon Sep 17 00:00:00 2001 From: Anthony Date: Mon, 13 Aug 2018 19:04:48 +1000 Subject: [PATCH 17/22] Return an error when trying to execute a task on a non running service (#317) * refactor execution api and check for service status * fix errors in test * update changelog * Add min arg requirement to service stop command * comment end of line * Code cleanup - direct return * Fix - check service first, then get the data * check service status after getting data --- CHANGELOG.md | 1 + api/core/error.go | 10 ++++ api/core/error_test.go | 12 ++++ api/core/execute.go | 42 +++++++++++--- api/core/execute_test.go | 118 ++++++++++++++++++++++++++++++++++----- cmd/service/stop.go | 1 + 6 files changed, 162 insertions(+), 22 deletions(-) create mode 100644 api/core/error.go create mode 100644 api/core/error_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cfce00ed..bd2e72033 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - (#303) Add command `service dev` that build and run the service with the logs - (#303) Add command `service execute` that execute a task on a service - (#316) Delete service when stoping the `service dev` command to avoid to keep all the versions of the services. +- (#317) Add errors when trying to execute a service that is not running (nothing was happening before) - (#344) Add `service execute --data` flag to pass arguments as key=value. #### Removed diff --git a/api/core/error.go b/api/core/error.go new file mode 100644 index 000000000..d4124909d --- /dev/null +++ b/api/core/error.go @@ -0,0 +1,10 @@ +package core + +// NotRunningServiceError is an error when a service is not running. +type NotRunningServiceError struct { + ServiceID string +} + +func (e *NotRunningServiceError) Error() string { + return "Service " + e.ServiceID + " is not running" +} diff --git a/api/core/error_test.go b/api/core/error_test.go new file mode 100644 index 000000000..468e14a9c --- /dev/null +++ b/api/core/error_test.go @@ -0,0 +1,12 @@ +package core + +import ( + "testing" + + "github.com/stvp/assert" +) + +func TestNotRunningServiceError(t *testing.T) { + e := NotRunningServiceError{ServiceID: "test"} + assert.Equal(t, "Service test is not running", e.Error()) +} diff --git a/api/core/execute.go b/api/core/execute.go index 7cf0c63d8..f92c0f253 100644 --- a/api/core/execute.go +++ b/api/core/execute.go @@ -6,25 +6,49 @@ import ( "github.com/mesg-foundation/core/database/services" "github.com/mesg-foundation/core/execution" + "github.com/mesg-foundation/core/service" ) // ExecuteTask executes a task for a given service. func (s *Server) ExecuteTask(ctx context.Context, request *ExecuteTaskRequest) (*ExecuteTaskReply, error) { - service, err := services.Get(request.ServiceID) + srv, err := services.Get(request.ServiceID) if err != nil { return nil, err } - - var inputs map[string]interface{} - if err := json.Unmarshal([]byte(request.InputData), &inputs); err != nil { + inputs, err := getData(request) + if err != nil { return nil, err } - execution, err := execution.Create(&service, request.TaskKey, inputs) - if err != nil { + if err := checkServiceStatus(&srv); err != nil { return nil, err } - + executionID, err := execute(&srv, request.TaskKey, inputs) return &ExecuteTaskReply{ - ExecutionID: execution.ID, - }, execution.Execute() + ExecutionID: executionID, + }, err +} + +func checkServiceStatus(srv *service.Service) error { + status, err := srv.Status() + if err != nil { + return err + } + if status != service.RUNNING { + return &NotRunningServiceError{ServiceID: srv.Hash()} + } + return nil +} + +func getData(request *ExecuteTaskRequest) (map[string]interface{}, error) { + var inputs map[string]interface{} + err := json.Unmarshal([]byte(request.InputData), &inputs) + return inputs, err +} + +func execute(srv *service.Service, key string, inputs map[string]interface{}) (executionID string, err error) { + exc, err := execution.Create(srv, key, inputs) + if err != nil { + return "", err + } + return exc.ID, exc.Execute() } diff --git a/api/core/execute_test.go b/api/core/execute_test.go index 9b2c399b8..a2f1fdfd4 100644 --- a/api/core/execute_test.go +++ b/api/core/execute_test.go @@ -12,14 +12,23 @@ import ( var serverexecute = new(Server) func TestExecute(t *testing.T) { - deployment, _ := serverexecute.DeployService(context.Background(), &DeployServiceRequest{ - Service: &service.Service{ - Name: "TestExecute", - Tasks: map[string]*service.Task{ - "test": {}, + srv := service.Service{ + Name: "TestExecute", + Tasks: map[string]*service.Task{ + "test": &service.Task{}, + }, + Dependencies: map[string]*service.Dependency{ + "test": { + Image: "nginx", }, }, + } + deployment, _ := serverexecute.DeployService(context.Background(), &DeployServiceRequest{ + Service: &srv, }) + defer services.Delete(deployment.ServiceID) + srv.Start() + defer srv.Stop() reply, err := serverexecute.ExecuteTask(context.Background(), &ExecuteTaskRequest{ ServiceID: deployment.ServiceID, TaskKey: "test", @@ -28,7 +37,6 @@ func TestExecute(t *testing.T) { assert.Nil(t, err) assert.NotNil(t, reply) - services.Delete(deployment.ServiceID) } func TestExecuteWithInvalidJSON(t *testing.T) { @@ -45,21 +53,29 @@ func TestExecuteWithInvalidJSON(t *testing.T) { TaskKey: "test", InputData: "", }) - assert.NotNil(t, err) assert.Equal(t, err.Error(), "unexpected end of JSON input") services.Delete(deployment.ServiceID) } func TestExecuteWithInvalidTask(t *testing.T) { - deployment, _ := serverexecute.DeployService(context.Background(), &DeployServiceRequest{ - Service: &service.Service{ - Name: "TestExecuteWithInvalidJSON", - Tasks: map[string]*service.Task{ - "test": {}, + srv := service.Service{ + Name: "TestExecuteWithInvalidTask", + Tasks: map[string]*service.Task{ + "test": {}, + }, + Dependencies: map[string]*service.Dependency{ + "test": { + Image: "nginx", }, }, + } + deployment, _ := serverexecute.DeployService(context.Background(), &DeployServiceRequest{ + Service: &srv, }) + defer services.Delete(deployment.ServiceID) + srv.Start() + defer srv.Stop() _, err := serverexecute.ExecuteTask(context.Background(), &ExecuteTaskRequest{ ServiceID: deployment.ServiceID, TaskKey: "error", @@ -69,7 +85,28 @@ func TestExecuteWithInvalidTask(t *testing.T) { assert.NotNil(t, err) _, invalid := err.(*service.TaskNotFoundError) assert.True(t, invalid) - services.Delete(deployment.ServiceID) +} + +func TestExecuteWithNonRunningService(t *testing.T) { + srv := service.Service{ + Name: "TestExecuteWithNonRunningService", + Tasks: map[string]*service.Task{ + "test": &service.Task{}, + }, + } + deployment, _ := serverexecute.DeployService(context.Background(), &DeployServiceRequest{ + Service: &srv, + }) + defer services.Delete(deployment.ServiceID) + _, err := serverexecute.ExecuteTask(context.Background(), &ExecuteTaskRequest{ + ServiceID: deployment.ServiceID, + TaskKey: "test", + InputData: "{}", + }) + + assert.NotNil(t, err) + _, nonRunning := err.(*NotRunningServiceError) + assert.True(t, nonRunning) } func TestExecuteWithNonExistingService(t *testing.T) { @@ -81,3 +118,58 @@ func TestExecuteWithNonExistingService(t *testing.T) { assert.NotNil(t, err) } + +func TestExecuteFunc(t *testing.T) { + srv := &service.Service{ + Name: "TestExecuteFunc", + Tasks: map[string]*service.Task{ + "test": {}, + }, + } + id, err := execute(srv, "test", map[string]interface{}{}) + assert.Nil(t, err) + assert.NotNil(t, id) +} + +func TestExecuteFuncInvalidTaskName(t *testing.T) { + srv := &service.Service{} + _, err := execute(srv, "test", map[string]interface{}{}) + assert.NotNil(t, err) +} + +func TestGetData(t *testing.T) { + inputs, err := getData(&ExecuteTaskRequest{ + InputData: "{\"foo\":\"bar\"}", + }) + assert.Nil(t, err) + assert.Equal(t, "bar", inputs["foo"]) +} + +func TestGetDataInvalid(t *testing.T) { + _, err := getData(&ExecuteTaskRequest{ + InputData: "", + }) + assert.NotNil(t, err) +} + +func TestCheckServiceNotRunning(t *testing.T) { + err := checkServiceStatus(&service.Service{Name: "TestCheckServiceNotRunning"}) + assert.NotNil(t, err) + _, notRunningError := err.(*NotRunningServiceError) + assert.True(t, notRunningError) +} + +func TestCheckService(t *testing.T) { + srv := service.Service{ + Name: "TestCheckService", + Dependencies: map[string]*service.Dependency{ + "test": { + Image: "nginx", + }, + }, + } + srv.Start() + defer srv.Stop() + err := checkServiceStatus(&srv) + assert.Nil(t, err) +} diff --git a/cmd/service/stop.go b/cmd/service/stop.go index 0c15c9ae1..187fbe71d 100644 --- a/cmd/service/stop.go +++ b/cmd/service/stop.go @@ -22,6 +22,7 @@ To have more explanation, see the page [stake explanation from the documentation Example: `mesg-core service stop SERVICE_ID`, Run: stopHandler, DisableAutoGenTag: true, + Args: cobra.MinimumNArgs(1), } func stopHandler(cmd *cobra.Command, args []string) { From ebe88c0f7ab8b45eb93e4a625d2f8b2b9af27efc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=CC=87lker=20Go=CC=88ktug=CC=86=20O=CC=88ztu=CC=88rk?= Date: Mon, 13 Aug 2018 12:29:06 +0300 Subject: [PATCH 18/22] fix typo on CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cb3f5bf7..7fed56bb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ - (#303) Deprecate command `service test` in favor of `service dev` and `service execute` #### Fixed -- (#358) Fix gorutinue leaks on api package handlers where gRPC streams are used. Handlers were blocking forever because of not respecting to context cancellation and stream.Send() errors. +- (#358) Fix goroutine leaks on api package handlers where gRPC streams are used. Handlers now doesn't block forever by exiting on context cancellation and stream.Send() errors. ## [v1.0.0] From 0ff23cf04a764c4aa715730b3c6331b9512eeea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lker=20G=C3=B6ktu=C4=9F=20=C3=96zt=C3=BCrk?= Date: Mon, 13 Aug 2018 12:46:09 +0300 Subject: [PATCH 19/22] container: remove timeouts for long-lived Docker API calls, fixes #360 (#361) --- container/build.go | 4 +--- container/service.go | 4 +--- container/shared_network_test.go | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/container/build.go b/container/build.go index c64d3f464..f992dca6c 100644 --- a/container/build.go +++ b/container/build.go @@ -31,9 +31,7 @@ func (c *Container) Build(path string) (tag string, err error) { return "", err } defer buildContext.Close() - ctx, cancel := context.WithTimeout(context.Background(), c.callTimeout) - defer cancel() - response, err := c.client.ImageBuild(ctx, buildContext, types.ImageBuildOptions{ + response, err := c.client.ImageBuild(context.Background(), buildContext, types.ImageBuildOptions{ Remove: true, ForceRemove: true, SuppressOutput: true, diff --git a/container/service.go b/container/service.go index 9029fc47d..ab2b07326 100644 --- a/container/service.go +++ b/container/service.go @@ -72,9 +72,7 @@ func (c *Container) ServiceStatus(namespace []string) (StatusType, error) { // ServiceLogs returns the logs of a service. func (c *Container) ServiceLogs(namespace []string) (io.ReadCloser, error) { - ctx, cancel := context.WithTimeout(context.Background(), c.callTimeout) - defer cancel() - return c.client.ServiceLogs(ctx, Namespace(namespace), + return c.client.ServiceLogs(context.Background(), Namespace(namespace), types.ContainerLogsOptions{ ShowStdout: true, ShowStderr: true, diff --git a/container/shared_network_test.go b/container/shared_network_test.go index a7e7b09ae..bc763fad4 100644 --- a/container/shared_network_test.go +++ b/container/shared_network_test.go @@ -73,7 +73,7 @@ func TestCreateSharedNetworkIfNeededExists(t *testing.T) { } } -func TestIntegrationSharedNetworkID(t *testing.T) { +func TestSharedNetworkID(t *testing.T) { id := "1" dt := dockertest.New() c, _ := New(ClientOption(dt.Client())) From f5d399608807ff8f67eb17f8adfa1d6072e12930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=CC=87lker=20Go=CC=88ktug=CC=86=20O=CC=88ztu=CC=88rk?= Date: Tue, 14 Aug 2018 07:24:10 +0300 Subject: [PATCH 20/22] pubsub: fix Unsubscribe() removes last listener without comparing it first --- pubsub/pubsub.go | 7 +++---- pubsub/pubsub_test.go | 2 ++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pubsub/pubsub.go b/pubsub/pubsub.go index 4276762bd..30dcb96f2 100644 --- a/pubsub/pubsub.go +++ b/pubsub/pubsub.go @@ -37,13 +37,12 @@ func Subscribe(channel string) chan Message { func Unsubscribe(channel string, listener chan Message) { mu.Lock() defer mu.Unlock() - if len(listeners[channel]) == 1 { - listeners[channel] = nil - return - } for i, l := range listeners[channel] { if l == listener { listeners[channel] = append(listeners[channel][:i], listeners[channel][i+1:]...) + if len(listeners[channel]) == 0 { + listeners[channel] = nil + } return } } diff --git a/pubsub/pubsub_test.go b/pubsub/pubsub_test.go index 75b0c1cbb..a3d51bb3b 100644 --- a/pubsub/pubsub_test.go +++ b/pubsub/pubsub_test.go @@ -52,6 +52,8 @@ func TestUnsubscribe(t *testing.T) { channel1 := Subscribe(key) Unsubscribe(key, channel) assert.Equal(t, len(listeners[key]), 1) + assert.NotNil(t, listeners[key]) Unsubscribe(key, channel1) assert.Equal(t, len(listeners[key]), 0) + assert.Nil(t, listeners[key]) } From 19b385f384908d75d47be02ae35205257dc3eb17 Mon Sep 17 00:00:00 2001 From: krhubert Date: Wed, 15 Aug 2018 11:28:59 +0200 Subject: [PATCH 21/22] Change testing pkg in favor of github.com/stretchr/testify (#356) * Use github.com/stretchr/testify * Change require.Contains args order * Update CHANGELOG * Fix pubsub tests --- CHANGELOG.md | 1 + api/client/client_test.go | 12 +-- api/client/service_test.go | 22 ++-- api/client/task_test.go | 18 ++-- api/client/workflow_test.go | 34 +++---- api/core/delete_test.go | 8 +- api/core/deploy_test.go | 8 +- api/core/execute_test.go | 21 ++-- api/core/get_service_test.go | 8 +- api/core/list_services_test.go | 6 +- api/core/listen_event_test.go | 20 ++-- api/core/listen_result_test.go | 46 ++++----- api/core/start_test.go | 8 +- api/core/stop_test.go | 8 +- api/server_test.go | 8 +- api/service/emit_event_test.go | 14 +-- api/service/error_test.go | 4 +- api/service/submit_result_test.go | 14 +-- cmd/service/execute_test.go | 14 +-- cmd/service/init_test.go | 28 ++--- cmd/service/list_test.go | 18 ++-- cmd/service/utils_test.go | 58 +++++------ cmd/utils/error_test.go | 24 ++--- config/api_test.go | 6 +- config/config_test.go | 4 +- config/directory_test.go | 8 +- container/build_integration_test.go | 18 ++-- container/build_test.go | 26 ++--- container/client_test.go | 8 +- container/container_integration_test.go | 38 +++---- container/container_test.go | 42 ++++---- container/dockertest/error_test.go | 6 +- container/dockertest/testing_test.go | 102 +++++++++---------- container/namespace_test.go | 6 +- container/network_integration_test.go | 36 +++---- container/network_test.go | 40 ++++---- container/service_integration_test.go | 80 +++++++-------- container/service_options_test.go | 56 +++++----- container/service_test.go | 74 +++++++------- container/shared_network_integration_test.go | 20 ++-- container/shared_network_test.go | 26 ++--- container/task_integration_test.go | 20 ++-- container/task_test.go | 20 ++-- container/wait_integration_test.go | 16 +-- container/wait_test.go | 8 +- daemon/logs_test.go | 6 +- daemon/start_test.go | 26 ++--- daemon/status_test.go | 10 +- daemon/stop_test.go | 4 +- database/services/all_test.go | 6 +- database/services/db_test.go | 10 +- database/services/delete_test.go | 4 +- database/services/get_test.go | 10 +- database/services/save_test.go | 8 +- event/event_test.go | 20 ++-- execution/complete_test.go | 28 ++--- execution/create_test.go | 24 ++--- execution/error_test.go | 4 +- execution/execute_test.go | 6 +- execution/state_test.go | 28 ++--- pubsub/pubsub_test.go | 20 ++-- service/cast_test.go | 10 +- service/dependency_test.go | 10 +- service/error_test.go | 16 +-- service/hash_test.go | 6 +- service/importer/docker_file_test.go | 10 +- service/importer/import_test.go | 16 +-- service/importer/service_file_test.go | 32 +++--- service/importer/validation_result_test.go | 10 +- service/importer/validation_test.go | 60 +++++------ service/logs_test.go | 10 +- service/namespace_test.go | 12 +-- service/start_test.go | 58 +++++------ service/status_test.go | 38 +++---- service/stop_test.go | 16 +-- service/validation_test.go | 40 ++++---- utils/array/include_test.go | 18 ++-- 77 files changed, 819 insertions(+), 819 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a21cf6dbe..a52e37b7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ #### Changed - (#282) Branch support added. You can now specify your branches with a `#branch` fragment at the end of your git url. E.g.: https://github.com/mesg-foundation/service-ethereum-erc20#websocket - (#299) Add more user friendly errors when failing to connect to the Core or Docker +- (#356) Use github.com/stretchr/testify package #### Added - (#242) Add more details in command `mesg-core service validate` diff --git a/api/client/client_test.go b/api/client/client_test.go index fda88b283..b23c0a424 100644 --- a/api/client/client_test.go +++ b/api/client/client_test.go @@ -3,18 +3,18 @@ package client import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestAPI(t *testing.T) { api, err := API() - assert.Nil(t, err) - assert.NotNil(t, api) + require.Nil(t, err) + require.NotNil(t, api) } func TestGetClient(t *testing.T) { c, err := getClient() - assert.Nil(t, err) - assert.NotNil(t, c) - assert.NotNil(t, _client) + require.Nil(t, err) + require.NotNil(t, c) + require.NotNil(t, _client) } diff --git a/api/client/service_test.go b/api/client/service_test.go index 103613a64..166776608 100644 --- a/api/client/service_test.go +++ b/api/client/service_test.go @@ -4,7 +4,7 @@ import ( "errors" "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestServices(t *testing.T) { @@ -14,10 +14,10 @@ func TestServices(t *testing.T) { Execute: &Task{ServiceID: "zzz"}, } services := wf.services() - assert.Equal(t, len(services), 3) - assert.Equal(t, services[0], "xxx") - assert.Equal(t, services[1], "yyy") - assert.Equal(t, services[2], "zzz") + require.Equal(t, len(services), 3) + require.Equal(t, services[0], "xxx") + require.Equal(t, services[1], "yyy") + require.Equal(t, services[2], "zzz") } func TestServicesDuplicate(t *testing.T) { @@ -27,9 +27,9 @@ func TestServicesDuplicate(t *testing.T) { Execute: &Task{ServiceID: "xxx"}, } services := wf.services() - assert.Equal(t, len(services), 2) - assert.Equal(t, services[0], "xxx") - assert.Equal(t, services[1], "yyy") + require.Equal(t, len(services), 2) + require.Equal(t, services[0], "xxx") + require.Equal(t, services[1], "yyy") } func TestIterateService(t *testing.T) { @@ -43,8 +43,8 @@ func TestIterateService(t *testing.T) { cpt++ return nil }) - assert.Nil(t, err) - assert.Equal(t, cpt, 3) + require.Nil(t, err) + require.Equal(t, cpt, 3) } func TestIterateServiceWithError(t *testing.T) { @@ -56,5 +56,5 @@ func TestIterateServiceWithError(t *testing.T) { err := iterateService(wf, func(ID string) error { return errors.New("test error") }) - assert.NotNil(t, err) + require.NotNil(t, err) } diff --git a/api/client/task_test.go b/api/client/task_test.go index 905eb8884..33018bdd0 100644 --- a/api/client/task_test.go +++ b/api/client/task_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/mesg-foundation/core/api/core" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestProcessEventWithInvalidEventData(t *testing.T) { @@ -19,7 +19,7 @@ func TestProcessEventWithInvalidEventData(t *testing.T) { EventData: "", } err := wf.Execute.processEvent(wf, data) - assert.Equal(t, err.Error(), "unexpected end of JSON input") + require.Equal(t, err.Error(), "unexpected end of JSON input") } func TestProcessResulsWithInvalidEventData(t *testing.T) { @@ -36,7 +36,7 @@ func TestProcessResulsWithInvalidEventData(t *testing.T) { TaskKey: "taskx", } err := wf.Execute.processResult(wf, data) - assert.Equal(t, err.Error(), "unexpected end of JSON input") + require.Equal(t, err.Error(), "unexpected end of JSON input") } func TestConvertData(t *testing.T) { @@ -46,8 +46,8 @@ func TestConvertData(t *testing.T) { }, } res, err := task.convertData("foo") - assert.Nil(t, err) - assert.Equal(t, res, "\"bar\"") + require.Nil(t, err) + require.Equal(t, res, "\"bar\"") } func TestConvertDataObject(t *testing.T) { @@ -60,8 +60,8 @@ func TestConvertDataObject(t *testing.T) { "foo": "bar", "number": 42, }) - assert.Nil(t, err) - assert.Equal(t, res, "{\"foo\":\"bar\",\"number\":42}") + require.Nil(t, err) + require.Equal(t, res, "{\"foo\":\"bar\",\"number\":42}") } func TestConvertDataWithNull(t *testing.T) { @@ -71,6 +71,6 @@ func TestConvertDataWithNull(t *testing.T) { }, } res, err := task.convertData("xxx") - assert.Nil(t, err) - assert.Equal(t, res, "null") + require.Nil(t, err) + require.Equal(t, res, "null") } diff --git a/api/client/workflow_test.go b/api/client/workflow_test.go index 0914a8809..ae999f98a 100644 --- a/api/client/workflow_test.go +++ b/api/client/workflow_test.go @@ -4,79 +4,79 @@ import ( "testing" "github.com/mesg-foundation/core/api/core" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestValidEventFromAny(t *testing.T) { wf := &Workflow{ OnEvent: &Event{Name: "*"}, } - assert.True(t, wf.validEvent(&core.EventData{EventKey: "xxx"})) + require.True(t, wf.validEvent(&core.EventData{EventKey: "xxx"})) } func TestValidEventFromValue(t *testing.T) { wf := &Workflow{ OnEvent: &Event{Name: "xxx"}, } - assert.True(t, wf.validEvent(&core.EventData{EventKey: "xxx"})) - assert.False(t, wf.validEvent(&core.EventData{EventKey: "yyy"})) + require.True(t, wf.validEvent(&core.EventData{EventKey: "xxx"})) + require.False(t, wf.validEvent(&core.EventData{EventKey: "yyy"})) } func TestValidResultFromAnyNameAndAnyOutput(t *testing.T) { wf := &Workflow{ OnResult: &Result{Name: "*", Output: "*"}, } - assert.True(t, wf.validResult(&core.ResultData{TaskKey: "xxx", OutputKey: "xxx"})) + require.True(t, wf.validResult(&core.ResultData{TaskKey: "xxx", OutputKey: "xxx"})) } func TestValidResultFromAnyNameAndNotAnyOutput(t *testing.T) { wf := &Workflow{ OnResult: &Result{Name: "*", Output: "xxx"}, } - assert.True(t, wf.validResult(&core.ResultData{TaskKey: "xxx", OutputKey: "xxx"})) - assert.False(t, wf.validResult(&core.ResultData{TaskKey: "yyy", OutputKey: "yyy"})) + require.True(t, wf.validResult(&core.ResultData{TaskKey: "xxx", OutputKey: "xxx"})) + require.False(t, wf.validResult(&core.ResultData{TaskKey: "yyy", OutputKey: "yyy"})) } func TestValidResultFromNotAnyNameAndAnyOutput(t *testing.T) { wf := &Workflow{ OnResult: &Result{Name: "xxx", Output: "*"}, } - assert.True(t, wf.validResult(&core.ResultData{TaskKey: "xxx", OutputKey: "xxx"})) - assert.False(t, wf.validResult(&core.ResultData{TaskKey: "yyy", OutputKey: "yyy"})) + require.True(t, wf.validResult(&core.ResultData{TaskKey: "xxx", OutputKey: "xxx"})) + require.False(t, wf.validResult(&core.ResultData{TaskKey: "yyy", OutputKey: "yyy"})) } func TestValidResultFromNotAnyNameAndNotAnyOutput(t *testing.T) { wf := &Workflow{ OnResult: &Result{Name: "xxx", Output: "yyy"}, } - assert.True(t, wf.validResult(&core.ResultData{TaskKey: "xxx", OutputKey: "yyy"})) - assert.False(t, wf.validResult(&core.ResultData{TaskKey: "yyy", OutputKey: "yyy"})) - assert.False(t, wf.validResult(&core.ResultData{TaskKey: "xxx", OutputKey: "xxx"})) - assert.False(t, wf.validResult(&core.ResultData{TaskKey: "yyy", OutputKey: "xxx"})) + require.True(t, wf.validResult(&core.ResultData{TaskKey: "xxx", OutputKey: "yyy"})) + require.False(t, wf.validResult(&core.ResultData{TaskKey: "yyy", OutputKey: "yyy"})) + require.False(t, wf.validResult(&core.ResultData{TaskKey: "xxx", OutputKey: "xxx"})) + require.False(t, wf.validResult(&core.ResultData{TaskKey: "yyy", OutputKey: "xxx"})) } func TestInvalidListenResult(t *testing.T) { wf := &Workflow{ OnResult: &Result{}, } - assert.NotNil(t, listenResults(wf)) + require.NotNil(t, listenResults(wf)) } func TestInvalidListenEvent(t *testing.T) { wf := &Workflow{ OnEvent: &Event{}, } - assert.NotNil(t, listenEvents(wf)) + require.NotNil(t, listenEvents(wf)) } func TestInvalidWorkflowWithNoExecute(t *testing.T) { wf := Workflow{OnEvent: &Event{}} err := wf.Start() - assert.Equal(t, err.Error(), "A workflow needs a task") + require.Equal(t, err.Error(), "A workflow needs a task") } func TestInvalidWorkflowWithNoEvent(t *testing.T) { wf := Workflow{Execute: &Task{}} err := wf.Start() - assert.Equal(t, err.Error(), "A workflow needs an event OnEvent or OnResult") + require.Equal(t, err.Error(), "A workflow needs an event OnEvent or OnResult") } diff --git a/api/core/delete_test.go b/api/core/delete_test.go index ddf9c19e3..790f1b25f 100644 --- a/api/core/delete_test.go +++ b/api/core/delete_test.go @@ -6,7 +6,7 @@ import ( "github.com/mesg-foundation/core/database/services" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) var serverdelete = new(Server) @@ -27,8 +27,8 @@ func TestDeleteService(t *testing.T) { reply, err := serverdelete.DeleteService(context.Background(), &DeleteServiceRequest{ ServiceID: deployment.ServiceID, }) - assert.Nil(t, err) - assert.NotNil(t, reply) + require.Nil(t, err) + require.NotNil(t, reply) x, _ := services.Get(deployment.ServiceID) - assert.Equal(t, x, emptyService) + require.Equal(t, x, emptyService) } diff --git a/api/core/deploy_test.go b/api/core/deploy_test.go index aa7403918..802c23d4d 100644 --- a/api/core/deploy_test.go +++ b/api/core/deploy_test.go @@ -6,7 +6,7 @@ import ( "github.com/mesg-foundation/core/database/services" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) var serverdeploy = new(Server) @@ -23,8 +23,8 @@ func TestDeployService(t *testing.T) { deployment, err := serverdeploy.DeployService(context.Background(), &DeployServiceRequest{ Service: &service, }) - assert.Nil(t, err) - assert.NotNil(t, deployment) - assert.NotEqual(t, "", deployment.ServiceID) + require.Nil(t, err) + require.NotNil(t, deployment) + require.NotEqual(t, "", deployment.ServiceID) services.Delete(deployment.ServiceID) } diff --git a/api/core/execute_test.go b/api/core/execute_test.go index a2f1fdfd4..27e0ed69d 100644 --- a/api/core/execute_test.go +++ b/api/core/execute_test.go @@ -6,6 +6,7 @@ import ( "github.com/mesg-foundation/core/database/services" "github.com/mesg-foundation/core/service" + "github.com/stretchr/testify/require" "github.com/stvp/assert" ) @@ -35,8 +36,8 @@ func TestExecute(t *testing.T) { InputData: "{}", }) - assert.Nil(t, err) - assert.NotNil(t, reply) + require.Nil(t, err) + require.NotNil(t, reply) } func TestExecuteWithInvalidJSON(t *testing.T) { @@ -53,8 +54,9 @@ func TestExecuteWithInvalidJSON(t *testing.T) { TaskKey: "test", InputData: "", }) - assert.NotNil(t, err) - assert.Equal(t, err.Error(), "unexpected end of JSON input") + + require.NotNil(t, err) + require.Equal(t, err.Error(), "unexpected end of JSON input") services.Delete(deployment.ServiceID) } @@ -82,9 +84,8 @@ func TestExecuteWithInvalidTask(t *testing.T) { InputData: "{}", }) - assert.NotNil(t, err) - _, invalid := err.(*service.TaskNotFoundError) - assert.True(t, invalid) + require.Error(t, err) + require.IsType(t, (*service.TaskNotFoundError)(nil), err) } func TestExecuteWithNonRunningService(t *testing.T) { @@ -104,9 +105,9 @@ func TestExecuteWithNonRunningService(t *testing.T) { InputData: "{}", }) - assert.NotNil(t, err) + require.NotNil(t, err) _, nonRunning := err.(*NotRunningServiceError) - assert.True(t, nonRunning) + require.True(t, nonRunning) } func TestExecuteWithNonExistingService(t *testing.T) { @@ -116,7 +117,7 @@ func TestExecuteWithNonExistingService(t *testing.T) { InputData: "{}", }) - assert.NotNil(t, err) + require.NotNil(t, err) } func TestExecuteFunc(t *testing.T) { diff --git a/api/core/get_service_test.go b/api/core/get_service_test.go index bbaedd5c5..7c999a367 100644 --- a/api/core/get_service_test.go +++ b/api/core/get_service_test.go @@ -6,7 +6,7 @@ import ( "github.com/mesg-foundation/core/database/services" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) var servergetservice = new(Server) @@ -19,7 +19,7 @@ func TestGetService(t *testing.T) { reply, err := servergetservice.GetService(context.Background(), &GetServiceRequest{ ServiceID: hash, }) - assert.Nil(t, err) - assert.NotNil(t, reply) - assert.Equal(t, reply.Service.Name, "TestGetService") + require.Nil(t, err) + require.NotNil(t, reply) + require.Equal(t, reply.Service.Name, "TestGetService") } diff --git a/api/core/list_services_test.go b/api/core/list_services_test.go index 6a95c7cec..8d7609d1f 100644 --- a/api/core/list_services_test.go +++ b/api/core/list_services_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/mesg-foundation/core/database/services" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) var serverlistservices = new(Server) @@ -13,6 +13,6 @@ var serverlistservices = new(Server) func TestListServices(t *testing.T) { servicesFromAPI, err := serverlistservices.ListServices(context.Background(), &ListServicesRequest{}) servicesFromDB, _ := services.All() - assert.Nil(t, err) - assert.Equal(t, len(servicesFromAPI.Services), len(servicesFromDB)) + require.Nil(t, err) + require.Equal(t, len(servicesFromAPI.Services), len(servicesFromDB)) } diff --git a/api/core/listen_event_test.go b/api/core/listen_event_test.go index 5dd828dca..712b61ff0 100644 --- a/api/core/listen_event_test.go +++ b/api/core/listen_event_test.go @@ -5,7 +5,7 @@ import ( "github.com/mesg-foundation/core/event" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestValidateEventKey(t *testing.T) { @@ -14,26 +14,26 @@ func TestValidateEventKey(t *testing.T) { "test": {}, }, } - assert.Nil(t, validateEventKey(s, "")) - assert.Nil(t, validateEventKey(s, "*")) - assert.Nil(t, validateEventKey(s, "test")) - assert.NotNil(t, validateEventKey(s, "xxx")) + require.Nil(t, validateEventKey(s, "")) + require.Nil(t, validateEventKey(s, "*")) + require.Nil(t, validateEventKey(s, "test")) + require.NotNil(t, validateEventKey(s, "xxx")) } func TestIsSubscribedEvent(t *testing.T) { e := &event.Event{Key: "test"} r := &ListenEventRequest{} - assert.True(t, isSubscribedEvent(r, e)) + require.True(t, isSubscribedEvent(r, e)) r = &ListenEventRequest{EventFilter: ""} - assert.True(t, isSubscribedEvent(r, e)) + require.True(t, isSubscribedEvent(r, e)) r = &ListenEventRequest{EventFilter: "*"} - assert.True(t, isSubscribedEvent(r, e)) + require.True(t, isSubscribedEvent(r, e)) r = &ListenEventRequest{EventFilter: "test"} - assert.True(t, isSubscribedEvent(r, e)) + require.True(t, isSubscribedEvent(r, e)) r = &ListenEventRequest{EventFilter: "xxx"} - assert.False(t, isSubscribedEvent(r, e)) + require.False(t, isSubscribedEvent(r, e)) } diff --git a/api/core/listen_result_test.go b/api/core/listen_result_test.go index 4d1b682fe..3221f91ff 100644 --- a/api/core/listen_result_test.go +++ b/api/core/listen_result_test.go @@ -5,7 +5,7 @@ import ( "github.com/mesg-foundation/core/execution" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestValidateTaskKey(t *testing.T) { @@ -14,10 +14,10 @@ func TestValidateTaskKey(t *testing.T) { "test": {}, }, } - assert.Nil(t, validateTaskKey(s, "")) - assert.Nil(t, validateTaskKey(s, "*")) - assert.Nil(t, validateTaskKey(s, "test")) - assert.NotNil(t, validateTaskKey(s, "xxx")) + require.Nil(t, validateTaskKey(s, "")) + require.Nil(t, validateTaskKey(s, "*")) + require.Nil(t, validateTaskKey(s, "test")) + require.NotNil(t, validateTaskKey(s, "xxx")) } func TestValidateOutputKey(t *testing.T) { @@ -30,48 +30,48 @@ func TestValidateOutputKey(t *testing.T) { }, }, } - assert.Nil(t, validateOutputKey(s, "test", "")) - assert.Nil(t, validateOutputKey(s, "test", "*")) - assert.Nil(t, validateOutputKey(s, "test", "outputx")) - assert.NotNil(t, validateOutputKey(s, "test", "xxx")) - assert.Nil(t, validateOutputKey(s, "xxx", "")) - assert.Nil(t, validateOutputKey(s, "xxx", "*")) - assert.NotNil(t, validateOutputKey(s, "xxx", "outputX")) - assert.NotNil(t, validateOutputKey(s, "xxx", "xxx")) + require.Nil(t, validateOutputKey(s, "test", "")) + require.Nil(t, validateOutputKey(s, "test", "*")) + require.Nil(t, validateOutputKey(s, "test", "outputx")) + require.NotNil(t, validateOutputKey(s, "test", "xxx")) + require.Nil(t, validateOutputKey(s, "xxx", "")) + require.Nil(t, validateOutputKey(s, "xxx", "*")) + require.NotNil(t, validateOutputKey(s, "xxx", "outputX")) + require.NotNil(t, validateOutputKey(s, "xxx", "xxx")) } func TestIsSubscribedTask(t *testing.T) { x := &execution.Execution{Task: "task"} r := &ListenResultRequest{} - assert.True(t, isSubscribedTask(r, x)) + require.True(t, isSubscribedTask(r, x)) r = &ListenResultRequest{TaskFilter: ""} - assert.True(t, isSubscribedTask(r, x)) + require.True(t, isSubscribedTask(r, x)) r = &ListenResultRequest{TaskFilter: "*"} - assert.True(t, isSubscribedTask(r, x)) + require.True(t, isSubscribedTask(r, x)) r = &ListenResultRequest{TaskFilter: "task"} - assert.True(t, isSubscribedTask(r, x)) + require.True(t, isSubscribedTask(r, x)) r = &ListenResultRequest{TaskFilter: "xxx"} - assert.False(t, isSubscribedTask(r, x)) + require.False(t, isSubscribedTask(r, x)) } func TestIsSubscribedOutput(t *testing.T) { x := &execution.Execution{Output: "output"} r := &ListenResultRequest{} - assert.True(t, isSubscribedOutput(r, x)) + require.True(t, isSubscribedOutput(r, x)) r = &ListenResultRequest{OutputFilter: ""} - assert.True(t, isSubscribedOutput(r, x)) + require.True(t, isSubscribedOutput(r, x)) r = &ListenResultRequest{OutputFilter: "*"} - assert.True(t, isSubscribedOutput(r, x)) + require.True(t, isSubscribedOutput(r, x)) r = &ListenResultRequest{OutputFilter: "output"} - assert.True(t, isSubscribedOutput(r, x)) + require.True(t, isSubscribedOutput(r, x)) r = &ListenResultRequest{OutputFilter: "xxx"} - assert.False(t, isSubscribedOutput(r, x)) + require.False(t, isSubscribedOutput(r, x)) } diff --git a/api/core/start_test.go b/api/core/start_test.go index 07242164e..a1f19b68d 100644 --- a/api/core/start_test.go +++ b/api/core/start_test.go @@ -6,7 +6,7 @@ import ( "github.com/mesg-foundation/core/database/services" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) var serverstart = new(Server) @@ -26,10 +26,10 @@ func TestStartService(t *testing.T) { reply, err := serverstart.StartService(context.Background(), &StartServiceRequest{ ServiceID: deployment.ServiceID, }) - assert.Nil(t, err) + require.Nil(t, err) status, _ := s.Status() - assert.Equal(t, service.RUNNING, status) - assert.NotNil(t, reply) + require.Equal(t, service.RUNNING, status) + require.NotNil(t, reply) s.Stop() services.Delete(deployment.ServiceID) } diff --git a/api/core/stop_test.go b/api/core/stop_test.go index 18d3af23d..f20314f18 100644 --- a/api/core/stop_test.go +++ b/api/core/stop_test.go @@ -6,7 +6,7 @@ import ( "github.com/mesg-foundation/core/database/services" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) var serverstop = new(Server) @@ -28,8 +28,8 @@ func TestStopService(t *testing.T) { ServiceID: deployment.ServiceID, }) status, _ := s.Status() - assert.Equal(t, service.STOPPED, status) - assert.Nil(t, err) - assert.NotNil(t, reply) + require.Equal(t, service.STOPPED, status) + require.Nil(t, err) + require.NotNil(t, reply) services.Delete(deployment.ServiceID) } diff --git a/api/server_test.go b/api/server_test.go index 30c2b8a14..7e707513a 100644 --- a/api/server_test.go +++ b/api/server_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) const ( @@ -21,7 +21,7 @@ func TestServerServe(t *testing.T) { s.Stop() }() err := s.Serve() - assert.Nil(t, err) + require.Nil(t, err) } func TestServerServeNoAddress(t *testing.T) { @@ -31,7 +31,7 @@ func TestServerServeNoAddress(t *testing.T) { s.Stop() }() err := s.Serve() - assert.NotNil(t, err) + require.NotNil(t, err) } func TestServerServeAlreadyListening(t *testing.T) { @@ -43,5 +43,5 @@ func TestServerServeAlreadyListening(t *testing.T) { time.Sleep(waitForServe) err := s.Serve() defer s.Stop() - assert.NotNil(t, err) + require.NotNil(t, err) } diff --git a/api/service/emit_event_test.go b/api/service/emit_event_test.go index ffb6b4366..256b8393c 100644 --- a/api/service/emit_event_test.go +++ b/api/service/emit_event_test.go @@ -7,7 +7,7 @@ import ( "github.com/mesg-foundation/core/database/services" "github.com/mesg-foundation/core/pubsub" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) var serveremit = new(Server) @@ -36,7 +36,7 @@ func TestEmit(t *testing.T) { }) res := <-subscription - assert.NotNil(t, res) + require.NotNil(t, res) } func TestEmitNoData(t *testing.T) { @@ -47,7 +47,7 @@ func TestEmitNoData(t *testing.T) { Token: service.Hash(), EventKey: "test", }) - assert.Equal(t, err.Error(), "unexpected end of JSON input") + require.Equal(t, err.Error(), "unexpected end of JSON input") } func TestEmitWrongData(t *testing.T) { @@ -59,7 +59,7 @@ func TestEmitWrongData(t *testing.T) { EventKey: "test", EventData: "", }) - assert.Equal(t, err.Error(), "unexpected end of JSON input") + require.Equal(t, err.Error(), "unexpected end of JSON input") } func TestEmitWrongEvent(t *testing.T) { @@ -71,9 +71,9 @@ func TestEmitWrongEvent(t *testing.T) { EventKey: "test", EventData: "{}", }) - assert.NotNil(t, err) + require.NotNil(t, err) _, notFound := err.(*service.EventNotFoundError) - assert.True(t, notFound) + require.True(t, notFound) } func TestServiceNotExists(t *testing.T) { @@ -83,5 +83,5 @@ func TestServiceNotExists(t *testing.T) { EventKey: "test", EventData: "{}", }) - assert.NotNil(t, err) + require.NotNil(t, err) } diff --git a/api/service/error_test.go b/api/service/error_test.go index 28cff23c6..524ca9ab5 100644 --- a/api/service/error_test.go +++ b/api/service/error_test.go @@ -3,10 +3,10 @@ package service import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestMissingExecutionError(t *testing.T) { e := MissingExecutionError{ID: "test"} - assert.Equal(t, "Execution test doesn't exists", e.Error()) + require.Equal(t, "Execution test doesn't exists", e.Error()) } diff --git a/api/service/submit_result_test.go b/api/service/submit_result_test.go index 007e23e9b..9c083fd54 100644 --- a/api/service/submit_result_test.go +++ b/api/service/submit_result_test.go @@ -6,7 +6,7 @@ import ( "github.com/mesg-foundation/core/execution" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) var serversubmit = new(Server) @@ -35,8 +35,8 @@ func TestSubmit(t *testing.T) { OutputData: "{}", }) - assert.Nil(t, err) - assert.NotNil(t, reply) + require.Nil(t, err) + require.NotNil(t, reply) } func TestSubmitWithInvalidJSON(t *testing.T) { @@ -47,7 +47,7 @@ func TestSubmitWithInvalidJSON(t *testing.T) { OutputData: "", }) - assert.NotNil(t, err) + require.NotNil(t, err) } func TestSubmitWithInvalidID(t *testing.T) { @@ -56,8 +56,8 @@ func TestSubmitWithInvalidID(t *testing.T) { OutputKey: "output", OutputData: "", }) - assert.NotNil(t, err) + require.NotNil(t, err) x, missingExecutionError := err.(*MissingExecutionError) - assert.True(t, missingExecutionError) - assert.Equal(t, "xxxx", x.ID) + require.True(t, missingExecutionError) + require.Equal(t, "xxxx", x.ID) } diff --git a/cmd/service/execute_test.go b/cmd/service/execute_test.go index d7e2fd043..7dbca7e5a 100644 --- a/cmd/service/execute_test.go +++ b/cmd/service/execute_test.go @@ -4,20 +4,20 @@ import ( "testing" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestReadJSONFile(t *testing.T) { d, e := readJSONFile("") - assert.Nil(t, e) - assert.Equal(t, "{}", d) + require.Nil(t, e) + require.Equal(t, "{}", d) d, e = readJSONFile("./doesntexistsfile") - assert.NotNil(t, e) + require.NotNil(t, e) d, e = readJSONFile("./tests/validData.json") - assert.Nil(t, e) - assert.Equal(t, "{\"foo\":\"bar\"}", d) + require.Nil(t, e) + require.Equal(t, "{\"foo\":\"bar\"}", d) } func TestTaskKeysFromService(t *testing.T) { @@ -26,5 +26,5 @@ func TestTaskKeysFromService(t *testing.T) { "task1": {}, }, }) - assert.Equal(t, "task1", keys[0]) + require.Equal(t, "task1", keys[0]) } diff --git a/cmd/service/init_test.go b/cmd/service/init_test.go index e3c083bfc..14ea6619f 100644 --- a/cmd/service/init_test.go +++ b/cmd/service/init_test.go @@ -4,18 +4,18 @@ import ( "os" "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestGetTemplate(t *testing.T) { templates, err := getTemplates(templatesURL) - assert.Nil(t, err) - assert.True(t, len(templates) > 0) + require.Nil(t, err) + require.True(t, len(templates) > 0) } func TestGetTemplateBadURL(t *testing.T) { _, err := getTemplates("...") - assert.NotNil(t, err) + require.NotNil(t, err) } func TestTemplatesToOption(t *testing.T) { @@ -24,15 +24,15 @@ func TestTemplatesToOption(t *testing.T) { {Name: "yyy", URL: "https://..."}, } options := templatesToOption(templates) - assert.Equal(t, len(options), len(templates)+2) - assert.Equal(t, options[0], "xxx (https://...)") - assert.Equal(t, options[1], "yyy (https://...)") - assert.Equal(t, options[2], custom) - assert.Equal(t, options[3], addMyOwn) + require.Equal(t, len(options), len(templates)+2) + require.Equal(t, options[0], "xxx (https://...)") + require.Equal(t, options[1], "yyy (https://...)") + require.Equal(t, options[2], custom) + require.Equal(t, options[3], addMyOwn) } func TestGetTemplateResultAddMyOwn(t *testing.T) { - assert.Nil(t, getTemplateResult(addMyOwn, []*templateStruct{})) + require.Nil(t, getTemplateResult(addMyOwn, []*templateStruct{})) } func TestGetTemplateResultAdd(t *testing.T) { @@ -42,8 +42,8 @@ func TestGetTemplateResultAdd(t *testing.T) { } result := "yyy (https://...)" tmpl := getTemplateResult(result, templates) - assert.NotNil(t, tmpl) - assert.Equal(t, tmpl.Name, templates[1].Name) + require.NotNil(t, tmpl) + require.Equal(t, tmpl.Name, templates[1].Name) } func TestDownloadTemplate(t *testing.T) { @@ -52,6 +52,6 @@ func TestDownloadTemplate(t *testing.T) { } path, err := downloadTemplate(tmpl) defer os.RemoveAll(path) - assert.Nil(t, err) - assert.NotNil(t, path) + require.Nil(t, err) + require.NotNil(t, path) } diff --git a/cmd/service/list_test.go b/cmd/service/list_test.go index 6e827882e..1a443f067 100644 --- a/cmd/service/list_test.go +++ b/cmd/service/list_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestServiceStatusString(t *testing.T) { @@ -14,9 +14,9 @@ func TestServiceStatusString(t *testing.T) { service: &s, status: service.RUNNING, } - assert.Contains(t, "[Running]", status.String()) - assert.Contains(t, s.Hash(), status.String()) - assert.Contains(t, s.Name, status.String()) + require.Contains(t, status.String(), "[Running]") + require.Contains(t, status.String(), s.Hash()) + require.Contains(t, status.String(), s.Name) } func TestSort(t *testing.T) { @@ -26,14 +26,14 @@ func TestSort(t *testing.T) { {status: service.STOPPED, service: &service.Service{Name: "Stopped"}}, } sort.Sort(byStatus(status)) - assert.Equal(t, status[0].status, service.RUNNING) - assert.Equal(t, status[1].status, service.PARTIAL) - assert.Equal(t, status[2].status, service.STOPPED) + require.Equal(t, status[0].status, service.RUNNING) + require.Equal(t, status[1].status, service.PARTIAL) + require.Equal(t, status[2].status, service.STOPPED) } func TestServicesWithStatus(t *testing.T) { services := append([]*service.Service{}, &service.Service{Name: "TestServicesWithStatus"}) status, err := servicesWithStatus(services) - assert.Nil(t, err) - assert.Equal(t, status[0].status, service.STOPPED) + require.Nil(t, err) + require.Equal(t, status[0].status, service.STOPPED) } diff --git a/cmd/service/utils_test.go b/cmd/service/utils_test.go index 1a96ec3e9..3cf62bd56 100644 --- a/cmd/service/utils_test.go +++ b/cmd/service/utils_test.go @@ -5,33 +5,33 @@ import ( "testing" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" git "gopkg.in/src-d/go-git.v4" ) func TestDefaultPath(t *testing.T) { - assert.Equal(t, defaultPath([]string{}), "./") - assert.Equal(t, defaultPath([]string{"foo"}), "foo") - assert.Equal(t, defaultPath([]string{"foo", "bar"}), "foo") + require.Equal(t, defaultPath([]string{}), "./") + require.Equal(t, defaultPath([]string{"foo"}), "foo") + require.Equal(t, defaultPath([]string{"foo", "bar"}), "foo") } func TestBuildDockerImagePathDoNotExist(t *testing.T) { _, err := buildDockerImage("/doNotExist") - assert.NotNil(t, err) + require.NotNil(t, err) } func TestGitCloneRepositoryDoNotExist(t *testing.T) { path, _ := createTempFolder() defer os.RemoveAll(path) err := gitClone("/doNotExist", path, "testing...") - assert.NotNil(t, err) + require.NotNil(t, err) } func TestGitCloneWithoutURLSchema(t *testing.T) { path, _ := createTempFolder() defer os.RemoveAll(path) err := gitClone("github.com/mesg-foundation/awesome.git", path, "testing...") - assert.Nil(t, err) + require.Nil(t, err) } func TestGitCloneCustomBranch(t *testing.T) { @@ -39,56 +39,56 @@ func TestGitCloneCustomBranch(t *testing.T) { path, _ := createTempFolder() defer os.RemoveAll(path) err := gitClone("github.com/mesg-foundation/service-ethereum-erc20#"+branchName, path, "testing...") - assert.Nil(t, err) + require.Nil(t, err) repo, err := git.PlainOpen(path) - assert.Nil(t, err) + require.Nil(t, err) branch, err := repo.Branch(branchName) - assert.Nil(t, err) - assert.NotNil(t, branch) + require.Nil(t, err) + require.NotNil(t, branch) } func TestDownloadServiceIfNeededAbsolutePath(t *testing.T) { path := "/users/paul/service-js-function" newPath, didDownload, err := downloadServiceIfNeeded(path) - assert.Nil(t, err) - assert.Equal(t, path, newPath) - assert.Equal(t, false, didDownload) + require.Nil(t, err) + require.Equal(t, path, newPath) + require.Equal(t, false, didDownload) } func TestDownloadServiceIfNeededRelativePath(t *testing.T) { path := "./service-js-function" newPath, didDownload, err := downloadServiceIfNeeded(path) - assert.Nil(t, err) - assert.Equal(t, path, newPath) - assert.Equal(t, false, didDownload) + require.Nil(t, err) + require.Equal(t, path, newPath) + require.Equal(t, false, didDownload) } func TestDownloadServiceIfNeededUrl(t *testing.T) { path := "https://github.com/mesg-foundation/awesome.git" newPath, didDownload, err := downloadServiceIfNeeded(path) defer os.RemoveAll(newPath) - assert.Nil(t, err) - assert.NotEqual(t, path, newPath) - assert.Equal(t, true, didDownload) + require.Nil(t, err) + require.NotEqual(t, path, newPath) + require.Equal(t, true, didDownload) } func TestCreateTempFolder(t *testing.T) { path, err := createTempFolder() defer os.RemoveAll(path) - assert.Nil(t, err) - assert.NotEqual(t, "", path) + require.Nil(t, err) + require.NotEqual(t, "", path) } func TestRemoveTempFolder(t *testing.T) { path, _ := createTempFolder() err := os.RemoveAll(path) - assert.Nil(t, err) + require.Nil(t, err) } func TestInjectConfigurationInDependencies(t *testing.T) { s := &service.Service{} injectConfigurationInDependencies(s, "TestInjectConfigurationInDependencies") - assert.Equal(t, s.Dependencies["service"].Image, "TestInjectConfigurationInDependencies") + require.Equal(t, s.Dependencies["service"].Image, "TestInjectConfigurationInDependencies") } func TestInjectConfigurationInDependenciesWithConfig(t *testing.T) { @@ -99,8 +99,8 @@ func TestInjectConfigurationInDependenciesWithConfig(t *testing.T) { }, } injectConfigurationInDependencies(s, "TestInjectConfigurationInDependenciesWithConfig") - assert.Equal(t, s.Dependencies["service"].Image, "TestInjectConfigurationInDependenciesWithConfig") - assert.Equal(t, s.Dependencies["service"].Command, "xxx") + require.Equal(t, s.Dependencies["service"].Image, "TestInjectConfigurationInDependenciesWithConfig") + require.Equal(t, s.Dependencies["service"].Command, "xxx") } func TestInjectConfigurationInDependenciesWithDependency(t *testing.T) { @@ -112,8 +112,8 @@ func TestInjectConfigurationInDependenciesWithDependency(t *testing.T) { }, } injectConfigurationInDependencies(s, "TestInjectConfigurationInDependenciesWithDependency") - assert.Equal(t, s.Dependencies["service"].Image, "TestInjectConfigurationInDependenciesWithDependency") - assert.Equal(t, s.Dependencies["test"].Image, "xxx") + require.Equal(t, s.Dependencies["service"].Image, "TestInjectConfigurationInDependenciesWithDependency") + require.Equal(t, s.Dependencies["test"].Image, "xxx") } func TestInjectConfigurationInDependenciesWithDependencyOverride(t *testing.T) { @@ -125,5 +125,5 @@ func TestInjectConfigurationInDependenciesWithDependencyOverride(t *testing.T) { }, } injectConfigurationInDependencies(s, "TestInjectConfigurationInDependenciesWithDependencyOverride") - assert.Equal(t, s.Dependencies["service"].Image, "TestInjectConfigurationInDependenciesWithDependencyOverride") + require.Equal(t, s.Dependencies["service"].Image, "TestInjectConfigurationInDependenciesWithDependencyOverride") } diff --git a/cmd/utils/error_test.go b/cmd/utils/error_test.go index 5510e013f..6b780cfc1 100644 --- a/cmd/utils/error_test.go +++ b/cmd/utils/error_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/docker/docker/client" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -14,23 +14,23 @@ var testCoreConnectionErr = status.Error(codes.Unavailable, "test") var testDockerConnectionErr = client.ErrorConnectionFailed("test") func TestCoreConnectionError(t *testing.T) { - assert.True(t, coreConnectionError(testCoreConnectionErr)) - assert.False(t, coreConnectionError(nil)) - assert.False(t, coreConnectionError(errors.New("test"))) + require.True(t, coreConnectionError(testCoreConnectionErr)) + require.False(t, coreConnectionError(nil)) + require.False(t, coreConnectionError(errors.New("test"))) } func TestDockerDaemonError(t *testing.T) { - assert.True(t, dockerDaemonError(testDockerConnectionErr)) - assert.False(t, dockerDaemonError(nil)) - assert.False(t, dockerDaemonError(errors.New("test"))) + require.True(t, dockerDaemonError(testDockerConnectionErr)) + require.False(t, dockerDaemonError(nil)) + require.False(t, dockerDaemonError(errors.New("test"))) } func TestErrorMessage(t *testing.T) { - assert.Contains(t, cannotReachTheCore, errorMessage(testCoreConnectionErr)) - assert.Contains(t, startCore, errorMessage(testCoreConnectionErr)) + require.Contains(t, errorMessage(testCoreConnectionErr), cannotReachTheCore) + require.Contains(t, errorMessage(testCoreConnectionErr), startCore) - assert.Contains(t, cannotReachDocker, errorMessage(testDockerConnectionErr)) - assert.Contains(t, installDocker, errorMessage(testDockerConnectionErr)) + require.Contains(t, errorMessage(testDockerConnectionErr), cannotReachDocker) + require.Contains(t, errorMessage(testDockerConnectionErr), installDocker) - assert.Contains(t, "errorX", errorMessage(errors.New("errorX"))) + require.Contains(t, errorMessage(errors.New("errorX")), "errorX") } diff --git a/config/api_test.go b/config/api_test.go index 0bf2ccfc4..a41690f15 100644 --- a/config/api_test.go +++ b/config/api_test.go @@ -5,12 +5,12 @@ import ( "testing" "github.com/spf13/viper" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func assertViperDefault(t *testing.T, key string, expected string) { value := viper.GetString(key) - assert.Equal(t, expected, value, "Wrong default for key "+key) + require.Equal(t, expected, value, "Wrong default for key "+key) } func TestAPIDefault(t *testing.T) { @@ -29,5 +29,5 @@ func TestAPIDefault(t *testing.T) { } // Override by ENV when testing, so only test the image name - assert.Contains(t, "mesg/core:", viper.GetString(CoreImage)) + require.Contains(t, viper.GetString(CoreImage), "mesg/core:") } diff --git a/config/config_test.go b/config/config_test.go index 52ee89814..485ab13e5 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -3,9 +3,9 @@ package config import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestToEnv(t *testing.T) { - assert.Equal(t, envPrefix+envSeparator+"FOO"+envSeparator+"BAR", ToEnv("foo.bar")) + require.Equal(t, envPrefix+envSeparator+"FOO"+envSeparator+"BAR", ToEnv("foo.bar")) } diff --git a/config/directory_test.go b/config/directory_test.go index bb9088be8..663de5e71 100644 --- a/config/directory_test.go +++ b/config/directory_test.go @@ -5,17 +5,17 @@ import ( "testing" homedir "github.com/mitchellh/go-homedir" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestCreateConfigPath(t *testing.T) { err := createConfigPath() - assert.Nil(t, err) + require.Nil(t, err) } func TestConfigPath(t *testing.T) { homePath, _ := homedir.Dir() dir, err := getConfigPath() - assert.Nil(t, err) - assert.Equal(t, dir, filepath.Join(homePath, configDirectory)) + require.Nil(t, err) + require.Equal(t, dir, filepath.Join(homePath, configDirectory)) } diff --git a/container/build_integration_test.go b/container/build_integration_test.go index 290619581..4f210f360 100644 --- a/container/build_integration_test.go +++ b/container/build_integration_test.go @@ -5,28 +5,28 @@ package container import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestIntegrationBuild(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) tag, err := c.Build("test/") - assert.Nil(t, err) - assert.NotEqual(t, "", tag) + require.Nil(t, err) + require.NotEqual(t, "", tag) } func TestIntegrationBuildNotWorking(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) tag, err := c.Build("test-not-valid/") - assert.NotNil(t, err) - assert.Equal(t, "", tag) + require.NotNil(t, err) + require.Equal(t, "", tag) } func TestIntegrationBuildWrongPath(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) _, err = c.Build("testss/") - assert.NotNil(t, err) + require.NotNil(t, err) } diff --git a/container/build_test.go b/container/build_test.go index 9740242b9..f97f04fb8 100644 --- a/container/build_test.go +++ b/container/build_test.go @@ -8,7 +8,7 @@ import ( "github.com/docker/docker/api/types" "github.com/mesg-foundation/core/container/dockertest" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestBuild(t *testing.T) { @@ -23,12 +23,12 @@ func TestBuild(t *testing.T) { )), nil) tag1, err := c.Build(path) - assert.Nil(t, err) - assert.Equal(t, tag, tag1) + require.Nil(t, err) + require.Equal(t, tag, tag1) li := <-dt.LastImageBuild() - assert.True(t, len(li.FileData) > 0) - assert.Equal(t, types.ImageBuildOptions{ + require.True(t, len(li.FileData) > 0) + require.Equal(t, types.ImageBuildOptions{ Remove: true, ForceRemove: true, SuppressOutput: true, @@ -47,8 +47,8 @@ func TestBuildNotWorking(t *testing.T) { {"errorDetail":{"message":"invalid reference format: repository name must be lowercase"},"error":"invalid reference format: repository name must be lowercase"}`)), nil) tag, err := c.Build(path) - assert.Equal(t, "Image build failed. invalid reference format: repository name must be lowercase", err.Error()) - assert.Equal(t, "", tag) + require.Equal(t, "Image build failed. invalid reference format: repository name must be lowercase", err.Error()) + require.Equal(t, "", tag) } func TestBuildWrongPath(t *testing.T) { @@ -58,7 +58,7 @@ func TestBuildWrongPath(t *testing.T) { dt.ProvideImageBuild(ioutil.NopCloser(strings.NewReader("")), nil) _, err := c.Build("testss/") - assert.Equal(t, "Could not parse container build response", err.Error()) + require.Equal(t, "Could not parse container build response", err.Error()) } func TestParseBuildResponseInvalidJSON(t *testing.T) { @@ -67,7 +67,7 @@ func TestParseBuildResponseInvalidJSON(t *testing.T) { Body: body, } _, err := parseBuildResponse(response) - assert.NotNil(t, err) + require.NotNil(t, err) } func TestParseBuildResponse(t *testing.T) { @@ -76,8 +76,8 @@ func TestParseBuildResponse(t *testing.T) { Body: body, } tag, err := parseBuildResponse(response) - assert.Nil(t, err) - assert.Equal(t, tag, "ok") + require.Nil(t, err) + require.Equal(t, tag, "ok") } func TestParseBuildResponseWithNewLine(t *testing.T) { @@ -86,6 +86,6 @@ func TestParseBuildResponseWithNewLine(t *testing.T) { Body: body, } tag, err := parseBuildResponse(response) - assert.Nil(t, err) - assert.Equal(t, tag, "ok") + require.Nil(t, err) + require.Equal(t, tag, "ok") } diff --git a/container/client_test.go b/container/client_test.go index 7bc5eff94..c66a6324d 100644 --- a/container/client_test.go +++ b/container/client_test.go @@ -5,15 +5,15 @@ package container // leaveSwarm() // dockerClient, _ := godocker.NewClientFromEnv() // ID, err := createSwarm(dockerClient) -// assert.Nil(t, err) -// assert.NotEqual(t, ID, "") +// require.Nil(t, err) +// require.NotEqual(t, ID, "") // } // func TestClientWithCreateSwarm(t *testing.T) { // leaveSwarm() // client, err := Client() -// assert.Nil(t, err) -// assert.NotNil(t, client) +// require.Nil(t, err) +// require.NotNil(t, client) // } // func leaveSwarm() { diff --git a/container/container_integration_test.go b/container/container_integration_test.go index 7b2dd5bf6..9147d00d3 100644 --- a/container/container_integration_test.go +++ b/container/container_integration_test.go @@ -5,74 +5,74 @@ package container import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestIntegrationCreateSwarmIfNeeded(t *testing.T) { c, err := New() - assert.Nil(t, err) - assert.Nil(t, c.createSwarmIfNeeded()) + require.Nil(t, err) + require.Nil(t, c.createSwarmIfNeeded()) } func TestIntegrationFindContainerNotExisting(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) _, err = c.FindContainer([]string{"TestFindContainerNotExisting"}) - assert.NotNil(t, err) + require.NotNil(t, err) } func TestIntegrationFindContainer(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestFindContainer"} startTestService(namespace) defer c.StopService(namespace) c.waitForStatus(namespace, RUNNING) container, err := c.FindContainer(namespace) - assert.Nil(t, err) - assert.NotEqual(t, "", container.ID) + require.Nil(t, err) + require.NotEqual(t, "", container.ID) } func TestIntegrationFindContainerStopped(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestFindContainerStopped"} startTestService(namespace) c.StopService(namespace) _, err = c.FindContainer(namespace) - assert.NotNil(t, err) + require.NotNil(t, err) } func TestIntegrationContainerStatusNeverStarted(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestContainerStatusNeverStarted"} status, err := c.Status(namespace) - assert.Nil(t, err) - assert.Equal(t, status, STOPPED) + require.Nil(t, err) + require.Equal(t, status, STOPPED) } func TestIntegrationContainerStatusRunning(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestContainerStatusRunning"} startTestService(namespace) defer c.StopService(namespace) c.waitForStatus(namespace, RUNNING) status, err := c.Status(namespace) - assert.Nil(t, err) - assert.Equal(t, status, RUNNING) + require.Nil(t, err) + require.Equal(t, status, RUNNING) } func TestIntegrationContainerStatusStopped(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestContainerStatusStopped"} startTestService(namespace) c.waitForStatus(namespace, RUNNING) c.StopService(namespace) c.waitForStatus(namespace, STOPPED) status, err := c.Status(namespace) - assert.Nil(t, err) - assert.Equal(t, status, STOPPED) + require.Nil(t, err) + require.Equal(t, status, STOPPED) } diff --git a/container/container_test.go b/container/container_test.go index 6cbbcd21a..09e86a46c 100644 --- a/container/container_test.go +++ b/container/container_test.go @@ -8,14 +8,14 @@ import ( "github.com/docker/docker/api/types/swarm" "github.com/mesg-foundation/core/container/dockertest" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestNew(t *testing.T) { dt := dockertest.New() c, err := New(ClientOption(dt.Client())) - assert.Nil(t, err) - assert.NotNil(t, c) + require.Nil(t, err) + require.NotNil(t, c) select { case <-dt.LastNegotiateAPIVersion(): @@ -29,11 +29,11 @@ func TestNew(t *testing.T) { t.Error("should fetch info") } - assert.Equal(t, "0.0.0.0:2377", (<-dt.LastSwarmInit()).Request.ListenAddr) + require.Equal(t, "0.0.0.0:2377", (<-dt.LastSwarmInit()).Request.ListenAddr) ln := <-dt.LastNetworkCreate() - assert.Equal(t, "mesg-shared", ln.Name) - assert.Equal(t, types.NetworkCreate{ + require.Equal(t, "mesg-shared", ln.Name) + require.Equal(t, types.NetworkCreate{ CheckDuplicate: true, Driver: "overlay", Labels: map[string]string{ @@ -47,8 +47,8 @@ func TestNewWithExistingNode(t *testing.T) { dt.ProvideInfo(types.Info{Swarm: swarm.Info{NodeID: "1"}}, nil) c, err := New(ClientOption(dt.Client())) - assert.Nil(t, err) - assert.NotNil(t, c) + require.Nil(t, err) + require.NotNil(t, c) select { case <-dt.LastSwarmInit(): @@ -66,9 +66,9 @@ func TestFindContainerNonExistent(t *testing.T) { dt.ProvideContainerList(nil, dockertest.NotFoundErr{}) _, err := c.FindContainer(namespace) - assert.Equal(t, dockertest.NotFoundErr{}, err) + require.Equal(t, dockertest.NotFoundErr{}, err) - assert.Equal(t, types.ContainerListOptions{ + require.Equal(t, types.ContainerListOptions{ Filters: filters.NewArgs(filters.KeyValuePair{ Key: "label", Value: "com.docker.stack.namespace=" + Namespace(namespace), @@ -96,10 +96,10 @@ func TestFindContainer(t *testing.T) { dt.ProvideContainerInspect(containerJSONData, nil) container, err := c.FindContainer(namespace) - assert.Nil(t, err) - assert.Equal(t, containerJSONData.ID, container.ID) + require.Nil(t, err) + require.Equal(t, containerJSONData.ID, container.ID) - assert.Equal(t, types.ContainerListOptions{ + require.Equal(t, types.ContainerListOptions{ Filters: filters.NewArgs(filters.KeyValuePair{ Key: "label", Value: "com.docker.stack.namespace=" + Namespace(namespace), @@ -107,7 +107,7 @@ func TestFindContainer(t *testing.T) { Limit: 1, }, (<-dt.LastContainerList()).Options) - assert.Equal(t, containerID, (<-dt.LastContainerInspect()).Container) + require.Equal(t, containerID, (<-dt.LastContainerInspect()).Container) } func TestNonExistentContainerStatus(t *testing.T) { @@ -119,10 +119,10 @@ func TestNonExistentContainerStatus(t *testing.T) { dt.ProvideContainerList(nil, dockertest.NotFoundErr{}) status, err := c.Status(namespace) - assert.Nil(t, err) - assert.Equal(t, STOPPED, status) + require.Nil(t, err) + require.Equal(t, STOPPED, status) - assert.Equal(t, types.ContainerListOptions{ + require.Equal(t, types.ContainerListOptions{ Filters: filters.NewArgs(filters.KeyValuePair{ Key: "label", Value: "com.docker.stack.namespace=" + Namespace(namespace), @@ -151,8 +151,8 @@ func TestExistentContainerStatus(t *testing.T) { dt.ProvideContainerInspect(containerJSONData, nil) status, err := c.Status(namespace) - assert.Nil(t, err) - assert.Equal(t, STOPPED, status) + require.Nil(t, err) + require.Equal(t, STOPPED, status) } func TestExistentContainerRunningStatus(t *testing.T) { @@ -175,6 +175,6 @@ func TestExistentContainerRunningStatus(t *testing.T) { dt.ProvideContainerInspect(containerJSONData, nil) status, err := c.Status(namespace) - assert.Nil(t, err) - assert.Equal(t, RUNNING, status) + require.Nil(t, err) + require.Equal(t, RUNNING, status) } diff --git a/container/dockertest/error_test.go b/container/dockertest/error_test.go index c56145c81..ac97ecdeb 100644 --- a/container/dockertest/error_test.go +++ b/container/dockertest/error_test.go @@ -3,12 +3,12 @@ package dockertest import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) // TestNotFoundErr makes sure NotFoundErr to implement docker client's notFound interface. func TestNotFoundErr(t *testing.T) { err := NotFoundErr{} - assert.True(t, err.NotFound()) - assert.Equal(t, "not found", err.Error()) + require.True(t, err.NotFound()) + require.Equal(t, "not found", err.Error()) } diff --git a/container/dockertest/testing_test.go b/container/dockertest/testing_test.go index f5c028ed4..e8c0f4222 100644 --- a/container/dockertest/testing_test.go +++ b/container/dockertest/testing_test.go @@ -10,19 +10,19 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/swarm" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) var errGeneric = errors.New("titan of the errors") func TestNew(t *testing.T) { dt := New() - assert.NotNil(t, dt) + require.NotNil(t, dt) } func TestClient(t *testing.T) { dt := New() - assert.NotNil(t, dt.Client()) + require.NotNil(t, dt.Client()) } func TestNegotiateAPIVersion(t *testing.T) { @@ -45,12 +45,12 @@ func TestNetworkInspect(t *testing.T) { dt.ProvideNetworkInspect(resource, errGeneric) resource1, err := dt.Client().NetworkInspect(context.Background(), network, options) - assert.Equal(t, errGeneric, err) - assert.Equal(t, resource, resource1) + require.Equal(t, errGeneric, err) + require.Equal(t, resource, resource1) ll := <-dt.LastNetworkInspect() - assert.Equal(t, network, ll.Network) - assert.Equal(t, options, ll.Options) + require.Equal(t, network, ll.Network) + require.Equal(t, options, ll.Options) } func TestNetworkCreate(t *testing.T) { @@ -62,12 +62,12 @@ func TestNetworkCreate(t *testing.T) { dt.ProvideNetworkCreate(response, errGeneric) response1, err := dt.Client().NetworkCreate(context.Background(), name, options) - assert.Equal(t, errGeneric, err) - assert.Equal(t, response, response1) + require.Equal(t, errGeneric, err) + require.Equal(t, response, response1) ll := <-dt.LastNetworkCreate() - assert.Equal(t, name, ll.Name) - assert.Equal(t, options, ll.Options) + require.Equal(t, name, ll.Name) + require.Equal(t, options, ll.Options) } func TestSwarmInit(t *testing.T) { @@ -76,10 +76,10 @@ func TestSwarmInit(t *testing.T) { dt := New() data, err := dt.Client().SwarmInit(context.Background(), request) - assert.Nil(t, err) - assert.Equal(t, "", data) + require.Nil(t, err) + require.Equal(t, "", data) - assert.Equal(t, request, (<-dt.LastSwarmInit()).Request) + require.Equal(t, request, (<-dt.LastSwarmInit()).Request) } func TestInfo(t *testing.T) { @@ -89,8 +89,8 @@ func TestInfo(t *testing.T) { dt.ProvideInfo(info, errGeneric) info1, err := dt.Client().Info(context.Background()) - assert.Equal(t, errGeneric, err) - assert.Equal(t, info, info1) + require.Equal(t, errGeneric, err) + require.Equal(t, info, info1) select { case <-dt.LastInfo(): @@ -107,11 +107,11 @@ func TestContainerList(t *testing.T) { dt.ProvideContainerList(containers, errGeneric) containers1, err := dt.Client().ContainerList(context.Background(), options) - assert.Equal(t, errGeneric, err) - assert.Equal(t, containers, containers1) + require.Equal(t, errGeneric, err) + require.Equal(t, containers, containers1) ll := <-dt.LastContainerList() - assert.Equal(t, options, ll.Options) + require.Equal(t, options, ll.Options) } func TestContainerInspect(t *testing.T) { @@ -122,11 +122,11 @@ func TestContainerInspect(t *testing.T) { dt.ProvideContainerInspect(containerJSON, errGeneric) containerJSON1, err := dt.Client().ContainerInspect(context.Background(), container) - assert.Equal(t, errGeneric, err) - assert.Equal(t, containerJSON, containerJSON1) + require.Equal(t, errGeneric, err) + require.Equal(t, containerJSON, containerJSON1) ll := <-dt.LastContainerInspect() - assert.Equal(t, container, ll.Container) + require.Equal(t, container, ll.Container) } func TestImageBuild(t *testing.T) { @@ -139,23 +139,23 @@ func TestImageBuild(t *testing.T) { resp, err := dt.Client().ImageBuild(context.Background(), ioutil.NopCloser(bytes.NewReader(request)), options) - assert.Equal(t, errGeneric, err) + require.Equal(t, errGeneric, err) defer resp.Body.Close() respData, err := ioutil.ReadAll(resp.Body) - assert.Nil(t, err) - assert.Equal(t, response, respData) + require.Nil(t, err) + require.Equal(t, response, respData) ll := <-dt.LastImageBuild() - assert.Equal(t, options, ll.Options) - assert.Equal(t, request, ll.FileData) + require.Equal(t, options, ll.Options) + require.Equal(t, request, ll.FileData) } func TestNetworkRemove(t *testing.T) { network := "1" dt := New() - assert.Nil(t, dt.Client().NetworkRemove(context.Background(), network)) - assert.Equal(t, network, (<-dt.LastNetworkRemove()).Network) + require.Nil(t, dt.Client().NetworkRemove(context.Background(), network)) + require.Equal(t, network, (<-dt.LastNetworkRemove()).Network) } func TestTaskList(t *testing.T) { @@ -170,10 +170,10 @@ func TestTaskList(t *testing.T) { dt.ProvideTaskList(tasks, errGeneric) tasks1, err := dt.Client().TaskList(context.Background(), options) - assert.Equal(t, errGeneric, err) - assert.Equal(t, tasks, tasks1) + require.Equal(t, errGeneric, err) + require.Equal(t, tasks, tasks1) - assert.Equal(t, options, (<-dt.LastTaskList()).Options) + require.Equal(t, options, (<-dt.LastTaskList()).Options) } func TestServiceCreate(t *testing.T) { @@ -185,12 +185,12 @@ func TestServiceCreate(t *testing.T) { dt.ProvideServiceCreate(response, errGeneric) response1, err := dt.Client().ServiceCreate(context.Background(), service, options) - assert.Equal(t, errGeneric, err) - assert.Equal(t, response, response1) + require.Equal(t, errGeneric, err) + require.Equal(t, response, response1) ll := <-dt.LastServiceCreate() - assert.Equal(t, service, ll.Service) - assert.Equal(t, options, ll.Options) + require.Equal(t, service, ll.Service) + require.Equal(t, options, ll.Options) } func TestServiceList(t *testing.T) { @@ -205,11 +205,11 @@ func TestServiceList(t *testing.T) { dt.ProvideServiceList(services, errGeneric) services1, err := dt.Client().ServiceList(context.Background(), options) - assert.Equal(t, errGeneric, err) - assert.Equal(t, services, services1) + require.Equal(t, errGeneric, err) + require.Equal(t, services, services1) ll := <-dt.LastServiceList() - assert.Equal(t, options, ll.Options) + require.Equal(t, options, ll.Options) } func TestServiceInspectWithRaw(t *testing.T) { @@ -222,13 +222,13 @@ func TestServiceInspectWithRaw(t *testing.T) { dt.ProvideServiceInspectWithRaw(service, data, errGeneric) service1, data1, err := dt.Client().ServiceInspectWithRaw(context.Background(), serviceID, options) - assert.Equal(t, errGeneric, err) - assert.Equal(t, service, service1) - assert.Equal(t, data, data1) + require.Equal(t, errGeneric, err) + require.Equal(t, service, service1) + require.Equal(t, data, data1) ll := <-dt.LastServiceInspectWithRaw() - assert.Equal(t, serviceID, ll.ServiceID) - assert.Equal(t, options, ll.Options) + require.Equal(t, serviceID, ll.ServiceID) + require.Equal(t, options, ll.Options) } func TestServiceRemove(t *testing.T) { @@ -237,10 +237,10 @@ func TestServiceRemove(t *testing.T) { dt := New() dt.ProvideServiceRemove(errGeneric) - assert.Equal(t, errGeneric, dt.Client().ServiceRemove(context.Background(), serviceID)) + require.Equal(t, errGeneric, dt.Client().ServiceRemove(context.Background(), serviceID)) ll := <-dt.LastServiceRemove() - assert.Equal(t, serviceID, ll.ServiceID) + require.Equal(t, serviceID, ll.ServiceID) } func TestServiceLogs(t *testing.T) { @@ -252,14 +252,14 @@ func TestServiceLogs(t *testing.T) { dt.ProvideServiceLogs(ioutil.NopCloser(bytes.NewReader(data)), errGeneric) rc, err := dt.Client().ServiceLogs(context.Background(), serviceID, options) - assert.Equal(t, errGeneric, err) + require.Equal(t, errGeneric, err) defer rc.Close() data1, err := ioutil.ReadAll(rc) - assert.Nil(t, err) - assert.Equal(t, data, data1) + require.Nil(t, err) + require.Equal(t, data, data1) ll := <-dt.LastServiceLogs() - assert.Equal(t, serviceID, ll.ServiceID) - assert.Equal(t, options, ll.Options) + require.Equal(t, serviceID, ll.ServiceID) + require.Equal(t, options, ll.Options) } diff --git a/container/namespace_test.go b/container/namespace_test.go index 1c138303e..a853e1861 100644 --- a/container/namespace_test.go +++ b/container/namespace_test.go @@ -4,15 +4,15 @@ import ( "strings" "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestNamespace(t *testing.T) { namespace := Namespace([]string{"test"}) - assert.Equal(t, namespace, strings.Join([]string{namespacePrefix, "test"}, namespaceSeparator)) + require.Equal(t, namespace, strings.Join([]string{namespacePrefix, "test"}, namespaceSeparator)) } func TestNamespaceReplaceSpace(t *testing.T) { namespace := Namespace([]string{"test foo"}) - assert.Equal(t, namespace, strings.Join([]string{namespacePrefix, "test-foo"}, namespaceSeparator)) + require.Equal(t, namespace, strings.Join([]string{namespacePrefix, "test-foo"}, namespaceSeparator)) } diff --git a/container/network_integration_test.go b/container/network_integration_test.go index 49c9e660f..4124852b3 100644 --- a/container/network_integration_test.go +++ b/container/network_integration_test.go @@ -5,65 +5,65 @@ package container import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestIntegrationCreateNetwork(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) networkID, err := c.CreateNetwork([]string{"TestCreateNetwork"}) defer c.DeleteNetwork([]string{"TestCreateNetwork"}) - assert.Nil(t, err) - assert.NotEqual(t, "", networkID) + require.Nil(t, err) + require.NotEqual(t, "", networkID) } func TestIntegrationCreateAlreadyExistingNetwork(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) c.CreateNetwork([]string{"TestCreateAlreadyExistingNetwork"}) networkID, err := c.CreateNetwork([]string{"TestCreateAlreadyExistingNetwork"}) defer c.DeleteNetwork([]string{"TestCreateAlreadyExistingNetwork"}) - assert.Nil(t, err) - assert.NotEqual(t, "", networkID) + require.Nil(t, err) + require.NotEqual(t, "", networkID) } func TestIntegrationDeleteNetwork(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) c.CreateNetwork([]string{"TestDeleteNetwork"}) err = c.DeleteNetwork([]string{"TestDeleteNetwork"}) - assert.Nil(t, err) + require.Nil(t, err) } func TestIntegrationDeleteNotExistingNetwork(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) err = c.DeleteNetwork([]string{"TestDeleteNotExistingNetwork"}) - assert.Nil(t, err) + require.Nil(t, err) } func TestIntegrationFindNetwork(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) c.CreateNetwork([]string{"TestFindNetwork"}) defer c.DeleteNetwork([]string{"TestFindNetwork"}) network, err := c.FindNetwork([]string{"TestFindNetwork"}) - assert.Nil(t, err) - assert.NotEqual(t, "", network.ID) + require.Nil(t, err) + require.NotEqual(t, "", network.ID) } func TestIntegrationFindNotExistingNetwork(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) _, err = c.FindNetwork([]string{"TestFindNotExistingNetwork"}) - assert.NotNil(t, err) + require.NotNil(t, err) } func TestIntegrationFindDeletedNetwork(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) c.CreateNetwork([]string{"TestFindDeletedNetwork"}) c.DeleteNetwork([]string{"TestFindDeletedNetwork"}) _, err = c.FindNetwork([]string{"TestFindDeletedNetwork"}) - assert.NotNil(t, err) + require.NotNil(t, err) } diff --git a/container/network_test.go b/container/network_test.go index 53a644702..bbeee8d82 100644 --- a/container/network_test.go +++ b/container/network_test.go @@ -6,7 +6,7 @@ import ( "github.com/docker/docker/api/types" "github.com/mesg-foundation/core/container/dockertest" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestCreateNetwork(t *testing.T) { @@ -24,12 +24,12 @@ func TestCreateNetwork(t *testing.T) { dt.ProvideNetworkInspect(types.NetworkResource{}, nil) networkID, err := c.CreateNetwork(namespace) - assert.Nil(t, err) - assert.Equal(t, id, networkID) + require.Nil(t, err) + require.Equal(t, id, networkID) li := <-dt.LastNetworkCreate() - assert.Equal(t, Namespace(namespace), li.Name) - assert.Equal(t, types.NetworkCreate{ + require.Equal(t, Namespace(namespace), li.Name) + require.Equal(t, types.NetworkCreate{ CheckDuplicate: true, Driver: "overlay", Labels: map[string]string{ @@ -52,12 +52,12 @@ func TestCreateAlreadyExistingNetwork(t *testing.T) { dt.ProvideNetworkInspect(types.NetworkResource{ID: id}, nil) networkID, err := c.CreateNetwork(namespace) - assert.Nil(t, err) - assert.Equal(t, id, networkID) + require.Nil(t, err) + require.Equal(t, id, networkID) li := <-dt.LastNetworkInspect() - assert.Equal(t, Namespace(namespace), li.Network) - assert.Equal(t, types.NetworkInspectOptions{}, li.Options) + require.Equal(t, Namespace(namespace), li.Network) + require.Equal(t, types.NetworkInspectOptions{}, li.Options) select { case <-dt.LastNetworkCreate(): @@ -79,13 +79,13 @@ func TestDeleteNetwork(t *testing.T) { dt.ProvideNetworkInspect(types.NetworkResource{ID: id}, nil) - assert.Nil(t, c.DeleteNetwork(namespace)) + require.Nil(t, c.DeleteNetwork(namespace)) li := <-dt.LastNetworkInspect() - assert.Equal(t, Namespace(namespace), li.Network) - assert.Equal(t, types.NetworkInspectOptions{}, li.Options) + require.Equal(t, Namespace(namespace), li.Network) + require.Equal(t, types.NetworkInspectOptions{}, li.Options) - assert.Equal(t, id, (<-dt.LastNetworkRemove()).Network) + require.Equal(t, id, (<-dt.LastNetworkRemove()).Network) } func TestDeleteNotExistingNetwork(t *testing.T) { @@ -100,7 +100,7 @@ func TestDeleteNotExistingNetwork(t *testing.T) { dt.ProvideNetworkInspect(types.NetworkResource{}, dockertest.NotFoundErr{}) - assert.Nil(t, c.DeleteNetwork(namespace)) + require.Nil(t, c.DeleteNetwork(namespace)) select { case <-dt.LastNetworkRemove(): @@ -123,7 +123,7 @@ func TestDeleteNetworkError(t *testing.T) { dt.ProvideNetworkInspect(types.NetworkResource{}, errNetworkDelete) - assert.NotNil(t, c.DeleteNetwork(namespace)) + require.NotNil(t, c.DeleteNetwork(namespace)) } func TestFindNetwork(t *testing.T) { @@ -140,12 +140,12 @@ func TestFindNetwork(t *testing.T) { dt.ProvideNetworkInspect(types.NetworkResource{ID: id}, nil) network, err := c.FindNetwork(namespace) - assert.Nil(t, err) - assert.Equal(t, id, network.ID) + require.Nil(t, err) + require.Equal(t, id, network.ID) li := <-dt.LastNetworkInspect() - assert.Equal(t, Namespace(namespace), li.Network) - assert.Equal(t, types.NetworkInspectOptions{}, li.Options) + require.Equal(t, Namespace(namespace), li.Network) + require.Equal(t, types.NetworkInspectOptions{}, li.Options) } func TestFindNotExistingNetwork(t *testing.T) { @@ -161,5 +161,5 @@ func TestFindNotExistingNetwork(t *testing.T) { dt.ProvideNetworkInspect(types.NetworkResource{}, dockertest.NotFoundErr{}) _, err := c.FindNetwork(namespace) - assert.Equal(t, dockertest.NotFoundErr{}, err) + require.Equal(t, dockertest.NotFoundErr{}, err) } diff --git a/container/service_integration_test.go b/container/service_integration_test.go index 7f016d388..a01ef637c 100644 --- a/container/service_integration_test.go +++ b/container/service_integration_test.go @@ -5,7 +5,7 @@ package container import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func startTestService(name []string) (string, error) { @@ -21,97 +21,97 @@ func startTestService(name []string) (string, error) { func TestIntegrationStartService(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestStartService"} serviceID, err := startTestService(namespace) defer c.StopService(namespace) - assert.Nil(t, err) - assert.NotEqual(t, "", serviceID) + require.Nil(t, err) + require.NotEqual(t, "", serviceID) } func TestIntegrationStartService2Times(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestStartService2Times"} startTestService(namespace) defer c.StopService(namespace) serviceID, err := startTestService(namespace) - assert.NotNil(t, err) - assert.Equal(t, "", serviceID) + require.NotNil(t, err) + require.Equal(t, "", serviceID) } func TestIntegrationStopService(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestStopService"} startTestService(namespace) err = c.StopService(namespace) - assert.Nil(t, err) + require.Nil(t, err) } func TestIntegrationStopNotExistingService(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestStopNotExistingService"} err = c.StopService(namespace) - assert.Nil(t, err) + require.Nil(t, err) } func TestIntegrationServiceStatusNeverStarted(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestServiceStatusNeverStarted"} status, err := c.ServiceStatus(namespace) - assert.Nil(t, err) - assert.NotEqual(t, RUNNING, status) - assert.Equal(t, STOPPED, status) + require.Nil(t, err) + require.NotEqual(t, RUNNING, status) + require.Equal(t, STOPPED, status) } func TestIntegrationServiceStatusRunning(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestServiceStatusRunning"} startTestService(namespace) defer c.StopService(namespace) status, err := c.ServiceStatus(namespace) - assert.Nil(t, err) - assert.Equal(t, status, RUNNING) - assert.NotEqual(t, status, STOPPED) + require.Nil(t, err) + require.Equal(t, status, RUNNING) + require.NotEqual(t, status, STOPPED) } func TestIntegrationServiceStatusStopped(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestServiceStatusStopped"} startTestService(namespace) c.StopService(namespace) status, err := c.ServiceStatus(namespace) - assert.Nil(t, err) - assert.Equal(t, status, STOPPED) - assert.NotEqual(t, status, RUNNING) + require.Nil(t, err) + require.Equal(t, status, STOPPED) + require.NotEqual(t, status, RUNNING) } func TestIntegrationFindServiceNotExisting(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) _, err = c.FindService([]string{"TestFindServiceNotExisting"}) - assert.NotNil(t, err) + require.NotNil(t, err) } func TestIntegrationFindService(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestFindService"} startTestService(namespace) defer c.StopService(namespace) service, err := c.FindService(namespace) - assert.Nil(t, err) - assert.NotEqual(t, "", service.ID) + require.Nil(t, err) + require.NotEqual(t, "", service.ID) } func TestIntegrationFindServiceCloseName(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestFindServiceCloseName", "name"} namespace1 := []string{"TestFindServiceCloseName", "name2"} startTestService(namespace) @@ -119,23 +119,23 @@ func TestIntegrationFindServiceCloseName(t *testing.T) { startTestService(namespace1) defer c.StopService(namespace1) service, err := c.FindService(namespace) - assert.Nil(t, err) - assert.NotEqual(t, "", service.ID) + require.Nil(t, err) + require.NotEqual(t, "", service.ID) } func TestIntegrationFindServiceStopped(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestFindServiceStopped"} startTestService(namespace) c.StopService(namespace) _, err = c.FindService(namespace) - assert.NotNil(t, err) + require.NotNil(t, err) } func TestIntegrationListServices(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) c.StartService(ServiceOptions{ Image: "nginx", Namespace: []string{"TestListServices"}, @@ -153,18 +153,18 @@ func TestIntegrationListServices(t *testing.T) { defer c.StopService([]string{"TestListServices"}) defer c.StopService([]string{"TestListServiceswithValue2"}) services, err := c.ListServices("label_name") - assert.Nil(t, err) - assert.Equal(t, 1, len(services)) - assert.Equal(t, Namespace([]string{"TestListServices"}), services[0].Spec.Name) + require.Nil(t, err) + require.Equal(t, 1, len(services)) + require.Equal(t, Namespace([]string{"TestListServices"}), services[0].Spec.Name) } func TestIntegrationServiceLogs(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestServiceLogs"} startTestService(namespace) defer c.StopService(namespace) reader, err := c.ServiceLogs(namespace) - assert.Nil(t, err) - assert.NotNil(t, reader) + require.Nil(t, err) + require.NotNil(t, reader) } diff --git a/container/service_options_test.go b/container/service_options_test.go index 7ee3207bc..79ba1bd06 100644 --- a/container/service_options_test.go +++ b/container/service_options_test.go @@ -3,7 +3,7 @@ package container import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestServiceOptionNamespace(t *testing.T) { @@ -13,9 +13,9 @@ func TestServiceOptionNamespace(t *testing.T) { } expectedNamespace := Namespace(namespace) service := options.toSwarmServiceSpec() - assert.Equal(t, expectedNamespace, service.Annotations.Name) - assert.Equal(t, expectedNamespace, service.Annotations.Labels["com.docker.stack.namespace"]) - assert.Equal(t, expectedNamespace, service.TaskTemplate.ContainerSpec.Labels["com.docker.stack.namespace"]) + require.Equal(t, expectedNamespace, service.Annotations.Name) + require.Equal(t, expectedNamespace, service.Annotations.Labels["com.docker.stack.namespace"]) + require.Equal(t, expectedNamespace, service.TaskTemplate.ContainerSpec.Labels["com.docker.stack.namespace"]) } func TestServiceOptionImage(t *testing.T) { @@ -24,8 +24,8 @@ func TestServiceOptionImage(t *testing.T) { Image: image, } service := options.toSwarmServiceSpec() - assert.Equal(t, image, service.Annotations.Labels["com.docker.stack.image"]) - assert.Equal(t, image, service.TaskTemplate.ContainerSpec.Image) + require.Equal(t, image, service.Annotations.Labels["com.docker.stack.image"]) + require.Equal(t, image, service.TaskTemplate.ContainerSpec.Image) } func TestServiceOptionMergeLabels(t *testing.T) { @@ -39,10 +39,10 @@ func TestServiceOptionMergeLabels(t *testing.T) { "label4": "bar", } labels := mergeLabels(l1, l2) - assert.Equal(t, "foo", labels["label1"]) - assert.Equal(t, "foo", labels["label2"]) - assert.Equal(t, "foo", labels["label3"]) - assert.Equal(t, "bar", labels["label4"]) + require.Equal(t, "foo", labels["label1"]) + require.Equal(t, "foo", labels["label2"]) + require.Equal(t, "foo", labels["label3"]) + require.Equal(t, "bar", labels["label4"]) } func TestServiceOptionLabels(t *testing.T) { @@ -53,8 +53,8 @@ func TestServiceOptionLabels(t *testing.T) { }, } service := options.toSwarmServiceSpec() - assert.Equal(t, "foo", service.Annotations.Labels["label1"]) - assert.Equal(t, "bar", service.Annotations.Labels["label2"]) + require.Equal(t, "foo", service.Annotations.Labels["label1"]) + require.Equal(t, "bar", service.Annotations.Labels["label2"]) } func TestServiceOptionPorts(t *testing.T) { @@ -71,11 +71,11 @@ func TestServiceOptionPorts(t *testing.T) { }, } ports := options.swarmPorts() - assert.Equal(t, 2, len(ports)) - assert.Equal(t, uint32(50503), ports[0].PublishedPort) - assert.Equal(t, uint32(50501), ports[0].TargetPort) - assert.Equal(t, uint32(30503), ports[1].PublishedPort) - assert.Equal(t, uint32(30501), ports[1].TargetPort) + require.Equal(t, 2, len(ports)) + require.Equal(t, uint32(50503), ports[0].PublishedPort) + require.Equal(t, uint32(50501), ports[0].TargetPort) + require.Equal(t, uint32(30503), ports[1].PublishedPort) + require.Equal(t, uint32(30501), ports[1].TargetPort) } func TestServiceOptionMounts(t *testing.T) { @@ -88,9 +88,9 @@ func TestServiceOptionMounts(t *testing.T) { }, } mounts := options.swarmMounts(true) - assert.Equal(t, 1, len(mounts)) - assert.Equal(t, "source/file", mounts[0].Source) - assert.Equal(t, "target/file", mounts[0].Target) + require.Equal(t, 1, len(mounts)) + require.Equal(t, "source/file", mounts[0].Source) + require.Equal(t, "target/file", mounts[0].Target) } func TestServiceOptionEnv(t *testing.T) { @@ -99,9 +99,9 @@ func TestServiceOptionEnv(t *testing.T) { } service := options.toSwarmServiceSpec() env := service.TaskTemplate.ContainerSpec.Env - assert.Equal(t, 2, len(env)) - assert.Equal(t, "env1", env[0]) - assert.Equal(t, "env2", env[1]) + require.Equal(t, 2, len(env)) + require.Equal(t, "env1", env[0]) + require.Equal(t, "env2", env[1]) } func TestServiceOptionNetworks(t *testing.T) { @@ -109,9 +109,9 @@ func TestServiceOptionNetworks(t *testing.T) { NetworksID: []string{"network1", "network2"}, } networks := options.swarmNetworks() - assert.Equal(t, 2, len(networks)) - assert.Equal(t, "network1", networks[0].Target) - assert.Equal(t, "network2", networks[1].Target) + require.Equal(t, 2, len(networks)) + require.Equal(t, "network1", networks[0].Target) + require.Equal(t, "network2", networks[1].Target) } func contains(list []string, item string) bool { @@ -128,6 +128,6 @@ func TestMapToEnv(t *testing.T) { "first": "first_value", "second": "second_value", }) - assert.True(t, contains(env, "first=first_value")) - assert.True(t, contains(env, "second=second_value")) + require.True(t, contains(env, "first=first_value")) + require.True(t, contains(env, "second=second_value")) } diff --git a/container/service_test.go b/container/service_test.go index 5f06c98b9..8da608d03 100644 --- a/container/service_test.go +++ b/container/service_test.go @@ -9,7 +9,7 @@ import ( "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/swarm" "github.com/mesg-foundation/core/container/dockertest" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestStartService(t *testing.T) { @@ -26,12 +26,12 @@ func TestStartService(t *testing.T) { dt.ProvideServiceCreate(types.ServiceCreateResponse{ID: containerID}, nil) id, err := c.StartService(options) - assert.Nil(t, err) - assert.Equal(t, containerID, id) + require.Nil(t, err) + require.Equal(t, containerID, id) ls := <-dt.LastServiceCreate() - assert.Equal(t, options.toSwarmServiceSpec(), ls.Service) - assert.Equal(t, types.ServiceCreateOptions{}, ls.Options) + require.Equal(t, options.toSwarmServiceSpec(), ls.Service) + require.Equal(t, types.ServiceCreateOptions{}, ls.Options) } func TestStopService(t *testing.T) { @@ -49,13 +49,13 @@ func TestStopService(t *testing.T) { dt.ProvideContainerList(containerData, nil) dt.ProvideContainerInspect(containerJSONData, nil) - assert.Nil(t, c.StopService(namespace)) + require.Nil(t, c.StopService(namespace)) li := <-dt.LastServiceInspectWithRaw() - assert.Equal(t, Namespace(namespace), li.ServiceID) - assert.Equal(t, types.ServiceInspectOptions{}, li.Options) + require.Equal(t, Namespace(namespace), li.ServiceID) + require.Equal(t, types.ServiceInspectOptions{}, li.Options) - assert.Equal(t, Namespace(namespace), (<-dt.LastServiceRemove()).ServiceID) + require.Equal(t, Namespace(namespace), (<-dt.LastServiceRemove()).ServiceID) } func TestStopNotExistingService(t *testing.T) { @@ -66,11 +66,11 @@ func TestStopNotExistingService(t *testing.T) { dt.ProvideServiceInspectWithRaw(swarm.Service{}, nil, dockertest.NotFoundErr{}) - assert.Nil(t, c.StopService(namespace)) + require.Nil(t, c.StopService(namespace)) li := <-dt.LastServiceInspectWithRaw() - assert.Equal(t, Namespace(namespace), li.ServiceID) - assert.Equal(t, types.ServiceInspectOptions{}, li.Options) + require.Equal(t, Namespace(namespace), li.ServiceID) + require.Equal(t, types.ServiceInspectOptions{}, li.Options) select { case <-dt.LastServiceRemove(): @@ -88,12 +88,12 @@ func TestServiceStatusNeverStarted(t *testing.T) { dt.ProvideServiceInspectWithRaw(swarm.Service{}, nil, dockertest.NotFoundErr{}) status, err := c.ServiceStatus(namespace) - assert.Nil(t, err) - assert.Equal(t, STOPPED, status) + require.Nil(t, err) + require.Equal(t, STOPPED, status) li := <-dt.LastServiceInspectWithRaw() - assert.Equal(t, Namespace(namespace), li.ServiceID) - assert.Equal(t, types.ServiceInspectOptions{}, li.Options) + require.Equal(t, Namespace(namespace), li.ServiceID) + require.Equal(t, types.ServiceInspectOptions{}, li.Options) } func TestServiceStatusRunning(t *testing.T) { @@ -103,12 +103,12 @@ func TestServiceStatusRunning(t *testing.T) { c, _ := New(ClientOption(dt.Client())) status, err := c.ServiceStatus(namespace) - assert.Nil(t, err) - assert.Equal(t, RUNNING, status) + require.Nil(t, err) + require.Equal(t, RUNNING, status) li := <-dt.LastServiceInspectWithRaw() - assert.Equal(t, Namespace(namespace), li.ServiceID) - assert.Equal(t, types.ServiceInspectOptions{}, li.Options) + require.Equal(t, Namespace(namespace), li.ServiceID) + require.Equal(t, types.ServiceInspectOptions{}, li.Options) } func TestFindService(t *testing.T) { @@ -121,12 +121,12 @@ func TestFindService(t *testing.T) { dt.ProvideServiceInspectWithRaw(swarmService, nil, nil) service, err := c.FindService(namespace) - assert.Nil(t, err) - assert.Equal(t, swarmService.ID, service.ID) + require.Nil(t, err) + require.Equal(t, swarmService.ID, service.ID) li := <-dt.LastServiceInspectWithRaw() - assert.Equal(t, Namespace(namespace), li.ServiceID) - assert.Equal(t, types.ServiceInspectOptions{}, li.Options) + require.Equal(t, Namespace(namespace), li.ServiceID) + require.Equal(t, types.ServiceInspectOptions{}, li.Options) } func TestFindServiceNotExisting(t *testing.T) { @@ -138,11 +138,11 @@ func TestFindServiceNotExisting(t *testing.T) { dt.ProvideServiceInspectWithRaw(swarm.Service{}, nil, dockertest.NotFoundErr{}) _, err := c.FindService(namespace) - assert.Equal(t, dockertest.NotFoundErr{}, err) + require.Equal(t, dockertest.NotFoundErr{}, err) li := <-dt.LastServiceInspectWithRaw() - assert.Equal(t, Namespace(namespace), li.ServiceID) - assert.Equal(t, types.ServiceInspectOptions{}, li.Options) + require.Equal(t, Namespace(namespace), li.ServiceID) + require.Equal(t, types.ServiceInspectOptions{}, li.Options) } func TestListServices(t *testing.T) { @@ -160,12 +160,12 @@ func TestListServices(t *testing.T) { dt.ProvideServiceList(swarmServices, nil) services, err := c.ListServices(label) - assert.Nil(t, err) - assert.Equal(t, 2, len(services)) - assert.Equal(t, Namespace(namespace), services[0].Spec.Name) - assert.Equal(t, Namespace(namespace1), services[1].Spec.Name) + require.Nil(t, err) + require.Equal(t, 2, len(services)) + require.Equal(t, Namespace(namespace), services[0].Spec.Name) + require.Equal(t, Namespace(namespace1), services[1].Spec.Name) - assert.Equal(t, types.ServiceListOptions{ + require.Equal(t, types.ServiceListOptions{ Filters: filters.NewArgs(filters.KeyValuePair{ Key: "label", Value: label, @@ -183,16 +183,16 @@ func TestServiceLogs(t *testing.T) { dt.ProvideServiceLogs(ioutil.NopCloser(bytes.NewReader(data)), nil) reader, err := c.ServiceLogs(namespace) - assert.Nil(t, err) + require.Nil(t, err) defer reader.Close() bytes, err := ioutil.ReadAll(reader) - assert.Nil(t, err) - assert.Equal(t, data, bytes) + require.Nil(t, err) + require.Equal(t, data, bytes) ll := <-dt.LastServiceLogs() - assert.Equal(t, Namespace(namespace), ll.ServiceID) - assert.Equal(t, types.ContainerLogsOptions{ + require.Equal(t, Namespace(namespace), ll.ServiceID) + require.Equal(t, types.ContainerLogsOptions{ ShowStdout: true, ShowStderr: true, Timestamps: false, diff --git a/container/shared_network_integration_test.go b/container/shared_network_integration_test.go index b00699f15..8a8e879f8 100644 --- a/container/shared_network_integration_test.go +++ b/container/shared_network_integration_test.go @@ -7,7 +7,7 @@ import ( "testing" docker "github.com/docker/docker/client" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func removeSharedNetworkIfExist(c *Container) error { @@ -22,25 +22,25 @@ func removeSharedNetworkIfExist(c *Container) error { func TestIntegrationCreateSharedNetworkIfNeeded(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) err = removeSharedNetworkIfExist(c) - assert.Nil(t, err) + require.Nil(t, err) err = c.createSharedNetworkIfNeeded() - assert.Nil(t, err) + require.Nil(t, err) } func TestIntegrationSharedNetwork(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) network, err := c.sharedNetwork() - assert.Nil(t, err) - assert.NotEqual(t, "", network.ID) + require.Nil(t, err) + require.NotEqual(t, "", network.ID) } func TestIntegrationSharedNetworkID(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) networkID, err := c.SharedNetworkID() - assert.Nil(t, err) - assert.NotEqual(t, "", networkID) + require.Nil(t, err) + require.NotEqual(t, "", networkID) } diff --git a/container/shared_network_test.go b/container/shared_network_test.go index bc763fad4..7b60e4705 100644 --- a/container/shared_network_test.go +++ b/container/shared_network_test.go @@ -5,7 +5,7 @@ import ( "github.com/docker/docker/api/types" "github.com/mesg-foundation/core/container/dockertest" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestSharedNetwork(t *testing.T) { @@ -21,12 +21,12 @@ func TestSharedNetwork(t *testing.T) { dt.ProvideNetworkInspect(types.NetworkResource{ID: id}, nil) network, err := c.sharedNetwork() - assert.Nil(t, err) - assert.Equal(t, id, network.ID) + require.Nil(t, err) + require.Equal(t, id, network.ID) li := <-dt.LastNetworkInspect() - assert.Equal(t, Namespace(sharedNetworkNamespace), li.Network) - assert.Equal(t, types.NetworkInspectOptions{}, li.Options) + require.Equal(t, Namespace(sharedNetworkNamespace), li.Network) + require.Equal(t, types.NetworkInspectOptions{}, li.Options) } func TestCreateSharedNetworkIfNeeded(t *testing.T) { @@ -39,11 +39,11 @@ func TestCreateSharedNetworkIfNeeded(t *testing.T) { dt.ProvideNetworkInspect(types.NetworkResource{}, nil) - assert.Nil(t, c.createSharedNetworkIfNeeded()) + require.Nil(t, c.createSharedNetworkIfNeeded()) lc := <-dt.LastNetworkCreate() - assert.Equal(t, Namespace(sharedNetworkNamespace), lc.Name) - assert.Equal(t, types.NetworkCreate{ + require.Equal(t, Namespace(sharedNetworkNamespace), lc.Name) + require.Equal(t, types.NetworkCreate{ CheckDuplicate: true, Driver: "overlay", Labels: map[string]string{ @@ -64,7 +64,7 @@ func TestCreateSharedNetworkIfNeededExists(t *testing.T) { dt.ProvideNetworkInspect(types.NetworkResource{ID: id}, nil) - assert.Nil(t, c.createSharedNetworkIfNeeded()) + require.Nil(t, c.createSharedNetworkIfNeeded()) select { case <-dt.LastNetworkCreate(): @@ -85,10 +85,10 @@ func TestSharedNetworkID(t *testing.T) { dt.ProvideNetworkInspect(types.NetworkResource{ID: id}, nil) network, err := c.SharedNetworkID() - assert.Nil(t, err) - assert.Equal(t, network, id) + require.Nil(t, err) + require.Equal(t, network, id) li := <-dt.LastNetworkInspect() - assert.Equal(t, Namespace(sharedNetworkNamespace), li.Network) - assert.Equal(t, types.NetworkInspectOptions{}, li.Options) + require.Equal(t, Namespace(sharedNetworkNamespace), li.Network) + require.Equal(t, types.NetworkInspectOptions{}, li.Options) } diff --git a/container/task_integration_test.go b/container/task_integration_test.go index 9e0129bc9..c2c7e2b62 100644 --- a/container/task_integration_test.go +++ b/container/task_integration_test.go @@ -6,24 +6,24 @@ import ( "testing" "time" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestIntegrationListTasks(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestListTasks"} startTestService(namespace) defer c.StopService(namespace) tasks, err := c.ListTasks(namespace) - assert.Nil(t, err) - assert.NotNil(t, tasks) - assert.Equal(t, 1, len(tasks)) + require.Nil(t, err) + require.NotNil(t, tasks) + require.Equal(t, 1, len(tasks)) } func TestIntegrationTasksError(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestTasksError"} c.StartService(ServiceOptions{ Image: "fiifioewifewiewfifewijopwjeokpfeo", @@ -38,8 +38,8 @@ func TestIntegrationTasksError(t *testing.T) { } time.Sleep(500 * time.Millisecond) } - assert.Nil(t, err) - assert.NotNil(t, errors) - assert.True(t, len(errors) > 0) - assert.Equal(t, "No such image: fiifioewifewiewfifewijopwjeokpfeo:latest", errors[0]) + require.Nil(t, err) + require.NotNil(t, errors) + require.True(t, len(errors) > 0) + require.Equal(t, "No such image: fiifioewifewiewfifewijopwjeokpfeo:latest", errors[0]) } diff --git a/container/task_test.go b/container/task_test.go index 4270d08e5..1ac41f494 100644 --- a/container/task_test.go +++ b/container/task_test.go @@ -8,7 +8,7 @@ import ( "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/swarm" "github.com/mesg-foundation/core/container/dockertest" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestListTasks(t *testing.T) { @@ -24,11 +24,11 @@ func TestListTasks(t *testing.T) { dt.ProvideTaskList(tasks, nil) tasks1, err := c.ListTasks(namespace) - assert.Nil(t, err) - assert.Equal(t, tasks, tasks1) - assert.Equal(t, len(tasks), len(tasks1)) + require.Nil(t, err) + require.Equal(t, tasks, tasks1) + require.Equal(t, len(tasks), len(tasks1)) - assert.Equal(t, types.TaskListOptions{ + require.Equal(t, types.TaskListOptions{ Filters: filters.NewArgs(filters.KeyValuePair{ Key: "label", Value: "com.docker.stack.namespace=" + Namespace(namespace), @@ -47,7 +47,7 @@ func TestListTasksError(t *testing.T) { dt.ProvideTaskList(nil, errTaskList) _, err := c.ListTasks(namespace) - assert.Equal(t, errTaskList, err) + require.Equal(t, errTaskList, err) } func TestTasksError(t *testing.T) { @@ -69,8 +69,8 @@ func TestTasksError(t *testing.T) { dt.ProvideTaskList(tasks, nil) errors, err := c.TasksError(namespace) - assert.Nil(t, err) - assert.Equal(t, len(tasks), len(errors)) - assert.Equal(t, tasks[0].Status.Err, errors[0]) - assert.Equal(t, tasks[1].Status.Err, errors[1]) + require.Nil(t, err) + require.Equal(t, len(tasks), len(errors)) + require.Equal(t, tasks[0].Status.Err, errors[0]) + require.Equal(t, tasks[1].Status.Err, errors[1]) } diff --git a/container/wait_integration_test.go b/container/wait_integration_test.go index 3f6af97b1..5ef38a79e 100644 --- a/container/wait_integration_test.go +++ b/container/wait_integration_test.go @@ -5,33 +5,33 @@ package container import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestIntegrationWaitForStatusRunning(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestWaitForStatusRunning"} startTestService(namespace) defer c.StopService(namespace) err = c.waitForStatus(namespace, RUNNING) - assert.Nil(t, err) + require.Nil(t, err) } func TestIntegrationWaitForStatusStopped(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestWaitForStatusStopped"} startTestService(namespace) c.waitForStatus(namespace, RUNNING) c.StopService(namespace) err = c.waitForStatus(namespace, STOPPED) - assert.Nil(t, err) + require.Nil(t, err) } func TestIntegrationWaitForStatusTaskError(t *testing.T) { c, err := New() - assert.Nil(t, err) + require.Nil(t, err) namespace := []string{"TestWaitForStatusTaskError"} c.StartService(ServiceOptions{ Image: "awgdaywudaywudwa", @@ -39,6 +39,6 @@ func TestIntegrationWaitForStatusTaskError(t *testing.T) { }) defer c.StopService(namespace) err = c.waitForStatus(namespace, RUNNING) - assert.NotNil(t, err) - assert.Equal(t, "No such image: awgdaywudaywudwa:latest", err.Error()) + require.NotNil(t, err) + require.Equal(t, "No such image: awgdaywudaywudwa:latest", err.Error()) } diff --git a/container/wait_test.go b/container/wait_test.go index 1174622be..2a803ff81 100644 --- a/container/wait_test.go +++ b/container/wait_test.go @@ -6,7 +6,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/swarm" "github.com/mesg-foundation/core/container/dockertest" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestWaitForStatusRunning(t *testing.T) { @@ -28,7 +28,7 @@ func TestWaitForStatusRunning(t *testing.T) { dt.ProvideContainerList(containerData, nil) dt.ProvideContainerInspect(containerJSONData, nil) - assert.Nil(t, c.waitForStatus(namespace, RUNNING)) + require.Nil(t, c.waitForStatus(namespace, RUNNING)) } func TestWaitForStatusStopped(t *testing.T) { @@ -50,7 +50,7 @@ func TestWaitForStatusStopped(t *testing.T) { dt.ProvideContainerList(containerData, nil) dt.ProvideContainerInspect(containerJSONData, nil) - assert.Nil(t, c.waitForStatus(namespace, STOPPED)) + require.Nil(t, c.waitForStatus(namespace, STOPPED)) } func TestWaitForStatusTaskError(t *testing.T) { @@ -71,7 +71,7 @@ func TestWaitForStatusTaskError(t *testing.T) { dt.ProvideTaskList(tasks, nil) - assert.Equal(t, "1-err, 2-err", c.waitForStatus(namespace, RUNNING).Error()) + require.Equal(t, "1-err, 2-err", c.waitForStatus(namespace, RUNNING).Error()) select { case <-dt.LastContainerList(): diff --git a/daemon/logs_test.go b/daemon/logs_test.go index 0b3a420b0..47dac8b85 100644 --- a/daemon/logs_test.go +++ b/daemon/logs_test.go @@ -3,12 +3,12 @@ package daemon import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestLogs(t *testing.T) { startForTest() reader, err := Logs() - assert.Nil(t, err) - assert.NotNil(t, reader) + require.Nil(t, err) + require.NotNil(t, reader) } diff --git a/daemon/start_test.go b/daemon/start_test.go index dbddaa9e7..434c5f3c3 100644 --- a/daemon/start_test.go +++ b/daemon/start_test.go @@ -7,7 +7,7 @@ import ( "github.com/mesg-foundation/core/config" "github.com/mesg-foundation/core/container" "github.com/spf13/viper" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) // startForTest starts a dummy MESG Core service @@ -37,8 +37,8 @@ func startForTest() { // func TestStart(t *testing.T) { // <-testForceAndWaitForFullStop() // service, err := Start() -// assert.Nil(t, err) -// assert.NotNil(t, service) +// require.Nil(t, err) +// require.NotNil(t, service) // } func contains(list []string, item string) bool { @@ -52,18 +52,18 @@ func contains(list []string, item string) bool { func TestStartConfig(t *testing.T) { spec, err := serviceSpec() - assert.Nil(t, err) + require.Nil(t, err) // Make sure that the config directory is passed in parameter to write on the same folder - assert.True(t, contains(spec.Env, "MESG_MESG_PATH=/mesg")) - assert.True(t, contains(spec.Env, "MESG_API_SERVICE_SOCKETPATH="+filepath.Join(viper.GetString(config.MESGPath), "server.sock"))) - assert.True(t, contains(spec.Env, "MESG_SERVICE_PATH_HOST="+filepath.Join(viper.GetString(config.MESGPath), "services"))) + require.True(t, contains(spec.Env, "MESG_MESG_PATH=/mesg")) + require.True(t, contains(spec.Env, "MESG_API_SERVICE_SOCKETPATH="+filepath.Join(viper.GetString(config.MESGPath), "server.sock"))) + require.True(t, contains(spec.Env, "MESG_SERVICE_PATH_HOST="+filepath.Join(viper.GetString(config.MESGPath), "services"))) // Ensure that the port is shared - assert.Equal(t, spec.Ports[0].Published, uint32(50052)) - assert.Equal(t, spec.Ports[0].Target, uint32(50052)) + require.Equal(t, spec.Ports[0].Published, uint32(50052)) + require.Equal(t, spec.Ports[0].Target, uint32(50052)) // Ensure that the docker socket is shared in the core - assert.Equal(t, spec.Mounts[0].Source, dockerSocket) - assert.Equal(t, spec.Mounts[0].Target, dockerSocket) + require.Equal(t, spec.Mounts[0].Source, dockerSocket) + require.Equal(t, spec.Mounts[0].Target, dockerSocket) // Ensure that the host users folder is sync with the core - assert.Equal(t, spec.Mounts[1].Source, viper.GetString(config.MESGPath)) - assert.Equal(t, spec.Mounts[1].Target, "/mesg") + require.Equal(t, spec.Mounts[1].Source, viper.GetString(config.MESGPath)) + require.Equal(t, spec.Mounts[1].Target, "/mesg") } diff --git a/daemon/status_test.go b/daemon/status_test.go index 7611a8c7a..324f7df95 100644 --- a/daemon/status_test.go +++ b/daemon/status_test.go @@ -6,7 +6,7 @@ import ( "time" "github.com/mesg-foundation/core/container" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func testForceAndWaitForFullStop() chan error { @@ -43,13 +43,13 @@ func testForceAndWaitForFullStop() chan error { func TestIsNotRunning(t *testing.T) { <-testForceAndWaitForFullStop() status, err := Status() - assert.Nil(t, err) - assert.Equal(t, container.STOPPED, status) + require.Nil(t, err) + require.Equal(t, container.STOPPED, status) } func TestIsRunning(t *testing.T) { startForTest() status, err := Status() - assert.Nil(t, err) - assert.Equal(t, container.RUNNING, status) + require.Nil(t, err) + require.Equal(t, container.RUNNING, status) } diff --git a/daemon/stop_test.go b/daemon/stop_test.go index 68d2fd08a..631fe3e57 100644 --- a/daemon/stop_test.go +++ b/daemon/stop_test.go @@ -3,11 +3,11 @@ package daemon import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestStop(t *testing.T) { startForTest() err := Stop() - assert.Nil(t, err) + require.Nil(t, err) } diff --git a/database/services/all_test.go b/database/services/all_test.go index 5438622a3..ab4a1d7a3 100644 --- a/database/services/all_test.go +++ b/database/services/all_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestAll(t *testing.T) { @@ -18,6 +18,6 @@ func TestAll(t *testing.T) { break } } - assert.Nil(t, err) - assert.True(t, founded) + require.Nil(t, err) + require.True(t, founded) } diff --git a/database/services/db_test.go b/database/services/db_test.go index bb27c7bfa..f2bcb12be 100644 --- a/database/services/db_test.go +++ b/database/services/db_test.go @@ -5,14 +5,14 @@ import ( "testing" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestDb(t *testing.T) { db, err := open() defer close() - assert.Nil(t, err) - assert.NotNil(t, db) + require.Nil(t, err) + require.NotNil(t, db) } // Test to stress the database with concurrency access @@ -28,8 +28,8 @@ func TestConcurrency(t *testing.T) { wg.Add(1) go func() { s, err := Get(hash) - assert.Nil(t, err) - assert.Equal(t, s.Name, service.Name) + require.Nil(t, err) + require.Equal(t, s.Name, service.Name) wg.Done() }() } diff --git a/database/services/delete_test.go b/database/services/delete_test.go index d9bcbb7b1..b57c9b90b 100644 --- a/database/services/delete_test.go +++ b/database/services/delete_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestDelete(t *testing.T) { @@ -12,5 +12,5 @@ func TestDelete(t *testing.T) { Name: "TestDelete", }) err := Delete(hash) - assert.Nil(t, err) + require.Nil(t, err) } diff --git a/database/services/get_test.go b/database/services/get_test.go index 837f2682a..8559e5b5a 100644 --- a/database/services/get_test.go +++ b/database/services/get_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestGet(t *testing.T) { @@ -13,13 +13,13 @@ func TestGet(t *testing.T) { }) defer Delete(hash) service, err := Get(hash) - assert.Nil(t, err) - assert.Equal(t, service.Name, "TestGet") + require.Nil(t, err) + require.Equal(t, service.Name, "TestGet") } func TestGetMissing(t *testing.T) { emptyService := service.Service{} service, err := Get("hash_that_doesnt_exists") - assert.Equal(t, err, NotFound{Hash: "hash_that_doesnt_exists"}) - assert.Equal(t, service, emptyService) + require.Equal(t, err, NotFound{Hash: "hash_that_doesnt_exists"}) + require.Equal(t, service, emptyService) } diff --git a/database/services/save_test.go b/database/services/save_test.go index d2e9902b3..2d0de58ea 100644 --- a/database/services/save_test.go +++ b/database/services/save_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestSaveReturningHash(t *testing.T) { @@ -14,8 +14,8 @@ func TestSaveReturningHash(t *testing.T) { calculatedHash := service.Hash() hash, err := Save(service) defer Delete(hash) - assert.Nil(t, err) - assert.Equal(t, hash, calculatedHash) + require.Nil(t, err) + require.Equal(t, hash, calculatedHash) } func TestSaveAndPresentInDB(t *testing.T) { @@ -24,5 +24,5 @@ func TestSaveAndPresentInDB(t *testing.T) { }) defer Delete(hash) service, _ := Get(hash) - assert.Equal(t, service.Name, "TestSaveAndPresentInDB") + require.Equal(t, service.Name, "TestSaveAndPresentInDB") } diff --git a/event/event_test.go b/event/event_test.go index 89a4187fe..226e42176 100644 --- a/event/event_test.go +++ b/event/event_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestCreate(t *testing.T) { @@ -16,11 +16,11 @@ func TestCreate(t *testing.T) { } var data map[string]interface{} exec, err := Create(&s, "test", data) - assert.Nil(t, err) - assert.Equal(t, &s, exec.Service) - assert.Equal(t, data, exec.Data) - assert.Equal(t, "test", exec.Key) - assert.NotNil(t, exec.CreatedAt) + require.Nil(t, err) + require.Equal(t, &s, exec.Service) + require.Equal(t, data, exec.Data) + require.Equal(t, "test", exec.Key) + require.NotNil(t, exec.CreatedAt) } func TestCreateNotPresentEvent(t *testing.T) { @@ -32,9 +32,9 @@ func TestCreateNotPresentEvent(t *testing.T) { } var data map[string]interface{} _, err := Create(&s, "testinvalid", data) - assert.NotNil(t, err) + require.NotNil(t, err) _, notFound := err.(*service.EventNotFoundError) - assert.True(t, notFound) + require.True(t, notFound) } func TestCreateInvalidData(t *testing.T) { @@ -50,7 +50,7 @@ func TestCreateInvalidData(t *testing.T) { } var data map[string]interface{} _, err := Create(&s, "test", data) - assert.NotNil(t, err) + require.NotNil(t, err) _, invalid := err.(*service.InvalidEventDataError) - assert.True(t, invalid) + require.True(t, invalid) } diff --git a/execution/complete_test.go b/execution/complete_test.go index 9a9056e30..71a728ca8 100644 --- a/execution/complete_test.go +++ b/execution/complete_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestComplete(t *testing.T) { @@ -23,10 +23,10 @@ func TestComplete(t *testing.T) { execution.Execute() var outputs map[string]interface{} err := execution.Complete("output", outputs) - assert.Nil(t, err) - assert.Equal(t, execution.Output, "output") - assert.Equal(t, execution.OutputData, outputs) - assert.True(t, execution.ExecutionDuration > 0) + require.Nil(t, err) + require.Equal(t, execution.Output, "output") + require.Equal(t, execution.OutputData, outputs) + require.True(t, execution.ExecutionDuration > 0) } func TestCompleteNotFound(t *testing.T) { @@ -41,10 +41,10 @@ func TestCompleteNotFound(t *testing.T) { execution.Execute() var outputs map[string]interface{} err := execution.Complete("output", outputs) - assert.NotNil(t, err) + require.NotNil(t, err) x, missingOutputError := err.(*service.OutputNotFoundError) - assert.True(t, missingOutputError) - assert.Equal(t, "output", x.OutputKey) + require.True(t, missingOutputError) + require.Equal(t, "output", x.OutputKey) } func TestCompleteInvalidOutputs(t *testing.T) { @@ -67,10 +67,10 @@ func TestCompleteInvalidOutputs(t *testing.T) { execution.Execute() var outputs map[string]interface{} err := execution.Complete("output", outputs) - assert.NotNil(t, err) + require.NotNil(t, err) x, invalidOutputError := err.(*service.InvalidOutputDataError) - assert.True(t, invalidOutputError) - assert.Equal(t, "output", x.Key) + require.True(t, invalidOutputError) + require.Equal(t, "output", x.Key) } func TestCompleteNotProcessed(t *testing.T) { @@ -88,8 +88,8 @@ func TestCompleteNotProcessed(t *testing.T) { execution, _ := Create(&s, "test", inputs) var outputs map[string]interface{} err := execution.Complete("output", outputs) - assert.NotNil(t, err) + require.NotNil(t, err) x, notInQueueError := err.(*NotInQueueError) - assert.True(t, notInQueueError) - assert.Equal(t, "inProgress", x.Queue) + require.True(t, notInQueueError) + require.Equal(t, "inProgress", x.Queue) } diff --git a/execution/create_test.go b/execution/create_test.go index 7fc80cd1f..269474e6c 100644 --- a/execution/create_test.go +++ b/execution/create_test.go @@ -7,7 +7,7 @@ import ( "github.com/mesg-foundation/core/service" "github.com/mesg-foundation/core/utils/hash" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestGenerateID(t *testing.T) { @@ -21,8 +21,8 @@ func TestGenerateID(t *testing.T) { Inputs: i, } id, err := generateID(&execution) - assert.Nil(t, err) - assert.Equal(t, id, hash.Calculate([]string{ + require.Nil(t, err) + require.Equal(t, id, hash.Calculate([]string{ execution.CreatedAt.UTC().String(), execution.Service.Name, execution.Task, @@ -39,11 +39,11 @@ func TestCreate(t *testing.T) { } var inputs map[string]interface{} exec, err := Create(&s, "test", inputs) - assert.Nil(t, err) - assert.Equal(t, exec.Service, &s) - assert.Equal(t, exec.Inputs, inputs) - assert.Equal(t, exec.Task, "test") - assert.Equal(t, pendingExecutions[exec.ID], exec) + require.Nil(t, err) + require.Equal(t, exec.Service, &s) + require.Equal(t, exec.Inputs, inputs) + require.Equal(t, exec.Task, "test") + require.Equal(t, pendingExecutions[exec.ID], exec) } func TestCreateInvalidTask(t *testing.T) { @@ -55,9 +55,9 @@ func TestCreateInvalidTask(t *testing.T) { } var inputs map[string]interface{} _, err := Create(&s, "testinvalid", inputs) - assert.NotNil(t, err) + require.NotNil(t, err) _, notFound := err.(*service.TaskNotFoundError) - assert.True(t, notFound) + require.True(t, notFound) } func TestCreateInvalidInputs(t *testing.T) { @@ -75,7 +75,7 @@ func TestCreateInvalidInputs(t *testing.T) { } var inputs map[string]interface{} _, err := Create(&s, "test", inputs) - assert.NotNil(t, err) + require.NotNil(t, err) _, invalid := err.(*service.InvalidTaskInputError) - assert.True(t, invalid) + require.True(t, invalid) } diff --git a/execution/error_test.go b/execution/error_test.go index 1d2439a65..d2cee9910 100644 --- a/execution/error_test.go +++ b/execution/error_test.go @@ -3,10 +3,10 @@ package execution import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestNotInQueueError(t *testing.T) { e := NotInQueueError{"test", "queueName"} - assert.Contains(t, "Execution 'test' not found in queue 'queueName'", e.Error()) + require.Contains(t, e.Error(), "Execution 'test' not found in queue 'queueName'") } diff --git a/execution/execute_test.go b/execution/execute_test.go index fd92357fc..97b4206a2 100644 --- a/execution/execute_test.go +++ b/execution/execute_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestExecute(t *testing.T) { @@ -17,7 +17,7 @@ func TestExecute(t *testing.T) { var inputs map[string]interface{} execution, _ := Create(&s, "test", inputs) err := execution.Execute() - assert.Nil(t, err) + require.Nil(t, err) } func TestExecuteNotPending(t *testing.T) { @@ -25,5 +25,5 @@ func TestExecuteNotPending(t *testing.T) { ID: "TestExecuteNotPending", } err := execution.Execute() - assert.NotNil(t, err) + require.NotNil(t, err) } diff --git a/execution/state_test.go b/execution/state_test.go index 1fed3a8c1..10c326bae 100644 --- a/execution/state_test.go +++ b/execution/state_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/mesg-foundation/core/service" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestMoveFromPendingToInProgress(t *testing.T) { @@ -17,16 +17,16 @@ func TestMoveFromPendingToInProgress(t *testing.T) { var inputs map[string]interface{} exec, _ := Create(&s, "test", inputs) err := exec.moveFromPendingToInProgress() - assert.Equal(t, inProgressExecutions[exec.ID], exec) - assert.Nil(t, pendingExecutions[exec.ID]) - assert.Nil(t, err) + require.Equal(t, inProgressExecutions[exec.ID], exec) + require.Nil(t, pendingExecutions[exec.ID]) + require.Nil(t, err) } func TestMoveFromPendingToInProgressNonExistingTask(t *testing.T) { exec := Execution{ID: "test"} err := exec.moveFromPendingToInProgress() - assert.NotNil(t, err) - assert.Nil(t, pendingExecutions[exec.ID]) + require.NotNil(t, err) + require.Nil(t, pendingExecutions[exec.ID]) } func TestMoveFromInProgressToCompleted(t *testing.T) { @@ -40,9 +40,9 @@ func TestMoveFromInProgressToCompleted(t *testing.T) { exec, _ := Create(&s, "test", inputs) exec.moveFromPendingToInProgress() err := exec.moveFromInProgressToProcessed() - assert.Equal(t, processedExecutions[exec.ID], exec) - assert.Nil(t, inProgressExecutions[exec.ID]) - assert.Nil(t, err) + require.Equal(t, processedExecutions[exec.ID], exec) + require.Nil(t, inProgressExecutions[exec.ID]) + require.Nil(t, err) } func TestMoveFromInProgressToCompletedNonExistingTask(t *testing.T) { @@ -55,13 +55,13 @@ func TestMoveFromInProgressToCompletedNonExistingTask(t *testing.T) { var inputs map[string]interface{} exec, _ := Create(&s, "test", inputs) err := exec.moveFromInProgressToProcessed() - assert.NotNil(t, err) - assert.Nil(t, inProgressExecutions[exec.ID]) + require.NotNil(t, err) + require.Nil(t, inProgressExecutions[exec.ID]) } func TestInProgress(t *testing.T) { inProgressExecutions["foo"] = &Execution{ID: "TestInProgress"} - assert.NotNil(t, InProgress("foo")) - assert.Equal(t, "TestInProgress", InProgress("foo").ID) - assert.Nil(t, InProgress("bar")) + require.NotNil(t, InProgress("foo")) + require.Equal(t, "TestInProgress", InProgress("foo").ID) + require.Nil(t, InProgress("bar")) } diff --git a/pubsub/pubsub_test.go b/pubsub/pubsub_test.go index a3d51bb3b..864f0e1ef 100644 --- a/pubsub/pubsub_test.go +++ b/pubsub/pubsub_test.go @@ -3,7 +3,7 @@ package pubsub import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) type messageStructTest struct { @@ -17,7 +17,7 @@ func TestPublish(t *testing.T) { res := Subscribe(key) go Publish(key, data) x := <-res - assert.Equal(t, x, data) + require.Equal(t, x, data) } func TestPublishMultipleListeners(t *testing.T) { @@ -28,22 +28,22 @@ func TestPublishMultipleListeners(t *testing.T) { go Publish(key, data) x := <-res1 y := <-res2 - assert.Equal(t, x, data) - assert.Equal(t, y, data) + require.Equal(t, x, data) + require.Equal(t, y, data) } func TestSubscribe(t *testing.T) { key := "TestSubscribe" res := Subscribe(key) - assert.NotNil(t, res) - assert.Equal(t, len(listeners[key]), 1) + require.NotNil(t, res) + require.Len(t, listeners[key], 1) } func TestSubscribeMultipleTimes(t *testing.T) { key := "TestSubscribeMultipleTimes" Subscribe(key) Subscribe(key) - assert.Equal(t, len(listeners[key]), 2) + require.Len(t, listeners[key], 2) } func TestUnsubscribe(t *testing.T) { @@ -51,9 +51,7 @@ func TestUnsubscribe(t *testing.T) { channel := Subscribe(key) channel1 := Subscribe(key) Unsubscribe(key, channel) - assert.Equal(t, len(listeners[key]), 1) - assert.NotNil(t, listeners[key]) + require.Len(t, listeners[key], 1) Unsubscribe(key, channel1) - assert.Equal(t, len(listeners[key]), 0) - assert.Nil(t, listeners[key]) + require.Nil(t, listeners[key]) } diff --git a/service/cast_test.go b/service/cast_test.go index 5128dfc92..9d9316c59 100644 --- a/service/cast_test.go +++ b/service/cast_test.go @@ -3,7 +3,7 @@ package service import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestServiceCast(t *testing.T) { @@ -69,16 +69,16 @@ func TestServiceCast(t *testing.T) { for _, tt := range tests { got, err := tt.service.Cast("test", tt.data) if tt.expectErr { - assert.NotNil(t, err) + require.NotNil(t, err) } else { - assert.Equal(t, len(tt.expected), len(got), "maps len are not equal") - assert.Equal(t, tt.expected, got, "maps are not equal") + require.Equal(t, len(tt.expected), len(got), "maps len are not equal") + require.Equal(t, tt.expected, got, "maps are not equal") } } // test if non-existing key returns error _, err := tests[0].service.Cast("_", nil) - assert.NotNil(t, err) + require.NotNil(t, err) } // creates test service with given inputs name and type under "test" task key. diff --git a/service/dependency_test.go b/service/dependency_test.go index 3c703174d..9640fccbe 100644 --- a/service/dependency_test.go +++ b/service/dependency_test.go @@ -3,7 +3,7 @@ package service import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestDependenciesFromService(t *testing.T) { @@ -19,8 +19,8 @@ func TestDependenciesFromService(t *testing.T) { }, } deps := service.DependenciesFromService() - assert.Equal(t, 2, len(deps)) - assert.Equal(t, "testa", deps[0].Name) - assert.Equal(t, "TestPartiallyRunningService", deps[0].Service.Name) - assert.Equal(t, "testb", deps[1].Name) + require.Equal(t, 2, len(deps)) + require.Equal(t, "testa", deps[0].Name) + require.Equal(t, "TestPartiallyRunningService", deps[0].Service.Name) + require.Equal(t, "testb", deps[1].Name) } diff --git a/service/error_test.go b/service/error_test.go index 7648dfa04..7ce4e3679 100644 --- a/service/error_test.go +++ b/service/error_test.go @@ -3,7 +3,7 @@ package service import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) type parameterTests []*parameterTest @@ -35,7 +35,7 @@ func (tests parameterTests) parameterTestsToMapData() map[string]interface{} { func (tests parameterTests) assert(t *testing.T, err string) { for _, test := range tests { - assert.Contains(t, "Value of '"+test.Key+"' is "+test.Error, err) + require.Contains(t, err, "Value of '"+test.Key+"' is "+test.Error) } } @@ -45,7 +45,7 @@ func TestEventNotFoundError(t *testing.T) { Service: &Service{Name: "TestEventNotFoundError"}, EventKey: "TestEventNotFoundErrorEventKey", } - assert.Equal(t, "Event 'TestEventNotFoundErrorEventKey' not found in service 'TestEventNotFoundError'", err.Error()) + require.Equal(t, "Event 'TestEventNotFoundErrorEventKey' not found in service 'TestEventNotFoundError'", err.Error()) } // Test InvalidEventDataError @@ -65,7 +65,7 @@ func TestInvalidEventDataError(t *testing.T) { Key: "TestInvalidEventDataErrorEventKey", Data: tests.parameterTestsToMapData(), } - assert.Contains(t, "Data of event 'TestInvalidEventDataErrorEventKey' is invalid", err.Error()) + require.Contains(t, err.Error(), "Data of event 'TestInvalidEventDataErrorEventKey' is invalid") tests.assert(t, err.Error()) } @@ -75,7 +75,7 @@ func TestTaskNotFoundError(t *testing.T) { Service: &Service{Name: "TestTaskNotFoundError"}, TaskKey: "TestTaskNotFoundErrorEventKey", } - assert.Equal(t, "Task 'TestTaskNotFoundErrorEventKey' not found in service 'TestTaskNotFoundError'", err.Error()) + require.Equal(t, "Task 'TestTaskNotFoundErrorEventKey' not found in service 'TestTaskNotFoundError'", err.Error()) } // Test InvalidTaskInputError @@ -95,7 +95,7 @@ func TestInvalidTaskInputError(t *testing.T) { Key: "TestInvalidTaskInputErrorEventKey", Inputs: tests.parameterTestsToMapData(), } - assert.Contains(t, "Inputs of task 'TestInvalidTaskInputErrorEventKey' are invalid", err.Error()) + require.Contains(t, err.Error(), "Inputs of task 'TestInvalidTaskInputErrorEventKey' are invalid") tests.assert(t, err.Error()) } @@ -105,7 +105,7 @@ func TestOutputNotFoundError(t *testing.T) { Service: &Service{Name: "TestOutputNotFoundError"}, OutputKey: "TestOutputNotFoundErrorEventKey", } - assert.Equal(t, "Output 'TestOutputNotFoundErrorEventKey' not found in service 'TestOutputNotFoundError'", err.Error()) + require.Equal(t, "Output 'TestOutputNotFoundErrorEventKey' not found in service 'TestOutputNotFoundError'", err.Error()) } // Test InvalidOutputDataError @@ -125,6 +125,6 @@ func TestInvalidOutputDataError(t *testing.T) { Key: "TestInvalidOutputDataErrorEventKey", Data: tests.parameterTestsToMapData(), } - assert.Contains(t, "Outputs of task 'TestInvalidOutputDataErrorEventKey' are invalid", err.Error()) + require.Contains(t, err.Error(), "Outputs of task 'TestInvalidOutputDataErrorEventKey' are invalid") tests.assert(t, err.Error()) } diff --git a/service/hash_test.go b/service/hash_test.go index 028ffe96d..e25d7cfc6 100644 --- a/service/hash_test.go +++ b/service/hash_test.go @@ -3,7 +3,7 @@ package service import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestGenerateId(t *testing.T) { @@ -11,7 +11,7 @@ func TestGenerateId(t *testing.T) { Name: "TestGenerateId", } hash := service.Hash() - assert.Equal(t, string(hash), "v1_b3664cde5d7fcb2d37fe2ebb45acdd27") + require.Equal(t, string(hash), "v1_b3664cde5d7fcb2d37fe2ebb45acdd27") } func TestNoCollision(t *testing.T) { @@ -23,5 +23,5 @@ func TestNoCollision(t *testing.T) { } hash1 := service1.Hash() hash2 := service2.Hash() - assert.NotEqual(t, string(hash1), string(hash2)) + require.NotEqual(t, string(hash1), string(hash2)) } diff --git a/service/importer/docker_file_test.go b/service/importer/docker_file_test.go index 2f38dbbf6..8086f1a4a 100644 --- a/service/importer/docker_file_test.go +++ b/service/importer/docker_file_test.go @@ -3,17 +3,17 @@ package importer import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestReadDockerFile(t *testing.T) { data, err := readDockerfile("./tests/service-valid") - assert.Nil(t, err) - assert.True(t, (len(data) > 0)) + require.Nil(t, err) + require.True(t, (len(data) > 0)) } func TestReadDockerFileDoesNotExist(t *testing.T) { data, err := readDockerfile("./tests/docker-missing") - assert.NotNil(t, err) - assert.True(t, (len(data) == 0)) + require.NotNil(t, err) + require.True(t, (len(data) == 0)) } diff --git a/service/importer/import_test.go b/service/importer/import_test.go index 37c122c11..7841231c4 100644 --- a/service/importer/import_test.go +++ b/service/importer/import_test.go @@ -3,27 +3,27 @@ package importer import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) // Test From function func TestFrom(t *testing.T) { service, err := From("./tests/service-minimal-valid") - assert.Nil(t, err) - assert.NotNil(t, service) - assert.Equal(t, service.Name, "minimal-valid") + require.Nil(t, err) + require.NotNil(t, service) + require.Equal(t, service.Name, "minimal-valid") } func TestFromMalFormattedFile(t *testing.T) { _, err := From("./tests/service-file-mal-formatted") - assert.NotNil(t, err) + require.NotNil(t, err) } func TestFromValidationError(t *testing.T) { _, err := From("./tests/service-file-invalid") - assert.NotNil(t, err) + require.NotNil(t, err) _, typeCasting := err.(*ValidationError) - assert.True(t, typeCasting) - assert.Equal(t, (&ValidationError{}).Error(), err.Error()) + require.True(t, typeCasting) + require.Equal(t, (&ValidationError{}).Error(), err.Error()) } diff --git a/service/importer/service_file_test.go b/service/importer/service_file_test.go index cb3a4aa8b..447dba3db 100644 --- a/service/importer/service_file_test.go +++ b/service/importer/service_file_test.go @@ -3,7 +3,7 @@ package importer import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" yaml "gopkg.in/yaml.v2" ) @@ -11,14 +11,14 @@ import ( func TestReadServiceFile(t *testing.T) { data, err := readServiceFile("./tests/service-valid") - assert.Nil(t, err) - assert.True(t, (len(data) > 0)) + require.Nil(t, err) + require.True(t, (len(data) > 0)) } func TestReadServiceFileDoesNotExist(t *testing.T) { data, err := readServiceFile("./tests/service-file-missing") - assert.NotNil(t, err) - assert.True(t, (len(data) == 0)) + require.NotNil(t, err) + require.True(t, (len(data) == 0)) } // Test validateServiceFileSchema function @@ -29,8 +29,8 @@ func TestValidateServiceFileSchema(t *testing.T) { _ = yaml.Unmarshal(data, &body) body = convert(body) result, err := validateServiceFileSchema(body, "service/importer/assets/schema.json") - assert.Nil(t, err) - assert.True(t, result.Valid()) + require.Nil(t, err) + require.True(t, result.Valid()) } func TestValidateServiceFileSchemaNotExisting(t *testing.T) { @@ -39,7 +39,7 @@ func TestValidateServiceFileSchemaNotExisting(t *testing.T) { _ = yaml.Unmarshal(data, &body) body = convert(body) _, err := validateServiceFileSchema(body, "service/assets/not_existing") - assert.NotNil(t, err) + require.NotNil(t, err) } // Test validateServiceFile function @@ -47,27 +47,27 @@ func TestValidateServiceFileSchemaNotExisting(t *testing.T) { func TestValidateServiceFile(t *testing.T) { data, _ := readServiceFile("./tests/service-valid") warnings, err := validateServiceFile(data) - assert.Nil(t, err) - assert.True(t, (len(warnings) == 0)) + require.Nil(t, err) + require.True(t, (len(warnings) == 0)) } func TestValidateServiceFileMalFormatted(t *testing.T) { data, _ := readServiceFile("./tests/service-file-mal-formatted") warnings, err := validateServiceFile(data) - assert.NotNil(t, err) - assert.True(t, (len(warnings) == 0)) + require.NotNil(t, err) + require.True(t, (len(warnings) == 0)) } func TestValidateServiceFileWithErrors(t *testing.T) { data, _ := readServiceFile("./tests/service-file-invalid") warnings, err := validateServiceFile(data) - assert.Nil(t, err) - assert.Equal(t, 1, len(warnings)) + require.Nil(t, err) + require.Equal(t, 1, len(warnings)) } func TestValidateServiceFileWithMultipleErrors(t *testing.T) { data, _ := readServiceFile("./tests/service-multiple-errors") warnings, err := validateServiceFile(data) - assert.Nil(t, err) - assert.Equal(t, 2, len(warnings)) + require.Nil(t, err) + require.Equal(t, 2, len(warnings)) } diff --git a/service/importer/validation_result_test.go b/service/importer/validation_result_test.go index a409b6f9e..0e1b3c7d7 100644 --- a/service/importer/validation_result_test.go +++ b/service/importer/validation_result_test.go @@ -3,7 +3,7 @@ package importer import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) // Test ValidationResult.IsValid function @@ -14,7 +14,7 @@ func TestValidationResultIsValid(t *testing.T) { ServiceFileWarnings: []string{}, DockerfileExist: true, } - assert.True(t, v.IsValid()) + require.True(t, v.IsValid()) } func TestValidationResultIsValidServiceFileDoesNotExist(t *testing.T) { @@ -23,7 +23,7 @@ func TestValidationResultIsValidServiceFileDoesNotExist(t *testing.T) { ServiceFileWarnings: []string{}, DockerfileExist: true, } - assert.False(t, v.IsValid()) + require.False(t, v.IsValid()) } func TestValidationResultIsValidServiceFileWarnings(t *testing.T) { @@ -32,7 +32,7 @@ func TestValidationResultIsValidServiceFileWarnings(t *testing.T) { ServiceFileWarnings: []string{"Warning"}, DockerfileExist: true, } - assert.False(t, v.IsValid()) + require.False(t, v.IsValid()) } func TestValidationResultIsValidDockfileDoesNotExist(t *testing.T) { @@ -41,5 +41,5 @@ func TestValidationResultIsValidDockfileDoesNotExist(t *testing.T) { ServiceFileWarnings: []string{}, DockerfileExist: false, } - assert.False(t, v.IsValid()) + require.False(t, v.IsValid()) } diff --git a/service/importer/validation_test.go b/service/importer/validation_test.go index 715182178..4d5981e56 100644 --- a/service/importer/validation_test.go +++ b/service/importer/validation_test.go @@ -3,70 +3,70 @@ package importer import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) // Test Validate function func TestValidate(t *testing.T) { validation, err := Validate("./tests/service-valid") - assert.Nil(t, err) - assert.True(t, validation.IsValid()) - assert.True(t, validation.ServiceFileExist) - assert.Equal(t, 0, len(validation.ServiceFileWarnings)) - assert.True(t, validation.DockerfileExist) + require.Nil(t, err) + require.True(t, validation.IsValid()) + require.True(t, validation.ServiceFileExist) + require.Equal(t, 0, len(validation.ServiceFileWarnings)) + require.True(t, validation.DockerfileExist) } func TestValidateDockerfileIsMissing(t *testing.T) { validation, err := Validate("./tests/service-docker-missing") - assert.Nil(t, err) - assert.False(t, validation.IsValid()) - assert.True(t, validation.ServiceFileExist) - assert.Equal(t, 0, len(validation.ServiceFileWarnings)) - assert.False(t, validation.DockerfileExist) + require.Nil(t, err) + require.False(t, validation.IsValid()) + require.True(t, validation.ServiceFileExist) + require.Equal(t, 0, len(validation.ServiceFileWarnings)) + require.False(t, validation.DockerfileExist) } func TestValidateFromMissingServiceFile(t *testing.T) { validation, err := Validate("./tests/service-file-missing") - assert.Nil(t, err) - assert.False(t, validation.IsValid()) - assert.False(t, validation.ServiceFileExist) - assert.Equal(t, 1, len(validation.ServiceFileWarnings)) - assert.True(t, validation.DockerfileExist) + require.Nil(t, err) + require.False(t, validation.IsValid()) + require.False(t, validation.ServiceFileExist) + require.Equal(t, 1, len(validation.ServiceFileWarnings)) + require.True(t, validation.DockerfileExist) } func TestValidateFromNonExistingPath(t *testing.T) { validation, err := Validate("./tests/service-non-existing") - assert.Nil(t, err) - assert.False(t, validation.IsValid()) - assert.False(t, validation.ServiceFileExist) - assert.Equal(t, 1, len(validation.ServiceFileWarnings)) - assert.False(t, validation.DockerfileExist) + require.Nil(t, err) + require.False(t, validation.IsValid()) + require.False(t, validation.ServiceFileExist) + require.Equal(t, 1, len(validation.ServiceFileWarnings)) + require.False(t, validation.DockerfileExist) } func TestValidateFromMalFormattedServiceFile(t *testing.T) { _, err := Validate("./tests/service-file-mal-formatted") - assert.NotNil(t, err) + require.NotNil(t, err) } func TestValidateFromInvalidServiceFile(t *testing.T) { validation, err := Validate("./tests/service-file-invalid") - assert.Nil(t, err) - assert.False(t, validation.IsValid()) - assert.True(t, validation.ServiceFileExist) - assert.Equal(t, 1, len(validation.ServiceFileWarnings)) - assert.True(t, validation.DockerfileExist) + require.Nil(t, err) + require.False(t, validation.IsValid()) + require.True(t, validation.ServiceFileExist) + require.Equal(t, 1, len(validation.ServiceFileWarnings)) + require.True(t, validation.DockerfileExist) } // Test IsValid function func TestIsValid(t *testing.T) { isValid, err := IsValid("./tests/service-valid") - assert.Nil(t, err) - assert.True(t, isValid) + require.Nil(t, err) + require.True(t, isValid) } func TestIsValidMalFormattedServiceFile(t *testing.T) { _, err := IsValid("./tests/service-file-mal-formatted") - assert.NotNil(t, err) + require.NotNil(t, err) } diff --git a/service/logs_test.go b/service/logs_test.go index 56047b2b5..f7b72bd0f 100644 --- a/service/logs_test.go +++ b/service/logs_test.go @@ -3,7 +3,7 @@ package service import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestLogs(t *testing.T) { @@ -21,8 +21,8 @@ func TestLogs(t *testing.T) { service.Start() defer service.Stop() readers, err := service.Logs("*") - assert.Nil(t, err) - assert.Equal(t, 2, len(readers)) + require.Nil(t, err) + require.Equal(t, 2, len(readers)) } func TestLogsOnlyOneDependency(t *testing.T) { @@ -40,6 +40,6 @@ func TestLogsOnlyOneDependency(t *testing.T) { service.Start() defer service.Stop() readers, err := service.Logs("test2") - assert.Nil(t, err) - assert.Equal(t, 1, len(readers)) + require.Nil(t, err) + require.Equal(t, 1, len(readers)) } diff --git a/service/namespace_test.go b/service/namespace_test.go index fd165fc49..26214fa33 100644 --- a/service/namespace_test.go +++ b/service/namespace_test.go @@ -4,13 +4,13 @@ import ( "testing" "github.com/mesg-foundation/core/utils/hash" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestServiceNamespace(t *testing.T) { service := &Service{Name: "TestServiceNamespace"} namespace := service.namespace() - assert.Equal(t, namespace, []string{service.Hash()}) + require.Equal(t, namespace, []string{service.Hash()}) } func TestDependencyNamespace(t *testing.T) { @@ -24,12 +24,12 @@ func TestDependencyNamespace(t *testing.T) { } dep := service.DependenciesFromService()[0] namespace := dep.namespace() - assert.Equal(t, namespace, []string{service.Hash(), "test"}) + require.Equal(t, namespace, []string{service.Hash(), "test"}) } func TestEventSubscriptionChannel(t *testing.T) { service := &Service{Name: "TestEventSubscriptionChannel"} - assert.Equal(t, service.EventSubscriptionChannel(), hash.Calculate(append( + require.Equal(t, service.EventSubscriptionChannel(), hash.Calculate(append( service.namespace(), eventChannel, ))) @@ -37,7 +37,7 @@ func TestEventSubscriptionChannel(t *testing.T) { func TestTaskSubscriptionChannel(t *testing.T) { service := &Service{Name: "TaskSubscriptionChannel"} - assert.Equal(t, service.TaskSubscriptionChannel(), hash.Calculate(append( + require.Equal(t, service.TaskSubscriptionChannel(), hash.Calculate(append( service.namespace(), taskChannel, ))) @@ -45,7 +45,7 @@ func TestTaskSubscriptionChannel(t *testing.T) { func TestResultSubscriptionChannel(t *testing.T) { service := &Service{Name: "ResultSubscriptionChannel"} - assert.Equal(t, service.ResultSubscriptionChannel(), hash.Calculate(append( + require.Equal(t, service.ResultSubscriptionChannel(), hash.Calculate(append( service.namespace(), resultChannel, ))) diff --git a/service/start_test.go b/service/start_test.go index 105b669cf..e95d7ecd8 100644 --- a/service/start_test.go +++ b/service/start_test.go @@ -5,13 +5,13 @@ import ( "time" "github.com/mesg-foundation/core/container" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestExtractPortEmpty(t *testing.T) { dep := Dependency{} ports := dep.extractPorts() - assert.Equal(t, len(ports), 0) + require.Equal(t, len(ports), 0) } func TestExtractPorts(t *testing.T) { @@ -22,11 +22,11 @@ func TestExtractPorts(t *testing.T) { }, } ports := dep.extractPorts() - assert.Equal(t, len(ports), 2) - assert.Equal(t, ports[0].Target, uint32(80)) - assert.Equal(t, ports[0].Published, uint32(80)) - assert.Equal(t, ports[1].Target, uint32(8080)) - assert.Equal(t, ports[1].Published, uint32(3000)) + require.Equal(t, len(ports), 2) + require.Equal(t, ports[0].Target, uint32(80)) + require.Equal(t, ports[0].Published, uint32(80)) + require.Equal(t, ports[1].Target, uint32(8080)) + require.Equal(t, ports[1].Published, uint32(3000)) } func TestStartService(t *testing.T) { @@ -40,10 +40,10 @@ func TestStartService(t *testing.T) { } dockerServices, err := service.Start() defer service.Stop() - assert.Nil(t, err) - assert.Equal(t, len(service.GetDependencies()), len(dockerServices)) + require.Nil(t, err) + require.Equal(t, len(service.GetDependencies()), len(dockerServices)) status, _ := service.Status() - assert.Equal(t, RUNNING, status) + require.Equal(t, RUNNING, status) } func TestStartWith2Dependencies(t *testing.T) { @@ -60,13 +60,13 @@ func TestStartWith2Dependencies(t *testing.T) { } servicesID, err := service.Start() defer service.Stop() - assert.Nil(t, err) - assert.Equal(t, 2, len(servicesID)) + require.Nil(t, err) + require.Equal(t, 2, len(servicesID)) deps := service.DependenciesFromService() container1, _ := defaultContainer.FindContainer(deps[0].namespace()) container2, _ := defaultContainer.FindContainer(deps[1].namespace()) - assert.Equal(t, "nginx:latest", container1.Config.Image) - assert.Equal(t, "alpine:latest", container2.Config.Image) + require.Equal(t, "nginx:latest", container1.Config.Image) + require.Equal(t, "alpine:latest", container2.Config.Image) } func TestStartAgainService(t *testing.T) { @@ -81,10 +81,10 @@ func TestStartAgainService(t *testing.T) { service.Start() defer service.Stop() dockerServices, err := service.Start() - assert.Nil(t, err) - assert.Equal(t, len(dockerServices), 0) // 0 because already started so no new one to start + require.Nil(t, err) + require.Equal(t, len(dockerServices), 0) // 0 because already started so no new one to start status, _ := service.Status() - assert.Equal(t, RUNNING, status) + require.Equal(t, RUNNING, status) } func TestPartiallyRunningService(t *testing.T) { @@ -103,12 +103,12 @@ func TestPartiallyRunningService(t *testing.T) { defer service.Stop() service.DependenciesFromService()[0].Stop() status, _ := service.Status() - assert.Equal(t, PARTIAL, status) + require.Equal(t, PARTIAL, status) dockerServices, err := service.Start() - assert.Nil(t, err) - assert.Equal(t, len(dockerServices), len(service.GetDependencies())) + require.Nil(t, err) + require.Equal(t, len(dockerServices), len(service.GetDependencies())) status, _ = service.Status() - assert.Equal(t, RUNNING, status) + require.Equal(t, RUNNING, status) } func TestStartDependency(t *testing.T) { @@ -125,10 +125,10 @@ func TestStartDependency(t *testing.T) { dep := service.DependenciesFromService()[0] serviceID, err := dep.Start(networkID) defer dep.Stop() - assert.Nil(t, err) - assert.NotEqual(t, "", serviceID) + require.Nil(t, err) + require.NotEqual(t, "", serviceID) status, _ := dep.Status() - assert.Equal(t, container.RUNNING, status) + require.Equal(t, container.RUNNING, status) } func TestNetworkCreated(t *testing.T) { @@ -143,8 +143,8 @@ func TestNetworkCreated(t *testing.T) { service.Start() defer service.Stop() network, err := defaultContainer.FindNetwork(service.namespace()) - assert.Nil(t, err) - assert.NotEqual(t, "", network.ID) + require.Nil(t, err) + require.NotEqual(t, "", network.ID) } // Test for https://github.com/mesg-foundation/core/issues/88 @@ -162,8 +162,8 @@ func TestStartStopStart(t *testing.T) { time.Sleep(10 * time.Second) dockerServices, err := service.Start() defer service.Stop() - assert.Nil(t, err) - assert.Equal(t, len(dockerServices), 1) + require.Nil(t, err) + require.Equal(t, len(dockerServices), 1) status, _ := service.Status() - assert.Equal(t, RUNNING, status) + require.Equal(t, RUNNING, status) } diff --git a/service/status_test.go b/service/status_test.go index 2db428dea..41f345273 100644 --- a/service/status_test.go +++ b/service/status_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/mesg-foundation/core/container" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestStatusService(t *testing.T) { @@ -17,15 +17,15 @@ func TestStatusService(t *testing.T) { }, } status, err := service.Status() - assert.Nil(t, err) - assert.Equal(t, STOPPED, status) + require.Nil(t, err) + require.Equal(t, STOPPED, status) dockerServices, err := service.Start() defer service.Stop() - assert.Nil(t, err) - assert.Equal(t, len(dockerServices), len(service.GetDependencies())) + require.Nil(t, err) + require.Equal(t, len(dockerServices), len(service.GetDependencies())) status, err = service.Status() - assert.Nil(t, err) - assert.Equal(t, RUNNING, status) + require.Nil(t, err) + require.Equal(t, RUNNING, status) } func TestStatusDependency(t *testing.T) { @@ -39,14 +39,14 @@ func TestStatusDependency(t *testing.T) { } dep := service.DependenciesFromService()[0] status, err := dep.Status() - assert.Nil(t, err) - assert.Equal(t, container.STOPPED, status) + require.Nil(t, err) + require.Equal(t, container.STOPPED, status) dockerServices, err := service.Start() - assert.Nil(t, err) - assert.Equal(t, len(dockerServices), len(service.GetDependencies())) + require.Nil(t, err) + require.Equal(t, len(dockerServices), len(service.GetDependencies())) status, err = dep.Status() - assert.Nil(t, err) - assert.Equal(t, container.RUNNING, status) + require.Nil(t, err) + require.Equal(t, container.RUNNING, status) service.Stop() } @@ -63,9 +63,9 @@ func TestList(t *testing.T) { service.Start() defer service.Stop() list, err := ListRunning() - assert.Nil(t, err) - assert.Equal(t, len(list), 1) - assert.Equal(t, list[0], hash) + require.Nil(t, err) + require.Equal(t, len(list), 1) + require.Equal(t, list[0], hash) } func TestListMultipleDependencies(t *testing.T) { @@ -84,7 +84,7 @@ func TestListMultipleDependencies(t *testing.T) { service.Start() defer service.Stop() list, err := ListRunning() - assert.Nil(t, err) - assert.Equal(t, len(list), 1) - assert.Equal(t, list[0], hash) + require.Nil(t, err) + require.Equal(t, len(list), 1) + require.Equal(t, list[0], hash) } diff --git a/service/stop_test.go b/service/stop_test.go index 07ca1a44f..c5621c362 100644 --- a/service/stop_test.go +++ b/service/stop_test.go @@ -5,7 +5,7 @@ import ( "time" "github.com/mesg-foundation/core/container" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestStopRunningService(t *testing.T) { @@ -19,9 +19,9 @@ func TestStopRunningService(t *testing.T) { } service.Start() err := service.Stop() - assert.Nil(t, err) + require.Nil(t, err) status, _ := service.Status() - assert.Equal(t, STOPPED, status) + require.Equal(t, STOPPED, status) } func TestStopNonRunningService(t *testing.T) { @@ -34,9 +34,9 @@ func TestStopNonRunningService(t *testing.T) { }, } err := service.Stop() - assert.Nil(t, err) + require.Nil(t, err) status, _ := service.Status() - assert.Equal(t, STOPPED, status) + require.Equal(t, STOPPED, status) } func TestStopDependency(t *testing.T) { @@ -53,9 +53,9 @@ func TestStopDependency(t *testing.T) { dep := service.DependenciesFromService()[0] dep.Start(networkID) err = dep.Stop() - assert.Nil(t, err) + require.Nil(t, err) status, _ := dep.Status() - assert.Equal(t, container.STOPPED, status) + require.Equal(t, container.STOPPED, status) } func TestNetworkDeleted(t *testing.T) { @@ -71,5 +71,5 @@ func TestNetworkDeleted(t *testing.T) { service.Stop() time.Sleep(5 * time.Second) _, err := defaultContainer.FindNetwork(service.namespace()) - assert.NotNil(t, err) + require.NotNil(t, err) } diff --git a/service/validation_test.go b/service/validation_test.go index 94965f924..bd4b6e18d 100644 --- a/service/validation_test.go +++ b/service/validation_test.go @@ -3,7 +3,7 @@ package service import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) var serviceTest = &Service{ @@ -33,42 +33,42 @@ var serviceTest = &Service{ var event = serviceTest.Events["test"] func TestRequired(t *testing.T) { - assert.Nil(t, event.Data["optional"].Validate("presence")) - assert.Nil(t, event.Data["optional"].Validate(nil)) + require.Nil(t, event.Data["optional"].Validate("presence")) + require.Nil(t, event.Data["optional"].Validate(nil)) // this parameter is required - assert.NotNil(t, event.Data["string"].Validate(nil)) + require.NotNil(t, event.Data["string"].Validate(nil)) } func TestString(t *testing.T) { - assert.Nil(t, event.Data["string"].Validate("valid")) - assert.NotNil(t, event.Data["string"].Validate(false)) + require.Nil(t, event.Data["string"].Validate("valid")) + require.NotNil(t, event.Data["string"].Validate(false)) } func TestNumber(t *testing.T) { - assert.Nil(t, event.Data["number"].Validate(10.5)) - assert.Nil(t, event.Data["number"].Validate(10)) - assert.NotNil(t, event.Data["number"].Validate("not a number")) + require.Nil(t, event.Data["number"].Validate(10.5)) + require.Nil(t, event.Data["number"].Validate(10)) + require.NotNil(t, event.Data["number"].Validate("not a number")) } func TestBoolean(t *testing.T) { - assert.Nil(t, event.Data["boolean"].Validate(true)) - assert.Nil(t, event.Data["boolean"].Validate(false)) - assert.NotNil(t, event.Data["boolean"].Validate("not a boolean")) + require.Nil(t, event.Data["boolean"].Validate(true)) + require.Nil(t, event.Data["boolean"].Validate(false)) + require.NotNil(t, event.Data["boolean"].Validate("not a boolean")) } func TestObject(t *testing.T) { - assert.Nil(t, event.Data["object"].Validate(map[string]interface{}{ + require.Nil(t, event.Data["object"].Validate(map[string]interface{}{ "foo": "bar", })) - assert.Nil(t, event.Data["object"].Validate([]interface{}{ + require.Nil(t, event.Data["object"].Validate([]interface{}{ "foo", "bar", })) - assert.NotNil(t, event.Data["object"].Validate(42)) + require.NotNil(t, event.Data["object"].Validate(42)) } func TestValidateParameters(t *testing.T) { - assert.Equal(t, 0, len(validateParameters(event.Data, map[string]interface{}{ + require.Equal(t, 0, len(validateParameters(event.Data, map[string]interface{}{ "string": "hello", "number": 10, "boolean": true, @@ -76,7 +76,7 @@ func TestValidateParameters(t *testing.T) { "foo": "bar", }, }))) - assert.Equal(t, 0, len(validateParameters(event.Data, map[string]interface{}{ + require.Equal(t, 0, len(validateParameters(event.Data, map[string]interface{}{ "optional": "yeah", "string": "hello", "number": 10, @@ -90,7 +90,7 @@ func TestValidateParameters(t *testing.T) { // - invalid number // - invalid boolean // - invalid object - assert.Equal(t, 4, len(validateParameters(event.Data, map[string]interface{}{ + require.Equal(t, 4, len(validateParameters(event.Data, map[string]interface{}{ "number": "string", "boolean": 42, "object": false, @@ -98,7 +98,7 @@ func TestValidateParameters(t *testing.T) { } func TestValidParameters(t *testing.T) { - assert.True(t, validParameters(event.Data, map[string]interface{}{ + require.True(t, validParameters(event.Data, map[string]interface{}{ "string": "hello", "number": 10, "boolean": true, @@ -106,5 +106,5 @@ func TestValidParameters(t *testing.T) { "foo": "bar", }, })) - assert.False(t, validParameters(event.Data, map[string]interface{}{})) + require.False(t, validParameters(event.Data, map[string]interface{}{})) } diff --git a/utils/array/include_test.go b/utils/array/include_test.go index f7b845dc6..0fe62f787 100644 --- a/utils/array/include_test.go +++ b/utils/array/include_test.go @@ -3,16 +3,16 @@ package array import ( "testing" - "github.com/stvp/assert" + "github.com/stretchr/testify/require" ) func TestIncludedIn(t *testing.T) { - assert.False(t, IncludedIn([]string{}, "")) - assert.True(t, IncludedIn([]string{""}, "")) - assert.False(t, IncludedIn([]string{"a"}, "")) - assert.True(t, IncludedIn([]string{"a"}, "a")) - assert.False(t, IncludedIn([]string{""}, "a")) - assert.True(t, IncludedIn([]string{"a", "b"}, "a")) - assert.True(t, IncludedIn([]string{"a", "b"}, "b")) - assert.False(t, IncludedIn([]string{"a", "b"}, "c")) + require.False(t, IncludedIn([]string{}, "")) + require.True(t, IncludedIn([]string{""}, "")) + require.False(t, IncludedIn([]string{"a"}, "")) + require.True(t, IncludedIn([]string{"a"}, "a")) + require.False(t, IncludedIn([]string{""}, "a")) + require.True(t, IncludedIn([]string{"a", "b"}, "a")) + require.True(t, IncludedIn([]string{"a", "b"}, "b")) + require.False(t, IncludedIn([]string{"a", "b"}, "c")) } From c09af90cfb5dbed73fbece85ab76c4430adfc442 Mon Sep 17 00:00:00 2001 From: Nicolas Mahe Date: Wed, 15 Aug 2018 16:38:27 +0700 Subject: [PATCH 22/22] Add more test to pubsub test --- pubsub/pubsub_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pubsub/pubsub_test.go b/pubsub/pubsub_test.go index 864f0e1ef..e4df9f297 100644 --- a/pubsub/pubsub_test.go +++ b/pubsub/pubsub_test.go @@ -52,6 +52,8 @@ func TestUnsubscribe(t *testing.T) { channel1 := Subscribe(key) Unsubscribe(key, channel) require.Len(t, listeners[key], 1) + require.NotNil(t, listeners[key]) Unsubscribe(key, channel1) + require.Len(t, listeners[key], 0) require.Nil(t, listeners[key]) }