blob: e072dd51b56ca1c38b0048f9be01b6b9f2a7d988 [file] [log] [blame]
Jiri Simsa78b646f2014-10-08 10:23:05 -07001package app
2
3import (
Matt Rosencrantz786f7272015-02-11 15:18:07 -08004 "bytes"
5 "encoding/hex"
Jiri Simsa78b646f2014-10-08 10:23:05 -07006 "fmt"
7 "reflect"
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -08008 "sync"
Jiri Simsa78b646f2014-10-08 10:23:05 -07009 "testing"
10
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -080011 "v.io/core/veyron/lib/testutil"
12 tsecurity "v.io/core/veyron/lib/testutil/security"
13 _ "v.io/core/veyron/profiles"
14 "v.io/core/veyron/runtimes/google/ipc/stream/proxy"
15 vsecurity "v.io/core/veyron/security"
16 mounttable "v.io/core/veyron/services/mounttable/lib"
Jiri Simsa1f1302c2015-02-23 16:18:34 -080017 "v.io/v23"
18 "v.io/v23/context"
19 "v.io/v23/ipc"
20 "v.io/v23/naming"
21 "v.io/v23/options"
22 "v.io/v23/security"
23 "v.io/v23/vdl"
Todd Wangac9e1902015-02-25 01:58:01 -080024 "v.io/v23/vdlroot/signature"
Jiri Simsa1f1302c2015-02-23 16:18:34 -080025 "v.io/v23/verror"
26 "v.io/v23/vom"
27 "v.io/v23/vtrace"
Jiri Simsa350ed9b2015-02-26 14:02:52 -080028 "v.io/core/veyron/services/wsprd/ipc/server"
29 "v.io/core/veyron/services/wsprd/lib"
30 "v.io/core/veyron/services/wsprd/lib/testwriter"
Jiri Simsa78b646f2014-10-08 10:23:05 -070031)
32
Ankure7889242014-10-20 18:37:29 -070033var (
34 testPrincipalBlessing = "test"
35 testPrincipal = newPrincipal(testPrincipalBlessing)
Ankure7889242014-10-20 18:37:29 -070036)
37
38// newBlessedPrincipal returns a new principal that has a blessing from the
39// provided runtime's principal which is set on its BlessingStore such
40// that it is revealed to all clients and servers.
Matt Rosencrantz306d9902015-01-10 17:46:07 -080041func newBlessedPrincipal(ctx *context.T) security.Principal {
Ankure7889242014-10-20 18:37:29 -070042 p, err := vsecurity.NewPrincipal()
43 if err != nil {
44 panic(err)
45 }
Matt Rosencrantz306d9902015-01-10 17:46:07 -080046
Jiri Simsa1f1302c2015-02-23 16:18:34 -080047 principal := v23.GetPrincipal(ctx)
Matt Rosencrantz306d9902015-01-10 17:46:07 -080048 b, err := principal.Bless(p.PublicKey(), principal.BlessingStore().Default(), "delegate", security.UnconstrainedUse())
Ankure7889242014-10-20 18:37:29 -070049 if err != nil {
50 panic(err)
51 }
52 tsecurity.SetDefaultBlessings(p, b)
53 return p
54}
55
56// newPrincipal returns a new principal that has a self-blessing with
57// the provided extension 'selfBlessing' which is set on its BlessingStore
58// such that it is revealed to all clients and servers.
59func newPrincipal(selfBlessing string) security.Principal {
60 p, err := vsecurity.NewPrincipal()
61 if err != nil {
62 panic(err)
63 }
64 b, err := p.BlessSelf(selfBlessing)
65 if err != nil {
66 panic(err)
67 }
68 tsecurity.SetDefaultBlessings(p, b)
69 return p
70}
Jiri Simsa78b646f2014-10-08 10:23:05 -070071
72type simpleAdder struct{}
73
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -080074func (s simpleAdder) Add(_ ipc.ServerContext, a, b int32) (int32, error) {
Jiri Simsa78b646f2014-10-08 10:23:05 -070075 return a + b, nil
76}
77
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -080078func (s simpleAdder) Divide(_ ipc.ServerContext, a, b int32) (int32, error) {
Jiri Simsa78b646f2014-10-08 10:23:05 -070079 if b == 0 {
Jiri Simsa94f68d02015-02-17 10:22:08 -080080 return 0, verror.New(verror.ErrBadArg, nil, "div 0")
Jiri Simsa78b646f2014-10-08 10:23:05 -070081 }
82 return a / b, nil
83}
84
85func (s simpleAdder) StreamingAdd(call ipc.ServerCall) (int32, error) {
86 total := int32(0)
87 var value int32
88 for err := call.Recv(&value); err == nil; err = call.Recv(&value) {
89 total += value
90 call.Send(total)
91 }
92 return total, nil
93}
94
Todd Wang72ef57b2015-01-08 10:23:21 -080095var simpleAddrSig = signature.Interface{
96 Doc: "The empty interface contains methods not attached to any interface.",
97 Methods: []signature.Method{
98 {
99 Name: "Add",
100 InArgs: []signature.Arg{{Type: vdl.Int32Type}, {Type: vdl.Int32Type}},
Benjamin Prosnitz518af1e2015-01-20 14:20:10 -0800101 OutArgs: []signature.Arg{{Type: vdl.Int32Type}},
Todd Wang72ef57b2015-01-08 10:23:21 -0800102 },
103 {
104 Name: "Divide",
105 InArgs: []signature.Arg{{Type: vdl.Int32Type}, {Type: vdl.Int32Type}},
Benjamin Prosnitz518af1e2015-01-20 14:20:10 -0800106 OutArgs: []signature.Arg{{Type: vdl.Int32Type}},
Todd Wang72ef57b2015-01-08 10:23:21 -0800107 },
108 {
109 Name: "StreamingAdd",
Benjamin Prosnitz518af1e2015-01-20 14:20:10 -0800110 OutArgs: []signature.Arg{{Type: vdl.Int32Type}},
Todd Wang72ef57b2015-01-08 10:23:21 -0800111 InStream: &signature.Arg{Type: vdl.AnyType},
112 OutStream: &signature.Arg{Type: vdl.AnyType},
Jiri Simsa78b646f2014-10-08 10:23:05 -0700113 },
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800114 },
Jiri Simsa78b646f2014-10-08 10:23:05 -0700115}
116
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800117func startAnyServer(ctx *context.T, servesMT bool, dispatcher ipc.Dispatcher) (ipc.Server, naming.Endpoint, error) {
Jiri Simsa78b646f2014-10-08 10:23:05 -0700118 // Create a new server instance.
Jiri Simsa1f1302c2015-02-23 16:18:34 -0800119 s, err := v23.NewServer(ctx, options.ServesMountTable(servesMT))
Jiri Simsa78b646f2014-10-08 10:23:05 -0700120 if err != nil {
121 return nil, nil, err
122 }
123
Jiri Simsa1f1302c2015-02-23 16:18:34 -0800124 endpoints, err := s.Listen(v23.GetListenSpec(ctx))
Jiri Simsa78b646f2014-10-08 10:23:05 -0700125 if err != nil {
126 return nil, nil, err
127 }
128
Cosmos Nicolaou4619b1f2014-11-05 07:23:13 -0800129 if err := s.ServeDispatcher("", dispatcher); err != nil {
Jiri Simsa78b646f2014-10-08 10:23:05 -0700130 return nil, nil, err
131 }
Cosmos Nicolaoud48178c2014-12-15 22:51:52 -0800132 return s, endpoints[0], nil
Jiri Simsa78b646f2014-10-08 10:23:05 -0700133}
134
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800135func startAdderServer(ctx *context.T) (ipc.Server, naming.Endpoint, error) {
136 return startAnyServer(ctx, false, testutil.LeafDispatcher(simpleAdder{}, nil))
Jiri Simsa78b646f2014-10-08 10:23:05 -0700137}
138
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800139func startProxy(ctx *context.T) (*proxy.Proxy, error) {
Jiri Simsa78b646f2014-10-08 10:23:05 -0700140 rid, err := naming.NewRoutingID()
141 if err != nil {
142 return nil, err
143 }
144 return proxy.New(rid, nil, "tcp", "127.0.0.1:0", "")
145}
146
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800147func startMountTableServer(ctx *context.T) (ipc.Server, naming.Endpoint, error) {
Bogdan Capritaa25b6c22015-02-03 17:30:21 -0800148 mt, err := mounttable.NewMountTableDispatcher("")
Jiri Simsa78b646f2014-10-08 10:23:05 -0700149 if err != nil {
150 return nil, nil, err
151 }
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800152 return startAnyServer(ctx, true, mt)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700153}
154
Jiri Simsa78b646f2014-10-08 10:23:05 -0700155func TestGetGoServerSignature(t *testing.T) {
Ankur9dec6d62015-01-30 15:07:01 -0800156 ctx, shutdown := testutil.InitForTest()
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800157 defer shutdown()
158
159 s, endpoint, err := startAdderServer(ctx)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700160 if err != nil {
161 t.Errorf("unable to start server: %v", err)
162 t.Fail()
163 return
164 }
165 defer s.Stop()
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800166
Jiri Simsa1f1302c2015-02-23 16:18:34 -0800167 spec := v23.GetListenSpec(ctx)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700168 spec.Proxy = "mockVeyronProxyEP"
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800169 controller, err := NewController(ctx, nil, &spec, nil, newBlessedPrincipal(ctx))
Jiri Simsa78b646f2014-10-08 10:23:05 -0700170
171 if err != nil {
Ankure7889242014-10-20 18:37:29 -0700172 t.Fatalf("Failed to create controller: %v", err)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700173 }
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800174 sig, err := controller.getSignature(ctx, "/"+endpoint.String())
Jiri Simsa78b646f2014-10-08 10:23:05 -0700175 if err != nil {
Ankure7889242014-10-20 18:37:29 -0700176 t.Fatalf("Failed to get signature: %v", err)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700177 }
Todd Wang72ef57b2015-01-08 10:23:21 -0800178 if got, want := len(sig), 2; got != want {
179 t.Fatalf("got signature %#v len %d, want %d", sig, got, want)
180 }
181 if got, want := sig[0], simpleAddrSig; !reflect.DeepEqual(got, want) {
182 t.Errorf("got sig[0] %#v, want: %#v", got, want)
183 }
184 if got, want := sig[1].Name, "__Reserved"; got != want {
185 t.Errorf("got sig[1].Name %#v, want: %#v", got, want)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700186 }
187}
188
189type goServerTestCase struct {
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800190 method string
Matt Rosencrantz786f7272015-02-11 15:18:07 -0800191 inArgs []interface{}
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800192 numOutArgs int32
193 streamingInputs []interface{}
194 expectedStream []lib.Response
195 expectedError error
Jiri Simsa78b646f2014-10-08 10:23:05 -0700196}
197
198func runGoServerTestCase(t *testing.T, test goServerTestCase) {
Ankur9dec6d62015-01-30 15:07:01 -0800199 ctx, shutdown := testutil.InitForTest()
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800200 defer shutdown()
201
202 s, endpoint, err := startAdderServer(ctx)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700203 if err != nil {
204 t.Errorf("unable to start server: %v", err)
205 t.Fail()
206 return
207 }
208 defer s.Stop()
Cosmos Nicolaou408de0f2014-10-24 13:32:29 -0700209
Jiri Simsa1f1302c2015-02-23 16:18:34 -0800210 spec := v23.GetListenSpec(ctx)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700211 spec.Proxy = "mockVeyronProxyEP"
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800212 controller, err := NewController(ctx, nil, &spec, nil, newBlessedPrincipal(ctx))
Jiri Simsa78b646f2014-10-08 10:23:05 -0700213
214 if err != nil {
215 t.Errorf("unable to create controller: %v", err)
216 t.Fail()
217 return
218 }
Jiri Simsa78b646f2014-10-08 10:23:05 -0700219 writer := testwriter.Writer{}
220 var stream *outstandingStream
221 if len(test.streamingInputs) > 0 {
222 stream = newStream()
Matt Rosencrantz4aabe572014-10-22 09:25:50 -0700223 controller.outstandingRequests[0] = &outstandingRequest{
224 stream: stream,
225 }
Jiri Simsa78b646f2014-10-08 10:23:05 -0700226 go func() {
227 for _, value := range test.streamingInputs {
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800228 controller.SendOnStream(0, lib.VomEncodeOrDie(value), &writer)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700229 }
230 controller.CloseStream(0)
231 }()
232 }
233
Matt Rosencrantzac1e3a82015-02-12 16:04:28 -0800234 request := VeyronRPCRequest{
Jiri Simsa78b646f2014-10-08 10:23:05 -0700235 Name: "/" + endpoint.String(),
236 Method: test.method,
Matt Rosencrantz786f7272015-02-11 15:18:07 -0800237 NumInArgs: int32(len(test.inArgs)),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700238 NumOutArgs: test.numOutArgs,
239 IsStreaming: stream != nil,
240 }
Matt Rosencrantzac1e3a82015-02-12 16:04:28 -0800241 controller.sendVeyronRequest(ctx, 0, &request, test.inArgs, &writer, stream, vtrace.GetSpan(ctx))
Jiri Simsa78b646f2014-10-08 10:23:05 -0700242
Matt Rosencrantz4aabe572014-10-22 09:25:50 -0700243 if err := testwriter.CheckResponses(&writer, test.expectedStream, test.expectedError); err != nil {
244 t.Error(err)
245 }
Jiri Simsa78b646f2014-10-08 10:23:05 -0700246}
247
Todd Wang5ab03662015-02-19 21:03:01 -0800248func makeRPCResponse(outArgs ...*vdl.Value) string {
Matt Rosencrantzac1e3a82015-02-12 16:04:28 -0800249 return lib.VomEncodeOrDie(VeyronRPCResponse{
Matt Rosencrantz8fa0ea12015-02-24 14:17:50 -0800250 OutArgs: outArgs,
251 TraceResponse: vtrace.Response{},
Matt Rosencrantzac1e3a82015-02-12 16:04:28 -0800252 })
253}
254
Jiri Simsa78b646f2014-10-08 10:23:05 -0700255func TestCallingGoServer(t *testing.T) {
256 runGoServerTestCase(t, goServerTestCase{
257 method: "Add",
Matt Rosencrantz786f7272015-02-11 15:18:07 -0800258 inArgs: []interface{}{2, 3},
Benjamin Prosnitz518af1e2015-01-20 14:20:10 -0800259 numOutArgs: 1,
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800260 expectedStream: []lib.Response{
261 lib.Response{
Todd Wang5ab03662015-02-19 21:03:01 -0800262 Message: makeRPCResponse(vdl.Int32Value(5)),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700263 Type: lib.ResponseFinal,
264 },
265 },
266 })
267}
268
269func TestCallingGoServerWithError(t *testing.T) {
270 runGoServerTestCase(t, goServerTestCase{
271 method: "Divide",
Matt Rosencrantz786f7272015-02-11 15:18:07 -0800272 inArgs: []interface{}{1, 0},
Benjamin Prosnitz518af1e2015-01-20 14:20:10 -0800273 numOutArgs: 1,
Jiri Simsa94f68d02015-02-17 10:22:08 -0800274 expectedError: verror.New(verror.ErrBadArg, nil, "div 0"),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700275 })
276}
277
278func TestCallingGoWithStreaming(t *testing.T) {
279 runGoServerTestCase(t, goServerTestCase{
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800280 method: "StreamingAdd",
281 streamingInputs: []interface{}{1, 2, 3, 4},
Benjamin Prosnitz518af1e2015-01-20 14:20:10 -0800282 numOutArgs: 1,
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800283 expectedStream: []lib.Response{
284 lib.Response{
285 Message: lib.VomEncodeOrDie(int32(1)),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700286 Type: lib.ResponseStream,
287 },
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800288 lib.Response{
289 Message: lib.VomEncodeOrDie(int32(3)),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700290 Type: lib.ResponseStream,
291 },
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800292 lib.Response{
293 Message: lib.VomEncodeOrDie(int32(6)),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700294 Type: lib.ResponseStream,
295 },
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800296 lib.Response{
297 Message: lib.VomEncodeOrDie(int32(10)),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700298 Type: lib.ResponseStream,
299 },
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800300 lib.Response{
Jiri Simsa78b646f2014-10-08 10:23:05 -0700301 Message: nil,
302 Type: lib.ResponseStreamClose,
303 },
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800304 lib.Response{
Todd Wang5ab03662015-02-19 21:03:01 -0800305 Message: makeRPCResponse(vdl.Int32Value(10)),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700306 Type: lib.ResponseFinal,
307 },
308 },
309 })
310}
311
312type runningTest struct {
313 controller *Controller
314 writer *testwriter.Writer
315 mounttableServer ipc.Server
316 proxyServer *proxy.Proxy
317}
318
Matt Rosencrantzac1e3a82015-02-12 16:04:28 -0800319func makeRequest(rpc VeyronRPCRequest, args ...interface{}) (string, error) {
Matt Rosencrantz786f7272015-02-11 15:18:07 -0800320 var buf bytes.Buffer
Todd Wangf619d432015-02-18 11:19:27 -0800321 encoder, err := vom.NewEncoder(&buf)
Matt Rosencrantz786f7272015-02-11 15:18:07 -0800322 if err != nil {
323 return "", err
324 }
325 if err := encoder.Encode(rpc); err != nil {
326 return "", err
327 }
328 for _, arg := range args {
329 if err := encoder.Encode(arg); err != nil {
330 return "", err
331 }
332 }
333 return hex.EncodeToString(buf.Bytes()), nil
334}
335
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800336func serveServer(ctx *context.T, writer lib.ClientWriter, setController func(*Controller)) (*runningTest, error) {
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800337 mounttableServer, endpoint, err := startMountTableServer(ctx)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700338 if err != nil {
339 return nil, fmt.Errorf("unable to start mounttable: %v", err)
340 }
341
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800342 proxyServer, err := startProxy(ctx)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700343 if err != nil {
344 return nil, fmt.Errorf("unable to start proxy: %v", err)
345 }
346
347 proxyEndpoint := proxyServer.Endpoint().String()
348
Benjamin Prosnitz86d52282014-12-19 15:48:38 -0800349 writerCreator := func(int32) lib.ClientWriter {
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800350 return writer
Jiri Simsa78b646f2014-10-08 10:23:05 -0700351 }
Jiri Simsa1f1302c2015-02-23 16:18:34 -0800352 spec := v23.GetListenSpec(ctx)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700353 spec.Proxy = "/" + proxyEndpoint
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800354 controller, err := NewController(ctx, writerCreator, &spec, nil, testPrincipal)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700355 if err != nil {
356 return nil, err
357 }
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800358
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800359 if setController != nil {
360 setController(controller)
361 }
362
Jiri Simsa1f1302c2015-02-23 16:18:34 -0800363 v23.GetNamespace(controller.Context()).SetRoots("/" + endpoint.String())
Jiri Simsa78b646f2014-10-08 10:23:05 -0700364
Matt Rosencrantzac1e3a82015-02-12 16:04:28 -0800365 req, err := makeRequest(VeyronRPCRequest{
Matt Rosencrantz9d2170b2015-02-21 16:19:53 -0800366 Name: "__controller",
Matt Rosencrantz786f7272015-02-11 15:18:07 -0800367 Method: "Serve",
368 NumInArgs: 2,
369 NumOutArgs: 1,
370 Timeout: 20000000000,
371 }, "adder", 0)
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800372 controller.HandleVeyronRequest(ctx, 0, req, writer)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700373
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800374 testWriter, _ := writer.(*testwriter.Writer)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700375 return &runningTest{
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800376 controller, testWriter, mounttableServer, proxyServer,
Jiri Simsa78b646f2014-10-08 10:23:05 -0700377 }, nil
378}
379
Jiri Simsa78b646f2014-10-08 10:23:05 -0700380// A test case to simulate a Javascript server talking to the App. All the
381// responses from Javascript are mocked and sent back through the method calls.
382// All messages from the client are sent using a go client.
383type jsServerTestCase struct {
384 method string
385 inArgs []interface{}
386 // The set of streaming inputs from the client to the server.
387 // This is passed to the client, which then passes it to the app.
388 clientStream []interface{}
389 // The set of JSON streaming messages sent from Javascript to the
390 // app.
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800391 serverStream []interface{}
Jiri Simsa78b646f2014-10-08 10:23:05 -0700392 // The final response sent by the Javascript server to the
393 // app.
Todd Wang5ab03662015-02-19 21:03:01 -0800394 finalResponse *vdl.Value
Jiri Simsa78b646f2014-10-08 10:23:05 -0700395 // The final error sent by the Javascript server to the app.
Mike Burrowsa727df72015-02-04 17:26:46 -0800396 err error
Jiri Simsa78b646f2014-10-08 10:23:05 -0700397
398 // Whether or not the Javascript server has an authorizer or not.
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800399 // If it does have an authorizer, then err is sent back from the server
Jiri Simsa78b646f2014-10-08 10:23:05 -0700400 // to the app.
401 hasAuthorizer bool
Jiri Simsa78b646f2014-10-08 10:23:05 -0700402}
403
Jiri Simsa78b646f2014-10-08 10:23:05 -0700404func runJsServerTestCase(t *testing.T, test jsServerTestCase) {
Ankur9dec6d62015-01-30 15:07:01 -0800405 ctx, shutdown := testutil.InitForTest()
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800406 defer shutdown()
407
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800408 vomClientStream := []string{}
409 for _, m := range test.clientStream {
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800410 vomClientStream = append(vomClientStream, lib.VomEncodeOrDie(m))
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800411 }
412 mock := &mockJSServer{
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800413 t: t,
414 method: test.method,
Todd Wang72ef57b2015-01-08 10:23:21 -0800415 serviceSignature: []signature.Interface{simpleAddrSig},
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800416 expectedClientStream: vomClientStream,
417 serverStream: test.serverStream,
418 hasAuthorizer: test.hasAuthorizer,
Shyam Jayaraman907219d2014-11-26 12:14:37 -0800419 inArgs: test.inArgs,
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800420 finalResponse: test.finalResponse,
421 finalError: test.err,
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800422 controllerReady: sync.RWMutex{},
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800423 }
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800424 rt, err := serveServer(ctx, mock, func(controller *Controller) {
425 mock.controller = controller
426 })
427 defer rt.mounttableServer.Stop()
428 defer rt.proxyServer.Shutdown()
429 defer rt.controller.Cleanup()
430
431 if err != nil {
432 t.Fatalf("could not serve server %v", err)
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800433 }
434
Matt Rosencrantzc90eb7b2015-01-09 08:32:01 -0800435 // Get the client that is relevant to the controller so it talks
436 // to the right mounttable.
Jiri Simsa1f1302c2015-02-23 16:18:34 -0800437 client := v23.GetClient(rt.controller.Context())
Jiri Simsa78b646f2014-10-08 10:23:05 -0700438
439 if err != nil {
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800440 t.Fatalf("unable to create client: %v", err)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700441 }
442
Matt Rosencrantzc90eb7b2015-01-09 08:32:01 -0800443 call, err := client.StartCall(rt.controller.Context(), "adder/adder", test.method, test.inArgs)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700444 if err != nil {
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800445 t.Fatalf("failed to start call: %v", err)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700446 }
447
Jiri Simsa78b646f2014-10-08 10:23:05 -0700448 for _, msg := range test.clientStream {
Jiri Simsa78b646f2014-10-08 10:23:05 -0700449 if err := call.Send(msg); err != nil {
450 t.Errorf("unexpected error while sending %v: %v", msg, err)
451 }
452 }
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800453 if err := call.CloseSend(); err != nil {
454 t.Errorf("unexpected error on close: %v", err)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700455 }
456
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800457 expectedStream := test.serverStream
Jiri Simsa78b646f2014-10-08 10:23:05 -0700458 for {
459 var data interface{}
460 if err := call.Recv(&data); err != nil {
461 break
462 }
463 if len(expectedStream) == 0 {
464 t.Errorf("unexpected stream value: %v", data)
465 continue
466 }
467 if !reflect.DeepEqual(data, expectedStream[0]) {
468 t.Errorf("unexpected stream value: got %v, expected %v", data, expectedStream[0])
469 }
470 expectedStream = expectedStream[1:]
471 }
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800472
Todd Wang5ab03662015-02-19 21:03:01 -0800473 var result *vdl.Value
Todd Wangf21e1552015-02-18 13:21:52 -0800474 err = call.Finish(&result)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700475
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800476 // If err is nil and test.err is nil reflect.DeepEqual will return
477 // false because the types are different. Because of this, we only use
478 // reflect.DeepEqual if one of the values is non-nil. If both values
479 // are nil, then we consider them equal.
480 if (err != nil || test.err != nil) && !verror.Equal(err, test.err) {
481 t.Errorf("unexpected err: got %#v, expected %#v", err, test.err)
482 }
483
484 if err != nil {
485 return
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800486 }
Nicolas LaCassed7ab8a12015-02-03 11:46:29 -0800487
Todd Wang5ab03662015-02-19 21:03:01 -0800488 if got, want := result, test.finalResponse; !vdl.EqualValue(got, want) {
489 t.Errorf("unexected final response: got %v, want %v", got, want)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700490 }
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800491
492 // ensure there is only one server and then stop the server
493 if len(rt.controller.servers) != 1 {
494 t.Errorf("expected only one server but got: %d", len(rt.controller.servers))
495 return
496 }
497 for serverId := range rt.controller.servers {
498 rt.controller.Stop(nil, serverId)
499 }
500
501 // ensure there is no more servers now
502 if len(rt.controller.servers) != 0 {
503 t.Errorf("expected no server after stopping the only one but got: %d", len(rt.controller.servers))
504 return
505 }
Jiri Simsa78b646f2014-10-08 10:23:05 -0700506}
507
508func TestSimpleJSServer(t *testing.T) {
509 runJsServerTestCase(t, jsServerTestCase{
510 method: "Add",
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800511 inArgs: []interface{}{int32(1), int32(2)},
Todd Wang5ab03662015-02-19 21:03:01 -0800512 finalResponse: vdl.Int32Value(3),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700513 })
514}
515
516func TestJSServerWithAuthorizer(t *testing.T) {
517 runJsServerTestCase(t, jsServerTestCase{
518 method: "Add",
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800519 inArgs: []interface{}{int32(1), int32(2)},
Todd Wang5ab03662015-02-19 21:03:01 -0800520 finalResponse: vdl.Int32Value(3),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700521 hasAuthorizer: true,
522 })
523}
524
525func TestJSServerWithError(t *testing.T) {
Jiri Simsa94f68d02015-02-17 10:22:08 -0800526 err := verror.New(verror.ErrInternal, nil)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700527 runJsServerTestCase(t, jsServerTestCase{
Nicolas LaCassed7ab8a12015-02-03 11:46:29 -0800528 method: "Divide",
529 inArgs: []interface{}{int32(1), int32(0)},
530 err: err,
Jiri Simsa78b646f2014-10-08 10:23:05 -0700531 })
532}
533
534func TestJSServerWithAuthorizerAndAuthError(t *testing.T) {
Jiri Simsa94f68d02015-02-17 10:22:08 -0800535 err := verror.New(verror.ErrNoAccess, nil)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700536 runJsServerTestCase(t, jsServerTestCase{
537 method: "Add",
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800538 inArgs: []interface{}{int32(1), int32(2)},
Jiri Simsa78b646f2014-10-08 10:23:05 -0700539 hasAuthorizer: true,
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800540 finalResponse: vdl.Int32Value(3),
541 err: err,
Jiri Simsa78b646f2014-10-08 10:23:05 -0700542 })
543}
544func TestJSServerWihStreamingInputs(t *testing.T) {
545 runJsServerTestCase(t, jsServerTestCase{
546 method: "StreamingAdd",
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800547 clientStream: []interface{}{int32(3), int32(4)},
Todd Wang5ab03662015-02-19 21:03:01 -0800548 finalResponse: vdl.Int32Value(10),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700549 })
550}
551
552func TestJSServerWihStreamingOutputs(t *testing.T) {
553 runJsServerTestCase(t, jsServerTestCase{
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800554 method: "StreamingAdd",
555 serverStream: []interface{}{int32(3), int32(4)},
Todd Wang5ab03662015-02-19 21:03:01 -0800556 finalResponse: vdl.Int32Value(10),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700557 })
558}
559
560func TestJSServerWihStreamingInputsAndOutputs(t *testing.T) {
561 runJsServerTestCase(t, jsServerTestCase{
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800562 method: "StreamingAdd",
563 clientStream: []interface{}{int32(1), int32(2)},
564 serverStream: []interface{}{int32(3), int32(4)},
Todd Wang5ab03662015-02-19 21:03:01 -0800565 finalResponse: vdl.Int32Value(10),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700566 })
567}
Nicolas LaCassed7ab8a12015-02-03 11:46:29 -0800568
569func TestJSServerWithWrongNumberOfArgs(t *testing.T) {
Todd Wangb63e9eb2015-02-10 19:57:39 -0800570 err := verror.New(server.ErrWrongNumberOfArgs, nil, "Add", 3, 2)
Nicolas LaCassed7ab8a12015-02-03 11:46:29 -0800571 runJsServerTestCase(t, jsServerTestCase{
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800572 method: "Add",
573 inArgs: []interface{}{int32(1), int32(2), int32(3)},
574 err: err,
Nicolas LaCassed7ab8a12015-02-03 11:46:29 -0800575 })
576}
577
578func TestJSServerWithMethodNotFound(t *testing.T) {
579 methodName := "UnknownMethod"
Todd Wangb63e9eb2015-02-10 19:57:39 -0800580 err := verror.New(server.ErrMethodNotFoundInSignature, nil, methodName)
Nicolas LaCassed7ab8a12015-02-03 11:46:29 -0800581 runJsServerTestCase(t, jsServerTestCase{
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800582 method: methodName,
583 inArgs: []interface{}{int32(1), int32(2)},
584 err: err,
Nicolas LaCassed7ab8a12015-02-03 11:46:29 -0800585 })
586}