You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kratos/transport/http/server_test.go

156 lines
3.3 KiB

4 years ago
package http
import (
"context"
"encoding/json"
"fmt"
"github.com/go-kratos/kratos/v2/errors"
"io/ioutil"
4 years ago
"net/http"
"strings"
4 years ago
"testing"
"time"
"github.com/go-kratos/kratos/v2/internal/host"
"github.com/stretchr/testify/assert"
4 years ago
)
type testKey struct{}
4 years ago
type testData struct {
Path string `json:"path"`
}
func TestServer(t *testing.T) {
fn := func(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(testData{Path: r.RequestURI})
4 years ago
}
ctx := context.Background()
4 years ago
srv := NewServer()
srv.HandleFunc("/index", fn)
srv.HandleFunc("/index/{id:[0-9]+}", fn)
4 years ago
if e, err := srv.Endpoint(); err != nil || e == nil || strings.HasSuffix(e.Host, ":0") {
t.Fatal(e, err)
4 years ago
}
go func() {
if err := srv.Start(ctx); err != nil {
panic(err)
}
}()
time.Sleep(time.Second)
testClient(t, srv)
srv.Stop(ctx)
4 years ago
}
func testClient(t *testing.T, srv *Server) {
tests := []struct {
method string
path string
}{
{"GET", "/index"},
{"PUT", "/index"},
{"POST", "/index"},
{"PATCH", "/index"},
{"DELETE", "/index"},
{"GET", "/index/1"},
{"PUT", "/index/1"},
{"POST", "/index/1"},
{"PATCH", "/index/1"},
{"DELETE", "/index/1"},
{"GET", "/index/notfound"},
4 years ago
}
e, err := srv.Endpoint()
if err != nil {
t.Fatal(err)
4 years ago
}
client, err := NewClient(context.Background(), WithEndpoint(e.Host))
if err != nil {
t.Fatal(err)
}
4 years ago
for _, test := range tests {
var res testData
url := fmt.Sprintf(e.String() + test.path)
4 years ago
req, err := http.NewRequest(test.method, url, nil)
if err != nil {
t.Fatal(err)
}
resp, err := client.Do(req)
if test.path == "/index/notfound" && err != nil {
if e, ok := err.(*errors.Error); ok && e.Code == http.StatusNotFound {
continue
}
}
if err != nil {
4 years ago
t.Fatal(err)
}
if resp.StatusCode != 200 {
t.Fatalf("http status got %d", resp.StatusCode)
}
content, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf("read resp error %v", err)
}
err = json.Unmarshal(content, &res)
if err != nil {
t.Fatalf("unmarshal resp error %v", err)
}
if res.Path != test.path {
t.Errorf("expected %s got %s", test.path, res.Path)
}
}
for _, test := range tests {
var res testData
err := client.Invoke(context.Background(), test.method, test.path, nil, &res)
if test.path == "/index/notfound" && err != nil {
if e, ok := err.(*errors.Error); ok && e.Code == http.StatusNotFound {
continue
}
}
if err != nil {
t.Fatalf("invoke error %v", err)
}
4 years ago
if res.Path != test.path {
t.Errorf("expected %s got %s", test.path, res.Path)
}
}
4 years ago
}
func BenchmarkServer(b *testing.B) {
fn := func(w http.ResponseWriter, r *http.Request) {
data := &testData{Path: r.RequestURI}
json.NewEncoder(w).Encode(data)
if r.Context().Value(testKey{}) != "test" {
w.WriteHeader(500)
}
}
ctx := context.Background()
ctx = context.WithValue(ctx, testKey{}, "test")
srv := NewServer()
srv.HandleFunc("/index", fn)
go func() {
if err := srv.Start(ctx); err != nil {
panic(err)
}
}()
time.Sleep(time.Second)
port, ok := host.Port(srv.lis)
assert.True(b, ok)
client, err := NewClient(context.Background(), WithEndpoint(fmt.Sprintf("127.0.0.1:%d", port)))
assert.NoError(b, err)
b.ResetTimer()
for i := 0; i < b.N; i++ {
var res testData
err := client.Invoke(context.Background(), "POST", "/index", nil, &res)
assert.NoError(b, err)
}
srv.Stop(ctx)
}