Skip to content
This repository has been archived by the owner on Mar 15, 2024. It is now read-only.

Commit

Permalink
🍅 Prepare v0.11.9 release (#18)
Browse files Browse the repository at this point in the history
* 🍅 Prepare v0.11.9 release

- use constant errors
- replace go-convey with `testify/require`
  • Loading branch information
im-kulikov authored Apr 25, 2019
1 parent 1ddddcb commit 617e4be
Show file tree
Hide file tree
Showing 7 changed files with 303 additions and 219 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ require (
github.com/prometheus/client_golang v0.9.2
github.com/prometheus/common v0.3.0 // indirect
github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967 // indirect
github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa
github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa // indirect
github.com/spf13/viper v1.3.2
github.com/stretchr/testify v1.3.0
go.uber.org/atomic v1.3.2
Expand Down
283 changes: 172 additions & 111 deletions helium_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,182 +15,243 @@ import (
"github.com/im-kulikov/helium/logger"
"github.com/im-kulikov/helium/module"
"github.com/im-kulikov/helium/settings"
. "github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/require"
"go.uber.org/dig"
"go.uber.org/zap"
)

type (
heliumApp struct{}
heliumErrApp struct{}

Error string
)

const ErrTest = Error("test")

func (e Error) Error() string {
return string(e)
}

func (h heliumApp) Run(ctx context.Context) error { return nil }
func (h heliumErrApp) Run(ctx context.Context) error { return errors.New("test") }
func (h heliumErrApp) Run(ctx context.Context) error { return ErrTest }

func TestHelium(t *testing.T) {
Convey("Helium test suite", t, func(c C) {
c.Convey("create new helium without errors", func(c C) {
h, err := New(&Settings{}, module.Module{
{Constructor: func() App { return heliumApp{} }},
}.Append(grace.Module, settings.Module, logger.Module))
t.Run("create new helium without errors", func(t *testing.T) {
h, err := New(&Settings{}, module.Module{
{Constructor: func() App { return heliumApp{} }},
}.Append(grace.Module, settings.Module, logger.Module))

require.NotNil(t, h)
require.NoError(t, err)
require.NoError(t, h.Run())
})

c.So(h, ShouldNotBeNil)
c.So(err, ShouldBeNil)
t.Run("create new helium and setup ENV", func(t *testing.T) {
tmpFile, err := ioutil.TempFile("", "example")
require.NoError(t, err)

defer func() {
require.NoError(t, os.Remove(tmpFile.Name()))
}() // clean up

err = os.Setenv("ABC_CONFIG", tmpFile.Name())
require.NoError(t, err)

err = os.Setenv("ABC_CONFIG_TYPE", "toml")
require.NoError(t, err)

h, err := New(&Settings{
Name: "Abc",
}, module.Module{
{Constructor: func(cfg *settings.Core) App {
require.Equal(t, tmpFile.Name(), cfg.File)
require.Equal(t, "toml", cfg.Type)
return heliumApp{}
}},
}.Append(grace.Module, settings.Module, logger.Module))

require.NotNil(t, h)
require.NoError(t, err)
require.NoError(t, h.Run())
})

c.So(h.Run(), ShouldBeNil)
t.Run("create new helium should fail on new", func(t *testing.T) {
h, err := New(&Settings{}, module.Module{
{Constructor: func() error { return nil }},
})

c.Convey("create new helium and setup ENV", func(c C) {
tmpFile, err := ioutil.TempFile("", "example")
c.So(err, ShouldBeNil)
require.Nil(t, h)
require.Error(t, err)
})
t.Run("create new helium should fail on start", func(t *testing.T) {
h, err := New(&Settings{}, module.Module{
{Constructor: func() App { return heliumErrApp{} }},
}.Append(grace.Module, settings.Module, logger.Module))

defer os.Remove(tmpFile.Name()) // clean up
require.NotNil(t, h)
require.NoError(t, err)

os.Setenv("ABC_CONFIG", tmpFile.Name())
os.Setenv("ABC_CONFIG_TYPE", "toml")
require.Error(t, h.Run())
})

h, err := New(&Settings{
Name: "Abc",
}, module.Module{
{Constructor: func(cfg *settings.Core) App {
c.So(cfg.File, ShouldEqual, tmpFile.Name())
c.So(cfg.Type, ShouldEqual, "toml")
return heliumApp{}
}},
}.Append(grace.Module, settings.Module, logger.Module))
t.Run("create new helium should fail on start", func(t *testing.T) {
h, err := New(&Settings{}, module.Module{
{Constructor: func() App { return heliumErrApp{} }},
}.Append(grace.Module, settings.Module, logger.Module))

c.So(h, ShouldNotBeNil)
c.So(err, ShouldBeNil)
require.NotNil(t, h)
require.NoError(t, err)

c.So(h.Run(), ShouldBeNil)
})
require.Error(t, h.Run())
})

c.Convey("create new helium should fail on new", func(c C) {
h, err := New(&Settings{}, module.Module{
{Constructor: func() error { return nil }},
})
t.Run("invoke dependencies from helium container", func(t *testing.T) {
t.Run("should be ok", func(t *testing.T) {
h, err := New(&Settings{}, grace.Module.Append(settings.Module, logger.Module))

require.NotNil(t, h)
require.NoError(t, err)

c.So(h, ShouldBeNil)
c.So(err, ShouldBeError)
require.Nil(t, h.Invoke(func() {}))
})

c.Convey("create new helium should fail on start", func(c C) {
h, err := New(&Settings{}, module.Module{
{Constructor: func() App { return heliumErrApp{} }},
}.Append(grace.Module, settings.Module, logger.Module))
t.Run("should fail", func(t *testing.T) {
h, err := New(&Settings{}, grace.Module.Append(settings.Module, logger.Module))

c.So(h, ShouldNotBeNil)
c.So(err, ShouldBeNil)
require.NotNil(t, h)
require.NoError(t, err)

c.So(h.Run(), ShouldBeError)
require.Error(t, h.Invoke(func(string) {}))
})
})

c.Convey("invoke dependencies from helium container", func(c C) {
c.Convey("should be ok", func(c C) {
h, err := New(&Settings{}, grace.Module.Append(settings.Module, logger.Module))
t.Run("check catch", func(t *testing.T) {
t.Run("should panic", func(t *testing.T) {
var exitCode int

c.So(h, ShouldNotBeNil)
c.So(err, ShouldBeNil)
monkey.Patch(os.Exit, func(code int) { exitCode = code })
monkey.Patch(log.Fatal, func(...interface{}) { exitCode = 2 })

defer monkey.UnpatchAll()

c.So(h.Invoke(func() {}), ShouldBeNil)
monkey.Patch(logger.NewLogger, func(*logger.Config, *settings.Core) (*zap.Logger, error) {
return nil, errors.New("test")
})
defer monkey.Unpatch(logger.NewLogger)

err := errors.New("test")
Catch(err)
require.Equal(t, 2, exitCode)
})

t.Run("should catch error", func(t *testing.T) {
var exitCode int

c.Convey("should fail", func(c C) {
h, err := New(&Settings{}, grace.Module.Append(settings.Module, logger.Module))
monkey.Patch(os.Exit, func(code int) { exitCode = code })
monkey.Patch(log.Fatal, func(...interface{}) { exitCode = 2 })

c.So(h, ShouldNotBeNil)
c.So(err, ShouldBeNil)
defer monkey.UnpatchAll()

c.So(h.Invoke(func(string) {}), ShouldBeError)
monkey.Patch(fmt.Fprintf, func(io.Writer, string, ...interface{}) (int, error) {
return 0, nil
})
defer monkey.Unpatch(fmt.Fprintf)

monkey.Patch(logger.NewLogger, func(*logger.Config, *settings.Core) (*zap.Logger, error) {
return zap.NewNop(), nil
})
defer monkey.Unpatch(logger.NewLogger)

err := errors.New("test")
Catch(err)
require.Equal(t, 1, exitCode)
})

c.Convey("check catch", func(c C) {
t.Run("shouldn't catch any", func(t *testing.T) {
var exitCode int

monkey.Patch(os.Exit, func(code int) { exitCode = code })
monkey.Patch(log.Fatal, func(...interface{}) { exitCode = 2 })

defer monkey.UnpatchAll()

c.Convey("should panic", func(c C) {
monkey.Patch(logger.NewLogger, func(*logger.Config, *settings.Core) (*zap.Logger, error) {
return nil, errors.New("test")
})
defer monkey.Unpatch(logger.NewLogger)
Catch(nil)
require.Empty(t, exitCode)
})

err := errors.New("test")
Catch(err)
c.So(exitCode, ShouldEqual, 2)
})
t.Run("should catch stacktrace simple error", func(t *testing.T) {
var exitCode int

c.Convey("should catch error", func(c C) {
monkey.Patch(fmt.Fprintf, func(io.Writer, string, ...interface{}) (int, error) {
return 0, nil
})
defer monkey.Unpatch(fmt.Fprintf)
monkey.Patch(os.Exit, func(code int) { exitCode = code })
monkey.Patch(log.Fatal, func(...interface{}) { exitCode = 2 })

monkey.Patch(logger.NewLogger, func(*logger.Config, *settings.Core) (*zap.Logger, error) {
return zap.NewNop(), nil
})
defer monkey.Unpatch(logger.NewLogger)
defer monkey.UnpatchAll()

err := errors.New("test")
Catch(err)
c.So(exitCode, ShouldEqual, 1)
monkey.Patch(fmt.Printf, func(string, ...interface{}) (int, error) {
return 0, nil
})

c.Convey("shouldn't catch any", func(c C) {
Catch(nil)
c.So(exitCode, ShouldBeZeroValue)
require.Panics(t, func() {
CatchTrace(
errors.New("test"))
})

c.Convey("should catch stacktrace simple error", func(c C) {
monkey.Patch(fmt.Printf, func(string, ...interface{}) (int, error) {
return 0, nil
})
require.Empty(t, exitCode)
})

t.Run("should catch stacktrace on nil", func(t *testing.T) {
var exitCode int

c.So(func() {
CatchTrace(
errors.New("test"))
}, ShouldPanic)
monkey.Patch(os.Exit, func(code int) { exitCode = code })
monkey.Patch(log.Fatal, func(...interface{}) { exitCode = 2 })

c.So(exitCode, ShouldEqual, 0)
defer monkey.UnpatchAll()

require.NotPanics(t, func() {
CatchTrace(nil)
})

c.Convey("should catch stacktrace on nil", func(c C) {
c.So(func() {
CatchTrace(nil)
}, ShouldNotPanic)
require.Empty(t, exitCode)
})

c.So(exitCode, ShouldEqual, 0)
})
t.Run("should catch stacktrace on dig.Errors", func(t *testing.T) {
var exitCode int

c.Convey("should catch stacktrace on dig.Errors", func(c C) {
monkey.Patch(fmt.Fprintf, func(io.Writer, string, ...interface{}) (int, error) { return 0, nil })
defer monkey.Unpatch(fmt.Fprintf)
monkey.Patch(os.Exit, func(code int) { exitCode = code })
monkey.Patch(log.Fatal, func(...interface{}) { exitCode = 2 })

c.So(func() {
di := dig.New()
CatchTrace(di.Invoke(func(log *zap.Logger) error {
return nil
}))
}, ShouldPanic)
defer monkey.UnpatchAll()

c.So(exitCode, ShouldEqual, 0)
monkey.Patch(fmt.Fprintf, func(io.Writer, string, ...interface{}) (int, error) { return 0, nil })
defer monkey.Unpatch(fmt.Fprintf)

require.Panics(t, func() {
di := dig.New()
CatchTrace(di.Invoke(func(log *zap.Logger) error {
return nil
}))
})

c.Convey("should catch context.DeadlineExceeded on dig.Errors", func(c C) {
c.So(func() {
di := dig.New()
CatchTrace(di.Invoke(func() error {
return context.DeadlineExceeded
}))
}, ShouldPanic)
require.Empty(t, exitCode)
})

t.Run("should catch context.DeadlineExceeded on dig.Errors", func(t *testing.T) {
var exitCode int

monkey.Patch(os.Exit, func(code int) { exitCode = code })
monkey.Patch(log.Fatal, func(...interface{}) { exitCode = 2 })

c.So(exitCode, ShouldEqual, 0)
defer monkey.UnpatchAll()

require.Panics(t, func() {
di := dig.New()
CatchTrace(di.Invoke(func() error {
return context.DeadlineExceeded
}))
})

require.Empty(t, exitCode)
})
})
}
Loading

0 comments on commit 617e4be

Please sign in to comment.