mirror of
				https://github.com/opencontainers/runc.git
				synced 2025-10-31 11:06:21 +08:00 
			
		
		
		
	 36be6d0510
			
		
	
	36be6d0510
	
	
	
		
			
			Since we're now testing on ARM, the test case fails when trying to do
pre-dump since MemTrack is not available.
Skip the pre-dump part if so.
This also reverts part of commit 3f4a73d6 as it is no longer needed
(now, instead of skipping the whole test, we're just skipping the
pre-dump).
[Review with --ignore-all-space]
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
		
	
		
			
				
	
	
		
			172 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			172 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package integration
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"os"
 | |
| 	"os/exec"
 | |
| 	"path/filepath"
 | |
| 	"regexp"
 | |
| 	"strings"
 | |
| 	"testing"
 | |
| 
 | |
| 	"github.com/opencontainers/runc/libcontainer"
 | |
| 	"golang.org/x/sys/unix"
 | |
| )
 | |
| 
 | |
| func criuFeature(feature string) bool {
 | |
| 	return exec.Command("criu", "check", "--feature", feature).Run() == nil
 | |
| }
 | |
| 
 | |
| func TestUsernsCheckpoint(t *testing.T) {
 | |
| 	testCheckpoint(t, true)
 | |
| }
 | |
| 
 | |
| func TestCheckpoint(t *testing.T) {
 | |
| 	testCheckpoint(t, false)
 | |
| }
 | |
| 
 | |
| func testCheckpoint(t *testing.T, userns bool) {
 | |
| 	if testing.Short() {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	if _, err := exec.LookPath("criu"); err != nil {
 | |
| 		t.Skipf("criu binary not found: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Workaround for https://github.com/opencontainers/runc/issues/3532.
 | |
| 	out, err := exec.Command("rpm", "-q", "criu").CombinedOutput()
 | |
| 	if err == nil && regexp.MustCompile(`^criu-3\.17-[123]\.el9`).Match(out) {
 | |
| 		t.Skip("Test requires criu >= 3.17-4 on CentOS Stream 9.")
 | |
| 	}
 | |
| 
 | |
| 	if userns && !criuFeature("userns") {
 | |
| 		t.Skip("Test requires userns")
 | |
| 	}
 | |
| 
 | |
| 	config := newTemplateConfig(t, &tParam{userns: userns})
 | |
| 	stateDir := t.TempDir()
 | |
| 
 | |
| 	container, err := libcontainer.Create(stateDir, "test", config)
 | |
| 	ok(t, err)
 | |
| 	defer destroyContainer(container)
 | |
| 
 | |
| 	stdinR, stdinW, err := os.Pipe()
 | |
| 	ok(t, err)
 | |
| 
 | |
| 	var stdout bytes.Buffer
 | |
| 
 | |
| 	pconfig := libcontainer.Process{
 | |
| 		Cwd:    "/",
 | |
| 		Args:   []string{"cat"},
 | |
| 		Env:    standardEnvironment,
 | |
| 		Stdin:  stdinR,
 | |
| 		Stdout: &stdout,
 | |
| 		Init:   true,
 | |
| 	}
 | |
| 
 | |
| 	err = container.Run(&pconfig)
 | |
| 	_ = stdinR.Close()
 | |
| 	defer stdinW.Close() //nolint: errcheck
 | |
| 	ok(t, err)
 | |
| 
 | |
| 	pid, err := pconfig.Pid()
 | |
| 	ok(t, err)
 | |
| 
 | |
| 	process, err := os.FindProcess(pid)
 | |
| 	ok(t, err)
 | |
| 
 | |
| 	tmp := t.TempDir()
 | |
| 	var parentImage string
 | |
| 
 | |
| 	// Test pre-dump if mem_dirty_track is available.
 | |
| 	if criuFeature("mem_dirty_track") {
 | |
| 		parentImage = "../criu-parent"
 | |
| 		parentDir := filepath.Join(tmp, "criu-parent")
 | |
| 		preDumpOpts := &libcontainer.CriuOpts{
 | |
| 			ImagesDirectory: parentDir,
 | |
| 			WorkDirectory:   parentDir,
 | |
| 			PreDump:         true,
 | |
| 		}
 | |
| 
 | |
| 		if err := container.Checkpoint(preDumpOpts); err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 
 | |
| 		state, err := container.Status()
 | |
| 		ok(t, err)
 | |
| 
 | |
| 		if state != libcontainer.Running {
 | |
| 			t.Fatal("Unexpected preDump state: ", state)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	imagesDir := filepath.Join(tmp, "criu")
 | |
| 
 | |
| 	checkpointOpts := &libcontainer.CriuOpts{
 | |
| 		ImagesDirectory: imagesDir,
 | |
| 		WorkDirectory:   imagesDir,
 | |
| 		ParentImage:     parentImage,
 | |
| 	}
 | |
| 
 | |
| 	if err := container.Checkpoint(checkpointOpts); err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	state, err := container.Status()
 | |
| 	ok(t, err)
 | |
| 
 | |
| 	if state != libcontainer.Stopped {
 | |
| 		t.Fatal("Unexpected state checkpoint: ", state)
 | |
| 	}
 | |
| 
 | |
| 	_ = stdinW.Close()
 | |
| 	_, err = process.Wait()
 | |
| 	ok(t, err)
 | |
| 
 | |
| 	// reload the container
 | |
| 	container, err = libcontainer.Load(stateDir, "test")
 | |
| 	ok(t, err)
 | |
| 
 | |
| 	restoreStdinR, restoreStdinW, err := os.Pipe()
 | |
| 	ok(t, err)
 | |
| 
 | |
| 	var restoreStdout bytes.Buffer
 | |
| 	restoreProcessConfig := &libcontainer.Process{
 | |
| 		Cwd:    "/",
 | |
| 		Stdin:  restoreStdinR,
 | |
| 		Stdout: &restoreStdout,
 | |
| 		Init:   true,
 | |
| 	}
 | |
| 
 | |
| 	err = container.Restore(restoreProcessConfig, checkpointOpts)
 | |
| 	_ = restoreStdinR.Close()
 | |
| 	defer restoreStdinW.Close() //nolint: errcheck
 | |
| 	if err != nil {
 | |
| 		t.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	state, err = container.Status()
 | |
| 	ok(t, err)
 | |
| 	if state != libcontainer.Running {
 | |
| 		t.Fatal("Unexpected restore state: ", state)
 | |
| 	}
 | |
| 
 | |
| 	pid, err = restoreProcessConfig.Pid()
 | |
| 	ok(t, err)
 | |
| 
 | |
| 	err = unix.Kill(pid, 0)
 | |
| 	ok(t, err)
 | |
| 
 | |
| 	_, err = restoreStdinW.WriteString("Hello!")
 | |
| 	ok(t, err)
 | |
| 
 | |
| 	_ = restoreStdinW.Close()
 | |
| 	waitProcess(restoreProcessConfig, t)
 | |
| 
 | |
| 	output := restoreStdout.String()
 | |
| 	if !strings.Contains(output, "Hello!") {
 | |
| 		t.Fatal("Did not restore the pipe correctly:", output)
 | |
| 	}
 | |
| }
 |