Merge pull request #829 from endocode/krnowak/non-destructive-functests

non destructive functional tests
This commit is contained in:
Krzesimir Nowak
2015-04-28 11:55:33 +02:00
9 changed files with 245 additions and 153 deletions
+3 -4
View File
@@ -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 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..."
# Run destructive tests too
export RKT_ENABLE_DESTRUCTIVE_TESTS=1
(cd tests && ./test)
else
echo "Functional tests disabled."
+57 -87
View File
@@ -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 (
@@ -40,50 +39,62 @@ 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, common.DefaultLocalConfigDir, authSuccessfulDownload},
{"basic-system-config", true, common.DefaultSystemConfigDir, 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, common.DefaultLocalConfigDir, authSuccessfulDownload},
{"oauth-system-config", true, common.DefaultSystemConfigDir, authSuccessfulDownload},
{"oauth-no-config", authConfDirNone, authFailedDownload},
{"oauth-local-config", authConfDirLocal, authSuccessfulDownload},
{"oauth-system-config", authConfDirSystem, 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 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(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 +108,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 +124,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 +163,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) {
+10 -2
View File
@@ -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"
@@ -91,7 +94,7 @@ func TestCaps(t *testing.T) {
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 {
@@ -119,10 +122,14 @@ func TestCaps(t *testing.T) {
t.Fatalf("rkt didn't terminate correctly: %v", err)
}
}
ctx.reset()
}
}
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
@@ -135,7 +142,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 {
@@ -162,5 +169,6 @@ func TestNonRootCaps(t *testing.T) {
if err != nil {
t.Fatalf("rkt didn't terminate correctly: %v", err)
}
ctx.reset()
}
}
+31 -24
View File
@@ -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()
}
}
+7 -2
View File
@@ -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")
}
+14 -9
View File
@@ -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)
}
+110 -13
View File
@@ -16,30 +16,127 @@ package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"testing"
"strings"
)
const enableDestructiveTestsEnvVar = "RKT_ENABLE_DESTRUCTIVE_TESTS"
// 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
}
func skipDestructive(t *testing.T) {
if !destructiveTestsEnabled() {
t.Skipf("%s envvar is not specified or has value different than 1, skipping the test", enableDestructiveTestsEnvVar)
// newDirDesc creates dirDesc instance managing a temporary directory.
func newDirDesc(prefix, desc, option string) *dirDesc {
dir := &dirDesc{
dir: "",
desc: desc,
prefix: prefix,
option: option,
}
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 removeDataDir(t *testing.T) {
if !destructiveTestsEnabled() {
panic("Trying to remove datadir when destructive tests are disabled")
}
if err := os.RemoveAll("/var/lib/rkt"); err != nil {
t.Fatalf("Failed to remove /var/lib/rkt: %v", err)
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 destructiveTestsEnabled() bool {
return os.Getenv(enableDestructiveTestsEnvVar) == "1"
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) {
+12 -10
View File
@@ -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"`,
`<<<dir1>>>`,
},
// 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"`,
`<<<host>>>`,
},
{
`/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"`,
`<<<host>>>`,
},
// 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(tt.rktCmd, "^TMPDIR^", tmpdir, -1)
cmd = strings.Replace(cmd, "^RKT_BIN^", ctx.cmd(), -1)
t.Logf("Running test #%v: %v", i, cmd)
+1 -2
View File
@@ -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 $*