master
parent
f6a0e82c39
commit
b0aad85f2b
13 changed files with 3 additions and 1062 deletions
@ -1,7 +0,0 @@ |
|||||||
# encoding |
|
||||||
|
|
||||||
## msgpack |
|
||||||
|
|
||||||
```shell |
|
||||||
go get -u github.com/go-kratos/kratos/contrib/encoding/msgpack/v2 |
|
||||||
``` |
|
@ -1,211 +0,0 @@ |
|||||||
package form |
|
||||||
|
|
||||||
import ( |
|
||||||
"encoding/base64" |
|
||||||
"reflect" |
|
||||||
"testing" |
|
||||||
|
|
||||||
"google.golang.org/protobuf/types/known/durationpb" |
|
||||||
"google.golang.org/protobuf/types/known/fieldmaskpb" |
|
||||||
"google.golang.org/protobuf/types/known/timestamppb" |
|
||||||
"google.golang.org/protobuf/types/known/wrapperspb" |
|
||||||
|
|
||||||
"github.com/go-kratos/kratos/v2/encoding" |
|
||||||
bdtest "github.com/go-kratos/kratos/v2/internal/testdata/binding" |
|
||||||
"github.com/go-kratos/kratos/v2/internal/testdata/complex" |
|
||||||
ectest "github.com/go-kratos/kratos/v2/internal/testdata/encoding" |
|
||||||
) |
|
||||||
|
|
||||||
type LoginRequest struct { |
|
||||||
Username string `json:"username,omitempty"` |
|
||||||
Password string `json:"password,omitempty"` |
|
||||||
} |
|
||||||
|
|
||||||
func TestFormCodecMarshal(t *testing.T) { |
|
||||||
req := &LoginRequest{ |
|
||||||
Username: "kratos", |
|
||||||
Password: "kratos_pwd", |
|
||||||
} |
|
||||||
content, err := encoding.GetCodec(Name).Marshal(req) |
|
||||||
if err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
if !reflect.DeepEqual([]byte("password=kratos_pwd&username=kratos"), content) { |
|
||||||
t.Errorf("expect %s, got %s", "password=kratos_pwd&username=kratos", content) |
|
||||||
} |
|
||||||
|
|
||||||
req = &LoginRequest{ |
|
||||||
Username: "kratos", |
|
||||||
Password: "", |
|
||||||
} |
|
||||||
content, err = encoding.GetCodec(Name).Marshal(req) |
|
||||||
if err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
if !reflect.DeepEqual([]byte("username=kratos"), content) { |
|
||||||
t.Errorf("expect %s, got %s", "username=kratos", content) |
|
||||||
} |
|
||||||
|
|
||||||
m := struct { |
|
||||||
ID int32 `json:"id"` |
|
||||||
Name string `json:"name"` |
|
||||||
}{ |
|
||||||
ID: 1, |
|
||||||
Name: "kratos", |
|
||||||
} |
|
||||||
content, err = encoding.GetCodec(Name).Marshal(m) |
|
||||||
if err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
if !reflect.DeepEqual([]byte("id=1&name=kratos"), content) { |
|
||||||
t.Errorf("expect %s, got %s", "id=1&name=kratos", content) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestFormCodecUnmarshal(t *testing.T) { |
|
||||||
req := &LoginRequest{ |
|
||||||
Username: "kratos", |
|
||||||
Password: "kratos_pwd", |
|
||||||
} |
|
||||||
content, err := encoding.GetCodec(Name).Marshal(req) |
|
||||||
if err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
|
|
||||||
bindReq := new(LoginRequest) |
|
||||||
err = encoding.GetCodec(Name).Unmarshal(content, bindReq) |
|
||||||
if err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
if !reflect.DeepEqual("kratos", bindReq.Username) { |
|
||||||
t.Errorf("expect %v, got %v", "kratos", bindReq.Username) |
|
||||||
} |
|
||||||
if !reflect.DeepEqual("kratos_pwd", bindReq.Password) { |
|
||||||
t.Errorf("expect %v, got %v", "kratos_pwd", bindReq.Password) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestProtoEncodeDecode(t *testing.T) { |
|
||||||
in := &complex.Complex{ |
|
||||||
Id: 2233, |
|
||||||
NoOne: "2233", |
|
||||||
Simple: &complex.Simple{Component: "5566"}, |
|
||||||
Simples: []string{"3344", "5566"}, |
|
||||||
B: true, |
|
||||||
Sex: complex.Sex_woman, |
|
||||||
Age: 18, |
|
||||||
A: 19, |
|
||||||
Count: 3, |
|
||||||
Price: 11.23, |
|
||||||
D: 22.22, |
|
||||||
Byte: []byte("123"), |
|
||||||
Map: map[string]string{"kratos": "https://go-kratos.dev/"}, |
|
||||||
|
|
||||||
Timestamp: ×tamppb.Timestamp{Seconds: 20, Nanos: 2}, |
|
||||||
Duration: &durationpb.Duration{Seconds: 120, Nanos: 22}, |
|
||||||
Field: &fieldmaskpb.FieldMask{Paths: []string{"1", "2"}}, |
|
||||||
Double: &wrapperspb.DoubleValue{Value: 12.33}, |
|
||||||
Float: &wrapperspb.FloatValue{Value: 12.34}, |
|
||||||
Int64: &wrapperspb.Int64Value{Value: 64}, |
|
||||||
Int32: &wrapperspb.Int32Value{Value: 32}, |
|
||||||
Uint64: &wrapperspb.UInt64Value{Value: 64}, |
|
||||||
Uint32: &wrapperspb.UInt32Value{Value: 32}, |
|
||||||
Bool: &wrapperspb.BoolValue{Value: false}, |
|
||||||
String_: &wrapperspb.StringValue{Value: "go-kratos"}, |
|
||||||
Bytes: &wrapperspb.BytesValue{Value: []byte("123")}, |
|
||||||
} |
|
||||||
content, err := encoding.GetCodec(Name).Marshal(in) |
|
||||||
if err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
if "a=19&age=18&b=true&bool=false&byte=MTIz&bytes=MTIz&count=3&d=22.22&double=12.33&duration="+ |
|
||||||
"2m0.000000022s&field=1%2C2&float=12.34&id=2233&int32=32&int64=64&map%5Bkratos%5D=https%3A%2F%2Fgo-kratos.dev%2F&"+ |
|
||||||
"numberOne=2233&price=11.23&sex=woman&simples=3344&simples=5566&string=go-kratos"+ |
|
||||||
"×tamp=1970-01-01T00%3A00%3A20.000000002Z&uint32=32&uint64=64&very_simple.component=5566" != string(content) { |
|
||||||
t.Errorf("rawpath is not equal to %s", content) |
|
||||||
} |
|
||||||
in2 := &complex.Complex{} |
|
||||||
err = encoding.GetCodec(Name).Unmarshal(content, in2) |
|
||||||
if err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
if int64(2233) != in2.Id { |
|
||||||
t.Errorf("expect %v, got %v", int64(2233), in2.Id) |
|
||||||
} |
|
||||||
if "2233" != in2.NoOne { |
|
||||||
t.Errorf("expect %v, got %v", "2233", in2.NoOne) |
|
||||||
} |
|
||||||
if in2.Simple == nil { |
|
||||||
t.Errorf("expect %v, got %v", nil, in2.Simple) |
|
||||||
} |
|
||||||
if "5566" != in2.Simple.Component { |
|
||||||
t.Errorf("expect %v, got %v", "5566", in2.Simple.Component) |
|
||||||
} |
|
||||||
if in2.Simples == nil { |
|
||||||
t.Errorf("expect %v, got %v", nil, in2.Simples) |
|
||||||
} |
|
||||||
if len(in2.Simples) != 2 { |
|
||||||
t.Errorf("expect %v, got %v", 2, len(in2.Simples)) |
|
||||||
} |
|
||||||
if "3344" != in2.Simples[0] { |
|
||||||
t.Errorf("expect %v, got %v", "3344", in2.Simples[0]) |
|
||||||
} |
|
||||||
if "5566" != in2.Simples[1] { |
|
||||||
t.Errorf("expect %v, got %v", "5566", in2.Simples[1]) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestDecodeStructPb(t *testing.T) { |
|
||||||
req := new(ectest.StructPb) |
|
||||||
query := `data={"name":"kratos"}&data_list={"name1": "kratos"}&data_list={"name2": "go-kratos"}` |
|
||||||
if err := encoding.GetCodec(Name).Unmarshal([]byte(query), req); err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
if "kratos" != req.Data.GetFields()["name"].GetStringValue() { |
|
||||||
t.Errorf("except %v, got %v", "kratos", req.Data.GetFields()["name"].GetStringValue()) |
|
||||||
} |
|
||||||
if len(req.DataList) != 2 { |
|
||||||
t.Fatalf("execpt %v, got %v", 2, len(req.DataList)) |
|
||||||
} |
|
||||||
if "kratos" != req.DataList[0].GetFields()["name1"].GetStringValue() { |
|
||||||
t.Errorf("except %v, got %v", "kratos", req.Data.GetFields()["name1"].GetStringValue()) |
|
||||||
} |
|
||||||
if "go-kratos" != req.DataList[1].GetFields()["name2"].GetStringValue() { |
|
||||||
t.Errorf("except %v, got %v", "go-kratos", req.Data.GetFields()["name2"].GetStringValue()) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestDecodeBytesValuePb(t *testing.T) { |
|
||||||
url := "https://example.com/xx/?a=1&b=2&c=3" |
|
||||||
val := base64.URLEncoding.EncodeToString([]byte(url)) |
|
||||||
content := "bytes=" + val |
|
||||||
in2 := &complex.Complex{} |
|
||||||
if err := encoding.GetCodec(Name).Unmarshal([]byte(content), in2); err != nil { |
|
||||||
t.Error(err) |
|
||||||
} |
|
||||||
if url != string(in2.Bytes.Value) { |
|
||||||
t.Errorf("except %s, got %s", val, in2.Bytes.Value) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestEncodeFieldMask(t *testing.T) { |
|
||||||
req := &bdtest.HelloRequest{ |
|
||||||
UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"foo", "bar"}}, |
|
||||||
} |
|
||||||
if v := EncodeFieldMask(req.ProtoReflect()); v != "updateMask=foo,bar" { |
|
||||||
t.Errorf("got %s", v) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestOptional(t *testing.T) { |
|
||||||
v := int32(100) |
|
||||||
req := &bdtest.HelloRequest{ |
|
||||||
Name: "foo", |
|
||||||
Sub: &bdtest.Sub{Name: "bar"}, |
|
||||||
OptInt32: &v, |
|
||||||
} |
|
||||||
query, _ := EncodeValues(req) |
|
||||||
if query.Encode() != "name=foo&optInt32=100&sub.naming=bar" { |
|
||||||
t.Fatalf("got %s", query.Encode()) |
|
||||||
} |
|
||||||
} |
|
@ -1,217 +0,0 @@ |
|||||||
package form |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
"net/url" |
|
||||||
"reflect" |
|
||||||
"strconv" |
|
||||||
"testing" |
|
||||||
|
|
||||||
"google.golang.org/protobuf/reflect/protoreflect" |
|
||||||
|
|
||||||
"github.com/go-kratos/kratos/v2/internal/testdata/complex" |
|
||||||
) |
|
||||||
|
|
||||||
func TestDecodeValues(t *testing.T) { |
|
||||||
form, err := url.ParseQuery("a=19&age=18&b=true&bool=false&byte=MTIz&bytes=MTIz&count=3&d=22.22&double=12.33&duration=" + |
|
||||||
"2m0.000000022s&field=1%2C2&float=12.34&id=2233&int32=32&int64=64&numberOne=2233&price=11.23&sex=woman&simples=3344&" + |
|
||||||
"simples=5566&string=go-kratos×tamp=1970-01-01T00%3A00%3A20.000000002Z&uint32=32&uint64=64&very_simple.component=5566") |
|
||||||
if err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
|
|
||||||
comp := &complex.Complex{} |
|
||||||
err = DecodeValues(comp, form) |
|
||||||
if err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
if comp.Id != int64(2233) { |
|
||||||
t.Errorf("want %v, got %v", int64(2233), comp.Id) |
|
||||||
} |
|
||||||
if comp.NoOne != "2233" { |
|
||||||
t.Errorf("want %v, got %v", "2233", comp.NoOne) |
|
||||||
} |
|
||||||
if comp.Simple == nil { |
|
||||||
t.Fatalf("want %v, got %v", nil, comp.Simple) |
|
||||||
} |
|
||||||
if comp.Simple.Component != "5566" { |
|
||||||
t.Errorf("want %v, got %v", "5566", comp.Simple.Component) |
|
||||||
} |
|
||||||
if len(comp.Simples) != 2 { |
|
||||||
t.Fatalf("want %v, got %v", 2, len(comp.Simples)) |
|
||||||
} |
|
||||||
if comp.Simples[0] != "3344" { |
|
||||||
t.Errorf("want %v, got %v", "3344", comp.Simples[0]) |
|
||||||
} |
|
||||||
if comp.Simples[1] != "5566" { |
|
||||||
t.Errorf("want %v, got %v", "5566", comp.Simples[1]) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestGetFieldDescriptor(t *testing.T) { |
|
||||||
comp := &complex.Complex{} |
|
||||||
|
|
||||||
field := getFieldDescriptor(comp.ProtoReflect(), "id") |
|
||||||
if field.Kind() != protoreflect.Int64Kind { |
|
||||||
t.Errorf("want: %d, got: %d", protoreflect.Int64Kind, field.Kind()) |
|
||||||
} |
|
||||||
|
|
||||||
field = getFieldDescriptor(comp.ProtoReflect(), "simples") |
|
||||||
if field.Kind() != protoreflect.StringKind { |
|
||||||
t.Errorf("want: %d, got: %d", protoreflect.StringKind, field.Kind()) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestPopulateRepeatedField(t *testing.T) { |
|
||||||
query, err := url.ParseQuery("simples=3344&simples=5566") |
|
||||||
if err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
comp := &complex.Complex{} |
|
||||||
field := getFieldDescriptor(comp.ProtoReflect(), "simples") |
|
||||||
|
|
||||||
err = populateRepeatedField(field, comp.ProtoReflect().Mutable(field).List(), query["simples"]) |
|
||||||
if err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
if !reflect.DeepEqual([]string{"3344", "5566"}, comp.GetSimples()) { |
|
||||||
t.Errorf("want: %v, got: %v", []string{"3344", "5566"}, comp.GetSimples()) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestPopulateMapField(t *testing.T) { |
|
||||||
query, err := url.ParseQuery("map%5Bkratos%5D=https://go-kratos.dev/") |
|
||||||
if err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
comp := &complex.Complex{} |
|
||||||
field := getFieldDescriptor(comp.ProtoReflect(), "map") |
|
||||||
// Fill the comp map field with the url query values
|
|
||||||
err = populateMapField(field, comp.ProtoReflect().Mutable(field).Map(), []string{"kratos"}, query["map[kratos]"]) |
|
||||||
if err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
// Get the comp map field value
|
|
||||||
if query["map[kratos]"][0] != comp.Map["kratos"] { |
|
||||||
t.Errorf("want: %s, got: %s", query["map[kratos]"], comp.Map["kratos"]) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestParseField(t *testing.T) { |
|
||||||
tests := []struct { |
|
||||||
name string |
|
||||||
fieldName string |
|
||||||
protoReflectKind protoreflect.Kind |
|
||||||
value string |
|
||||||
targetProtoReflectValue protoreflect.Value |
|
||||||
targetErr error |
|
||||||
}{ |
|
||||||
{ |
|
||||||
name: "BoolKind", |
|
||||||
fieldName: "b", |
|
||||||
protoReflectKind: protoreflect.BoolKind, |
|
||||||
value: "true", |
|
||||||
targetProtoReflectValue: protoreflect.ValueOfBool(true), |
|
||||||
targetErr: nil, |
|
||||||
}, |
|
||||||
{ |
|
||||||
name: "BoolKind", |
|
||||||
fieldName: "b", |
|
||||||
protoReflectKind: protoreflect.BoolKind, |
|
||||||
value: "a", |
|
||||||
targetProtoReflectValue: protoreflect.Value{}, |
|
||||||
targetErr: &strconv.NumError{Func: "ParseBool", Num: "a", Err: strconv.ErrSyntax}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
name: "EnumKind", |
|
||||||
fieldName: "sex", |
|
||||||
protoReflectKind: protoreflect.EnumKind, |
|
||||||
value: "1", |
|
||||||
targetProtoReflectValue: protoreflect.ValueOfEnum(1), |
|
||||||
targetErr: nil, |
|
||||||
}, |
|
||||||
{ |
|
||||||
name: "EnumKind", |
|
||||||
fieldName: "sex", |
|
||||||
protoReflectKind: protoreflect.EnumKind, |
|
||||||
value: "2", |
|
||||||
targetProtoReflectValue: protoreflect.Value{}, |
|
||||||
targetErr: fmt.Errorf("%q is not a valid value", "2"), |
|
||||||
}, |
|
||||||
} |
|
||||||
for _, test := range tests { |
|
||||||
t.Run(test.name, func(t *testing.T) { |
|
||||||
comp := &complex.Complex{} |
|
||||||
field := getFieldDescriptor(comp.ProtoReflect(), test.fieldName) |
|
||||||
if test.protoReflectKind != field.Kind() { |
|
||||||
t.Fatalf("want: %d, got: %d", test.protoReflectKind, field.Kind()) |
|
||||||
} |
|
||||||
val, err := parseField(field, test.value) |
|
||||||
if !reflect.DeepEqual(test.targetErr, err) { |
|
||||||
t.Fatalf("want: %s, got: %s", test.targetErr, err) |
|
||||||
} |
|
||||||
if !reflect.DeepEqual(test.targetProtoReflectValue, val) { |
|
||||||
t.Errorf("want: %s, got: %s", test.targetProtoReflectValue, val) |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestJsonSnakeCase(t *testing.T) { |
|
||||||
tests := []struct { |
|
||||||
camelCase string |
|
||||||
snakeCase string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
"userId", "user_id", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"user", "user", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"userIdAndUsername", "user_id_and_username", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"", "", |
|
||||||
}, |
|
||||||
} |
|
||||||
for _, test := range tests { |
|
||||||
t.Run(test.camelCase, func(t *testing.T) { |
|
||||||
snake := jsonSnakeCase(test.camelCase) |
|
||||||
if snake != test.snakeCase { |
|
||||||
t.Errorf("want: %s, got: %s", test.snakeCase, snake) |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestIsASCIIUpper(t *testing.T) { |
|
||||||
tests := []struct { |
|
||||||
b byte |
|
||||||
upper bool |
|
||||||
}{ |
|
||||||
{ |
|
||||||
'A', true, |
|
||||||
}, |
|
||||||
{ |
|
||||||
'a', false, |
|
||||||
}, |
|
||||||
{ |
|
||||||
',', false, |
|
||||||
}, |
|
||||||
{ |
|
||||||
'1', false, |
|
||||||
}, |
|
||||||
{ |
|
||||||
' ', false, |
|
||||||
}, |
|
||||||
} |
|
||||||
for _, test := range tests { |
|
||||||
t.Run(string(test.b), func(t *testing.T) { |
|
||||||
upper := isASCIIUpper(test.b) |
|
||||||
if test.upper != upper { |
|
||||||
t.Errorf("'%s' is not ascii upper", string(test.b)) |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
@ -1,110 +0,0 @@ |
|||||||
package form |
|
||||||
|
|
||||||
import ( |
|
||||||
"testing" |
|
||||||
|
|
||||||
"google.golang.org/protobuf/types/known/durationpb" |
|
||||||
"google.golang.org/protobuf/types/known/fieldmaskpb" |
|
||||||
"google.golang.org/protobuf/types/known/timestamppb" |
|
||||||
"google.golang.org/protobuf/types/known/wrapperspb" |
|
||||||
|
|
||||||
"github.com/go-kratos/kratos/v2/internal/testdata/complex" |
|
||||||
) |
|
||||||
|
|
||||||
func TestEncodeValues(t *testing.T) { |
|
||||||
in := &complex.Complex{ |
|
||||||
Id: 2233, |
|
||||||
NoOne: "2233", |
|
||||||
Simple: &complex.Simple{Component: "5566"}, |
|
||||||
Simples: []string{"3344", "5566"}, |
|
||||||
B: true, |
|
||||||
Sex: complex.Sex_woman, |
|
||||||
Age: 18, |
|
||||||
A: 19, |
|
||||||
Count: 3, |
|
||||||
Price: 11.23, |
|
||||||
D: 22.22, |
|
||||||
Byte: []byte("123"), |
|
||||||
Map: map[string]string{"kratos": "https://go-kratos.dev/", "kratos_start": "https://go-kratos.dev/en/docs/getting-started/start/"}, |
|
||||||
|
|
||||||
Timestamp: ×tamppb.Timestamp{Seconds: 20, Nanos: 2}, |
|
||||||
Duration: &durationpb.Duration{Seconds: 120, Nanos: 22}, |
|
||||||
Field: &fieldmaskpb.FieldMask{Paths: []string{"1", "2"}}, |
|
||||||
Double: &wrapperspb.DoubleValue{Value: 12.33}, |
|
||||||
Float: &wrapperspb.FloatValue{Value: 12.34}, |
|
||||||
Int64: &wrapperspb.Int64Value{Value: 64}, |
|
||||||
Int32: &wrapperspb.Int32Value{Value: 32}, |
|
||||||
Uint64: &wrapperspb.UInt64Value{Value: 64}, |
|
||||||
Uint32: &wrapperspb.UInt32Value{Value: 32}, |
|
||||||
Bool: &wrapperspb.BoolValue{Value: false}, |
|
||||||
String_: &wrapperspb.StringValue{Value: "go-kratos"}, |
|
||||||
Bytes: &wrapperspb.BytesValue{Value: []byte("123")}, |
|
||||||
} |
|
||||||
query, err := EncodeValues(in) |
|
||||||
if err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
want := "a=19&age=18&b=true&bool=false&byte=MTIz&bytes=MTIz&count=3&d=22.22&double=12.33&duration=2m0.000000022s&field=1%2C2&float=12.34&id=2233&int32=32&int64=64&map%5Bkratos%5D=https%3A%2F%2Fgo-kratos.dev%2F&map%5Bkratos_start%5D=https%3A%2F%2Fgo-kratos.dev%2Fen%2Fdocs%2Fgetting-started%2Fstart%2F&numberOne=2233&price=11.23&sex=woman&simples=3344&simples=5566&string=go-kratos×tamp=1970-01-01T00%3A00%3A20.000000002Z&uint32=32&uint64=64&very_simple.component=5566" // nolint:lll
|
|
||||||
if got := query.Encode(); want != got { |
|
||||||
t.Errorf("want: %s, got: %s", want, got) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestJsonCamelCase(t *testing.T) { |
|
||||||
tests := []struct { |
|
||||||
camelCase string |
|
||||||
snakeCase string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
"userId", "user_id", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"user", "user", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"userIdAndUsername", "user_id_and_username", |
|
||||||
}, |
|
||||||
{ |
|
||||||
"", "", |
|
||||||
}, |
|
||||||
} |
|
||||||
for _, test := range tests { |
|
||||||
t.Run(test.snakeCase, func(t *testing.T) { |
|
||||||
camel := jsonCamelCase(test.snakeCase) |
|
||||||
if camel != test.camelCase { |
|
||||||
t.Errorf("want: %s, got: %s", test.camelCase, camel) |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestIsASCIILower(t *testing.T) { |
|
||||||
tests := []struct { |
|
||||||
b byte |
|
||||||
lower bool |
|
||||||
}{ |
|
||||||
{ |
|
||||||
'A', false, |
|
||||||
}, |
|
||||||
{ |
|
||||||
'a', true, |
|
||||||
}, |
|
||||||
{ |
|
||||||
',', false, |
|
||||||
}, |
|
||||||
{ |
|
||||||
'1', false, |
|
||||||
}, |
|
||||||
{ |
|
||||||
' ', false, |
|
||||||
}, |
|
||||||
} |
|
||||||
for _, test := range tests { |
|
||||||
t.Run(string(test.b), func(t *testing.T) { |
|
||||||
lower := isASCIILower(test.b) |
|
||||||
if test.lower != lower { |
|
||||||
t.Errorf("'%s' is not ascii lower", string(test.b)) |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
@ -1,95 +0,0 @@ |
|||||||
package form |
|
||||||
|
|
||||||
import ( |
|
||||||
"encoding/base64" |
|
||||||
"testing" |
|
||||||
"time" |
|
||||||
|
|
||||||
"google.golang.org/protobuf/reflect/protoreflect" |
|
||||||
"google.golang.org/protobuf/types/known/durationpb" |
|
||||||
"google.golang.org/protobuf/types/known/timestamppb" |
|
||||||
"google.golang.org/protobuf/types/known/wrapperspb" |
|
||||||
) |
|
||||||
|
|
||||||
func TestMarshalTimeStamp(t *testing.T) { |
|
||||||
tests := []struct { |
|
||||||
input *timestamppb.Timestamp |
|
||||||
expect string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
input: timestamppb.New(time.Date(2022, 1, 2, 3, 4, 5, 6, time.UTC)), |
|
||||||
expect: "2022-01-02T03:04:05.000000006Z", |
|
||||||
}, |
|
||||||
{ |
|
||||||
input: timestamppb.New(time.Date(2022, 13, 1, 13, 61, 61, 100, time.UTC)), |
|
||||||
expect: "2023-01-01T14:02:01.000000100Z", |
|
||||||
}, |
|
||||||
} |
|
||||||
for _, v := range tests { |
|
||||||
got, err := marshalTimestamp(v.input.ProtoReflect()) |
|
||||||
if err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
if want := v.expect; got != want { |
|
||||||
t.Errorf("expect %v, got %v", want, got) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestMarshalDuration(t *testing.T) { |
|
||||||
tests := []struct { |
|
||||||
input *durationpb.Duration |
|
||||||
expect string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
input: durationpb.New(time.Duration(1<<63 - 1)), |
|
||||||
expect: "2562047h47m16.854775807s", |
|
||||||
}, |
|
||||||
{ |
|
||||||
input: durationpb.New(time.Duration(-1 << 63)), |
|
||||||
expect: "-2562047h47m16.854775808s", |
|
||||||
}, |
|
||||||
{ |
|
||||||
input: durationpb.New(100 * time.Second), |
|
||||||
expect: "1m40s", |
|
||||||
}, |
|
||||||
{ |
|
||||||
input: durationpb.New(-100 * time.Second), |
|
||||||
expect: "-1m40s", |
|
||||||
}, |
|
||||||
} |
|
||||||
for _, v := range tests { |
|
||||||
got, err := marshalDuration(v.input.ProtoReflect()) |
|
||||||
if err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
if want := v.expect; got != want { |
|
||||||
t.Errorf("expect %s, got %s", want, got) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestMarshalBytes(t *testing.T) { |
|
||||||
tests := []struct { |
|
||||||
input protoreflect.Message |
|
||||||
expect string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
input: wrapperspb.Bytes([]byte("abc123!?$*&()'-=@~")).ProtoReflect(), |
|
||||||
expect: base64.StdEncoding.EncodeToString([]byte("abc123!?$*&()'-=@~")), |
|
||||||
}, |
|
||||||
{ |
|
||||||
input: wrapperspb.Bytes([]byte("kratos")).ProtoReflect(), |
|
||||||
expect: base64.StdEncoding.EncodeToString([]byte("kratos")), |
|
||||||
}, |
|
||||||
} |
|
||||||
for _, v := range tests { |
|
||||||
got, err := marshalBytes(v.input) |
|
||||||
if err != nil { |
|
||||||
t.Fatal(err) |
|
||||||
} |
|
||||||
if want := v.expect; got != want { |
|
||||||
t.Errorf("expect %v, got %v", want, got) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,147 +0,0 @@ |
|||||||
package json |
|
||||||
|
|
||||||
import ( |
|
||||||
"encoding/json" |
|
||||||
"reflect" |
|
||||||
"strings" |
|
||||||
"testing" |
|
||||||
|
|
||||||
testData "github.com/go-kratos/kratos/v2/internal/testdata/encoding" |
|
||||||
) |
|
||||||
|
|
||||||
type testEmbed struct { |
|
||||||
Level1a int `json:"a"` |
|
||||||
Level1b int `json:"b"` |
|
||||||
Level1c int `json:"c"` |
|
||||||
} |
|
||||||
|
|
||||||
type testMessage struct { |
|
||||||
Field1 string `json:"a"` |
|
||||||
Field2 string `json:"b"` |
|
||||||
Field3 string `json:"c"` |
|
||||||
Embed *testEmbed `json:"embed,omitempty"` |
|
||||||
} |
|
||||||
|
|
||||||
type mock struct { |
|
||||||
value int |
|
||||||
} |
|
||||||
|
|
||||||
const ( |
|
||||||
Unknown = iota |
|
||||||
Gopher |
|
||||||
Zebra |
|
||||||
) |
|
||||||
|
|
||||||
func (a *mock) UnmarshalJSON(b []byte) error { |
|
||||||
var s string |
|
||||||
if err := json.Unmarshal(b, &s); err != nil { |
|
||||||
return err |
|
||||||
} |
|
||||||
switch strings.ToLower(s) { |
|
||||||
default: |
|
||||||
a.value = Unknown |
|
||||||
case "gopher": |
|
||||||
a.value = Gopher |
|
||||||
case "zebra": |
|
||||||
a.value = Zebra |
|
||||||
} |
|
||||||
|
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
func (a *mock) MarshalJSON() ([]byte, error) { |
|
||||||
var s string |
|
||||||
switch a.value { |
|
||||||
default: |
|
||||||
s = "unknown" |
|
||||||
case Gopher: |
|
||||||
s = "gopher" |
|
||||||
case Zebra: |
|
||||||
s = "zebra" |
|
||||||
} |
|
||||||
|
|
||||||
return json.Marshal(s) |
|
||||||
} |
|
||||||
|
|
||||||
func TestJSON_Marshal(t *testing.T) { |
|
||||||
tests := []struct { |
|
||||||
input interface{} |
|
||||||
expect string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
input: &testMessage{}, |
|
||||||
expect: `{"a":"","b":"","c":""}`, |
|
||||||
}, |
|
||||||
{ |
|
||||||
input: &testMessage{Field1: "a", Field2: "b", Field3: "c"}, |
|
||||||
expect: `{"a":"a","b":"b","c":"c"}`, |
|
||||||
}, |
|
||||||
{ |
|
||||||
input: &testData.TestModel{Id: 1, Name: "go-kratos", Hobby: []string{"1", "2"}}, |
|
||||||
expect: `{"id":"1","name":"go-kratos","hobby":["1","2"],"attrs":{}}`, |
|
||||||
}, |
|
||||||
{ |
|
||||||
input: &mock{value: Gopher}, |
|
||||||
expect: `"gopher"`, |
|
||||||
}, |
|
||||||
} |
|
||||||
for _, v := range tests { |
|
||||||
data, err := (codec{}).Marshal(v.input) |
|
||||||
if err != nil { |
|
||||||
t.Errorf("marshal(%#v): %s", v.input, err) |
|
||||||
} |
|
||||||
if got, want := string(data), v.expect; strings.ReplaceAll(got, " ", "") != want { |
|
||||||
if strings.Contains(want, "\n") { |
|
||||||
t.Errorf("marshal(%#v):\nHAVE:\n%s\nWANT:\n%s", v.input, got, want) |
|
||||||
} else { |
|
||||||
t.Errorf("marshal(%#v):\nhave %#q\nwant %#q", v.input, got, want) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestJSON_Unmarshal(t *testing.T) { |
|
||||||
p := testMessage{} |
|
||||||
p2 := testData.TestModel{} |
|
||||||
p3 := &testData.TestModel{} |
|
||||||
p4 := &mock{} |
|
||||||
tests := []struct { |
|
||||||
input string |
|
||||||
expect interface{} |
|
||||||
}{ |
|
||||||
{ |
|
||||||
input: `{"a":"","b":"","c":""}`, |
|
||||||
expect: &testMessage{}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
input: `{"a":"a","b":"b","c":"c"}`, |
|
||||||
expect: &p, |
|
||||||
}, |
|
||||||
{ |
|
||||||
input: `{"id":"1","name":"go-kratos","hobby":["1","2"],"attrs":{}}`, |
|
||||||
expect: &p2, |
|
||||||
}, |
|
||||||
{ |
|
||||||
input: `{"id":1,"name":"go-kratos","hobby":["1","2"]}`, |
|
||||||
expect: &p3, |
|
||||||
}, |
|
||||||
{ |
|
||||||
input: `"zebra"`, |
|
||||||
expect: p4, |
|
||||||
}, |
|
||||||
} |
|
||||||
for _, v := range tests { |
|
||||||
want := []byte(v.input) |
|
||||||
err := (codec{}).Unmarshal(want, v.expect) |
|
||||||
if err != nil { |
|
||||||
t.Errorf("marshal(%#v): %s", v.input, err) |
|
||||||
} |
|
||||||
got, err := codec{}.Marshal(v.expect) |
|
||||||
if err != nil { |
|
||||||
t.Errorf("marshal(%#v): %s", v.input, err) |
|
||||||
} |
|
||||||
if !reflect.DeepEqual(strings.ReplaceAll(string(got), " ", ""), strings.ReplaceAll(string(want), " ", "")) { |
|
||||||
t.Errorf("marshal(%#v):\nhave %#q\nwant %#q", v.input, got, want) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,46 +0,0 @@ |
|||||||
package proto |
|
||||||
|
|
||||||
import ( |
|
||||||
"reflect" |
|
||||||
"testing" |
|
||||||
|
|
||||||
testData "github.com/go-kratos/kratos/v2/internal/testdata/encoding" |
|
||||||
) |
|
||||||
|
|
||||||
func TestName(t *testing.T) { |
|
||||||
c := new(codec) |
|
||||||
if !reflect.DeepEqual(c.Name(), "proto") { |
|
||||||
t.Errorf("no expect float_key value: %v, but got: %v", c.Name(), "proto") |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestCodec(t *testing.T) { |
|
||||||
c := new(codec) |
|
||||||
|
|
||||||
model := testData.TestModel{ |
|
||||||
Id: 1, |
|
||||||
Name: "kratos", |
|
||||||
Hobby: []string{"study", "eat", "play"}, |
|
||||||
} |
|
||||||
|
|
||||||
m, err := c.Marshal(&model) |
|
||||||
if err != nil { |
|
||||||
t.Errorf("Marshal() should be nil, but got %s", err) |
|
||||||
} |
|
||||||
|
|
||||||
var res testData.TestModel |
|
||||||
|
|
||||||
err = c.Unmarshal(m, &res) |
|
||||||
if err != nil { |
|
||||||
t.Errorf("Unmarshal() should be nil, but got %s", err) |
|
||||||
} |
|
||||||
if !reflect.DeepEqual(res.Id, model.Id) { |
|
||||||
t.Errorf("ID should be %d, but got %d", res.Id, model.Id) |
|
||||||
} |
|
||||||
if !reflect.DeepEqual(res.Name, model.Name) { |
|
||||||
t.Errorf("Name should be %s, but got %s", res.Name, model.Name) |
|
||||||
} |
|
||||||
if !reflect.DeepEqual(res.Hobby, model.Hobby) { |
|
||||||
t.Errorf("Hobby should be %s, but got %s", res.Hobby, model.Hobby) |
|
||||||
} |
|
||||||
} |
|
@ -1,117 +0,0 @@ |
|||||||
package xml |
|
||||||
|
|
||||||
import ( |
|
||||||
"reflect" |
|
||||||
"strings" |
|
||||||
"testing" |
|
||||||
) |
|
||||||
|
|
||||||
type Plain struct { |
|
||||||
V interface{} |
|
||||||
} |
|
||||||
|
|
||||||
type NestedOrder struct { |
|
||||||
XMLName struct{} `xml:"result"` |
|
||||||
Field1 string `xml:"parent>c"` |
|
||||||
Field2 string `xml:"parent>b"` |
|
||||||
Field3 string `xml:"parent>a"` |
|
||||||
} |
|
||||||
|
|
||||||
func TestCodec_Marshal(t *testing.T) { |
|
||||||
tests := []struct { |
|
||||||
Value interface{} |
|
||||||
ExpectXML string |
|
||||||
}{ |
|
||||||
// Test value types
|
|
||||||
{Value: &Plain{true}, ExpectXML: `<Plain><V>true</V></Plain>`}, |
|
||||||
{Value: &Plain{false}, ExpectXML: `<Plain><V>false</V></Plain>`}, |
|
||||||
{Value: &Plain{42}, ExpectXML: `<Plain><V>42</V></Plain>`}, |
|
||||||
{ |
|
||||||
Value: &NestedOrder{Field1: "C", Field2: "B", Field3: "A"}, |
|
||||||
ExpectXML: `<result>` + |
|
||||||
`<parent>` + |
|
||||||
`<c>C</c>` + |
|
||||||
`<b>B</b>` + |
|
||||||
`<a>A</a>` + |
|
||||||
`</parent>` + |
|
||||||
`</result>`, |
|
||||||
}, |
|
||||||
} |
|
||||||
for _, tt := range tests { |
|
||||||
data, err := (codec{}).Marshal(tt.Value) |
|
||||||
if err != nil { |
|
||||||
t.Errorf("marshal(%#v): %s", tt.Value, err) |
|
||||||
} |
|
||||||
if got, want := string(data), tt.ExpectXML; got != want { |
|
||||||
if strings.Contains(want, "\n") { |
|
||||||
t.Errorf("marshal(%#v):\nHAVE:\n%s\nWANT:\n%s", tt.Value, got, want) |
|
||||||
} else { |
|
||||||
t.Errorf("marshal(%#v):\nhave %#q\nwant %#q", tt.Value, got, want) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestCodec_Unmarshal(t *testing.T) { |
|
||||||
tests := []struct { |
|
||||||
want interface{} |
|
||||||
InputXML string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
want: &NestedOrder{Field1: "C", Field2: "B", Field3: "A"}, |
|
||||||
InputXML: `<result>` + |
|
||||||
`<parent>` + |
|
||||||
`<c>C</c>` + |
|
||||||
`<b>B</b>` + |
|
||||||
`<a>A</a>` + |
|
||||||
`</parent>` + |
|
||||||
`</result>`, |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
for _, tt := range tests { |
|
||||||
vt := reflect.TypeOf(tt.want) |
|
||||||
dest := reflect.New(vt.Elem()).Interface() |
|
||||||
data := []byte(tt.InputXML) |
|
||||||
err := (codec{}).Unmarshal(data, dest) |
|
||||||
if err != nil { |
|
||||||
t.Errorf("unmarshal(%#v, %#v): %s", tt.InputXML, dest, err) |
|
||||||
} |
|
||||||
if got, want := dest, tt.want; !reflect.DeepEqual(got, want) { |
|
||||||
t.Errorf("unmarshal(%q):\nhave %#v\nwant %#v", tt.InputXML, got, want) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestCodec_NilUnmarshal(t *testing.T) { |
|
||||||
tests := []struct { |
|
||||||
want interface{} |
|
||||||
InputXML string |
|
||||||
}{ |
|
||||||
{ |
|
||||||
want: &NestedOrder{Field1: "C", Field2: "B", Field3: "A"}, |
|
||||||
InputXML: `<result>` + |
|
||||||
`<parent>` + |
|
||||||
`<c>C</c>` + |
|
||||||
`<b>B</b>` + |
|
||||||
`<a>A</a>` + |
|
||||||
`</parent>` + |
|
||||||
`</result>`, |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
for _, tt := range tests { |
|
||||||
s := struct { |
|
||||||
A string `xml:"a"` |
|
||||||
B *NestedOrder |
|
||||||
}{A: "a"} |
|
||||||
data := []byte(tt.InputXML) |
|
||||||
err := (codec{}).Unmarshal(data, &s.B) |
|
||||||
if err != nil { |
|
||||||
t.Errorf("unmarshal(%#v, %#v): %s", tt.InputXML, s.B, err) |
|
||||||
} |
|
||||||
if got, want := s.B, tt.want; !reflect.DeepEqual(got, want) { |
|
||||||
t.Errorf("unmarshal(%q):\nhave %#v\nwant %#v", tt.InputXML, got, want) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,104 +0,0 @@ |
|||||||
package yaml |
|
||||||
|
|
||||||
import ( |
|
||||||
"math" |
|
||||||
"reflect" |
|
||||||
"testing" |
|
||||||
) |
|
||||||
|
|
||||||
func TestCodec_Unmarshal(t *testing.T) { |
|
||||||
tests := []struct { |
|
||||||
data string |
|
||||||
value interface{} |
|
||||||
}{ |
|
||||||
{ |
|
||||||
"", |
|
||||||
(*struct{})(nil), |
|
||||||
}, |
|
||||||
{ |
|
||||||
"{}", &struct{}{}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"v: hi", |
|
||||||
map[string]string{"v": "hi"}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"v: hi", map[string]interface{}{"v": "hi"}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"v: true", |
|
||||||
map[string]string{"v": "true"}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"v: true", |
|
||||||
map[string]interface{}{"v": true}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"v: 10", |
|
||||||
map[string]interface{}{"v": 10}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"v: 0b10", |
|
||||||
map[string]interface{}{"v": 2}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"v: 0xA", |
|
||||||
map[string]interface{}{"v": 10}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"v: 4294967296", |
|
||||||
map[string]int64{"v": 4294967296}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"v: 0.1", |
|
||||||
map[string]interface{}{"v": 0.1}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"v: .1", |
|
||||||
map[string]interface{}{"v": 0.1}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"v: .Inf", |
|
||||||
map[string]interface{}{"v": math.Inf(+1)}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"v: -.Inf", |
|
||||||
map[string]interface{}{"v": math.Inf(-1)}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"v: -10", |
|
||||||
map[string]interface{}{"v": -10}, |
|
||||||
}, |
|
||||||
{ |
|
||||||
"v: -.1", |
|
||||||
map[string]interface{}{"v": -0.1}, |
|
||||||
}, |
|
||||||
} |
|
||||||
for _, tt := range tests { |
|
||||||
v := reflect.ValueOf(tt.value).Type() |
|
||||||
value := reflect.New(v) |
|
||||||
err := (codec{}).Unmarshal([]byte(tt.data), value.Interface()) |
|
||||||
if err != nil { |
|
||||||
t.Fatalf("(codec{}).Unmarshal should not return err") |
|
||||||
} |
|
||||||
} |
|
||||||
spec := struct { |
|
||||||
A string |
|
||||||
B map[string]interface{} |
|
||||||
}{A: "a"} |
|
||||||
err := (codec{}).Unmarshal([]byte("v: hi"), &spec.B) |
|
||||||
if err != nil { |
|
||||||
t.Fatalf("(codec{}).Unmarshal should not return err") |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
func TestCodec_Marshal(t *testing.T) { |
|
||||||
value := map[string]string{"v": "hi"} |
|
||||||
got, err := (codec{}).Marshal(value) |
|
||||||
if err != nil { |
|
||||||
t.Fatalf("should not return err") |
|
||||||
} |
|
||||||
if string(got) != "v: hi\n" { |
|
||||||
t.Fatalf("want \"v: hi\n\" return \"%s\"", string(got)) |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue