Skip to content

Commit

Permalink
fix: more unit tests (#2)
Browse files Browse the repository at this point in the history
* more unit tests

* expect string

* expect string

* expect string

* expect string

* expect string

* tty
  • Loading branch information
shipengqi authored Sep 30, 2022
1 parent 8f29dc4 commit 00de059
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 59 deletions.
6 changes: 3 additions & 3 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -862,8 +862,8 @@ linters:
- predeclared
- promlinter
- revive
- rowserrcheck
- sqlclosecheck
#- rowserrcheck # disabled, because of generics. https://github.com/golangci/golangci-lint/issues/2649
#- sqlclosecheck # disabled, because of generics. https://github.com/golangci/golangci-lint/issues/2649
- staticcheck
#- structcheck # deprecated, replaced by unused
- stylecheck
Expand All @@ -873,7 +873,7 @@ linters:
- unparam
- unused
#- varcheck # deprecated, replaced by unused
- wastedassign
#- wastedassign #disabled because of generics. https://github.com/golangci/golangci-lint/issues/2649
- whitespace
- bidichk
- gomoddirectives
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ func newSubAction2() *action.Action {
}
```

`Executable`: whether is an executable action.
`Execute` will find the first executable action of the root action and execute it.
- `Executable`: whether is an executable action.
- `Execute()` will find the first executable action of the root action and execute it.

## Documentation

Expand Down
100 changes: 100 additions & 0 deletions action_linux_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package action

import (
"os"
"testing"

"github.com/Netflix/go-expect"
"github.com/stretchr/testify/assert"
)

type expectConsole interface {
ExpectString(string)
ExpectEOF()
SendLine(string)
Send(string)
}

type consoleWithErrorHandling struct {
console *expect.Console
t *testing.T
}

func (c *consoleWithErrorHandling) ExpectString(s string) {
if _, err := c.console.ExpectString(s); err != nil {
c.t.Helper()
c.t.Fatalf("ExpectString(%q) = %v", s, err)
}
}

func (c *consoleWithErrorHandling) SendLine(s string) {
if _, err := c.console.SendLine(s); err != nil {
c.t.Helper()
c.t.Fatalf("SendLine(%q) = %v", s, err)
}
}

func (c *consoleWithErrorHandling) Send(s string) {
if _, err := c.console.Send(s); err != nil {
c.t.Helper()
c.t.Fatalf("Send(%q) = %v", s, err)
}
}

func (c *consoleWithErrorHandling) ExpectEOF() {
if _, err := c.console.ExpectEOF(); err != nil {
c.t.Helper()
c.t.Fatalf("ExpectEOF() = %v", err)
}
}

func TestActionFind(t *testing.T) {
c, err := expect.NewConsole(expect.WithStdin(os.Stdin), expect.WithStdout(os.Stdout))
if err != nil {
t.Fatalf("failed to create console: %v", err)
}
defer func() { _ = c.Close() }()
console := &consoleWithErrorHandling{console: c, t: t}

t.Run("cannot find target without sub actions", func(t *testing.T) {
act := getRootAction(c.Tty())
err = act.Execute()
assert.NoError(t, err)

console.ExpectString("PersistentPreRun action name: root")
console.ExpectString("PreRun action name: root")
console.ExpectString("Run action name: root")
console.ExpectString("PostRun action name: root")
console.ExpectString("PersistentPostRun action name: root")
})

t.Run("execute the target action", func(t *testing.T) {
act := getRootAction(c.Tty())
acts := getSubActions(c.Tty(), _rootActionName, 10)
acts[9].Executable = getTargetFunc(true)
_ = act.AddAction(acts...)
err = act.Execute()
assert.NoError(t, err)
console.ExpectString("PersistentPreRun action name: root-sub-action-10")
console.ExpectString("PreRun action name: root-sub-action-10")
console.ExpectString("Run action name: root-sub-action-10")
console.ExpectString("PostRun action name: root-sub-action-10")
console.ExpectString("PersistentPostRun action name: root-sub-action-10")
})

t.Run("execute the multi layers target action", func(t *testing.T) {
act := getRootAction(c.Tty())
acts := getSubActions(c.Tty(), _rootActionName, 5)
subsubs := getSubActions(c.Tty(), "root-sub-action-5", 10)
subsubs[9].Executable = getTargetFunc(true)
_ = acts[4].AddAction(subsubs...)
_ = act.AddAction(acts...)
err = act.Execute()
assert.NoError(t, err)
console.ExpectString("PersistentPreRun action name: root-sub-action-5-sub-action-10")
console.ExpectString("PreRun action name: root-sub-action-5-sub-action-10")
console.ExpectString("Run action name: root-sub-action-5-sub-action-10")
console.ExpectString("PostRun action name: root-sub-action-5-sub-action-10")
console.ExpectString("PersistentPostRun action name: root-sub-action-5-sub-action-10")
})
}
122 changes: 69 additions & 53 deletions action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"os"
"testing"
"time"

Expand All @@ -12,9 +13,9 @@ import (

const _rootActionName = "root"

func getTestHookFunc(t *testing.T, name string) func(act *Action) error {
func getTestHookFunc(tty *os.File, name string) func(act *Action) error {
return func(act *Action) error {
t.Logf("%s action name: %s", name, act.Name)
_, _ = fmt.Fprintf(tty, "%s action name: %s\n", name, act.Name)
return nil
}
}
Expand All @@ -25,62 +26,62 @@ func getTargetFunc(istarget bool) func(act *Action) bool {
}
}

func getRootAction(t *testing.T) *Action {
func getRootAction(tty *os.File) *Action {
return &Action{
Name: "root",
PersistentPreRun: getTestHookFunc(t, "PersistentPreRun"),
PreRun: getTestHookFunc(t, "PreRun"),
Run: getTestHookFunc(t, "Run"),
PostRun: getTestHookFunc(t, "PostRun"),
PersistentPostRun: getTestHookFunc(t, "PersistentPostRun"),
PersistentPreRun: getTestHookFunc(tty, "PersistentPreRun"),
PreRun: getTestHookFunc(tty, "PreRun"),
Run: getTestHookFunc(tty, "Run"),
PostRun: getTestHookFunc(tty, "PostRun"),
PersistentPostRun: getTestHookFunc(tty, "PersistentPostRun"),
Executable: getTargetFunc(false),
}
}

func getSubActions(t *testing.T, parent string, count int) []*Action {
func getSubActions(tty *os.File, parent string, count int) []*Action {
if count < 1 {
return nil
}
var actions []*Action
for i := 0; i < count; i++ {
actions = append(actions, &Action{
Name: fmt.Sprintf("%s-sub-action-%d", parent, i+1),
PersistentPreRun: getTestHookFunc(t, "PersistentPreRun"),
PreRun: getTestHookFunc(t, "PreRun"),
Run: getTestHookFunc(t, "Run"),
PostRun: getTestHookFunc(t, "PostRun"),
PersistentPostRun: getTestHookFunc(t, "PersistentPostRun"),
PersistentPreRun: getTestHookFunc(tty, "PersistentPreRun"),
PreRun: getTestHookFunc(tty, "PreRun"),
Run: getTestHookFunc(tty, "Run"),
PostRun: getTestHookFunc(tty, "PostRun"),
PersistentPostRun: getTestHookFunc(tty, "PersistentPostRun"),
Executable: getTargetFunc(false),
})
}
return actions
}

func TestActionRunnable(t *testing.T) {
act := getRootAction(t)
act := getRootAction(os.Stdout)
assert.True(t, act.Runnable())
act.Run = nil
assert.False(t, act.Runnable())
}

func TestActionAddAction(t *testing.T) {
t.Run("successfully add 5 actions", func(t *testing.T) {
act := getRootAction(t)
acts := getSubActions(t, _rootActionName, 5)
act := getRootAction(os.Stdout)
acts := getSubActions(os.Stdout, _rootActionName, 5)
_ = act.AddAction(acts...)
assert.Equal(t, 5, len(act.Actions()))
})
t.Run("doesn't accept self as sub action", func(t *testing.T) {
act := getRootAction(t)
act := getRootAction(os.Stdout)
err := act.AddAction(act)
assert.EqualError(t, err, "action can't be a child of itself")
})
}

func TestActionParent(t *testing.T) {
t.Run("should returns parent action", func(t *testing.T) {
act := getRootAction(t)
acts := getSubActions(t, _rootActionName, 1)
act := getRootAction(os.Stdout)
acts := getSubActions(os.Stdout, _rootActionName, 1)
_ = act.AddAction(acts...)
assert.False(t, act.HasParent())
assert.True(t, act.HasSubActions())
Expand All @@ -90,8 +91,8 @@ func TestActionParent(t *testing.T) {
}

func TestActionRemove(t *testing.T) {
act := getRootAction(t)
acts := getSubActions(t, _rootActionName, 10)
act := getRootAction(os.Stdout)
acts := getSubActions(os.Stdout, _rootActionName, 10)
_ = act.AddAction(acts...)
acts[9].Executable = getTargetFunc(true)
assert.Equal(t, acts[9], act.Find())
Expand All @@ -100,43 +101,15 @@ func TestActionRemove(t *testing.T) {
}

func TestActionRoot(t *testing.T) {
act := getRootAction(t)
acts := getSubActions(t, _rootActionName, 10)
act := getRootAction(os.Stdout)
acts := getSubActions(os.Stdout, _rootActionName, 10)
_ = act.AddAction(acts...)
assert.Equal(t, act, act)
assert.Equal(t, act, acts[9].Root())
}

func TestActionFind(t *testing.T) {
t.Run("cannot find target without sub actions", func(t *testing.T) {
act := getRootAction(t)
err := act.Execute()
t.Log(err)
})

t.Run("execute the target action", func(t *testing.T) {
act := getRootAction(t)
acts := getSubActions(t, _rootActionName, 10)
acts[9].Executable = getTargetFunc(true)
_ = act.AddAction(acts...)
err := act.Execute()
t.Log(err)
})

t.Run("execute the multi layers target action", func(t *testing.T) {
act := getRootAction(t)
acts := getSubActions(t, _rootActionName, 10)
subsubs := getSubActions(t, "root-sub-action-10", 10)
subsubs[9].Executable = getTargetFunc(true)
_ = acts[9].AddAction(subsubs...)
_ = act.AddAction(acts...)
err := act.Execute()
t.Log(err)
})
}

func TestActionExecuteContext(t *testing.T) {
act := getRootAction(t)
act := getRootAction(os.Stdout)
act.Run = func(act *Action) error {
for {
select {
Expand All @@ -155,3 +128,46 @@ func TestActionExecuteContext(t *testing.T) {
err := act.ExecuteContext(ctx)
assert.EqualError(t, err, "done")
}

func TestActionExecute(t *testing.T) {
t.Run("ignore action without Run", func(t *testing.T) {
act := getRootAction(os.Stdout)
assert.Nil(t, act.Execute())
})

t.Run("returns error in PreRun", func(t *testing.T) {
act := getRootAction(os.Stdout)
act.PreRun = func(act *Action) error {
return errors.New("PreRun error")
}
err := act.Execute()
assert.EqualError(t, err, "PreRun error")
})

t.Run("returns error in PostRun", func(t *testing.T) {
act := getRootAction(os.Stdout)
act.PostRun = func(act *Action) error {
return errors.New("PostRun error")
}
err := act.Execute()
assert.EqualError(t, err, "PostRun error")
})

t.Run("returns error in PersistentPreRun", func(t *testing.T) {
act := getRootAction(os.Stdout)
act.PersistentPreRun = func(act *Action) error {
return errors.New("PersistentPreRun error")
}
err := act.Execute()
assert.EqualError(t, err, "PersistentPreRun error")
})

t.Run("returns error in PersistentPostRun", func(t *testing.T) {
act := getRootAction(os.Stdout)
act.PersistentPostRun = func(act *Action) error {
return errors.New("PersistentPostRun error")
}
err := act.Execute()
assert.EqualError(t, err, "PersistentPostRun error")
})
}
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ module github.com/shipengqi/action

go 1.18

require github.com/stretchr/testify v1.8.0
require (
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2
github.com/stretchr/testify v1.8.0
)

require (
github.com/creack/pty v1.1.17 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
Expand Down

0 comments on commit 00de059

Please sign in to comment.