Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(565)

Side by Side Diff: common/prpc/client_test.go

Issue 1605363002: common/prpc, tools/cmd/cproto: prpc client (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-go@master
Patch Set: rebased and addressed comments Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « common/prpc/client.go ('k') | common/prpc/codes.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package prpc
6
7 import (
8 "fmt"
9 "io/ioutil"
10 "net/http"
11 "net/http/httptest"
12 "strconv"
13 "strings"
14 "testing"
15 "time"
16
17 "github.com/golang/protobuf/proto"
18 "golang.org/x/net/context"
19 "google.golang.org/grpc"
20 "google.golang.org/grpc/codes"
21
22 "github.com/luci/luci-go/common/logging"
23 "github.com/luci/luci-go/common/logging/memlogger"
24 "github.com/luci/luci-go/common/retry"
25
26 . "github.com/smartystreets/goconvey/convey"
27 )
28
29 func sayHello(c C) http.HandlerFunc {
30 return func(w http.ResponseWriter, r *http.Request) {
31 c.So(r.Method, ShouldEqual, "POST")
32 c.So(r.URL.Path, ShouldEqual, "/prpc/prpc.Greeter/SayHello")
33 c.So(r.Header.Get("Accept"), ShouldEqual, "application/prpc")
34 c.So(r.Header.Get("Content-Type"), ShouldEqual, "application/prp c")
35 c.So(r.Header.Get("User-Agent"), ShouldEqual, "prpc-test")
36
37 reqBody, err := ioutil.ReadAll(r.Body)
38 c.So(err, ShouldBeNil)
39
40 var req HelloRequest
41 err = proto.Unmarshal(reqBody, &req)
42 c.So(err, ShouldBeNil)
43
44 res := HelloReply{"Hello " + req.Name}
45 buf, err := proto.Marshal(&res)
46 c.So(err, ShouldBeNil)
47
48 w.Header().Set(HeaderGRPCCode, strconv.Itoa(int(codes.OK)))
49 _, err = w.Write(buf)
50 c.So(err, ShouldBeNil)
51 }
52 }
53
54 func transientErrors(count int, then http.Handler) http.HandlerFunc {
55 return func(w http.ResponseWriter, r *http.Request) {
56 if count > 0 {
57 count--
58 w.Header().Set(HeaderGRPCCode, strconv.Itoa(int(codes.In ternal)))
59 w.WriteHeader(http.StatusInternalServerError)
60 fmt.Fprintln(w, "Server misbehaved")
61 return
62 }
63 then.ServeHTTP(w, r)
64 }
65 }
66
67 func shouldHaveMessagesLike(actual interface{}, expected ...interface{}) string {
68 log := actual.(*memlogger.MemLogger)
69 msgs := log.Messages()
70
71 So(msgs, ShouldHaveLength, len(expected))
72 for i, actual := range msgs {
73 expected := expected[i].(memlogger.LogEntry)
74 So(actual.Level, ShouldEqual, expected.Level)
75 So(actual.Msg, ShouldContainSubstring, expected.Msg)
76 }
77 return ""
78 }
79
80 func TestClient(t *testing.T) {
81 t.Parallel()
82
83 Convey("Client", t, func() {
84 setUp := func(h http.HandlerFunc) (*Client, *httptest.Server) {
85 server := httptest.NewServer(h)
86 client := &Client{
87 Host: strings.TrimPrefix(server.URL, "http://"),
88 Options: &Options{
89 Retry: func() retry.Iterator {
90 return &retry.ExponentialBackoff {
91 Limited: retry.Limited{
92 Retries: 3,
93 Delay: time.Mi llisecond,
94 },
95 }
96 },
97 Insecure: true,
98 UserAgent: "prpc-test",
99 },
100 }
101 return client, server
102 }
103
104 ctx := memlogger.Use(context.Background())
105 log := logging.Get(ctx).(*memlogger.MemLogger)
106 expectedCallLogEntry := func(c *Client) memlogger.LogEntry {
107 return memlogger.LogEntry{
108 Level: logging.Debug,
109 Msg: fmt.Sprintf("RPC %s/prpc.Greeter.SayHello ", c.Host),
110 }
111 }
112
113 req := &HelloRequest{"John"}
114 res := &HelloReply{}
115
116 Convey("Call", func() {
117 Convey("Works", func(c C) {
118 client, server := setUp(sayHello(c))
119 defer server.Close()
120
121 err := client.Call(ctx, "prpc.Greeter", "SayHell o", req, res)
122 So(err, ShouldBeNil)
123 So(res.Message, ShouldEqual, "Hello John")
124
125 So(log, shouldHaveMessagesLike, expectedCallLogE ntry(client))
126 })
127
128 Convey("HTTP 500 x2", func(c C) {
129 client, server := setUp(transientErrors(2, sayHe llo(c)))
130 defer server.Close()
131
132 err := client.Call(ctx, "prpc.Greeter", "SayHell o", req, res)
133 So(err, ShouldBeNil)
134 So(res.Message, ShouldEqual, "Hello John")
135
136 So(log, shouldHaveMessagesLike,
137 expectedCallLogEntry(client),
138 memlogger.LogEntry{Level: logging.Warnin g, Msg: "RPC failed transiently. Will retry in 1ms"},
139
140 expectedCallLogEntry(client),
141 memlogger.LogEntry{Level: logging.Warnin g, Msg: "RPC failed transiently. Will retry in 2ms"},
142
143 expectedCallLogEntry(client),
144 )
145 })
146
147 Convey("HTTP 500 many", func(c C) {
148 client, server := setUp(transientErrors(10, sayH ello(c)))
149 defer server.Close()
150
151 err := client.Call(ctx, "prpc.Greeter", "SayHell o", req, res)
152 So(grpc.Code(err), ShouldEqual, codes.Internal)
153 So(grpc.ErrorDesc(err), ShouldEqual, "Server mis behaved")
154
155 So(log, shouldHaveMessagesLike,
156 expectedCallLogEntry(client),
157 memlogger.LogEntry{Level: logging.Warnin g, Msg: "RPC failed transiently. Will retry in 1ms"},
158
159 expectedCallLogEntry(client),
160 memlogger.LogEntry{Level: logging.Warnin g, Msg: "RPC failed transiently. Will retry in 2ms"},
161
162 expectedCallLogEntry(client),
163 memlogger.LogEntry{Level: logging.Warnin g, Msg: "RPC failed transiently. Will retry in 4ms"},
164
165 expectedCallLogEntry(client),
166 memlogger.LogEntry{Level: logging.Warnin g, Msg: "RPC failed permanently"},
167 )
168 })
169
170 Convey("Forbidden", func(c C) {
171 client, server := setUp(func(w http.ResponseWrit er, r *http.Request) {
172 w.Header().Set(HeaderGRPCCode, strconv.I toa(int(codes.PermissionDenied)))
173 w.WriteHeader(http.StatusForbidden)
174 fmt.Fprintln(w, "Access denied")
175 })
176 defer server.Close()
177
178 err := client.Call(ctx, "prpc.Greeter", "SayHell o", req, res)
179 So(grpc.Code(err), ShouldEqual, codes.Permission Denied)
180 So(grpc.ErrorDesc(err), ShouldEqual, "Access den ied")
181
182 So(log, shouldHaveMessagesLike,
183 expectedCallLogEntry(client),
184 memlogger.LogEntry{Level: logging.Warnin g, Msg: "RPC failed permanently"},
185 )
186 })
187
188 Convey(HeaderGRPCCode, func(c C) {
189 client, server := setUp(func(w http.ResponseWrit er, r *http.Request) {
190 w.Header().Set(HeaderGRPCCode, strconv.I toa(int(codes.Canceled)))
191 w.WriteHeader(http.StatusBadRequest)
192 })
193 defer server.Close()
194
195 err := client.Call(ctx, "prpc.Greeter", "SayHell o", req, res)
196 So(grpc.Code(err), ShouldEqual, codes.Canceled)
197 })
198 })
199 })
200 }
OLDNEW
« no previous file with comments | « common/prpc/client.go ('k') | common/prpc/codes.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698