...

Source file src/github.com/opencontainers/runc/libcontainer/factory_linux_test.go

Documentation: github.com/opencontainers/runc/libcontainer

     1  package libcontainer
     2  
     3  import (
     4  	"errors"
     5  	"os"
     6  	"path/filepath"
     7  	"reflect"
     8  	"testing"
     9  
    10  	"github.com/moby/sys/mountinfo"
    11  	"github.com/opencontainers/runc/libcontainer/configs"
    12  	"github.com/opencontainers/runc/libcontainer/utils"
    13  	"github.com/opencontainers/runtime-spec/specs-go"
    14  
    15  	"golang.org/x/sys/unix"
    16  )
    17  
    18  func TestFactoryNew(t *testing.T) {
    19  	root := t.TempDir()
    20  	factory, err := New(root)
    21  	if err != nil {
    22  		t.Fatal(err)
    23  	}
    24  	if factory == nil {
    25  		t.Fatal("factory should not be nil")
    26  	}
    27  	lfactory, ok := factory.(*LinuxFactory)
    28  	if !ok {
    29  		t.Fatal("expected linux factory returned on linux based systems")
    30  	}
    31  	if lfactory.Root != root {
    32  		t.Fatalf("expected factory root to be %q but received %q", root, lfactory.Root)
    33  	}
    34  
    35  	if factory.Type() != "libcontainer" {
    36  		t.Fatalf("unexpected factory type: %q, expected %q", factory.Type(), "libcontainer")
    37  	}
    38  }
    39  
    40  func TestFactoryNewTmpfs(t *testing.T) {
    41  	root := t.TempDir()
    42  	factory, err := New(root, TmpfsRoot)
    43  	if err != nil {
    44  		t.Fatal(err)
    45  	}
    46  	if factory == nil {
    47  		t.Fatal("factory should not be nil")
    48  	}
    49  	lfactory, ok := factory.(*LinuxFactory)
    50  	if !ok {
    51  		t.Fatal("expected linux factory returned on linux based systems")
    52  	}
    53  	if lfactory.Root != root {
    54  		t.Fatalf("expected factory root to be %q but received %q", root, lfactory.Root)
    55  	}
    56  
    57  	if factory.Type() != "libcontainer" {
    58  		t.Fatalf("unexpected factory type: %q, expected %q", factory.Type(), "libcontainer")
    59  	}
    60  	mounted, err := mountinfo.Mounted(lfactory.Root)
    61  	if err != nil {
    62  		t.Fatal(err)
    63  	}
    64  	if !mounted {
    65  		t.Fatalf("Factory Root is not mounted")
    66  	}
    67  	mounts, err := mountinfo.GetMounts(mountinfo.SingleEntryFilter(lfactory.Root))
    68  	if err != nil {
    69  		t.Fatal(err)
    70  	}
    71  	if len(mounts) != 1 {
    72  		t.Fatalf("Factory Root is not listed in mounts list")
    73  	}
    74  	m := mounts[0]
    75  	if m.FSType != "tmpfs" {
    76  		t.Fatalf("FSType of root: %s, expected %s", m.FSType, "tmpfs")
    77  	}
    78  	if m.Source != "tmpfs" {
    79  		t.Fatalf("Source of root: %s, expected %s", m.Source, "tmpfs")
    80  	}
    81  	err = unix.Unmount(root, unix.MNT_DETACH)
    82  	if err != nil {
    83  		t.Error("failed to unmount root:", err)
    84  	}
    85  }
    86  
    87  func TestFactoryLoadNotExists(t *testing.T) {
    88  	factory, err := New(t.TempDir())
    89  	if err != nil {
    90  		t.Fatal(err)
    91  	}
    92  	_, err = factory.Load("nocontainer")
    93  	if err == nil {
    94  		t.Fatal("expected nil error loading non-existing container")
    95  	}
    96  	if !errors.Is(err, ErrNotExist) {
    97  		t.Fatalf("expected ErrNotExist, got %v", err)
    98  	}
    99  }
   100  
   101  func TestFactoryLoadContainer(t *testing.T) {
   102  	root := t.TempDir()
   103  	// setup default container config and state for mocking
   104  	var (
   105  		id            = "1"
   106  		expectedHooks = configs.Hooks{
   107  			configs.Prestart: configs.HookList{
   108  				configs.CommandHook{Command: configs.Command{Path: "prestart-hook"}},
   109  			},
   110  			configs.Poststart: configs.HookList{
   111  				configs.CommandHook{Command: configs.Command{Path: "poststart-hook"}},
   112  			},
   113  			configs.Poststop: configs.HookList{
   114  				unserializableHook{},
   115  				configs.CommandHook{Command: configs.Command{Path: "poststop-hook"}},
   116  			},
   117  		}
   118  		expectedConfig = &configs.Config{
   119  			Rootfs: "/mycontainer/root",
   120  			Hooks:  expectedHooks,
   121  			Cgroups: &configs.Cgroup{
   122  				Resources: &configs.Resources{},
   123  			},
   124  		}
   125  		expectedState = &State{
   126  			BaseState: BaseState{
   127  				InitProcessPid: 1024,
   128  				Config:         *expectedConfig,
   129  			},
   130  		}
   131  	)
   132  	if err := os.Mkdir(filepath.Join(root, id), 0o700); err != nil {
   133  		t.Fatal(err)
   134  	}
   135  	if err := marshal(filepath.Join(root, id, stateFilename), expectedState); err != nil {
   136  		t.Fatal(err)
   137  	}
   138  	factory, err := New(root)
   139  	if err != nil {
   140  		t.Fatal(err)
   141  	}
   142  	container, err := factory.Load(id)
   143  	if err != nil {
   144  		t.Fatal(err)
   145  	}
   146  	if container.ID() != id {
   147  		t.Fatalf("expected container id %q but received %q", id, container.ID())
   148  	}
   149  	config := container.Config()
   150  	if config.Rootfs != expectedConfig.Rootfs {
   151  		t.Fatalf("expected rootfs %q but received %q", expectedConfig.Rootfs, config.Rootfs)
   152  	}
   153  	expectedHooks[configs.Poststop] = expectedHooks[configs.Poststop][1:] // expect unserializable hook to be skipped
   154  	if !reflect.DeepEqual(config.Hooks, expectedHooks) {
   155  		t.Fatalf("expects hooks %q but received %q", expectedHooks, config.Hooks)
   156  	}
   157  	lcontainer, ok := container.(*linuxContainer)
   158  	if !ok {
   159  		t.Fatal("expected linux container on linux based systems")
   160  	}
   161  	if lcontainer.initProcess.pid() != expectedState.InitProcessPid {
   162  		t.Fatalf("expected init pid %d but received %d", expectedState.InitProcessPid, lcontainer.initProcess.pid())
   163  	}
   164  }
   165  
   166  func marshal(path string, v interface{}) error {
   167  	f, err := os.Create(path)
   168  	if err != nil {
   169  		return err
   170  	}
   171  	defer f.Close() //nolint: errcheck
   172  	return utils.WriteJSON(f, v)
   173  }
   174  
   175  type unserializableHook struct{}
   176  
   177  func (unserializableHook) Run(*specs.State) error {
   178  	return nil
   179  }
   180  

View as plain text