完成该功能 (#308)

This commit is contained in:
guonaihong
2021-08-22 17:36:21 +08:00
committed by GitHub
parent f9c10cce30
commit 1f7f892c34
5 changed files with 109 additions and 8 deletions

View File

@@ -51,7 +51,7 @@ func BytesToString(b []byte) string {
// StringToBytes 没有内存开销的转换
func StringToBytes(s string) (b []byte) {
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
sh := *(*reflect.StringHeader)(unsafe.Pointer(&s))
sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
bh.Data = sh.Data
bh.Len = sh.Len
bh.Cap = sh.Len

View File

@@ -8,6 +8,8 @@ import (
"strings"
"time"
"unsafe"
"github.com/guonaihong/gout/core"
)
// ErrUnsupported Unsupported type error returned
@@ -41,10 +43,12 @@ func Encode(in interface{}, a Adder) error {
case reflect.Map:
iter := v.MapRange()
for iter.Next() {
if err := a.Add(valToStr(iter.Key(), emptyField), iter.Value(), emptyField); err != nil {
keyName := valToStr(iter.Key(), emptyField)
if err := setMoreTypes(iter.Value(), emptyField, a, keyName); err != nil {
return err
}
}
return nil
case reflect.Struct:
@@ -64,7 +68,8 @@ func Encode(in interface{}, a Adder) error {
for i, l := 0, v.Len(); i < l; i += 2 {
if err := a.Add(valToStr(v.Index(i), emptyField), v.Index(i+1), emptyField); err != nil {
keyName := valToStr(v.Index(i), emptyField)
if err := setMoreTypes(v.Index(i+1), emptyField, a, keyName); err != nil {
return err
}
}
@@ -131,6 +136,27 @@ func valToStr(v reflect.Value, sf reflect.StructField) string {
return fmt.Sprint(v.Interface())
}
func setMoreTypes(val reflect.Value, sf reflect.StructField, a Adder, tagName string) error {
switch val.Interface().(type) {
case string, []byte, core.FormMem, core.FormFile:
default:
if val.Kind() == reflect.Interface {
val = val.Elem()
}
switch val.Kind() {
case reflect.Slice, reflect.Array:
for i, l := 0, val.Len(); i < l; i++ {
if err := a.Add(tagName, val.Index(i), sf); err != nil {
return err
}
}
return nil
}
}
return a.Add(tagName, val, sf)
}
func parseTagAndSet(val reflect.Value, sf reflect.StructField, a Adder) error {
tagName := sf.Tag.Get(a.Name())
@@ -148,7 +174,7 @@ func parseTagAndSet(val reflect.Value, sf reflect.StructField, a Adder) error {
return nil
}
return a.Add(tagName, val, sf)
return setMoreTypes(val, sf, a, tagName)
}
func encode(val reflect.Value, sf reflect.StructField, a Adder) error {

View File

@@ -79,13 +79,19 @@ func checkForm(t *testing.T, boundary string, out *bytes.Buffer, caseID int, nee
}
if needCheckFileName && p.FileName() != "" {
assert.Equal(t, p.FileName(), "voice.pcm", fmt.Sprintf("-->test case id:%d", caseID))
b := assert.Equal(t, p.FileName(), "voice.pcm", fmt.Sprintf("-->test case id:%d", caseID))
if !b {
return
}
}
// key
key := p.FormName()
if key == "voice" || key == "voice2" {
assert.NotEqual(t, len(p.FileName()), 0, fmt.Sprintf("filename is empty:%d", caseID))
b := assert.NotEqual(t, len(p.FileName()), 0, fmt.Sprintf("filename is empty:%d", caseID))
if !b {
return
}
}
// slurp is value
v := need[key]

View File

@@ -1,14 +1,17 @@
package encode
import (
"github.com/guonaihong/gout/setting"
"github.com/stretchr/testify/assert"
"net/http"
"strconv"
"testing"
"time"
"github.com/guonaihong/gout/core"
"github.com/guonaihong/gout/setting"
"github.com/stretchr/testify/assert"
)
// 测试[]string类型
func TestQueryStringSlice(t *testing.T) {
req, _ := http.NewRequest("GET", "/", nil)
@@ -21,6 +24,7 @@ func TestQueryStringSlice(t *testing.T) {
assert.Equal(t, q.End(), "q1=v1&q2=v2&q3=v3")
}
// 测试map[string]interface{}
func TestQueryMap(t *testing.T) {
req, _ := http.NewRequest("GET", "/", nil)
@@ -41,6 +45,7 @@ type testQuery struct {
Q5 time.Time `query:"q5" time_format:"unixNano"`
}
// 测试结构体
func TestQueryStruct(t *testing.T) {
req, _ := http.NewRequest("GET", "/", nil)
@@ -55,3 +60,29 @@ func TestQueryStruct(t *testing.T) {
assert.Equal(t, q.End(), "q1=v1&q2=v2&q3=v3&q4="+strconv.FormatInt(unixTime.Unix(), 10)+"&q5="+strconv.FormatInt(unixNano.UnixNano(), 10))
}
// 结构体带[]string
type queryWithSlice struct {
A []string `query:"a"`
B string `query:"b"`
}
func TestQueryFieldWithSlice(t *testing.T) {
for _, v := range []interface{}{
queryWithSlice{A: []string{"1", "2", "3"}, B: "b"},
core.H{"a": []string{"1", "2", "3"}, "b": "b"},
core.A{"a", []string{"1", "2", "3"}, "b", "b"},
} {
req, _ := http.NewRequest("GET", "/", nil)
q := NewQueryEncode(req, setting.Setting{})
err := Encode(v, q)
assert.NoError(t, err)
assert.Equal(t, q.End(), "a=1&a=2&a=3&b=b")
}
}

View File

@@ -6,11 +6,49 @@ import (
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/guonaihong/gout/dataflow"
)
type queryWithSlice struct {
A []string `query:"a" form:"a"`
B string `query:"b" form:"b"`
}
func testQueryWithSliceServer(t *testing.T) *httptest.Server {
r := gin.New()
need := queryWithSlice{A: []string{"1", "2", "3"}, B: "b"}
r.GET("/query", func(c *gin.Context) {
got := queryWithSlice{}
err := c.ShouldBindQuery(&got)
assert.NoError(t, err)
assert.Equal(t, need, got)
})
return httptest.NewServer(http.HandlerFunc(r.ServeHTTP))
}
// 测试query接口带slice的情况
func TestQuery_slice(t *testing.T) {
ts := testQueryWithSliceServer(t)
for _, v := range []interface{}{
queryWithSlice{A: []string{"1", "2", "3"}, B: "b"},
H{"a": []string{"1", "2", "3"}, "b": "b"},
A{"a", []string{"1", "2", "3"}, "b", "b"},
} {
err := GET(ts.URL + "/query").Debug(true).SetQuery(v).Do()
assert.NoError(t, err)
}
}
func TestQuery_NotIgnoreEmpty(t *testing.T) {
total := int32(0)