Compare commits

..

10 Commits

Author SHA1 Message Date
a5849d15be GoWeb: add service container into Gin's engine and context
Some checks failed
CodeQL / Analyze (go) (push) Has been cancelled
Run Tests / lint (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -tags "sonic avx") (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, ) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -race) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -tags go_json) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -tags nomsgpack) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, ) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -race) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -tags "sonic avx") (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -tags go_json) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -tags nomsgpack) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, ) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -race) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -tags "sonic avx") (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -tags go_json) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -tags nomsgpack) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, ) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -race) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -tags "sonic avx") (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -tags go_json) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -tags nomsgpack) (push) Has been cancelled
2024-09-30 09:23:32 +02:00
f05f966a08 feat(form): Support default values for collections in form binding (#4048)
Some checks failed
CodeQL / Analyze (go) (push) Has been cancelled
Run Tests / lint (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, ) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -race) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -tags "sonic avx") (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -tags go_json) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -tags nomsgpack) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, ) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -race) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -tags "sonic avx") (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -tags go_json) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -tags nomsgpack) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, ) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -race) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -tags "sonic avx") (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -tags go_json) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -tags nomsgpack) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, ) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -race) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -tags "sonic avx") (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -tags go_json) (push) Has been cancelled
Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -tags nomsgpack) (push) Has been cancelled
2024-09-21 23:24:18 +08:00
9d7c0e9e1a feat(context): GetXxx added support for more go native types (#3633) 2024-09-15 08:58:59 +08:00
f2c861a24f docs: fix route group example code (#4020) 2024-09-15 08:54:23 +08:00
28e57f58b1 fix(form): Set default value for form fields (#4047)
- Use specified default value in struct tags when binding a request input to struct for validation, even if sent empty, not only when not sent at all.
- Add string field to `TestMappingDefault` test case.
- Add test case for not sent form field to default to the value specified via code.
- Add test case for form field sent empty to default to the value specified via code.

Fixes: How to apply default value if empty value provided by client during model binding? #4042, #13042df, #a41721a
2024-09-06 13:21:19 +08:00
3cb30679b5 feat(form): add array collection format in form binding (#3986)
* feat(form): add array collection format in form binding

* feat(form): add array collection format in form binding

* test(form): fix test code for array collection format in form binding
2024-08-24 14:16:30 +08:00
cc4e11438c chore(deps): bump golang.org/x/net from 0.25.0 to 0.27.0 (#4013)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.25.0 to 0.27.0.
- [Commits](https://github.com/golang/net/compare/v0.25.0...v0.27.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-14 20:34:34 +08:00
5f55c6a711 ci(lint): enable testifylint linter (#4010)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2024-07-14 20:33:08 +08:00
626d55b0c0 fix(gin): Do not panic when handling method not allowed on empty tree (#4003)
Signed-off-by: Pierre-Henri Symoneaux <pierre-henri.symoneaux@ovhcloud.com>
2024-06-22 22:19:04 +08:00
9c081de9cd docs: fix typo in Gin Quick Start (#3997) 2024-06-16 00:28:08 +08:00
27 changed files with 1137 additions and 487 deletions

View File

@ -17,6 +17,7 @@ linters:
- nilerr - nilerr
- nolintlint - nolintlint
- revive - revive
- testifylint
- wastedassign - wastedassign
linters-settings: linters-settings:
@ -33,6 +34,8 @@ linters-settings:
- G112 - G112
- G201 - G201
- G203 - G203
testifylint:
enable-all: true
issues: issues:
exclude-rules: exclude-rules:

View File

@ -11,6 +11,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/ugorji/go/codec" "github.com/ugorji/go/codec"
) )
@ -24,7 +25,7 @@ func TestBindingMsgPack(t *testing.T) {
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
assert.NotNil(t, buf) assert.NotNil(t, buf)
err := codec.NewEncoder(buf, h).Encode(test) err := codec.NewEncoder(buf, h).Encode(test)
assert.NoError(t, err) require.NoError(t, err)
data := buf.Bytes() data := buf.Bytes()
@ -41,14 +42,14 @@ func testMsgPackBodyBinding(t *testing.T, b Binding, name, path, badPath, body,
req := requestWithBody("POST", path, body) req := requestWithBody("POST", path, body)
req.Header.Add("Content-Type", MIMEMSGPACK) req.Header.Add("Content-Type", MIMEMSGPACK)
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
obj = FooStruct{} obj = FooStruct{}
req = requestWithBody("POST", badPath, badBody) req = requestWithBody("POST", badPath, badBody)
req.Header.Add("Content-Type", MIMEMSGPACK) req.Header.Add("Content-Type", MIMEMSGPACK)
err = MsgPack.Bind(req, &obj) err = MsgPack.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func TestBindingDefaultMsgPack(t *testing.T) { func TestBindingDefaultMsgPack(t *testing.T) {

View File

@ -20,6 +20,7 @@ import (
"github.com/gin-gonic/gin/testdata/protoexample" "github.com/gin-gonic/gin/testdata/protoexample"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
@ -175,7 +176,7 @@ func TestBindingJSONNilBody(t *testing.T) {
var obj FooStruct var obj FooStruct
req, _ := http.NewRequest(http.MethodPost, "/", nil) req, _ := http.NewRequest(http.MethodPost, "/", nil)
err := JSON.Bind(req, &obj) err := JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func TestBindingJSON(t *testing.T) { func TestBindingJSON(t *testing.T) {
@ -376,7 +377,7 @@ func TestBindingFormStringSliceMap(t *testing.T) {
req := requestWithBody("POST", "/", "foo=something&foo=bar&hello=world") req := requestWithBody("POST", "/", "foo=something&foo=bar&hello=world")
req.Header.Add("Content-Type", MIMEPOSTForm) req.Header.Add("Content-Type", MIMEPOSTForm)
err := Form.Bind(req, &obj) err := Form.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.NotNil(t, obj) assert.NotNil(t, obj)
assert.Len(t, obj, 2) assert.Len(t, obj, 2)
target := map[string][]string{ target := map[string][]string{
@ -389,7 +390,7 @@ func TestBindingFormStringSliceMap(t *testing.T) {
req = requestWithBody("POST", "/", "foo=something&foo=bar&hello=world") req = requestWithBody("POST", "/", "foo=something&foo=bar&hello=world")
req.Header.Add("Content-Type", MIMEPOSTForm) req.Header.Add("Content-Type", MIMEPOSTForm)
err = Form.Bind(req, &objInvalid) err = Form.Bind(req, &objInvalid)
assert.Error(t, err) require.Error(t, err)
} }
func TestBindingQuery(t *testing.T) { func TestBindingQuery(t *testing.T) {
@ -428,7 +429,7 @@ func TestBindingQueryStringMap(t *testing.T) {
obj := make(map[string]string) obj := make(map[string]string)
req := requestWithBody("GET", "/?foo=bar&hello=world", "") req := requestWithBody("GET", "/?foo=bar&hello=world", "")
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.NotNil(t, obj) assert.NotNil(t, obj)
assert.Len(t, obj, 2) assert.Len(t, obj, 2)
assert.Equal(t, "bar", obj["foo"]) assert.Equal(t, "bar", obj["foo"])
@ -437,7 +438,7 @@ func TestBindingQueryStringMap(t *testing.T) {
obj = make(map[string]string) obj = make(map[string]string)
req = requestWithBody("GET", "/?foo=bar&foo=2&hello=world", "") // should pick last req = requestWithBody("GET", "/?foo=bar&foo=2&hello=world", "") // should pick last
err = b.Bind(req, &obj) err = b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.NotNil(t, obj) assert.NotNil(t, obj)
assert.Len(t, obj, 2) assert.Len(t, obj, 2)
assert.Equal(t, "2", obj["foo"]) assert.Equal(t, "2", obj["foo"])
@ -495,28 +496,28 @@ func TestBindingYAMLFail(t *testing.T) {
func createFormPostRequest(t *testing.T) *http.Request { func createFormPostRequest(t *testing.T) *http.Request {
req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar&bar=foo")) req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar&bar=foo"))
assert.NoError(t, err) require.NoError(t, err)
req.Header.Set("Content-Type", MIMEPOSTForm) req.Header.Set("Content-Type", MIMEPOSTForm)
return req return req
} }
func createDefaultFormPostRequest(t *testing.T) *http.Request { func createDefaultFormPostRequest(t *testing.T) *http.Request {
req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar")) req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar"))
assert.NoError(t, err) require.NoError(t, err)
req.Header.Set("Content-Type", MIMEPOSTForm) req.Header.Set("Content-Type", MIMEPOSTForm)
return req return req
} }
func createFormPostRequestForMap(t *testing.T) *http.Request { func createFormPostRequestForMap(t *testing.T) *http.Request {
req, err := http.NewRequest("POST", "/?map_foo=getfoo", bytes.NewBufferString("map_foo={\"bar\":123}")) req, err := http.NewRequest("POST", "/?map_foo=getfoo", bytes.NewBufferString("map_foo={\"bar\":123}"))
assert.NoError(t, err) require.NoError(t, err)
req.Header.Set("Content-Type", MIMEPOSTForm) req.Header.Set("Content-Type", MIMEPOSTForm)
return req return req
} }
func createFormPostRequestForMapFail(t *testing.T) *http.Request { func createFormPostRequestForMapFail(t *testing.T) *http.Request {
req, err := http.NewRequest("POST", "/?map_foo=getfoo", bytes.NewBufferString("map_foo=hello")) req, err := http.NewRequest("POST", "/?map_foo=getfoo", bytes.NewBufferString("map_foo=hello"))
assert.NoError(t, err) require.NoError(t, err)
req.Header.Set("Content-Type", MIMEPOSTForm) req.Header.Set("Content-Type", MIMEPOSTForm)
return req return req
} }
@ -527,20 +528,20 @@ func createFormFilesMultipartRequest(t *testing.T) *http.Request {
mw := multipart.NewWriter(body) mw := multipart.NewWriter(body)
defer mw.Close() defer mw.Close()
assert.NoError(t, mw.SetBoundary(boundary)) require.NoError(t, mw.SetBoundary(boundary))
assert.NoError(t, mw.WriteField("foo", "bar")) require.NoError(t, mw.WriteField("foo", "bar"))
assert.NoError(t, mw.WriteField("bar", "foo")) require.NoError(t, mw.WriteField("bar", "foo"))
f, err := os.Open("form.go") f, err := os.Open("form.go")
assert.NoError(t, err) require.NoError(t, err)
defer f.Close() defer f.Close()
fw, err1 := mw.CreateFormFile("file", "form.go") fw, err1 := mw.CreateFormFile("file", "form.go")
assert.NoError(t, err1) require.NoError(t, err1)
_, err = io.Copy(fw, f) _, err = io.Copy(fw, f)
assert.NoError(t, err) require.NoError(t, err)
req, err2 := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body) req, err2 := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body)
assert.NoError(t, err2) require.NoError(t, err2)
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary) req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
return req return req
@ -552,20 +553,20 @@ func createFormFilesMultipartRequestFail(t *testing.T) *http.Request {
mw := multipart.NewWriter(body) mw := multipart.NewWriter(body)
defer mw.Close() defer mw.Close()
assert.NoError(t, mw.SetBoundary(boundary)) require.NoError(t, mw.SetBoundary(boundary))
assert.NoError(t, mw.WriteField("foo", "bar")) require.NoError(t, mw.WriteField("foo", "bar"))
assert.NoError(t, mw.WriteField("bar", "foo")) require.NoError(t, mw.WriteField("bar", "foo"))
f, err := os.Open("form.go") f, err := os.Open("form.go")
assert.NoError(t, err) require.NoError(t, err)
defer f.Close() defer f.Close()
fw, err1 := mw.CreateFormFile("file_foo", "form_foo.go") fw, err1 := mw.CreateFormFile("file_foo", "form_foo.go")
assert.NoError(t, err1) require.NoError(t, err1)
_, err = io.Copy(fw, f) _, err = io.Copy(fw, f)
assert.NoError(t, err) require.NoError(t, err)
req, err2 := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body) req, err2 := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body)
assert.NoError(t, err2) require.NoError(t, err2)
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary) req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
return req return req
@ -577,11 +578,11 @@ func createFormMultipartRequest(t *testing.T) *http.Request {
mw := multipart.NewWriter(body) mw := multipart.NewWriter(body)
defer mw.Close() defer mw.Close()
assert.NoError(t, mw.SetBoundary(boundary)) require.NoError(t, mw.SetBoundary(boundary))
assert.NoError(t, mw.WriteField("foo", "bar")) require.NoError(t, mw.WriteField("foo", "bar"))
assert.NoError(t, mw.WriteField("bar", "foo")) require.NoError(t, mw.WriteField("bar", "foo"))
req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body) req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body)
assert.NoError(t, err) require.NoError(t, err)
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary) req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
return req return req
} }
@ -592,10 +593,10 @@ func createFormMultipartRequestForMap(t *testing.T) *http.Request {
mw := multipart.NewWriter(body) mw := multipart.NewWriter(body)
defer mw.Close() defer mw.Close()
assert.NoError(t, mw.SetBoundary(boundary)) require.NoError(t, mw.SetBoundary(boundary))
assert.NoError(t, mw.WriteField("map_foo", "{\"bar\":123, \"name\":\"thinkerou\", \"pai\": 3.14}")) require.NoError(t, mw.WriteField("map_foo", "{\"bar\":123, \"name\":\"thinkerou\", \"pai\": 3.14}"))
req, err := http.NewRequest("POST", "/?map_foo=getfoo", body) req, err := http.NewRequest("POST", "/?map_foo=getfoo", body)
assert.NoError(t, err) require.NoError(t, err)
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary) req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
return req return req
} }
@ -606,10 +607,10 @@ func createFormMultipartRequestForMapFail(t *testing.T) *http.Request {
mw := multipart.NewWriter(body) mw := multipart.NewWriter(body)
defer mw.Close() defer mw.Close()
assert.NoError(t, mw.SetBoundary(boundary)) require.NoError(t, mw.SetBoundary(boundary))
assert.NoError(t, mw.WriteField("map_foo", "3.14")) require.NoError(t, mw.WriteField("map_foo", "3.14"))
req, err := http.NewRequest("POST", "/?map_foo=getfoo", body) req, err := http.NewRequest("POST", "/?map_foo=getfoo", body)
assert.NoError(t, err) require.NoError(t, err)
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary) req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
return req return req
} }
@ -617,7 +618,7 @@ func createFormMultipartRequestForMapFail(t *testing.T) *http.Request {
func TestBindingFormPost(t *testing.T) { func TestBindingFormPost(t *testing.T) {
req := createFormPostRequest(t) req := createFormPostRequest(t)
var obj FooBarStruct var obj FooBarStruct
assert.NoError(t, FormPost.Bind(req, &obj)) require.NoError(t, FormPost.Bind(req, &obj))
assert.Equal(t, "form-urlencoded", FormPost.Name()) assert.Equal(t, "form-urlencoded", FormPost.Name())
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
@ -627,7 +628,7 @@ func TestBindingFormPost(t *testing.T) {
func TestBindingDefaultValueFormPost(t *testing.T) { func TestBindingDefaultValueFormPost(t *testing.T) {
req := createDefaultFormPostRequest(t) req := createDefaultFormPostRequest(t)
var obj FooDefaultBarStruct var obj FooDefaultBarStruct
assert.NoError(t, FormPost.Bind(req, &obj)) require.NoError(t, FormPost.Bind(req, &obj))
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
assert.Equal(t, "hello", obj.Bar) assert.Equal(t, "hello", obj.Bar)
@ -637,22 +638,22 @@ func TestBindingFormPostForMap(t *testing.T) {
req := createFormPostRequestForMap(t) req := createFormPostRequestForMap(t)
var obj FooStructForMapType var obj FooStructForMapType
err := FormPost.Bind(req, &obj) err := FormPost.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, float64(123), obj.MapFoo["bar"].(float64)) assert.InDelta(t, float64(123), obj.MapFoo["bar"].(float64), 0.01)
} }
func TestBindingFormPostForMapFail(t *testing.T) { func TestBindingFormPostForMapFail(t *testing.T) {
req := createFormPostRequestForMapFail(t) req := createFormPostRequestForMapFail(t)
var obj FooStructForMapType var obj FooStructForMapType
err := FormPost.Bind(req, &obj) err := FormPost.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func TestBindingFormFilesMultipart(t *testing.T) { func TestBindingFormFilesMultipart(t *testing.T) {
req := createFormFilesMultipartRequest(t) req := createFormFilesMultipartRequest(t)
var obj FooBarFileStruct var obj FooBarFileStruct
err := FormMultipart.Bind(req, &obj) err := FormMultipart.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
// file from os // file from os
f, _ := os.Open("form.go") f, _ := os.Open("form.go")
@ -664,9 +665,9 @@ func TestBindingFormFilesMultipart(t *testing.T) {
defer mf.Close() defer mf.Close()
fileExpect, _ := io.ReadAll(mf) fileExpect, _ := io.ReadAll(mf)
assert.Equal(t, FormMultipart.Name(), "multipart/form-data") assert.Equal(t, "multipart/form-data", FormMultipart.Name())
assert.Equal(t, obj.Foo, "bar") assert.Equal(t, "bar", obj.Foo)
assert.Equal(t, obj.Bar, "foo") assert.Equal(t, "foo", obj.Bar)
assert.Equal(t, fileExpect, fileActual) assert.Equal(t, fileExpect, fileActual)
} }
@ -674,13 +675,13 @@ func TestBindingFormFilesMultipartFail(t *testing.T) {
req := createFormFilesMultipartRequestFail(t) req := createFormFilesMultipartRequestFail(t)
var obj FooBarFileFailStruct var obj FooBarFileFailStruct
err := FormMultipart.Bind(req, &obj) err := FormMultipart.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func TestBindingFormMultipart(t *testing.T) { func TestBindingFormMultipart(t *testing.T) {
req := createFormMultipartRequest(t) req := createFormMultipartRequest(t)
var obj FooBarStruct var obj FooBarStruct
assert.NoError(t, FormMultipart.Bind(req, &obj)) require.NoError(t, FormMultipart.Bind(req, &obj))
assert.Equal(t, "multipart/form-data", FormMultipart.Name()) assert.Equal(t, "multipart/form-data", FormMultipart.Name())
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
@ -691,17 +692,17 @@ func TestBindingFormMultipartForMap(t *testing.T) {
req := createFormMultipartRequestForMap(t) req := createFormMultipartRequestForMap(t)
var obj FooStructForMapType var obj FooStructForMapType
err := FormMultipart.Bind(req, &obj) err := FormMultipart.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, float64(123), obj.MapFoo["bar"].(float64)) assert.InDelta(t, float64(123), obj.MapFoo["bar"].(float64), 0.01)
assert.Equal(t, "thinkerou", obj.MapFoo["name"].(string)) assert.Equal(t, "thinkerou", obj.MapFoo["name"].(string))
assert.Equal(t, float64(3.14), obj.MapFoo["pai"].(float64)) assert.InDelta(t, float64(3.14), obj.MapFoo["pai"].(float64), 0.01)
} }
func TestBindingFormMultipartForMapFail(t *testing.T) { func TestBindingFormMultipartForMapFail(t *testing.T) {
req := createFormMultipartRequestForMapFail(t) req := createFormMultipartRequestForMapFail(t)
var obj FooStructForMapType var obj FooStructForMapType
err := FormMultipart.Bind(req, &obj) err := FormMultipart.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func TestBindingProtoBuf(t *testing.T) { func TestBindingProtoBuf(t *testing.T) {
@ -732,7 +733,7 @@ func TestValidationFails(t *testing.T) {
var obj FooStruct var obj FooStruct
req := requestWithBody("POST", "/", `{"bar": "foo"}`) req := requestWithBody("POST", "/", `{"bar": "foo"}`)
err := JSON.Bind(req, &obj) err := JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func TestValidationDisabled(t *testing.T) { func TestValidationDisabled(t *testing.T) {
@ -743,7 +744,7 @@ func TestValidationDisabled(t *testing.T) {
var obj FooStruct var obj FooStruct
req := requestWithBody("POST", "/", `{"bar": "foo"}`) req := requestWithBody("POST", "/", `{"bar": "foo"}`)
err := JSON.Bind(req, &obj) err := JSON.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
} }
func TestRequiredSucceeds(t *testing.T) { func TestRequiredSucceeds(t *testing.T) {
@ -754,7 +755,7 @@ func TestRequiredSucceeds(t *testing.T) {
var obj HogeStruct var obj HogeStruct
req := requestWithBody("POST", "/", `{"hoge": 0}`) req := requestWithBody("POST", "/", `{"hoge": 0}`)
err := JSON.Bind(req, &obj) err := JSON.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
} }
func TestRequiredFails(t *testing.T) { func TestRequiredFails(t *testing.T) {
@ -765,7 +766,7 @@ func TestRequiredFails(t *testing.T) {
var obj HogeStruct var obj HogeStruct
req := requestWithBody("POST", "/", `{"boen": 0}`) req := requestWithBody("POST", "/", `{"boen": 0}`)
err := JSON.Bind(req, &obj) err := JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func TestHeaderBinding(t *testing.T) { func TestHeaderBinding(t *testing.T) {
@ -779,7 +780,7 @@ func TestHeaderBinding(t *testing.T) {
var theader tHeader var theader tHeader
req := requestWithBody("GET", "/", "") req := requestWithBody("GET", "/", "")
req.Header.Add("limit", "1000") req.Header.Add("limit", "1000")
assert.NoError(t, h.Bind(req, &theader)) require.NoError(t, h.Bind(req, &theader))
assert.Equal(t, 1000, theader.Limit) assert.Equal(t, 1000, theader.Limit)
req = requestWithBody("GET", "/", "") req = requestWithBody("GET", "/", "")
@ -790,7 +791,7 @@ func TestHeaderBinding(t *testing.T) {
} }
err := h.Bind(req, &failStruct{}) err := h.Bind(req, &failStruct{})
assert.Error(t, err) require.Error(t, err)
} }
func TestUriBinding(t *testing.T) { func TestUriBinding(t *testing.T) {
@ -803,14 +804,14 @@ func TestUriBinding(t *testing.T) {
var tag Tag var tag Tag
m := make(map[string][]string) m := make(map[string][]string)
m["name"] = []string{"thinkerou"} m["name"] = []string{"thinkerou"}
assert.NoError(t, b.BindUri(m, &tag)) require.NoError(t, b.BindUri(m, &tag))
assert.Equal(t, "thinkerou", tag.Name) assert.Equal(t, "thinkerou", tag.Name)
type NotSupportStruct struct { type NotSupportStruct struct {
Name map[string]any `uri:"name"` Name map[string]any `uri:"name"`
} }
var not NotSupportStruct var not NotSupportStruct
assert.Error(t, b.BindUri(m, &not)) require.Error(t, b.BindUri(m, &not))
assert.Equal(t, map[string]any(nil), not.Name) assert.Equal(t, map[string]any(nil), not.Name)
} }
@ -831,9 +832,9 @@ func TestUriInnerBinding(t *testing.T) {
} }
var tag Tag var tag Tag
assert.NoError(t, Uri.BindUri(m, &tag)) require.NoError(t, Uri.BindUri(m, &tag))
assert.Equal(t, tag.Name, expectedName) assert.Equal(t, expectedName, tag.Name)
assert.Equal(t, tag.S.Age, expectedAge) assert.Equal(t, expectedAge, tag.S.Age)
} }
func testFormBindingEmbeddedStruct(t *testing.T, method, path, badPath, body, badBody string) { func testFormBindingEmbeddedStruct(t *testing.T, method, path, badPath, body, badBody string) {
@ -846,7 +847,7 @@ func testFormBindingEmbeddedStruct(t *testing.T, method, path, badPath, body, ba
req.Header.Add("Content-Type", MIMEPOSTForm) req.Header.Add("Content-Type", MIMEPOSTForm)
} }
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 1, obj.Page) assert.Equal(t, 1, obj.Page)
assert.Equal(t, 2, obj.Size) assert.Equal(t, 2, obj.Size)
assert.Equal(t, "test-appkey", obj.Appkey) assert.Equal(t, "test-appkey", obj.Appkey)
@ -862,14 +863,14 @@ func testFormBinding(t *testing.T, method, path, badPath, body, badBody string)
req.Header.Add("Content-Type", MIMEPOSTForm) req.Header.Add("Content-Type", MIMEPOSTForm)
} }
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
assert.Equal(t, "foo", obj.Bar) assert.Equal(t, "foo", obj.Bar)
obj = FooBarStruct{} obj = FooBarStruct{}
req = requestWithBody(method, badPath, badBody) req = requestWithBody(method, badPath, badBody)
err = JSON.Bind(req, &obj) err = JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func testFormBindingDefaultValue(t *testing.T, method, path, badPath, body, badBody string) { func testFormBindingDefaultValue(t *testing.T, method, path, badPath, body, badBody string) {
@ -882,14 +883,14 @@ func testFormBindingDefaultValue(t *testing.T, method, path, badPath, body, badB
req.Header.Add("Content-Type", MIMEPOSTForm) req.Header.Add("Content-Type", MIMEPOSTForm)
} }
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
assert.Equal(t, "hello", obj.Bar) assert.Equal(t, "hello", obj.Bar)
obj = FooDefaultBarStruct{} obj = FooDefaultBarStruct{}
req = requestWithBody(method, badPath, badBody) req = requestWithBody(method, badPath, badBody)
err = JSON.Bind(req, &obj) err = JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func TestFormBindingFail(t *testing.T) { func TestFormBindingFail(t *testing.T) {
@ -899,18 +900,18 @@ func TestFormBindingFail(t *testing.T) {
obj := FooBarStruct{} obj := FooBarStruct{}
req, _ := http.NewRequest("POST", "/", nil) req, _ := http.NewRequest("POST", "/", nil)
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func TestFormBindingMultipartFail(t *testing.T) { func TestFormBindingMultipartFail(t *testing.T) {
obj := FooBarStruct{} obj := FooBarStruct{}
req, err := http.NewRequest("POST", "/", strings.NewReader("foo=bar")) req, err := http.NewRequest("POST", "/", strings.NewReader("foo=bar"))
assert.NoError(t, err) require.NoError(t, err)
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+";boundary=testboundary") req.Header.Set("Content-Type", MIMEMultipartPOSTForm+";boundary=testboundary")
_, err = req.MultipartReader() _, err = req.MultipartReader()
assert.NoError(t, err) require.NoError(t, err)
err = Form.Bind(req, &obj) err = Form.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func TestFormPostBindingFail(t *testing.T) { func TestFormPostBindingFail(t *testing.T) {
@ -920,7 +921,7 @@ func TestFormPostBindingFail(t *testing.T) {
obj := FooBarStruct{} obj := FooBarStruct{}
req, _ := http.NewRequest("POST", "/", nil) req, _ := http.NewRequest("POST", "/", nil)
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func TestFormMultipartBindingFail(t *testing.T) { func TestFormMultipartBindingFail(t *testing.T) {
@ -930,7 +931,7 @@ func TestFormMultipartBindingFail(t *testing.T) {
obj := FooBarStruct{} obj := FooBarStruct{}
req, _ := http.NewRequest("POST", "/", nil) req, _ := http.NewRequest("POST", "/", nil)
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody string) { func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody string) {
@ -944,7 +945,7 @@ func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody s
} }
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, int64(1510675200), obj.TimeFoo.Unix()) assert.Equal(t, int64(1510675200), obj.TimeFoo.Unix())
assert.Equal(t, "Asia/Chongqing", obj.TimeFoo.Location().String()) assert.Equal(t, "Asia/Chongqing", obj.TimeFoo.Location().String())
assert.Equal(t, int64(-62135596800), obj.TimeBar.Unix()) assert.Equal(t, int64(-62135596800), obj.TimeBar.Unix())
@ -955,7 +956,7 @@ func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody s
obj = FooBarStructForTimeType{} obj = FooBarStructForTimeType{}
req = requestWithBody(method, badPath, badBody) req = requestWithBody(method, badPath, badBody)
err = JSON.Bind(req, &obj) err = JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func testFormBindingForTimeNotUnixFormat(t *testing.T, method, path, badPath, body, badBody string) { func testFormBindingForTimeNotUnixFormat(t *testing.T, method, path, badPath, body, badBody string) {
@ -968,12 +969,12 @@ func testFormBindingForTimeNotUnixFormat(t *testing.T, method, path, badPath, bo
req.Header.Add("Content-Type", MIMEPOSTForm) req.Header.Add("Content-Type", MIMEPOSTForm)
} }
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
obj = FooStructForTimeTypeNotUnixFormat{} obj = FooStructForTimeTypeNotUnixFormat{}
req = requestWithBody(method, badPath, badBody) req = requestWithBody(method, badPath, badBody)
err = JSON.Bind(req, &obj) err = JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func testFormBindingForTimeNotFormat(t *testing.T, method, path, badPath, body, badBody string) { func testFormBindingForTimeNotFormat(t *testing.T, method, path, badPath, body, badBody string) {
@ -986,12 +987,12 @@ func testFormBindingForTimeNotFormat(t *testing.T, method, path, badPath, body,
req.Header.Add("Content-Type", MIMEPOSTForm) req.Header.Add("Content-Type", MIMEPOSTForm)
} }
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
obj = FooStructForTimeTypeNotFormat{} obj = FooStructForTimeTypeNotFormat{}
req = requestWithBody(method, badPath, badBody) req = requestWithBody(method, badPath, badBody)
err = JSON.Bind(req, &obj) err = JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func testFormBindingForTimeFailFormat(t *testing.T, method, path, badPath, body, badBody string) { func testFormBindingForTimeFailFormat(t *testing.T, method, path, badPath, body, badBody string) {
@ -1004,12 +1005,12 @@ func testFormBindingForTimeFailFormat(t *testing.T, method, path, badPath, body,
req.Header.Add("Content-Type", MIMEPOSTForm) req.Header.Add("Content-Type", MIMEPOSTForm)
} }
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
obj = FooStructForTimeTypeFailFormat{} obj = FooStructForTimeTypeFailFormat{}
req = requestWithBody(method, badPath, badBody) req = requestWithBody(method, badPath, badBody)
err = JSON.Bind(req, &obj) err = JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func testFormBindingForTimeFailLocation(t *testing.T, method, path, badPath, body, badBody string) { func testFormBindingForTimeFailLocation(t *testing.T, method, path, badPath, body, badBody string) {
@ -1022,12 +1023,12 @@ func testFormBindingForTimeFailLocation(t *testing.T, method, path, badPath, bod
req.Header.Add("Content-Type", MIMEPOSTForm) req.Header.Add("Content-Type", MIMEPOSTForm)
} }
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
obj = FooStructForTimeTypeFailLocation{} obj = FooStructForTimeTypeFailLocation{}
req = requestWithBody(method, badPath, badBody) req = requestWithBody(method, badPath, badBody)
err = JSON.Bind(req, &obj) err = JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func testFormBindingIgnoreField(t *testing.T, method, path, badPath, body, badBody string) { func testFormBindingIgnoreField(t *testing.T, method, path, badPath, body, badBody string) {
@ -1040,7 +1041,7 @@ func testFormBindingIgnoreField(t *testing.T, method, path, badPath, body, badBo
req.Header.Add("Content-Type", MIMEPOSTForm) req.Header.Add("Content-Type", MIMEPOSTForm)
} }
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Nil(t, obj.Foo) assert.Nil(t, obj.Foo)
} }
@ -1055,13 +1056,13 @@ func testFormBindingInvalidName(t *testing.T, method, path, badPath, body, badBo
req.Header.Add("Content-Type", MIMEPOSTForm) req.Header.Add("Content-Type", MIMEPOSTForm)
} }
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "", obj.TestName) assert.Equal(t, "", obj.TestName)
obj = InvalidNameType{} obj = InvalidNameType{}
req = requestWithBody(method, badPath, badBody) req = requestWithBody(method, badPath, badBody)
err = JSON.Bind(req, &obj) err = JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func testFormBindingInvalidName2(t *testing.T, method, path, badPath, body, badBody string) { func testFormBindingInvalidName2(t *testing.T, method, path, badPath, body, badBody string) {
@ -1074,12 +1075,12 @@ func testFormBindingInvalidName2(t *testing.T, method, path, badPath, body, badB
req.Header.Add("Content-Type", MIMEPOSTForm) req.Header.Add("Content-Type", MIMEPOSTForm)
} }
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
obj = InvalidNameMapType{} obj = InvalidNameMapType{}
req = requestWithBody(method, badPath, badBody) req = requestWithBody(method, badPath, badBody)
err = JSON.Bind(req, &obj) err = JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func testFormBindingForType(t *testing.T, method, path, badPath, body, badBody string, typ string) { func testFormBindingForType(t *testing.T, method, path, badPath, body, badBody string, typ string) {
@ -1094,17 +1095,17 @@ func testFormBindingForType(t *testing.T, method, path, badPath, body, badBody s
case "Slice": case "Slice":
obj := FooStructForSliceType{} obj := FooStructForSliceType{}
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, []int{1, 2}, obj.SliceFoo) assert.Equal(t, []int{1, 2}, obj.SliceFoo)
obj = FooStructForSliceType{} obj = FooStructForSliceType{}
req = requestWithBody(method, badPath, badBody) req = requestWithBody(method, badPath, badBody)
err = JSON.Bind(req, &obj) err = JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
case "Struct": case "Struct":
obj := FooStructForStructType{} obj := FooStructForStructType{}
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, assert.Equal(t,
struct { struct {
Idx int "form:\"idx\"" Idx int "form:\"idx\""
@ -1113,7 +1114,7 @@ func testFormBindingForType(t *testing.T, method, path, badPath, body, badBody s
case "StructPointer": case "StructPointer":
obj := FooStructForStructPointerType{} obj := FooStructForStructPointerType{}
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, assert.Equal(t,
struct { struct {
Name string "form:\"name\"" Name string "form:\"name\""
@ -1122,33 +1123,33 @@ func testFormBindingForType(t *testing.T, method, path, badPath, body, badBody s
case "Map": case "Map":
obj := FooStructForMapType{} obj := FooStructForMapType{}
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, float64(123), obj.MapFoo["bar"].(float64)) assert.InDelta(t, float64(123), obj.MapFoo["bar"].(float64), 0.01)
case "SliceMap": case "SliceMap":
obj := FooStructForSliceMapType{} obj := FooStructForSliceMapType{}
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
case "Ptr": case "Ptr":
obj := FooStructForStringPtrType{} obj := FooStructForStringPtrType{}
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Nil(t, obj.PtrFoo) assert.Nil(t, obj.PtrFoo)
assert.Equal(t, "test", *obj.PtrBar) assert.Equal(t, "test", *obj.PtrBar)
obj = FooStructForStringPtrType{} obj = FooStructForStringPtrType{}
obj.PtrBar = new(string) obj.PtrBar = new(string)
err = b.Bind(req, &obj) err = b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "test", *obj.PtrBar) assert.Equal(t, "test", *obj.PtrBar)
objErr := FooStructForMapPtrType{} objErr := FooStructForMapPtrType{}
err = b.Bind(req, &objErr) err = b.Bind(req, &objErr)
assert.Error(t, err) require.Error(t, err)
obj = FooStructForStringPtrType{} obj = FooStructForStringPtrType{}
req = requestWithBody(method, badPath, badBody) req = requestWithBody(method, badPath, badBody)
err = b.Bind(req, &obj) err = b.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
} }
@ -1162,7 +1163,7 @@ func testQueryBinding(t *testing.T, method, path, badPath, body, badBody string)
req.Header.Add("Content-Type", MIMEPOSTForm) req.Header.Add("Content-Type", MIMEPOSTForm)
} }
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
assert.Equal(t, "foo", obj.Bar) assert.Equal(t, "foo", obj.Bar)
} }
@ -1177,7 +1178,7 @@ func testQueryBindingFail(t *testing.T, method, path, badPath, body, badBody str
req.Header.Add("Content-Type", MIMEPOSTForm) req.Header.Add("Content-Type", MIMEPOSTForm)
} }
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func testQueryBindingBoolFail(t *testing.T, method, path, badPath, body, badBody string) { func testQueryBindingBoolFail(t *testing.T, method, path, badPath, body, badBody string) {
@ -1190,7 +1191,7 @@ func testQueryBindingBoolFail(t *testing.T, method, path, badPath, body, badBody
req.Header.Add("Content-Type", MIMEPOSTForm) req.Header.Add("Content-Type", MIMEPOSTForm)
} }
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) { func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
@ -1199,13 +1200,13 @@ func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody
obj := FooStruct{} obj := FooStruct{}
req := requestWithBody("POST", path, body) req := requestWithBody("POST", path, body)
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
obj = FooStruct{} obj = FooStruct{}
req = requestWithBody("POST", badPath, badBody) req = requestWithBody("POST", badPath, badBody)
err = JSON.Bind(req, &obj) err = JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func testBodyBindingSlice(t *testing.T, b Binding, name, path, badPath, body, badBody string) { func testBodyBindingSlice(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
@ -1214,12 +1215,12 @@ func testBodyBindingSlice(t *testing.T, b Binding, name, path, badPath, body, ba
var obj1 []FooStruct var obj1 []FooStruct
req := requestWithBody("POST", path, body) req := requestWithBody("POST", path, body)
err := b.Bind(req, &obj1) err := b.Bind(req, &obj1)
assert.NoError(t, err) require.NoError(t, err)
var obj2 []FooStruct var obj2 []FooStruct
req = requestWithBody("POST", badPath, badBody) req = requestWithBody("POST", badPath, badBody)
err = JSON.Bind(req, &obj2) err = JSON.Bind(req, &obj2)
assert.Error(t, err) require.Error(t, err)
} }
func testBodyBindingStringMap(t *testing.T, b Binding, path, badPath, body, badBody string) { func testBodyBindingStringMap(t *testing.T, b Binding, path, badPath, body, badBody string) {
@ -1229,7 +1230,7 @@ func testBodyBindingStringMap(t *testing.T, b Binding, path, badPath, body, badB
req.Header.Add("Content-Type", MIMEPOSTForm) req.Header.Add("Content-Type", MIMEPOSTForm)
} }
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.NotNil(t, obj) assert.NotNil(t, obj)
assert.Len(t, obj, 2) assert.Len(t, obj, 2)
assert.Equal(t, "bar", obj["foo"]) assert.Equal(t, "bar", obj["foo"])
@ -1239,13 +1240,13 @@ func testBodyBindingStringMap(t *testing.T, b Binding, path, badPath, body, badB
obj = make(map[string]string) obj = make(map[string]string)
req = requestWithBody("POST", badPath, badBody) req = requestWithBody("POST", badPath, badBody)
err = b.Bind(req, &obj) err = b.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
objInt := make(map[string]int) objInt := make(map[string]int)
req = requestWithBody("POST", path, body) req = requestWithBody("POST", path, body)
err = b.Bind(req, &objInt) err = b.Bind(req, &objInt)
assert.Error(t, err) require.Error(t, err)
} }
func testBodyBindingUseNumber(t *testing.T, b Binding, name, path, badPath, body, badBody string) { func testBodyBindingUseNumber(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
@ -1255,16 +1256,16 @@ func testBodyBindingUseNumber(t *testing.T, b Binding, name, path, badPath, body
req := requestWithBody("POST", path, body) req := requestWithBody("POST", path, body)
EnableDecoderUseNumber = true EnableDecoderUseNumber = true
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
// we hope it is int64(123) // we hope it is int64(123)
v, e := obj.Foo.(json.Number).Int64() v, e := obj.Foo.(json.Number).Int64()
assert.NoError(t, e) require.NoError(t, e)
assert.Equal(t, int64(123), v) assert.Equal(t, int64(123), v)
obj = FooStructUseNumber{} obj = FooStructUseNumber{}
req = requestWithBody("POST", badPath, badBody) req = requestWithBody("POST", badPath, badBody)
err = JSON.Bind(req, &obj) err = JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func testBodyBindingUseNumber2(t *testing.T, b Binding, name, path, badPath, body, badBody string) { func testBodyBindingUseNumber2(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
@ -1274,15 +1275,15 @@ func testBodyBindingUseNumber2(t *testing.T, b Binding, name, path, badPath, bod
req := requestWithBody("POST", path, body) req := requestWithBody("POST", path, body)
EnableDecoderUseNumber = false EnableDecoderUseNumber = false
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
// it will return float64(123) if not use EnableDecoderUseNumber // it will return float64(123) if not use EnableDecoderUseNumber
// maybe it is not hoped // maybe it is not hoped
assert.Equal(t, float64(123), obj.Foo) assert.InDelta(t, float64(123), obj.Foo, 0.01)
obj = FooStructUseNumber{} obj = FooStructUseNumber{}
req = requestWithBody("POST", badPath, badBody) req = requestWithBody("POST", badPath, badBody)
err = JSON.Bind(req, &obj) err = JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func testBodyBindingDisallowUnknownFields(t *testing.T, b Binding, path, badPath, body, badBody string) { func testBodyBindingDisallowUnknownFields(t *testing.T, b Binding, path, badPath, body, badBody string) {
@ -1294,13 +1295,13 @@ func testBodyBindingDisallowUnknownFields(t *testing.T, b Binding, path, badPath
obj := FooStructDisallowUnknownFields{} obj := FooStructDisallowUnknownFields{}
req := requestWithBody("POST", path, body) req := requestWithBody("POST", path, body)
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
obj = FooStructDisallowUnknownFields{} obj = FooStructDisallowUnknownFields{}
req = requestWithBody("POST", badPath, badBody) req = requestWithBody("POST", badPath, badBody)
err = JSON.Bind(req, &obj) err = JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
assert.Contains(t, err.Error(), "what") assert.Contains(t, err.Error(), "what")
} }
@ -1310,13 +1311,13 @@ func testBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body, bad
obj := FooStruct{} obj := FooStruct{}
req := requestWithBody("POST", path, body) req := requestWithBody("POST", path, body)
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
assert.Equal(t, "", obj.Foo) assert.Equal(t, "", obj.Foo)
obj = FooStruct{} obj = FooStruct{}
req = requestWithBody("POST", badPath, badBody) req = requestWithBody("POST", badPath, badBody)
err = JSON.Bind(req, &obj) err = JSON.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func testProtoBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) { func testProtoBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
@ -1326,14 +1327,14 @@ func testProtoBodyBinding(t *testing.T, b Binding, name, path, badPath, body, ba
req := requestWithBody("POST", path, body) req := requestWithBody("POST", path, body)
req.Header.Add("Content-Type", MIMEPROTOBUF) req.Header.Add("Content-Type", MIMEPROTOBUF)
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "yes", *obj.Label) assert.Equal(t, "yes", *obj.Label)
obj = protoexample.Test{} obj = protoexample.Test{}
req = requestWithBody("POST", badPath, badBody) req = requestWithBody("POST", badPath, badBody)
req.Header.Add("Content-Type", MIMEPROTOBUF) req.Header.Add("Content-Type", MIMEPROTOBUF)
err = ProtoBuf.Bind(req, &obj) err = ProtoBuf.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
type hook struct{} type hook struct{}
@ -1358,28 +1359,28 @@ func TestPlainBinding(t *testing.T) {
var s string var s string
req := requestWithBody("POST", "/", "test string") req := requestWithBody("POST", "/", "test string")
assert.NoError(t, p.Bind(req, &s)) require.NoError(t, p.Bind(req, &s))
assert.Equal(t, s, "test string") assert.Equal(t, "test string", s)
var bs []byte var bs []byte
req = requestWithBody("POST", "/", "test []byte") req = requestWithBody("POST", "/", "test []byte")
assert.NoError(t, p.Bind(req, &bs)) require.NoError(t, p.Bind(req, &bs))
assert.Equal(t, bs, []byte("test []byte")) assert.Equal(t, bs, []byte("test []byte"))
var i int var i int
req = requestWithBody("POST", "/", "test fail") req = requestWithBody("POST", "/", "test fail")
assert.Error(t, p.Bind(req, &i)) require.Error(t, p.Bind(req, &i))
req = requestWithBody("POST", "/", "") req = requestWithBody("POST", "/", "")
req.Body = &failRead{} req.Body = &failRead{}
assert.Error(t, p.Bind(req, &s)) require.Error(t, p.Bind(req, &s))
req = requestWithBody("POST", "/", "") req = requestWithBody("POST", "/", "")
assert.Nil(t, p.Bind(req, nil)) require.NoError(t, p.Bind(req, nil))
var ptr *string var ptr *string
req = requestWithBody("POST", "/", "") req = requestWithBody("POST", "/", "")
assert.Nil(t, p.Bind(req, ptr)) require.NoError(t, p.Bind(req, ptr))
} }
func testProtoBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body, badBody string) { func testProtoBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
@ -1391,20 +1392,20 @@ func testProtoBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body
req.Body = io.NopCloser(&hook{}) req.Body = io.NopCloser(&hook{})
req.Header.Add("Content-Type", MIMEPROTOBUF) req.Header.Add("Content-Type", MIMEPROTOBUF)
err := b.Bind(req, &obj) err := b.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
invalidobj := FooStruct{} invalidobj := FooStruct{}
req.Body = io.NopCloser(strings.NewReader(`{"msg":"hello"}`)) req.Body = io.NopCloser(strings.NewReader(`{"msg":"hello"}`))
req.Header.Add("Content-Type", MIMEPROTOBUF) req.Header.Add("Content-Type", MIMEPROTOBUF)
err = b.Bind(req, &invalidobj) err = b.Bind(req, &invalidobj)
assert.Error(t, err) require.Error(t, err)
assert.Equal(t, err.Error(), "obj is not ProtoMessage") assert.Equal(t, "obj is not ProtoMessage", err.Error())
obj = protoexample.Test{} obj = protoexample.Test{}
req = requestWithBody("POST", badPath, badBody) req = requestWithBody("POST", badPath, badBody)
req.Header.Add("Content-Type", MIMEPROTOBUF) req.Header.Add("Content-Type", MIMEPROTOBUF)
err = ProtoBuf.Bind(req, &obj) err = ProtoBuf.Bind(req, &obj)
assert.Error(t, err) require.Error(t, err)
} }
func requestWithBody(method, path, body string) (req *http.Request) { func requestWithBody(method, path, body string) (req *http.Request) {

View File

@ -159,6 +159,14 @@ func tryToSetValue(value reflect.Value, field reflect.StructField, setter setter
if k, v := head(opt, "="); k == "default" { if k, v := head(opt, "="); k == "default" {
setOpt.isDefaultExists = true setOpt.isDefaultExists = true
setOpt.defaultValue = v setOpt.defaultValue = v
// convert semicolon-separated default values to csv-separated values for processing in setByForm
if field.Type.Kind() == reflect.Slice || field.Type.Kind() == reflect.Array {
cfTag := field.Tag.Get("collection_format")
if cfTag == "" || cfTag == "multi" || cfTag == "csv" {
setOpt.defaultValue = strings.ReplaceAll(v, ";", ",")
}
}
} }
} }
@ -182,6 +190,38 @@ func trySetCustom(val string, value reflect.Value) (isSet bool, err error) {
return false, nil return false, nil
} }
func trySplit(vs []string, field reflect.StructField) (newVs []string, err error) {
cfTag := field.Tag.Get("collection_format")
if cfTag == "" || cfTag == "multi" {
return vs, nil
}
var sep string
switch cfTag {
case "csv":
sep = ","
case "ssv":
sep = " "
case "tsv":
sep = "\t"
case "pipes":
sep = "|"
default:
return vs, fmt.Errorf("%s is not supported in the collection_format. (csv, ssv, pipes)", cfTag)
}
totalLength := 0
for _, v := range vs {
totalLength += strings.Count(v, sep) + 1
}
newVs = make([]string, 0, totalLength)
for _, v := range vs {
newVs = append(newVs, strings.Split(v, sep)...)
}
return newVs, nil
}
func setByForm(value reflect.Value, field reflect.StructField, form map[string][]string, tagValue string, opt setOptions) (isSet bool, err error) { func setByForm(value reflect.Value, field reflect.StructField, form map[string][]string, tagValue string, opt setOptions) (isSet bool, err error) {
vs, ok := form[tagValue] vs, ok := form[tagValue]
if !ok && !opt.isDefaultExists { if !ok && !opt.isDefaultExists {
@ -192,22 +232,42 @@ func setByForm(value reflect.Value, field reflect.StructField, form map[string][
case reflect.Slice: case reflect.Slice:
if !ok { if !ok {
vs = []string{opt.defaultValue} vs = []string{opt.defaultValue}
// pre-process the default value for multi if present
cfTag := field.Tag.Get("collection_format")
if cfTag == "" || cfTag == "multi" {
vs = strings.Split(opt.defaultValue, ",")
}
} }
if ok, err = trySetCustom(vs[0], value); ok { if ok, err = trySetCustom(vs[0], value); ok {
return ok, err return ok, err
} }
if vs, err = trySplit(vs, field); err != nil {
return false, err
}
return true, setSlice(vs, value, field) return true, setSlice(vs, value, field)
case reflect.Array: case reflect.Array:
if !ok { if !ok {
vs = []string{opt.defaultValue} vs = []string{opt.defaultValue}
// pre-process the default value for multi if present
cfTag := field.Tag.Get("collection_format")
if cfTag == "" || cfTag == "multi" {
vs = strings.Split(opt.defaultValue, ",")
}
} }
if ok, err = trySetCustom(vs[0], value); ok { if ok, err = trySetCustom(vs[0], value); ok {
return ok, err return ok, err
} }
if vs, err = trySplit(vs, field); err != nil {
return false, err
}
if len(vs) != value.Len() { if len(vs) != value.Len() {
return false, fmt.Errorf("%q is not valid value for %s", vs, value.Type().String()) return false, fmt.Errorf("%q is not valid value for %s", vs, value.Type().String())
} }
@ -221,6 +281,9 @@ func setByForm(value reflect.Value, field reflect.StructField, form map[string][
if len(vs) > 0 { if len(vs) > 0 {
val = vs[0] val = vs[0]
if val == "" {
val = opt.defaultValue
}
} }
if ok, err := trySetCustom(val, value); ok { if ok, err := trySetCustom(val, value); ok {
return ok, err return ok, err

View File

@ -15,6 +15,7 @@ import (
"time" "time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestMappingBaseTypes(t *testing.T) { func TestMappingBaseTypes(t *testing.T) {
@ -59,7 +60,7 @@ func TestMappingBaseTypes(t *testing.T) {
field := val.Elem().Type().Field(0) field := val.Elem().Type().Field(0)
_, err := mapping(val, emptyField, formSource{field.Name: {tt.form}}, "form") _, err := mapping(val, emptyField, formSource{field.Name: {tt.form}}, "form")
assert.NoError(t, err, testName) require.NoError(t, err, testName)
actual := val.Elem().Field(0).Interface() actual := val.Elem().Field(0).Interface()
assert.Equal(t, tt.expect, actual, testName) assert.Equal(t, tt.expect, actual, testName)
@ -68,13 +69,15 @@ func TestMappingBaseTypes(t *testing.T) {
func TestMappingDefault(t *testing.T) { func TestMappingDefault(t *testing.T) {
var s struct { var s struct {
Str string `form:",default=defaultVal"`
Int int `form:",default=9"` Int int `form:",default=9"`
Slice []int `form:",default=9"` Slice []int `form:",default=9"`
Array [1]int `form:",default=9"` Array [1]int `form:",default=9"`
} }
err := mappingByPtr(&s, formSource{}, "form") err := mappingByPtr(&s, formSource{}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "defaultVal", s.Str)
assert.Equal(t, 9, s.Int) assert.Equal(t, 9, s.Int)
assert.Equal(t, []int{9}, s.Slice) assert.Equal(t, []int{9}, s.Slice)
assert.Equal(t, [1]int{9}, s.Array) assert.Equal(t, [1]int{9}, s.Array)
@ -85,7 +88,7 @@ func TestMappingSkipField(t *testing.T) {
A int A int
} }
err := mappingByPtr(&s, formSource{}, "form") err := mappingByPtr(&s, formSource{}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 0, s.A) assert.Equal(t, 0, s.A)
} }
@ -96,7 +99,7 @@ func TestMappingIgnoreField(t *testing.T) {
B int `form:"-"` B int `form:"-"`
} }
err := mappingByPtr(&s, formSource{"A": {"9"}, "B": {"9"}}, "form") err := mappingByPtr(&s, formSource{"A": {"9"}, "B": {"9"}}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 9, s.A) assert.Equal(t, 9, s.A)
assert.Equal(t, 0, s.B) assert.Equal(t, 0, s.B)
@ -108,7 +111,7 @@ func TestMappingUnexportedField(t *testing.T) {
b int `form:"b"` b int `form:"b"`
} }
err := mappingByPtr(&s, formSource{"a": {"9"}, "b": {"9"}}, "form") err := mappingByPtr(&s, formSource{"a": {"9"}, "b": {"9"}}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 9, s.A) assert.Equal(t, 9, s.A)
assert.Equal(t, 0, s.b) assert.Equal(t, 0, s.b)
@ -119,7 +122,7 @@ func TestMappingPrivateField(t *testing.T) {
f int `form:"field"` f int `form:"field"`
} }
err := mappingByPtr(&s, formSource{"field": {"6"}}, "form") err := mappingByPtr(&s, formSource{"field": {"6"}}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 0, s.f) assert.Equal(t, 0, s.f)
} }
@ -129,7 +132,7 @@ func TestMappingUnknownFieldType(t *testing.T) {
} }
err := mappingByPtr(&s, formSource{"U": {"unknown"}}, "form") err := mappingByPtr(&s, formSource{"U": {"unknown"}}, "form")
assert.Error(t, err) require.Error(t, err)
assert.Equal(t, errUnknownType, err) assert.Equal(t, errUnknownType, err)
} }
@ -138,7 +141,7 @@ func TestMappingURI(t *testing.T) {
F int `uri:"field"` F int `uri:"field"`
} }
err := mapURI(&s, map[string][]string{"field": {"6"}}) err := mapURI(&s, map[string][]string{"field": {"6"}})
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 6, s.F) assert.Equal(t, 6, s.F)
} }
@ -147,16 +150,34 @@ func TestMappingForm(t *testing.T) {
F int `form:"field"` F int `form:"field"`
} }
err := mapForm(&s, map[string][]string{"field": {"6"}}) err := mapForm(&s, map[string][]string{"field": {"6"}})
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 6, s.F) assert.Equal(t, 6, s.F)
} }
func TestMappingFormFieldNotSent(t *testing.T) {
var s struct {
F string `form:"field,default=defVal"`
}
err := mapForm(&s, map[string][]string{})
require.NoError(t, err)
assert.Equal(t, "defVal", s.F)
}
func TestMappingFormWithEmptyToDefault(t *testing.T) {
var s struct {
F string `form:"field,default=DefVal"`
}
err := mapForm(&s, map[string][]string{"field": {""}})
require.NoError(t, err)
assert.Equal(t, "DefVal", s.F)
}
func TestMapFormWithTag(t *testing.T) { func TestMapFormWithTag(t *testing.T) {
var s struct { var s struct {
F int `externalTag:"field"` F int `externalTag:"field"`
} }
err := MapFormWithTag(&s, map[string][]string{"field": {"6"}}, "externalTag") err := MapFormWithTag(&s, map[string][]string{"field": {"6"}}, "externalTag")
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 6, s.F) assert.Equal(t, 6, s.F)
} }
@ -171,7 +192,7 @@ func TestMappingTime(t *testing.T) {
var err error var err error
time.Local, err = time.LoadLocation("Europe/Berlin") time.Local, err = time.LoadLocation("Europe/Berlin")
assert.NoError(t, err) require.NoError(t, err)
err = mapForm(&s, map[string][]string{ err = mapForm(&s, map[string][]string{
"Time": {"2019-01-20T16:02:58Z"}, "Time": {"2019-01-20T16:02:58Z"},
@ -180,7 +201,7 @@ func TestMappingTime(t *testing.T) {
"CSTTime": {"2019-01-20"}, "CSTTime": {"2019-01-20"},
"UTCTime": {"2019-01-20"}, "UTCTime": {"2019-01-20"},
}) })
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "2019-01-20 16:02:58 +0000 UTC", s.Time.String()) assert.Equal(t, "2019-01-20 16:02:58 +0000 UTC", s.Time.String())
assert.Equal(t, "2019-01-20 00:00:00 +0100 CET", s.LocalTime.String()) assert.Equal(t, "2019-01-20 00:00:00 +0100 CET", s.LocalTime.String())
@ -195,14 +216,14 @@ func TestMappingTime(t *testing.T) {
Time time.Time `time_location:"wrong"` Time time.Time `time_location:"wrong"`
} }
err = mapForm(&wrongLoc, map[string][]string{"Time": {"2019-01-20T16:02:58Z"}}) err = mapForm(&wrongLoc, map[string][]string{"Time": {"2019-01-20T16:02:58Z"}})
assert.Error(t, err) require.Error(t, err)
// wrong time value // wrong time value
var wrongTime struct { var wrongTime struct {
Time time.Time Time time.Time
} }
err = mapForm(&wrongTime, map[string][]string{"Time": {"wrong"}}) err = mapForm(&wrongTime, map[string][]string{"Time": {"wrong"}})
assert.Error(t, err) require.Error(t, err)
} }
func TestMappingTimeDuration(t *testing.T) { func TestMappingTimeDuration(t *testing.T) {
@ -212,12 +233,12 @@ func TestMappingTimeDuration(t *testing.T) {
// ok // ok
err := mappingByPtr(&s, formSource{"D": {"5s"}}, "form") err := mappingByPtr(&s, formSource{"D": {"5s"}}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 5*time.Second, s.D) assert.Equal(t, 5*time.Second, s.D)
// error // error
err = mappingByPtr(&s, formSource{"D": {"wrong"}}, "form") err = mappingByPtr(&s, formSource{"D": {"wrong"}}, "form")
assert.Error(t, err) require.Error(t, err)
} }
func TestMappingSlice(t *testing.T) { func TestMappingSlice(t *testing.T) {
@ -227,17 +248,17 @@ func TestMappingSlice(t *testing.T) {
// default value // default value
err := mappingByPtr(&s, formSource{}, "form") err := mappingByPtr(&s, formSource{}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, []int{9}, s.Slice) assert.Equal(t, []int{9}, s.Slice)
// ok // ok
err = mappingByPtr(&s, formSource{"slice": {"3", "4"}}, "form") err = mappingByPtr(&s, formSource{"slice": {"3", "4"}}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, []int{3, 4}, s.Slice) assert.Equal(t, []int{3, 4}, s.Slice)
// error // error
err = mappingByPtr(&s, formSource{"slice": {"wrong"}}, "form") err = mappingByPtr(&s, formSource{"slice": {"wrong"}}, "form")
assert.Error(t, err) require.Error(t, err)
} }
func TestMappingArray(t *testing.T) { func TestMappingArray(t *testing.T) {
@ -247,20 +268,125 @@ func TestMappingArray(t *testing.T) {
// wrong default // wrong default
err := mappingByPtr(&s, formSource{}, "form") err := mappingByPtr(&s, formSource{}, "form")
assert.Error(t, err) require.Error(t, err)
// ok // ok
err = mappingByPtr(&s, formSource{"array": {"3", "4"}}, "form") err = mappingByPtr(&s, formSource{"array": {"3", "4"}}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, [2]int{3, 4}, s.Array) assert.Equal(t, [2]int{3, 4}, s.Array)
// error - not enough vals // error - not enough vals
err = mappingByPtr(&s, formSource{"array": {"3"}}, "form") err = mappingByPtr(&s, formSource{"array": {"3"}}, "form")
assert.Error(t, err) require.Error(t, err)
// error - wrong value // error - wrong value
err = mappingByPtr(&s, formSource{"array": {"wrong"}}, "form") err = mappingByPtr(&s, formSource{"array": {"wrong"}}, "form")
assert.Error(t, err) require.Error(t, err)
}
func TestMappingCollectionFormat(t *testing.T) {
var s struct {
SliceMulti []int `form:"slice_multi" collection_format:"multi"`
SliceCsv []int `form:"slice_csv" collection_format:"csv"`
SliceSsv []int `form:"slice_ssv" collection_format:"ssv"`
SliceTsv []int `form:"slice_tsv" collection_format:"tsv"`
SlicePipes []int `form:"slice_pipes" collection_format:"pipes"`
ArrayMulti [2]int `form:"array_multi" collection_format:"multi"`
ArrayCsv [2]int `form:"array_csv" collection_format:"csv"`
ArraySsv [2]int `form:"array_ssv" collection_format:"ssv"`
ArrayTsv [2]int `form:"array_tsv" collection_format:"tsv"`
ArrayPipes [2]int `form:"array_pipes" collection_format:"pipes"`
}
err := mappingByPtr(&s, formSource{
"slice_multi": {"1", "2"},
"slice_csv": {"1,2"},
"slice_ssv": {"1 2"},
"slice_tsv": {"1 2"},
"slice_pipes": {"1|2"},
"array_multi": {"1", "2"},
"array_csv": {"1,2"},
"array_ssv": {"1 2"},
"array_tsv": {"1 2"},
"array_pipes": {"1|2"},
}, "form")
require.NoError(t, err)
assert.Equal(t, []int{1, 2}, s.SliceMulti)
assert.Equal(t, []int{1, 2}, s.SliceCsv)
assert.Equal(t, []int{1, 2}, s.SliceSsv)
assert.Equal(t, []int{1, 2}, s.SliceTsv)
assert.Equal(t, []int{1, 2}, s.SlicePipes)
assert.Equal(t, [2]int{1, 2}, s.ArrayMulti)
assert.Equal(t, [2]int{1, 2}, s.ArrayCsv)
assert.Equal(t, [2]int{1, 2}, s.ArraySsv)
assert.Equal(t, [2]int{1, 2}, s.ArrayTsv)
assert.Equal(t, [2]int{1, 2}, s.ArrayPipes)
}
func TestMappingCollectionFormatInvalid(t *testing.T) {
var s struct {
SliceCsv []int `form:"slice_csv" collection_format:"xxx"`
}
err := mappingByPtr(&s, formSource{
"slice_csv": {"1,2"},
}, "form")
require.Error(t, err)
var s2 struct {
ArrayCsv [2]int `form:"array_csv" collection_format:"xxx"`
}
err = mappingByPtr(&s2, formSource{
"array_csv": {"1,2"},
}, "form")
require.Error(t, err)
}
func TestMappingMultipleDefaultWithCollectionFormat(t *testing.T) {
var s struct {
SliceMulti []int `form:",default=1;2;3" collection_format:"multi"`
SliceCsv []int `form:",default=1;2;3" collection_format:"csv"`
SliceSsv []int `form:",default=1 2 3" collection_format:"ssv"`
SliceTsv []int `form:",default=1\t2\t3" collection_format:"tsv"`
SlicePipes []int `form:",default=1|2|3" collection_format:"pipes"`
ArrayMulti [2]int `form:",default=1;2" collection_format:"multi"`
ArrayCsv [2]int `form:",default=1;2" collection_format:"csv"`
ArraySsv [2]int `form:",default=1 2" collection_format:"ssv"`
ArrayTsv [2]int `form:",default=1\t2" collection_format:"tsv"`
ArrayPipes [2]int `form:",default=1|2" collection_format:"pipes"`
SliceStringMulti []string `form:",default=1;2;3" collection_format:"multi"`
SliceStringCsv []string `form:",default=1;2;3" collection_format:"csv"`
SliceStringSsv []string `form:",default=1 2 3" collection_format:"ssv"`
SliceStringTsv []string `form:",default=1\t2\t3" collection_format:"tsv"`
SliceStringPipes []string `form:",default=1|2|3" collection_format:"pipes"`
ArrayStringMulti [2]string `form:",default=1;2" collection_format:"multi"`
ArrayStringCsv [2]string `form:",default=1;2" collection_format:"csv"`
ArrayStringSsv [2]string `form:",default=1 2" collection_format:"ssv"`
ArrayStringTsv [2]string `form:",default=1\t2" collection_format:"tsv"`
ArrayStringPipes [2]string `form:",default=1|2" collection_format:"pipes"`
}
err := mappingByPtr(&s, formSource{}, "form")
require.NoError(t, err)
assert.Equal(t, []int{1, 2, 3}, s.SliceMulti)
assert.Equal(t, []int{1, 2, 3}, s.SliceCsv)
assert.Equal(t, []int{1, 2, 3}, s.SliceSsv)
assert.Equal(t, []int{1, 2, 3}, s.SliceTsv)
assert.Equal(t, []int{1, 2, 3}, s.SlicePipes)
assert.Equal(t, [2]int{1, 2}, s.ArrayMulti)
assert.Equal(t, [2]int{1, 2}, s.ArrayCsv)
assert.Equal(t, [2]int{1, 2}, s.ArraySsv)
assert.Equal(t, [2]int{1, 2}, s.ArrayTsv)
assert.Equal(t, [2]int{1, 2}, s.ArrayPipes)
assert.Equal(t, []string{"1", "2", "3"}, s.SliceStringMulti)
assert.Equal(t, []string{"1", "2", "3"}, s.SliceStringCsv)
assert.Equal(t, []string{"1", "2", "3"}, s.SliceStringSsv)
assert.Equal(t, []string{"1", "2", "3"}, s.SliceStringTsv)
assert.Equal(t, []string{"1", "2", "3"}, s.SliceStringPipes)
assert.Equal(t, [2]string{"1", "2"}, s.ArrayStringMulti)
assert.Equal(t, [2]string{"1", "2"}, s.ArrayStringCsv)
assert.Equal(t, [2]string{"1", "2"}, s.ArrayStringSsv)
assert.Equal(t, [2]string{"1", "2"}, s.ArrayStringTsv)
assert.Equal(t, [2]string{"1", "2"}, s.ArrayStringPipes)
} }
func TestMappingStructField(t *testing.T) { func TestMappingStructField(t *testing.T) {
@ -271,7 +397,7 @@ func TestMappingStructField(t *testing.T) {
} }
err := mappingByPtr(&s, formSource{"J": {`{"I": 9}`}}, "form") err := mappingByPtr(&s, formSource{"J": {`{"I": 9}`}}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 9, s.J.I) assert.Equal(t, 9, s.J.I)
} }
@ -289,20 +415,20 @@ func TestMappingPtrField(t *testing.T) {
// With 0 items. // With 0 items.
var req0 ptrRequest var req0 ptrRequest
err = mappingByPtr(&req0, formSource{}, "form") err = mappingByPtr(&req0, formSource{}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.Empty(t, req0.Items) assert.Empty(t, req0.Items)
// With 1 item. // With 1 item.
var req1 ptrRequest var req1 ptrRequest
err = mappingByPtr(&req1, formSource{"items": {`{"key": 1}`}}, "form") err = mappingByPtr(&req1, formSource{"items": {`{"key": 1}`}}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, req1.Items, 1) assert.Len(t, req1.Items, 1)
assert.EqualValues(t, 1, req1.Items[0].Key) assert.EqualValues(t, 1, req1.Items[0].Key)
// With 2 items. // With 2 items.
var req2 ptrRequest var req2 ptrRequest
err = mappingByPtr(&req2, formSource{"items": {`{"key": 1}`, `{"key": 2}`}}, "form") err = mappingByPtr(&req2, formSource{"items": {`{"key": 1}`, `{"key": 2}`}}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, req2.Items, 2) assert.Len(t, req2.Items, 2)
assert.EqualValues(t, 1, req2.Items[0].Key) assert.EqualValues(t, 1, req2.Items[0].Key)
assert.EqualValues(t, 2, req2.Items[1].Key) assert.EqualValues(t, 2, req2.Items[1].Key)
@ -314,7 +440,7 @@ func TestMappingMapField(t *testing.T) {
} }
err := mappingByPtr(&s, formSource{"M": {`{"one": 1}`}}, "form") err := mappingByPtr(&s, formSource{"M": {`{"one": 1}`}}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, map[string]int{"one": 1}, s.M) assert.Equal(t, map[string]int{"one": 1}, s.M)
} }
@ -325,7 +451,7 @@ func TestMappingIgnoredCircularRef(t *testing.T) {
var s S var s S
err := mappingByPtr(&s, formSource{}, "form") err := mappingByPtr(&s, formSource{}, "form")
assert.NoError(t, err) require.NoError(t, err)
} }
type customUnmarshalParamHex int type customUnmarshalParamHex int
@ -344,7 +470,7 @@ func TestMappingCustomUnmarshalParamHexWithFormTag(t *testing.T) {
Foo customUnmarshalParamHex `form:"foo"` Foo customUnmarshalParamHex `form:"foo"`
} }
err := mappingByPtr(&s, formSource{"foo": {`f5`}}, "form") err := mappingByPtr(&s, formSource{"foo": {`f5`}}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.EqualValues(t, 245, s.Foo) assert.EqualValues(t, 245, s.Foo)
} }
@ -354,7 +480,7 @@ func TestMappingCustomUnmarshalParamHexWithURITag(t *testing.T) {
Foo customUnmarshalParamHex `uri:"foo"` Foo customUnmarshalParamHex `uri:"foo"`
} }
err := mappingByPtr(&s, formSource{"foo": {`f5`}}, "uri") err := mappingByPtr(&s, formSource{"foo": {`f5`}}, "uri")
assert.NoError(t, err) require.NoError(t, err)
assert.EqualValues(t, 245, s.Foo) assert.EqualValues(t, 245, s.Foo)
} }
@ -381,7 +507,7 @@ func TestMappingCustomStructTypeWithFormTag(t *testing.T) {
FileData customUnmarshalParamType `form:"data"` FileData customUnmarshalParamType `form:"data"`
} }
err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "form") err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.EqualValues(t, "file", s.FileData.Protocol) assert.EqualValues(t, "file", s.FileData.Protocol)
assert.EqualValues(t, "/foo", s.FileData.Path) assert.EqualValues(t, "/foo", s.FileData.Path)
@ -393,7 +519,7 @@ func TestMappingCustomStructTypeWithURITag(t *testing.T) {
FileData customUnmarshalParamType `uri:"data"` FileData customUnmarshalParamType `uri:"data"`
} }
err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "uri") err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "uri")
assert.NoError(t, err) require.NoError(t, err)
assert.EqualValues(t, "file", s.FileData.Protocol) assert.EqualValues(t, "file", s.FileData.Protocol)
assert.EqualValues(t, "/foo", s.FileData.Path) assert.EqualValues(t, "/foo", s.FileData.Path)
@ -405,7 +531,7 @@ func TestMappingCustomPointerStructTypeWithFormTag(t *testing.T) {
FileData *customUnmarshalParamType `form:"data"` FileData *customUnmarshalParamType `form:"data"`
} }
err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "form") err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.EqualValues(t, "file", s.FileData.Protocol) assert.EqualValues(t, "file", s.FileData.Protocol)
assert.EqualValues(t, "/foo", s.FileData.Path) assert.EqualValues(t, "/foo", s.FileData.Path)
@ -417,7 +543,7 @@ func TestMappingCustomPointerStructTypeWithURITag(t *testing.T) {
FileData *customUnmarshalParamType `uri:"data"` FileData *customUnmarshalParamType `uri:"data"`
} }
err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "uri") err := mappingByPtr(&s, formSource{"data": {`file:/foo:happiness`}}, "uri")
assert.NoError(t, err) require.NoError(t, err)
assert.EqualValues(t, "file", s.FileData.Protocol) assert.EqualValues(t, "file", s.FileData.Protocol)
assert.EqualValues(t, "/foo", s.FileData.Path) assert.EqualValues(t, "/foo", s.FileData.Path)
@ -442,7 +568,7 @@ func TestMappingCustomSliceUri(t *testing.T) {
FileData customPath `uri:"path"` FileData customPath `uri:"path"`
} }
err := mappingByPtr(&s, formSource{"path": {`bar/foo`}}, "uri") err := mappingByPtr(&s, formSource{"path": {`bar/foo`}}, "uri")
assert.NoError(t, err) require.NoError(t, err)
assert.EqualValues(t, "bar", s.FileData[0]) assert.EqualValues(t, "bar", s.FileData[0])
assert.EqualValues(t, "foo", s.FileData[1]) assert.EqualValues(t, "foo", s.FileData[1])
@ -453,7 +579,7 @@ func TestMappingCustomSliceForm(t *testing.T) {
FileData customPath `form:"path"` FileData customPath `form:"path"`
} }
err := mappingByPtr(&s, formSource{"path": {`bar/foo`}}, "form") err := mappingByPtr(&s, formSource{"path": {`bar/foo`}}, "form")
assert.NoError(t, err) require.NoError(t, err)
assert.EqualValues(t, "bar", s.FileData[0]) assert.EqualValues(t, "bar", s.FileData[0])
assert.EqualValues(t, "foo", s.FileData[1]) assert.EqualValues(t, "foo", s.FileData[1])
@ -492,7 +618,7 @@ func TestMappingCustomArrayUri(t *testing.T) {
} }
val := `664a062ac74a8ad104e0e80f` val := `664a062ac74a8ad104e0e80f`
err := mappingByPtr(&s, formSource{"id": {val}}, "uri") err := mappingByPtr(&s, formSource{"id": {val}}, "uri")
assert.NoError(t, err) require.NoError(t, err)
expected, _ := convertTo(val) expected, _ := convertTo(val)
assert.EqualValues(t, expected, s.FileData) assert.EqualValues(t, expected, s.FileData)
@ -504,7 +630,7 @@ func TestMappingCustomArrayForm(t *testing.T) {
} }
val := `664a062ac74a8ad104e0e80f` val := `664a062ac74a8ad104e0e80f`
err := mappingByPtr(&s, formSource{"id": {val}}, "form") err := mappingByPtr(&s, formSource{"id": {val}}, "form")
assert.NoError(t, err) require.NoError(t, err)
expected, _ := convertTo(val) expected, _ := convertTo(val)
assert.EqualValues(t, expected, s.FileData) assert.EqualValues(t, expected, s.FileData)

View File

@ -12,6 +12,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestFormMultipartBindingBindOneFile(t *testing.T) { func TestFormMultipartBindingBindOneFile(t *testing.T) {
@ -27,7 +28,7 @@ func TestFormMultipartBindingBindOneFile(t *testing.T) {
req := createRequestMultipartFiles(t, file) req := createRequestMultipartFiles(t, file)
err := FormMultipart.Bind(req, &s) err := FormMultipart.Bind(req, &s)
assert.NoError(t, err) require.NoError(t, err)
assertMultipartFileHeader(t, &s.FileValue, file) assertMultipartFileHeader(t, &s.FileValue, file)
assertMultipartFileHeader(t, s.FilePtr, file) assertMultipartFileHeader(t, s.FilePtr, file)
@ -53,7 +54,7 @@ func TestFormMultipartBindingBindTwoFiles(t *testing.T) {
req := createRequestMultipartFiles(t, files...) req := createRequestMultipartFiles(t, files...)
err := FormMultipart.Bind(req, &s) err := FormMultipart.Bind(req, &s)
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, s.SliceValues, len(files)) assert.Len(t, s.SliceValues, len(files))
assert.Len(t, s.SlicePtrs, len(files)) assert.Len(t, s.SlicePtrs, len(files))
@ -90,7 +91,7 @@ func TestFormMultipartBindingBindError(t *testing.T) {
} { } {
req := createRequestMultipartFiles(t, files...) req := createRequestMultipartFiles(t, files...)
err := FormMultipart.Bind(req, tt.s) err := FormMultipart.Bind(req, tt.s)
assert.Error(t, err) require.Error(t, err)
} }
} }
@ -106,17 +107,17 @@ func createRequestMultipartFiles(t *testing.T, files ...testFile) *http.Request
mw := multipart.NewWriter(&body) mw := multipart.NewWriter(&body)
for _, file := range files { for _, file := range files {
fw, err := mw.CreateFormFile(file.Fieldname, file.Filename) fw, err := mw.CreateFormFile(file.Fieldname, file.Filename)
assert.NoError(t, err) require.NoError(t, err)
n, err := fw.Write(file.Content) n, err := fw.Write(file.Content)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, len(file.Content), n) assert.Equal(t, len(file.Content), n)
} }
err := mw.Close() err := mw.Close()
assert.NoError(t, err) require.NoError(t, err)
req, err := http.NewRequest("POST", "/", &body) req, err := http.NewRequest("POST", "/", &body)
assert.NoError(t, err) require.NoError(t, err)
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+mw.Boundary()) req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+mw.Boundary())
return req return req
@ -127,12 +128,12 @@ func assertMultipartFileHeader(t *testing.T, fh *multipart.FileHeader, file test
assert.Equal(t, int64(len(file.Content)), fh.Size) assert.Equal(t, int64(len(file.Content)), fh.Size)
fl, err := fh.Open() fl, err := fh.Open()
assert.NoError(t, err) require.NoError(t, err)
body, err := io.ReadAll(fl) body, err := io.ReadAll(fl)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, string(file.Content), string(body)) assert.Equal(t, string(file.Content), string(body))
err = fl.Close() err = fl.Close()
assert.NoError(t, err) require.NoError(t, err)
} }

View File

@ -11,6 +11,7 @@ import (
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
type testInterface interface { type testInterface interface {
@ -113,10 +114,10 @@ func TestValidateNoValidationValues(t *testing.T) {
test := createNoValidationValues() test := createNoValidationValues()
empty := structNoValidationValues{} empty := structNoValidationValues{}
assert.Nil(t, validate(test)) require.NoError(t, validate(test))
assert.Nil(t, validate(&test)) require.NoError(t, validate(&test))
assert.Nil(t, validate(empty)) require.NoError(t, validate(empty))
assert.Nil(t, validate(&empty)) require.NoError(t, validate(&empty))
assert.Equal(t, origin, test) assert.Equal(t, origin, test)
} }
@ -163,8 +164,8 @@ func TestValidateNoValidationPointers(t *testing.T) {
//assert.Nil(t, validate(test)) //assert.Nil(t, validate(test))
//assert.Nil(t, validate(&test)) //assert.Nil(t, validate(&test))
assert.Nil(t, validate(empty)) require.NoError(t, validate(empty))
assert.Nil(t, validate(&empty)) require.NoError(t, validate(&empty))
//assert.Equal(t, origin, test) //assert.Equal(t, origin, test)
} }
@ -173,22 +174,22 @@ type Object map[string]any
func TestValidatePrimitives(t *testing.T) { func TestValidatePrimitives(t *testing.T) {
obj := Object{"foo": "bar", "bar": 1} obj := Object{"foo": "bar", "bar": 1}
assert.NoError(t, validate(obj)) require.NoError(t, validate(obj))
assert.NoError(t, validate(&obj)) require.NoError(t, validate(&obj))
assert.Equal(t, Object{"foo": "bar", "bar": 1}, obj) assert.Equal(t, Object{"foo": "bar", "bar": 1}, obj)
obj2 := []Object{{"foo": "bar", "bar": 1}, {"foo": "bar", "bar": 1}} obj2 := []Object{{"foo": "bar", "bar": 1}, {"foo": "bar", "bar": 1}}
assert.NoError(t, validate(obj2)) require.NoError(t, validate(obj2))
assert.NoError(t, validate(&obj2)) require.NoError(t, validate(&obj2))
nu := 10 nu := 10
assert.NoError(t, validate(nu)) require.NoError(t, validate(nu))
assert.NoError(t, validate(&nu)) require.NoError(t, validate(&nu))
assert.Equal(t, 10, nu) assert.Equal(t, 10, nu)
str := "value" str := "value"
assert.NoError(t, validate(str)) require.NoError(t, validate(str))
assert.NoError(t, validate(&str)) require.NoError(t, validate(&str))
assert.Equal(t, "value", str) assert.Equal(t, "value", str)
} }
@ -212,8 +213,8 @@ func TestValidateAndModifyStruct(t *testing.T) {
s := structModifyValidation{Integer: 1} s := structModifyValidation{Integer: 1}
errs := validate(&s) errs := validate(&s)
assert.Nil(t, errs) require.NoError(t, errs)
assert.Equal(t, s, structModifyValidation{Integer: 0}) assert.Equal(t, structModifyValidation{Integer: 0}, s)
} }
// structCustomValidation is a helper struct we use to check that // structCustomValidation is a helper struct we use to check that
@ -239,14 +240,14 @@ func TestValidatorEngine(t *testing.T) {
err := engine.RegisterValidation("notone", notOne) err := engine.RegisterValidation("notone", notOne)
// Check that we can register custom validation without error // Check that we can register custom validation without error
assert.Nil(t, err) require.NoError(t, err)
// Create an instance which will fail validation // Create an instance which will fail validation
withOne := structCustomValidation{Integer: 1} withOne := structCustomValidation{Integer: 1}
errs := validate(withOne) errs := validate(withOne)
// Check that we got back non-nil errs // Check that we got back non-nil errs
assert.NotNil(t, errs) require.Error(t, errs)
// Check that the error matches expectation // Check that the error matches expectation
assert.Error(t, errs, "", "", "notone") require.Error(t, errs, "", "", "notone")
} }

View File

@ -19,6 +19,7 @@ import (
"sync" "sync"
"time" "time"
"git.vinchent.xyz/vinchent/go-web/framework"
"github.com/gin-contrib/sse" "github.com/gin-contrib/sse"
"github.com/gin-gonic/gin/binding" "github.com/gin-gonic/gin/binding"
"github.com/gin-gonic/gin/render" "github.com/gin-gonic/gin/render"
@ -89,6 +90,9 @@ type Context struct {
// SameSite allows a server to define a cookie attribute making it impossible for // SameSite allows a server to define a cookie attribute making it impossible for
// the browser to send this cookie along with cross-site requests. // the browser to send this cookie along with cross-site requests.
sameSite http.SameSite sameSite http.SameSite
// GoWeb service container
container framework.Container
} }
/************************************/ /************************************/
@ -315,7 +319,31 @@ func (c *Context) GetInt(key string) (i int) {
return return
} }
// GetInt64 returns the value associated with the key as an integer. // GetInt8 returns the value associated with the key as an integer 8.
func (c *Context) GetInt8(key string) (i8 int8) {
if val, ok := c.Get(key); ok && val != nil {
i8, _ = val.(int8)
}
return
}
// GetInt16 returns the value associated with the key as an integer 16.
func (c *Context) GetInt16(key string) (i16 int16) {
if val, ok := c.Get(key); ok && val != nil {
i16, _ = val.(int16)
}
return
}
// GetInt32 returns the value associated with the key as an integer 32.
func (c *Context) GetInt32(key string) (i32 int32) {
if val, ok := c.Get(key); ok && val != nil {
i32, _ = val.(int32)
}
return
}
// GetInt64 returns the value associated with the key as an integer 64.
func (c *Context) GetInt64(key string) (i64 int64) { func (c *Context) GetInt64(key string) (i64 int64) {
if val, ok := c.Get(key); ok && val != nil { if val, ok := c.Get(key); ok && val != nil {
i64, _ = val.(int64) i64, _ = val.(int64)
@ -331,7 +359,31 @@ func (c *Context) GetUint(key string) (ui uint) {
return return
} }
// GetUint64 returns the value associated with the key as an unsigned integer. // GetUint8 returns the value associated with the key as an unsigned integer 8.
func (c *Context) GetUint8(key string) (ui8 uint8) {
if val, ok := c.Get(key); ok && val != nil {
ui8, _ = val.(uint8)
}
return
}
// GetUint16 returns the value associated with the key as an unsigned integer 16.
func (c *Context) GetUint16(key string) (ui16 uint16) {
if val, ok := c.Get(key); ok && val != nil {
ui16, _ = val.(uint16)
}
return
}
// GetUint32 returns the value associated with the key as an unsigned integer 32.
func (c *Context) GetUint32(key string) (ui32 uint32) {
if val, ok := c.Get(key); ok && val != nil {
ui32, _ = val.(uint32)
}
return
}
// GetUint64 returns the value associated with the key as an unsigned integer 64.
func (c *Context) GetUint64(key string) (ui64 uint64) { func (c *Context) GetUint64(key string) (ui64 uint64) {
if val, ok := c.Get(key); ok && val != nil { if val, ok := c.Get(key); ok && val != nil {
ui64, _ = val.(uint64) ui64, _ = val.(uint64)
@ -339,6 +391,14 @@ func (c *Context) GetUint64(key string) (ui64 uint64) {
return return
} }
// GetFloat32 returns the value associated with the key as a float32.
func (c *Context) GetFloat32(key string) (f32 float32) {
if val, ok := c.Get(key); ok && val != nil {
f32, _ = val.(float32)
}
return
}
// GetFloat64 returns the value associated with the key as a float64. // GetFloat64 returns the value associated with the key as a float64.
func (c *Context) GetFloat64(key string) (f64 float64) { func (c *Context) GetFloat64(key string) (f64 float64) {
if val, ok := c.Get(key); ok && val != nil { if val, ok := c.Get(key); ok && val != nil {
@ -363,6 +423,90 @@ func (c *Context) GetDuration(key string) (d time.Duration) {
return return
} }
func (c *Context) GetIntSlice(key string) (is []int) {
if val, ok := c.Get(key); ok && val != nil {
is, _ = val.([]int)
}
return
}
func (c *Context) GetInt8Slice(key string) (i8s []int8) {
if val, ok := c.Get(key); ok && val != nil {
i8s, _ = val.([]int8)
}
return
}
func (c *Context) GetInt16Slice(key string) (i16s []int16) {
if val, ok := c.Get(key); ok && val != nil {
i16s, _ = val.([]int16)
}
return
}
func (c *Context) GetInt32Slice(key string) (i32s []int32) {
if val, ok := c.Get(key); ok && val != nil {
i32s, _ = val.([]int32)
}
return
}
func (c *Context) GetInt64Slice(key string) (i64s []int64) {
if val, ok := c.Get(key); ok && val != nil {
i64s, _ = val.([]int64)
}
return
}
func (c *Context) GetUintSlice(key string) (uis []uint) {
if val, ok := c.Get(key); ok && val != nil {
uis, _ = val.([]uint)
}
return
}
func (c *Context) GetUint8Slice(key string) (ui8s []uint8) {
if val, ok := c.Get(key); ok && val != nil {
ui8s, _ = val.([]uint8)
}
return
}
func (c *Context) GetUint16Slice(key string) (ui16s []uint16) {
if val, ok := c.Get(key); ok && val != nil {
ui16s, _ = val.([]uint16)
}
return
}
func (c *Context) GetUint32Slice(key string) (ui32s []uint32) {
if val, ok := c.Get(key); ok && val != nil {
ui32s, _ = val.([]uint32)
}
return
}
func (c *Context) GetUint64Slice(key string) (ui64s []uint64) {
if val, ok := c.Get(key); ok && val != nil {
ui64s, _ = val.([]uint64)
}
return
}
func (c *Context) GetFloat32Slice(key string) (f32s []float32) {
if val, ok := c.Get(key); ok && val != nil {
f32s, _ = val.([]float32)
}
return
}
func (c *Context) GetFloat64Slice(key string) (f64s []float64) {
if val, ok := c.Get(key); ok && val != nil {
f64s, _ = val.([]float64)
}
return
}
// GetStringSlice returns the value associated with the key as a slice of strings. // GetStringSlice returns the value associated with the key as a slice of strings.
func (c *Context) GetStringSlice(key string) (ss []string) { func (c *Context) GetStringSlice(key string) (ss []string) {
if val, ok := c.Get(key); ok && val != nil { if val, ok := c.Get(key); ok && val != nil {

View File

@ -27,6 +27,7 @@ import (
"github.com/gin-gonic/gin/binding" "github.com/gin-gonic/gin/binding"
testdata "github.com/gin-gonic/gin/testdata/protoexample" testdata "github.com/gin-gonic/gin/testdata/protoexample"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
@ -74,20 +75,18 @@ func TestContextFormFile(t *testing.T) {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
mw := multipart.NewWriter(buf) mw := multipart.NewWriter(buf)
w, err := mw.CreateFormFile("file", "test") w, err := mw.CreateFormFile("file", "test")
if assert.NoError(t, err) { require.NoError(t, err)
_, err = w.Write([]byte("test")) _, err = w.Write([]byte("test"))
assert.NoError(t, err) require.NoError(t, err)
}
mw.Close() mw.Close()
c, _ := CreateTestContext(httptest.NewRecorder()) c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", buf) c.Request, _ = http.NewRequest("POST", "/", buf)
c.Request.Header.Set("Content-Type", mw.FormDataContentType()) c.Request.Header.Set("Content-Type", mw.FormDataContentType())
f, err := c.FormFile("file") f, err := c.FormFile("file")
if assert.NoError(t, err) { require.NoError(t, err)
assert.Equal(t, "test", f.Filename) assert.Equal(t, "test", f.Filename)
}
assert.NoError(t, c.SaveUploadedFile(f, "test")) require.NoError(t, c.SaveUploadedFile(f, "test"))
} }
func TestContextFormFileFailed(t *testing.T) { func TestContextFormFileFailed(t *testing.T) {
@ -99,29 +98,27 @@ func TestContextFormFileFailed(t *testing.T) {
c.Request.Header.Set("Content-Type", mw.FormDataContentType()) c.Request.Header.Set("Content-Type", mw.FormDataContentType())
c.engine.MaxMultipartMemory = 8 << 20 c.engine.MaxMultipartMemory = 8 << 20
f, err := c.FormFile("file") f, err := c.FormFile("file")
assert.Error(t, err) require.Error(t, err)
assert.Nil(t, f) assert.Nil(t, f)
} }
func TestContextMultipartForm(t *testing.T) { func TestContextMultipartForm(t *testing.T) {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
mw := multipart.NewWriter(buf) mw := multipart.NewWriter(buf)
assert.NoError(t, mw.WriteField("foo", "bar")) require.NoError(t, mw.WriteField("foo", "bar"))
w, err := mw.CreateFormFile("file", "test") w, err := mw.CreateFormFile("file", "test")
if assert.NoError(t, err) { require.NoError(t, err)
_, err = w.Write([]byte("test")) _, err = w.Write([]byte("test"))
assert.NoError(t, err) require.NoError(t, err)
}
mw.Close() mw.Close()
c, _ := CreateTestContext(httptest.NewRecorder()) c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", buf) c.Request, _ = http.NewRequest("POST", "/", buf)
c.Request.Header.Set("Content-Type", mw.FormDataContentType()) c.Request.Header.Set("Content-Type", mw.FormDataContentType())
f, err := c.MultipartForm() f, err := c.MultipartForm()
if assert.NoError(t, err) { require.NoError(t, err)
assert.NotNil(t, f) assert.NotNil(t, f)
}
assert.NoError(t, c.SaveUploadedFile(f.File["file"][0], "test")) require.NoError(t, c.SaveUploadedFile(f.File["file"][0], "test"))
} }
func TestSaveUploadedOpenFailed(t *testing.T) { func TestSaveUploadedOpenFailed(t *testing.T) {
@ -136,27 +133,25 @@ func TestSaveUploadedOpenFailed(t *testing.T) {
f := &multipart.FileHeader{ f := &multipart.FileHeader{
Filename: "file", Filename: "file",
} }
assert.Error(t, c.SaveUploadedFile(f, "test")) require.Error(t, c.SaveUploadedFile(f, "test"))
} }
func TestSaveUploadedCreateFailed(t *testing.T) { func TestSaveUploadedCreateFailed(t *testing.T) {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
mw := multipart.NewWriter(buf) mw := multipart.NewWriter(buf)
w, err := mw.CreateFormFile("file", "test") w, err := mw.CreateFormFile("file", "test")
if assert.NoError(t, err) { require.NoError(t, err)
_, err = w.Write([]byte("test")) _, err = w.Write([]byte("test"))
assert.NoError(t, err) require.NoError(t, err)
}
mw.Close() mw.Close()
c, _ := CreateTestContext(httptest.NewRecorder()) c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", buf) c.Request, _ = http.NewRequest("POST", "/", buf)
c.Request.Header.Set("Content-Type", mw.FormDataContentType()) c.Request.Header.Set("Content-Type", mw.FormDataContentType())
f, err := c.FormFile("file") f, err := c.FormFile("file")
if assert.NoError(t, err) { require.NoError(t, err)
assert.Equal(t, "test", f.Filename) assert.Equal(t, "test", f.Filename)
}
assert.Error(t, c.SaveUploadedFile(f, "/")) require.Error(t, c.SaveUploadedFile(f, "/"))
} }
func TestContextReset(t *testing.T) { func TestContextReset(t *testing.T) {
@ -174,10 +169,10 @@ func TestContextReset(t *testing.T) {
assert.False(t, c.IsAborted()) assert.False(t, c.IsAborted())
assert.Nil(t, c.Keys) assert.Nil(t, c.Keys)
assert.Nil(t, c.Accepted) assert.Nil(t, c.Accepted)
assert.Len(t, c.Errors, 0) assert.Empty(t, c.Errors)
assert.Empty(t, c.Errors.Errors()) assert.Empty(t, c.Errors.Errors())
assert.Empty(t, c.Errors.ByType(ErrorTypeAny)) assert.Empty(t, c.Errors.ByType(ErrorTypeAny))
assert.Len(t, c.Params, 0) assert.Empty(t, c.Params)
assert.EqualValues(t, c.index, -1) assert.EqualValues(t, c.index, -1)
assert.Equal(t, c.Writer.(*responseWriter), &c.writermem) assert.Equal(t, c.Writer.(*responseWriter), &c.writermem)
} }
@ -230,13 +225,13 @@ func TestContextSetGetValues(t *testing.T) {
var a any = 1 var a any = 1
c.Set("intInterface", a) c.Set("intInterface", a)
assert.Exactly(t, c.MustGet("string").(string), "this is a string") assert.Exactly(t, "this is a string", c.MustGet("string").(string))
assert.Exactly(t, c.MustGet("int32").(int32), int32(-42)) assert.Exactly(t, c.MustGet("int32").(int32), int32(-42))
assert.Exactly(t, c.MustGet("int64").(int64), int64(42424242424242)) assert.Exactly(t, int64(42424242424242), c.MustGet("int64").(int64))
assert.Exactly(t, c.MustGet("uint64").(uint64), uint64(42)) assert.Exactly(t, uint64(42), c.MustGet("uint64").(uint64))
assert.Exactly(t, c.MustGet("float32").(float32), float32(4.2)) assert.InDelta(t, float32(4.2), c.MustGet("float32").(float32), 0.01)
assert.Exactly(t, c.MustGet("float64").(float64), 4.2) assert.InDelta(t, 4.2, c.MustGet("float64").(float64), 0.01)
assert.Exactly(t, c.MustGet("intInterface").(int), 1) assert.Exactly(t, 1, c.MustGet("intInterface").(int))
} }
func TestContextGetString(t *testing.T) { func TestContextGetString(t *testing.T) {
@ -257,6 +252,30 @@ func TestContextGetInt(t *testing.T) {
assert.Equal(t, 1, c.GetInt("int")) assert.Equal(t, 1, c.GetInt("int"))
} }
func TestContextGetInt8(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "int8"
value := int8(0x7F)
c.Set(key, value)
assert.Equal(t, value, c.GetInt8(key))
}
func TestContextGetInt16(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "int16"
value := int16(0x7FFF)
c.Set(key, value)
assert.Equal(t, value, c.GetInt16(key))
}
func TestContextGetInt32(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "int32"
value := int32(0x7FFFFFFF)
c.Set(key, value)
assert.Equal(t, value, c.GetInt32(key))
}
func TestContextGetInt64(t *testing.T) { func TestContextGetInt64(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder()) c, _ := CreateTestContext(httptest.NewRecorder())
c.Set("int64", int64(42424242424242)) c.Set("int64", int64(42424242424242))
@ -269,16 +288,48 @@ func TestContextGetUint(t *testing.T) {
assert.Equal(t, uint(1), c.GetUint("uint")) assert.Equal(t, uint(1), c.GetUint("uint"))
} }
func TestContextGetUint8(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "uint8"
value := uint8(0xFF)
c.Set(key, value)
assert.Equal(t, value, c.GetUint8(key))
}
func TestContextGetUint16(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "uint16"
value := uint16(0xFFFF)
c.Set(key, value)
assert.Equal(t, value, c.GetUint16(key))
}
func TestContextGetUint32(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "uint32"
value := uint32(0xFFFFFFFF)
c.Set(key, value)
assert.Equal(t, value, c.GetUint32(key))
}
func TestContextGetUint64(t *testing.T) { func TestContextGetUint64(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder()) c, _ := CreateTestContext(httptest.NewRecorder())
c.Set("uint64", uint64(18446744073709551615)) c.Set("uint64", uint64(18446744073709551615))
assert.Equal(t, uint64(18446744073709551615), c.GetUint64("uint64")) assert.Equal(t, uint64(18446744073709551615), c.GetUint64("uint64"))
} }
func TestContextGetFloat32(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "float32"
value := float32(3.14)
c.Set(key, value)
assert.Equal(t, value, c.GetFloat32(key))
}
func TestContextGetFloat64(t *testing.T) { func TestContextGetFloat64(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder()) c, _ := CreateTestContext(httptest.NewRecorder())
c.Set("float64", 4.2) c.Set("float64", 4.2)
assert.Equal(t, 4.2, c.GetFloat64("float64")) assert.InDelta(t, 4.2, c.GetFloat64("float64"), 0.01)
} }
func TestContextGetTime(t *testing.T) { func TestContextGetTime(t *testing.T) {
@ -294,6 +345,102 @@ func TestContextGetDuration(t *testing.T) {
assert.Equal(t, time.Second, c.GetDuration("duration")) assert.Equal(t, time.Second, c.GetDuration("duration"))
} }
func TestContextGetIntSlice(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "int-slice"
value := []int{1, 2}
c.Set(key, value)
assert.Equal(t, value, c.GetIntSlice(key))
}
func TestContextGetInt8Slice(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "int8-slice"
value := []int8{1, 2}
c.Set(key, value)
assert.Equal(t, value, c.GetInt8Slice(key))
}
func TestContextGetInt16Slice(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "int16-slice"
value := []int16{1, 2}
c.Set(key, value)
assert.Equal(t, value, c.GetInt16Slice(key))
}
func TestContextGetInt32Slice(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "int32-slice"
value := []int32{1, 2}
c.Set(key, value)
assert.Equal(t, value, c.GetInt32Slice(key))
}
func TestContextGetInt64Slice(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "int64-slice"
value := []int64{1, 2}
c.Set(key, value)
assert.Equal(t, value, c.GetInt64Slice(key))
}
func TestContextGetUintSlice(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "uint-slice"
value := []uint{1, 2}
c.Set(key, value)
assert.Equal(t, value, c.GetUintSlice(key))
}
func TestContextGetUint8Slice(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "uint8-slice"
value := []uint8{1, 2}
c.Set(key, value)
assert.Equal(t, value, c.GetUint8Slice(key))
}
func TestContextGetUint16Slice(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "uint16-slice"
value := []uint16{1, 2}
c.Set(key, value)
assert.Equal(t, value, c.GetUint16Slice(key))
}
func TestContextGetUint32Slice(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "uint32-slice"
value := []uint32{1, 2}
c.Set(key, value)
assert.Equal(t, value, c.GetUint32Slice(key))
}
func TestContextGetUint64Slice(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "uint64-slice"
value := []uint64{1, 2}
c.Set(key, value)
assert.Equal(t, value, c.GetUint64Slice(key))
}
func TestContextGetFloat32Slice(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "float32-slice"
value := []float32{1, 2}
c.Set(key, value)
assert.Equal(t, value, c.GetFloat32Slice(key))
}
func TestContextGetFloat64Slice(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
key := "float64-slice"
value := []float64{1, 2}
c.Set(key, value)
assert.Equal(t, value, c.GetFloat64Slice(key))
}
func TestContextGetStringSlice(t *testing.T) { func TestContextGetStringSlice(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder()) c, _ := CreateTestContext(httptest.NewRecorder())
c.Set("slice", []string{"foo"}) c.Set("slice", []string{"foo"})
@ -344,12 +491,12 @@ func TestContextCopy(t *testing.T) {
assert.Nil(t, cp.writermem.ResponseWriter) assert.Nil(t, cp.writermem.ResponseWriter)
assert.Equal(t, &cp.writermem, cp.Writer.(*responseWriter)) assert.Equal(t, &cp.writermem, cp.Writer.(*responseWriter))
assert.Equal(t, cp.Request, c.Request) assert.Equal(t, cp.Request, c.Request)
assert.Equal(t, cp.index, abortIndex) assert.Equal(t, abortIndex, cp.index)
assert.Equal(t, cp.Keys, c.Keys) assert.Equal(t, cp.Keys, c.Keys)
assert.Equal(t, cp.engine, c.engine) assert.Equal(t, cp.engine, c.engine)
assert.Equal(t, cp.Params, c.Params) assert.Equal(t, cp.Params, c.Params)
cp.Set("foo", "notBar") cp.Set("foo", "notBar")
assert.False(t, cp.Keys["foo"] == c.Keys["foo"]) assert.NotEqual(t, cp.Keys["foo"], c.Keys["foo"])
assert.Equal(t, cp.fullPath, c.fullPath) assert.Equal(t, cp.fullPath, c.fullPath)
} }
@ -366,7 +513,7 @@ func TestContextHandlerNames(t *testing.T) {
names := c.HandlerNames() names := c.HandlerNames()
assert.True(t, len(names) == 4) assert.Len(t, names, 4)
for _, name := range names { for _, name := range names {
assert.Regexp(t, `^(.*/vendor/)?(github\.com/gin-gonic/gin\.){1}(TestContextHandlerNames\.func.*){0,1}(handlerNameTest.*){0,1}`, name) assert.Regexp(t, `^(.*/vendor/)?(github\.com/gin-gonic/gin\.){1}(TestContextHandlerNames\.func.*){0,1}(handlerNameTest.*){0,1}`, name)
} }
@ -425,7 +572,7 @@ func TestContextQuery(t *testing.T) {
func TestContextInitQueryCache(t *testing.T) { func TestContextInitQueryCache(t *testing.T) {
validURL, err := url.Parse("https://github.com/gin-gonic/gin/pull/3969?key=value&otherkey=othervalue") validURL, err := url.Parse("https://github.com/gin-gonic/gin/pull/3969?key=value&otherkey=othervalue")
assert.Nil(t, err) require.NoError(t, err)
tests := []struct { tests := []struct {
testName string testName string
@ -531,7 +678,7 @@ func TestContextQueryAndPostForm(t *testing.T) {
Both string `form:"both"` Both string `form:"both"`
Array []string `form:"array[]"` Array []string `form:"array[]"`
} }
assert.NoError(t, c.Bind(&obj)) require.NoError(t, c.Bind(&obj))
assert.Equal(t, "bar", obj.Foo, "bar") assert.Equal(t, "bar", obj.Foo, "bar")
assert.Equal(t, "main", obj.ID, "main") assert.Equal(t, "main", obj.ID, "main")
assert.Equal(t, 11, obj.Page, 11) assert.Equal(t, 11, obj.Page, 11)
@ -548,10 +695,10 @@ func TestContextQueryAndPostForm(t *testing.T) {
assert.Equal(t, "second", values[1]) assert.Equal(t, "second", values[1])
values = c.QueryArray("nokey") values = c.QueryArray("nokey")
assert.Equal(t, 0, len(values)) assert.Empty(t, values)
values = c.QueryArray("both") values = c.QueryArray("both")
assert.Equal(t, 1, len(values)) assert.Len(t, values, 1)
assert.Equal(t, "GET", values[0]) assert.Equal(t, "GET", values[0])
dicts, ok := c.GetQueryMap("ids") dicts, ok := c.GetQueryMap("ids")
@ -561,22 +708,22 @@ func TestContextQueryAndPostForm(t *testing.T) {
dicts, ok = c.GetQueryMap("nokey") dicts, ok = c.GetQueryMap("nokey")
assert.False(t, ok) assert.False(t, ok)
assert.Equal(t, 0, len(dicts)) assert.Empty(t, dicts)
dicts, ok = c.GetQueryMap("both") dicts, ok = c.GetQueryMap("both")
assert.False(t, ok) assert.False(t, ok)
assert.Equal(t, 0, len(dicts)) assert.Empty(t, dicts)
dicts, ok = c.GetQueryMap("array") dicts, ok = c.GetQueryMap("array")
assert.False(t, ok) assert.False(t, ok)
assert.Equal(t, 0, len(dicts)) assert.Empty(t, dicts)
dicts = c.QueryMap("ids") dicts = c.QueryMap("ids")
assert.Equal(t, "hi", dicts["a"]) assert.Equal(t, "hi", dicts["a"])
assert.Equal(t, "3.14", dicts["b"]) assert.Equal(t, "3.14", dicts["b"])
dicts = c.QueryMap("nokey") dicts = c.QueryMap("nokey")
assert.Equal(t, 0, len(dicts)) assert.Empty(t, dicts)
} }
func TestContextPostFormMultipart(t *testing.T) { func TestContextPostFormMultipart(t *testing.T) {
@ -594,7 +741,7 @@ func TestContextPostFormMultipart(t *testing.T) {
TimeLocation time.Time `form:"time_location" time_format:"02/01/2006 15:04" time_location:"Asia/Tokyo"` TimeLocation time.Time `form:"time_location" time_format:"02/01/2006 15:04" time_location:"Asia/Tokyo"`
BlankTime time.Time `form:"blank_time" time_format:"02/01/2006 15:04"` BlankTime time.Time `form:"blank_time" time_format:"02/01/2006 15:04"`
} }
assert.NoError(t, c.Bind(&obj)) require.NoError(t, c.Bind(&obj))
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
assert.Equal(t, "10", obj.Bar) assert.Equal(t, "10", obj.Bar)
assert.Equal(t, 10, obj.BarAsInt) assert.Equal(t, 10, obj.BarAsInt)
@ -648,10 +795,10 @@ func TestContextPostFormMultipart(t *testing.T) {
assert.Equal(t, "second", values[1]) assert.Equal(t, "second", values[1])
values = c.PostFormArray("nokey") values = c.PostFormArray("nokey")
assert.Equal(t, 0, len(values)) assert.Empty(t, values)
values = c.PostFormArray("foo") values = c.PostFormArray("foo")
assert.Equal(t, 1, len(values)) assert.Len(t, values, 1)
assert.Equal(t, "bar", values[0]) assert.Equal(t, "bar", values[0])
dicts, ok := c.GetPostFormMap("names") dicts, ok := c.GetPostFormMap("names")
@ -661,14 +808,14 @@ func TestContextPostFormMultipart(t *testing.T) {
dicts, ok = c.GetPostFormMap("nokey") dicts, ok = c.GetPostFormMap("nokey")
assert.False(t, ok) assert.False(t, ok)
assert.Equal(t, 0, len(dicts)) assert.Empty(t, dicts)
dicts = c.PostFormMap("names") dicts = c.PostFormMap("names")
assert.Equal(t, "thinkerou", dicts["a"]) assert.Equal(t, "thinkerou", dicts["a"])
assert.Equal(t, "tianou", dicts["b"]) assert.Equal(t, "tianou", dicts["b"])
dicts = c.PostFormMap("nokey") dicts = c.PostFormMap("nokey")
assert.Equal(t, 0, len(dicts)) assert.Empty(t, dicts)
} }
func TestContextSetCookie(t *testing.T) { func TestContextSetCookie(t *testing.T) {
@ -693,7 +840,7 @@ func TestContextGetCookie(t *testing.T) {
assert.Equal(t, "gin", cookie) assert.Equal(t, "gin", cookie)
_, err := c.Cookie("nokey") _, err := c.Cookie("nokey")
assert.Error(t, err) require.Error(t, err)
} }
func TestContextBodyAllowedForStatus(t *testing.T) { func TestContextBodyAllowedForStatus(t *testing.T) {
@ -798,7 +945,7 @@ func TestContextRenderNoContentAPIJSON(t *testing.T) {
assert.Equal(t, http.StatusNoContent, w.Code) assert.Equal(t, http.StatusNoContent, w.Code)
assert.Empty(t, w.Body.String()) assert.Empty(t, w.Body.String())
assert.Equal(t, w.Header().Get("Content-Type"), "application/vnd.api+json") assert.Equal(t, "application/vnd.api+json", w.Header().Get("Content-Type"))
} }
// Tests that the response is serialized as JSON // Tests that the response is serialized as JSON
@ -1160,7 +1307,7 @@ func TestContextRenderProtoBuf(t *testing.T) {
c.ProtoBuf(http.StatusCreated, data) c.ProtoBuf(http.StatusCreated, data)
protoData, err := proto.Marshal(data) protoData, err := proto.Marshal(data)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, http.StatusCreated, w.Code) assert.Equal(t, http.StatusCreated, w.Code)
assert.Equal(t, string(protoData), w.Body.String()) assert.Equal(t, string(protoData), w.Body.String())
@ -1321,7 +1468,7 @@ func TestContextNegotiationNotSupport(t *testing.T) {
}) })
assert.Equal(t, http.StatusNotAcceptable, w.Code) assert.Equal(t, http.StatusNotAcceptable, w.Code)
assert.Equal(t, c.index, abortIndex) assert.Equal(t, abortIndex, c.index)
assert.True(t, c.IsAborted()) assert.True(t, c.IsAborted())
} }
@ -1349,23 +1496,23 @@ func TestContextNegotiationFormatWithWildcardAccept(t *testing.T) {
c.Request, _ = http.NewRequest("POST", "/", nil) c.Request, _ = http.NewRequest("POST", "/", nil)
c.Request.Header.Add("Accept", "*/*") c.Request.Header.Add("Accept", "*/*")
assert.Equal(t, c.NegotiateFormat("*/*"), "*/*") assert.Equal(t, "*/*", c.NegotiateFormat("*/*"))
assert.Equal(t, c.NegotiateFormat("text/*"), "text/*") assert.Equal(t, "text/*", c.NegotiateFormat("text/*"))
assert.Equal(t, c.NegotiateFormat("application/*"), "application/*") assert.Equal(t, "application/*", c.NegotiateFormat("application/*"))
assert.Equal(t, c.NegotiateFormat(MIMEJSON), MIMEJSON) assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON))
assert.Equal(t, c.NegotiateFormat(MIMEXML), MIMEXML) assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEXML))
assert.Equal(t, c.NegotiateFormat(MIMEHTML), MIMEHTML) assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEHTML))
c, _ = CreateTestContext(httptest.NewRecorder()) c, _ = CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", nil) c.Request, _ = http.NewRequest("POST", "/", nil)
c.Request.Header.Add("Accept", "text/*") c.Request.Header.Add("Accept", "text/*")
assert.Equal(t, c.NegotiateFormat("*/*"), "*/*") assert.Equal(t, "*/*", c.NegotiateFormat("*/*"))
assert.Equal(t, c.NegotiateFormat("text/*"), "text/*") assert.Equal(t, "text/*", c.NegotiateFormat("text/*"))
assert.Equal(t, c.NegotiateFormat("application/*"), "") assert.Equal(t, "", c.NegotiateFormat("application/*"))
assert.Equal(t, c.NegotiateFormat(MIMEJSON), "") assert.Equal(t, "", c.NegotiateFormat(MIMEJSON))
assert.Equal(t, c.NegotiateFormat(MIMEXML), "") assert.Equal(t, "", c.NegotiateFormat(MIMEXML))
assert.Equal(t, c.NegotiateFormat(MIMEHTML), MIMEHTML) assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEHTML))
} }
func TestContextNegotiationFormatCustom(t *testing.T) { func TestContextNegotiationFormatCustom(t *testing.T) {
@ -1444,7 +1591,7 @@ func TestContextAbortWithStatusJSON(t *testing.T) {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
_, err := buf.ReadFrom(w.Body) _, err := buf.ReadFrom(w.Body)
assert.NoError(t, err) require.NoError(t, err)
jsonStringBody := buf.String() jsonStringBody := buf.String()
assert.Equal(t, "{\"foo\":\"fooValue\",\"bar\":\"barValue\"}", jsonStringBody) assert.Equal(t, "{\"foo\":\"fooValue\",\"bar\":\"barValue\"}", jsonStringBody)
} }
@ -1669,7 +1816,7 @@ func TestContextAutoBindJSON(t *testing.T) {
Foo string `json:"foo"` Foo string `json:"foo"`
Bar string `json:"bar"` Bar string `json:"bar"`
} }
assert.NoError(t, c.Bind(&obj)) require.NoError(t, c.Bind(&obj))
assert.Equal(t, "foo", obj.Bar) assert.Equal(t, "foo", obj.Bar)
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
assert.Empty(t, c.Errors) assert.Empty(t, c.Errors)
@ -1686,7 +1833,7 @@ func TestContextBindWithJSON(t *testing.T) {
Foo string `json:"foo"` Foo string `json:"foo"`
Bar string `json:"bar"` Bar string `json:"bar"`
} }
assert.NoError(t, c.BindJSON(&obj)) require.NoError(t, c.BindJSON(&obj))
assert.Equal(t, "foo", obj.Bar) assert.Equal(t, "foo", obj.Bar)
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
assert.Equal(t, 0, w.Body.Len()) assert.Equal(t, 0, w.Body.Len())
@ -1707,7 +1854,7 @@ func TestContextBindWithXML(t *testing.T) {
Foo string `xml:"foo"` Foo string `xml:"foo"`
Bar string `xml:"bar"` Bar string `xml:"bar"`
} }
assert.NoError(t, c.BindXML(&obj)) require.NoError(t, c.BindXML(&obj))
assert.Equal(t, "FOO", obj.Foo) assert.Equal(t, "FOO", obj.Foo)
assert.Equal(t, "BAR", obj.Bar) assert.Equal(t, "BAR", obj.Bar)
assert.Equal(t, 0, w.Body.Len()) assert.Equal(t, 0, w.Body.Len())
@ -1722,7 +1869,7 @@ func TestContextBindPlain(t *testing.T) {
var s string var s string
assert.NoError(t, c.BindPlain(&s)) require.NoError(t, c.BindPlain(&s))
assert.Equal(t, "test string", s) assert.Equal(t, "test string", s)
assert.Equal(t, 0, w.Body.Len()) assert.Equal(t, 0, w.Body.Len())
@ -1732,7 +1879,7 @@ func TestContextBindPlain(t *testing.T) {
var bs []byte var bs []byte
assert.NoError(t, c.BindPlain(&bs)) require.NoError(t, c.BindPlain(&bs))
assert.Equal(t, []byte("test []byte"), bs) assert.Equal(t, []byte("test []byte"), bs)
assert.Equal(t, 0, w.Body.Len()) assert.Equal(t, 0, w.Body.Len())
} }
@ -1752,7 +1899,7 @@ func TestContextBindHeader(t *testing.T) {
Limit int `header:"limit"` Limit int `header:"limit"`
} }
assert.NoError(t, c.BindHeader(&testHeader)) require.NoError(t, c.BindHeader(&testHeader))
assert.Equal(t, 8000, testHeader.Rate) assert.Equal(t, 8000, testHeader.Rate)
assert.Equal(t, "music", testHeader.Domain) assert.Equal(t, "music", testHeader.Domain)
assert.Equal(t, 1000, testHeader.Limit) assert.Equal(t, 1000, testHeader.Limit)
@ -1769,7 +1916,7 @@ func TestContextBindWithQuery(t *testing.T) {
Foo string `form:"foo"` Foo string `form:"foo"`
Bar string `form:"bar"` Bar string `form:"bar"`
} }
assert.NoError(t, c.BindQuery(&obj)) require.NoError(t, c.BindQuery(&obj))
assert.Equal(t, "foo", obj.Bar) assert.Equal(t, "foo", obj.Bar)
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
assert.Equal(t, 0, w.Body.Len()) assert.Equal(t, 0, w.Body.Len())
@ -1786,7 +1933,7 @@ func TestContextBindWithYAML(t *testing.T) {
Foo string `yaml:"foo"` Foo string `yaml:"foo"`
Bar string `yaml:"bar"` Bar string `yaml:"bar"`
} }
assert.NoError(t, c.BindYAML(&obj)) require.NoError(t, c.BindYAML(&obj))
assert.Equal(t, "foo", obj.Bar) assert.Equal(t, "foo", obj.Bar)
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
assert.Equal(t, 0, w.Body.Len()) assert.Equal(t, 0, w.Body.Len())
@ -1803,7 +1950,7 @@ func TestContextBindWithTOML(t *testing.T) {
Foo string `toml:"foo"` Foo string `toml:"foo"`
Bar string `toml:"bar"` Bar string `toml:"bar"`
} }
assert.NoError(t, c.BindTOML(&obj)) require.NoError(t, c.BindTOML(&obj))
assert.Equal(t, "foo", obj.Bar) assert.Equal(t, "foo", obj.Bar)
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
assert.Equal(t, 0, w.Body.Len()) assert.Equal(t, 0, w.Body.Len())
@ -1821,7 +1968,7 @@ func TestContextBadAutoBind(t *testing.T) {
} }
assert.False(t, c.IsAborted()) assert.False(t, c.IsAborted())
assert.Error(t, c.Bind(&obj)) require.Error(t, c.Bind(&obj))
c.Writer.WriteHeaderNow() c.Writer.WriteHeaderNow()
assert.Empty(t, obj.Bar) assert.Empty(t, obj.Bar)
@ -1839,7 +1986,7 @@ func TestContextAutoShouldBindJSON(t *testing.T) {
Foo string `json:"foo"` Foo string `json:"foo"`
Bar string `json:"bar"` Bar string `json:"bar"`
} }
assert.NoError(t, c.ShouldBind(&obj)) require.NoError(t, c.ShouldBind(&obj))
assert.Equal(t, "foo", obj.Bar) assert.Equal(t, "foo", obj.Bar)
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
assert.Empty(t, c.Errors) assert.Empty(t, c.Errors)
@ -1856,7 +2003,7 @@ func TestContextShouldBindWithJSON(t *testing.T) {
Foo string `json:"foo"` Foo string `json:"foo"`
Bar string `json:"bar"` Bar string `json:"bar"`
} }
assert.NoError(t, c.ShouldBindJSON(&obj)) require.NoError(t, c.ShouldBindJSON(&obj))
assert.Equal(t, "foo", obj.Bar) assert.Equal(t, "foo", obj.Bar)
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
assert.Equal(t, 0, w.Body.Len()) assert.Equal(t, 0, w.Body.Len())
@ -1877,7 +2024,7 @@ func TestContextShouldBindWithXML(t *testing.T) {
Foo string `xml:"foo"` Foo string `xml:"foo"`
Bar string `xml:"bar"` Bar string `xml:"bar"`
} }
assert.NoError(t, c.ShouldBindXML(&obj)) require.NoError(t, c.ShouldBindXML(&obj))
assert.Equal(t, "FOO", obj.Foo) assert.Equal(t, "FOO", obj.Foo)
assert.Equal(t, "BAR", obj.Bar) assert.Equal(t, "BAR", obj.Bar)
assert.Equal(t, 0, w.Body.Len()) assert.Equal(t, 0, w.Body.Len())
@ -1892,7 +2039,7 @@ func TestContextShouldBindPlain(t *testing.T) {
var s string var s string
assert.NoError(t, c.ShouldBindPlain(&s)) require.NoError(t, c.ShouldBindPlain(&s))
assert.Equal(t, "test string", s) assert.Equal(t, "test string", s)
assert.Equal(t, 0, w.Body.Len()) assert.Equal(t, 0, w.Body.Len())
// []byte // []byte
@ -1902,7 +2049,7 @@ func TestContextShouldBindPlain(t *testing.T) {
var bs []byte var bs []byte
assert.NoError(t, c.ShouldBindPlain(&bs)) require.NoError(t, c.ShouldBindPlain(&bs))
assert.Equal(t, []byte("test []byte"), bs) assert.Equal(t, []byte("test []byte"), bs)
assert.Equal(t, 0, w.Body.Len()) assert.Equal(t, 0, w.Body.Len())
} }
@ -1922,7 +2069,7 @@ func TestContextShouldBindHeader(t *testing.T) {
Limit int `header:"limit"` Limit int `header:"limit"`
} }
assert.NoError(t, c.ShouldBindHeader(&testHeader)) require.NoError(t, c.ShouldBindHeader(&testHeader))
assert.Equal(t, 8000, testHeader.Rate) assert.Equal(t, 8000, testHeader.Rate)
assert.Equal(t, "music", testHeader.Domain) assert.Equal(t, "music", testHeader.Domain)
assert.Equal(t, 1000, testHeader.Limit) assert.Equal(t, 1000, testHeader.Limit)
@ -1941,7 +2088,7 @@ func TestContextShouldBindWithQuery(t *testing.T) {
Foo1 string `form:"Foo"` Foo1 string `form:"Foo"`
Bar1 string `form:"Bar"` Bar1 string `form:"Bar"`
} }
assert.NoError(t, c.ShouldBindQuery(&obj)) require.NoError(t, c.ShouldBindQuery(&obj))
assert.Equal(t, "foo", obj.Bar) assert.Equal(t, "foo", obj.Bar)
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
assert.Equal(t, "foo1", obj.Bar1) assert.Equal(t, "foo1", obj.Bar1)
@ -1960,7 +2107,7 @@ func TestContextShouldBindWithYAML(t *testing.T) {
Foo string `yaml:"foo"` Foo string `yaml:"foo"`
Bar string `yaml:"bar"` Bar string `yaml:"bar"`
} }
assert.NoError(t, c.ShouldBindYAML(&obj)) require.NoError(t, c.ShouldBindYAML(&obj))
assert.Equal(t, "foo", obj.Bar) assert.Equal(t, "foo", obj.Bar)
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
assert.Equal(t, 0, w.Body.Len()) assert.Equal(t, 0, w.Body.Len())
@ -1977,7 +2124,7 @@ func TestContextShouldBindWithTOML(t *testing.T) {
Foo string `toml:"foo"` Foo string `toml:"foo"`
Bar string `toml:"bar"` Bar string `toml:"bar"`
} }
assert.NoError(t, c.ShouldBindTOML(&obj)) require.NoError(t, c.ShouldBindTOML(&obj))
assert.Equal(t, "foo", obj.Bar) assert.Equal(t, "foo", obj.Bar)
assert.Equal(t, "bar", obj.Foo) assert.Equal(t, "bar", obj.Foo)
assert.Equal(t, 0, w.Body.Len()) assert.Equal(t, 0, w.Body.Len())
@ -1995,7 +2142,7 @@ func TestContextBadAutoShouldBind(t *testing.T) {
} }
assert.False(t, c.IsAborted()) assert.False(t, c.IsAborted())
assert.Error(t, c.ShouldBind(&obj)) require.Error(t, c.ShouldBind(&obj))
assert.Empty(t, obj.Bar) assert.Empty(t, obj.Bar)
assert.Empty(t, obj.Foo) assert.Empty(t, obj.Foo)
@ -2056,10 +2203,10 @@ func TestContextShouldBindBodyWith(t *testing.T) {
// When it binds to typeA and typeB, it finds the body is // When it binds to typeA and typeB, it finds the body is
// not typeB but typeA. // not typeB but typeA.
objA := typeA{} objA := typeA{}
assert.NoError(t, c.ShouldBindBodyWith(&objA, tt.bindingA)) require.NoError(t, c.ShouldBindBodyWith(&objA, tt.bindingA))
assert.Equal(t, typeA{"FOO"}, objA) assert.Equal(t, typeA{"FOO"}, objA)
objB := typeB{} objB := typeB{}
assert.Error(t, c.ShouldBindBodyWith(&objB, tt.bindingB)) require.Error(t, c.ShouldBindBodyWith(&objB, tt.bindingB))
assert.NotEqual(t, typeB{"BAR"}, objB) assert.NotEqual(t, typeB{"BAR"}, objB)
} }
// bodyB to typeA and typeB // bodyB to typeA and typeB
@ -2072,10 +2219,10 @@ func TestContextShouldBindBodyWith(t *testing.T) {
"POST", "http://example.com", bytes.NewBufferString(tt.bodyB), "POST", "http://example.com", bytes.NewBufferString(tt.bodyB),
) )
objA := typeA{} objA := typeA{}
assert.Error(t, c.ShouldBindBodyWith(&objA, tt.bindingA)) require.Error(t, c.ShouldBindBodyWith(&objA, tt.bindingA))
assert.NotEqual(t, typeA{"FOO"}, objA) assert.NotEqual(t, typeA{"FOO"}, objA)
objB := typeB{} objB := typeB{}
assert.NoError(t, c.ShouldBindBodyWith(&objB, tt.bindingB)) require.NoError(t, c.ShouldBindBodyWith(&objB, tt.bindingB))
assert.Equal(t, typeB{"BAR"}, objB) assert.Equal(t, typeB{"BAR"}, objB)
} }
} }
@ -2124,22 +2271,22 @@ func TestContextShouldBindBodyWithJSON(t *testing.T) {
objJSON := typeJSON{} objJSON := typeJSON{}
if tt.bindingBody == binding.JSON { if tt.bindingBody == binding.JSON {
assert.NoError(t, c.ShouldBindBodyWithJSON(&objJSON)) require.NoError(t, c.ShouldBindBodyWithJSON(&objJSON))
assert.Equal(t, typeJSON{"FOO"}, objJSON) assert.Equal(t, typeJSON{"FOO"}, objJSON)
} }
if tt.bindingBody == binding.XML { if tt.bindingBody == binding.XML {
assert.Error(t, c.ShouldBindBodyWithJSON(&objJSON)) require.Error(t, c.ShouldBindBodyWithJSON(&objJSON))
assert.Equal(t, typeJSON{}, objJSON) assert.Equal(t, typeJSON{}, objJSON)
} }
if tt.bindingBody == binding.YAML { if tt.bindingBody == binding.YAML {
assert.Error(t, c.ShouldBindBodyWithJSON(&objJSON)) require.Error(t, c.ShouldBindBodyWithJSON(&objJSON))
assert.Equal(t, typeJSON{}, objJSON) assert.Equal(t, typeJSON{}, objJSON)
} }
if tt.bindingBody == binding.TOML { if tt.bindingBody == binding.TOML {
assert.Error(t, c.ShouldBindBodyWithJSON(&objJSON)) require.Error(t, c.ShouldBindBodyWithJSON(&objJSON))
assert.Equal(t, typeJSON{}, objJSON) assert.Equal(t, typeJSON{}, objJSON)
} }
} }
@ -2188,22 +2335,22 @@ func TestContextShouldBindBodyWithXML(t *testing.T) {
objXML := typeXML{} objXML := typeXML{}
if tt.bindingBody == binding.JSON { if tt.bindingBody == binding.JSON {
assert.Error(t, c.ShouldBindBodyWithXML(&objXML)) require.Error(t, c.ShouldBindBodyWithXML(&objXML))
assert.Equal(t, typeXML{}, objXML) assert.Equal(t, typeXML{}, objXML)
} }
if tt.bindingBody == binding.XML { if tt.bindingBody == binding.XML {
assert.NoError(t, c.ShouldBindBodyWithXML(&objXML)) require.NoError(t, c.ShouldBindBodyWithXML(&objXML))
assert.Equal(t, typeXML{"FOO"}, objXML) assert.Equal(t, typeXML{"FOO"}, objXML)
} }
if tt.bindingBody == binding.YAML { if tt.bindingBody == binding.YAML {
assert.Error(t, c.ShouldBindBodyWithXML(&objXML)) require.Error(t, c.ShouldBindBodyWithXML(&objXML))
assert.Equal(t, typeXML{}, objXML) assert.Equal(t, typeXML{}, objXML)
} }
if tt.bindingBody == binding.TOML { if tt.bindingBody == binding.TOML {
assert.Error(t, c.ShouldBindBodyWithXML(&objXML)) require.Error(t, c.ShouldBindBodyWithXML(&objXML))
assert.Equal(t, typeXML{}, objXML) assert.Equal(t, typeXML{}, objXML)
} }
} }
@ -2253,22 +2400,22 @@ func TestContextShouldBindBodyWithYAML(t *testing.T) {
// YAML belongs to a super collection of JSON, so JSON can be parsed by YAML // YAML belongs to a super collection of JSON, so JSON can be parsed by YAML
if tt.bindingBody == binding.JSON { if tt.bindingBody == binding.JSON {
assert.NoError(t, c.ShouldBindBodyWithYAML(&objYAML)) require.NoError(t, c.ShouldBindBodyWithYAML(&objYAML))
assert.Equal(t, typeYAML{"FOO"}, objYAML) assert.Equal(t, typeYAML{"FOO"}, objYAML)
} }
if tt.bindingBody == binding.XML { if tt.bindingBody == binding.XML {
assert.Error(t, c.ShouldBindBodyWithYAML(&objYAML)) require.Error(t, c.ShouldBindBodyWithYAML(&objYAML))
assert.Equal(t, typeYAML{}, objYAML) assert.Equal(t, typeYAML{}, objYAML)
} }
if tt.bindingBody == binding.YAML { if tt.bindingBody == binding.YAML {
assert.NoError(t, c.ShouldBindBodyWithYAML(&objYAML)) require.NoError(t, c.ShouldBindBodyWithYAML(&objYAML))
assert.Equal(t, typeYAML{"FOO"}, objYAML) assert.Equal(t, typeYAML{"FOO"}, objYAML)
} }
if tt.bindingBody == binding.TOML { if tt.bindingBody == binding.TOML {
assert.Error(t, c.ShouldBindBodyWithYAML(&objYAML)) require.Error(t, c.ShouldBindBodyWithYAML(&objYAML))
assert.Equal(t, typeYAML{}, objYAML) assert.Equal(t, typeYAML{}, objYAML)
} }
} }
@ -2317,22 +2464,22 @@ func TestContextShouldBindBodyWithTOML(t *testing.T) {
objTOML := typeTOML{} objTOML := typeTOML{}
if tt.bindingBody == binding.JSON { if tt.bindingBody == binding.JSON {
assert.Error(t, c.ShouldBindBodyWithTOML(&objTOML)) require.Error(t, c.ShouldBindBodyWithTOML(&objTOML))
assert.Equal(t, typeTOML{}, objTOML) assert.Equal(t, typeTOML{}, objTOML)
} }
if tt.bindingBody == binding.XML { if tt.bindingBody == binding.XML {
assert.Error(t, c.ShouldBindBodyWithTOML(&objTOML)) require.Error(t, c.ShouldBindBodyWithTOML(&objTOML))
assert.Equal(t, typeTOML{}, objTOML) assert.Equal(t, typeTOML{}, objTOML)
} }
if tt.bindingBody == binding.YAML { if tt.bindingBody == binding.YAML {
assert.Error(t, c.ShouldBindBodyWithTOML(&objTOML)) require.Error(t, c.ShouldBindBodyWithTOML(&objTOML))
assert.Equal(t, typeTOML{}, objTOML) assert.Equal(t, typeTOML{}, objTOML)
} }
if tt.bindingBody == binding.TOML { if tt.bindingBody == binding.TOML {
assert.NoError(t, c.ShouldBindBodyWithTOML(&objTOML)) require.NoError(t, c.ShouldBindBodyWithTOML(&objTOML))
assert.Equal(t, typeTOML{"FOO"}, objTOML) assert.Equal(t, typeTOML{"FOO"}, objTOML)
} }
} }
@ -2387,27 +2534,27 @@ func TestContextShouldBindBodyWithPlain(t *testing.T) {
if tt.bindingBody == binding.Plain { if tt.bindingBody == binding.Plain {
body := "" body := ""
assert.NoError(t, c.ShouldBindBodyWithPlain(&body)) require.NoError(t, c.ShouldBindBodyWithPlain(&body))
assert.Equal(t, body, "foo=FOO") assert.Equal(t, "foo=FOO", body)
} }
if tt.bindingBody == binding.JSON { if tt.bindingBody == binding.JSON {
assert.NoError(t, c.ShouldBindBodyWithJSON(&objJSON)) require.NoError(t, c.ShouldBindBodyWithJSON(&objJSON))
assert.Equal(t, typeJSON{"FOO"}, objJSON) assert.Equal(t, typeJSON{"FOO"}, objJSON)
} }
if tt.bindingBody == binding.XML { if tt.bindingBody == binding.XML {
assert.Error(t, c.ShouldBindBodyWithJSON(&objJSON)) require.Error(t, c.ShouldBindBodyWithJSON(&objJSON))
assert.Equal(t, typeJSON{}, objJSON) assert.Equal(t, typeJSON{}, objJSON)
} }
if tt.bindingBody == binding.YAML { if tt.bindingBody == binding.YAML {
assert.Error(t, c.ShouldBindBodyWithJSON(&objJSON)) require.Error(t, c.ShouldBindBodyWithJSON(&objJSON))
assert.Equal(t, typeJSON{}, objJSON) assert.Equal(t, typeJSON{}, objJSON)
} }
if tt.bindingBody == binding.TOML { if tt.bindingBody == binding.TOML {
assert.Error(t, c.ShouldBindBodyWithJSON(&objJSON)) require.Error(t, c.ShouldBindBodyWithJSON(&objJSON))
assert.Equal(t, typeJSON{}, objJSON) assert.Equal(t, typeJSON{}, objJSON)
} }
} }
@ -2416,10 +2563,10 @@ func TestContextShouldBindBodyWithPlain(t *testing.T) {
func TestContextGolangContext(t *testing.T) { func TestContextGolangContext(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder()) c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}")) c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
assert.NoError(t, c.Err()) require.NoError(t, c.Err())
assert.Nil(t, c.Done()) assert.Nil(t, c.Done())
ti, ok := c.Deadline() ti, ok := c.Deadline()
assert.Equal(t, ti, time.Time{}) assert.Equal(t, time.Time{}, ti)
assert.False(t, ok) assert.False(t, ok)
assert.Equal(t, c.Value(ContextRequestKey), c.Request) assert.Equal(t, c.Value(ContextRequestKey), c.Request)
assert.Equal(t, c.Value(ContextKey), c) assert.Equal(t, c.Value(ContextKey), c)
@ -2468,7 +2615,7 @@ func TestContextGetRawData(t *testing.T) {
c.Request.Header.Add("Content-Type", MIMEPOSTForm) c.Request.Header.Add("Content-Type", MIMEPOSTForm)
data, err := c.GetRawData() data, err := c.GetRawData()
assert.Nil(t, err) require.NoError(t, err)
assert.Equal(t, "Fetch binary post data", string(data)) assert.Equal(t, "Fetch binary post data", string(data))
} }
@ -2539,7 +2686,7 @@ func TestContextStream(t *testing.T) {
}() }()
_, err := w.Write([]byte("test")) _, err := w.Write([]byte("test"))
assert.NoError(t, err) require.NoError(t, err)
return stopStream return stopStream
}) })
@ -2557,7 +2704,7 @@ func TestContextStreamWithClientGone(t *testing.T) {
}() }()
_, err := writer.Write([]byte("test")) _, err := writer.Write([]byte("test"))
assert.NoError(t, err) require.NoError(t, err)
return true return true
}) })
@ -2685,7 +2832,7 @@ func TestContextWithFallbackErrFromRequestContext(t *testing.T) {
// enable ContextWithFallback feature flag // enable ContextWithFallback feature flag
c.engine.ContextWithFallback = true c.engine.ContextWithFallback = true
assert.Nil(t, c.Err()) require.NoError(t, c.Err())
c2, _ := CreateTestContext(httptest.NewRecorder()) c2, _ := CreateTestContext(httptest.NewRecorder())
// enable ContextWithFallback feature flag // enable ContextWithFallback feature flag
@ -2834,7 +2981,7 @@ func TestContextAddParam(t *testing.T) {
c.AddParam(id, value) c.AddParam(id, value)
v, ok := c.Params.Get(id) v, ok := c.Params.Get(id)
assert.Equal(t, ok, true) assert.True(t, ok)
assert.Equal(t, value, v) assert.Equal(t, value, v)
} }

