From 4839e8d33a997ac09a9d5b7abe8510b3eebec227 Mon Sep 17 00:00:00 2001 From: Mihail Stoykov Date: Wed, 24 Jan 2024 14:57:39 +0200 Subject: [PATCH] lib: lint fixes --- lib/archive.go | 25 ++++++++++-------- lib/consts/consts.go | 1 + lib/context.go | 5 ++-- lib/execution_segment.go | 4 +-- lib/execution_segment_test.go | 31 ++++++++++++----------- lib/executor/base_executor.go | 1 + lib/executor/common_test.go | 1 + lib/executor/constant_arrival_rate.go | 2 +- lib/executor/constant_vus.go | 8 +++--- lib/executor/constant_vus_test.go | 2 +- lib/executor/executors_test.go | 4 +-- lib/executor/externally_controlled.go | 12 ++++----- lib/executor/per_vu_iterations_test.go | 4 +-- lib/executor/ramping_arrival_rate.go | 2 +- lib/executor/ramping_arrival_rate_test.go | 3 +-- lib/executor/ramping_vus.go | 2 +- lib/executor/shared_iterations.go | 2 +- lib/executor/shared_iterations_test.go | 2 +- lib/executor/vu_handle_test.go | 2 +- lib/models.go | 27 +++++++++++--------- lib/netext/httpext/request.go | 2 +- lib/options.go | 30 ++++++++++++++-------- lib/options_test.go | 8 +++--- lib/types/hostnametrie.go | 2 +- lib/types/hosts.go | 2 +- lib/util.go | 6 +++-- 26 files changed, 106 insertions(+), 84 deletions(-) diff --git a/lib/archive.go b/lib/archive.go index 2de180d5f47..52fc5f27cf3 100644 --- a/lib/archive.go +++ b/lib/archive.go @@ -4,6 +4,7 @@ import ( "archive/tar" "bytes" "encoding/json" + "errors" "fmt" "io" "io/fs" @@ -20,18 +21,20 @@ import ( ) var ( - volumeRE = regexp.MustCompile(`^[/\\]?([a-zA-Z]):(.*)`) - sharedRE = regexp.MustCompile(`^\\\\([^\\]+)`) // matches a shared folder in Windows before backslack replacement. i.e \\VMBOXSVR\k6\script.js + volumeRE = regexp.MustCompile(`^[/\\]?([a-zA-Z]):(.*)`) + // matches a shared folder in Windows before backslack replacement. i.e \\VMBOXSVR\k6\script.js + sharedRE = regexp.MustCompile(`^\\\\([^\\]+)`) homeDirRE = regexp.MustCompile(`(?i)^(/[a-zA-Z])?/(Users|home|Documents and Settings)/(?:[^/]+)`) ) -// NormalizeAndAnonymizePath Normalizes (to use a / path separator) and anonymizes a file path, by scrubbing usernames from home directories. +// NormalizeAndAnonymizePath Normalizes (to use a / path separator) and anonymizes a file path, +// by scrubbing usernames from home directories. func NormalizeAndAnonymizePath(path string) string { path = filepath.Clean(path) p := volumeRE.ReplaceAllString(path, `/$1$2`) p = sharedRE.ReplaceAllString(p, `/nobody`) - p = strings.Replace(p, "\\", "/", -1) + p = strings.ReplaceAll(p, "\\", "/") return homeDirRE.ReplaceAllString(p, `$1/$2/nobody`) } @@ -106,6 +109,8 @@ func (arc *Archive) loadMetadataJSON(data []byte) (err error) { } // ReadArchive reads an archive created by Archive.Write from a reader. +// +//nolint:gocognit func ReadArchive(in io.Reader) (*Archive, error) { r := tar.NewReader(in) arc := &Archive{Filesystems: make(map[string]fsext.Fs, 2)} @@ -115,12 +120,12 @@ func ReadArchive(in io.Reader) (*Archive, error) { for { hdr, err := r.Next() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { break } return nil, err } - if hdr.Typeflag != tar.TypeReg && hdr.Typeflag != tar.TypeRegA { + if hdr.Typeflag != tar.TypeReg && hdr.Typeflag != tar.TypeRegA { //nolint:staticcheck continue } @@ -161,12 +166,10 @@ func ReadArchive(in io.Reader) (*Archive, error) { case "https", "file": fileSystem := arc.getFs(pfx) name = filepath.FromSlash(name) - err = fsext.WriteFile(fileSystem, name, data, fs.FileMode(hdr.Mode)) - if err != nil { + if err = fsext.WriteFile(fileSystem, name, data, fs.FileMode(hdr.Mode)); err != nil { return nil, err } - err = fileSystem.Chtimes(name, hdr.AccessTime, hdr.ModTime) - if err != nil { + if err = fileSystem.Chtimes(name, hdr.AccessTime, hdr.ModTime); err != nil { return nil, err } default: @@ -218,6 +221,8 @@ func getURLtoString(u *url.URL) string { // The format should be treated as opaque; currently it is simply a TAR rollup, but this may // change. If it does change, ReadArchive must be able to handle all previous formats as well as // the current one. +// +//nolint:funlen,gocognit func (arc *Archive) Write(out io.Writer) error { w := tar.NewWriter(out) diff --git a/lib/consts/consts.go b/lib/consts/consts.go index c11360de158..09229130312 100644 --- a/lib/consts/consts.go +++ b/lib/consts/consts.go @@ -1,3 +1,4 @@ +// Package consts houses some constants needed across k6 package consts import ( diff --git a/lib/context.go b/lib/context.go index 896547b2466..9bee954e445 100644 --- a/lib/context.go +++ b/lib/context.go @@ -22,7 +22,8 @@ func GetExecutionState(ctx context.Context) *ExecutionState { if v == nil { return nil } - return v.(*ExecutionState) + + return v.(*ExecutionState) //nolint:forcetypeassert } // WithScenarioState embeds a ScenarioState in ctx. @@ -36,5 +37,5 @@ func GetScenarioState(ctx context.Context) *ScenarioState { if v == nil { return nil } - return v.(*ScenarioState) + return v.(*ScenarioState) //nolint:forcetypeassert } diff --git a/lib/execution_segment.go b/lib/execution_segment.go index 012006a43e9..7c469c81a4a 100644 --- a/lib/execution_segment.go +++ b/lib/execution_segment.go @@ -78,7 +78,7 @@ func stringToRat(s string) (*big.Rat, error) { } return new(big.Rat).SetFrac(num, big.NewInt(100)), nil } - rat, ok := new(big.Rat).SetString(s) + rat, ok := new(big.Rat).SetString(s) //nolint:gosec // the vulnerability was patched in 1.16 if !ok { return nil, fmt.Errorf("'%s' is not a valid percentage, decimal, fraction or interval value", s) } @@ -417,7 +417,7 @@ func gcd(a, b int64) int64 { // IsFull returns whether the sequences is full, that is, whether it starts at 0 // and ends at 1. Use GetFilledExecutionSegmentSequence() to get a full sequence. func (ess ExecutionSegmentSequence) IsFull() bool { - return ess != nil && len(ess) != 0 && ess[0].from.Cmp(zeroRat) == 0 && ess[len(ess)-1].to.Cmp(oneRat) == 0 + return len(ess) != 0 && ess[0].from.Cmp(zeroRat) == 0 && ess[len(ess)-1].to.Cmp(oneRat) == 0 } // FindSegmentPosition returns the index of the supplied execution segment in diff --git a/lib/execution_segment_test.go b/lib/execution_segment_test.go index 5114b9efd9a..c8eaa65288b 100644 --- a/lib/execution_segment_test.go +++ b/lib/execution_segment_test.go @@ -31,7 +31,7 @@ func TestExecutionSegmentEquals(t *testing.T) { t.Run("To it's self", func(t *testing.T) { t.Parallel() es := stringToES(t, "1/2:2/3") - require.True(t, es.Equal(es)) + require.True(t, es.Equal(es)) //nolint:gocritic }) } @@ -422,6 +422,14 @@ func TestExecutionSegmentStringSequences(t *testing.T) { } } +func getTestRand(t testing.TB) *rand.Rand { + t.Helper() + seed := time.Now().UnixNano() + r := rand.New(rand.NewSource(seed)) //nolint:gosec + t.Logf("Random source seeded with %d\n", seed) + return r +} + // Return a randomly distributed sequence of n amount of // execution segments whose length totals 1. func generateRandomSequence(t testing.TB, n, m int64, r *rand.Rand) ExecutionSegmentSequence { @@ -449,13 +457,11 @@ func generateRandomSequence(t testing.TB, n, m int64, r *rand.Rand) ExecutionSeg func TestExecutionSegmentScaleConsistency(t *testing.T) { t.Parallel() - seed := time.Now().UnixNano() - r := rand.New(rand.NewSource(seed)) - t.Logf("Random source seeded with %d\n", seed) + r := getTestRand(t) const numTests = 10 for i := 0; i < numTests; i++ { - scale := rand.Int31n(99) + 2 + scale := r.Int31n(99) + 2 seq := generateRandomSequence(t, r.Int63n(9)+2, 100, r) t.Run(fmt.Sprintf("%d_%s", scale, seq), func(t *testing.T) { @@ -474,13 +480,10 @@ func TestExecutionSegmentScaleConsistency(t *testing.T) { func TestExecutionTupleScaleConsistency(t *testing.T) { t.Parallel() - seed := time.Now().UnixNano() - r := rand.New(rand.NewSource(seed)) - t.Logf("Random source seeded with %d\n", seed) - + r := getTestRand(t) const numTests = 10 for i := 0; i < numTests; i++ { - scale := rand.Int31n(99) + 2 + scale := r.Int31n(99) + 2 seq := generateRandomSequence(t, r.Int63n(9)+2, 200, r) et, err := NewExecutionTuple(seq[0], &seq) @@ -517,16 +520,14 @@ func TestExecutionSegmentScaleNoWobble(t *testing.T) { requireSegmentScaleGreater(t, et) }) - seed := time.Now().UnixNano() - r := rand.New(rand.NewSource(seed)) - t.Logf("Random source seeded with %d\n", seed) + r := getTestRand(t) // Random segments const numTests = 10 for i := 0; i < numTests; i++ { seq := generateRandomSequence(t, r.Int63n(9)+2, 100, r) - es := seq[rand.Intn(len(seq))] + es := seq[r.Intn(len(seq))] et, err := NewExecutionTuple(seq[0], &seq) require.NoError(t, err) @@ -623,7 +624,7 @@ func TestSequenceLCD(t *testing.T) { func BenchmarkGetStripedOffsets(b *testing.B) { lengths := [...]int64{10, 100} const seed = 777 - r := rand.New(rand.NewSource(seed)) + r := rand.New(rand.NewSource(seed)) //nolint:gosec for _, length := range lengths { length := length diff --git a/lib/executor/base_executor.go b/lib/executor/base_executor.go index a025082e8ec..ee5ed0c343a 100644 --- a/lib/executor/base_executor.go +++ b/lib/executor/base_executor.go @@ -1,3 +1,4 @@ +// Package executor defines the executors k6 can use. package executor import ( diff --git a/lib/executor/common_test.go b/lib/executor/common_test.go index 6d0a76ebf32..ed629d08cad 100644 --- a/lib/executor/common_test.go +++ b/lib/executor/common_test.go @@ -93,6 +93,7 @@ type executorTest struct { logHook *testutils.SimpleLogrusHook } +//nolint:unparam func setupExecutorTest( t testing.TB, segmentStr, sequenceStr string, extraOptions lib.Options, runner lib.Runner, config lib.ExecutorConfig, diff --git a/lib/executor/constant_arrival_rate.go b/lib/executor/constant_arrival_rate.go index 7b576e3a96f..c53339ab5bf 100644 --- a/lib/executor/constant_arrival_rate.go +++ b/lib/executor/constant_arrival_rate.go @@ -170,7 +170,7 @@ type ConstantArrivalRate struct { var _ lib.Executor = &ConstantArrivalRate{} // Init values needed for the execution -func (car *ConstantArrivalRate) Init(ctx context.Context) error { +func (car *ConstantArrivalRate) Init(_ context.Context) error { // err should always be nil, because Init() won't be called for executors // with no work, as determined by their config's HasWork() method. et, err := car.BaseExecutor.executionState.ExecutionTuple.GetNewExecutionTupleFromValue(car.config.MaxVUs.Int64) diff --git a/lib/executor/constant_vus.go b/lib/executor/constant_vus.go index 214cc7461f6..414ccfbdee5 100644 --- a/lib/executor/constant_vus.go +++ b/lib/executor/constant_vus.go @@ -122,7 +122,7 @@ var _ lib.Executor = &ConstantVUs{} // Run constantly loops through as many iterations as possible on a fixed number // of VUs for the specified duration. -func (clv ConstantVUs) Run(parentCtx context.Context, out chan<- metrics.SampleContainer) (err error) { +func (clv ConstantVUs) Run(parentCtx context.Context, _ chan<- metrics.SampleContainer) (err error) { numVUs := clv.config.GetVUs(clv.executionState.ExecutionTuple) duration := clv.config.Duration.TimeDuration() gracefulStop := clv.config.GetGracefulStop() @@ -180,15 +180,13 @@ func (clv ConstantVUs) Run(parentCtx context.Context, out chan<- metrics.SampleC defer cancel() activeVU := initVU.Activate( - getVUActivationParams(ctx, clv.config.BaseConfig, returnVU, - clv.nextIterationCounters)) + getVUActivationParams(ctx, clv.config.BaseConfig, returnVU, clv.nextIterationCounters)) for { select { case <-regDurationDone: return // don't make more iterations - default: - // continue looping + default: // continue looping } runIteration(maxDurationCtx, activeVU) } diff --git a/lib/executor/constant_vus_test.go b/lib/executor/constant_vus_test.go index 667573c1953..ec8757a2f8a 100644 --- a/lib/executor/constant_vus_test.go +++ b/lib/executor/constant_vus_test.go @@ -45,7 +45,7 @@ func TestConstantVUsRun(t *testing.T) { var totalIters uint64 result.Range(func(key, value interface{}) bool { - vuIters := value.(uint64) + vuIters := value.(uint64) //nolint:forcetypeassert assert.Equal(t, uint64(5), vuIters) totalIters += vuIters return true diff --git a/lib/executor/executors_test.go b/lib/executor/executors_test.go index f8e40a7fff9..60978d32482 100644 --- a/lib/executor/executors_test.go +++ b/lib/executor/executors_test.go @@ -344,7 +344,7 @@ var configMapTestCases = []configMapTestCase{ `{"carrival": {"executor": "constant-arrival-rate", "rate": 10, "duration": "10m", "preAllocatedVUs": 20}}`, exp{custom: func(t *testing.T, cm lib.ScenarioConfigs) { assert.Empty(t, cm["carrival"].Validate()) - require.EqualValues(t, 20, cm["carrival"].(*ConstantArrivalRateConfig).MaxVUs.Int64) + require.EqualValues(t, 20, cm["carrival"].(*ConstantArrivalRateConfig).MaxVUs.Int64) //nolint:forcetypeassert }}, }, {`{"carrival": {"executor": "constant-arrival-rate", "rate": 10, "duration": "10m", "maxVUs": 30}}`, exp{validationError: true}}, @@ -396,7 +396,7 @@ var configMapTestCases = []configMapTestCase{ `{"varrival": {"executor": "ramping-arrival-rate", "preAllocatedVUs": 20, "stages": [{"duration": "5m", "target": 10}]}}`, exp{custom: func(t *testing.T, cm lib.ScenarioConfigs) { assert.Empty(t, cm["varrival"].Validate()) - require.EqualValues(t, 20, cm["varrival"].(*RampingArrivalRateConfig).MaxVUs.Int64) + require.EqualValues(t, 20, cm["varrival"].(*RampingArrivalRateConfig).MaxVUs.Int64) //nolint:forcetypeassert }}, }, {`{"varrival": {"executor": "ramping-arrival-rate", "maxVUs": 50, "stages": [{"duration": "5m", "target": 10}]}}`, exp{validationError: true}}, diff --git a/lib/executor/externally_controlled.go b/lib/executor/externally_controlled.go index 031fbaa44c4..5be86f44db7 100644 --- a/lib/executor/externally_controlled.go +++ b/lib/executor/externally_controlled.go @@ -225,7 +225,7 @@ func (mex ExternallyControlled) GetLogger() *logrus.Entry { } // Init doesn't do anything... -func (mex ExternallyControlled) Init(ctx context.Context) error { +func (mex ExternallyControlled) Init(_ context.Context) error { return nil } @@ -480,7 +480,7 @@ func (rs *externallyControlledRunState) handleConfigChange(oldCfg, newCfg Extern // until the test is manually stopped. // //nolint:funlen,gocognit -func (mex *ExternallyControlled) Run(parentCtx context.Context, out chan<- metrics.SampleContainer) (err error) { +func (mex *ExternallyControlled) Run(parentCtx context.Context, _ chan<- metrics.SampleContainer) (err error) { mex.configLock.RLock() // Safely get the current config - it's important that the close of the // hasStarted channel is inside of the lock, so that there are no data races @@ -528,7 +528,7 @@ func (mex *ExternallyControlled) Run(parentCtx context.Context, out chan<- metri ss.ProgressFn = runState.progressFn *runState.maxVUs = startMaxVUs - if err = runState.retrieveStartMaxVUs(); err != nil { + if err = runState.retrieveStartMaxVUs(); err != nil { //nolint:contextcheck return err } @@ -537,7 +537,7 @@ func (mex *ExternallyControlled) Run(parentCtx context.Context, out chan<- metri trackProgress(parentCtx, ctx, ctx, mex, runState.progressFn) close(waitOnProgressChannel) }() - + //nolint:contextcheck err = runState.handleConfigChange( // Start by setting MaxVUs to the starting MaxVUs ExternallyControlledConfigParams{MaxVUs: mex.config.MaxVUs}, currentControlConfig, ) @@ -553,10 +553,10 @@ func (mex *ExternallyControlled) Run(parentCtx context.Context, out chan<- metri case <-ctx.Done(): return nil case updateConfigEvent := <-mex.newControlConfigs: - err := runState.handleConfigChange(currentControlConfig, updateConfigEvent.newConfig) + err := runState.handleConfigChange(currentControlConfig, updateConfigEvent.newConfig) //nolint:contextcheck if err != nil { updateConfigEvent.err <- err - if ctx.Err() == err { + if errors.Is(ctx.Err(), err) { return nil // we've already returned an error to the API client, but k6 should stop normally } return err diff --git a/lib/executor/per_vu_iterations_test.go b/lib/executor/per_vu_iterations_test.go index 0e09671787d..3d4780a6a4f 100644 --- a/lib/executor/per_vu_iterations_test.go +++ b/lib/executor/per_vu_iterations_test.go @@ -44,7 +44,7 @@ func TestPerVUIterationsRun(t *testing.T) { var totalIters uint64 result.Range(func(key, value interface{}) bool { - vuIters := value.(uint64) + vuIters := value.(uint64) //nolint:forcetypeassert assert.Equal(t, uint64(100), vuIters) totalIters += vuIters return true @@ -81,7 +81,7 @@ func TestPerVUIterationsRunVariableVU(t *testing.T) { var totalIters uint64 result.Range(func(key, value interface{}) bool { - vuIters := value.(uint64) + vuIters := value.(uint64) //nolint:forcetypeassert if key != slowVUID { assert.Equal(t, uint64(100), vuIters) } diff --git a/lib/executor/ramping_arrival_rate.go b/lib/executor/ramping_arrival_rate.go index 2846517e69d..dc490b358f6 100644 --- a/lib/executor/ramping_arrival_rate.go +++ b/lib/executor/ramping_arrival_rate.go @@ -161,7 +161,7 @@ type RampingArrivalRate struct { var _ lib.Executor = &RampingArrivalRate{} // Init values needed for the execution -func (varr *RampingArrivalRate) Init(ctx context.Context) error { +func (varr *RampingArrivalRate) Init(_ context.Context) error { // err should always be nil, because Init() won't be called for executors // with no work, as determined by their config's HasWork() method. et, err := varr.BaseExecutor.executionState.ExecutionTuple.GetNewExecutionTupleFromValue(varr.config.MaxVUs.Int64) diff --git a/lib/executor/ramping_arrival_rate_test.go b/lib/executor/ramping_arrival_rate_test.go index 7ff7386eb81..2e3f43f6a64 100644 --- a/lib/executor/ramping_arrival_rate_test.go +++ b/lib/executor/ramping_arrival_rate_test.go @@ -268,8 +268,7 @@ func BenchmarkRampingArrivalRateRun(b *testing.B) { engineOut := make(chan metrics.SampleContainer, 1000) defer close(engineOut) go func() { - for range engineOut { - // discard + for range engineOut { //nolint:revive // we want to discard samples } }() diff --git a/lib/executor/ramping_vus.go b/lib/executor/ramping_vus.go index 2b12bc63c86..58afcfe8c64 100644 --- a/lib/executor/ramping_vus.go +++ b/lib/executor/ramping_vus.go @@ -609,7 +609,7 @@ func (rs *rampingVUsRunState) runLoopsIfPossible(ctx context.Context, cancel fun rs.vuHandles[i] = newStoppedVUHandle( ctx, getVU, returnVU, rs.executor.nextIterationCounters, &rs.executor.config.BaseConfig, rs.executor.logger.WithField("vuNum", i)) - go rs.vuHandles[i].runLoopsIfPossible(rs.runIteration) + go rs.vuHandles[i].runLoopsIfPossible(rs.runIteration) //nolint:contextcheck } } diff --git a/lib/executor/shared_iterations.go b/lib/executor/shared_iterations.go index e37f9416d24..b58a4442030 100644 --- a/lib/executor/shared_iterations.go +++ b/lib/executor/shared_iterations.go @@ -150,7 +150,7 @@ func (sic SharedIterationsConfig) HasWork(et *lib.ExecutionTuple) bool { } // Init values needed for the execution -func (si *SharedIterations) Init(ctx context.Context) error { +func (si *SharedIterations) Init(_ context.Context) error { // err should always be nil, because Init() won't be called for executors // with no work, as determined by their config's HasWork() method. et, err := si.BaseExecutor.executionState.ExecutionTuple.GetNewExecutionTupleFromValue(si.config.VUs.Int64) diff --git a/lib/executor/shared_iterations_test.go b/lib/executor/shared_iterations_test.go index 46353174adb..2bd032901af 100644 --- a/lib/executor/shared_iterations_test.go +++ b/lib/executor/shared_iterations_test.go @@ -74,7 +74,7 @@ func TestSharedIterationsRunVariableVU(t *testing.T) { var totalIters uint64 result.Range(func(key, value interface{}) bool { - totalIters += value.(uint64) + totalIters += value.(uint64) //nolint:forcetypeassert return true }) diff --git a/lib/executor/vu_handle_test.go b/lib/executor/vu_handle_test.go index 0d024eebd81..5ca41154fa7 100644 --- a/lib/executor/vu_handle_test.go +++ b/lib/executor/vu_handle_test.go @@ -138,7 +138,7 @@ func TestVUHandleStartStopRace(t *testing.T) { } returnVU := func(v lib.InitializedVU) { - require.Equal(t, atomic.LoadUint64(&vuID), v.(*minirunner.VU).ID) + require.Equal(t, atomic.LoadUint64(&vuID), v.(*minirunner.VU).ID) //nolint:forcetypeassert close(returned) } var interruptedIter int64 diff --git a/lib/models.go b/lib/models.go index c6843d6e257..aff29a70c43 100644 --- a/lib/models.go +++ b/lib/models.go @@ -1,7 +1,7 @@ package lib import ( - "crypto/md5" + "crypto/md5" //nolint:gosec "encoding/hex" "encoding/json" "errors" @@ -15,10 +15,10 @@ import ( "go.k6.io/k6/lib/types" ) -// Separator for group IDs. +// GroupSeparator for group IDs. const GroupSeparator = "::" -// Error emitted if you attempt to instantiate a Group or Check that contains the separator. +// ErrNameContainsGroupSeparator is emitted if you attempt to instantiate a Group or Check that contains the separator. var ErrNameContainsGroupSeparator = errors.New("group and check names may not contain '::'") // StageFields defines the fields used for a Stage; this is a dumb hack to make the JSON code @@ -34,7 +34,8 @@ type StageFields struct { // A Stage defines a step in a test's timeline. type Stage StageFields -// For some reason, implementing UnmarshalText makes encoding/json treat the type as a string. +// UnmarshalJSON implements the json.Unmarshaler interface +// for some reason, implementing UnmarshalText makes encoding/json treat the type as a string. func (s *Stage) UnmarshalJSON(b []byte) error { var fields StageFields if err := json.Unmarshal(b, &fields); err != nil { @@ -44,10 +45,12 @@ func (s *Stage) UnmarshalJSON(b []byte) error { return nil } +// MarshalJSON implements the json.Marshaler interface func (s Stage) MarshalJSON() ([]byte, error) { return json.Marshal(StageFields(s)) } +// UnmarshalText implements the encoding.TextUnmarshaler interface func (s *Stage) UnmarshalText(b []byte) error { var stage Stage parts := strings.SplitN(string(b), ":", 2) @@ -99,7 +102,7 @@ type Group struct { checkMutex sync.Mutex } -// Creates a new group with the given name and parent group. +// NewGroup creates a new group with the given name and parent group. // // The root group must be created with the name "" and parent set to nil; this is the only case // where a nil parent or empty name is allowed. @@ -113,7 +116,7 @@ func NewGroup(name string, parent *Group) (*Group, error) { path = parent.Path + GroupSeparator + path } - hash := md5.Sum([]byte(path)) + hash := md5.Sum([]byte(path)) //nolint:gosec id := hex.EncodeToString(hash[:]) return &Group{ @@ -133,13 +136,13 @@ func (g *Group) Group(name string) (*Group, error) { defer g.groupMutex.Unlock() group, ok := g.Groups[name] if !ok { - group, err := NewGroup(name, g) + var err error + group, err = NewGroup(name, g) if err != nil { return nil, err } g.Groups[name] = group g.OrderedGroups = append(g.OrderedGroups, group) - return group, nil } return group, nil } @@ -151,13 +154,13 @@ func (g *Group) Check(name string) (*Check, error) { defer g.checkMutex.Unlock() check, ok := g.Checks[name] if !ok { - check, err := NewCheck(name, g) + var err error + check, err = NewCheck(name, g) if err != nil { return nil, err } g.Checks[name] = check g.OrderedChecks = append(g.OrderedChecks, check) - return check, nil } return check, nil } @@ -187,14 +190,14 @@ type Check struct { Fails int64 `json:"fails"` } -// Creates a new check with the given name and parent group. The group may not be nil. +// NewCheck creates a new check with the given name and parent group. The group may not be nil. func NewCheck(name string, group *Group) (*Check, error) { if strings.Contains(name, GroupSeparator) { return nil, ErrNameContainsGroupSeparator } path := group.Path + GroupSeparator + name - hash := md5.Sum([]byte(path)) + hash := md5.Sum([]byte(path)) //nolint:gosec id := hex.EncodeToString(hash[:]) return &Check{ diff --git a/lib/netext/httpext/request.go b/lib/netext/httpext/request.go index cfa5b2ba46b..4117752f516 100644 --- a/lib/netext/httpext/request.go +++ b/lib/netext/httpext/request.go @@ -110,7 +110,7 @@ func updateK6Response(k6Response *Response, finishedReq *finishedRequest) { // // TODO: split apart... // -//nolint:cyclop, gocyclo, funlen, gocognit +//nolint:cyclop, gocyclo, funlen, gocognit, nestif func MakeRequest(ctx context.Context, state *lib.State, preq *ParsedHTTPRequest) (*Response, error) { respReq := &Request{ Method: preq.Req.Method, diff --git a/lib/options.go b/lib/options.go index 5baad062b8f..fafdcc4fee5 100644 --- a/lib/options.go +++ b/lib/options.go @@ -24,13 +24,15 @@ const DefaultScenarioName = "default" //nolint:gochecknoglobals var DefaultSummaryTrendStats = []string{"avg", "min", "med", "max", "p(90)", "p(95)"} -// Describes a TLS version. Serialised to/from JSON as a string, eg. "tls1.2". +// TLSVersion describes a TLS version. Serialised to/from JSON as a string, eg. "tls1.2". type TLSVersion int +// MarshalJSON implements the json.Marshaler interface func (v TLSVersion) MarshalJSON() ([]byte, error) { return []byte(`"` + SupportedTLSVersionsToString[v] + `"`), nil } +// UnmarshalJSON implements the json.Unmarshaler interface func (v *TLSVersion) UnmarshalJSON(data []byte) error { var str string if err := StrictJSONUnmarshal(data, &str); err != nil { @@ -49,16 +51,17 @@ func (v *TLSVersion) UnmarshalJSON(data []byte) error { } // Fields for TLSVersions. Unmarshalling hack. -type TLSVersionsFields struct { +type tlsVersionsFields struct { Min TLSVersion `json:"min" ignored:"true"` // Minimum allowed version, 0 = any. Max TLSVersion `json:"max" ignored:"true"` // Maximum allowed version, 0 = any. } -// Describes a set (min/max) of TLS versions. -type TLSVersions TLSVersionsFields +// TLSVersions describes a set (min/max) of TLS versions. +type TLSVersions tlsVersionsFields +// UnmarshalJSON implements the json.Unmarshaler interface func (v *TLSVersions) UnmarshalJSON(data []byte) error { - var fields TLSVersionsFields + var fields tlsVersionsFields if err := StrictJSONUnmarshal(data, &fields); err != nil { var ver TLSVersion if err2 := StrictJSONUnmarshal(data, &ver); err2 != nil { @@ -71,7 +74,7 @@ func (v *TLSVersions) UnmarshalJSON(data []byte) error { return nil } -// A list of TLS cipher suites. +// TLSCipherSuites represents a list of TLS cipher suites. // Marshals and unmarshals from a list of names, eg. "TLS_ECDHE_RSA_WITH_RC4_128_SHA". type TLSCipherSuites []uint16 @@ -89,6 +92,7 @@ func (s *TLSCipherSuites) MarshalJSON() ([]byte, error) { return json.Marshal(suiteNames) } +// UnmarshalJSON implements the json.Unmarshaler interface func (s *TLSCipherSuites) UnmarshalJSON(data []byte) error { var suiteNames []string if err := StrictJSONUnmarshal(data, &suiteNames); err != nil { @@ -109,7 +113,7 @@ func (s *TLSCipherSuites) UnmarshalJSON(data []byte) error { return nil } -// Fields for TLSAuth. Unmarshalling hack. +// TLSAuthFields for TLSAuth. Unmarshalling hack. type TLSAuthFields struct { // Certificate and key as a PEM-encoded string, including "-----BEGIN CERTIFICATE-----". Cert string `json:"cert"` @@ -120,12 +124,13 @@ type TLSAuthFields struct { Domains []string `json:"domains"` } -// Defines a TLS client certificate to present to certain hosts. +// TLSAuth defines a TLS client certificate to present to certain hosts. type TLSAuth struct { TLSAuthFields certificate *tls.Certificate } +// UnmarshalJSON implements the json.Unmarshaler interface func (c *TLSAuth) UnmarshalJSON(data []byte) error { if err := StrictJSONUnmarshal(data, &c.TLSAuthFields); err != nil { return err @@ -136,6 +141,8 @@ func (c *TLSAuth) UnmarshalJSON(data []byte) error { return nil } +// Certificate returns a certificate based on the TLSAuth +// not thread safe func (c *TLSAuth) Certificate() (*tls.Certificate, error) { key := []byte(c.Key) var err error @@ -216,6 +223,7 @@ func ParseCIDR(s string) (*IPNet, error) { return &parsedIPNet, nil } +// Options represent configure options for k6. type Options struct { // Should the test start in a paused state? Paused null.Bool `json:"paused" envconfig:"K6_PAUSED"` @@ -332,13 +340,15 @@ type Options struct { LocalIPs types.NullIPPool `json:"-" envconfig:"K6_LOCAL_IPS"` } -// Returns the result of overwriting any fields with any that are set on the argument. +// Apply returns the result of overwriting any fields with any that are set on the argument. // // Example: // // a := Options{VUs: null.IntFrom(10)} // b := Options{VUs: null.IntFrom(5)} // a.Apply(b) // Options{VUs: null.IntFrom(5)} +// +//nolint:funlen,gocognit,cyclop func (o Options) Apply(opts Options) Options { if opts.Paused.Valid { o.Paused = opts.Paused @@ -531,7 +541,7 @@ func (o Options) ForEachSpecified(structTag string, callback func(key string, va fieldVal := structVal.Field(i) value := fieldVal.Interface() - shouldCall := false + var shouldCall bool switch fieldType.Type.Kind() { case reflect.Struct: // Unpack any guregu/null values diff --git a/lib/options_test.go b/lib/options_test.go index 586cfc52324..351cf0a7e55 100644 --- a/lib/options_test.go +++ b/lib/options_test.go @@ -160,11 +160,11 @@ func TestOptions(t *testing.T) { }) t.Run("TLSVersion", func(t *testing.T) { t.Parallel() - versions := TLSVersions{Min: tls.VersionSSL30, Max: tls.VersionTLS12} + versions := TLSVersions{Min: tls.VersionSSL30, Max: tls.VersionTLS12} //nolint:staticcheck opts := Options{}.Apply(Options{TLSVersion: &versions}) assert.NotNil(t, opts.TLSVersion) - assert.Equal(t, opts.TLSVersion.Min, TLSVersion(tls.VersionSSL30)) + assert.Equal(t, opts.TLSVersion.Min, TLSVersion(tls.VersionSSL30)) //nolint:staticcheck assert.Equal(t, opts.TLSVersion.Max, TLSVersion(tls.VersionTLS12)) t.Run("JSON", func(t *testing.T) { @@ -239,11 +239,11 @@ func TestOptions(t *testing.T) { "CgYIKoZIzj0EAwIDSAAwRQIgSGxnJ+/cLUNTzt7fhr/mjJn7ShsTW33dAdfLM7H2\n" + "z/gCIQDyVf8DePtxlkMBScTxZmIlMQdNc6+6VGZQ4QscruVLmg==\n" + "-----END CERTIFICATE-----", - Key: "-----BEGIN EC PRIVATE KEY-----\n" + + Key: "-----BEGIN EC PRIVATE KEY-----\n" + //nolint:goconst "MHcCAQEEIAfJeoc+XgcqmYV0b4owmofx0LXwPRqOPXMO+PUKxZSgoAoGCCqGSM49\n" + "AwEHoUQDQgAEtp/EQ6YEeTNup33/RVlf/f2o7bJCrYbPl9pF2/LfyS4swJX70dit\n" + "8zHoZgJnNNQirqHxBc6uWBhOLG5RV+Ek1Q==\n" + - "-----END EC PRIVATE KEY-----", + "-----END EC PRIVATE KEY-----", //nolint:goconst }, nil}, {TLSAuthFields{ Domains: []string{"sub.example.com"}, diff --git a/lib/types/hostnametrie.go b/lib/types/hostnametrie.go index 1004f02cb78..c1cb5f68c32 100644 --- a/lib/types/hostnametrie.go +++ b/lib/types/hostnametrie.go @@ -110,7 +110,7 @@ func NewHostnameTrie(source []string) (*HostnameTrie, error) { // Based on regex from https://stackoverflow.com/a/106223/5427244 // //nolint:lll -var validHostnamePattern *regexp.Regexp = regexp.MustCompile(`^(\*\.?)?((([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9]))?$`) +var validHostnamePattern = regexp.MustCompile(`^(\*\.?)?((([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9]))?$`) func isValidHostnamePattern(s string) error { if len(validHostnamePattern.FindString(s)) != len(s) { diff --git a/lib/types/hosts.go b/lib/types/hosts.go index a7de0ca35af..ddd084704f1 100644 --- a/lib/types/hosts.go +++ b/lib/types/hosts.go @@ -118,7 +118,7 @@ func NewHosts(source map[string]Host) (*Hosts, error) { // Based on regex from https://stackoverflow.com/a/106223/5427244 // //nolint:lll -var validHostPattern *regexp.Regexp = regexp.MustCompile(`^(\*\.?)?((([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9]))?(:[0-9]{1,5})?$`) +var validHostPattern = regexp.MustCompile(`^(\*\.?)?((([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9]))?(:[0-9]{1,5})?$`) func isValidHostPattern(s string) error { if len(validHostPattern.FindString(s)) != len(s) { diff --git a/lib/util.go b/lib/util.go index f4f7f70ad84..0c4f2aef553 100644 --- a/lib/util.go +++ b/lib/util.go @@ -1,6 +1,7 @@ package lib -// Returns the maximum value of a and b. +// Max returns the maximum value of a and b. +// TODO: replace after 1.21 is the minimal supported version. func Max(a, b int64) int64 { if a > b { return a @@ -8,7 +9,8 @@ func Max(a, b int64) int64 { return b } -// Returns the minimum value of a and b. +// Min returns the minimum value of a and b. +// TODO: replace after 1.21 is the minimal supported version. func Min(a, b int64) int64 { if a < b { return a