blob: 07f540ade032aa308da8d6b706919060e67d3b89 [file] [log] [blame]
Jiri Simsad7616c92015-03-24 23:44:30 -07001// Copyright 2015 The Vanadium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Cosmos Nicolaou4e029972014-06-13 14:53:08 -07005package namespace_test
Jiri Simsa5293dcb2014-05-10 09:56:38 -07006
7import (
Asim Shankar263c73b2015-03-19 18:31:26 -07008 "fmt"
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -07009 "runtime"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070010 "runtime/debug"
Matt Rosencrantz50c2bb82014-07-24 09:10:33 -070011 "sync"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070012 "testing"
13 "time"
14
Jiri Simsa6ac95222015-02-23 16:11:49 -080015 "v.io/v23"
16 "v.io/v23/context"
Todd Wang5082a552015-04-02 10:56:11 -070017 "v.io/v23/namespace"
Jiri Simsa6ac95222015-02-23 16:11:49 -080018 "v.io/v23/naming"
19 "v.io/v23/options"
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070020 "v.io/v23/rpc"
Jiri Simsa6ac95222015-02-23 16:11:49 -080021 "v.io/v23/security"
22 "v.io/v23/verror"
Jiri Simsa337af232015-02-27 14:36:46 -080023 "v.io/x/lib/vlog"
Cosmos Nicolaouf889c732014-10-16 20:46:54 -070024
Jiri Simsaffceefa2015-02-28 11:03:34 -080025 _ "v.io/x/ref/profiles"
Todd Wang5082a552015-04-02 10:56:11 -070026 inamespace "v.io/x/ref/profiles/internal/naming/namespace"
Todd Wang5987a942015-04-06 11:06:17 -070027 "v.io/x/ref/services/mounttable/mounttablelib"
Todd Wang5082a552015-04-02 10:56:11 -070028 "v.io/x/ref/test"
Cosmos Nicolaou1381f8a2015-03-13 09:40:34 -070029 "v.io/x/ref/test/testutil"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070030)
31
Suharsh Sivakumard19c95d2015-02-19 14:44:50 -080032//go:generate v23 test generate
Asim Shankarc920db32014-10-16 19:18:21 -070033
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -080034func createContexts(t *testing.T) (sc, c *context.T, cleanup func()) {
Cosmos Nicolaoua18a1eb2015-03-12 13:15:01 -070035 ctx, shutdown := test.InitForTest()
Asim Shankarb547ea92015-02-17 18:49:45 -080036 var (
37 err error
Asim Shankar4a698282015-03-21 21:59:18 -070038 psc = testutil.NewPrincipal("sc")
39 pc = testutil.NewPrincipal("c")
Asim Shankarb547ea92015-02-17 18:49:45 -080040 )
41 // Setup the principals so that they recognize each other.
42 if err := psc.AddToRoots(pc.BlessingStore().Default()); err != nil {
Ankurfb9255a2015-01-21 15:29:38 -080043 t.Fatal(err)
44 }
Asim Shankarb547ea92015-02-17 18:49:45 -080045 if err := pc.AddToRoots(psc.BlessingStore().Default()); err != nil {
46 t.Fatal(err)
47 }
Todd Wangad492042015-04-17 15:58:40 -070048 if sc, err = v23.WithPrincipal(ctx, psc); err != nil {
Asim Shankarb547ea92015-02-17 18:49:45 -080049 t.Fatal(err)
50 }
Todd Wangad492042015-04-17 15:58:40 -070051 if c, err = v23.WithPrincipal(ctx, pc); err != nil {
Ankurfb9255a2015-01-21 15:29:38 -080052 t.Fatal(err)
53 }
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -080054 return sc, c, shutdown
Matt Rosencrantzac32b6c2014-12-01 15:49:18 -080055}
56
Jiri Simsa5293dcb2014-05-10 09:56:38 -070057func boom(t *testing.T, f string, v ...interface{}) {
58 t.Logf(f, v...)
59 t.Fatal(string(debug.Stack()))
60}
61
David Why Use Two When One Will Do Presottocce8f4f2014-09-30 14:50:44 -070062// N squared but who cares, this is a little test.
63// Ignores dups.
Cosmos Nicolaou6bed4192015-05-07 21:31:15 -070064func contains(container, contained []string) (string, bool) {
David Why Use Two When One Will Do Presottocce8f4f2014-09-30 14:50:44 -070065L:
66 for _, d := range contained {
67 for _, r := range container {
68 if r == d {
69 continue L
70 }
71 }
Cosmos Nicolaou6bed4192015-05-07 21:31:15 -070072 return d, false
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -070073 }
Cosmos Nicolaou6bed4192015-05-07 21:31:15 -070074 return "", true
David Why Use Two When One Will Do Presottocce8f4f2014-09-30 14:50:44 -070075}
76
77func compare(t *testing.T, caller, name string, got, want []string) {
78 // Compare ignoring dups.
Cosmos Nicolaou6bed4192015-05-07 21:31:15 -070079 a, foundA := contains(got, want)
80 b, foundB := contains(want, got)
81 if !foundA {
82 vlog.Infof("%s: %q: failed to find %q: got %v, want %v", caller, name, a, got, want)
83 boom(t, "%s: %q: failed to find %q: got %v, want %v", caller, name, a, got, want)
84 }
85 if !foundB {
86 vlog.Infof("%s: %q: failed to find %q: got %v, want %v", caller, name, a, got, want)
87 boom(t, "%s: %q: failed to find %q: got %v, want %v", caller, name, b, got, want)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -070088 }
89}
90
Todd Wang5082a552015-04-02 10:56:11 -070091func doGlob(t *testing.T, ctx *context.T, ns namespace.T, pattern string, limit int) []string {
Jiri Simsa5293dcb2014-05-10 09:56:38 -070092 var replies []string
Cosmos Nicolaou6bed4192015-05-07 21:31:15 -070093
94 sctx, done := context.WithTimeout(ctx, 2*time.Minute)
95 defer done()
96 rc, err := ns.Glob(sctx, pattern)
Jiri Simsa5293dcb2014-05-10 09:56:38 -070097 if err != nil {
98 boom(t, "Glob(%s): %s", pattern, err)
99 }
100 for s := range rc {
David Why Use Two When One Will Do Presotto03c34d62015-02-10 01:38:58 -0800101 switch v := s.(type) {
James Ringc971dca2015-04-09 09:51:20 -0700102 case *naming.GlobReplyEntry:
103 replies = append(replies, v.Value.Name)
David Why Use Two When One Will Do Presotto03c34d62015-02-10 01:38:58 -0800104 if limit > 0 && len(replies) > limit {
105 boom(t, "Glob returns too many results, perhaps not limiting recursion")
106 }
Cosmos Nicolaou6bed4192015-05-07 21:31:15 -0700107 case *naming.GlobReplyError:
108 boom(t, "Glob failed at %q: %v", v.Value.Name, v.Value.Error)
David Why Use Two When One Will Do Presotto2db32f92014-07-18 12:20:35 -0700109 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700110 }
111 return replies
112}
113
Robin Thellend434e39f2014-08-27 14:46:27 -0700114type testServer struct {
115 suffix string
116}
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700117
Todd Wang54feabe2015-04-15 23:38:26 -0700118func (testServer) KnockKnock(*context.T, rpc.ServerCall) (string, error) {
Todd Wange77f9952015-02-18 13:20:50 -0800119 return "Who's there?", nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700120}
121
Robin Thellend39ac3232014-12-02 09:50:41 -0800122// testServer has the following namespace:
Robin Thellend434e39f2014-08-27 14:46:27 -0700123// "" -> {level1} -> {level2}
Todd Wang54feabe2015-04-15 23:38:26 -0700124func (t *testServer) GlobChildren__(*context.T, rpc.ServerCall) (<-chan string, error) {
Robin Thellend39ac3232014-12-02 09:50:41 -0800125 ch := make(chan string, 1)
126 switch t.suffix {
127 case "":
128 ch <- "level1"
129 case "level1":
130 ch <- "level2"
131 default:
132 return nil, nil
Robin Thellend434e39f2014-08-27 14:46:27 -0700133 }
Robin Thellend39ac3232014-12-02 09:50:41 -0800134 close(ch)
135 return ch, nil
Robin Thellend434e39f2014-08-27 14:46:27 -0700136}
137
138type dispatcher struct{}
139
Robin Thellenda02fe8f2014-11-19 09:58:29 -0800140func (d *dispatcher) Lookup(suffix string) (interface{}, security.Authorizer, error) {
Asim Shankar149b4972015-04-23 13:29:58 -0700141 return &testServer{suffix}, security.AllowEveryone(), nil
Robin Thellend434e39f2014-08-27 14:46:27 -0700142}
143
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800144func knockKnock(t *testing.T, ctx *context.T, name string) {
Jiri Simsa6ac95222015-02-23 16:11:49 -0800145 client := v23.GetClient(ctx)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700146 var result string
Suharsh Sivakumar1abd5a82015-04-10 00:24:14 -0700147 if err := client.Call(ctx, name, "KnockKnock", nil, []interface{}{&result}); err != nil {
148 boom(t, "Call failed: %s", err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700149 }
150 if result != "Who's there?" {
151 boom(t, "Wrong result: %v", result)
152 }
153}
154
David Why Use Two When One Will Do Presotto38788d42015-03-31 17:13:54 -0700155func doResolveTest(t *testing.T, fname string, f func(*context.T, string, ...naming.NamespaceOpt) (*naming.MountEntry, error), ctx *context.T, name string, want []string, opts ...naming.NamespaceOpt) {
Cosmos Nicolaou6bed4192015-05-07 21:31:15 -0700156 maxretries := 5
157 var lastErr error
158 for i := 0; i < maxretries; i++ {
159 me, err := f(ctx, name, opts...)
160 if err == nil {
161 if i > 0 {
162 t.Logf("doResolveTest: retried %d times", i)
163 }
164 compare(t, fname, name, me.Names(), want)
165 return
166 }
167 if err != nil && verror.Action(err).RetryAction() != 0 {
168 boom(t, "Failed to %s %s: %s, attempt %d", fname, name, err, i)
169 }
170 lastErr = err
Ryan Brownbc2c87c2014-11-17 18:55:25 +0000171 }
Cosmos Nicolaou6bed4192015-05-07 21:31:15 -0700172 boom(t, "Failed to %s %s: %s after %d attempts", fname, name, lastErr, maxretries)
Ryan Brownfc290142014-11-24 15:47:24 -0800173}
174
Todd Wang5082a552015-04-02 10:56:11 -0700175func testResolveToMountTable(t *testing.T, ctx *context.T, ns namespace.T, name string, want ...string) {
David Why Use Two When One Will Do Presotto8de85852015-01-21 11:05:09 -0800176 doResolveTest(t, "ResolveToMountTable", ns.ResolveToMountTable, ctx, name, want)
Ryan Brownfc290142014-11-24 15:47:24 -0800177}
178
Todd Wang5082a552015-04-02 10:56:11 -0700179func testResolveToMountTableWithPattern(t *testing.T, ctx *context.T, ns namespace.T, name string, pattern naming.NamespaceOpt, want ...string) {
David Why Use Two When One Will Do Presotto8de85852015-01-21 11:05:09 -0800180 doResolveTest(t, "ResolveToMountTable", ns.ResolveToMountTable, ctx, name, want, pattern)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700181}
182
Todd Wang5082a552015-04-02 10:56:11 -0700183func testResolve(t *testing.T, ctx *context.T, ns namespace.T, name string, want ...string) {
David Why Use Two When One Will Do Presotto8de85852015-01-21 11:05:09 -0800184 doResolveTest(t, "Resolve", ns.Resolve, ctx, name, want)
Ryan Brownfc290142014-11-24 15:47:24 -0800185}
186
Todd Wang5082a552015-04-02 10:56:11 -0700187func testResolveWithPattern(t *testing.T, ctx *context.T, ns namespace.T, name string, pattern naming.NamespaceOpt, want ...string) {
David Why Use Two When One Will Do Presotto8de85852015-01-21 11:05:09 -0800188 doResolveTest(t, "Resolve", ns.Resolve, ctx, name, want, pattern)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700189}
190
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700191type serverEntry struct {
192 mountPoint string
Matt Rosencrantz94502cf2015-03-18 09:43:44 -0700193 server rpc.Server
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700194 endpoint naming.Endpoint
195 name string
196}
197
Matt Rosencrantz94502cf2015-03-18 09:43:44 -0700198func runServer(t *testing.T, ctx *context.T, disp rpc.Dispatcher, mountPoint string) *serverEntry {
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800199 return run(t, ctx, disp, mountPoint, false)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700200}
201
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800202func runMT(t *testing.T, ctx *context.T, mountPoint string) *serverEntry {
David Why Use Two When One Will Do Presottoba9593f2015-04-22 12:29:26 -0700203 mtd, err := mounttablelib.NewMountTableDispatcher("", "", "mounttable")
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700204 if err != nil {
Bogdan Capritae96cd042015-02-03 17:32:57 -0800205 boom(t, "NewMountTableDispatcher returned error: %v", err)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700206 }
Bogdan Capritae96cd042015-02-03 17:32:57 -0800207 return run(t, ctx, mtd, mountPoint, true)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700208}
209
Matt Rosencrantz94502cf2015-03-18 09:43:44 -0700210func run(t *testing.T, ctx *context.T, disp rpc.Dispatcher, mountPoint string, mt bool) *serverEntry {
Jiri Simsa6ac95222015-02-23 16:11:49 -0800211 s, err := v23.NewServer(ctx, options.ServesMountTable(mt))
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700212 if err != nil {
213 boom(t, "r.NewServer: %s", err)
214 }
215 // Add a mount table server.
216 // Start serving on a loopback address.
Jiri Simsa6ac95222015-02-23 16:11:49 -0800217 eps, err := s.Listen(v23.GetListenSpec(ctx))
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700218 if err != nil {
219 boom(t, "Failed to Listen: %s", err)
220 }
Cosmos Nicolaou92dba582014-11-05 17:24:10 -0800221 if err := s.ServeDispatcher(mountPoint, disp); err != nil {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700222 boom(t, "Failed to serve mount table at %s: %s", mountPoint, err)
223 }
Cosmos Nicolaou6bed4192015-05-07 21:31:15 -0700224 t.Logf("server %q -> %s", eps[0].Name(), mountPoint)
Cosmos Nicolaou8bd8e102015-01-13 21:52:53 -0800225 return &serverEntry{mountPoint: mountPoint, server: s, endpoint: eps[0], name: eps[0].Name()}
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700226}
227
228const (
229 mt1MP = "mt1"
230 mt2MP = "mt2"
231 mt3MP = "mt3"
232 mt4MP = "mt4"
233 mt5MP = "mt5"
234 j1MP = "joke1"
235 j2MP = "joke2"
236 j3MP = "joke3"
237
238 ttl = 100 * time.Second
239)
240
241// runMountTables creates a root mountable with some mount tables mounted
242// in it: mt{1,2,3,4,5}
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800243func runMountTables(t *testing.T, ctx *context.T) (*serverEntry, map[string]*serverEntry) {
244 root := runMT(t, ctx, "")
Jiri Simsa6ac95222015-02-23 16:11:49 -0800245 v23.GetNamespace(ctx).SetRoots(root.name)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700246 t.Logf("mountTable %q -> %s", root.mountPoint, root.endpoint)
247
248 mps := make(map[string]*serverEntry)
249 for _, mp := range []string{mt1MP, mt2MP, mt3MP, mt4MP, mt5MP} {
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800250 m := runMT(t, ctx, mp)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700251 t.Logf("mountTable %q -> %s", mp, m.endpoint)
252 mps[mp] = m
253 }
254 return root, mps
255}
256
Robin Thellend434e39f2014-08-27 14:46:27 -0700257// createNamespace creates a hierarchy of mounttables and servers
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700258// as follows:
259// /mt1, /mt2, /mt3, /mt4, /mt5, /joke1, /joke2, /joke3.
260// That is, mt1 is a mount table mounted in the root mount table,
261// joke1 is a server mounted in the root mount table.
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800262func createNamespace(t *testing.T, ctx *context.T) (*serverEntry, map[string]*serverEntry, map[string]*serverEntry, func()) {
263 root, mts := runMountTables(t, ctx)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700264 jokes := make(map[string]*serverEntry)
265 // Let's run some non-mount table services.
266 for _, j := range []string{j1MP, j2MP, j3MP} {
Robin Thellend434e39f2014-08-27 14:46:27 -0700267 disp := &dispatcher{}
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800268 jokes[j] = runServer(t, ctx, disp, j)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700269 }
270 return root, mts, jokes, func() {
271 for _, s := range jokes {
272 s.server.Stop()
273 }
274 for _, s := range mts {
275 s.server.Stop()
276 }
277 root.server.Stop()
278 }
279}
280
281// runNestedMountTables creates some nested mount tables in the hierarchy
282// created by createNamespace as follows:
283// /mt4/foo, /mt4/foo/bar and /mt4/baz where foo, bar and baz are mount tables.
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800284func runNestedMountTables(t *testing.T, ctx *context.T, mts map[string]*serverEntry) {
Jiri Simsa6ac95222015-02-23 16:11:49 -0800285 ns := v23.GetNamespace(ctx)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700286 // Set up some nested mounts and verify resolution.
287 for _, m := range []string{"mt4/foo", "mt4/foo/bar"} {
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800288 mts[m] = runMT(t, ctx, m)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700289 }
290
291 // Use a global name for a mount, rather than a relative one.
292 // We directly mount baz into the mt4/foo mount table.
293 globalMP := naming.JoinAddressName(mts["mt4/foo"].name, "baz")
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800294 mts["baz"] = runMT(t, ctx, "baz")
Cosmos Nicolaou6bed4192015-05-07 21:31:15 -0700295 sctx, done := context.WithTimeout(ctx, 2*time.Minute)
296 defer done()
297 if err := ns.Mount(sctx, globalMP, mts["baz"].name, ttl); err != nil {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700298 boom(t, "Failed to Mount %s: %s", globalMP, err)
299 }
300}
301
302// TestNamespaceCommon tests common use of the Namespace library
303// against a root mount table and some mount tables mounted on it.
304func TestNamespaceCommon(t *testing.T) {
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800305 _, c, cleanup := createContexts(t)
Matt Rosencrantzac32b6c2014-12-01 15:49:18 -0800306 defer cleanup()
307
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800308 root, mts, jokes, stopper := createNamespace(t, c)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700309 defer stopper()
Jiri Simsa6ac95222015-02-23 16:11:49 -0800310 ns := v23.GetNamespace(c)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700311
312 // All of the initial mounts are served by the root mounttable
313 // and hence ResolveToMountTable should return the root mountable
314 // as the address portion of the terminal name for those mounttables.
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800315 testResolveToMountTable(t, c, ns, "", root.name)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700316 for _, m := range []string{mt2MP, mt3MP, mt5MP} {
David Why Use Two When One Will Do Presotto8b4dbbf2014-11-06 10:50:14 -0800317 rootMT := naming.Join(root.name, m)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700318 // All of these mount tables are hosted by the root mount table
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800319 testResolveToMountTable(t, c, ns, m, rootMT)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700320
321 // The server registered for each mount point is a mount table
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800322 testResolve(t, c, ns, m, mts[m].name)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700323
324 // ResolveToMountTable will walk through to the sub MountTables
325 mtbar := naming.Join(m, "bar")
David Why Use Two When One Will Do Presotto8b4dbbf2014-11-06 10:50:14 -0800326 subMT := naming.Join(mts[m].name, "bar")
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800327 testResolveToMountTable(t, c, ns, mtbar, subMT)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700328 }
329
330 for _, j := range []string{j1MP, j2MP, j3MP} {
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800331 testResolve(t, c, ns, j, jokes[j].name)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700332 }
333}
334
Cosmos Nicolaou8bd8e102015-01-13 21:52:53 -0800335// TestNamespaceDetails tests more detailed use of the Namespace library.
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700336func TestNamespaceDetails(t *testing.T) {
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800337 sc, c, cleanup := createContexts(t)
Matt Rosencrantzac32b6c2014-12-01 15:49:18 -0800338 defer cleanup()
339
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800340 root, mts, _, stopper := createNamespace(t, sc)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700341 defer stopper()
342
Jiri Simsa6ac95222015-02-23 16:11:49 -0800343 ns := v23.GetNamespace(c)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700344 ns.SetRoots(root.name)
345
David Why Use Two When One Will Do Presottoadf0ca12014-11-13 10:49:01 -0800346 // /mt2 is not an endpoint. Thus, the example below will fail.
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700347 mt3Server := mts[mt3MP].name
David Why Use Two When One Will Do Presottoadf0ca12014-11-13 10:49:01 -0800348 mt2a := "/mt2/a"
Todd Wang8fa38762015-03-25 14:04:59 -0700349 if err := ns.Mount(c, mt2a, mt3Server, ttl); verror.ErrorID(err) == naming.ErrNoSuchName.ID {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700350 boom(t, "Successfully mounted %s - expected an err %v, not %v", mt2a, naming.ErrNoSuchName, err)
351 }
352
David Why Use Two When One Will Do Presottoadf0ca12014-11-13 10:49:01 -0800353 // Mount using the relative name.
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700354 // This means walk through mt2 if it already exists and mount within
355 // the lower level mount table, if the name doesn't exist we'll create
356 // a new name for it.
357 mt2a = "mt2/a"
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800358 if err := ns.Mount(c, mt2a, mt3Server, ttl); err != nil {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700359 boom(t, "Failed to Mount %s: %s", mt2a, err)
360 }
361
David Why Use Two When One Will Do Presotto8b4dbbf2014-11-06 10:50:14 -0800362 mt2mt := naming.Join(mts[mt2MP].name, "a")
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700363 // The mt2/a is served by the mt2 mount table
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800364 testResolveToMountTable(t, c, ns, mt2a, mt2mt)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700365 // The server for mt2a is mt3server from the second mount above.
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800366 testResolve(t, c, ns, mt2a, mt3Server)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700367
David Why Use Two When One Will Do Presottoadf0ca12014-11-13 10:49:01 -0800368 // Add two more mounts. The // should be stripped off of the
369 // second.
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700370 for _, mp := range []struct{ name, server string }{
371 {"mt2", mts[mt4MP].name},
David Why Use Two When One Will Do Presottoadf0ca12014-11-13 10:49:01 -0800372 {"mt2//", mts[mt5MP].name},
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700373 } {
David Why Use Two When One Will Do Presotto38788d42015-03-31 17:13:54 -0700374 if err := ns.Mount(c, mp.name, mp.server, ttl, naming.ServesMountTable(true)); err != nil {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700375 boom(t, "Failed to Mount %s: %s", mp.name, err)
376 }
377 }
378
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800379 names := []string{naming.JoinAddressName(mts[mt4MP].name, "a"),
380 naming.JoinAddressName(mts[mt5MP].name, "a")}
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800381 names = append(names, naming.JoinAddressName(mts[mt2MP].name, "a"))
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700382 // We now have 3 mount tables prepared to serve mt2/a
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800383 testResolveToMountTable(t, c, ns, "mt2/a", names...)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800384 names = []string{mts[mt4MP].name, mts[mt5MP].name}
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800385 names = append(names, mts[mt2MP].name)
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800386 testResolve(t, c, ns, "mt2", names...)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700387}
388
389// TestNestedMounts tests some more deeply nested mounts
390func TestNestedMounts(t *testing.T) {
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800391 sc, c, cleanup := createContexts(t)
Matt Rosencrantzac32b6c2014-12-01 15:49:18 -0800392 defer cleanup()
393
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800394 root, mts, _, stopper := createNamespace(t, sc)
395 runNestedMountTables(t, sc, mts)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700396 defer stopper()
397
Jiri Simsa6ac95222015-02-23 16:11:49 -0800398 ns := v23.GetNamespace(c)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700399 ns.SetRoots(root.name)
400
401 // Set up some nested mounts and verify resolution.
402 for _, m := range []string{"mt4/foo", "mt4/foo/bar"} {
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800403 testResolve(t, c, ns, m, mts[m].name)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700404 }
405
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800406 testResolveToMountTable(t, c, ns, "mt4/foo",
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800407 naming.JoinAddressName(mts[mt4MP].name, "foo"))
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800408 testResolveToMountTable(t, c, ns, "mt4/foo/bar",
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800409 naming.JoinAddressName(mts["mt4/foo"].name, "bar"))
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800410 testResolveToMountTable(t, c, ns, "mt4/foo/baz",
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800411 naming.JoinAddressName(mts["mt4/foo"].name, "baz"))
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700412}
413
414// TestServers tests invoking RPCs on simple servers
415func TestServers(t *testing.T) {
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800416 sc, c, cleanup := createContexts(t)
Matt Rosencrantzac32b6c2014-12-01 15:49:18 -0800417 defer cleanup()
418
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800419 root, mts, jokes, stopper := createNamespace(t, sc)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700420 defer stopper()
Jiri Simsa6ac95222015-02-23 16:11:49 -0800421 ns := v23.GetNamespace(c)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700422 ns.SetRoots(root.name)
423
Robin Thellend434e39f2014-08-27 14:46:27 -0700424 // Let's run some non-mount table services
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700425 for _, j := range []string{j1MP, j2MP, j3MP} {
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800426 testResolve(t, c, ns, j, jokes[j].name)
427 knockKnock(t, c, j)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700428 globalName := naming.JoinAddressName(mts["mt4"].name, j)
Robin Thellend434e39f2014-08-27 14:46:27 -0700429 disp := &dispatcher{}
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700430 gj := "g_" + j
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800431 jokes[gj] = runServer(t, c, disp, globalName)
432 testResolve(t, c, ns, "mt4/"+j, jokes[gj].name)
433 knockKnock(t, c, "mt4/"+j)
434 testResolveToMountTable(t, c, ns, "mt4/"+j, globalName)
435 testResolveToMountTable(t, c, ns, "mt4/"+j+"/garbage", globalName+"/garbage")
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700436 }
437}
438
439// TestGlob tests some glob patterns.
440func TestGlob(t *testing.T) {
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800441 sc, c, cleanup := createContexts(t)
Matt Rosencrantzac32b6c2014-12-01 15:49:18 -0800442 defer cleanup()
443
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800444 root, mts, _, stopper := createNamespace(t, sc)
445 runNestedMountTables(t, sc, mts)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700446 defer stopper()
Jiri Simsa6ac95222015-02-23 16:11:49 -0800447 ns := v23.GetNamespace(c)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700448 ns.SetRoots(root.name)
449
450 tln := []string{"baz", "mt1", "mt2", "mt3", "mt4", "mt5", "joke1", "joke2", "joke3"}
451 barbaz := []string{"mt4/foo/bar", "mt4/foo/baz"}
Robin Thellend434e39f2014-08-27 14:46:27 -0700452 level12 := []string{"joke1/level1", "joke1/level1/level2", "joke2/level1", "joke2/level1/level2", "joke3/level1", "joke3/level1/level2"}
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700453 foo := append([]string{"mt4/foo"}, barbaz...)
Robin Thellend434e39f2014-08-27 14:46:27 -0700454 foo = append(foo, level12...)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700455 // Try various globs.
456 globTests := []struct {
457 pattern string
458 expected []string
459 }{
460 {"*", tln},
David Why Use Two When One Will Do Presottocce8f4f2014-09-30 14:50:44 -0700461 {"x", []string{}},
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700462 {"m*", []string{"mt1", "mt2", "mt3", "mt4", "mt5"}},
463 {"mt[2,3]", []string{"mt2", "mt3"}},
464 {"*z", []string{"baz"}},
Robin Thellend434e39f2014-08-27 14:46:27 -0700465 {"joke1/*", []string{"joke1/level1"}},
466 {"j?ke1/level1/*", []string{"joke1/level1/level2"}},
467 {"joke1/level1/*", []string{"joke1/level1/level2"}},
468 {"joke1/level1/level2/...", []string{"joke1/level1/level2"}},
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700469 {"...", append(append(tln, foo...), "")},
470 {"*/...", append(tln, foo...)},
471 {"*/foo/*", barbaz},
472 {"*/*/*z", []string{"mt4/foo/baz"}},
473 {"*/f??/*z", []string{"mt4/foo/baz"}},
Robin Thellend434e39f2014-08-27 14:46:27 -0700474 {"mt4/foo/baz", []string{"mt4/foo/baz"}},
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700475 }
476 for _, test := range globTests {
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800477 out := doGlob(t, c, ns, test.pattern, 0)
Robin Thellend434e39f2014-08-27 14:46:27 -0700478 compare(t, "Glob", test.pattern, out, test.expected)
Robin Thellend5f838572014-07-10 13:28:56 -0700479 // Do the same with a full rooted name.
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800480 out = doGlob(t, c, ns, naming.JoinAddressName(root.name, test.pattern), 0)
Robin Thellend5f838572014-07-10 13:28:56 -0700481 var expectedWithRoot []string
482 for _, s := range test.expected {
483 expectedWithRoot = append(expectedWithRoot, naming.JoinAddressName(root.name, s))
484 }
Robin Thellend434e39f2014-08-27 14:46:27 -0700485 compare(t, "Glob", test.pattern, out, expectedWithRoot)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700486 }
487}
488
Matt Rosencrantz50c2bb82014-07-24 09:10:33 -0700489type GlobbableServer struct {
490 callCount int
491 mu sync.Mutex
492}
493
Todd Wang54feabe2015-04-15 23:38:26 -0700494func (g *GlobbableServer) Glob__(*context.T, rpc.ServerCall, string) (<-chan naming.GlobReply, error) {
Matt Rosencrantz50c2bb82014-07-24 09:10:33 -0700495 g.mu.Lock()
496 defer g.mu.Unlock()
497 g.callCount++
Robin Thellend39ac3232014-12-02 09:50:41 -0800498 return nil, nil
Matt Rosencrantz50c2bb82014-07-24 09:10:33 -0700499}
500
501func (g *GlobbableServer) GetAndResetCount() int {
502 g.mu.Lock()
503 defer g.mu.Unlock()
504 cnt := g.callCount
505 g.callCount = 0
506
507 return cnt
508}
509
510// TestGlobEarlyStop tests that Glob doesn't query terminal servers with finished patterns.
511func TestGlobEarlyStop(t *testing.T) {
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800512 sc, c, cleanup := createContexts(t)
Matt Rosencrantzac32b6c2014-12-01 15:49:18 -0800513 defer cleanup()
514
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800515 root, mts, _, stopper := createNamespace(t, sc)
516 runNestedMountTables(t, sc, mts)
Matt Rosencrantz50c2bb82014-07-24 09:10:33 -0700517 defer stopper()
518
519 globServer := &GlobbableServer{}
520 name := naming.JoinAddressName(mts["mt4/foo/bar"].name, "glob")
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800521 runningGlobServer := runServer(t, c, testutil.LeafDispatcher(globServer, nil), name)
Matt Rosencrantz50c2bb82014-07-24 09:10:33 -0700522 defer runningGlobServer.server.Stop()
523
Jiri Simsa6ac95222015-02-23 16:11:49 -0800524 ns := v23.GetNamespace(c)
Matt Rosencrantz50c2bb82014-07-24 09:10:33 -0700525 ns.SetRoots(root.name)
526
527 tests := []struct {
528 pattern string
529 expectedCalls int
David Why Use Two When One Will Do Presottoc28686e2014-11-05 11:19:29 -0800530 expected []string
Matt Rosencrantz50c2bb82014-07-24 09:10:33 -0700531 }{
David Why Use Two When One Will Do Presottoc28686e2014-11-05 11:19:29 -0800532 {"mt4/foo/bar/glob", 0, []string{"mt4/foo/bar/glob"}},
533 {"mt4/foo/bar/glob/...", 1, []string{"mt4/foo/bar/glob"}},
534 {"mt4/foo/bar/glob/*", 1, nil},
535 {"mt4/foo/bar/***", 0, []string{"mt4/foo/bar", "mt4/foo/bar/glob"}},
536 {"mt4/foo/bar/...", 1, []string{"mt4/foo/bar", "mt4/foo/bar/glob"}},
537 {"mt4/foo/bar/*", 0, []string{"mt4/foo/bar/glob"}},
538 {"mt4/***/bar/***", 0, []string{"mt4/foo/bar", "mt4/foo/bar/glob"}},
539 {"mt4/*/bar/***", 0, []string{"mt4/foo/bar", "mt4/foo/bar/glob"}},
Matt Rosencrantz50c2bb82014-07-24 09:10:33 -0700540 }
David Why Use Two When One Will Do Presottoc28686e2014-11-05 11:19:29 -0800541 // Test allowing the tests to descend into leaves.
Matt Rosencrantz50c2bb82014-07-24 09:10:33 -0700542 for _, test := range tests {
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800543 out := doGlob(t, c, ns, test.pattern, 0)
David Why Use Two When One Will Do Presottoc28686e2014-11-05 11:19:29 -0800544 compare(t, "Glob", test.pattern, out, test.expected)
Matt Rosencrantz50c2bb82014-07-24 09:10:33 -0700545 if calls := globServer.GetAndResetCount(); calls != test.expectedCalls {
546 boom(t, "Wrong number of Glob calls to terminal server got: %d want: %d.", calls, test.expectedCalls)
547 }
548 }
549}
550
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700551func TestCycles(t *testing.T) {
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800552 sc, c, cleanup := createContexts(t)
Matt Rosencrantzac32b6c2014-12-01 15:49:18 -0800553 defer cleanup()
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700554
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800555 root, _, _, stopper := createNamespace(t, sc)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700556 defer stopper()
Jiri Simsa6ac95222015-02-23 16:11:49 -0800557 ns := v23.GetNamespace(c)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700558 ns.SetRoots(root.name)
559
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800560 c1 := runMT(t, c, "c1")
561 c2 := runMT(t, c, "c2")
562 c3 := runMT(t, c, "c3")
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700563 defer c1.server.Stop()
564 defer c2.server.Stop()
565 defer c3.server.Stop()
566
567 m := "c1/c2"
David Why Use Two When One Will Do Presotto38788d42015-03-31 17:13:54 -0700568 if err := ns.Mount(c, m, c1.name, ttl, naming.ServesMountTable(true)); err != nil {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700569 boom(t, "Failed to Mount %s: %s", "c1/c2", err)
570 }
571
572 m = "c1/c2/c3"
David Why Use Two When One Will Do Presotto38788d42015-03-31 17:13:54 -0700573 if err := ns.Mount(c, m, c3.name, ttl, naming.ServesMountTable(true)); err != nil {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700574 boom(t, "Failed to Mount %s: %s", m, err)
575 }
576
577 m = "c1/c3/c4"
David Why Use Two When One Will Do Presotto38788d42015-03-31 17:13:54 -0700578 if err := ns.Mount(c, m, c1.name, ttl, naming.ServesMountTable(true)); err != nil {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700579 boom(t, "Failed to Mount %s: %s", m, err)
580 }
581
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800582 // Since c1 was mounted with the Serve call, it will have both the tcp and ws endpoints.
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800583 testResolve(t, c, ns, "c1", c1.name)
584 testResolve(t, c, ns, "c1/c2", c1.name)
585 testResolve(t, c, ns, "c1/c3", c3.name)
586 testResolve(t, c, ns, "c1/c3/c4", c1.name)
587 testResolve(t, c, ns, "c1/c3/c4/c3/c4", c1.name)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700588 cycle := "c3/c4"
589 for i := 0; i < 40; i++ {
590 cycle += "/c3/c4"
591 }
Todd Wang8fa38762015-03-25 14:04:59 -0700592 if _, err := ns.Resolve(c, "c1/"+cycle); verror.ErrorID(err) != naming.ErrResolutionDepthExceeded.ID {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700593 boom(t, "Failed to detect cycle")
594 }
595
David Why Use Two When One Will Do Presotto3fc13f42015-03-30 09:56:26 -0700596 // Perform the glob with a response length limit and dup suppression. The dup supression
597 // should win.
598 r := doGlob(t, c, ns, "c1/...", 1000)
599 if len(r) != 6 {
Asim Shankara036a0f2015-05-08 11:22:54 -0700600 t.Fatalf("expected 6 replies, got %v", r)
David Why Use Two When One Will Do Presotto3fc13f42015-03-30 09:56:26 -0700601 }
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700602}
603
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700604// TestGoroutineLeaks tests for leaking goroutines - we have many:-(
605func TestGoroutineLeaks(t *testing.T) {
606 t.Skip()
Suharsh Sivakumar19fbf992015-01-23 11:02:27 -0800607 sc, _, cleanup := createContexts(t)
Matt Rosencrantzac32b6c2014-12-01 15:49:18 -0800608 defer cleanup()
609
Matt Rosencrantz6edab562015-01-12 11:07:55 -0800610 _, _, _, stopper := createNamespace(t, sc)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700611 defer func() {
612 vlog.Infof("%d goroutines:", runtime.NumGoroutine())
613 }()
614 defer stopper()
615 defer func() {
616 vlog.Infof("%d goroutines:", runtime.NumGoroutine())
617 }()
618 //panic("this will show up lots of goroutine+channel leaks!!!!")
619}
620
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700621func TestBadRoots(t *testing.T) {
Todd Wang5082a552015-04-02 10:56:11 -0700622 if _, err := inamespace.New(); err != nil {
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700623 t.Errorf("namespace.New should not have failed with no roots")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700624 }
Todd Wang5082a552015-04-02 10:56:11 -0700625 if _, err := inamespace.New("not a rooted name"); err == nil {
Cosmos Nicolaou4e029972014-06-13 14:53:08 -0700626 t.Errorf("namespace.New should have failed with an unrooted name")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700627 }
628}
Ryan Brownfc290142014-11-24 15:47:24 -0800629
630func bless(blesser, delegate security.Principal, extension string) {
631 b, err := blesser.Bless(delegate.PublicKey(), blesser.BlessingStore().Default(), extension, security.UnconstrainedUse())
632 if err != nil {
633 panic(err)
634 }
635 delegate.BlessingStore().SetDefault(b)
636}
637
Asim Shankar263c73b2015-03-19 18:31:26 -0700638func TestAuthorizationDuringResolve(t *testing.T) {
Jiri Simsa6ac95222015-02-23 16:11:49 -0800639 ctx, shutdown := v23.Init()
Asim Shankarb547ea92015-02-17 18:49:45 -0800640 defer shutdown()
641
642 var (
Todd Wangad492042015-04-17 15:58:40 -0700643 rootMtCtx, _ = v23.WithPrincipal(ctx, testutil.NewPrincipal()) // root mounttable
644 mtCtx, _ = v23.WithPrincipal(ctx, testutil.NewPrincipal()) // intermediate mounttable
645 serverCtx, _ = v23.WithPrincipal(ctx, testutil.NewPrincipal()) // end server
646 clientCtx, _ = v23.WithPrincipal(ctx, testutil.NewPrincipal()) // client process (doing Resolves).
647 idp = testutil.NewIDProvider("idp") // identity provider
Asim Shankar263c73b2015-03-19 18:31:26 -0700648 serverEndpoint = naming.FormatEndpoint("tcp", "127.0.0.1:14141")
Asim Shankarb547ea92015-02-17 18:49:45 -0800649
David Why Use Two When One Will Do Presotto38788d42015-03-31 17:13:54 -0700650 resolve = func(name string, opts ...naming.NamespaceOpt) (*naming.MountEntry, error) {
Jiri Simsa6ac95222015-02-23 16:11:49 -0800651 return v23.GetNamespace(clientCtx).Resolve(clientCtx, name, opts...)
Asim Shankarb547ea92015-02-17 18:49:45 -0800652 }
653
David Why Use Two When One Will Do Presotto38788d42015-03-31 17:13:54 -0700654 mount = func(name, server string, ttl time.Duration, opts ...naming.NamespaceOpt) error {
Jiri Simsa6ac95222015-02-23 16:11:49 -0800655 return v23.GetNamespace(serverCtx).Mount(serverCtx, name, server, ttl, opts...)
Asim Shankarb547ea92015-02-17 18:49:45 -0800656 }
657 )
658 // Setup default blessings for the processes.
Jiri Simsa6ac95222015-02-23 16:11:49 -0800659 idp.Bless(v23.GetPrincipal(rootMtCtx), "rootmt")
660 idp.Bless(v23.GetPrincipal(serverCtx), "server")
661 idp.Bless(v23.GetPrincipal(mtCtx), "childmt")
662 idp.Bless(v23.GetPrincipal(clientCtx), "client")
Asim Shankarb547ea92015-02-17 18:49:45 -0800663
664 // Setup the namespace root for all the "processes".
665 rootmt := runMT(t, rootMtCtx, "")
666 for _, ctx := range []*context.T{mtCtx, serverCtx, clientCtx} {
Jiri Simsa6ac95222015-02-23 16:11:49 -0800667 v23.GetNamespace(ctx).SetRoots(rootmt.name)
Asim Shankarb547ea92015-02-17 18:49:45 -0800668 }
669 // Disable caching in the client so that any Mount calls by the server
670 // are noticed immediately.
Jiri Simsa6ac95222015-02-23 16:11:49 -0800671 v23.GetNamespace(clientCtx).CacheCtl(naming.DisableCache(true))
Asim Shankarb547ea92015-02-17 18:49:45 -0800672
Asim Shankarb547ea92015-02-17 18:49:45 -0800673 // Intermediate mounttables should be authenticated.
Suharsh Sivakumar77357d72015-02-21 22:14:20 -0800674 mt := runMT(t, mtCtx, "mt")
Cosmos Nicolaou6bed4192015-05-07 21:31:15 -0700675 defer func() {
676 mt.server.Stop()
677 }()
Suharsh Sivakumar77357d72015-02-21 22:14:20 -0800678 // Mount a server on "mt".
David Why Use Two When One Will Do Presotto38788d42015-03-31 17:13:54 -0700679 if err := mount("mt/server", serverEndpoint, time.Minute, naming.ReplaceMount(true)); err != nil {
Asim Shankarb547ea92015-02-17 18:49:45 -0800680 t.Error(err)
Suharsh Sivakumar77357d72015-02-21 22:14:20 -0800681 }
Asim Shankar263c73b2015-03-19 18:31:26 -0700682 // The namespace root should be authenticated too
683 if e, err := resolve("mt/server"); err != nil {
684 t.Errorf("Got (%v, %v)", e, err)
685 } else {
686 // Host:Port and Endpoint versions of the other namespace root
687 // (which has different blessings)
688 hproot := fmt.Sprintf("(otherroot)@%v", rootmt.endpoint.Addr())
David Why Use Two When One Will Do Presotto38788d42015-03-31 17:13:54 -0700689 eproot := naming.FormatEndpoint(rootmt.endpoint.Addr().Network(), rootmt.endpoint.Addr().String(), rootmt.endpoint.RoutingID(), naming.BlessingOpt("otherroot"), naming.ServesMountTable(rootmt.endpoint.ServesMountTable()))
Asim Shankar263c73b2015-03-19 18:31:26 -0700690 for _, root := range []string{hproot, eproot} {
691 name := naming.JoinAddressName(root, "mt")
692 // Rooted name resolutions should fail authorization because of the "otherrot"
Todd Wang8fa38762015-03-25 14:04:59 -0700693 if e, err := resolve(name); verror.ErrorID(err) != verror.ErrNotTrusted.ID {
Asim Shankar263c73b2015-03-19 18:31:26 -0700694 t.Errorf("resolve(%q) returned (%v, errorid=%v %v), wanted errorid=%v", name, e, verror.ErrorID(err), err, verror.ErrNotTrusted.ID)
695 }
696 // But not fail if the skip-authorization option is provided
697 if e, err := resolve(name, options.SkipServerEndpointAuthorization{}); err != nil {
698 t.Errorf("resolve(%q): Got (%v, %v), expected resolution to succeed", name, e, err)
699 }
700 // The namespace root from the context should be authorized as well.
Todd Wangad492042015-04-17 15:58:40 -0700701 ctx, ns, _ := v23.WithNewNamespace(clientCtx, naming.JoinAddressName(root, ""))
Todd Wang8fa38762015-03-25 14:04:59 -0700702 if e, err := ns.Resolve(ctx, "mt/server"); verror.ErrorID(err) != verror.ErrNotTrusted.ID {
Matt Rosencrantz0e207172015-04-16 14:58:02 -0700703 t.Errorf("resolve with root=%q returned (%v, errorid=%v %v), wanted errorid=%v: %s", root, e, verror.ErrorID(err), err, verror.ErrNotTrusted.ID, verror.DebugString(err))
Asim Shankar263c73b2015-03-19 18:31:26 -0700704 }
705 if _, err := ns.Resolve(ctx, "mt/server", options.SkipServerEndpointAuthorization{}); err != nil {
Matt Rosencrantz0e207172015-04-16 14:58:02 -0700706 t.Errorf("resolve with root=%q should have succeeded when authorization checks are skipped. Got %v: %s", root, err, verror.DebugString(err))
Asim Shankar263c73b2015-03-19 18:31:26 -0700707 }
708 }
709 }
710 // Imagine that the network address of "mt" has been taken over by an
711 // attacker. However, this attacker cannot mess with the mount entry
712 // for "mt". This would result in "mt" and its mount entry (in the
713 // global mounttable) having inconsistent blessings. Simulate this by
714 // explicitly changing the mount entry for "mt".
715 goodChildMTEndpoint := naming.FormatEndpoint(mt.endpoint.Addr().Network(), mt.endpoint.Addr().String(), naming.BlessingOpt("idp/goodchildmt"), mt.endpoint.RoutingID())
David Why Use Two When One Will Do Presotto38788d42015-03-31 17:13:54 -0700716 if err := v23.GetNamespace(mtCtx).Mount(mtCtx, "mt", goodChildMTEndpoint, time.Minute, naming.ServesMountTable(true), naming.ReplaceMount(true)); err != nil {
Asim Shankarb547ea92015-02-17 18:49:45 -0800717 t.Error(err)
Suharsh Sivakumar77357d72015-02-21 22:14:20 -0800718 }
719
Asim Shankar263c73b2015-03-19 18:31:26 -0700720 if e, err := resolve("mt/server", options.SkipServerEndpointAuthorization{}); err != nil {
Matt Rosencrantz0e207172015-04-16 14:58:02 -0700721 t.Errorf("Resolve should succeed when skipping server authorization. Got (%v, %v) %s", e, err, verror.DebugString(err))
Todd Wang8fa38762015-03-25 14:04:59 -0700722 } else if e, err := resolve("mt/server"); verror.ErrorID(err) != verror.ErrNotTrusted.ID {
Asim Shankarb547ea92015-02-17 18:49:45 -0800723 t.Errorf("Resolve should have failed with %q because an attacker has taken over the intermediate mounttable. Got (%+v, errorid=%q:%v)", verror.ErrNotTrusted.ID, e, verror.ErrorID(err), err)
724 }
725}
David Why Use Two When One Will Do Presotto18be8b02015-03-02 17:26:25 -0800726
727// TestDelete tests deleting some parts of the name space.
728func TestDelete(t *testing.T) {
729 _, c, cleanup := createContexts(t)
730 defer cleanup()
731 ns := v23.GetNamespace(c)
732
733 // Create a root mount table with mount tables mounted at mt1, mt1, ...
734 root, _, _, stopper := createNamespace(t, c)
735 defer stopper()
736 ns.SetRoots(root.name)
737
738 // We should be able to remove servers below the root.
739 if err := ns.Delete(c, "mt1", false); err != nil {
740 t.Errorf("Delete failed: %s", err)
741 }
742
743 // Create a server below one level down.
744 if err := ns.Mount(c, "mt2/b/c", "/madeup:1111/server", time.Minute); err != nil {
745 t.Errorf("Mount mt2/b/c failed: %s", err)
746 }
747
748 // We should not be able to delete mt2/b...
749 if err := ns.Delete(c, "mt2/b", false); err == nil {
750 t.Errorf("Delete mt2/b should have failed")
751 }
752
753 // ...unless we include its children.
754 if err := ns.Delete(c, "mt2/b", true); err != nil {
755 t.Errorf("Delete failed: %s", err)
756 }
757}
Robin Thellend89e95232015-03-24 13:48:48 -0700758
759type leafObject struct{}
760
Todd Wang54feabe2015-04-15 23:38:26 -0700761func (leafObject) Foo(*context.T, rpc.ServerCall) error {
Robin Thellend89e95232015-03-24 13:48:48 -0700762 return nil
763}
764
765func TestLeaf(t *testing.T) {
766 _, ctx, cleanup := createContexts(t)
767 defer cleanup()
768 root := runMT(t, ctx, "")
Cosmos Nicolaou6bed4192015-05-07 21:31:15 -0700769 defer func() { root.server.Stop() }()
770
Robin Thellend89e95232015-03-24 13:48:48 -0700771 ns := v23.GetNamespace(ctx)
772 ns.SetRoots(root.name)
773
774 server, err := v23.NewServer(ctx)
775 if err != nil {
776 boom(t, "v23.NewServer: %s", err)
777 }
778 ls := rpc.ListenSpec{Addrs: rpc.ListenAddrs{{"tcp", "127.0.0.1:0"}}}
779 if _, err := server.Listen(ls); err != nil {
780 boom(t, "Failed to Listen: %s", err)
781 }
782 if err := server.Serve("leaf", &leafObject{}, nil); err != nil {
783 boom(t, "server.Serve failed: %s", err)
784 }
Cosmos Nicolaou6bed4192015-05-07 21:31:15 -0700785 defer server.Stop()
Robin Thellend89e95232015-03-24 13:48:48 -0700786
787 mountEntry, err := ns.Resolve(ctx, "leaf")
788 if err != nil {
789 boom(t, "ns.Resolve failed: %v", err)
790 }
791 if expected := true; mountEntry.IsLeaf != expected {
792 boom(t, "unexpected mountEntry.IsLeaf value. Got %v, expected %v", mountEntry.IsLeaf, expected)
793 }
Robin Thellend00643742015-04-01 10:36:50 -0700794
795 c, err := ns.Glob(ctx, "leaf")
796 if err != nil {
797 boom(t, "ns.Glob failed: %v", err)
798 }
799 count := 0
800 for result := range c {
James Ringc971dca2015-04-09 09:51:20 -0700801 if me, ok := result.(*naming.GlobReplyEntry); ok {
Robin Thellend00643742015-04-01 10:36:50 -0700802 count++
James Ringc971dca2015-04-09 09:51:20 -0700803 if expected := true; me.Value.IsLeaf != expected {
804 boom(t, "unexpected me.IsLeaf value. Got %v, expected %v", me.Value.IsLeaf, expected)
Robin Thellend00643742015-04-01 10:36:50 -0700805 }
806 }
807 }
808 if count == 0 {
809 boom(t, "Glob did not return any results. Expected 1")
810 }
Robin Thellend89e95232015-03-24 13:48:48 -0700811}