229 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			229 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
| package libpod
 | |
| 
 | |
| import (
 | |
| 	"encoding/json"
 | |
| 	"net"
 | |
| 	"path/filepath"
 | |
| 	"reflect"
 | |
| 	"strings"
 | |
| 	"testing"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/containers/storage"
 | |
| 	"github.com/cri-o/ocicni/pkg/ocicni"
 | |
| 	"github.com/opencontainers/runtime-tools/generate"
 | |
| 	"github.com/stretchr/testify/assert"
 | |
| 	"github.com/stretchr/testify/require"
 | |
| )
 | |
| 
 | |
| func getTestContainer(id, name, locksDir string) (*Container, error) {
 | |
| 	ctr := &Container{
 | |
| 		config: &ContainerConfig{
 | |
| 			ID:              id,
 | |
| 			Name:            name,
 | |
| 			RootfsImageID:   id,
 | |
| 			RootfsImageName: "testimg",
 | |
| 			ImageVolumes:    true,
 | |
| 			StaticDir:       "/does/not/exist/",
 | |
| 			LogPath:         "/does/not/exist/",
 | |
| 			Stdin:           true,
 | |
| 			Labels:          map[string]string{"a": "b", "c": "d"},
 | |
| 			StopSignal:      0,
 | |
| 			StopTimeout:     0,
 | |
| 			CreatedTime:     time.Now(),
 | |
| 			Privileged:      true,
 | |
| 			Mounts:          []string{"/does/not/exist"},
 | |
| 			DNSServer:       []net.IP{net.ParseIP("192.168.1.1"), net.ParseIP("192.168.2.2")},
 | |
| 			DNSSearch:       []string{"example.com", "example.example.com"},
 | |
| 			PortMappings: []ocicni.PortMapping{
 | |
| 				{
 | |
| 					HostPort:      80,
 | |
| 					ContainerPort: 90,
 | |
| 					Protocol:      "tcp",
 | |
| 					HostIP:        "192.168.3.3",
 | |
| 				},
 | |
| 				{
 | |
| 					HostPort:      100,
 | |
| 					ContainerPort: 110,
 | |
| 					Protocol:      "udp",
 | |
| 					HostIP:        "192.168.4.4",
 | |
| 				},
 | |
| 			},
 | |
| 		},
 | |
| 		state: &containerState{
 | |
| 			State:      ContainerStateRunning,
 | |
| 			ConfigPath: "/does/not/exist/specs/" + id,
 | |
| 			RunDir:     "/does/not/exist/tmp/",
 | |
| 			Mounted:    true,
 | |
| 			Mountpoint: "/does/not/exist/tmp/" + id,
 | |
| 			PID:        1234,
 | |
| 			ExecSessions: map[string]*ExecSession{
 | |
| 				"abcd": {
 | |
| 					ID:      "1",
 | |
| 					Command: []string{"2", "3"},
 | |
| 					PID:     9876,
 | |
| 				},
 | |
| 				"ef01": {
 | |
| 					ID:      "5",
 | |
| 					Command: []string{"hello", "world"},
 | |
| 					PID:     46765,
 | |
| 				},
 | |
| 			},
 | |
| 			BindMounts: map[string]string{
 | |
| 				"/1/2/3":          "/4/5/6",
 | |
| 				"/test/file.test": "/test2/file2.test",
 | |
| 			},
 | |
| 		},
 | |
| 		valid: true,
 | |
| 	}
 | |
| 
 | |
| 	g, err := generate.New("linux")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	ctr.config.Spec = g.Config
 | |
| 
 | |
| 	ctr.config.Labels["test"] = "testing"
 | |
| 
 | |
| 	// Must make lockfile or container will error on being retrieved from DB
 | |
| 	lockPath := filepath.Join(locksDir, id)
 | |
| 	lock, err := storage.GetLockfile(lockPath)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	ctr.lock = lock
 | |
| 
 | |
| 	return ctr, nil
 | |
| }
 | |
| 
 | |
| func getTestPod(id, name, locksDir string) (*Pod, error) {
 | |
| 	pod := &Pod{
 | |
| 		config: &PodConfig{
 | |
| 			ID:           id,
 | |
| 			Name:         name,
 | |
| 			Labels:       map[string]string{"a": "b", "c": "d"},
 | |
| 			CgroupParent: "/hello/world/cgroup/parent",
 | |
| 		},
 | |
| 		state: &podState{
 | |
| 			CgroupPath: "/path/to/cgroups/hello/",
 | |
| 		},
 | |
| 		valid: true,
 | |
| 	}
 | |
| 
 | |
| 	lockPath := filepath.Join(locksDir, id)
 | |
| 	lock, err := storage.GetLockfile(lockPath)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	pod.lock = lock
 | |
| 
 | |
| 	return pod, nil
 | |
| }
 | |
| 
 | |
