Jiri Simsa | d7616c9 | 2015-03-24 23:44:30 -0700 | [diff] [blame] | 1 | // Copyright 2015 The Vanadium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 5 | package utiltest |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 6 | |
| 7 | import ( |
Robin Thellend | 3480f8e | 2015-03-13 09:50:41 -0700 | [diff] [blame] | 8 | "errors" |
| 9 | "fmt" |
Bogdan Caprita | d2b9f03 | 2014-10-10 17:43:29 -0700 | [diff] [blame] | 10 | "io/ioutil" |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 11 | "os" |
Robert Kroeger | ef27d6e | 2015-05-01 16:58:59 -0700 | [diff] [blame] | 12 | "os/user" |
Bogdan Caprita | d2b9f03 | 2014-10-10 17:43:29 -0700 | [diff] [blame] | 13 | "path/filepath" |
Robert Kroeger | 1cb4a0d | 2014-10-20 11:55:38 -0700 | [diff] [blame] | 14 | "reflect" |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 15 | "regexp" |
Robert Kroeger | 1cb4a0d | 2014-10-20 11:55:38 -0700 | [diff] [blame] | 16 | "sort" |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 17 | "strings" |
Robert Kroeger | 4740f88 | 2015-06-11 16:26:13 -0700 | [diff] [blame] | 18 | "syscall" |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 19 | "testing" |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 20 | "time" |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 21 | |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 22 | "v.io/v23" |
| 23 | "v.io/v23/context" |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 24 | "v.io/v23/naming" |
| 25 | "v.io/v23/options" |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 26 | "v.io/v23/rpc" |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 27 | "v.io/v23/security" |
Todd Wang | 94c9d0b | 2015-04-01 14:27:00 -0700 | [diff] [blame] | 28 | "v.io/v23/services/application" |
| 29 | "v.io/v23/services/device" |
| 30 | "v.io/v23/services/logreader" |
| 31 | "v.io/v23/services/pprof" |
| 32 | "v.io/v23/services/stats" |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 33 | "v.io/v23/verror" |
Cosmos Nicolaou | 1848973 | 2015-06-29 16:01:38 -0700 | [diff] [blame] | 34 | "v.io/x/ref/internal/logger" |
Matt Rosencrantz | bb6295d | 2015-06-19 15:13:58 -0700 | [diff] [blame] | 35 | "v.io/x/ref/lib/xrpc" |
Suharsh Sivakumar | dcc11d7 | 2015-05-11 12:19:20 -0700 | [diff] [blame] | 36 | _ "v.io/x/ref/runtime/factories/roaming" |
Bogdan Caprita | 1bba736 | 2015-06-30 14:03:17 -0700 | [diff] [blame] | 37 | "v.io/x/ref/services/device/deviced/internal/impl" |
Bogdan Caprita | 226d88e | 2015-06-30 17:34:57 -0700 | [diff] [blame] | 38 | "v.io/x/ref/services/device/deviced/internal/versioning" |
Robert Kroeger | 60e0305 | 2015-05-04 17:35:16 -0700 | [diff] [blame] | 39 | "v.io/x/ref/services/internal/binarylib" |
Todd Wang | 5fc3644 | 2015-04-07 15:15:27 -0700 | [diff] [blame] | 40 | "v.io/x/ref/services/internal/servicetest" |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 41 | "v.io/x/ref/test" |
| 42 | "v.io/x/ref/test/modules" |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 43 | "v.io/x/ref/test/testutil" |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 44 | ) |
| 45 | |
Bogdan Caprita | 916e99f | 2014-11-24 15:47:19 -0800 | [diff] [blame] | 46 | const ( |
Bogdan Caprita | 916e99f | 2014-11-24 15:47:19 -0800 | [diff] [blame] | 47 | // TODO(caprita): Set the timeout in a more principled manner. |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 48 | killTimeout = 20 * time.Second |
Bogdan Caprita | 916e99f | 2014-11-24 15:47:19 -0800 | [diff] [blame] | 49 | ) |
Bogdan Caprita | d2b9f03 | 2014-10-10 17:43:29 -0700 | [diff] [blame] | 50 | |
Robert Kroeger | ef27d6e | 2015-05-01 16:58:59 -0700 | [diff] [blame] | 51 | func init() { |
| 52 | impl.Describe = func() (descr device.Description, err error) { |
| 53 | return device.Description{Profiles: map[string]struct{}{"test-profile": struct{}{}}}, nil |
| 54 | } |
Robert Kroeger | 3278a0c | 2015-05-05 14:29:24 -0700 | [diff] [blame] | 55 | |
Cosmos Nicolaou | 1848973 | 2015-06-29 16:01:38 -0700 | [diff] [blame] | 56 | impl.CleanupDir = func(ctx *context.T, dir, helper string) { |
Robert Kroeger | 3278a0c | 2015-05-05 14:29:24 -0700 | [diff] [blame] | 57 | if dir == "" { |
| 58 | return |
| 59 | } |
| 60 | parentDir, base := filepath.Dir(dir), filepath.Base(dir) |
| 61 | var renamed string |
| 62 | if helper != "" { |
| 63 | renamed = filepath.Join(parentDir, "helper_deleted_"+base) |
| 64 | } else { |
| 65 | renamed = filepath.Join(parentDir, "deleted_"+base) |
| 66 | } |
| 67 | if err := os.Rename(dir, renamed); err != nil { |
Cosmos Nicolaou | 1848973 | 2015-06-29 16:01:38 -0700 | [diff] [blame] | 68 | ctx.Errorf("Rename(%v, %v) failed: %v", dir, renamed, err) |
Robert Kroeger | 3278a0c | 2015-05-05 14:29:24 -0700 | [diff] [blame] | 69 | } |
| 70 | } |
Robert Kroeger | 742a610 | 2015-06-15 10:41:28 -0700 | [diff] [blame] | 71 | |
Robert Kroeger | afd85ff | 2015-06-17 17:40:24 -0700 | [diff] [blame] | 72 | // Return a sequence of times separated by 25 hours. |
| 73 | impl.MockableNow = func() time.Time { |
| 74 | now := time.Now() |
| 75 | impl.MockableNow = func() time.Time { |
| 76 | now = now.Add(time.Hour * 25) |
| 77 | return now |
| 78 | } |
| 79 | return now |
| 80 | } |
| 81 | |
Robert Kroeger | ef27d6e | 2015-05-01 16:58:59 -0700 | [diff] [blame] | 82 | } |
| 83 | |
Todd Wang | 9587390 | 2015-05-22 14:21:30 -0700 | [diff] [blame] | 84 | func EnvelopeFromShell(sh *modules.Shell, env []string, prog modules.Program, title string, retries int, window time.Duration, args ...string) application.Envelope { |
| 85 | args, nenv := sh.ProgramEnvelope(env, prog, args...) |
Cosmos Nicolaou | ad2793f | 2014-10-27 16:24:15 -0700 | [diff] [blame] | 86 | return application.Envelope{ |
| 87 | Title: title, |
| 88 | Args: args[1:], |
| 89 | // TODO(caprita): revisit how the environment is sanitized for arbirary |
| 90 | // apps. |
Robert Kroeger | 73310c8 | 2015-05-14 16:51:10 -0700 | [diff] [blame] | 91 | Env: impl.VanadiumEnvironment(nenv), |
| 92 | Binary: application.SignedFile{File: MockBinaryRepoName}, |
| 93 | Restarts: int32(retries), |
| 94 | RestartTimeWindow: window, |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 95 | } |
| 96 | } |
| 97 | |
Arup Mukherjee | 13c0038 | 2015-06-04 15:54:38 -0700 | [diff] [blame] | 98 | func SignedEnvelopeFromShell(ctx *context.T, sh *modules.Shell, env []string, prog modules.Program, title string, retries int, window time.Duration, args ...string) (application.Envelope, error) { |
| 99 | envelope := EnvelopeFromShell(sh, env, prog, title, retries, window, args...) |
| 100 | reader, cleanup, err := mockBinaryBytesReader() |
| 101 | defer cleanup() |
| 102 | sig, err := binarylib.Sign(ctx, reader) |
| 103 | if err != nil { |
| 104 | return application.Envelope{}, err |
| 105 | } |
| 106 | envelope.Binary.Signature = *sig |
| 107 | |
| 108 | // Add a publisher blessing |
| 109 | p := v23.GetPrincipal(ctx) |
| 110 | publisher, err := p.Bless(p.PublicKey(), p.BlessingStore().Default(), "angryapp.v10", security.UnconstrainedUse()) |
| 111 | if err != nil { |
| 112 | return application.Envelope{}, err |
| 113 | } |
| 114 | envelope.Publisher = publisher |
| 115 | return envelope, nil |
| 116 | } |
| 117 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 118 | // ResolveExpectNotFound verifies that the given name is not in the mounttable. |
Cosmos Nicolaou | 33cf898 | 2015-05-26 10:39:49 -0700 | [diff] [blame] | 119 | func ResolveExpectNotFound(t *testing.T, ctx *context.T, name string, retry bool) { |
| 120 | expectErr := naming.ErrNoSuchName.ID |
| 121 | for { |
| 122 | me, err := v23.GetNamespace(ctx).Resolve(ctx, name) |
| 123 | if err == nil || verror.ErrorID(err) != expectErr { |
| 124 | if retry { |
| 125 | time.Sleep(10 * time.Millisecond) |
| 126 | continue |
| 127 | } |
| 128 | if err == nil { |
| 129 | t.Fatalf(testutil.FormatLogLine(2, "Resolve(%v) succeeded with results %v when it was expected to fail", name, me.Names())) |
| 130 | } else { |
| 131 | t.Fatalf(testutil.FormatLogLine(2, "Resolve(%v) failed with error %v, expected error ID %v", name, err, expectErr)) |
| 132 | } |
| 133 | } else { |
| 134 | return |
| 135 | } |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 136 | } |
| 137 | } |
| 138 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 139 | // Resolve looks up the given name in the mounttable. |
Cosmos Nicolaou | 33cf898 | 2015-05-26 10:39:49 -0700 | [diff] [blame] | 140 | func Resolve(t *testing.T, ctx *context.T, name string, replicas int, retry bool) []string { |
| 141 | for { |
| 142 | me, err := v23.GetNamespace(ctx).Resolve(ctx, name) |
| 143 | if err != nil { |
| 144 | if retry { |
| 145 | time.Sleep(10 * time.Millisecond) |
| 146 | continue |
| 147 | } else { |
| 148 | t.Fatalf("Resolve(%v) failed: %v", name, err) |
| 149 | } |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 150 | } |
Cosmos Nicolaou | 33cf898 | 2015-05-26 10:39:49 -0700 | [diff] [blame] | 151 | |
| 152 | filteredResults := []string{} |
| 153 | for _, r := range me.Names() { |
| 154 | if strings.Index(r, "@tcp") != -1 { |
| 155 | filteredResults = append(filteredResults, r) |
| 156 | } |
| 157 | } |
| 158 | // We are going to get a websocket and a tcp endpoint for each replica. |
| 159 | if want, got := replicas, len(filteredResults); want != got { |
| 160 | t.Fatalf("Resolve(%v) expected %d result(s), got %d instead", name, want, got) |
| 161 | } |
| 162 | return filteredResults |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 163 | } |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 164 | } |
| 165 | |
| 166 | // The following set of functions are convenience wrappers around Update and |
Bogdan Caprita | 2b21936 | 2014-12-09 17:03:33 -0800 | [diff] [blame] | 167 | // Revert for device manager. |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 168 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 169 | func DeviceStub(name string) device.DeviceClientMethods { |
Bogdan Caprita | 9c4aa22 | 2014-12-10 14:46:30 -0800 | [diff] [blame] | 170 | deviceName := naming.Join(name, "device") |
Bogdan Caprita | a456f47 | 2014-12-10 10:18:03 -0800 | [diff] [blame] | 171 | return device.DeviceClient(deviceName) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 172 | } |
| 173 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 174 | func ClaimDevice(t *testing.T, ctx *context.T, claimableName, deviceName, extension, pairingToken string) { |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 175 | // Setup blessings to be granted to the claimed device |
Ankur | dda1649 | 2015-04-07 12:35:42 -0700 | [diff] [blame] | 176 | g := &granter{extension: extension} |
Asim Shankar | 263c73b | 2015-03-19 18:31:26 -0700 | [diff] [blame] | 177 | s := options.SkipServerEndpointAuthorization{} |
Asim Shankar | b547ea9 | 2015-02-17 18:49:45 -0800 | [diff] [blame] | 178 | // Call the Claim RPC: Skip server authorization because the unclaimed |
| 179 | // device presents nothing that can be used to recognize it. |
Bogdan Caprita | e807368 | 2015-04-25 15:37:53 -0700 | [diff] [blame] | 180 | if err := device.ClaimableClient(claimableName).Claim(ctx, pairingToken, g, s); err != nil { |
| 181 | t.Fatalf(testutil.FormatLogLine(2, "%q.Claim(%q) failed: %v [%v]", claimableName, pairingToken, verror.ErrorID(err), err)) |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 182 | } |
| 183 | // Wait for the device to remount itself with the device service after |
| 184 | // being claimed. |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 185 | start := time.Now() |
| 186 | for { |
Bogdan Caprita | e807368 | 2015-04-25 15:37:53 -0700 | [diff] [blame] | 187 | _, err := v23.GetNamespace(ctx).Resolve(ctx, deviceName) |
| 188 | if err == nil { |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 189 | return |
| 190 | } |
Cosmos Nicolaou | 1848973 | 2015-06-29 16:01:38 -0700 | [diff] [blame] | 191 | ctx.VI(4).Infof("Resolve(%q) failed: %v", err) |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 192 | time.Sleep(time.Millisecond) |
| 193 | if elapsed := time.Since(start); elapsed > time.Minute { |
| 194 | t.Fatalf("Device hasn't remounted itself in %v since it was claimed", elapsed) |
| 195 | } |
| 196 | } |
| 197 | } |
| 198 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 199 | func ClaimDeviceExpectError(t *testing.T, ctx *context.T, name, extension, pairingToken string, errID verror.ID) { |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 200 | // Setup blessings to be granted to the claimed device |
Ankur | dda1649 | 2015-04-07 12:35:42 -0700 | [diff] [blame] | 201 | g := &granter{extension: extension} |
Asim Shankar | 263c73b | 2015-03-19 18:31:26 -0700 | [diff] [blame] | 202 | s := options.SkipServerEndpointAuthorization{} |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 203 | // Call the Claim RPC |
Todd Wang | 8fa3876 | 2015-03-25 14:04:59 -0700 | [diff] [blame] | 204 | if err := device.ClaimableClient(name).Claim(ctx, pairingToken, g, s); verror.ErrorID(err) != errID { |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 205 | t.Fatalf(testutil.FormatLogLine(2, "%q.Claim(%q) expected to fail with %v, got %v [%v]", name, pairingToken, errID, verror.ErrorID(err), err)) |
| 206 | } |
| 207 | } |
| 208 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 209 | func UpdateDeviceExpectError(t *testing.T, ctx *context.T, name string, errID verror.ID) { |
| 210 | if err := DeviceStub(name).Update(ctx); verror.ErrorID(err) != errID { |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 211 | t.Fatalf(testutil.FormatLogLine(2, "%q.Update expected to fail with %v, got %v [%v]", name, errID, verror.ErrorID(err), err)) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 212 | } |
| 213 | } |
| 214 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 215 | func UpdateDevice(t *testing.T, ctx *context.T, name string) { |
| 216 | if err := DeviceStub(name).Update(ctx); err != nil { |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 217 | t.Fatalf(testutil.FormatLogLine(2, "%q.Update() failed: %v [%v]", name, verror.ErrorID(err), err)) |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 218 | } |
| 219 | } |
| 220 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 221 | func RevertDeviceExpectError(t *testing.T, ctx *context.T, name string, errID verror.ID) { |
| 222 | if err := DeviceStub(name).Revert(ctx); verror.ErrorID(err) != errID { |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 223 | t.Fatalf(testutil.FormatLogLine(2, "%q.Revert() expected to fail with %v, got %v [%v]", name, errID, verror.ErrorID(err), err)) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 224 | } |
| 225 | } |
| 226 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 227 | func RevertDevice(t *testing.T, ctx *context.T, name string) { |
| 228 | if err := DeviceStub(name).Revert(ctx); err != nil { |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 229 | t.Fatalf(testutil.FormatLogLine(2, "%q.Revert() failed: %v [%v]", name, verror.ErrorID(err), err)) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 230 | } |
| 231 | } |
| 232 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 233 | func KillDevice(t *testing.T, ctx *context.T, name string) { |
| 234 | if err := DeviceStub(name).Kill(ctx, killTimeout); err != nil { |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 235 | t.Fatalf(testutil.FormatLogLine(2, "%q.Kill(%v) failed: %v [%v]", name, killTimeout, verror.ErrorID(err), err)) |
Bogdan Caprita | 4ea9b03 | 2014-12-27 14:56:51 -0800 | [diff] [blame] | 236 | } |
| 237 | } |
| 238 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 239 | func ShutdownDevice(t *testing.T, ctx *context.T, name string) { |
| 240 | if err := DeviceStub(name).Delete(ctx); err != nil { |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 241 | t.Fatalf(testutil.FormatLogLine(2, "%q.Delete() failed: %v [%v]", name, verror.ErrorID(err), err)) |
Bogdan Caprita | 4ea9b03 | 2014-12-27 14:56:51 -0800 | [diff] [blame] | 242 | } |
| 243 | } |
| 244 | |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 245 | // The following set of functions are convenience wrappers around various app |
| 246 | // management methods. |
| 247 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 248 | func Ocfg(opt []interface{}) device.Config { |
Bogdan Caprita | 17666dd | 2015-01-14 09:27:46 -0800 | [diff] [blame] | 249 | for _, o := range opt { |
| 250 | if c, ok := o.(device.Config); ok { |
| 251 | return c |
| 252 | } |
| 253 | } |
| 254 | return device.Config{} |
| 255 | } |
| 256 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 257 | func Opkg(opt []interface{}) application.Packages { |
Bogdan Caprita | c25a48c | 2015-02-12 13:45:51 -0800 | [diff] [blame] | 258 | for _, o := range opt { |
| 259 | if c, ok := o.(application.Packages); ok { |
| 260 | return c |
| 261 | } |
| 262 | } |
| 263 | return application.Packages{} |
| 264 | } |
| 265 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 266 | func AppStub(nameComponents ...string) device.ApplicationClientMethods { |
Robert Kroeger | 7464517 | 2015-02-11 14:22:21 -0800 | [diff] [blame] | 267 | appsName := "dm/apps" |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 268 | appName := naming.Join(append([]string{appsName}, nameComponents...)...) |
Bogdan Caprita | a456f47 | 2014-12-10 10:18:03 -0800 | [diff] [blame] | 269 | return device.ApplicationClient(appName) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 270 | } |
| 271 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 272 | func StatsStub(nameComponents ...string) stats.StatsClientMethods { |
Robert Kroeger | bc22606 | 2015-03-16 17:24:07 -0700 | [diff] [blame] | 273 | statsName := naming.Join(nameComponents...) |
Robert Kroeger | 6e4ed12 | 2015-03-06 13:03:54 -0800 | [diff] [blame] | 274 | return stats.StatsClient(statsName) |
| 275 | } |
| 276 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 277 | func InstallApp(t *testing.T, ctx *context.T, opt ...interface{}) string { |
| 278 | appID, err := AppStub().Install(ctx, MockApplicationRepoName, Ocfg(opt), Opkg(opt)) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 279 | if err != nil { |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 280 | t.Fatalf(testutil.FormatLogLine(2, "Install failed: %v [%v]", verror.ErrorID(err), err)) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 281 | } |
| 282 | return appID |
| 283 | } |
| 284 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 285 | func InstallAppExpectError(t *testing.T, ctx *context.T, expectedError verror.ID, opt ...interface{}) { |
| 286 | if _, err := AppStub().Install(ctx, MockApplicationRepoName, Ocfg(opt), Opkg(opt)); err == nil || verror.ErrorID(err) != expectedError { |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 287 | t.Fatalf(testutil.FormatLogLine(2, "Install expected to fail with %v, got %v [%v]", expectedError, verror.ErrorID(err), err)) |
Bogdan Caprita | 17666dd | 2015-01-14 09:27:46 -0800 | [diff] [blame] | 288 | } |
| 289 | } |
| 290 | |
Bogdan Caprita | 2692910 | 2014-11-07 11:56:56 -0800 | [diff] [blame] | 291 | type granter struct { |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 292 | rpc.CallOpt |
Bogdan Caprita | 2692910 | 2014-11-07 11:56:56 -0800 | [diff] [blame] | 293 | p security.Principal |
| 294 | extension string |
| 295 | } |
| 296 | |
Todd Wang | 4264e4b | 2015-04-16 22:43:40 -0700 | [diff] [blame] | 297 | func (g *granter) Grant(ctx *context.T, call security.Call) (security.Blessings, error) { |
Ankur | dda1649 | 2015-04-07 12:35:42 -0700 | [diff] [blame] | 298 | p := call.LocalPrincipal() |
| 299 | return p.Bless(call.RemoteBlessings().PublicKey(), p.BlessingStore().Default(), g.extension, security.UnconstrainedUse()) |
Bogdan Caprita | 2692910 | 2014-11-07 11:56:56 -0800 | [diff] [blame] | 300 | } |
| 301 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 302 | func LaunchAppImpl(t *testing.T, ctx *context.T, appID, grant string) (string, error) { |
| 303 | instanceID, err := NewInstanceImpl(t, ctx, appID, grant) |
Robin Thellend | 3480f8e | 2015-03-13 09:50:41 -0700 | [diff] [blame] | 304 | if err != nil { |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 305 | return "", err |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 306 | } |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 307 | return instanceID, AppStub(appID, instanceID).Run(ctx) |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 308 | } |
| 309 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 310 | func NewInstanceImpl(t *testing.T, ctx *context.T, appID, grant string) (string, error) { |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 311 | ctx, delete := context.WithCancel(ctx) |
| 312 | defer delete() |
| 313 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 314 | call, err := AppStub(appID).Instantiate(ctx) |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 315 | if err != nil { |
| 316 | return "", err |
| 317 | } |
Robin Thellend | 3480f8e | 2015-03-13 09:50:41 -0700 | [diff] [blame] | 318 | for call.RecvStream().Advance() { |
| 319 | switch msg := call.RecvStream().Value().(type) { |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 320 | case device.BlessServerMessageInstancePublicKey: |
Robin Thellend | 3480f8e | 2015-03-13 09:50:41 -0700 | [diff] [blame] | 321 | p := v23.GetPrincipal(ctx) |
| 322 | pubKey, err := security.UnmarshalPublicKey(msg.Value) |
| 323 | if err != nil { |
| 324 | return "", err |
| 325 | } |
| 326 | blessings, err := p.Bless(pubKey, p.BlessingStore().Default(), grant, security.UnconstrainedUse()) |
| 327 | if err != nil { |
| 328 | return "", errors.New("bless failed") |
| 329 | } |
Jiri Simsa | d9a7b3c | 2015-08-12 16:38:27 -0700 | [diff] [blame] | 330 | call.SendStream().Send(device.BlessClientMessageAppBlessings{Value: blessings}) |
Robin Thellend | 3480f8e | 2015-03-13 09:50:41 -0700 | [diff] [blame] | 331 | default: |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 332 | return "", fmt.Errorf("newInstanceImpl: received unexpected message: %#v", msg) |
Robin Thellend | 3480f8e | 2015-03-13 09:50:41 -0700 | [diff] [blame] | 333 | } |
| 334 | } |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 335 | var instanceID string |
| 336 | if instanceID, err = call.Finish(); err != nil { |
Robin Thellend | 3480f8e | 2015-03-13 09:50:41 -0700 | [diff] [blame] | 337 | return "", err |
| 338 | } |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 339 | return instanceID, nil |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 340 | } |
| 341 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 342 | func LaunchApp(t *testing.T, ctx *context.T, appID string) string { |
| 343 | instanceID, err := LaunchAppImpl(t, ctx, appID, "forapp") |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 344 | if err != nil { |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 345 | t.Fatalf(testutil.FormatLogLine(2, "launching %v failed: %v [%v]", appID, verror.ErrorID(err), err)) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 346 | } |
| 347 | return instanceID |
| 348 | } |
| 349 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 350 | func LaunchAppExpectError(t *testing.T, ctx *context.T, appID string, expectedError verror.ID) { |
| 351 | if _, err := LaunchAppImpl(t, ctx, appID, "forapp"); err == nil || verror.ErrorID(err) != expectedError { |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 352 | t.Fatalf(testutil.FormatLogLine(2, "launching %v expected to fail with %v, got %v [%v]", appID, expectedError, verror.ErrorID(err), err)) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 353 | } |
| 354 | } |
| 355 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 356 | func TerminateApp(t *testing.T, ctx *context.T, appID, instanceID string) { |
| 357 | if err := AppStub(appID, instanceID).Kill(ctx, killTimeout); err != nil { |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 358 | t.Fatalf(testutil.FormatLogLine(2, "Kill(%v/%v) failed: %v [%v]", appID, instanceID, verror.ErrorID(err), err)) |
| 359 | } |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 360 | if err := AppStub(appID, instanceID).Delete(ctx); err != nil { |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 361 | t.Fatalf(testutil.FormatLogLine(2, "Delete(%v/%v) failed: %v [%v]", appID, instanceID, verror.ErrorID(err), err)) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 362 | } |
| 363 | } |
| 364 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 365 | func KillApp(t *testing.T, ctx *context.T, appID, instanceID string) { |
| 366 | if err := AppStub(appID, instanceID).Kill(ctx, killTimeout); err != nil { |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 367 | t.Fatalf(testutil.FormatLogLine(2, "Kill(%v/%v) failed: %v [%v]", appID, instanceID, verror.ErrorID(err), err)) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 368 | } |
| 369 | } |
| 370 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 371 | func DeleteApp(t *testing.T, ctx *context.T, appID, instanceID string) { |
| 372 | if err := AppStub(appID, instanceID).Delete(ctx); err != nil { |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 373 | t.Fatalf(testutil.FormatLogLine(2, "Delete(%v/%v) failed: %v [%v]", appID, instanceID, verror.ErrorID(err), err)) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 374 | } |
| 375 | } |
| 376 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 377 | func RunApp(t *testing.T, ctx *context.T, appID, instanceID string) { |
| 378 | if err := AppStub(appID, instanceID).Run(ctx); err != nil { |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 379 | t.Fatalf(testutil.FormatLogLine(2, "Run(%v/%v) failed: %v [%v]", appID, instanceID, verror.ErrorID(err), err)) |
| 380 | } |
| 381 | } |
| 382 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 383 | func RunAppExpectError(t *testing.T, ctx *context.T, appID, instanceID string, expectedError verror.ID) { |
| 384 | if err := AppStub(appID, instanceID).Run(ctx); err == nil || verror.ErrorID(err) != expectedError { |
Bogdan Caprita | 2b05032 | 2015-04-17 09:04:03 -0700 | [diff] [blame] | 385 | t.Fatalf(testutil.FormatLogLine(2, "Run(%v/%v) expected to fail with %v, got %v [%v]", appID, instanceID, expectedError, verror.ErrorID(err), err)) |
Robert Kroeger | 1ce0bd7 | 2014-10-22 13:57:14 -0700 | [diff] [blame] | 386 | } |
| 387 | } |
| 388 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 389 | func UpdateInstance(t *testing.T, ctx *context.T, appID, instanceID string) { |
| 390 | if err := AppStub(appID, instanceID).Update(ctx); err != nil { |
Bogdan Caprita | b4d1dfd | 2015-02-26 11:18:34 -0800 | [diff] [blame] | 391 | t.Fatalf(testutil.FormatLogLine(2, "Update(%v/%v) failed: %v [%v]", appID, instanceID, verror.ErrorID(err), err)) |
| 392 | } |
| 393 | } |
| 394 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 395 | func UpdateInstanceExpectError(t *testing.T, ctx *context.T, appID, instanceID string, expectedError verror.ID) { |
| 396 | if err := AppStub(appID, instanceID).Update(ctx); err == nil || verror.ErrorID(err) != expectedError { |
Bogdan Caprita | b4d1dfd | 2015-02-26 11:18:34 -0800 | [diff] [blame] | 397 | t.Fatalf(testutil.FormatLogLine(2, "Update(%v/%v) expected to fail with %v, got %v [%v]", appID, instanceID, expectedError, verror.ErrorID(err), err)) |
| 398 | } |
| 399 | } |
| 400 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 401 | func UpdateApp(t *testing.T, ctx *context.T, appID string) { |
| 402 | if err := AppStub(appID).Update(ctx); err != nil { |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 403 | t.Fatalf(testutil.FormatLogLine(2, "Update(%v) failed: %v [%v]", appID, verror.ErrorID(err), err)) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 404 | } |
| 405 | } |
| 406 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 407 | func UpdateAppExpectError(t *testing.T, ctx *context.T, appID string, expectedError verror.ID) { |
| 408 | if err := AppStub(appID).Update(ctx); err == nil || verror.ErrorID(err) != expectedError { |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 409 | t.Fatalf(testutil.FormatLogLine(2, "Update(%v) expected to fail with %v, got %v [%v]", appID, expectedError, verror.ErrorID(err), err)) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 410 | } |
| 411 | } |
| 412 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 413 | func RevertApp(t *testing.T, ctx *context.T, appID string) { |
| 414 | if err := AppStub(appID).Revert(ctx); err != nil { |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 415 | t.Fatalf(testutil.FormatLogLine(2, "Revert(%v) failed: %v [%v]", appID, verror.ErrorID(err), err)) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 416 | } |
| 417 | } |
| 418 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 419 | func RevertAppExpectError(t *testing.T, ctx *context.T, appID string, expectedError verror.ID) { |
| 420 | if err := AppStub(appID).Revert(ctx); err == nil || verror.ErrorID(err) != expectedError { |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 421 | t.Fatalf(testutil.FormatLogLine(2, "Revert(%v) expected to fail with %v, got %v [%v]", appID, expectedError, verror.ErrorID(err), err)) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 422 | } |
| 423 | } |
| 424 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 425 | func UninstallApp(t *testing.T, ctx *context.T, appID string) { |
| 426 | if err := AppStub(appID).Uninstall(ctx); err != nil { |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 427 | t.Fatalf(testutil.FormatLogLine(2, "Uninstall(%v) failed: %v [%v]", appID, verror.ErrorID(err), err)) |
Bogdan Caprita | 48bbd14 | 2014-09-04 16:07:23 -0700 | [diff] [blame] | 428 | } |
Bogdan Caprita | c87a914 | 2014-07-21 10:38:13 -0700 | [diff] [blame] | 429 | } |
Robert Kroeger | 1cb4a0d | 2014-10-20 11:55:38 -0700 | [diff] [blame] | 430 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 431 | func Debug(t *testing.T, ctx *context.T, nameComponents ...string) string { |
| 432 | dbg, err := AppStub(nameComponents...).Debug(ctx) |
Bogdan Caprita | d8373a1 | 2015-01-28 19:52:37 -0800 | [diff] [blame] | 433 | if err != nil { |
Asim Shankar | 23dac32 | 2015-02-14 12:42:26 -0800 | [diff] [blame] | 434 | t.Fatalf(testutil.FormatLogLine(2, "Debug(%v) failed: %v [%v]", nameComponents, verror.ErrorID(err), err)) |
Bogdan Caprita | d8373a1 | 2015-01-28 19:52:37 -0800 | [diff] [blame] | 435 | } |
| 436 | return dbg |
| 437 | } |
| 438 | |
Bogdan Caprita | 019f0ad | 2015-05-21 10:45:10 -0700 | [diff] [blame] | 439 | func VerifyDeviceState(t *testing.T, ctx *context.T, want device.InstanceState, name string) string { |
| 440 | s, err := DeviceStub(name).Status(ctx) |
| 441 | if err != nil { |
| 442 | t.Fatalf(testutil.FormatLogLine(2, "Status(%v) failed: %v [%v]", name, verror.ErrorID(err), err)) |
| 443 | } |
Bogdan Caprita | d2188b7 | 2015-05-22 12:31:48 -0700 | [diff] [blame] | 444 | status, ok := s.(device.StatusDevice) |
Bogdan Caprita | 019f0ad | 2015-05-21 10:45:10 -0700 | [diff] [blame] | 445 | if !ok { |
| 446 | t.Fatalf(testutil.FormatLogLine(2, "Status(%v) returned unknown type: %T", name, s)) |
| 447 | } |
| 448 | if status.Value.State != want { |
| 449 | t.Fatalf(testutil.FormatLogLine(2, "Status(%v) state: wanted %v, got %v", name, want, status.Value.State)) |
| 450 | } |
| 451 | return status.Value.Version |
| 452 | } |
| 453 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 454 | func Status(t *testing.T, ctx *context.T, nameComponents ...string) device.Status { |
| 455 | s, err := AppStub(nameComponents...).Status(ctx) |
Bogdan Caprita | b7f5d77 | 2015-03-24 16:37:59 -0700 | [diff] [blame] | 456 | if err != nil { |
Robert Kroeger | 8c2be90 | 2015-06-19 15:33:45 -0700 | [diff] [blame] | 457 | t.Errorf(testutil.FormatLogLine(3, "Status(%v) failed: %v [%v]", nameComponents, verror.ErrorID(err), err)) |
Bogdan Caprita | b7f5d77 | 2015-03-24 16:37:59 -0700 | [diff] [blame] | 458 | } |
| 459 | return s |
| 460 | } |
| 461 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 462 | func VerifyState(t *testing.T, ctx *context.T, want interface{}, nameComponents ...string) string { |
| 463 | s := Status(t, ctx, nameComponents...) |
Bogdan Caprita | b7f5d77 | 2015-03-24 16:37:59 -0700 | [diff] [blame] | 464 | var ( |
| 465 | state interface{} |
| 466 | version string |
| 467 | ) |
| 468 | switch s := s.(type) { |
| 469 | case device.StatusInstance: |
| 470 | state = s.Value.State |
| 471 | version = s.Value.Version |
| 472 | case device.StatusInstallation: |
| 473 | state = s.Value.State |
| 474 | version = s.Value.Version |
| 475 | default: |
Robert Kroeger | 8c2be90 | 2015-06-19 15:33:45 -0700 | [diff] [blame] | 476 | t.Errorf(testutil.FormatLogLine(2, "Status(%v) returned unknown type: %T", nameComponents, s)) |
Bogdan Caprita | b7f5d77 | 2015-03-24 16:37:59 -0700 | [diff] [blame] | 477 | } |
| 478 | if state != want { |
Robert Kroeger | 8c2be90 | 2015-06-19 15:33:45 -0700 | [diff] [blame] | 479 | t.Errorf(testutil.FormatLogLine(2, "Status(%v) state: wanted %v (%T), got %v (%T)", nameComponents, want, want, state, state)) |
Bogdan Caprita | b7f5d77 | 2015-03-24 16:37:59 -0700 | [diff] [blame] | 480 | } |
| 481 | return version |
| 482 | } |
| 483 | |
Robert Kroeger | 1cb4a0d | 2014-10-20 11:55:38 -0700 | [diff] [blame] | 484 | // Code to make Association lists sortable. |
Bogdan Caprita | a456f47 | 2014-12-10 10:18:03 -0800 | [diff] [blame] | 485 | type byIdentity []device.Association |
Robert Kroeger | 1cb4a0d | 2014-10-20 11:55:38 -0700 | [diff] [blame] | 486 | |
| 487 | func (a byIdentity) Len() int { return len(a) } |
| 488 | func (a byIdentity) Swap(i, j int) { a[i], a[j] = a[j], a[i] } |
| 489 | func (a byIdentity) Less(i, j int) bool { return a[i].IdentityName < a[j].IdentityName } |
| 490 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 491 | func CompareAssociations(t *testing.T, got, expected []device.Association) { |
Robert Kroeger | 1cb4a0d | 2014-10-20 11:55:38 -0700 | [diff] [blame] | 492 | sort.Sort(byIdentity(got)) |
| 493 | sort.Sort(byIdentity(expected)) |
| 494 | if !reflect.DeepEqual(got, expected) { |
Robert Kroeger | 8c2be90 | 2015-06-19 15:33:45 -0700 | [diff] [blame] | 495 | t.Errorf("ListAssociations() got %v, expected %v", got, expected) |
Robert Kroeger | 1cb4a0d | 2014-10-20 11:55:38 -0700 | [diff] [blame] | 496 | } |
| 497 | } |
Robert Kroeger | 94ec756 | 2014-10-28 17:58:44 -0700 | [diff] [blame] | 498 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 499 | // GenerateSuidHelperScript builds a script to execute the test target as |
Robert Kroeger | 94ec756 | 2014-10-28 17:58:44 -0700 | [diff] [blame] | 500 | // a suidhelper instance and returns the path to the script. |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 501 | func GenerateSuidHelperScript(t *testing.T, root string) string { |
Robert Kroeger | 94ec756 | 2014-10-28 17:58:44 -0700 | [diff] [blame] | 502 | output := "#!/bin/bash\n" |
Asim Shankar | 3a6ca47 | 2015-03-31 00:35:37 -0700 | [diff] [blame] | 503 | output += "V23_SUIDHELPER_TEST=1" |
Robert Kroeger | 94ec756 | 2014-10-28 17:58:44 -0700 | [diff] [blame] | 504 | output += " " |
Arup Mukherjee | 504a1e6 | 2015-02-25 11:09:56 -0800 | [diff] [blame] | 505 | output += "exec " + os.Args[0] + " -minuid=1 -test.run=TestSuidHelper \"$@\"" |
Robert Kroeger | 94ec756 | 2014-10-28 17:58:44 -0700 | [diff] [blame] | 506 | output += "\n" |
| 507 | |
Cosmos Nicolaou | 1848973 | 2015-06-29 16:01:38 -0700 | [diff] [blame] | 508 | logger.Global().VI(1).Infof("script\n%s", output) |
Robert Kroeger | 94ec756 | 2014-10-28 17:58:44 -0700 | [diff] [blame] | 509 | |
| 510 | if err := os.MkdirAll(root, 0755); err != nil { |
| 511 | t.Fatalf("MkdirAll failed: %v", err) |
| 512 | } |
Robert Kroeger | 94ec756 | 2014-10-28 17:58:44 -0700 | [diff] [blame] | 513 | path := filepath.Join(root, "helper.sh") |
| 514 | if err := ioutil.WriteFile(path, []byte(output), 0755); err != nil { |
| 515 | t.Fatalf("WriteFile(%v) failed: %v", path, err) |
| 516 | } |
| 517 | return path |
| 518 | } |
Bogdan Caprita | c7e72b6 | 2015-01-07 19:22:23 -0800 | [diff] [blame] | 519 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 520 | // GenerateAgentScript creates a simple script that acts as the security agent |
Bogdan Caprita | c7e72b6 | 2015-01-07 19:22:23 -0800 | [diff] [blame] | 521 | // for tests. It blackholes arguments meant for the agent. |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 522 | func GenerateAgentScript(t *testing.T, root string) string { |
Bogdan Caprita | c7e72b6 | 2015-01-07 19:22:23 -0800 | [diff] [blame] | 523 | output := ` |
| 524 | #!/bin/bash |
| 525 | ARGS=$* |
| 526 | for ARG in ${ARGS[@]}; do |
| 527 | if [[ ${ARG} = -- ]]; then |
| 528 | ARGS=(${ARGS[@]/$ARG}) |
| 529 | break |
| 530 | elif [[ ${ARG} == --* ]]; then |
| 531 | ARGS=(${ARGS[@]/$ARG}) |
| 532 | else |
| 533 | break |
| 534 | fi |
| 535 | done |
| 536 | |
| 537 | exec ${ARGS[@]} |
| 538 | ` |
| 539 | if err := os.MkdirAll(root, 0755); err != nil { |
| 540 | t.Fatalf("MkdirAll failed: %v", err) |
| 541 | } |
| 542 | path := filepath.Join(root, "agenthelper.sh") |
| 543 | if err := ioutil.WriteFile(path, []byte(output), 0755); err != nil { |
| 544 | t.Fatalf("WriteFile(%v) failed: %v", path, err) |
| 545 | } |
| 546 | return path |
| 547 | } |
Asim Shankar | b547ea9 | 2015-02-17 18:49:45 -0800 | [diff] [blame] | 548 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 549 | func CtxWithNewPrincipal(t *testing.T, ctx *context.T, idp *testutil.IDProvider, extension string) *context.T { |
Todd Wang | ad49204 | 2015-04-17 15:58:40 -0700 | [diff] [blame] | 550 | ret, err := v23.WithPrincipal(ctx, testutil.NewPrincipal()) |
Asim Shankar | b547ea9 | 2015-02-17 18:49:45 -0800 | [diff] [blame] | 551 | if err != nil { |
Todd Wang | ad49204 | 2015-04-17 15:58:40 -0700 | [diff] [blame] | 552 | t.Fatalf(testutil.FormatLogLine(2, "v23.WithPrincipal failed: %v", err)) |
Asim Shankar | b547ea9 | 2015-02-17 18:49:45 -0800 | [diff] [blame] | 553 | } |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 554 | if err := idp.Bless(v23.GetPrincipal(ret), extension); err != nil { |
Asim Shankar | b547ea9 | 2015-02-17 18:49:45 -0800 | [diff] [blame] | 555 | t.Fatalf(testutil.FormatLogLine(2, "idp.Bless(?, %q) failed: %v", extension, err)) |
| 556 | } |
| 557 | return ret |
| 558 | } |
Robert Kroeger | 6e4ed12 | 2015-03-06 13:03:54 -0800 | [diff] [blame] | 559 | |
| 560 | // TODO(rjkroege): This helper is generally useful. Use it to reduce |
| 561 | // boiler plate across all device manager tests. |
Cosmos Nicolaou | 1848973 | 2015-06-29 16:01:38 -0700 | [diff] [blame] | 562 | func StartupHelper(t *testing.T) (_ func(), ctx *context.T, _ *modules.Shell, _ *application.Envelope, _ string, _ string, _ *testutil.IDProvider) { |
Todd Wang | 60052d8 | 2015-05-22 15:00:10 -0700 | [diff] [blame] | 563 | ctx, shutdown := test.V23Init() |
Robert Kroeger | 6e4ed12 | 2015-03-06 13:03:54 -0800 | [diff] [blame] | 564 | |
| 565 | // Make a new identity context. |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 566 | idp := testutil.NewIDProvider("root") |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 567 | ctx = CtxWithNewPrincipal(t, ctx, idp, "self") |
Robert Kroeger | 6e4ed12 | 2015-03-06 13:03:54 -0800 | [diff] [blame] | 568 | |
Todd Wang | 5fc3644 | 2015-04-07 15:15:27 -0700 | [diff] [blame] | 569 | sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, nil) |
Robert Kroeger | 6e4ed12 | 2015-03-06 13:03:54 -0800 | [diff] [blame] | 570 | |
| 571 | // Set up mock application and binary repositories. |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 572 | envelope, envCleanup := StartMockRepos(t, ctx) |
Robert Kroeger | 6e4ed12 | 2015-03-06 13:03:54 -0800 | [diff] [blame] | 573 | |
Todd Wang | 5fc3644 | 2015-04-07 15:15:27 -0700 | [diff] [blame] | 574 | root, rootCleanup := servicetest.SetupRootDir(t, "devicemanager") |
Bogdan Caprita | 226d88e | 2015-06-30 17:34:57 -0700 | [diff] [blame] | 575 | if err := versioning.SaveCreatorInfo(ctx, root); err != nil { |
Robert Kroeger | 6e4ed12 | 2015-03-06 13:03:54 -0800 | [diff] [blame] | 576 | t.Fatal(err) |
| 577 | } |
| 578 | |
| 579 | // Create a script wrapping the test target that implements suidhelper. |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 580 | helperPath := GenerateSuidHelperScript(t, root) |
Robert Kroeger | 6e4ed12 | 2015-03-06 13:03:54 -0800 | [diff] [blame] | 581 | |
| 582 | return func() { |
| 583 | rootCleanup() |
| 584 | envCleanup() |
| 585 | deferFn() |
| 586 | shutdown() |
| 587 | }, ctx, sh, envelope, root, helperPath, idp |
| 588 | } |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 589 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 590 | type GlobTestVector struct { |
| 591 | Name, Pattern string |
| 592 | Expected []string |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 593 | } |
| 594 | |
| 595 | type globTestRegexHelper struct { |
| 596 | logFileTimeStampRE *regexp.Regexp |
| 597 | logFileTrimInfoRE *regexp.Regexp |
| 598 | logFileRemoveErrorFatalWarningRE *regexp.Regexp |
| 599 | statsTrimRE *regexp.Regexp |
| 600 | } |
| 601 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 602 | func NewGlobTestRegexHelper(appName string) *globTestRegexHelper { |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 603 | return &globTestRegexHelper{ |
| 604 | logFileTimeStampRE: regexp.MustCompile("(STDOUT|STDERR)-[0-9]+$"), |
| 605 | logFileTrimInfoRE: regexp.MustCompile(appName + `\..*\.INFO\.[0-9.-]+$`), |
| 606 | logFileRemoveErrorFatalWarningRE: regexp.MustCompile("(ERROR|FATAL|WARNING)"), |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 607 | statsTrimRE: regexp.MustCompile("/stats/(rpc|system(/start-time.*)?)$"), |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 608 | } |
| 609 | } |
| 610 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 611 | // VerifyGlob verifies that for each GlobTestVector instance that the |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 612 | // pattern returns the expected matches. |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 613 | func VerifyGlob(t *testing.T, ctx *context.T, appName string, testcases []GlobTestVector, res *globTestRegexHelper) { |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 614 | for _, tc := range testcases { |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 615 | results, _, err := testutil.GlobName(ctx, tc.Name, tc.Pattern) |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 616 | if err != nil { |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 617 | t.Errorf(testutil.FormatLogLine(2, "unexpected glob error for (%q, %q): %v", tc.Name, tc.Pattern, err)) |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 618 | continue |
| 619 | } |
| 620 | filteredResults := []string{} |
| 621 | for _, name := range results { |
| 622 | // Keep only the stats object names that match this RE. |
| 623 | if strings.Contains(name, "/stats/") && !res.statsTrimRE.MatchString(name) { |
| 624 | continue |
| 625 | } |
| 626 | // Remove ERROR, WARNING, FATAL log files because |
| 627 | // they're not consistently there. |
| 628 | if res.logFileRemoveErrorFatalWarningRE.MatchString(name) { |
| 629 | continue |
| 630 | } |
| 631 | name = res.logFileTimeStampRE.ReplaceAllString(name, "$1-<timestamp>") |
| 632 | name = res.logFileTrimInfoRE.ReplaceAllString(name, appName+".<*>.INFO.<timestamp>") |
| 633 | filteredResults = append(filteredResults, name) |
| 634 | } |
| 635 | sort.Strings(filteredResults) |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 636 | sort.Strings(tc.Expected) |
| 637 | if !reflect.DeepEqual(filteredResults, tc.Expected) { |
| 638 | t.Errorf(testutil.FormatLogLine(2, "unexpected result for (%q, %q). Got %q, want %q", tc.Name, tc.Pattern, filteredResults, tc.Expected)) |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 639 | } |
| 640 | } |
| 641 | } |
| 642 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 643 | // VerifyFailGlob verifies that for each GlobTestVector instance that the |
Robert Kroeger | 8f914be | 2015-03-14 16:32:37 -0700 | [diff] [blame] | 644 | // pattern returns no matches. |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 645 | func VerifyFailGlob(t *testing.T, ctx *context.T, testcases []GlobTestVector) { |
Robert Kroeger | 8f914be | 2015-03-14 16:32:37 -0700 | [diff] [blame] | 646 | for _, tc := range testcases { |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 647 | results, _, _ := testutil.GlobName(ctx, tc.Name, tc.Pattern) |
Robert Kroeger | 8f914be | 2015-03-14 16:32:37 -0700 | [diff] [blame] | 648 | if len(results) != 0 { |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 649 | t.Errorf(testutil.FormatLogLine(2, "verifyFailGlob should have failed for %q, %q", tc.Name, tc.Pattern)) |
Robert Kroeger | 8f914be | 2015-03-14 16:32:37 -0700 | [diff] [blame] | 650 | } |
| 651 | } |
| 652 | } |
| 653 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 654 | // VerifyLog calls Size() on a selection of log file objects to |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 655 | // demonstrate that the log files are accessible and have been written by |
| 656 | // the application. |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 657 | func VerifyLog(t *testing.T, ctx *context.T, nameComponents ...string) { |
Robert Kroeger | 8f914be | 2015-03-14 16:32:37 -0700 | [diff] [blame] | 658 | a := nameComponents |
| 659 | pattern, prefix := a[len(a)-1], a[:len(a)-1] |
| 660 | path := naming.Join(prefix...) |
| 661 | files, _, err := testutil.GlobName(ctx, path, pattern) |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 662 | if err != nil { |
| 663 | t.Errorf(testutil.FormatLogLine(2, "unexpected glob error: %v", err)) |
| 664 | } |
| 665 | if want, got := 4, len(files); got < want { |
| 666 | t.Errorf(testutil.FormatLogLine(2, "Unexpected number of matches. Got %d, want at least %d", got, want)) |
| 667 | } |
| 668 | for _, file := range files { |
Robert Kroeger | 8f914be | 2015-03-14 16:32:37 -0700 | [diff] [blame] | 669 | name := naming.Join(path, file) |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 670 | c := logreader.LogFileClient(name) |
| 671 | if _, err := c.Size(ctx); err != nil { |
| 672 | t.Errorf(testutil.FormatLogLine(2, "Size(%q) failed: %v", name, err)) |
| 673 | } |
| 674 | } |
| 675 | } |
| 676 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 677 | // VerifyStatsValues call Value() on some of the stats objects to prove |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 678 | // that they are correctly being proxied to the device manager. |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 679 | func VerifyStatsValues(t *testing.T, ctx *context.T, nameComponents ...string) { |
Robert Kroeger | 8f914be | 2015-03-14 16:32:37 -0700 | [diff] [blame] | 680 | a := nameComponents |
| 681 | pattern, prefix := a[len(a)-1], a[:len(a)-1] |
| 682 | path := naming.Join(prefix...) |
| 683 | objects, _, err := testutil.GlobName(ctx, path, pattern) |
| 684 | |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 685 | if err != nil { |
| 686 | t.Errorf(testutil.FormatLogLine(2, "unexpected glob error: %v", err)) |
| 687 | } |
| 688 | if want, got := 2, len(objects); got != want { |
| 689 | t.Errorf(testutil.FormatLogLine(2, "Unexpected number of matches. Got %d, want %d", got, want)) |
| 690 | } |
| 691 | for _, obj := range objects { |
Robert Kroeger | 8f914be | 2015-03-14 16:32:37 -0700 | [diff] [blame] | 692 | name := naming.Join(path, obj) |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 693 | c := stats.StatsClient(name) |
| 694 | if _, err := c.Value(ctx); err != nil { |
| 695 | t.Errorf(testutil.FormatLogLine(2, "Value(%q) failed: %v", name, err)) |
| 696 | } |
| 697 | } |
| 698 | } |
| 699 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 700 | // VerifyPProfCmdLine calls CmdLine() on the pprof object to validate |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 701 | // that it the proxy correctly accessess pprof names. |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 702 | func VerifyPProfCmdLine(t *testing.T, ctx *context.T, appName string, nameComponents ...string) { |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 703 | name := naming.Join(nameComponents...) |
| 704 | c := pprof.PProfClient(name) |
| 705 | v, err := c.CmdLine(ctx) |
| 706 | if err != nil { |
| 707 | t.Errorf(testutil.FormatLogLine(2, "CmdLine(%q) failed: %v", name, err)) |
| 708 | } |
| 709 | if len(v) == 0 { |
Robert Kroeger | 8c2be90 | 2015-06-19 15:33:45 -0700 | [diff] [blame] | 710 | t.Errorf("Unexpected empty cmdline: %v", v) |
Robert Kroeger | 95f4e68 | 2015-03-13 10:40:26 -0700 | [diff] [blame] | 711 | } |
| 712 | if got, want := filepath.Base(v[0]), appName; got != want { |
| 713 | t.Errorf(testutil.FormatLogLine(2, "Unexpected value for argv[0]. Got %v, want %v", got, want)) |
| 714 | } |
| 715 | |
| 716 | } |
Robert Kroeger | 5e27320 | 2015-04-06 16:56:38 -0700 | [diff] [blame] | 717 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 718 | func VerifyNoRunningProcesses(t *testing.T) { |
Robert Kroeger | 5e27320 | 2015-04-06 16:56:38 -0700 | [diff] [blame] | 719 | if impl.RunningChildrenProcesses() { |
| 720 | t.Errorf("device manager incorrectly terminating with child processes still running") |
| 721 | } |
| 722 | } |
Bogdan Caprita | e807368 | 2015-04-25 15:37:53 -0700 | [diff] [blame] | 723 | |
Robert Kroeger | 22fcb03 | 2015-04-30 07:40:11 -0700 | [diff] [blame] | 724 | func SetNamespaceRootsForUnclaimedDevice(ctx *context.T) (*context.T, error) { |
Bogdan Caprita | e807368 | 2015-04-25 15:37:53 -0700 | [diff] [blame] | 725 | origroots := v23.GetNamespace(ctx).Roots() |
| 726 | roots := make([]string, len(origroots)) |
| 727 | for i, orig := range origroots { |
| 728 | addr, suffix := naming.SplitAddressName(orig) |
| 729 | origep, err := v23.NewEndpoint(addr) |
| 730 | if err != nil { |
| 731 | return nil, err |
| 732 | } |
| 733 | ep := naming.FormatEndpoint( |
| 734 | origep.Addr().Network(), |
| 735 | origep.Addr().String(), |
| 736 | origep.RoutingID(), |
| 737 | naming.ServesMountTable(origep.ServesMountTable())) |
| 738 | roots[i] = naming.JoinAddressName(ep, suffix) |
| 739 | } |
Cosmos Nicolaou | 1848973 | 2015-06-29 16:01:38 -0700 | [diff] [blame] | 740 | ctx.Infof("Changing namespace roots from %v to %v", origroots, roots) |
Bogdan Caprita | e807368 | 2015-04-25 15:37:53 -0700 | [diff] [blame] | 741 | ctx, _, err := v23.WithNewNamespace(ctx, roots...) |
| 742 | return ctx, err |
| 743 | } |
Robert Kroeger | ef27d6e | 2015-05-01 16:58:59 -0700 | [diff] [blame] | 744 | |
| 745 | func UserName(t *testing.T) string { |
| 746 | u, err := user.Current() |
| 747 | if err != nil { |
| 748 | t.Fatalf("user.Current() failed: %v", err) |
| 749 | } |
| 750 | return u.Username |
| 751 | } |
Robert Kroeger | 6e2efd9 | 2015-05-01 18:47:28 -0700 | [diff] [blame] | 752 | |
Robert Kroeger | 60e0305 | 2015-05-04 17:35:16 -0700 | [diff] [blame] | 753 | func StartRealBinaryRepository(t *testing.T, ctx *context.T, von string) func() { |
| 754 | rootDir, err := binarylib.SetupRootDir("") |
| 755 | if err != nil { |
| 756 | t.Fatalf("binarylib.SetupRootDir failed: %v", err) |
| 757 | } |
| 758 | state, err := binarylib.NewState(rootDir, "", 3) |
| 759 | if err != nil { |
| 760 | t.Fatalf("binarylib.NewState failed: %v", err) |
| 761 | } |
Cosmos Nicolaou | 7a4221f | 2015-06-21 08:02:23 -0700 | [diff] [blame] | 762 | d, err := binarylib.NewDispatcher(ctx, state) |
Robert Kroeger | 60e0305 | 2015-05-04 17:35:16 -0700 | [diff] [blame] | 763 | if err != nil { |
| 764 | t.Fatalf("server.NewDispatcher failed: %v", err) |
| 765 | } |
Matt Rosencrantz | bb6295d | 2015-06-19 15:13:58 -0700 | [diff] [blame] | 766 | server, err := xrpc.NewDispatchingServer(ctx, von, d) |
| 767 | if err != nil { |
Robert Kroeger | 60e0305 | 2015-05-04 17:35:16 -0700 | [diff] [blame] | 768 | t.Fatalf("server.ServeDispatcher failed: %v", err) |
| 769 | } |
| 770 | return func() { |
| 771 | if err := server.Stop(); err != nil { |
| 772 | t.Fatalf("server.Stop failed: %v", err) |
| 773 | } |
| 774 | if err := os.RemoveAll(rootDir); err != nil { |
| 775 | t.Fatalf("os.RemoveAll(%q) failed: %v", rootDir, err) |
| 776 | } |
| 777 | } |
| 778 | } |
Robert Kroeger | 9e10d4f | 2015-05-07 16:33:04 -0700 | [diff] [blame] | 779 | |
| 780 | func GetPid(t *testing.T, ctx *context.T, appID, instanceID string) int { |
| 781 | name := naming.Join("dm", "apps/"+appID+"/"+instanceID+"/stats/system/pid") |
| 782 | c := stats.StatsClient(name) |
| 783 | v, err := c.Value(ctx) |
| 784 | if err != nil { |
| 785 | t.Fatalf("Value() failed: %v", err) |
| 786 | } |
| 787 | return int(v.Int()) |
| 788 | } |
Robert Kroeger | 4740f88 | 2015-06-11 16:26:13 -0700 | [diff] [blame] | 789 | |
| 790 | // PollingWait polls a given process to make sure that it has exited |
| 791 | // before continuing or fails with a time-out. |
| 792 | func PollingWait(t *testing.T, pid int) { |
| 793 | timeOut := time.After(5 * time.Second) |
| 794 | for syscall.Kill(pid, 0) == nil { |
| 795 | select { |
| 796 | case <-timeOut: |
Robert Kroeger | 8c2be90 | 2015-06-19 15:33:45 -0700 | [diff] [blame] | 797 | syscall.Kill(pid, 9) |
Robert Kroeger | 4740f88 | 2015-06-11 16:26:13 -0700 | [diff] [blame] | 798 | t.Fatalf("Timed out waiting for PID %v to terminate", pid) |
| 799 | case <-time.After(time.Millisecond): |
| 800 | // Try again. |
| 801 | } |
| 802 | } |
| 803 | } |