Skip to content

Commit

Permalink
Move the RunStatus type from the lib/ package to cloudapi/
Browse files Browse the repository at this point in the history
The run_status constants are something very specific to the k6 cloud, they shouldn't be a part of the main packages.
  • Loading branch information
na-- committed Jan 20, 2023
1 parent 0b563d4 commit e8b0320
Show file tree
Hide file tree
Showing 10 changed files with 48 additions and 58 deletions.
14 changes: 8 additions & 6 deletions cloudapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ type CreateTestRunResponse struct {
}

type TestProgressResponse struct {
RunStatusText string `json:"run_status_text"`
RunStatus lib.RunStatus `json:"run_status"`
ResultStatus ResultStatus `json:"result_status"`
Progress float64 `json:"progress"`
RunStatusText string `json:"run_status_text"`
RunStatus RunStatus `json:"run_status"`
ResultStatus ResultStatus `json:"result_status"`
Progress float64 `json:"progress"`
}

type LoginResponse struct {
Expand Down Expand Up @@ -107,7 +107,9 @@ func (c *Client) StartCloudTestRun(name string, projectID int64, arc *lib.Archiv
return ctrr.ReferenceID, nil
}

func (c *Client) TestFinished(referenceID string, thresholds ThresholdResult, tained bool, runStatus lib.RunStatus) error {
// TestFinished sends the result and run status values to the cloud, along with
// information for the test thresholds, and marks the test run as finished.
func (c *Client) TestFinished(referenceID string, thresholds ThresholdResult, tained bool, runStatus RunStatus) error {
url := fmt.Sprintf("%s/tests/%s", c.baseURL, referenceID)

resultStatus := ResultStatusPassed
Expand All @@ -117,7 +119,7 @@ func (c *Client) TestFinished(referenceID string, thresholds ThresholdResult, ta

data := struct {
ResultStatus ResultStatus `json:"result_status"`
RunStatus lib.RunStatus `json:"run_status"`
RunStatus RunStatus `json:"run_status"`
Thresholds ThresholdResult `json:"thresholds"`
}{
resultStatus,
Expand Down
9 changes: 3 additions & 6 deletions lib/run_status.go → cloudapi/run_status.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package lib
package cloudapi

// TODO: move to some other package - types? models?

// RunStatus values can be used by k6 to denote how a script run ends
// and by the cloud executor and collector so that k6 knows the current
// status of a particular script run.
// RunStatus values are used to tell the cloud output how a local test run
// ended, and to get that information from the cloud for cloud tests.
type RunStatus int

// Possible run status values; iota isn't used intentionally
Expand Down
8 changes: 4 additions & 4 deletions cmd/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,9 @@ func (c *cmdCloud) run(cmd *cobra.Command, args []string) error {

statusText := testProgress.RunStatusText

if testProgress.RunStatus == lib.RunStatusFinished {
if testProgress.RunStatus == cloudapi.RunStatusFinished {
testProgress.Progress = 1
} else if testProgress.RunStatus == lib.RunStatusRunning {
} else if testProgress.RunStatus == cloudapi.RunStatusRunning {
if startTime.IsZero() {
startTime = time.Now()
}
Expand Down Expand Up @@ -270,8 +270,8 @@ func (c *cmdCloud) run(cmd *cobra.Command, args []string) error {
testProgress = newTestProgress
testProgressLock.Unlock()

if (newTestProgress.RunStatus > lib.RunStatusRunning) ||
(c.exitOnRunning && newTestProgress.RunStatus == lib.RunStatusRunning) {
if (newTestProgress.RunStatus > cloudapi.RunStatusRunning) ||
(c.exitOnRunning && newTestProgress.RunStatus == cloudapi.RunStatusRunning) {
globalCancel()
break
}
Expand Down
31 changes: 15 additions & 16 deletions cmd/tests/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"go.k6.io/k6/cloudapi"
"go.k6.io/k6/cmd"
"go.k6.io/k6/errext/exitcodes"
"go.k6.io/k6/lib"
"go.k6.io/k6/lib/consts"
"go.k6.io/k6/lib/testutils"
"go.k6.io/k6/lib/testutils/httpmultibin"
Expand Down Expand Up @@ -424,7 +423,7 @@ func getTestServer(t *testing.T, routes map[string]http.Handler) *httptest.Serve
return httptest.NewServer(mux)
}

func getCloudTestEndChecker(t *testing.T, expRunStatus lib.RunStatus, expResultStatus cloudapi.ResultStatus) *httptest.Server {
func getCloudTestEndChecker(t *testing.T, expRunStatus cloudapi.RunStatus, expResultStatus cloudapi.ResultStatus) *httptest.Server {
testFinished := false
srv := getTestServer(t, map[string]http.Handler{
"POST ^/v1/tests$": http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
Expand All @@ -445,7 +444,7 @@ func getCloudTestEndChecker(t *testing.T, expRunStatus lib.RunStatus, expResultS
runStatus := gjson.GetBytes(body, "run_status")
require.True(t, runStatus.Exists()) // important to check, since run_status can be 0
assert.Equalf(
t, expRunStatus, lib.RunStatus(runStatus.Int()),
t, expRunStatus, cloudapi.RunStatus(runStatus.Int()),
"received wrong run_status value",
)

Expand All @@ -469,7 +468,7 @@ func getCloudTestEndChecker(t *testing.T, expRunStatus lib.RunStatus, expResultS

func getSimpleCloudOutputTestState(
t *testing.T, script string, cliFlags []string,
expRunStatus lib.RunStatus, expResultStatus cloudapi.ResultStatus, expExitCode exitcodes.ExitCode,
expRunStatus cloudapi.RunStatus, expResultStatus cloudapi.ResultStatus, expExitCode exitcodes.ExitCode,
) *GlobalTestState {
if cliFlags == nil {
cliFlags = []string{"-v", "--log-output=stdout"}
Expand Down Expand Up @@ -516,7 +515,7 @@ func TestSetupTeardownThresholds(t *testing.T) {
};
`)

ts := getSimpleCloudOutputTestState(t, script, nil, lib.RunStatusFinished, cloudapi.ResultStatusPassed, 0)
ts := getSimpleCloudOutputTestState(t, script, nil, cloudapi.RunStatusFinished, cloudapi.ResultStatusPassed, 0)
cmd.ExecuteWithGlobalState(ts.GlobalState)

stdOut := ts.Stdout.String()
Expand Down Expand Up @@ -562,7 +561,7 @@ func TestThresholdsFailed(t *testing.T) {
// Since these thresholds don't have an abortOnFail property, the run_status
// in the cloud will still be Finished, even if the test itself failed.
ts := getSimpleCloudOutputTestState(
t, script, nil, lib.RunStatusFinished, cloudapi.ResultStatusFailed, exitcodes.ThresholdsHaveFailed,
t, script, nil, cloudapi.RunStatusFinished, cloudapi.ResultStatusFailed, exitcodes.ThresholdsHaveFailed,
)
cmd.ExecuteWithGlobalState(ts.GlobalState)

Expand Down Expand Up @@ -603,7 +602,7 @@ func TestAbortedByThreshold(t *testing.T) {
`

ts := getSimpleCloudOutputTestState(
t, script, nil, lib.RunStatusAbortedThreshold, cloudapi.ResultStatusFailed, exitcodes.ThresholdsHaveFailed,
t, script, nil, cloudapi.RunStatusAbortedThreshold, cloudapi.ResultStatusFailed, exitcodes.ThresholdsHaveFailed,
)
cmd.ExecuteWithGlobalState(ts.GlobalState)

Expand Down Expand Up @@ -650,7 +649,7 @@ func TestAbortedByUserWithGoodThresholds(t *testing.T) {
};
`

ts := getSimpleCloudOutputTestState(t, script, nil, lib.RunStatusAbortedUser, cloudapi.ResultStatusPassed, exitcodes.ExternalAbort)
ts := getSimpleCloudOutputTestState(t, script, nil, cloudapi.RunStatusAbortedUser, cloudapi.ResultStatusPassed, exitcodes.ExternalAbort)

asyncWaitForStdoutAndStopTestWithInterruptSignal(t, ts, 15, time.Second, "simple iter 2")

Expand Down Expand Up @@ -778,7 +777,7 @@ func TestAbortedByUserWithRestAPI(t *testing.T) {

ts := getSimpleCloudOutputTestState(
t, script, []string{"-v", "--log-output=stdout", "--iterations", "20"},
lib.RunStatusAbortedUser, cloudapi.ResultStatusPassed, exitcodes.ScriptStoppedFromRESTAPI,
cloudapi.RunStatusAbortedUser, cloudapi.ResultStatusPassed, exitcodes.ScriptStoppedFromRESTAPI,
)

asyncWaitForStdoutAndStopTestFromRESTAPI(t, ts, 15, time.Second, "a simple iteration")
Expand Down Expand Up @@ -818,7 +817,7 @@ func TestAbortedByScriptSetupErrorWithDependency(t *testing.T) {
export { handleSummary } from "./bar.js";
`

srv := getCloudTestEndChecker(t, lib.RunStatusAbortedScriptError, cloudapi.ResultStatusPassed)
srv := getCloudTestEndChecker(t, cloudapi.RunStatusAbortedScriptError, cloudapi.ResultStatusPassed)

ts := NewGlobalTestState(t)
require.NoError(t, afero.WriteFile(ts.FS, filepath.Join(ts.Cwd, "test.js"), []byte(mainScript), 0o644))
Expand Down Expand Up @@ -933,7 +932,7 @@ func TestAbortedByScriptTeardownError(t *testing.T) {

func testAbortedByScriptError(t *testing.T, script string, runTest func(*testing.T, *GlobalTestState)) *GlobalTestState {
ts := getSimpleCloudOutputTestState(
t, script, nil, lib.RunStatusAbortedScriptError, cloudapi.ResultStatusPassed, exitcodes.ScriptException,
t, script, nil, cloudapi.RunStatusAbortedScriptError, cloudapi.ResultStatusPassed, exitcodes.ScriptException,
)
runTest(t, ts)

Expand Down Expand Up @@ -1078,7 +1077,7 @@ func testAbortedByScriptTestAbort(
t *testing.T, shouldHaveMetrics bool, script string, runTest func(*testing.T, *GlobalTestState),
) *GlobalTestState { //nolint:unparam
ts := getSimpleCloudOutputTestState(
t, script, nil, lib.RunStatusAbortedUser, cloudapi.ResultStatusPassed, exitcodes.ScriptAborted,
t, script, nil, cloudapi.RunStatusAbortedUser, cloudapi.ResultStatusPassed, exitcodes.ScriptAborted,
)
runTest(t, ts)

Expand Down Expand Up @@ -1119,7 +1118,7 @@ func TestAbortedByInterruptDuringVUInit(t *testing.T) {
// This is testing the current behavior, which is expected, but it's not
// actually the desired one! See https://github.com/grafana/k6/issues/2804
ts := getSimpleCloudOutputTestState(
t, script, nil, lib.RunStatusAbortedSystem, cloudapi.ResultStatusPassed, exitcodes.GenericEngine,
t, script, nil, cloudapi.RunStatusAbortedSystem, cloudapi.ResultStatusPassed, exitcodes.GenericEngine,
)
asyncWaitForStdoutAndStopTestWithInterruptSignal(t, ts, 15, time.Second, "VU init sleeping for a while")
cmd.ExecuteWithGlobalState(ts.GlobalState)
Expand Down Expand Up @@ -1151,7 +1150,7 @@ func TestAbortedByScriptInitError(t *testing.T) {
`

ts := getSimpleCloudOutputTestState(
t, script, nil, lib.RunStatusAbortedScriptError, cloudapi.ResultStatusPassed, exitcodes.ScriptException,
t, script, nil, cloudapi.RunStatusAbortedScriptError, cloudapi.ResultStatusPassed, exitcodes.ScriptException,
)
cmd.ExecuteWithGlobalState(ts.GlobalState)

Expand Down Expand Up @@ -1249,7 +1248,7 @@ func TestMetricTagAndSetupDataIsolation(t *testing.T) {

ts := getSimpleCloudOutputTestState(
t, script, []string{"--quiet", "--log-output", "stdout"},
lib.RunStatusFinished, cloudapi.ResultStatusPassed, 0,
cloudapi.RunStatusFinished, cloudapi.ResultStatusPassed, 0,
)
cmd.ExecuteWithGlobalState(ts.GlobalState)

Expand Down Expand Up @@ -1419,7 +1418,7 @@ func TestMinIterationDuration(t *testing.T) {
export function teardown() { c.add(1); };
`

ts := getSimpleCloudOutputTestState(t, script, nil, lib.RunStatusFinished, cloudapi.ResultStatusPassed, 0)
ts := getSimpleCloudOutputTestState(t, script, nil, cloudapi.RunStatusFinished, cloudapi.ResultStatusPassed, 0)

start := time.Now()
cmd.ExecuteWithGlobalState(ts.GlobalState)
Expand Down
15 changes: 8 additions & 7 deletions core/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/sirupsen/logrus"

"go.k6.io/k6/cloudapi"
"go.k6.io/k6/errext"
"go.k6.io/k6/errext/exitcodes"
"go.k6.io/k6/lib"
Expand Down Expand Up @@ -151,11 +152,11 @@ func (e *Engine) setRunStatusFromError(err error) {
var serr errext.Exception
switch {
case errors.As(err, &serr):
e.OutputManager.SetRunStatus(lib.RunStatusAbortedScriptError)
e.OutputManager.SetRunStatus(cloudapi.RunStatusAbortedScriptError)
case errext.IsInterruptError(err):
e.OutputManager.SetRunStatus(lib.RunStatusAbortedUser)
e.OutputManager.SetRunStatus(cloudapi.RunStatusAbortedUser)
default:
e.OutputManager.SetRunStatus(lib.RunStatusAbortedSystem)
e.OutputManager.SetRunStatus(cloudapi.RunStatusAbortedSystem)
}
}

Expand Down Expand Up @@ -198,23 +199,23 @@ func (e *Engine) startBackgroundProcesses(
e.setRunStatusFromError(err)
} else {
e.logger.Debug("run: execution scheduler finished nominally")
e.OutputManager.SetRunStatus(lib.RunStatusFinished)
e.OutputManager.SetRunStatus(cloudapi.RunStatusFinished)
}
// do nothing, return the same err value we got from the Run()
// ExecutionScheduler result, we just set the run_status based on it
case <-runCtx.Done():
e.logger.Debug("run: context expired; exiting...")
e.OutputManager.SetRunStatus(lib.RunStatusAbortedUser)
e.OutputManager.SetRunStatus(cloudapi.RunStatusAbortedUser)
err = errext.WithExitCodeIfNone(errors.New("test run aborted by signal"), exitcodes.ExternalAbort)
case <-e.stopChan:
runSubCancel()
e.logger.Debug("run: stopped by user via REST API; exiting...")
e.OutputManager.SetRunStatus(lib.RunStatusAbortedUser)
e.OutputManager.SetRunStatus(cloudapi.RunStatusAbortedUser)
err = errext.WithExitCodeIfNone(errors.New("test run stopped from the REST API"), exitcodes.ScriptStoppedFromRESTAPI)
case <-thresholdAbortChan:
e.logger.Debug("run: stopped by thresholds; exiting...")
runSubCancel()
e.OutputManager.SetRunStatus(lib.RunStatusAbortedThreshold)
e.OutputManager.SetRunStatus(cloudapi.RunStatusAbortedThreshold)
err = errext.WithExitCodeIfNone(errors.New("test run aborted by failed thresholds"), exitcodes.ThresholdsHaveFailed)
}
}()
Expand Down
10 changes: 0 additions & 10 deletions lib/testutils/mockoutput/mockoutput.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package mockoutput

import (
"go.k6.io/k6/lib"
"go.k6.io/k6/metrics"
"go.k6.io/k6/output"
)

// New exists so that the usage from tests avoids repetition, i.e. is
Expand All @@ -16,15 +14,12 @@ func New() *MockOutput {
type MockOutput struct {
SampleContainers []metrics.SampleContainer
Samples []metrics.Sample
RunStatus lib.RunStatus

DescFn func() string
StartFn func() error
StopFn func() error
}

var _ output.WithRunStatusUpdates = &MockOutput{}

// AddMetricSamples just saves the results in memory.
func (mo *MockOutput) AddMetricSamples(scs []metrics.SampleContainer) {
mo.SampleContainers = append(mo.SampleContainers, scs...)
Expand All @@ -33,11 +28,6 @@ func (mo *MockOutput) AddMetricSamples(scs []metrics.SampleContainer) {
}
}

// SetRunStatus updates the RunStatus property.
func (mo *MockOutput) SetRunStatus(latestStatus lib.RunStatus) {
mo.RunStatus = latestStatus
}

// Description calls the supplied DescFn callback, if available.
func (mo *MockOutput) Description() string {
if mo.DescFn != nil {
Expand Down
8 changes: 4 additions & 4 deletions output/cloud/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ type Output struct {
thresholds map[string][]*metrics.Threshold
client *MetricsClient

runStatus lib.RunStatus
runStatus cloudapi.RunStatus

bufferMutex sync.Mutex
bufferHTTPTrails []*httpext.Trail
Expand Down Expand Up @@ -284,7 +284,7 @@ func (out *Output) Description() string {
}

// SetRunStatus receives the latest run status from the Engine.
func (out *Output) SetRunStatus(status lib.RunStatus) {
func (out *Output) SetRunStatus(status cloudapi.RunStatus) {
out.runStatus = status
}

Expand Down Expand Up @@ -634,8 +634,8 @@ func (out *Output) testFinished() error {
}
}

runStatus := lib.RunStatusFinished
if out.runStatus != lib.RunStatusQueued {
runStatus := cloudapi.RunStatusFinished
if out.runStatus != cloudapi.RunStatusQueued {
runStatus = out.runStatus
}

Expand Down
4 changes: 2 additions & 2 deletions output/cloud/output_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ func testCloudOutputStopSendingMetric(t *testing.T, stopOnError bool) {

require.NoError(t, out.Stop())

require.Equal(t, lib.RunStatusQueued, out.runStatus)
require.Equal(t, cloudapi.RunStatusQueued, out.runStatus)
select {
case <-out.stopSendingMetrics:
// all is fine
Expand Down Expand Up @@ -598,7 +598,7 @@ func TestCloudOutputAggregationPeriodZeroNoBlock(t *testing.T) {
tb.Mux.HandleFunc(fmt.Sprintf("/v1/metrics/%s", out.referenceID), getSampleChecker(t, expSamples))

require.NoError(t, out.Stop())
require.Equal(t, lib.RunStatusQueued, out.runStatus)
require.Equal(t, cloudapi.RunStatusQueued, out.runStatus)
}

func TestCloudOutputPushRefID(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions output/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package output

import (
"github.com/sirupsen/logrus"
"go.k6.io/k6/lib"
"go.k6.io/k6/cloudapi"
"go.k6.io/k6/metrics"
)

Expand Down Expand Up @@ -58,7 +58,7 @@ func (om *Manager) stopOutputs(upToID int) {

// SetRunStatus checks which outputs implement the WithRunStatusUpdates
// interface and sets the provided RunStatus to them.
func (om *Manager) SetRunStatus(status lib.RunStatus) {
func (om *Manager) SetRunStatus(status cloudapi.RunStatus) {
for _, out := range om.outputs {
if statUpdOut, ok := out.(WithRunStatusUpdates); ok {
statUpdOut.SetRunStatus(status)
Expand Down
3 changes: 2 additions & 1 deletion output/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/spf13/afero"

"go.k6.io/k6/cloudapi"
"go.k6.io/k6/lib"
"go.k6.io/k6/metrics"
)
Expand Down Expand Up @@ -78,7 +79,7 @@ type WithTestRunStop interface {
// WithRunStatusUpdates means the output can receive test run status updates.
type WithRunStatusUpdates interface {
Output
SetRunStatus(latestStatus lib.RunStatus)
SetRunStatus(latestStatus cloudapi.RunStatus)
}

// WithBuiltinMetrics means the output can receive the builtin metrics.
Expand Down

0 comments on commit e8b0320

Please sign in to comment.