View File

@ -17,6 +17,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
// TODO // TODO
@ -154,13 +155,13 @@ func TestGetMinVer(t *testing.T) {
var m uint64 var m uint64
var e error var e error
_, e = getMinVer("go1") _, e = getMinVer("go1")
assert.NotNil(t, e) require.Error(t, e)
m, e = getMinVer("go1.1") m, e = getMinVer("go1.1")
assert.Equal(t, uint64(1), m) assert.Equal(t, uint64(1), m)
assert.Nil(t, e) require.NoError(t, e)
m, e = getMinVer("go1.1.1") m, e = getMinVer("go1.1.1")
assert.Nil(t, e) require.NoError(t, e)
assert.Equal(t, uint64(1), m) assert.Equal(t, uint64(1), m)
_, e = getMinVer("go1.1.1.1") _, e = getMinVer("go1.1.1.1")
assert.NotNil(t, e) require.Error(t, e)
} }

View File

@ -26,6 +26,8 @@
- [Custom Validators](#custom-validators) - [Custom Validators](#custom-validators)
- [Only Bind Query String](#only-bind-query-string) - [Only Bind Query String](#only-bind-query-string)
- [Bind Query String or Post Data](#bind-query-string-or-post-data) - [Bind Query String or Post Data](#bind-query-string-or-post-data)
- [Bind default value if none provided](#bind-default-value-if-none-provided)
- [Collection format for arrays](#collection-format-for-arrays)
- [Bind Uri](#bind-uri) - [Bind Uri](#bind-uri)
- [Bind custom unmarshaler](#bind-custom-unmarshaler) - [Bind custom unmarshaler](#bind-custom-unmarshaler)
- [Bind Header](#bind-header) - [Bind Header](#bind-header)
@ -338,16 +340,16 @@ func main() {
router := gin.Default() router := gin.Default()
// Simple group: v1 // Simple group: v1
v1 := router.Group("/v1")
{ {
v1 := router.Group("/v1")
v1.POST("/login", loginEndpoint) v1.POST("/login", loginEndpoint)
v1.POST("/submit", submitEndpoint) v1.POST("/submit", submitEndpoint)
v1.POST("/read", readEndpoint) v1.POST("/read", readEndpoint)
} }
// Simple group: v2 // Simple group: v2
v2 := router.Group("/v2")
{ {
v2 := router.Group("/v2")
v2.POST("/login", loginEndpoint) v2.POST("/login", loginEndpoint)
v2.POST("/submit", submitEndpoint) v2.POST("/submit", submitEndpoint)
v2.POST("/read", readEndpoint) v2.POST("/read", readEndpoint)
@ -524,7 +526,7 @@ func main() {
return c.Writer.Status() < http.StatusInternalServerError return c.Writer.Status() < http.StatusInternalServerError
} }
engine.Use(gin.LoggerWithConfig(loggerConfig)) router.Use(gin.LoggerWithConfig(loggerConfig))
router.Use(gin.Recovery()) router.Use(gin.Recovery())
// skipped // skipped
@ -861,6 +863,106 @@ Test it with:
curl -X GET "localhost:8085/testing?name=appleboy&address=xyz&birthday=1992-03-15&createTime=1562400033000000123&unixTime=1562400033" curl -X GET "localhost:8085/testing?name=appleboy&address=xyz&birthday=1992-03-15&createTime=1562400033000000123&unixTime=1562400033"
``` ```
### Bind default value if none provided
If the server should bind a default value to a field when the client does not provide one, specify the default value using the `default` key within the `form` tag:
```
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
type Person struct {
Name string `form:"name,default=William"`
Age int `form:"age,default=10"`
Friends []string `form:"friends,default=Will;Bill"`
Addresses [2]string `form:"addresses,default=foo bar" collection_format:"ssv"`
LapTimes []int `form:"lap_times,default=1;2;3" collection_format:"csv"`
}
func main() {
g := gin.Default()
g.POST("/person", func(c *gin.Context) {
var req Person
if err := c.ShouldBindQuery(&req); err != nil {
c.JSON(http.StatusBadRequest, err)
return
}
c.JSON(http.StatusOK, req)
})
_ = g.Run("localhost:8080")
}
```
```
curl -X POST http://localhost:8080/person
{"Name":"William","Age":10,"Friends":["Will","Bill"],"Colors":["red","blue"],"LapTimes":[1,2,3]}
```
NOTE: For default [collection values](#collection-format-for-arrays), the following rules apply:
- Since commas are used to delimit tag options, they are not supported within a default value and will result in undefined behavior
- For the collection formats "multi" and "csv", a semicolon should be used in place of a comma to delimited default values
- Since semicolons are used to delimit default values for "multi" and "csv", they are not supported within a default value for "multi" and "csv"
#### Collection format for arrays
| Format | Description | Example |
| --------------- | --------------------------------------------------------- | ----------------------- |
| multi (default) | Multiple parameter instances rather than multiple values. | key=foo&key=bar&key=baz |
| csv | Comma-separated values. | foo,bar,baz |
| ssv | Space-separated values. | foo bar baz |
| tsv | Tab-separated values. | "foo\tbar\tbaz" |
| pipes | Pipe-separated values. | foo\|bar\|baz |
```go
package main
import (
"log"
"time"
"github.com/gin-gonic/gin"
)
type Person struct {
Name string `form:"name"`
Addresses []string `form:"addresses" collection_format:"csv"`
Birthday time.Time `form:"birthday" time_format:"2006-01-02" time_utc:"1"`
CreateTime time.Time `form:"createTime" time_format:"unixNano"`
UnixTime time.Time `form:"unixTime" time_format:"unix"`
}
func main() {
route := gin.Default()
route.GET("/testing", startPage)
route.Run(":8085")
}
func startPage(c *gin.Context) {
var person Person
// If `GET`, only `Form` binding engine (`query`) used.
// If `POST`, first checks the `content-type` for `JSON` or `XML`, then uses `Form` (`form-data`).
// See more at https://github.com/gin-gonic/gin/blob/master/binding/binding.go#L48
if c.ShouldBind(&person) == nil {
log.Println(person.Name)
log.Println(person.Addresses)
log.Println(person.Birthday)
log.Println(person.CreateTime)
log.Println(person.UnixTime)
}
c.String(200, "Success")
}
```
Test it with:
```sh
$ curl -X GET "localhost:8085/testing?name=appleboy&addresses=foo,bar&birthday=1992-03-15&createTime=1562400033000000123&unixTime=1562400033"
```
### Bind Uri ### Bind Uri
See the [detail information](https://github.com/gin-gonic/gin/issues/846). See the [detail information](https://github.com/gin-gonic/gin/issues/846).

View File

@ -11,6 +11,7 @@ import (
"github.com/gin-gonic/gin/internal/json" "github.com/gin-gonic/gin/internal/json"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestError(t *testing.T) { func TestError(t *testing.T) {
@ -122,7 +123,7 @@ func TestErrorUnwrap(t *testing.T) {
}) })
// check that 'errors.Is()' and 'errors.As()' behave as expected : // check that 'errors.Is()' and 'errors.As()' behave as expected :
assert.True(t, errors.Is(err, innerErr)) require.ErrorIs(t, err, innerErr)
var testErr TestErr var testErr TestErr
assert.True(t, errors.As(err, &testErr)) require.ErrorAs(t, err, &testErr)
} }

View File

@ -7,6 +7,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
type mockFileSystem struct { type mockFileSystem struct {
@ -28,7 +29,7 @@ func TestOnlyFilesFS_Open(t *testing.T) {
file, err := fs.Open("foo") file, err := fs.Open("foo")
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, testFile, file.(neutralizedReaddirFile).File) assert.Equal(t, testFile, file.(neutralizedReaddirFile).File)
} }
@ -43,7 +44,7 @@ func TestOnlyFilesFS_Open_err(t *testing.T) {
file, err := fs.Open("foo") file, err := fs.Open("foo")
assert.ErrorIs(t, err, testError) require.ErrorIs(t, err, testError)
assert.Nil(t, file) assert.Nil(t, file)
} }
@ -52,7 +53,7 @@ func Test_neuteredReaddirFile_Readdir(t *testing.T) {
res, err := n.Readdir(0) res, err := n.Readdir(0)
assert.NoError(t, err) require.NoError(t, err)
assert.Nil(t, res) assert.Nil(t, res)
} }

6
gin.go
View File

@ -15,6 +15,7 @@ import (
"strings" "strings"
"sync" "sync"
"git.vinchent.xyz/vinchent/go-web/framework"
"github.com/gin-gonic/gin/internal/bytesconv" "github.com/gin-gonic/gin/internal/bytesconv"
"github.com/gin-gonic/gin/render" "github.com/gin-gonic/gin/render"
@ -178,6 +179,9 @@ type Engine struct {
maxSections uint16 maxSections uint16
trustedProxies []string trustedProxies []string
trustedCIDRs []*net.IPNet trustedCIDRs []*net.IPNet
// GoWeb service container
container framework.Container
} }
var _ IRouter = (*Engine)(nil) var _ IRouter = (*Engine)(nil)
@ -687,7 +691,7 @@ func (engine *Engine) handleHTTPRequest(c *Context) {
break break
} }
if engine.HandleMethodNotAllowed { if engine.HandleMethodNotAllowed && len(t) > 0 {
// According to RFC 7231 section 6.5.5, MUST generate an Allow header field in response // According to RFC 7231 section 6.5.5, MUST generate an Allow header field in response
// containing a list of the target resource's currently supported methods. // containing a list of the target resource's currently supported methods.
allowed := make([]string, 0, len(t)-1) allowed := make([]string, 0, len(t)-1)

View File

@ -21,6 +21,7 @@ import (
"time" "time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
// params[0]=url example:http://127.0.0.1:8080/index (cannot be empty) // params[0]=url example:http://127.0.0.1:8080/index (cannot be empty)
@ -40,11 +41,11 @@ func testRequest(t *testing.T, params ...string) {
client := &http.Client{Transport: tr} client := &http.Client{Transport: tr}
resp, err := client.Get(params[0]) resp, err := client.Get(params[0])
assert.NoError(t, err) require.NoError(t, err)
defer resp.Body.Close() defer resp.Body.Close()
body, ioerr := io.ReadAll(resp.Body) body, ioerr := io.ReadAll(resp.Body)
assert.NoError(t, ioerr) require.NoError(t, ioerr)
var responseStatus = "200 OK" var responseStatus = "200 OK"
if len(params) > 1 && params[1] != "" { if len(params) > 1 && params[1] != "" {
@ -73,13 +74,13 @@ func TestRunEmpty(t *testing.T) {
// otherwise the main thread will complete // otherwise the main thread will complete
time.Sleep(5 * time.Millisecond) time.Sleep(5 * time.Millisecond)
assert.Error(t, router.Run(":8080")) require.Error(t, router.Run(":8080"))
testRequest(t, "http://localhost:8080/example") testRequest(t, "http://localhost:8080/example")
} }
func TestBadTrustedCIDRs(t *testing.T) { func TestBadTrustedCIDRs(t *testing.T) {
router := New() router := New()
assert.Error(t, router.SetTrustedProxies([]string{"hello/world"})) require.Error(t, router.SetTrustedProxies([]string{"hello/world"}))
} }
/* legacy tests /* legacy tests
@ -87,7 +88,7 @@ func TestBadTrustedCIDRsForRun(t *testing.T) {
os.Setenv("PORT", "") os.Setenv("PORT", "")
router := New() router := New()
router.TrustedProxies = []string{"hello/world"} router.TrustedProxies = []string{"hello/world"}
assert.Error(t, router.Run(":8080")) require.Error(t, router.Run(":8080"))
} }
func TestBadTrustedCIDRsForRunUnix(t *testing.T) { func TestBadTrustedCIDRsForRunUnix(t *testing.T) {
@ -100,7 +101,7 @@ func TestBadTrustedCIDRsForRunUnix(t *testing.T) {
go func() { go func() {
router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") }) router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") })
assert.Error(t, router.RunUnix(unixTestSocket)) require.Error(t, router.RunUnix(unixTestSocket))
}() }()
// have to wait for the goroutine to start and run the server // have to wait for the goroutine to start and run the server
// otherwise the main thread will complete // otherwise the main thread will complete
@ -112,15 +113,15 @@ func TestBadTrustedCIDRsForRunFd(t *testing.T) {
router.TrustedProxies = []string{"hello/world"} router.TrustedProxies = []string{"hello/world"}
addr, err := net.ResolveTCPAddr("tcp", "localhost:0") addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
assert.NoError(t, err) require.NoError(t, err)
listener, err := net.ListenTCP("tcp", addr) listener, err := net.ListenTCP("tcp", addr)
assert.NoError(t, err) require.NoError(t, err)
socketFile, err := listener.File() socketFile, err := listener.File()
assert.NoError(t, err) require.NoError(t, err)
go func() { go func() {
router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") }) router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") })
assert.Error(t, router.RunFd(int(socketFile.Fd()))) require.Error(t, router.RunFd(int(socketFile.Fd())))
}() }()
// have to wait for the goroutine to start and run the server // have to wait for the goroutine to start and run the server
// otherwise the main thread will complete // otherwise the main thread will complete
@ -132,12 +133,12 @@ func TestBadTrustedCIDRsForRunListener(t *testing.T) {
router.TrustedProxies = []string{"hello/world"} router.TrustedProxies = []string{"hello/world"}
addr, err := net.ResolveTCPAddr("tcp", "localhost:0") addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
assert.NoError(t, err) require.NoError(t, err)
listener, err := net.ListenTCP("tcp", addr) listener, err := net.ListenTCP("tcp", addr)
assert.NoError(t, err) require.NoError(t, err)
go func() { go func() {
router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") }) router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") })
assert.Error(t, router.RunListener(listener)) require.Error(t, router.RunListener(listener))
}() }()
// have to wait for the goroutine to start and run the server // have to wait for the goroutine to start and run the server
// otherwise the main thread will complete // otherwise the main thread will complete
@ -148,7 +149,7 @@ func TestBadTrustedCIDRsForRunTLS(t *testing.T) {
os.Setenv("PORT", "") os.Setenv("PORT", "")
router := New() router := New()
router.TrustedProxies = []string{"hello/world"} router.TrustedProxies = []string{"hello/world"}
assert.Error(t, router.RunTLS(":8080", "./testdata/certificate/cert.pem", "./testdata/certificate/key.pem")) require.Error(t, router.RunTLS(":8080", "./testdata/certificate/cert.pem", "./testdata/certificate/key.pem"))
} }
*/ */
@ -164,7 +165,7 @@ func TestRunTLS(t *testing.T) {
// otherwise the main thread will complete // otherwise the main thread will complete
time.Sleep(5 * time.Millisecond) time.Sleep(5 * time.Millisecond)
assert.Error(t, router.RunTLS(":8443", "./testdata/certificate/cert.pem", "./testdata/certificate/key.pem")) require.Error(t, router.RunTLS(":8443", "./testdata/certificate/cert.pem", "./testdata/certificate/key.pem"))
testRequest(t, "https://localhost:8443/example") testRequest(t, "https://localhost:8443/example")
} }
@ -201,7 +202,7 @@ func TestPusher(t *testing.T) {
// otherwise the main thread will complete // otherwise the main thread will complete
time.Sleep(5 * time.Millisecond) time.Sleep(5 * time.Millisecond)
assert.Error(t, router.RunTLS(":8449", "./testdata/certificate/cert.pem", "./testdata/certificate/key.pem")) require.Error(t, router.RunTLS(":8449", "./testdata/certificate/cert.pem", "./testdata/certificate/key.pem"))
testRequest(t, "https://localhost:8449/pusher") testRequest(t, "https://localhost:8449/pusher")
} }
@ -216,14 +217,14 @@ func TestRunEmptyWithEnv(t *testing.T) {
// otherwise the main thread will complete // otherwise the main thread will complete
time.Sleep(5 * time.Millisecond) time.Sleep(5 * time.Millisecond)
assert.Error(t, router.Run(":3123")) require.Error(t, router.Run(":3123"))
testRequest(t, "http://localhost:3123/example") testRequest(t, "http://localhost:3123/example")
} }
func TestRunTooMuchParams(t *testing.T) { func TestRunTooMuchParams(t *testing.T) {
router := New() router := New()
assert.Panics(t, func() { assert.Panics(t, func() {
assert.NoError(t, router.Run("2", "2")) require.NoError(t, router.Run("2", "2"))
}) })
} }
@ -237,7 +238,7 @@ func TestRunWithPort(t *testing.T) {
// otherwise the main thread will complete // otherwise the main thread will complete
time.Sleep(5 * time.Millisecond) time.Sleep(5 * time.Millisecond)
assert.Error(t, router.Run(":5150")) require.Error(t, router.Run(":5150"))
testRequest(t, "http://localhost:5150/example") testRequest(t, "http://localhost:5150/example")
} }
@ -257,7 +258,7 @@ func TestUnixSocket(t *testing.T) {
time.Sleep(5 * time.Millisecond) time.Sleep(5 * time.Millisecond)
c, err := net.Dial("unix", unixTestSocket) c, err := net.Dial("unix", unixTestSocket)
assert.NoError(t, err) require.NoError(t, err)
fmt.Fprint(c, "GET /example HTTP/1.0\r\n\r\n") fmt.Fprint(c, "GET /example HTTP/1.0\r\n\r\n")
scanner := bufio.NewScanner(c) scanner := bufio.NewScanner(c)
@ -271,7 +272,7 @@ func TestUnixSocket(t *testing.T) {
func TestBadUnixSocket(t *testing.T) { func TestBadUnixSocket(t *testing.T) {
router := New() router := New()
assert.Error(t, router.RunUnix("#/tmp/unix_unit_test")) require.Error(t, router.RunUnix("#/tmp/unix_unit_test"))
} }
func TestRunQUIC(t *testing.T) { func TestRunQUIC(t *testing.T) {
@ -286,7 +287,7 @@ func TestRunQUIC(t *testing.T) {
// otherwise the main thread will complete // otherwise the main thread will complete
time.Sleep(5 * time.Millisecond) time.Sleep(5 * time.Millisecond)
assert.Error(t, router.RunQUIC(":8443", "./testdata/certificate/cert.pem", "./testdata/certificate/key.pem")) require.Error(t, router.RunQUIC(":8443", "./testdata/certificate/cert.pem", "./testdata/certificate/key.pem"))
testRequest(t, "https://localhost:8443/example") testRequest(t, "https://localhost:8443/example")
} }
@ -294,15 +295,15 @@ func TestFileDescriptor(t *testing.T) {
router := New() router := New()
addr, err := net.ResolveTCPAddr("tcp", "localhost:0") addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
assert.NoError(t, err) require.NoError(t, err)
listener, err := net.ListenTCP("tcp", addr) listener, err := net.ListenTCP("tcp", addr)
assert.NoError(t, err) require.NoError(t, err)
socketFile, err := listener.File() socketFile, err := listener.File()
if isWindows() { if isWindows() {
// not supported by windows, it is unimplemented now // not supported by windows, it is unimplemented now
assert.Error(t, err) require.Error(t, err)
} else { } else {
assert.NoError(t, err) require.NoError(t, err)
} }
if socketFile == nil { if socketFile == nil {
@ -318,7 +319,7 @@ func TestFileDescriptor(t *testing.T) {
time.Sleep(5 * time.Millisecond) time.Sleep(5 * time.Millisecond)
c, err := net.Dial("tcp", listener.Addr().String()) c, err := net.Dial("tcp", listener.Addr().String())
assert.NoError(t, err) require.NoError(t, err)
fmt.Fprintf(c, "GET /example HTTP/1.0\r\n\r\n") fmt.Fprintf(c, "GET /example HTTP/1.0\r\n\r\n")
scanner := bufio.NewScanner(c) scanner := bufio.NewScanner(c)
@ -332,15 +333,15 @@ func TestFileDescriptor(t *testing.T) {
func TestBadFileDescriptor(t *testing.T) { func TestBadFileDescriptor(t *testing.T) {
router := New() router := New()
assert.Error(t, router.RunFd(0)) require.Error(t, router.RunFd(0))
} }
func TestListener(t *testing.T) { func TestListener(t *testing.T) {
router := New() router := New()
addr, err := net.ResolveTCPAddr("tcp", "localhost:0") addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
assert.NoError(t, err) require.NoError(t, err)
listener, err := net.ListenTCP("tcp", addr) listener, err := net.ListenTCP("tcp", addr)
assert.NoError(t, err) require.NoError(t, err)
go func() { go func() {
router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") }) router.GET("/example", func(c *Context) { c.String(http.StatusOK, "it worked") })
assert.NoError(t, router.RunListener(listener)) assert.NoError(t, router.RunListener(listener))
@ -350,7 +351,7 @@ func TestListener(t *testing.T) {
time.Sleep(5 * time.Millisecond) time.Sleep(5 * time.Millisecond)
c, err := net.Dial("tcp", listener.Addr().String()) c, err := net.Dial("tcp", listener.Addr().String())
assert.NoError(t, err) require.NoError(t, err)
fmt.Fprintf(c, "GET /example HTTP/1.0\r\n\r\n") fmt.Fprintf(c, "GET /example HTTP/1.0\r\n\r\n")
scanner := bufio.NewScanner(c) scanner := bufio.NewScanner(c)
@ -365,11 +366,11 @@ func TestListener(t *testing.T) {
func TestBadListener(t *testing.T) { func TestBadListener(t *testing.T) {
router := New() router := New()
addr, err := net.ResolveTCPAddr("tcp", "localhost:10086") addr, err := net.ResolveTCPAddr("tcp", "localhost:10086")
assert.NoError(t, err) require.NoError(t, err)
listener, err := net.ListenTCP("tcp", addr) listener, err := net.ListenTCP("tcp", addr)
assert.NoError(t, err) require.NoError(t, err)
listener.Close() listener.Close()
assert.Error(t, router.RunListener(listener)) require.Error(t, router.RunListener(listener))
} }
func TestWithHttptestWithAutoSelectedPort(t *testing.T) { func TestWithHttptestWithAutoSelectedPort(t *testing.T) {
@ -395,7 +396,14 @@ func TestConcurrentHandleContext(t *testing.T) {
wg.Add(iterations) wg.Add(iterations)
for i := 0; i < iterations; i++ { for i := 0; i < iterations; i++ {
go func() { go func() {
testGetRequestHandler(t, router, "/") req, err := http.NewRequest(http.MethodGet, "/", nil)
assert.NoError(t, err)
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
assert.Equal(t, "it worked", w.Body.String(), "resp body should match")
assert.Equal(t, 200, w.Code, "should get a 200")
wg.Done() wg.Done()
}() }()
} }
@ -417,17 +425,6 @@ func TestConcurrentHandleContext(t *testing.T) {
// testRequest(t, "http://localhost:8033/example") // testRequest(t, "http://localhost:8033/example")
// } // }
func testGetRequestHandler(t *testing.T, h http.Handler, url string) {
req, err := http.NewRequest(http.MethodGet, url, nil)
assert.NoError(t, err)
w := httptest.NewRecorder()
h.ServeHTTP(w, req)
assert.Equal(t, "it worked", w.Body.String(), "resp body should match")
assert.Equal(t, 200, w.Code, "should get a 200")
}
func TestTreeRunDynamicRouting(t *testing.T) { func TestTreeRunDynamicRouting(t *testing.T) {
router := New() router := New()
router.GET("/aa/*xx", func(c *Context) { c.String(http.StatusOK, "/aa/*xx") }) router.GET("/aa/*xx", func(c *Context) { c.String(http.StatusOK, "/aa/*xx") })

View File

@ -20,6 +20,7 @@ import (
"time" "time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/net/http2" "golang.org/x/net/http2"
) )
@ -547,10 +548,10 @@ func TestEngineHandleContextManyReEntries(t *testing.T) {
r.GET("/:count", func(c *Context) { r.GET("/:count", func(c *Context) {
countStr := c.Param("count") countStr := c.Param("count")
count, err := strconv.Atoi(countStr) count, err := strconv.Atoi(countStr)
assert.NoError(t, err) require.NoError(t, err)
n, err := c.Writer.Write([]byte(".")) n, err := c.Writer.Write([]byte("."))
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 1, n) assert.Equal(t, 1, n)
switch { switch {
@ -580,7 +581,7 @@ func TestPrepareTrustedCIRDsWith(t *testing.T) {
expectedTrustedCIDRs := []*net.IPNet{parseCIDR("0.0.0.0/0")} expectedTrustedCIDRs := []*net.IPNet{parseCIDR("0.0.0.0/0")}
err := r.SetTrustedProxies([]string{"0.0.0.0/0"}) err := r.SetTrustedProxies([]string{"0.0.0.0/0"})
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, expectedTrustedCIDRs, r.trustedCIDRs) assert.Equal(t, expectedTrustedCIDRs, r.trustedCIDRs)
} }
@ -588,7 +589,7 @@ func TestPrepareTrustedCIRDsWith(t *testing.T) {
{ {
err := r.SetTrustedProxies([]string{"192.168.1.33/33"}) err := r.SetTrustedProxies([]string{"192.168.1.33/33"})
assert.Error(t, err) require.Error(t, err)
} }
// valid ipv4 address // valid ipv4 address
@ -597,7 +598,7 @@ func TestPrepareTrustedCIRDsWith(t *testing.T) {
err := r.SetTrustedProxies([]string{"192.168.1.33"}) err := r.SetTrustedProxies([]string{"192.168.1.33"})
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, expectedTrustedCIDRs, r.trustedCIDRs) assert.Equal(t, expectedTrustedCIDRs, r.trustedCIDRs)
} }
@ -605,7 +606,7 @@ func TestPrepareTrustedCIRDsWith(t *testing.T) {
{ {
err := r.SetTrustedProxies([]string{"192.168.1.256"}) err := r.SetTrustedProxies([]string{"192.168.1.256"})
assert.Error(t, err) require.Error(t, err)
} }
// valid ipv6 address // valid ipv6 address
@ -613,7 +614,7 @@ func TestPrepareTrustedCIRDsWith(t *testing.T) {
expectedTrustedCIDRs := []*net.IPNet{parseCIDR("2002:0000:0000:1234:abcd:ffff:c0a8:0101/128")} expectedTrustedCIDRs := []*net.IPNet{parseCIDR("2002:0000:0000:1234:abcd:ffff:c0a8:0101/128")}
err := r.SetTrustedProxies([]string{"2002:0000:0000:1234:abcd:ffff:c0a8:0101"}) err := r.SetTrustedProxies([]string{"2002:0000:0000:1234:abcd:ffff:c0a8:0101"})
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, expectedTrustedCIDRs, r.trustedCIDRs) assert.Equal(t, expectedTrustedCIDRs, r.trustedCIDRs)
} }
@ -621,7 +622,7 @@ func TestPrepareTrustedCIRDsWith(t *testing.T) {
{ {
err := r.SetTrustedProxies([]string{"gggg:0000:0000:1234:abcd:ffff:c0a8:0101"}) err := r.SetTrustedProxies([]string{"gggg:0000:0000:1234:abcd:ffff:c0a8:0101"})
assert.Error(t, err) require.Error(t, err)
} }
// valid ipv6 cidr // valid ipv6 cidr
@ -629,7 +630,7 @@ func TestPrepareTrustedCIRDsWith(t *testing.T) {
expectedTrustedCIDRs := []*net.IPNet{parseCIDR("::/0")} expectedTrustedCIDRs := []*net.IPNet{parseCIDR("::/0")}
err := r.SetTrustedProxies([]string{"::/0"}) err := r.SetTrustedProxies([]string{"::/0"})
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, expectedTrustedCIDRs, r.trustedCIDRs) assert.Equal(t, expectedTrustedCIDRs, r.trustedCIDRs)
} }
@ -637,7 +638,7 @@ func TestPrepareTrustedCIRDsWith(t *testing.T) {
{ {
err := r.SetTrustedProxies([]string{"gggg:0000:0000:1234:abcd:ffff:c0a8:0101/129"}) err := r.SetTrustedProxies([]string{"gggg:0000:0000:1234:abcd:ffff:c0a8:0101/129"})
assert.Error(t, err) require.Error(t, err)
} }
// valid combination // valid combination
@ -653,7 +654,7 @@ func TestPrepareTrustedCIRDsWith(t *testing.T) {
"172.16.0.1", "172.16.0.1",
}) })
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, expectedTrustedCIDRs, r.trustedCIDRs) assert.Equal(t, expectedTrustedCIDRs, r.trustedCIDRs)
} }
@ -665,7 +666,7 @@ func TestPrepareTrustedCIRDsWith(t *testing.T) {
"172.16.0.256", "172.16.0.256",
}) })
assert.Error(t, err) require.Error(t, err)
} }
// nil value // nil value
@ -673,7 +674,7 @@ func TestPrepareTrustedCIRDsWith(t *testing.T) {
err := r.SetTrustedProxies(nil) err := r.SetTrustedProxies(nil)
assert.Nil(t, r.trustedCIDRs) assert.Nil(t, r.trustedCIDRs)
assert.Nil(t, err) require.NoError(t, err)
} }
} }
@ -754,3 +755,14 @@ func TestCustomUnmarshalStruct(t *testing.T) {
assert.Equal(t, 200, w.Code) assert.Equal(t, 200, w.Code)
assert.Equal(t, `"2000/01/01"`, w.Body.String()) assert.Equal(t, `"2000/01/01"`, w.Body.String())
} }
// Test the fix for https://github.com/gin-gonic/gin/issues/4002
func TestMethodNotAllowedNoRoute(t *testing.T) {
g := New()
g.HandleMethodNotAllowed = true
req := httptest.NewRequest("GET", "/", nil)
resp := httptest.NewRecorder()
assert.NotPanics(t, func() { g.ServeHTTP(resp, req) })
assert.Equal(t, http.StatusNotFound, resp.Code)
}

View File

@ -14,6 +14,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
type route struct { type route struct {
@ -295,9 +296,9 @@ 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
assert.NoError(t, c.ShouldBindUri(&person)) require.NoError(t, c.ShouldBindUri(&person))
assert.True(t, person.Name != "") assert.NotEqual(t, "", person.Name)
assert.True(t, person.ID != "") assert.NotEqual(t, "", person.ID)
c.String(http.StatusOK, "ShouldBindUri test OK") c.String(http.StatusOK, "ShouldBindUri test OK")
}) })
@ -317,9 +318,9 @@ 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
assert.NoError(t, c.BindUri(&person)) require.NoError(t, c.BindUri(&person))
assert.True(t, person.Name != "") assert.NotEqual(t, "", person.Name)
assert.True(t, person.ID != "") assert.NotEqual(t, "", person.ID)
c.String(http.StatusOK, "BindUri test OK") c.String(http.StatusOK, "BindUri test OK")
}) })
@ -338,7 +339,7 @@ func TestBindUriError(t *testing.T) {
} }
router.Handle(http.MethodGet, "/new/rest/:num", func(c *Context) { router.Handle(http.MethodGet, "/new/rest/:num", func(c *Context) {
var m Member var m Member
assert.Error(t, c.BindUri(&m)) require.Error(t, c.BindUri(&m))
}) })
path1, _ := exampleFromPath("/new/rest/:num") path1, _ := exampleFromPath("/new/rest/:num")

28
go.mod
View File

@ -1,8 +1,11 @@
module github.com/gin-gonic/gin module github.com/gin-gonic/gin
go 1.21.0 go 1.22.5
toolchain go1.23.1
require ( require (
git.vinchent.xyz/vinchent/go-web v0.0.0-20240929215000-f0fc7ee2cb65
github.com/bytedance/sonic v1.11.6 github.com/bytedance/sonic v1.11.6
github.com/gin-contrib/sse v0.1.0 github.com/gin-contrib/sse v0.1.0
github.com/go-playground/validator/v10 v10.20.0 github.com/go-playground/validator/v10 v10.20.0
@ -13,7 +16,7 @@ require (
github.com/quic-go/quic-go v0.43.1 github.com/quic-go/quic-go v0.43.1
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.9.0
github.com/ugorji/go/codec v1.2.12 github.com/ugorji/go/codec v1.2.12
golang.org/x/net v0.25.0 golang.org/x/net v0.27.0
google.golang.org/protobuf v1.34.1 google.golang.org/protobuf v1.34.1
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
@ -28,21 +31,24 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/onsi/ginkgo/v2 v2.9.5 // indirect github.com/onsi/ginkgo/v2 v2.9.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
go.uber.org/mock v0.4.0 // indirect go.uber.org/mock v0.4.0 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.23.0 // indirect golang.org/x/crypto v0.25.0 // indirect
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
golang.org/x/mod v0.11.0 // indirect golang.org/x/mod v0.17.0 // indirect
golang.org/x/sys v0.20.0 // indirect golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.15.0 // indirect golang.org/x/text v0.16.0 // indirect
golang.org/x/tools v0.9.1 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
) )
replace git.vinchent.xyz/vinchent/go-web/ => ./../../

43
go.sum
View File

@ -1,3 +1,5 @@
git.vinchent.xyz/vinchent/go-web v0.0.0-20240929215000-f0fc7ee2cb65 h1:7sHTzY0WpgX4UW2g+dp+icvRyfcreP1fknOJ7/EDvtY=
git.vinchent.xyz/vinchent/go-web v0.0.0-20240929215000-f0fc7ee2cb65/go.mod h1:0t1NertSVVZD1FU7F6RkLb1Y5lcLU96pWygIOIeYjTI=
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
@ -33,16 +35,17 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
@ -52,8 +55,9 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
@ -62,7 +66,6 @@ github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
@ -90,26 +93,30 @@ github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65E
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
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.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o= golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
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.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

27
goweb_context.go Normal file
View File

@ -0,0 +1,27 @@
package gin
import "git.vinchent.xyz/vinchent/go-web/framework"
// Engine handles the bind process
func (engine *Engine) Bind(provider framework.ServiceProvider) error {
return engine.container.Bind(provider)
}
func (engine *Engine) IsBound(key string) bool {
return engine.container.IsBound(key)
}
// Context handle the use process.
func (ctx *Context) Make(name string) (interface{}, error) {
return ctx.container.Make(name)
}
func (ctx *Context) MustMake(name string) interface{} {
return ctx.container.MustMake(name)
}
func (ctx *Context) MakeNew(name string, params []interface{}) (interface{}, error) {
return ctx.container.MakeNew(name, params)
}

View File

@ -329,13 +329,13 @@ func TestIsOutputColor(t *testing.T) {
} }
consoleColorMode = autoColor consoleColorMode = autoColor
assert.Equal(t, true, p.IsOutputColor()) assert.True(t, p.IsOutputColor())
ForceConsoleColor() ForceConsoleColor()
assert.Equal(t, true, p.IsOutputColor()) assert.True(t, p.IsOutputColor())
DisableConsoleColor() DisableConsoleColor()
assert.Equal(t, false, p.IsOutputColor()) assert.False(t, p.IsOutputColor())
// test with isTerm flag false. // test with isTerm flag false.
p = LogFormatterParams{ p = LogFormatterParams{
@ -343,13 +343,13 @@ func TestIsOutputColor(t *testing.T) {
} }
consoleColorMode = autoColor consoleColorMode = autoColor
assert.Equal(t, false, p.IsOutputColor()) assert.False(t, p.IsOutputColor())
ForceConsoleColor() ForceConsoleColor()
assert.Equal(t, true, p.IsOutputColor()) assert.True(t, p.IsOutputColor())
DisableConsoleColor() DisableConsoleColor()
assert.Equal(t, false, p.IsOutputColor()) assert.False(t, p.IsOutputColor())
// reset console color mode. // reset console color mode.
consoleColorMode = autoColor consoleColorMode = autoColor

View File

@ -87,7 +87,7 @@ func TestPathCleanMallocs(t *testing.T) {
for _, test := range cleanTests { for _, test := range cleanTests {
allocs := testing.AllocsPerRun(100, func() { cleanPath(test.result) }) allocs := testing.AllocsPerRun(100, func() { cleanPath(test.result) })
assert.EqualValues(t, allocs, 0) assert.InDelta(t, 0, allocs, 0.01)
} }
} }

View File

@ -12,6 +12,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/ugorji/go/codec" "github.com/ugorji/go/codec"
) )
@ -29,7 +30,7 @@ func TestRenderMsgPack(t *testing.T) {
err := (MsgPack{data}).Render(w) err := (MsgPack{data}).Render(w)
assert.NoError(t, err) require.NoError(t, err)
h := new(codec.MsgpackHandle) h := new(codec.MsgpackHandle)
assert.NotNil(t, h) assert.NotNil(t, h)
@ -37,7 +38,7 @@ func TestRenderMsgPack(t *testing.T) {
assert.NotNil(t, buf) assert.NotNil(t, buf)
err = codec.NewEncoder(buf, h).Encode(data) err = codec.NewEncoder(buf, h).Encode(data)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, w.Body.String(), buf.String()) assert.Equal(t, w.Body.String(), buf.String())
assert.Equal(t, "application/msgpack; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "application/msgpack; charset=utf-8", w.Header().Get("Content-Type"))
} }

View File

@ -18,6 +18,7 @@ import (
"github.com/gin-gonic/gin/internal/json" "github.com/gin-gonic/gin/internal/json"
testdata "github.com/gin-gonic/gin/testdata/protoexample" testdata "github.com/gin-gonic/gin/testdata/protoexample"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
@ -36,7 +37,7 @@ func TestRenderJSON(t *testing.T) {
err := (JSON{data}).Render(w) err := (JSON{data}).Render(w)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"\\u003cb\\u003e\"}", w.Body.String()) assert.Equal(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"))
} }
@ -46,7 +47,7 @@ func TestRenderJSONError(t *testing.T) {
data := make(chan int) data := make(chan int)
// json: unsupported type: chan int // json: unsupported type: chan int
assert.Error(t, (JSON{data}).Render(w)) require.Error(t, (JSON{data}).Render(w))
} }
func TestRenderIndentedJSON(t *testing.T) { func TestRenderIndentedJSON(t *testing.T) {
@ -58,7 +59,7 @@ func TestRenderIndentedJSON(t *testing.T) {
err := (IndentedJSON{data}).Render(w) err := (IndentedJSON{data}).Render(w)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "{\n \"bar\": \"foo\",\n \"foo\": \"bar\"\n}", w.Body.String()) assert.Equal(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"))
} }
@ -69,7 +70,7 @@ func TestRenderIndentedJSONPanics(t *testing.T) {
// json: unsupported type: chan int // json: unsupported type: chan int
err := (IndentedJSON{data}).Render(w) err := (IndentedJSON{data}).Render(w)
assert.Error(t, err) require.Error(t, err)
} }
func TestRenderSecureJSON(t *testing.T) { func TestRenderSecureJSON(t *testing.T) {
@ -83,7 +84,7 @@ func TestRenderSecureJSON(t *testing.T) {
err1 := (SecureJSON{"while(1);", data}).Render(w1) err1 := (SecureJSON{"while(1);", data}).Render(w1)
assert.NoError(t, err1) require.NoError(t, err1)
assert.Equal(t, "{\"foo\":\"bar\"}", w1.Body.String()) assert.Equal(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"))
@ -95,7 +96,7 @@ func TestRenderSecureJSON(t *testing.T) {
}} }}
err2 := (SecureJSON{"while(1);", datas}).Render(w2) err2 := (SecureJSON{"while(1);", datas}).Render(w2)
assert.NoError(t, err2) require.NoError(t, err2)
assert.Equal(t, "while(1);[{\"foo\":\"bar\"},{\"bar\":\"foo\"}]", w2.Body.String()) assert.Equal(t, "while(1);[{\"foo\":\"bar\"},{\"bar\":\"foo\"}]", w2.Body.String())
assert.Equal(t, "application/json; charset=utf-8", w2.Header().Get("Content-Type")) assert.Equal(t, "application/json; charset=utf-8", w2.Header().Get("Content-Type"))
} }
@ -106,7 +107,7 @@ func TestRenderSecureJSONFail(t *testing.T) {
// json: unsupported type: chan int // json: unsupported type: chan int
err := (SecureJSON{"while(1);", data}).Render(w) err := (SecureJSON{"while(1);", data}).Render(w)
assert.Error(t, err) require.Error(t, err)
} }
func TestRenderJsonpJSON(t *testing.T) { func TestRenderJsonpJSON(t *testing.T) {
@ -120,7 +121,7 @@ func TestRenderJsonpJSON(t *testing.T) {
err1 := (JsonpJSON{"x", data}).Render(w1) err1 := (JsonpJSON{"x", data}).Render(w1)
assert.NoError(t, err1) require.NoError(t, err1)
assert.Equal(t, "x({\"foo\":\"bar\"});", w1.Body.String()) assert.Equal(t, "x({\"foo\":\"bar\"});", w1.Body.String())
assert.Equal(t, "application/javascript; charset=utf-8", w1.Header().Get("Content-Type")) assert.Equal(t, "application/javascript; charset=utf-8", w1.Header().Get("Content-Type"))
@ -132,7 +133,7 @@ func TestRenderJsonpJSON(t *testing.T) {
}} }}
err2 := (JsonpJSON{"x", datas}).Render(w2) err2 := (JsonpJSON{"x", datas}).Render(w2)
assert.NoError(t, err2) require.NoError(t, err2)
assert.Equal(t, "x([{\"foo\":\"bar\"},{\"bar\":\"foo\"}]);", w2.Body.String()) assert.Equal(t, "x([{\"foo\":\"bar\"},{\"bar\":\"foo\"}]);", w2.Body.String())
assert.Equal(t, "application/javascript; charset=utf-8", w2.Header().Get("Content-Type")) assert.Equal(t, "application/javascript; charset=utf-8", w2.Header().Get("Content-Type"))
} }
@ -191,7 +192,7 @@ func TestRenderJsonpJSONError2(t *testing.T) {
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"))
e := (JsonpJSON{"", data}).Render(w) e := (JsonpJSON{"", data}).Render(w)
assert.NoError(t, e) require.NoError(t, e)
assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String()) assert.Equal(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"))
@ -203,7 +204,7 @@ func TestRenderJsonpJSONFail(t *testing.T) {
// json: unsupported type: chan int // json: unsupported type: chan int
err := (JsonpJSON{"x", data}).Render(w) err := (JsonpJSON{"x", data}).Render(w)
assert.Error(t, err) require.Error(t, err)
} }
func TestRenderAsciiJSON(t *testing.T) { func TestRenderAsciiJSON(t *testing.T) {
@ -215,7 +216,7 @@ func TestRenderAsciiJSON(t *testing.T) {
err := (AsciiJSON{data1}).Render(w1) err := (AsciiJSON{data1}).Render(w1)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "{\"lang\":\"GO\\u8bed\\u8a00\",\"tag\":\"\\u003cbr\\u003e\"}", w1.Body.String()) assert.Equal(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"))
@ -223,7 +224,7 @@ func TestRenderAsciiJSON(t *testing.T) {
data2 := 3.1415926 data2 := 3.1415926
err = (AsciiJSON{data2}).Render(w2) err = (AsciiJSON{data2}).Render(w2)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "3.1415926", w2.Body.String()) assert.Equal(t, "3.1415926", w2.Body.String())
} }
@ -232,7 +233,7 @@ func TestRenderAsciiJSONFail(t *testing.T) {
data := make(chan int) data := make(chan int)
// json: unsupported type: chan int // json: unsupported type: chan int
assert.Error(t, (AsciiJSON{data}).Render(w)) require.Error(t, (AsciiJSON{data}).Render(w))
} }
func TestRenderPureJSON(t *testing.T) { func TestRenderPureJSON(t *testing.T) {
@ -242,7 +243,7 @@ func TestRenderPureJSON(t *testing.T) {
"html": "<b>", "html": "<b>",
} }
err := (PureJSON{data}).Render(w) err := (PureJSON{data}).Render(w)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"<b>\"}\n", w.Body.String()) assert.Equal(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"))
} }
@ -283,7 +284,7 @@ b:
assert.Equal(t, "application/yaml; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "application/yaml; charset=utf-8", w.Header().Get("Content-Type"))
err := (YAML{data}).Render(w) err := (YAML{data}).Render(w)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "|4-\n a : Easy!\n b:\n \tc: 2\n \td: [3, 4]\n \t\n", w.Body.String()) assert.Equal(t, "|4-\n a : Easy!\n b:\n \tc: 2\n \td: [3, 4]\n \t\n", w.Body.String())
assert.Equal(t, "application/yaml; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "application/yaml; charset=utf-8", w.Header().Get("Content-Type"))
} }
@ -298,7 +299,7 @@ func (ft *fail) MarshalYAML() (any, error) {
func TestRenderYAMLFail(t *testing.T) { func TestRenderYAMLFail(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
err := (YAML{&fail{}}).Render(w) err := (YAML{&fail{}}).Render(w)
assert.Error(t, err) require.Error(t, err)
} }
func TestRenderTOML(t *testing.T) { func TestRenderTOML(t *testing.T) {
@ -311,7 +312,7 @@ func TestRenderTOML(t *testing.T) {
assert.Equal(t, "application/toml; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "application/toml; charset=utf-8", w.Header().Get("Content-Type"))
err := (TOML{data}).Render(w) err := (TOML{data}).Render(w)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "foo = 'bar'\nhtml = '<b>'\n", w.Body.String()) assert.Equal(t, "foo = 'bar'\nhtml = '<b>'\n", w.Body.String())
assert.Equal(t, "application/toml; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "application/toml; charset=utf-8", w.Header().Get("Content-Type"))
} }
@ -319,7 +320,7 @@ func TestRenderTOML(t *testing.T) {
func TestRenderTOMLFail(t *testing.T) { func TestRenderTOMLFail(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
err := (TOML{net.IPv4bcast}).Render(w) err := (TOML{net.IPv4bcast}).Render(w)
assert.Error(t, err) require.Error(t, err)
} }
// test Protobuf rendering // test Protobuf rendering
@ -334,12 +335,12 @@ func TestRenderProtoBuf(t *testing.T) {
(ProtoBuf{data}).WriteContentType(w) (ProtoBuf{data}).WriteContentType(w)
protoData, err := proto.Marshal(data) protoData, err := proto.Marshal(data)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "application/x-protobuf", w.Header().Get("Content-Type")) assert.Equal(t, "application/x-protobuf", w.Header().Get("Content-Type"))
err = (ProtoBuf{data}).Render(w) err = (ProtoBuf{data}).Render(w)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, string(protoData), w.Body.String()) assert.Equal(t, string(protoData), w.Body.String())
assert.Equal(t, "application/x-protobuf", w.Header().Get("Content-Type")) assert.Equal(t, "application/x-protobuf", w.Header().Get("Content-Type"))
} }
@ -348,7 +349,7 @@ func TestRenderProtoBufFail(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
data := &testdata.Test{} data := &testdata.Test{}
err := (ProtoBuf{data}).Render(w) err := (ProtoBuf{data}).Render(w)
assert.Error(t, err) require.Error(t, err)
} }
func TestRenderXML(t *testing.T) { func TestRenderXML(t *testing.T) {
@ -362,14 +363,14 @@ func TestRenderXML(t *testing.T) {
err := (XML{data}).Render(w) err := (XML{data}).Render(w)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "<map><foo>bar</foo></map>", w.Body.String()) assert.Equal(t, "<map><foo>bar</foo></map>", w.Body.String())
assert.Equal(t, "application/xml; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "application/xml; charset=utf-8", w.Header().Get("Content-Type"))
} }
func TestRenderRedirect(t *testing.T) { func TestRenderRedirect(t *testing.T) {
req, err := http.NewRequest("GET", "/test-redirect", nil) req, err := http.NewRequest("GET", "/test-redirect", nil)
assert.NoError(t, err) require.NoError(t, err)
data1 := Redirect{ data1 := Redirect{
Code: http.StatusMovedPermanently, Code: http.StatusMovedPermanently,
@ -379,7 +380,7 @@ func TestRenderRedirect(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
err = data1.Render(w) err = data1.Render(w)
assert.NoError(t, err) require.NoError(t, err)
data2 := Redirect{ data2 := Redirect{
Code: http.StatusOK, Code: http.StatusOK,
@ -390,7 +391,7 @@ func TestRenderRedirect(t *testing.T) {
w = httptest.NewRecorder() w = httptest.NewRecorder()
assert.PanicsWithValue(t, "Cannot redirect with status code 200", func() { assert.PanicsWithValue(t, "Cannot redirect with status code 200", func() {
err := data2.Render(w) err := data2.Render(w)
assert.NoError(t, err) require.NoError(t, err)
}) })
data3 := Redirect{ data3 := Redirect{
@ -401,7 +402,7 @@ func TestRenderRedirect(t *testing.T) {
w = httptest.NewRecorder() w = httptest.NewRecorder()
err = data3.Render(w) err = data3.Render(w)
assert.NoError(t, err) require.NoError(t, err)
// only improve coverage // only improve coverage
data2.WriteContentType(w) data2.WriteContentType(w)
@ -416,7 +417,7 @@ func TestRenderData(t *testing.T) {
Data: data, Data: data,
}).Render(w) }).Render(w)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "#!PNG some raw data", w.Body.String()) assert.Equal(t, "#!PNG some raw data", w.Body.String())
assert.Equal(t, "image/png", w.Header().Get("Content-Type")) assert.Equal(t, "image/png", w.Header().Get("Content-Type"))
} }
@ -435,7 +436,7 @@ func TestRenderString(t *testing.T) {
Data: []any{"manu", 2}, Data: []any{"manu", 2},
}).Render(w) }).Render(w)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "hola manu 2", w.Body.String()) assert.Equal(t, "hola manu 2", w.Body.String())
assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
} }
@ -448,7 +449,7 @@ func TestRenderStringLenZero(t *testing.T) {
Data: []any{}, Data: []any{},
}).Render(w) }).Render(w)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "hola %s %d", w.Body.String()) assert.Equal(t, "hola %s %d", w.Body.String())
assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
} }
@ -464,7 +465,7 @@ func TestRenderHTMLTemplate(t *testing.T) {
err := instance.Render(w) err := instance.Render(w)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "Hello alexandernyquist", w.Body.String()) assert.Equal(t, "Hello alexandernyquist", w.Body.String())
assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
} }
@ -480,7 +481,7 @@ func TestRenderHTMLTemplateEmptyName(t *testing.T) {
err := instance.Render(w) err := instance.Render(w)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "Hello alexandernyquist", w.Body.String()) assert.Equal(t, "Hello alexandernyquist", w.Body.String())
assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
} }
@ -499,7 +500,7 @@ func TestRenderHTMLDebugFiles(t *testing.T) {
err := instance.Render(w) err := instance.Render(w)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "<h1>Hello thinkerou</h1>", w.Body.String()) assert.Equal(t, "<h1>Hello thinkerou</h1>", w.Body.String())
assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
} }
@ -518,7 +519,7 @@ func TestRenderHTMLDebugGlob(t *testing.T) {
err := instance.Render(w) err := instance.Render(w)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "<h1>Hello thinkerou</h1>", w.Body.String()) assert.Equal(t, "<h1>Hello thinkerou</h1>", w.Body.String())
assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
} }
@ -548,7 +549,7 @@ func TestRenderReader(t *testing.T) {
Headers: headers, Headers: headers,
}).Render(w) }).Render(w)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, body, w.Body.String()) assert.Equal(t, body, w.Body.String())
assert.Equal(t, "image/png", w.Header().Get("Content-Type")) assert.Equal(t, "image/png", w.Header().Get("Content-Type"))
assert.Equal(t, strconv.Itoa(len(body)), w.Header().Get("Content-Length")) assert.Equal(t, strconv.Itoa(len(body)), w.Header().Get("Content-Length"))
@ -571,7 +572,7 @@ func TestRenderReaderNoContentLength(t *testing.T) {
Headers: headers, Headers: headers,
}).Render(w) }).Render(w)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, body, w.Body.String()) assert.Equal(t, body, w.Body.String())
assert.Equal(t, "image/png", w.Header().Get("Content-Type")) assert.Equal(t, "image/png", w.Header().Get("Content-Type"))
assert.NotContains(t, "Content-Length", w.Header()) assert.NotContains(t, "Content-Length", w.Header())
@ -588,6 +589,6 @@ func TestRenderWriteError(t *testing.T) {
ResponseRecorder: httptest.NewRecorder(), ResponseRecorder: httptest.NewRecorder(),
} }
err := r.Render(ew) err := r.Render(ew)
assert.NotNil(t, err) require.Error(t, err)
assert.Equal(t, `write "my-prefix:" error`, err.Error()) assert.Equal(t, `write "my-prefix:" error`, err.Error())
} }

