Skip to content

Commit

Permalink
Merge branch 'master' into feature/diable-setup-with-timeout-0
Browse files Browse the repository at this point in the history
  • Loading branch information
tsukasaI authored Aug 24, 2024
2 parents 9cb8bf9 + 8244d49 commit c258fb8
Show file tree
Hide file tree
Showing 114 changed files with 1,161 additions and 291 deletions.
5 changes: 4 additions & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# v1.57.2
# v1.60.1
# Please don't remove the first line. It uses in CI to determine the golangci version
run:
timeout: 5m
Expand All @@ -19,6 +19,7 @@ issues:
# files (due to common repeats and long functions in test code)
- path: _(test|gen)\.go
linters:
- canonicalheader
- cyclop
- dupl
- gocognit
Expand Down Expand Up @@ -68,6 +69,7 @@ linters:
- asciicheck
- bidichk
- bodyclose
- canonicalheader
- contextcheck
- cyclop
- dogsled
Expand All @@ -79,6 +81,7 @@ linters:
- errorlint
- exhaustive
- exportloopref
- fatcontext
- forbidigo
- forcetypeassert
- funlen
Expand Down
4 changes: 2 additions & 2 deletions cloudapi/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const (
// MaxRetries specifies max retry attempts
MaxRetries = 3

k6IdempotencyKeyHeader = "k6-Idempotency-Key"
k6IdempotencyKeyHeader = "K6-Idempotency-Key"
)

// Client handles communication with the k6 Cloud API.
Expand Down Expand Up @@ -212,7 +212,7 @@ func shouldRetry(resp *http.Response, err error, attempt, maxAttempts int) bool
return true
}

