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

Move InterruptError in errext and other refactorings #2536

Merged
merged 2 commits into from
Jun 1, 2022
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ func (c *cmdRun) run(cmd *cobra.Command, args []string) error {
err = engineRun()
if err != nil {
err = common.UnwrapGojaInterruptedError(err)
if common.IsInterruptError(err) {
if errext.IsInterruptError(err) {
// Don't return here since we need to work with --linger,
// show the end-of-test summary and exit cleanly.
interrupt = err
Expand Down
13 changes: 6 additions & 7 deletions cmd/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ import (

"go.k6.io/k6/errext"
"go.k6.io/k6/errext/exitcodes"
"go.k6.io/k6/js/common"
"go.k6.io/k6/lib/fsext"
"go.k6.io/k6/lib/testutils"
)
Expand Down Expand Up @@ -138,27 +137,27 @@ func TestRunScriptErrorsAndAbort(t *testing.T) {
testCases := []struct {
testFilename, name string
expErr, expLogOutput string
expExitCode errext.ExitCode
expExitCode exitcodes.ExitCode
extraArgs []string
}{
{
testFilename: "abort.js",
expErr: common.AbortTest,
expErr: errext.AbortTest,
expExitCode: exitcodes.ScriptAborted,
},
{
testFilename: "abort_initerr.js",
expErr: common.AbortTest,
expErr: errext.AbortTest,
expExitCode: exitcodes.ScriptAborted,
},
{
testFilename: "abort_initvu.js",
expErr: common.AbortTest,
expErr: errext.AbortTest,
expExitCode: exitcodes.ScriptAborted,
},
{
testFilename: "abort_teardown.js",
expErr: common.AbortTest,
expErr: errext.AbortTest,
expExitCode: exitcodes.ScriptAborted,
expLogOutput: "Calling teardown function after test.abort()",
},
Expand Down Expand Up @@ -246,7 +245,7 @@ func TestInvalidOptionsThresholdErrExitCode(t *testing.T) {
testCases := []struct {
name string
testFilename string
expExitCode errext.ExitCode
expExitCode exitcodes.ExitCode
extraArgs []string
}{
{
Expand Down
3 changes: 1 addition & 2 deletions core/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import (
"github.com/sirupsen/logrus"

"go.k6.io/k6/errext"
"go.k6.io/k6/js/common"
"go.k6.io/k6/lib"
"go.k6.io/k6/metrics"
"go.k6.io/k6/metrics/engine"
Expand Down Expand Up @@ -196,7 +195,7 @@ func (e *Engine) startBackgroundProcesses(
switch {
case errors.As(err, &serr):
e.OutputManager.SetRunStatus(lib.RunStatusAbortedScriptError)
case common.IsInterruptError(err):
case errext.IsInterruptError(err):
e.OutputManager.SetRunStatus(lib.RunStatusAbortedUser)
default:
e.OutputManager.SetRunStatus(lib.RunStatusAbortedSystem)
Expand Down
3 changes: 1 addition & 2 deletions core/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (
"github.com/sirupsen/logrus"

"go.k6.io/k6/errext"
"go.k6.io/k6/js/common"
"go.k6.io/k6/lib"
"go.k6.io/k6/lib/executor"
"go.k6.io/k6/metrics"
Expand Down Expand Up @@ -485,7 +484,7 @@ func (e *ExecutionScheduler) Run(globalCtx, runCtx context.Context, engineOut ch
return err
}
}
if err := executor.CancelReason(execCtx); err != nil && common.IsInterruptError(err) {
if err := executor.CancelReason(execCtx); err != nil && errext.IsInterruptError(err) {
interrupted = true
return err
}
Expand Down
7 changes: 4 additions & 3 deletions errext/errext_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.k6.io/k6/errext/exitcodes"
)

func assertHasHint(t *testing.T, err error, hint string) {
Expand All @@ -36,7 +37,7 @@ func assertHasHint(t *testing.T, err error, hint string) {
assert.Contains(t, err.Error(), typederr.Error())
}

func assertHasExitCode(t *testing.T, err error, exitcode ExitCode) {
func assertHasExitCode(t *testing.T, err error, exitcode exitcodes.ExitCode) {
var typederr HasExitCode
require.ErrorAs(t, err, &typederr)
assert.Equal(t, typederr.ExitCode(), exitcode)
Expand All @@ -46,7 +47,7 @@ func assertHasExitCode(t *testing.T, err error, exitcode ExitCode) {
func TestErrextHelpers(t *testing.T) {
t.Parallel()

const testExitCode ExitCode = 13
const testExitCode exitcodes.ExitCode = 13
assert.Nil(t, WithHint(nil, "test hint"))
assert.Nil(t, WithExitCodeIfNone(nil, testExitCode))

Expand All @@ -63,7 +64,7 @@ func TestErrextHelpers(t *testing.T) {
assertHasHint(t, errWithExitCode, "better hint (test hint)")
assertHasExitCode(t, errWithExitCode, testExitCode)

errWithExitCodeAgain := WithExitCodeIfNone(errWithExitCode, ExitCode(27))
errWithExitCodeAgain := WithExitCodeIfNone(errWithExitCode, exitcodes.ExitCode(27))
assertHasHint(t, errWithExitCodeAgain, "better hint (test hint)")
assertHasExitCode(t, errWithExitCodeAgain, testExitCode)

Expand Down
15 changes: 9 additions & 6 deletions errext/exit_code.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,27 @@

package errext

import "errors"
import (
"errors"

"go.k6.io/k6/errext/exitcodes"
)

// ExitCode is the code with which the application should exit if this error
// bubbles up to the top of the scope. Values should be between 0 and 125:
// https://unix.stackexchange.com/questions/418784/what-is-the-min-and-max-values-of-exit-codes-in-linux
type ExitCode uint8

// HasExitCode is a wrapper around an error with an attached exit code.
type HasExitCode interface {
error
ExitCode() ExitCode
ExitCode() exitcodes.ExitCode
}

// WithExitCodeIfNone can attach an exit code to the given error, if it doesn't
// have one already. It won't do anything if the error already had an exit code
// attached. Similarly, if there is no error (i.e. the given error is nil), it
// also won't do anything.
func WithExitCodeIfNone(err error, exitCode ExitCode) error {
func WithExitCodeIfNone(err error, exitCode exitcodes.ExitCode) error {
if err == nil {
// No error, do nothing
return nil
Expand All @@ -52,14 +55,14 @@ func WithExitCodeIfNone(err error, exitCode ExitCode) error {

type withExitCode struct {
error
exitCode ExitCode
exitCode exitcodes.ExitCode
}

func (wh withExitCode) Unwrap() error {
return wh.error
}

func (wh withExitCode) ExitCode() ExitCode {
func (wh withExitCode) ExitCode() exitcodes.ExitCode {
return wh.exitCode
}

Expand Down
28 changes: 15 additions & 13 deletions errext/exitcodes/codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,21 @@
//nolint: golint
package exitcodes

import "go.k6.io/k6/errext"
// ExitCode is just a type representing a process exit code for k6
type ExitCode uint8

// list of exit codes used by k6
const (
CloudTestRunFailed errext.ExitCode = 97 // This used to be 99 before k6 v0.33.0
CloudFailedToGetProgress errext.ExitCode = 98
ThresholdsHaveFailed errext.ExitCode = 99
SetupTimeout errext.ExitCode = 100
TeardownTimeout errext.ExitCode = 101
GenericTimeout errext.ExitCode = 102 // TODO: remove?
GenericEngine errext.ExitCode = 103
InvalidConfig errext.ExitCode = 104
ExternalAbort errext.ExitCode = 105
CannotStartRESTAPI errext.ExitCode = 106
ScriptException errext.ExitCode = 107
ScriptAborted errext.ExitCode = 108
CloudTestRunFailed ExitCode = 97 // This used to be 99 before k6 v0.33.0
CloudFailedToGetProgress ExitCode = 98
ThresholdsHaveFailed ExitCode = 99
SetupTimeout ExitCode = 100
TeardownTimeout ExitCode = 101
GenericTimeout ExitCode = 102 // TODO: remove?
GenericEngine ExitCode = 103
InvalidConfig ExitCode = 104
ExternalAbort ExitCode = 105
CannotStartRESTAPI ExitCode = 106
ScriptException ExitCode = 107
ScriptAborted ExitCode = 108
)
36 changes: 36 additions & 0 deletions errext/interrupt_error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package errext

import (
"errors"

"go.k6.io/k6/errext/exitcodes"
)

// InterruptError is an error that halts engine execution
type InterruptError struct {
Reason string
}

var _ HasExitCode = &InterruptError{}

// Error returns the reason of the interruption.
func (i *InterruptError) Error() string {
return i.Reason
}

// ExitCode returns the status code used when the k6 process exits.
func (i *InterruptError) ExitCode() exitcodes.ExitCode {
return exitcodes.ScriptAborted
}

// AbortTest is the reason emitted when a test script calls test.abort()
const AbortTest = "test aborted"

// IsInterruptError returns true if err is *InterruptError.
func IsInterruptError(err error) bool {
if err == nil {
return false
}
var intErr *InterruptError
return errors.As(err, &intErr)
}
31 changes: 0 additions & 31 deletions js/common/interrupt_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,39 +24,8 @@ import (
"errors"

"github.com/dop251/goja"
"go.k6.io/k6/errext"
"go.k6.io/k6/errext/exitcodes"
)

// InterruptError is an error that halts engine execution
type InterruptError struct {
Reason string
}

var _ errext.HasExitCode = &InterruptError{}

// Error returns the reason of the interruption.
func (i *InterruptError) Error() string {
return i.Reason
}

// ExitCode returns the status code used when the k6 process exits.
func (i *InterruptError) ExitCode() errext.ExitCode {
return exitcodes.ScriptAborted
}

// AbortTest is the reason emitted when a test script calls test.abort()
const AbortTest = "test aborted"

// IsInterruptError returns true if err is *InterruptError.
func IsInterruptError(err error) bool {
if err == nil {
return false
}
var intErr *InterruptError
return errors.As(err, &intErr)
}

// UnwrapGojaInterruptedError returns the internal error handled by goja.
func UnwrapGojaInterruptedError(err error) error {
var gojaErr *goja.InterruptedError
Expand Down
3 changes: 2 additions & 1 deletion js/common/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (

"github.com/dop251/goja"
"github.com/sirupsen/logrus"
"go.k6.io/k6/errext"
)

// Throw a JS error; avoids re-wrapping GoErrors.
Expand Down Expand Up @@ -89,7 +90,7 @@ func RunWithPanicCatching(logger logrus.FieldLogger, rt *goja.Runtime, fn func()
if r := recover(); r != nil {
gojaStack := rt.CaptureCallStack(20, nil)

err = &InterruptError{Reason: fmt.Sprintf("a panic occurred during JS execution: %s", r)}
err = &errext.InterruptError{Reason: fmt.Sprintf("a panic occurred during JS execution: %s", r)}
// TODO figure out how to use PanicLevel without panicing .. this might require changing
// the logger we use see
// https://github.com/sirupsen/logrus/issues/1028
Expand Down
5 changes: 3 additions & 2 deletions js/modules/k6/execution/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (

"github.com/dop251/goja"

"go.k6.io/k6/errext"
"go.k6.io/k6/js/common"
"go.k6.io/k6/js/modules"
"go.k6.io/k6/lib"
Expand Down Expand Up @@ -176,11 +177,11 @@ func (mi *ModuleInstance) newTestInfo() (*goja.Object, error) {
// stop the test run
"abort": func() interface{} {
return func(msg goja.Value) {
reason := common.AbortTest
reason := errext.AbortTest
if msg != nil && !goja.IsUndefined(msg) {
reason = fmt.Sprintf("%s: %s", reason, msg.String())
}
rt.Interrupt(&common.InterruptError{Reason: reason})
rt.Interrupt(&errext.InterruptError{Reason: reason})
}
},
"options": func() interface{} {
Expand Down
7 changes: 4 additions & 3 deletions js/modules/k6/execution/execution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.k6.io/k6/errext"
"go.k6.io/k6/js/common"
"go.k6.io/k6/js/modulestest"
"go.k6.io/k6/lib"
Expand Down Expand Up @@ -197,16 +198,16 @@ func TestAbortTest(t *testing.T) { //nolint:tparallel
require.NotNil(t, err)
var x *goja.InterruptedError
assert.ErrorAs(t, err, &x)
v, ok := x.Value().(*common.InterruptError)
v, ok := x.Value().(*errext.InterruptError)
require.True(t, ok)
require.Equal(t, v.Reason, reason)
}

t.Run("default reason", func(t *testing.T) { //nolint: paralleltest
prove(t, "exec.test.abort()", common.AbortTest)
prove(t, "exec.test.abort()", errext.AbortTest)
})
t.Run("custom reason", func(t *testing.T) { //nolint: paralleltest
prove(t, `exec.test.abort("mayday")`, fmt.Sprintf("%s: mayday", common.AbortTest))
prove(t, `exec.test.abort("mayday")`, fmt.Sprintf("%s: mayday", errext.AbortTest))
})
}

Expand Down
4 changes: 2 additions & 2 deletions js/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ func (u *ActiveVU) RunOnce() error {
if err != nil {
var x *goja.InterruptedError
if errors.As(err, &x) {
if v, ok := x.Value().(*common.InterruptError); ok {
if v, ok := x.Value().(*errext.InterruptError); ok {
v.Reason = x.Error()
err = v
}
Expand Down Expand Up @@ -872,6 +872,6 @@ func (s *scriptException) Hint() string {
return "script exception"
}

func (s *scriptException) ExitCode() errext.ExitCode {
func (s *scriptException) ExitCode() exitcodes.ExitCode {
return exitcodes.ScriptException
}
4 changes: 2 additions & 2 deletions js/runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import (

"go.k6.io/k6/core"
"go.k6.io/k6/core/local"
"go.k6.io/k6/js/common"
"go.k6.io/k6/errext"
"go.k6.io/k6/js/modules/k6"
k6http "go.k6.io/k6/js/modules/k6/http"
k6metrics "go.k6.io/k6/js/modules/k6/metrics"
Expand Down Expand Up @@ -1690,7 +1690,7 @@ func TestInitContextForbidden(t *testing.T) {
`var test = require("k6/execution").test;
test.abort();
exports.default = function() { console.log("p"); }`,
common.AbortTest,
errext.AbortTest,
},
{
"group",
Expand Down
2 changes: 1 addition & 1 deletion js/timeout_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func (t timeoutError) Hint() string {
}

// ExitCode returns the coresponding exit code value to the place.
func (t timeoutError) ExitCode() errext.ExitCode {
func (t timeoutError) ExitCode() exitcodes.ExitCode {
// TODO: add handleSummary()
switch t.place {
case consts.SetupFn:
Expand Down
Loading