Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unit test for commands flags #501

Merged
merged 4 commits into from Oct 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
87 changes: 78 additions & 9 deletions commands/commands_mock_test.go
Expand Up @@ -2,17 +2,86 @@ package commands

import (
"io"
"os"
"strings"
"sync"
"testing"

"github.com/mesg-foundation/core/commands/provider"
"github.com/mesg-foundation/core/container"
"github.com/mesg-foundation/core/protobuf/coreapi"
"github.com/mesg-foundation/core/service"
"github.com/mesg-foundation/core/utils/servicetemplate"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)

// captureStd is helper function that captures Stdout and Stderr and returns function
// that returns standard output and standard error as string.
func captureStd(t *testing.T) func() (string, string) {
var (
bufout strings.Builder
buferr strings.Builder
wg sync.WaitGroup

stdout = os.Stdout
stderr = os.Stderr
)

or, ow, err := os.Pipe()
require.NoError(t, err)

er, ew, err := os.Pipe()
require.NoError(t, err)

os.Stdout = ow
os.Stderr = ew

wg.Add(1)
// copy out and err to buffers
go func() {
_, err := io.Copy(&bufout, or)
require.NoError(t, err)
or.Close()

_, err = io.Copy(&buferr, er)
require.NoError(t, err)
er.Close()

wg.Done()
}()

return func() (string, string) {
// close writers and wait for copy to finish
ow.Close()
ew.Close()
wg.Wait()

// set back oginal stdout and stderr
os.Stdout = stdout
os.Stderr = stderr

// return stdout and stderr
return bufout.String(), buferr.String()
}
}

type mockExecutor struct {
*mock.Mock
*mockRootExecutor
*mockServiceExecutor
}

func newMockExecutor() *mockExecutor {
m := &mock.Mock{}
return &mockExecutor{
Mock: m,
mockRootExecutor: &mockRootExecutor{m},
mockServiceExecutor: &mockServiceExecutor{m},
}
}

type mockRootExecutor struct {
mock.Mock
*mock.Mock
}

