github.com/bowei/containerd@v0.2.5/runtime/runtime_test.go (about)

     1  package runtime
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"os/exec"
     9  	"path/filepath"
    10  	"syscall"
    11  	"testing"
    12  	"time"
    13  
    14  	utils "github.com/docker/containerd/testutils"
    15  )
    16  
    17  var (
    18  	devNull     = "/dev/null"
    19  	stdin       io.WriteCloser
    20  	runtimeTool = flag.String("runtime", "runc", "Runtime to use for this test")
    21  )
    22  
    23  // Create containerd state and oci bundles directory
    24  func setup() error {
    25  	if err := os.MkdirAll(utils.StateDir, 0755); err != nil {
    26  		return err
    27  	}
    28  
    29  	if err := os.MkdirAll(utils.BundlesRoot, 0755); err != nil {
    30  		return err
    31  	}
    32  	return nil
    33  }
    34  
    35  // Creates the bundleDir with rootfs, io fifo dir and a default spec.
    36  // On success, returns the bundlePath
    37  func setupBundle(bundleName string) (string, error) {
    38  	bundlePath := filepath.Join(utils.BundlesRoot, bundleName)
    39  	if err := os.MkdirAll(bundlePath, 0755); err != nil {
    40  		fmt.Println("Unable to create bundlePath due to ", err)
    41  		return "", err
    42  	}
    43  
    44  	io := filepath.Join(bundlePath, "io")
    45  	if err := os.MkdirAll(io, 0755); err != nil {
    46  		fmt.Println("Unable to create io dir due to ", err)
    47  		return "", err
    48  	}
    49  
    50  	if err := utils.GenerateReferenceSpecs(bundlePath); err != nil {
    51  		fmt.Println("Unable to generate OCI reference spec: ", err)
    52  		return "", err
    53  	}
    54  
    55  	if err := utils.CreateBusyboxBundle(bundleName); err != nil {
    56  		fmt.Println("CreateBusyboxBundle error: ", err)
    57  		return "", err
    58  	}
    59  
    60  	return bundlePath, nil
    61  }
    62  
    63  func setupStdio(cwd string, bundlePath string, bundleName string) (Stdio, error) {
    64  	s := NewStdio(devNull, devNull, devNull)
    65  
    66  	pid := "init"
    67  	for stdName, stdPath := range map[string]*string{
    68  		"stdin":  &s.Stdin,
    69  		"stdout": &s.Stdout,
    70  		"stderr": &s.Stderr,
    71  	} {
    72  		*stdPath = filepath.Join(cwd, bundlePath, "io", bundleName+"-"+pid+"-"+stdName)
    73  		if err := syscall.Mkfifo(*stdPath, 0755); err != nil && !os.IsExist(err) {
    74  			fmt.Println("Mkfifo error: ", err)
    75  			return s, err
    76  		}
    77  	}
    78  
    79  	err := attachStdio(s)
    80  	if err != nil {
    81  		fmt.Println("attachStdio error: ", err)
    82  		return s, err
    83  	}
    84  
    85  	return s, nil
    86  }
    87  
    88  func attachStdio(s Stdio) error {
    89  	stdinf, err := os.OpenFile(s.Stdin, syscall.O_RDWR, 0)
    90  	if err != nil {
    91  		return err
    92  	}
    93  	stdin = stdinf
    94  	stdoutf, err := os.OpenFile(s.Stdout, syscall.O_RDWR, 0)
    95  	if err != nil {
    96  		return err
    97  	}
    98  	go io.Copy(os.Stdout, stdoutf)
    99  	stderrf, err := os.OpenFile(s.Stderr, syscall.O_RDWR, 0)
   100  	if err != nil {
   101  		return err
   102  	}
   103  	go io.Copy(os.Stderr, stderrf)
   104  	return nil
   105  }
   106  
   107  func teardownBundle(bundleName string) {
   108  	containerRoot := filepath.Join(utils.StateDir, bundleName)
   109  	os.RemoveAll(containerRoot)
   110  
   111  	bundlePath := filepath.Join(utils.BundlesRoot, bundleName)
   112  	os.RemoveAll(bundlePath)
   113  	return
   114  }
   115  
   116  // Remove containerd state and oci bundles directory
   117  func teardown() {
   118  	os.RemoveAll(utils.StateDir)
   119  	os.RemoveAll(utils.BundlesRoot)
   120  }
   121  
   122  func BenchmarkBusyboxSh(b *testing.B) {
   123  	bundleName := "busybox-sh"
   124  
   125  	wd := utils.GetTestOutDir()
   126  	if err := os.Chdir(wd); err != nil {
   127  		b.Fatalf("Could not change working directory: %v", err)
   128  	}
   129  
   130  	if err := setup(); err != nil {
   131  		b.Fatalf("Error setting up test: %v", err)
   132  	}
   133  	defer teardown()
   134  
   135  	for n := 0; n < b.N; n++ {
   136  		bundlePath, err := setupBundle(bundleName)
   137  		if err != nil {
   138  			return
   139  		}
   140  
   141  		s, err := setupStdio(wd, bundlePath, bundleName)
   142  		if err != nil {
   143  			return
   144  		}
   145  
   146  		c, err := New(ContainerOpts{
   147  			Root:    utils.StateDir,
   148  			ID:      bundleName,
   149  			Bundle:  filepath.Join(wd, bundlePath),
   150  			Runtime: *runtimeTool,
   151  			Shim:    "containerd-shim",
   152  			Timeout: 15 * time.Second,
   153  		})
   154  
   155  		if err != nil {
   156  			b.Fatalf("Error creating a New container: ", err)
   157  		}
   158  
   159  		benchmarkStartContainer(b, c, s, bundleName)
   160  
   161  		teardownBundle(bundleName)
   162  	}
   163  }
   164  
   165  func benchmarkStartContainer(b *testing.B, c Container, s Stdio, bundleName string) {
   166  	p, err := c.Start("", s)
   167  	if err != nil {
   168  		b.Fatalf("Error starting container %v", err)
   169  	}
   170  
   171  	kill := exec.Command(c.Runtime(), "kill", bundleName, "KILL")
   172  	kill.Run()
   173  
   174  	p.Wait()
   175  	c.Delete()
   176  
   177  	// wait for kill to finish. selected wait time is arbitrary
   178  	time.Sleep(500 * time.Millisecond)
   179  
   180  }