if resp.StatusCode >= 500 || resp.StatusCode == 429 {
if resp.StatusCode >= 500 || resp.StatusCode == http.StatusTooManyRequests {
return true
}

Expand Down
8 changes: 4 additions & 4 deletions cloudapi/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func (c *Config) logtailConn(ctx context.Context, referenceID string, since time
headers := make(http.Header)
headers.Add("Sec-WebSocket-Protocol", "token="+c.Token.String)
headers.Add("Authorization", "token "+c.Token.String)
headers.Add("X-K6TestRun-Id", referenceID)
headers.Add("X-K6testrun-Id", referenceID)

var conn *websocket.Conn
err = retry(sleeperFunc(time.Sleep), 3, 5*time.Second, 2*time.Minute, func() (err error) {
Expand Down Expand Up @@ -226,7 +226,7 @@ func (sfn sleeperFunc) Sleep(d time.Duration) {
// between the latest iteration and the next retry.
// Interval is used as the base to compute an exponential backoff,
// if the computed interval overtakes the max interval then max will be used.
func retry(s sleeper, attempts uint, interval, max time.Duration, do func() error) (err error) {
func retry(s sleeper, attempts uint, interval, maxDuration time.Duration, do func() error) (err error) {
baseInterval := math.Abs(interval.Truncate(time.Second).Seconds())
r := rand.New(rand.NewSource(time.Now().UnixNano())) //nolint:gosec

Expand All @@ -236,8 +236,8 @@ func retry(s sleeper, attempts uint, interval, max time.Duration, do func() erro
wait := time.Duration(math.Pow(baseInterval, float64(i))) * time.Second
wait += time.Duration(r.Int63n(1000)) * time.Millisecond

if wait > max {
wait = max
if wait > maxDuration {
wait = maxDuration
}
s.Sleep(wait)
}
Expand Down
25 changes: 15 additions & 10 deletions cmd/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

"github.com/fatih/color"
"go.k6.io/k6/cloudapi"
"go.k6.io/k6/cmd/state"
"go.k6.io/k6/errext"
"go.k6.io/k6/errext/exitcodes"
"go.k6.io/k6/lib"
Expand All @@ -22,8 +23,6 @@ import (

"github.com/spf13/cobra"
"github.com/spf13/pflag"

"go.k6.io/k6/cmd/state"
)

// cmdCloud handles the `k6 cloud` sub-command
Expand Down Expand Up @@ -313,9 +312,16 @@ func (c *cmdCloud) run(cmd *cobra.Command, args []string) error {
logger.WithField("run_status", testProgress.RunStatusText).Debug("Test finished")
}

//nolint:stylecheck,golint
if testProgress.ResultStatus == cloudapi.ResultStatusFailed {
// Although by looking at [ResultStatus] and [RunStatus] isn't self-explanatory,
// the scenario when the test run has finished, but it failed is an exceptional case for those situations
// when thresholds have been crossed (failed). So, we report this situation as such.
if testProgress.RunStatus == cloudapi.RunStatusFinished {
return errext.WithExitCodeIfNone(errors.New("Thresholds have been crossed"), exitcodes.ThresholdsHaveFailed)
}

// TODO: use different exit codes for failed thresholds vs failed test (e.g. aborted by system/limit)
//nolint:stylecheck,golint
return errext.WithExitCodeIfNone(errors.New("The test has failed"), exitcodes.CloudTestRunFailed)
}

Expand Down Expand Up @@ -366,16 +372,15 @@ func getCmdCloud(gs *state.GlobalState) *cobra.Command {
cloudCmd := &cobra.Command{
Use: "cloud",
Short: "Run a test on the cloud",
Long: `Run a test in the Grafana Cloud k6.
Long: `The original behavior of the "k6 cloud" command described below is deprecated.
In future versions, the "cloud" command will only display a help text and will no longer run tests
in Grafana Cloud k6. To continue running tests in the cloud, please transition to using the "k6 cloud run" command.
Run a test in the Grafana Cloud k6.
This will archive test script(s), including all necessary resources, and execute the test in the Grafana Cloud k6
service. Be sure to run the "k6 cloud login" command prior to authenticate with Grafana Cloud k6.`,
Args: exactCloudArgs(),
Deprecated: `the k6 team is in the process of modifying and deprecating the "k6 cloud" command behavior.
In the future, the "cloud" command will only display a help text, instead of running tests in the Grafana Cloud k6.
To run tests in the cloud, users are now invited to migrate to the "k6 cloud run" command instead.
`,
Args: exactCloudArgs(),
PreRunE: c.preRun,
RunE: c.run,
Example: exampleText,
Expand Down
90 changes: 90 additions & 0 deletions cmd/root_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package cmd

import (
"testing"

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

func TestRootCommandHelpDisplayCommands(t *testing.T) {
t.Parallel()

testCases := []struct {
name string
extraArgs []string
wantExitCode exitcodes.ExitCode
wantStdoutContains string
wantStdoutNotContains string
}{
{
name: "should have archive command",
wantStdoutContains: " archive Create an archive",
},
{
name: "should have cloud command",
wantStdoutContains: " cloud Run a test on the cloud",
},
{
name: "should have completion command",
wantStdoutContains: " completion Generate the autocompletion script for the specified shell",
},
{
name: "should have help command",
wantStdoutContains: " help Help about any command",
},
{
name: "should have inspect command",
wantStdoutContains: " inspect Inspect a script or archive",
},
{
name: "should have new command",
wantStdoutContains: " new Create and initialize a new k6 script",
},
{
name: "should have pause command",
wantStdoutContains: " pause Pause a running test",
},
{
name: "should have resume command",
wantStdoutContains: " resume Resume a paused test",
},
{
name: "should have run command",
wantStdoutContains: " run Start a test",
},
{
name: "should have scale command",
wantStdoutContains: " scale Scale a running test",
},
{
name: "should have stats command",
wantStdoutContains: " stats Show test metrics",
},
{
name: "should have status command",
wantStdoutContains: " status Show test status",
},
{
name: "should have version command",
wantStdoutContains: " version Show application version",
},
}

for _, tc := range testCases {
tc := tc

t.Run(tc.name, func(t *testing.T) {
t.Parallel()

ts := tests.NewGlobalTestState(t)
ts.CmdArgs = []string{"k6", "help"}
newRootCommand(ts.GlobalState).execute()

if tc.wantStdoutContains != "" {
assert.Contains(t, ts.Stdout.String(), tc.wantStdoutContains)
}
})
}
}
6 changes: 3 additions & 3 deletions cmd/scale.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ func getCmdScale(gs *state.GlobalState) *cobra.Command {
Use the global --address flag to specify the URL to the API server.`,
RunE: func(cmd *cobra.Command, _ []string) error {
vus := getNullInt64(cmd.Flags(), "vus")
max := getNullInt64(cmd.Flags(), "max")
if !vus.Valid && !max.Valid {
maxVUs := getNullInt64(cmd.Flags(), "max")
if !vus.Valid && !maxVUs.Valid {
return errors.New("Specify either -u/--vus or -m/--max") //nolint:golint,stylecheck
}

c, err := client.New(gs.Flags.Address)
if err != nil {
return err
}
status, err := c.SetStatus(gs.Ctx, v1.Status{VUs: vus, VUsMax: max})
status, err := c.SetStatus(gs.Ctx, v1.Status{VUs: vus, VUsMax: maxVUs})
if err != nil {
return err
}
Expand Down
29 changes: 25 additions & 4 deletions cmd/tests/cmd_cloud_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import (
"path/filepath"
"testing"

"go.k6.io/k6/lib/testutils"

"go.k6.io/k6/cloudapi"
"go.k6.io/k6/cmd"
"go.k6.io/k6/errext/exitcodes"
"go.k6.io/k6/lib/fsext"
"go.k6.io/k6/lib/testutils"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.k6.io/k6/cloudapi"
"go.k6.io/k6/lib/fsext"
)

func TestK6Cloud(t *testing.T) {
Expand Down Expand Up @@ -236,6 +236,27 @@ func runCloudTests(t *testing.T, setupCmd setupCommandFunc) {
assert.Contains(t, stdout, `output: https://app.k6.io/runs/123`)
assert.Contains(t, stdout, `test status: Finished`)
})

t.Run("TestCloudThresholdsHaveFailed", func(t *testing.T) {
t.Parallel()

progressCallback := func() cloudapi.TestProgressResponse {
return cloudapi.TestProgressResponse{
RunStatusText: "Finished",
RunStatus: cloudapi.RunStatusFinished,
ResultStatus: cloudapi.ResultStatusFailed,
Progress: 1.0,
}
}
ts := getSimpleCloudTestState(t, nil, setupCmd, nil, nil, progressCallback)
ts.ExpectedExitCode = int(exitcodes.ThresholdsHaveFailed)

cmd.ExecuteWithGlobalState(ts.GlobalState)

stdout := ts.Stdout.String()
t.Log(stdout)
assert.Contains(t, stdout, `Thresholds have been crossed`)
})
}

func cloudTestStartSimple(tb testing.TB, testRunID int) http.Handler {
Expand Down
14 changes: 7 additions & 7 deletions cmd/tests/cmd_run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1434,14 +1434,14 @@ func sum(vals []float64) (sum float64) {
return sum
}

func max(vals []float64) float64 {
max := vals[0]
func maxFloat64(vals []float64) float64 {
result := vals[0]
for _, val := range vals {
if max < val {
max = val
if result < val {
result = val
}
}
return max
return result
}

func TestActiveVUsCount(t *testing.T) {
Expand Down Expand Up @@ -1499,8 +1499,8 @@ func TestActiveVUsCount(t *testing.T) {
jsonResults, err := fsext.ReadFile(ts.FS, "results.json")
require.NoError(t, err)
// t.Log(string(jsonResults))
assert.Equal(t, float64(10), max(getSampleValues(t, jsonResults, "vus_max", nil)))
assert.Equal(t, float64(10), max(getSampleValues(t, jsonResults, "vus", nil)))
assert.Equal(t, float64(10), maxFloat64(getSampleValues(t, jsonResults, "vus_max", nil)))
assert.Equal(t, float64(10), maxFloat64(getSampleValues(t, jsonResults, "vus", nil)))
assert.Equal(t, float64(0), sum(getSampleValues(t, jsonResults, "iterations", nil)))

logEntries := ts.LoggerHook.Drain()
Expand Down
Loading

0 comments on commit c258fb8

Please sign in to comment.