Merge 21df7395ca7f06a3d8792d8352219fe75b61525e into 674522db91d637d179c16c372d87756ea26fa089

This commit is contained in:
Flc゛ 2025-05-21 15:45:37 +00:00 committed by GitHub
commit 9fa88f7798
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 183 additions and 151 deletions

View File

@ -24,9 +24,9 @@ jobs:
with: with:
go-version: "^1" go-version: "^1"
- name: Setup golangci-lint - name: Setup golangci-lint
uses: golangci/golangci-lint-action@v6 uses: golangci/golangci-lint-action@v8
with: with:
version: v1.61.0 version: v2.1.6
args: --verbose args: --verbose
test: test:
needs: lint needs: lint

View File

@ -1,16 +1,11 @@
run: version: "2"
timeout: 5m
linters: linters:
enable: enable:
- asciicheck - asciicheck
- copyloopvar
- dogsled - dogsled
- durationcheck - durationcheck
- errcheck
- errorlint - errorlint
- copyloopvar
- gci
- gofmt
- goimports
- gosec - gosec
- misspell - misspell
- nakedret - nakedret
@ -21,51 +16,66 @@ linters:
- testifylint - testifylint
- usestdlibvars - usestdlibvars
- wastedassign - wastedassign
settings:
linters-settings: gosec:
gosec: includes:
# To select a subset of rules to run. - G102
# Available rules: https://github.com/securego/gosec#available-rules - G106
# Default: [] - means include all rules - G108
includes: - G109
- G102 - G111
- G106 - G112
- G108 - G201
- G109 - G203
- G111 perfsprint:
- G112 int-conversion: true
- G201 err-error: true
- G203 errorf: true
perfsprint: sprintf1: true
err-error: true strconcat: true
errorf: true testifylint:
int-conversion: true enable-all: true
sprintf1: true exclusions:
strconcat: true generated: lax
testifylint: presets:
enable-all: true - comments
- common-false-positives
issues: - legacy
exclude-rules: - std-error-handling
- linters: rules:
- structcheck - linters:
- unused - structcheck
text: "`data` is unused" - unused
- linters: text: '`data` is unused'
- staticcheck - linters:
text: "SA1019:" - staticcheck
- linters: text: 'SA1019:'
- revive - linters:
text: "var-naming:" - revive
- linters: text: 'var-naming:'
- revive - linters:
text: "exported:" - revive
- path: _test\.go text: 'exported:'
linters: - linters:
- gosec # security is not make sense in tests - gosec
- linters: path: _test\.go
- revive - linters:
path: _test\.go - revive
- path: gin.go path: _test\.go
linters: paths:
- gci - third_party$
- builtin$
- examples$
formatters:
enable:
- gci
- gofmt
- gofumpt
- goimports
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
- gin.go

View File

