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 | |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 5 | package modules_test |
| 6 | |
| 7 | import ( |
| 8 | "bufio" |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 9 | "bytes" |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 10 | "fmt" |
| 11 | "io" |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 12 | "io/ioutil" |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 13 | "math/rand" |
Cosmos Nicolaou | 1e78ccc | 2014-10-09 08:10:26 -0700 | [diff] [blame] | 14 | "os" |
Cosmos Nicolaou | d4f0056 | 2014-11-17 20:35:48 -0800 | [diff] [blame] | 15 | "reflect" |
Cosmos Nicolaou | 5339a7b | 2014-11-18 17:28:00 -0800 | [diff] [blame] | 16 | "sort" |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 17 | "strconv" |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 18 | "strings" |
Bogdan Caprita | 490a451 | 2014-11-20 21:12:19 -0800 | [diff] [blame] | 19 | "syscall" |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 20 | "testing" |
| 21 | "time" |
| 22 | |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 23 | "v.io/v23" |
| 24 | |
Jiri Simsa | ffceefa | 2015-02-28 11:03:34 -0800 | [diff] [blame] | 25 | "v.io/x/ref/lib/exec" |
| 26 | execconsts "v.io/x/ref/lib/exec/consts" |
Jiri Simsa | ffceefa | 2015-02-28 11:03:34 -0800 | [diff] [blame] | 27 | "v.io/x/ref/lib/flags/consts" |
Jiri Simsa | ffceefa | 2015-02-28 11:03:34 -0800 | [diff] [blame] | 28 | _ "v.io/x/ref/profiles" |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 29 | vsecurity "v.io/x/ref/security" |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 30 | "v.io/x/ref/test" |
| 31 | "v.io/x/ref/test/modules" |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 32 | "v.io/x/ref/test/testutil" |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 33 | ) |
| 34 | |
Ankur | 9f95794 | 2014-11-24 16:34:18 -0800 | [diff] [blame] | 35 | const credentialsEnvPrefix = "\"" + consts.VeyronCredentials + "=" |
| 36 | |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 37 | func init() { |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 38 | modules.RegisterChild("envtest", "envtest: <variables to print>...", PrintFromEnv) |
| 39 | modules.RegisterChild("printenv", "printenv", PrintEnv) |
Ryan Brown | a08a221 | 2015-01-15 15:40:10 -0800 | [diff] [blame] | 40 | modules.RegisterChild("printblessing", "printblessing", PrintBlessing) |
Cosmos Nicolaou | d4f0056 | 2014-11-17 20:35:48 -0800 | [diff] [blame] | 41 | modules.RegisterChild("echos", "[args]*", Echo) |
| 42 | modules.RegisterChild("errortestChild", "", ErrorMain) |
Bogdan Caprita | 490a451 | 2014-11-20 21:12:19 -0800 | [diff] [blame] | 43 | modules.RegisterChild("ignores_stdin", "", ignoresStdin) |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 44 | modules.RegisterChild("pipeProc", "", pipeEcho) |
| 45 | modules.RegisterChild("lifo", "", lifo) |
Cosmos Nicolaou | d4f0056 | 2014-11-17 20:35:48 -0800 | [diff] [blame] | 46 | |
| 47 | modules.RegisterFunction("envtestf", "envtest: <variables to print>...", PrintFromEnv) |
| 48 | modules.RegisterFunction("echof", "[args]*", Echo) |
| 49 | modules.RegisterFunction("errortestFunc", "", ErrorMain) |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 50 | modules.RegisterFunction("pipeFunc", "", pipeEcho) |
Bogdan Caprita | 490a451 | 2014-11-20 21:12:19 -0800 | [diff] [blame] | 51 | } |
Cosmos Nicolaou | d4f0056 | 2014-11-17 20:35:48 -0800 | [diff] [blame] | 52 | |
Suharsh Sivakumar | d19c95d | 2015-02-19 14:44:50 -0800 | [diff] [blame] | 53 | // We must call Testmain ourselves because using v23 test generate |
| 54 | // creates an import cycle for this package. |
| 55 | func TestMain(m *testing.M) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 56 | test.Init() |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 57 | if modules.IsModulesChildProcess() { |
Suharsh Sivakumar | d19c95d | 2015-02-19 14:44:50 -0800 | [diff] [blame] | 58 | if err := modules.Dispatch(); err != nil { |
| 59 | fmt.Fprintf(os.Stderr, "modules.Dispatch failed: %v\n", err) |
| 60 | os.Exit(1) |
| 61 | } |
| 62 | return |
| 63 | } |
| 64 | os.Exit(m.Run()) |
| 65 | } |
| 66 | |
Bogdan Caprita | 490a451 | 2014-11-20 21:12:19 -0800 | [diff] [blame] | 67 | func ignoresStdin(io.Reader, io.Writer, io.Writer, map[string]string, ...string) error { |
| 68 | <-time.After(time.Minute) |
| 69 | return nil |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 70 | } |
| 71 | |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 72 | func Echo(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error { |
| 73 | for _, a := range args { |
| 74 | fmt.Fprintf(stdout, "stdout: %s\n", a) |
| 75 | fmt.Fprintf(stderr, "stderr: %s\n", a) |
| 76 | } |
| 77 | return nil |
| 78 | } |
| 79 | |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 80 | func pipeEcho(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error { |
| 81 | scanner := bufio.NewScanner(stdin) |
| 82 | for scanner.Scan() { |
| 83 | fmt.Fprintf(stdout, "%p: %s\n", pipeEcho, scanner.Text()) |
| 84 | } |
| 85 | return nil |
| 86 | } |
| 87 | |
| 88 | func lifo(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error { |
| 89 | scanner := bufio.NewScanner(stdin) |
| 90 | scanner.Scan() |
| 91 | msg := scanner.Text() |
| 92 | modules.WaitForEOF(stdin) |
| 93 | fmt.Fprintf(stdout, "%p: %s\n", lifo, msg) |
| 94 | return nil |
| 95 | } |
| 96 | |
Ryan Brown | a08a221 | 2015-01-15 15:40:10 -0800 | [diff] [blame] | 97 | func PrintBlessing(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 98 | ctx, shutdown := test.InitForTest() |
Suharsh Sivakumar | 19fbf99 | 2015-01-23 11:02:27 -0800 | [diff] [blame] | 99 | defer shutdown() |
| 100 | |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 101 | blessing := v23.GetPrincipal(ctx).BlessingStore().Default() |
Ryan Brown | a08a221 | 2015-01-15 15:40:10 -0800 | [diff] [blame] | 102 | fmt.Fprintf(stdout, "%s", blessing) |
| 103 | return nil |
| 104 | } |
| 105 | |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 106 | func PrintFromEnv(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error { |
Suharsh Sivakumar | 9d17e4a | 2015-02-02 22:42:16 -0800 | [diff] [blame] | 107 | for _, a := range args { |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 108 | if v := env[a]; len(v) > 0 { |
Cosmos Nicolaou | 74cc9b2 | 2014-10-23 15:25:35 -0700 | [diff] [blame] | 109 | fmt.Fprintf(stdout, "%s\n", a+"="+v) |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 110 | } else { |
| 111 | fmt.Fprintf(stderr, "missing %s\n", a) |
| 112 | } |
| 113 | } |
| 114 | modules.WaitForEOF(stdin) |
| 115 | fmt.Fprintf(stdout, "done\n") |
| 116 | return nil |
| 117 | } |
| 118 | |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 119 | const printEnvArgPrefix = "PRINTENV_ARG=" |
| 120 | |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 121 | func PrintEnv(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error { |
| 122 | for _, a := range args { |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 123 | fmt.Fprintf(stdout, "%s%s\n", printEnvArgPrefix, a) |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 124 | } |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 125 | for k, v := range env { |
Cosmos Nicolaou | 74cc9b2 | 2014-10-23 15:25:35 -0700 | [diff] [blame] | 126 | fmt.Fprintf(stdout, "%q\n", k+"="+v) |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 127 | } |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 128 | return nil |
| 129 | } |
| 130 | |
Cosmos Nicolaou | 66afced | 2014-09-15 22:12:43 -0700 | [diff] [blame] | 131 | func ErrorMain(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error { |
| 132 | return fmt.Errorf("an error") |
| 133 | } |
| 134 | |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 135 | func waitForInput(scanner *bufio.Scanner) bool { |
| 136 | ch := make(chan struct{}) |
| 137 | go func(ch chan<- struct{}) { |
| 138 | scanner.Scan() |
| 139 | ch <- struct{}{} |
| 140 | }(ch) |
| 141 | select { |
| 142 | case <-ch: |
| 143 | return true |
| 144 | case <-time.After(10 * time.Second): |
| 145 | return false |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | func testCommand(t *testing.T, sh *modules.Shell, name, key, val string) { |
Cosmos Nicolaou | 612ad38 | 2014-10-29 19:41:35 -0700 | [diff] [blame] | 150 | h, err := sh.Start(name, nil, key) |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 151 | if err != nil { |
| 152 | t.Fatalf("unexpected error: %s", err) |
| 153 | } |
| 154 | defer func() { |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 155 | var stdout, stderr bytes.Buffer |
| 156 | sh.Cleanup(&stdout, &stderr) |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 157 | want := "" |
| 158 | if testing.Verbose() { |
| 159 | want = "---- Shell Cleanup ----\n" |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 160 | } |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 161 | if got := stdout.String(); got != "" && got != want { |
| 162 | t.Errorf("got %q, want %q", got, want) |
| 163 | } |
| 164 | if got := stderr.String(); got != "" && got != want { |
| 165 | t.Errorf("got %q, want %q", got, want) |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 166 | } |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 167 | }() |
| 168 | scanner := bufio.NewScanner(h.Stdout()) |
| 169 | if !waitForInput(scanner) { |
| 170 | t.Errorf("timeout") |
| 171 | return |
| 172 | } |
| 173 | if got, want := scanner.Text(), key+"="+val; got != want { |
| 174 | t.Errorf("got %q, want %q", got, want) |
| 175 | } |
Cosmos Nicolaou | 66afced | 2014-09-15 22:12:43 -0700 | [diff] [blame] | 176 | h.CloseStdin() |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 177 | if !waitForInput(scanner) { |
Cosmos Nicolaou | 2cb05fb | 2014-10-23 13:37:32 -0700 | [diff] [blame] | 178 | t.Fatalf("timeout") |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 179 | return |
| 180 | } |
| 181 | if got, want := scanner.Text(), "done"; got != want { |
| 182 | t.Errorf("got %q, want %q", got, want) |
| 183 | } |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 184 | if err := h.Shutdown(nil, nil); err != nil { |
Cosmos Nicolaou | 66afced | 2014-09-15 22:12:43 -0700 | [diff] [blame] | 185 | t.Fatalf("unexpected error: %s", err) |
| 186 | } |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 187 | } |
| 188 | |
Ryan Brown | a08a221 | 2015-01-15 15:40:10 -0800 | [diff] [blame] | 189 | func getBlessing(t *testing.T, sh *modules.Shell, env ...string) string { |
| 190 | h, err := sh.Start("printblessing", env) |
| 191 | if err != nil { |
| 192 | t.Fatalf("unexpected error: %s", err) |
| 193 | } |
| 194 | scanner := bufio.NewScanner(h.Stdout()) |
| 195 | if !waitForInput(scanner) { |
| 196 | t.Errorf("timeout") |
| 197 | return "" |
| 198 | } |
| 199 | return scanner.Text() |
| 200 | } |
| 201 | |
Ryan Brown | 61d6938 | 2015-02-25 11:13:39 -0800 | [diff] [blame] | 202 | func getCustomBlessing(t *testing.T, sh *modules.Shell, creds *modules.CustomCredentials) string { |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 203 | h, err := sh.StartWithOpts(sh.DefaultStartOpts().WithCustomCredentials(creds), nil, "printblessing") |
Ryan Brown | 61d6938 | 2015-02-25 11:13:39 -0800 | [diff] [blame] | 204 | if err != nil { |
| 205 | t.Fatalf("unexpected error: %s", err) |
| 206 | } |
| 207 | scanner := bufio.NewScanner(h.Stdout()) |
| 208 | if !waitForInput(scanner) { |
| 209 | t.Errorf("timeout") |
| 210 | return "" |
| 211 | } |
| 212 | return scanner.Text() |
| 213 | } |
| 214 | |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 215 | func TestChild(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 216 | ctx, shutdown := test.InitForTest() |
Suharsh Sivakumar | 19fbf99 | 2015-01-23 11:02:27 -0800 | [diff] [blame] | 217 | defer shutdown() |
| 218 | |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 219 | sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t) |
Cosmos Nicolaou | 344cc4a | 2014-11-26 15:38:43 -0800 | [diff] [blame] | 220 | if err != nil { |
| 221 | t.Fatalf("unexpected error: %s", err) |
| 222 | } |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 223 | defer sh.Cleanup(nil, nil) |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 224 | key, val := "simpleVar", "foo & bar" |
| 225 | sh.SetVar(key, val) |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 226 | testCommand(t, sh, "envtest", key, val) |
| 227 | } |
| 228 | |
Ryan Brown | a08a221 | 2015-01-15 15:40:10 -0800 | [diff] [blame] | 229 | func TestAgent(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 230 | ctx, shutdown := test.InitForTest() |
Suharsh Sivakumar | 19fbf99 | 2015-01-23 11:02:27 -0800 | [diff] [blame] | 231 | defer shutdown() |
| 232 | |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 233 | sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t) |
Ryan Brown | a08a221 | 2015-01-15 15:40:10 -0800 | [diff] [blame] | 234 | if err != nil { |
| 235 | t.Fatalf("unexpected error: %s", err) |
| 236 | } |
| 237 | defer sh.Cleanup(os.Stdout, os.Stderr) |
| 238 | a := getBlessing(t, sh) |
| 239 | b := getBlessing(t, sh) |
| 240 | if a != b { |
| 241 | t.Errorf("Expected same blessing for children, got %s and %s", a, b) |
| 242 | } |
Ryan Brown | a08a221 | 2015-01-15 15:40:10 -0800 | [diff] [blame] | 243 | } |
| 244 | |
| 245 | func TestCustomPrincipal(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 246 | ctx, shutdown := test.InitForTest() |
Suharsh Sivakumar | 19fbf99 | 2015-01-23 11:02:27 -0800 | [diff] [blame] | 247 | defer shutdown() |
| 248 | |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 249 | p, err := vsecurity.NewPrincipal() |
| 250 | if err != nil { |
| 251 | t.Fatal(err) |
| 252 | } |
| 253 | b, err := p.BlessSelf("myshell") |
| 254 | if err != nil { |
| 255 | t.Fatal(err) |
| 256 | } |
| 257 | if err := vsecurity.SetDefaultBlessings(p, b); err != nil { |
| 258 | t.Fatal(err) |
| 259 | } |
Ryan Brown | a08a221 | 2015-01-15 15:40:10 -0800 | [diff] [blame] | 260 | cleanDebug := p.BlessingStore().DebugString() |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 261 | sh, err := modules.NewShell(ctx, p, testing.Verbose(), t) |
Ryan Brown | a08a221 | 2015-01-15 15:40:10 -0800 | [diff] [blame] | 262 | if err != nil { |
| 263 | t.Fatalf("unexpected error: %s", err) |
| 264 | } |
| 265 | defer sh.Cleanup(os.Stdout, os.Stderr) |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 266 | if got, want := getBlessing(t, sh), "myshell/child"; got != want { |
| 267 | t.Errorf("Bad blessing. Got %q, want %q", got, want) |
Ryan Brown | a08a221 | 2015-01-15 15:40:10 -0800 | [diff] [blame] | 268 | } |
| 269 | newDebug := p.BlessingStore().DebugString() |
| 270 | if cleanDebug != newDebug { |
| 271 | t.Errorf("Shell modified custom principal. Was:\n%q\nNow:\n%q", cleanDebug, newDebug) |
| 272 | } |
| 273 | } |
| 274 | |
Ryan Brown | 61d6938 | 2015-02-25 11:13:39 -0800 | [diff] [blame] | 275 | func TestCustomCredentials(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 276 | ctx, shutdown := test.InitForTest() |
Ryan Brown | 61d6938 | 2015-02-25 11:13:39 -0800 | [diff] [blame] | 277 | defer shutdown() |
| 278 | |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 279 | root := testutil.NewIDProvider("myshell") |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 280 | sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t) |
Ryan Brown | 61d6938 | 2015-02-25 11:13:39 -0800 | [diff] [blame] | 281 | if err != nil { |
| 282 | t.Fatal(err) |
| 283 | } |
| 284 | defer sh.Cleanup(os.Stdout, os.Stderr) |
| 285 | |
| 286 | newCreds := func(ext string) *modules.CustomCredentials { |
| 287 | p, err := sh.NewCustomCredentials() |
| 288 | if err != nil { |
| 289 | t.Fatal(err) |
| 290 | } |
| 291 | b, err := root.NewBlessings(p.Principal(), ext) |
| 292 | if err != nil { |
| 293 | t.Fatal(err) |
| 294 | } |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 295 | if err := vsecurity.SetDefaultBlessings(p.Principal(), b); err != nil { |
| 296 | t.Fatal(err) |
| 297 | } |
Ryan Brown | 61d6938 | 2015-02-25 11:13:39 -0800 | [diff] [blame] | 298 | return p |
| 299 | } |
| 300 | |
| 301 | a := newCreds("a") |
| 302 | cleanDebug := a.Principal().BlessingStore().DebugString() |
| 303 | |
| 304 | blessing := getCustomBlessing(t, sh, a) |
| 305 | if blessing != "myshell/a" { |
| 306 | t.Errorf("Bad blessing. Expected myshell/a, go %q", blessing) |
| 307 | } |
| 308 | |
| 309 | b := newCreds("bar") |
| 310 | blessing = getCustomBlessing(t, sh, b) |
| 311 | if blessing != "myshell/bar" { |
| 312 | t.Errorf("Bad blessing. Expected myshell/bar, go %q", blessing) |
| 313 | } |
| 314 | |
| 315 | // Make sure we can re-use credentials |
| 316 | blessing = getCustomBlessing(t, sh, a) |
| 317 | if blessing != "myshell/a" { |
| 318 | t.Errorf("Bad blessing. Expected myshell/a, go %q", blessing) |
| 319 | } |
| 320 | |
| 321 | newDebug := a.Principal().BlessingStore().DebugString() |
| 322 | if cleanDebug != newDebug { |
| 323 | t.Errorf("Shell modified custom principal. Was:\n%q\nNow:\n%q", cleanDebug, newDebug) |
| 324 | } |
| 325 | } |
| 326 | |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 327 | func createCredentials(blessing string) (string, error) { |
| 328 | dir, err := ioutil.TempDir("", "TestNoAgent_v23_credentials") |
| 329 | if err != nil { |
| 330 | return "", err |
| 331 | } |
| 332 | p, err := vsecurity.CreatePersistentPrincipal(dir, nil) |
| 333 | if err != nil { |
| 334 | os.RemoveAll(dir) |
| 335 | return "", err |
| 336 | } |
| 337 | b, err := p.BlessSelf(blessing) |
| 338 | if err != nil { |
| 339 | os.RemoveAll(dir) |
| 340 | return "", err |
| 341 | } |
| 342 | if err := vsecurity.SetDefaultBlessings(p, b); err != nil { |
| 343 | os.RemoveAll(dir) |
| 344 | return "", err |
| 345 | } |
| 346 | return dir, nil |
| 347 | } |
| 348 | |
Ryan Brown | a08a221 | 2015-01-15 15:40:10 -0800 | [diff] [blame] | 349 | func TestNoAgent(t *testing.T) { |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 350 | const noagent = "noagent" |
| 351 | creds, err := createCredentials(noagent) |
| 352 | if err != nil { |
| 353 | t.Fatal(err) |
| 354 | } |
Ryan Brown | a08a221 | 2015-01-15 15:40:10 -0800 | [diff] [blame] | 355 | defer os.RemoveAll(creds) |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 356 | sh, err := modules.NewShell(nil, nil, testing.Verbose(), t) |
Ryan Brown | a08a221 | 2015-01-15 15:40:10 -0800 | [diff] [blame] | 357 | if err != nil { |
| 358 | t.Fatalf("unexpected error: %s", err) |
| 359 | } |
| 360 | defer sh.Cleanup(os.Stdout, os.Stderr) |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 361 | if got, want := getBlessing(t, sh, fmt.Sprintf("VEYRON_CREDENTIALS=%s", creds)), noagent; got != want { |
| 362 | t.Errorf("Bad blessing. Got %q, want %q", got, want) |
Ryan Brown | a08a221 | 2015-01-15 15:40:10 -0800 | [diff] [blame] | 363 | } |
| 364 | } |
| 365 | |
Cosmos Nicolaou | 1e78ccc | 2014-10-09 08:10:26 -0700 | [diff] [blame] | 366 | func TestChildNoRegistration(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 367 | ctx, shutdown := test.InitForTest() |
Suharsh Sivakumar | 19fbf99 | 2015-01-23 11:02:27 -0800 | [diff] [blame] | 368 | defer shutdown() |
| 369 | |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 370 | sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t) |
Cosmos Nicolaou | 344cc4a | 2014-11-26 15:38:43 -0800 | [diff] [blame] | 371 | if err != nil { |
| 372 | t.Fatalf("unexpected error: %s", err) |
| 373 | } |
Cosmos Nicolaou | 1e78ccc | 2014-10-09 08:10:26 -0700 | [diff] [blame] | 374 | defer sh.Cleanup(os.Stderr, os.Stderr) |
| 375 | key, val := "simpleVar", "foo & bar" |
| 376 | sh.SetVar(key, val) |
| 377 | testCommand(t, sh, "envtest", key, val) |
Cosmos Nicolaou | 344cc4a | 2014-11-26 15:38:43 -0800 | [diff] [blame] | 378 | _, err = sh.Start("non-existent-command", nil, "random", "args") |
Cosmos Nicolaou | d4f0056 | 2014-11-17 20:35:48 -0800 | [diff] [blame] | 379 | if err == nil { |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 380 | fmt.Fprintf(os.Stderr, "Failed: %v\n", err) |
Cosmos Nicolaou | d4f0056 | 2014-11-17 20:35:48 -0800 | [diff] [blame] | 381 | t.Fatalf("expected error") |
Cosmos Nicolaou | 1e78ccc | 2014-10-09 08:10:26 -0700 | [diff] [blame] | 382 | } |
| 383 | } |
| 384 | |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 385 | func TestFunction(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 386 | ctx, shutdown := test.InitForTest() |
Suharsh Sivakumar | 19fbf99 | 2015-01-23 11:02:27 -0800 | [diff] [blame] | 387 | defer shutdown() |
| 388 | |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 389 | sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t) |
Cosmos Nicolaou | 344cc4a | 2014-11-26 15:38:43 -0800 | [diff] [blame] | 390 | if err != nil { |
| 391 | t.Fatalf("unexpected error: %s", err) |
| 392 | } |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 393 | defer sh.Cleanup(nil, nil) |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 394 | key, val := "simpleVar", "foo & bar & baz" |
| 395 | sh.SetVar(key, val) |
Cosmos Nicolaou | 1e78ccc | 2014-10-09 08:10:26 -0700 | [diff] [blame] | 396 | testCommand(t, sh, "envtestf", key, val) |
Cosmos Nicolaou | 6261384 | 2014-08-25 21:57:37 -0700 | [diff] [blame] | 397 | } |
| 398 | |
Cosmos Nicolaou | 66afced | 2014-09-15 22:12:43 -0700 | [diff] [blame] | 399 | func TestErrorChild(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 400 | ctx, shutdown := test.InitForTest() |
Suharsh Sivakumar | 19fbf99 | 2015-01-23 11:02:27 -0800 | [diff] [blame] | 401 | defer shutdown() |
| 402 | |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 403 | sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t) |
Cosmos Nicolaou | 344cc4a | 2014-11-26 15:38:43 -0800 | [diff] [blame] | 404 | if err != nil { |
| 405 | t.Fatalf("unexpected error: %s", err) |
| 406 | } |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 407 | defer sh.Cleanup(nil, nil) |
Cosmos Nicolaou | d4f0056 | 2014-11-17 20:35:48 -0800 | [diff] [blame] | 408 | h, err := sh.Start("errortestChild", nil) |
Cosmos Nicolaou | 66afced | 2014-09-15 22:12:43 -0700 | [diff] [blame] | 409 | if err != nil { |
| 410 | t.Fatalf("unexpected error: %s", err) |
| 411 | } |
Suharsh Sivakumar | d19c95d | 2015-02-19 14:44:50 -0800 | [diff] [blame] | 412 | if got, want := h.Shutdown(nil, nil), "exit status 1"; got == nil || got.Error() != want { |
Cosmos Nicolaou | 66afced | 2014-09-15 22:12:43 -0700 | [diff] [blame] | 413 | t.Errorf("got %q, want %q", got, want) |
| 414 | } |
| 415 | } |
| 416 | |
Cosmos Nicolaou | d4f0056 | 2014-11-17 20:35:48 -0800 | [diff] [blame] | 417 | func testShutdown(t *testing.T, sh *modules.Shell, command string, isfunc bool) { |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 418 | result := "" |
| 419 | args := []string{"a", "b c", "ddd"} |
Cosmos Nicolaou | d4f0056 | 2014-11-17 20:35:48 -0800 | [diff] [blame] | 420 | if _, err := sh.Start(command, nil, args...); err != nil { |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 421 | t.Fatalf("unexpected error: %s", err) |
| 422 | } |
| 423 | var stdoutBuf bytes.Buffer |
| 424 | var stderrBuf bytes.Buffer |
| 425 | sh.Cleanup(&stdoutBuf, &stderrBuf) |
Suharsh Sivakumar | 9d17e4a | 2015-02-02 22:42:16 -0800 | [diff] [blame] | 426 | var stdoutOutput, stderrOutput string |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 427 | for _, a := range args { |
| 428 | stdoutOutput += fmt.Sprintf("stdout: %s\n", a) |
| 429 | stderrOutput += fmt.Sprintf("stderr: %s\n", a) |
| 430 | } |
| 431 | if got, want := stdoutBuf.String(), stdoutOutput+result; got != want { |
| 432 | t.Errorf("got %q want %q", got, want) |
| 433 | } |
Cosmos Nicolaou | 2cb05fb | 2014-10-23 13:37:32 -0700 | [diff] [blame] | 434 | if !isfunc { |
| 435 | stderrBuf.ReadString('\n') // Skip past the random # generator output |
| 436 | } |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 437 | if got, want := stderrBuf.String(), stderrOutput; got != want { |
| 438 | t.Errorf("got %q want %q", got, want) |
| 439 | } |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 440 | } |
| 441 | |
| 442 | func TestShutdownSubprocess(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 443 | ctx, shutdown := test.InitForTest() |
Suharsh Sivakumar | 19fbf99 | 2015-01-23 11:02:27 -0800 | [diff] [blame] | 444 | defer shutdown() |
| 445 | |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 446 | sh, err := modules.NewShell(ctx, nil, false, t) |
Cosmos Nicolaou | 344cc4a | 2014-11-26 15:38:43 -0800 | [diff] [blame] | 447 | if err != nil { |
| 448 | t.Fatalf("unexpected error: %s", err) |
| 449 | } |
Robin Thellend | cf140c0 | 2014-12-08 14:56:24 -0800 | [diff] [blame] | 450 | defer sh.Cleanup(nil, nil) |
Cosmos Nicolaou | 344cc4a | 2014-11-26 15:38:43 -0800 | [diff] [blame] | 451 | testShutdown(t, sh, "echos", false) |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 452 | } |
| 453 | |
Bogdan Caprita | 490a451 | 2014-11-20 21:12:19 -0800 | [diff] [blame] | 454 | // TestShutdownSubprocessIgnoresStdin verifies that Shutdown doesn't wait |
| 455 | // forever if a child does not die upon closing stdin; but instead times out and |
| 456 | // returns an appropriate error. |
| 457 | func TestShutdownSubprocessIgnoresStdin(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 458 | ctx, shutdown := test.InitForTest() |
Suharsh Sivakumar | 19fbf99 | 2015-01-23 11:02:27 -0800 | [diff] [blame] | 459 | defer shutdown() |
| 460 | |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 461 | sh, err := modules.NewShell(ctx, nil, false, t) |
Cosmos Nicolaou | 344cc4a | 2014-11-26 15:38:43 -0800 | [diff] [blame] | 462 | if err != nil { |
| 463 | t.Fatalf("unexpected error: %s", err) |
| 464 | } |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 465 | opts := sh.DefaultStartOpts() |
| 466 | opts.ShutdownTimeout = time.Second |
| 467 | h, err := sh.StartWithOpts(opts, nil, "ignores_stdin") |
Bogdan Caprita | 490a451 | 2014-11-20 21:12:19 -0800 | [diff] [blame] | 468 | if err != nil { |
| 469 | t.Fatalf("unexpected error: %s", err) |
| 470 | } |
| 471 | var stdoutBuf, stderrBuf bytes.Buffer |
| 472 | if err := sh.Cleanup(&stdoutBuf, &stderrBuf); err == nil || err.Error() != exec.ErrTimeout.Error() { |
| 473 | t.Errorf("unexpected error in Cleanup: got %v, want %v", err, exec.ErrTimeout) |
| 474 | } |
| 475 | if err := syscall.Kill(h.Pid(), syscall.SIGINT); err != nil { |
| 476 | t.Errorf("Kill failed: %v", err) |
| 477 | } |
| 478 | } |
| 479 | |
| 480 | // TestStdoutRace exemplifies a potential race between reading from child's |
| 481 | // stdout and closing stdout in Wait (called by Shutdown). |
| 482 | // |
| 483 | // NOTE: triggering the actual --race failure is hard, even if the |
| 484 | // implementation inappropriately sets stdout to the file that is to be closed |
| 485 | // in Wait. |
| 486 | func TestStdoutRace(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 487 | ctx, shutdown := test.InitForTest() |
Suharsh Sivakumar | 19fbf99 | 2015-01-23 11:02:27 -0800 | [diff] [blame] | 488 | defer shutdown() |
| 489 | |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 490 | sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t) |
Cosmos Nicolaou | 344cc4a | 2014-11-26 15:38:43 -0800 | [diff] [blame] | 491 | if err != nil { |
| 492 | t.Fatalf("unexpected error: %s", err) |
| 493 | } |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 494 | opts := sh.DefaultStartOpts() |
| 495 | opts.ShutdownTimeout = time.Second |
| 496 | h, err := sh.StartWithOpts(opts, nil, "ignores_stdin") |
Bogdan Caprita | 490a451 | 2014-11-20 21:12:19 -0800 | [diff] [blame] | 497 | if err != nil { |
| 498 | t.Fatalf("unexpected error: %s", err) |
| 499 | } |
| 500 | ch := make(chan error, 1) |
| 501 | go func() { |
| 502 | buf := make([]byte, 5) |
| 503 | // This will block since the child is not writing anything on |
| 504 | // stdout. |
| 505 | _, err := h.Stdout().Read(buf) |
| 506 | ch <- err |
| 507 | }() |
| 508 | // Give the goroutine above a chance to run, so that we're blocked on |
| 509 | // stdout.Read. |
| 510 | <-time.After(time.Second) |
| 511 | // Cleanup should close stdout, and unblock the goroutine. |
| 512 | sh.Cleanup(nil, nil) |
| 513 | if got, want := <-ch, io.EOF; got != want { |
| 514 | t.Errorf("Expected %v, got %v instead", want, got) |
| 515 | } |
| 516 | |
| 517 | if err := syscall.Kill(h.Pid(), syscall.SIGINT); err != nil { |
| 518 | t.Errorf("Kill failed: %v", err) |
| 519 | } |
| 520 | } |
| 521 | |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 522 | func TestShutdownFunction(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 523 | ctx, shutdown := test.InitForTest() |
Suharsh Sivakumar | 19fbf99 | 2015-01-23 11:02:27 -0800 | [diff] [blame] | 524 | defer shutdown() |
| 525 | |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 526 | sh, err := modules.NewShell(ctx, nil, false, t) |
Cosmos Nicolaou | 344cc4a | 2014-11-26 15:38:43 -0800 | [diff] [blame] | 527 | if err != nil { |
| 528 | t.Fatalf("unexpected error: %s", err) |
| 529 | } |
Robin Thellend | cf140c0 | 2014-12-08 14:56:24 -0800 | [diff] [blame] | 530 | defer sh.Cleanup(nil, nil) |
Cosmos Nicolaou | 344cc4a | 2014-11-26 15:38:43 -0800 | [diff] [blame] | 531 | testShutdown(t, sh, "echof", true) |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 532 | } |
| 533 | |
Cosmos Nicolaou | 66afced | 2014-09-15 22:12:43 -0700 | [diff] [blame] | 534 | func TestErrorFunc(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 535 | ctx, shutdown := test.InitForTest() |
Suharsh Sivakumar | 19fbf99 | 2015-01-23 11:02:27 -0800 | [diff] [blame] | 536 | defer shutdown() |
| 537 | |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 538 | sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t) |
Cosmos Nicolaou | 344cc4a | 2014-11-26 15:38:43 -0800 | [diff] [blame] | 539 | if err != nil { |
| 540 | t.Fatalf("unexpected error: %s", err) |
| 541 | } |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 542 | defer sh.Cleanup(nil, nil) |
Cosmos Nicolaou | d4f0056 | 2014-11-17 20:35:48 -0800 | [diff] [blame] | 543 | h, err := sh.Start("errortestFunc", nil) |
Cosmos Nicolaou | 66afced | 2014-09-15 22:12:43 -0700 | [diff] [blame] | 544 | if err != nil { |
| 545 | t.Fatalf("unexpected error: %s", err) |
| 546 | } |
Cosmos Nicolaou | bbae388 | 2014-10-02 22:58:19 -0700 | [diff] [blame] | 547 | if got, want := h.Shutdown(nil, nil), "an error"; got != nil && got.Error() != want { |
Cosmos Nicolaou | 66afced | 2014-09-15 22:12:43 -0700 | [diff] [blame] | 548 | t.Errorf("got %q, want %q", got, want) |
| 549 | } |
| 550 | } |
| 551 | |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 552 | func find(want string, in []string) bool { |
| 553 | for _, a := range in { |
| 554 | if a == want { |
| 555 | return true |
| 556 | } |
| 557 | } |
| 558 | return false |
| 559 | } |
| 560 | |
| 561 | func TestEnvelope(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 562 | ctx, shutdown := test.InitForTest() |
Suharsh Sivakumar | 19fbf99 | 2015-01-23 11:02:27 -0800 | [diff] [blame] | 563 | defer shutdown() |
| 564 | |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 565 | sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t) |
Cosmos Nicolaou | 344cc4a | 2014-11-26 15:38:43 -0800 | [diff] [blame] | 566 | if err != nil { |
| 567 | t.Fatalf("unexpected error: %s", err) |
| 568 | } |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 569 | defer sh.Cleanup(nil, nil) |
| 570 | sh.SetVar("a", "1") |
| 571 | sh.SetVar("b", "2") |
| 572 | args := []string{"oh", "ah"} |
Cosmos Nicolaou | 612ad38 | 2014-10-29 19:41:35 -0700 | [diff] [blame] | 573 | h, err := sh.Start("printenv", nil, args...) |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 574 | if err != nil { |
| 575 | t.Fatalf("unexpected error: %s", err) |
| 576 | } |
| 577 | scanner := bufio.NewScanner(h.Stdout()) |
| 578 | childArgs, childEnv := []string{}, []string{} |
| 579 | for scanner.Scan() { |
| 580 | o := scanner.Text() |
| 581 | if strings.HasPrefix(o, printEnvArgPrefix) { |
| 582 | childArgs = append(childArgs, strings.TrimPrefix(o, printEnvArgPrefix)) |
| 583 | } else { |
| 584 | childEnv = append(childEnv, o) |
| 585 | } |
| 586 | } |
Cosmos Nicolaou | 2cb05fb | 2014-10-23 13:37:32 -0700 | [diff] [blame] | 587 | shArgs, shEnv := sh.CommandEnvelope("printenv", nil, args...) |
Cosmos Nicolaou | 74cc9b2 | 2014-10-23 15:25:35 -0700 | [diff] [blame] | 588 | for i, ev := range shEnv { |
| 589 | shEnv[i] = fmt.Sprintf("%q", ev) |
| 590 | } |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 591 | for _, want := range args { |
| 592 | if !find(want, childArgs) { |
| 593 | t.Errorf("failed to find %q in %s", want, childArgs) |
| 594 | } |
| 595 | if !find(want, shArgs) { |
| 596 | t.Errorf("failed to find %q in %s", want, shArgs) |
| 597 | } |
| 598 | } |
| 599 | |
| 600 | for _, want := range shEnv { |
| 601 | if !find(want, childEnv) { |
Cosmos Nicolaou | 74cc9b2 | 2014-10-23 15:25:35 -0700 | [diff] [blame] | 602 | t.Errorf("failed to find %s in %#v", want, childEnv) |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 603 | } |
| 604 | } |
Ankur | 9f95794 | 2014-11-24 16:34:18 -0800 | [diff] [blame] | 605 | |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 606 | for _, want := range childEnv { |
Cosmos Nicolaou | a6fef89 | 2015-02-20 23:09:03 -0800 | [diff] [blame] | 607 | if want == "\""+execconsts.ExecVersionVariable+"=\"" { |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 608 | continue |
| 609 | } |
| 610 | if !find(want, shEnv) { |
Cosmos Nicolaou | 74cc9b2 | 2014-10-23 15:25:35 -0700 | [diff] [blame] | 611 | t.Errorf("failed to find %s in %#v", want, shEnv) |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 612 | } |
| 613 | } |
| 614 | } |
| 615 | |
| 616 | func TestEnvMerge(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 617 | ctx, shutdown := test.InitForTest() |
Suharsh Sivakumar | 19fbf99 | 2015-01-23 11:02:27 -0800 | [diff] [blame] | 618 | defer shutdown() |
| 619 | |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 620 | sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t) |
Cosmos Nicolaou | 344cc4a | 2014-11-26 15:38:43 -0800 | [diff] [blame] | 621 | if err != nil { |
| 622 | t.Fatalf("unexpected error: %s", err) |
| 623 | } |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 624 | defer sh.Cleanup(nil, nil) |
| 625 | sh.SetVar("a", "1") |
| 626 | os.Setenv("a", "wrong, should be 1") |
Cosmos Nicolaou | 2cb05fb | 2014-10-23 13:37:32 -0700 | [diff] [blame] | 627 | sh.SetVar("b", "2 also wrong") |
| 628 | os.Setenv("b", "wrong, should be 2") |
Cosmos Nicolaou | 612ad38 | 2014-10-29 19:41:35 -0700 | [diff] [blame] | 629 | h, err := sh.Start("printenv", []string{"b=2"}) |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 630 | if err != nil { |
| 631 | t.Fatalf("unexpected error: %s", err) |
| 632 | } |
| 633 | scanner := bufio.NewScanner(h.Stdout()) |
| 634 | for scanner.Scan() { |
| 635 | o := scanner.Text() |
| 636 | if strings.HasPrefix(o, "a=") { |
| 637 | if got, want := o, "a=1"; got != want { |
Cosmos Nicolaou | 2cb05fb | 2014-10-23 13:37:32 -0700 | [diff] [blame] | 638 | t.Errorf("got: %q, want %q", got, want) |
| 639 | } |
| 640 | } |
| 641 | if strings.HasPrefix(o, "b=") { |
| 642 | if got, want := o, "b=2"; got != want { |
| 643 | t.Errorf("got: %q, want %q", got, want) |
Cosmos Nicolaou | e664f3f | 2014-10-20 17:40:05 -0700 | [diff] [blame] | 644 | } |
| 645 | } |
| 646 | } |
| 647 | } |
| 648 | |
Cosmos Nicolaou | d4f0056 | 2014-11-17 20:35:48 -0800 | [diff] [blame] | 649 | func TestSetEntryPoint(t *testing.T) { |
| 650 | env := map[string]string{"a": "a", "b": "b"} |
| 651 | nenv := modules.SetEntryPoint(env, "eg1") |
| 652 | if got, want := len(nenv), 3; got != want { |
| 653 | t.Errorf("got %d, want %d", got, want) |
| 654 | } |
| 655 | nenv = modules.SetEntryPoint(env, "eg2") |
| 656 | if got, want := len(nenv), 3; got != want { |
| 657 | t.Errorf("got %d, want %d", got, want) |
| 658 | } |
Cosmos Nicolaou | 5339a7b | 2014-11-18 17:28:00 -0800 | [diff] [blame] | 659 | sort.Strings(nenv) |
| 660 | if got, want := nenv, []string{"VEYRON_SHELL_HELPER_PROCESS_ENTRY_POINT=eg2", "a=a", "b=b"}; !reflect.DeepEqual(got, want) { |
Cosmos Nicolaou | d4f0056 | 2014-11-17 20:35:48 -0800 | [diff] [blame] | 661 | t.Errorf("got %d, want %d", got, want) |
| 662 | } |
| 663 | } |
| 664 | |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 665 | func TestNoExec(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 666 | ctx, shutdown := test.InitForTest() |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 667 | defer shutdown() |
| 668 | |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 669 | sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t) |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 670 | if err != nil { |
| 671 | t.Fatalf("unexpected error: %s", err) |
| 672 | } |
| 673 | defer sh.Cleanup(nil, nil) |
| 674 | h, err := sh.StartWithOpts(sh.DefaultStartOpts().NoExecCommand(), nil, "/bin/echo", "hello", "world") |
| 675 | if err != nil { |
| 676 | t.Fatalf("unexpected error: %s", err) |
| 677 | } |
| 678 | scanner := bufio.NewScanner(h.Stdout()) |
| 679 | scanner.Scan() |
| 680 | if got, want := scanner.Text(), "hello world"; got != want { |
| 681 | t.Fatalf("got %v, want %v", got, want) |
| 682 | } |
| 683 | } |
| 684 | |
| 685 | func TestExternal(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 686 | ctx, shutdown := test.InitForTest() |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 687 | defer shutdown() |
| 688 | |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 689 | sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t) |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 690 | if err != nil { |
| 691 | t.Fatalf("unexpected error: %s", err) |
| 692 | } |
| 693 | defer sh.Cleanup(nil, nil) |
| 694 | cookie := strconv.Itoa(rand.Int()) |
| 695 | sh.SetConfigKey("cookie", cookie) |
| 696 | h, err := sh.StartWithOpts(sh.DefaultStartOpts().ExternalCommand(), nil, os.Args[0], "--test.run=TestExternalTestHelper") |
| 697 | if err != nil { |
| 698 | t.Fatalf("unexpected error: %s", err) |
| 699 | } |
| 700 | scanner := bufio.NewScanner(h.Stdout()) |
| 701 | scanner.Scan() |
| 702 | if got, want := scanner.Text(), fmt.Sprintf("cookie: %s", cookie); got != want { |
| 703 | h.Shutdown(os.Stderr, os.Stderr) |
| 704 | t.Fatalf("got %v, want %v", got, want) |
| 705 | } |
| 706 | } |
| 707 | |
| 708 | // TestExternalTestHelper is used by TestExternal above and has not utility |
| 709 | // as a test in it's own right. |
| 710 | func TestExternalTestHelper(t *testing.T) { |
| 711 | child, err := exec.GetChildHandle() |
| 712 | if err != nil { |
| 713 | return |
| 714 | } |
| 715 | child.SetReady() |
| 716 | val, err := child.Config.Get("cookie") |
| 717 | if err != nil { |
| 718 | t.Fatalf("failed to get child handle: %s", err) |
| 719 | } |
| 720 | fmt.Printf("cookie: %s\n", val) |
| 721 | } |
| 722 | |
| 723 | func TestPipe(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 724 | ctx, shutdown := test.InitForTest() |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 725 | defer shutdown() |
| 726 | |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 727 | sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t) |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 728 | if err != nil { |
| 729 | t.Fatalf("unexpected error: %s", err) |
| 730 | } |
| 731 | defer sh.Cleanup(nil, nil) |
| 732 | |
| 733 | for _, cmd := range []string{"pipeProc", "pipeFunc"} { |
| 734 | r, w, err := os.Pipe() |
| 735 | if err != nil { |
| 736 | t.Fatal(err) |
| 737 | } |
| 738 | opts := sh.DefaultStartOpts() |
| 739 | opts.Stdin = r |
| 740 | h, err := sh.StartWithOpts(opts, nil, cmd) |
| 741 | if err != nil { |
| 742 | t.Fatal(err) |
| 743 | } |
| 744 | cookie := strconv.Itoa(rand.Int()) |
| 745 | go func(w *os.File, s string) { |
| 746 | fmt.Fprintf(w, "hello world\n") |
| 747 | fmt.Fprintf(w, "%s\n", s) |
| 748 | w.Close() |
| 749 | }(w, cookie) |
| 750 | |
| 751 | scanner := bufio.NewScanner(h.Stdout()) |
| 752 | want := []string{ |
| 753 | fmt.Sprintf("%p: hello world", pipeEcho), |
| 754 | fmt.Sprintf("%p: %s", pipeEcho, cookie), |
| 755 | } |
| 756 | i := 0 |
| 757 | for scanner.Scan() { |
| 758 | if got, want := scanner.Text(), want[i]; got != want { |
| 759 | t.Fatalf("%s: got %v, want %v", cmd, got, want) |
| 760 | } |
| 761 | i++ |
| 762 | } |
| 763 | if got, want := i, 2; got != want { |
| 764 | t.Fatalf("%s: got %v, want %v", cmd, got, want) |
| 765 | } |
| 766 | if err := h.Shutdown(os.Stderr, os.Stderr); err != nil { |
| 767 | t.Fatal(err) |
| 768 | } |
| 769 | r.Close() |
| 770 | } |
| 771 | } |
| 772 | |
| 773 | func TestLIFO(t *testing.T) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 774 | ctx, shutdown := test.InitForTest() |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 775 | defer shutdown() |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 776 | sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t) |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 777 | if err != nil { |
| 778 | t.Fatalf("unexpected error: %s", err) |
| 779 | } |
| 780 | defer sh.Cleanup(nil, nil) |
| 781 | |
| 782 | cases := []string{"a", "b", "c"} |
| 783 | for _, msg := range cases { |
| 784 | h, err := sh.Start("lifo", nil) |
| 785 | if err != nil { |
| 786 | t.Fatal(err) |
| 787 | } |
| 788 | fmt.Fprintf(h.Stdin(), "%s\n", msg) |
| 789 | } |
| 790 | var buf bytes.Buffer |
| 791 | if err := sh.Cleanup(&buf, nil); err != nil { |
| 792 | t.Fatal(err) |
| 793 | } |
| 794 | lines := strings.Split(strings.TrimRight(buf.String(), "\n"), "\n") |
| 795 | if got, want := len(lines), len(cases); got != want { |
| 796 | t.Fatalf("got %v, want %v", got, want) |
| 797 | } |
| 798 | sort.Sort(sort.Reverse(sort.StringSlice(cases))) |
| 799 | for i, msg := range cases { |
| 800 | if got, want := lines[i], fmt.Sprintf("%p: %s", lifo, msg); got != want { |
| 801 | t.Fatalf("got %v, want %v", got, want) |
| 802 | } |
| 803 | } |
| 804 | } |
| 805 | |
| 806 | func TestStartOpts(t *testing.T) { |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 807 | sh, err := modules.NewShell(nil, nil, testing.Verbose(), t) |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 808 | if err != nil { |
| 809 | t.Fatalf("unexpected error: %s", err) |
| 810 | } |
| 811 | opts := modules.StartOpts{ |
| 812 | External: true, |
| 813 | } |
| 814 | sh.SetDefaultStartOpts(opts) |
| 815 | def := sh.DefaultStartOpts() |
| 816 | if got, want := def.External, opts.External; got != want { |
| 817 | t.Fatalf("got %v, want %v", got, want) |
| 818 | } |
| 819 | def.External = false |
| 820 | if got, want := def, (modules.StartOpts{}); !reflect.DeepEqual(got, want) { |
| 821 | t.Fatalf("got %v, want %v", got, want) |
| 822 | } |
| 823 | |
| 824 | // Verify that the shell retains a copy. |
| 825 | opts.External = false |
| 826 | opts.ExecProtocol = true |
| 827 | def = sh.DefaultStartOpts() |
| 828 | if got, want := def.External, true; got != want { |
| 829 | t.Fatalf("got %v, want %v", got, want) |
| 830 | } |
| 831 | if got, want := def.ExecProtocol, false; got != want { |
| 832 | t.Fatalf("got %v, want %v", got, want) |
| 833 | } |
| 834 | |
| 835 | sh.SetDefaultStartOpts(opts) |
| 836 | def = sh.DefaultStartOpts() |
| 837 | if got, want := def.ExecProtocol, true; got != want { |
| 838 | t.Fatalf("got %v, want %v", got, want) |
| 839 | } |
| 840 | } |
| 841 | |
| 842 | func TestEmbeddedSession(t *testing.T) { |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 843 | sh, err := modules.NewShell(nil, nil, testing.Verbose(), t) |
Cosmos Nicolaou | 42a1736 | 2015-03-10 16:40:18 -0700 | [diff] [blame] | 844 | if err != nil { |
| 845 | t.Fatalf("unexpected error: %s", err) |
| 846 | } |
| 847 | def := sh.DefaultStartOpts() |
| 848 | if def.ExpectTesting == nil { |
| 849 | t.Fatalf("ExpectTesting should be non nil") |
| 850 | } |
| 851 | } |
Cosmos Nicolaou | 52e9a22 | 2015-03-16 21:57:16 -0700 | [diff] [blame] | 852 | |
| 853 | func TestCredentialsAndNoExec(t *testing.T) { |
| 854 | ctx, shutdown := test.InitForTest() |
| 855 | defer shutdown() |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 856 | sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t) |
Cosmos Nicolaou | 52e9a22 | 2015-03-16 21:57:16 -0700 | [diff] [blame] | 857 | if err != nil { |
| 858 | t.Fatalf("unexpected error: %s", err) |
| 859 | } |
| 860 | opts := sh.DefaultStartOpts() |
| 861 | opts = opts.NoExecCommand() |
| 862 | creds, err := sh.NewCustomCredentials() |
| 863 | if err != nil { |
| 864 | t.Fatalf("unexpected error: %s", err) |
| 865 | } |
| 866 | opts = opts.WithCustomCredentials(creds) |
| 867 | h, err := sh.StartWithOpts(opts, nil, "echos", "a") |
| 868 | |
| 869 | if got, want := err, modules.ErrNoExecAndCustomCreds; got != want { |
| 870 | t.Fatalf("got %v, want %v", got, want) |
| 871 | } |
| 872 | if got, want := h, modules.Handle(nil); got != want { |
| 873 | t.Fatalf("got %v, want %v", got, want) |
| 874 | } |
| 875 | } |