From 776aa80ba133b03eee6856deacee3ab7f539eb41 Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Fri, 24 Apr 2015 11:17:21 +0200 Subject: [PATCH 01/13] functional tests: Add rkt run context This context manages rkt's data directory, local and system configuration directories. They are by default placed somewhere in /tmp dir. The context also provides basic rkt command to call, so rkt uses those directories instead of default ones. With this context tests do not have to be destructive - they can be self-contained. --- tests/rkt_tests.go | 124 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 117 insertions(+), 7 deletions(-) diff --git a/tests/rkt_tests.go b/tests/rkt_tests.go index 97c9e8a..ac6a1e1 100644 --- a/tests/rkt_tests.go +++ b/tests/rkt_tests.go @@ -16,8 +16,10 @@ package main import ( "fmt" + "io/ioutil" "os" "os/exec" + "strings" "testing" ) @@ -29,17 +31,125 @@ func skipDestructive(t *testing.T) { } } -func removeDataDir(t *testing.T) { - if !destructiveTestsEnabled() { - panic("Trying to remove datadir when destructive tests are disabled") +func destructiveTestsEnabled() bool { + return os.Getenv(enableDestructiveTestsEnvVar) == "1" +} + +// dirDesc structure manages one directory and provides an option for +// rkt invocations +type dirDesc struct { + dir string // directory path + desc string // directory description, mostly for failure cases + prefix string // temporary directory prefix + option string // rkt option for given directory +} + +// newDirDesc creates dirDesc instance managing a temporary directory. +func newDirDesc(prefix, desc, option string) *dirDesc { + dir := &dirDesc{ + dir: "", + desc: desc, + prefix: prefix, + option: option, } - if err := os.RemoveAll("/var/lib/rkt"); err != nil { - t.Fatalf("Failed to remove /var/lib/rkt: %v", err) + dir.reset() + return dir +} + +// reset removes the managed directory and recreates it +func (d *dirDesc) reset() { + d.cleanup() + dir, err := ioutil.TempDir("", d.prefix) + if err != nil { + panic(fmt.Sprintf("Failed to create temporary %s directory: %v", d.desc, err)) + } + d.dir = dir +} + +// cleanup removes the managed directory. After cleanup this instance +// cannot be used for anything, until it is reset. +func (d *dirDesc) cleanup() { + if d.dir == "" { + return + } + if err := os.RemoveAll(d.dir); err != nil { + panic(fmt.Sprintf("Failed to remove temporary %s directory %q: %s", d.desc, d.dir, err)) + } + d.dir = "" +} + +// rktOption returns option for rkt invocation +func (d *dirDesc) rktOption() string { + d.ensureValid() + return fmt.Sprintf("--%s='%s'", d.option, d.dir) +} + +func (d *dirDesc) ensureValid() { + if d.dir == "" { + panic(fmt.Sprintf("A temporary %s directory is not set up", d.desc)) } } -func destructiveTestsEnabled() bool { - return os.Getenv(enableDestructiveTestsEnvVar) == "1" +type rktRunCtx struct { + directories []*dirDesc + useDefaults bool +} + +func newRktRunCtx() *rktRunCtx { + return &rktRunCtx{ + directories: []*dirDesc{ + newDirDesc("datadir-", "data", "dir"), + newDirDesc("localdir-", "local configuration", "local-config"), + newDirDesc("systemdir-", "system configuration", "system-config"), + }, + } +} + +func (ctx *rktRunCtx) dataDir() string { + return ctx.dir(0) +} + +func (ctx *rktRunCtx) localDir() string { + return ctx.dir(1) +} + +func (ctx *rktRunCtx) systemDir() string { + return ctx.dir(2) +} + +func (ctx *rktRunCtx) dir(idx int) string { + ctx.ensureValid() + if idx < len(ctx.directories) { + return ctx.directories[idx].dir + } + panic("Directory index out of bounds") +} + +func (ctx *rktRunCtx) reset() { + for _, d := range ctx.directories { + d.reset() + } +} + +func (ctx *rktRunCtx) cleanup() { + for _, d := range ctx.directories { + d.cleanup() + } +} + +func (ctx *rktRunCtx) cmd() string { + ctx.ensureValid() + opts := make([]string, 0, len(ctx.directories)) + for _, d := range ctx.directories { + opts = append(opts, d.rktOption()) + } + return fmt.Sprintf("../bin/rkt %s", strings.Join(opts, " ")) +} + +func (ctx *rktRunCtx) ensureValid() { + for _, d := range ctx.directories { + d.ensureValid() + } } func patchTestACI(newFileName string, args ...string) { From 68bb9a923edfdc06f3077b77e0f7f0b1fc75506f Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Fri, 24 Apr 2015 11:18:20 +0200 Subject: [PATCH 02/13] functional tests: Port auth tests to rkt run context --- tests/rkt_auth_test.go | 127 +++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 82 deletions(-) diff --git a/tests/rkt_auth_test.go b/tests/rkt_auth_test.go index 04f9339..7667023 100644 --- a/tests/rkt_auth_test.go +++ b/tests/rkt_auth_test.go @@ -23,16 +23,15 @@ import ( "testing" "github.com/coreos/rkt/Godeps/_workspace/src/github.com/ThomasRooney/gexpect" - "github.com/coreos/rkt/common" taas "github.com/coreos/rkt/tests/test-auth-server/aci" ) func TestAuthSanity(t *testing.T) { - skipDestructive(t) - removeDataDir(t) + ctx := newRktRunCtx() + defer ctx.cleanup() server := runServer(t, taas.None) defer server.Close() - successfulRunRkt(t, server.URL, "sanity") + expectedRunRkt(ctx, t, server.URL, "sanity", authSuccessfulDownload) } const ( @@ -50,8 +49,8 @@ type genericAuthTest struct { func TestAuthBasic(t *testing.T) { tests := []genericAuthTest{ {"basic-no-config", false, "", authFailedDownload}, - {"basic-local-config", true, common.DefaultLocalConfigDir, authSuccessfulDownload}, - {"basic-system-config", true, common.DefaultSystemConfigDir, authSuccessfulDownload}, + {"basic-local-config", true, "local", authSuccessfulDownload}, + {"basic-system-config", true, "system", authSuccessfulDownload}, } testAuthGeneric(t, taas.Basic, tests) } @@ -59,31 +58,36 @@ func TestAuthBasic(t *testing.T) { func TestAuthOauth(t *testing.T) { tests := []genericAuthTest{ {"oauth-no-config", false, "", authFailedDownload}, - {"oauth-local-config", true, common.DefaultLocalConfigDir, authSuccessfulDownload}, - {"oauth-system-config", true, common.DefaultSystemConfigDir, authSuccessfulDownload}, + {"oauth-local-config", true, "local", authSuccessfulDownload}, + {"oauth-system-config", true, "system", authSuccessfulDownload}, } testAuthGeneric(t, taas.Oauth, tests) } func testAuthGeneric(t *testing.T, auth taas.Type, tests []genericAuthTest) { - skipDestructive(t) - removeDataDir(t) - defer removeAllConfig(t) server := runServer(t, auth) defer server.Close() + ctx := newRktRunCtx() + defer ctx.cleanup() for _, tt := range tests { - removeAllConfig(t) if tt.useServerConf { - writeConfig(t, tt.confDir, "test.json", server.Conf) + switch tt.confDir { + case "local": + writeConfig(t, ctx.localDir(), "test.json", server.Conf) + case "system": + writeConfig(t, ctx.systemDir(), "test.json", server.Conf) + default: + panic("Wrong config directory") + } } - expectedRunRkt(t, server.URL, tt.name, tt.expectedLine) + expectedRunRkt(ctx, t, server.URL, tt.name, tt.expectedLine) + ctx.reset() } } func TestAuthOverride(t *testing.T) { - skipDestructive(t) - removeDataDir(t) - defer removeAllConfig(t) + ctx := newRktRunCtx() + defer ctx.cleanup() server := runServer(t, taas.Oauth) defer server.Close() tests := []struct { @@ -97,18 +101,15 @@ func TestAuthOverride(t *testing.T) { {getInvalidOAuthConfig(server.Conf), server.Conf, "invalid-system-valid-local", authFailedDownload, authSuccessfulDownload}, } for _, tt := range tests { - removeAllConfig(t) - writeSystemConfig(t, "test.json", tt.systemConfig) - expectedRunRkt(t, server.URL, tt.name+"-1", tt.resultBeforeOverride) - writeLocalConfig(t, "test.json", tt.localConfig) - expectedRunRkt(t, server.URL, tt.name+"-2", tt.resultAfterOverride) + writeConfig(t, ctx.systemDir(), "test.json", tt.systemConfig) + expectedRunRkt(ctx, t, server.URL, tt.name+"-1", tt.resultBeforeOverride) + writeConfig(t, ctx.localDir(), "test.json", tt.localConfig) + expectedRunRkt(ctx, t, server.URL, tt.name+"-2", tt.resultAfterOverride) + ctx.reset() } } func TestAuthIgnore(t *testing.T) { - skipDestructive(t) - removeDataDir(t) - defer removeAllConfig(t) server := runServer(t, taas.Oauth) defer server.Close() testAuthIgnoreBogusFiles(t, server) @@ -116,21 +117,23 @@ func TestAuthIgnore(t *testing.T) { } func testAuthIgnoreBogusFiles(t *testing.T, server *taas.Server) { - removeAllConfig(t) - writeSystemConfig(t, "README", "This is system config") - writeLocalConfig(t, "README", "This is local config") - writeSystemConfig(t, "test.notjson", server.Conf) - writeLocalConfig(t, "test.notjson", server.Conf) - failedRunRkt(t, server.URL, "oauth-bogus-files") + ctx := newRktRunCtx() + defer ctx.cleanup() + writeConfig(t, ctx.systemDir(), "README", "This is system config") + writeConfig(t, ctx.localDir(), "README", "This is local config") + writeConfig(t, ctx.systemDir(), "test.notjson", server.Conf) + writeConfig(t, ctx.localDir(), "test.notjson", server.Conf) + expectedRunRkt(ctx, t, server.URL, "oauth-bogus-files", authFailedDownload) } func testAuthIgnoreSubdirectories(t *testing.T, server *taas.Server) { - removeAllConfig(t) - localSubdir := filepath.Join(common.DefaultLocalConfigDir, "subdir") - systemSubdir := filepath.Join(common.DefaultSystemConfigDir, "subdir") + ctx := newRktRunCtx() + defer ctx.cleanup() + localSubdir := filepath.Join(ctx.localDir(), "subdir") + systemSubdir := filepath.Join(ctx.systemDir(), "subdir") writeConfig(t, localSubdir, "test.json", server.Conf) writeConfig(t, systemSubdir, "test.json", server.Conf) - failedRunRkt(t, server.URL, "oauth-subdirectories") + expectedRunRkt(ctx, t, server.URL, "oauth-subdirectories", authFailedDownload) } func runServer(t *testing.T, auth taas.Type) *taas.Server { @@ -153,61 +156,21 @@ func serverHandler(t *testing.T, server *taas.Server) { } } -func successfulRunRkt(t *testing.T, host, dir string) { - expectedRunRkt(t, host, dir, authSuccessfulDownload) -} - -func failedRunRkt(t *testing.T, host, dir string) { - expectedRunRkt(t, host, dir, authFailedDownload) -} - -func expectedRunRkt(t *testing.T, host, dir, line string) { - child := runRkt(t, host, dir) - defer child.Wait() - if err := child.Expect(line); err != nil { - t.Fatalf("Didn't receive expected output %q", line) - } -} - -// TODO (krnowak): Use --dir option when we also add -// --system-config-dir and --local-config-dir options. Then we can -// remove destructive tests checks. - -// runRkt tries to fetch and run a prog.aci from host within given -// directory on host. Note that directory can be anything - it's +// expectedRunRkt tries to fetch and run a prog.aci from host within +// given directory on host. Note that directory can be anything - it's // useful for ensuring that image name is unique and for descriptive // purposes. -func runRkt(t *testing.T, host, dir string) *gexpect.ExpectSubprocess { - cmd := fmt.Sprintf(`../bin/rkt --debug --insecure-skip-verify run %s/%s/prog.aci`, host, dir) +func expectedRunRkt(ctx *rktRunCtx, t *testing.T, host, dir, line string) { + cmd := fmt.Sprintf(`%s --debug --insecure-skip-verify run %s/%s/prog.aci`, ctx.cmd(), host, dir) t.Logf("Running rkt: %s", cmd) child, err := gexpect.Spawn(cmd) if err != nil { t.Fatalf("Failed to run rkt: %v", err) } - return child -} - -func removeAllConfig(t *testing.T) { - dirs := []string{ - authDir(common.DefaultLocalConfigDir), - authDir(common.DefaultSystemConfigDir), + defer child.Wait() + if err := child.Expect(line); err != nil { + t.Fatalf("Didn't receive expected output %q", line) } - for _, p := range dirs { - if err := os.RemoveAll(p); err != nil { - t.Fatalf("Failed to remove config directory %q: %v", p, err) - } - if err := os.MkdirAll(p, 0755); err != nil { - t.Fatalf("Failed to create config directory %q: %v", p, err) - } - } -} - -func writeLocalConfig(t *testing.T, filename, contents string) { - writeConfig(t, common.DefaultLocalConfigDir, filename, contents) -} - -func writeSystemConfig(t *testing.T, filename, contents string) { - writeConfig(t, common.DefaultSystemConfigDir, filename, contents) } func writeConfig(t *testing.T, baseDir, filename, contents string) { From 493b30d5b6b9e3fdd6a36baffbeebc23250f27e9 Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Mon, 27 Apr 2015 13:01:42 +0200 Subject: [PATCH 03/13] functional tests: Port exit tests to rkt run context --- tests/rkt_exit_test.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/rkt_exit_test.go b/tests/rkt_exit_test.go index 3d21bef..318347b 100644 --- a/tests/rkt_exit_test.go +++ b/tests/rkt_exit_test.go @@ -15,6 +15,7 @@ package main import ( + "fmt" "os" "strings" "testing" @@ -25,8 +26,10 @@ import ( func TestSuccess(t *testing.T) { patchTestACI("rkt-inspect-exit0.aci", "--exec=/inspect --print-msg=Hello --exit-code=0") defer os.Remove("rkt-inspect-exit0.aci") + ctx := newRktRunCtx() + defer ctx.cleanup() - child, err := gexpect.Spawn("../bin/rkt --debug --insecure-skip-verify run ./rkt-inspect-exit0.aci") + child, err := gexpect.Spawn(fmt.Sprintf("%s --debug --insecure-skip-verify run ./rkt-inspect-exit0.aci", ctx.cmd())) if err != nil { t.Fatalf("Cannot exec rkt") } @@ -55,8 +58,10 @@ func TestSuccess(t *testing.T) { func TestFailure(t *testing.T) { patchTestACI("rkt-inspect-exit20.aci", "--exec=/inspect --print-msg=Hello --exit-code=20") defer os.Remove("rkt-inspect-exit20.aci") + ctx := newRktRunCtx() + defer ctx.cleanup() - child, err := gexpect.Spawn("../bin/rkt --debug --insecure-skip-verify run ./rkt-inspect-exit20.aci") + child, err := gexpect.Spawn(fmt.Sprintf("%s --debug --insecure-skip-verify run ./rkt-inspect-exit20.aci", ctx.cmd())) if err != nil { t.Fatalf("Cannot exec rkt") } From ec857f6ed471e875da62750eb479792f338a37c4 Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Mon, 27 Apr 2015 13:10:58 +0200 Subject: [PATCH 04/13] functional tests: Port env tests to rkt run context --- tests/rkt_env_test.go | 55 ++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/tests/rkt_env_test.go b/tests/rkt_env_test.go index 2c3bdec..6bebbbb 100644 --- a/tests/rkt_env_test.go +++ b/tests/rkt_env_test.go @@ -16,6 +16,7 @@ package main import ( "os" + "strings" "testing" "github.com/coreos/rkt/Godeps/_workspace/src/github.com/ThomasRooney/gexpect" @@ -28,40 +29,40 @@ var envTests = []struct { enterCmd string }{ { - `../bin/rkt --debug --insecure-skip-verify run ./rkt-inspect-print-var-from-manifest.aci`, + `^RKT_BIN^ --debug --insecure-skip-verify run ./rkt-inspect-print-var-from-manifest.aci`, "VAR_FROM_MANIFEST=manifest", - `../bin/rkt --debug --insecure-skip-verify run ./rkt-inspect-sleep.aci`, - `/bin/sh -c "../bin/rkt --debug enter $(../bin/rkt list --full|grep running|awk '{print $1}') /inspect --print-env=VAR_FROM_MANIFEST"`, + `^RKT_BIN^ --debug --insecure-skip-verify run ./rkt-inspect-sleep.aci`, + `/bin/sh -c "^RKT_BIN^ --debug enter $(^RKT_BIN^ list --full|grep running|awk '{print $1}') /inspect --print-env=VAR_FROM_MANIFEST"`, }, { - `../bin/rkt --debug --insecure-skip-verify run --set-env=VAR_OTHER=setenv ./rkt-inspect-print-var-other.aci`, + `^RKT_BIN^ --debug --insecure-skip-verify run --set-env=VAR_OTHER=setenv ./rkt-inspect-print-var-other.aci`, "VAR_OTHER=setenv", - `../bin/rkt --debug --insecure-skip-verify run --set-env=VAR_OTHER=setenv ./rkt-inspect-sleep.aci`, - `/bin/sh -c "../bin/rkt --debug enter $(../bin/rkt list --full|grep running|awk '{print $1}') /inspect --print-env=VAR_OTHER"`, + `^RKT_BIN^ --debug --insecure-skip-verify run --set-env=VAR_OTHER=setenv ./rkt-inspect-sleep.aci`, + `/bin/sh -c "^RKT_BIN^ --debug enter $(^RKT_BIN^ list --full|grep running|awk '{print $1}') /inspect --print-env=VAR_OTHER"`, }, { - `../bin/rkt --debug --insecure-skip-verify run --set-env=VAR_FROM_MANIFEST=setenv ./rkt-inspect-print-var-from-manifest.aci`, + `^RKT_BIN^ --debug --insecure-skip-verify run --set-env=VAR_FROM_MANIFEST=setenv ./rkt-inspect-print-var-from-manifest.aci`, "VAR_FROM_MANIFEST=setenv", - `../bin/rkt --debug --insecure-skip-verify run --set-env=VAR_FROM_MANIFEST=setenv ./rkt-inspect-sleep.aci`, - `/bin/sh -c "../bin/rkt --debug enter $(../bin/rkt list --full|grep running|awk '{print $1}') /inspect --print-env=VAR_FROM_MANIFEST"`, + `^RKT_BIN^ --debug --insecure-skip-verify run --set-env=VAR_FROM_MANIFEST=setenv ./rkt-inspect-sleep.aci`, + `/bin/sh -c "^RKT_BIN^ --debug enter $(^RKT_BIN^ list --full|grep running|awk '{print $1}') /inspect --print-env=VAR_FROM_MANIFEST"`, }, { - `/bin/sh -c "export VAR_OTHER=host ; ../bin/rkt --debug --insecure-skip-verify run --inherit-env=true ./rkt-inspect-print-var-other.aci"`, + `/bin/sh -c "export VAR_OTHER=host ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true ./rkt-inspect-print-var-other.aci"`, "VAR_OTHER=host", - `/bin/sh -c "export VAR_OTHER=host ; ../bin/rkt --debug --insecure-skip-verify run --inherit-env=true ./rkt-inspect-sleep.aci"`, - `/bin/sh -c "export VAR_OTHER=host ; ../bin/rkt --debug enter $(../bin/rkt list --full|grep running|awk '{print $1}') /inspect --print-env=VAR_OTHER"`, + `/bin/sh -c "export VAR_OTHER=host ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true ./rkt-inspect-sleep.aci"`, + `/bin/sh -c "export VAR_OTHER=host ; ^RKT_BIN^ --debug enter $(^RKT_BIN^ list --full|grep running|awk '{print $1}') /inspect --print-env=VAR_OTHER"`, }, { - `/bin/sh -c "export VAR_FROM_MANIFEST=host ; ../bin/rkt --debug --insecure-skip-verify run --inherit-env=true ./rkt-inspect-print-var-from-manifest.aci"`, + `/bin/sh -c "export VAR_FROM_MANIFEST=host ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true ./rkt-inspect-print-var-from-manifest.aci"`, "VAR_FROM_MANIFEST=manifest", - `/bin/sh -c "export VAR_FROM_MANIFEST=host ; ../bin/rkt --debug --insecure-skip-verify run --inherit-env=true ./rkt-inspect-sleep.aci"`, - `/bin/sh -c "export VAR_FROM_MANIFEST=host ; ../bin/rkt --debug enter $(../bin/rkt list --full|grep running|awk '{print $1}') /inspect --print-env=VAR_FROM_MANIFEST"`, + `/bin/sh -c "export VAR_FROM_MANIFEST=host ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true ./rkt-inspect-sleep.aci"`, + `/bin/sh -c "export VAR_FROM_MANIFEST=host ; ^RKT_BIN^ --debug enter $(^RKT_BIN^ list --full|grep running|awk '{print $1}') /inspect --print-env=VAR_FROM_MANIFEST"`, }, { - `/bin/sh -c "export VAR_OTHER=host ; ../bin/rkt --debug --insecure-skip-verify run --inherit-env=true --set-env=VAR_OTHER=setenv ./rkt-inspect-print-var-other.aci"`, + `/bin/sh -c "export VAR_OTHER=host ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true --set-env=VAR_OTHER=setenv ./rkt-inspect-print-var-other.aci"`, "VAR_OTHER=setenv", - `/bin/sh -c "export VAR_OTHER=host ; ../bin/rkt --debug --insecure-skip-verify run --inherit-env=true --set-env=VAR_OTHER=setenv ./rkt-inspect-sleep.aci"`, - `/bin/sh -c "export VAR_OTHER=host ; ../bin/rkt --debug enter $(../bin/rkt list --full|grep running|awk '{print $1}') /inspect --print-env=VAR_OTHER"`, + `/bin/sh -c "export VAR_OTHER=host ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true --set-env=VAR_OTHER=setenv ./rkt-inspect-sleep.aci"`, + `/bin/sh -c "export VAR_OTHER=host ; ^RKT_BIN^ --debug enter $(^RKT_BIN^ list --full|grep running|awk '{print $1}') /inspect --print-env=VAR_OTHER"`, }, } @@ -72,11 +73,14 @@ func TestEnv(t *testing.T) { defer os.Remove("rkt-inspect-print-var-other.aci") patchTestACI("rkt-inspect-sleep.aci", "--exec=/inspect --print-msg=Hello --sleep=84000") defer os.Remove("rkt-inspect-sleep.aci") + ctx := newRktRunCtx() + defer ctx.cleanup() for i, tt := range envTests { // 'run' tests - t.Logf("Running 'run' test #%v: %v", i, tt.runCmd) - child, err := gexpect.Spawn(tt.runCmd) + runCmd := strings.Replace(tt.runCmd, "^RKT_BIN^", ctx.cmd(), -1) + t.Logf("Running 'run' test #%v: %v", i, runCmd) + child, err := gexpect.Spawn(runCmd) if err != nil { t.Fatalf("Cannot exec rkt #%v: %v", i, err) } @@ -92,8 +96,9 @@ func TestEnv(t *testing.T) { } // 'enter' tests - t.Logf("Running 'enter' test #%v: sleep: %v", i, tt.sleepCmd) - child, err = gexpect.Spawn(tt.sleepCmd) + sleepCmd := strings.Replace(tt.sleepCmd, "^RKT_BIN^", ctx.cmd(), -1) + t.Logf("Running 'enter' test #%v: sleep: %v", i, sleepCmd) + child, err = gexpect.Spawn(sleepCmd) if err != nil { t.Fatalf("Cannot exec rkt #%v: %v", i, err) } @@ -103,8 +108,9 @@ func TestEnv(t *testing.T) { t.Fatalf("Expected %q but not found", tt.runExpect) } - t.Logf("Running 'enter' test #%v: enter: %v", i, tt.enterCmd) - enterChild, err := gexpect.Spawn(tt.enterCmd) + enterCmd := strings.Replace(tt.enterCmd, "^RKT_BIN^", ctx.cmd(), -1) + t.Logf("Running 'enter' test #%v: enter: %v", i, enterCmd) + enterChild, err := gexpect.Spawn(enterCmd) if err != nil { t.Fatalf("Cannot exec rkt #%v: %v", i, err) } @@ -122,5 +128,6 @@ func TestEnv(t *testing.T) { if err != nil { t.Fatalf("rkt didn't terminate correctly: %v", err) } + ctx.reset() } } From 0a161531fde591898e75fd8d52f9f093eb005769 Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Mon, 27 Apr 2015 13:15:58 +0200 Subject: [PATCH 05/13] functional tests: Port capabilities tests to rkt run context --- tests/rkt_caps_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/rkt_caps_test.go b/tests/rkt_caps_test.go index 10b8c3a..9d1d40f 100644 --- a/tests/rkt_caps_test.go +++ b/tests/rkt_caps_test.go @@ -87,11 +87,13 @@ func TestCaps(t *testing.T) { patchTestACI(stage2FileName, stage2Args...) defer os.Remove(stage1FileName) defer os.Remove(stage2FileName) + ctx := newRktRunCtx() + defer ctx.cleanup() for _, stage := range []int{1, 2} { t.Logf("Running test #%v: %v [stage %v]", i, tt.testName, stage) - cmd := fmt.Sprintf("../bin/rkt --debug --insecure-skip-verify run --set-env=CAPABILITY=%d ./rkt-inspect-print-caps-stage%d.aci", int(tt.capa), stage) + cmd := fmt.Sprintf("%s --debug --insecure-skip-verify run --set-env=CAPABILITY=%d ./rkt-inspect-print-caps-stage%d.aci", ctx.cmd(), int(tt.capa), stage) t.Logf("Command: %v", cmd) child, err := gexpect.Spawn(cmd) if err != nil { From 3bc4b51880e57bd511ddf99f69d71f6204e6a91e Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Mon, 27 Apr 2015 13:20:18 +0200 Subject: [PATCH 06/13] functional tests: Port interactive tests to rkt run context --- tests/rkt_interactive_test.go | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/tests/rkt_interactive_test.go b/tests/rkt_interactive_test.go index 27a9e87..3e4cef5 100644 --- a/tests/rkt_interactive_test.go +++ b/tests/rkt_interactive_test.go @@ -15,6 +15,7 @@ package main import ( + "fmt" "os" "testing" "time" @@ -25,55 +26,58 @@ import ( var interactiveTests = []struct { testName string aciBuildArgs []string - rktCmd string + rktArgs string say string expect string }{ { `Check tty without interactive`, []string{"--exec=/inspect --check-tty"}, - `../bin/rkt --debug --insecure-skip-verify run rkt-inspect-interactive.aci`, + `--debug --insecure-skip-verify run rkt-inspect-interactive.aci`, ``, `stdin is not a terminal`, }, { `Check tty without interactive (with parameter)`, []string{"--exec=/inspect"}, - `../bin/rkt --debug --insecure-skip-verify run rkt-inspect-interactive.aci -- --check-tty`, + `--debug --insecure-skip-verify run rkt-inspect-interactive.aci -- --check-tty`, ``, `stdin is not a terminal`, }, { `Check tty with interactive`, []string{"--exec=/inspect --check-tty"}, - `../bin/rkt --debug --insecure-skip-verify run --interactive rkt-inspect-interactive.aci`, + `--debug --insecure-skip-verify run --interactive rkt-inspect-interactive.aci`, ``, `stdin is a terminal`, }, { `Check tty with interactive (with parameter)`, []string{"--exec=/inspect"}, - `../bin/rkt --debug --insecure-skip-verify run --interactive rkt-inspect-interactive.aci -- --check-tty`, + `--debug --insecure-skip-verify run --interactive rkt-inspect-interactive.aci -- --check-tty`, ``, `stdin is a terminal`, }, { `Reading from stdin`, []string{"--exec=/inspect --read-stdin"}, - `../bin/rkt --debug --insecure-skip-verify run --interactive rkt-inspect-interactive.aci`, + `--debug --insecure-skip-verify run --interactive rkt-inspect-interactive.aci`, `Saluton`, `Received text: Saluton`, }, { `Reading from stdin (with parameter)`, []string{"--exec=/inspect"}, - `../bin/rkt --debug --insecure-skip-verify run --interactive rkt-inspect-interactive.aci -- --read-stdin`, + `--debug --insecure-skip-verify run --interactive rkt-inspect-interactive.aci -- --read-stdin`, `Saluton`, `Received text: Saluton`, }, } func TestInteractive(t *testing.T) { + ctx := newRktRunCtx() + defer ctx.cleanup() + for i, tt := range interactiveTests { t.Logf("Running test #%v: %v", i, tt.testName) @@ -81,8 +85,9 @@ func TestInteractive(t *testing.T) { patchTestACI(aciFileName, tt.aciBuildArgs...) defer os.Remove(aciFileName) - t.Logf("Command: %v", tt.rktCmd) - child, err := gexpect.Spawn(tt.rktCmd) + rktCmd := fmt.Sprintf("%s %s", ctx.cmd(), tt.rktArgs) + t.Logf("Command: %v", rktCmd) + child, err := gexpect.Spawn(rktCmd) if err != nil { t.Fatalf("Cannot exec rkt #%v: %v", i, err) } From eb458e526ad684ded8f4747ff3cbd6898a2b4e64 Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Mon, 27 Apr 2015 13:24:55 +0200 Subject: [PATCH 07/13] functional tests: Port volume tests to rkt run context --- tests/rkt_volume_test.go | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tests/rkt_volume_test.go b/tests/rkt_volume_test.go index c07d530..c822582 100644 --- a/tests/rkt_volume_test.go +++ b/tests/rkt_volume_test.go @@ -31,35 +31,35 @@ var volTests = []struct { }{ // Check that we can read files in the ACI { - `/bin/sh -c "export FILE=/dir1/file ; ../bin/rkt --debug --insecure-skip-verify run --inherit-env=true ./rkt-inspect-read-file.aci"`, + `/bin/sh -c "export FILE=/dir1/file ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true ./rkt-inspect-read-file.aci"`, `<<>>`, }, // Check that we can read files from a volume (both ro and rw) { - `/bin/sh -c "export FILE=/dir1/file ; ../bin/rkt --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=$TMPDIR ./rkt-inspect-vol-rw-read-file.aci"`, + `/bin/sh -c "export FILE=/dir1/file ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=$TMPDIR ./rkt-inspect-vol-rw-read-file.aci"`, `<<>>`, }, { - `/bin/sh -c "export FILE=/dir1/file ; ../bin/rkt --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=$TMPDIR ./rkt-inspect-vol-ro-read-file.aci"`, + `/bin/sh -c "export FILE=/dir1/file ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=$TMPDIR ./rkt-inspect-vol-ro-read-file.aci"`, `<<>>`, }, // Check that we can write to files in the ACI { - `/bin/sh -c "export FILE=/dir1/file CONTENT=1 ; ../bin/rkt --debug --insecure-skip-verify run --inherit-env=true ./rkt-inspect-write-file.aci"`, + `/bin/sh -c "export FILE=/dir1/file CONTENT=1 ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true ./rkt-inspect-write-file.aci"`, `<<<1>>>`, }, // Check that we can write files to a volume (both ro and rw) { - `/bin/sh -c "export FILE=/dir1/file CONTENT=2 ; ../bin/rkt --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=$TMPDIR ./rkt-inspect-vol-rw-write-file.aci"`, + `/bin/sh -c "export FILE=/dir1/file CONTENT=2 ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=$TMPDIR ./rkt-inspect-vol-rw-write-file.aci"`, `<<<2>>>`, }, { - `/bin/sh -c "export FILE=/dir1/file CONTENT=3 ; ../bin/rkt --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=$TMPDIR ./rkt-inspect-vol-ro-write-file.aci"`, + `/bin/sh -c "export FILE=/dir1/file CONTENT=3 ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=$TMPDIR ./rkt-inspect-vol-ro-write-file.aci"`, `Cannot write to file "/dir1/file": open /dir1/file: read-only file system`, }, // Check that the volume still contain the file previously written { - `/bin/sh -c "export FILE=/dir1/file ; ../bin/rkt --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=$TMPDIR ./rkt-inspect-vol-ro-read-file.aci"`, + `/bin/sh -c "export FILE=/dir1/file ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=$TMPDIR ./rkt-inspect-vol-ro-read-file.aci"`, `<<<2>>>`, }, } @@ -77,22 +77,24 @@ func TestVolumes(t *testing.T) { defer os.Remove("rkt-inspect-vol-ro-read-file.aci") patchTestACI("rkt-inspect-vol-ro-write-file.aci", "--exec=/inspect --write-file --read-file", "--mounts=dir1,path=/dir1,readOnly=true") defer os.Remove("rkt-inspect-vol-ro-write-file.aci") + ctx := newRktRunCtx() + defer ctx.cleanup() tmpdir, err := ioutil.TempDir("", "rkt-tests.") if err != nil { t.Fatalf("Cannot create temporary directory: %v", err) } - defer os.Remove(tmpdir) + defer os.RemoveAll(tmpdir) tmpfile := filepath.Join(tmpdir, "file") err = ioutil.WriteFile(tmpfile, []byte("host"), 0600) if err != nil { t.Fatalf("Cannot create temporary file: %v", err) } - defer os.Remove(tmpfile) for i, tt := range volTests { cmd := strings.Replace(tt.rktCmd, "$TMPDIR", tmpdir, -1) + cmd = strings.Replace(cmd, "^RKT_BIN^", ctx.cmd(), -1) t.Logf("Running test #%v: %v", i, cmd) From 25e2a39a2830252d1e89df07ef29f5e1bcd03649 Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Mon, 27 Apr 2015 14:21:02 +0200 Subject: [PATCH 08/13] functional tests: Drop dead code for destructive tests --- test | 7 +++---- tests/rkt_tests.go | 13 ------------- tests/test | 3 +-- 3 files changed, 4 insertions(+), 19 deletions(-) diff --git a/test b/test index 8606b10..4d9b10c 100755 --- a/test +++ b/test @@ -54,13 +54,12 @@ if [ -n "${vetRes}" ]; then exit 255 fi -# Functional tests are more dangerous than unit tests: they use 'sudo' and access -# /var/lib/rkt/ directly. Only run them inside well-known CI systems. +# Functional tests may need manual intervention to run and are more +# dangerous than unit tests: they use 'sudo'. Only run them inside +# well-known CI systems. if [ "$CI" == true ] ; then if [ "${CIRCLECI}" == true -o "${SEMAPHORE}" == true ] ; then echo "Checking functional tests..." - # Run destructive tests too - export RKT_ENABLE_DESTRUCTIVE_TESTS=1 (cd tests && ./test) else echo "Functional tests disabled." diff --git a/tests/rkt_tests.go b/tests/rkt_tests.go index ac6a1e1..e092340 100644 --- a/tests/rkt_tests.go +++ b/tests/rkt_tests.go @@ -20,21 +20,8 @@ import ( "os" "os/exec" "strings" - "testing" ) -const enableDestructiveTestsEnvVar = "RKT_ENABLE_DESTRUCTIVE_TESTS" - -func skipDestructive(t *testing.T) { - if !destructiveTestsEnabled() { - t.Skipf("%s envvar is not specified or has value different than 1, skipping the test", enableDestructiveTestsEnvVar) - } -} - -func destructiveTestsEnabled() bool { - return os.Getenv(enableDestructiveTestsEnvVar) == "1" -} - // dirDesc structure manages one directory and provides an option for // rkt invocations type dirDesc struct { diff --git a/tests/test b/tests/test index 9fa6ee1..784bbb1 100755 --- a/tests/test +++ b/tests/test @@ -18,5 +18,4 @@ # version as the system-wide installed go. GO=`which go` -sudo GOPATH="${PWD}/../gopath" RKT_ENABLE_DESTRUCTIVE_TESTS="$RKT_ENABLE_DESTRUCTIVE_TESTS" GOROOT="$GOROOT" $GO test -v $* - +sudo GOPATH="${PWD}/../gopath" GOROOT="$GOROOT" $GO test -v $* From a4d595e7198af248bb04e8198e6bd66fb7343434 Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Mon, 27 Apr 2015 16:56:03 +0200 Subject: [PATCH 09/13] functional tests: Use enumeration to specify config directory --- tests/rkt_auth_test.go | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/tests/rkt_auth_test.go b/tests/rkt_auth_test.go index 7667023..06020da 100644 --- a/tests/rkt_auth_test.go +++ b/tests/rkt_auth_test.go @@ -39,27 +39,34 @@ const ( authFailedDownload = "error downloading ACI: bad HTTP status code: 401" ) +type authConfDir int + +const ( + authConfDirNone authConfDir = iota + authConfDirLocal + authConfDirSystem +) + type genericAuthTest struct { name string - useServerConf bool - confDir string + confDir authConfDir expectedLine string } func TestAuthBasic(t *testing.T) { tests := []genericAuthTest{ - {"basic-no-config", false, "", authFailedDownload}, - {"basic-local-config", true, "local", authSuccessfulDownload}, - {"basic-system-config", true, "system", authSuccessfulDownload}, + {"basic-no-config", authConfDirNone, authFailedDownload}, + {"basic-local-config", authConfDirLocal, authSuccessfulDownload}, + {"basic-system-config", authConfDirSystem, authSuccessfulDownload}, } testAuthGeneric(t, taas.Basic, tests) } func TestAuthOauth(t *testing.T) { tests := []genericAuthTest{ - {"oauth-no-config", false, "", authFailedDownload}, - {"oauth-local-config", true, "local", authSuccessfulDownload}, - {"oauth-system-config", true, "system", authSuccessfulDownload}, + {"oauth-no-config", authConfDirNone, authFailedDownload}, + {"oauth-local-config", authConfDirLocal, authSuccessfulDownload}, + {"oauth-system-config", authConfDirSystem, authSuccessfulDownload}, } testAuthGeneric(t, taas.Oauth, tests) } @@ -70,15 +77,15 @@ func testAuthGeneric(t *testing.T, auth taas.Type, tests []genericAuthTest) { ctx := newRktRunCtx() defer ctx.cleanup() for _, tt := range tests { - if tt.useServerConf { - switch tt.confDir { - case "local": - writeConfig(t, ctx.localDir(), "test.json", server.Conf) - case "system": - writeConfig(t, ctx.systemDir(), "test.json", server.Conf) - default: - panic("Wrong config directory") - } + switch tt.confDir { + case authConfDirNone: + // no config to write + case authConfDirLocal: + writeConfig(t, ctx.localDir(), "test.json", server.Conf) + case authConfDirSystem: + writeConfig(t, ctx.systemDir(), "test.json", server.Conf) + default: + panic("Wrong config directory") } expectedRunRkt(ctx, t, server.URL, tt.name, tt.expectedLine) ctx.reset() From f9a66a464fc5abac5abb0dae80f20cac2cd75bec Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Mon, 27 Apr 2015 17:06:00 +0200 Subject: [PATCH 10/13] functional tests: Replace leftover "../bin/rkt" with rkt run context --- tests/rkt_caps_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/rkt_caps_test.go b/tests/rkt_caps_test.go index 9d1d40f..23efa42 100644 --- a/tests/rkt_caps_test.go +++ b/tests/rkt_caps_test.go @@ -125,6 +125,9 @@ func TestCaps(t *testing.T) { } func TestNonRootCaps(t *testing.T) { + ctx := newRktRunCtx() + defer ctx.cleanup() + for i, tt := range capsTests { var fileName = "rkt-inspect-print-caps-nonroot.aci" var args []string @@ -137,7 +140,7 @@ func TestNonRootCaps(t *testing.T) { t.Logf("Running test #%v: %v [non-root]", i, tt.testName) - cmd := fmt.Sprintf("../bin/rkt --debug --insecure-skip-verify run --set-env=CAPABILITY=%d ./%s", int(tt.capa), fileName) + cmd := fmt.Sprintf("%s --debug --insecure-skip-verify run --set-env=CAPABILITY=%d ./%s", ctx.cmd(), int(tt.capa), fileName) t.Logf("Command: %v", cmd) child, err := gexpect.Spawn(cmd) if err != nil { @@ -164,5 +167,6 @@ func TestNonRootCaps(t *testing.T) { if err != nil { t.Fatalf("rkt didn't terminate correctly: %v", err) } + ctx.reset() } } From d302fdbf898e8b735660e280d22f96085e8d9dad Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Mon, 27 Apr 2015 17:06:54 +0200 Subject: [PATCH 11/13] functional tests: Fix rkt run context use Create just one context for the test and reset it after each iteration, so unused directories are removed immediately instead of during deferred cleanup. --- tests/rkt_caps_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/rkt_caps_test.go b/tests/rkt_caps_test.go index 23efa42..b923e0a 100644 --- a/tests/rkt_caps_test.go +++ b/tests/rkt_caps_test.go @@ -74,6 +74,9 @@ var capsTests = []struct { } func TestCaps(t *testing.T) { + ctx := newRktRunCtx() + defer ctx.cleanup() + for i, tt := range capsTests { var stage1FileName = "rkt-inspect-print-caps-stage1.aci" var stage2FileName = "rkt-inspect-print-caps-stage2.aci" @@ -87,8 +90,6 @@ func TestCaps(t *testing.T) { patchTestACI(stage2FileName, stage2Args...) defer os.Remove(stage1FileName) defer os.Remove(stage2FileName) - ctx := newRktRunCtx() - defer ctx.cleanup() for _, stage := range []int{1, 2} { t.Logf("Running test #%v: %v [stage %v]", i, tt.testName, stage) @@ -121,6 +122,7 @@ func TestCaps(t *testing.T) { t.Fatalf("rkt didn't terminate correctly: %v", err) } } + ctx.reset() } } From 4bded6e58b67841fbff0ffe69258d7382d2c8a1f Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Mon, 27 Apr 2015 17:19:35 +0200 Subject: [PATCH 12/13] functional tests: Change $TMPDIR to ^TMPDIR^ This is to avoid confusion - $TMPDIR is replaced before the command is ran. Also, it's more consistent - we use this format for RKT_BIN. --- tests/rkt_volume_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/rkt_volume_test.go b/tests/rkt_volume_test.go index c822582..c15ec1f 100644 --- a/tests/rkt_volume_test.go +++ b/tests/rkt_volume_test.go @@ -36,11 +36,11 @@ var volTests = []struct { }, // Check that we can read files from a volume (both ro and rw) { - `/bin/sh -c "export FILE=/dir1/file ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=$TMPDIR ./rkt-inspect-vol-rw-read-file.aci"`, + `/bin/sh -c "export FILE=/dir1/file ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=^TMPDIR^ ./rkt-inspect-vol-rw-read-file.aci"`, `<<>>`, }, { - `/bin/sh -c "export FILE=/dir1/file ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=$TMPDIR ./rkt-inspect-vol-ro-read-file.aci"`, + `/bin/sh -c "export FILE=/dir1/file ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=^TMPDIR^ ./rkt-inspect-vol-ro-read-file.aci"`, `<<>>`, }, // Check that we can write to files in the ACI @@ -50,16 +50,16 @@ var volTests = []struct { }, // Check that we can write files to a volume (both ro and rw) { - `/bin/sh -c "export FILE=/dir1/file CONTENT=2 ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=$TMPDIR ./rkt-inspect-vol-rw-write-file.aci"`, + `/bin/sh -c "export FILE=/dir1/file CONTENT=2 ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=^TMPDIR^ ./rkt-inspect-vol-rw-write-file.aci"`, `<<<2>>>`, }, { - `/bin/sh -c "export FILE=/dir1/file CONTENT=3 ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=$TMPDIR ./rkt-inspect-vol-ro-write-file.aci"`, + `/bin/sh -c "export FILE=/dir1/file CONTENT=3 ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=^TMPDIR^ ./rkt-inspect-vol-ro-write-file.aci"`, `Cannot write to file "/dir1/file": open /dir1/file: read-only file system`, }, // Check that the volume still contain the file previously written { - `/bin/sh -c "export FILE=/dir1/file ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=$TMPDIR ./rkt-inspect-vol-ro-read-file.aci"`, + `/bin/sh -c "export FILE=/dir1/file ; ^RKT_BIN^ --debug --insecure-skip-verify run --inherit-env=true --volume=dir1,kind=host,source=^TMPDIR^ ./rkt-inspect-vol-ro-read-file.aci"`, `<<<2>>>`, }, } @@ -93,7 +93,7 @@ func TestVolumes(t *testing.T) { } for i, tt := range volTests { - cmd := strings.Replace(tt.rktCmd, "$TMPDIR", tmpdir, -1) + cmd := strings.Replace(tt.rktCmd, "^TMPDIR^", tmpdir, -1) cmd = strings.Replace(cmd, "^RKT_BIN^", ctx.cmd(), -1) t.Logf("Running test #%v: %v", i, cmd) From 08f9d8c3ee5a6f273fc370c464035847689dff93 Mon Sep 17 00:00:00 2001 From: Krzesimir Nowak Date: Tue, 28 Apr 2015 11:37:44 +0200 Subject: [PATCH 13/13] functional tests: Reword the comment --- test | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test b/test index 4d9b10c..fecd750 100755 --- a/test +++ b/test @@ -54,9 +54,9 @@ if [ -n "${vetRes}" ]; then exit 255 fi -# Functional tests may need manual intervention to run and are more -# dangerous than unit tests: they use 'sudo'. Only run them inside -# well-known CI systems. +# Functional tests use 'sudo' to run as root - it's more dangerous +# than unit tests and may require typing a password. Only run them +# inside well-known CI systems. if [ "$CI" == true ] ; then if [ "${CIRCLECI}" == true -o "${SEMAPHORE}" == true ] ; then echo "Checking functional tests..."