@ -51,8 +51,6 @@ type FooBarFileStruct struct {
type FooBarFileFailStruct struct { type FooBarFileFailStruct struct {
FooBarStruct FooBarStruct
File *multipart.FileHeader `invalid_name:"file" binding:"required"` File *multipart.FileHeader `invalid_name:"file" binding:"required"`
// for unexport test
data *multipart.FileHeader `form:"data" binding:"required"`
} }
type FooDefaultBarStruct struct { type FooDefaultBarStruct struct {
@ -1063,7 +1061,7 @@ func testFormBindingInvalidName(t *testing.T, method, path, badPath, body, badBo
} }
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "", obj.TestName) assert.Empty(t, obj.TestName)
obj = InvalidNameType{} obj = InvalidNameType{}
req = requestWithBody(method, badPath, badBody) req = requestWithBody(method, badPath, badBody)
@ -1318,7 +1316,7 @@ func testBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body, bad
req := requestWithBody(http.MethodPost, path, body) req := requestWithBody(http.MethodPost, path, body)
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
require.Error(t, err) require.Error(t, err)
assert.Equal(t, "", obj.Foo) assert.Empty(t, obj.Foo)
obj = FooStruct{} obj = FooStruct{}
req = requestWithBody(http.MethodPost, badPath, badBody) req = requestWithBody(http.MethodPost, badPath, badBody)

View File

@ -18,14 +18,16 @@ func TestSliceValidationError(t *testing.T) {
{"has nil elements", SliceValidationError{errors.New("test error"), nil}, "[0]: test error"}, {"has nil elements", SliceValidationError{errors.New("test error"), nil}, "[0]: test error"},
{"has zero elements", SliceValidationError{}, ""}, {"has zero elements", SliceValidationError{}, ""},
{"has one element", SliceValidationError{errors.New("test one error")}, "[0]: test one error"}, {"has one element", SliceValidationError{errors.New("test one error")}, "[0]: test one error"},
{"has two elements", {
"has two elements",
SliceValidationError{ SliceValidationError{
errors.New("first error"), errors.New("first error"),
errors.New("second error"), errors.New("second error"),
}, },
"[0]: first error\n[1]: second error", "[0]: first error\n[1]: second error",
}, },
{"has many elements", {
"has many elements",
SliceValidationError{ SliceValidationError{
errors.New("first error"), errors.New("first error"),
errors.New("second error"), errors.New("second error"),

View File

@ -11,9 +11,11 @@ import (
const defaultMemory = 32 << 20 const defaultMemory = 32 << 20
type formBinding struct{} type (
type formPostBinding struct{} formBinding struct{}
type formMultipartBinding struct{} formPostBinding struct{}
formMultipartBinding struct{}
)
func (formBinding) Name() string { func (formBinding) Name() string {
return "form" return "form"

View File

@ -515,9 +515,9 @@ func TestMappingCustomStructTypeWithFormTag(t *testing.T) {
err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "form") err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "form")
require.NoError(t, err) require.NoError(t, err)
assert.EqualValues(t, "file", s.FileData.Protocol) assert.Equal(t, "file", s.FileData.Protocol)
assert.EqualValues(t, "/foo", s.FileData.Path) assert.Equal(t, "/foo", s.FileData.Path)
assert.EqualValues(t, "happiness", s.FileData.Name) assert.Equal(t, "happiness", s.FileData.Name)
} }
func TestMappingCustomStructTypeWithURITag(t *testing.T) { func TestMappingCustomStructTypeWithURITag(t *testing.T) {
@ -527,9 +527,9 @@ func TestMappingCustomStructTypeWithURITag(t *testing.T) {
err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "uri") err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "uri")
require.NoError(t, err) require.NoError(t, err)
assert.EqualValues(t, "file", s.FileData.Protocol) assert.Equal(t, "file", s.FileData.Protocol)
assert.EqualValues(t, "/foo", s.FileData.Path) assert.Equal(t, "/foo", s.FileData.Path)
assert.EqualValues(t, "happiness", s.FileData.Name) assert.Equal(t, "happiness", s.FileData.Name)
} }
func TestMappingCustomPointerStructTypeWithFormTag(t *testing.T) { func TestMappingCustomPointerStructTypeWithFormTag(t *testing.T) {
@ -539,9 +539,9 @@ func TestMappingCustomPointerStructTypeWithFormTag(t *testing.T) {
err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "form") err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "form")
require.NoError(t, err) require.NoError(t, err)
assert.EqualValues(t, "file", s.FileData.Protocol) assert.Equal(t, "file", s.FileData.Protocol)
assert.EqualValues(t, "/foo", s.FileData.Path) assert.Equal(t, "/foo", s.FileData.Path)
assert.EqualValues(t, "happiness", s.FileData.Name) assert.Equal(t, "happiness", s.FileData.Name)
} }
func TestMappingCustomPointerStructTypeWithURITag(t *testing.T) { func TestMappingCustomPointerStructTypeWithURITag(t *testing.T) {
@ -551,9 +551,9 @@ func TestMappingCustomPointerStructTypeWithURITag(t *testing.T) {
err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "uri") err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "uri")
require.NoError(t, err) require.NoError(t, err)
assert.EqualValues(t, "file", s.FileData.Protocol) assert.Equal(t, "file", s.FileData.Protocol)
assert.EqualValues(t, "/foo", s.FileData.Path) assert.Equal(t, "/foo", s.FileData.Path)
assert.EqualValues(t, "happiness", s.FileData.Name) assert.Equal(t, "happiness", s.FileData.Name)
} }
type customPath []string type customPath []string
@ -576,8 +576,8 @@ func TestMappingCustomSliceUri(t *testing.T) {
err := mappingByPtr(&s, formSource{"path": {`bar/foo`}}, "uri") err := mappingByPtr(&s, formSource{"path": {`bar/foo`}}, "uri")
require.NoError(t, err) require.NoError(t, err)
assert.EqualValues(t, "bar", s.FileData[0]) assert.Equal(t, "bar", s.FileData[0])
assert.EqualValues(t, "foo", s.FileData[1]) assert.Equal(t, "foo", s.FileData[1])
} }
func TestMappingCustomSliceForm(t *testing.T) { func TestMappingCustomSliceForm(t *testing.T) {
@ -587,8 +587,8 @@ func TestMappingCustomSliceForm(t *testing.T) {
err := mappingByPtr(&s, formSource{"path": {`bar/foo`}}, "form") err := mappingByPtr(&s, formSource{"path": {`bar/foo`}}, "form")
require.NoError(t, err) require.NoError(t, err)
assert.EqualValues(t, "bar", s.FileData[0]) assert.Equal(t, "bar", s.FileData[0])
assert.EqualValues(t, "foo", s.FileData[1]) assert.Equal(t, "foo", s.FileData[1])
} }
type objectID [12]byte type objectID [12]byte
@ -627,7 +627,7 @@ func TestMappingCustomArrayUri(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
expected, _ := convertTo(val) expected, _ := convertTo(val)
assert.EqualValues(t, expected, s.FileData) assert.Equal(t, expected, s.FileData)
} }
func TestMappingCustomArrayForm(t *testing.T) { func TestMappingCustomArrayForm(t *testing.T) {
@ -639,5 +639,5 @@ func TestMappingCustomArrayForm(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
expected, _ := convertTo(val) expected, _ := convertTo(val)
assert.EqualValues(t, expected, s.FileData) assert.Equal(t, expected, s.FileData)
} }

View File

@ -17,7 +17,6 @@ func (headerBinding) Name() string {
} }
func (headerBinding) Bind(req *http.Request, obj any) error { func (headerBinding) Bind(req *http.Request, obj any) error {
if err := mapHeader(obj, req.Header); err != nil { if err := mapHeader(obj, req.Header); err != nil {
return err return err
} }

View File

@ -158,16 +158,16 @@ type structNoValidationPointer struct {
} }
func TestValidateNoValidationPointers(t *testing.T) { func TestValidateNoValidationPointers(t *testing.T) {
//origin := createNoValidation_values() // origin := createNoValidation_values()
//test := createNoValidation_values() // test := createNoValidation_values()
empty := structNoValidationPointer{} empty := structNoValidationPointer{}
//assert.Nil(t, validate(test)) // assert.Nil(t, validate(test))
//assert.Nil(t, validate(&test)) // assert.Nil(t, validate(&test))
require.NoError(t, validate(empty)) require.NoError(t, validate(empty))
require.NoError(t, validate(&empty)) require.NoError(t, validate(&empty))
//assert.Equal(t, origin, test) // assert.Equal(t, origin, test)
} }
type Object map[string]any type Object map[string]any
@ -198,7 +198,7 @@ type structModifyValidation struct {
} }
func toZero(sl validator.StructLevel) { func toZero(sl validator.StructLevel) {
var s *structModifyValidation = sl.Top().Interface().(*structModifyValidation) s := sl.Top().Interface().(*structModifyValidation)
s.Integer = 0 s.Integer = 0
} }
@ -249,5 +249,5 @@ func TestValidatorEngine(t *testing.T) {
// Check that we got back non-nil errs // Check that we got back non-nil errs
require.Error(t, errs) require.Error(t, errs)
// Check that the error matches expectation // Check that the error matches expectation
require.Error(t, errs, "", "", "notone") require.Error(t, errs, "notone")
} }

View File

@ -24,6 +24,7 @@ func (xmlBinding) Bind(req *http.Request, obj any) error {
func (xmlBinding) BindBody(body []byte, obj any) error { func (xmlBinding) BindBody(body []byte, obj any) error {
return decodeXML(bytes.NewReader(body), obj) return decodeXML(bytes.NewReader(body), obj)
} }
func decodeXML(r io.Reader, obj any) error { func decodeXML(r io.Reader, obj any) error {
decoder := xml.NewDecoder(r) decoder := xml.NewDecoder(r)
if err := decoder.Decode(obj); err != nil { if err := decoder.Decode(obj); err != nil {

View File

@ -918,7 +918,7 @@ func TestContextRenderJSON(t *testing.T) {
c.JSON(http.StatusCreated, H{"foo": "bar", "html": "<b>"}) c.JSON(http.StatusCreated, H{"foo": "bar", "html": "<b>"})
assert.Equal(t, http.StatusCreated, w.Code) assert.Equal(t, http.StatusCreated, w.Code)
assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"\\u003cb\\u003e\"}", w.Body.String()) assert.JSONEq(t, "{\"foo\":\"bar\",\"html\":\"\\u003cb\\u003e\"}", w.Body.String())
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
} }
@ -946,7 +946,7 @@ func TestContextRenderJSONPWithoutCallback(t *testing.T) {
c.JSONP(http.StatusCreated, H{"foo": "bar"}) c.JSONP(http.StatusCreated, H{"foo": "bar"})
assert.Equal(t, http.StatusCreated, w.Code) assert.Equal(t, http.StatusCreated, w.Code)
assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String()) assert.JSONEq(t, "{\"foo\":\"bar\"}", w.Body.String())
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
} }
@ -972,7 +972,7 @@ func TestContextRenderAPIJSON(t *testing.T) {
c.JSON(http.StatusCreated, H{"foo": "bar"}) c.JSON(http.StatusCreated, H{"foo": "bar"})
assert.Equal(t, http.StatusCreated, w.Code) assert.Equal(t, http.StatusCreated, w.Code)
assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String()) assert.JSONEq(t, "{\"foo\":\"bar\"}", w.Body.String())
assert.Equal(t, "application/vnd.api+json", w.Header().Get("Content-Type")) assert.Equal(t, "application/vnd.api+json", w.Header().Get("Content-Type"))
} }
@ -998,7 +998,7 @@ func TestContextRenderIndentedJSON(t *testing.T) {
c.IndentedJSON(http.StatusCreated, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}}) c.IndentedJSON(http.StatusCreated, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})
assert.Equal(t, http.StatusCreated, w.Code) assert.Equal(t, http.StatusCreated, w.Code)
assert.Equal(t, "{\n \"bar\": \"foo\",\n \"foo\": \"bar\",\n \"nested\": {\n \"foo\": \"bar\"\n }\n}", w.Body.String()) assert.JSONEq(t, "{\n \"bar\": \"foo\",\n \"foo\": \"bar\",\n \"nested\": {\n \"foo\": \"bar\"\n }\n}", w.Body.String())
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
} }
@ -1059,7 +1059,7 @@ func TestContextRenderPureJSON(t *testing.T) {
c, _ := CreateTestContext(w) c, _ := CreateTestContext(w)
c.PureJSON(http.StatusCreated, H{"foo": "bar", "html": "<b>"}) c.PureJSON(http.StatusCreated, H{"foo": "bar", "html": "<b>"})
assert.Equal(t, http.StatusCreated, w.Code) assert.Equal(t, http.StatusCreated, w.Code)
assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"<b>\"}\n", w.Body.String()) assert.JSONEq(t, "{\"foo\":\"bar\",\"html\":\"<b>\"}\n", w.Body.String())
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
} }
@ -1233,7 +1233,7 @@ func TestContextRenderSSE(t *testing.T) {
"bar": "foo", "bar": "foo",
}) })
assert.Equal(t, strings.Replace(w.Body.String(), " ", "", -1), strings.Replace("event:float\ndata:1.5\n\nid:123\ndata:text\n\nevent:chat\ndata:{\"bar\":\"foo\",\"foo\":\"bar\"}\n\n", " ", "", -1)) assert.Equal(t, strings.ReplaceAll(w.Body.String(), " ", ""), strings.ReplaceAll("event:float\ndata:1.5\n\nid:123\ndata:text\n\nevent:chat\ndata:{\"bar\":\"foo\",\"foo\":\"bar\"}\n\n", " ", ""))
} }
func TestContextRenderFile(t *testing.T) { func TestContextRenderFile(t *testing.T) {
@ -1247,7 +1247,7 @@ func TestContextRenderFile(t *testing.T) {
assert.Contains(t, w.Body.String(), "func New(opts ...OptionFunc) *Engine {") assert.Contains(t, w.Body.String(), "func New(opts ...OptionFunc) *Engine {")
// Content-Type='text/plain; charset=utf-8' when go version <= 1.16, // Content-Type='text/plain; charset=utf-8' when go version <= 1.16,
// else, Content-Type='text/x-go; charset=utf-8' // else, Content-Type='text/x-go; charset=utf-8'
assert.NotEqual(t, "", w.Header().Get("Content-Type")) assert.NotEmpty(t, w.Header().Get("Content-Type"))
} }
func TestContextRenderFileFromFS(t *testing.T) { func TestContextRenderFileFromFS(t *testing.T) {
@ -1261,7 +1261,7 @@ func TestContextRenderFileFromFS(t *testing.T) {
assert.Contains(t, w.Body.String(), "func New(opts ...OptionFunc) *Engine {") assert.Contains(t, w.Body.String(), "func New(opts ...OptionFunc) *Engine {")
// Content-Type='text/plain; charset=utf-8' when go version <= 1.16, // Content-Type='text/plain; charset=utf-8' when go version <= 1.16,
// else, Content-Type='text/x-go; charset=utf-8' // else, Content-Type='text/x-go; charset=utf-8'
assert.NotEqual(t, "", w.Header().Get("Content-Type")) assert.NotEmpty(t, w.Header().Get("Content-Type"))
assert.Equal(t, "/some/path", c.Request.URL.Path) assert.Equal(t, "/some/path", c.Request.URL.Path)
} }
@ -1432,7 +1432,7 @@ func TestContextNegotiationWithJSON(t *testing.T) {
}) })
assert.Equal(t, http.StatusOK, w.Code) assert.Equal(t, http.StatusOK, w.Code)
assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String()) assert.JSONEq(t, "{\"foo\":\"bar\"}", w.Body.String())
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
} }
@ -1518,7 +1518,7 @@ func TestContextNegotiationFormat(t *testing.T) {
c.Request, _ = http.NewRequest(http.MethodPost, "", nil) c.Request, _ = http.NewRequest(http.MethodPost, "", nil)
assert.Panics(t, func() { c.NegotiateFormat() }) assert.Panics(t, func() { c.NegotiateFormat() })
assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON, MIMEXML)) assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON, MIMEXML)) //nolint:testifylint
assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEHTML, MIMEJSON)) assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEHTML, MIMEJSON))
} }
@ -1540,7 +1540,7 @@ func TestContextNegotiationFormatWithWildcardAccept(t *testing.T) {
assert.Equal(t, "*/*", c.NegotiateFormat("*/*")) assert.Equal(t, "*/*", c.NegotiateFormat("*/*"))
assert.Equal(t, "text/*", c.NegotiateFormat("text/*")) assert.Equal(t, "text/*", c.NegotiateFormat("text/*"))
assert.Equal(t, "application/*", c.NegotiateFormat("application/*")) assert.Equal(t, "application/*", c.NegotiateFormat("application/*"))
assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON)) assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON)) //nolint:testifylint
assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEXML)) assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEXML))
assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEHTML)) assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEHTML))
@ -1550,9 +1550,9 @@ func TestContextNegotiationFormatWithWildcardAccept(t *testing.T) {
assert.Equal(t, "*/*", c.NegotiateFormat("*/*")) assert.Equal(t, "*/*", c.NegotiateFormat("*/*"))
assert.Equal(t, "text/*", c.NegotiateFormat("text/*")) assert.Equal(t, "text/*", c.NegotiateFormat("text/*"))
assert.Equal(t, "", c.NegotiateFormat("application/*")) assert.Empty(t, c.NegotiateFormat("application/*"))
assert.Equal(t, "", c.NegotiateFormat(MIMEJSON)) assert.Empty(t, c.NegotiateFormat(MIMEJSON))
assert.Equal(t, "", c.NegotiateFormat(MIMEXML)) assert.Empty(t, c.NegotiateFormat(MIMEXML))
assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEHTML)) assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEHTML))
} }
@ -1564,9 +1564,9 @@ func TestContextNegotiationFormatCustom(t *testing.T) {
c.Accepted = nil c.Accepted = nil
c.SetAccepted(MIMEJSON, MIMEXML) c.SetAccepted(MIMEJSON, MIMEXML)
assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON, MIMEXML)) assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON, MIMEXML)) //nolint:testifylint
assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEXML, MIMEHTML)) assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEXML, MIMEHTML))
assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON)) assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON)) //nolint:testifylint
} }
func TestContextNegotiationFormat2(t *testing.T) { func TestContextNegotiationFormat2(t *testing.T) {
@ -1574,7 +1574,7 @@ func TestContextNegotiationFormat2(t *testing.T) {
c.Request, _ = http.NewRequest(http.MethodPost, "/", nil) c.Request, _ = http.NewRequest(http.MethodPost, "/", nil)
c.Request.Header.Add("Accept", "image/tiff-fx") c.Request.Header.Add("Accept", "image/tiff-fx")
assert.Equal(t, "", c.NegotiateFormat("image/tiff")) assert.Empty(t, c.NegotiateFormat("image/tiff"))
} }
func TestContextIsAborted(t *testing.T) { func TestContextIsAborted(t *testing.T) {
@ -1634,7 +1634,7 @@ func TestContextAbortWithStatusJSON(t *testing.T) {
_, err := buf.ReadFrom(w.Body) _, err := buf.ReadFrom(w.Body)
require.NoError(t, err) require.NoError(t, err)
jsonStringBody := buf.String() jsonStringBody := buf.String()
assert.Equal(t, "{\"foo\":\"fooValue\",\"bar\":\"barValue\"}", jsonStringBody) assert.JSONEq(t, "{\"foo\":\"fooValue\",\"bar\":\"barValue\"}", jsonStringBody)
} }
func TestContextError(t *testing.T) { func TestContextError(t *testing.T) {
@ -3076,7 +3076,7 @@ func TestInterceptedHeader(t *testing.T) {
// Compared to this time, this is when the response headers will be flushed // Compared to this time, this is when the response headers will be flushed
// As response is flushed on c.String, the Header cannot be set by the first // As response is flushed on c.String, the Header cannot be set by the first
// middleware. Assert this // middleware. Assert this
assert.Equal(t, "", w.Result().Header.Get("X-Test")) assert.Empty(t, w.Result().Header.Get("X-Test"))
assert.Equal(t, "present", w.Result().Header.Get("X-Test-2")) assert.Equal(t, "present", w.Result().Header.Get("X-Test-2"))
} }

View File

@ -34,7 +34,7 @@ func TestError(t *testing.T) {
}, err.JSON()) }, err.JSON())
jsonBytes, _ := json.Marshal(err) jsonBytes, _ := json.Marshal(err)
assert.Equal(t, "{\"error\":\"test error\",\"meta\":\"some data\"}", string(jsonBytes)) assert.JSONEq(t, "{\"error\":\"test error\",\"meta\":\"some data\"}", string(jsonBytes))
err.SetMeta(H{ //nolint: errcheck err.SetMeta(H{ //nolint: errcheck
"status": "200", "status": "200",
@ -93,13 +93,13 @@ Error #03: third
H{"error": "third", "status": "400"}, H{"error": "third", "status": "400"},
}, errs.JSON()) }, errs.JSON())
jsonBytes, _ := json.Marshal(errs) jsonBytes, _ := json.Marshal(errs)
assert.Equal(t, "[{\"error\":\"first\"},{\"error\":\"second\",\"meta\":\"some data\"},{\"error\":\"third\",\"status\":\"400\"}]", string(jsonBytes)) assert.JSONEq(t, "[{\"error\":\"first\"},{\"error\":\"second\",\"meta\":\"some data\"},{\"error\":\"third\",\"status\":\"400\"}]", string(jsonBytes))
errs = errorMsgs{ errs = errorMsgs{
{Err: errors.New("first"), Type: ErrorTypePrivate}, {Err: errors.New("first"), Type: ErrorTypePrivate},
} }
assert.Equal(t, H{"error": "first"}, errs.JSON()) assert.Equal(t, H{"error": "first"}, errs.JSON())
jsonBytes, _ = json.Marshal(errs) jsonBytes, _ = json.Marshal(errs)
assert.Equal(t, "{\"error\":\"first\"}", string(jsonBytes)) assert.JSONEq(t, "{\"error\":\"first\"}", string(jsonBytes))
errs = errorMsgs{} errs = errorMsgs{}
assert.Nil(t, errs.Last()) assert.Nil(t, errs.Last())