View File

@ -10,6 +10,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
// TODO // TODO
@ -95,13 +96,13 @@ func TestResponseWriterWrite(t *testing.T) {
assert.Equal(t, http.StatusOK, w.Status()) assert.Equal(t, http.StatusOK, w.Status())
assert.Equal(t, http.StatusOK, testWriter.Code) assert.Equal(t, http.StatusOK, testWriter.Code)
assert.Equal(t, "hola", testWriter.Body.String()) assert.Equal(t, "hola", testWriter.Body.String())
assert.NoError(t, err) require.NoError(t, err)
n, err = w.Write([]byte(" adios")) n, err = w.Write([]byte(" adios"))
assert.Equal(t, 6, n) assert.Equal(t, 6, n)
assert.Equal(t, 10, w.Size()) assert.Equal(t, 10, w.Size())
assert.Equal(t, "hola adios", testWriter.Body.String()) assert.Equal(t, "hola adios", testWriter.Body.String())
assert.NoError(t, err) require.NoError(t, err)
} }
func TestResponseWriterHijack(t *testing.T) { func TestResponseWriterHijack(t *testing.T) {
@ -112,7 +113,7 @@ func TestResponseWriterHijack(t *testing.T) {
assert.Panics(t, func() { assert.Panics(t, func() {
_, _, err := w.Hijack() _, _, err := w.Hijack()
assert.NoError(t, err) require.NoError(t, err)
}) })
assert.True(t, w.Written()) assert.True(t, w.Written())
@ -135,7 +136,7 @@ func TestResponseWriterFlush(t *testing.T) {
// should return 500 // should return 500
resp, err := http.Get(testServer.URL) resp, err := http.Get(testServer.URL)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
} }

View File

@ -13,6 +13,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
type header struct { type header struct {
@ -386,7 +387,7 @@ func TestRouteStaticFile(t *testing.T) {
} }
defer os.Remove(f.Name()) defer os.Remove(f.Name())
_, err = f.WriteString("Gin Web Framework") _, err = f.WriteString("Gin Web Framework")
assert.NoError(t, err) require.NoError(t, err)
f.Close() f.Close()
dir, filename := filepath.Split(f.Name()) dir, filename := filepath.Split(f.Name())
@ -421,7 +422,7 @@ func TestRouteStaticFileFS(t *testing.T) {
} }
defer os.Remove(f.Name()) defer os.Remove(f.Name())
_, err = f.WriteString("Gin Web Framework") _, err = f.WriteString("Gin Web Framework")
assert.NoError(t, err) require.NoError(t, err)
f.Close() f.Close()
dir, filename := filepath.Split(f.Name()) dir, filename := filepath.Split(f.Name())
@ -484,7 +485,7 @@ func TestRouterMiddlewareAndStatic(t *testing.T) {
// 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.NotEqual(t, "", w.Header().Get("Content-Type"))
assert.NotEqual(t, w.Header().Get("Last-Modified"), "Mon, 02 Jan 2006 15:04:05 MST") 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"))
} }

View File

@ -145,6 +145,6 @@ func TestMarshalXMLforH(t *testing.T) {
} }
func TestIsASCII(t *testing.T) { func TestIsASCII(t *testing.T) {
assert.Equal(t, isASCII("test"), true) assert.True(t, isASCII("test"))
assert.Equal(t, isASCII("🧡💛💚💙💜"), false) assert.False(t, isASCII("🧡💛💚💙💜"))
} }