diff --git a/libcontainer/integration/bench_test.go b/libcontainer/integration/bench_test.go new file mode 100644 index 00000000000..da95b20b0b7 --- /dev/null +++ b/libcontainer/integration/bench_test.go @@ -0,0 +1,51 @@ +package integration + +import ( + "os" + "testing" + + "github.com/opencontainers/runc/libcontainer" +) + +func BenchmarkExecTrue(b *testing.B) { + config := newTemplateConfig(b, nil) + container, err := newContainer(b, config) + ok(b, err) + defer destroyContainer(container) + + // Execute a first process in the container + stdinR, stdinW, err := os.Pipe() + ok(b, err) + process := &libcontainer.Process{ + Cwd: "/", + Args: []string{"cat"}, + Env: standardEnvironment, + Stdin: stdinR, + Init: true, + } + err = container.Run(process) + _ = stdinR.Close() + defer func() { + _ = stdinW.Close() + if _, err := process.Wait(); err != nil { + b.Log(err) + } + }() + ok(b, err) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + exec := &libcontainer.Process{ + Cwd: "/", + Args: []string{"/bin/true"}, + Env: standardEnvironment, + LogLevel: "0", // Minimize forwardChildLogs involvement. + } + err := container.Run(exec) + if err != nil { + b.Fatal("exec failed:", err) + } + waitProcess(exec, b) + } + b.StopTimer() +} diff --git a/libcontainer/integration/template_test.go b/libcontainer/integration/template_test.go index 473f601ed49..38024c571d3 100644 --- a/libcontainer/integration/template_test.go +++ b/libcontainer/integration/template_test.go @@ -32,7 +32,7 @@ type tParam struct { // and the default setup for devices. // // If p is nil, a default container is created. -func newTemplateConfig(t *testing.T, p *tParam) *configs.Config { +func newTemplateConfig(t testing.TB, p *tParam) *configs.Config { var allowedDevices []*devices.Rule for _, device := range specconv.AllowedDevices { allowedDevices = append(allowedDevices, &device.Rule) diff --git a/libcontainer/integration/utils_test.go b/libcontainer/integration/utils_test.go index 780288ad02b..9b4121bc5d6 100644 --- a/libcontainer/integration/utils_test.go +++ b/libcontainer/integration/utils_test.go @@ -85,7 +85,7 @@ func ok(t testing.TB, err error) { } } -func waitProcess(p *libcontainer.Process, t *testing.T) { +func waitProcess(p *libcontainer.Process, t testing.TB) { t.Helper() status, err := p.Wait() if err != nil { @@ -99,7 +99,7 @@ func waitProcess(p *libcontainer.Process, t *testing.T) { // newRootfs creates a new tmp directory and copies the busybox root // filesystem to it. -func newRootfs(t *testing.T) string { +func newRootfs(t testing.TB) string { t.Helper() dir := t.TempDir() if err := copyBusybox(dir); err != nil { @@ -165,7 +165,7 @@ func copyBusybox(dest string) error { return nil } -func newContainer(t *testing.T, config *configs.Config) (*libcontainer.Container, error) { +func newContainer(t testing.TB, config *configs.Config) (*libcontainer.Container, error) { name := strings.ReplaceAll(t.Name(), "/", "_") + strconv.FormatInt(-int64(time.Now().Nanosecond()), 35) root := t.TempDir() @@ -176,7 +176,7 @@ func newContainer(t *testing.T, config *configs.Config) (*libcontainer.Container // // buffers are returned containing the STDOUT and STDERR output for the run // along with the exit code and any go error -func runContainer(t *testing.T, config *configs.Config, args ...string) (buffers *stdBuffers, exitCode int, err error) { +func runContainer(t testing.TB, config *configs.Config, args ...string) (buffers *stdBuffers, exitCode int, err error) { container, err := newContainer(t, config) if err != nil { return nil, -1, err @@ -214,7 +214,7 @@ func runContainer(t *testing.T, config *configs.Config, args ...string) (buffers // runContainerOk is a wrapper for runContainer, simplifying its use for cases // when the run is expected to succeed and return exit code of 0. -func runContainerOk(t *testing.T, config *configs.Config, args ...string) *stdBuffers { +func runContainerOk(t testing.TB, config *configs.Config, args ...string) *stdBuffers { buffers, exitCode, err := runContainer(t, config, args...) t.Helper()