1
fs.go
View File

@ -17,7 +17,6 @@ type OnlyFilesFS struct {
// Open passes `Open` to the upstream implementation without `Readdir` functionality. // Open passes `Open` to the upstream implementation without `Readdir` functionality.
func (o OnlyFilesFS) Open(name string) (http.File, error) { func (o OnlyFilesFS) Open(name string) (http.File, error) {
f, err := o.FileSystem.Open(name) f, err := o.FileSystem.Open(name)
if err != nil { if err != nil {
return nil, err return nil, err
} }

3
gin.go
View File

@ -18,7 +18,6 @@ import (
"github.com/gin-gonic/gin/internal/bytesconv" "github.com/gin-gonic/gin/internal/bytesconv"
filesystem "github.com/gin-gonic/gin/internal/fs" filesystem "github.com/gin-gonic/gin/internal/fs"
"github.com/gin-gonic/gin/render" "github.com/gin-gonic/gin/render"
"github.com/quic-go/quic-go/http3" "github.com/quic-go/quic-go/http3"
"golang.org/x/net/http2" "golang.org/x/net/http2"
"golang.org/x/net/http2/h2c" "golang.org/x/net/http2/h2c"
@ -216,7 +215,7 @@ func New(opts ...OptionFunc) *Engine {
trustedProxies: []string{"0.0.0.0/0", "::/0"}, trustedProxies: []string{"0.0.0.0/0", "::/0"},
trustedCIDRs: defaultTrustedCIDRs, trustedCIDRs: defaultTrustedCIDRs,
} }
engine.RouterGroup.engine = engine engine.engine = engine
engine.pool.New = func() any { engine.pool.New = func() any {
return engine.allocateContext(engine.maxParams) return engine.allocateContext(engine.maxParams)
} }

View File

@ -12,8 +12,10 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
var once sync.Once var (
var internalEngine *gin.Engine once sync.Once
internalEngine *gin.Engine
)
func engine() *gin.Engine { func engine() *gin.Engine {
once.Do(func() { once.Do(func() {

View File

@ -28,7 +28,6 @@ import (
// params[1]=response status (custom compare status) default:"200 OK" // params[1]=response status (custom compare status) default:"200 OK"
// params[2]=response body (custom compare content) default:"it worked" // params[2]=response body (custom compare content) default:"it worked"
func testRequest(t *testing.T, params ...string) { func testRequest(t *testing.T, params ...string) {
if len(params) == 0 { if len(params) == 0 {
t.Fatal("url cannot be empty") t.Fatal("url cannot be empty")
} }
@ -47,12 +46,12 @@ func testRequest(t *testing.T, params ...string) {
body, ioerr := io.ReadAll(resp.Body) body, ioerr := io.ReadAll(resp.Body)
require.NoError(t, ioerr) require.NoError(t, ioerr)
var responseStatus = "200 OK" responseStatus := "200 OK"
if len(params) > 1 && params[1] != "" { if len(params) > 1 && params[1] != "" {
responseStatus = params[1] responseStatus = params[1]
} }
var responseBody = "it worked" responseBody := "it worked"
if len(params) > 2 && params[2] != "" { if len(params) > 2 && params[2] != "" {
responseBody = params[2] responseBody = params[2]
} }
@ -170,7 +169,7 @@ func TestRunTLS(t *testing.T) {
} }
func TestPusher(t *testing.T) { func TestPusher(t *testing.T) {
var html = template.Must(template.New("https").Parse(` html := template.Must(template.New("https").Parse(`
<html> <html>
<head> <head>
<title>Https Test</title> <title>Https Test</title>

View File

@ -46,7 +46,7 @@ func setupHTMLFiles(t *testing.T, mode string, tls bool, loadMethod func(*Engine
}) })
router.GET("/raw", func(c *Context) { router.GET("/raw", func(c *Context) {
c.HTML(http.StatusOK, "raw.tmpl", map[string]any{ c.HTML(http.StatusOK, "raw.tmpl", map[string]any{
"now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC), "now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC), //nolint:gofumpt
}) })
}) })
}) })
@ -883,7 +883,7 @@ func TestWithOptionFunc(t *testing.T) {
type Birthday string type Birthday string
func (b *Birthday) UnmarshalParam(param string) error { func (b *Birthday) UnmarshalParam(param string) error {
*b = Birthday(strings.Replace(param, "-", "/", -1)) *b = Birthday(strings.ReplaceAll(param, "-", "/"))
return nil return nil
} }

View File

@ -298,8 +298,8 @@ func TestShouldBindUri(t *testing.T) {
router.Handle(http.MethodGet, "/rest/:name/:id", func(c *Context) { router.Handle(http.MethodGet, "/rest/:name/:id", func(c *Context) {
var person Person var person Person
require.NoError(t, c.ShouldBindUri(&person)) require.NoError(t, c.ShouldBindUri(&person))
assert.NotEqual(t, "", person.Name) assert.NotEmpty(t, person.Name)
assert.NotEqual(t, "", person.ID) assert.NotEmpty(t, person.ID)
c.String(http.StatusOK, "ShouldBindUri test OK") c.String(http.StatusOK, "ShouldBindUri test OK")
}) })
@ -320,8 +320,8 @@ func TestBindUri(t *testing.T) {
router.Handle(http.MethodGet, "/rest/:name/:id", func(c *Context) { router.Handle(http.MethodGet, "/rest/:name/:id", func(c *Context) {
var person Person var person Person
require.NoError(t, c.BindUri(&person)) require.NoError(t, c.BindUri(&person))
assert.NotEqual(t, "", person.Name) assert.NotEmpty(t, person.Name)
assert.NotEqual(t, "", person.ID) assert.NotEmpty(t, person.ID)
c.String(http.StatusOK, "BindUri test OK") c.String(http.StatusOK, "BindUri test OK")
}) })

5
go.mod
View File

@ -38,9 +38,10 @@ require (
go.uber.org/mock v0.5.0 // indirect go.uber.org/mock v0.5.0 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/crypto v0.38.0 // indirect golang.org/x/crypto v0.38.0 // indirect
golang.org/x/mod v0.18.0 // indirect golang.org/x/lint v0.0.0-20241112194109-818c5a804067 // indirect
golang.org/x/mod v0.24.0 // indirect
golang.org/x/sync v0.14.0 // indirect golang.org/x/sync v0.14.0 // indirect
golang.org/x/sys v0.33.0 // indirect golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.25.0 // indirect golang.org/x/text v0.25.0 // indirect
golang.org/x/tools v0.22.0 // indirect golang.org/x/tools v0.33.0 // indirect
) )

16
go.sum
View File

@ -82,22 +82,38 @@ go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
golang.org/x/lint v0.0.0-20241112194109-818c5a804067 h1:adDmSQyFTCiv19j015EGKJBoaa7ElV0Q1Wovb/4G7NA=
golang.org/x/lint v0.0.0-20241112194109-818c5a804067/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=

View File

@ -12,8 +12,10 @@ import (
"time" "time"
) )
var testString = "Albert Einstein: Logic will get you from A to B. Imagination will take you everywhere." var (
var testBytes = []byte(testString) testString = "Albert Einstein: Logic will get you from A to B. Imagination will take you everywhere."
testBytes = []byte(testString)
)
func rawBytesToStr(b []byte) string { func rawBytesToStr(b []byte) string {
return string(b) return string(b)

View File

@ -13,7 +13,6 @@ type FileSystem struct {
// Open passes `Open` to the upstream implementation and return an [fs.File]. // Open passes `Open` to the upstream implementation and return an [fs.File].
func (o FileSystem) Open(name string) (fs.File, error) { func (o FileSystem) Open(name string) (fs.File, error) {
f, err := o.FileSystem.Open(name) f, err := o.FileSystem.Open(name)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -371,11 +371,11 @@ func TestErrorLogger(t *testing.T) {
w := PerformRequest(router, http.MethodGet, "/error") w := PerformRequest(router, http.MethodGet, "/error")
assert.Equal(t, http.StatusOK, w.Code) assert.Equal(t, http.StatusOK, w.Code)
assert.Equal(t, "{\"error\":\"this is an error\"}", w.Body.String()) assert.JSONEq(t, "{\"error\":\"this is an error\"}", w.Body.String())
w = PerformRequest(router, http.MethodGet, "/abort") w = PerformRequest(router, http.MethodGet, "/abort")
assert.Equal(t, http.StatusUnauthorized, w.Code) assert.Equal(t, http.StatusUnauthorized, w.Code)
assert.Equal(t, "{\"error\":\"no authorized\"}", w.Body.String()) assert.JSONEq(t, "{\"error\":\"no authorized\"}", w.Body.String())
w = PerformRequest(router, http.MethodGet, "/print") w = PerformRequest(router, http.MethodGet, "/print")
assert.Equal(t, http.StatusInternalServerError, w.Code) assert.Equal(t, http.StatusInternalServerError, w.Code)

View File

@ -249,5 +249,5 @@ func TestMiddlewareWrite(t *testing.T) {
w := PerformRequest(router, http.MethodGet, "/") w := PerformRequest(router, http.MethodGet, "/")
assert.Equal(t, http.StatusBadRequest, w.Code) assert.Equal(t, http.StatusBadRequest, w.Code)
assert.Equal(t, strings.Replace("hola\n<map><foo>bar</foo></map>{\"foo\":\"bar\"}{\"foo\":\"bar\"}event:test\ndata:message\n\n", " ", "", -1), strings.Replace(w.Body.String(), " ", "", -1)) assert.Equal(t, strings.ReplaceAll("hola\n<map><foo>bar</foo></map>{\"foo\":\"bar\"}{\"foo\":\"bar\"}event:test\ndata:message\n\n", " ", ""), strings.ReplaceAll(w.Body.String(), " ", ""))
} }

View File

@ -44,8 +44,10 @@ var DefaultWriter io.Writer = os.Stdout
// DefaultErrorWriter is the default io.Writer used by Gin to debug errors // DefaultErrorWriter is the default io.Writer used by Gin to debug errors
var DefaultErrorWriter io.Writer = os.Stderr var DefaultErrorWriter io.Writer = os.Stderr
var ginMode int32 = debugCode var (
var modeName atomic.Value ginMode int32 = debugCode
modeName atomic.Value
)
func init() { func init() {
mode := os.Getenv(EnvGinMode) mode := os.Getenv(EnvGinMode)

View File

@ -67,6 +67,7 @@ func (r HTMLDebug) Instance(name string, data any) Render {
Data: data, Data: data,
} }
} }
func (r HTMLDebug) loadTemplate() *template.Template { func (r HTMLDebug) loadTemplate() *template.Template {
if r.FuncMap == nil { if r.FuncMap == nil {
r.FuncMap = template.FuncMap{} r.FuncMap = template.FuncMap{}

View File

@ -38,7 +38,7 @@ func TestRenderJSON(t *testing.T) {
err := (JSON{data}).Render(w) err := (JSON{data}).Render(w)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"\\u003cb\\u003e\"}", w.Body.String()) assert.JSONEq(t, "{\"foo\":\"bar\",\"html\":\"\\u003cb\\u003e\"}", w.Body.String())
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
} }
@ -60,7 +60,7 @@ func TestRenderIndentedJSON(t *testing.T) {
err := (IndentedJSON{data}).Render(w) err := (IndentedJSON{data}).Render(w)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "{\n \"bar\": \"foo\",\n \"foo\": \"bar\"\n}", w.Body.String()) assert.JSONEq(t, "{\n \"bar\": \"foo\",\n \"foo\": \"bar\"\n}", w.Body.String())
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
} }
@ -85,7 +85,7 @@ func TestRenderSecureJSON(t *testing.T) {
err1 := (SecureJSON{"while(1);", data}).Render(w1) err1 := (SecureJSON{"while(1);", data}).Render(w1)
require.NoError(t, err1) require.NoError(t, err1)
assert.Equal(t, "{\"foo\":\"bar\"}", w1.Body.String()) assert.JSONEq(t, "{\"foo\":\"bar\"}", w1.Body.String())
assert.Equal(t, "application/json; charset=utf-8", w1.Header().Get("Content-Type")) assert.Equal(t, "application/json; charset=utf-8", w1.Header().Get("Content-Type"))
w2 := httptest.NewRecorder() w2 := httptest.NewRecorder()
@ -194,7 +194,7 @@ func TestRenderJsonpJSONError2(t *testing.T) {
e := (JsonpJSON{"", data}).Render(w) e := (JsonpJSON{"", data}).Render(w)
require.NoError(t, e) require.NoError(t, e)
assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String()) assert.JSONEq(t, "{\"foo\":\"bar\"}", w.Body.String())
assert.Equal(t, "application/javascript; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "application/javascript; charset=utf-8", w.Header().Get("Content-Type"))
} }
@ -217,7 +217,7 @@ func TestRenderAsciiJSON(t *testing.T) {
err := (AsciiJSON{data1}).Render(w1) err := (AsciiJSON{data1}).Render(w1)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "{\"lang\":\"GO\\u8bed\\u8a00\",\"tag\":\"\\u003cbr\\u003e\"}", w1.Body.String()) assert.JSONEq(t, "{\"lang\":\"GO\\u8bed\\u8a00\",\"tag\":\"\\u003cbr\\u003e\"}", w1.Body.String())
assert.Equal(t, "application/json", w1.Header().Get("Content-Type")) assert.Equal(t, "application/json", w1.Header().Get("Content-Type"))
w2 := httptest.NewRecorder() w2 := httptest.NewRecorder()
@ -244,7 +244,7 @@ func TestRenderPureJSON(t *testing.T) {
} }
err := (PureJSON{data}).Render(w) err := (PureJSON{data}).Render(w)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"<b>\"}\n", w.Body.String()) assert.JSONEq(t, "{\"foo\":\"bar\",\"html\":\"<b>\"}\n", w.Body.String())
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
} }

View File

@ -484,7 +484,7 @@ func TestRouterMiddlewareAndStatic(t *testing.T) {
assert.Contains(t, w.Body.String(), "package gin") assert.Contains(t, w.Body.String(), "package gin")
// Content-Type='text/plain; charset=utf-8' when go version <= 1.16, // Content-Type='text/plain; charset=utf-8' when go version <= 1.16,
// else, Content-Type='text/x-go; charset=utf-8' // else, Content-Type='text/x-go; charset=utf-8'
assert.NotEqual(t, "", w.Header().Get("Content-Type")) assert.NotEmpty(t, w.Header().Get("Content-Type"))
assert.NotEqual(t, "Mon, 02 Jan 2006 15:04:05 MST", w.Header().Get("Last-Modified")) assert.NotEqual(t, "Mon, 02 Jan 2006 15:04:05 MST", w.Header().Get("Last-Modified"))
assert.Equal(t, "Mon, 02 Jan 2006 15:04:05 MST", w.Header().Get("Expires")) assert.Equal(t, "Mon, 02 Jan 2006 15:04:05 MST", w.Header().Get("Expires"))
assert.Equal(t, "Gin Framework", w.Header().Get("x-GIN")) assert.Equal(t, "Gin Framework", w.Header().Get("x-GIN"))
@ -764,7 +764,7 @@ func TestRouteContextHoldsFullPath(t *testing.T) {
// Test not found // Test not found
router.Use(func(c *Context) { router.Use(func(c *Context) {
// For not found routes full path is empty // For not found routes full path is empty
assert.Equal(t, "", c.FullPath()) assert.Empty(t, c.FullPath())
}) })
w := PerformRequest(router, http.MethodGet, "/not-found") w := PerformRequest(router, http.MethodGet, "/not-found")

View File

@ -481,7 +481,7 @@ func TestTreeDuplicatePath(t *testing.T) {
} }
} }
//printChildren(tree, "") // printChildren(tree, "")
checkRequests(t, tree, testRequests{ checkRequests(t, tree, testRequests{
{"/", false, "/", nil}, {"/", false, "/", nil},
@ -532,7 +532,7 @@ func TestTreeCatchAllConflictRoot(t *testing.T) {
func TestTreeCatchMaxParams(t *testing.T) { func TestTreeCatchMaxParams(t *testing.T) {
tree := &node{} tree := &node{}
var route = "/cmd/*filepath" route := "/cmd/*filepath"
tree.addRoute(route, fakeHandler(route)) tree.addRoute(route, fakeHandler(route))
} }
@ -692,7 +692,7 @@ func TestTreeRootTrailingSlashRedirect(t *testing.T) {
} }
func TestRedirectTrailingSlash(t *testing.T) { func TestRedirectTrailingSlash(t *testing.T) {
var data = []struct { data := []struct {
path string path string
}{ }{
{"/hello/:name"}, {"/hello/:name"},

View File

@ -94,7 +94,7 @@ func somefunction() {
} }
func TestJoinPaths(t *testing.T) { func TestJoinPaths(t *testing.T) {
assert.Equal(t, "", joinPaths("", "")) assert.Empty(t, joinPaths("", ""))
assert.Equal(t, "/", joinPaths("", "/")) assert.Equal(t, "/", joinPaths("", "/"))
assert.Equal(t, "/a", joinPaths("/a", "")) assert.Equal(t, "/a", joinPaths("/a", ""))
assert.Equal(t, "/a/", joinPaths("/a/", "")) assert.Equal(t, "/a/", joinPaths("/a/", ""))