| func getTestCtrN(n, lockPath string) (*Container, error) {
 | |
| 	return getTestContainer(strings.Repeat(n, 32), "test"+n, lockPath)
 | |
| }
 | |
| 
 | |
| func getTestCtr1(lockPath string) (*Container, error) {
 | |
| 	return getTestCtrN("1", lockPath)
 | |
| }
 | |
| 
 | |
| func getTestCtr2(lockPath string) (*Container, error) {
 | |
| 	return getTestCtrN("2", lockPath)
 | |
| }
 | |
| 
 | |
| func getTestPodN(n, lockPath string) (*Pod, error) {
 | |
| 	return getTestPod(strings.Repeat(n, 32), "test"+n, lockPath)
 | |
| }
 | |
| 
 | |
| func getTestPod1(lockPath string) (*Pod, error) {
 | |
| 	return getTestPodN("1", lockPath)
 | |
| }
 | |
| 
 | |
| func getTestPod2(lockPath string) (*Pod, error) {
 | |
| 	return getTestPodN("2", lockPath)
 | |
| }
 | |
| 
 | |
| // This horrible hack tests if containers are equal in a way that should handle
 | |
| // empty arrays being dropped to nil pointers in the spec JSON
 | |
| // For some operations (container retrieval from the database) state is allowed
 | |
| // to be empty. This is controlled by the allowedEmpty bool.
 | |
| func testContainersEqual(t *testing.T, a, b *Container, allowedEmpty bool) {
 | |
| 	if a == nil && b == nil {
 | |
| 		return
 | |
| 	}
 | |
| 	require.NotNil(t, a)
 | |
| 	require.NotNil(t, b)
 | |
| 
 | |
| 	require.NotNil(t, a.config)
 | |
| 	require.NotNil(t, b.config)
 | |
| 	require.NotNil(t, a.state)
 | |
| 	require.NotNil(t, b.state)
 | |
| 
 | |
| 	aConfig := new(ContainerConfig)
 | |
| 	bConfig := new(ContainerConfig)
 | |
| 	aState := new(containerState)
 | |
| 	bState := new(containerState)
 | |
| 
 | |
| 	blankState := new(containerState)
 | |
| 
 | |
| 	assert.Equal(t, a.valid, b.valid)
 | |
| 
 | |
| 	aConfigJSON, err := json.Marshal(a.config)
 | |
| 	assert.NoError(t, err)
 | |
| 	err = json.Unmarshal(aConfigJSON, aConfig)
 | |
| 	assert.NoError(t, err)
 | |
| 
 | |
| 	bConfigJSON, err := json.Marshal(b.config)
 | |
| 	assert.NoError(t, err)
 | |
| 	err = json.Unmarshal(bConfigJSON, bConfig)
 | |
| 	assert.NoError(t, err)
 | |
| 
 | |
| 	assert.EqualValues(t, aConfig, bConfig)
 | |
| 
 | |
| 	aStateJSON, err := json.Marshal(a.state)
 | |
| 	assert.NoError(t, err)
 | |
| 	err = json.Unmarshal(aStateJSON, aState)
 | |
| 	assert.NoError(t, err)
 | |
| 
 | |
| 	bStateJSON, err := json.Marshal(b.state)
 | |
| 	assert.NoError(t, err)
 | |
| 	err = json.Unmarshal(bStateJSON, bState)
 | |
| 	assert.NoError(t, err)
 | |
| 
 | |
| 	if allowedEmpty {
 | |
| 		assert.True(t, reflect.DeepEqual(aState, bState) || reflect.DeepEqual(aState, blankState))
 | |
| 	} else {
 | |
| 		assert.EqualValues(t, aState, bState)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Test if pods are equal.
 | |
| // For some operations (pod retrieval from the database) state is allowed to be
 | |
| // empty. This is controlled by the allowedEmpty bool.
 | |
| func testPodsEqual(t *testing.T, a, b *Pod, allowedEmpty bool) {
 | |
| 	if a == nil && b == nil {
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	blankState := new(podState)
 | |
| 
 | |
| 	require.NotNil(t, a)
 | |
| 	require.NotNil(t, b)
 | |
| 
 | |
| 	require.NotNil(t, a.config)
 | |
| 	require.NotNil(t, b.config)
 | |
| 	require.NotNil(t, a.state)
 | |
| 	require.NotNil(t, b.state)
 | |
| 
 | |
| 	assert.Equal(t, a.valid, b.valid)
 | |
| 
 | |
| 	assert.EqualValues(t, a.config, b.config)
 | |
| 
 | |
| 	if allowedEmpty {
 | |
| 		assert.True(t, reflect.DeepEqual(a.state, b.state) || reflect.DeepEqual(a.state, blankState))
 | |
| 	} else {
 | |
| 		assert.EqualValues(t, a.state, b.state)
 | |
| 	}
 | |
| }
 |