func (m *mockRootExecutor) Start() error {
Expand All @@ -36,12 +105,12 @@ func (m *mockRootExecutor) Logs() (io.ReadCloser, error) {
}

type mockServiceExecutor struct {
mock.Mock
*mock.Mock
}

func (m *mockServiceExecutor) ServiceByID(id string) (*service.Service, error) {
func (m *mockServiceExecutor) ServiceByID(id string) (*coreapi.Service, error) {
args := m.Called()
return args.Get(0).(*service.Service), args.Error(1)
return args.Get(0).(*coreapi.Service), args.Error(1)
}

func (m *mockServiceExecutor) ServiceDeleteAll() error {
Expand Down Expand Up @@ -74,9 +143,9 @@ func (m *mockServiceExecutor) ServiceLogs(id string, dependencies ...string) (lo
return args.Get(0).([]*provider.Log), args.Get(1).(func()), args.Error(2)
}

func (m *mockServiceExecutor) ServiceExecuteTask(id, taskKey, inputData string, tags []string) (listenResults chan coreapi.ResultData, err error) {
func (m *mockServiceExecutor) ServiceExecuteTask(id, taskKey, inputData string, tags []string) error {
args := m.Called()
return args.Get(0).(chan coreapi.ResultData), args.Error(1)
return args.Error(0)
}

func (m *mockServiceExecutor) ServiceStart(id string) error {
Expand All @@ -99,9 +168,9 @@ func (m *mockServiceExecutor) ServiceGenerateDocs(path string) error {
return args.Error(0)
}

func (m *mockServiceExecutor) ServiceList() ([]*service.Service, error) {
func (m *mockServiceExecutor) ServiceList() ([]*coreapi.Service, error) {
args := m.Called()
return args.Get(0).([]*service.Service), args.Error(1)
return args.Get(0).([]*coreapi.Service), args.Error(1)
}

func (m *mockServiceExecutor) ServiceInit(name, description, templateURL string, currentDir bool) error {
Expand Down
26 changes: 26 additions & 0 deletions commands/logs_test.go
@@ -0,0 +1,26 @@
package commands

import (
"bytes"
"io/ioutil"
"testing"

"github.com/docker/docker/pkg/stdcopy"
"github.com/mesg-foundation/core/container"
)

func TestLogsCmdRunE(t *testing.T) {
m := newMockExecutor()
c := newLogsCmd(m)

// create reader for docker stdcopy
buf := new(bytes.Buffer)
w := stdcopy.NewStdWriter(buf, stdcopy.Stdout)
w.Write([]byte("core: 2018-01-01 log\n"))

m.On("Status").Return(container.RUNNING, nil)
m.On("Logs").Return(ioutil.NopCloser(buf), nil)
krhubert marked this conversation as resolved.
Show resolved Hide resolved
c.cmd.Execute()

m.AssertExpectations(t)
krhubert marked this conversation as resolved.
Show resolved Hide resolved
}
27 changes: 23 additions & 4 deletions commands/root_test.go
@@ -1,23 +1,32 @@
package commands

import (
"os"
"strings"
"testing"

"github.com/mesg-foundation/core/utils/pretty"
"github.com/spf13/cobra"
"github.com/stretchr/testify/require"
)

func findCommandChildByUse(root *cobra.Command, use string) bool {
func findCommandChildByUsePrefix(root *cobra.Command, use string) bool {
for _, cmd := range root.Commands() {
if cmd.Use == use {
if strings.HasPrefix(cmd.Use, use) {
return true
}
}
return false
}

func TestMain(m *testing.M) {
pretty.DisableColor()
pretty.DisableSpinner()
os.Exit(m.Run())
}

func TestRootCmd(t *testing.T) {
cmd := Build(nil)
cmd := newRootCmd(nil).cmd
for _, tt := range []struct {
use string
}{
Expand All @@ -27,6 +36,16 @@ func TestRootCmd(t *testing.T) {
{"logs"},
{"service"},
} {
require.Truef(t, findCommandChildByUse(cmd, tt.use), "command %q not found", tt.use)
require.Truef(t, findCommandChildByUsePrefix(cmd, tt.use), "command %q not found", tt.use)
}
}

func TestRootCmdFlags(t *testing.T) {
c := newRootCmd(nil)

c.cmd.PersistentFlags().Set("no-color", "true")
require.True(t, c.noColor)

c.cmd.PersistentFlags().Set("no-spinner", "true")
require.True(t, c.noSpinner)
}
20 changes: 20 additions & 0 deletions commands/service_delete_test.go
@@ -0,0 +1,20 @@
package commands

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestServiceDeleteCmdFlags(t *testing.T) {
c := newServiceDeleteCmd(nil)

flags := c.cmd.Flags()
require.Equal(t, flags.ShorthandLookup("f"), flags.Lookup("force"))

flags.Set("force", "true")
require.True(t, c.force)

flags.Set("all", "true")
require.True(t, c.all)
}
25 changes: 25 additions & 0 deletions commands/service_dev_test.go
@@ -0,0 +1,25 @@
package commands

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestServiceDevCmdFlags(t *testing.T) {
c := newServiceDevCmd(nil)

flags := c.cmd.Flags()
require.Equal(t, flags.ShorthandLookup("e"), flags.Lookup("event-filter"))
require.Equal(t, flags.ShorthandLookup("t"), flags.Lookup("task-filter"))
require.Equal(t, flags.ShorthandLookup("o"), flags.Lookup("output-filter"))

flags.Set("event-filter", "ef")
require.Equal(t, "ef", c.eventFilter)

flags.Set("task-filter", "tf")
require.Equal(t, "tf", c.taskFilter)

flags.Set("output-filter", "of")
require.Equal(t, "of", c.outputFilter)
}
25 changes: 25 additions & 0 deletions commands/service_execute_test.go
@@ -0,0 +1,25 @@
package commands

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestServiceExecuteCmdFlags(t *testing.T) {
c := newServiceExecuteCmd(nil)

flags := c.cmd.Flags()
require.Equal(t, flags.ShorthandLookup("t"), flags.Lookup("task"))
require.Equal(t, flags.ShorthandLookup("d"), flags.Lookup("data"))
require.Equal(t, flags.ShorthandLookup("j"), flags.Lookup("json"))

flags.Set("task", "t")
require.Equal(t, "t", c.taskKey)

flags.Set("data", "k=v")
require.Equal(t, map[string]string{"k": "v"}, c.executeData)

flags.Set("json", "data.json")
require.Equal(t, "data.json", c.jsonFile)
}
20 changes: 20 additions & 0 deletions commands/service_init_test.go
@@ -0,0 +1,20 @@
package commands

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestServiceInitCmdFlags(t *testing.T) {
c := newServiceInitCmd(nil)

flags := c.cmd.Flags()
require.Equal(t, flags.ShorthandLookup("t"), flags.Lookup("template"))

flags.Set("dir", "/")
require.Equal(t, "/", c.dir)

flags.Set("template", "github.com/mesg-foundation/awesome")
require.Equal(t, "github.com/mesg-foundation/awesome", c.templateURL)
}
19 changes: 19 additions & 0 deletions commands/service_logs_test.go
@@ -0,0 +1,19 @@
package commands

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestServiceLogsCmdFlags(t *testing.T) {
c := newServiceLogsCmd(nil)

flags := c.cmd.Flags()
require.Equal(t, flags.ShorthandLookup("d"), flags.Lookup("dependencies"))

flags.Set("dependencies", "a")
flags.Set("dependencies", "b")
require.Equal(t, []string{"a", "b"}, c.dependencies)

}
29 changes: 29 additions & 0 deletions commands/service_test.go
@@ -0,0 +1,29 @@
package commands

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestRootServiceCmd(t *testing.T) {
cmd := newRootServiceCmd(nil).cmd
for _, tt := range []struct {
use string
}{
{"deploy"},
{"validate"},
{"start"},
{"stop"},
{"detail"},
{"list"},
{"init"},
{"delete"},
{"logs"},
{"gen-doc"},
{"dev"},
{"execute"},
} {
require.Truef(t, findCommandChildByUsePrefix(cmd, tt.use), "command %q not found", tt.use)
}
}
17 changes: 17 additions & 0 deletions commands/start_test.go
Expand Up @@ -6,6 +6,23 @@ import (
"github.com/stretchr/testify/require"
)

func TestStartCmdRunE(t *testing.T) {
m := newMockExecutor()
c := newStartCmd(m)

closeStd := captureStd(t)
NicolasMahe marked this conversation as resolved.
Show resolved Hide resolved

m.On("Start").Return(nil)
c.cmd.Execute()

stdout, stderr := closeStd()
require.Contains(t, stdout, "Starting Core.")
require.Contains(t, stdout, "Core started")
require.Empty(t, stderr)

m.AssertExpectations(t)
}

func TestStartCmdFlags(t *testing.T) {
c := newStartCmd(nil)
require.Equal(t, "text", c.lfv.String())
Expand Down
17 changes: 17 additions & 0 deletions commands/status_test.go
@@ -0,0 +1,17 @@
package commands

import (
"testing"

"github.com/mesg-foundation/core/container"
)

func TestStatusCmdRunE(t *testing.T) {
m := newMockExecutor()
c := newStatusCmd(m)

m.On("Status").Return(container.RUNNING, nil)
c.cmd.Execute()

m.AssertExpectations(t)
}