Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 1 | package app |
| 2 | |
| 3 | import ( |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 4 | "fmt" |
| 5 | "reflect" |
| 6 | "testing" |
| 7 | |
Jiri Simsa | 22b87ac | 2014-12-25 20:59:13 -0800 | [diff] [blame] | 8 | "v.io/core/veyron2" |
Matt Rosencrantz | 306d990 | 2015-01-10 17:46:07 -0800 | [diff] [blame] | 9 | "v.io/core/veyron2/context" |
Jiri Simsa | 22b87ac | 2014-12-25 20:59:13 -0800 | [diff] [blame] | 10 | "v.io/core/veyron2/ipc" |
| 11 | "v.io/core/veyron2/naming" |
| 12 | "v.io/core/veyron2/options" |
| 13 | "v.io/core/veyron2/rt" |
| 14 | "v.io/core/veyron2/security" |
| 15 | "v.io/core/veyron2/vdl" |
| 16 | "v.io/core/veyron2/vdl/vdlroot/src/signature" |
| 17 | "v.io/core/veyron2/verror2" |
Jiri Simsa | 1127716 | 2014-12-25 15:50:27 -0800 | [diff] [blame] | 18 | "v.io/wspr/veyron/services/wsprd/lib" |
| 19 | "v.io/wspr/veyron/services/wsprd/lib/testwriter" |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 20 | |
Bogdan Caprita | 38773f3 | 2015-01-08 13:47:57 -0800 | [diff] [blame] | 21 | "v.io/core/veyron/lib/testutil" |
Jiri Simsa | 22b87ac | 2014-12-25 20:59:13 -0800 | [diff] [blame] | 22 | tsecurity "v.io/core/veyron/lib/testutil/security" |
| 23 | "v.io/core/veyron/profiles" |
| 24 | "v.io/core/veyron/runtimes/google/ipc/stream/proxy" |
| 25 | vsecurity "v.io/core/veyron/security" |
| 26 | mounttable "v.io/core/veyron/services/mounttable/lib" |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 27 | ) |
| 28 | |
Ankur | e788924 | 2014-10-20 18:37:29 -0700 | [diff] [blame] | 29 | var ( |
| 30 | testPrincipalBlessing = "test" |
| 31 | testPrincipal = newPrincipal(testPrincipalBlessing) |
Matt Rosencrantz | 306d990 | 2015-01-10 17:46:07 -0800 | [diff] [blame] | 32 | gctx *context.T |
Ankur | e788924 | 2014-10-20 18:37:29 -0700 | [diff] [blame] | 33 | ) |
| 34 | |
Matt Rosencrantz | 2ffef74 | 2014-12-04 09:51:40 -0800 | [diff] [blame] | 35 | func init() { |
| 36 | var err error |
Matt Rosencrantz | 306d990 | 2015-01-10 17:46:07 -0800 | [diff] [blame] | 37 | r, err := rt.New() |
| 38 | if err != nil { |
Matt Rosencrantz | 2ffef74 | 2014-12-04 09:51:40 -0800 | [diff] [blame] | 39 | panic(err) |
| 40 | } |
Matt Rosencrantz | 306d990 | 2015-01-10 17:46:07 -0800 | [diff] [blame] | 41 | gctx = r.NewContext() |
Matt Rosencrantz | 2ffef74 | 2014-12-04 09:51:40 -0800 | [diff] [blame] | 42 | } |
| 43 | |
Ankur | e788924 | 2014-10-20 18:37:29 -0700 | [diff] [blame] | 44 | // newBlessedPrincipal returns a new principal that has a blessing from the |
| 45 | // provided runtime's principal which is set on its BlessingStore such |
| 46 | // that it is revealed to all clients and servers. |
Matt Rosencrantz | 306d990 | 2015-01-10 17:46:07 -0800 | [diff] [blame] | 47 | func newBlessedPrincipal(ctx *context.T) security.Principal { |
Ankur | e788924 | 2014-10-20 18:37:29 -0700 | [diff] [blame] | 48 | p, err := vsecurity.NewPrincipal() |
| 49 | if err != nil { |
| 50 | panic(err) |
| 51 | } |
Matt Rosencrantz | 306d990 | 2015-01-10 17:46:07 -0800 | [diff] [blame] | 52 | |
| 53 | principal := veyron2.GetPrincipal(ctx) |
| 54 | b, err := principal.Bless(p.PublicKey(), principal.BlessingStore().Default(), "delegate", security.UnconstrainedUse()) |
Ankur | e788924 | 2014-10-20 18:37:29 -0700 | [diff] [blame] | 55 | if err != nil { |
| 56 | panic(err) |
| 57 | } |
| 58 | tsecurity.SetDefaultBlessings(p, b) |
| 59 | return p |
| 60 | } |
| 61 | |
| 62 | // newPrincipal returns a new principal that has a self-blessing with |
| 63 | // the provided extension 'selfBlessing' which is set on its BlessingStore |
| 64 | // such that it is revealed to all clients and servers. |
| 65 | func newPrincipal(selfBlessing string) security.Principal { |
| 66 | p, err := vsecurity.NewPrincipal() |
| 67 | if err != nil { |
| 68 | panic(err) |
| 69 | } |
| 70 | b, err := p.BlessSelf(selfBlessing) |
| 71 | if err != nil { |
| 72 | panic(err) |
| 73 | } |
| 74 | tsecurity.SetDefaultBlessings(p, b) |
| 75 | return p |
| 76 | } |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 77 | |
| 78 | type simpleAdder struct{} |
| 79 | |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 80 | func (s simpleAdder) Add(_ ipc.ServerContext, a, b int32) (int32, error) { |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 81 | return a + b, nil |
| 82 | } |
| 83 | |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 84 | func (s simpleAdder) Divide(_ ipc.ServerContext, a, b int32) (int32, error) { |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 85 | if b == 0 { |
Mike Burrows | b6689c2 | 2014-10-08 11:14:15 -0700 | [diff] [blame] | 86 | return 0, verror2.Make(verror2.BadArg, nil, "div 0") |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 87 | } |
| 88 | return a / b, nil |
| 89 | } |
| 90 | |
| 91 | func (s simpleAdder) StreamingAdd(call ipc.ServerCall) (int32, error) { |
| 92 | total := int32(0) |
| 93 | var value int32 |
| 94 | for err := call.Recv(&value); err == nil; err = call.Recv(&value) { |
| 95 | total += value |
| 96 | call.Send(total) |
| 97 | } |
| 98 | return total, nil |
| 99 | } |
| 100 | |
Todd Wang | 72ef57b | 2015-01-08 10:23:21 -0800 | [diff] [blame] | 101 | var simpleAddrSig = signature.Interface{ |
| 102 | Doc: "The empty interface contains methods not attached to any interface.", |
| 103 | Methods: []signature.Method{ |
| 104 | { |
| 105 | Name: "Add", |
| 106 | InArgs: []signature.Arg{{Type: vdl.Int32Type}, {Type: vdl.Int32Type}}, |
Benjamin Prosnitz | 518af1e | 2015-01-20 14:20:10 -0800 | [diff] [blame^] | 107 | OutArgs: []signature.Arg{{Type: vdl.Int32Type}}, |
Todd Wang | 72ef57b | 2015-01-08 10:23:21 -0800 | [diff] [blame] | 108 | }, |
| 109 | { |
| 110 | Name: "Divide", |
| 111 | InArgs: []signature.Arg{{Type: vdl.Int32Type}, {Type: vdl.Int32Type}}, |
Benjamin Prosnitz | 518af1e | 2015-01-20 14:20:10 -0800 | [diff] [blame^] | 112 | OutArgs: []signature.Arg{{Type: vdl.Int32Type}}, |
Todd Wang | 72ef57b | 2015-01-08 10:23:21 -0800 | [diff] [blame] | 113 | }, |
| 114 | { |
| 115 | Name: "StreamingAdd", |
Benjamin Prosnitz | 518af1e | 2015-01-20 14:20:10 -0800 | [diff] [blame^] | 116 | OutArgs: []signature.Arg{{Type: vdl.Int32Type}}, |
Todd Wang | 72ef57b | 2015-01-08 10:23:21 -0800 | [diff] [blame] | 117 | InStream: &signature.Arg{Type: vdl.AnyType}, |
| 118 | OutStream: &signature.Arg{Type: vdl.AnyType}, |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 119 | }, |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 120 | }, |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 121 | } |
| 122 | |
| 123 | func startAnyServer(servesMT bool, dispatcher ipc.Dispatcher) (ipc.Server, naming.Endpoint, error) { |
| 124 | // Create a new server instance. |
Matt Rosencrantz | 306d990 | 2015-01-10 17:46:07 -0800 | [diff] [blame] | 125 | s, err := veyron2.NewServer(gctx, options.ServesMountTable(servesMT)) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 126 | if err != nil { |
| 127 | return nil, nil, err |
| 128 | } |
| 129 | |
Cosmos Nicolaou | d48178c | 2014-12-15 22:51:52 -0800 | [diff] [blame] | 130 | endpoints, err := s.Listen(profiles.LocalListenSpec) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 131 | if err != nil { |
| 132 | return nil, nil, err |
| 133 | } |
| 134 | |
Cosmos Nicolaou | 4619b1f | 2014-11-05 07:23:13 -0800 | [diff] [blame] | 135 | if err := s.ServeDispatcher("", dispatcher); err != nil { |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 136 | return nil, nil, err |
| 137 | } |
Cosmos Nicolaou | d48178c | 2014-12-15 22:51:52 -0800 | [diff] [blame] | 138 | return s, endpoints[0], nil |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 139 | } |
| 140 | |
| 141 | func startAdderServer() (ipc.Server, naming.Endpoint, error) { |
Bogdan Caprita | 38773f3 | 2015-01-08 13:47:57 -0800 | [diff] [blame] | 142 | return startAnyServer(false, testutil.LeafDispatcher(simpleAdder{}, nil)) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 143 | } |
| 144 | |
| 145 | func startProxy() (*proxy.Proxy, error) { |
| 146 | rid, err := naming.NewRoutingID() |
| 147 | if err != nil { |
| 148 | return nil, err |
| 149 | } |
| 150 | return proxy.New(rid, nil, "tcp", "127.0.0.1:0", "") |
| 151 | } |
| 152 | |
| 153 | func startMountTableServer() (ipc.Server, naming.Endpoint, error) { |
| 154 | mt, err := mounttable.NewMountTable("") |
| 155 | if err != nil { |
| 156 | return nil, nil, err |
| 157 | } |
| 158 | return startAnyServer(true, mt) |
| 159 | } |
| 160 | |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 161 | func TestGetGoServerSignature(t *testing.T) { |
| 162 | s, endpoint, err := startAdderServer() |
| 163 | if err != nil { |
| 164 | t.Errorf("unable to start server: %v", err) |
| 165 | t.Fail() |
| 166 | return |
| 167 | } |
| 168 | defer s.Stop() |
Cosmos Nicolaou | 408de0f | 2014-10-24 13:32:29 -0700 | [diff] [blame] | 169 | spec := profiles.LocalListenSpec |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 170 | spec.Proxy = "mockVeyronProxyEP" |
Matt Rosencrantz | 306d990 | 2015-01-10 17:46:07 -0800 | [diff] [blame] | 171 | controller, err := NewController(nil, nil, &spec, nil, options.RuntimePrincipal{newBlessedPrincipal(gctx)}) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 172 | |
| 173 | if err != nil { |
Ankur | e788924 | 2014-10-20 18:37:29 -0700 | [diff] [blame] | 174 | t.Fatalf("Failed to create controller: %v", err) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 175 | } |
Matt Rosencrantz | 306d990 | 2015-01-10 17:46:07 -0800 | [diff] [blame] | 176 | sig, err := controller.getSignature(gctx, "/"+endpoint.String()) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 177 | if err != nil { |
Ankur | e788924 | 2014-10-20 18:37:29 -0700 | [diff] [blame] | 178 | t.Fatalf("Failed to get signature: %v", err) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 179 | } |
Todd Wang | 72ef57b | 2015-01-08 10:23:21 -0800 | [diff] [blame] | 180 | if got, want := len(sig), 2; got != want { |
| 181 | t.Fatalf("got signature %#v len %d, want %d", sig, got, want) |
| 182 | } |
| 183 | if got, want := sig[0], simpleAddrSig; !reflect.DeepEqual(got, want) { |
| 184 | t.Errorf("got sig[0] %#v, want: %#v", got, want) |
| 185 | } |
| 186 | if got, want := sig[1].Name, "__Reserved"; got != want { |
| 187 | t.Errorf("got sig[1].Name %#v, want: %#v", got, want) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 188 | } |
| 189 | } |
| 190 | |
| 191 | type goServerTestCase struct { |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 192 | method string |
| 193 | inArgs []interface{} |
| 194 | numOutArgs int32 |
| 195 | streamingInputs []interface{} |
| 196 | expectedStream []lib.Response |
| 197 | expectedError error |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 198 | } |
| 199 | |
| 200 | func runGoServerTestCase(t *testing.T, test goServerTestCase) { |
| 201 | s, endpoint, err := startAdderServer() |
| 202 | if err != nil { |
| 203 | t.Errorf("unable to start server: %v", err) |
| 204 | t.Fail() |
| 205 | return |
| 206 | } |
| 207 | defer s.Stop() |
Cosmos Nicolaou | 408de0f | 2014-10-24 13:32:29 -0700 | [diff] [blame] | 208 | |
| 209 | spec := profiles.LocalListenSpec |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 210 | spec.Proxy = "mockVeyronProxyEP" |
Matt Rosencrantz | 306d990 | 2015-01-10 17:46:07 -0800 | [diff] [blame] | 211 | controller, err := NewController(nil, nil, &spec, nil, options.RuntimePrincipal{newBlessedPrincipal(gctx)}) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 212 | |
| 213 | if err != nil { |
| 214 | t.Errorf("unable to create controller: %v", err) |
| 215 | t.Fail() |
| 216 | return |
| 217 | } |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 218 | writer := testwriter.Writer{} |
| 219 | var stream *outstandingStream |
| 220 | if len(test.streamingInputs) > 0 { |
| 221 | stream = newStream() |
Matt Rosencrantz | 4aabe57 | 2014-10-22 09:25:50 -0700 | [diff] [blame] | 222 | controller.outstandingRequests[0] = &outstandingRequest{ |
| 223 | stream: stream, |
| 224 | } |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 225 | go func() { |
| 226 | for _, value := range test.streamingInputs { |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 227 | controller.SendOnStream(0, lib.VomEncodeOrDie(value), &writer) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 228 | } |
| 229 | controller.CloseStream(0) |
| 230 | }() |
| 231 | } |
| 232 | |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 233 | request := VeyronRPC{ |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 234 | Name: "/" + endpoint.String(), |
| 235 | Method: test.method, |
| 236 | InArgs: test.inArgs, |
| 237 | NumOutArgs: test.numOutArgs, |
| 238 | IsStreaming: stream != nil, |
| 239 | } |
Matt Rosencrantz | 306d990 | 2015-01-10 17:46:07 -0800 | [diff] [blame] | 240 | controller.sendVeyronRequest(gctx, 0, &request, &writer, stream) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 241 | |
Matt Rosencrantz | 4aabe57 | 2014-10-22 09:25:50 -0700 | [diff] [blame] | 242 | if err := testwriter.CheckResponses(&writer, test.expectedStream, test.expectedError); err != nil { |
| 243 | t.Error(err) |
| 244 | } |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 245 | } |
| 246 | |
| 247 | func TestCallingGoServer(t *testing.T) { |
| 248 | runGoServerTestCase(t, goServerTestCase{ |
| 249 | method: "Add", |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 250 | inArgs: []interface{}{2, 3}, |
Benjamin Prosnitz | 518af1e | 2015-01-20 14:20:10 -0800 | [diff] [blame^] | 251 | numOutArgs: 1, |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 252 | expectedStream: []lib.Response{ |
| 253 | lib.Response{ |
| 254 | Message: lib.VomEncodeOrDie([]interface{}{int32(5)}), |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 255 | Type: lib.ResponseFinal, |
| 256 | }, |
| 257 | }, |
| 258 | }) |
| 259 | } |
| 260 | |
| 261 | func TestCallingGoServerWithError(t *testing.T) { |
| 262 | runGoServerTestCase(t, goServerTestCase{ |
| 263 | method: "Divide", |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 264 | inArgs: []interface{}{1, 0}, |
Benjamin Prosnitz | 518af1e | 2015-01-20 14:20:10 -0800 | [diff] [blame^] | 265 | numOutArgs: 1, |
Mike Burrows | b6689c2 | 2014-10-08 11:14:15 -0700 | [diff] [blame] | 266 | expectedError: verror2.Make(verror2.BadArg, nil, "div 0"), |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 267 | }) |
| 268 | } |
| 269 | |
| 270 | func TestCallingGoWithStreaming(t *testing.T) { |
| 271 | runGoServerTestCase(t, goServerTestCase{ |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 272 | method: "StreamingAdd", |
| 273 | streamingInputs: []interface{}{1, 2, 3, 4}, |
Benjamin Prosnitz | 518af1e | 2015-01-20 14:20:10 -0800 | [diff] [blame^] | 274 | numOutArgs: 1, |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 275 | expectedStream: []lib.Response{ |
| 276 | lib.Response{ |
| 277 | Message: lib.VomEncodeOrDie(int32(1)), |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 278 | Type: lib.ResponseStream, |
| 279 | }, |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 280 | lib.Response{ |
| 281 | Message: lib.VomEncodeOrDie(int32(3)), |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 282 | Type: lib.ResponseStream, |
| 283 | }, |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 284 | lib.Response{ |
| 285 | Message: lib.VomEncodeOrDie(int32(6)), |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 286 | Type: lib.ResponseStream, |
| 287 | }, |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 288 | lib.Response{ |
| 289 | Message: lib.VomEncodeOrDie(int32(10)), |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 290 | Type: lib.ResponseStream, |
| 291 | }, |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 292 | lib.Response{ |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 293 | Message: nil, |
| 294 | Type: lib.ResponseStreamClose, |
| 295 | }, |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 296 | lib.Response{ |
| 297 | Message: lib.VomEncodeOrDie([]interface{}{int32(10)}), |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 298 | Type: lib.ResponseFinal, |
| 299 | }, |
| 300 | }, |
| 301 | }) |
| 302 | } |
| 303 | |
| 304 | type runningTest struct { |
| 305 | controller *Controller |
| 306 | writer *testwriter.Writer |
| 307 | mounttableServer ipc.Server |
| 308 | proxyServer *proxy.Proxy |
| 309 | } |
| 310 | |
| 311 | func serveServer() (*runningTest, error) { |
| 312 | mounttableServer, endpoint, err := startMountTableServer() |
| 313 | |
| 314 | if err != nil { |
| 315 | return nil, fmt.Errorf("unable to start mounttable: %v", err) |
| 316 | } |
| 317 | |
| 318 | proxyServer, err := startProxy() |
| 319 | |
| 320 | if err != nil { |
| 321 | return nil, fmt.Errorf("unable to start proxy: %v", err) |
| 322 | } |
| 323 | |
| 324 | proxyEndpoint := proxyServer.Endpoint().String() |
| 325 | |
| 326 | writer := testwriter.Writer{} |
| 327 | |
Benjamin Prosnitz | 86d5228 | 2014-12-19 15:48:38 -0800 | [diff] [blame] | 328 | writerCreator := func(int32) lib.ClientWriter { |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 329 | return &writer |
| 330 | } |
Cosmos Nicolaou | 408de0f | 2014-10-24 13:32:29 -0700 | [diff] [blame] | 331 | spec := profiles.LocalListenSpec |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 332 | spec.Proxy = "/" + proxyEndpoint |
Shyam Jayaraman | 2a42ebe | 2014-11-19 08:54:45 -0800 | [diff] [blame] | 333 | controller, err := NewController(writerCreator, nil, &spec, nil, options.RuntimePrincipal{testPrincipal}) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 334 | |
| 335 | if err != nil { |
| 336 | return nil, err |
| 337 | } |
Matt Rosencrantz | c90eb7b | 2015-01-09 08:32:01 -0800 | [diff] [blame] | 338 | veyron2.GetNamespace(controller.Context()).SetRoots("/" + endpoint.String()) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 339 | |
| 340 | controller.serve(serveRequest{ |
| 341 | Name: "adder", |
| 342 | }, &writer) |
| 343 | |
| 344 | return &runningTest{ |
| 345 | controller, &writer, mounttableServer, proxyServer, |
| 346 | }, nil |
| 347 | } |
| 348 | |
| 349 | func TestJavascriptServeServer(t *testing.T) { |
| 350 | rt, err := serveServer() |
| 351 | defer rt.mounttableServer.Stop() |
| 352 | defer rt.proxyServer.Shutdown() |
| 353 | defer rt.controller.Cleanup() |
| 354 | if err != nil { |
| 355 | t.Fatalf("could not serve server %v", err) |
| 356 | } |
| 357 | |
| 358 | if len(rt.writer.Stream) != 1 { |
| 359 | t.Errorf("expected only one response, got %d", len(rt.writer.Stream)) |
| 360 | return |
| 361 | } |
| 362 | |
| 363 | resp := rt.writer.Stream[0] |
| 364 | |
| 365 | if resp.Type != lib.ResponseFinal { |
| 366 | t.Errorf("unknown stream message Got: %v, expected: serve response", resp) |
| 367 | return |
| 368 | } |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 369 | } |
| 370 | |
| 371 | func TestJavascriptStopServer(t *testing.T) { |
| 372 | rt, err := serveServer() |
| 373 | defer rt.mounttableServer.Stop() |
| 374 | defer rt.proxyServer.Shutdown() |
| 375 | defer rt.controller.Cleanup() |
| 376 | |
| 377 | if err != nil { |
| 378 | t.Errorf("could not serve server %v", err) |
| 379 | return |
| 380 | } |
| 381 | |
| 382 | // ensure there is only one server and then stop the server |
| 383 | if len(rt.controller.servers) != 1 { |
| 384 | t.Errorf("expected only one server but got: %d", len(rt.controller.servers)) |
| 385 | return |
| 386 | } |
| 387 | for serverId := range rt.controller.servers { |
| 388 | rt.controller.removeServer(serverId) |
| 389 | } |
| 390 | |
| 391 | // ensure there is no more servers now |
| 392 | if len(rt.controller.servers) != 0 { |
| 393 | t.Errorf("expected no server after stopping the only one but got: %d", len(rt.controller.servers)) |
| 394 | return |
| 395 | } |
| 396 | |
| 397 | return |
| 398 | } |
| 399 | |
| 400 | // A test case to simulate a Javascript server talking to the App. All the |
| 401 | // responses from Javascript are mocked and sent back through the method calls. |
| 402 | // All messages from the client are sent using a go client. |
| 403 | type jsServerTestCase struct { |
| 404 | method string |
| 405 | inArgs []interface{} |
| 406 | // The set of streaming inputs from the client to the server. |
| 407 | // This is passed to the client, which then passes it to the app. |
| 408 | clientStream []interface{} |
| 409 | // The set of JSON streaming messages sent from Javascript to the |
| 410 | // app. |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 411 | serverStream []interface{} |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 412 | // The final response sent by the Javascript server to the |
| 413 | // app. |
| 414 | finalResponse interface{} |
| 415 | // The final error sent by the Javascript server to the app. |
Mike Burrows | b6689c2 | 2014-10-08 11:14:15 -0700 | [diff] [blame] | 416 | err verror2.E |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 417 | |
| 418 | // Whether or not the Javascript server has an authorizer or not. |
| 419 | // If it does have an authorizer, then authError is sent back from the server |
| 420 | // to the app. |
| 421 | hasAuthorizer bool |
Mike Burrows | b6689c2 | 2014-10-08 11:14:15 -0700 | [diff] [blame] | 422 | authError verror2.E |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 423 | } |
| 424 | |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 425 | func runJsServerTestCase(t *testing.T, test jsServerTestCase) { |
| 426 | rt, err := serveServer() |
| 427 | defer rt.mounttableServer.Stop() |
| 428 | defer rt.proxyServer.Shutdown() |
| 429 | defer rt.controller.Cleanup() |
| 430 | |
| 431 | if err != nil { |
| 432 | t.Errorf("could not serve server %v", err) |
| 433 | } |
| 434 | |
| 435 | if len(rt.writer.Stream) != 1 { |
| 436 | t.Errorf("expected only on response, got %d", len(rt.writer.Stream)) |
| 437 | return |
| 438 | } |
| 439 | |
| 440 | resp := rt.writer.Stream[0] |
| 441 | |
| 442 | if resp.Type != lib.ResponseFinal { |
| 443 | t.Errorf("unknown stream message Got: %v, expected: serve response", resp) |
| 444 | return |
| 445 | } |
| 446 | |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 447 | rt.writer.Stream = nil |
| 448 | |
Shyam Jayaraman | e56df9a | 2014-11-20 17:38:54 -0800 | [diff] [blame] | 449 | vomClientStream := []string{} |
| 450 | for _, m := range test.clientStream { |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 451 | vomClientStream = append(vomClientStream, lib.VomEncodeOrDie(m)) |
Shyam Jayaraman | e56df9a | 2014-11-20 17:38:54 -0800 | [diff] [blame] | 452 | } |
| 453 | mock := &mockJSServer{ |
| 454 | controller: rt.controller, |
| 455 | t: t, |
| 456 | method: test.method, |
Todd Wang | 72ef57b | 2015-01-08 10:23:21 -0800 | [diff] [blame] | 457 | serviceSignature: []signature.Interface{simpleAddrSig}, |
Shyam Jayaraman | e56df9a | 2014-11-20 17:38:54 -0800 | [diff] [blame] | 458 | expectedClientStream: vomClientStream, |
| 459 | serverStream: test.serverStream, |
| 460 | hasAuthorizer: test.hasAuthorizer, |
| 461 | authError: test.authError, |
Shyam Jayaraman | 907219d | 2014-11-26 12:14:37 -0800 | [diff] [blame] | 462 | inArgs: test.inArgs, |
Shyam Jayaraman | e56df9a | 2014-11-20 17:38:54 -0800 | [diff] [blame] | 463 | finalResponse: test.finalResponse, |
| 464 | finalError: test.err, |
| 465 | } |
| 466 | // Let's replace the test writer with the mockJSServer |
Benjamin Prosnitz | 86d5228 | 2014-12-19 15:48:38 -0800 | [diff] [blame] | 467 | rt.controller.writerCreator = func(int32) lib.ClientWriter { |
Shyam Jayaraman | e56df9a | 2014-11-20 17:38:54 -0800 | [diff] [blame] | 468 | return mock |
| 469 | } |
| 470 | |
Matt Rosencrantz | c90eb7b | 2015-01-09 08:32:01 -0800 | [diff] [blame] | 471 | // Get the client that is relevant to the controller so it talks |
| 472 | // to the right mounttable. |
| 473 | client := veyron2.GetClient(rt.controller.Context()) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 474 | |
| 475 | if err != nil { |
| 476 | t.Errorf("unable to create client: %v", err) |
| 477 | } |
| 478 | |
Matt Rosencrantz | c90eb7b | 2015-01-09 08:32:01 -0800 | [diff] [blame] | 479 | call, err := client.StartCall(rt.controller.Context(), "adder/adder", test.method, test.inArgs) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 480 | if err != nil { |
| 481 | t.Errorf("failed to start call: %v", err) |
| 482 | } |
| 483 | |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 484 | for _, msg := range test.clientStream { |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 485 | if err := call.Send(msg); err != nil { |
| 486 | t.Errorf("unexpected error while sending %v: %v", msg, err) |
| 487 | } |
| 488 | } |
Shyam Jayaraman | e56df9a | 2014-11-20 17:38:54 -0800 | [diff] [blame] | 489 | if err := call.CloseSend(); err != nil { |
| 490 | t.Errorf("unexpected error on close: %v", err) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 491 | } |
| 492 | |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 493 | expectedStream := test.serverStream |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 494 | for { |
| 495 | var data interface{} |
| 496 | if err := call.Recv(&data); err != nil { |
| 497 | break |
| 498 | } |
| 499 | if len(expectedStream) == 0 { |
| 500 | t.Errorf("unexpected stream value: %v", data) |
| 501 | continue |
| 502 | } |
| 503 | if !reflect.DeepEqual(data, expectedStream[0]) { |
| 504 | t.Errorf("unexpected stream value: got %v, expected %v", data, expectedStream[0]) |
| 505 | } |
| 506 | expectedStream = expectedStream[1:] |
| 507 | } |
Shyam Jayaraman | e56df9a | 2014-11-20 17:38:54 -0800 | [diff] [blame] | 508 | |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 509 | var result interface{} |
| 510 | var err2 error |
| 511 | |
Shyam Jayaraman | e56df9a | 2014-11-20 17:38:54 -0800 | [diff] [blame] | 512 | err = call.Finish(&result, &err2) |
| 513 | if (err == nil && test.authError != nil) || (err != nil && test.authError == nil) { |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 514 | t.Errorf("unexpected err: %v, %v", err, test.authError) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 515 | } |
| 516 | |
Shyam Jayaraman | e56df9a | 2014-11-20 17:38:54 -0800 | [diff] [blame] | 517 | if err != nil { |
| 518 | return |
| 519 | } |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 520 | if !reflect.DeepEqual(result, test.finalResponse) { |
| 521 | t.Errorf("unexected final response: got %v, expected %v", result, test.finalResponse) |
| 522 | } |
| 523 | |
| 524 | // If err2 is nil and test.err is nil reflect.DeepEqual will return false because the |
| 525 | // types are different. Because of this, we only use reflect.DeepEqual if one of |
| 526 | // the values is non-nil. If both values are nil, then we consider them equal. |
Mike Burrows | b6689c2 | 2014-10-08 11:14:15 -0700 | [diff] [blame] | 527 | if (err2 != nil || test.err != nil) && !verror2.Equal(err2, test.err) { |
| 528 | t.Errorf("unexpected error: got %#v, expected %#v", err2, test.err) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 529 | } |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 530 | } |
| 531 | |
| 532 | func TestSimpleJSServer(t *testing.T) { |
| 533 | runJsServerTestCase(t, jsServerTestCase{ |
| 534 | method: "Add", |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 535 | inArgs: []interface{}{int32(1), int32(2)}, |
| 536 | finalResponse: int32(3), |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 537 | }) |
| 538 | } |
| 539 | |
| 540 | func TestJSServerWithAuthorizer(t *testing.T) { |
| 541 | runJsServerTestCase(t, jsServerTestCase{ |
| 542 | method: "Add", |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 543 | inArgs: []interface{}{int32(1), int32(2)}, |
| 544 | finalResponse: int32(3), |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 545 | hasAuthorizer: true, |
| 546 | }) |
| 547 | } |
| 548 | |
| 549 | func TestJSServerWithError(t *testing.T) { |
Mike Burrows | b6689c2 | 2014-10-08 11:14:15 -0700 | [diff] [blame] | 550 | err := verror2.Make(verror2.Internal, nil) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 551 | runJsServerTestCase(t, jsServerTestCase{ |
| 552 | method: "Add", |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 553 | inArgs: []interface{}{int32(1), int32(2)}, |
| 554 | finalResponse: int32(3), |
Mike Burrows | b6689c2 | 2014-10-08 11:14:15 -0700 | [diff] [blame] | 555 | err: err, |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 556 | }) |
| 557 | } |
| 558 | |
| 559 | func TestJSServerWithAuthorizerAndAuthError(t *testing.T) { |
Mike Burrows | b6689c2 | 2014-10-08 11:14:15 -0700 | [diff] [blame] | 560 | err := verror2.Make(verror2.Internal, nil) |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 561 | runJsServerTestCase(t, jsServerTestCase{ |
| 562 | method: "Add", |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 563 | inArgs: []interface{}{int32(1), int32(2)}, |
| 564 | finalResponse: int32(3), |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 565 | hasAuthorizer: true, |
Mike Burrows | b6689c2 | 2014-10-08 11:14:15 -0700 | [diff] [blame] | 566 | authError: err, |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 567 | }) |
| 568 | } |
| 569 | func TestJSServerWihStreamingInputs(t *testing.T) { |
| 570 | runJsServerTestCase(t, jsServerTestCase{ |
| 571 | method: "StreamingAdd", |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 572 | clientStream: []interface{}{int32(3), int32(4)}, |
| 573 | finalResponse: int32(10), |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 574 | }) |
| 575 | } |
| 576 | |
| 577 | func TestJSServerWihStreamingOutputs(t *testing.T) { |
| 578 | runJsServerTestCase(t, jsServerTestCase{ |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 579 | method: "StreamingAdd", |
| 580 | serverStream: []interface{}{int32(3), int32(4)}, |
| 581 | finalResponse: int32(10), |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 582 | }) |
| 583 | } |
| 584 | |
| 585 | func TestJSServerWihStreamingInputsAndOutputs(t *testing.T) { |
| 586 | runJsServerTestCase(t, jsServerTestCase{ |
Benjamin Prosnitz | a2ac3b3 | 2014-12-12 11:40:31 -0800 | [diff] [blame] | 587 | method: "StreamingAdd", |
| 588 | clientStream: []interface{}{int32(1), int32(2)}, |
| 589 | serverStream: []interface{}{int32(3), int32(4)}, |
| 590 | finalResponse: int32(10), |
Jiri Simsa | 78b646f | 2014-10-08 10:23:05 -0700 | [diff] [blame] | 591 | }) |
| 592 | } |