blob: ed4c11504ddadd4b3c284a8d7aa2346a85285bd8 [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
Jiri Simsa1f1302c2015-02-23 16:18:34 -080011 "v.io/v23"
12 "v.io/v23/context"
13 "v.io/v23/ipc"
14 "v.io/v23/naming"
15 "v.io/v23/options"
16 "v.io/v23/security"
17 "v.io/v23/vdl"
Todd Wangac9e1902015-02-25 01:58:01 -080018 "v.io/v23/vdlroot/signature"
Jiri Simsa1f1302c2015-02-23 16:18:34 -080019 "v.io/v23/verror"
20 "v.io/v23/vom"
21 "v.io/v23/vtrace"
Jiri Simsaffceefa2015-02-28 11:03:34 -080022 "v.io/x/ref/lib/testutil"
23 tsecurity "v.io/x/ref/lib/testutil/security"
Matt Rosencrantz2b675f92015-03-05 12:52:50 -080024 "v.io/x/ref/profiles"
Jiri Simsaffceefa2015-02-28 11:03:34 -080025 vsecurity "v.io/x/ref/security"
26 mounttable "v.io/x/ref/services/mounttable/lib"
27 "v.io/x/ref/services/wsprd/ipc/server"
28 "v.io/x/ref/services/wsprd/lib"
29 "v.io/x/ref/services/wsprd/lib/testwriter"
Jiri Simsa78b646f2014-10-08 10:23:05 -070030)
31
Ankure7889242014-10-20 18:37:29 -070032var (
33 testPrincipalBlessing = "test"
34 testPrincipal = newPrincipal(testPrincipalBlessing)
Ankure7889242014-10-20 18:37:29 -070035)
36
37// newBlessedPrincipal returns a new principal that has a blessing from the
38// provided runtime's principal which is set on its BlessingStore such
39// that it is revealed to all clients and servers.
Matt Rosencrantz306d9902015-01-10 17:46:07 -080040func newBlessedPrincipal(ctx *context.T) security.Principal {
Ankure7889242014-10-20 18:37:29 -070041 p, err := vsecurity.NewPrincipal()
42 if err != nil {
43 panic(err)
44 }
Matt Rosencrantz306d9902015-01-10 17:46:07 -080045
Jiri Simsa1f1302c2015-02-23 16:18:34 -080046 principal := v23.GetPrincipal(ctx)
Matt Rosencrantz306d9902015-01-10 17:46:07 -080047 b, err := principal.Bless(p.PublicKey(), principal.BlessingStore().Default(), "delegate", security.UnconstrainedUse())
Ankure7889242014-10-20 18:37:29 -070048 if err != nil {
49 panic(err)
50 }
51 tsecurity.SetDefaultBlessings(p, b)
52 return p
53}
54
55// newPrincipal returns a new principal that has a self-blessing with
56// the provided extension 'selfBlessing' which is set on its BlessingStore
57// such that it is revealed to all clients and servers.
58func newPrincipal(selfBlessing string) security.Principal {
59 p, err := vsecurity.NewPrincipal()
60 if err != nil {
61 panic(err)
62 }
63 b, err := p.BlessSelf(selfBlessing)
64 if err != nil {
65 panic(err)
66 }
67 tsecurity.SetDefaultBlessings(p, b)
68 return p
69}
Jiri Simsa78b646f2014-10-08 10:23:05 -070070
71type simpleAdder struct{}
72
Matt Rosencrantz5c7ed212015-02-27 22:42:35 -080073func (s simpleAdder) Add(_ ipc.ServerCall, a, b int32) (int32, error) {
Jiri Simsa78b646f2014-10-08 10:23:05 -070074 return a + b, nil
75}
76
Matt Rosencrantz5c7ed212015-02-27 22:42:35 -080077func (s simpleAdder) Divide(_ ipc.ServerCall, a, b int32) (int32, error) {
Jiri Simsa78b646f2014-10-08 10:23:05 -070078 if b == 0 {
Jiri Simsa94f68d02015-02-17 10:22:08 -080079 return 0, verror.New(verror.ErrBadArg, nil, "div 0")
Jiri Simsa78b646f2014-10-08 10:23:05 -070080 }
81 return a / b, nil
82}
83
Matt Rosencrantz1dcd0a92015-02-27 11:05:59 -080084func (s simpleAdder) StreamingAdd(call ipc.StreamServerCall) (int32, error) {
Jiri Simsa78b646f2014-10-08 10:23:05 -070085 total := int32(0)
86 var value int32
87 for err := call.Recv(&value); err == nil; err = call.Recv(&value) {
88 total += value
89 call.Send(total)
90 }
91 return total, nil
92}
93
Todd Wang72ef57b2015-01-08 10:23:21 -080094var simpleAddrSig = signature.Interface{
95 Doc: "The empty interface contains methods not attached to any interface.",
96 Methods: []signature.Method{
97 {
98 Name: "Add",
99 InArgs: []signature.Arg{{Type: vdl.Int32Type}, {Type: vdl.Int32Type}},
Benjamin Prosnitz518af1e2015-01-20 14:20:10 -0800100 OutArgs: []signature.Arg{{Type: vdl.Int32Type}},
Todd Wang72ef57b2015-01-08 10:23:21 -0800101 },
102 {
103 Name: "Divide",
104 InArgs: []signature.Arg{{Type: vdl.Int32Type}, {Type: vdl.Int32Type}},
Benjamin Prosnitz518af1e2015-01-20 14:20:10 -0800105 OutArgs: []signature.Arg{{Type: vdl.Int32Type}},
Todd Wang72ef57b2015-01-08 10:23:21 -0800106 },
107 {
108 Name: "StreamingAdd",
Benjamin Prosnitz518af1e2015-01-20 14:20:10 -0800109 OutArgs: []signature.Arg{{Type: vdl.Int32Type}},
Todd Wang72ef57b2015-01-08 10:23:21 -0800110 InStream: &signature.Arg{Type: vdl.AnyType},
111 OutStream: &signature.Arg{Type: vdl.AnyType},
Jiri Simsa78b646f2014-10-08 10:23:05 -0700112 },
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800113 },
Jiri Simsa78b646f2014-10-08 10:23:05 -0700114}
115
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800116func startAnyServer(ctx *context.T, servesMT bool, dispatcher ipc.Dispatcher) (ipc.Server, naming.Endpoint, error) {
Jiri Simsa78b646f2014-10-08 10:23:05 -0700117 // Create a new server instance.
Jiri Simsa1f1302c2015-02-23 16:18:34 -0800118 s, err := v23.NewServer(ctx, options.ServesMountTable(servesMT))
Jiri Simsa78b646f2014-10-08 10:23:05 -0700119 if err != nil {
120 return nil, nil, err
121 }
122
Jiri Simsa1f1302c2015-02-23 16:18:34 -0800123 endpoints, err := s.Listen(v23.GetListenSpec(ctx))
Jiri Simsa78b646f2014-10-08 10:23:05 -0700124 if err != nil {
125 return nil, nil, err
126 }
127
Cosmos Nicolaou4619b1f2014-11-05 07:23:13 -0800128 if err := s.ServeDispatcher("", dispatcher); err != nil {
Jiri Simsa78b646f2014-10-08 10:23:05 -0700129 return nil, nil, err
130 }
Cosmos Nicolaoud48178c2014-12-15 22:51:52 -0800131 return s, endpoints[0], nil
Jiri Simsa78b646f2014-10-08 10:23:05 -0700132}
133
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800134func startAdderServer(ctx *context.T) (ipc.Server, naming.Endpoint, error) {
135 return startAnyServer(ctx, false, testutil.LeafDispatcher(simpleAdder{}, nil))
Jiri Simsa78b646f2014-10-08 10:23:05 -0700136}
137
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800138func startMountTableServer(ctx *context.T) (ipc.Server, naming.Endpoint, error) {
Bogdan Capritaa25b6c22015-02-03 17:30:21 -0800139 mt, err := mounttable.NewMountTableDispatcher("")
Jiri Simsa78b646f2014-10-08 10:23:05 -0700140 if err != nil {
141 return nil, nil, err
142 }
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800143 return startAnyServer(ctx, true, mt)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700144}
145
Jiri Simsa78b646f2014-10-08 10:23:05 -0700146func TestGetGoServerSignature(t *testing.T) {
Ankur9dec6d62015-01-30 15:07:01 -0800147 ctx, shutdown := testutil.InitForTest()
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800148 defer shutdown()
149
150 s, endpoint, err := startAdderServer(ctx)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700151 if err != nil {
152 t.Errorf("unable to start server: %v", err)
153 t.Fail()
154 return
155 }
156 defer s.Stop()
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800157
Jiri Simsa1f1302c2015-02-23 16:18:34 -0800158 spec := v23.GetListenSpec(ctx)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700159 spec.Proxy = "mockVeyronProxyEP"
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800160 controller, err := NewController(ctx, nil, &spec, nil, newBlessedPrincipal(ctx))
Jiri Simsa78b646f2014-10-08 10:23:05 -0700161
162 if err != nil {
Ankure7889242014-10-20 18:37:29 -0700163 t.Fatalf("Failed to create controller: %v", err)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700164 }
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800165 sig, err := controller.getSignature(ctx, "/"+endpoint.String())
Jiri Simsa78b646f2014-10-08 10:23:05 -0700166 if err != nil {
Ankure7889242014-10-20 18:37:29 -0700167 t.Fatalf("Failed to get signature: %v", err)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700168 }
Todd Wang72ef57b2015-01-08 10:23:21 -0800169 if got, want := len(sig), 2; got != want {
170 t.Fatalf("got signature %#v len %d, want %d", sig, got, want)
171 }
172 if got, want := sig[0], simpleAddrSig; !reflect.DeepEqual(got, want) {
173 t.Errorf("got sig[0] %#v, want: %#v", got, want)
174 }
175 if got, want := sig[1].Name, "__Reserved"; got != want {
176 t.Errorf("got sig[1].Name %#v, want: %#v", got, want)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700177 }
178}
179
180type goServerTestCase struct {
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800181 method string
Matt Rosencrantz786f7272015-02-11 15:18:07 -0800182 inArgs []interface{}
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800183 numOutArgs int32
184 streamingInputs []interface{}
185 expectedStream []lib.Response
186 expectedError error
Jiri Simsa78b646f2014-10-08 10:23:05 -0700187}
188
189func runGoServerTestCase(t *testing.T, test goServerTestCase) {
Ankur9dec6d62015-01-30 15:07:01 -0800190 ctx, shutdown := testutil.InitForTest()
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800191 defer shutdown()
192
193 s, endpoint, err := startAdderServer(ctx)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700194 if err != nil {
195 t.Errorf("unable to start server: %v", err)
196 t.Fail()
197 return
198 }
199 defer s.Stop()
Cosmos Nicolaou408de0f2014-10-24 13:32:29 -0700200
Jiri Simsa1f1302c2015-02-23 16:18:34 -0800201 spec := v23.GetListenSpec(ctx)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700202 spec.Proxy = "mockVeyronProxyEP"
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800203 controller, err := NewController(ctx, nil, &spec, nil, newBlessedPrincipal(ctx))
Jiri Simsa78b646f2014-10-08 10:23:05 -0700204
205 if err != nil {
206 t.Errorf("unable to create controller: %v", err)
207 t.Fail()
208 return
209 }
Jiri Simsa78b646f2014-10-08 10:23:05 -0700210 writer := testwriter.Writer{}
211 var stream *outstandingStream
212 if len(test.streamingInputs) > 0 {
213 stream = newStream()
Matt Rosencrantz4aabe572014-10-22 09:25:50 -0700214 controller.outstandingRequests[0] = &outstandingRequest{
215 stream: stream,
216 }
Jiri Simsa78b646f2014-10-08 10:23:05 -0700217 go func() {
218 for _, value := range test.streamingInputs {
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800219 controller.SendOnStream(0, lib.VomEncodeOrDie(value), &writer)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700220 }
221 controller.CloseStream(0)
222 }()
223 }
224
Matt Rosencrantzac1e3a82015-02-12 16:04:28 -0800225 request := VeyronRPCRequest{
Jiri Simsa78b646f2014-10-08 10:23:05 -0700226 Name: "/" + endpoint.String(),
227 Method: test.method,
Matt Rosencrantz786f7272015-02-11 15:18:07 -0800228 NumInArgs: int32(len(test.inArgs)),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700229 NumOutArgs: test.numOutArgs,
230 IsStreaming: stream != nil,
231 }
Matt Rosencrantzac1e3a82015-02-12 16:04:28 -0800232 controller.sendVeyronRequest(ctx, 0, &request, test.inArgs, &writer, stream, vtrace.GetSpan(ctx))
Jiri Simsa78b646f2014-10-08 10:23:05 -0700233
Matt Rosencrantz4aabe572014-10-22 09:25:50 -0700234 if err := testwriter.CheckResponses(&writer, test.expectedStream, test.expectedError); err != nil {
235 t.Error(err)
236 }
Jiri Simsa78b646f2014-10-08 10:23:05 -0700237}
238
Todd Wang5ab03662015-02-19 21:03:01 -0800239func makeRPCResponse(outArgs ...*vdl.Value) string {
Matt Rosencrantzac1e3a82015-02-12 16:04:28 -0800240 return lib.VomEncodeOrDie(VeyronRPCResponse{
Matt Rosencrantz8fa0ea12015-02-24 14:17:50 -0800241 OutArgs: outArgs,
242 TraceResponse: vtrace.Response{},
Matt Rosencrantzac1e3a82015-02-12 16:04:28 -0800243 })
244}
245
Jiri Simsa78b646f2014-10-08 10:23:05 -0700246func TestCallingGoServer(t *testing.T) {
247 runGoServerTestCase(t, goServerTestCase{
248 method: "Add",
Matt Rosencrantz786f7272015-02-11 15:18:07 -0800249 inArgs: []interface{}{2, 3},
Benjamin Prosnitz518af1e2015-01-20 14:20:10 -0800250 numOutArgs: 1,
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800251 expectedStream: []lib.Response{
252 lib.Response{
Todd Wang5ab03662015-02-19 21:03:01 -0800253 Message: makeRPCResponse(vdl.Int32Value(5)),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700254 Type: lib.ResponseFinal,
255 },
256 },
257 })
258}
259
260func TestCallingGoServerWithError(t *testing.T) {
261 runGoServerTestCase(t, goServerTestCase{
262 method: "Divide",
Matt Rosencrantz786f7272015-02-11 15:18:07 -0800263 inArgs: []interface{}{1, 0},
Benjamin Prosnitz518af1e2015-01-20 14:20:10 -0800264 numOutArgs: 1,
Jiri Simsa94f68d02015-02-17 10:22:08 -0800265 expectedError: verror.New(verror.ErrBadArg, nil, "div 0"),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700266 })
267}
268
269func TestCallingGoWithStreaming(t *testing.T) {
270 runGoServerTestCase(t, goServerTestCase{
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800271 method: "StreamingAdd",
272 streamingInputs: []interface{}{1, 2, 3, 4},
Benjamin Prosnitz518af1e2015-01-20 14:20:10 -0800273 numOutArgs: 1,
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800274 expectedStream: []lib.Response{
275 lib.Response{
276 Message: lib.VomEncodeOrDie(int32(1)),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700277 Type: lib.ResponseStream,
278 },
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800279 lib.Response{
280 Message: lib.VomEncodeOrDie(int32(3)),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700281 Type: lib.ResponseStream,
282 },
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800283 lib.Response{
284 Message: lib.VomEncodeOrDie(int32(6)),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700285 Type: lib.ResponseStream,
286 },
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800287 lib.Response{
288 Message: lib.VomEncodeOrDie(int32(10)),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700289 Type: lib.ResponseStream,
290 },
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800291 lib.Response{
Jiri Simsa78b646f2014-10-08 10:23:05 -0700292 Message: nil,
293 Type: lib.ResponseStreamClose,
294 },
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800295 lib.Response{
Todd Wang5ab03662015-02-19 21:03:01 -0800296 Message: makeRPCResponse(vdl.Int32Value(10)),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700297 Type: lib.ResponseFinal,
298 },
299 },
300 })
301}
302
303type runningTest struct {
304 controller *Controller
305 writer *testwriter.Writer
306 mounttableServer ipc.Server
Matt Rosencrantz2b675f92015-03-05 12:52:50 -0800307 proxyShutdown func()
Jiri Simsa78b646f2014-10-08 10:23:05 -0700308}
309
Matt Rosencrantzac1e3a82015-02-12 16:04:28 -0800310func makeRequest(rpc VeyronRPCRequest, args ...interface{}) (string, error) {
Matt Rosencrantz786f7272015-02-11 15:18:07 -0800311 var buf bytes.Buffer
Todd Wangf619d432015-02-18 11:19:27 -0800312 encoder, err := vom.NewEncoder(&buf)
Matt Rosencrantz786f7272015-02-11 15:18:07 -0800313 if err != nil {
314 return "", err
315 }
316 if err := encoder.Encode(rpc); err != nil {
317 return "", err
318 }
319 for _, arg := range args {
320 if err := encoder.Encode(arg); err != nil {
321 return "", err
322 }
323 }
324 return hex.EncodeToString(buf.Bytes()), nil
325}
326
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800327func serveServer(ctx *context.T, writer lib.ClientWriter, setController func(*Controller)) (*runningTest, error) {
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800328 mounttableServer, endpoint, err := startMountTableServer(ctx)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700329 if err != nil {
330 return nil, fmt.Errorf("unable to start mounttable: %v", err)
331 }
332
Matt Rosencrantz2b675f92015-03-05 12:52:50 -0800333 proxyShutdown, proxyEndpoint, err := profiles.NewProxy(ctx, "tcp", "127.0.0.1:0", "")
Jiri Simsa78b646f2014-10-08 10:23:05 -0700334 if err != nil {
335 return nil, fmt.Errorf("unable to start proxy: %v", err)
336 }
337
Benjamin Prosnitz86d52282014-12-19 15:48:38 -0800338 writerCreator := func(int32) lib.ClientWriter {
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800339 return writer
Jiri Simsa78b646f2014-10-08 10:23:05 -0700340 }
Jiri Simsa1f1302c2015-02-23 16:18:34 -0800341 spec := v23.GetListenSpec(ctx)
Matt Rosencrantz2b675f92015-03-05 12:52:50 -0800342 spec.Proxy = proxyEndpoint.Name()
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800343 controller, err := NewController(ctx, writerCreator, &spec, nil, testPrincipal)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700344 if err != nil {
345 return nil, err
346 }
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800347
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800348 if setController != nil {
349 setController(controller)
350 }
351
Jiri Simsa1f1302c2015-02-23 16:18:34 -0800352 v23.GetNamespace(controller.Context()).SetRoots("/" + endpoint.String())
Jiri Simsa78b646f2014-10-08 10:23:05 -0700353
Matt Rosencrantzac1e3a82015-02-12 16:04:28 -0800354 req, err := makeRequest(VeyronRPCRequest{
Matt Rosencrantz9d2170b2015-02-21 16:19:53 -0800355 Name: "__controller",
Matt Rosencrantz786f7272015-02-11 15:18:07 -0800356 Method: "Serve",
357 NumInArgs: 2,
358 NumOutArgs: 1,
359 Timeout: 20000000000,
360 }, "adder", 0)
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800361 controller.HandleVeyronRequest(ctx, 0, req, writer)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700362
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800363 testWriter, _ := writer.(*testwriter.Writer)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700364 return &runningTest{
Matt Rosencrantz2b675f92015-03-05 12:52:50 -0800365 controller, testWriter, mounttableServer, proxyShutdown,
Jiri Simsa78b646f2014-10-08 10:23:05 -0700366 }, nil
367}
368
Jiri Simsa78b646f2014-10-08 10:23:05 -0700369// A test case to simulate a Javascript server talking to the App. All the
370// responses from Javascript are mocked and sent back through the method calls.
371// All messages from the client are sent using a go client.
372type jsServerTestCase struct {
373 method string
374 inArgs []interface{}
375 // The set of streaming inputs from the client to the server.
376 // This is passed to the client, which then passes it to the app.
377 clientStream []interface{}
378 // The set of JSON streaming messages sent from Javascript to the
379 // app.
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800380 serverStream []interface{}
Jiri Simsa78b646f2014-10-08 10:23:05 -0700381 // The final response sent by the Javascript server to the
382 // app.
Todd Wang5ab03662015-02-19 21:03:01 -0800383 finalResponse *vdl.Value
Jiri Simsa78b646f2014-10-08 10:23:05 -0700384 // The final error sent by the Javascript server to the app.
Mike Burrowsa727df72015-02-04 17:26:46 -0800385 err error
Jiri Simsa78b646f2014-10-08 10:23:05 -0700386
387 // Whether or not the Javascript server has an authorizer or not.
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800388 // If it does have an authorizer, then err is sent back from the server
Jiri Simsa78b646f2014-10-08 10:23:05 -0700389 // to the app.
390 hasAuthorizer bool
Jiri Simsa78b646f2014-10-08 10:23:05 -0700391}
392
Jiri Simsa78b646f2014-10-08 10:23:05 -0700393func runJsServerTestCase(t *testing.T, test jsServerTestCase) {
Ankur9dec6d62015-01-30 15:07:01 -0800394 ctx, shutdown := testutil.InitForTest()
Suharsh Sivakumar94d00662015-01-21 14:31:30 -0800395 defer shutdown()
396
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800397 vomClientStream := []string{}
398 for _, m := range test.clientStream {
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800399 vomClientStream = append(vomClientStream, lib.VomEncodeOrDie(m))
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800400 }
401 mock := &mockJSServer{
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800402 t: t,
403 method: test.method,
Todd Wang72ef57b2015-01-08 10:23:21 -0800404 serviceSignature: []signature.Interface{simpleAddrSig},
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800405 expectedClientStream: vomClientStream,
406 serverStream: test.serverStream,
407 hasAuthorizer: test.hasAuthorizer,
Shyam Jayaraman907219d2014-11-26 12:14:37 -0800408 inArgs: test.inArgs,
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800409 finalResponse: test.finalResponse,
410 finalError: test.err,
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800411 controllerReady: sync.RWMutex{},
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800412 }
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800413 rt, err := serveServer(ctx, mock, func(controller *Controller) {
414 mock.controller = controller
415 })
416 defer rt.mounttableServer.Stop()
Matt Rosencrantz2b675f92015-03-05 12:52:50 -0800417 defer rt.proxyShutdown()
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800418 defer rt.controller.Cleanup()
419
420 if err != nil {
421 t.Fatalf("could not serve server %v", err)
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800422 }
423
Matt Rosencrantzc90eb7b2015-01-09 08:32:01 -0800424 // Get the client that is relevant to the controller so it talks
425 // to the right mounttable.
Jiri Simsa1f1302c2015-02-23 16:18:34 -0800426 client := v23.GetClient(rt.controller.Context())
Jiri Simsa78b646f2014-10-08 10:23:05 -0700427
428 if err != nil {
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800429 t.Fatalf("unable to create client: %v", err)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700430 }
431
Matt Rosencrantzc90eb7b2015-01-09 08:32:01 -0800432 call, err := client.StartCall(rt.controller.Context(), "adder/adder", test.method, test.inArgs)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700433 if err != nil {
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800434 t.Fatalf("failed to start call: %v", err)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700435 }
436
Jiri Simsa78b646f2014-10-08 10:23:05 -0700437 for _, msg := range test.clientStream {
Jiri Simsa78b646f2014-10-08 10:23:05 -0700438 if err := call.Send(msg); err != nil {
439 t.Errorf("unexpected error while sending %v: %v", msg, err)
440 }
441 }
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800442 if err := call.CloseSend(); err != nil {
443 t.Errorf("unexpected error on close: %v", err)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700444 }
445
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800446 expectedStream := test.serverStream
Jiri Simsa78b646f2014-10-08 10:23:05 -0700447 for {
448 var data interface{}
449 if err := call.Recv(&data); err != nil {
450 break
451 }
452 if len(expectedStream) == 0 {
453 t.Errorf("unexpected stream value: %v", data)
454 continue
455 }
456 if !reflect.DeepEqual(data, expectedStream[0]) {
457 t.Errorf("unexpected stream value: got %v, expected %v", data, expectedStream[0])
458 }
459 expectedStream = expectedStream[1:]
460 }
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800461
Todd Wang5ab03662015-02-19 21:03:01 -0800462 var result *vdl.Value
Todd Wangf21e1552015-02-18 13:21:52 -0800463 err = call.Finish(&result)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700464
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800465 // If err is nil and test.err is nil reflect.DeepEqual will return
466 // false because the types are different. Because of this, we only use
467 // reflect.DeepEqual if one of the values is non-nil. If both values
468 // are nil, then we consider them equal.
469 if (err != nil || test.err != nil) && !verror.Equal(err, test.err) {
470 t.Errorf("unexpected err: got %#v, expected %#v", err, test.err)
471 }
472
473 if err != nil {
474 return
Shyam Jayaramane56df9a2014-11-20 17:38:54 -0800475 }
Nicolas LaCassed7ab8a12015-02-03 11:46:29 -0800476
Todd Wang5ab03662015-02-19 21:03:01 -0800477 if got, want := result, test.finalResponse; !vdl.EqualValue(got, want) {
478 t.Errorf("unexected final response: got %v, want %v", got, want)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700479 }
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800480
481 // ensure there is only one server and then stop the server
482 if len(rt.controller.servers) != 1 {
483 t.Errorf("expected only one server but got: %d", len(rt.controller.servers))
484 return
485 }
486 for serverId := range rt.controller.servers {
487 rt.controller.Stop(nil, serverId)
488 }
489
490 // ensure there is no more servers now
491 if len(rt.controller.servers) != 0 {
492 t.Errorf("expected no server after stopping the only one but got: %d", len(rt.controller.servers))
493 return
494 }
Jiri Simsa78b646f2014-10-08 10:23:05 -0700495}
496
497func TestSimpleJSServer(t *testing.T) {
498 runJsServerTestCase(t, jsServerTestCase{
499 method: "Add",
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800500 inArgs: []interface{}{int32(1), int32(2)},
Todd Wang5ab03662015-02-19 21:03:01 -0800501 finalResponse: vdl.Int32Value(3),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700502 })
503}
504
505func TestJSServerWithAuthorizer(t *testing.T) {
506 runJsServerTestCase(t, jsServerTestCase{
507 method: "Add",
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800508 inArgs: []interface{}{int32(1), int32(2)},
Todd Wang5ab03662015-02-19 21:03:01 -0800509 finalResponse: vdl.Int32Value(3),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700510 hasAuthorizer: true,
511 })
512}
513
514func TestJSServerWithError(t *testing.T) {
Jiri Simsa94f68d02015-02-17 10:22:08 -0800515 err := verror.New(verror.ErrInternal, nil)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700516 runJsServerTestCase(t, jsServerTestCase{
Nicolas LaCassed7ab8a12015-02-03 11:46:29 -0800517 method: "Divide",
518 inArgs: []interface{}{int32(1), int32(0)},
519 err: err,
Jiri Simsa78b646f2014-10-08 10:23:05 -0700520 })
521}
522
523func TestJSServerWithAuthorizerAndAuthError(t *testing.T) {
Jiri Simsa94f68d02015-02-17 10:22:08 -0800524 err := verror.New(verror.ErrNoAccess, nil)
Jiri Simsa78b646f2014-10-08 10:23:05 -0700525 runJsServerTestCase(t, jsServerTestCase{
526 method: "Add",
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800527 inArgs: []interface{}{int32(1), int32(2)},
Jiri Simsa78b646f2014-10-08 10:23:05 -0700528 hasAuthorizer: true,
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800529 finalResponse: vdl.Int32Value(3),
530 err: err,
Jiri Simsa78b646f2014-10-08 10:23:05 -0700531 })
532}
533func TestJSServerWihStreamingInputs(t *testing.T) {
534 runJsServerTestCase(t, jsServerTestCase{
535 method: "StreamingAdd",
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800536 clientStream: []interface{}{int32(3), int32(4)},
Todd Wang5ab03662015-02-19 21:03:01 -0800537 finalResponse: vdl.Int32Value(10),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700538 })
539}
540
541func TestJSServerWihStreamingOutputs(t *testing.T) {
542 runJsServerTestCase(t, jsServerTestCase{
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800543 method: "StreamingAdd",
544 serverStream: []interface{}{int32(3), int32(4)},
Todd Wang5ab03662015-02-19 21:03:01 -0800545 finalResponse: vdl.Int32Value(10),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700546 })
547}
548
549func TestJSServerWihStreamingInputsAndOutputs(t *testing.T) {
550 runJsServerTestCase(t, jsServerTestCase{
Benjamin Prosnitza2ac3b32014-12-12 11:40:31 -0800551 method: "StreamingAdd",
552 clientStream: []interface{}{int32(1), int32(2)},
553 serverStream: []interface{}{int32(3), int32(4)},
Todd Wang5ab03662015-02-19 21:03:01 -0800554 finalResponse: vdl.Int32Value(10),
Jiri Simsa78b646f2014-10-08 10:23:05 -0700555 })
556}
Nicolas LaCassed7ab8a12015-02-03 11:46:29 -0800557
558func TestJSServerWithWrongNumberOfArgs(t *testing.T) {
Todd Wangb63e9eb2015-02-10 19:57:39 -0800559 err := verror.New(server.ErrWrongNumberOfArgs, nil, "Add", 3, 2)
Nicolas LaCassed7ab8a12015-02-03 11:46:29 -0800560 runJsServerTestCase(t, jsServerTestCase{
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800561 method: "Add",
562 inArgs: []interface{}{int32(1), int32(2), int32(3)},
563 err: err,
Nicolas LaCassed7ab8a12015-02-03 11:46:29 -0800564 })
565}
566
567func TestJSServerWithMethodNotFound(t *testing.T) {
568 methodName := "UnknownMethod"
Todd Wangb63e9eb2015-02-10 19:57:39 -0800569 err := verror.New(server.ErrMethodNotFoundInSignature, nil, methodName)
Nicolas LaCassed7ab8a12015-02-03 11:46:29 -0800570 runJsServerTestCase(t, jsServerTestCase{
Benjamin Prosnitze8e2b9b2015-02-24 12:55:25 -0800571 method: methodName,
572 inArgs: []interface{}{int32(1), int32(2)},
573 err: err,
Nicolas LaCassed7ab8a12015-02-03 11:46:29 -0800574 })
575}