|
|
|
package http
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"encoding/json"
|
|
|
|
"io/ioutil"
|
|
|
|
nethttp "net/http"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/go-kratos/kratos/v2/errors"
|
|
|
|
"github.com/go-kratos/kratos/v2/middleware"
|
|
|
|
"github.com/go-kratos/kratos/v2/registry"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
)
|
|
|
|
|
|
|
|
type mockRoundTripper struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rt *mockRoundTripper) RoundTrip(req *nethttp.Request) (resp *nethttp.Response, err error) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWithTransport(t *testing.T) {
|
|
|
|
ov := &mockRoundTripper{}
|
|
|
|
o := WithTransport(ov)
|
|
|
|
co := &clientOptions{}
|
|
|
|
o(co)
|
|
|
|
assert.Equal(t, co.transport, ov)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWithTimeout(t *testing.T) {
|
|
|
|
ov := 1 * time.Second
|
|
|
|
o := WithTimeout(ov)
|
|
|
|
co := &clientOptions{}
|
|
|
|
o(co)
|
|
|
|
assert.Equal(t, co.timeout, ov)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWithBalancer(t *testing.T) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWithUserAgent(t *testing.T) {
|
|
|
|
ov := "kratos"
|
|
|
|
o := WithUserAgent(ov)
|
|
|
|
co := &clientOptions{}
|
|
|
|
o(co)
|
|
|
|
assert.Equal(t, co.userAgent, ov)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWithMiddleware(t *testing.T) {
|
|
|
|
o := &clientOptions{}
|
|
|
|
v := []middleware.Middleware{
|
|
|
|
func(middleware.Handler) middleware.Handler { return nil },
|
|
|
|
}
|
|
|
|
WithMiddleware(v...)(o)
|
|
|
|
assert.Equal(t, v, o.middleware)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWithEndpoint(t *testing.T) {
|
|
|
|
ov := "some-endpoint"
|
|
|
|
o := WithEndpoint(ov)
|
|
|
|
co := &clientOptions{}
|
|
|
|
o(co)
|
|
|
|
assert.Equal(t, co.endpoint, ov)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWithRequestEncoder(t *testing.T) {
|
|
|
|
o := &clientOptions{}
|
|
|
|
v := func(ctx context.Context, contentType string, in interface{}) (body []byte, err error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
WithRequestEncoder(v)(o)
|
|
|
|
assert.NotNil(t, o.encoder)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWithResponseDecoder(t *testing.T) {
|
|
|
|
o := &clientOptions{}
|
|
|
|
v := func(ctx context.Context, res *nethttp.Response, out interface{}) error { return nil }
|
|
|
|
WithResponseDecoder(v)(o)
|
|
|
|
assert.NotNil(t, o.decoder)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWithErrorDecoder(t *testing.T) {
|
|
|
|
o := &clientOptions{}
|
|
|
|
v := func(ctx context.Context, res *nethttp.Response) error { return nil }
|
|
|
|
WithErrorDecoder(v)(o)
|
|
|
|
assert.NotNil(t, o.errorDecoder)
|
|
|
|
}
|
|
|
|
|
|
|
|
type mockDiscovery struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*mockDiscovery) GetService(ctx context.Context, serviceName string) ([]*registry.ServiceInstance, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*mockDiscovery) Watch(ctx context.Context, serviceName string) (registry.Watcher, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestWithDiscovery(t *testing.T) {
|
|
|
|
ov := &mockDiscovery{}
|
|
|
|
o := WithDiscovery(ov)
|
|
|
|
co := &clientOptions{}
|
|
|
|
o(co)
|
|
|
|
assert.Equal(t, co.discovery, ov)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDefaultRequestEncoder(t *testing.T) {
|
|
|
|
req1 := &nethttp.Request{
|
|
|
|
Header: make(nethttp.Header),
|
|
|
|
Body: ioutil.NopCloser(bytes.NewBufferString("{\"a\":\"1\", \"b\": 2}")),
|
|
|
|
}
|
|
|
|
req1.Header.Set("Content-Type", "application/xml")
|
|
|
|
|
|
|
|
v1 := &struct {
|
|
|
|
A string `json:"a"`
|
|
|
|
B int64 `json:"b"`
|
|
|
|
}{"a", 1}
|
|
|
|
b, err1 := DefaultRequestEncoder(context.TODO(), "application/json", v1)
|
|
|
|
assert.Nil(t, err1)
|
|
|
|
v1b := &struct {
|
|
|
|
A string `json:"a"`
|
|
|
|
B int64 `json:"b"`
|
|
|
|
}{}
|
|
|
|
err1 = json.Unmarshal(b, v1b)
|
|
|
|
assert.Nil(t, err1)
|
|
|
|
assert.Equal(t, v1, v1b)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDefaultResponseDecoder(t *testing.T) {
|
|
|
|
resp1 := &nethttp.Response{
|
|
|
|
Header: make(nethttp.Header),
|
|
|
|
StatusCode: 200,
|
|
|
|
Body: ioutil.NopCloser(bytes.NewBufferString("{\"a\":\"1\", \"b\": 2}")),
|
|
|
|
}
|
|
|
|
v1 := &struct {
|
|
|
|
A string `json:"a"`
|
|
|
|
B int64 `json:"b"`
|
|
|
|
}{}
|
|
|
|
err1 := DefaultResponseDecoder(context.TODO(), resp1, &v1)
|
|
|
|
assert.Nil(t, err1)
|
|
|
|
assert.Equal(t, "1", v1.A)
|
|
|
|
assert.Equal(t, int64(2), v1.B)
|
|
|
|
|
|
|
|
resp2 := &nethttp.Response{
|
|
|
|
Header: make(nethttp.Header),
|
|
|
|
StatusCode: 200,
|
|
|
|
Body: ioutil.NopCloser(bytes.NewBufferString("{badjson}")),
|
|
|
|
}
|
|
|
|
v2 := &struct {
|
|
|
|
A string `json:"a"`
|
|
|
|
B int64 `json:"b"`
|
|
|
|
}{}
|
|
|
|
err2 := DefaultResponseDecoder(context.TODO(), resp2, &v2)
|
|
|
|
terr1 := &json.SyntaxError{}
|
|
|
|
assert.ErrorAs(t, err2, &terr1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDefaultErrorDecoder(t *testing.T) {
|
|
|
|
for i := 200; i < 300; i++ {
|
|
|
|
resp := &nethttp.Response{Header: make(nethttp.Header), StatusCode: i}
|
|
|
|
assert.Nil(t, DefaultErrorDecoder(context.TODO(), resp))
|
|
|
|
}
|
|
|
|
resp1 := &nethttp.Response{
|
|
|
|
Header: make(nethttp.Header),
|
|
|
|
StatusCode: 300,
|
|
|
|
Body: ioutil.NopCloser(bytes.NewBufferString("{\"foo\":\"bar\"}")),
|
|
|
|
}
|
|
|
|
assert.Error(t, DefaultErrorDecoder(context.TODO(), resp1))
|
|
|
|
|
|
|
|
resp2 := &nethttp.Response{
|
|
|
|
Header: make(nethttp.Header),
|
|
|
|
StatusCode: 500,
|
|
|
|
Body: ioutil.NopCloser(bytes.NewBufferString("{\"code\":54321, \"message\": \"hi\", \"reason\": \"FOO\"}")),
|
|
|
|
}
|
|
|
|
err2 := DefaultErrorDecoder(context.TODO(), resp2)
|
|
|
|
assert.Error(t, err2)
|
|
|
|
assert.Equal(t, int32(500), err2.(*errors.Error).GetCode())
|
|
|
|
assert.Equal(t, "hi", err2.(*errors.Error).GetMessage())
|
|
|
|
assert.Equal(t, "FOO", err2.(*errors.Error).GetReason())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCodecForResponse(t *testing.T) {
|
|
|
|
resp := &nethttp.Response{Header: make(nethttp.Header)}
|
|
|
|
resp.Header.Set("Content-Type", "application/xml")
|
|
|
|
c := CodecForResponse(resp)
|
|
|
|
assert.Equal(t, "xml", c.Name())
|
|
|
|
}
|