mirror of
				https://github.com/kata-containers/kata-containers.git
				synced 2025-11-03 19:15:58 +00:00 
			
		
		
		
	Many cli and arch files were using the 'older style' fairly full Apache license text. The project standard is the shorter SPDX style. Convert them over. Fixes: #225 Signed-off-by: Graham whaley <graham.whaley@intel.com>
		
			
				
	
	
		
			746 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			746 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright (c) 2017 Intel Corporation
 | 
						|
//
 | 
						|
// SPDX-License-Identifier: Apache-2.0
 | 
						|
//
 | 
						|
 | 
						|
package main
 | 
						|
 | 
						|
import (
 | 
						|
	"encoding/json"
 | 
						|
	"flag"
 | 
						|
	"fmt"
 | 
						|
	"io/ioutil"
 | 
						|
	"os"
 | 
						|
	"path/filepath"
 | 
						|
	"regexp"
 | 
						|
	"strings"
 | 
						|
	"testing"
 | 
						|
	"time"
 | 
						|
 | 
						|
	vc "github.com/kata-containers/runtime/virtcontainers"
 | 
						|
	vcAnnotations "github.com/kata-containers/runtime/virtcontainers/pkg/annotations"
 | 
						|
	"github.com/kata-containers/runtime/virtcontainers/pkg/vcmock"
 | 
						|
	"github.com/stretchr/testify/assert"
 | 
						|
	"github.com/urfave/cli"
 | 
						|
)
 | 
						|
 | 
						|
type TestFileWriter struct {
 | 
						|
	Name string
 | 
						|
	File *os.File
 | 
						|
}
 | 
						|
 | 
						|
var hypervisorDetails1 = hypervisorDetails{
 | 
						|
	HypervisorAsset: asset{
 | 
						|
		Path: "/hypervisor/path",
 | 
						|
	},
 | 
						|
	ImageAsset: asset{
 | 
						|
		Path: "/image/path",
 | 
						|
	},
 | 
						|
	KernelAsset: asset{
 | 
						|
		Path: "/kernel/path",
 | 
						|
	},
 | 
						|
}
 | 
						|
 | 
						|
var hypervisorDetails2 = hypervisorDetails{
 | 
						|
	HypervisorAsset: asset{
 | 
						|
		Path: "/hypervisor/path2",
 | 
						|
	},
 | 
						|
	ImageAsset: asset{
 | 
						|
		Path: "/image/path2",
 | 
						|
	},
 | 
						|
	KernelAsset: asset{
 | 
						|
		Path: "/kernel/path2",
 | 
						|
	},
 | 
						|
}
 | 
						|
 | 
						|
var hypervisorDetails3 = hypervisorDetails{
 | 
						|
	HypervisorAsset: asset{
 | 
						|
		Path: "/hypervisor/path3",
 | 
						|
	},
 | 
						|
	ImageAsset: asset{
 | 
						|
		Path: "/image/path3",
 | 
						|
	},
 | 
						|
	KernelAsset: asset{
 | 
						|
		Path: "/kernel/path3",
 | 
						|
	},
 | 
						|
}
 | 
						|
 | 
						|
var testStatuses = []fullContainerState{
 | 
						|
	{
 | 
						|
		containerState: containerState{
 | 
						|
			Version:        "",
 | 
						|
			ID:             "1",
 | 
						|
			InitProcessPid: 1234,
 | 
						|
			Status:         "running",
 | 
						|
			Bundle:         "/somewhere/over/the/rainbow",
 | 
						|
			Created:        time.Now().UTC(),
 | 
						|
			Annotations:    map[string]string(nil),
 | 
						|
			Owner:          "#0",
 | 
						|
		},
 | 
						|
 | 
						|
		CurrentHypervisorDetails: hypervisorDetails1,
 | 
						|
		LatestHypervisorDetails:  hypervisorDetails1,
 | 
						|
		StaleAssets:              []string{},
 | 
						|
	},
 | 
						|
	{
 | 
						|
		containerState: containerState{
 | 
						|
			Version:        "",
 | 
						|
			ID:             "2",
 | 
						|
			InitProcessPid: 2345,
 | 
						|
			Status:         "stopped",
 | 
						|
			Bundle:         "/this/path/is/invalid",
 | 
						|
			Created:        time.Now().UTC(),
 | 
						|
			Annotations:    map[string]string(nil),
 | 
						|
			Owner:          "#0",
 | 
						|
		},
 | 
						|
 | 
						|
		CurrentHypervisorDetails: hypervisorDetails2,
 | 
						|
		LatestHypervisorDetails:  hypervisorDetails2,
 | 
						|
		StaleAssets:              []string{},
 | 
						|
	},
 | 
						|
	{
 | 
						|
		containerState: containerState{
 | 
						|
			Version:        "",
 | 
						|
			ID:             "3",
 | 
						|
			InitProcessPid: 9999,
 | 
						|
			Status:         "ready",
 | 
						|
			Bundle:         "/foo/bar/baz",
 | 
						|
			Created:        time.Now().UTC(),
 | 
						|
			Annotations:    map[string]string(nil),
 | 
						|
			Owner:          "#0",
 | 
						|
		},
 | 
						|
 | 
						|
		CurrentHypervisorDetails: hypervisorDetails3,
 | 
						|
		LatestHypervisorDetails:  hypervisorDetails3,
 | 
						|
		StaleAssets:              []string{},
 | 
						|
	},
 | 
						|
}
 | 
						|
 | 
						|
// Implement the io.Writer interface
 | 
						|
func (w *TestFileWriter) Write(bytes []byte) (n int, err error) {
 | 
						|
	return w.File.Write(bytes)
 | 
						|
}
 | 
						|
 | 
						|
func formatListDataAsBytes(formatter formatState, state []fullContainerState, showAll bool) (bytes []byte, err error) {
 | 
						|
	tmpfile, err := ioutil.TempFile("", "formatListData-")
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	defer os.Remove(tmpfile.Name())
 | 
						|
 | 
						|
	err = formatter.Write(state, showAll, tmpfile)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	tmpfile.Close()
 | 
						|
 | 
						|
	return ioutil.ReadFile(tmpfile.Name())
 | 
						|
}
 | 
						|
 | 
						|
func formatListDataAsString(formatter formatState, state []fullContainerState, showAll bool) (lines []string, err error) {
 | 
						|
	bytes, err := formatListDataAsBytes(formatter, state, showAll)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	lines = strings.Split(string(bytes), "\n")
 | 
						|
 | 
						|
	// Remove last line if empty
 | 
						|
	length := len(lines)
 | 
						|
	last := lines[length-1]
 | 
						|
	if last == "" {
 | 
						|
		lines = lines[:length-1]
 | 
						|
	}
 | 
						|
 | 
						|
	return lines, nil
 | 
						|
}
 | 
						|
 | 
						|
