blob: 178022214870e47d03d3d18dec880f289542e0ec [file] [log] [blame]
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001package mounttable
2
3import (
4 "errors"
Asim Shankar88292912014-10-09 19:41:07 -07005 "fmt"
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -07006 "io"
Jiri Simsa5293dcb2014-05-10 09:56:38 -07007 "reflect"
8 "runtime/debug"
9 "sort"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070010 "testing"
11 "time"
12
Jiri Simsa519c5072014-09-17 21:37:57 -070013 "veyron.io/veyron/veyron2"
Jiri Simsa519c5072014-09-17 21:37:57 -070014 "veyron.io/veyron/veyron2/ipc"
15 "veyron.io/veyron/veyron2/naming"
Asim Shankarcc044212014-10-15 23:25:26 -070016 "veyron.io/veyron/veyron2/options"
Jiri Simsa519c5072014-09-17 21:37:57 -070017 "veyron.io/veyron/veyron2/rt"
18 "veyron.io/veyron/veyron2/security"
Jiri Simsa519c5072014-09-17 21:37:57 -070019 "veyron.io/veyron/veyron2/services/mounttable/types"
20 "veyron.io/veyron/veyron2/vlog"
Cosmos Nicolaoud6c3c9c2014-09-30 15:42:53 -070021
Asim Shankarc920db32014-10-16 19:18:21 -070022 "veyron.io/veyron/veyron/lib/testutil"
Cosmos Nicolaoud6c3c9c2014-09-30 15:42:53 -070023 "veyron.io/veyron/veyron/profiles"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070024)
25
Asim Shankar88292912014-10-09 19:41:07 -070026// Simulate different processes with different runtimes.
27// rootRT is the one running the mounttable service.
28var rootRT, aliceRT, bobRT veyron2.Runtime
Jiri Simsa5293dcb2014-05-10 09:56:38 -070029
30const ttlSecs = 60 * 60
31
32func boom(t *testing.T, f string, v ...interface{}) {
33 t.Logf(f, v...)
34 t.Fatal(string(debug.Stack()))
35}
36
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -070037func doMount(t *testing.T, ep, suffix, service string, shouldSucceed bool, as veyron2.Runtime) {
38 name := naming.JoinAddressName(ep, suffix)
39 ctx := as.NewContext()
40 client := as.Client()
41 call, err := client.StartCall(ctx, name, "Mount", []interface{}{service, uint32(ttlSecs), 0}, options.NoResolve(true))
Jiri Simsa5293dcb2014-05-10 09:56:38 -070042 if err != nil {
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -070043 if !shouldSucceed {
44 return
Jiri Simsa5293dcb2014-05-10 09:56:38 -070045 }
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -070046 boom(t, "Failed to Mount %s onto %s: %s", service, name, err)
47 }
48 if ierr := call.Finish(&err); ierr != nil {
49 if !shouldSucceed {
50 return
51 }
52 boom(t, "Failed to Mount %s onto %s: %s", service, name, ierr)
53 }
54 if err != nil {
55 if !shouldSucceed {
56 return
57 }
58 boom(t, "Failed to Mount %s onto %s: %s", service, name, err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -070059 }
60}
61
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -070062func doUnmount(t *testing.T, ep, suffix, service string, shouldSucceed bool, as veyron2.Runtime) {
63 name := naming.JoinAddressName(ep, suffix)
64 ctx := as.NewContext()
65 client := as.Client()
66 call, err := client.StartCall(ctx, name, "Unmount", []interface{}{service}, options.NoResolve(true))
Jiri Simsa5293dcb2014-05-10 09:56:38 -070067 if err != nil {
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -070068 if !shouldSucceed {
69 return
Ryan Brownac972652014-05-19 10:57:32 -070070 }
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -070071 boom(t, "Failed to Mount %s onto %s: %s", service, name, err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -070072 }
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -070073 if ierr := call.Finish(&err); ierr != nil {
74 if !shouldSucceed {
75 return
76 }
77 boom(t, "Failed to Mount %s onto %s: %s", service, name, ierr)
78 }
79 if err != nil {
80 if !shouldSucceed {
81 return
82 }
83 boom(t, "Failed to Mount %s onto %s: %s", service, name, err)
84 }
85}
86
87// resolve assumes that the mount contains 0 or 1 servers.
88func resolve(name string, as veyron2.Runtime) (string, error) {
89 // Resolve the name one level.
90 ctx := as.NewContext()
91 client := as.Client()
92 call, err := client.StartCall(ctx, name, "ResolveStepX", nil, options.NoResolve(true))
93 if err != nil {
94 return "", err
95 }
96 var entry types.MountEntry
97 if ierr := call.Finish(&entry, &err); ierr != nil {
98 return "", ierr
99 }
100 if len(entry.Servers) < 1 {
101 return "", errors.New("resolve returned no servers")
102 }
103 return naming.JoinAddressName(entry.Servers[0].Server, entry.Name), nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700104}
105
Asim Shankar88292912014-10-09 19:41:07 -0700106func export(t *testing.T, name, contents string, as veyron2.Runtime) {
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700107 // Resolve the name.
108 resolved, err := resolve(name, as)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700109 if err != nil {
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700110 boom(t, "Failed to Export.Resolve %s: %s", name, err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700111 }
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700112 // Export the value.
113 ctx := as.NewContext()
114 client := as.Client()
115 call, err := client.StartCall(ctx, resolved, "Export", []interface{}{contents, true}, options.NoResolve(true))
116 if err != nil {
117 boom(t, "Failed to Export.StartCall %s to %s: %s", name, contents, err)
118 }
119 if ierr := call.Finish(&err); ierr != nil {
120 err = ierr
121 }
122 if err != nil {
123 boom(t, "Failed to Export.StartCall %s to %s: %s", name, contents, err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700124 }
125}
126
Asim Shankar88292912014-10-09 19:41:07 -0700127func checkContents(t *testing.T, name, expected string, shouldSucceed bool, as veyron2.Runtime) {
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700128 // Resolve the name.
129 resolved, err := resolve(name, as)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700130 if err != nil {
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700131 if !shouldSucceed {
132 return
133 }
134 boom(t, "Failed to Resolve %s: %s", name, err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700135 }
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700136 // Look up the value.
137 ctx := as.NewContext()
138 client := as.Client()
139 call, err := client.StartCall(ctx, resolved, "Lookup", nil, options.NoResolve(true))
140 if err != nil {
141 if shouldSucceed {
142 boom(t, "Failed Lookup.StartCall %s: %s", name, err)
143 }
144 return
145 }
146 var contents []byte
147 if ierr := call.Finish(&contents, &err); ierr != nil {
148 err = ierr
149 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700150 if err != nil {
151 if shouldSucceed {
152 boom(t, "Failed to Lookup %s: %s", name, err)
153 }
154 return
155 }
156 if string(contents) != expected {
157 boom(t, "Lookup %s, expected %q, got %q", name, expected, contents)
158 }
159 if !shouldSucceed {
160 boom(t, "Lookup %s, expected failure, got %q", name, contents)
161 }
162}
163
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700164func newMT(t *testing.T, acl string) (ipc.Server, string) {
Asim Shankarcc044212014-10-15 23:25:26 -0700165 server, err := rootRT.NewServer(options.ServesMountTable(true))
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700166 if err != nil {
167 boom(t, "r.NewServer: %s", err)
168 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700169 // Add mount table service.
Ryan Brownac972652014-05-19 10:57:32 -0700170 mt, err := NewMountTable(acl)
171 if err != nil {
172 boom(t, "NewMountTable: %v", err)
173 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700174 // Start serving on a loopback address.
Cosmos Nicolaoud6c3c9c2014-09-30 15:42:53 -0700175 e, err := server.ListenX(profiles.LocalListenSpec)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700176 if err != nil {
177 boom(t, "Failed to Listen mount table: %s", err)
178 }
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700179 if err := server.Serve("", mt); err != nil {
180 boom(t, "Failed to register mock collection: %s", err)
181 }
182 estr := e.String()
183 t.Logf("endpoint %s", estr)
184 return server, estr
185}
186
187func newCollection(t *testing.T, acl string) (ipc.Server, string) {
Asim Shankar88292912014-10-09 19:41:07 -0700188 server, err := rootRT.NewServer()
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700189 if err != nil {
190 boom(t, "r.NewServer: %s", err)
191 }
192 // Start serving on a loopback address.
Cosmos Nicolaoud6c3c9c2014-09-30 15:42:53 -0700193 e, err := server.ListenX(profiles.LocalListenSpec)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700194 if err != nil {
195 boom(t, "Failed to Listen mount table: %s", err)
196 }
197 // Add a collection service. This is just a service we can mount
198 // and test against.
199 cPrefix := "collection"
200 if err := server.Serve(cPrefix, newCollectionServer()); err != nil {
201 boom(t, "Failed to register mock collection: %s", err)
202 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700203 estr := e.String()
204 t.Logf("endpoint %s", estr)
205 return server, estr
206}
207
208func TestMountTable(t *testing.T) {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700209 mt, mtAddr := newMT(t, "testdata/test.acl")
210 defer mt.Stop()
211 collection, collectionAddr := newCollection(t, "testdata/test.acl")
212 defer collection.Stop()
213
214 collectionName := naming.JoinAddressName(collectionAddr, "collection")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700215
216 // Mount the collection server into the mount table.
David Why Use Two When One Will Do Presotto5add67e2014-07-31 11:14:30 -0700217 vlog.Infof("Mount the collection server into the mount table.")
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700218 doMount(t, mtAddr, "mounttable/stuff", collectionName, true, rootRT)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700219
220 // Create a few objects and make sure we can read them.
David Why Use Two When One Will Do Presotto5add67e2014-07-31 11:14:30 -0700221 vlog.Infof("Create a few objects.")
Asim Shankar88292912014-10-09 19:41:07 -0700222 export(t, naming.JoinAddressName(mtAddr, "mounttable/stuff/the/rain"), "the rain", rootRT)
223 export(t, naming.JoinAddressName(mtAddr, "mounttable/stuff/in/spain"), "in spain", rootRT)
224 export(t, naming.JoinAddressName(mtAddr, "mounttable/stuff/falls"), "falls mainly on the plain", rootRT)
David Why Use Two When One Will Do Presotto5add67e2014-07-31 11:14:30 -0700225 vlog.Infof("Make sure we can read them.")
Asim Shankar88292912014-10-09 19:41:07 -0700226 checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/stuff/the/rain"), "the rain", true, rootRT)
227 checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/stuff/in/spain"), "in spain", true, rootRT)
228 checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/stuff/falls"), "falls mainly on the plain", true, rootRT)
229 checkContents(t, naming.JoinAddressName(mtAddr, "mounttable//stuff/falls"), "falls mainly on the plain", false, rootRT)
230 checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/stuff/nonexistant"), "falls mainly on the plain", false, rootRT)
231 checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/stuff/the/rain"), "the rain", true, bobRT)
232 checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/stuff/the/rain"), "the rain", false, aliceRT)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700233
234 // Test multiple mounts.
David Why Use Two When One Will Do Presotto5add67e2014-07-31 11:14:30 -0700235 vlog.Infof("Multiple mounts.")
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700236 doMount(t, mtAddr, "mounttable/a/b", collectionName, true, rootRT)
237 doMount(t, mtAddr, "mounttable/x/y", collectionName, true, rootRT)
238 doMount(t, mtAddr, "mounttable/alpha//beta", collectionName, true, rootRT)
David Why Use Two When One Will Do Presotto5add67e2014-07-31 11:14:30 -0700239 vlog.Infof("Make sure we can read them.")
Asim Shankar88292912014-10-09 19:41:07 -0700240 checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/stuff/falls"), "falls mainly on the plain", true, rootRT)
241 checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/a/b/falls"), "falls mainly on the plain", true, rootRT)
242 checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/x/y/falls"), "falls mainly on the plain", true, rootRT)
243 checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/alpha/beta/falls"), "falls mainly on the plain", true, rootRT)
244 checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/a/b/falls"), "falls mainly on the plain", true, aliceRT)
245 checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/a/b/falls"), "falls mainly on the plain", false, bobRT)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700246
247 // Test generic unmount.
David Why Use Two When One Will Do Presotto5add67e2014-07-31 11:14:30 -0700248 vlog.Info("Test generic unmount.")
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700249 doUnmount(t, mtAddr, "mounttable/a/b", "", true, rootRT)
Asim Shankar88292912014-10-09 19:41:07 -0700250 checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/a/b/falls"), "falls mainly on the plain", false, rootRT)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700251
252 // Test specific unmount.
David Why Use Two When One Will Do Presotto5add67e2014-07-31 11:14:30 -0700253 vlog.Info("Test specific unmount.")
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700254 doMount(t, mtAddr, "mounttable/a/b", collectionName, true, rootRT)
255 doUnmount(t, mtAddr, "mounttable/a/b", collectionName, true, rootRT)
Asim Shankar88292912014-10-09 19:41:07 -0700256 checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/a/b/falls"), "falls mainly on the plain", false, rootRT)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700257
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700258 // Try timing out a mount.
David Why Use Two When One Will Do Presotto5add67e2014-07-31 11:14:30 -0700259 vlog.Info("Try timing out a mount.")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700260 ft := NewFakeTimeClock()
261 setServerListClock(ft)
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700262 doMount(t, mtAddr, "mounttable/stuffWithTTL", collectionName, true, rootRT)
Asim Shankar88292912014-10-09 19:41:07 -0700263 checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/stuffWithTTL/the/rain"), "the rain", true, rootRT)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700264 ft.advance(time.Duration(ttlSecs+4) * time.Second)
Asim Shankar88292912014-10-09 19:41:07 -0700265 checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/stuffWithTTL/the/rain"), "the rain", false, rootRT)
Ryan Brownac972652014-05-19 10:57:32 -0700266
David Why Use Two When One Will Do Presotto5add67e2014-07-31 11:14:30 -0700267 // Test unauthorized mount.
268 vlog.Info("Test unauthorized mount.")
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700269 doMount(t, mtAddr, "mounttable//a/b", collectionName, false, bobRT)
270 doMount(t, mtAddr, "mounttable//a/b", collectionName, false, aliceRT)
Ryan Brownac972652014-05-19 10:57:32 -0700271
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700272 doUnmount(t, mtAddr, "mounttable/x/y", collectionName, false, bobRT)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700273}
274
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700275func doGlobX(t *testing.T, ep, suffix, pattern string, as veyron2.Runtime, joinServer bool) []string {
276 name := naming.JoinAddressName(ep, suffix)
277 ctx := as.NewContext()
278 client := as.Client()
279 call, err := client.StartCall(ctx, name, "Glob", []interface{}{pattern}, options.NoResolve(true))
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700280 if err != nil {
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700281 boom(t, "Glob.StartCall %s %s: %s", name, pattern, err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700282 }
283 var reply []string
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700284 for {
285 var e types.MountEntry
286 err := call.Recv(&e)
287 if err == io.EOF {
288 break
289 }
290 if err != nil {
291 boom(t, "Glob.StartCall %s: %s", name, pattern, err)
292 }
293 if joinServer && len(e.Servers) > 0 {
294 reply = append(reply, naming.JoinAddressName(e.Servers[0].Server, e.Name))
295 } else {
296 reply = append(reply, e.Name)
297 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700298 }
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700299 if ierr := call.Finish(&err); ierr != nil {
300 err = ierr
301 }
302 if err != nil {
303 boom(t, "Glob.Finish %s: %s", name, pattern, err)
Shyam Jayaramanc4aed6e2014-07-22 14:25:06 -0700304 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700305 return reply
306}
307
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700308func doGlob(t *testing.T, ep, suffix, pattern string, as veyron2.Runtime) []string {
309 return doGlobX(t, ep, suffix, pattern, as, false)
310}
311
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700312// checkMatch verified that the two slices contain the same string items, albeit
313// not necessarily in the same order. Item repetitions are allowed, but their
314// numbers need to match as well.
315func checkMatch(t *testing.T, want []string, got []string) {
316 w := sort.StringSlice(want)
317 w.Sort()
318 g := sort.StringSlice(got)
319 g.Sort()
320 if !reflect.DeepEqual(w, g) {
321 boom(t, "Glob expected %v got %v", want, got)
322 }
323}
324
325func TestGlob(t *testing.T) {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700326 server, estr := newMT(t, "")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700327 defer server.Stop()
328
329 // set up a mount space
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700330 fakeServer := naming.JoinAddressName(estr, "quux")
331 doMount(t, estr, "one/bright/day", fakeServer, true, rootRT)
332 doMount(t, estr, "in/the/middle", fakeServer, true, rootRT)
333 doMount(t, estr, "of/the/night", fakeServer, true, rootRT)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700334
335 // Try various globs.
336 tests := []struct {
337 in string
338 expected []string
339 }{
340 {"*", []string{"one", "in", "of"}},
Bogdan Capritab6b195a2014-06-11 17:55:03 -0700341 {"...", []string{"", "one", "in", "of", "one/bright", "in/the", "of/the", "one/bright/day", "in/the/middle", "of/the/night"}},
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700342 {"*/...", []string{"one", "in", "of", "one/bright", "in/the", "of/the", "one/bright/day", "in/the/middle", "of/the/night"}},
Bogdan Capritab6b195a2014-06-11 17:55:03 -0700343 {"one/...", []string{"one", "one/bright", "one/bright/day"}},
Robin Thellend434e39f2014-08-27 14:46:27 -0700344 {"of/the/night/two/dead/boys", []string{"of/the/night"}},
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700345 {"*/the", []string{"in/the", "of/the"}},
346 {"*/the/...", []string{"in/the", "of/the", "in/the/middle", "of/the/night"}},
347 {"o*", []string{"one", "of"}},
348 {"", []string{""}},
349 }
350 for _, test := range tests {
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700351 out := doGlob(t, estr, "", test.in, rootRT)
Ryan Brownac972652014-05-19 10:57:32 -0700352 checkMatch(t, test.expected, out)
353 }
Robin Thellend434e39f2014-08-27 14:46:27 -0700354
355 // Test Glob on a name that is under a mounted server. The result should the
356 // the address the mounted server with the extra suffix.
357 {
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700358 results := doGlobX(t, estr, "of/the/night/two/dead/boys/got/up/to/fight", "*", rootRT, true)
Robin Thellend434e39f2014-08-27 14:46:27 -0700359 if len(results) != 1 {
360 boom(t, "Unexpected number of results. Got %v, want 1", len(results))
361 }
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700362 _, suffix := naming.SplitAddressName(results[0])
363 if expected := "quux/two/dead/boys/got/up/to/fight"; suffix != expected {
Robin Thellend434e39f2014-08-27 14:46:27 -0700364 boom(t, "Unexpected suffix. Got %v, want %v", suffix, expected)
365 }
366 }
Ryan Brownac972652014-05-19 10:57:32 -0700367}
368
369func TestGlobACLs(t *testing.T) {
Tilak Sharmada5165e2014-10-07 16:39:51 -0700370 t.Skip("Skipped until ACLs are correctly implemented for mounttable.Glob.")
371
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700372 server, estr := newMT(t, "testdata/test.acl")
Ryan Brownac972652014-05-19 10:57:32 -0700373 defer server.Stop()
374
375 // set up a mount space
376 fakeServer := naming.JoinAddressName(estr, "quux")
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700377 doMount(t, estr, "one/bright/day", fakeServer, true, rootRT)
378 doMount(t, estr, "a/b/c", fakeServer, true, rootRT)
Ryan Brownac972652014-05-19 10:57:32 -0700379
380 // Try various globs.
381 tests := []struct {
Asim Shankar88292912014-10-09 19:41:07 -0700382 as veyron2.Runtime
Ryan Brownac972652014-05-19 10:57:32 -0700383 in string
384 expected []string
385 }{
Asim Shankar88292912014-10-09 19:41:07 -0700386 {rootRT, "*", []string{"one", "a"}},
387 {aliceRT, "*", []string{"one", "a"}},
388 {bobRT, "*", []string{"one"}},
389 {rootRT, "*/...", []string{"one", "a", "one/bright", "a/b", "one/bright/day", "a/b/c"}},
390 {aliceRT, "*/...", []string{"one", "a", "one/bright", "a/b", "one/bright/day", "a/b/c"}},
391 {bobRT, "*/...", []string{"one", "one/bright", "one/bright/day"}},
Ryan Brownac972652014-05-19 10:57:32 -0700392 }
393 for _, test := range tests {
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700394 out := doGlob(t, estr, "", test.in, test.as)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700395 checkMatch(t, test.expected, out)
396 }
397}
398
399func TestServerFormat(t *testing.T) {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700400 server, estr := newMT(t, "")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700401 defer server.Stop()
402
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700403 doMount(t, estr, "mounttable/endpoint", naming.JoinAddressName(estr, "life/on/the/mississippi"), true, rootRT)
404 doMount(t, estr, "mounttable/hostport", "/atrampabroad:8000", true, rootRT)
405 doMount(t, estr, "mounttable/hostport-endpoint-platypus", "/@atrampabroad:8000@@", true, rootRT)
406 doMount(t, estr, "mounttable/invalid/not/rooted", "atrampabroad:8000", false, rootRT)
407 doMount(t, estr, "mounttable/invalid/no/port", "/atrampabroad", false, rootRT)
408 doMount(t, estr, "mounttable/invalid/endpoint", "/@following the equator:8000@@@", false, rootRT)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700409}
410
411func TestExpiry(t *testing.T) {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700412 server, estr := newMT(t, "")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700413 defer server.Stop()
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700414 collection, collectionAddr := newCollection(t, "testdata/test.acl")
415 defer collection.Stop()
416
417 collectionName := naming.JoinAddressName(collectionAddr, "collection")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700418
419 ft := NewFakeTimeClock()
420 setServerListClock(ft)
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700421 doMount(t, estr, "mounttable/a1/b1", collectionName, true, rootRT)
422 doMount(t, estr, "mounttable/a1/b2", collectionName, true, rootRT)
423 doMount(t, estr, "mounttable/a2/b1", collectionName, true, rootRT)
424 doMount(t, estr, "mounttable/a2/b2/c", collectionName, true, rootRT)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700425
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700426 checkMatch(t, []string{"a1/b1", "a2/b1"}, doGlob(t, estr, "mounttable", "*/b1/...", rootRT))
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700427 ft.advance(time.Duration(ttlSecs/2) * time.Second)
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700428 checkMatch(t, []string{"a1/b1", "a2/b1"}, doGlob(t, estr, "mounttable", "*/b1/...", rootRT))
429 checkMatch(t, []string{"c"}, doGlob(t, estr, "mounttable/a2/b2", "*", rootRT))
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700430 // Refresh only a1/b1. All the other mounts will expire upon the next
431 // ft advance.
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700432 doMount(t, estr, "mounttable/a1/b1", collectionName, true, rootRT)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700433 ft.advance(time.Duration(ttlSecs/2+4) * time.Second)
David Why Use Two When One Will Do Presotto9c374c22014-10-21 16:16:30 -0700434 checkMatch(t, []string{"a1"}, doGlob(t, estr, "mounttable", "*", rootRT))
435 checkMatch(t, []string{"a1/b1"}, doGlob(t, estr, "mounttable", "*/b1/...", rootRT))
Ryan Brownac972652014-05-19 10:57:32 -0700436}
437
438func TestBadACLs(t *testing.T) {
439 _, err := NewMountTable("testdata/invalid.acl")
440 if err == nil {
441 boom(t, "Expected json parse error in acl file")
442 }
443 _, err = NewMountTable("testdata/doesntexist.acl")
444 if err == nil {
445 boom(t, "Expected error from missing acl file")
446 }
447 _, err = NewMountTable("testdata/noroot.acl")
448 if err == nil {
449 boom(t, "Expected error for missing '/' acl")
450 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700451}
Asim Shankar88292912014-10-09 19:41:07 -0700452
453func init() {
Asim Shankarc920db32014-10-16 19:18:21 -0700454 testutil.Init()
Asim Shankar88292912014-10-09 19:41:07 -0700455 // Create the runtime for each of the three "processes"
Asim Shankarcc044212014-10-15 23:25:26 -0700456 rootRT = rt.Init(options.ForceNewSecurityModel{})
Asim Shankar88292912014-10-09 19:41:07 -0700457 var err error
Asim Shankarcc044212014-10-15 23:25:26 -0700458 if aliceRT, err = rt.New(options.ForceNewSecurityModel{}); err != nil {
Asim Shankar88292912014-10-09 19:41:07 -0700459 panic(err)
460 }
Asim Shankarcc044212014-10-15 23:25:26 -0700461 if bobRT, err = rt.New(options.ForceNewSecurityModel{}); err != nil {
Asim Shankar88292912014-10-09 19:41:07 -0700462 panic(err)
463 }
464
465 // And setup their blessings so that they present "root", "alice" and "bob"
466 // and these blessings are recognized by the others.
467 principals := map[string]security.Principal{
468 "root": rootRT.Principal(),
469 "alice": aliceRT.Principal(),
470 "bob": bobRT.Principal(),
471 }
472 for name, p := range principals {
473 blessing, err := p.BlessSelf(name)
474 if err != nil {
475 panic(fmt.Sprintf("BlessSelf(%q) failed: %v", name, err))
476 }
477 // Share this blessing with all servers and use it when serving clients.
478 if err = p.BlessingStore().SetDefault(blessing); err != nil {
479 panic(fmt.Sprintf("%v: %v", blessing, err))
480 }
481 if _, err = p.BlessingStore().Set(blessing, security.AllPrincipals); err != nil {
482 panic(fmt.Sprintf("%v: %v", blessing, err))
483 }
484 // Have all principals trust the root of this blessing.
485 for _, other := range principals {
486 if err := other.AddToRoots(blessing); err != nil {
487 panic(err)
488 }
489 }
490 }
491}