Add testing for linux factory Load
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
parent
7760faaab4
commit
926ab56ea8
60
container.go
60
container.go
|
@ -9,30 +9,30 @@ type ContainerInfo interface {
|
||||||
|
|
||||||
// Returns the current run state of the container.
|
// Returns the current run state of the container.
|
||||||
//
|
//
|
||||||
// Errors:
|
// errors:
|
||||||
// ContainerDestroyed - Container no longer exists,
|
// ContainerDestroyed - Container no longer exists,
|
||||||
// SystemError - System error.
|
// Systemerror - System error.
|
||||||
RunState() (*RunState, Error)
|
RunState() (*RunState, error)
|
||||||
|
|
||||||
// Returns the current config of the container.
|
// Returns the current config of the container.
|
||||||
Config() *Config
|
Config() *Config
|
||||||
|
|
||||||
// Returns the PIDs inside this container. The PIDs are in the namespace of the calling process.
|
// Returns the PIDs inside this container. The PIDs are in the namespace of the calling process.
|
||||||
//
|
//
|
||||||
// Errors:
|
// errors:
|
||||||
// ContainerDestroyed - Container no longer exists,
|
// ContainerDestroyed - Container no longer exists,
|
||||||
// SystemError - System error.
|
// Systemerror - System error.
|
||||||
//
|
//
|
||||||
// Some of the returned PIDs may no longer refer to processes in the Container, unless
|
// Some of the returned PIDs may no longer refer to processes in the Container, unless
|
||||||
// the Container state is PAUSED in which case every PID in the slice is valid.
|
// the Container state is PAUSED in which case every PID in the slice is valid.
|
||||||
Processes() ([]int, Error)
|
Processes() ([]int, error)
|
||||||
|
|
||||||
// Returns statistics for the container.
|
// Returns statistics for the container.
|
||||||
//
|
//
|
||||||
// Errors:
|
// errors:
|
||||||
// ContainerDestroyed - Container no longer exists,
|
// ContainerDestroyed - Container no longer exists,
|
||||||
// SystemError - System error.
|
// Systemerror - System error.
|
||||||
Stats() (*ContainerStats, Error)
|
Stats() (*ContainerStats, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A libcontainer container object.
|
// A libcontainer container object.
|
||||||
|
@ -45,60 +45,60 @@ type Container interface {
|
||||||
|
|
||||||
// Start a process inside the container. Returns the PID of the new process (in the caller process's namespace) and a channel that will return the exit status of the process whenever it dies.
|
// Start a process inside the container. Returns the PID of the new process (in the caller process's namespace) and a channel that will return the exit status of the process whenever it dies.
|
||||||
//
|
//
|
||||||
// Errors:
|
// errors:
|
||||||
// ContainerDestroyed - Container no longer exists,
|
// ContainerDestroyed - Container no longer exists,
|
||||||
// ConfigInvalid - config is invalid,
|
// ConfigInvalid - config is invalid,
|
||||||
// ContainerPaused - Container is paused,
|
// ContainerPaused - Container is paused,
|
||||||
// SystemError - System error.
|
// Systemerror - System error.
|
||||||
StartProcess(config *ProcessConfig) (pid int, err Error)
|
StartProcess(config *ProcessConfig) (pid int, err error)
|
||||||
|
|
||||||
// Destroys the container after killing all running processes.
|
// Destroys the container after killing all running processes.
|
||||||
//
|
//
|
||||||
// Any event registrations are removed before the container is destroyed.
|
// Any event registrations are removed before the container is destroyed.
|
||||||
// No error is returned if the container is already destroyed.
|
// No error is returned if the container is already destroyed.
|
||||||
//
|
//
|
||||||
// Errors:
|
// errors:
|
||||||
// SystemError - System error.
|
// Systemerror - System error.
|
||||||
Destroy() Error
|
Destroy() error
|
||||||
|
|
||||||
// If the Container state is RUNNING or PAUSING, sets the Container state to PAUSING and pauses
|
// If the Container state is RUNNING or PAUSING, sets the Container state to PAUSING and pauses
|
||||||
// the execution of any user processes. Asynchronously, when the container finished being paused the
|
// the execution of any user processes. Asynchronously, when the container finished being paused the
|
||||||
// state is changed to PAUSED.
|
// state is changed to PAUSED.
|
||||||
// If the Container state is PAUSED, do nothing.
|
// If the Container state is PAUSED, do nothing.
|
||||||
//
|
//
|
||||||
// Errors:
|
// errors:
|
||||||
// ContainerDestroyed - Container no longer exists,
|
// ContainerDestroyed - Container no longer exists,
|
||||||
// SystemError - System error.
|
// Systemerror - System error.
|
||||||
Pause() Error
|
Pause() error
|
||||||
|
|
||||||
// If the Container state is PAUSED, resumes the execution of any user processes in the
|
// If the Container state is PAUSED, resumes the execution of any user processes in the
|
||||||
// Container before setting the Container state to RUNNING.
|
// Container before setting the Container state to RUNNING.
|
||||||
// If the Container state is RUNNING, do nothing.
|
// If the Container state is RUNNING, do nothing.
|
||||||
//
|
//
|
||||||
// Errors:
|
// errors:
|
||||||
// ContainerDestroyed - Container no longer exists,
|
// ContainerDestroyed - Container no longer exists,
|
||||||
// SystemError - System error.
|
// Systemerror - System error.
|
||||||
Resume() Error
|
Resume() error
|
||||||
|
|
||||||
// Signal sends the specified signal to a process owned by the container.
|
// Signal sends the specified signal to a process owned by the container.
|
||||||
//
|
//
|
||||||
// Errors:
|
// errors:
|
||||||
// ContainerDestroyed - Container no longer exists,
|
// ContainerDestroyed - Container no longer exists,
|
||||||
// ContainerPaused - Container is paused,
|
// ContainerPaused - Container is paused,
|
||||||
// SystemError - System error.
|
// Systemerror - System error.
|
||||||
Signal(pid, signal int) Error
|
Signal(pid, signal int) error
|
||||||
|
|
||||||
// Wait waits for the init process of the conatiner to die and returns it's exit status.
|
// Wait waits for the init process of the conatiner to die and returns it's exit status.
|
||||||
//
|
//
|
||||||
// Errors:
|
// errors:
|
||||||
// ContainerDestroyed - Container no longer exists,
|
// ContainerDestroyed - Container no longer exists,
|
||||||
// SystemError - System error.
|
// Systemerror - System error.
|
||||||
Wait() (exitStatus int, err Error)
|
Wait() (exitStatus int, err error)
|
||||||
|
|
||||||
// WaitProcess waits on a process owned by the container.
|
// WaitProcess waits on a process owned by the container.
|
||||||
//
|
//
|
||||||
// Errors:
|
// errors:
|
||||||
// ContainerDestroyed - Container no longer exists,
|
// ContainerDestroyed - Container no longer exists,
|
||||||
// SystemError - System error.
|
// Systemerror - System error.
|
||||||
WaitProcess(pid int) (exitStatus int, err Error)
|
WaitProcess(pid int) (exitStatus int, err error)
|
||||||
}
|
}
|
||||||
|
|
12
error.go
12
error.go
|
@ -1,5 +1,7 @@
|
||||||
package libcontainer
|
package libcontainer
|
||||||
|
|
||||||
|
import "io"
|
||||||
|
|
||||||
// API error code type.
|
// API error code type.
|
||||||
type ErrorCode int
|
type ErrorCode int
|
||||||
|
|
||||||
|
@ -10,7 +12,7 @@ const (
|
||||||
InvalidIdFormat
|
InvalidIdFormat
|
||||||
|
|
||||||
// Container errors
|
// Container errors
|
||||||
ContainerDestroyed
|
ContainerNotExists
|
||||||
ContainerPaused
|
ContainerPaused
|
||||||
|
|
||||||
// Common errors
|
// Common errors
|
||||||
|
@ -24,14 +26,14 @@ func (c ErrorCode) String() string {
|
||||||
return "Id already in use"
|
return "Id already in use"
|
||||||
case InvalidIdFormat:
|
case InvalidIdFormat:
|
||||||
return "Invalid format"
|
return "Invalid format"
|
||||||
case ContainerDestroyed:
|
|
||||||
return "Container destroyed"
|
|
||||||
case ContainerPaused:
|
case ContainerPaused:
|
||||||
return "Container paused"
|
return "Container paused"
|
||||||
case ConfigInvalid:
|
case ConfigInvalid:
|
||||||
return "Invalid configuration"
|
return "Invalid configuration"
|
||||||
case SystemError:
|
case SystemError:
|
||||||
return "System Error"
|
return "System error"
|
||||||
|
case ContainerNotExists:
|
||||||
|
return "Container does not exist"
|
||||||
default:
|
default:
|
||||||
return "Unknown error"
|
return "Unknown error"
|
||||||
}
|
}
|
||||||
|
@ -44,7 +46,7 @@ type Error interface {
|
||||||
// Returns a verbose string including the error message
|
// Returns a verbose string including the error message
|
||||||
// and a representation of the stack trace suitable for
|
// and a representation of the stack trace suitable for
|
||||||
// printing.
|
// printing.
|
||||||
Detail() string
|
Detail(w io.Writer) error
|
||||||
|
|
||||||
// Returns the error code for this error.
|
// Returns the error code for this error.
|
||||||
Code() ErrorCode
|
Code() ErrorCode
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package libcontainer
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestErrorCode(t *testing.T) {
|
||||||
|
codes := map[ErrorCode]string{
|
||||||
|
IdInUse: "Id already in use",
|
||||||
|
InvalidIdFormat: "Invalid format",
|
||||||
|
ContainerPaused: "Container paused",
|
||||||
|
ConfigInvalid: "Invalid configuration",
|
||||||
|
SystemError: "System error",
|
||||||
|
ContainerNotExists: "Container does not exist",
|
||||||
|
}
|
||||||
|
|
||||||
|
for code, expected := range codes {
|
||||||
|
if actual := code.String(); actual != expected {
|
||||||
|
t.Fatalf("expected string %q but received %q", expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
factory.go
10
factory.go
|
@ -10,21 +10,21 @@ type Factory interface {
|
||||||
//
|
//
|
||||||
// Returns the new container with a running process.
|
// Returns the new container with a running process.
|
||||||
//
|
//
|
||||||
// Errors:
|
// errors:
|
||||||
// IdInUse - id is already in use by a container
|
// IdInUse - id is already in use by a container
|
||||||
// InvalidIdFormat - id has incorrect format
|
// InvalidIdFormat - id has incorrect format
|
||||||
// ConfigInvalid - config is invalid
|
// ConfigInvalid - config is invalid
|
||||||
// SystemError - System error
|
// Systemerror - System error
|
||||||
//
|
//
|
||||||
// On error, any partially created container parts are cleaned up (the operation is atomic).
|
// On error, any partially created container parts are cleaned up (the operation is atomic).
|
||||||
Create(id string, config *Config) (Container, Error)
|
Create(id string, config *Config) (Container, error)
|
||||||
|
|
||||||
// Load takes an ID for an existing container and returns the container information
|
// Load takes an ID for an existing container and returns the container information
|
||||||
// from the state. This presents a read only view of the container.
|
// from the state. This presents a read only view of the container.
|
||||||
//
|
//
|
||||||
// Errors:
|
// errors:
|
||||||
// Path does not exist
|
// Path does not exist
|
||||||
// Container is stopped
|
// Container is stopped
|
||||||
// System error
|
// System error
|
||||||
Load(id string) (ContainerInfo, Error)
|
Load(id string) (ContainerInfo, error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,46 +1,48 @@
|
||||||
package libcontainer
|
package libcontainer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"io"
|
||||||
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/docker/libcontainer/stacktrace"
|
||||||
)
|
)
|
||||||
|
|
||||||
var newLine = []byte("\n")
|
var errorTemplate = template.Must(template.New("error").Parse(`Timestamp: {{.Timestamp}}
|
||||||
|
Code: {{.ECode}}
|
||||||
|
Message: {{.Err.Error}}
|
||||||
|
Frames:{{range $i, $frame := .Stack.Frames}}
|
||||||
|
---
|
||||||
|
{{$i}}: {{$frame.Function}}
|
||||||
|
Package: {{$frame.Package}}
|
||||||
|
File: {{$frame.File}}{{end}}
|
||||||
|
`))
|
||||||
|
|
||||||
func newGenericError(err error, c ErrorCode) Error {
|
func newGenericError(err error, c ErrorCode) Error {
|
||||||
return &GenericError{
|
return &GenericError{
|
||||||
timestamp: time.Now(),
|
Timestamp: time.Now(),
|
||||||
err: err,
|
Err: err,
|
||||||
code: c,
|
ECode: c,
|
||||||
stack: captureStackTrace(2),
|
Stack: stacktrace.Capture(2),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func captureStackTrace(skip int) string {
|
|
||||||
buf := make([]byte, 4096)
|
|
||||||
buf = buf[:runtime.Stack(buf, true)]
|
|
||||||
|
|
||||||
lines := bytes.Split(buf, newLine)
|
|
||||||
return string(bytes.Join(lines[skip:], newLine))
|
|
||||||
}
|
|
||||||
|
|
||||||
type GenericError struct {
|
type GenericError struct {
|
||||||
timestamp time.Time
|
Timestamp time.Time
|
||||||
code ErrorCode
|
ECode ErrorCode
|
||||||
err error
|
Err error
|
||||||
stack string
|
Stack stacktrace.Stacktrace
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *GenericError) Error() string {
|
func (e *GenericError) Error() string {
|
||||||
return fmt.Sprintf("[%d] %s: %s", e.code, e.code, e.err)
|
return fmt.Sprintf("[%d] %s: %s", e.ECode, e.ECode, e.Err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *GenericError) Code() ErrorCode {
|
func (e *GenericError) Code() ErrorCode {
|
||||||
return e.code
|
return e.ECode
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *GenericError) Detail() string {
|
func (e *GenericError) Detail(w io.Writer) error {
|
||||||
return fmt.Sprintf("[%d] %s\n%s", e.code, e.err, e.stack)
|
return errorTemplate.Execute(w, e)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package libcontainer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestErrorDetail(t *testing.T) {
|
||||||
|
err := newGenericError(fmt.Errorf("test error"), SystemError)
|
||||||
|
if derr := err.Detail(ioutil.Discard); derr != nil {
|
||||||
|
t.Fatal(derr)
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,11 +23,11 @@ func (c *linuxContainer) Config() *Config {
|
||||||
return c.config
|
return c.config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *linuxContainer) RunState() (*RunState, Error) {
|
func (c *linuxContainer) RunState() (*RunState, error) {
|
||||||
panic("not implemented")
|
panic("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *linuxContainer) Processes() ([]int, Error) {
|
func (c *linuxContainer) Processes() ([]int, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
pids []int
|
pids []int
|
||||||
|
@ -44,7 +44,7 @@ func (c *linuxContainer) Processes() ([]int, Error) {
|
||||||
return pids, nil
|
return pids, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *linuxContainer) Stats() (*ContainerStats, Error) {
|
func (c *linuxContainer) Stats() (*ContainerStats, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
stats = &ContainerStats{}
|
stats = &ContainerStats{}
|
||||||
|
|
|
@ -14,7 +14,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// New returns a linux based container factory based in the root directory.
|
// New returns a linux based container factory based in the root directory.
|
||||||
func New(root string) (Factory, Error) {
|
func New(root string) (Factory, error) {
|
||||||
if err := os.MkdirAll(root, 0700); err != nil {
|
if err := os.MkdirAll(root, 0700); err != nil {
|
||||||
return nil, newGenericError(err, SystemError)
|
return nil, newGenericError(err, SystemError)
|
||||||
}
|
}
|
||||||
|
@ -30,11 +30,11 @@ type linuxFactory struct {
|
||||||
root string
|
root string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *linuxFactory) Create(id string, config *Config) (Container, Error) {
|
func (l *linuxFactory) Create(id string, config *Config) (Container, error) {
|
||||||
panic("not implemented")
|
panic("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *linuxFactory) Load(id string) (ContainerInfo, Error) {
|
func (l *linuxFactory) Load(id string) (ContainerInfo, error) {
|
||||||
containerRoot := filepath.Join(l.root, id)
|
containerRoot := filepath.Join(l.root, id)
|
||||||
config, err := l.loadContainerConfig(containerRoot)
|
config, err := l.loadContainerConfig(containerRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -54,11 +54,11 @@ func (l *linuxFactory) Load(id string) (ContainerInfo, Error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *linuxFactory) loadContainerConfig(root string) (*Config, Error) {
|
func (l *linuxFactory) loadContainerConfig(root string) (*Config, error) {
|
||||||
f, err := os.Open(filepath.Join(root, configFilename))
|
f, err := os.Open(filepath.Join(root, configFilename))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return nil, newGenericError(err, ContainerDestroyed)
|
return nil, newGenericError(err, ContainerNotExists)
|
||||||
}
|
}
|
||||||
return nil, newGenericError(err, SystemError)
|
return nil, newGenericError(err, SystemError)
|
||||||
}
|
}
|
||||||
|
@ -71,11 +71,11 @@ func (l *linuxFactory) loadContainerConfig(root string) (*Config, Error) {
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *linuxFactory) loadContainerState(root string) (*State, Error) {
|
func (l *linuxFactory) loadContainerState(root string) (*State, error) {
|
||||||
f, err := os.Open(filepath.Join(root, stateFilename))
|
f, err := os.Open(filepath.Join(root, stateFilename))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return nil, newGenericError(err, ContainerDestroyed)
|
return nil, newGenericError(err, ContainerNotExists)
|
||||||
}
|
}
|
||||||
return nil, newGenericError(err, SystemError)
|
return nil, newGenericError(err, SystemError)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package libcontainer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newTestRoot() (string, error) {
|
||||||
|
dir, err := ioutil.TempDir("", "libcontainer")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll(dir, 0700); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return dir, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFactoryNew(t *testing.T) {
|
||||||
|
root, rerr := newTestRoot()
|
||||||
|
if rerr != nil {
|
||||||
|
t.Fatal(rerr)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(root)
|
||||||
|
|
||||||
|
factory, err := New(root)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if factory == nil {
|
||||||
|
t.Fatal("factory should not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
lfactory, ok := factory.(*linuxFactory)
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("expected linux factory returned on linux based systems")
|
||||||
|
}
|
||||||
|
|
||||||
|
if lfactory.root != root {
|
||||||
|
t.Fatalf("expected factory root to be %q but received %q", root, lfactory.root)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFactoryLoadNotExists(t *testing.T) {
|
||||||
|
root, rerr := newTestRoot()
|
||||||
|
if rerr != nil {
|
||||||
|
t.Fatal(rerr)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(root)
|
||||||
|
|
||||||
|
factory, err := New(root)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = factory.Load("nocontainer")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected nil error loading non-existing container")
|
||||||
|
}
|
||||||
|
|
||||||
|
lerr, ok := err.(Error)
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("expected libcontainer error type")
|
||||||
|
}
|
||||||
|
if lerr.Code() != ContainerNotExists {
|
||||||
|
t.Fatalf("expected error code %s but received %s", ContainerNotExists, lerr.Code())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFactoryLoadContainer(t *testing.T) {
|
||||||
|
root, err := newTestRoot()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(root)
|
||||||
|
|
||||||
|
// setup default container config and state for mocking
|
||||||
|
var (
|
||||||
|
id = "1"
|
||||||
|
expectedConfig = &Config{
|
||||||
|
RootFs: "/mycontainer/root",
|
||||||
|
}
|
||||||
|
expectedState = &State{
|
||||||
|
InitPid: 1024,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := os.Mkdir(filepath.Join(root, id), 0700); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := marshal(filepath.Join(root, id, configFilename), expectedConfig); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := marshal(filepath.Join(root, id, stateFilename), expectedState); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
factory, err := New(root)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
container, err := factory.Load(id)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if container.ID() != id {
|
||||||
|
t.Fatalf("expected container id %q but received %q", id, container.ID())
|
||||||
|
}
|
||||||
|
|
||||||
|
config := container.Config()
|
||||||
|
if config == nil {
|
||||||
|
t.Fatal("expected non nil container config")
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.RootFs != expectedConfig.RootFs {
|
||||||
|
t.Fatalf("expected rootfs %q but received %q", expectedConfig.RootFs, config.RootFs)
|
||||||
|
}
|
||||||
|
|
||||||
|
lcontainer, ok := container.(*linuxContainer)
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("expected linux container on linux based systems")
|
||||||
|
}
|
||||||
|
|
||||||
|
if lcontainer.state.InitPid != expectedState.InitPid {
|
||||||
|
t.Fatalf("expected init pid %d but received %d", expectedState.InitPid, lcontainer.state.InitPid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func marshal(path string, v interface{}) error {
|
||||||
|
f, err := os.Create(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
return json.NewEncoder(f).Encode(v)
|
||||||
|
}
|
Loading…
Reference in New Issue