gitee.com/leisunstar/runtime@v0.0.0-20200521203717-5cef3e7b53f9/virtcontainers/kata_shim_test.go (about)

     1  // Copyright (c) 2017 Intel Corporation
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  //
     5  
     6  package virtcontainers
     7  
     8  import (
     9  	"fmt"
    10  	"io"
    11  	"io/ioutil"
    12  	"os"
    13  	"path/filepath"
    14  	"strings"
    15  	"syscall"
    16  	"testing"
    17  	"time"
    18  	"unsafe"
    19  
    20  	. "github.com/kata-containers/runtime/virtcontainers/pkg/mock"
    21  	"github.com/kata-containers/runtime/virtcontainers/utils"
    22  	"github.com/stretchr/testify/assert"
    23  )
    24  
    25  const (
    26  	testContainer = "testContainer"
    27  )
    28  
    29  var (
    30  	testKataShimPath     = "/usr/bin/virtcontainers/bin/test/kata-shim"
    31  	testKataShimProxyURL = "foo:///foo/kata-containers/proxy.sock"
    32  	testWrongConsolePath = "/foo/wrong-console"
    33  )
    34  
    35  func getMockKataShimBinPath() string {
    36  	if DefaultMockKataShimBinPath == "" {
    37  		return testKataShimPath
    38  	}
    39  
    40  	return DefaultMockKataShimBinPath
    41  }
    42  
    43  func testKataShimStart(t *testing.T, sandbox *Sandbox, params ShimParams, expectFail bool) {
    44  	s := &kataShim{}
    45  	assert := assert.New(t)
    46  
    47  	pid, err := s.start(sandbox, params)
    48  	if expectFail {
    49  		assert.Error(err)
    50  		assert.Equal(pid, -1)
    51  	} else {
    52  		assert.NoError(err)
    53  		assert.NotEqual(pid, -1)
    54  	}
    55  }
    56  
    57  func TestKataShimStartNilSandboxConfigFailure(t *testing.T) {
    58  	testKataShimStart(t, &Sandbox{}, ShimParams{}, true)
    59  }
    60  
    61  func TestKataShimStartNilShimConfigFailure(t *testing.T) {
    62  	sandbox := &Sandbox{
    63  		config: &SandboxConfig{},
    64  	}
    65  
    66  	testKataShimStart(t, sandbox, ShimParams{}, true)
    67  }
    68  
    69  func TestKataShimStartShimPathEmptyFailure(t *testing.T) {
    70  	sandbox := &Sandbox{
    71  		config: &SandboxConfig{
    72  			ShimType:   KataShimType,
    73  			ShimConfig: ShimConfig{},
    74  		},
    75  	}
    76  
    77  	testKataShimStart(t, sandbox, ShimParams{}, true)
    78  }
    79  
    80  func TestKataShimStartShimTypeInvalid(t *testing.T) {
    81  	sandbox := &Sandbox{
    82  		config: &SandboxConfig{
    83  			ShimType:   "foo",
    84  			ShimConfig: ShimConfig{},
    85  		},
    86  	}
    87  
    88  	testKataShimStart(t, sandbox, ShimParams{}, true)
    89  }
    90  
    91  func TestKataShimStartParamsTokenEmptyFailure(t *testing.T) {
    92  	sandbox := &Sandbox{
    93  		config: &SandboxConfig{
    94  			ShimType: KataShimType,
    95  			ShimConfig: ShimConfig{
    96  				Path: getMockKataShimBinPath(),
    97  			},
    98  		},
    99  	}
   100  
   101  	testKataShimStart(t, sandbox, ShimParams{}, true)
   102  }
   103  
   104  func TestKataShimStartParamsURLEmptyFailure(t *testing.T) {
   105  	sandbox := &Sandbox{
   106  		config: &SandboxConfig{
   107  			ShimType: KataShimType,
   108  			ShimConfig: ShimConfig{
   109  				Path: getMockKataShimBinPath(),
   110  			},
   111  		},
   112  	}
   113  
   114  	params := ShimParams{
   115  		Token: "testToken",
   116  	}
   117  
   118  	testKataShimStart(t, sandbox, params, true)
   119  }
   120  
   121  func TestKataShimStartParamsContainerEmptyFailure(t *testing.T) {
   122  	sandbox := &Sandbox{
   123  		config: &SandboxConfig{
   124  			ShimType: KataShimType,
   125  			ShimConfig: ShimConfig{
   126  				Path: getMockKataShimBinPath(),
   127  			},
   128  		},
   129  	}
   130  
   131  	params := ShimParams{
   132  		Token: "testToken",
   133  		URL:   "unix://is/awesome",
   134  	}
   135  
   136  	testKataShimStart(t, sandbox, params, true)
   137  }
   138  
   139  func TestKataShimStartParamsInvalidCommand(t *testing.T) {
   140  	dir, err := ioutil.TempDir("", "")
   141  	assert.NoError(t, err)
   142  	defer os.RemoveAll(dir)
   143  
   144  	cmd := filepath.Join(dir, "does-not-exist")
   145  
   146  	sandbox := &Sandbox{
   147  		config: &SandboxConfig{
   148  			ShimType: KataShimType,
   149  			ShimConfig: ShimConfig{
   150  				Path: cmd,
   151  			},
   152  		},
   153  	}
   154  
   155  	params := ShimParams{
   156  		Token: "testToken",
   157  		URL:   "http://foo",
   158  	}
   159  
   160  	testKataShimStart(t, sandbox, params, true)
   161  }
   162  
   163  func startKataShimStartWithoutConsoleSuccessful(t *testing.T, detach bool) (*os.File, *os.File, *os.File, *Sandbox, ShimParams, error) {
   164  	saveStdout := os.Stdout
   165  	rStdout, wStdout, err := os.Pipe()
   166  	if err != nil {
   167  		return nil, nil, nil, &Sandbox{}, ShimParams{}, err
   168  	}
   169  
   170  	os.Stdout = wStdout
   171  
   172  	sandbox := &Sandbox{
   173  		config: &SandboxConfig{
   174  			ShimType: KataShimType,
   175  			ShimConfig: ShimConfig{
   176  				Path: getMockKataShimBinPath(),
   177  			},
   178  		},
   179  	}
   180  
   181  	params := ShimParams{
   182  		Container: testContainer,
   183  		Token:     "testToken",
   184  		URL:       testKataShimProxyURL,
   185  		Detach:    detach,
   186  	}
   187  
   188  	return rStdout, wStdout, saveStdout, sandbox, params, nil
   189  }
   190  
   191  func TestKataShimStartSuccessful(t *testing.T) {
   192  	rStdout, wStdout, saveStdout, sandbox, params, err := startKataShimStartWithoutConsoleSuccessful(t, false)
   193  	assert := assert.New(t)
   194  	assert.NoError(err)
   195  
   196  	defer func() {
   197  		os.Stdout = saveStdout
   198  		rStdout.Close()
   199  		wStdout.Close()
   200  	}()
   201  
   202  	testKataShimStart(t, sandbox, params, false)
   203  
   204  	bufStdout := make([]byte, 1024)
   205  	_, err = rStdout.Read(bufStdout)
   206  	assert.NoError(err)
   207  	assert.True(strings.Contains(string(bufStdout), ShimStdoutOutput))
   208  }
   209  
   210  func TestKataShimStartDetachSuccessful(t *testing.T) {
   211  	rStdout, wStdout, saveStdout, sandbox, params, err := startKataShimStartWithoutConsoleSuccessful(t, true)
   212  	assert.NoError(t, err)
   213  
   214  	defer func() {
   215  		os.Stdout = saveStdout
   216  		wStdout.Close()
   217  		rStdout.Close()
   218  	}()
   219  
   220  	testKataShimStart(t, sandbox, params, false)
   221  
   222  	readCh := make(chan error, 1)
   223  	go func() {
   224  		defer close(readCh)
   225  		bufStdout := make([]byte, 1024)
   226  		n, err := rStdout.Read(bufStdout)
   227  		if err != nil && err != io.EOF {
   228  			readCh <- err
   229  			return
   230  		}
   231  
   232  		if n > 0 {
   233  			readCh <- fmt.Errorf("Not expecting to read anything, Got %q", string(bufStdout))
   234  			return
   235  		}
   236  
   237  		readCh <- nil
   238  	}()
   239  
   240  	select {
   241  	case err := <-readCh:
   242  		assert.NoError(t, err)
   243  	case <-time.After(time.Duration(20) * time.Millisecond):
   244  		return
   245  	}
   246  }
   247  
   248  func TestKataShimStartWithConsoleNonExistingFailure(t *testing.T) {
   249  	sandbox := &Sandbox{
   250  		config: &SandboxConfig{
   251  			ShimType: KataShimType,
   252  			ShimConfig: ShimConfig{
   253  				Path: getMockKataShimBinPath(),
   254  			},
   255  		},
   256  	}
   257  
   258  	params := ShimParams{
   259  		Token:   "testToken",
   260  		URL:     testKataShimProxyURL,
   261  		Console: testWrongConsolePath,
   262  	}
   263  
   264  	testKataShimStart(t, sandbox, params, true)
   265  }
   266  
   267  // unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f.
   268  func unlockpt(f *os.File) error {
   269  	var u int32
   270  
   271  	return utils.Ioctl(f.Fd(), syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u)))
   272  }
   273  
   274  // ptsname retrieves the name of the first available pts for the given master.
   275  func ptsname(f *os.File) (string, error) {
   276  	var n int32
   277  
   278  	if err := utils.Ioctl(f.Fd(), syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))); err != nil {
   279  		return "", err
   280  	}
   281  
   282  	return fmt.Sprintf("/dev/pts/%d", n), nil
   283  }
   284  
   285  func newConsole() (*os.File, string, error) {
   286  	master, err := os.OpenFile("/dev/ptmx", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_CLOEXEC, 0)
   287  	if err != nil {
   288  		return nil, "", err
   289  	}
   290  
   291  	console, err := ptsname(master)
   292  	if err != nil {
   293  		return nil, "", err
   294  	}
   295  
   296  	if err := unlockpt(master); err != nil {
   297  		return nil, "", err
   298  	}
   299  
   300  	if err := os.Chmod(console, 0600); err != nil {
   301  		return nil, "", err
   302  	}
   303  
   304  	return master, console, nil
   305  }
   306  
   307  func TestKataShimStartWithConsoleSuccessful(t *testing.T) {
   308  	defer cleanUp()
   309  
   310  	master, console, err := newConsole()
   311  	t.Logf("Console created for tests:%s\n", console)
   312  	assert.NoError(t, err)
   313  
   314  	sandbox := &Sandbox{
   315  		config: &SandboxConfig{
   316  			ShimType: KataShimType,
   317  			ShimConfig: ShimConfig{
   318  				Path: getMockKataShimBinPath(),
   319  			},
   320  		},
   321  	}
   322  
   323  	params := ShimParams{
   324  		Container: testContainer,
   325  		Token:     "testToken",
   326  		URL:       testKataShimProxyURL,
   327  		Console:   console,
   328  	}
   329  
   330  	testKataShimStart(t, sandbox, params, false)
   331  	master.Close()
   332  }