...

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

Documentation: github.com/grpc-ecosystem/grpc-gateway/v2/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  	"net/http"
    12  	"net/url"
    13  	"reflect"
    14  	"strconv"
    15  	"strings"
    16  	"sync"
    17  	"testing"
    18  	"time"
    19  
    20  	"github.com/google/go-cmp/cmp"
    21  	"github.com/grpc-ecosystem/grpc-gateway/v2/examples/internal/proto/examplepb"
    22  	"github.com/grpc-ecosystem/grpc-gateway/v2/examples/internal/proto/pathenum"
    23  	"github.com/grpc-ecosystem/grpc-gateway/v2/examples/internal/proto/sub"
    24  	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
    25  	statuspb "google.golang.org/genproto/googleapis/rpc/status"
    26  	"google.golang.org/grpc/codes"
    27  	"google.golang.org/protobuf/encoding/protojson"
    28  	"google.golang.org/protobuf/proto"
    29  	"google.golang.org/protobuf/testing/protocmp"
    30  	"google.golang.org/protobuf/types/known/emptypb"
    31  	fieldmaskpb "google.golang.org/protobuf/types/known/fieldmaskpb"
    32  	"google.golang.org/protobuf/types/known/structpb"
    33  )
    34  
    35  var marshaler = &runtime.JSONPb{}
    36  
    37  func TestEcho(t *testing.T) {
    38  	if testing.Short() {
    39  		t.Skip()
    40  		return
    41  	}
    42  
    43  	for _, apiPrefix := range []string{"v1", "v2"} {
    44  		t.Run(apiPrefix, func(t *testing.T) {
    45  			testEcho(t, 8088, apiPrefix, "application/json")
    46  			testEchoOneof(t, 8088, apiPrefix, "application/json")
    47  			testEchoOneof1(t, 8088, apiPrefix, "application/json")
    48  			testEchoOneof2(t, 8088, apiPrefix, "application/json")
    49  			testEchoPathParamOverwrite(t, 8088)
    50  			testEchoNested(t, 8088)
    51  			testEchoNestedOverride(t, 8088)
    52  			testEchoBody(t, 8088, apiPrefix, true)
    53  			testEchoBody(t, 8088, apiPrefix, false)
    54  			// Use SendHeader/SetTrailer without gRPC server https://github.com/grpc-ecosystem/grpc-gateway/issues/517#issuecomment-684625645
    55  			testEchoBody(t, 8089, apiPrefix, true)
    56  			testEchoBody(t, 8089, apiPrefix, false)
    57  			testEchoWithNonASCIIHeaderValues(t, 8088, apiPrefix)
    58  			testEchoWithInvalidHeaderKey(t, 8088, apiPrefix)
    59  		})
    60  	}
    61  }
    62  
    63  func TestEchoUnauthorized(t *testing.T) {
    64  	if testing.Short() {
    65  		t.Skip()
    66  		return
    67  	}
    68  	apiURL := "http://localhost:8088/v1/example/echo_unauthorized"
    69  	resp, err := http.Get(apiURL)
    70  	if err != nil {
    71  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
    72  		return
    73  	}
    74  	defer resp.Body.Close()
    75  	buf, err := io.ReadAll(resp.Body)
    76  	if err != nil {
    77  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
    78  		return
    79  	}
    80  	msg := new(statuspb.Status)
    81  	if err := marshaler.Unmarshal(buf, msg); err != nil {
    82  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
    83  		return
    84  	}
    85  
    86  	if got, want := resp.StatusCode, http.StatusUnauthorized; got != want {
    87  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
    88  	}
    89  
    90  	if value := resp.Header.Get("WWW-Authenticate"); value == "" {
    91  		t.Errorf("WWW-Authenticate header should not be empty")
    92  	}
    93  }
    94  
    95  func TestEchoPatch(t *testing.T) {
    96  	if testing.Short() {
    97  		t.Skip()
    98  		return
    99  	}
   100  
   101  	sent := examplepb.DynamicMessage{
   102  		StructField: &structpb.Struct{Fields: map[string]*structpb.Value{
   103  			"struct_key": {Kind: &structpb.Value_StructValue{
   104  				StructValue: &structpb.Struct{Fields: map[string]*structpb.Value{
   105  					"layered_struct_key": {Kind: &structpb.Value_StringValue{StringValue: "struct_val"}},
   106  				}},
   107  			}},
   108  		}},
   109  		ValueField: &structpb.Value{Kind: &structpb.Value_StructValue{
   110  			StructValue: &structpb.Struct{Fields: map[string]*structpb.Value{
   111  				"value_struct_key": {Kind: &structpb.Value_StringValue{StringValue: "value_struct_val"}},
   112  			}},
   113  		}},
   114  	}
   115  	payload, err := protojson.MarshalOptions{UseProtoNames: true}.Marshal(&sent)
   116  	if err != nil {
   117  		t.Fatalf("marshaler.Marshal(%#v) failed with %v; want success", payload, err)
   118  	}
   119  
   120  	apiURL := "http://localhost:8088/v1/example/echo_patch"
   121  	req, err := http.NewRequest("PATCH", apiURL, bytes.NewReader(payload))
   122  	if err != nil {
   123  		t.Errorf("http.NewRequest(PATCH, %q) failed with %v; want success", apiURL, err)
   124  		return
   125  	}
   126  	resp, err := http.DefaultClient.Do(req)
   127  	if err != nil {
   128  		t.Errorf("http.Post(%#v) failed with %v; want success", req, err)
   129  		return
   130  	}
   131  	defer resp.Body.Close()
   132  	buf, err := io.ReadAll(resp.Body)
   133  	if err != nil {
   134  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
   135  		return
   136  	}
   137  
   138  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   139  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   140  		t.Logf("%s", buf)
   141  	}
   142  
   143  	var received examplepb.DynamicMessageUpdate
   144  	if err := marshaler.Unmarshal(buf, &received); err != nil {
   145  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
   146  		return
   147  	}
   148  	if diff := cmp.Diff(received.Body, sent, protocmp.Transform()); diff != "" {
   149  		t.Errorf(diff)
   150  	}
   151  	if diff := cmp.Diff(received.UpdateMask, fieldmaskpb.FieldMask{Paths: []string{
   152  		"struct_field.struct_key.layered_struct_key", "value_field.value_struct_key",
   153  	}}, protocmp.Transform(), protocmp.SortRepeatedFields(received.UpdateMask, "paths")); diff != "" {
   154  		t.Errorf(diff)
   155  	}
   156  }
   157  
   158  func TestForwardResponseOption(t *testing.T) {
   159  	if testing.Short() {
   160  		t.Skip()
   161  		return
   162  	}
   163  
   164  	ctx := context.Background()
   165  	ctx, cancel := context.WithCancel(ctx)
   166  	defer cancel()
   167  
   168  	port := 7079
   169  	go func() {
   170  		if err := runGateway(
   171  			ctx,
   172  			fmt.Sprintf(":%d", port),
   173  			runtime.WithForwardResponseOption(
   174  				func(_ context.Context, w http.ResponseWriter, _ proto.Message) error {
   175  					w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1.1+json")
   176  					return nil
   177  				},
   178  			),
   179  		); err != nil {
   180  			t.Errorf("runGateway() failed with %v; want success", err)
   181  			return
   182  		}
   183  	}()
   184  	if err := waitForGateway(ctx, uint16(port)); err != nil {
   185  		t.Errorf("waitForGateway(ctx, %d) failed with %v; want success", port, err)
   186  	}
   187  	testEcho(t, port, "v1", "application/vnd.docker.plugins.v1.1+json")
   188  }
   189  
   190  func TestForwardResponseOptionHTTPPathPattern(t *testing.T) {
   191  	if testing.Short() {
   192  		t.Skip()
   193  		return
   194  	}
   195  
   196  	ctx := context.Background()
   197  	ctx, cancel := context.WithCancel(ctx)
   198  	defer cancel()
   199  
   200  	port := 7080
   201  	go func() {
   202  		if err := runGateway(
   203  			ctx,
   204  			fmt.Sprintf(":%d", port),
   205  			runtime.WithForwardResponseOption(
   206  				func(ctx context.Context, w http.ResponseWriter, _ proto.Message) error {
   207  					path, _ := runtime.HTTPPathPattern(ctx)
   208  					w.Header().Set("Content-Type", path)
   209  					return nil
   210  				},
   211  			),
   212  		); err != nil {
   213  			t.Errorf("runGateway() failed with %v; want success", err)
   214  			return
   215  		}
   216  	}()
   217  	if err := waitForGateway(ctx, uint16(port)); err != nil {
   218  		t.Errorf("waitForGateway(ctx, %d) failed with %v; want success", port, err)
   219  	}
   220  	testEcho(t, port, "v1", "/v1/example/echo/{id}")
   221  }
   222  
   223  func testEcho(t *testing.T, port int, apiPrefix string, contentType string) {
   224  	apiURL := fmt.Sprintf("http://localhost:%d/%s/example/echo/myid", port, apiPrefix)
   225  	resp, err := http.Post(apiURL, "application/json", strings.NewReader("{}"))
   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 := io.ReadAll(resp.Body)
   232  	if err != nil {
   233  		t.Errorf("io.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  	msg := new(examplepb.UnannotatedSimpleMessage)
   243  	if err := marshaler.Unmarshal(buf, msg); err != nil {
   244  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
   245  		return
   246  	}
   247  	if got, want := msg.Id, "myid"; got != want {
   248  		t.Errorf("msg.Id = %q; want %q", got, want)
   249  	}
   250  
   251  	if value := resp.Header.Get("Content-Type"); value != contentType {
   252  		t.Errorf("Content-Type was %s, wanted %s", value, contentType)
   253  	}
   254  }
   255  
   256  func testEchoOneof(t *testing.T, port int, apiPrefix string, contentType string) {
   257  	apiURL := fmt.Sprintf("http://localhost:%d/%s/example/echo/myid/10/golang", port, apiPrefix)
   258  	resp, err := http.Get(apiURL)
   259  	if err != nil {
   260  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
   261  		return
   262  	}
   263  	defer resp.Body.Close()
   264  	buf, err := io.ReadAll(resp.Body)
   265  	if err != nil {
   266  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
   267  		return
   268  	}
   269  
   270  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   271  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   272  		t.Logf("%s", buf)
   273  	}
   274  
   275  	msg := new(examplepb.UnannotatedSimpleMessage)
   276  	if err := marshaler.Unmarshal(buf, msg); err != nil {
   277  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
   278  		return
   279  	}
   280  	if got, want := msg.GetLang(), "golang"; got != want {
   281  		t.Errorf("msg.GetLang() = %q; want %q", got, want)
   282  	}
   283  
   284  	if value := resp.Header.Get("Content-Type"); value != contentType {
   285  		t.Errorf("Content-Type was %s, wanted %s", value, contentType)
   286  	}
   287  }
   288  
   289  func testEchoOneof1(t *testing.T, port int, apiPrefix string, contentType string) {
   290  	apiURL := fmt.Sprintf("http://localhost:%d/%s/example/echo1/myid/10/golang", port, apiPrefix)
   291  	resp, err := http.Get(apiURL)
   292  	if err != nil {
   293  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
   294  		return
   295  	}
   296  	defer resp.Body.Close()
   297  	buf, err := io.ReadAll(resp.Body)
   298  	if err != nil {
   299  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
   300  		return
   301  	}
   302  
   303  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   304  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   305  		t.Logf("%s", buf)
   306  	}
   307  
   308  	msg := new(examplepb.UnannotatedSimpleMessage)
   309  	if err := marshaler.Unmarshal(buf, msg); err != nil {
   310  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
   311  		return
   312  	}
   313  	if got, want := msg.GetStatus().GetNote(), "golang"; got != want {
   314  		t.Errorf("msg.GetStatus().GetNote() = %q; want %q", got, want)
   315  	}
   316  
   317  	if value := resp.Header.Get("Content-Type"); value != contentType {
   318  		t.Errorf("Content-Type was %s, wanted %s", value, contentType)
   319  	}
   320  }
   321  
   322  func testEchoOneof2(t *testing.T, port int, apiPrefix string, contentType string) {
   323  	apiURL := fmt.Sprintf("http://localhost:%d/%s/example/echo2/golang", port, apiPrefix)
   324  	resp, err := http.Get(apiURL)
   325  	if err != nil {
   326  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
   327  		return
   328  	}
   329  	defer resp.Body.Close()
   330  	buf, err := io.ReadAll(resp.Body)
   331  	if err != nil {
   332  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
   333  		return
   334  	}
   335  
   336  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   337  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   338  		t.Logf("%s", buf)
   339  	}
   340  
   341  	msg := new(examplepb.UnannotatedSimpleMessage)
   342  	if err := marshaler.Unmarshal(buf, msg); err != nil {
   343  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
   344  		return
   345  	}
   346  	if got, want := msg.GetNo().GetNote(), "golang"; got != want {
   347  		t.Errorf("msg.GetNo().GetNote() = %q; want %q", got, want)
   348  	}
   349  
   350  	if value := resp.Header.Get("Content-Type"); value != contentType {
   351  		t.Errorf("Content-Type was %s, wanted %s", value, contentType)
   352  	}
   353  }
   354  
   355  func testEchoPathParamOverwrite(t *testing.T, port int) {
   356  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/echo/resource/my_resource_id?resourceId=bad_resource_id", port)
   357  	resp, err := http.Get(apiURL)
   358  	if err != nil {
   359  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
   360  		return
   361  	}
   362  	defer resp.Body.Close()
   363  	buf, err := io.ReadAll(resp.Body)
   364  	if err != nil {
   365  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
   366  		return
   367  	}
   368  
   369  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   370  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   371  		t.Logf("%s", buf)
   372  	}
   373  
   374  	msg := new(examplepb.UnannotatedSimpleMessage)
   375  	if err := marshaler.Unmarshal(buf, msg); err != nil {
   376  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
   377  		return
   378  	}
   379  	if got, want := msg.GetResourceId(), "my_resource_id"; got != want {
   380  		t.Errorf("msg.GetResourceId() = %q; want %q", got, want)
   381  	}
   382  }
   383  
   384  func testEchoNested(t *testing.T, port int) {
   385  	resp, err := http.Get(fmt.Sprintf("http://localhost:%d/v1/example/echo/nested/my_nested_id?n_id.val=foo", port))
   386  	if err != nil {
   387  		t.Errorf("http.Get() failed with %v; want success", err)
   388  		return
   389  	}
   390  	defer resp.Body.Close()
   391  	buf, err := io.ReadAll(resp.Body)
   392  	if err != nil {
   393  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
   394  		return
   395  	}
   396  
   397  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   398  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   399  		t.Logf("%s", buf)
   400  	}
   401  
   402  	msg := new(examplepb.UnannotatedSimpleMessage)
   403  	if err := marshaler.Unmarshal(buf, msg); err != nil {
   404  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
   405  		return
   406  	}
   407  	if got, want := msg.NId.Val, "foo"; got != want {
   408  		t.Errorf("msg.NId.Val = %q; want %q", got, want)
   409  	}
   410  }
   411  
   412  func testEchoNestedOverride(t *testing.T, port int) {
   413  	resp, err := http.Get(fmt.Sprintf("http://localhost:%d/v1/example/echo/nested/my_nested_id?nId.nId=bad_id", port))
   414  	if err != nil {
   415  		t.Errorf("http.Get() failed with %v; want success", err)
   416  		return
   417  	}
   418  	defer resp.Body.Close()
   419  	buf, err := io.ReadAll(resp.Body)
   420  	if err != nil {
   421  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
   422  		return
   423  	}
   424  
   425  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   426  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   427  		t.Logf("%s", buf)
   428  	}
   429  
   430  	msg := new(examplepb.UnannotatedSimpleMessage)
   431  	if err := marshaler.Unmarshal(buf, msg); err != nil {
   432  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
   433  		return
   434  	}
   435  	if got, want := msg.NId.NId, "my_nested_id"; got != want {
   436  		t.Errorf("msg.NId.NId = %q; want %q", got, want)
   437  	}
   438  }
   439  
   440  func testEchoBody(t *testing.T, port int, apiPrefix string, useTrailers bool) {
   441  	sent := examplepb.UnannotatedSimpleMessage{Id: "example"}
   442  	payload, err := marshaler.Marshal(&sent)
   443  	if err != nil {
   444  		t.Fatalf("marshaler.Marshal(%#v) failed with %v; want success", payload, err)
   445  	}
   446  
   447  	apiURL := fmt.Sprintf("http://localhost:%d/%s/example/echo_body", port, apiPrefix)
   448  
   449  	req, err := http.NewRequest("POST", apiURL, bytes.NewReader(payload))
   450  	if err != nil {
   451  		t.Errorf("http.NewRequest() failed with %v; want success", err)
   452  		return
   453  	}
   454  	if useTrailers {
   455  		req.Header.Set("TE", "trailers")
   456  	}
   457  
   458  	resp, err := http.DefaultClient.Do(req)
   459  	if err != nil {
   460  		t.Errorf("client.Do(%v) failed with %v; want success", req, err)
   461  		return
   462  	}
   463  	defer resp.Body.Close()
   464  	buf, err := io.ReadAll(resp.Body)
   465  	if err != nil {
   466  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
   467  		return
   468  	}
   469  
   470  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   471  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   472  		t.Logf("%s", buf)
   473  	}
   474  
   475  	var received examplepb.UnannotatedSimpleMessage
   476  	if err := marshaler.Unmarshal(buf, &received); err != nil {
   477  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
   478  		return
   479  	}
   480  	if diff := cmp.Diff(&received, &sent, protocmp.Transform()); diff != "" {
   481  		t.Errorf(diff)
   482  	}
   483  
   484  	if got, want := resp.Header.Get("Grpc-Metadata-Foo"), "foo1"; got != want {
   485  		t.Errorf("Grpc-Metadata-Foo was %q, wanted %q", got, want)
   486  	}
   487  	if got, want := resp.Header.Get("Grpc-Metadata-Bar"), "bar1"; got != want {
   488  		t.Errorf("Grpc-Metadata-Bar was %q, wanted %q", got, want)
   489  	}
   490  
   491  	wantedTrailers := map[bool]map[string]string{
   492  		true: {
   493  			"Grpc-Trailer-Foo": "foo2",
   494  			"Grpc-Trailer-Bar": "bar2",
   495  		},
   496  		false: {},
   497  	}
   498  
   499  	for trailer, want := range wantedTrailers[useTrailers] {
   500  		if got := resp.Trailer.Get(trailer); got != want {
   501  			t.Errorf("%s was %q, wanted %q", trailer, got, want)
   502  		}
   503  	}
   504  }
   505  
   506  func TestABE(t *testing.T) {
   507  	if testing.Short() {
   508  		t.Skip()
   509  		return
   510  	}
   511  
   512  	testABECreate(t, 8088)
   513  	testABECreateBody(t, 8088)
   514  	testABEBulkCreate(t, 8088, true)
   515  	testABEBulkCreate(t, 8088, false)
   516  	testABEBulkCreateWithError(t, 8088)
   517  	testABELookup(t, 8088)
   518  	testABELookupNotFound(t, 8088, true)
   519  	testABELookupNotFound(t, 8088, false)
   520  	testABEList(t, 8088)
   521  	testABEDownload(t, 8088)
   522  	testABEBulkEcho(t, 8088)
   523  	testABEBulkEchoZeroLength(t, 8088)
   524  	testAdditionalBindings(t, 8088)
   525  	testABERepeated(t, 8088)
   526  	testABEExists(t, 8088)
   527  	testABEExistsNotFound(t, 8088)
   528  	testABEOptions(t, 8088)
   529  	testABETrace(t, 8088)
   530  }
   531  
   532  func testABECreate(t *testing.T, port int) {
   533  	want := &examplepb.ABitOfEverything{
   534  		FloatValue:               1.5,
   535  		DoubleValue:              2.5,
   536  		Int64Value:               4294967296,
   537  		Uint64Value:              9223372036854775807,
   538  		Int32Value:               -2147483648,
   539  		Fixed64Value:             9223372036854775807,
   540  		Fixed32Value:             4294967295,
   541  		BoolValue:                true,
   542  		StringValue:              "strprefix/foo",
   543  		Uint32Value:              4294967295,
   544  		Sfixed32Value:            2147483647,
   545  		Sfixed64Value:            -4611686018427387904,
   546  		Sint32Value:              2147483647,
   547  		Sint64Value:              4611686018427387903,
   548  		NonConventionalNameValue: "camelCase",
   549  		EnumValue:                examplepb.NumericEnum_ZERO,
   550  		PathEnumValue:            pathenum.PathEnum_DEF,
   551  		NestedPathEnumValue:      pathenum.MessagePathEnum_JKL,
   552  		EnumValueAnnotation:      examplepb.NumericEnum_ONE,
   553  	}
   554  	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)
   555  
   556  	resp, err := http.Post(apiURL, "application/json", strings.NewReader("{}"))
   557  	if err != nil {
   558  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
   559  		return
   560  	}
   561  	defer resp.Body.Close()
   562  	buf, err := io.ReadAll(resp.Body)
   563  	if err != nil {
   564  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
   565  		return
   566  	}
   567  
   568  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   569  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   570  		t.Logf("%s", buf)
   571  	}
   572  
   573  	msg := new(examplepb.ABitOfEverything)
   574  	if err := marshaler.Unmarshal(buf, msg); err != nil {
   575  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
   576  		return
   577  	}
   578  	if msg.Uuid == "" {
   579  		t.Error("msg.Uuid is empty; want not empty")
   580  	}
   581  	msg.Uuid = ""
   582  	if diff := cmp.Diff(msg, want, protocmp.Transform()); diff != "" {
   583  		t.Errorf(diff)
   584  	}
   585  }
   586  
   587  func testABECreateBody(t *testing.T, port int) {
   588  	optionalStrVal := "optional-str"
   589  	want := &examplepb.ABitOfEverything{
   590  		FloatValue:               1.5,
   591  		DoubleValue:              2.5,
   592  		Int64Value:               4294967296,
   593  		Uint64Value:              9223372036854775807,
   594  		Int32Value:               -2147483648,
   595  		Fixed64Value:             9223372036854775807,
   596  		Fixed32Value:             4294967295,
   597  		BoolValue:                true,
   598  		StringValue:              "strprefix/foo",
   599  		Uint32Value:              4294967295,
   600  		Sfixed32Value:            2147483647,
   601  		Sfixed64Value:            -4611686018427387904,
   602  		Sint32Value:              2147483647,
   603  		Sint64Value:              4611686018427387903,
   604  		NonConventionalNameValue: "camelCase",
   605  		EnumValue:                examplepb.NumericEnum_ONE,
   606  		PathEnumValue:            pathenum.PathEnum_ABC,
   607  		NestedPathEnumValue:      pathenum.MessagePathEnum_GHI,
   608  
   609  		Nested: []*examplepb.ABitOfEverything_Nested{
   610  			{
   611  				Name:   "bar",
   612  				Amount: 10,
   613  			},
   614  			{
   615  				Name:   "baz",
   616  				Amount: 20,
   617  			},
   618  		},
   619  		RepeatedStringValue: []string{"a", "b", "c"},
   620  		OneofValue: &examplepb.ABitOfEverything_OneofString{
   621  			OneofString: "x",
   622  		},
   623  		MapValue: map[string]examplepb.NumericEnum{
   624  			"a": examplepb.NumericEnum_ONE,
   625  			"b": examplepb.NumericEnum_ZERO,
   626  		},
   627  		MappedStringValue: map[string]string{
   628  			"a": "x",
   629  			"b": "y",
   630  		},
   631  		MappedNestedValue: map[string]*examplepb.ABitOfEverything_Nested{
   632  			"a": {Name: "x", Amount: 1},
   633  			"b": {Name: "y", Amount: 2},
   634  		},
   635  		RepeatedEnumAnnotation: []examplepb.NumericEnum{
   636  			examplepb.NumericEnum_ONE,
   637  			examplepb.NumericEnum_ZERO,
   638  		},
   639  		EnumValueAnnotation: examplepb.NumericEnum_ONE,
   640  		RepeatedStringAnnotation: []string{
   641  			"a",
   642  			"b",
   643  		},
   644  		RepeatedNestedAnnotation: []*examplepb.ABitOfEverything_Nested{
   645  			{
   646  				Name:   "hoge",
   647  				Amount: 10,
   648  			},
   649  			{
   650  				Name:   "fuga",
   651  				Amount: 20,
   652  			},
   653  		},
   654  		NestedAnnotation: &examplepb.ABitOfEverything_Nested{
   655  			Name:   "hoge",
   656  			Amount: 10,
   657  		},
   658  		OptionalStringValue: &optionalStrVal,
   659  	}
   660  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything", port)
   661  	payload, err := marshaler.Marshal(want)
   662  	if err != nil {
   663  		t.Fatalf("marshaler.Marshal(%#v) failed with %v; want success", want, err)
   664  	}
   665  
   666  	resp, err := http.Post(apiURL, "application/json", bytes.NewReader(payload))
   667  	if err != nil {
   668  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
   669  		return
   670  	}
   671  	defer resp.Body.Close()
   672  	buf, err := io.ReadAll(resp.Body)
   673  	if err != nil {
   674  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
   675  		return
   676  	}
   677  
   678  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   679  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   680  		t.Logf("%s", buf)
   681  	}
   682  
   683  	msg := new(examplepb.ABitOfEverything)
   684  	if err := marshaler.Unmarshal(buf, msg); err != nil {
   685  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
   686  		return
   687  	}
   688  	if msg.Uuid == "" {
   689  		t.Error("msg.Uuid is empty; want not empty")
   690  	}
   691  	msg.Uuid = ""
   692  	if diff := cmp.Diff(msg, want, protocmp.Transform()); diff != "" {
   693  		t.Errorf(diff)
   694  	}
   695  }
   696  
   697  func testABEBulkCreate(t *testing.T, port int, useTrailers bool) {
   698  	count := 0
   699  	r, w := io.Pipe()
   700  	go func(w io.WriteCloser) {
   701  		defer func() {
   702  			if cerr := w.Close(); cerr != nil {
   703  				t.Errorf("w.Close() failed with %v; want success", cerr)
   704  			}
   705  		}()
   706  		for _, val := range []string{
   707  			"foo", "bar", "baz", "qux", "quux",
   708  		} {
   709  			strVal := fmt.Sprintf("strprefix/%s", val)
   710  			want := &examplepb.ABitOfEverything{
   711  				FloatValue:               1.5,
   712  				DoubleValue:              2.5,
   713  				Int64Value:               4294967296,
   714  				Uint64Value:              9223372036854775807,
   715  				Int32Value:               -2147483648,
   716  				Fixed64Value:             9223372036854775807,
   717  				Fixed32Value:             4294967295,
   718  				BoolValue:                true,
   719  				StringValue:              strVal,
   720  				Uint32Value:              4294967295,
   721  				Sfixed32Value:            2147483647,
   722  				Sfixed64Value:            -4611686018427387904,
   723  				Sint32Value:              2147483647,
   724  				Sint64Value:              4611686018427387903,
   725  				NonConventionalNameValue: "camelCase",
   726  				EnumValue:                examplepb.NumericEnum_ONE,
   727  				PathEnumValue:            pathenum.PathEnum_ABC,
   728  				NestedPathEnumValue:      pathenum.MessagePathEnum_GHI,
   729  
   730  				Nested: []*examplepb.ABitOfEverything_Nested{
   731  					{
   732  						Name:   "hoge",
   733  						Amount: 10,
   734  					},
   735  					{
   736  						Name:   "fuga",
   737  						Amount: 20,
   738  					},
   739  				},
   740  				RepeatedEnumAnnotation: []examplepb.NumericEnum{
   741  					examplepb.NumericEnum_ONE,
   742  					examplepb.NumericEnum_ZERO,
   743  				},
   744  				EnumValueAnnotation: examplepb.NumericEnum_ONE,
   745  				RepeatedStringAnnotation: []string{
   746  					"a",
   747  					"b",
   748  				},
   749  				RepeatedNestedAnnotation: []*examplepb.ABitOfEverything_Nested{
   750  					{
   751  						Name:   "hoge",
   752  						Amount: 10,
   753  					},
   754  					{
   755  						Name:   "fuga",
   756  						Amount: 20,
   757  					},
   758  				},
   759  				NestedAnnotation: &examplepb.ABitOfEverything_Nested{
   760  					Name:   "hoge",
   761  					Amount: 10,
   762  				},
   763  				OptionalStringValue: &strVal,
   764  			}
   765  			out, err := marshaler.Marshal(want)
   766  			if err != nil {
   767  				t.Errorf("marshaler.Marshal(%#v, w) failed with %v; want success", want, err)
   768  				return
   769  			}
   770  			if _, err := w.Write(out); err != nil {
   771  				t.Errorf("w.Write() failed with %v; want success", err)
   772  				return
   773  			}
   774  			if _, err := io.WriteString(w, "\n"); err != nil {
   775  				t.Errorf("w.Write(%q) failed with %v; want success", "\n", err)
   776  				return
   777  			}
   778  			count++
   779  		}
   780  	}(w)
   781  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/bulk", port)
   782  
   783  	req, err := http.NewRequest("POST", apiURL, r)
   784  	if err != nil {
   785  		t.Errorf("http.NewRequest() failed with %v; want success", err)
   786  		return
   787  	}
   788  	req.Header.Set("Content-Type", "application/json")
   789  
   790  	if useTrailers {
   791  		req.Header.Set("TE", "trailers")
   792  	}
   793  
   794  	resp, err := http.DefaultClient.Do(req)
   795  	if err != nil {
   796  		t.Errorf("client.Do(%v) failed with %v; want success", req, err)
   797  		return
   798  	}
   799  
   800  	defer resp.Body.Close()
   801  	buf, err := io.ReadAll(resp.Body)
   802  	if err != nil {
   803  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
   804  		return
   805  	}
   806  
   807  	if got, want := resp.StatusCode, http.StatusOK; got != want {
   808  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   809  		t.Logf("%s", buf)
   810  	}
   811  
   812  	msg := new(emptypb.Empty)
   813  	if err := marshaler.Unmarshal(buf, msg); err != nil {
   814  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
   815  		return
   816  	}
   817  
   818  	if got, want := resp.Header.Get("Grpc-Metadata-Count"), fmt.Sprintf("%d", count); got != want {
   819  		t.Errorf("Grpc-Metadata-Count was %q, wanted %q", got, want)
   820  	}
   821  
   822  	wantedTrailers := map[bool]map[string]string{
   823  		true: {
   824  			"Grpc-Trailer-Foo": "foo2",
   825  			"Grpc-Trailer-Bar": "bar2",
   826  		},
   827  		false: {},
   828  	}
   829  
   830  	for trailer, want := range wantedTrailers[useTrailers] {
   831  		if got := resp.Trailer.Get(trailer); got != want {
   832  			t.Errorf("%s was %q, wanted %q", trailer, got, want)
   833  		}
   834  	}
   835  }
   836  
   837  func testABEBulkCreateWithError(t *testing.T, port int) {
   838  	count := 0
   839  	r, w := io.Pipe()
   840  	go func(w io.WriteCloser) {
   841  		defer func() {
   842  			if cerr := w.Close(); cerr != nil {
   843  				t.Errorf("w.Close() failed with %v; want success", cerr)
   844  			}
   845  		}()
   846  		for _, val := range []string{
   847  			"foo", "bar", "baz", "qux", "quux",
   848  		} {
   849  			time.Sleep(1 * time.Millisecond)
   850  
   851  			want := &examplepb.ABitOfEverything{
   852  				StringValue: fmt.Sprintf("strprefix/%s", val),
   853  			}
   854  			out, err := marshaler.Marshal(want)
   855  			if err != nil {
   856  				t.Errorf("marshaler.Marshal(%#v, w) failed with %v; want success", want, err)
   857  				return
   858  			}
   859  			if _, err := w.Write(out); err != nil {
   860  				t.Errorf("w.Write() failed with %v; want success", err)
   861  				return
   862  			}
   863  			if _, err := io.WriteString(w, "\n"); err != nil {
   864  				t.Errorf("w.Write(%q) failed with %v; want success", "\n", err)
   865  				return
   866  			}
   867  			count++
   868  		}
   869  	}(w)
   870  
   871  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/bulk", port)
   872  	request, err := http.NewRequest("POST", apiURL, r)
   873  	if err != nil {
   874  		t.Fatalf("http.NewRequest(%q, %q, nil) failed with %v; want success", "POST", apiURL, err)
   875  	}
   876  	request.Header.Add("Grpc-Metadata-error", "some error")
   877  
   878  	resp, err := http.DefaultClient.Do(request)
   879  	if err != nil {
   880  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
   881  		return
   882  	}
   883  	defer resp.Body.Close()
   884  	buf, err := io.ReadAll(resp.Body)
   885  	if err != nil {
   886  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
   887  		return
   888  	}
   889  
   890  	if got, want := resp.StatusCode, http.StatusBadRequest; got != want {
   891  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   892  		t.Logf("%s", buf)
   893  	}
   894  
   895  	msg := new(statuspb.Status)
   896  	if err := marshaler.Unmarshal(buf, msg); err != nil {
   897  		t.Fatalf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
   898  	}
   899  }
   900  
   901  func testABELookup(t *testing.T, port int) {
   902  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything", port)
   903  	cresp, err := http.Post(apiURL, "application/json", strings.NewReader(`
   904  		{"bool_value": true, "string_value": "strprefix/example"}
   905  	`))
   906  	if err != nil {
   907  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
   908  		return
   909  	}
   910  	defer cresp.Body.Close()
   911  	buf, err := io.ReadAll(cresp.Body)
   912  	if err != nil {
   913  		t.Errorf("io.ReadAll(cresp.Body) failed with %v; want success", err)
   914  		return
   915  	}
   916  	if got, want := cresp.StatusCode, http.StatusOK; got != want {
   917  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
   918  		t.Logf("%s", buf)
   919  		return
   920  	}
   921  
   922  	want := new(examplepb.ABitOfEverything)
   923  	if err := marshaler.Unmarshal(buf, want); err != nil {
   924  		t.Errorf("marshaler.Unmarshal(%s, want) failed with %v; want success", buf, err)
   925  		return
   926  	}
   927  
   928  	apiURL = fmt.Sprintf("%s/%s", apiURL, want.Uuid)
   929  	resp, err := http.Get(apiURL)
   930  	if err != nil {
   931  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
   932  		return
   933  	}
   934  	defer resp.Body.Close()
   935  
   936  	buf, err = io.ReadAll(resp.Body)
   937  	if err != nil {
   938  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
   939  		return
   940  	}
   941  
   942  	msg := new(examplepb.ABitOfEverything)
   943  	if err := marshaler.Unmarshal(buf, msg); err != nil {
   944  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
   945  		return
   946  	}
   947  	if diff := cmp.Diff(msg, want, protocmp.Transform()); diff != "" {
   948  		t.Errorf(diff)
   949  	}
   950  
   951  	if got, want := resp.Header.Get("Grpc-Metadata-Uuid"), want.Uuid; got != want {
   952  		t.Errorf("Grpc-Metadata-Uuid was %s, wanted %s", got, want)
   953  	}
   954  }
   955  
   956  // TestABEPatch demonstrates partially updating a resource.
   957  // First, we'll create an ABE resource with known values for string_value and int32_value
   958  // Then, issue a PATCH request updating only the string_value
   959  // Then, GET the resource and verify that string_value is changed, but int32_value isn't
   960  func TestABEPatch(t *testing.T) {
   961  	if testing.Short() {
   962  		t.Skip()
   963  		return
   964  	}
   965  
   966  	port := 8088
   967  
   968  	// create a record with a known string_value and int32_value
   969  	uuid := postABE(t, port, &examplepb.ABitOfEverything{StringValue: "strprefix/bar", Int32Value: 32})
   970  
   971  	// issue PATCH request, only updating string_value
   972  	req, err := http.NewRequest(
   973  		http.MethodPatch,
   974  		fmt.Sprintf("http://localhost:%d/v2/example/a_bit_of_everything/%s", port, uuid),
   975  		strings.NewReader(`{"string_value": "strprefix/foo"}`),
   976  	)
   977  	if err != nil {
   978  		t.Fatalf("http.NewRequest(PATCH) failed with %v; want success", err)
   979  	}
   980  	patchResp, err := http.DefaultClient.Do(req)
   981  	if err != nil {
   982  		t.Fatalf("failed to issue PATCH request: %v", err)
   983  	}
   984  	if got, want := patchResp.StatusCode, http.StatusOK; got != want {
   985  		if body, err := io.ReadAll(patchResp.Body); err != nil {
   986  			t.Errorf("patchResp body couldn't be read: %v", err)
   987  		} else {
   988  			t.Errorf("patchResp.StatusCode= %d; want %d resp: %v", got, want, string(body))
   989  		}
   990  	}
   991  
   992  	// issue GET request, verifying that string_value is changed and int32_value is not
   993  	getRestatuspbody := getABE(t, port, uuid)
   994  	if got, want := getRestatuspbody.StringValue, "strprefix/foo"; got != want {
   995  		t.Errorf("string_value= %q; want %q", got, want)
   996  	}
   997  	if got, want := getRestatuspbody.Int32Value, int32(32); got != want {
   998  		t.Errorf("int_32_value= %d; want %d", got, want)
   999  	}
  1000  }
  1001  
  1002  // TestABEPatchBody demonstrates the ability to specify an update mask within the request body.
  1003  // This binding does not use an automatically generated update_mask.
  1004  func TestABEPatchBody(t *testing.T) {
  1005  	if testing.Short() {
  1006  		t.Skip()
  1007  		return
  1008  	}
  1009  
  1010  	port := 8088
  1011  
  1012  	for _, tc := range []struct {
  1013  		name          string
  1014  		originalValue *examplepb.ABitOfEverything
  1015  		input         *examplepb.UpdateV2Request
  1016  		want          *examplepb.ABitOfEverything
  1017  	}{
  1018  		{
  1019  			name: "with fieldmask provided",
  1020  			originalValue: &examplepb.ABitOfEverything{
  1021  				Int32Value:  42,
  1022  				StringValue: "rabbit",
  1023  				SingleNested: &examplepb.ABitOfEverything_Nested{
  1024  					Name:   "some value that will get overwritten",
  1025  					Amount: 345,
  1026  				},
  1027  			},
  1028  			input: &examplepb.UpdateV2Request{
  1029  				Abe: &examplepb.ABitOfEverything{
  1030  					StringValue: "some value that won't get updated because it's not in the field mask",
  1031  					SingleNested: &examplepb.ABitOfEverything_Nested{
  1032  						Amount: 456,
  1033  					},
  1034  				},
  1035  				UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"single_nested"}},
  1036  			},
  1037  			want: &examplepb.ABitOfEverything{
  1038  				Int32Value:  42,
  1039  				StringValue: "rabbit",
  1040  				SingleNested: &examplepb.ABitOfEverything_Nested{
  1041  					Amount: 456,
  1042  				},
  1043  			},
  1044  		},
  1045  		{
  1046  			// N.B. This case passes the empty field mask to the UpdateV2 method so falls back to PUT semantics as per the implementation.
  1047  			name: "with empty fieldmask",
  1048  			originalValue: &examplepb.ABitOfEverything{
  1049  				Int32Value:  42,
  1050  				StringValue: "some value that will get overwritten",
  1051  				SingleNested: &examplepb.ABitOfEverything_Nested{
  1052  					Name:   "value that will get empty",
  1053  					Amount: 345,
  1054  				},
  1055  			},
  1056  			input: &examplepb.UpdateV2Request{
  1057  				Abe: &examplepb.ABitOfEverything{
  1058  					StringValue: "some updated value because the fieldMask is nil",
  1059  					SingleNested: &examplepb.ABitOfEverything_Nested{
  1060  						Amount: 456,
  1061  					},
  1062  				},
  1063  				UpdateMask: &fieldmaskpb.FieldMask{},
  1064  			},
  1065  			want: &examplepb.ABitOfEverything{
  1066  				StringValue: "some updated value because the fieldMask is nil",
  1067  				SingleNested: &examplepb.ABitOfEverything_Nested{
  1068  					Amount: 456,
  1069  				},
  1070  			},
  1071  		},
  1072  		{
  1073  			// N.B. This case passes the nil field mask to the UpdateV2 method so falls back to PUT semantics as per the implementation.
  1074  			name: "with nil fieldmask",
  1075  			originalValue: &examplepb.ABitOfEverything{
  1076  				Int32Value:  42,
  1077  				StringValue: "some value that will get overwritten",
  1078  				SingleNested: &examplepb.ABitOfEverything_Nested{
  1079  					Name:   "value that will get empty",
  1080  					Amount: 123,
  1081  				},
  1082  			},
  1083  			input: &examplepb.UpdateV2Request{
  1084  				Abe: &examplepb.ABitOfEverything{
  1085  					StringValue: "some updated value because the fieldMask is nil",
  1086  					SingleNested: &examplepb.ABitOfEverything_Nested{
  1087  						Amount: 657,
  1088  					},
  1089  				},
  1090  				UpdateMask: nil,
  1091  			},
  1092  			want: &examplepb.ABitOfEverything{
  1093  				StringValue: "some updated value because the fieldMask is nil",
  1094  				SingleNested: &examplepb.ABitOfEverything_Nested{
  1095  					Amount: 657,
  1096  				},
  1097  			},
  1098  		},
  1099  	} {
  1100  		t.Run(tc.name, func(t *testing.T) {
  1101  			originalABE := tc.originalValue
  1102  			uuid := postABE(t, port, originalABE)
  1103  
  1104  			patchBody := tc.input
  1105  			patchReq, err := http.NewRequest(
  1106  				http.MethodPatch,
  1107  				fmt.Sprintf("http://localhost:%d/v2a/example/a_bit_of_everything/%s", port, uuid),
  1108  				strings.NewReader(mustMarshal(t, patchBody)),
  1109  			)
  1110  			if err != nil {
  1111  				t.Fatalf("http.NewRequest(PATCH) failed with %v; want success", err)
  1112  			}
  1113  			patchResp, err := http.DefaultClient.Do(patchReq)
  1114  			if err != nil {
  1115  				t.Fatalf("failed to issue PATCH request: %v", err)
  1116  			}
  1117  			if got, want := patchResp.StatusCode, http.StatusOK; got != want {
  1118  				if body, err := io.ReadAll(patchResp.Body); err != nil {
  1119  					t.Errorf("patchResp body couldn't be read: %v", err)
  1120  				} else {
  1121  					t.Errorf("patchResp.StatusCode= %d; want %d resp: %v", got, want, string(body))
  1122  				}
  1123  			}
  1124  
  1125  			want, got := tc.want, getABE(t, port, uuid)
  1126  			got.Uuid = "" // empty out uuid so we don't need to worry about it in comparisons
  1127  			if diff := cmp.Diff(got, want, protocmp.Transform()); diff != "" {
  1128  				t.Errorf(diff)
  1129  			}
  1130  		})
  1131  	}
  1132  }
  1133  
  1134  // mustMarshal marshals the given object into a json string, calling t.Fatal if an error occurs. Useful in testing to
  1135  // inline marshalling whenever you don't expect the marshalling to return an error
  1136  func mustMarshal(t *testing.T, i interface{}) string {
  1137  	b, err := marshaler.Marshal(i)
  1138  	if err != nil {
  1139  		t.Fatalf("failed to marshal %#v: %v", i, err)
  1140  	}
  1141  
  1142  	return string(b)
  1143  }
  1144  
  1145  // postABE conveniently creates a new ABE record for ease in testing
  1146  func postABE(t *testing.T, port int, abe *examplepb.ABitOfEverything) (uuid string) {
  1147  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything", port)
  1148  	postResp, err := http.Post(apiURL, "application/json", strings.NewReader(mustMarshal(t, abe)))
  1149  	if err != nil {
  1150  		t.Fatalf("http.Post(%q) failed with %v; want success", apiURL, err)
  1151  		return
  1152  	}
  1153  	body, err := io.ReadAll(postResp.Body)
  1154  	if err != nil {
  1155  		t.Fatalf("postResp body couldn't be read: %v", err)
  1156  	}
  1157  	var f struct {
  1158  		UUID string `json:"uuid"`
  1159  	}
  1160  	if err := marshaler.Unmarshal(body, &f); err != nil {
  1161  		t.Fatalf("postResp body couldn't be unmarshalled: %v. body: %s", err, string(body))
  1162  	}
  1163  	if f.UUID == "" {
  1164  		t.Fatalf("want uuid from postResp, but got none. body: %s", string(body))
  1165  	}
  1166  	return f.UUID
  1167  }
  1168  
  1169  // getABE conveniently fetches an ABE record for ease in testing
  1170  func getABE(t *testing.T, port int, uuid string) *examplepb.ABitOfEverything {
  1171  	gURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/%s", port, uuid)
  1172  	getResp, err := http.Get(gURL)
  1173  	if err != nil {
  1174  		t.Fatalf("http.Get(%s) failed with %v; want success", gURL, err)
  1175  	}
  1176  	defer getResp.Body.Close()
  1177  
  1178  	if got, want := getResp.StatusCode, http.StatusOK; got != want {
  1179  		t.Fatalf("getResp.StatusCode= %d, want %d. resp: %v", got, want, getResp)
  1180  	}
  1181  	var getRestatuspbody examplepb.ABitOfEverything
  1182  	body, err := io.ReadAll(getResp.Body)
  1183  	if err != nil {
  1184  		t.Fatalf("getResp body couldn't be read: %v", err)
  1185  	}
  1186  	if err := marshaler.Unmarshal(body, &getRestatuspbody); err != nil {
  1187  		t.Fatalf("getResp body couldn't be unmarshalled: %v body: %s", err, string(body))
  1188  	}
  1189  
  1190  	return &getRestatuspbody
  1191  }
  1192  
  1193  func testABELookupNotFound(t *testing.T, port int, useTrailers bool) {
  1194  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything", port)
  1195  	uuid := "not_exist"
  1196  	apiURL = fmt.Sprintf("%s/%s", apiURL, uuid)
  1197  
  1198  	req, err := http.NewRequest("GET", apiURL, nil)
  1199  	if err != nil {
  1200  		t.Errorf("http.NewRequest() failed with %v; want success", err)
  1201  		return
  1202  	}
  1203  
  1204  	if useTrailers {
  1205  		req.Header.Set("TE", "trailers")
  1206  	}
  1207  
  1208  	resp, err := http.DefaultClient.Do(req)
  1209  	if err != nil {
  1210  		t.Errorf("client.Do(%v) failed with %v; want success", req, err)
  1211  		return
  1212  	}
  1213  	defer resp.Body.Close()
  1214  
  1215  	buf, err := io.ReadAll(resp.Body)
  1216  	if err != nil {
  1217  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
  1218  		return
  1219  	}
  1220  
  1221  	if got, want := resp.StatusCode, http.StatusNotFound; got != want {
  1222  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1223  		t.Logf("%s", buf)
  1224  		return
  1225  	}
  1226  
  1227  	msg := new(statuspb.Status)
  1228  	if err := marshaler.Unmarshal(buf, msg); err != nil {
  1229  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
  1230  		return
  1231  	}
  1232  
  1233  	if got, want := msg.Code, int32(codes.NotFound); got != want {
  1234  		t.Errorf("msg.Code = %d; want %d", got, want)
  1235  		return
  1236  	}
  1237  
  1238  	if got, want := msg.Message, "not found"; got != want {
  1239  		t.Errorf("msg.Message = %s; want %s", got, want)
  1240  		return
  1241  	}
  1242  
  1243  	if got, want := resp.Header.Get("Grpc-Metadata-Uuid"), uuid; got != want {
  1244  		t.Errorf("Grpc-Metadata-Uuid was %s, wanted %s", got, want)
  1245  	}
  1246  
  1247  	trailers := map[bool]map[string]string{
  1248  		true: {
  1249  			"Grpc-Trailer-Foo": "foo2",
  1250  			"Grpc-Trailer-Bar": "bar2",
  1251  		},
  1252  		false: {
  1253  			"Grpc-Trailer-Foo": "",
  1254  			"Grpc-Trailer-Bar": "",
  1255  		},
  1256  	}
  1257  
  1258  	for trailer, want := range trailers[useTrailers] {
  1259  		if got := resp.Trailer.Get(trailer); got != want {
  1260  			t.Errorf("%s was %q, wanted %q", trailer, got, want)
  1261  		}
  1262  	}
  1263  }
  1264  
  1265  func testABEList(t *testing.T, port int) {
  1266  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything", port)
  1267  	resp, err := http.Get(apiURL)
  1268  	if err != nil {
  1269  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
  1270  		return
  1271  	}
  1272  	defer resp.Body.Close()
  1273  
  1274  	dec := marshaler.NewDecoder(resp.Body)
  1275  	var i int
  1276  	for i = 0; ; i++ {
  1277  		var item struct {
  1278  			Result json.RawMessage        `json:"result"`
  1279  			Error  map[string]interface{} `json:"error"`
  1280  		}
  1281  		err := dec.Decode(&item)
  1282  		if err == io.EOF {
  1283  			break
  1284  		}
  1285  		if err != nil {
  1286  			t.Errorf("dec.Decode(&item) failed with %v; want success; i = %d", err, i)
  1287  		}
  1288  		if len(item.Error) != 0 {
  1289  			t.Errorf("item.Error = %#v; want empty; i = %d", item.Error, i)
  1290  			continue
  1291  		}
  1292  		msg := new(examplepb.ABitOfEverything)
  1293  		if err := marshaler.Unmarshal(item.Result, msg); err != nil {
  1294  			t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", item.Result, err)
  1295  		}
  1296  	}
  1297  	if i <= 0 {
  1298  		t.Errorf("i == %d; want > 0", i)
  1299  	}
  1300  
  1301  	value := resp.Header.Get("Grpc-Metadata-Count")
  1302  	if value == "" {
  1303  		t.Errorf("Grpc-Metadata-Count should not be empty")
  1304  	}
  1305  
  1306  	count, err := strconv.Atoi(value)
  1307  	if err != nil {
  1308  		t.Errorf("failed to Atoi %q: %v", value, err)
  1309  	}
  1310  
  1311  	if count <= 0 {
  1312  		t.Errorf("count == %d; want > 0", count)
  1313  	}
  1314  }
  1315  
  1316  func testABEDownload(t *testing.T, port int) {
  1317  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/download", port)
  1318  	resp, err := http.Get(apiURL)
  1319  	if err != nil {
  1320  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
  1321  		return
  1322  	}
  1323  	defer resp.Body.Close()
  1324  
  1325  	wantHeader := "text/html"
  1326  	if value := resp.Header.Get("Content-Type"); value != wantHeader {
  1327  		t.Fatalf("testABEDownload() Content-Type failed: got %s, want %s", value, wantHeader)
  1328  	}
  1329  
  1330  	body, err := readAll(resp.Body)
  1331  	if err != nil {
  1332  		t.Fatalf("readAll(resp.Body) failed with %v; want success", err)
  1333  	}
  1334  
  1335  	want := []string{"Hello 1", "Hello 2"}
  1336  	if !reflect.DeepEqual(body, want) {
  1337  		t.Errorf("testABEDownload() failed: got %v, want %v", body, want)
  1338  	}
  1339  }
  1340  
  1341  func testABEBulkEcho(t *testing.T, port int) {
  1342  	reqr, reqw := io.Pipe()
  1343  	var wg sync.WaitGroup
  1344  	var want []*sub.StringMessage
  1345  	wg.Add(1)
  1346  	go func() {
  1347  		defer wg.Done()
  1348  		defer reqw.Close()
  1349  		for i := 0; i < 10; i++ {
  1350  			s := fmt.Sprintf("message %d", i)
  1351  			msg := &sub.StringMessage{Value: &s}
  1352  			buf, err := marshaler.Marshal(msg)
  1353  			if err != nil {
  1354  				t.Errorf("marshaler.Marshal(%v) failed with %v; want success", msg, err)
  1355  				return
  1356  			}
  1357  			if _, err = reqw.Write(buf); err != nil {
  1358  				t.Errorf("reqw.Write(%q) failed with %v; want success", string(buf), err)
  1359  				return
  1360  			}
  1361  			want = append(want, msg)
  1362  		}
  1363  	}()
  1364  
  1365  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/echo", port)
  1366  	req, err := http.NewRequest("POST", apiURL, reqr)
  1367  	if err != nil {
  1368  		t.Errorf("http.NewRequest(%q, %q, reqr) failed with %v; want success", "POST", apiURL, err)
  1369  		return
  1370  	}
  1371  	req.Header.Set("Content-Type", "application/json")
  1372  	req.Header.Set("Transfer-Encoding", "chunked")
  1373  	resp, err := http.DefaultClient.Do(req)
  1374  	if err != nil {
  1375  		t.Errorf("http.Post(%q, %q, req) failed with %v; want success", apiURL, "application/json", err)
  1376  		return
  1377  	}
  1378  	defer resp.Body.Close()
  1379  	if got, want := resp.StatusCode, http.StatusOK; got != want {
  1380  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1381  	}
  1382  
  1383  	var got []*sub.StringMessage
  1384  	wg.Add(1)
  1385  	go func() {
  1386  		defer wg.Done()
  1387  
  1388  		dec := marshaler.NewDecoder(resp.Body)
  1389  		for i := 0; ; i++ {
  1390  			var item struct {
  1391  				Result json.RawMessage        `json:"result"`
  1392  				Error  map[string]interface{} `json:"error"`
  1393  			}
  1394  			err := dec.Decode(&item)
  1395  			if err == io.EOF {
  1396  				break
  1397  			}
  1398  			if err != nil {
  1399  				t.Errorf("dec.Decode(&item) failed with %v; want success; i = %d", err, i)
  1400  			}
  1401  			if len(item.Error) != 0 {
  1402  				t.Errorf("item.Error = %#v; want empty; i = %d", item.Error, i)
  1403  				continue
  1404  			}
  1405  			msg := new(sub.StringMessage)
  1406  			if err := marshaler.Unmarshal(item.Result, msg); err != nil {
  1407  				t.Errorf("marshaler.Unmarshal(%q, msg) failed with %v; want success", item.Result, err)
  1408  			}
  1409  			got = append(got, msg)
  1410  		}
  1411  	}()
  1412  
  1413  	wg.Wait()
  1414  	if diff := cmp.Diff(got, want, protocmp.Transform()); diff != "" {
  1415  		t.Errorf(diff)
  1416  	}
  1417  }
  1418  
  1419  func testABEBulkEchoZeroLength(t *testing.T, port int) {
  1420  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/echo", port)
  1421  	req, err := http.NewRequest("POST", apiURL, bytes.NewReader(nil))
  1422  	if err != nil {
  1423  		t.Errorf("http.NewRequest(%q, %q, bytes.NewReader(nil)) failed with %v; want success", "POST", apiURL, err)
  1424  		return
  1425  	}
  1426  	req.Header.Set("Content-Type", "application/json")
  1427  	req.Header.Set("Transfer-Encoding", "chunked")
  1428  	resp, err := http.DefaultClient.Do(req)
  1429  	if err != nil {
  1430  		t.Errorf("http.Post(%q, %q, req) failed with %v; want success", apiURL, "application/json", err)
  1431  		return
  1432  	}
  1433  	defer resp.Body.Close()
  1434  	if got, want := resp.StatusCode, http.StatusOK; got != want {
  1435  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1436  	}
  1437  
  1438  	dec := marshaler.NewDecoder(resp.Body)
  1439  	var item struct {
  1440  		Result json.RawMessage        `json:"result"`
  1441  		Error  map[string]interface{} `json:"error"`
  1442  	}
  1443  	if err := dec.Decode(&item); err == nil {
  1444  		t.Errorf("dec.Decode(&item) succeeded; want io.EOF; item = %#v", item)
  1445  	} else if err != io.EOF {
  1446  		t.Errorf("dec.Decode(&item) failed with %v; want success", err)
  1447  		return
  1448  	}
  1449  }
  1450  
  1451  func testAdditionalBindings(t *testing.T, port int) {
  1452  	for i, f := range []func() *http.Response{
  1453  		func() *http.Response {
  1454  			apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/echo/hello", port)
  1455  			resp, err := http.Get(apiURL)
  1456  			if err != nil {
  1457  				t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
  1458  				return nil
  1459  			}
  1460  			return resp
  1461  		},
  1462  		func() *http.Response {
  1463  			apiURL := fmt.Sprintf("http://localhost:%d/v2/example/echo", port)
  1464  			resp, err := http.Post(apiURL, "application/json", strings.NewReader(`"hello"`))
  1465  			if err != nil {
  1466  				t.Errorf("http.Post(%q, %q, %q) failed with %v; want success", apiURL, "application/json", `"hello"`, err)
  1467  				return nil
  1468  			}
  1469  			return resp
  1470  		},
  1471  		func() *http.Response {
  1472  			r, w := io.Pipe()
  1473  			go func() {
  1474  				defer w.Close()
  1475  				w.Write([]byte(`"hello"`))
  1476  			}()
  1477  			apiURL := fmt.Sprintf("http://localhost:%d/v2/example/echo", port)
  1478  			resp, err := http.Post(apiURL, "application/json", r)
  1479  			if err != nil {
  1480  				t.Errorf("http.Post(%q, %q, %q) failed with %v; want success", apiURL, "application/json", `"hello"`, err)
  1481  				return nil
  1482  			}
  1483  			return resp
  1484  		},
  1485  		func() *http.Response {
  1486  			apiURL := fmt.Sprintf("http://localhost:%d/v2/example/echo?value=hello", port)
  1487  			resp, err := http.Get(apiURL)
  1488  			if err != nil {
  1489  				t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
  1490  				return nil
  1491  			}
  1492  			return resp
  1493  		},
  1494  	} {
  1495  		resp := f()
  1496  		if resp == nil {
  1497  			continue
  1498  		}
  1499  
  1500  		defer resp.Body.Close()
  1501  		buf, err := io.ReadAll(resp.Body)
  1502  		if err != nil {
  1503  			t.Errorf("io.ReadAll(resp.Body) failed with %v; want success; i=%d", err, i)
  1504  			return
  1505  		}
  1506  		if got, want := resp.StatusCode, http.StatusOK; got != want {
  1507  			t.Errorf("resp.StatusCode = %d; want %d; i=%d", got, want, i)
  1508  			t.Logf("%s", buf)
  1509  		}
  1510  
  1511  		msg := new(sub.StringMessage)
  1512  		if err := marshaler.Unmarshal(buf, msg); err != nil {
  1513  			t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success; %d", buf, err, i)
  1514  			return
  1515  		}
  1516  		if got, want := msg.GetValue(), "hello"; got != want {
  1517  			t.Errorf("msg.GetValue() = %q; want %q", got, want)
  1518  		}
  1519  	}
  1520  }
  1521  
  1522  func testABERepeated(t *testing.T, port int) {
  1523  	f := func(v reflect.Value) string {
  1524  		var f func(v reflect.Value, idx int) string
  1525  		s := make([]string, v.Len())
  1526  		switch v.Index(0).Kind() {
  1527  		case reflect.Slice:
  1528  			f = func(v reflect.Value, idx int) string {
  1529  				t := v.Index(idx).Type().Elem().Kind()
  1530  				if t == reflect.Uint8 {
  1531  					return base64.URLEncoding.EncodeToString(v.Index(idx).Interface().([]byte))
  1532  				}
  1533  				// Could handle more elegantly
  1534  				panic("unknown slice of type: " + t.String())
  1535  			}
  1536  		default:
  1537  			f = func(v reflect.Value, idx int) string {
  1538  				return fmt.Sprintf("%v", v.Index(idx).Interface())
  1539  			}
  1540  		}
  1541  		for i := 0; i < v.Len(); i++ {
  1542  			s[i] = f(v, i)
  1543  		}
  1544  		return strings.Join(s, ",")
  1545  	}
  1546  	want := &examplepb.ABitOfEverythingRepeated{
  1547  		PathRepeatedFloatValue: []float32{
  1548  			1.5,
  1549  			-1.5,
  1550  		},
  1551  		PathRepeatedDoubleValue: []float64{
  1552  			2.5,
  1553  			-2.5,
  1554  		},
  1555  		PathRepeatedInt64Value: []int64{
  1556  			4294967296,
  1557  			-4294967296,
  1558  		},
  1559  		PathRepeatedUint64Value: []uint64{
  1560  			0,
  1561  			9223372036854775807,
  1562  		},
  1563  		PathRepeatedInt32Value: []int32{
  1564  			2147483647,
  1565  			-2147483648,
  1566  		},
  1567  		PathRepeatedFixed64Value: []uint64{
  1568  			0,
  1569  			9223372036854775807,
  1570  		},
  1571  		PathRepeatedFixed32Value: []uint32{
  1572  			0,
  1573  			4294967295,
  1574  		},
  1575  		PathRepeatedBoolValue: []bool{
  1576  			true,
  1577  			false,
  1578  		},
  1579  		PathRepeatedStringValue: []string{
  1580  			"foo",
  1581  			"bar",
  1582  		},
  1583  		PathRepeatedBytesValue: [][]byte{
  1584  			{0x00},
  1585  			{0xFF},
  1586  		},
  1587  		PathRepeatedUint32Value: []uint32{
  1588  			0,
  1589  			4294967295,
  1590  		},
  1591  		PathRepeatedEnumValue: []examplepb.NumericEnum{
  1592  			examplepb.NumericEnum_ZERO,
  1593  			examplepb.NumericEnum_ONE,
  1594  		},
  1595  		PathRepeatedSfixed32Value: []int32{
  1596  			2147483647,
  1597  			-2147483648,
  1598  		},
  1599  		PathRepeatedSfixed64Value: []int64{
  1600  			4294967296,
  1601  			-4294967296,
  1602  		},
  1603  		PathRepeatedSint32Value: []int32{
  1604  			2147483647,
  1605  			-2147483648,
  1606  		},
  1607  		PathRepeatedSint64Value: []int64{
  1608  			4611686018427387903,
  1609  			-4611686018427387904,
  1610  		},
  1611  	}
  1612  	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)))
  1613  
  1614  	resp, err := http.Get(apiURL)
  1615  	if err != nil {
  1616  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
  1617  		return
  1618  	}
  1619  	defer resp.Body.Close()
  1620  	buf, err := io.ReadAll(resp.Body)
  1621  	if err != nil {
  1622  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
  1623  		return
  1624  	}
  1625  
  1626  	if got, want := resp.StatusCode, http.StatusOK; got != want {
  1627  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1628  		t.Logf("%s", buf)
  1629  	}
  1630  
  1631  	msg := new(examplepb.ABitOfEverythingRepeated)
  1632  	if err := marshaler.Unmarshal(buf, msg); err != nil {
  1633  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
  1634  		return
  1635  	}
  1636  	if diff := cmp.Diff(msg, want, protocmp.Transform()); diff != "" {
  1637  		t.Errorf(diff)
  1638  	}
  1639  }
  1640  
  1641  func TestTimeout(t *testing.T) {
  1642  	if testing.Short() {
  1643  		t.Skip()
  1644  		return
  1645  	}
  1646  
  1647  	apiURL := "http://localhost:8088/v2/example/timeout"
  1648  	req, err := http.NewRequest("GET", apiURL, nil)
  1649  	if err != nil {
  1650  		t.Errorf(`http.NewRequest("GET", %q, nil) failed with %v; want success`, apiURL, err)
  1651  		return
  1652  	}
  1653  	req.Header.Set("Grpc-Timeout", "10m")
  1654  	resp, err := http.DefaultClient.Do(req)
  1655  	if err != nil {
  1656  		t.Errorf("http.DefaultClient.Do(%#v) failed with %v; want success", req, err)
  1657  		return
  1658  	}
  1659  	defer resp.Body.Close()
  1660  
  1661  	if got, want := resp.StatusCode, http.StatusGatewayTimeout; got != want {
  1662  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1663  	}
  1664  }
  1665  
  1666  func TestInvalidTimeout(t *testing.T) {
  1667  	if testing.Short() {
  1668  		t.Skip()
  1669  		return
  1670  	}
  1671  
  1672  	apiURL := "http://localhost:8088/v2/example/timeout"
  1673  	req, err := http.NewRequest("GET", apiURL, nil)
  1674  	if err != nil {
  1675  		t.Errorf(`http.NewRequest("GET", %q, nil) failed with %v; want success`, apiURL, err)
  1676  		return
  1677  	}
  1678  	req.Header.Set("Grpc-Timeout", "INVALID")
  1679  	resp, err := http.DefaultClient.Do(req)
  1680  	if err != nil {
  1681  		t.Errorf("http.DefaultClient.Do(%#v) failed with %v; want success", req, err)
  1682  		return
  1683  	}
  1684  	defer resp.Body.Close()
  1685  
  1686  	if got, want := resp.StatusCode, http.StatusBadRequest; got != want {
  1687  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1688  	}
  1689  }
  1690  
  1691  func TestPostWithEmptyBody(t *testing.T) {
  1692  	if testing.Short() {
  1693  		t.Skip()
  1694  		return
  1695  	}
  1696  
  1697  	apiURL := "http://localhost:8088/v2/example/postwithemptybody/name"
  1698  	rep, err := http.Post(apiURL, "application/json", nil)
  1699  	if err != nil {
  1700  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
  1701  		return
  1702  	}
  1703  
  1704  	if rep.StatusCode != http.StatusOK {
  1705  		t.Errorf("http.Post(%q) response code is %d; want %d", apiURL,
  1706  			rep.StatusCode, http.StatusOK)
  1707  		return
  1708  	}
  1709  }
  1710  
  1711  func TestUnknownPath(t *testing.T) {
  1712  	if testing.Short() {
  1713  		t.Skip()
  1714  		return
  1715  	}
  1716  
  1717  	apiURL := "http://localhost:8088"
  1718  	resp, err := http.Post(apiURL, "application/json", strings.NewReader("{}"))
  1719  	if err != nil {
  1720  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
  1721  		return
  1722  	}
  1723  	defer resp.Body.Close()
  1724  	buf, err := io.ReadAll(resp.Body)
  1725  	if err != nil {
  1726  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
  1727  		return
  1728  	}
  1729  
  1730  	if got, want := resp.StatusCode, http.StatusNotFound; got != want {
  1731  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1732  		t.Logf("%s", buf)
  1733  	}
  1734  }
  1735  
  1736  func TestNotImplemented(t *testing.T) {
  1737  	if testing.Short() {
  1738  		t.Skip()
  1739  		return
  1740  	}
  1741  
  1742  	apiURL := "http://localhost:8088/v1/example/echo/myid"
  1743  	resp, err := http.Get(apiURL)
  1744  	if err != nil {
  1745  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
  1746  		return
  1747  	}
  1748  	defer resp.Body.Close()
  1749  	buf, err := io.ReadAll(resp.Body)
  1750  	if err != nil {
  1751  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
  1752  		return
  1753  	}
  1754  	if got, want := resp.StatusCode, http.StatusNotImplemented; got != want {
  1755  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1756  		t.Logf("%s", buf)
  1757  	}
  1758  }
  1759  
  1760  func TestInvalidArgument(t *testing.T) {
  1761  	if testing.Short() {
  1762  		t.Skip()
  1763  		return
  1764  	}
  1765  
  1766  	apiURL := "http://localhost:8088/v1/example/echo/myid/not_int64"
  1767  	resp, err := http.Get(apiURL)
  1768  	if err != nil {
  1769  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
  1770  		return
  1771  	}
  1772  	defer resp.Body.Close()
  1773  	buf, err := io.ReadAll(resp.Body)
  1774  	if err != nil {
  1775  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
  1776  		return
  1777  	}
  1778  
  1779  	if got, want := resp.StatusCode, http.StatusBadRequest; got != want {
  1780  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1781  		t.Logf("%s", buf)
  1782  	}
  1783  }
  1784  
  1785  func TestResponseBody(t *testing.T) {
  1786  	if testing.Short() {
  1787  		t.Skip()
  1788  		return
  1789  	}
  1790  
  1791  	testResponseBody(t, 8088)
  1792  	testResponseBodies(t, 8088)
  1793  	testResponseStrings(t, 8088)
  1794  }
  1795  
  1796  func testResponseBody(t *testing.T, port int) {
  1797  	apiURL := fmt.Sprintf("http://localhost:%d/responsebody/foo", port)
  1798  	resp, err := http.Get(apiURL)
  1799  	if err != nil {
  1800  		t.Fatalf("http.Get(%q) failed with %v; want success", apiURL, err)
  1801  	}
  1802  
  1803  	defer resp.Body.Close()
  1804  	buf, err := io.ReadAll(resp.Body)
  1805  	if err != nil {
  1806  		t.Fatalf("io.ReadAll(resp.Body) failed with %v; want success", err)
  1807  	}
  1808  
  1809  	if got, want := resp.StatusCode, http.StatusOK; got != want {
  1810  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1811  		t.Logf("%s", buf)
  1812  	}
  1813  
  1814  	if diff := cmp.Diff(string(buf), `{"data":"foo"}`); diff != "" {
  1815  		t.Errorf(diff)
  1816  	}
  1817  }
  1818  
  1819  func TestResponseBodyStream(t *testing.T) {
  1820  	apiURL := "http://localhost:8088/responsebody/stream/foo"
  1821  	resp, err := http.Get(apiURL)
  1822  	if err != nil {
  1823  		t.Fatalf("http.Get(%q) failed with %v; want success", apiURL, err)
  1824  	}
  1825  
  1826  	defer resp.Body.Close()
  1827  	body, err := readAll(resp.Body)
  1828  	if err != nil {
  1829  		t.Fatalf("readAll(resp.Body) failed with %v; want success", err)
  1830  	}
  1831  
  1832  	if got, want := resp.StatusCode, http.StatusOK; got != want {
  1833  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1834  	}
  1835  
  1836  	if diff := cmp.Diff(body, []string{`{"result":{"data":"first foo"}}`, `{"result":{"data":"second foo"}}`}); diff != "" {
  1837  		t.Errorf(diff)
  1838  	}
  1839  }
  1840  
  1841  func TestResponseBodyStreamHttpBody(t *testing.T) {
  1842  	apiURL := "http://localhost:8088/v1/example/download"
  1843  	resp, err := http.Get(apiURL)
  1844  	if err != nil {
  1845  		t.Fatalf("http.Get(%q) failed with %v; want success", apiURL, err)
  1846  	}
  1847  
  1848  	defer resp.Body.Close()
  1849  	body, err := readAll(resp.Body)
  1850  	if err != nil {
  1851  		t.Fatalf("readAll(resp.Body) failed with %v; want success", err)
  1852  	}
  1853  
  1854  	if got, want := resp.StatusCode, http.StatusOK; got != want {
  1855  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1856  	}
  1857  
  1858  	if diff := cmp.Diff(body, []string{"Hello 1", "Hello 2"}); diff != "" {
  1859  		t.Errorf(diff)
  1860  	}
  1861  }
  1862  
  1863  func TestResponseBodyStreamHttpBodyError(t *testing.T) {
  1864  	apiURL := "http://localhost:8088/v1/example/download?error=true"
  1865  	resp, err := http.Get(apiURL)
  1866  	if err != nil {
  1867  		t.Fatalf("http.Get(%q) failed with %v; want success", apiURL, err)
  1868  	}
  1869  
  1870  	defer resp.Body.Close()
  1871  	body, err := readAll(resp.Body)
  1872  	if err != nil {
  1873  		t.Fatalf("readAll(resp.Body) failed with %v; want success", err)
  1874  	}
  1875  
  1876  	if got, want := resp.StatusCode, http.StatusOK; got != want {
  1877  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1878  	}
  1879  
  1880  	if diff := cmp.Diff(body, []string{"Hello 1", "Hello 2", `{"error":{"code":3,"message":"error","details":[]}}`}); diff != "" {
  1881  		t.Errorf(diff)
  1882  	}
  1883  }
  1884  
  1885  func readAll(body io.ReadCloser) ([]string, error) {
  1886  	var b []string
  1887  	reader := bufio.NewReader(body)
  1888  	for {
  1889  		l, err := reader.ReadBytes('\n')
  1890  		switch {
  1891  		case err == io.EOF:
  1892  			return b, nil
  1893  		case err != nil:
  1894  			return nil, err
  1895  		}
  1896  
  1897  		b = append(b, string(bytes.TrimSpace(l)))
  1898  	}
  1899  }
  1900  
  1901  func testResponseBodies(t *testing.T, port int) {
  1902  	apiURL := fmt.Sprintf("http://localhost:%d/responsebodies/foo", port)
  1903  	resp, err := http.Get(apiURL)
  1904  	if err != nil {
  1905  		t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
  1906  		return
  1907  	}
  1908  	defer resp.Body.Close()
  1909  	buf, err := io.ReadAll(resp.Body)
  1910  	if err != nil {
  1911  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
  1912  		return
  1913  	}
  1914  
  1915  	if got, want := resp.StatusCode, http.StatusOK; got != want {
  1916  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1917  		t.Logf("%s", buf)
  1918  	}
  1919  
  1920  	var got []*examplepb.RepeatedResponseBodyOut_Response
  1921  	err = marshaler.Unmarshal(buf, &got)
  1922  	if err != nil {
  1923  		t.Errorf("marshaler.Unmarshal failed with %v; want success", err)
  1924  		return
  1925  	}
  1926  	want := []*examplepb.RepeatedResponseBodyOut_Response{
  1927  		{
  1928  			Data: "foo",
  1929  			Type: examplepb.RepeatedResponseBodyOut_Response_UNKNOWN,
  1930  		},
  1931  	}
  1932  	if diff := cmp.Diff(got, want, protocmp.Transform()); diff != "" {
  1933  		t.Errorf(diff)
  1934  	}
  1935  }
  1936  
  1937  func testResponseStrings(t *testing.T, port int) {
  1938  	ctx, cancel := context.WithCancel(context.Background())
  1939  	defer cancel()
  1940  
  1941  	port = 8087
  1942  	// Run Secondary server with different marshalling
  1943  	ch := make(chan error)
  1944  	go func() {
  1945  		err := runGateway(
  1946  			ctx,
  1947  			fmt.Sprintf(":%d", port),
  1948  		)
  1949  		if err != nil {
  1950  			ch <- fmt.Errorf("cannot run gateway service: %v", err)
  1951  		}
  1952  	}()
  1953  
  1954  	if err := waitForGateway(ctx, uint16(port)); err != nil {
  1955  		t.Fatalf("waitForGateway(ctx, %d) failed with %v; want success", port, err)
  1956  	}
  1957  
  1958  	t.Run("Response strings", func(t *testing.T) {
  1959  		apiURL := fmt.Sprintf("http://localhost:%d/responsestrings/foo", port)
  1960  		resp, err := http.Get(apiURL)
  1961  		if err != nil {
  1962  			t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
  1963  			return
  1964  		}
  1965  		defer resp.Body.Close()
  1966  		buf, err := io.ReadAll(resp.Body)
  1967  		if err != nil {
  1968  			t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
  1969  			return
  1970  		}
  1971  
  1972  		if got, want := resp.StatusCode, http.StatusOK; got != want {
  1973  			t.Errorf("resp.StatusCode = %d; want %d", got, want)
  1974  			t.Logf("%s", buf)
  1975  		}
  1976  
  1977  		var got []string
  1978  		err = marshaler.Unmarshal(buf, &got)
  1979  		if err != nil {
  1980  			t.Errorf("marshaler.Unmarshal failed with %v; want success", err)
  1981  			return
  1982  		}
  1983  		want := []string{"hello", "foo"}
  1984  		if diff := cmp.Diff(got, want); diff != "" {
  1985  			t.Errorf(diff)
  1986  		}
  1987  	})
  1988  
  1989  	t.Run("Empty response strings", func(t *testing.T) {
  1990  		apiURL := fmt.Sprintf("http://localhost:%d/responsestrings/empty", port)
  1991  		resp, err := http.Get(apiURL)
  1992  		if err != nil {
  1993  			t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
  1994  			return
  1995  		}
  1996  		defer resp.Body.Close()
  1997  		buf, err := io.ReadAll(resp.Body)
  1998  		if err != nil {
  1999  			t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
  2000  			return
  2001  		}
  2002  
  2003  		if got, want := resp.StatusCode, http.StatusOK; got != want {
  2004  			t.Errorf("resp.StatusCode = %d; want %d", got, want)
  2005  			t.Logf("%s", buf)
  2006  		}
  2007  
  2008  		var got []string
  2009  		err = marshaler.Unmarshal(buf, &got)
  2010  		if err != nil {
  2011  			t.Errorf("marshaler.Unmarshal failed with %v; want success", err)
  2012  			return
  2013  		}
  2014  		want := []string{}
  2015  		if diff := cmp.Diff(got, want); diff != "" {
  2016  			t.Errorf(diff)
  2017  		}
  2018  	})
  2019  
  2020  	t.Run("Response bodies", func(t *testing.T) {
  2021  		apiURL := fmt.Sprintf("http://localhost:%d/responsebodies/foo", port)
  2022  		resp, err := http.Get(apiURL)
  2023  		if err != nil {
  2024  			t.Errorf("http.Get(%q) failed with %v; want success", apiURL, err)
  2025  			return
  2026  		}
  2027  		defer resp.Body.Close()
  2028  		buf, err := io.ReadAll(resp.Body)
  2029  		if err != nil {
  2030  			t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
  2031  			return
  2032  		}
  2033  
  2034  		if got, want := resp.StatusCode, http.StatusOK; got != want {
  2035  			t.Errorf("resp.StatusCode = %d; want %d", got, want)
  2036  			t.Logf("%s", buf)
  2037  		}
  2038  
  2039  		var got []*examplepb.RepeatedResponseBodyOut_Response
  2040  		err = marshaler.Unmarshal(buf, &got)
  2041  		if err != nil {
  2042  			t.Errorf("marshaler.Unmarshal failed with %v; want success", err)
  2043  			return
  2044  		}
  2045  		want := []*examplepb.RepeatedResponseBodyOut_Response{
  2046  			{
  2047  				Data: "foo",
  2048  				Type: examplepb.RepeatedResponseBodyOut_Response_UNKNOWN,
  2049  			},
  2050  		}
  2051  		if diff := cmp.Diff(got, want, protocmp.Transform()); diff != "" {
  2052  			t.Errorf(diff)
  2053  		}
  2054  	})
  2055  }
  2056  
  2057  func TestRequestQueryParams(t *testing.T) {
  2058  	testRequestQueryParams(t, 8088)
  2059  }
  2060  
  2061  func TestRequestQueryParamsInProcessGateway(t *testing.T) {
  2062  	testRequestQueryParams(t, 8089)
  2063  }
  2064  
  2065  func testRequestQueryParams(t *testing.T, port int) {
  2066  	if testing.Short() {
  2067  		t.Skip()
  2068  		return
  2069  	}
  2070  
  2071  	formValues := url.Values{}
  2072  	formValues.Set("string_value", "hello-world")
  2073  	formValues.Add("repeated_string_value", "demo1")
  2074  	formValues.Add("repeated_string_value", "demo2")
  2075  	formValues.Add("optional_string_value", "optional-val")
  2076  	mappedStringValueStr := fmt.Sprintf("mapped_string_value[%v]=%v", "map_key", "map_value")
  2077  
  2078  	testCases := []struct {
  2079  		name           string
  2080  		httpMethod     string
  2081  		contentType    string
  2082  		apiURL         string
  2083  		wantContent    *examplepb.ABitOfEverything
  2084  		requestContent io.Reader
  2085  	}{
  2086  		{
  2087  			name:        "get url query values",
  2088  			httpMethod:  "GET",
  2089  			contentType: "application/json",
  2090  			apiURL:      fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/params/get/foo?double_value=%v&bool_value=%v&%v", port, 1234.56, true, mappedStringValueStr),
  2091  			wantContent: &examplepb.ABitOfEverything{
  2092  				SingleNested: &examplepb.ABitOfEverything_Nested{
  2093  					Name: "foo",
  2094  				},
  2095  				DoubleValue: 1234.56,
  2096  				BoolValue:   true,
  2097  				MappedStringValue: map[string]string{
  2098  					"map_key": "map_value",
  2099  				},
  2100  			},
  2101  		},
  2102  		{
  2103  			name:        "get nested enum url parameter",
  2104  			httpMethod:  "GET",
  2105  			contentType: "application/json",
  2106  			// If nested_enum.OK were FALSE, the content of single_nested would be {} due to how 0 values are serialized
  2107  			apiURL: fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/params/get/nested_enum/TRUE", port),
  2108  			wantContent: &examplepb.ABitOfEverything{
  2109  				SingleNested: &examplepb.ABitOfEverything_Nested{
  2110  					Ok: examplepb.ABitOfEverything_Nested_TRUE,
  2111  				},
  2112  			},
  2113  		},
  2114  		{
  2115  			name:        "post url query values",
  2116  			httpMethod:  "POST",
  2117  			contentType: "application/json",
  2118  			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),
  2119  			wantContent: &examplepb.ABitOfEverything{
  2120  				SingleNested: &examplepb.ABitOfEverything_Nested{
  2121  					Name:   "foo",
  2122  					Amount: 100,
  2123  				},
  2124  				DoubleValue: 1234.56,
  2125  				BoolValue:   true,
  2126  				StringValue: "hello-world",
  2127  			},
  2128  			requestContent: strings.NewReader(`{"name":"foo","amount":100}`),
  2129  		},
  2130  		{
  2131  			name:        "post form and url query values",
  2132  			httpMethod:  "POST",
  2133  			contentType: "application/x-www-form-urlencoded",
  2134  			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),
  2135  			wantContent: &examplepb.ABitOfEverything{
  2136  				SingleNested: &examplepb.ABitOfEverything_Nested{
  2137  					Name: "foo",
  2138  				},
  2139  				DoubleValue:         1234.56,
  2140  				BoolValue:           true,
  2141  				StringValue:         "hello-world",
  2142  				RepeatedStringValue: []string{"demo1", "demo2"},
  2143  				OptionalStringValue: func() *string {
  2144  					val := formValues.Get("optional_string_value")
  2145  					return &val
  2146  				}(),
  2147  			},
  2148  			requestContent: strings.NewReader(formValues.Encode()),
  2149  		},
  2150  	}
  2151  
  2152  	for _, tc := range testCases {
  2153  		t.Run(tc.name, func(t *testing.T) {
  2154  			req, err := http.NewRequest(tc.httpMethod, tc.apiURL, tc.requestContent)
  2155  			if err != nil {
  2156  				t.Errorf("http.method (%q) http.url (%q) failed with %v; want success", tc.httpMethod, tc.apiURL, err)
  2157  				return
  2158  			}
  2159  
  2160  			req.Header.Add("Content-Type", tc.contentType)
  2161  
  2162  			resp, err := http.DefaultClient.Do(req)
  2163  			if err != nil {
  2164  				t.Errorf("http.method (%q) http.url (%q) failed with %v; want success", tc.httpMethod, tc.apiURL, err)
  2165  				return
  2166  			}
  2167  			defer resp.Body.Close()
  2168  
  2169  			buf, err := io.ReadAll(resp.Body)
  2170  			if err != nil {
  2171  				t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
  2172  				return
  2173  			}
  2174  
  2175  			if gotCode, wantCode := resp.StatusCode, http.StatusOK; gotCode != wantCode {
  2176  				t.Errorf("resp.StatusCode = %d; want %d", gotCode, wantCode)
  2177  				t.Logf("%s", buf)
  2178  			}
  2179  
  2180  			got := new(examplepb.ABitOfEverything)
  2181  			err = marshaler.Unmarshal(buf, &got)
  2182  			if err != nil {
  2183  				t.Errorf("marshaler.Unmarshal(buf, got) failed with %v; want success", err)
  2184  				return
  2185  			}
  2186  			if diff := cmp.Diff(got, tc.wantContent, protocmp.Transform()); diff != "" {
  2187  				t.Errorf("http.method (%q) http.url (%q)\n%s", tc.httpMethod, tc.apiURL, diff)
  2188  			}
  2189  		})
  2190  	}
  2191  }
  2192  
  2193  func TestNonStandardNames(t *testing.T) {
  2194  	if testing.Short() {
  2195  		t.Skip()
  2196  		return
  2197  	}
  2198  
  2199  	ctx := context.Background()
  2200  	ctx, cancel := context.WithCancel(ctx)
  2201  	defer cancel()
  2202  
  2203  	go func() {
  2204  		marshaler := &runtime.JSONPb{
  2205  			MarshalOptions: protojson.MarshalOptions{
  2206  				UseEnumNumbers:  false,
  2207  				EmitUnpopulated: true,
  2208  				UseProtoNames:   true,
  2209  			},
  2210  		}
  2211  		err := runGateway(
  2212  			ctx,
  2213  			":8081",
  2214  			runtime.WithMarshalerOption(runtime.MIMEWildcard, marshaler),
  2215  		)
  2216  		if err != nil {
  2217  			t.Errorf("runGateway() failed with %v; want success", err)
  2218  			return
  2219  		}
  2220  	}()
  2221  	go func() {
  2222  		err := runGateway(
  2223  			ctx,
  2224  			":8082",
  2225  		)
  2226  		if err != nil {
  2227  			t.Errorf("runGateway() failed with %v; want success", err)
  2228  			return
  2229  		}
  2230  	}()
  2231  
  2232  	if err := waitForGateway(ctx, 8081); err != nil {
  2233  		t.Errorf("waitForGateway(ctx, 8081) failed with %v; want success", err)
  2234  	}
  2235  	if err := waitForGateway(ctx, 8082); err != nil {
  2236  		t.Errorf("waitForGateway(ctx, 8082) failed with %v; want success", err)
  2237  	}
  2238  
  2239  	for _, tc := range []struct {
  2240  		name     string
  2241  		port     int
  2242  		method   string
  2243  		jsonBody string
  2244  		want     proto.Message
  2245  	}{
  2246  		{
  2247  			"Test standard update method",
  2248  			8081,
  2249  			"update",
  2250  			`{
  2251  				"id": "foo",
  2252  				"Num": "1",
  2253  				"line_num": "42",
  2254  				"langIdent": "English",
  2255  				"STATUS": "good",
  2256  				"en_GB": "1",
  2257  				"no": "yes",
  2258  				"thing": {
  2259  					"subThing": {
  2260  						"sub_value": "hi"
  2261  					}
  2262  				}
  2263  			}`,
  2264  			&examplepb.NonStandardMessage{
  2265  				Id:        "foo",
  2266  				Num:       1,
  2267  				LineNum:   42,
  2268  				LangIdent: "English",
  2269  				STATUS:    "good",
  2270  				En_GB:     1,
  2271  				No:        "yes",
  2272  				Thing: &examplepb.NonStandardMessage_Thing{
  2273  					SubThing: &examplepb.NonStandardMessage_Thing_SubThing{
  2274  						SubValue: "hi",
  2275  					},
  2276  				},
  2277  			},
  2278  		},
  2279  		{
  2280  			"Test update method using json_names in message",
  2281  			8081,
  2282  			"update_with_json_names",
  2283  			// N.B. json_names have no effect if not using UseProtoNames: false
  2284  			`{
  2285  				"id": "foo",
  2286  				"Num": "1",
  2287  				"line_num": "42",
  2288  				"langIdent": "English",
  2289  				"STATUS": "good",
  2290  				"en_GB": "1",
  2291  				"no": "yes",
  2292  				"thing": {
  2293  					"subThing": {
  2294  						"sub_value": "hi"
  2295  					}
  2296  				}
  2297  			}`,
  2298  			&examplepb.NonStandardMessageWithJSONNames{
  2299  				Id:        "foo",
  2300  				Num:       1,
  2301  				LineNum:   42,
  2302  				LangIdent: "English",
  2303  				STATUS:    "good",
  2304  				En_GB:     1,
  2305  				No:        "yes",
  2306  				Thing: &examplepb.NonStandardMessageWithJSONNames_Thing{
  2307  					SubThing: &examplepb.NonStandardMessageWithJSONNames_Thing_SubThing{
  2308  						SubValue: "hi",
  2309  					},
  2310  				},
  2311  			},
  2312  		},
  2313  		{
  2314  			"Test standard update method with UseProtoNames: false marshaller option",
  2315  			8082,
  2316  			"update",
  2317  			`{
  2318  				"id": "foo",
  2319  				"Num": "1",
  2320  				"lineNum": "42",
  2321  				"langIdent": "English",
  2322  				"STATUS": "good",
  2323  				"enGB": "1",
  2324  				"no": "yes",
  2325  				"thing": {
  2326  					"subThing": {
  2327  						"subValue": "hi"
  2328  					}
  2329  				}
  2330  			}`,
  2331  			&examplepb.NonStandardMessage{
  2332  				Id:        "foo",
  2333  				Num:       1,
  2334  				LineNum:   42,
  2335  				LangIdent: "English",
  2336  				STATUS:    "good",
  2337  				En_GB:     1,
  2338  				No:        "yes",
  2339  				Thing: &examplepb.NonStandardMessage_Thing{
  2340  					SubThing: &examplepb.NonStandardMessage_Thing_SubThing{
  2341  						SubValue: "hi",
  2342  					},
  2343  				},
  2344  			},
  2345  		},
  2346  		{
  2347  			"Test update method using json_names in message with UseProtoNames: false marshaller option",
  2348  			8082,
  2349  			"update_with_json_names",
  2350  			`{
  2351  				"ID": "foo",
  2352  				"Num": "1",
  2353  				"LineNum": "42",
  2354  				"langIdent": "English",
  2355  				"status": "good",
  2356  				"En_GB": "1",
  2357  				"yes": "yes",
  2358  				"Thingy": {
  2359  					"SubThing": {
  2360  						"sub_Value": "hi"
  2361  					}
  2362  				}
  2363  			}`,
  2364  			&examplepb.NonStandardMessageWithJSONNames{
  2365  				Id:        "foo",
  2366  				Num:       1,
  2367  				LineNum:   42,
  2368  				LangIdent: "English",
  2369  				STATUS:    "good",
  2370  				En_GB:     1,
  2371  				No:        "yes",
  2372  				Thing: &examplepb.NonStandardMessageWithJSONNames_Thing{
  2373  					SubThing: &examplepb.NonStandardMessageWithJSONNames_Thing_SubThing{
  2374  						SubValue: "hi",
  2375  					},
  2376  				},
  2377  			},
  2378  		},
  2379  	} {
  2380  		t.Run(tc.name, func(t *testing.T) {
  2381  			testNonStandardNames(t, tc.port, tc.method, tc.jsonBody, tc.want)
  2382  		})
  2383  	}
  2384  }
  2385  
  2386  func testNonStandardNames(t *testing.T, port int, method string, jsonBody string, want proto.Message) {
  2387  	req, err := http.NewRequest(
  2388  		http.MethodPatch,
  2389  		fmt.Sprintf("http://localhost:%d/v1/example/non_standard/%s", port, method),
  2390  		strings.NewReader(jsonBody),
  2391  	)
  2392  	if err != nil {
  2393  		t.Fatalf("http.NewRequest(PATCH) failed with %v; want success", err)
  2394  	}
  2395  	patchResp, err := http.DefaultClient.Do(req)
  2396  	if err != nil {
  2397  		t.Fatalf("failed to issue PATCH request: %v", err)
  2398  	}
  2399  
  2400  	body, err := io.ReadAll(patchResp.Body)
  2401  	if err != nil {
  2402  		t.Errorf("patchResp body couldn't be read: %v", err)
  2403  	}
  2404  
  2405  	t.Log(string(body))
  2406  
  2407  	if got, want := patchResp.StatusCode, http.StatusOK; got != want {
  2408  		t.Errorf("patchResp.StatusCode= %d; want %d resp: %v", got, want, string(body))
  2409  	}
  2410  
  2411  	got := want.ProtoReflect().New().Interface()
  2412  	err = marshaler.Unmarshal(body, got)
  2413  	if err != nil {
  2414  		t.Fatalf("marshaler.Unmarshal failed: %v", err)
  2415  	}
  2416  	if diff := cmp.Diff(got, want, protocmp.Transform()); diff != "" {
  2417  		t.Errorf(diff)
  2418  	}
  2419  }
  2420  
  2421  func testABEExists(t *testing.T, port int) {
  2422  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything", port)
  2423  	cresp, err := http.Post(apiURL, "application/json", strings.NewReader(`
  2424  		{"bool_value": true, "string_value": "strprefix/example"}
  2425  	`))
  2426  	if err != nil {
  2427  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
  2428  		return
  2429  	}
  2430  	defer cresp.Body.Close()
  2431  	buf, err := io.ReadAll(cresp.Body)
  2432  	if err != nil {
  2433  		t.Errorf("io.ReadAll(cresp.Body) failed with %v; want success", err)
  2434  		return
  2435  	}
  2436  	if got, want := cresp.StatusCode, http.StatusOK; got != want {
  2437  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  2438  		t.Logf("%s", buf)
  2439  		return
  2440  	}
  2441  
  2442  	want := new(examplepb.ABitOfEverything)
  2443  	if err := marshaler.Unmarshal(buf, want); err != nil {
  2444  		t.Errorf("marshaler.Unmarshal(%s, want) failed with %v; want success", buf, err)
  2445  		return
  2446  	}
  2447  
  2448  	apiURL = fmt.Sprintf("%s/%s", apiURL, want.Uuid)
  2449  	resp, err := http.Head(apiURL)
  2450  	if err != nil {
  2451  		t.Errorf("http.Head(%q) failed with %v; want success", apiURL, err)
  2452  		return
  2453  	}
  2454  	defer resp.Body.Close()
  2455  
  2456  	if got, want := resp.StatusCode, http.StatusOK; got != want {
  2457  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  2458  		t.Logf("%s", buf)
  2459  	}
  2460  }
  2461  
  2462  func testABEExistsNotFound(t *testing.T, port int) {
  2463  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything", port)
  2464  	apiURL = fmt.Sprintf("%s/%s", apiURL, "not_exist")
  2465  	resp, err := http.Head(apiURL)
  2466  	if err != nil {
  2467  		t.Errorf("http.Head(%q) failed with %v; want success", apiURL, err)
  2468  		return
  2469  	}
  2470  	defer resp.Body.Close()
  2471  
  2472  	if got, want := resp.StatusCode, http.StatusNotFound; got != want {
  2473  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  2474  		return
  2475  	}
  2476  }
  2477  
  2478  func testABEOptions(t *testing.T, port int) {
  2479  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/test", port)
  2480  	req, err := http.NewRequest(http.MethodOptions, apiURL, strings.NewReader(`
  2481  		{"bool_value": true, "string_value": "strprefix/example"}
  2482  	`))
  2483  	req.Header.Set("Content-Type", "application/json")
  2484  	if err != nil {
  2485  		t.Errorf("http.NewRequest(http.MethodTrace, %q, ...) failed with %v; want success", apiURL, err)
  2486  		return
  2487  	}
  2488  	client := &http.Client{}
  2489  	resp, err := client.Do(req)
  2490  	if err != nil {
  2491  		t.Fatal(err)
  2492  	}
  2493  	defer resp.Body.Close()
  2494  	if got, want := resp.StatusCode, http.StatusOK; got != want {
  2495  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  2496  		return
  2497  	}
  2498  
  2499  	value := resp.Header.Get("Grpc-Metadata-Allow")
  2500  	if value != "OPTIONS, GET, HEAD, POST, PUT, TRACE" {
  2501  		t.Errorf("Grpc-Metadata-Allow does not have the expected HTTP methods")
  2502  		t.Logf("%s", value)
  2503  	}
  2504  }
  2505  
  2506  func testABETrace(t *testing.T, port int) {
  2507  	apiURL := fmt.Sprintf("http://localhost:%d/v1/example/a_bit_of_everything/test", port)
  2508  	req, err := http.NewRequest(http.MethodTrace, apiURL, strings.NewReader(`
  2509  		{"bool_value": true, "string_value": "strprefix/example"}
  2510  	`))
  2511  	req.Header.Set("Content-Type", "application/json")
  2512  	if err != nil {
  2513  		t.Errorf("http.NewRequest(http.MethodTrace, %q, ...) failed with %v; want success", apiURL, err)
  2514  		return
  2515  	}
  2516  	client := &http.Client{}
  2517  	resp, err := client.Do(req)
  2518  	if err != nil {
  2519  		t.Fatal(err)
  2520  	}
  2521  	defer resp.Body.Close()
  2522  	buf, err := io.ReadAll(resp.Body)
  2523  	if err != nil {
  2524  		t.Errorf("io.ReadAll(cresp.Body) failed with %v; want success", err)
  2525  		return
  2526  	}
  2527  	if got, want := resp.StatusCode, http.StatusOK; got != want {
  2528  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  2529  		t.Logf("%s", buf)
  2530  		return
  2531  	}
  2532  
  2533  	want := new(examplepb.ABitOfEverything)
  2534  	if err := marshaler.Unmarshal(buf, want); err != nil {
  2535  		t.Errorf("marshaler.Unmarshal(%s, want) failed with %v; want success", buf, err)
  2536  		return
  2537  	}
  2538  }
  2539  
  2540  func testEchoWithNonASCIIHeaderValues(t *testing.T, port int, apiPrefix string) {
  2541  	apiURL := fmt.Sprintf("http://localhost:%d/%s/example/echo/myid", port, apiPrefix)
  2542  
  2543  	req, err := http.NewRequest("POST", apiURL, strings.NewReader("{}"))
  2544  	if err != nil {
  2545  		t.Errorf("http.NewRequest() = err: %v", err)
  2546  		return
  2547  	}
  2548  	req.Header.Add("Content-Type", "application/json")
  2549  	req.Header.Add("Grpc-Metadata-Location", "Gjøvik")
  2550  	resp, err := http.DefaultClient.Do(req)
  2551  	if err != nil {
  2552  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
  2553  		return
  2554  	}
  2555  	defer resp.Body.Close()
  2556  
  2557  	buf, err := io.ReadAll(resp.Body)
  2558  	if err != nil {
  2559  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
  2560  		return
  2561  	}
  2562  
  2563  	if got, want := resp.StatusCode, http.StatusOK; got != want {
  2564  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  2565  		t.Logf("%s", buf)
  2566  	}
  2567  
  2568  	msg := new(examplepb.UnannotatedSimpleMessage)
  2569  	if err := marshaler.Unmarshal(buf, msg); err != nil {
  2570  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
  2571  		return
  2572  	}
  2573  	if got, want := msg.Id, "myid"; got != want {
  2574  		t.Errorf("msg.Id = %q; want %q", got, want)
  2575  	}
  2576  }
  2577  
  2578  func testEchoWithInvalidHeaderKey(t *testing.T, port int, apiPrefix string) {
  2579  	apiURL := fmt.Sprintf("http://localhost:%d/%s/example/echo/myid", port, apiPrefix)
  2580  
  2581  	req, err := http.NewRequest("POST", apiURL, strings.NewReader("{}"))
  2582  	if err != nil {
  2583  		t.Errorf("http.NewRequest() = err: %v", err)
  2584  		return
  2585  	}
  2586  	req.Header.Add("Content-Type", "application/json")
  2587  	req.Header.Add("Grpc-Metadata-Foo+Bar", "Hello")
  2588  	resp, err := http.DefaultClient.Do(req)
  2589  	if err != nil {
  2590  		t.Errorf("http.Post(%q) failed with %v; want success", apiURL, err)
  2591  		return
  2592  	}
  2593  	defer resp.Body.Close()
  2594  
  2595  	buf, err := io.ReadAll(resp.Body)
  2596  	if err != nil {
  2597  		t.Errorf("io.ReadAll(resp.Body) failed with %v; want success", err)
  2598  		return
  2599  	}
  2600  
  2601  	if got, want := resp.StatusCode, http.StatusOK; got != want {
  2602  		t.Errorf("resp.StatusCode = %d; want %d", got, want)
  2603  		t.Logf("%s", buf)
  2604  	}
  2605  
  2606  	msg := new(examplepb.UnannotatedSimpleMessage)
  2607  	if err := marshaler.Unmarshal(buf, msg); err != nil {
  2608  		t.Errorf("marshaler.Unmarshal(%s, msg) failed with %v; want success", buf, err)
  2609  		return
  2610  	}
  2611  	if got, want := msg.Id, "myid"; got != want {
  2612  		t.Errorf("msg.Id = %q; want %q", got, want)
  2613  	}
  2614  }
  2615  

View as plain text