Skip to content

Commit

Permalink
chore: update linter and address its issues
Browse files Browse the repository at this point in the history
  • Loading branch information
areknoster committed Oct 11, 2024
1 parent 64d8762 commit 7312f75
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 47 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.57
version: v1.60

test:
env:
Expand Down
21 changes: 0 additions & 21 deletions golangci.yml → .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,16 @@ run:

linters:
enable:
- deadcode # : Finds unused code [fast: false, auto-fix: false]
- errcheck # : Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases [fast: false, auto-fix: false]
- gosimple # (megacheck): Linter for Go source code that specializes in simplifying a code [fast: false, auto-fix: false]
- govet # (vet, vetshadow): Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string [fast: false, auto-fix: false]
- ineffassign # : Detects when assignments to existing variables are not used [fast: true, auto-fix: false]
- staticcheck # (megacheck): Staticcheck is a go vet on steroids, applying a ton of static analysis checks [fast: false, auto-fix: false]
- structcheck # : Finds unused struct fields [fast: false, auto-fix: false]
- typecheck # : Like the front-end of a Go compiler, parses and type-checks Go code [fast: false, auto-fix: false]
- unused # (megacheck): Checks Go code for unused constants, variables, functions and types [fast: false, auto-fix: false]
- varcheck # : Finds unused global variables and constants [fast: false, auto-fix: false]
- asciicheck # : Simple linter to check that your code does not contain non-ASCII identifiers [fast: true, auto-fix: false]
- bodyclose # : checks whether HTTP response body is closed successfully [fast: false, auto-fix: false]
- durationcheck # : check for two durations multiplied together [fast: false, auto-fix: false]
- exportloopref # : checks for pointers to enclosing loop variables [fast: false, auto-fix: false]
- gocritic # : Provides many diagnostics that check for bugs, performance and style issues. [fast: false, auto-fix: false]
- importas # : Enforces consistent import aliases [fast: false, auto-fix: false]
- misspell # : Finds commonly misspelled English words in comments [fast: true, auto-fix: true]
Expand All @@ -79,13 +75,7 @@ linters:
- unconvert # : Remove unnecessary type conversions [fast: false, auto-fix: false]
- unparam # : Reports unused function parameters [fast: false, auto-fix: false]
- wastedassign # : wastedassign finds wasted assignment statements. [fast: false, auto-fix: false]
- nilerr
- dogsled
- wrapcheck
- golint
- goconst
- gomnd
- nilerr
disable:
- forcetypeassert # : finds forced type assertions [fast: true, auto-fix: false]
- goimports # : In addition to fixing imports, goimports also formats your code in the same style as gofmt. [fast: true, auto-fix: true]
Expand All @@ -97,7 +87,6 @@ linters:
- gofmt # : Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification [fast: true, auto-fix: true]
- gomnd # : An analyzer to detect magic numbers. [fast: true, auto-fix: false]
- gosec # (gas): Inspects source code for security problems [fast: false, auto-fix: false]
- interfacer # : Linter that suggests narrower interface types [fast: false, auto-fix: false]
- makezero # : Finds slice declarations with non-zero initial length [fast: false, auto-fix: false]
- nestif # : Reports deeply nested if statements [fast: true, auto-fix: false]
- nilerr # : Finds the code that returns nil even if it checks that the error is not nil. [fast: false, auto-fix: false]
Expand All @@ -109,11 +98,9 @@ linters:
- sqlclosecheck # : Checks that sql.Rows and sql.Stmt are closed. [fast: false, auto-fix: false]
- cyclop # : checks function and package cyclomatic complexity [fast: false, auto-fix: false]
- depguard # : Go linter that checks if package imports are in a list of acceptable packages [fast: false, auto-fix: false]
- # : Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false]
- dupl # : Tool for code clone detection [fast: true, auto-fix: false]
- errname # : Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. [fast: false, auto-fix: false]
- errorlint # : errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. [fast: false, auto-fix: false]
- exhaustivestruct # : Checks if all struct's fields are initialized [fast: false, auto-fix: false]
- forbidigo # : Forbids identifiers [fast: true, auto-fix: false]
- funlen # : Tool for detection of long functions [fast: true, auto-fix: false]
- gci # : Gci control golang package import order and make it always deterministic. [fast: true, auto-fix: true]
Expand All @@ -122,16 +109,12 @@ linters:
- gocognit # : Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false]
- gocyclo # : Computes and checks the cyclomatic complexity of functions [fast: true, auto-fix: false]
- godox # : Tool for detection of FIXME, TODO and other comment keywords [fast: true, auto-fix: false]
- goerr113 # : Golang linter to check the errors handling expressions [fast: false, auto-fix: false]
- goheader # : Checks is file header matches to pattern [fast: true, auto-fix: false]
- gomoddirectives # : Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. [fast: true, auto-fix: false]
- gomodguard # : Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. [fast: true, auto-fix: false]
- goprintffuncname # : Checks that printf-like functions are named with `f` at the end [fast: true, auto-fix: false]
- ifshort # : Checks that your code uses short syntax for if-statements whenever possible [fast: true, auto-fix: false]
- maligned # : Tool to detect Go structs that would take less memory if their fields were sorted [fast: false, auto-fix: false]
- nlreturn # : nlreturn checks for a new line before return and branch statements to increase code clarity [fast: true, auto-fix: false]
- paralleltest # : paralleltest detects missing usage of t.Parallel() method in your Go test [fast: true, auto-fix: false]
- scopelint # : Scopelint checks for unpinned variables in go programs [fast: true, auto-fix: false]
- tagliatelle # : Checks the struct tags. [fast: true, auto-fix: false]
- tenv #: tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 [fast: false, auto-fix: false]
- testpackage # : linter that makes you use a separate _test package [fast: true, auto-fix: false]
Expand All @@ -146,10 +129,6 @@ linters:

# output configuration options
output:
# colored-line-number|line-number|json|tab|checkstyle|code-climate|junit-xml|github-actions
# default is "colored-line-number"
format: line-number

# print lines of code with issue, default is true
print-issued-lines: false

Expand Down
6 changes: 4 additions & 2 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ func (n noopRequestSanitizer) SanitizeRequest(req *http.Request) *http.Request {

type noopRequestValidator struct{}

func (n noopRequestValidator) Validate(_ T, recorded RequestData, got RequestData) {}
func (n noopRequestValidator) Validate(_ T, _ RequestData, _ RequestData) error {

Check failure on line 16 in client_test.go

View workflow job for this annotation

GitHub Actions / lint

paramTypeCombine: func(_ T, _ RequestData, _ RequestData) error could be replaced with func(_ T, _, _ RequestData) error (gocritic)

Check failure on line 16 in client_test.go

View workflow job for this annotation

GitHub Actions / lint

paramTypeCombine: func(_ T, _ RequestData, _ RequestData) error could be replaced with func(_ T, _, _ RequestData) error (gocritic)
return nil
}

func Test_configWithDefaults(t *testing.T) {
t.Run("should return default config", func(t *testing.T) {
Expand Down Expand Up @@ -58,7 +60,7 @@ func Test_configWithDefaults(t *testing.T) {
if cfg.parentHTTPClient != parentHTTPClient {
t.Error("expected parentHTTPClient to be set")
}
if cfg.requestValidator != validator {
if cfg.requestValidator == nil || cfg.requestValidator != validator {
t.Error("expected requestValidator to be set")
}
})
Expand Down
2 changes: 1 addition & 1 deletion naming_scheme.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type SequentialNamingScheme struct {
// The directory is created with 0760 permissions if doesn't exists.
// You can use DefaultTestdataDir function for a sane default directory name.
func NewSequentialNamingScheme(dir string) (*SequentialNamingScheme, error) {
err := os.MkdirAll(dir, 0760)
err := os.MkdirAll(dir, 0o760)
if err != nil {
return nil, fmt.Errorf("error creating directory: %w", err)
}
Expand Down
9 changes: 6 additions & 3 deletions record_transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func TestRecordTransport_RoundTrip(t *testing.T) {
})

mockRT := &mockRoundTripper{
resp: sampleResp(),
resp: sampleResp(), //nolint:bodyclose

Check failure on line 102 in record_transport_test.go

View workflow job for this annotation

GitHub Actions / lint

whyNoLint: include an explanation for nolint directive (gocritic)

Check failure on line 102 in record_transport_test.go

View workflow job for this annotation

GitHub Actions / lint

whyNoLint: include an explanation for nolint directive (gocritic)
}

rt := recordTransport{
Expand All @@ -117,6 +117,7 @@ func TestRecordTransport_RoundTrip(t *testing.T) {
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
defer gotResp.Body.Close()

if gotResp.StatusCode != http.StatusOK {
t.Errorf("expected status code %d, got %d", http.StatusOK, gotResp.StatusCode)
Expand Down Expand Up @@ -157,6 +158,7 @@ func TestRecordTransport_RoundTrip(t *testing.T) {
if err != nil {
t.Fatalf("error when reading response from file: %v", err)
}
defer storedResp.Body.Close()
if storedResp.StatusCode != http.StatusOK {
t.Errorf("expected status code %d, got %d", http.StatusOK, storedResp.StatusCode)
}
Expand Down Expand Up @@ -202,7 +204,7 @@ func TestRecordTransport_NilBody(t *testing.T) {
}

mockRT := &mockRoundTripper{
resp: sampleResp(),
resp: sampleResp(), //nolint:bodyclose

Check failure on line 207 in record_transport_test.go

View workflow job for this annotation

GitHub Actions / lint

whyNoLint: include an explanation for nolint directive (gocritic)

Check failure on line 207 in record_transport_test.go

View workflow job for this annotation

GitHub Actions / lint

whyNoLint: include an explanation for nolint directive (gocritic)
}

rt := recordTransport{
Expand All @@ -211,10 +213,11 @@ func TestRecordTransport_NilBody(t *testing.T) {
sanitizer: NoOpRequestSanitizer{},
}

_, err := rt.RoundTrip(sampleReq())
resp, err := rt.RoundTrip(sampleReq())
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
defer resp.Body.Close()

// Check if the response file was created and contains the expected body
respContent, err := os.ReadFile(staticNS.respFile)
Expand Down
13 changes: 10 additions & 3 deletions replay_transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestReplayTransport_HappyPath(t *testing.T) {
return req
})
mockedT := &mockT{}
validator := RequestValidatorFunc(func(sanitizerT T, recorded RequestData, got RequestData) {
validator := RequestValidatorFunc(func(sanitizerT T, recorded RequestData, got RequestData) error {
if recorded.Method != "GET" {
t.Errorf("expected read from file method to be GET, got %s", recorded.Method)
}
Expand All @@ -58,6 +58,7 @@ func TestReplayTransport_HappyPath(t *testing.T) {
}

sanitizerT.Errorf("this should fail the mocked T")
return nil
})

transport := replayTransport{
Expand All @@ -74,6 +75,7 @@ func TestReplayTransport_HappyPath(t *testing.T) {
if err != nil {
t.Fatalf("failed to round trip: %v", err)
}
defer resp.Body.Close()
if resp.Header.Get("SampleRespHeader") != "SampleRespHeaderValue" {
t.Fatalf("expected SampleRespHeader to be set")
}
Expand All @@ -99,7 +101,9 @@ func TestReplayTransport_FilesDontExist(t *testing.T) {
respFile: "testdata/doesnt_exist.resp.http",
}
sanitizer := noopRequestSanitizer{}
validator := noopRequestValidator{}
validator := RequestValidatorFunc(func(_ T, _ RequestData, _ RequestData) error {
return nil
})
sampleReq := func(t *testing.T) *http.Request {
req, err := http.NewRequest("PUT", "https://example.com", nil)
if err != nil {
Expand Down Expand Up @@ -141,6 +145,7 @@ func TestReplayTransport_FilesDontExist(t *testing.T) {
if err == nil {
t.Fatalf("expected error, got nil")
}
// Remove the defer resp.Body.Close() line, as resp might be nil
if !mockedT.failed || !mockedT.fatal {
t.Errorf("expected mocked T to fail fatally ")
}
Expand All @@ -157,7 +162,9 @@ func TestReplayTransport_TransformModes(t *testing.T) {
}

sanitizer := NoOpRequestSanitizer{}
validator := noopRequestValidator{}
validator := RequestValidatorFunc(func(_ T, _ RequestData, _ RequestData) error {
return nil
})

transform := ResponseTransformFunc(func(r *http.Response) *http.Response {
r.Body = io.NopCloser(bytes.NewBufferString("transformed response body"))
Expand Down
28 changes: 17 additions & 11 deletions request_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@ package hypert

// RequestValidator does assertions, that allows to make assertions on request that was caught by TestClient in the replay mode.
type RequestValidator interface {
Validate(t T, recorded RequestData, got RequestData)
Validate(t T, recorded RequestData, got RequestData) error
}

type RequestValidatorFunc func(t T, recorded RequestData, got RequestData)
type RequestValidatorFunc func(t T, recorded RequestData, got RequestData) error

func (f RequestValidatorFunc) Validate(t T, recorded RequestData, got RequestData) {
f(t, recorded, got)
func (f RequestValidatorFunc) Validate(t T, recorded RequestData, got RequestData) error {
return f(t, recorded, got)
}

func ComposedRequestValidator(validators ...RequestValidator) RequestValidator {
return RequestValidatorFunc(func(t T, recorded RequestData, got RequestData) {
return RequestValidatorFunc(func(t T, recorded RequestData, got RequestData) error {
for _, validator := range validators {
validator.Validate(t, recorded, got)
}
return nil

Check warning on line 19 in request_validator.go

View check run for this annotation

Codecov / codecov/patch

request_validator.go#L19

Added line #L19 was not covered by tests
})
}

Expand All @@ -30,17 +31,18 @@ func DefaultRequestValidator() RequestValidator {
}

func PathValidator() RequestValidator {
return RequestValidatorFunc(func(t T, recorded RequestData, got RequestData) {
return RequestValidatorFunc(func(t T, recorded RequestData, got RequestData) error {
if recorded.URL.Path != got.URL.Path {
t.Errorf("expected path '%s', got '%s'", recorded.URL.Path, got.URL.Path)
}
return nil
})
}

// QueryParamsValidator validates query parameters of the request.
// It is not sensitive to the order of query parameters.
func QueryParamsValidator() RequestValidator {
return RequestValidatorFunc(func(t T, recorded RequestData, got RequestData) {
return RequestValidatorFunc(func(t T, recorded RequestData, got RequestData) error {
recordedQ, gotQ := recorded.URL.Query(), got.URL.Query()

for key := range recordedQ {
Expand All @@ -53,32 +55,36 @@ func QueryParamsValidator() RequestValidator {
for key := range gotQ {
t.Errorf("unexpected query parameter '%s' with value '%s'", key, gotQ.Get(key))
}
return nil
})
}

// MethodValidator validates the method of the request.
func MethodValidator() RequestValidator {
return RequestValidatorFunc(func(t T, recorded RequestData, got RequestData) {
return RequestValidatorFunc(func(t T, recorded RequestData, got RequestData) error {
if recorded.Method != got.Method {
t.Errorf("expected method '%s', got '%s'", recorded.Method, got.Method)
return nil
}
return nil
})
}

// SchemeValidator validates the scheme of the request.
func SchemeValidator() RequestValidator {
return RequestValidatorFunc(func(t T, recorded RequestData, got RequestData) {
return RequestValidatorFunc(func(t T, recorded RequestData, got RequestData) error {
if recorded.URL.Scheme != got.URL.Scheme {
t.Errorf("expected scheme '%s', got '%s'", recorded.URL.Scheme, got.URL.Scheme)
}
return nil
})
}

// HeadersValidator validates headers of the request.
// It is not sensitive to the order of headers.
// User-Agent and Content-Length are removed from the comparison, because it is added deeper in the http client call.
func HeadersValidator() RequestValidator {
return RequestValidatorFunc(func(t T, recorded RequestData, got RequestData) {
return RequestValidatorFunc(func(t T, recorded RequestData, got RequestData) error {
recordedHeaders := recorded.Headers.Clone()
recordedHeaders.Del("User-Agent")
recordedHeaders.Del("Content-Length")
Expand All @@ -92,10 +98,10 @@ func HeadersValidator() RequestValidator {
t.Errorf("expected header '%s' to be '%s', got '%s'", key, recordedHeader, gotHeader)
}
got.Headers.Del(key)

}
for key := range got.Headers {
t.Errorf("unexpected header '%s' with value '%s'", key, got.Headers.Get(key))
}
return nil
})
}
14 changes: 9 additions & 5 deletions transform_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import (
"testing"
)

func TestTransformResponseFormatJSON(t *testing.T) {
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
// User represents a user in the system.
// TODO: This type is currently unused but will be used in future tests.
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}

func TestTransformResponseFormatJSON(t *testing.T) {
tests := []struct {
name string
body string
Expand Down Expand Up @@ -65,9 +67,11 @@ func TestTransformResponseFormatJSON(t *testing.T) {
t.Fatalf("Failed to read response body: %v", err)
}
got.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
defer got.Body.Close()
if string(bodyBytes) != tt.want {
t.Errorf("Response body = %v, want %v", string(bodyBytes), tt.want)
}
got.Body.Close()
})
}
}

0 comments on commit 7312f75

Please sign in to comment.