720 lines
20 KiB
Go
720 lines
20 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"io/ioutil"
|
||
|
"net/http"
|
||
|
"reflect"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
"sync"
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"github.com/golang/protobuf/jsonpb"
|
||
|
"github.com/golang/protobuf/proto"
|
||
|
"github.com/golang/protobuf/ptypes/empty"
|
||
|
gw "github.com/grpc-ecosystem/grpc-gateway/examples/examplepb"
|
||
|
sub "github.com/grpc-ecosystem/grpc-gateway/examples/sub"
|
||
|
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||
|
"golang.org/x/net/context"
|
||
|
"google.golang.org/grpc/codes"
|
||
|
)
|
||
|
|
||
|
type errorBody struct {
|
||
|
Error string `json:"error"`
|
||
|
Code int `json:"code"`
|
||
|
}
|
||
|
|
||
|
func TestEcho(t *testing.T) {
|
||
|
if testing.Short() {
|
||
|
t.Skip()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
testEcho(t, 8080, "application/json")
|
||
|
testEchoBody(t)
|
||
|
}
|
||
|
|
||
|
func TestForwardResponseOption(t *testing.T) {
|
||
|
go func() {
|
||
|
if err := Run(
|
||
|
":8081",
|
||
|
runtime.WithForwardResponseOption(
|
||
|
func(_ context.Context, w http.ResponseWriter, _ proto.Message) error {
|
||
|
w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1.1+json")
|
||
|
return nil
|
||
|
},
|
||
|
),
|
||
|
); err != nil {
|
||
|
t.Errorf("gw.Run() failed with %v; want success", err)
|
||
|
return
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
time.Sleep(100 * time.Millisecond)
|
||
|
testEcho(t, 8081, "application/vnd.docker.plugins.v1.1+json")
|
||
|
}
|
||
|
|
||
|
func testEcho(t *testing.T, port int, contentType string) {
|
||
|
url := fmt.Sprintf("http://localhost:%d/v1/example/echo/myid", port)
|
||
|
resp, err := http.Post(url, "application/json", strings.NewReader("{}"))
|
||
|
if err != nil {
|
||
|
t.Errorf("http.Post(%q) failed with %v; want success", url, err)
|
||
|
return
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
buf, err := ioutil.ReadAll(resp.Body)
|
||
|
if err != nil {
|
||
|
t.Errorf("iotuil.ReadAll(resp.Body) failed with %v; want success", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
||
|
t.Errorf("resp.StatusCode = %d; want %d", got, want)
|
||
|
t.Logf("%s", buf)
|
||
|
}
|
||
|
|
||
|
var msg gw.SimpleMessage
|
||
|
if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil {
|
||
|
t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err)
|
||
|
return
|
||
|
}
|
||
|
if got, want := msg.Id, "myid"; got != want {
|
||
|
t.Errorf("msg.Id = %q; want %q", got, want)
|
||
|
}
|
||
|
|
||
|
if value := resp.Header.Get("Content-Type"); value != contentType {
|
||
|
t.Errorf("Content-Type was %s, wanted %s", value, contentType)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func testEchoBody(t *testing.T) {
|
||
|
sent := gw.SimpleMessage{Id: "example"}
|
||
|
var m jsonpb.Marshaler
|
||
|
payload, err := m.MarshalToString(&sent)
|
||
|
if err != nil {
|
||
|
t.Fatalf("m.MarshalToString(%#v) failed with %v; want success", payload, err)
|
||
|
}
|
||
|
|
||
|
url := "http://localhost:8080/v1/example/echo_body"
|
||
|
resp, err := http.Post(url, "", strings.NewReader(payload))
|
||
|
if err != nil {
|
||
|
t.Errorf("http.Post(%q) failed with %v; want success", url, err)
|
||
|
return
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
buf, err := ioutil.ReadAll(resp.Body)
|
||
|
if err != nil {
|
||
|
t.Errorf("iotuil.ReadAll(resp.Body) failed with %v; want success", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
||
|
t.Errorf("resp.StatusCode = %d; want %d", got, want)
|
||
|
t.Logf("%s", buf)
|
||
|
}
|
||
|
|
||
|
var received gw.SimpleMessage
|
||
|
if err := jsonpb.UnmarshalString(string(buf), &received); err != nil {
|
||
|
t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err)
|
||
|
return
|
||
|
}
|
||
|
if got, want := received, sent; !reflect.DeepEqual(got, want) {
|
||
|
t.Errorf("msg.Id = %q; want %q", got, want)
|
||
|
}
|
||
|
|
||
|
if got, want := resp.Header.Get("Grpc-Metadata-Foo"), "foo1"; got != want {
|
||
|
t.Errorf("Grpc-Metadata-Foo was %q, wanted %q", got, want)
|
||
|
}
|
||
|
if got, want := resp.Header.Get("Grpc-Metadata-Bar"), "bar1"; got != want {
|
||
|
t.Errorf("Grpc-Metadata-Bar was %q, wanted %q", got, want)
|
||
|
}
|
||
|
|
||
|
if got, want := resp.Trailer.Get("Grpc-Trailer-Foo"), "foo2"; got != want {
|
||
|
t.Errorf("Grpc-Trailer-Foo was %q, wanted %q", got, want)
|
||
|
}
|
||
|
if got, want := resp.Trailer.Get("Grpc-Trailer-Bar"), "bar2"; got != want {
|
||
|
t.Errorf("Grpc-Trailer-Bar was %q, wanted %q", got, want)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestABE(t *testing.T) {
|
||
|
if testing.Short() {
|
||
|
t.Skip()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
testABECreate(t)
|
||
|
testABECreateBody(t)
|
||
|
testABEBulkCreate(t)
|
||
|
testABELookup(t)
|
||
|
testABELookupNotFound(t)
|
||
|
testABEList(t)
|
||
|
testABEBulkEcho(t)
|
||
|
testABEBulkEchoZeroLength(t)
|
||
|
testAdditionalBindings(t)
|
||
|
}
|
||
|
|
||
|
func testABECreate(t *testing.T) {
|
||
|
want := gw.ABitOfEverything{
|
||
|
FloatValue: 1.5,
|
||
|
DoubleValue: 2.5,
|
||
|
Int64Value: 4294967296,
|
||
|
Uint64Value: 9223372036854775807,
|
||
|
Int32Value: -2147483648,
|
||
|
Fixed64Value: 9223372036854775807,
|
||
|
Fixed32Value: 4294967295,
|
||
|
BoolValue: true,
|
||
|
StringValue: "strprefix/foo",
|
||
|
Uint32Value: 4294967295,
|
||
|
Sfixed32Value: 2147483647,
|
||
|
Sfixed64Value: -4611686018427387904,
|
||
|
Sint32Value: 2147483647,
|
||
|
Sint64Value: 4611686018427387903,
|
||
|
NonConventionalNameValue: "camelCase",
|
||
|
}
|
||
|
url := fmt.Sprintf("http://localhost:8080/v1/example/a_bit_of_everything/%f/%f/%d/separator/%d/%d/%d/%d/%v/%s/%d/%d/%d/%d/%d/%s", want.FloatValue, want.DoubleValue, want.Int64Value, want.Uint64Value, want.Int32Value, want.Fixed64Value, want.Fixed32Value, want.BoolValue, want.StringValue, want.Uint32Value, want.Sfixed32Value, want.Sfixed64Value, want.Sint32Value, want.Sint64Value, want.NonConventionalNameValue)
|
||
|
|
||
|
resp, err := http.Post(url, "application/json", strings.NewReader("{}"))
|
||
|
if err != nil {
|
||
|
t.Errorf("http.Post(%q) failed with %v; want success", url, err)
|
||
|
return
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
buf, err := ioutil.ReadAll(resp.Body)
|
||
|
if err != nil {
|
||
|
t.Errorf("iotuil.ReadAll(resp.Body) failed with %v; want success", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
||
|
t.Errorf("resp.StatusCode = %d; want %d", got, want)
|
||
|
t.Logf("%s", buf)
|
||
|
}
|
||
|
|
||
|
var msg gw.ABitOfEverything
|
||
|
if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil {
|
||
|
t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err)
|
||
|
return
|
||
|
}
|
||
|
if msg.Uuid == "" {
|
||
|
t.Error("msg.Uuid is empty; want not empty")
|
||
|
}
|
||
|
msg.Uuid = ""
|
||
|
if got := msg; !reflect.DeepEqual(got, want) {
|
||
|
t.Errorf("msg= %v; want %v", &got, &want)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func testABECreateBody(t *testing.T) {
|
||
|
want := gw.ABitOfEverything{
|
||
|
FloatValue: 1.5,
|
||
|
DoubleValue: 2.5,
|
||
|
Int64Value: 4294967296,
|
||
|
Uint64Value: 9223372036854775807,
|
||
|
Int32Value: -2147483648,
|
||
|
Fixed64Value: 9223372036854775807,
|
||
|
Fixed32Value: 4294967295,
|
||
|
BoolValue: true,
|
||
|
StringValue: "strprefix/foo",
|
||
|
Uint32Value: 4294967295,
|
||
|
Sfixed32Value: 2147483647,
|
||
|
Sfixed64Value: -4611686018427387904,
|
||
|
Sint32Value: 2147483647,
|
||
|
Sint64Value: 4611686018427387903,
|
||
|
NonConventionalNameValue: "camelCase",
|
||
|
|
||
|
Nested: []*gw.ABitOfEverything_Nested{
|
||
|
{
|
||
|
Name: "bar",
|
||
|
Amount: 10,
|
||
|
},
|
||
|
{
|
||
|
Name: "baz",
|
||
|
Amount: 20,
|
||
|
},
|
||
|
},
|
||
|
RepeatedStringValue: []string{"a", "b", "c"},
|
||
|
OneofValue: &gw.ABitOfEverything_OneofString{
|
||
|
OneofString: "x",
|
||
|
},
|
||
|
MapValue: map[string]gw.NumericEnum{
|
||
|
"a": gw.NumericEnum_ONE,
|
||
|
"b": gw.NumericEnum_ZERO,
|
||
|
},
|
||
|
MappedStringValue: map[string]string{
|
||
|
"a": "x",
|
||
|
"b": "y",
|
||
|
},
|
||
|
MappedNestedValue: map[string]*gw.ABitOfEverything_Nested{
|
||
|
"a": {Name: "x", Amount: 1},
|
||
|
"b": {Name: "y", Amount: 2},
|
||
|
},
|
||
|
}
|
||
|
url := "http://localhost:8080/v1/example/a_bit_of_everything"
|
||
|
var m jsonpb.Marshaler
|
||
|
payload, err := m.MarshalToString(&want)
|
||
|
if err != nil {
|
||
|
t.Fatalf("m.MarshalToString(%#v) failed with %v; want success", want, err)
|
||
|
}
|
||
|
|
||
|
resp, err := http.Post(url, "application/json", strings.NewReader(payload))
|
||
|
if err != nil {
|
||
|
t.Errorf("http.Post(%q) failed with %v; want success", url, err)
|
||
|
return
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
buf, err := ioutil.ReadAll(resp.Body)
|
||
|
if err != nil {
|
||
|
t.Errorf("iotuil.ReadAll(resp.Body) failed with %v; want success", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
||
|
t.Errorf("resp.StatusCode = %d; want %d", got, want)
|
||
|
t.Logf("%s", buf)
|
||
|
}
|
||
|
|
||
|
var msg gw.ABitOfEverything
|
||
|
if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil {
|
||
|
t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err)
|
||
|
return
|
||
|
}
|
||
|
if msg.Uuid == "" {
|
||
|
t.Error("msg.Uuid is empty; want not empty")
|
||
|
}
|
||
|
msg.Uuid = ""
|
||
|
if got := msg; !reflect.DeepEqual(got, want) {
|
||
|
t.Errorf("msg= %v; want %v", &got, &want)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func testABEBulkCreate(t *testing.T) {
|
||
|
count := 0
|
||
|
r, w := io.Pipe()
|
||
|
go func(w io.WriteCloser) {
|
||
|
defer func() {
|
||
|
if cerr := w.Close(); cerr != nil {
|
||
|
t.Errorf("w.Close() failed with %v; want success", cerr)
|
||
|
}
|
||
|
}()
|
||
|
for _, val := range []string{
|
||
|
"foo", "bar", "baz", "qux", "quux",
|
||
|
} {
|
||
|
want := gw.ABitOfEverything{
|
||
|
FloatValue: 1.5,
|
||
|
DoubleValue: 2.5,
|
||
|
Int64Value: 4294967296,
|
||
|
Uint64Value: 9223372036854775807,
|
||
|
Int32Value: -2147483648,
|
||
|
Fixed64Value: 9223372036854775807,
|
||
|
Fixed32Value: 4294967295,
|
||
|
BoolValue: true,
|
||
|
StringValue: fmt.Sprintf("strprefix/%s", val),
|
||
|
Uint32Value: 4294967295,
|
||
|
Sfixed32Value: 2147483647,
|
||
|
Sfixed64Value: -4611686018427387904,
|
||
|
Sint32Value: 2147483647,
|
||
|
Sint64Value: 4611686018427387903,
|
||
|
NonConventionalNameValue: "camelCase",
|
||
|
|
||
|
Nested: []*gw.ABitOfEverything_Nested{
|
||
|
{
|
||
|
Name: "hoge",
|
||
|
Amount: 10,
|
||
|
},
|
||
|
{
|
||
|
Name: "fuga",
|
||
|
Amount: 20,
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
var m jsonpb.Marshaler
|
||
|
if err := m.Marshal(w, &want); err != nil {
|
||
|
t.Fatalf("m.Marshal(%#v, w) failed with %v; want success", want, err)
|
||
|
}
|
||
|
if _, err := io.WriteString(w, "\n"); err != nil {
|
||
|
t.Errorf("w.Write(%q) failed with %v; want success", "\n", err)
|
||
|
return
|
||
|
}
|
||
|
count++
|
||
|
}
|
||
|
}(w)
|
||
|
url := "http://localhost:8080/v1/example/a_bit_of_everything/bulk"
|
||
|
resp, err := http.Post(url, "application/json", r)
|
||
|
if err != nil {
|
||
|
t.Errorf("http.Post(%q) failed with %v; want success", url, err)
|
||
|
return
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
buf, err := ioutil.ReadAll(resp.Body)
|
||
|
if err != nil {
|
||
|
t.Errorf("iotuil.ReadAll(resp.Body) failed with %v; want success", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
||
|
t.Errorf("resp.StatusCode = %d; want %d", got, want)
|
||
|
t.Logf("%s", buf)
|
||
|
}
|
||
|
|
||
|
var msg empty.Empty
|
||
|
if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil {
|
||
|
t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if got, want := resp.Header.Get("Grpc-Metadata-Count"), fmt.Sprintf("%d", count); got != want {
|
||
|
t.Errorf("Grpc-Metadata-Count was %q, wanted %q", got, want)
|
||
|
}
|
||
|
|
||
|
if got, want := resp.Trailer.Get("Grpc-Trailer-Foo"), "foo2"; got != want {
|
||
|
t.Errorf("Grpc-Trailer-Foo was %q, wanted %q", got, want)
|
||
|
}
|
||
|
if got, want := resp.Trailer.Get("Grpc-Trailer-Bar"), "bar2"; got != want {
|
||
|
t.Errorf("Grpc-Trailer-Bar was %q, wanted %q", got, want)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func testABELookup(t *testing.T) {
|
||
|
url := "http://localhost:8080/v1/example/a_bit_of_everything"
|
||
|
cresp, err := http.Post(url, "application/json", strings.NewReader(`
|
||
|
{"bool_value": true, "string_value": "strprefix/example"}
|
||
|
`))
|
||
|
if err != nil {
|
||
|
t.Errorf("http.Post(%q) failed with %v; want success", url, err)
|
||
|
return
|
||
|
}
|
||
|
defer cresp.Body.Close()
|
||
|
buf, err := ioutil.ReadAll(cresp.Body)
|
||
|
if err != nil {
|
||
|
t.Errorf("iotuil.ReadAll(cresp.Body) failed with %v; want success", err)
|
||
|
return
|
||
|
}
|
||
|
if got, want := cresp.StatusCode, http.StatusOK; got != want {
|
||
|
t.Errorf("resp.StatusCode = %d; want %d", got, want)
|
||
|
t.Logf("%s", buf)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var want gw.ABitOfEverything
|
||
|
if err := jsonpb.UnmarshalString(string(buf), &want); err != nil {
|
||
|
t.Errorf("jsonpb.UnmarshalString(%s, &want) failed with %v; want success", buf, err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
url = fmt.Sprintf("%s/%s", url, want.Uuid)
|
||
|
resp, err := http.Get(url)
|
||
|
if err != nil {
|
||
|
t.Errorf("http.Get(%q) failed with %v; want success", url, err)
|
||
|
return
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
|
||
|
buf, err = ioutil.ReadAll(resp.Body)
|
||
|
if err != nil {
|
||
|
t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var msg gw.ABitOfEverything
|
||
|
if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil {
|
||
|
t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err)
|
||
|
return
|
||
|
}
|
||
|
if got := msg; !reflect.DeepEqual(got, want) {
|
||
|
t.Errorf("msg= %v; want %v", &got, &want)
|
||
|
}
|
||
|
|
||
|
if got, want := resp.Header.Get("Grpc-Metadata-Uuid"), want.Uuid; got != want {
|
||
|
t.Errorf("Grpc-Metadata-Uuid was %s, wanted %s", got, want)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func testABELookupNotFound(t *testing.T) {
|
||
|
url := "http://localhost:8080/v1/example/a_bit_of_everything"
|
||
|
uuid := "not_exist"
|
||
|
url = fmt.Sprintf("%s/%s", url, uuid)
|
||
|
resp, err := http.Get(url)
|
||
|
if err != nil {
|
||
|
t.Errorf("http.Get(%q) failed with %v; want success", url, err)
|
||
|
return
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
|
||
|
buf, err := ioutil.ReadAll(resp.Body)
|
||
|
if err != nil {
|
||
|
t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if got, want := resp.StatusCode, http.StatusNotFound; got != want {
|
||
|
t.Errorf("resp.StatusCode = %d; want %d", got, want)
|
||
|
t.Logf("%s", buf)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var msg errorBody
|
||
|
if err := json.Unmarshal(buf, &msg); err != nil {
|
||
|
t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if got, want := msg.Code, int(codes.NotFound); got != want {
|
||
|
t.Errorf("msg.Code = %d; want %d", got, want)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if got, want := resp.Header.Get("Grpc-Metadata-Uuid"), uuid; got != want {
|
||
|
t.Errorf("Grpc-Metadata-Uuid was %s, wanted %s", got, want)
|
||
|
}
|
||
|
if got, want := resp.Trailer.Get("Grpc-Trailer-Foo"), "foo2"; got != want {
|
||
|
t.Errorf("Grpc-Trailer-Foo was %q, wanted %q", got, want)
|
||
|
}
|
||
|
if got, want := resp.Trailer.Get("Grpc-Trailer-Bar"), "bar2"; got != want {
|
||
|
t.Errorf("Grpc-Trailer-Bar was %q, wanted %q", got, want)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func testABEList(t *testing.T) {
|
||
|
url := "http://localhost:8080/v1/example/a_bit_of_everything"
|
||
|
resp, err := http.Get(url)
|
||
|
if err != nil {
|
||
|
t.Errorf("http.Get(%q) failed with %v; want success", url, err)
|
||
|
return
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
|
||
|
dec := json.NewDecoder(resp.Body)
|
||
|
var i int
|
||
|
for i = 0; ; i++ {
|
||
|
var item struct {
|
||
|
Result json.RawMessage `json:"result"`
|
||
|
Error map[string]interface{} `json:"error"`
|
||
|
}
|
||
|
err := dec.Decode(&item)
|
||
|
if err == io.EOF {
|
||
|
break
|
||
|
}
|
||
|
if err != nil {
|
||
|
t.Errorf("dec.Decode(&item) failed with %v; want success; i = %d", err, i)
|
||
|
}
|
||
|
if len(item.Error) != 0 {
|
||
|
t.Errorf("item.Error = %#v; want empty; i = %d", item.Error, i)
|
||
|
continue
|
||
|
}
|
||
|
var msg gw.ABitOfEverything
|
||
|
if err := jsonpb.UnmarshalString(string(item.Result), &msg); err != nil {
|
||
|
t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", item.Result, err)
|
||
|
}
|
||
|
}
|
||
|
if i <= 0 {
|
||
|
t.Errorf("i == %d; want > 0", i)
|
||
|
}
|
||
|
|
||
|
value := resp.Header.Get("Grpc-Metadata-Count")
|
||
|
if value == "" {
|
||
|
t.Errorf("Grpc-Metadata-Count should not be empty")
|
||
|
}
|
||
|
|
||
|
count, err := strconv.Atoi(value)
|
||
|
if err != nil {
|
||
|
t.Errorf("failed to Atoi %q: %v", value, err)
|
||
|
}
|
||
|
|
||
|
if count <= 0 {
|
||
|
t.Errorf("count == %d; want > 0", count)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func testABEBulkEcho(t *testing.T) {
|
||
|
reqr, reqw := io.Pipe()
|
||
|
var wg sync.WaitGroup
|
||
|
var want []*sub.StringMessage
|
||
|
wg.Add(1)
|
||
|
go func() {
|
||
|
defer wg.Done()
|
||
|
defer reqw.Close()
|
||
|
var m jsonpb.Marshaler
|
||
|
for i := 0; i < 1000; i++ {
|
||
|
msg := sub.StringMessage{Value: proto.String(fmt.Sprintf("message %d", i))}
|
||
|
buf, err := m.MarshalToString(&msg)
|
||
|
if err != nil {
|
||
|
t.Errorf("m.Marshal(%v) failed with %v; want success", &msg, err)
|
||
|
return
|
||
|
}
|
||
|
if _, err := fmt.Fprintln(reqw, buf); err != nil {
|
||
|
t.Errorf("fmt.Fprintln(reqw, %q) failed with %v; want success", buf, err)
|
||
|
return
|
||
|
}
|
||
|
want = append(want, &msg)
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
url := "http://localhost:8080/v1/example/a_bit_of_everything/echo"
|
||
|
req, err := http.NewRequest("POST", url, reqr)
|
||
|
if err != nil {
|
||
|
t.Errorf("http.NewRequest(%q, %q, reqr) failed with %v; want success", "POST", url, err)
|
||
|
return
|
||
|
}
|
||
|
req.Header.Set("Content-Type", "application/json")
|
||
|
req.Header.Set("Transfer-Encoding", "chunked")
|
||
|
resp, err := http.DefaultClient.Do(req)
|
||
|
if err != nil {
|
||
|
t.Errorf("http.Post(%q, %q, req) failed with %v; want success", url, "application/json", err)
|
||
|
return
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
||
|
t.Errorf("resp.StatusCode = %d; want %d", got, want)
|
||
|
}
|
||
|
|
||
|
var got []*sub.StringMessage
|
||
|
wg.Add(1)
|
||
|
go func() {
|
||
|
defer wg.Done()
|
||
|
|
||
|
dec := json.NewDecoder(resp.Body)
|
||
|
for i := 0; ; i++ {
|
||
|
var item struct {
|
||
|
Result json.RawMessage `json:"result"`
|
||
|
Error map[string]interface{} `json:"error"`
|
||
|
}
|
||
|
err := dec.Decode(&item)
|
||
|
if err == io.EOF {
|
||
|
break
|
||
|
}
|
||
|
if err != nil {
|
||
|
t.Errorf("dec.Decode(&item) failed with %v; want success; i = %d", err, i)
|
||
|
}
|
||
|
if len(item.Error) != 0 {
|
||
|
t.Errorf("item.Error = %#v; want empty; i = %d", item.Error, i)
|
||
|
continue
|
||
|
}
|
||
|
var msg sub.StringMessage
|
||
|
if err := jsonpb.UnmarshalString(string(item.Result), &msg); err != nil {
|
||
|
t.Errorf("jsonpb.UnmarshalString(%q, &msg) failed with %v; want success", item.Result, err)
|
||
|
}
|
||
|
got = append(got, &msg)
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
wg.Wait()
|
||
|
if !reflect.DeepEqual(got, want) {
|
||
|
t.Errorf("got = %v; want %v", got, want)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func testABEBulkEchoZeroLength(t *testing.T) {
|
||
|
url := "http://localhost:8080/v1/example/a_bit_of_everything/echo"
|
||
|
req, err := http.NewRequest("POST", url, bytes.NewReader(nil))
|
||
|
if err != nil {
|
||
|
t.Errorf("http.NewRequest(%q, %q, bytes.NewReader(nil)) failed with %v; want success", "POST", url, err)
|
||
|
return
|
||
|
}
|
||
|
req.Header.Set("Content-Type", "application/json")
|
||
|
req.Header.Set("Transfer-Encoding", "chunked")
|
||
|
resp, err := http.DefaultClient.Do(req)
|
||
|
if err != nil {
|
||
|
t.Errorf("http.Post(%q, %q, req) failed with %v; want success", url, "application/json", err)
|
||
|
return
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
||
|
t.Errorf("resp.StatusCode = %d; want %d", got, want)
|
||
|
}
|
||
|
|
||
|
dec := json.NewDecoder(resp.Body)
|
||
|
var item struct {
|
||
|
Result json.RawMessage `json:"result"`
|
||
|
Error map[string]interface{} `json:"error"`
|
||
|
}
|
||
|
if err := dec.Decode(&item); err == nil {
|
||
|
t.Errorf("dec.Decode(&item) succeeded; want io.EOF; item = %#v", item)
|
||
|
} else if err != io.EOF {
|
||
|
t.Errorf("dec.Decode(&item) failed with %v; want success", err)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func testAdditionalBindings(t *testing.T) {
|
||
|
for i, f := range []func() *http.Response{
|
||
|
func() *http.Response {
|
||
|
url := "http://localhost:8080/v1/example/a_bit_of_everything/echo/hello"
|
||
|
resp, err := http.Get(url)
|
||
|
if err != nil {
|
||
|
t.Errorf("http.Get(%q) failed with %v; want success", url, err)
|
||
|
return nil
|
||
|
}
|
||
|
return resp
|
||
|
},
|
||
|
func() *http.Response {
|
||
|
url := "http://localhost:8080/v2/example/echo"
|
||
|
resp, err := http.Post(url, "application/json", strings.NewReader(`"hello"`))
|
||
|
if err != nil {
|
||
|
t.Errorf("http.Post(%q, %q, %q) failed with %v; want success", url, "application/json", `"hello"`, err)
|
||
|
return nil
|
||
|
}
|
||
|
return resp
|
||
|
},
|
||
|
func() *http.Response {
|
||
|
url := "http://localhost:8080/v2/example/echo?value=hello"
|
||
|
resp, err := http.Get(url)
|
||
|
if err != nil {
|
||
|
t.Errorf("http.Get(%q) failed with %v; want success", url, err)
|
||
|
return nil
|
||
|
}
|
||
|
return resp
|
||
|
},
|
||
|
} {
|
||
|
resp := f()
|
||
|
if resp == nil {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
defer resp.Body.Close()
|
||
|
buf, err := ioutil.ReadAll(resp.Body)
|
||
|
if err != nil {
|
||
|
t.Errorf("iotuil.ReadAll(resp.Body) failed with %v; want success; i=%d", err, i)
|
||
|
return
|
||
|
}
|
||
|
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
||
|
t.Errorf("resp.StatusCode = %d; want %d; i=%d", got, want, i)
|
||
|
t.Logf("%s", buf)
|
||
|
}
|
||
|
|
||
|
var msg sub.StringMessage
|
||
|
if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil {
|
||
|
t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success; %d", buf, err, i)
|
||
|
return
|
||
|
}
|
||
|
if got, want := msg.GetValue(), "hello"; got != want {
|
||
|
t.Errorf("msg.GetValue() = %q; want %q", got, want)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestTimeout(t *testing.T) {
|
||
|
url := "http://localhost:8080/v2/example/timeout"
|
||
|
req, err := http.NewRequest("GET", url, nil)
|
||
|
if err != nil {
|
||
|
t.Errorf(`http.NewRequest("GET", %q, nil) failed with %v; want success`, url, err)
|
||
|
return
|
||
|
}
|
||
|
req.Header.Set("Grpc-Timeout", "10m")
|
||
|
resp, err := http.DefaultClient.Do(req)
|
||
|
if err != nil {
|
||
|
t.Errorf("http.DefaultClient.Do(%#v) failed with %v; want success", req, err)
|
||
|
return
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
|
||
|
if got, want := resp.StatusCode, http.StatusRequestTimeout; got != want {
|
||
|
t.Errorf("resp.StatusCode = %d; want %d", got, want)
|
||
|
}
|
||
|
}
|