Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 1 | package mounttable |
| 2 | |
| 3 | import ( |
| 4 | "errors" |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 5 | "fmt" |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 6 | "io" |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 7 | "reflect" |
| 8 | "runtime/debug" |
| 9 | "sort" |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 10 | "testing" |
| 11 | "time" |
| 12 | |
Jiri Simsa | 519c507 | 2014-09-17 21:37:57 -0700 | [diff] [blame] | 13 | "veyron.io/veyron/veyron2" |
Jiri Simsa | 519c507 | 2014-09-17 21:37:57 -0700 | [diff] [blame] | 14 | "veyron.io/veyron/veyron2/ipc" |
| 15 | "veyron.io/veyron/veyron2/naming" |
Asim Shankar | cc04421 | 2014-10-15 23:25:26 -0700 | [diff] [blame] | 16 | "veyron.io/veyron/veyron2/options" |
Jiri Simsa | 519c507 | 2014-09-17 21:37:57 -0700 | [diff] [blame] | 17 | "veyron.io/veyron/veyron2/rt" |
| 18 | "veyron.io/veyron/veyron2/security" |
Jiri Simsa | 519c507 | 2014-09-17 21:37:57 -0700 | [diff] [blame] | 19 | "veyron.io/veyron/veyron2/services/mounttable/types" |
| 20 | "veyron.io/veyron/veyron2/vlog" |
Cosmos Nicolaou | d6c3c9c | 2014-09-30 15:42:53 -0700 | [diff] [blame] | 21 | |
Asim Shankar | c920db3 | 2014-10-16 19:18:21 -0700 | [diff] [blame] | 22 | "veyron.io/veyron/veyron/lib/testutil" |
Cosmos Nicolaou | d6c3c9c | 2014-09-30 15:42:53 -0700 | [diff] [blame] | 23 | "veyron.io/veyron/veyron/profiles" |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 24 | ) |
| 25 | |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 26 | // Simulate different processes with different runtimes. |
| 27 | // rootRT is the one running the mounttable service. |
| 28 | var rootRT, aliceRT, bobRT veyron2.Runtime |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 29 | |
| 30 | const ttlSecs = 60 * 60 |
| 31 | |
| 32 | func 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 Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 37 | func 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 42 | if err != nil { |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 43 | if !shouldSucceed { |
| 44 | return |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 45 | } |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 46 | 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 59 | } |
| 60 | } |
| 61 | |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 62 | func 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 67 | if err != nil { |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 68 | if !shouldSucceed { |
| 69 | return |
Ryan Brown | ac97265 | 2014-05-19 10:57:32 -0700 | [diff] [blame] | 70 | } |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 71 | boom(t, "Failed to Mount %s onto %s: %s", service, name, err) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 72 | } |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 73 | 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. |
| 88 | func 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 104 | } |
| 105 | |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 106 | func export(t *testing.T, name, contents string, as veyron2.Runtime) { |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 107 | // Resolve the name. |
| 108 | resolved, err := resolve(name, as) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 109 | if err != nil { |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 110 | boom(t, "Failed to Export.Resolve %s: %s", name, err) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 111 | } |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 112 | // 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 124 | } |
| 125 | } |
| 126 | |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 127 | func checkContents(t *testing.T, name, expected string, shouldSucceed bool, as veyron2.Runtime) { |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 128 | // Resolve the name. |
| 129 | resolved, err := resolve(name, as) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 130 | if err != nil { |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 131 | if !shouldSucceed { |
| 132 | return |
| 133 | } |
| 134 | boom(t, "Failed to Resolve %s: %s", name, err) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 135 | } |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 136 | // 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 150 | 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 Nicolaou | fdc838b | 2014-06-30 21:44:27 -0700 | [diff] [blame] | 164 | func newMT(t *testing.T, acl string) (ipc.Server, string) { |
Asim Shankar | cc04421 | 2014-10-15 23:25:26 -0700 | [diff] [blame] | 165 | server, err := rootRT.NewServer(options.ServesMountTable(true)) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 166 | if err != nil { |
| 167 | boom(t, "r.NewServer: %s", err) |
| 168 | } |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 169 | // Add mount table service. |
Ryan Brown | ac97265 | 2014-05-19 10:57:32 -0700 | [diff] [blame] | 170 | mt, err := NewMountTable(acl) |
| 171 | if err != nil { |
| 172 | boom(t, "NewMountTable: %v", err) |
| 173 | } |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 174 | // Start serving on a loopback address. |
Cosmos Nicolaou | f8d4c2b | 2014-10-23 22:36:38 -0700 | [diff] [blame] | 175 | e, err := server.Listen(profiles.LocalListenSpec) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 176 | if err != nil { |
| 177 | boom(t, "Failed to Listen mount table: %s", err) |
| 178 | } |
Cosmos Nicolaou | fdc838b | 2014-06-30 21:44:27 -0700 | [diff] [blame] | 179 | 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 | |
| 187 | func newCollection(t *testing.T, acl string) (ipc.Server, string) { |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 188 | server, err := rootRT.NewServer() |
Cosmos Nicolaou | fdc838b | 2014-06-30 21:44:27 -0700 | [diff] [blame] | 189 | if err != nil { |
| 190 | boom(t, "r.NewServer: %s", err) |
| 191 | } |
| 192 | // Start serving on a loopback address. |
Cosmos Nicolaou | f8d4c2b | 2014-10-23 22:36:38 -0700 | [diff] [blame] | 193 | e, err := server.Listen(profiles.LocalListenSpec) |
Cosmos Nicolaou | fdc838b | 2014-06-30 21:44:27 -0700 | [diff] [blame] | 194 | 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 203 | estr := e.String() |
| 204 | t.Logf("endpoint %s", estr) |
| 205 | return server, estr |
| 206 | } |
| 207 | |
| 208 | func TestMountTable(t *testing.T) { |
Cosmos Nicolaou | fdc838b | 2014-06-30 21:44:27 -0700 | [diff] [blame] | 209 | 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 215 | |
| 216 | // Mount the collection server into the mount table. |
David Why Use Two When One Will Do Presotto | 5add67e | 2014-07-31 11:14:30 -0700 | [diff] [blame] | 217 | vlog.Infof("Mount the collection server into the mount table.") |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 218 | doMount(t, mtAddr, "mounttable/stuff", collectionName, true, rootRT) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 219 | |
| 220 | // Create a few objects and make sure we can read them. |
David Why Use Two When One Will Do Presotto | 5add67e | 2014-07-31 11:14:30 -0700 | [diff] [blame] | 221 | vlog.Infof("Create a few objects.") |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 222 | 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 Presotto | 5add67e | 2014-07-31 11:14:30 -0700 | [diff] [blame] | 225 | vlog.Infof("Make sure we can read them.") |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 226 | 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 233 | |
| 234 | // Test multiple mounts. |
David Why Use Two When One Will Do Presotto | 5add67e | 2014-07-31 11:14:30 -0700 | [diff] [blame] | 235 | vlog.Infof("Multiple mounts.") |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 236 | 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 Presotto | 5add67e | 2014-07-31 11:14:30 -0700 | [diff] [blame] | 239 | vlog.Infof("Make sure we can read them.") |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 240 | 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 246 | |
| 247 | // Test generic unmount. |
David Why Use Two When One Will Do Presotto | 5add67e | 2014-07-31 11:14:30 -0700 | [diff] [blame] | 248 | vlog.Info("Test generic unmount.") |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 249 | doUnmount(t, mtAddr, "mounttable/a/b", "", true, rootRT) |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 250 | checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/a/b/falls"), "falls mainly on the plain", false, rootRT) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 251 | |
| 252 | // Test specific unmount. |
David Why Use Two When One Will Do Presotto | 5add67e | 2014-07-31 11:14:30 -0700 | [diff] [blame] | 253 | vlog.Info("Test specific unmount.") |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 254 | doMount(t, mtAddr, "mounttable/a/b", collectionName, true, rootRT) |
| 255 | doUnmount(t, mtAddr, "mounttable/a/b", collectionName, true, rootRT) |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 256 | checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/a/b/falls"), "falls mainly on the plain", false, rootRT) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 257 | |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 258 | // Try timing out a mount. |
David Why Use Two When One Will Do Presotto | 5add67e | 2014-07-31 11:14:30 -0700 | [diff] [blame] | 259 | vlog.Info("Try timing out a mount.") |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 260 | ft := NewFakeTimeClock() |
| 261 | setServerListClock(ft) |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 262 | doMount(t, mtAddr, "mounttable/stuffWithTTL", collectionName, true, rootRT) |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 263 | checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/stuffWithTTL/the/rain"), "the rain", true, rootRT) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 264 | ft.advance(time.Duration(ttlSecs+4) * time.Second) |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 265 | checkContents(t, naming.JoinAddressName(mtAddr, "mounttable/stuffWithTTL/the/rain"), "the rain", false, rootRT) |
Ryan Brown | ac97265 | 2014-05-19 10:57:32 -0700 | [diff] [blame] | 266 | |
David Why Use Two When One Will Do Presotto | 5add67e | 2014-07-31 11:14:30 -0700 | [diff] [blame] | 267 | // Test unauthorized mount. |
| 268 | vlog.Info("Test unauthorized mount.") |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 269 | doMount(t, mtAddr, "mounttable//a/b", collectionName, false, bobRT) |
| 270 | doMount(t, mtAddr, "mounttable//a/b", collectionName, false, aliceRT) |
Ryan Brown | ac97265 | 2014-05-19 10:57:32 -0700 | [diff] [blame] | 271 | |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 272 | doUnmount(t, mtAddr, "mounttable/x/y", collectionName, false, bobRT) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 273 | } |
| 274 | |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 275 | func 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 280 | if err != nil { |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 281 | boom(t, "Glob.StartCall %s %s: %s", name, pattern, err) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 282 | } |
| 283 | var reply []string |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 284 | 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 298 | } |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 299 | 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 Jayaraman | c4aed6e | 2014-07-22 14:25:06 -0700 | [diff] [blame] | 304 | } |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 305 | return reply |
| 306 | } |
| 307 | |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 308 | func doGlob(t *testing.T, ep, suffix, pattern string, as veyron2.Runtime) []string { |
| 309 | return doGlobX(t, ep, suffix, pattern, as, false) |
| 310 | } |
| 311 | |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 312 | // 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. |
| 315 | func 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 | |
| 325 | func TestGlob(t *testing.T) { |
Cosmos Nicolaou | fdc838b | 2014-06-30 21:44:27 -0700 | [diff] [blame] | 326 | server, estr := newMT(t, "") |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 327 | defer server.Stop() |
| 328 | |
| 329 | // set up a mount space |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 330 | 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 334 | |
| 335 | // Try various globs. |
| 336 | tests := []struct { |
| 337 | in string |
| 338 | expected []string |
| 339 | }{ |
| 340 | {"*", []string{"one", "in", "of"}}, |
Bogdan Caprita | b6b195a | 2014-06-11 17:55:03 -0700 | [diff] [blame] | 341 | {"...", []string{"", "one", "in", "of", "one/bright", "in/the", "of/the", "one/bright/day", "in/the/middle", "of/the/night"}}, |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 342 | {"*/...", []string{"one", "in", "of", "one/bright", "in/the", "of/the", "one/bright/day", "in/the/middle", "of/the/night"}}, |
Bogdan Caprita | b6b195a | 2014-06-11 17:55:03 -0700 | [diff] [blame] | 343 | {"one/...", []string{"one", "one/bright", "one/bright/day"}}, |
Robin Thellend | 434e39f | 2014-08-27 14:46:27 -0700 | [diff] [blame] | 344 | {"of/the/night/two/dead/boys", []string{"of/the/night"}}, |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 345 | {"*/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 Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 351 | out := doGlob(t, estr, "", test.in, rootRT) |
Ryan Brown | ac97265 | 2014-05-19 10:57:32 -0700 | [diff] [blame] | 352 | checkMatch(t, test.expected, out) |
| 353 | } |
Robin Thellend | 434e39f | 2014-08-27 14:46:27 -0700 | [diff] [blame] | 354 | |
| 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 Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 358 | results := doGlobX(t, estr, "of/the/night/two/dead/boys/got/up/to/fight", "*", rootRT, true) |
Robin Thellend | 434e39f | 2014-08-27 14:46:27 -0700 | [diff] [blame] | 359 | 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 Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 362 | _, suffix := naming.SplitAddressName(results[0]) |
| 363 | if expected := "quux/two/dead/boys/got/up/to/fight"; suffix != expected { |
Robin Thellend | 434e39f | 2014-08-27 14:46:27 -0700 | [diff] [blame] | 364 | boom(t, "Unexpected suffix. Got %v, want %v", suffix, expected) |
| 365 | } |
| 366 | } |
Ryan Brown | ac97265 | 2014-05-19 10:57:32 -0700 | [diff] [blame] | 367 | } |
| 368 | |
| 369 | func TestGlobACLs(t *testing.T) { |
Tilak Sharma | da5165e | 2014-10-07 16:39:51 -0700 | [diff] [blame] | 370 | t.Skip("Skipped until ACLs are correctly implemented for mounttable.Glob.") |
| 371 | |
Cosmos Nicolaou | fdc838b | 2014-06-30 21:44:27 -0700 | [diff] [blame] | 372 | server, estr := newMT(t, "testdata/test.acl") |
Ryan Brown | ac97265 | 2014-05-19 10:57:32 -0700 | [diff] [blame] | 373 | defer server.Stop() |
| 374 | |
| 375 | // set up a mount space |
| 376 | fakeServer := naming.JoinAddressName(estr, "quux") |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 377 | doMount(t, estr, "one/bright/day", fakeServer, true, rootRT) |
| 378 | doMount(t, estr, "a/b/c", fakeServer, true, rootRT) |
Ryan Brown | ac97265 | 2014-05-19 10:57:32 -0700 | [diff] [blame] | 379 | |
| 380 | // Try various globs. |
| 381 | tests := []struct { |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 382 | as veyron2.Runtime |
Ryan Brown | ac97265 | 2014-05-19 10:57:32 -0700 | [diff] [blame] | 383 | in string |
| 384 | expected []string |
| 385 | }{ |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 386 | {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 Brown | ac97265 | 2014-05-19 10:57:32 -0700 | [diff] [blame] | 392 | } |
| 393 | for _, test := range tests { |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 394 | out := doGlob(t, estr, "", test.in, test.as) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 395 | checkMatch(t, test.expected, out) |
| 396 | } |
| 397 | } |
| 398 | |
| 399 | func TestServerFormat(t *testing.T) { |
Cosmos Nicolaou | fdc838b | 2014-06-30 21:44:27 -0700 | [diff] [blame] | 400 | server, estr := newMT(t, "") |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 401 | defer server.Stop() |
| 402 | |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 403 | 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 409 | } |
| 410 | |
| 411 | func TestExpiry(t *testing.T) { |
Cosmos Nicolaou | fdc838b | 2014-06-30 21:44:27 -0700 | [diff] [blame] | 412 | server, estr := newMT(t, "") |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 413 | defer server.Stop() |
Cosmos Nicolaou | fdc838b | 2014-06-30 21:44:27 -0700 | [diff] [blame] | 414 | collection, collectionAddr := newCollection(t, "testdata/test.acl") |
| 415 | defer collection.Stop() |
| 416 | |
| 417 | collectionName := naming.JoinAddressName(collectionAddr, "collection") |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 418 | |
| 419 | ft := NewFakeTimeClock() |
| 420 | setServerListClock(ft) |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 421 | 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 425 | |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 426 | checkMatch(t, []string{"a1/b1", "a2/b1"}, doGlob(t, estr, "mounttable", "*/b1/...", rootRT)) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 427 | ft.advance(time.Duration(ttlSecs/2) * time.Second) |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 428 | 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 430 | // Refresh only a1/b1. All the other mounts will expire upon the next |
| 431 | // ft advance. |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 432 | doMount(t, estr, "mounttable/a1/b1", collectionName, true, rootRT) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 433 | ft.advance(time.Duration(ttlSecs/2+4) * time.Second) |
David Why Use Two When One Will Do Presotto | 9c374c2 | 2014-10-21 16:16:30 -0700 | [diff] [blame] | 434 | checkMatch(t, []string{"a1"}, doGlob(t, estr, "mounttable", "*", rootRT)) |
| 435 | checkMatch(t, []string{"a1/b1"}, doGlob(t, estr, "mounttable", "*/b1/...", rootRT)) |
Ryan Brown | ac97265 | 2014-05-19 10:57:32 -0700 | [diff] [blame] | 436 | } |
| 437 | |
| 438 | func 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 451 | } |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 452 | |
| 453 | func init() { |
Asim Shankar | c920db3 | 2014-10-16 19:18:21 -0700 | [diff] [blame] | 454 | testutil.Init() |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 455 | // Create the runtime for each of the three "processes" |
Asim Shankar | 7b5c94a | 2014-10-28 21:42:56 -0700 | [diff] [blame^] | 456 | rootRT = rt.Init() |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 457 | var err error |
Asim Shankar | 7b5c94a | 2014-10-28 21:42:56 -0700 | [diff] [blame^] | 458 | if aliceRT, err = rt.New(); err != nil { |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 459 | panic(err) |
| 460 | } |
Asim Shankar | 7b5c94a | 2014-10-28 21:42:56 -0700 | [diff] [blame^] | 461 | if bobRT, err = rt.New(); err != nil { |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 462 | 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 | } |