func TestStateToIDList(t *testing.T) {
 | 
						|
 | 
						|
	// no header
 | 
						|
	expectedLength := len(testStatuses)
 | 
						|
 | 
						|
	// showAll should not affect the output
 | 
						|
	for _, showAll := range []bool{true, false} {
 | 
						|
		lines, err := formatListDataAsString(&formatIDList{}, testStatuses, showAll)
 | 
						|
		if err != nil {
 | 
						|
			t.Fatal(err)
 | 
						|
		}
 | 
						|
 | 
						|
		var expected []string
 | 
						|
		for _, s := range testStatuses {
 | 
						|
			expected = append(expected, s.ID)
 | 
						|
		}
 | 
						|
 | 
						|
		length := len(lines)
 | 
						|
 | 
						|
		if length != expectedLength {
 | 
						|
			t.Fatalf("Expected %d lines, got %d: %v", expectedLength, length, lines)
 | 
						|
		}
 | 
						|
 | 
						|
		assert.Equal(t, lines, expected, "lines + expected")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestStateToTabular(t *testing.T) {
 | 
						|
	// +1 for header line
 | 
						|
	expectedLength := len(testStatuses) + 1
 | 
						|
 | 
						|
	expectedDefaultHeaderPattern := `\AID\s+PID\s+STATUS\s+BUNDLE\s+CREATED\s+OWNER`
 | 
						|
	expectedExtendedHeaderPattern := `HYPERVISOR\s+KERNEL\s+IMAGE\s+LATEST-KERNEL\s+LATEST-IMAGE\s+STALE`
 | 
						|
	endingPattern := `\s*\z`
 | 
						|
 | 
						|
	lines, err := formatListDataAsString(&formatTabular{}, testStatuses, false)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	length := len(lines)
 | 
						|
 | 
						|
	expectedHeaderPattern := expectedDefaultHeaderPattern + endingPattern
 | 
						|
	expectedHeaderRE := regexp.MustCompile(expectedHeaderPattern)
 | 
						|
 | 
						|
	if length != expectedLength {
 | 
						|
		t.Fatalf("Expected %d lines, got %d", expectedLength, length)
 | 
						|
	}
 | 
						|
 | 
						|
	header := lines[0]
 | 
						|
 | 
						|
	matches := expectedHeaderRE.FindAllStringSubmatch(header, -1)
 | 
						|
	if matches == nil {
 | 
						|
		t.Fatalf("Header line failed to match:\n"+
 | 
						|
			"pattern : %v\n"+
 | 
						|
			"line    : %v\n",
 | 
						|
			expectedDefaultHeaderPattern,
 | 
						|
			header)
 | 
						|
	}
 | 
						|
 | 
						|
	for i, status := range testStatuses {
 | 
						|
		lineIndex := i + 1
 | 
						|
		line := lines[lineIndex]
 | 
						|
 | 
						|
		expectedLinePattern := fmt.Sprintf(`\A%s\s+%d\s+%s\s+%s\s+%s\s+%s\s*\z`,
 | 
						|
			regexp.QuoteMeta(status.ID),
 | 
						|
			status.InitProcessPid,
 | 
						|
			regexp.QuoteMeta(status.Status),
 | 
						|
			regexp.QuoteMeta(status.Bundle),
 | 
						|
			regexp.QuoteMeta(status.Created.Format(time.RFC3339Nano)),
 | 
						|
			regexp.QuoteMeta(status.Owner))
 | 
						|
 | 
						|
		expectedLineRE := regexp.MustCompile(expectedLinePattern)
 | 
						|
 | 
						|
		matches := expectedLineRE.FindAllStringSubmatch(line, -1)
 | 
						|
		if matches == nil {
 | 
						|
			t.Fatalf("Data line failed to match:\n"+
 | 
						|
				"pattern : %v\n"+
 | 
						|
				"line    : %v\n",
 | 
						|
				expectedLinePattern,
 | 
						|
				line)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// Try again with full details this time
 | 
						|
	lines, err = formatListDataAsString(&formatTabular{}, testStatuses, true)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	length = len(lines)
 | 
						|
 | 
						|
	expectedHeaderPattern = expectedDefaultHeaderPattern + `\s+` + expectedExtendedHeaderPattern + endingPattern
 | 
						|
	expectedHeaderRE = regexp.MustCompile(expectedHeaderPattern)
 | 
						|
 | 
						|
	if length != expectedLength {
 | 
						|
		t.Fatalf("Expected %d lines, got %d", expectedLength, length)
 | 
						|
	}
 | 
						|
 | 
						|
	header = lines[0]
 | 
						|
 | 
						|
	matches = expectedHeaderRE.FindAllStringSubmatch(header, -1)
 | 
						|
	if matches == nil {
 | 
						|
		t.Fatalf("Header line failed to match:\n"+
 | 
						|
			"pattern : %v\n"+
 | 
						|
			"line    : %v\n",
 | 
						|
			expectedDefaultHeaderPattern,
 | 
						|
			header)
 | 
						|
	}
 | 
						|
 | 
						|
	for i, status := range testStatuses {
 | 
						|
		lineIndex := i + 1
 | 
						|
		line := lines[lineIndex]
 | 
						|
 | 
						|
		expectedLinePattern := fmt.Sprintf(`\A%s\s+%d\s+%s\s+%s\s+%s\s+%s\s+%s\s+%s\s+%s\s+%s\s+%s\s+%s\s*\z`,
 | 
						|
			regexp.QuoteMeta(status.ID),
 | 
						|
			status.InitProcessPid,
 | 
						|
			regexp.QuoteMeta(status.Status),
 | 
						|
			regexp.QuoteMeta(status.Bundle),
 | 
						|
			regexp.QuoteMeta(status.Created.Format(time.RFC3339Nano)),
 | 
						|
			regexp.QuoteMeta(status.Owner),
 | 
						|
			regexp.QuoteMeta(status.CurrentHypervisorDetails.HypervisorAsset.Path),
 | 
						|
			regexp.QuoteMeta(status.CurrentHypervisorDetails.KernelAsset.Path),
 | 
						|
			regexp.QuoteMeta(status.CurrentHypervisorDetails.ImageAsset.Path),
 | 
						|
			regexp.QuoteMeta(status.LatestHypervisorDetails.KernelAsset.Path),
 | 
						|
			regexp.QuoteMeta(status.LatestHypervisorDetails.ImageAsset.Path),
 | 
						|
			regexp.QuoteMeta("-"))
 | 
						|
 | 
						|
		expectedLineRE := regexp.MustCompile(expectedLinePattern)
 | 
						|
 | 
						|
		matches := expectedLineRE.FindAllStringSubmatch(line, -1)
 | 
						|
		if matches == nil {
 | 
						|
			t.Fatalf("Data line failed to match:\n"+
 | 
						|
				"pattern : %v\n"+
 | 
						|
				"line    : %v\n",
 | 
						|
				expectedLinePattern,
 | 
						|
				line)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestStateToJSON(t *testing.T) {
 | 
						|
	expectedLength := len(testStatuses)
 | 
						|
 | 
						|
	// showAll should not affect the output
 | 
						|
	for _, showAll := range []bool{true, false} {
 | 
						|
		bytes, err := formatListDataAsBytes(&formatJSON{}, testStatuses, showAll)
 | 
						|
		if err != nil {
 | 
						|
			t.Fatal(err)
 | 
						|
		}
 | 
						|
 | 
						|
		// Force capacity to match the original otherwise assert.Equal() complains.
 | 
						|
		states := make([]fullContainerState, 0, len(testStatuses))
 | 
						|
 | 
						|
		err = json.Unmarshal(bytes, &states)
 | 
						|
		if err != nil {
 | 
						|
			t.Fatal(err)
 | 
						|
		}
 | 
						|
 | 
						|
		length := len(states)
 | 
						|
 | 
						|
		if length != expectedLength {
 | 
						|
			t.Fatalf("Expected %d lines, got %d", expectedLength, length)
 | 
						|
		}
 | 
						|
 | 
						|
		// golang tip (what will presumably become v1.9) now
 | 
						|
		// stores a monotonic clock value as part of time.Time's
 | 
						|
		// internal representation (this is shown by a suffix in
 | 
						|
		// the form "m=±ddd.nnnnnnnnn" when calling String() on
 | 
						|
		// the time.Time object). However, this monotonic value
 | 
						|
		// is stripped out when marshaling.
 | 
						|
		//
 | 
						|
		// This behaviour change makes comparing the original
 | 
						|
		// object and the marshaled-and-then-unmarshaled copy of
 | 
						|
		// the object doomed to failure.
 | 
						|
		//
 | 
						|
		// The solution? Manually strip the monotonic time out
 | 
						|
		// of the original before comparison (yuck!)
 | 
						|
		//
 | 
						|
		// See:
 | 
						|
		//
 | 
						|
		// - https://go-review.googlesource.com/c/36255/7/src/time/time.go#54
 | 
						|
		//
 | 
						|
		for i := 0; i < expectedLength; i++ {
 | 
						|
			// remove monotonic time part
 | 
						|
			testStatuses[i].Created = testStatuses[i].Created.Truncate(0)
 | 
						|
		}
 | 
						|
 | 
						|
		assert.Equal(t, states, testStatuses, "states + testStatuses")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestListCLIFunctionNoContainers(t *testing.T) {
 | 
						|
	app := cli.NewApp()
 | 
						|
	ctx := cli.NewContext(app, nil, nil)
 | 
						|
	app.Name = "foo"
 | 
						|
	ctx.App.Metadata = map[string]interface{}{
 | 
						|
		"foo": "bar",
 | 
						|
	}
 | 
						|
 | 
						|
	fn, ok := listCLICommand.Action.(func(context *cli.Context) error)
 | 
						|
	assert.True(t, ok)
 | 
						|
 | 
						|
	err := fn(ctx)
 | 
						|
 | 
						|
	// no config in the Metadata
 | 
						|
	assert.Error(t, err)
 | 
						|
}
 | 
						|
 | 
						|
func TestListGetContainersListSandboxFail(t *testing.T) {
 | 
						|
	assert := assert.New(t)
 | 
						|
 | 
						|
	tmpdir, err := ioutil.TempDir(testDir, "")
 | 
						|
	assert.NoError(err)
 | 
						|
	defer os.RemoveAll(tmpdir)
 | 
						|
 | 
						|
	app := cli.NewApp()
 | 
						|
	ctx := cli.NewContext(app, nil, nil)
 | 
						|
	app.Name = "foo"
 | 
						|
 | 
						|
	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true)
 | 
						|
	assert.NoError(err)
 | 
						|
 | 
						|
	ctx.App.Metadata = map[string]interface{}{
 | 
						|
		"runtimeConfig": runtimeConfig,
 | 
						|
	}
 | 
						|
 | 
						|
	_, err = getContainers(ctx)
 | 
						|
	assert.Error(err)
 | 
						|
	assert.True(vcmock.IsMockError(err))
 | 
						|
}
 | 
						|
 | 
						|
func TestListGetContainers(t *testing.T) {
 | 
						|
	assert := assert.New(t)
 | 
						|
 | 
						|
	testingImpl.ListSandboxFunc = func() ([]vc.SandboxStatus, error) {
 | 
						|
		// No pre-existing sandboxes
 | 
						|
		return []vc.SandboxStatus{}, nil
 | 
						|
	}
 | 
						|
 | 
						|
	defer func() {
 | 
						|
		testingImpl.ListSandboxFunc = nil
 | 
						|
	}()
 | 
						|
 | 
						|
	tmpdir, err := ioutil.TempDir(testDir, "")
 | 
						|
	assert.NoError(err)
 | 
						|
	defer os.RemoveAll(tmpdir)
 | 
						|
 | 
						|
	app := cli.NewApp()
 | 
						|
	ctx := cli.NewContext(app, nil, nil)
 | 
						|
	app.Name = "foo"
 | 
						|
 | 
						|
	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true)
 | 
						|
	assert.NoError(err)
 | 
						|
 | 
						|
	ctx.App.Metadata = map[string]interface{}{
 | 
						|
		"runtimeConfig": runtimeConfig,
 | 
						|
	}
 | 
						|
 | 
						|
	state, err := getContainers(ctx)
 | 
						|
	assert.NoError(err)
 | 
						|
	assert.Equal(state, []fullContainerState(nil))
 | 
						|
}
 | 
						|
 | 
						|
func TestListGetContainersSandboxWithoutContainers(t *testing.T) {
 | 
						|
	assert := assert.New(t)
 | 
						|
 | 
						|
	sandbox := &vcmock.Sandbox{
 | 
						|
		MockID: testSandboxID,
 | 
						|
	}
 | 
						|
 | 
						|
	testingImpl.ListSandboxFunc = func() ([]vc.SandboxStatus, error) {
 | 
						|
		return []vc.SandboxStatus{
 | 
						|
			{
 | 
						|
				ID:               sandbox.ID(),
 | 
						|
				ContainersStatus: []vc.ContainerStatus(nil),
 | 
						|
			},
 | 
						|
		}, nil
 | 
						|
	}
 | 
						|
 | 
						|
	defer func() {
 | 
						|
		testingImpl.ListSandboxFunc = nil
 | 
						|
	}()
 | 
						|
 | 
						|
	tmpdir, err := ioutil.TempDir(testDir, "")
 | 
						|
	assert.NoError(err)
 | 
						|
	defer os.RemoveAll(tmpdir)
 | 
						|
 | 
						|
	app := cli.NewApp()
 | 
						|
	ctx := cli.NewContext(app, nil, nil)
 | 
						|
	app.Name = "foo"
 | 
						|
 | 
						|
	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true)
 | 
						|
	assert.NoError(err)
 | 
						|
 | 
						|
	ctx.App.Metadata = map[string]interface{}{
 | 
						|
		"runtimeConfig": runtimeConfig,
 | 
						|
	}
 | 
						|
 | 
						|
	state, err := getContainers(ctx)
 | 
						|
	assert.NoError(err)
 | 
						|
	assert.Equal(state, []fullContainerState(nil))
 | 
						|
}
 | 
						|
 | 
						|
func TestListGetContainersSandboxWithContainer(t *testing.T) {
 | 
						|
	assert := assert.New(t)
 | 
						|
 | 
						|
	tmpdir, err := ioutil.TempDir(testDir, "")
 | 
						|
	assert.NoError(err)
 | 
						|
	defer os.RemoveAll(tmpdir)
 | 
						|
 | 
						|
	sandbox := &vcmock.Sandbox{
 | 
						|
		MockID: testSandboxID,
 | 
						|
	}
 | 
						|
 | 
						|
	rootfs := filepath.Join(tmpdir, "rootfs")
 | 
						|
	err = os.MkdirAll(rootfs, testDirMode)
 | 
						|
	assert.NoError(err)
 | 
						|
 | 
						|
	testingImpl.ListSandboxFunc = func() ([]vc.SandboxStatus, error) {
 | 
						|
		return []vc.SandboxStatus{
 | 
						|
			{
 | 
						|
				ID: sandbox.ID(),
 | 
						|
				ContainersStatus: []vc.ContainerStatus{
 | 
						|
					{
 | 
						|
						ID:          sandbox.ID(),
 | 
						|
						Annotations: map[string]string{},
 | 
						|
						RootFs:      rootfs,
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
		}, nil
 | 
						|
	}
 | 
						|
 | 
						|
	defer func() {
 | 
						|
		testingImpl.ListSandboxFunc = nil
 | 
						|
	}()
 | 
						|
 | 
						|
	app := cli.NewApp()
 | 
						|
	ctx := cli.NewContext(app, nil, nil)
 | 
						|
	app.Name = "foo"
 | 
						|
 | 
						|
	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true)
 | 
						|
	assert.NoError(err)
 | 
						|
 | 
						|
	ctx.App.Metadata = map[string]interface{}{
 | 
						|
		"runtimeConfig": runtimeConfig,
 | 
						|
	}
 | 
						|
 | 
						|
	_, err = getContainers(ctx)
 | 
						|
	assert.NoError(err)
 | 
						|
}
 | 
						|
 | 
						|
func TestListCLIFunctionFormatFail(t *testing.T) {
 | 
						|
	assert := assert.New(t)
 | 
						|
 | 
						|
	tmpdir, err := ioutil.TempDir(testDir, "")
 | 
						|
	assert.NoError(err)
 | 
						|
	defer os.RemoveAll(tmpdir)
 | 
						|
 | 
						|
	quietFlags := flag.NewFlagSet("test", 0)
 | 
						|
	quietFlags.Bool("quiet", true, "")
 | 
						|
 | 
						|
	tableFlags := flag.NewFlagSet("test", 0)
 | 
						|
	tableFlags.String("format", "table", "")
 | 
						|
 | 
						|
	jsonFlags := flag.NewFlagSet("test", 0)
 | 
						|
	jsonFlags.String("format", "json", "")
 | 
						|
 | 
						|
	invalidFlags := flag.NewFlagSet("test", 0)
 | 
						|
	invalidFlags.String("format", "not-a-valid-format", "")
 | 
						|
 | 
						|
	type testData struct {
 | 
						|
		format string
 | 
						|
		flags  *flag.FlagSet
 | 
						|
	}
 | 
						|
 | 
						|
	data := []testData{
 | 
						|
		{"quiet", quietFlags},
 | 
						|
		{"table", tableFlags},
 | 
						|
		{"json", jsonFlags},
 | 
						|
		{"invalid", invalidFlags},
 | 
						|
	}
 | 
						|
 | 
						|
	sandbox := &vcmock.Sandbox{
 | 
						|
		MockID: testSandboxID,
 | 
						|
	}
 | 
						|
 | 
						|
	rootfs := filepath.Join(tmpdir, "rootfs")
 | 
						|
 | 
						|
	testingImpl.ListSandboxFunc = func() ([]vc.SandboxStatus, error) {
 | 
						|
		return []vc.SandboxStatus{
 | 
						|
			{
 | 
						|
				ID: sandbox.ID(),
 | 
						|
				ContainersStatus: []vc.ContainerStatus{
 | 
						|
					{
 | 
						|
						ID: sandbox.ID(),
 | 
						|
						Annotations: map[string]string{
 | 
						|
							vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
 | 
						|
						},
 | 
						|
						RootFs: rootfs,
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
		}, nil
 | 
						|
	}
 | 
						|
 | 
						|
	defer func() {
 | 
						|
		testingImpl.ListSandboxFunc = nil
 | 
						|
	}()
 | 
						|
 | 
						|
	savedOutputFile := defaultOutputFile
 | 
						|
	defer func() {
 | 
						|
		defaultOutputFile = savedOutputFile
 | 
						|
	}()
 | 
						|
 | 
						|
	// purposely invalid
 | 
						|
	var invalidFile *os.File
 | 
						|
 | 
						|
	for _, d := range data {
 | 
						|
		// start off with an invalid output file
 | 
						|
		defaultOutputFile = invalidFile
 | 
						|
 | 
						|
		app := cli.NewApp()
 | 
						|
		ctx := cli.NewContext(app, d.flags, nil)
 | 
						|
		app.Name = "foo"
 | 
						|
		ctx.App.Metadata = map[string]interface{}{
 | 
						|
			"foo": "bar",
 | 
						|
		}
 | 
						|
 | 
						|
		fn, ok := listCLICommand.Action.(func(context *cli.Context) error)
 | 
						|
		assert.True(ok, d)
 | 
						|
 | 
						|
		err = fn(ctx)
 | 
						|
 | 
						|
		// no config in the Metadata
 | 
						|
		assert.Error(err, d)
 | 
						|
 | 
						|
		runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true)
 | 
						|
		assert.NoError(err, d)
 | 
						|
 | 
						|
		ctx.App.Metadata["runtimeConfig"] = runtimeConfig
 | 
						|
 | 
						|
		_ = os.Remove(rootfs)
 | 
						|
 | 
						|
		err = fn(ctx)
 | 
						|
		assert.Error(err)
 | 
						|
 | 
						|
		err = os.MkdirAll(rootfs, testDirMode)
 | 
						|
		assert.NoError(err)
 | 
						|
 | 
						|
		err = fn(ctx)
 | 
						|
 | 
						|
		// invalid output file
 | 
						|
		assert.Error(err, d)
 | 
						|
		assert.False(vcmock.IsMockError(err), d)
 | 
						|
 | 
						|
		output := filepath.Join(tmpdir, "output")
 | 
						|
		f, err := os.OpenFile(output, os.O_WRONLY|os.O_CREATE, testFileMode)
 | 
						|
		assert.NoError(err)
 | 
						|
		defer f.Close()
 | 
						|
 | 
						|
		// output file is now valid
 | 
						|
		defaultOutputFile = f
 | 
						|
 | 
						|
		err = fn(ctx)
 | 
						|
		if d.format == "invalid" {
 | 
						|
			assert.Error(err)
 | 
						|
			assert.False(vcmock.IsMockError(err), d)
 | 
						|
		} else {
 | 
						|
			assert.NoError(err)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestListCLIFunctionQuiet(t *testing.T) {
 | 
						|
	assert := assert.New(t)
 | 
						|
 | 
						|
	tmpdir, err := ioutil.TempDir(testDir, "")
 | 
						|
	assert.NoError(err)
 | 
						|
	defer os.RemoveAll(tmpdir)
 | 
						|
 | 
						|
	runtimeConfig, err := newTestRuntimeConfig(tmpdir, testConsole, true)
 | 
						|
	assert.NoError(err)
 | 
						|
 | 
						|
	sandbox := &vcmock.Sandbox{
 | 
						|
		MockID: testSandboxID,
 | 
						|
	}
 | 
						|
 | 
						|
	rootfs := filepath.Join(tmpdir, "rootfs")
 | 
						|
	err = os.MkdirAll(rootfs, testDirMode)
 | 
						|
	assert.NoError(err)
 | 
						|
 | 
						|
	testingImpl.ListSandboxFunc = func() ([]vc.SandboxStatus, error) {
 | 
						|
		return []vc.SandboxStatus{
 | 
						|
			{
 | 
						|
				ID: sandbox.ID(),
 | 
						|
				ContainersStatus: []vc.ContainerStatus{
 | 
						|
					{
 | 
						|
						ID: sandbox.ID(),
 | 
						|
						Annotations: map[string]string{
 | 
						|
							vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
 | 
						|
						},
 | 
						|
						RootFs: rootfs,
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
		}, nil
 | 
						|
	}
 | 
						|
 | 
						|
	defer func() {
 | 
						|
		testingImpl.ListSandboxFunc = nil
 | 
						|
	}()
 | 
						|
 | 
						|
	set := flag.NewFlagSet("test", 0)
 | 
						|
	set.Bool("quiet", true, "")
 | 
						|
 | 
						|
	app := cli.NewApp()
 | 
						|
	ctx := cli.NewContext(app, set, nil)
 | 
						|
	app.Name = "foo"
 | 
						|
	ctx.App.Metadata = map[string]interface{}{
 | 
						|
		"runtimeConfig": runtimeConfig,
 | 
						|
	}
 | 
						|
 | 
						|
	savedOutputFile := defaultOutputFile
 | 
						|
	defer func() {
 | 
						|
		defaultOutputFile = savedOutputFile
 | 
						|
	}()
 | 
						|
 | 
						|
	output := filepath.Join(tmpdir, "output")
 | 
						|
	f, err := os.OpenFile(output, os.O_CREATE|os.O_WRONLY|os.O_SYNC, testFileMode)
 | 
						|
	assert.NoError(err)
 | 
						|
	defer f.Close()
 | 
						|
 | 
						|
	defaultOutputFile = f
 | 
						|
 | 
						|
	fn, ok := listCLICommand.Action.(func(context *cli.Context) error)
 | 
						|
	assert.True(ok)
 | 
						|
 | 
						|
	err = fn(ctx)
 | 
						|
	assert.NoError(err)
 | 
						|
	f.Close()
 | 
						|
 | 
						|
	text, err := getFileContents(output)
 | 
						|
	assert.NoError(err)
 | 
						|
 | 
						|
	trimmed := strings.TrimSpace(text)
 | 
						|
	assert.Equal(testSandboxID, trimmed)
 | 
						|
}
 | 
						|
 | 
						|
func TestListGetDirOwner(t *testing.T) {
 | 
						|
	assert := assert.New(t)
 | 
						|
 | 
						|
	tmpdir, err := ioutil.TempDir(testDir, "")
 | 
						|
	assert.NoError(err)
 | 
						|
	defer os.RemoveAll(tmpdir)
 | 
						|
 | 
						|
	_, err = getDirOwner("")
 | 
						|
	// invalid parameter
 | 
						|
	assert.Error(err)
 | 
						|
 | 
						|
	dir := filepath.Join(tmpdir, "dir")
 | 
						|
 | 
						|
	_, err = getDirOwner(dir)
 | 
						|
	// ENOENT
 | 
						|
	assert.Error(err)
 | 
						|
 | 
						|
	err = createEmptyFile(dir)
 | 
						|
	assert.NoError(err)
 | 
						|
 | 
						|
	_, err = getDirOwner(dir)
 | 
						|
	// wrong file type
 | 
						|
	assert.Error(err)
 | 
						|
 | 
						|
	err = os.Remove(dir)
 | 
						|
	assert.NoError(err)
 | 
						|
 | 
						|
	err = os.MkdirAll(dir, testDirMode)
 | 
						|
	assert.NoError(err)
 | 
						|
 | 
						|
	uid := uint32(os.Getuid())
 | 
						|
 | 
						|
	dirUID, err := getDirOwner(dir)
 | 
						|
	assert.NoError(err)
 | 
						|
	assert.Equal(dirUID, uid)
 | 
						|
}
 |