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