...

Source file src/github.com/grpc-ecosystem/grpc-gateway/examples/internal/integration/integration_test.go

Documentation: github.com/grpc-ecosystem/grpc-gateway/examples/internal/integration

     1  package integration_test
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"context"
     7  	"encoding/base64"
     8  	"encoding/json"
     9  	"fmt"
    10  	"io"
    11  	"io/ioutil"
    12  	"net/http"
    13  	"net/url"
    14  	"reflect"
    15  	"strconv"
    16  	"strings"
    17  	"sync"
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/golang/protobuf/jsonpb"
    22  	"github.com/golang/protobuf/proto"
    23  	"github.com/golang/protobuf/ptypes/empty"
    24  	gw "github.com/grpc-ecosystem/grpc-gateway/examples/internal/proto/examplepb"
    25  	"github.com/grpc-ecosystem/grpc-gateway/examples/internal/proto/pathenum"
    26  	"github.com/grpc-ecosystem/grpc-gateway/examples/internal/proto/sub"
    27  	"github.com/grpc-ecosystem/grpc-gateway/runtime"
    28  	"google.golang.org/genproto/protobuf/field_mask"
    29  	"google.golang.org/grpc/codes"
    30  )
    31  
    32  type errorBody struct {
    33  	Error   string        `json:"error"`
    34  	Code    int           `json:"code"`
    35  	Details []interface{} `json:"details"`
    36  }
    37  
    38  func TestEcho(t *testing.T) {
    39  	if testing.Short() {
    40  		t.Skip()
    41  		return
    42  	}
    43  
    44  	testEcho(t, 8088, "application/json")
    45  	testEchoOneof(t, 8088, "application/json")
    46  	testEchoOneof1(t, 8088, "application/json")
    47  	testEchoOneof2(t, 8088, "application/json")
    48  	testEchoBody(t, 8088)
    49  	// Use SendHeader/SetTrailer without gRPC server https://github.com/grpc-ecosystem/grpc-gateway/issues/517#issuecomment-684625645
    50  	testEchoBody(t, 8089)
    51  }
    52  
    53  func TestForwardResponseOption(t *testing.T) {
    54  	if testing.Short() {
    55  		t.Skip()
    56  		return
    57  	}
    58  
    59  	ctx := context.Background()
    60  	ctx, cancel := context.WithCancel(ctx)
    61  	defer cancel()
    62  
    63  	go func() {
    64  		if err := runGateway(
    65  			ctx,
    66  			":8081",
    67  			runtime.WithForwardResponseOption(
    68  				func(_ context.Context, w http.ResponseWriter, _ proto.Message) error {
    69  					w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1.1+json")
    70  					return nil
    71  				},
    72  			),
    73  		); err != nil {
    74  			t.Errorf("runGateway() failed with %v; want success", err)
    75  			return
    76  		}
    77  	}()
    78  	if err := waitForGateway(ctx, 8081); err != nil {
    79  		t.Errorf("waitForGateway(ctx, 8081) failed with %v; want success", err)
    80  	}
    81  	testEcho(t, 8081, "application/vnd.docker.plugins.v1.1+json")
    82  }
    83  
    84  func testEcho(t *testing.T, port int, contentType string) {
    85  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/echo/myid", port)
    86  	resp, err := http.Post(apiURL, "application/json", strings.NewReader("{}"))
    87  	if err != nil {
    88  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
    89  		return
    90  	}
    91  	defer resp.Body.Close()
    92  	buf, err := ioutil.ReadAll(resp.Body)
    93  	if err != nil {
    94  		t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
    95  		return
    96  	}
    97  
    98  	if got, want := resp.StatusCode, http.StatusOK; got != want {
    99  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   100  		t.Logf("%s", buf)
   101  	}
   102  
   103  	var msg gw.SimpleMessage
   104  	if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil {
   105  		t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err)
   106  		return
   107  	}
   108  	if got, want := msg.Id, "myid"; got != want {
   109  		t.Errorf("msg.Id = %q; want %q", got, want)
   110  	}
   111  
   112  	if value := resp.Header.Get("Content-Type"); value != contentType {
   113  		t.Errorf("Content-Type was %s, wanted %s", value, contentType)
   114  	}
   115  }
   116  
   117  func testEchoOneof(t *testing.T, port int, contentType string) {
   118  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/echo/myid/10/golang", port)
   119  	resp, err := http.Get(apiURL)
   120  	if err != nil {
   121  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
   122  		return
   123  	}
   124  	defer resp.Body.Close()
   125  	buf, err := ioutil.ReadAll(resp.Body)
   126  	if err != nil {
   127  		t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
   128  		return
   129  	}
   130  
   131  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   132  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   133  		t.Logf("%s", buf)
   134  	}
   135  
   136  	var msg gw.SimpleMessage
   137  	if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil {
   138  		t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err)
   139  		return
   140  	}
   141  	if got, want := msg.GetLang(), "golang"; got != want {
   142  		t.Errorf("msg.GetLang() = %q; want %q", got, want)
   143  	}
   144  
   145  	if value := resp.Header.Get("Content-Type"); value != contentType {
   146  		t.Errorf("Content-Type was %s, wanted %s", value, contentType)
   147  	}
   148  }
   149  
   150  func testEchoOneof1(t *testing.T, port int, contentType string) {
   151  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/echo1/myid/10/golang", port)
   152  	resp, err := http.Get(apiURL)
   153  	if err != nil {
   154  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
   155  		return
   156  	}
   157  	defer resp.Body.Close()
   158  	buf, err := ioutil.ReadAll(resp.Body)
   159  	if err != nil {
   160  		t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
   161  		return
   162  	}
   163  
   164  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   165  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   166  		t.Logf("%s", buf)
   167  	}
   168  
   169  	var msg gw.SimpleMessage
   170  	if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil {
   171  		t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err)
   172  		return
   173  	}
   174  	if got, want := msg.GetStatus().GetNote(), "golang"; got != want {
   175  		t.Errorf("msg.GetStatus().GetNote() = %q; want %q", got, want)
   176  	}
   177  
   178  	if value := resp.Header.Get("Content-Type"); value != contentType {
   179  		t.Errorf("Content-Type was %s, wanted %s", value, contentType)
   180  	}
   181  }
   182  
   183  func testEchoOneof2(t *testing.T, port int, contentType string) {
   184  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/echo2/golang", port)
   185  	resp, err := http.Get(apiURL)
   186  	if err != nil {
   187  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
   188  		return
   189  	}
   190  	defer resp.Body.Close()
   191  	buf, err := ioutil.ReadAll(resp.Body)
   192  	if err != nil {
   193  		t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
   194  		return
   195  	}
   196  
   197  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   198  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   199  		t.Logf("%s", buf)
   200  	}
   201  
   202  	var msg gw.SimpleMessage
   203  	if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil {
   204  		t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err)
   205  		return
   206  	}
   207  	if got, want := msg.GetNo().GetNote(), "golang"; got != want {
   208  		t.Errorf("msg.GetNo().GetNote() = %q; want %q", got, want)
   209  	}
   210  
   211  	if value := resp.Header.Get("Content-Type"); value != contentType {
   212  		t.Errorf("Content-Type was %s, wanted %s", value, contentType)
   213  	}
   214  }
   215  
   216  func testEchoBody(t *testing.T, port int) {
   217  	sent := gw.SimpleMessage{Id: "example"}
   218  	var m jsonpb.Marshaler
   219  	payload, err := m.MarshalToString(&sent)
   220  	if err != nil {
   221  		t.Fatalf("m.MarshalToString(%#v) failed with %v; want success", payload, err)
   222  	}
   223  
   224  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/echo_body", port)
   225  	resp, err := http.Post(apiURL, "", strings.NewReader(payload))
   226  	if err != nil {
   227  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
   228  		return
   229  	}
   230  	defer resp.Body.Close()
   231  	buf, err := ioutil.ReadAll(resp.Body)
   232  	if err != nil {
   233  		t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
   234  		return
   235  	}
   236  
   237  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   238  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   239  		t.Logf("%s", buf)
   240  	}
   241  
   242  	var received gw.SimpleMessage
   243  	if err := jsonpb.UnmarshalString(string(buf), &received); err != nil {
   244  		t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err)
   245  		return
   246  	}
   247  	if got, want := received, sent; !reflect.DeepEqual(got, want) {
   248  		t.Errorf("msg.Id = %q; want %q", got, want)
   249  	}
   250  
   251  	if got, want := resp.Header.Get("Grpc-Metadata-Foo"), "foo1"; got != want {
   252  		t.Errorf("Grpc-Metadata-Foo was %q, wanted %q", got, want)
   253  	}
   254  	if got, want := resp.Header.Get("Grpc-Metadata-Bar"), "bar1"; got != want {
   255  		t.Errorf("Grpc-Metadata-Bar was %q, wanted %q", got, want)
   256  	}
   257  
   258  	if got, want := resp.Trailer.Get("Grpc-Trailer-Foo"), "foo2"; got != want {
   259  		t.Errorf("Grpc-Trailer-Foo was %q, wanted %q", got, want)
   260  	}
   261  	if got, want := resp.Trailer.Get("Grpc-Trailer-Bar"), "bar2"; got != want {
   262  		t.Errorf("Grpc-Trailer-Bar was %q, wanted %q", got, want)
   263  	}
   264  }
   265  
   266  func TestABE(t *testing.T) {
   267  	if testing.Short() {
   268  		t.Skip()
   269  		return
   270  	}
   271  
   272  	testABECreate(t, 8088)
   273  	testABECreateBody(t, 8088)
   274  	testABEBulkCreate(t, 8088)
   275  	testABEBulkCreateWithError(t, 8088)
   276  	testABELookup(t, 8088)
   277  	testABELookupNotFound(t, 8088, true)
   278  	testABELookupNotFound(t, 8088, false)
   279  	testABEList(t, 8088)
   280  	testABEBulkEcho(t, 8088)
   281  	testABEBulkEchoZeroLength(t, 8088)
   282  	testAdditionalBindings(t, 8088)
   283  	testABERepeated(t, 8088)
   284  }
   285  
   286  func testABECreate(t *testing.T, port int) {
   287  	want := gw.ABitOfEverything{
   288  		FloatValue:               1.5,
   289  		DoubleValue:              2.5,
   290  		Int64Value:               4294967296,
   291  		Uint64Value:              9223372036854775807,
   292  		Int32Value:               -2147483648,
   293  		Fixed64Value:             9223372036854775807,
   294  		Fixed32Value:             4294967295,
   295  		BoolValue:                true,
   296  		StringValue:              "strprefix/foo",
   297  		Uint32Value:              4294967295,
   298  		Sfixed32Value:            2147483647,
   299  		Sfixed64Value:            -4611686018427387904,
   300  		Sint32Value:              2147483647,
   301  		Sint64Value:              4611686018427387903,
   302  		NonConventionalNameValue: "camelCase",
   303  		EnumValue:                gw.NumericEnum_ZERO,
   304  		PathEnumValue:            pathenum.PathEnum_DEF,
   305  		NestedPathEnumValue:      pathenum.MessagePathEnum_JKL,
   306  		EnumValueAnnotation:      gw.NumericEnum_ONE,
   307  	}
   308  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/%f/%f/%d/separator/%d/%d/%d/%d/%v/%s/%d/%d/%d/%d/%d/%s/%s/%s/%s/%s", port, 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, want.EnumValue, want.PathEnumValue, want.NestedPathEnumValue, want.EnumValueAnnotation)
   309  
   310  	resp, err := http.Post(apiURL, "application/json", strings.NewReader("{}"))
   311  	if err != nil {
   312  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
   313  		return
   314  	}
   315  	defer resp.Body.Close()
   316  	buf, err := ioutil.ReadAll(resp.Body)
   317  	if err != nil {
   318  		t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
   319  		return
   320  	}
   321  
   322  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   323  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   324  		t.Logf("%s", buf)
   325  	}
   326  
   327  	var msg gw.ABitOfEverything
   328  	if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil {
   329  		t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err)
   330  		return
   331  	}
   332  	if msg.Uuid == "" {
   333  		t.Error("msg.Uuid is empty; want not empty")
   334  	}
   335  	msg.Uuid = ""
   336  	if got := msg; !reflect.DeepEqual(got, want) {
   337  		t.Errorf("msg= %v; want %v", &got, &want)
   338  	}
   339  }
   340  
   341  func testABECreateBody(t *testing.T, port int) {
   342  	want := gw.ABitOfEverything{
   343  		FloatValue:               1.5,
   344  		DoubleValue:              2.5,
   345  		Int64Value:               4294967296,
   346  		Uint64Value:              9223372036854775807,
   347  		Int32Value:               -2147483648,
   348  		Fixed64Value:             9223372036854775807,
   349  		Fixed32Value:             4294967295,
   350  		BoolValue:                true,
   351  		StringValue:              "strprefix/foo",
   352  		Uint32Value:              4294967295,
   353  		Sfixed32Value:            2147483647,
   354  		Sfixed64Value:            -4611686018427387904,
   355  		Sint32Value:              2147483647,
   356  		Sint64Value:              4611686018427387903,
   357  		NonConventionalNameValue: "camelCase",
   358  		EnumValue:                gw.NumericEnum_ONE,
   359  		PathEnumValue:            pathenum.PathEnum_ABC,
   360  		NestedPathEnumValue:      pathenum.MessagePathEnum_GHI,
   361  
   362  		Nested: []*gw.ABitOfEverything_Nested{
   363  			{
   364  				Name:   "bar",
   365  				Amount: 10,
   366  			},
   367  			{
   368  				Name:   "baz",
   369  				Amount: 20,
   370  			},
   371  		},
   372  		RepeatedStringValue: []string{"a", "b", "c"},
   373  		OneofValue: &gw.ABitOfEverything_OneofString{
   374  			OneofString: "x",
   375  		},
   376  		MapValue: map[string]gw.NumericEnum{
   377  			"a": gw.NumericEnum_ONE,
   378  			"b": gw.NumericEnum_ZERO,
   379  		},
   380  		MappedStringValue: map[string]string{
   381  			"a": "x",
   382  			"b": "y",
   383  		},
   384  		MappedNestedValue: map[string]*gw.ABitOfEverything_Nested{
   385  			"a": {Name: "x", Amount: 1},
   386  			"b": {Name: "y", Amount: 2},
   387  		},
   388  		RepeatedEnumAnnotation: []gw.NumericEnum{
   389  			gw.NumericEnum_ONE,
   390  			gw.NumericEnum_ZERO,
   391  		},
   392  		EnumValueAnnotation: gw.NumericEnum_ONE,
   393  		RepeatedStringAnnotation: []string{
   394  			"a",
   395  			"b",
   396  		},
   397  		RepeatedNestedAnnotation: []*gw.ABitOfEverything_Nested{
   398  			{
   399  				Name:   "hoge",
   400  				Amount: 10,
   401  			},
   402  			{
   403  				Name:   "fuga",
   404  				Amount: 20,
   405  			},
   406  		},
   407  		NestedAnnotation: &gw.ABitOfEverything_Nested{
   408  			Name:   "hoge",
   409  			Amount: 10,
   410  		},
   411  	}
   412  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything", port)
   413  	var m jsonpb.Marshaler
   414  	payload, err := m.MarshalToString(&want)
   415  	if err != nil {
   416  		t.Fatalf("m.MarshalToString(%#v) failed with %v; want success", want, err)
   417  	}
   418  
   419  	resp, err := http.Post(apiURL, "application/json", strings.NewReader(payload))
   420  	if err != nil {
   421  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
   422  		return
   423  	}
   424  	defer resp.Body.Close()
   425  	buf, err := ioutil.ReadAll(resp.Body)
   426  	if err != nil {
   427  		t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
   428  		return
   429  	}
   430  
   431  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   432  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   433  		t.Logf("%s", buf)
   434  	}
   435  
   436  	var msg gw.ABitOfEverything
   437  	if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil {
   438  		t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err)
   439  		return
   440  	}
   441  	if msg.Uuid == "" {
   442  		t.Error("msg.Uuid is empty; want not empty")
   443  	}
   444  	msg.Uuid = ""
   445  	if got := msg; !reflect.DeepEqual(got, want) {
   446  		t.Errorf("msg= %v; want %v", &got, &want)
   447  	}
   448  }
   449  
   450  func testABEBulkCreate(t *testing.T, port int) {
   451  	count := 0
   452  	r, w := io.Pipe()
   453  	go func(w io.WriteCloser) {
   454  		defer func() {
   455  			if cerr := w.Close(); cerr != nil {
   456  				t.Errorf("w.Close() failed with %v; want success", cerr)
   457  			}
   458  		}()
   459  		for _, val := range []string{
   460  			"foo", "bar", "baz", "qux", "quux",
   461  		} {
   462  			want := gw.ABitOfEverything{
   463  				FloatValue:               1.5,
   464  				DoubleValue:              2.5,
   465  				Int64Value:               4294967296,
   466  				Uint64Value:              9223372036854775807,
   467  				Int32Value:               -2147483648,
   468  				Fixed64Value:             9223372036854775807,
   469  				Fixed32Value:             4294967295,
   470  				BoolValue:                true,
   471  				StringValue:              fmt.Sprintf("strprefix/%s", val),
   472  				Uint32Value:              4294967295,
   473  				Sfixed32Value:            2147483647,
   474  				Sfixed64Value:            -4611686018427387904,
   475  				Sint32Value:              2147483647,
   476  				Sint64Value:              4611686018427387903,
   477  				NonConventionalNameValue: "camelCase",
   478  				EnumValue:                gw.NumericEnum_ONE,
   479  				PathEnumValue:            pathenum.PathEnum_ABC,
   480  				NestedPathEnumValue:      pathenum.MessagePathEnum_GHI,
   481  
   482  				Nested: []*gw.ABitOfEverything_Nested{
   483  					{
   484  						Name:   "hoge",
   485  						Amount: 10,
   486  					},
   487  					{
   488  						Name:   "fuga",
   489  						Amount: 20,
   490  					},
   491  				},
   492  				RepeatedEnumAnnotation: []gw.NumericEnum{
   493  					gw.NumericEnum_ONE,
   494  					gw.NumericEnum_ZERO,
   495  				},
   496  				EnumValueAnnotation: gw.NumericEnum_ONE,
   497  				RepeatedStringAnnotation: []string{
   498  					"a",
   499  					"b",
   500  				},
   501  				RepeatedNestedAnnotation: []*gw.ABitOfEverything_Nested{
   502  					{
   503  						Name:   "hoge",
   504  						Amount: 10,
   505  					},
   506  					{
   507  						Name:   "fuga",
   508  						Amount: 20,
   509  					},
   510  				},
   511  				NestedAnnotation: &gw.ABitOfEverything_Nested{
   512  					Name:   "hoge",
   513  					Amount: 10,
   514  				},
   515  			}
   516  			var m jsonpb.Marshaler
   517  			if err := m.Marshal(w, &want); err != nil {
   518  				t.Fatalf("m.Marshal(%#v, w) failed with %v; want success", want, err)
   519  			}
   520  			if _, err := io.WriteString(w, "\n"); err != nil {
   521  				t.Errorf("w.Write(%q) failed with %v; want success", "\n", err)
   522  				return
   523  			}
   524  			count++
   525  		}
   526  	}(w)
   527  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/bulk", port)
   528  	resp, err := http.Post(apiURL, "application/json", r)
   529  	if err != nil {
   530  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
   531  		return
   532  	}
   533  	defer resp.Body.Close()
   534  	buf, err := ioutil.ReadAll(resp.Body)
   535  	if err != nil {
   536  		t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
   537  		return
   538  	}
   539  
   540  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   541  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   542  		t.Logf("%s", buf)
   543  	}
   544  
   545  	var msg empty.Empty
   546  	if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil {
   547  		t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err)
   548  		return
   549  	}
   550  
   551  	if got, want := resp.Header.Get("Grpc-Metadata-Count"), fmt.Sprintf("%d", count); got != want {
   552  		t.Errorf("Grpc-Metadata-Count was %q, wanted %q", got, want)
   553  	}
   554  
   555  	if got, want := resp.Trailer.Get("Grpc-Trailer-Foo"), "foo2"; got != want {
   556  		t.Errorf("Grpc-Trailer-Foo was %q, wanted %q", got, want)
   557  	}
   558  	if got, want := resp.Trailer.Get("Grpc-Trailer-Bar"), "bar2"; got != want {
   559  		t.Errorf("Grpc-Trailer-Bar was %q, wanted %q", got, want)
   560  	}
   561  }
   562  
   563  func testABEBulkCreateWithError(t *testing.T, port int) {
   564  	count := 0
   565  	r, w := io.Pipe()
   566  	go func(w io.WriteCloser) {
   567  		defer func() {
   568  			if cerr := w.Close(); cerr != nil {
   569  				t.Errorf("w.Close() failed with %v; want success", cerr)
   570  			}
   571  		}()
   572  		for _, val := range []string{
   573  			"foo", "bar", "baz", "qux", "quux",
   574  		} {
   575  			time.Sleep(1 * time.Millisecond)
   576  
   577  			want := gw.ABitOfEverything{
   578  				StringValue: fmt.Sprintf("strprefix/%s", val),
   579  			}
   580  			var m jsonpb.Marshaler
   581  			if err := m.Marshal(w, &want); err != nil {
   582  				t.Fatalf("m.Marshal(%#v, w) failed with %v; want success", want, err)
   583  			}
   584  			if _, err := io.WriteString(w, "\n"); err != nil {
   585  				t.Errorf("w.Write(%q) failed with %v; want success", "\n", err)
   586  				return
   587  			}
   588  			count++
   589  		}
   590  	}(w)
   591  
   592  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/bulk", port)
   593  	request, err := http.NewRequest("POST", apiURL, r)
   594  	if err != nil {
   595  		t.Fatalf("http.NewRequest(%q, %q, nil) failed with %v; want success", "POST", apiURL, err)
   596  	}
   597  	request.Header.Add("Grpc-Metadata-error", "some error")
   598  
   599  	resp, err := http.DefaultClient.Do(request)
   600  	if err != nil {
   601  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
   602  		return
   603  	}
   604  	defer resp.Body.Close()
   605  	buf, err := ioutil.ReadAll(resp.Body)
   606  	if err != nil {
   607  		t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
   608  		return
   609  	}
   610  
   611  	if got, want := resp.StatusCode, http.StatusBadRequest; got != want {
   612  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   613  		t.Logf("%s", buf)
   614  	}
   615  
   616  	var msg errorBody
   617  	if err := json.Unmarshal(buf, &msg); err != nil {
   618  		t.Fatalf("json.Unmarshal(%s, &msg) failed with %v; want success", buf, err)
   619  	}
   620  }
   621  
   622  func testABELookup(t *testing.T, port int) {
   623  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything", port)
   624  	cresp, err := http.Post(apiURL, "application/json", strings.NewReader(`
   625  		{"bool_value": true, "string_value": "strprefix/example"}
   626  	`))
   627  	if err != nil {
   628  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
   629  		return
   630  	}
   631  	defer cresp.Body.Close()
   632  	buf, err := ioutil.ReadAll(cresp.Body)
   633  	if err != nil {
   634  		t.Errorf("ioutil.ReadAll(cresp.Body) failed with %v; want success", err)
   635  		return
   636  	}
   637  	if got, want := cresp.StatusCode, http.StatusOK; got != want {
   638  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   639  		t.Logf("%s", buf)
   640  		return
   641  	}
   642  
   643  	var want gw.ABitOfEverything
   644  	if err := jsonpb.UnmarshalString(string(buf), &want); err != nil {
   645  		t.Errorf("jsonpb.UnmarshalString(%s, &want) failed with %v; want success", buf, err)
   646  		return
   647  	}
   648  
   649  	apiURL = fmt.Sprintf("%s/%s", apiURL, want.Uuid)
   650  	resp, err := http.Get(apiURL)
   651  	if err != nil {
   652  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
   653  		return
   654  	}
   655  	defer resp.Body.Close()
   656  
   657  	buf, err = ioutil.ReadAll(resp.Body)
   658  	if err != nil {
   659  		t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
   660  		return
   661  	}
   662  
   663  	var msg gw.ABitOfEverything
   664  	if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil {
   665  		t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err)
   666  		return
   667  	}
   668  	if got := msg; !reflect.DeepEqual(got, want) {
   669  		t.Errorf("msg= %v; want %v", &got, &want)
   670  	}
   671  
   672  	if got, want := resp.Header.Get("Grpc-Metadata-Uuid"), want.Uuid; got != want {
   673  		t.Errorf("Grpc-Metadata-Uuid was %s, wanted %s", got, want)
   674  	}
   675  }
   676  
   677  // TestABEPatch demonstrates partially updating a resource.
   678  // First, we'll create an ABE resource with known values for string_value and int32_value
   679  // Then, issue a PATCH request updating only the string_value
   680  // Then, GET the resource and verify that string_value is changed, but int32_value isn't
   681  func TestABEPatch(t *testing.T) {
   682  	if testing.Short() {
   683  		t.Skip()
   684  		return
   685  	}
   686  
   687  	port := 8088
   688  
   689  	// create a record with a known string_value and int32_value
   690  	uuid := postABE(t, port, gw.ABitOfEverything{StringValue: "strprefix/bar", Int32Value: 32})
   691  
   692  	// issue PATCH request, only updating string_value
   693  	req, err := http.NewRequest(
   694  		http.MethodPatch,
   695  		fmt.Sprintf("http://localhost:%d/v2/example/a_bit_of_everything/%s", port, uuid),
   696  		strings.NewReader(`{"string_value": "strprefix/foo"}`),
   697  	)
   698  	if err != nil {
   699  		t.Fatalf("http.NewRequest(PATCH) failed with %v; want success", err)
   700  	}
   701  	patchResp, err := http.DefaultClient.Do(req)
   702  	if err != nil {
   703  		t.Fatalf("failed to issue PATCH request: %v", err)
   704  	}
   705  	if got, want := patchResp.StatusCode, http.StatusOK; got != want {
   706  		if body, err := ioutil.ReadAll(patchResp.Body); err != nil {
   707  			t.Errorf("patchResp body couldn't be read: %v", err)
   708  		} else {
   709  			t.Errorf("patchResp.StatusCode= %d; want %d resp: %v", got, want, string(body))
   710  		}
   711  	}
   712  
   713  	// issue GET request, verifying that string_value is changed and int32_value is not
   714  	getRespBody := getABE(t, port, uuid)
   715  	if got, want := getRespBody.StringValue, "strprefix/foo"; got != want {
   716  		t.Errorf("string_value= %q; want %q", got, want)
   717  	}
   718  	if got, want := getRespBody.Int32Value, int32(32); got != want {
   719  		t.Errorf("int_32_value= %d; want %d", got, want)
   720  	}
   721  }
   722  
   723  // TestABEPatchBody demonstrates the ability to specify an update mask within the request body.
   724  // This binding does not use an automatically generated update_mask.
   725  func TestABEPatchBody(t *testing.T) {
   726  	if testing.Short() {
   727  		t.Skip()
   728  		return
   729  	}
   730  
   731  	port := 8088
   732  
   733  	for _, tc := range []struct {
   734  		name          string
   735  		originalValue gw.ABitOfEverything
   736  		input         gw.UpdateV2Request
   737  		want          gw.ABitOfEverything
   738  	}{
   739  		{
   740  			name: "with fieldmask provided",
   741  			originalValue: gw.ABitOfEverything{
   742  				Int32Value:   42,
   743  				StringValue:  "rabbit",
   744  				SingleNested: &gw.ABitOfEverything_Nested{Name: "some value that will get overwritten", Amount: 345},
   745  			},
   746  			input: gw.UpdateV2Request{Abe: &gw.ABitOfEverything{
   747  				StringValue:  "some value that won't get updated because it's not in the field mask",
   748  				SingleNested: &gw.ABitOfEverything_Nested{Amount: 456},
   749  			}, UpdateMask: &field_mask.FieldMask{Paths: []string{"single_nested"}}},
   750  			want: gw.ABitOfEverything{
   751  				Int32Value:   42,
   752  				StringValue:  "rabbit",
   753  				SingleNested: &gw.ABitOfEverything_Nested{Amount: 456},
   754  			},
   755  		},
   756  		{
   757  			// N.B. This case passes the empty field mask to the UpdateV2 method so falls back to PUT semantics as per the implementation.
   758  			name: "with empty fieldmask",
   759  			originalValue: gw.ABitOfEverything{
   760  				Int32Value:   42,
   761  				StringValue:  "some value that will get overwritten",
   762  				SingleNested: &gw.ABitOfEverything_Nested{Name: "value that will get empty", Amount: 345},
   763  			},
   764  			input: gw.UpdateV2Request{Abe: &gw.ABitOfEverything{
   765  				StringValue:  "some updated value because the fieldMask is nil",
   766  				SingleNested: &gw.ABitOfEverything_Nested{Amount: 456},
   767  			}, UpdateMask: &field_mask.FieldMask{}},
   768  			want: gw.ABitOfEverything{
   769  				StringValue:  "some updated value because the fieldMask is nil",
   770  				SingleNested: &gw.ABitOfEverything_Nested{Amount: 456},
   771  			},
   772  		},
   773  		{
   774  			// N.B. This case passes the nil field mask to the UpdateV2 method so falls back to PUT semantics as per the implementation.
   775  			name: "with nil fieldmask",
   776  			originalValue: gw.ABitOfEverything{
   777  				Int32Value:   42,
   778  				StringValue:  "some value that will get overwritten",
   779  				SingleNested: &gw.ABitOfEverything_Nested{Name: "value that will get empty", Amount: 123},
   780  			},
   781  			input: gw.UpdateV2Request{Abe: &gw.ABitOfEverything{
   782  				StringValue:  "some updated value because the fieldMask is nil",
   783  				SingleNested: &gw.ABitOfEverything_Nested{Amount: 657},
   784  			}, UpdateMask: nil},
   785  			want: gw.ABitOfEverything{
   786  				StringValue:  "some updated value because the fieldMask is nil",
   787  				SingleNested: &gw.ABitOfEverything_Nested{Amount: 657},
   788  			},
   789  		},
   790  	} {
   791  		t.Run(tc.name, func(t *testing.T) {
   792  			originalABE := tc.originalValue
   793  			uuid := postABE(t, port, originalABE)
   794  
   795  			patchBody := tc.input
   796  			patchReq, err := http.NewRequest(
   797  				http.MethodPatch,
   798  				fmt.Sprintf("http://localhost:%d/v2a/example/a_bit_of_everything/%s", port, uuid),
   799  				strings.NewReader(mustMarshal(t, patchBody)),
   800  			)
   801  			if err != nil {
   802  				t.Fatalf("http.NewRequest(PATCH) failed with %v; want success", err)
   803  			}
   804  			patchResp, err := http.DefaultClient.Do(patchReq)
   805  			if err != nil {
   806  				t.Fatalf("failed to issue PATCH request: %v", err)
   807  			}
   808  			if got, want := patchResp.StatusCode, http.StatusOK; got != want {
   809  				if body, err := ioutil.ReadAll(patchResp.Body); err != nil {
   810  					t.Errorf("patchResp body couldn't be read: %v", err)
   811  				} else {
   812  					t.Errorf("patchResp.StatusCode= %d; want %d resp: %v", got, want, string(body))
   813  				}
   814  			}
   815  
   816  			want, got := tc.want, getABE(t, port, uuid)
   817  			got.Uuid = "" // empty out uuid so we don't need to worry about it in comparisons
   818  			if !reflect.DeepEqual(want, got) {
   819  				t.Errorf("want %v\ngot %v", want, got)
   820  			}
   821  		})
   822  	}
   823  }
   824  
   825  // mustMarshal marshals the given object into a json string, calling t.Fatal if an error occurs. Useful in testing to
   826  // inline marshalling whenever you don't expect the marshalling to return an error
   827  func mustMarshal(t *testing.T, i interface{}) string {
   828  	b, err := json.Marshal(i)
   829  	if err != nil {
   830  		t.Fatalf("failed to marshal %#v: %v", i, err)
   831  	}
   832  
   833  	return string(b)
   834  }
   835  
   836  // postABE conveniently creates a new ABE record for ease in testing
   837  func postABE(t *testing.T, port int, abe gw.ABitOfEverything) (uuid string) {
   838  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything", port)
   839  	postResp, err := http.Post(apiURL, "application/json", strings.NewReader(mustMarshal(t, abe)))
   840  	if err != nil {
   841  		t.Fatalf("http.Post(%q) failed with %v; want success", apiURL, err)
   842  		return
   843  	}
   844  	body, err := ioutil.ReadAll(postResp.Body)
   845  	if err != nil {
   846  		t.Fatalf("postResp body couldn't be read: %v", err)
   847  	}
   848  	var f struct {
   849  		UUID string `json:"uuid"`
   850  	}
   851  	if err := json.Unmarshal(body, &f); err != nil {
   852  		t.Fatalf("postResp body couldn't be unmarshalled: %v. body: %s", err, string(body))
   853  	}
   854  	if f.UUID == "" {
   855  		t.Fatalf("want uuid from postResp, but got none. body: %s", string(body))
   856  	}
   857  	return f.UUID
   858  }
   859  
   860  // getABE conveniently fetches an ABE record for ease in testing
   861  func getABE(t *testing.T, port int, uuid string) gw.ABitOfEverything {
   862  	gURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/%s", port, uuid)
   863  	getResp, err := http.Get(gURL)
   864  	if err != nil {
   865  		t.Fatalf("http.Get(%s) failed with %v; want success", gURL, err)
   866  	}
   867  	defer getResp.Body.Close()
   868  
   869  	if got, want := getResp.StatusCode, http.StatusOK; got != want {
   870  		t.Fatalf("getResp.StatusCode= %d, want %d. resp: %v", got, want, getResp)
   871  	}
   872  	var getRespBody gw.ABitOfEverything
   873  	body, err := ioutil.ReadAll(getResp.Body)
   874  	if err != nil {
   875  		t.Fatalf("getResp body couldn't be read: %v", err)
   876  	}
   877  	if err := json.Unmarshal(body, &getRespBody); err != nil {
   878  		t.Fatalf("getResp body couldn't be unmarshalled: %v body: %s", err, string(body))
   879  	}
   880  
   881  	return getRespBody
   882  }
   883  
   884  func testABELookupNotFound(t *testing.T, port int, useTrailers bool) {
   885  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything", port)
   886  	uuid := "not_exist"
   887  	apiURL = fmt.Sprintf("%s/%s", apiURL, uuid)
   888  
   889  	client := &http.Client{}
   890  	req, err := http.NewRequest("GET", apiURL, nil)
   891  	if err != nil {
   892  		t.Errorf("http.NewRequest() failed with %v; want success", err)
   893  		return
   894  	}
   895  
   896  	if useTrailers {
   897  		req.Header.Set("TE", "trailers")
   898  	}
   899  
   900  	resp, err := client.Do(req)
   901  	if err != nil {
   902  		t.Errorf("client.Do(%v) failed with %v; want success", req, err)
   903  		return
   904  	}
   905  	defer resp.Body.Close()
   906  
   907  	buf, err := ioutil.ReadAll(resp.Body)
   908  	if err != nil {
   909  		t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
   910  		return
   911  	}
   912  
   913  	if got, want := resp.StatusCode, http.StatusNotFound; got != want {
   914  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   915  		t.Logf("%s", buf)
   916  		return
   917  	}
   918  
   919  	var msg errorBody
   920  	if err := json.Unmarshal(buf, &msg); err != nil {
   921  		t.Errorf("json.Unmarshal(%s, &msg) failed with %v; want success", buf, err)
   922  		return
   923  	}
   924  
   925  	if got, want := msg.Code, int(codes.NotFound); got != want {
   926  		t.Errorf("msg.Code = %d; want %d", got, want)
   927  		return
   928  	}
   929  
   930  	if got, want := msg.Error, "not found"; got != want {
   931  		t.Errorf("msg.Error = %s; want %s", got, want)
   932  		return
   933  	}
   934  
   935  	if got, want := resp.Header.Get("Grpc-Metadata-Uuid"), uuid; got != want {
   936  		t.Errorf("Grpc-Metadata-Uuid was %s, wanted %s", got, want)
   937  	}
   938  
   939  	var trailers = map[bool]map[string]string{
   940  		true: {
   941  			"Grpc-Trailer-Foo": "foo2",
   942  			"Grpc-Trailer-Bar": "bar2",
   943  		},
   944  		false: {
   945  			"Grpc-Trailer-Foo": "",
   946  			"Grpc-Trailer-Bar": "",
   947  		},
   948  	}
   949  
   950  	for trailer, want := range trailers[useTrailers] {
   951  		if got := resp.Trailer.Get(trailer); got != want {
   952  			t.Errorf("%s was %q, wanted %q", trailer, got, want)
   953  		}
   954  	}
   955  }
   956  
   957  func testABEList(t *testing.T, port int) {
   958  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything", port)
   959  	resp, err := http.Get(apiURL)
   960  	if err != nil {
   961  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
   962  		return
   963  	}
   964  	defer resp.Body.Close()
   965  
   966  	dec := json.NewDecoder(resp.Body)
   967  	var i int
   968  	for i = 0; ; i++ {
   969  		var item struct {
   970  			Result json.RawMessage        `json:"result"`
   971  			Error  map[string]interface{} `json:"error"`
   972  		}
   973  		err := dec.Decode(&item)
   974  		if err == io.EOF {
   975  			break
   976  		}
   977  		if err != nil {
   978  			t.Errorf("dec.Decode(&item) failed with %v; want success; i = %d", err, i)
   979  		}
   980  		if len(item.Error) != 0 {
   981  			t.Errorf("item.Error = %#v; want empty; i = %d", item.Error, i)
   982  			continue
   983  		}
   984  		var msg gw.ABitOfEverything
   985  		if err := jsonpb.UnmarshalString(string(item.Result), &msg); err != nil {
   986  			t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", item.Result, err)
   987  		}
   988  	}
   989  	if i <= 0 {
   990  		t.Errorf("i == %d; want > 0", i)
   991  	}
   992  
   993  	value := resp.Header.Get("Grpc-Metadata-Count")
   994  	if value == "" {
   995  		t.Errorf("Grpc-Metadata-Count should not be empty")
   996  	}
   997  
   998  	count, err := strconv.Atoi(value)
   999  	if err != nil {
  1000  		t.Errorf("failed to Atoi %q: %v", value, err)
  1001  	}
  1002  
  1003  	if count <= 0 {
  1004  		t.Errorf("count == %d; want > 0", count)
  1005  	}
  1006  }
  1007  
  1008  func testABEBulkEcho(t *testing.T, port int) {
  1009  	reqr, reqw := io.Pipe()
  1010  	var wg sync.WaitGroup
  1011  	var want []*sub.StringMessage
  1012  	wg.Add(1)
  1013  	go func() {
  1014  		defer wg.Done()
  1015  		defer reqw.Close()
  1016  		var m jsonpb.Marshaler
  1017  		for i := 0; i < 1000; i++ {
  1018  			msg := sub.StringMessage{Value: proto.String(fmt.Sprintf("message %d", i))}
  1019  			buf, err := m.MarshalToString(&msg)
  1020  			if err != nil {
  1021  				t.Errorf("m.Marshal(%v) failed with %v; want success", &msg, err)
  1022  				return
  1023  			}
  1024  			if _, err := fmt.Fprintln(reqw, buf); err != nil {
  1025  				t.Errorf("fmt.Fprintln(reqw, %q) failed with %v; want success", buf, err)
  1026  				return
  1027  			}
  1028  			want = append(want, &msg)
  1029  		}
  1030  	}()
  1031  
  1032  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/echo", port)
  1033  	req, err := http.NewRequest("POST", apiURL, reqr)
  1034  	if err != nil {
  1035  		t.Errorf("http.NewRequest(%q, %q, reqr) failed with %v; want success", "POST", apiURL, err)
  1036  		return
  1037  	}
  1038  	req.Header.Set("Content-Type", "application/json")
  1039  	req.Header.Set("Transfer-Encoding", "chunked")
  1040  	resp, err := http.DefaultClient.Do(req)
  1041  	if err != nil {
  1042  		t.Errorf("http.Post(%q, %q, req) failed with %v; want success", apiURL, "application/json", err)
  1043  		return
  1044  	}
  1045  	defer resp.Body.Close()
  1046  	if got, want := resp.StatusCode, http.StatusOK; got != want {
  1047  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1048  	}
  1049  
  1050  	var got []*sub.StringMessage
  1051  	wg.Add(1)
  1052  	go func() {
  1053  		defer wg.Done()
  1054  
  1055  		dec := json.NewDecoder(resp.Body)
  1056  		for i := 0; ; i++ {
  1057  			var item struct {
  1058  				Result json.RawMessage        `json:"result"`
  1059  				Error  map[string]interface{} `json:"error"`
  1060  			}
  1061  			err := dec.Decode(&item)
  1062  			if err == io.EOF {
  1063  				break
  1064  			}
  1065  			if err != nil {
  1066  				t.Errorf("dec.Decode(&item) failed with %v; want success; i = %d", err, i)
  1067  			}
  1068  			if len(item.Error) != 0 {
  1069  				t.Errorf("item.Error = %#v; want empty; i = %d", item.Error, i)
  1070  				continue
  1071  			}
  1072  			var msg sub.StringMessage
  1073  			if err := jsonpb.UnmarshalString(string(item.Result), &msg); err != nil {
  1074  				t.Errorf("jsonpb.UnmarshalString(%q, &msg) failed with %v; want success", item.Result, err)
  1075  			}
  1076  			got = append(got, &msg)
  1077  		}
  1078  	}()
  1079  
  1080  	wg.Wait()
  1081  	if !reflect.DeepEqual(got, want) {
  1082  		t.Errorf("got = %v; want %v", got, want)
  1083  	}
  1084  }
  1085  
  1086  func testABEBulkEchoZeroLength(t *testing.T, port int) {
  1087  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/echo", port)
  1088  	req, err := http.NewRequest("POST", apiURL, bytes.NewReader(nil))
  1089  	if err != nil {
  1090  		t.Errorf("http.NewRequest(%q, %q, bytes.NewReader(nil)) failed with %v; want success", "POST", apiURL, err)
  1091  		return
  1092  	}
  1093  	req.Header.Set("Content-Type", "application/json")
  1094  	req.Header.Set("Transfer-Encoding", "chunked")
  1095  	resp, err := http.DefaultClient.Do(req)
  1096  	if err != nil {
  1097  		t.Errorf("http.Post(%q, %q, req) failed with %v; want success", apiURL, "application/json", err)
  1098  		return
  1099  	}
  1100  	defer resp.Body.Close()
  1101  	if got, want := resp.StatusCode, http.StatusOK; got != want {
  1102  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1103  	}
  1104  
  1105  	dec := json.NewDecoder(resp.Body)
  1106  	var item struct {
  1107  		Result json.RawMessage        `json:"result"`
  1108  		Error  map[string]interface{} `json:"error"`
  1109  	}
  1110  	if err := dec.Decode(&item); err == nil {
  1111  		t.Errorf("dec.Decode(&item) succeeded; want io.EOF; item = %#v", item)
  1112  	} else if err != io.EOF {
  1113  		t.Errorf("dec.Decode(&item) failed with %v; want success", err)
  1114  		return
  1115  	}
  1116  }
  1117  
  1118  func testAdditionalBindings(t *testing.T, port int) {
  1119  	for i, f := range []func() *http.Response{
  1120  		func() *http.Response {
  1121  			apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/echo/hello", port)
  1122  			resp, err := http.Get(apiURL)
  1123  			if err != nil {
  1124  				t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
  1125  				return nil
  1126  			}
  1127  			return resp
  1128  		},
  1129  		func() *http.Response {
  1130  			apiURL := fmt.Sprintf("http://localhost:%d/v2/example/echo", port)
  1131  			resp, err := http.Post(apiURL, "application/json", strings.NewReader(`"hello"`))
  1132  			if err != nil {
  1133  				t.Errorf("http.Post(%q, %q, %q) failed with %v; want success", apiURL, "application/json", `"hello"`, err)
  1134  				return nil
  1135  			}
  1136  			return resp
  1137  		},
  1138  		func() *http.Response {
  1139  			r, w := io.Pipe()
  1140  			go func() {
  1141  				defer w.Close()
  1142  				w.Write([]byte(`"hello"`))
  1143  			}()
  1144  			apiURL := fmt.Sprintf("http://localhost:%d/v2/example/echo", port)
  1145  			resp, err := http.Post(apiURL, "application/json", r)
  1146  			if err != nil {
  1147  				t.Errorf("http.Post(%q, %q, %q) failed with %v; want success", apiURL, "application/json", `"hello"`, err)
  1148  				return nil
  1149  			}
  1150  			return resp
  1151  		},
  1152  		func() *http.Response {
  1153  			apiURL := fmt.Sprintf("http://localhost:%d/v2/example/echo?value=hello", port)
  1154  			resp, err := http.Get(apiURL)
  1155  			if err != nil {
  1156  				t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
  1157  				return nil
  1158  			}
  1159  			return resp
  1160  		},
  1161  	} {
  1162  		resp := f()
  1163  		if resp == nil {
  1164  			continue
  1165  		}
  1166  
  1167  		defer resp.Body.Close()
  1168  		buf, err := ioutil.ReadAll(resp.Body)
  1169  		if err != nil {
  1170  			t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success; i=%d", err, i)
  1171  			return
  1172  		}
  1173  		if got, want := resp.StatusCode, http.StatusOK; got != want {
  1174  			t.Errorf("resp.StatusCode = %d; want %d; i=%d", got, want, i)
  1175  			t.Logf("%s", buf)
  1176  		}
  1177  
  1178  		var msg sub.StringMessage
  1179  		if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil {
  1180  			t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success; %d", buf, err, i)
  1181  			return
  1182  		}
  1183  		if got, want := msg.GetValue(), "hello"; got != want {
  1184  			t.Errorf("msg.GetValue() = %q; want %q", got, want)
  1185  		}
  1186  	}
  1187  }
  1188  
  1189  func testABERepeated(t *testing.T, port int) {
  1190  	f := func(v reflect.Value) string {
  1191  		var f func(v reflect.Value, idx int) string
  1192  		s := make([]string, v.Len())
  1193  		switch v.Index(0).Kind() {
  1194  		case reflect.Slice:
  1195  			f = func(v reflect.Value, idx int) string {
  1196  				t := v.Index(idx).Type().Elem().Kind()
  1197  				if t == reflect.Uint8 {
  1198  					return base64.URLEncoding.EncodeToString(v.Index(idx).Interface().([]byte))
  1199  				}
  1200  				// Could handle more elegantly
  1201  				panic("unknown slice of type: " + t.String())
  1202  			}
  1203  		default:
  1204  			f = func(v reflect.Value, idx int) string {
  1205  				return fmt.Sprintf("%v", v.Index(idx).Interface())
  1206  			}
  1207  		}
  1208  		for i := 0; i < v.Len(); i++ {
  1209  			s[i] = f(v, i)
  1210  		}
  1211  		return strings.Join(s, ",")
  1212  	}
  1213  	want := gw.ABitOfEverythingRepeated{
  1214  		PathRepeatedFloatValue: []float32{
  1215  			1.5,
  1216  			-1.5,
  1217  		},
  1218  		PathRepeatedDoubleValue: []float64{
  1219  			2.5,
  1220  			-2.5,
  1221  		},
  1222  		PathRepeatedInt64Value: []int64{
  1223  			4294967296,
  1224  			-4294967296,
  1225  		},
  1226  		PathRepeatedUint64Value: []uint64{
  1227  			0,
  1228  			9223372036854775807,
  1229  		},
  1230  		PathRepeatedInt32Value: []int32{
  1231  			2147483647,
  1232  			-2147483648,
  1233  		},
  1234  		PathRepeatedFixed64Value: []uint64{
  1235  			0,
  1236  			9223372036854775807,
  1237  		},
  1238  		PathRepeatedFixed32Value: []uint32{
  1239  			0,
  1240  			4294967295,
  1241  		},
  1242  		PathRepeatedBoolValue: []bool{
  1243  			true,
  1244  			false,
  1245  		},
  1246  		PathRepeatedStringValue: []string{
  1247  			"foo",
  1248  			"bar",
  1249  		},
  1250  		PathRepeatedBytesValue: [][]byte{
  1251  			[]byte{0x00},
  1252  			[]byte{0xFF},
  1253  		},
  1254  		PathRepeatedUint32Value: []uint32{
  1255  			0,
  1256  			4294967295,
  1257  		},
  1258  		PathRepeatedEnumValue: []gw.NumericEnum{
  1259  			gw.NumericEnum_ZERO,
  1260  			gw.NumericEnum_ONE,
  1261  		},
  1262  		PathRepeatedSfixed32Value: []int32{
  1263  			2147483647,
  1264  			-2147483648,
  1265  		},
  1266  		PathRepeatedSfixed64Value: []int64{
  1267  			4294967296,
  1268  			-4294967296,
  1269  		},
  1270  		PathRepeatedSint32Value: []int32{
  1271  			2147483647,
  1272  			-2147483648,
  1273  		},
  1274  		PathRepeatedSint64Value: []int64{
  1275  			4611686018427387903,
  1276  			-4611686018427387904,
  1277  		},
  1278  	}
  1279  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything_repeated/%s/%s/%s/%s/%s/%s/%s/%s/%s/%s/%s/%s/%s/%s/%s/%s", port, f(reflect.ValueOf(want.PathRepeatedFloatValue)), f(reflect.ValueOf(want.PathRepeatedDoubleValue)), f(reflect.ValueOf(want.PathRepeatedInt64Value)), f(reflect.ValueOf(want.PathRepeatedUint64Value)), f(reflect.ValueOf(want.PathRepeatedInt32Value)), f(reflect.ValueOf(want.PathRepeatedFixed64Value)), f(reflect.ValueOf(want.PathRepeatedFixed32Value)), f(reflect.ValueOf(want.PathRepeatedBoolValue)), f(reflect.ValueOf(want.PathRepeatedStringValue)), f(reflect.ValueOf(want.PathRepeatedBytesValue)), f(reflect.ValueOf(want.PathRepeatedUint32Value)), f(reflect.ValueOf(want.PathRepeatedEnumValue)), f(reflect.ValueOf(want.PathRepeatedSfixed32Value)), f(reflect.ValueOf(want.PathRepeatedSfixed64Value)), f(reflect.ValueOf(want.PathRepeatedSint32Value)), f(reflect.ValueOf(want.PathRepeatedSint64Value)))
  1280  
  1281  	resp, err := http.Get(apiURL)
  1282  	if err != nil {
  1283  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
  1284  		return
  1285  	}
  1286  	defer resp.Body.Close()
  1287  	buf, err := ioutil.ReadAll(resp.Body)
  1288  	if err != nil {
  1289  		t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
  1290  		return
  1291  	}
  1292  
  1293  	if got, want := resp.StatusCode, http.StatusOK; got != want {
  1294  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1295  		t.Logf("%s", buf)
  1296  	}
  1297  
  1298  	var msg gw.ABitOfEverythingRepeated
  1299  	if err := jsonpb.UnmarshalString(string(buf), &msg); err != nil {
  1300  		t.Errorf("jsonpb.UnmarshalString(%s, &msg) failed with %v; want success", buf, err)
  1301  		return
  1302  	}
  1303  	if got := msg; !reflect.DeepEqual(got, want) {
  1304  		t.Errorf("msg= %v; want %v", &got, &want)
  1305  	}
  1306  }
  1307  
  1308  func TestTimeout(t *testing.T) {
  1309  	if testing.Short() {
  1310  		t.Skip()
  1311  		return
  1312  	}
  1313  
  1314  	apiURL := "http://localhost:8088/v2/example/timeout"
  1315  	req, err := http.NewRequest("GET", apiURL, nil)
  1316  	if err != nil {
  1317  		t.Errorf(`http.NewRequest("GET", %q, nil) failed with %v; want success`, apiURL, err)
  1318  		return
  1319  	}
  1320  	req.Header.Set("Grpc-Timeout", "10m")
  1321  	resp, err := http.DefaultClient.Do(req)
  1322  	if err != nil {
  1323  		t.Errorf("http.DefaultClient.Do(%#v) failed with %v; want success", req, err)
  1324  		return
  1325  	}
  1326  	defer resp.Body.Close()
  1327  
  1328  	if got, want := resp.StatusCode, http.StatusGatewayTimeout; got != want {
  1329  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1330  	}
  1331  }
  1332  
  1333  func TestErrorWithDetails(t *testing.T) {
  1334  	if testing.Short() {
  1335  		t.Skip()
  1336  		return
  1337  	}
  1338  
  1339  	apiURL := "http://localhost:8088/v2/example/errorwithdetails"
  1340  	resp, err := http.Get(apiURL)
  1341  	if err != nil {
  1342  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
  1343  		return
  1344  	}
  1345  	defer resp.Body.Close()
  1346  
  1347  	buf, err := ioutil.ReadAll(resp.Body)
  1348  	if err != nil {
  1349  		t.Fatalf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
  1350  	}
  1351  
  1352  	if got, want := resp.StatusCode, http.StatusInternalServerError; got != want {
  1353  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1354  	}
  1355  
  1356  	var msg errorBody
  1357  	if err := json.Unmarshal(buf, &msg); err != nil {
  1358  		t.Fatalf("json.Unmarshal(%s, &msg) failed with %v; want success", buf, err)
  1359  	}
  1360  
  1361  	if got, want := msg.Code, int(codes.Unknown); got != want {
  1362  		t.Errorf("msg.Code = %d; want %d", got, want)
  1363  	}
  1364  	if got, want := msg.Error, "with details"; got != want {
  1365  		t.Errorf("msg.Error = %s; want %s", got, want)
  1366  	}
  1367  	if got, want := len(msg.Details), 1; got != want {
  1368  		t.Fatalf("len(msg.Details) = %q; want %q", got, want)
  1369  	}
  1370  
  1371  	details, ok := msg.Details[0].(map[string]interface{})
  1372  	if got, want := ok, true; got != want {
  1373  		t.Fatalf("msg.Details[0] got type: %T, want %T", msg.Details[0], map[string]interface{}{})
  1374  	}
  1375  	typ, ok := details["@type"].(string)
  1376  	if got, want := ok, true; got != want {
  1377  		t.Fatalf("msg.Details[0][\"@type\"] got type: %T, want %T", typ, "")
  1378  	}
  1379  	if got, want := details["@type"], "type.googleapis.com/google.rpc.DebugInfo"; got != want {
  1380  		t.Errorf("msg.Details[\"@type\"] = %q; want %q", got, want)
  1381  	}
  1382  	if got, want := details["detail"], "error debug details"; got != want {
  1383  		t.Errorf("msg.Details[\"detail\"] = %q; want %q", got, want)
  1384  	}
  1385  	entries, ok := details["stack_entries"].([]interface{})
  1386  	if got, want := ok, true; got != want {
  1387  		t.Fatalf("msg.Details[0][\"stack_entries\"] got type: %T, want %T", entries, []string{})
  1388  	}
  1389  	entry, ok := entries[0].(string)
  1390  	if got, want := ok, true; got != want {
  1391  		t.Fatalf("msg.Details[0][\"stack_entries\"][0] got type: %T, want %T", entry, "")
  1392  	}
  1393  	if got, want := entries[0], "foo:1"; got != want {
  1394  		t.Errorf("msg.Details[\"stack_entries\"][0] = %q; want %q", got, want)
  1395  	}
  1396  }
  1397  
  1398  func TestPostWithEmptyBody(t *testing.T) {
  1399  	if testing.Short() {
  1400  		t.Skip()
  1401  		return
  1402  	}
  1403  
  1404  	apiURL := "http://localhost:8088/v2/example/postwithemptybody/name"
  1405  	rep, err := http.Post(apiURL, "application/json", nil)
  1406  
  1407  	if err != nil {
  1408  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
  1409  		return
  1410  	}
  1411  
  1412  	if rep.StatusCode != http.StatusOK {
  1413  		t.Errorf("http.Post(%q) response code is %d; want %d", apiURL,
  1414  			rep.StatusCode, http.StatusOK)
  1415  		return
  1416  	}
  1417  }
  1418  
  1419  func TestUnknownPath(t *testing.T) {
  1420  	if testing.Short() {
  1421  		t.Skip()
  1422  		return
  1423  	}
  1424  
  1425  	apiURL := "http://localhost:8088"
  1426  	resp, err := http.Post(apiURL, "application/json", strings.NewReader("{}"))
  1427  	if err != nil {
  1428  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
  1429  		return
  1430  	}
  1431  	defer resp.Body.Close()
  1432  	buf, err := ioutil.ReadAll(resp.Body)
  1433  	if err != nil {
  1434  		t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
  1435  		return
  1436  	}
  1437  
  1438  	if got, want := resp.StatusCode, http.StatusNotFound; got != want {
  1439  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1440  		t.Logf("%s", buf)
  1441  	}
  1442  }
  1443  
  1444  func TestMethodNotAllowed(t *testing.T) {
  1445  	if testing.Short() {
  1446  		t.Skip()
  1447  		return
  1448  	}
  1449  
  1450  	apiURL := "http://localhost:8088/v1/example/echo/myid"
  1451  	resp, err := http.Get(apiURL)
  1452  	if err != nil {
  1453  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
  1454  		return
  1455  	}
  1456  	defer resp.Body.Close()
  1457  	buf, err := ioutil.ReadAll(resp.Body)
  1458  	if err != nil {
  1459  		t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
  1460  		return
  1461  	}
  1462  
  1463  	if got, want := resp.StatusCode, http.StatusMethodNotAllowed; got != want {
  1464  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1465  		t.Logf("%s", buf)
  1466  	}
  1467  }
  1468  
  1469  func TestInvalidArgument(t *testing.T) {
  1470  	if testing.Short() {
  1471  		t.Skip()
  1472  		return
  1473  	}
  1474  
  1475  	apiURL := "http://localhost:8088/v1/example/echo/myid/not_int64"
  1476  	resp, err := http.Get(apiURL)
  1477  	if err != nil {
  1478  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
  1479  		return
  1480  	}
  1481  	defer resp.Body.Close()
  1482  	buf, err := ioutil.ReadAll(resp.Body)
  1483  	if err != nil {
  1484  		t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
  1485  		return
  1486  	}
  1487  
  1488  	if got, want := resp.StatusCode, http.StatusBadRequest; got != want {
  1489  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1490  		t.Logf("%s", buf)
  1491  	}
  1492  }
  1493  
  1494  func TestResponseBody(t *testing.T) {
  1495  	if testing.Short() {
  1496  		t.Skip()
  1497  		return
  1498  	}
  1499  
  1500  	testResponseBody(t, 8088)
  1501  	testResponseBodies(t, 8088)
  1502  	testResponseStrings(t, 8088)
  1503  }
  1504  
  1505  func testResponseBody(t *testing.T, port int) {
  1506  	tests := []struct {
  1507  		name       string
  1508  		url        string
  1509  		wantStatus int
  1510  		wantBody   string
  1511  	}{{
  1512  		name:       "unary case",
  1513  		url:        "http://localhost:%d/responsebody/foo",
  1514  		wantStatus: http.StatusOK,
  1515  		wantBody:   `{"data":"foo"}`,
  1516  	}}
  1517  
  1518  	for _, tt := range tests {
  1519  		t.Run(tt.name, func(t *testing.T) {
  1520  			apiURL := fmt.Sprintf(tt.url, port)
  1521  			resp, err := http.Get(apiURL)
  1522  			if err != nil {
  1523  				t.Fatalf("http.Get(%q) failed with %v; want success", apiURL, err)
  1524  			}
  1525  
  1526  			defer resp.Body.Close()
  1527  			buf, err := ioutil.ReadAll(resp.Body)
  1528  			if err != nil {
  1529  				t.Fatalf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
  1530  			}
  1531  
  1532  			if got, want := resp.StatusCode, tt.wantStatus; got != want {
  1533  				t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1534  				t.Logf("%s", buf)
  1535  			}
  1536  
  1537  			if got, want := string(buf), tt.wantBody; got != want {
  1538  				t.Errorf("response = %q; want %q", got, want)
  1539  			}
  1540  		})
  1541  	}
  1542  }
  1543  
  1544  func TestResponseBodyStream(t *testing.T) {
  1545  	tests := []struct {
  1546  		name       string
  1547  		url        string
  1548  		wantStatus int
  1549  		wantBody   []string
  1550  	}{{
  1551  		name:       "stream case",
  1552  		url:        "http://localhost:%d/responsebody/stream/foo",
  1553  		wantStatus: http.StatusOK,
  1554  		wantBody:   []string{`{"result":{"data":"first foo"}}`, `{"result":{"data":"second foo"}}`},
  1555  	}}
  1556  
  1557  	port := 8088
  1558  	for _, tt := range tests {
  1559  		t.Run(tt.name, func(t *testing.T) {
  1560  			apiURL := fmt.Sprintf(tt.url, port)
  1561  			resp, err := http.Get(apiURL)
  1562  			if err != nil {
  1563  				t.Fatalf("http.Get(%q) failed with %v; want success", apiURL, err)
  1564  			}
  1565  
  1566  			defer resp.Body.Close()
  1567  			body, err := readAll(resp.Body)
  1568  			if err != nil {
  1569  				t.Fatalf("readAll(resp.Body) failed with %v; want success", err)
  1570  			}
  1571  
  1572  			if got, want := resp.StatusCode, tt.wantStatus; got != want {
  1573  				t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1574  			}
  1575  
  1576  			if !reflect.DeepEqual(tt.wantBody, body) {
  1577  				t.Errorf("response = %v; want %v", body, tt.wantBody)
  1578  			}
  1579  		})
  1580  	}
  1581  }
  1582  
  1583  func readAll(body io.ReadCloser) ([]string, error) {
  1584  	var b []string
  1585  	reader := bufio.NewReader(body)
  1586  	for {
  1587  		l, err := reader.ReadBytes('\n')
  1588  		switch {
  1589  		case err == io.EOF:
  1590  			return b, nil
  1591  		case err != nil:
  1592  			return nil, err
  1593  		}
  1594  
  1595  		b = append(b, string(bytes.TrimSpace(l)))
  1596  	}
  1597  }
  1598  
  1599  func testResponseBodies(t *testing.T, port int) {
  1600  	apiURL := fmt.Sprintf("http://localhost:%d/responsebodies/foo", port)
  1601  	resp, err := http.Get(apiURL)
  1602  	if err != nil {
  1603  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
  1604  		return
  1605  	}
  1606  	defer resp.Body.Close()
  1607  	buf, err := ioutil.ReadAll(resp.Body)
  1608  	if err != nil {
  1609  		t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
  1610  		return
  1611  	}
  1612  
  1613  	if got, want := resp.StatusCode, http.StatusOK; got != want {
  1614  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1615  		t.Logf("%s", buf)
  1616  	}
  1617  
  1618  	if got, want := string(buf), `[{"data":"foo"}]`; got != want {
  1619  		t.Errorf("response = %q; want %q", got, want)
  1620  	}
  1621  }
  1622  
  1623  func testResponseStrings(t *testing.T, port int) {
  1624  	ctx, cancel := context.WithCancel(context.Background())
  1625  	defer cancel()
  1626  
  1627  	port = 8087
  1628  	// Run Secondary server with different marshalling
  1629  	ch := make(chan error)
  1630  	go func() {
  1631  		if err := runGateway(ctx, fmt.Sprintf(":%d", port), runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{EnumsAsInts: false, EmitDefaults: true})); err != nil {
  1632  			ch <- fmt.Errorf("cannot run gateway service: %v", err)
  1633  		}
  1634  	}()
  1635  
  1636  	if err := waitForGateway(ctx, uint16(port)); err != nil {
  1637  		t.Fatalf("waitForGateway(ctx, %d) failed with %v; want success", port, err)
  1638  	}
  1639  
  1640  	for i, spec := range []struct {
  1641  		endpoint     string
  1642  		expectedCode int
  1643  		expectedBody string
  1644  	}{
  1645  		{
  1646  			endpoint:     fmt.Sprintf("http://localhost:%d/responsestrings/foo", port),
  1647  			expectedCode: http.StatusOK,
  1648  			expectedBody: `["hello","foo"]`,
  1649  		},
  1650  		{
  1651  			endpoint:     fmt.Sprintf("http://localhost:%d/responsestrings/empty", port),
  1652  			expectedCode: http.StatusOK,
  1653  			expectedBody: `[]`,
  1654  		},
  1655  		{
  1656  			endpoint:     fmt.Sprintf("http://localhost:%d/responsebodies/foo", port),
  1657  			expectedCode: http.StatusOK,
  1658  			expectedBody: `[{"data":"foo","type":"UNKNOWN"}]`,
  1659  		},
  1660  	} {
  1661  		t.Run(strconv.Itoa(i), func(t *testing.T) {
  1662  			apiURL := spec.endpoint
  1663  			resp, err := http.Get(apiURL)
  1664  			if err != nil {
  1665  				t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
  1666  				return
  1667  			}
  1668  			defer resp.Body.Close()
  1669  			buf, err := ioutil.ReadAll(resp.Body)
  1670  			if err != nil {
  1671  				t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
  1672  				return
  1673  			}
  1674  
  1675  			if got, want := resp.StatusCode, spec.expectedCode; got != want {
  1676  				t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1677  				t.Logf("%s", buf)
  1678  			}
  1679  
  1680  			if got, want := string(buf), spec.expectedBody; got != want {
  1681  				t.Errorf("response = %q; want %q", got, want)
  1682  			}
  1683  		})
  1684  	}
  1685  
  1686  }
  1687  
  1688  func TestRequestQueryParams(t *testing.T) {
  1689  	testRequestQueryParams(t, 8088)
  1690  }
  1691  
  1692  func TestRequestQueryParamsInProcessGateway(t *testing.T) {
  1693  	testRequestQueryParams(t, 8089)
  1694  }
  1695  
  1696  func testRequestQueryParams(t *testing.T, port int) {
  1697  	if testing.Short() {
  1698  		t.Skip()
  1699  		return
  1700  	}
  1701  
  1702  	formValues := url.Values{}
  1703  	formValues.Set("string_value", "hello-world")
  1704  	formValues.Add("repeated_string_value", "demo1")
  1705  	formValues.Add("repeated_string_value", "demo2")
  1706  
  1707  	testCases := []struct {
  1708  		name           string
  1709  		httpMethod     string
  1710  		contentType    string
  1711  		apiURL         string
  1712  		wantContent    string
  1713  		requestContent io.Reader
  1714  	}{
  1715  		{
  1716  			name:        "get url query values",
  1717  			httpMethod:  "GET",
  1718  			contentType: "application/json",
  1719  			apiURL:      fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/params/get/foo?double_value=%v&bool_value=%v", port, 1234.56, true),
  1720  			wantContent: `{"single_nested":{"name":"foo"},"double_value":1234.56,"bool_value":true}`,
  1721  		},
  1722  		{
  1723  			name:        "get nested enum url parameter",
  1724  			httpMethod:  "GET",
  1725  			contentType: "application/json",
  1726  			// If nested_enum.OK were FALSE, the content of single_nested would be {} due to how 0 values are serialized
  1727  			apiURL:      fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/params/get/nested_enum/TRUE", port),
  1728  			wantContent: `{"single_nested":{"ok":"TRUE"}}`,
  1729  		},
  1730  		{
  1731  			name:           "post url query values",
  1732  			httpMethod:     "POST",
  1733  			contentType:    "application/json",
  1734  			apiURL:         fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/params/post/hello-world?double_value=%v&bool_value=%v", port, 1234.56, true),
  1735  			wantContent:    `{"single_nested":{"name":"foo","amount":100},"double_value":1234.56,"bool_value":true,"string_value":"hello-world"}`,
  1736  			requestContent: strings.NewReader(`{"name":"foo","amount":100}`),
  1737  		},
  1738  		{
  1739  			name:           "post form and url query values",
  1740  			httpMethod:     "POST",
  1741  			contentType:    "application/x-www-form-urlencoded",
  1742  			apiURL:         fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/params/get/foo?double_value=%v&bool_value=%v", port, 1234.56, true),
  1743  			wantContent:    `{"single_nested":{"name":"foo"},"double_value":1234.56,"bool_value":true,"string_value":"hello-world","repeated_string_value":["demo1","demo2"]}`,
  1744  			requestContent: strings.NewReader(formValues.Encode()),
  1745  		},
  1746  	}
  1747  
  1748  	for _, tc := range testCases {
  1749  		t.Run(tc.name, func(t *testing.T) {
  1750  			req, err := http.NewRequest(tc.httpMethod, tc.apiURL, tc.requestContent)
  1751  			if err != nil {
  1752  				t.Errorf("http.method (%q) http.url (%q) failed with %v; want success", tc.httpMethod, tc.apiURL, err)
  1753  				return
  1754  			}
  1755  
  1756  			req.Header.Add("Content-Type", tc.contentType)
  1757  
  1758  			resp, err := http.DefaultClient.Do(req)
  1759  			if err != nil {
  1760  				t.Errorf("http.method (%q) http.url (%q) failed with %v; want success", tc.httpMethod, tc.apiURL, err)
  1761  				return
  1762  			}
  1763  			defer resp.Body.Close()
  1764  
  1765  			buf, err := ioutil.ReadAll(resp.Body)
  1766  			if err != nil {
  1767  				t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
  1768  				return
  1769  			}
  1770  
  1771  			if gotCode, wantCode := resp.StatusCode, http.StatusOK; gotCode != wantCode {
  1772  				t.Errorf("resp.StatusCode = %d; want %d", gotCode, wantCode)
  1773  				t.Logf("%s", buf)
  1774  			}
  1775  
  1776  			gotContent := string(buf)
  1777  			if gotContent != tc.wantContent {
  1778  				t.Errorf("http.method (%q) http.url (%q) response = %q; want %q", tc.httpMethod, tc.apiURL, gotContent, tc.wantContent)
  1779  			}
  1780  		})
  1781  	}
  1782  }
  1783  
  1784  func TestNonStandardNames(t *testing.T) {
  1785  	if testing.Short() {
  1786  		t.Skip()
  1787  		return
  1788  	}
  1789  
  1790  	ctx := context.Background()
  1791  	ctx, cancel := context.WithCancel(ctx)
  1792  	defer cancel()
  1793  
  1794  	go func() {
  1795  		if err := runGateway(
  1796  			ctx,
  1797  			":8081",
  1798  			runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{OrigName: true, EmitDefaults: true}),
  1799  		); err != nil {
  1800  			t.Errorf("runGateway() failed with %v; want success", err)
  1801  			return
  1802  		}
  1803  	}()
  1804  	go func() {
  1805  		if err := runGateway(
  1806  			ctx,
  1807  			":8082",
  1808  			runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{OrigName: false, EmitDefaults: true}),
  1809  		); err != nil {
  1810  			t.Errorf("runGateway() failed with %v; want success", err)
  1811  			return
  1812  		}
  1813  	}()
  1814  
  1815  	if err := waitForGateway(ctx, 8081); err != nil {
  1816  		t.Errorf("waitForGateway(ctx, 8081) failed with %v; want success", err)
  1817  	}
  1818  	if err := waitForGateway(ctx, 8082); err != nil {
  1819  		t.Errorf("waitForGateway(ctx, 8082) failed with %v; want success", err)
  1820  	}
  1821  
  1822  	for _, tc := range []struct {
  1823  		name     string
  1824  		port     int
  1825  		method   string
  1826  		jsonBody string
  1827  	}{
  1828  		{
  1829  			"Test standard update method",
  1830  			8081,
  1831  			"update",
  1832  			`{"id":"foo","Num":"1","line_num":"42","langIdent":"English","STATUS":"good","en_GB":"1","no":"yes","thing":{"subThing":{"sub_value":"hi"}}}`,
  1833  		},
  1834  		{
  1835  			"Test update method using json_names in message",
  1836  			8081,
  1837  			"update_with_json_names",
  1838  			// N.B. json_names have no effect if not using OrigName: false
  1839  			`{"id":"foo","Num":"1","line_num":"42","langIdent":"English","STATUS":"good","en_GB":"1","no":"yes","thing":{"subThing":{"sub_value":"hi"}}}`,
  1840  		},
  1841  		{
  1842  			"Test standard update method with OrigName: false marshaller option",
  1843  			8082,
  1844  			"update",
  1845  			`{"id":"foo","Num":"1","lineNum":"42","langIdent":"English","STATUS":"good","enGB":"1","no":"yes","thing":{"subThing":{"subValue":"hi"}}}`,
  1846  		},
  1847  		{
  1848  			"Test update method using json_names in message with OrigName: false marshaller option",
  1849  			8082,
  1850  			"update_with_json_names",
  1851  			`{"ID":"foo","Num":"1","LineNum":"42","langIdent":"English","status":"good","En_GB":"1","yes":"no","Thingy":{"SubThing":{"sub_Value":"hi"}}}`,
  1852  		},
  1853  	} {
  1854  		t.Run(tc.name, func(t *testing.T) {
  1855  			testNonStandardNames(t, tc.port, tc.method, tc.jsonBody)
  1856  		})
  1857  	}
  1858  }
  1859  
  1860  func testNonStandardNames(t *testing.T, port int, method string, jsonBody string) {
  1861  	req, err := http.NewRequest(
  1862  		http.MethodPatch,
  1863  		fmt.Sprintf("http://localhost:%d/v1/example/non_standard/%s", port, method),
  1864  		strings.NewReader(jsonBody),
  1865  	)
  1866  	if err != nil {
  1867  		t.Fatalf("http.NewRequest(PATCH) failed with %v; want success", err)
  1868  	}
  1869  	patchResp, err := http.DefaultClient.Do(req)
  1870  	if err != nil {
  1871  		t.Fatalf("failed to issue PATCH request: %v", err)
  1872  	}
  1873  
  1874  	body, err := ioutil.ReadAll(patchResp.Body)
  1875  	if err != nil {
  1876  		t.Errorf("patchResp body couldn't be read: %v", err)
  1877  	}
  1878  
  1879  	if got, want := patchResp.StatusCode, http.StatusOK; got != want {
  1880  		t.Errorf("patchResp.StatusCode= %d; want %d resp: %v", got, want, string(body))
  1881  	}
  1882  
  1883  	if got, want := string(body), jsonBody; got != want {
  1884  		t.Errorf("got %q; want %q", got, want)
  1885  	}
  1886  }
  1887  

View as plain text