Files
kata-containers/cli/exec_test.go
Wei Zhang 9507f45a0f CompatOCISpec: limit usage of CompatOCISpec
Fixes: #2023

CompatOCISpec is used to gurantee backward compatbility for old runtime
specs, after we convert CompatOCISpec to standard specs.Spec, we should
use specs.Spec instead of CompatOCISpec, and CompatOCISpec should be
useless from then.

Spread usage of CompatOCISpec can make code structure confusing and making
the runtime spec usage non-standard. Besides, this can be the very first
step of removing CompatOCISpec from config's Annotations field.

Signed-off-by: Wei Zhang <weizhang555.zw@gmail.com>
2019-09-05 11:05:55 +08:00

795 lines
22 KiB
Go

// Copyright (c) 2017 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"context"
"flag"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"testing"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli"
vc "github.com/kata-containers/runtime/virtcontainers"
vcAnnotations "github.com/kata-containers/runtime/virtcontainers/pkg/annotations"
"github.com/kata-containers/runtime/virtcontainers/pkg/vcmock"
"github.com/kata-containers/runtime/virtcontainers/types"
)
func TestExecCLIFunction(t *testing.T) {
assert := assert.New(t)
flagSet := &flag.FlagSet{}
ctx := createCLIContext(flagSet)
fn, ok := startCLICommand.Action.(func(context *cli.Context) error)
assert.True(ok)
// no container-id in the Metadata
err := fn(ctx)
assert.Error(err)
assert.False(vcmock.IsMockError(err))
path, err := createTempContainerIDMapping("xyz", "xyz")
assert.NoError(err)
defer os.RemoveAll(path)
// pass container-id
flagSet = flag.NewFlagSet("container-id", flag.ContinueOnError)
flagSet.Parse([]string{"xyz"})
ctx = createCLIContext(flagSet)
err = fn(ctx)
assert.Error(err)
assert.True(vcmock.IsMockError(err))
}
func TestExecuteErrors(t *testing.T) {
assert := assert.New(t)
flagSet := flag.NewFlagSet("", 0)
ctx := createCLIContext(flagSet)
// missing container id
err := execute(context.Background(), ctx)
assert.Error(err)
assert.False(vcmock.IsMockError(err))
path, err := createTempContainerIDMapping(testContainerID, testSandboxID)
assert.NoError(err)
defer os.RemoveAll(path)
// StatusSandbox error
flagSet.Parse([]string{testContainerID})
err = execute(context.Background(), ctx)
assert.Error(err)
assert.True(vcmock.IsMockError(err))
// Config path missing in annotations
annotations := map[string]string{
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
}
testingImpl.StatusContainerFunc = func(ctx context.Context, sandboxID, containerID string) (vc.ContainerStatus, error) {
return newSingleContainerStatus(testContainerID, types.ContainerState{}, annotations), nil
}
defer func() {
testingImpl.StatusContainerFunc = nil
}()
err = execute(context.Background(), ctx)
assert.Error(err)
assert.False(vcmock.IsMockError(err))
// Container state undefined
rootPath, bundlePath := testConfigSetup(t)
defer os.RemoveAll(rootPath)
configJSON, err := readOCIConfigJSON(bundlePath)
assert.NoError(err)
annotations = map[string]string{
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
vcAnnotations.ConfigJSONKey: configJSON,
}
containerState := types.ContainerState{}
testingImpl.StatusContainerFunc = func(ctx context.Context, sandboxID, containerID string) (vc.ContainerStatus, error) {
return newSingleContainerStatus(testContainerID, containerState, annotations), nil
}
err = execute(context.Background(), ctx)
assert.Error(err)
assert.False(vcmock.IsMockError(err))
// Container paused
containerState = types.ContainerState{
State: types.StatePaused,
}
testingImpl.StatusContainerFunc = func(ctx context.Context, sandboxID, containerID string) (vc.ContainerStatus, error) {
return newSingleContainerStatus(testContainerID, containerState, annotations), nil
}
err = execute(context.Background(), ctx)
assert.Error(err)
assert.False(vcmock.IsMockError(err))
// Container stopped
containerState = types.ContainerState{
State: types.StateStopped,
}
testingImpl.StatusContainerFunc = func(ctx context.Context, sandboxID, containerID string) (vc.ContainerStatus, error) {
return newSingleContainerStatus(testContainerID, containerState, annotations), nil
}
err = execute(context.Background(), ctx)
assert.Error(err)
assert.False(vcmock.IsMockError(err))
}
func TestExecuteErrorReadingProcessJson(t *testing.T) {
assert := assert.New(t)
tmpdir, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(tmpdir)
// non-existent path
processPath := filepath.Join(tmpdir, "process.json")
flagSet := flag.NewFlagSet("", 0)
flagSet.String("process", processPath, "")
flagSet.Parse([]string{testContainerID})
ctx := createCLIContext(flagSet)
rootPath, bundlePath := testConfigSetup(t)
defer os.RemoveAll(rootPath)
configJSON, err := readOCIConfigJSON(bundlePath)
assert.NoError(err)
annotations := map[string]string{
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
vcAnnotations.ConfigJSONKey: configJSON,
}
state := types.ContainerState{
State: types.StateRunning,
}
path, err := createTempContainerIDMapping(testContainerID, testSandboxID)
assert.NoError(err)
defer os.RemoveAll(path)
testingImpl.StatusContainerFunc = func(ctx context.Context, sandboxID, containerID string) (vc.ContainerStatus, error) {
return newSingleContainerStatus(testContainerID, state, annotations), nil
}
defer func() {
testingImpl.StatusContainerFunc = nil
}()
// Note: flags can only be tested with the CLI command function
fn, ok := execCLICommand.Action.(func(context *cli.Context) error)
assert.True(ok)
err = fn(ctx)
assert.Error(err)
assert.False(vcmock.IsMockError(err))
}
func TestExecuteErrorOpeningConsole(t *testing.T) {
assert := assert.New(t)
tmpdir, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(tmpdir)
consoleSock := filepath.Join(tmpdir, "console-sock")
flagSet := flag.NewFlagSet("", 0)
flagSet.String("console-socket", consoleSock, "")
flagSet.Parse([]string{testContainerID})
ctx := createCLIContext(flagSet)
rootPath, bundlePath := testConfigSetup(t)
defer os.RemoveAll(rootPath)
configJSON, err := readOCIConfigJSON(bundlePath)
assert.NoError(err)
annotations := map[string]string{
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
vcAnnotations.ConfigJSONKey: configJSON,
}
state := types.ContainerState{
State: types.StateRunning,
}
path, err := createTempContainerIDMapping(testContainerID, testSandboxID)
assert.NoError(err)
defer os.RemoveAll(path)
testingImpl.StatusContainerFunc = func(ctx context.Context, sandboxID, containerID string) (vc.ContainerStatus, error) {
return newSingleContainerStatus(testContainerID, state, annotations), nil
}
defer func() {
testingImpl.StatusContainerFunc = nil
}()
// Note: flags can only be tested with the CLI command function
fn, ok := execCLICommand.Action.(func(context *cli.Context) error)
assert.True(ok)
err = fn(ctx)
assert.Error(err)
assert.False(vcmock.IsMockError(err))
}
func testExecParamsSetup(t *testing.T, pidFilePath, consolePath string, detach bool) *flag.FlagSet {
flagSet := flag.NewFlagSet("", 0)
flagSet.String("pid-file", pidFilePath, "")
flagSet.String("console", consolePath, "")
flagSet.String("console-socket", "", "")
flagSet.Bool("detach", detach, "")
flagSet.String("process-label", "testlabel", "")
flagSet.Bool("no-subreaper", false, "")
return flagSet
}
func TestExecuteWithFlags(t *testing.T) {
assert := assert.New(t)
tmpdir, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(tmpdir)
pidFilePath := filepath.Join(tmpdir, "pid")
consolePath := "/dev/ptmx"
flagSet := testExecParamsSetup(t, pidFilePath, consolePath, false)
flagSet.String("user", "root", "")
flagSet.String("cwd", "/home/root", "")
flagSet.String("apparmor", "/tmp/profile", "")
flagSet.Bool("no-new-privs", false, "")
flagSet.Parse([]string{testContainerID, "/tmp/foo"})
ctx := createCLIContext(flagSet)
rootPath, bundlePath := testConfigSetup(t)
defer os.RemoveAll(rootPath)
configJSON, err := readOCIConfigJSON(bundlePath)
assert.NoError(err)
annotations := map[string]string{
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
vcAnnotations.ConfigJSONKey: configJSON,
}
state := types.ContainerState{
State: types.StateRunning,
}
path, err := createTempContainerIDMapping(testContainerID, testSandboxID)
assert.NoError(err)
defer os.RemoveAll(path)
testingImpl.StatusContainerFunc = func(ctx context.Context, sandboxID, containerID string) (vc.ContainerStatus, error) {
return newSingleContainerStatus(testContainerID, state, annotations), nil
}
defer func() {
testingImpl.StatusContainerFunc = nil
}()
fn, ok := execCLICommand.Action.(func(context *cli.Context) error)
assert.True(ok)
// EnterContainer error
err = fn(ctx)
assert.Error(err)
assert.True(vcmock.IsMockError(err))
testingImpl.EnterContainerFunc = func(ctx context.Context, sandboxID, containerID string, cmd types.Cmd) (vc.VCSandbox, vc.VCContainer, *vc.Process, error) {
return &vcmock.Sandbox{}, &vcmock.Container{}, &vc.Process{}, nil
}
defer func() {
testingImpl.EnterContainerFunc = nil
os.Remove(pidFilePath)
}()
// Process not running error
err = fn(ctx)
assert.Error(err)
assert.False(vcmock.IsMockError(err))
os.Remove(pidFilePath)
// Process ran and exited successfully
testingImpl.EnterContainerFunc = func(ctx context.Context, sandboxID, containerID string, cmd types.Cmd) (vc.VCSandbox, vc.VCContainer, *vc.Process, error) {
// create a fake container process
workload := []string{"cat", "/dev/null"}
command := exec.Command(workload[0], workload[1:]...)
err := command.Start()
assert.NoError(err, "Unable to start process %v: %s", workload, err)
vcProcess := vc.Process{}
vcProcess.Pid = command.Process.Pid
return &vcmock.Sandbox{}, &vcmock.Container{}, &vcProcess, nil
}
defer func() {
testingImpl.EnterContainerFunc = nil
os.Remove(pidFilePath)
}()
// Should get an exit code when run in non-detached mode.
err = fn(ctx)
_, ok = err.(*cli.ExitError)
assert.True(ok, true, "Exit code not received for fake workload process")
}
func TestExecuteWithFlagsDetached(t *testing.T) {
assert := assert.New(t)
tmpdir, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(tmpdir)
pidFilePath := filepath.Join(tmpdir, "pid")
consolePath := "/dev/ptmx"
detach := true
flagSet := testExecParamsSetup(t, pidFilePath, consolePath, detach)
flagSet.Parse([]string{testContainerID, "/tmp/foo"})
ctx := createCLIContext(flagSet)
rootPath, bundlePath := testConfigSetup(t)
defer os.RemoveAll(rootPath)
configJSON, err := readOCIConfigJSON(bundlePath)
assert.NoError(err)
annotations := map[string]string{
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
vcAnnotations.ConfigJSONKey: configJSON,
}
state := types.ContainerState{
State: types.StateRunning,
}
path, err := createTempContainerIDMapping(testContainerID, testSandboxID)
assert.NoError(err)
defer os.RemoveAll(path)
testingImpl.StatusContainerFunc = func(ctx context.Context, sandboxID, containerID string) (vc.ContainerStatus, error) {
return newSingleContainerStatus(testContainerID, state, annotations), nil
}
defer func() {
testingImpl.StatusContainerFunc = nil
}()
testingImpl.EnterContainerFunc = func(ctx context.Context, sandboxID, containerID string, cmd types.Cmd) (vc.VCSandbox, vc.VCContainer, *vc.Process, error) {
// create a fake container process
workload := []string{"cat", "/dev/null"}
command := exec.Command(workload[0], workload[1:]...)
err := command.Start()
assert.NoError(err, "Unable to start process %v: %s", workload, err)
vcProcess := vc.Process{}
vcProcess.Pid = command.Process.Pid
return &vcmock.Sandbox{}, &vcmock.Container{}, &vcProcess, nil
}
defer func() {
testingImpl.EnterContainerFunc = nil
os.Remove(pidFilePath)
}()
fn, ok := execCLICommand.Action.(func(context *cli.Context) error)
assert.True(ok)
err = fn(ctx)
assert.NoError(err)
}
func TestExecuteWithInvalidProcessJson(t *testing.T) {
assert := assert.New(t)
tmpdir, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(tmpdir)
pidFilePath := filepath.Join(tmpdir, "pid")
consolePath := "/dev/ptmx"
detach := false
flagSet := testExecParamsSetup(t, pidFilePath, consolePath, detach)
processPath := filepath.Join(tmpdir, "process.json")
flagSet.String("process", processPath, "")
f, err := os.OpenFile(processPath, os.O_RDWR|os.O_CREATE, testFileMode)
assert.NoError(err)
// invalidate the JSON
_, err = f.WriteString("{")
assert.NoError(err)
f.Close()
defer os.Remove(processPath)
flagSet.Parse([]string{testContainerID})
ctx := createCLIContext(flagSet)
rootPath, bundlePath := testConfigSetup(t)
defer os.RemoveAll(rootPath)
configJSON, err := readOCIConfigJSON(bundlePath)
assert.NoError(err)
annotations := map[string]string{
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
vcAnnotations.ConfigJSONKey: configJSON,
}
state := types.ContainerState{
State: types.StateRunning,
}
path, err := createTempContainerIDMapping(testContainerID, testSandboxID)
assert.NoError(err)
defer os.RemoveAll(path)
testingImpl.StatusContainerFunc = func(ctx context.Context, sandboxID, containerID string) (vc.ContainerStatus, error) {
return newSingleContainerStatus(testContainerID, state, annotations), nil
}
defer func() {
testingImpl.StatusContainerFunc = nil
}()
fn, ok := execCLICommand.Action.(func(context *cli.Context) error)
assert.True(ok)
err = fn(ctx)
assert.Error(err)
assert.False(vcmock.IsMockError(err))
}
func TestExecuteWithValidProcessJson(t *testing.T) {
assert := assert.New(t)
tmpdir, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(tmpdir)
pidFilePath := filepath.Join(tmpdir, "pid")
consolePath := "/dev/ptmx"
flagSet := testExecParamsSetup(t, pidFilePath, consolePath, false)
processPath := filepath.Join(tmpdir, "process.json")
flagSet.String("process", processPath, "")
flagSet.Parse([]string{testContainerID, "/tmp/foo"})
ctx := createCLIContext(flagSet)
rootPath, bundlePath := testConfigSetup(t)
defer os.RemoveAll(rootPath)
configJSON, err := readOCIConfigJSON(bundlePath)
assert.NoError(err)
annotations := map[string]string{
vcAnnotations.ContainerTypeKey: string(vc.PodContainer),
vcAnnotations.ConfigJSONKey: configJSON,
}
state := types.ContainerState{
State: types.StateRunning,
}
path, err := createTempContainerIDMapping(testContainerID, testSandboxID)
assert.NoError(err)
defer os.RemoveAll(path)
testingImpl.StatusContainerFunc = func(ctx context.Context, sandboxID, containerID string) (vc.ContainerStatus, error) {
return newSingleContainerStatus(testContainerID, state, annotations), nil
}
defer func() {
testingImpl.StatusContainerFunc = nil
}()
processJSON := `{
"consoleSize": {
"height": 15,
"width": 15
},
"terminal": true,
"user": {
"uid": 0,
"gid": 0
},
"args": [
"sh"
],
"env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TERM=xterm"
],
"cwd": "/"
}`
f, err := os.OpenFile(processPath, os.O_RDWR|os.O_CREATE, testFileMode)
assert.NoError(err)
_, err = f.WriteString(processJSON)
assert.NoError(err)
f.Close()
defer os.Remove(processPath)
workload := []string{"cat", "/dev/null"}
testingImpl.EnterContainerFunc = func(ctx context.Context, sandboxID, containerID string, cmd types.Cmd) (vc.VCSandbox, vc.VCContainer, *vc.Process, error) {
// create a fake container process
command := exec.Command(workload[0], workload[1:]...)
err := command.Start()
assert.NoError(err, "Unable to start process %v: %s", workload, err)
vcProcess := vc.Process{}
vcProcess.Pid = command.Process.Pid
return &vcmock.Sandbox{}, &vcmock.Container{}, &vcProcess, nil
}
defer func() {
testingImpl.EnterContainerFunc = nil
os.Remove(pidFilePath)
}()
fn, ok := execCLICommand.Action.(func(context *cli.Context) error)
assert.True(ok)
err = fn(ctx)
exitErr, ok := err.(*cli.ExitError)
assert.True(ok, true, "Exit code not received for fake workload process")
assert.Equal(exitErr.ExitCode(), 0, "Exit code should have been 0 for fake workload %s", workload)
}
func TestExecuteWithEmptyEnvironmentValue(t *testing.T) {
assert := assert.New(t)
tmpdir, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(tmpdir)
pidFilePath := filepath.Join(tmpdir, "pid")
consolePath := "/dev/ptmx"
flagSet := testExecParamsSetup(t, pidFilePath, consolePath, false)
processPath := filepath.Join(tmpdir, "process.json")
flagSet.String("process", processPath, "")
flagSet.Parse([]string{testContainerID})
ctx := createCLIContext(flagSet)
rootPath, bundlePath := testConfigSetup(t)
defer os.RemoveAll(rootPath)
configJSON, err := readOCIConfigJSON(bundlePath)
assert.NoError(err)
annotations := map[string]string{
vcAnnotations.ContainerTypeKey: string(vc.PodContainer),
vcAnnotations.ConfigJSONKey: configJSON,
}
state := types.ContainerState{
State: types.StateRunning,
}
path, err := createTempContainerIDMapping(testContainerID, testSandboxID)
assert.NoError(err)
defer os.RemoveAll(path)
testingImpl.StatusContainerFunc = func(ctx context.Context, sandboxID, containerID string) (vc.ContainerStatus, error) {
return newSingleContainerStatus(testContainerID, state, annotations), nil
}
defer func() {
testingImpl.StatusContainerFunc = nil
}()
processJSON := `{
"consoleSize": {
"height": 15,
"width": 15
},
"terminal": true,
"user": {
"uid": 0,
"gid": 0
},
"args": [
"sh"
],
"env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TERM="
],
"cwd": "/"
}`
f, err := os.OpenFile(processPath, os.O_RDWR|os.O_CREATE, testFileMode)
assert.NoError(err)
_, err = f.WriteString(processJSON)
assert.NoError(err)
f.Close()
defer os.Remove(processPath)
workload := []string{"cat", "/dev/null"}
testingImpl.EnterContainerFunc = func(ctx context.Context, sandboxID, containerID string, cmd types.Cmd) (vc.VCSandbox, vc.VCContainer, *vc.Process, error) {
// create a fake container process
command := exec.Command(workload[0], workload[1:]...)
err := command.Start()
assert.NoError(err, "Unable to start process %v: %s", workload, err)
vcProcess := vc.Process{}
vcProcess.Pid = command.Process.Pid
return &vcmock.Sandbox{}, &vcmock.Container{}, &vcProcess, nil
}
defer func() {
testingImpl.EnterContainerFunc = nil
os.Remove(pidFilePath)
}()
fn, ok := execCLICommand.Action.(func(context *cli.Context) error)
assert.True(ok)
// vcAnnotations.EnvVars error due to incorrect environment
err = fn(ctx)
exitErr, ok := err.(*cli.ExitError)
assert.True(ok, true, "Exit code not received for fake workload process")
assert.Equal(exitErr.ExitCode(), 0, "Exit code should have been 0 for empty environment variable value")
}
func TestGenerateExecParams(t *testing.T) {
assert := assert.New(t)
tmpdir, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(tmpdir)
pidFilePath := filepath.Join(tmpdir, "pid")
consolePath := "/dev/ptmx"
consoleSocket := "/tmp/console-sock"
processLabel := "testlabel"
user := "root"
cwd := "cwd"
apparmor := "apparmorProf"
flagSet := flag.NewFlagSet("", 0)
flagSet.String("pid-file", pidFilePath, "")
flagSet.String("console", consolePath, "")
flagSet.String("console-socket", consoleSocket, "")
flagSet.String("process-label", processLabel, "")
flagSet.String("user", user, "")
flagSet.String("cwd", cwd, "")
flagSet.String("apparmor", apparmor, "")
ctx := createCLIContext(flagSet)
process := &specs.Process{}
params, err := generateExecParams(ctx, process)
assert.NoError(err)
assert.Equal(params.pidFile, pidFilePath)
assert.Equal(params.console, consolePath)
assert.Equal(params.consoleSock, consoleSocket)
assert.Equal(params.processLabel, processLabel)
assert.Equal(params.noSubreaper, false)
assert.Equal(params.detach, false)
assert.Equal(params.ociProcess.Terminal, false)
assert.Equal(params.ociProcess.User.UID, uint32(0))
assert.Equal(params.ociProcess.User.GID, uint32(0))
assert.Equal(params.ociProcess.Cwd, cwd)
assert.Equal(params.ociProcess.ApparmorProfile, apparmor)
}
func TestGenerateExecParamsWithProcessJsonFile(t *testing.T) {
assert := assert.New(t)
tmpdir, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(tmpdir)
pidFilePath := filepath.Join(tmpdir, "pid")
consolePath := "/dev/ptmx"
consoleSocket := "/tmp/console-sock"
detach := true
processLabel := "testlabel"
flagSet := flag.NewFlagSet("", 0)
flagSet.String("pid-file", pidFilePath, "")
flagSet.String("console", consolePath, "")
flagSet.String("console-socket", consoleSocket, "")
flagSet.Bool("detach", detach, "")
flagSet.String("process-label", processLabel, "")
processPath := filepath.Join(tmpdir, "process.json")
flagSet.String("process", processPath, "")
flagSet.Parse([]string{testContainerID})
ctx := createCLIContext(flagSet)
processJSON := `{
"consoleSize": {
"height": 15,
"width": 15
},
"terminal": true,
"user": {
"uid": 0,
"gid": 0
},
"args": [
"sh"
],
"env": [
"TERM=xterm",
"foo=bar"
],
"cwd": "/"
}`
f, err := os.OpenFile(processPath, os.O_RDWR|os.O_CREATE, testFileMode)
assert.NoError(err)
_, err = f.WriteString(processJSON)
assert.NoError(err)
f.Close()
defer os.Remove(processPath)
process := &specs.Process{}
params, err := generateExecParams(ctx, process)
assert.NoError(err)
assert.Equal(params.pidFile, pidFilePath)
assert.Equal(params.console, consolePath)
assert.Equal(params.consoleSock, consoleSocket)
assert.Equal(params.processLabel, processLabel)
assert.Equal(params.noSubreaper, false)
assert.Equal(params.detach, detach)
assert.Equal(params.ociProcess.Terminal, true)
assert.Equal(params.ociProcess.ConsoleSize.Height, uint(15))
assert.Equal(params.ociProcess.ConsoleSize.Width, uint(15))
assert.Equal(params.ociProcess.User.UID, uint32(0))
assert.Equal(params.ociProcess.User.GID, uint32(0))
assert.Equal(params.ociProcess.Cwd, "/")
assert.Equal(params.ociProcess.Env[0], "TERM=xterm")
assert.Equal(params.ociProcess.Env[1], "foo=bar")
}