Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 1 | package impl_test |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
| 5 | "os" |
| 6 | "testing" |
| 7 | |
Jiri Simsa | 519c507 | 2014-09-17 21:37:57 -0700 | [diff] [blame] | 8 | "veyron.io/veyron/veyron2" |
| 9 | "veyron.io/veyron/veyron2/ipc" |
| 10 | "veyron.io/veyron/veyron2/naming" |
| 11 | "veyron.io/veyron/veyron2/rt" |
| 12 | "veyron.io/veyron/veyron2/services/mgmt/node" |
| 13 | "veyron.io/veyron/veyron2/verror" |
| 14 | "veyron.io/veyron/veyron2/vlog" |
Cosmos Nicolaou | d6c3c9c | 2014-09-30 15:42:53 -0700 | [diff] [blame] | 15 | |
Cosmos Nicolaou | 486d349 | 2014-09-30 22:21:20 -0700 | [diff] [blame] | 16 | "veyron.io/veyron/veyron/lib/exec" |
Cosmos Nicolaou | d6c3c9c | 2014-09-30 15:42:53 -0700 | [diff] [blame] | 17 | "veyron.io/veyron/veyron/lib/testutil/blackbox" |
| 18 | "veyron.io/veyron/veyron/lib/testutil/security" |
| 19 | "veyron.io/veyron/veyron/profiles" |
Cosmos Nicolaou | d6c3c9c | 2014-09-30 15:42:53 -0700 | [diff] [blame] | 20 | mtlib "veyron.io/veyron/veyron/services/mounttable/lib" |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 21 | ) |
| 22 | |
| 23 | // TODO(caprita): I've had to write one too many of these, let's move it to some |
| 24 | // central utility library. |
| 25 | |
| 26 | // setupLocalNamespace sets up a mounttable and sets the local namespace root |
| 27 | // to point to it. Returns a cleanup function. |
| 28 | func setupLocalNamespace(t *testing.T) func() { |
| 29 | server, err := rt.R().NewServer(veyron2.ServesMountTableOpt(true)) |
| 30 | if err != nil { |
| 31 | t.Fatalf("NewServer() failed: %v", err) |
| 32 | } |
| 33 | dispatcher, err := mtlib.NewMountTable("") |
| 34 | if err != nil { |
| 35 | t.Fatalf("NewMountTable() failed: %v", err) |
| 36 | } |
Cosmos Nicolaou | d6c3c9c | 2014-09-30 15:42:53 -0700 | [diff] [blame] | 37 | endpoint, err := server.ListenX(profiles.LocalListenSpec) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 38 | if err != nil { |
Cosmos Nicolaou | d6c3c9c | 2014-09-30 15:42:53 -0700 | [diff] [blame] | 39 | t.Fatalf("Listen(%s) failed: %v", profiles.LocalListenSpec, err) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 40 | } |
| 41 | if err := server.Serve("", dispatcher); err != nil { |
| 42 | t.Fatalf("Serve(%v) failed: %v", dispatcher, err) |
| 43 | } |
| 44 | name := naming.JoinAddressName(endpoint.String(), "") |
| 45 | vlog.VI(1).Infof("Mount table object name: %v", name) |
| 46 | ns := rt.R().Namespace() |
| 47 | // Make the runtime's namespace rooted at the MountTable server started |
| 48 | // above. |
| 49 | ns.SetRoots(name) |
| 50 | return func() { |
| 51 | if err := server.Stop(); err != nil { |
| 52 | t.Fatalf("Stop() failed: %v", err) |
| 53 | } |
| 54 | // The runtime outlives the particular test case that invokes |
| 55 | // setupLocalNamespace. It's good practice to reset the |
| 56 | // runtime's state before the next test uses it. |
| 57 | ns.SetRoots() |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | // TODO(caprita): Move this setup into the blackbox lib. |
| 62 | |
| 63 | // setupChildCommand configures the child to use the right mounttable root |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 64 | // and blessings. It returns a cleanup function. |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 65 | func setupChildCommand(child *blackbox.Child) func() { |
Bogdan Caprita | b9501d1 | 2014-10-10 15:02:03 -0700 | [diff] [blame] | 66 | return setupChildCommandWithBlessing(child, "child") |
| 67 | } |
| 68 | |
| 69 | func setupChildCommandWithBlessing(child *blackbox.Child, blessing string) func() { |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 70 | cmd := child.Cmd |
| 71 | for i, root := range rt.R().Namespace().Roots() { |
| 72 | cmd.Env = exec.Setenv(cmd.Env, fmt.Sprintf("NAMESPACE_ROOT%d", i), root) |
| 73 | } |
Bogdan Caprita | b9501d1 | 2014-10-10 15:02:03 -0700 | [diff] [blame] | 74 | childcreds := security.NewVeyronCredentials(rt.R().Principal(), blessing) |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 75 | cmd.Env = exec.Setenv(cmd.Env, "VEYRON_CREDENTIALS", childcreds) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 76 | return func() { |
Asim Shankar | 8829291 | 2014-10-09 19:41:07 -0700 | [diff] [blame] | 77 | os.RemoveAll(childcreds) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 78 | } |
| 79 | } |
| 80 | |
| 81 | func newServer() (ipc.Server, string) { |
| 82 | server, err := rt.R().NewServer() |
| 83 | if err != nil { |
| 84 | vlog.Fatalf("NewServer() failed: %v", err) |
| 85 | } |
Cosmos Nicolaou | 9348da6 | 2014-10-03 14:21:19 -0700 | [diff] [blame] | 86 | endpoint, err := server.ListenX(profiles.LocalListenSpec) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 87 | if err != nil { |
Cosmos Nicolaou | 9348da6 | 2014-10-03 14:21:19 -0700 | [diff] [blame] | 88 | vlog.Fatalf("Listen(%s) failed: %v", profiles.LocalListenSpec, err) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 89 | } |
| 90 | return server, endpoint.String() |
| 91 | } |
| 92 | |
| 93 | // resolveExpectError verifies that the given name is not in the mounttable. |
Bogdan Caprita | bce0a63 | 2014-09-03 16:15:26 -0700 | [diff] [blame] | 94 | func resolveExpectNotFound(t *testing.T, name string) { |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 95 | 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] | 96 | t.Fatalf("Resolve(%v) succeeded with results %v when it was expected to fail", name, results) |
Tilak Sharma | 492e8e9 | 2014-09-18 10:58:14 -0700 | [diff] [blame] | 97 | } else if expectErr := verror.NoExist; !verror.Is(err, expectErr) { |
| 98 | 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] | 99 | } |
| 100 | } |
| 101 | |
| 102 | // resolve looks up the given name in the mounttable. |
Bogdan Caprita | bce0a63 | 2014-09-03 16:15:26 -0700 | [diff] [blame] | 103 | func resolve(t *testing.T, name string, replicas int) []string { |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 104 | results, err := rt.R().Namespace().Resolve(rt.R().NewContext(), name) |
| 105 | if err != nil { |
| 106 | t.Fatalf("Resolve(%v) failed: %v", name, err) |
| 107 | } |
Bogdan Caprita | bce0a63 | 2014-09-03 16:15:26 -0700 | [diff] [blame] | 108 | if want, got := replicas, len(results); want != got { |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 109 | t.Fatalf("Resolve(%v) expected %d result(s), got %d instead", name, want, got) |
| 110 | } |
Bogdan Caprita | bce0a63 | 2014-09-03 16:15:26 -0700 | [diff] [blame] | 111 | return results |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | // The following set of functions are convenience wrappers around Update and |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 115 | // Revert for node manager. |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 116 | |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 117 | func nodeStub(t *testing.T, name string) node.Node { |
| 118 | nodeName := naming.Join(name, "nm") |
| 119 | stub, err := node.BindNode(nodeName) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 120 | if err != nil { |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 121 | t.Fatalf("BindNode(%v) failed: %v", nodeName, err) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 122 | } |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 123 | return stub |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 124 | } |
| 125 | |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 126 | func updateNodeExpectError(t *testing.T, name string, errID verror.ID) { |
| 127 | if err := nodeStub(t, name).Update(rt.R().NewContext()); !verror.Is(err, errID) { |
| 128 | t.Fatalf("Update(%v) expected to fail with %v, got %v instead", name, errID, err) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 129 | } |
| 130 | } |
| 131 | |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 132 | func updateNode(t *testing.T, name string) { |
| 133 | if err := nodeStub(t, name).Update(rt.R().NewContext()); err != nil { |
| 134 | t.Fatalf("Update(%v) failed: %v", name, err) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 135 | } |
| 136 | } |
| 137 | |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 138 | func revertNodeExpectError(t *testing.T, name string, errID verror.ID) { |
| 139 | if err := nodeStub(t, name).Revert(rt.R().NewContext()); !verror.Is(err, errID) { |
| 140 | t.Fatalf("Revert(%v) expected to fail with %v, got %v instead", name, errID, err) |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | func revertNode(t *testing.T, name string) { |
| 145 | if err := nodeStub(t, name).Revert(rt.R().NewContext()); err != nil { |
| 146 | t.Fatalf("Revert(%v) failed: %v", name, err) |
| 147 | } |
| 148 | } |
| 149 | |
| 150 | // The following set of functions are convenience wrappers around various app |
| 151 | // management methods. |
| 152 | |
| 153 | func appStub(t *testing.T, nameComponents ...string) node.Application { |
| 154 | appsName := "nm//apps" |
| 155 | appName := naming.Join(append([]string{appsName}, nameComponents...)...) |
| 156 | stub, err := node.BindApplication(appName) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 157 | if err != nil { |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 158 | t.Fatalf("BindApplication(%v) failed: %v", appName, err) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 159 | } |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 160 | return stub |
| 161 | } |
| 162 | |
| 163 | func installApp(t *testing.T) string { |
| 164 | appID, err := appStub(t).Install(rt.R().NewContext(), "ar") |
| 165 | if err != nil { |
| 166 | t.Fatalf("Install failed: %v", err) |
| 167 | } |
| 168 | return appID |
| 169 | } |
| 170 | |
| 171 | func startAppImpl(t *testing.T, appID string) (string, error) { |
| 172 | if instanceIDs, err := appStub(t, appID).Start(rt.R().NewContext()); err != nil { |
| 173 | return "", err |
| 174 | } else { |
| 175 | if want, got := 1, len(instanceIDs); want != got { |
| 176 | t.Fatalf("Start(%v): expected %v instance ids, got %v instead", appID, want, got) |
| 177 | } |
| 178 | return instanceIDs[0], nil |
| 179 | } |
| 180 | } |
| 181 | |
| 182 | func startApp(t *testing.T, appID string) string { |
| 183 | instanceID, err := startAppImpl(t, appID) |
| 184 | if err != nil { |
| 185 | t.Fatalf("Start(%v) failed: %v", appID, err) |
| 186 | } |
| 187 | return instanceID |
| 188 | } |
| 189 | |
| 190 | func startAppExpectError(t *testing.T, appID string, expectedError verror.ID) { |
| 191 | if _, err := startAppImpl(t, appID); err == nil || !verror.Is(err, expectedError) { |
| 192 | t.Fatalf("Start(%v) expected to fail with %v, got %v instead", appID, expectedError, err) |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | func stopApp(t *testing.T, appID, instanceID string) { |
| 197 | if err := appStub(t, appID, instanceID).Stop(rt.R().NewContext(), 5); err != nil { |
| 198 | t.Fatalf("Stop(%v/%v) failed: %v", appID, instanceID, err) |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | func suspendApp(t *testing.T, appID, instanceID string) { |
| 203 | if err := appStub(t, appID, instanceID).Suspend(rt.R().NewContext()); err != nil { |
| 204 | t.Fatalf("Suspend(%v/%v) failed: %v", appID, instanceID, err) |
| 205 | } |
| 206 | } |
| 207 | |
| 208 | func resumeApp(t *testing.T, appID, instanceID string) { |
| 209 | if err := appStub(t, appID, instanceID).Resume(rt.R().NewContext()); err != nil { |
| 210 | t.Fatalf("Resume(%v/%v) failed: %v", appID, instanceID, err) |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | func updateApp(t *testing.T, appID string) { |
| 215 | if err := appStub(t, appID).Update(rt.R().NewContext()); err != nil { |
| 216 | t.Fatalf("Update(%v) failed: %v", appID, err) |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | func updateAppExpectError(t *testing.T, appID string, expectedError verror.ID) { |
| 221 | if err := appStub(t, appID).Update(rt.R().NewContext()); err == nil || !verror.Is(err, expectedError) { |
| 222 | t.Fatalf("Update(%v) expected to fail with %v, got %v instead", appID, expectedError, err) |
| 223 | } |
| 224 | } |
| 225 | |
| 226 | func revertApp(t *testing.T, appID string) { |
| 227 | if err := appStub(t, appID).Revert(rt.R().NewContext()); err != nil { |
| 228 | t.Fatalf("Revert(%v) failed: %v", appID, err) |
| 229 | } |
| 230 | } |
| 231 | |
| 232 | func revertAppExpectError(t *testing.T, appID string, expectedError verror.ID) { |
| 233 | if err := appStub(t, appID).Revert(rt.R().NewContext()); err == nil || !verror.Is(err, expectedError) { |
| 234 | t.Fatalf("Revert(%v) expected to fail with %v, got %v instead", appID, expectedError, err) |
| 235 | } |
| 236 | } |
| 237 | |
| 238 | func uninstallApp(t *testing.T, appID string) { |
| 239 | if err := appStub(t, appID).Uninstall(rt.R().NewContext()); err != nil { |
| 240 | t.Fatalf("Uninstall(%v) failed: %v", appID, err) |
| 241 | } |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 242 | } |