Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 1 | package impl_test |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
Bogdan Caprita | d2b9f03 | 2014-10-10 17:43:29 -0700 | [diff] [blame] | 5 | "io/ioutil" |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 6 | "os" |
Bogdan Caprita | d2b9f03 | 2014-10-10 17:43:29 -0700 | [diff] [blame] | 7 | "path/filepath" |
Robert Kroeger | 1cb4a0d | 2014-10-20 11:55:38 -0700 | [diff] [blame] | 8 | "reflect" |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 9 | "runtime" |
Robert Kroeger | 1cb4a0d | 2014-10-20 11:55:38 -0700 | [diff] [blame] | 10 | "sort" |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame^] | 11 | "strings" |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 12 | "testing" |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 13 | "time" |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 14 | |
Jiri Simsa | 519c507 | 2014-09-17 21:37:57 -0700 | [diff] [blame] | 15 | "veyron.io/veyron/veyron2" |
| 16 | "veyron.io/veyron/veyron2/ipc" |
| 17 | "veyron.io/veyron/veyron2/naming" |
| 18 | "veyron.io/veyron/veyron2/rt" |
Bogdan Caprita | 2692910 | 2014-11-07 11:56:56 -0800 | [diff] [blame] | 19 | "veyron.io/veyron/veyron2/security" |
Jiri Simsa | 519c507 | 2014-09-17 21:37:57 -0700 | [diff] [blame] | 20 | "veyron.io/veyron/veyron2/services/mgmt/node" |
| 21 | "veyron.io/veyron/veyron2/verror" |
| 22 | "veyron.io/veyron/veyron2/vlog" |
Cosmos Nicolaou | d6c3c9c | 2014-09-30 15:42:53 -0700 | [diff] [blame] | 23 | |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 24 | "veyron.io/veyron/veyron/lib/expect" |
Asim Shankar | 95910b6 | 2014-10-31 22:02:29 -0700 | [diff] [blame] | 25 | "veyron.io/veyron/veyron/lib/flags/consts" |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 26 | "veyron.io/veyron/veyron/lib/modules" |
| 27 | "veyron.io/veyron/veyron/lib/modules/core" |
Bogdan Caprita | 2692910 | 2014-11-07 11:56:56 -0800 | [diff] [blame] | 28 | tsecurity "veyron.io/veyron/veyron/lib/testutil/security" |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 29 | "veyron.io/veyron/veyron/profiles/static" |
| 30 | "veyron.io/veyron/veyron/services/mgmt/node/impl" |
| 31 | "veyron.io/veyron/veyron2/services/mgmt/application" |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 32 | ) |
| 33 | |
Bogdan Caprita | d2b9f03 | 2014-10-10 17:43:29 -0700 | [diff] [blame] | 34 | // Setting this environment variable to any non-empty value avoids removing the |
| 35 | // node manager's workspace for successful test runs (for failed test runs, this |
| 36 | // is already the case). This is useful when developing test cases. |
| 37 | const preserveNMWorkspaceEnv = "VEYRON_TEST_PRESERVE_NM_WORKSPACE" |
| 38 | |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 39 | func loc(d int) string { |
| 40 | _, file, line, _ := runtime.Caller(d + 1) |
| 41 | return fmt.Sprintf("%s:%d", filepath.Base(file), line) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 42 | } |
| 43 | |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 44 | func startRootMT(t *testing.T, sh *modules.Shell) (string, modules.Handle, *expect.Session) { |
Cosmos Nicolaou | 612ad38 | 2014-10-29 19:41:35 -0700 | [diff] [blame] | 45 | h, err := sh.Start(core.RootMTCommand, nil, "--", "--veyron.tcp.address=127.0.0.1:0") |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 46 | if err != nil { |
| 47 | t.Fatalf("failed to start root mount table: %s", err) |
| 48 | } |
| 49 | s := expect.NewSession(t, h.Stdout(), time.Minute) |
| 50 | rootName := s.ExpectVar("MT_NAME") |
| 51 | if t.Failed() { |
| 52 | t.Fatalf("failed to read mt name: %s", s.Error()) |
| 53 | } |
| 54 | return rootName, h, s |
Bogdan Caprita | b9501d1 | 2014-10-10 15:02:03 -0700 | [diff] [blame] | 55 | } |
| 56 | |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 57 | func credentialsForChild(blessing string) (string, []string) { |
Bogdan Caprita | 2692910 | 2014-11-07 11:56:56 -0800 | [diff] [blame] | 58 | creds := tsecurity.NewVeyronCredentials(rt.R().Principal(), blessing) |
Asim Shankar | 95910b6 | 2014-10-31 22:02:29 -0700 | [diff] [blame] | 59 | return creds, []string{consts.VeyronCredentials + "=" + creds} |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 60 | } |
| 61 | |
| 62 | func createShellAndMountTable(t *testing.T) (*modules.Shell, func()) { |
| 63 | sh := core.NewShell() |
| 64 | // The shell, will, by default share credentials with its children. |
Asim Shankar | 95910b6 | 2014-10-31 22:02:29 -0700 | [diff] [blame] | 65 | sh.ClearVar(consts.VeyronCredentials) |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 66 | |
| 67 | mtName, mtHandle, _ := startRootMT(t, sh) |
| 68 | // Make sure the root mount table is the last process to be shutdown |
| 69 | // since the others will likely want to communicate with it during |
| 70 | // their shutdown process |
| 71 | sh.Forget(mtHandle) |
| 72 | |
| 73 | fn := func() { |
| 74 | vlog.VI(1).Info("------------ CLEANUP ------------") |
| 75 | vlog.VI(1).Info("---------------------------------") |
| 76 | sh.Cleanup(nil, os.Stderr) |
| 77 | mtHandle.Shutdown(nil, os.Stderr) |
Cosmos Nicolaou | 612ad38 | 2014-10-29 19:41:35 -0700 | [diff] [blame] | 78 | sh.Start(core.SetNamespaceRootsCommand, nil, "") |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 79 | } |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 80 | |
Cosmos Nicolaou | 612ad38 | 2014-10-29 19:41:35 -0700 | [diff] [blame] | 81 | if _, err := sh.Start(core.SetNamespaceRootsCommand, nil, mtName); err != nil { |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 82 | t.Fatalf("%s: unexpected error: %s", loc(1), err) |
| 83 | } |
Asim Shankar | 95910b6 | 2014-10-31 22:02:29 -0700 | [diff] [blame] | 84 | sh.SetVar(consts.NamespaceRootPrefix, mtName) |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 85 | return sh, fn |
| 86 | } |
| 87 | |
| 88 | func runShellCommand(t *testing.T, sh *modules.Shell, env []string, cmd string, args ...string) (modules.Handle, *expect.Session) { |
Cosmos Nicolaou | 612ad38 | 2014-10-29 19:41:35 -0700 | [diff] [blame] | 89 | h, err := sh.Start(cmd, env, args...) |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 90 | if err != nil { |
| 91 | t.Fatalf("%s: failed to start %q: %s", loc(1), cmd, err) |
| 92 | return nil, nil |
| 93 | } |
| 94 | s := expect.NewSession(t, h.Stdout(), 10*time.Second) |
| 95 | s.SetVerbosity(testing.Verbose()) |
| 96 | return h, s |
| 97 | } |
| 98 | |
| 99 | func envelopeFromShell(sh *modules.Shell, env []string, cmd, title string, args ...string) application.Envelope { |
| 100 | args, nenv := sh.CommandEnvelope(cmd, env, args...) |
| 101 | return application.Envelope{ |
| 102 | Title: title, |
| 103 | Args: args[1:], |
| 104 | // TODO(caprita): revisit how the environment is sanitized for arbirary |
| 105 | // apps. |
| 106 | Env: impl.VeyronEnvironment(nenv), |
| 107 | Binary: mockBinaryRepoName, |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 108 | } |
| 109 | } |
| 110 | |
Bogdan Caprita | d2b9f03 | 2014-10-10 17:43:29 -0700 | [diff] [blame] | 111 | // setupRootDir sets up and returns the local filesystem location that the node |
| 112 | // manager is told to use, as well as a cleanup function. |
| 113 | func setupRootDir(t *testing.T) (string, func()) { |
| 114 | rootDir, err := ioutil.TempDir("", "nodemanager") |
| 115 | if err != nil { |
| 116 | t.Fatalf("Failed to set up temporary dir for test: %v", err) |
| 117 | } |
| 118 | // On some operating systems (e.g. darwin) os.TempDir() can return a |
| 119 | // symlink. To avoid having to account for this eventuality later, |
| 120 | // evaluate the symlink. |
| 121 | rootDir, err = filepath.EvalSymlinks(rootDir) |
| 122 | if err != nil { |
| 123 | vlog.Fatalf("EvalSymlinks(%v) failed: %v", rootDir, err) |
| 124 | } |
| 125 | return rootDir, func() { |
| 126 | if t.Failed() || os.Getenv(preserveNMWorkspaceEnv) != "" { |
| 127 | t.Logf("You can examine the node manager workspace at %v", rootDir) |
| 128 | } else { |
| 129 | os.RemoveAll(rootDir) |
| 130 | } |
| 131 | } |
| 132 | } |
| 133 | |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 134 | func newServer() (ipc.Server, string) { |
| 135 | server, err := rt.R().NewServer() |
| 136 | if err != nil { |
| 137 | vlog.Fatalf("NewServer() failed: %v", err) |
| 138 | } |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 139 | spec := static.ListenSpec |
| 140 | spec.Address = "127.0.0.1:0" |
| 141 | endpoint, err := server.Listen(spec) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 142 | if err != nil { |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 143 | vlog.Fatalf("Listen(%s) failed: %v", static.ListenSpec, err) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 144 | } |
| 145 | return server, endpoint.String() |
| 146 | } |
| 147 | |
| 148 | // resolveExpectError verifies that the given name is not in the mounttable. |
Bogdan Caprita | bce0a63 | 2014-09-03 16:15:26 -0700 | [diff] [blame] | 149 | func resolveExpectNotFound(t *testing.T, name string) { |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 150 | if results, err := rt.R().Namespace().Resolve(rt.R().NewContext(), name); err == nil { |
Jiri Simsa | 6351ee7 | 2014-08-18 16:44:41 -0700 | [diff] [blame] | 151 | t.Fatalf("Resolve(%v) succeeded with results %v when it was expected to fail", name, results) |
Benjamin Prosnitz | b8178d3 | 2014-11-04 10:24:12 -0800 | [diff] [blame] | 152 | } else if expectErr := naming.ErrNoSuchName.ID; !verror.Is(err, expectErr) { |
Tilak Sharma | 492e8e9 | 2014-09-18 10:58:14 -0700 | [diff] [blame] | 153 | t.Fatalf("Resolve(%v) failed with error %v, expected error ID %v", name, err, expectErr) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 154 | } |
| 155 | } |
| 156 | |
| 157 | // resolve looks up the given name in the mounttable. |
Bogdan Caprita | bce0a63 | 2014-09-03 16:15:26 -0700 | [diff] [blame] | 158 | func resolve(t *testing.T, name string, replicas int) []string { |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 159 | results, err := rt.R().Namespace().Resolve(rt.R().NewContext(), name) |
| 160 | if err != nil { |
| 161 | t.Fatalf("Resolve(%v) failed: %v", name, err) |
| 162 | } |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame^] | 163 | |
| 164 | filteredResults := []string{} |
| 165 | for _, r := range results { |
| 166 | if strings.Index(r, "@tcp") != -1 { |
| 167 | filteredResults = append(filteredResults, r) |
| 168 | } |
| 169 | } |
| 170 | // We are going to get a websocket and a tcp endpoint for each replica. |
| 171 | if want, got := replicas, len(filteredResults); want != got { |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 172 | t.Fatalf("Resolve(%v) expected %d result(s), got %d instead", name, want, got) |
| 173 | } |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame^] | 174 | return filteredResults |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 175 | } |
| 176 | |
| 177 | // The following set of functions are convenience wrappers around Update and |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 178 | // Revert for node manager. |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 179 | |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 180 | func nodeStub(name string) node.NodeClientMethods { |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 181 | nodeName := naming.Join(name, "nm") |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 182 | return node.NodeClient(nodeName) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 183 | } |
| 184 | |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 185 | func updateNodeExpectError(t *testing.T, name string, errID verror.ID) { |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 186 | if err := nodeStub(name).Update(rt.R().NewContext()); !verror.Is(err, errID) { |
Benjamin Prosnitz | b8178d3 | 2014-11-04 10:24:12 -0800 | [diff] [blame] | 187 | if errID == naming.ErrNoSuchName.ID && err.Error() == "no different version available" { |
| 188 | // TODO(bprosnitz) Remove this check when errUpdateNoOp is updated to verror2 |
| 189 | return |
| 190 | } |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 191 | t.Fatalf("%s: Update(%v) expected to fail with %v, got %v instead", loc(1), name, errID, err) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 192 | } |
| 193 | } |
| 194 | |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 195 | func updateNode(t *testing.T, name string) { |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 196 | if err := nodeStub(name).Update(rt.R().NewContext()); err != nil { |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 197 | t.Fatalf("%s: Update(%v) failed: %v", loc(1), name, err) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 198 | } |
| 199 | } |
| 200 | |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 201 | func revertNodeExpectError(t *testing.T, name string, errID verror.ID) { |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 202 | if err := nodeStub(name).Revert(rt.R().NewContext()); !verror.Is(err, errID) { |
Benjamin Prosnitz | b8178d3 | 2014-11-04 10:24:12 -0800 | [diff] [blame] | 203 | if errID == naming.ErrNoSuchName.ID && err.Error() == "no different version available" { |
| 204 | // TODO(bprosnitz) Remove this check when errUpdateNoOp is updated to verror2 |
| 205 | return |
| 206 | } |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 207 | t.Fatalf("%s: Revert(%v) expected to fail with %v, got %v instead", loc(1), name, errID, err) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 208 | } |
| 209 | } |
| 210 | |
| 211 | func revertNode(t *testing.T, name string) { |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 212 | if err := nodeStub(name).Revert(rt.R().NewContext()); err != nil { |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 213 | t.Fatalf("%s: Revert(%v) failed: %v", loc(1), name, err) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 214 | } |
| 215 | } |
| 216 | |
| 217 | // The following set of functions are convenience wrappers around various app |
| 218 | // management methods. |
| 219 | |
Robert Kroeger | 362ff89 | 2014-09-29 14:23:47 -0700 | [diff] [blame] | 220 | func ort(opt []veyron2.Runtime) veyron2.Runtime { |
| 221 | if len(opt) > 0 { |
| 222 | return opt[0] |
| 223 | } else { |
| 224 | return rt.R() |
| 225 | } |
| 226 | } |
| 227 | |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 228 | func appStub(nameComponents ...string) node.ApplicationClientMethods { |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 229 | appsName := "nm//apps" |
| 230 | appName := naming.Join(append([]string{appsName}, nameComponents...)...) |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 231 | return node.ApplicationClient(appName) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 232 | } |
| 233 | |
Robert Kroeger | 362ff89 | 2014-09-29 14:23:47 -0700 | [diff] [blame] | 234 | func installApp(t *testing.T, opt ...veyron2.Runtime) string { |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 235 | appID, err := appStub().Install(ort(opt).NewContext(), mockApplicationRepoName) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 236 | if err != nil { |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 237 | t.Fatalf("%s: Install failed: %v", loc(1), err) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 238 | } |
| 239 | return appID |
| 240 | } |
| 241 | |
Bogdan Caprita | 2692910 | 2014-11-07 11:56:56 -0800 | [diff] [blame] | 242 | type granter struct { |
| 243 | ipc.CallOpt |
| 244 | p security.Principal |
| 245 | extension string |
| 246 | } |
| 247 | |
| 248 | func (g *granter) Grant(other security.Blessings) (security.Blessings, error) { |
| 249 | return g.p.Bless(other.PublicKey(), g.p.BlessingStore().Default(), g.extension, security.UnconstrainedUse()) |
| 250 | } |
| 251 | |
Bogdan Caprita | 730bde1 | 2014-11-08 15:35:43 -0800 | [diff] [blame] | 252 | func startAppImpl(t *testing.T, appID, grant string, opt ...veyron2.Runtime) (string, error) { |
| 253 | var opts []ipc.CallOpt |
| 254 | if grant != "" { |
| 255 | opts = append(opts, &granter{p: ort(opt).Principal(), extension: grant}) |
| 256 | } |
| 257 | if instanceIDs, err := appStub(appID).Start(ort(opt).NewContext(), opts...); err != nil { |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 258 | return "", err |
| 259 | } else { |
| 260 | if want, got := 1, len(instanceIDs); want != got { |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 261 | t.Fatalf("%s: Start(%v): expected %v instance ids, got %v instead", loc(1), appID, want, got) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 262 | } |
| 263 | return instanceIDs[0], nil |
| 264 | } |
| 265 | } |
| 266 | |
Robert Kroeger | 362ff89 | 2014-09-29 14:23:47 -0700 | [diff] [blame] | 267 | func startApp(t *testing.T, appID string, opt ...veyron2.Runtime) string { |
Bogdan Caprita | 730bde1 | 2014-11-08 15:35:43 -0800 | [diff] [blame] | 268 | instanceID, err := startAppImpl(t, appID, "forapp", opt...) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 269 | if err != nil { |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 270 | t.Fatalf("%s: Start(%v) failed: %v", loc(1), appID, err) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 271 | } |
| 272 | return instanceID |
| 273 | } |
| 274 | |
Robert Kroeger | 362ff89 | 2014-09-29 14:23:47 -0700 | [diff] [blame] | 275 | func startAppExpectError(t *testing.T, appID string, expectedError verror.ID, opt ...veyron2.Runtime) { |
Bogdan Caprita | 730bde1 | 2014-11-08 15:35:43 -0800 | [diff] [blame] | 276 | if _, err := startAppImpl(t, appID, "forapp", opt...); err == nil || !verror.Is(err, expectedError) { |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 277 | t.Fatalf("%s: Start(%v) expected to fail with %v, got %v instead", loc(1), appID, expectedError, err) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 278 | } |
| 279 | } |
| 280 | |
Robert Kroeger | 362ff89 | 2014-09-29 14:23:47 -0700 | [diff] [blame] | 281 | func stopApp(t *testing.T, appID, instanceID string, opt ...veyron2.Runtime) { |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 282 | if err := appStub(appID, instanceID).Stop(ort(opt).NewContext(), 5); err != nil { |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 283 | t.Fatalf("%s: Stop(%v/%v) failed: %v", loc(1), appID, instanceID, err) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 284 | } |
| 285 | } |
| 286 | |
Robert Kroeger | 362ff89 | 2014-09-29 14:23:47 -0700 | [diff] [blame] | 287 | func suspendApp(t *testing.T, appID, instanceID string, opt ...veyron2.Runtime) { |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 288 | if err := appStub(appID, instanceID).Suspend(ort(opt).NewContext()); err != nil { |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 289 | t.Fatalf("%s: Suspend(%v/%v) failed: %v", loc(1), appID, instanceID, err) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 290 | } |
| 291 | } |
| 292 | |
Robert Kroeger | 362ff89 | 2014-09-29 14:23:47 -0700 | [diff] [blame] | 293 | func resumeApp(t *testing.T, appID, instanceID string, opt ...veyron2.Runtime) { |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 294 | if err := appStub(appID, instanceID).Resume(ort(opt).NewContext()); err != nil { |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 295 | t.Fatalf("%s: Resume(%v/%v) failed: %v", loc(1), appID, instanceID, err) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 296 | } |
| 297 | } |
| 298 | |
Robert Kroeger | 1ce0bd7 | 2014-10-22 13:57:14 -0700 | [diff] [blame] | 299 | func resumeAppExpectError(t *testing.T, appID, instanceID string, expectedError verror.ID, opt ...veyron2.Runtime) { |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 300 | if err := appStub(appID, instanceID).Resume(ort(opt).NewContext()); err == nil || !verror.Is(err, expectedError) { |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 301 | t.Fatalf("%s: Resume(%v/%v) expected to fail with %v, got %v instead", loc(1), appID, instanceID, expectedError, err) |
Robert Kroeger | 1ce0bd7 | 2014-10-22 13:57:14 -0700 | [diff] [blame] | 302 | } |
| 303 | } |
| 304 | |
Robert Kroeger | 362ff89 | 2014-09-29 14:23:47 -0700 | [diff] [blame] | 305 | func updateApp(t *testing.T, appID string, opt ...veyron2.Runtime) { |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 306 | if err := appStub(appID).Update(ort(opt).NewContext()); err != nil { |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 307 | t.Fatalf("%s: Update(%v) failed: %v", loc(1), appID, err) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 308 | } |
| 309 | } |
| 310 | |
| 311 | func updateAppExpectError(t *testing.T, appID string, expectedError verror.ID) { |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 312 | if err := appStub(appID).Update(rt.R().NewContext()); err == nil || !verror.Is(err, expectedError) { |
Benjamin Prosnitz | b8178d3 | 2014-11-04 10:24:12 -0800 | [diff] [blame] | 313 | if expectedError == naming.ErrNoSuchName.ID && err.Error() == "no different version available" { |
| 314 | // TODO(bprosnitz) Remove this check when errUpdateNoOp is updated to verror2 |
| 315 | return |
| 316 | } |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 317 | t.Fatalf("%s: Update(%v) expected to fail with %v, got %v instead", loc(1), appID, expectedError, err) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 318 | } |
| 319 | } |
| 320 | |
| 321 | func revertApp(t *testing.T, appID string) { |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 322 | if err := appStub(appID).Revert(rt.R().NewContext()); err != nil { |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 323 | t.Fatalf("%s: Revert(%v) failed: %v", loc(1), appID, err) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 324 | } |
| 325 | } |
| 326 | |
| 327 | func revertAppExpectError(t *testing.T, appID string, expectedError verror.ID) { |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 328 | if err := appStub(appID).Revert(rt.R().NewContext()); err == nil || !verror.Is(err, expectedError) { |
Benjamin Prosnitz | b8178d3 | 2014-11-04 10:24:12 -0800 | [diff] [blame] | 329 | if expectedError == naming.ErrNoSuchName.ID && err.Error() == "no different version available" { |
| 330 | // TODO(bprosnitz) Remove this check when errUpdateNoOp is updated to verror2 |
| 331 | return |
| 332 | } |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 333 | t.Fatalf("%s: Revert(%v) expected to fail with %v, got %v instead", loc(1), appID, expectedError, err) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 334 | } |
| 335 | } |
| 336 | |
| 337 | func uninstallApp(t *testing.T, appID string) { |
Todd Wang | 702385a | 2014-11-07 01:54:08 -0800 | [diff] [blame] | 338 | if err := appStub(appID).Uninstall(rt.R().NewContext()); err != nil { |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 339 | t.Fatalf("%s: Uninstall(%v) failed: %v", loc(1), appID, err) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 340 | } |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 341 | } |
Robert Kroeger | 1cb4a0d | 2014-10-20 11:55:38 -0700 | [diff] [blame] | 342 | |
| 343 | // Code to make Association lists sortable. |
| 344 | type byIdentity []node.Association |
| 345 | |
| 346 | func (a byIdentity) Len() int { return len(a) } |
| 347 | func (a byIdentity) Swap(i, j int) { a[i], a[j] = a[j], a[i] } |
| 348 | func (a byIdentity) Less(i, j int) bool { return a[i].IdentityName < a[j].IdentityName } |
| 349 | |
| 350 | func compareAssociations(t *testing.T, got, expected []node.Association) { |
| 351 | sort.Sort(byIdentity(got)) |
| 352 | sort.Sort(byIdentity(expected)) |
| 353 | if !reflect.DeepEqual(got, expected) { |
| 354 | t.Fatalf("ListAssociations() got %v, expected %v", got, expected) |
| 355 | } |
| 356 | } |
Robert Kroeger | 94ec756 | 2014-10-28 17:58:44 -0700 | [diff] [blame] | 357 | |
| 358 | // generateSuidHelperScript builds a script to execute the test target as |
| 359 | // a suidhelper instance and returns the path to the script. |
| 360 | func generateSuidHelperScript(t *testing.T, root string) string { |
| 361 | output := "#!/bin/bash\n" |
| 362 | output += "VEYRON_SUIDHELPER_TEST=1" |
| 363 | output += " " |
| 364 | output += "exec" + " " + os.Args[0] + " " + "-minuid=1" + " " + "-test.run=TestSuidHelper $*" |
| 365 | output += "\n" |
| 366 | |
| 367 | vlog.VI(1).Infof("script\n%s", output) |
| 368 | |
| 369 | if err := os.MkdirAll(root, 0755); err != nil { |
| 370 | t.Fatalf("MkdirAll failed: %v", err) |
| 371 | } |
| 372 | // Helper does not need to live under the node manager's root dir, but |
| 373 | // we put it there for convenience. |
| 374 | path := filepath.Join(root, "helper.sh") |
| 375 | if err := ioutil.WriteFile(path, []byte(output), 0755); err != nil { |
| 376 | t.Fatalf("WriteFile(%v) failed: %v", path, err) |
| 377 | } |
| 378 | return path |
| 379 | } |