blob: 8f3f127245af8705a95d4a74cb3335edd7a0026f [file] [log] [blame]
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001package ipc
2
3import (
4 "errors"
5 "fmt"
6 "io"
Bogdan Caprita187269b2014-05-13 19:59:46 -07007 "net"
Bogdan Caprita783f7792014-05-15 09:29:17 -07008 "os"
Jiri Simsa5293dcb2014-05-10 09:56:38 -07009 "reflect"
10 "strings"
Bogdan Caprita27953142014-05-12 11:41:42 -070011 "sync"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070012 "testing"
13 "time"
14
Jiri Simsa73e9cac2014-06-30 09:55:10 -070015 _ "veyron/lib/testutil"
Bogdan Caprita783f7792014-05-15 09:29:17 -070016 "veyron/lib/testutil/blackbox"
Jiri Simsa73e9cac2014-06-30 09:55:10 -070017 tsecurity "veyron/lib/testutil/security"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070018 imanager "veyron/runtimes/google/ipc/stream/manager"
Asim Shankar0ea02ab2014-06-09 11:39:24 -070019 "veyron/runtimes/google/ipc/stream/proxy"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070020 "veyron/runtimes/google/ipc/stream/vc"
21 "veyron/runtimes/google/ipc/version"
Asim Shankarae713442014-06-05 15:31:23 -070022 "veyron/runtimes/google/lib/publisher"
Bogdan Caprita187269b2014-05-13 19:59:46 -070023 inaming "veyron/runtimes/google/naming"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070024 isecurity "veyron/runtimes/google/security"
Tilak Sharma3ed30242014-08-11 11:45:55 -070025 vsecurity "veyron/security"
Asim Shankar45054a62014-05-15 10:32:54 -070026 "veyron/security/caveat"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070027
28 "veyron2"
Matt Rosencrantz29147f72014-06-06 12:46:01 -070029 "veyron2/context"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070030 "veyron2/ipc"
31 "veyron2/ipc/stream"
32 "veyron2/naming"
33 "veyron2/security"
Todd Wang0ecdd7a2014-07-14 16:24:38 -070034 "veyron2/vdl/vdlutil"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070035 "veyron2/verror"
36 "veyron2/vlog"
Andres Erbsenb7f95f32014-07-07 12:07:56 -070037 "veyron2/vom"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070038)
39
40var (
Andres Erbsenb7f95f32014-07-07 12:07:56 -070041 errAuthorizer = errors.New("ipc: application Authorizer denied access")
Jiri Simsa51d78fc2014-07-09 18:34:08 -070042 errMethod = verror.Abortedf("server returned an error")
Ankura3c97652014-07-17 20:01:21 -070043 clientID = newID("client")
44 serverID = newID("server")
Jiri Simsa51d78fc2014-07-09 18:34:08 -070045 clock = new(fakeClock)
Jiri Simsa5293dcb2014-05-10 09:56:38 -070046)
47
Andres Erbsenb7f95f32014-07-07 12:07:56 -070048type fakeClock struct {
49 sync.Mutex
50 time int
51}
52
53func (c *fakeClock) Now() int {
54 c.Lock()
55 defer c.Unlock()
56 return c.time
57}
58
59func (c *fakeClock) Advance(steps uint) {
60 c.Lock()
61 c.time += int(steps)
62 c.Unlock()
63}
64
65type fakeTimeCaveat int
66
67func (c fakeTimeCaveat) Validate(security.Context) error {
68 now := clock.Now()
69 if now > int(c) {
70 return fmt.Errorf("fakeTimeCaveat expired: now=%d > then=%d", now, c)
71 }
72 return nil
73}
Jiri Simsa5293dcb2014-05-10 09:56:38 -070074
75type userType string
76
77type testServer struct{}
78
79func (*testServer) Closure(call ipc.ServerCall) {
80}
81
82func (*testServer) Error(call ipc.ServerCall) error {
83 return errMethod
84}
85
86func (*testServer) Echo(call ipc.ServerCall, arg string) string {
87 return fmt.Sprintf("method:%q,suffix:%q,arg:%q", call.Method(), call.Suffix(), arg)
88}
89
90func (*testServer) EchoUser(call ipc.ServerCall, arg string, u userType) (string, userType) {
91 return fmt.Sprintf("method:%q,suffix:%q,arg:%q", call.Method(), call.Suffix(), arg), u
92}
93
94func (*testServer) EchoIDs(call ipc.ServerCall) (server, client string) {
95 return fmt.Sprintf("%v", call.LocalID()), fmt.Sprintf("%v", call.RemoteID())
96}
97
Asim Shankarb54d7642014-06-05 13:08:04 -070098func (*testServer) EchoBlessing(call ipc.ServerCall, arg string) (result, blessing string) {
99 return arg, fmt.Sprintf("%v", call.Blessing())
100}
101
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700102func (*testServer) EchoAndError(call ipc.ServerCall, arg string) (string, error) {
103 result := fmt.Sprintf("method:%q,suffix:%q,arg:%q", call.Method(), call.Suffix(), arg)
104 if arg == "error" {
105 return result, errMethod
106 }
107 return result, nil
108}
109
110func (*testServer) Stream(call ipc.ServerCall, arg string) (string, error) {
111 result := fmt.Sprintf("method:%q,suffix:%q,arg:%q", call.Method(), call.Suffix(), arg)
112 var u userType
113 var err error
114 for err = call.Recv(&u); err == nil; err = call.Recv(&u) {
115 result += " " + string(u)
116 if err := call.Send(u); err != nil {
117 return "", err
118 }
119 }
120 if err == io.EOF {
121 err = nil
122 }
123 return result, err
124}
125
126func (*testServer) Unauthorized(ipc.ServerCall) (string, error) {
127 return "UnauthorizedResult", fmt.Errorf("Unauthorized should never be called")
128}
129
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700130type dischargeServer struct{}
131
Tilak Sharmad6ade0e2014-08-20 16:28:32 -0700132func (*dischargeServer) Discharge(ctx ipc.ServerCall, cav vdlutil.Any, _ security.DischargeImpetus) (vdlutil.Any, error) {
133 c, ok := cav.(security.ThirdPartyCaveat)
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700134 if !ok {
Tilak Sharmad6ade0e2014-08-20 16:28:32 -0700135 return nil, fmt.Errorf("discharger: unknown caveat(%T)", cav)
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700136 }
137 // Add a fakeTimeCaveat to allow the discharge to expire
138 expiry := fakeTimeCaveat(clock.Now())
Ankurf044a8d2014-09-05 17:05:24 -0700139 return serverID.MintDischarge(c, ctx, time.Hour, newCaveat(expiry))
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700140}
141
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700142type testServerAuthorizer struct{}
143
144func (testServerAuthorizer) Authorize(c security.Context) error {
145 if c.Method() != "Unauthorized" {
146 return nil
147 }
148 return errAuthorizer
149}
150
151type testServerDisp struct{ server interface{} }
152
Cosmos Nicolaou8bfacf22014-08-19 11:19:36 -0700153func (t testServerDisp) Lookup(suffix, method string) (ipc.Invoker, security.Authorizer, error) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700154 // If suffix is "nilAuth" we use default authorization, if it is "aclAuth" we
155 // use an ACL based authorizer, and otherwise we use the custom testServerAuthorizer.
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700156 var authorizer security.Authorizer
157 switch suffix {
158 case "discharger":
159 return ipc.ReflectInvoker(&dischargeServer{}), testServerAuthorizer{}, nil
160 case "nilAuth":
161 authorizer = nil
162 case "aclAuth":
Asim Shankar9f6db082014-08-27 16:44:03 -0700163 // Only authorize clients matching patterns "client" or "server/...".
164 authorizer = vsecurity.NewACLAuthorizer(security.ACL{In: map[security.BlessingPattern]security.LabelSet{
165 "server/...": security.LabelSet(security.AdminLabel),
166 "client": security.LabelSet(security.AdminLabel),
167 }})
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700168 default:
169 authorizer = testServerAuthorizer{}
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700170 }
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700171 return ipc.ReflectInvoker(t.server), authorizer, nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700172}
173
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700174// namespace is a simple partial implementation of naming.Namespace. In
Bogdan Caprita27953142014-05-12 11:41:42 -0700175// particular, it ignores TTLs and not allow fully overlapping mount names.
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700176type namespace struct {
Bogdan Caprita27953142014-05-12 11:41:42 -0700177 sync.Mutex
178 mounts map[string][]string
179}
180
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700181func newNamespace() naming.Namespace {
182 return &namespace{mounts: make(map[string][]string)}
Bogdan Caprita27953142014-05-12 11:41:42 -0700183}
184
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700185func (ns *namespace) Mount(ctx context.T, name, server string, _ time.Duration) error {
186 ns.Lock()
187 defer ns.Unlock()
188 for n, _ := range ns.mounts {
Bogdan Caprita27953142014-05-12 11:41:42 -0700189 if n != name && (strings.HasPrefix(name, n) || strings.HasPrefix(n, name)) {
190 return fmt.Errorf("simple mount table does not allow names that are a prefix of each other")
191 }
192 }
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700193 ns.mounts[name] = append(ns.mounts[name], server)
Bogdan Caprita27953142014-05-12 11:41:42 -0700194 return nil
195}
196
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700197func (ns *namespace) Unmount(ctx context.T, name, server string) error {
Bogdan Caprita27953142014-05-12 11:41:42 -0700198 var servers []string
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700199 ns.Lock()
200 defer ns.Unlock()
201 for _, s := range ns.mounts[name] {
Bogdan Caprita27953142014-05-12 11:41:42 -0700202 // When server is "", we remove all servers under name.
203 if len(server) > 0 && s != server {
204 servers = append(servers, s)
205 }
206 }
207 if len(servers) > 0 {
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700208 ns.mounts[name] = servers
Bogdan Caprita27953142014-05-12 11:41:42 -0700209 } else {
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700210 delete(ns.mounts, name)
Bogdan Caprita27953142014-05-12 11:41:42 -0700211 }
212 return nil
213}
214
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700215func (ns *namespace) Resolve(ctx context.T, name string) ([]string, error) {
Bogdan Caprita27953142014-05-12 11:41:42 -0700216 if address, _ := naming.SplitAddressName(name); len(address) > 0 {
217 return []string{name}, nil
218 }
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700219 ns.Lock()
220 defer ns.Unlock()
221 for prefix, servers := range ns.mounts {
Bogdan Caprita27953142014-05-12 11:41:42 -0700222 if strings.HasPrefix(name, prefix) {
223 suffix := strings.TrimLeft(strings.TrimPrefix(name, prefix), "/")
224 var ret []string
225 for _, s := range servers {
226 ret = append(ret, naming.Join(s, suffix))
227 }
228 return ret, nil
229 }
230 }
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700231 return nil, verror.NotFoundf("Resolve name %q not found in %v", name, ns.mounts)
Bogdan Caprita27953142014-05-12 11:41:42 -0700232}
233
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700234func (ns *namespace) ResolveToMountTable(ctx context.T, name string) ([]string, error) {
Bogdan Caprita27953142014-05-12 11:41:42 -0700235 panic("ResolveToMountTable not implemented")
236 return nil, nil
237}
238
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700239func (ns *namespace) Unresolve(ctx context.T, name string) ([]string, error) {
Bogdan Caprita27953142014-05-12 11:41:42 -0700240 panic("Unresolve not implemented")
241 return nil, nil
242}
243
David Why Use Two When One Will Do Presotto39602db2014-08-18 14:28:27 -0700244func (ns *namespace) FlushCacheEntry(name string) bool {
245 return false
246}
247
David Why Use Two When One Will Do Presotto7764f312014-08-20 16:24:05 -0700248func (ns *namespace) CacheCtl(ctls ...naming.CacheCtl) []naming.CacheCtl {
249 return nil
250}
251
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700252func (ns *namespace) Glob(ctx context.T, pattern string) (chan naming.MountEntry, error) {
Bogdan Caprita27953142014-05-12 11:41:42 -0700253 panic("Glob not implemented")
254 return nil, nil
255}
256
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700257func (ns *namespace) SetRoots(...string) error {
Cosmos Nicolaoue6e87f12014-06-03 14:29:10 -0700258 panic("SetRoots not implemented")
259 return nil
260}
261
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700262func (ns *namespace) Roots() []string {
263 panic("Roots not implemented")
264 return nil
265}
266
267func startServer(t *testing.T, serverID security.PrivateID, sm stream.Manager, ns naming.Namespace, ts interface{}) (naming.Endpoint, ipc.Server) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700268 vlog.VI(1).Info("InternalNewServer")
Matt Rosencrantzbf85d542014-08-22 13:31:14 -0700269 server, err := InternalNewServer(testContext(), sm, ns, vc.FixedLocalID(serverID))
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700270 if err != nil {
271 t.Errorf("InternalNewServer failed: %v", err)
272 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700273 vlog.VI(1).Info("server.Listen")
Adam Sadovsky5181bdb2014-08-13 10:29:11 -0700274 ep, err := server.Listen("tcp", "127.0.0.1:0")
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700275 if err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700276 t.Errorf("server.Listen failed: %v", err)
277 }
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700278 vlog.VI(1).Info("server.Serve")
279 disp := testServerDisp{ts}
280 if err := server.Serve("mountpoint/server", disp); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700281 t.Errorf("server.Publish failed: %v", err)
282 }
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700283 if err := server.Serve("mountpoint/discharger", disp); err != nil {
284 t.Errorf("server.Publish for discharger failed: %v", err)
285 }
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700286 return ep, server
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700287}
288
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700289func verifyMount(t *testing.T, ns naming.Namespace, name string) {
Matt Rosencrantzbf85d542014-08-22 13:31:14 -0700290 if _, err := ns.Resolve(testContext(), name); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700291 t.Errorf("%s not found in mounttable", name)
292 }
293}
294
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700295func verifyMountMissing(t *testing.T, ns naming.Namespace, name string) {
Matt Rosencrantzbf85d542014-08-22 13:31:14 -0700296 if servers, err := ns.Resolve(testContext(), name); err == nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700297 t.Errorf("%s not supposed to be found in mounttable; got %d servers instead", name, len(servers))
298 }
299}
300
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700301func stopServer(t *testing.T, server ipc.Server, ns naming.Namespace) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700302 vlog.VI(1).Info("server.Stop")
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700303 n1 := "mountpoint/server"
304 n2 := "should_appear_in_mt/server"
305 verifyMount(t, ns, n1)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700306
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700307 // publish a second name
308 if err := server.Serve(n2, nil); err != nil {
309 t.Errorf("server.Serve failed: %v", err)
310 }
311 verifyMount(t, ns, n2)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700312
313 if err := server.Stop(); err != nil {
314 t.Errorf("server.Stop failed: %v", err)
315 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700316
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700317 verifyMountMissing(t, ns, n1)
318 verifyMountMissing(t, ns, n2)
319
320 // Check that we can no longer serve after Stop.
321 err := server.Serve("name doesn't matter", nil)
322 if err == nil || err.Error() != "ipc: server is stopped" {
323 t.Errorf("either no error, or a wrong error was returned: %v", err)
324 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700325 vlog.VI(1).Info("server.Stop DONE")
326}
327
Bogdan Caprita27953142014-05-12 11:41:42 -0700328type bundle struct {
329 client ipc.Client
330 server ipc.Server
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700331 ep naming.Endpoint
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700332 ns naming.Namespace
Bogdan Caprita27953142014-05-12 11:41:42 -0700333 sm stream.Manager
334}
335
336func (b bundle) cleanup(t *testing.T) {
Ankura3c97652014-07-17 20:01:21 -0700337 if b.server != nil {
338 stopServer(t, b.server, b.ns)
339 }
340 if b.client != nil {
341 b.client.Close()
342 }
Bogdan Caprita27953142014-05-12 11:41:42 -0700343}
344
345func createBundle(t *testing.T, clientID, serverID security.PrivateID, ts interface{}) (b bundle) {
346 b.sm = imanager.InternalNew(naming.FixedRoutingID(0x555555555))
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700347 b.ns = newNamespace()
Ankura3c97652014-07-17 20:01:21 -0700348 if serverID != nil {
349 b.ep, b.server = startServer(t, serverID, b.sm, b.ns, ts)
350 }
351 if clientID != nil {
352 var err error
353 if b.client, err = InternalNewClient(b.sm, b.ns, vc.FixedLocalID(clientID)); err != nil {
354 t.Fatalf("InternalNewClient failed: %v", err)
355 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700356 }
Bogdan Caprita27953142014-05-12 11:41:42 -0700357 return
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700358}
359
Ankurf044a8d2014-09-05 17:05:24 -0700360func bless(blessor security.PrivateID, blessee security.PublicID, name string, caveats ...security.Caveat) security.PublicID {
Asim Shankarb54d7642014-06-05 13:08:04 -0700361 blessed, err := blessor.Bless(blessee, name, 24*time.Hour, caveats)
362 if err != nil {
363 panic(err)
364 }
365 return blessed
366}
367
Ankurf044a8d2014-09-05 17:05:24 -0700368func derive(blessor security.PrivateID, name string, caveats ...security.Caveat) security.PrivateID {
Ankura3c97652014-07-17 20:01:21 -0700369 id := newID("irrelevant")
Asim Shankarb54d7642014-06-05 13:08:04 -0700370 derivedID, err := id.Derive(bless(blessor, id.PublicID(), name, caveats...))
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700371 if err != nil {
372 panic(err)
373 }
374 return derivedID
375}
376
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700377// deriveForThirdPartyCaveats creates a SetPrivateID that can be used for
378// 1. talking to the server, if the caveats are fulfilled
379// 2. getting discharges, even if the caveats are not fulfilled
380// As an identity with an unfulfilled caveat is invalid (even for asking for a
381// discharge), this function creates a set of two identities. The first will
382// have the caveats, the second will always be valid, but only for getting
383// discharges. The client presents both blessings in both cases, the discharger
384// ignores the first if it is invalid.
Ankurf044a8d2014-09-05 17:05:24 -0700385func deriveForThirdPartyCaveats(blessor security.PrivateID, name string, caveats ...security.Caveat) security.PrivateID {
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700386 id := derive(blessor, name, caveats...)
Ankurf044a8d2014-09-05 17:05:24 -0700387 dischargeID, err := id.Derive(bless(blessor, id.PublicID(), name, newCaveat(caveat.MethodRestriction{"Discharge"})...))
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700388 if err != nil {
389 panic(err)
390 }
391 id, err = isecurity.NewSetPrivateID(id, dischargeID)
392 if err != nil {
393 panic(err)
394 }
395 return id
396}
397
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700398func matchesErrorPattern(err error, pattern string) bool {
399 if (len(pattern) == 0) != (err == nil) {
400 return false
401 }
402 return err == nil || strings.Index(err.Error(), pattern) >= 0
403}
404
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700405func TestMultipleCallsToServe(t *testing.T) {
406 sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
407 ns := newNamespace()
Matt Rosencrantzbf85d542014-08-22 13:31:14 -0700408 server, err := InternalNewServer(testContext(), sm, ns, vc.FixedLocalID(serverID))
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700409 if err != nil {
410 t.Errorf("InternalNewServer failed: %v", err)
411 }
Adam Sadovsky5181bdb2014-08-13 10:29:11 -0700412 _, err = server.Listen("tcp", "127.0.0.1:0")
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700413 if err != nil {
414 t.Errorf("server.Listen failed: %v", err)
415 }
416
417 disp := &testServerDisp{&testServer{}}
418 if err := server.Serve("mountpoint/server", disp); err != nil {
419 t.Errorf("server.Publish failed: %v", err)
420 }
421
422 n1 := "mountpoint/server"
423 n2 := "should_appear_in_mt/server"
424 n3 := "should_appear_in_mt/server"
425 n4 := "should_not_appear_in_mt/server"
426
427 verifyMount(t, ns, n1)
428
429 if err := server.Serve(n2, disp); err != nil {
430 t.Errorf("server.Serve failed: %v", err)
431 }
432 if err := server.Serve(n3, nil); err != nil {
433 t.Errorf("server.Serve failed: %v", err)
434 }
435 verifyMount(t, ns, n2)
436 verifyMount(t, ns, n3)
437
438 if err := server.Serve(n4, &testServerDisp{&testServer{}}); err == nil {
439 t.Errorf("server.Serve should have failed")
440 }
441 verifyMountMissing(t, ns, n4)
442
443 if err := server.Stop(); err != nil {
444 t.Errorf("server.Stop failed: %v", err)
445 }
446
447 verifyMountMissing(t, ns, n1)
448 verifyMountMissing(t, ns, n2)
449 verifyMountMissing(t, ns, n3)
450}
451
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700452func TestStartCall(t *testing.T) {
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700453 const (
454 authorizeErr = "not authorized because"
455 nameErr = "does not match the provided pattern"
456 )
457 var (
Ankurf044a8d2014-09-05 17:05:24 -0700458 // TODO(ataly, ashankar): Uncomment the following once server authorization
459 // is enabled.
460 // now = time.Now()
461 // cavOnlyV1 = caveat.UniversalCaveat(caveat.PeerIdentity{"client/v1"})
462 // cavExpired = security.ServiceCaveat{
463 // Service: security.AllPrincipals,
464 // Caveat: &caveat.Expiry{IssueTime: now, ExpiryTime: now},
465 // }
466 // clientV1ID = derive(clientID, "v1")
467 // clientV2ID = derive(clientID, "v2")
468 // serverV1ID = derive(serverID, "v1", cavOnlyV1)
469 // serverExpiredID = derive(serverID, "expired", cavExpired)
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700470 )
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700471
472 tests := []struct {
473 clientID, serverID security.PrivateID
Asim Shankar6bc64582014-08-27 12:51:42 -0700474 pattern security.BlessingPattern // pattern on the server identity expected by client.
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700475 err string
476 }{
477 // Client accepts talking to server only if server's identity matches the
478 // provided pattern.
Asim Shankarddc0c222014-07-29 15:47:00 -0700479 {clientID, serverID, security.AllPrincipals, ""},
480 {clientID, serverID, "server", ""},
481 {clientID, serverID, "server/v1", ""},
482 {clientID, serverID, "anotherServer", nameErr},
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700483
Ankur2959fc82014-09-05 14:07:23 -0700484 // TODO(ataly, ashankar): Uncomment the following once server authorization
485 // is enabled.
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700486 // All clients reject talking to a server with an expired identity.
Ankur2959fc82014-09-05 14:07:23 -0700487 // {clientID, serverExpiredID, security.AllPrincipals, authorizeErr},
488 // {clientV1ID, serverExpiredID, security.AllPrincipals, authorizeErr},
489 // {clientV2ID, serverExpiredID, security.AllPrincipals, authorizeErr},
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700490
491 // Only clientV1 accepts talking to serverV1.
Ankur2959fc82014-09-05 14:07:23 -0700492 // {clientV1ID, serverV1ID, security.AllPrincipals, ""},
493 // {clientV2ID, serverV1ID, security.AllPrincipals, authorizeErr},
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700494 }
495 // Servers and clients will be created per-test, use the same stream manager and mounttable.
496 mgr := imanager.InternalNew(naming.FixedRoutingID(0x1111111))
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700497 ns := newNamespace()
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700498 for _, test := range tests {
499 name := fmt.Sprintf("(clientID:%q serverID:%q)", test.clientID, test.serverID)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700500 _, server := startServer(t, test.serverID, mgr, ns, &testServer{})
Ankura3c97652014-07-17 20:01:21 -0700501 client, err := InternalNewClient(mgr, ns, vc.FixedLocalID(test.clientID))
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700502 if err != nil {
503 t.Errorf("%s: Client creation failed: %v", name, err)
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700504 stopServer(t, server, ns)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700505 continue
506 }
Matt Rosencrantzbf85d542014-08-22 13:31:14 -0700507 if _, err := client.StartCall(testContext(), "mountpoint/server/suffix", "irrelevant", nil, veyron2.RemoteID(test.pattern)); !matchesErrorPattern(err, test.err) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700508 t.Errorf(`%s: client.StartCall: got error "%v", want to match "%v"`, name, err, test.err)
509 }
510 client.Close()
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700511 stopServer(t, server, ns)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700512 }
513}
514
515func TestRPC(t *testing.T) {
Tilak Sharma0c766112014-05-20 17:47:27 -0700516 testRPC(t, true)
517}
518
519// TestCloseSendOnFinish tests that Finish informs the server that no more
520// inputs will be sent by the client if CloseSend has not already done so.
521func TestRPCCloseSendOnFinish(t *testing.T) {
522 testRPC(t, false)
523}
524
525func testRPC(t *testing.T, shouldCloseSend bool) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700526 type v []interface{}
527 type testcase struct {
528 name string
529 method string
530 args v
531 streamArgs v
532 startErr error
533 results v
534 finishErr error
535 }
536 tests := []testcase{
537 {"mountpoint/server/suffix", "Closure", nil, nil, nil, nil, nil},
538 {"mountpoint/server/suffix", "Error", nil, nil, nil, v{errMethod}, nil},
539
540 {"mountpoint/server/suffix", "Echo", v{"foo"}, nil, nil, v{`method:"Echo",suffix:"suffix",arg:"foo"`}, nil},
541 {"mountpoint/server/suffix/abc", "Echo", v{"bar"}, nil, nil, v{`method:"Echo",suffix:"suffix/abc",arg:"bar"`}, nil},
542
543 {"mountpoint/server/suffix", "EchoUser", v{"foo", userType("bar")}, nil, nil, v{`method:"EchoUser",suffix:"suffix",arg:"foo"`, userType("bar")}, nil},
544 {"mountpoint/server/suffix/abc", "EchoUser", v{"baz", userType("bla")}, nil, nil, v{`method:"EchoUser",suffix:"suffix/abc",arg:"baz"`, userType("bla")}, nil},
545 {"mountpoint/server/suffix", "Stream", v{"foo"}, v{userType("bar"), userType("baz")}, nil, v{`method:"Stream",suffix:"suffix",arg:"foo" bar baz`, nil}, nil},
546 {"mountpoint/server/suffix/abc", "Stream", v{"123"}, v{userType("456"), userType("789")}, nil, v{`method:"Stream",suffix:"suffix/abc",arg:"123" 456 789`, nil}, nil},
547 {"mountpoint/server/suffix", "EchoIDs", nil, nil, nil, v{"server", "client"}, nil},
548 {"mountpoint/server/suffix", "EchoAndError", v{"bugs bunny"}, nil, nil, v{`method:"EchoAndError",suffix:"suffix",arg:"bugs bunny"`, nil}, nil},
549 {"mountpoint/server/suffix", "EchoAndError", v{"error"}, nil, nil, v{`method:"EchoAndError",suffix:"suffix",arg:"error"`, errMethod}, nil},
550 }
551 name := func(t testcase) string {
552 return fmt.Sprintf("%s.%s(%v)", t.name, t.method, t.args)
553 }
Bogdan Caprita27953142014-05-12 11:41:42 -0700554 b := createBundle(t, clientID, serverID, &testServer{})
555 defer b.cleanup(t)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700556 for _, test := range tests {
557 vlog.VI(1).Infof("%s client.StartCall", name(test))
Matt Rosencrantzbf85d542014-08-22 13:31:14 -0700558 call, err := b.client.StartCall(testContext(), test.name, test.method, test.args)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700559 if err != test.startErr {
560 t.Errorf(`%s client.StartCall got error "%v", want "%v"`, name(test), err, test.startErr)
561 continue
562 }
563 for _, sarg := range test.streamArgs {
564 vlog.VI(1).Infof("%s client.Send(%v)", name(test), sarg)
565 if err := call.Send(sarg); err != nil {
566 t.Errorf(`%s call.Send(%v) got unexpected error "%v"`, name(test), sarg, err)
567 }
568 var u userType
569 if err := call.Recv(&u); err != nil {
570 t.Errorf(`%s call.Recv(%v) got unexpected error "%v"`, name(test), sarg, err)
571 }
572 if !reflect.DeepEqual(u, sarg) {
573 t.Errorf("%s call.Recv got value %v, want %v", name(test), u, sarg)
574 }
575 }
Tilak Sharma0c766112014-05-20 17:47:27 -0700576 if shouldCloseSend {
577 vlog.VI(1).Infof("%s call.CloseSend", name(test))
Asim Shankar062d4222014-08-18 11:14:42 -0700578 // When the method does not involve streaming
579 // arguments, the server gets all the arguments in
580 // StartCall and then sends a response without
581 // (unnecessarily) waiting for a CloseSend message from
582 // the client. If the server responds before the
583 // CloseSend call is made at the client, the CloseSend
584 // call will fail. Thus, only check for errors on
585 // CloseSend if there are streaming arguments to begin
586 // with (i.e., only if the server is expected to wait
587 // for the CloseSend notification).
588 if err := call.CloseSend(); err != nil && len(test.streamArgs) > 0 {
Tilak Sharma0c766112014-05-20 17:47:27 -0700589 t.Errorf(`%s call.CloseSend got unexpected error "%v"`, name(test), err)
590 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700591 }
592 vlog.VI(1).Infof("%s client.Finish", name(test))
593 results := makeResultPtrs(test.results)
594 err = call.Finish(results...)
595 if err != test.finishErr {
596 t.Errorf(`%s call.Finish got error "%v", want "%v"`, name(test), err, test.finishErr)
597 }
598 checkResultPtrs(t, name(test), results, test.results)
599 }
600}
601
Asim Shankarb54d7642014-06-05 13:08:04 -0700602// granter implements ipc.Granter, returning a fixed (security.PublicID, error) pair.
603type granter struct {
604 ipc.CallOpt
605 id security.PublicID
606 err error
607}
608
609func (g granter) Grant(id security.PublicID) (security.PublicID, error) { return g.id, g.err }
610
611func TestBlessing(t *testing.T) {
612 b := createBundle(t, clientID, serverID, &testServer{})
613 defer b.cleanup(t)
614
615 tests := []struct {
616 granter ipc.CallOpt
617 blessing, starterr, finisherr string
618 }{
619 {blessing: "<nil>"},
620 {granter: granter{id: bless(clientID, serverID.PublicID(), "blessed")}, blessing: "client/blessed"},
621 {granter: granter{err: errors.New("hell no")}, starterr: "hell no"},
622 {granter: granter{id: clientID.PublicID()}, finisherr: "blessing provided not bound to this server"},
623 }
624 for _, test := range tests {
Matt Rosencrantzbf85d542014-08-22 13:31:14 -0700625 call, err := b.client.StartCall(testContext(), "mountpoint/server/suffix", "EchoBlessing", []interface{}{"argument"}, test.granter)
Asim Shankarb54d7642014-06-05 13:08:04 -0700626 if !matchesErrorPattern(err, test.starterr) {
627 t.Errorf("%+v: StartCall returned error %v", test, err)
628 }
629 if err != nil {
630 continue
631 }
632 var result, blessing string
633 if err = call.Finish(&result, &blessing); !matchesErrorPattern(err, test.finisherr) {
634 t.Errorf("%+v: Finish returned error %v", test, err)
635 }
636 if err != nil {
637 continue
638 }
639 if result != "argument" || blessing != test.blessing {
640 t.Errorf("%+v: Got (%q, %q)", test, result, blessing)
641 }
642 }
643}
644
Asim Shankarddc0c222014-07-29 15:47:00 -0700645func mkThirdPartyCaveat(discharger security.PublicID, location string, c security.Caveat) security.ThirdPartyCaveat {
Ankurf044a8d2014-09-05 17:05:24 -0700646 tpc, err := caveat.NewPublicKeyCaveat(c, discharger.PublicKey(), location, security.ThirdPartyRequirements{})
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700647 if err != nil {
648 panic(err)
649 }
650 return tpc
651}
652
Asim Shankara94e5072014-08-19 18:18:36 -0700653type dischargeImpetusTester struct {
654 LastDischargeImpetus security.DischargeImpetus
655}
656
657// Implements ipc.Dispatcher
658func (s *dischargeImpetusTester) Lookup(_, _ string) (ipc.Invoker, security.Authorizer, error) {
659 return ipc.ReflectInvoker(s), nil, nil
660}
661
662// Implements the discharge service: Always fails to issue a discharge, but records the impetus
663func (s *dischargeImpetusTester) Discharge(ctx ipc.ServerCall, cav vdlutil.Any, impetus security.DischargeImpetus) (vdlutil.Any, error) {
664 s.LastDischargeImpetus = impetus
665 return nil, fmt.Errorf("discharges not issued")
666}
667
668func TestDischargeImpetus(t *testing.T) {
669 var (
670 // The Discharge service can be run by anyone, but in these tests it is the same as the server.
671 dischargerID = serverID.PublicID()
672
673 mkClientID = func(req security.ThirdPartyRequirements) security.PrivateID {
Ankurf044a8d2014-09-05 17:05:24 -0700674 tpc, err := caveat.NewPublicKeyCaveat(newCaveat(alwaysValidCaveat{})[0], dischargerID.PublicKey(), "mountpoint/discharger", req)
Asim Shankara94e5072014-08-19 18:18:36 -0700675 if err != nil {
676 t.Fatalf("Failed to create ThirdPartyCaveat: %v", err)
677 }
Ankurf044a8d2014-09-05 17:05:24 -0700678 caveat := newCaveat(tpc)
679 return deriveForThirdPartyCaveats(serverID, "client", caveat...)
Asim Shankara94e5072014-08-19 18:18:36 -0700680 }
681 )
682 sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
683 ns := newNamespace()
Matt Rosencrantzbf85d542014-08-22 13:31:14 -0700684 server, err := InternalNewServer(testContext(), sm, ns, vc.FixedLocalID(serverID))
Asim Shankara94e5072014-08-19 18:18:36 -0700685 if err != nil {
686 t.Fatal(err)
687 }
688 defer server.Stop()
689 if _, err := server.Listen("tcp", "127.0.0.1:0"); err != nil {
690 t.Fatal(err)
691 }
692
693 var tester dischargeImpetusTester
694 if err := server.Serve("mountpoint", &tester); err != nil {
695 t.Fatal(err)
696 }
697
698 tests := []struct {
699 Requirements security.ThirdPartyRequirements
700 Impetus security.DischargeImpetus
701 }{
702 { // No requirements, no impetus
703 Requirements: security.ThirdPartyRequirements{},
704 Impetus: security.DischargeImpetus{},
705 },
706 { // Require everything
707 Requirements: security.ThirdPartyRequirements{ReportServer: true, ReportMethod: true, ReportArguments: true},
708 Impetus: security.DischargeImpetus{Server: vdlutil.Any(serverID.PublicID()), Method: "Method", Arguments: []vdlutil.Any{vdlutil.Any("argument")}},
709 },
710 { // Require only the method name
711 Requirements: security.ThirdPartyRequirements{ReportMethod: true},
712 Impetus: security.DischargeImpetus{Method: "Method"},
713 },
714 }
715
716 for _, test := range tests {
717 client, err := InternalNewClient(sm, ns, vc.FixedLocalID(mkClientID(test.Requirements)))
718 if err != nil {
719 t.Fatalf("InternalNewClient(%+v) failed: %v", test.Requirements, err)
720 }
721 defer client.Close()
722 // StartCall should fetch the discharge, do not worry about finishing the RPC - do not care about that for this test.
Matt Rosencrantzbf85d542014-08-22 13:31:14 -0700723 if _, err := client.StartCall(testContext(), "mountpoint/object", "Method", []interface{}{"argument"}); err != nil {
Asim Shankara94e5072014-08-19 18:18:36 -0700724 t.Errorf("StartCall(%+v) failed: %v", test.Requirements, err)
725 continue
726 }
727 if got, want := tester.LastDischargeImpetus, test.Impetus; !reflect.DeepEqual(got, want) {
728 t.Errorf("Got [%v] want [%v] for test %+v", got, want, test.Requirements)
729 }
730 }
731}
732
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700733func TestRPCAuthorization(t *testing.T) {
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700734 var (
735 now = time.Now()
736 // First-party caveats
Ankurf044a8d2014-09-05 17:05:24 -0700737 cavOnlyEcho = newCaveat(caveat.MethodRestriction{"Echo"})
738 cavExpired = newCaveat(&caveat.Expiry{IssueTime: now, ExpiryTime: now})
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700739 // Third-party caveats
740 // The Discharge service can be run by any identity, but in our tests the same server runs
741 // a Discharge service as well.
742 dischargerID = serverID.PublicID()
Ankurf044a8d2014-09-05 17:05:24 -0700743 cavTPValid = newCaveat(mkThirdPartyCaveat(dischargerID, "mountpoint/server/discharger", newCaveat(&caveat.Expiry{ExpiryTime: now.Add(24 * time.Hour)})[0]))
744 cavTPExpired = newCaveat(mkThirdPartyCaveat(dischargerID, "mountpoint/server/discharger", newCaveat(&caveat.Expiry{IssueTime: now, ExpiryTime: now})[0]))
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700745
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700746 // Client blessings that will be tested
Ankurf044a8d2014-09-05 17:05:24 -0700747 blessedByServerOnlyEcho = derive(serverID, "onlyEcho", cavOnlyEcho...)
748 blessedByServerExpired = derive(serverID, "expired", cavExpired...)
749 blessedByServerTPValid = deriveForThirdPartyCaveats(serverID, "tpvalid", cavTPValid...)
750 blessedByServerTPExpired = deriveForThirdPartyCaveats(serverID, "tpexpired", cavTPExpired...)
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700751 blessedByClient = derive(clientID, "blessed")
752 )
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700753 const (
754 expiredIDErr = "forbids credential from being used at this time"
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700755 aclAuthErr = "no matching ACL entry found"
756 )
757 invalidMethodErr := func(method string) string {
Asim Shankar45054a62014-05-15 10:32:54 -0700758 return fmt.Sprintf(`caveat.MethodRestriction{"Echo"} forbids invocation of method %s`, method)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700759 }
760
761 type v []interface{}
762 type testcase struct {
763 clientID security.PrivateID
764 name string
765 method string
766 args v
767 results v
768 finishErr string
769 }
770 tests := []testcase{
771 // Clients whose identities have invalid caveats are not by authorized by any authorizer.
772 {blessedByServerExpired, "mountpoint/server/nilAuth", "Echo", v{"foo"}, v{""}, expiredIDErr},
773 {blessedByServerExpired, "mountpoint/server/suffix", "Echo", v{"foo"}, v{""}, expiredIDErr},
774 {blessedByServerOnlyEcho, "mountpoint/server/nilAuth", "Closure", nil, nil, invalidMethodErr("Closure")},
775 {blessedByServerOnlyEcho, "mountpoint/server/suffix", "Closure", nil, nil, invalidMethodErr("Closure")},
776 // Only clients with a trusted name that matches either the server's identity or an identity blessed
777 // by the server are authorized by the (default) nilAuth authorizer.
Ankur992269a2014-05-13 13:03:24 -0700778 {clientID, "mountpoint/server/nilAuth", "Echo", v{"foo"}, v{""}, aclAuthErr},
779 {blessedByClient, "mountpoint/server/nilAuth", "Echo", v{"foo"}, v{""}, aclAuthErr},
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700780 {serverID, "mountpoint/server/nilAuth", "Echo", v{"foo"}, v{`method:"Echo",suffix:"nilAuth",arg:"foo"`}, ""},
781 {serverID, "mountpoint/server/nilAuth", "Closure", nil, nil, ""},
782 {blessedByServerOnlyEcho, "mountpoint/server/nilAuth", "Echo", v{"foo"}, v{`method:"Echo",suffix:"nilAuth",arg:"foo"`}, ""},
783 // Only clients matching the server's ACL are authorized.
784 {clientID, "mountpoint/server/aclAuth", "Echo", v{"foo"}, v{`method:"Echo",suffix:"aclAuth",arg:"foo"`}, ""},
785 {blessedByClient, "mountpoint/server/aclAuth", "Echo", v{"foo"}, v{""}, aclAuthErr},
786 {serverID, "mountpoint/server/aclAuth", "Echo", v{"foo"}, v{`method:"Echo",suffix:"aclAuth",arg:"foo"`}, ""},
787 {blessedByServerOnlyEcho, "mountpoint/server/aclAuth", "Echo", v{"foo"}, v{`method:"Echo",suffix:"aclAuth",arg:"foo"`}, ""},
788 {clientID, "mountpoint/server/aclAuth", "Closure", nil, nil, ""},
789 {blessedByClient, "mountpoint/server/aclAuth", "Closure", nil, nil, aclAuthErr},
790 {serverID, "mountpoint/server/aclAuth", "Closure", nil, nil, ""},
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700791 // All methods except "Unauthorized" are authorized by the custom authorizer.
792 {clientID, "mountpoint/server/suffix", "Echo", v{"foo"}, v{`method:"Echo",suffix:"suffix",arg:"foo"`}, ""},
793 {blessedByClient, "mountpoint/server/suffix", "Echo", v{"foo"}, v{`method:"Echo",suffix:"suffix",arg:"foo"`}, ""},
794 {serverID, "mountpoint/server/suffix", "Echo", v{"foo"}, v{`method:"Echo",suffix:"suffix",arg:"foo"`}, ""},
795 {blessedByServerOnlyEcho, "mountpoint/server/suffix", "Echo", v{"foo"}, v{`method:"Echo",suffix:"suffix",arg:"foo"`}, ""},
796 {clientID, "mountpoint/server/suffix", "Closure", nil, nil, ""},
797 {blessedByClient, "mountpoint/server/suffix", "Closure", nil, nil, ""},
798 {serverID, "mountpoint/server/suffix", "Closure", nil, nil, ""},
799 {clientID, "mountpoint/server/suffix", "Unauthorized", nil, v{""}, "application Authorizer denied access"},
800 {blessedByClient, "mountpoint/server/suffix", "Unauthorized", nil, v{""}, "application Authorizer denied access"},
801 {serverID, "mountpoint/server/suffix", "Unauthorized", nil, v{""}, "application Authorizer denied access"},
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700802 // Third-party caveat discharges should be fetched and forwarded
803 {blessedByServerTPValid, "mountpoint/server/suffix", "Echo", v{"foo"}, v{`method:"Echo",suffix:"suffix",arg:"foo"`}, ""},
804 {blessedByServerTPExpired, "mountpoint/server/suffix", "Echo", v{"foo"}, v{""}, "missing discharge"},
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700805 }
806 name := func(t testcase) string {
807 return fmt.Sprintf("%q RPCing %s.%s(%v)", t.clientID.PublicID(), t.name, t.method, t.args)
808 }
809
Ankura3c97652014-07-17 20:01:21 -0700810 b := createBundle(t, nil, serverID, &testServer{}) // we only create the server, a separate client will be created for each test.
Bogdan Caprita27953142014-05-12 11:41:42 -0700811 defer b.cleanup(t)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700812 for _, test := range tests {
Ankura3c97652014-07-17 20:01:21 -0700813 client, err := InternalNewClient(b.sm, b.ns, vc.FixedLocalID(test.clientID))
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700814 if err != nil {
815 t.Fatalf("InternalNewClient failed: %v", err)
816 }
817 defer client.Close()
Matt Rosencrantzbf85d542014-08-22 13:31:14 -0700818 call, err := client.StartCall(testContext(), test.name, test.method, test.args)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700819 if err != nil {
820 t.Errorf(`%s client.StartCall got unexpected error: "%v"`, name(test), err)
821 continue
822 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700823 results := makeResultPtrs(test.results)
824 err = call.Finish(results...)
825 if !matchesErrorPattern(err, test.finishErr) {
826 t.Errorf(`%s call.Finish got error: "%v", want to match: "%v"`, name(test), err, test.finishErr)
827 }
828 }
829}
830
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700831type alwaysValidCaveat struct{}
832
833func (alwaysValidCaveat) Validate(security.Context) error { return nil }
834
835func TestDischargePurgeFromCache(t *testing.T) {
836 var (
837 dischargerID = serverID.PublicID()
Ankurf044a8d2014-09-05 17:05:24 -0700838 c = mkThirdPartyCaveat(dischargerID, "mountpoint/server/discharger", newCaveat(alwaysValidCaveat{})[0])
839 clientCID = deriveForThirdPartyCaveats(serverID, "client", newCaveat(c)...)
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700840 )
841 b := createBundle(t, clientCID, serverID, &testServer{})
842 defer b.cleanup(t)
843
844 call := func() error {
Matt Rosencrantzbf85d542014-08-22 13:31:14 -0700845 call, err := b.client.StartCall(testContext(), "mountpoint/server/suffix", "Echo", []interface{}{"batman"})
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700846 if err != nil {
847 return fmt.Errorf("client.StartCall failed: %v", err)
848 }
849 var got string
850 if err := call.Finish(&got); err != nil {
851 return fmt.Errorf("client.Finish failed: %v", err)
852 }
853 if want := `method:"Echo",suffix:"suffix",arg:"batman"`; got != want {
854 return fmt.Errorf("Got [%v] want [%v]", got, want)
855 }
856 return nil
857 }
858
859 // First call should succeed
860 if err := call(); err != nil {
861 t.Fatal(err)
862 }
863 // Advance virtual clock, which will invalidate the discharge
864 clock.Advance(1)
865 if err := call(); !matchesErrorPattern(err, "fakeTimeCaveat expired") {
866 t.Errorf("Got error [%v] wanted to match pattern 'fakeTimeCaveat expired'", err)
867 }
868 // But retrying will succeed since the discharge should be purged from cache and refreshed
869 if err := call(); err != nil {
870 t.Fatal(err)
871 }
872}
873
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700874type cancelTestServer struct {
875 started chan struct{}
876 cancelled chan struct{}
877}
878
879func newCancelTestServer() *cancelTestServer {
880 return &cancelTestServer{
881 started: make(chan struct{}),
882 cancelled: make(chan struct{}),
883 }
884}
885
886func (s *cancelTestServer) CancelStreamReader(call ipc.ServerCall) error {
887 close(s.started)
888 for {
889 var b []byte
890 if err := call.Recv(&b); err != nil && err != io.EOF {
891 return err
892 }
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700893 select {
894 case <-call.Done():
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700895 close(s.cancelled)
896 return nil
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700897 default:
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700898 }
899 }
900}
901
902// CancelStreamIgnorer doesn't read from it's input stream so all it's
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700903// buffers fill. The intention is to show that call.Done() is closed
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700904// even when the stream is stalled.
905func (s *cancelTestServer) CancelStreamIgnorer(call ipc.ServerCall) error {
906 close(s.started)
907 for {
908 time.Sleep(time.Millisecond)
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700909 select {
910 case <-call.Done():
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700911 close(s.cancelled)
912 return nil
Matt Rosencrantz137b8d22014-08-18 09:56:15 -0700913 default:
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700914 }
915 }
916}
917
Matt Rosencrantzf5afcaf2014-06-02 11:31:22 -0700918func waitForCancel(t *testing.T, ts *cancelTestServer, call ipc.Call) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700919 <-ts.started
920 call.Cancel()
921 <-ts.cancelled
922}
923
924// TestCancel tests cancellation while the server is reading from a stream.
925func TestCancel(t *testing.T) {
926 ts := newCancelTestServer()
Bogdan Caprita27953142014-05-12 11:41:42 -0700927 b := createBundle(t, clientID, serverID, ts)
928 defer b.cleanup(t)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700929
Matt Rosencrantzbf85d542014-08-22 13:31:14 -0700930 call, err := b.client.StartCall(testContext(), "mountpoint/server/suffix", "CancelStreamReader", []interface{}{})
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700931 if err != nil {
932 t.Fatalf("Start call failed: %v", err)
933 }
934 for i := 0; i <= 10; i++ {
935 b := []byte{1, 2, 3}
936 if err := call.Send(b); err != nil {
937 t.Errorf("clientCall.Send error %q", err)
938 }
939 }
940 waitForCancel(t, ts, call)
941}
942
943// TestCancelWithFullBuffers tests that even if the writer has filled the buffers and
944// the server is not reading that the cancel message gets through.
945func TestCancelWithFullBuffers(t *testing.T) {
946 ts := newCancelTestServer()
Bogdan Caprita27953142014-05-12 11:41:42 -0700947 b := createBundle(t, clientID, serverID, ts)
948 defer b.cleanup(t)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700949
Matt Rosencrantzbf85d542014-08-22 13:31:14 -0700950 call, err := b.client.StartCall(testContext(), "mountpoint/server/suffix", "CancelStreamIgnorer", []interface{}{})
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700951 if err != nil {
952 t.Fatalf("Start call failed: %v", err)
953 }
954 // Fill up all the write buffers to ensure that cancelling works even when the stream
955 // is blocked.
956 call.Send(make([]byte, vc.MaxSharedBytes))
957 call.Send(make([]byte, vc.DefaultBytesBufferedPerFlow))
958
959 waitForCancel(t, ts, call)
960}
961
962type streamRecvInGoroutineServer struct{ c chan error }
963
964func (s *streamRecvInGoroutineServer) RecvInGoroutine(call ipc.ServerCall) error {
965 // Spawn a goroutine to read streaming data from the client.
966 go func() {
967 var i interface{}
968 for {
969 err := call.Recv(&i)
970 if err != nil {
971 s.c <- err
972 return
973 }
974 }
975 }()
976 // Imagine the server did some processing here and now that it is done,
977 // it does not care to see what else the client has to say.
978 return nil
979}
980
981func TestStreamReadTerminatedByServer(t *testing.T) {
982 s := &streamRecvInGoroutineServer{c: make(chan error, 1)}
Bogdan Caprita27953142014-05-12 11:41:42 -0700983 b := createBundle(t, clientID, serverID, s)
984 defer b.cleanup(t)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700985
Matt Rosencrantzbf85d542014-08-22 13:31:14 -0700986 call, err := b.client.StartCall(testContext(), "mountpoint/server/suffix", "RecvInGoroutine", []interface{}{})
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700987 if err != nil {
988 t.Fatalf("StartCall failed: %v", err)
989 }
990
991 c := make(chan error, 1)
992 go func() {
993 for i := 0; true; i++ {
994 if err := call.Send(i); err != nil {
995 c <- err
996 return
997 }
998 }
999 }()
1000
1001 // The goroutine at the server executing "Recv" should have terminated
1002 // with EOF.
1003 if err := <-s.c; err != io.EOF {
1004 t.Errorf("Got %v at server, want io.EOF", err)
1005 }
1006 // The client Send should have failed since the RPC has been
1007 // terminated.
1008 if err := <-c; err == nil {
1009 t.Errorf("Client Send should fail as the server should have closed the flow")
1010 }
1011}
1012
1013// TestConnectWithIncompatibleServers tests that clients ignore incompatible endpoints.
1014func TestConnectWithIncompatibleServers(t *testing.T) {
Bogdan Caprita27953142014-05-12 11:41:42 -07001015 b := createBundle(t, clientID, serverID, &testServer{})
1016 defer b.cleanup(t)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001017
1018 // Publish some incompatible endpoints.
Matt Rosencrantzbf85d542014-08-22 13:31:14 -07001019 publisher := publisher.New(testContext(), b.ns, publishPeriod)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001020 defer publisher.WaitForStop()
1021 defer publisher.Stop()
1022 publisher.AddName("incompatible")
1023 publisher.AddServer("/@2@tcp@localhost:10000@@1000000@2000000@@")
1024 publisher.AddServer("/@2@tcp@localhost:10001@@2000000@3000000@@")
1025
Matt Rosencrantzbf85d542014-08-22 13:31:14 -07001026 _, err := b.client.StartCall(testContext(), "incompatible/suffix", "Echo", []interface{}{"foo"})
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001027 if !strings.Contains(err.Error(), version.NoCompatibleVersionErr.Error()) {
1028 t.Errorf("Expected error %v, found: %v", version.NoCompatibleVersionErr, err)
1029 }
1030
1031 // Now add a server with a compatible endpoint and try again.
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -07001032 publisher.AddServer("/" + b.ep.String())
1033 publisher.AddName("incompatible")
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001034
Matt Rosencrantzbf85d542014-08-22 13:31:14 -07001035 call, err := b.client.StartCall(testContext(), "incompatible/suffix", "Echo", []interface{}{"foo"})
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001036 if err != nil {
Asim Shankar3a8a7e22014-05-12 18:01:44 -07001037 t.Fatal(err)
1038 }
1039 var result string
1040 if err = call.Finish(&result); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001041 t.Errorf("Unexpected error finishing call %v", err)
1042 }
Asim Shankar3a8a7e22014-05-12 18:01:44 -07001043 expected := `method:"Echo",suffix:"suffix",arg:"foo"`
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001044 if result != expected {
1045 t.Errorf("Wrong result returned. Got %s, wanted %s", result, expected)
1046 }
1047}
1048
Bogdan Caprita783f7792014-05-15 09:29:17 -07001049// TestReconnect verifies that the client transparently re-establishes the
1050// connection to the server if the server dies and comes back (on the same
1051// endpoint).
1052func TestReconnect(t *testing.T) {
1053 b := createBundle(t, clientID, nil, nil) // We only need the client from the bundle.
1054 defer b.cleanup(t)
Jiri Simsa73e9cac2014-06-30 09:55:10 -07001055 idFile := tsecurity.SaveIdentityToFile(derive(clientID, "server"))
Bogdan Caprita783f7792014-05-15 09:29:17 -07001056 server := blackbox.HelperCommand(t, "runServer", "127.0.0.1:0", idFile)
1057 server.Cmd.Start()
1058 addr, err := server.ReadLineFromChild()
1059 if err != nil {
1060 t.Fatalf("Failed to read server address from process: %v", err)
1061 }
1062 ep, err := inaming.NewEndpoint(addr)
1063 if err != nil {
1064 t.Fatalf("inaming.NewEndpoint(%q): %v", addr, err)
1065 }
Asim Shankarddc0c222014-07-29 15:47:00 -07001066 serverName := naming.JoinAddressName(ep.String(), "suffix")
Bogdan Caprita783f7792014-05-15 09:29:17 -07001067 makeCall := func() (string, error) {
Matt Rosencrantzbf85d542014-08-22 13:31:14 -07001068 call, err := b.client.StartCall(testContext(), serverName, "Echo", []interface{}{"bratman"})
Bogdan Caprita783f7792014-05-15 09:29:17 -07001069 if err != nil {
1070 return "", err
1071 }
1072 var result string
1073 if err = call.Finish(&result); err != nil {
1074 return "", err
1075 }
1076 return result, nil
1077 }
1078 expected := `method:"Echo",suffix:"suffix",arg:"bratman"`
1079 if result, err := makeCall(); err != nil || result != expected {
1080 t.Errorf("Got (%q, %v) want (%q, nil)", result, err, expected)
1081 }
1082 // Kill the server, verify client can't talk to it anymore.
1083 server.Cleanup()
1084 if _, err := makeCall(); err == nil {
1085 t.Fatal("Expected call to fail since server is dead")
1086 }
1087 // Resurrect the server with the same address, verify client
1088 // re-establishes the connection.
1089 server = blackbox.HelperCommand(t, "runServer", addr, idFile)
1090 defer server.Cleanup()
1091 server.Cmd.Start()
1092 if addr2, err := server.ReadLineFromChild(); addr2 != addr || err != nil {
1093 t.Fatalf("Got (%q, %v) want (%q, nil)", addr2, err, addr)
1094 }
1095 if result, err := makeCall(); err != nil || result != expected {
1096 t.Errorf("Got (%q, %v) want (%q, nil)", result, err, expected)
1097 }
1098}
1099
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001100func TestPreferredAddress(t *testing.T) {
1101 sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
1102 defer sm.Shutdown()
1103 ns := newNamespace()
Cosmos Nicolaouf7a11d92014-08-29 09:56:07 -07001104 pa := func(string, []net.Addr) (net.Addr, error) {
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001105 a := &net.IPAddr{}
1106 a.IP = net.ParseIP("1.1.1.1")
1107 return a, nil
1108 }
1109 server, err := InternalNewServer(testContext(), sm, ns, vc.FixedLocalID(serverID), veyron2.PreferredAddressOpt(pa))
1110 if err != nil {
1111 t.Errorf("InternalNewServer failed: %v", err)
1112 }
1113 defer server.Stop()
1114 ep, err := server.Listen("tcp4", ":0")
1115 iep := ep.(*inaming.Endpoint)
1116 host, _, err := net.SplitHostPort(iep.Address)
1117 if err != nil {
1118 t.Errorf("unexpected error: %s", err)
1119 }
1120 if got, want := host, "1.1.1.1"; got != want {
1121 t.Errorf("got %q, want %q", got, want)
1122 }
1123 // Won't override the specified address.
1124 ep, err = server.Listen("tcp4", "127.0.0.1:0")
1125 iep = ep.(*inaming.Endpoint)
1126 host, _, err = net.SplitHostPort(iep.Address)
1127 if err != nil {
1128 t.Errorf("unexpected error: %s", err)
1129 }
1130 if got, want := host, "127.0.0.1"; got != want {
1131 t.Errorf("got %q, want %q", got, want)
1132 }
1133}
1134
1135func TestPreferredAddressErrors(t *testing.T) {
1136 sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
1137 defer sm.Shutdown()
1138 ns := newNamespace()
Cosmos Nicolaouf7a11d92014-08-29 09:56:07 -07001139 paerr := func(string, []net.Addr) (net.Addr, error) {
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001140 return nil, fmt.Errorf("oops")
1141 }
1142 server, err := InternalNewServer(testContext(), sm, ns, vc.FixedLocalID(serverID), veyron2.PreferredAddressOpt(paerr))
1143 if err != nil {
1144 t.Errorf("InternalNewServer failed: %v", err)
1145 }
1146 defer server.Stop()
1147 ep, err := server.Listen("tcp4", ":0")
1148 iep := ep.(*inaming.Endpoint)
1149 host, _, err := net.SplitHostPort(iep.Address)
1150 if err != nil {
1151 t.Errorf("unexpected error: %s", err)
1152 }
1153 if got, want := host, "0.0.0.0"; got != want {
1154 t.Errorf("got %q, want %q", got, want)
1155 }
1156}
1157
Asim Shankar0ea02ab2014-06-09 11:39:24 -07001158type proxyHandle struct {
Cosmos Nicolaou4e029972014-06-13 14:53:08 -07001159 ns naming.Namespace
Asim Shankar0ea02ab2014-06-09 11:39:24 -07001160 process *blackbox.Child
1161 mount string
1162}
1163
1164func (h *proxyHandle) Start(t *testing.T) error {
1165 h.process = blackbox.HelperCommand(t, "runProxy")
1166 h.process.Cmd.Start()
1167 var err error
1168 if h.mount, err = h.process.ReadLineFromChild(); err != nil {
1169 return err
1170 }
Matt Rosencrantzbf85d542014-08-22 13:31:14 -07001171 if err := h.ns.Mount(testContext(), "proxy", h.mount, time.Hour); err != nil {
Asim Shankar0ea02ab2014-06-09 11:39:24 -07001172 return err
1173 }
1174 return nil
1175}
1176
1177func (h *proxyHandle) Stop() error {
1178 if h.process == nil {
1179 return nil
1180 }
1181 h.process.Cleanup()
1182 h.process = nil
1183 if len(h.mount) == 0 {
1184 return nil
1185 }
Matt Rosencrantzbf85d542014-08-22 13:31:14 -07001186 return h.ns.Unmount(testContext(), "proxy", h.mount)
Asim Shankar0ea02ab2014-06-09 11:39:24 -07001187}
1188
1189func TestProxy(t *testing.T) {
1190 sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
Cosmos Nicolaou4e029972014-06-13 14:53:08 -07001191 ns := newNamespace()
Ankura3c97652014-07-17 20:01:21 -07001192 client, err := InternalNewClient(sm, ns, vc.FixedLocalID(clientID))
Asim Shankar0ea02ab2014-06-09 11:39:24 -07001193 if err != nil {
1194 t.Fatal(err)
1195 }
1196 defer client.Close()
Matt Rosencrantzbf85d542014-08-22 13:31:14 -07001197 server, err := InternalNewServer(testContext(), sm, ns, vc.FixedLocalID(serverID))
Asim Shankar0ea02ab2014-06-09 11:39:24 -07001198 if err != nil {
1199 t.Fatal(err)
1200 }
1201 defer server.Stop()
Asim Shankar0ea02ab2014-06-09 11:39:24 -07001202
1203 name := "mountpoint/server/suffix"
1204 makeCall := func() (string, error) {
Matt Rosencrantzbf85d542014-08-22 13:31:14 -07001205 call, err := client.StartCall(testContext(), name, "Echo", []interface{}{"batman"})
Asim Shankar0ea02ab2014-06-09 11:39:24 -07001206 if err != nil {
1207 return "", err
1208 }
1209 var result string
1210 if err = call.Finish(&result); err != nil {
1211 return "", err
1212 }
1213 return result, nil
1214 }
Cosmos Nicolaou4e029972014-06-13 14:53:08 -07001215 proxy := &proxyHandle{ns: ns}
Asim Shankar0ea02ab2014-06-09 11:39:24 -07001216 if err := proxy.Start(t); err != nil {
1217 t.Fatal(err)
1218 }
1219 defer proxy.Stop()
1220 if _, err := server.Listen(inaming.Network, "proxy"); err != nil {
1221 t.Fatal(err)
1222 }
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -07001223 if err := server.Serve("mountpoint/server", testServerDisp{&testServer{}}); err != nil {
Asim Shankar0ea02ab2014-06-09 11:39:24 -07001224 t.Fatal(err)
1225 }
Cosmos Nicolaou4e029972014-06-13 14:53:08 -07001226 verifyMount(t, ns, name)
Asim Shankar0ea02ab2014-06-09 11:39:24 -07001227 // Proxied endpoint should be published and RPC should succeed (through proxy)
1228 const expected = `method:"Echo",suffix:"suffix",arg:"batman"`
1229 if result, err := makeCall(); result != expected || err != nil {
1230 t.Fatalf("Got (%v, %v) want (%v, nil)", result, err, expected)
1231 }
1232
1233 // Proxy dies, calls should fail and the name should be unmounted.
1234 if err := proxy.Stop(); err != nil {
1235 t.Fatal(err)
1236 }
1237 if result, err := makeCall(); err == nil {
1238 t.Fatalf(`Got (%v, %v) want ("", <non-nil>) as proxy is down`, result, err)
1239 }
1240 for {
Matt Rosencrantzbf85d542014-08-22 13:31:14 -07001241 if _, err := ns.Resolve(testContext(), name); err != nil {
Asim Shankar0ea02ab2014-06-09 11:39:24 -07001242 break
1243 }
1244 }
Cosmos Nicolaou4e029972014-06-13 14:53:08 -07001245 verifyMountMissing(t, ns, name)
Asim Shankar0ea02ab2014-06-09 11:39:24 -07001246
1247 // Proxy restarts, calls should eventually start succeeding.
1248 if err := proxy.Start(t); err != nil {
1249 t.Fatal(err)
1250 }
1251 for {
1252 if result, err := makeCall(); err == nil {
1253 if result != expected {
1254 t.Errorf("Got (%v, %v) want (%v, nil)", result, err, expected)
1255 }
1256 break
1257 }
1258 }
1259}
1260
Bogdan Caprita783f7792014-05-15 09:29:17 -07001261func loadIdentityFromFile(file string) security.PrivateID {
1262 f, err := os.Open(file)
1263 if err != nil {
1264 vlog.Fatalf("failed to open %v: %v", file, err)
1265 }
Tilak Sharmad6ade0e2014-08-20 16:28:32 -07001266 id, err := vsecurity.LoadIdentity(f)
Bogdan Caprita783f7792014-05-15 09:29:17 -07001267 f.Close()
1268 if err != nil {
1269 vlog.Fatalf("Failed to load identity from %v: %v", file, err)
1270 }
1271 return id
1272}
1273
1274func runServer(argv []string) {
1275 mgr := imanager.InternalNew(naming.FixedRoutingID(0x1111111))
Cosmos Nicolaou4e029972014-06-13 14:53:08 -07001276 ns := newNamespace()
Bogdan Caprita783f7792014-05-15 09:29:17 -07001277 id := loadIdentityFromFile(argv[1])
1278 isecurity.TrustIdentityProviders(id)
Matt Rosencrantzbf85d542014-08-22 13:31:14 -07001279 server, err := InternalNewServer(testContext(), mgr, ns, vc.FixedLocalID(id))
Bogdan Caprita783f7792014-05-15 09:29:17 -07001280 if err != nil {
1281 vlog.Fatalf("InternalNewServer failed: %v", err)
1282 }
1283 disp := testServerDisp{new(testServer)}
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -07001284 if err := server.Serve("server", disp); err != nil {
Bogdan Caprita783f7792014-05-15 09:29:17 -07001285 vlog.Fatalf("server.Register failed: %v", err)
1286 }
1287 ep, err := server.Listen("tcp", argv[0])
1288 if err != nil {
1289 vlog.Fatalf("server.Listen failed: %v", err)
1290 }
1291 fmt.Println(ep.Addr())
1292 // Live forever (parent process should explicitly kill us).
1293 <-make(chan struct{})
1294}
1295
Asim Shankar0ea02ab2014-06-09 11:39:24 -07001296func runProxy([]string) {
1297 rid, err := naming.NewRoutingID()
1298 if err != nil {
1299 vlog.Fatal(err)
1300 }
Adam Sadovsky5181bdb2014-08-13 10:29:11 -07001301 proxy, err := proxy.New(rid, nil, "tcp", "127.0.0.1:0", "")
Asim Shankar0ea02ab2014-06-09 11:39:24 -07001302 if err != nil {
1303 vlog.Fatal(err)
1304 }
1305 fmt.Println("/" + proxy.Endpoint().String())
1306 <-make(chan struct{})
1307}
1308
Bogdan Caprita783f7792014-05-15 09:29:17 -07001309// Required by blackbox framework.
1310func TestHelperProcess(t *testing.T) {
1311 blackbox.HelperProcess(t)
1312}
1313
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001314func init() {
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001315 isecurity.TrustIdentityProviders(clientID)
1316 isecurity.TrustIdentityProviders(serverID)
Bogdan Caprita783f7792014-05-15 09:29:17 -07001317
1318 blackbox.CommandTable["runServer"] = runServer
Asim Shankar0ea02ab2014-06-09 11:39:24 -07001319 blackbox.CommandTable["runProxy"] = runProxy
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001320
1321 vom.Register(fakeTimeCaveat(0))
Asim Shankara60d4902014-08-07 00:37:45 -07001322 vom.Register(alwaysValidCaveat{})
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001323}