github.com/kata-containers/runtime@v0.0.0-20210505125100-04f29832a923/virtcontainers/hypervisor_test.go (about)

     1  // Copyright (c) 2016 Intel Corporation
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  //
     5  
     6  package virtcontainers
     7  
     8  import (
     9  	"fmt"
    10  	"io/ioutil"
    11  	"os"
    12  	"path/filepath"
    13  	"testing"
    14  
    15  	ktu "github.com/kata-containers/runtime/pkg/katatestutils"
    16  	"github.com/kata-containers/runtime/virtcontainers/types"
    17  	"github.com/stretchr/testify/assert"
    18  )
    19  
    20  func testSetHypervisorType(t *testing.T, value string, expected HypervisorType) {
    21  	var hypervisorType HypervisorType
    22  	assert := assert.New(t)
    23  
    24  	err := (&hypervisorType).Set(value)
    25  	assert.NoError(err)
    26  	assert.Equal(hypervisorType, expected)
    27  }
    28  
    29  func TestSetQemuHypervisorType(t *testing.T) {
    30  	testSetHypervisorType(t, "qemu", QemuHypervisor)
    31  }
    32  
    33  func TestSetMockHypervisorType(t *testing.T) {
    34  	testSetHypervisorType(t, "mock", MockHypervisor)
    35  }
    36  
    37  func TestSetUnknownHypervisorType(t *testing.T) {
    38  	var hypervisorType HypervisorType
    39  	assert := assert.New(t)
    40  
    41  	err := (&hypervisorType).Set("unknown")
    42  	assert.Error(err)
    43  	assert.NotEqual(hypervisorType, QemuHypervisor)
    44  	assert.NotEqual(hypervisorType, MockHypervisor)
    45  }
    46  
    47  func testStringFromHypervisorType(t *testing.T, hypervisorType HypervisorType, expected string) {
    48  	hypervisorTypeStr := (&hypervisorType).String()
    49  	assert := assert.New(t)
    50  	assert.Equal(hypervisorTypeStr, expected)
    51  }
    52  
    53  func TestStringFromQemuHypervisorType(t *testing.T) {
    54  	hypervisorType := QemuHypervisor
    55  	testStringFromHypervisorType(t, hypervisorType, "qemu")
    56  }
    57  
    58  func TestStringFromMockHypervisorType(t *testing.T) {
    59  	hypervisorType := MockHypervisor
    60  	testStringFromHypervisorType(t, hypervisorType, "mock")
    61  }
    62  
    63  func TestStringFromUnknownHypervisorType(t *testing.T) {
    64  	var hypervisorType HypervisorType
    65  	testStringFromHypervisorType(t, hypervisorType, "")
    66  }
    67  
    68  func testNewHypervisorFromHypervisorType(t *testing.T, hypervisorType HypervisorType, expected hypervisor) {
    69  	assert := assert.New(t)
    70  	hy, err := newHypervisor(hypervisorType)
    71  	assert.NoError(err)
    72  	assert.Exactly(hy, expected)
    73  }
    74  
    75  func TestNewHypervisorFromMockHypervisorType(t *testing.T) {
    76  	hypervisorType := MockHypervisor
    77  	expectedHypervisor := &mockHypervisor{}
    78  	testNewHypervisorFromHypervisorType(t, hypervisorType, expectedHypervisor)
    79  }
    80  
    81  func TestNewHypervisorFromUnknownHypervisorType(t *testing.T) {
    82  	var hypervisorType HypervisorType
    83  	assert := assert.New(t)
    84  
    85  	hy, err := newHypervisor(hypervisorType)
    86  	assert.Error(err)
    87  	assert.Nil(hy)
    88  }
    89  
    90  func testHypervisorConfigValid(t *testing.T, hypervisorConfig *HypervisorConfig, success bool) {
    91  	err := hypervisorConfig.valid()
    92  	assert := assert.New(t)
    93  	assert.False(success && err != nil)
    94  	assert.False(!success && err == nil)
    95  }
    96  
    97  func TestHypervisorConfigNoKernelPath(t *testing.T) {
    98  	hypervisorConfig := &HypervisorConfig{
    99  		KernelPath:     "",
   100  		ImagePath:      fmt.Sprintf("%s/%s", testDir, testImage),
   101  		HypervisorPath: fmt.Sprintf("%s/%s", testDir, testHypervisor),
   102  	}
   103  
   104  	testHypervisorConfigValid(t, hypervisorConfig, false)
   105  }
   106  
   107  func TestHypervisorConfigNoImagePath(t *testing.T) {
   108  	hypervisorConfig := &HypervisorConfig{
   109  		KernelPath:     fmt.Sprintf("%s/%s", testDir, testKernel),
   110  		ImagePath:      "",
   111  		HypervisorPath: fmt.Sprintf("%s/%s", testDir, testHypervisor),
   112  	}
   113  
   114  	testHypervisorConfigValid(t, hypervisorConfig, false)
   115  }
   116  
   117  func TestHypervisorConfigNoHypervisorPath(t *testing.T) {
   118  	hypervisorConfig := &HypervisorConfig{
   119  		KernelPath:     fmt.Sprintf("%s/%s", testDir, testKernel),
   120  		ImagePath:      fmt.Sprintf("%s/%s", testDir, testImage),
   121  		HypervisorPath: "",
   122  	}
   123  
   124  	testHypervisorConfigValid(t, hypervisorConfig, true)
   125  }
   126  
   127  func TestHypervisorConfigIsValid(t *testing.T) {
   128  	hypervisorConfig := &HypervisorConfig{
   129  		KernelPath:     fmt.Sprintf("%s/%s", testDir, testKernel),
   130  		ImagePath:      fmt.Sprintf("%s/%s", testDir, testImage),
   131  		HypervisorPath: fmt.Sprintf("%s/%s", testDir, testHypervisor),
   132  	}
   133  
   134  	testHypervisorConfigValid(t, hypervisorConfig, true)
   135  }
   136  
   137  func TestHypervisorConfigValidTemplateConfig(t *testing.T) {
   138  	hypervisorConfig := &HypervisorConfig{
   139  		KernelPath:       fmt.Sprintf("%s/%s", testDir, testKernel),
   140  		ImagePath:        fmt.Sprintf("%s/%s", testDir, testImage),
   141  		HypervisorPath:   fmt.Sprintf("%s/%s", testDir, testHypervisor),
   142  		BootToBeTemplate: true,
   143  		BootFromTemplate: true,
   144  	}
   145  	testHypervisorConfigValid(t, hypervisorConfig, false)
   146  
   147  	hypervisorConfig.BootToBeTemplate = false
   148  	testHypervisorConfigValid(t, hypervisorConfig, false)
   149  	hypervisorConfig.MemoryPath = "foobar"
   150  	testHypervisorConfigValid(t, hypervisorConfig, false)
   151  	hypervisorConfig.DevicesStatePath = "foobar"
   152  	testHypervisorConfigValid(t, hypervisorConfig, true)
   153  
   154  	hypervisorConfig.BootFromTemplate = false
   155  	hypervisorConfig.BootToBeTemplate = true
   156  	testHypervisorConfigValid(t, hypervisorConfig, true)
   157  	hypervisorConfig.MemoryPath = ""
   158  	testHypervisorConfigValid(t, hypervisorConfig, false)
   159  }
   160  
   161  func TestHypervisorConfigDefaults(t *testing.T) {
   162  	assert := assert.New(t)
   163  	hypervisorConfig := &HypervisorConfig{
   164  		KernelPath:     fmt.Sprintf("%s/%s", testDir, testKernel),
   165  		ImagePath:      fmt.Sprintf("%s/%s", testDir, testImage),
   166  		HypervisorPath: "",
   167  	}
   168  	testHypervisorConfigValid(t, hypervisorConfig, true)
   169  
   170  	hypervisorConfigDefaultsExpected := &HypervisorConfig{
   171  		KernelPath:        fmt.Sprintf("%s/%s", testDir, testKernel),
   172  		ImagePath:         fmt.Sprintf("%s/%s", testDir, testImage),
   173  		HypervisorPath:    "",
   174  		NumVCPUs:          defaultVCPUs,
   175  		MemorySize:        defaultMemSzMiB,
   176  		DefaultBridges:    defaultBridges,
   177  		BlockDeviceDriver: defaultBlockDriver,
   178  		DefaultMaxVCPUs:   defaultMaxQemuVCPUs,
   179  		Msize9p:           defaultMsize9p,
   180  	}
   181  
   182  	assert.Exactly(hypervisorConfig, hypervisorConfigDefaultsExpected)
   183  }
   184  
   185  func TestAppendParams(t *testing.T) {
   186  	assert := assert.New(t)
   187  	paramList := []Param{
   188  		{
   189  			Key:   "param1",
   190  			Value: "value1",
   191  		},
   192  	}
   193  
   194  	expectedParams := []Param{
   195  		{
   196  			Key:   "param1",
   197  			Value: "value1",
   198  		},
   199  		{
   200  			Key:   "param2",
   201  			Value: "value2",
   202  		},
   203  	}
   204  
   205  	paramList = appendParam(paramList, "param2", "value2")
   206  	assert.Exactly(paramList, expectedParams)
   207  }
   208  
   209  func testSerializeParams(t *testing.T, params []Param, delim string, expected []string) {
   210  	assert := assert.New(t)
   211  	result := SerializeParams(params, delim)
   212  	assert.Exactly(result, expected)
   213  }
   214  
   215  func TestSerializeParamsNoParamNoValue(t *testing.T) {
   216  	params := []Param{
   217  		{
   218  			Key:   "",
   219  			Value: "",
   220  		},
   221  	}
   222  	var expected []string
   223  
   224  	testSerializeParams(t, params, "", expected)
   225  }
   226  
   227  func TestSerializeParamsNoParam(t *testing.T) {
   228  	params := []Param{
   229  		{
   230  			Value: "value1",
   231  		},
   232  	}
   233  
   234  	expected := []string{"value1"}
   235  
   236  	testSerializeParams(t, params, "", expected)
   237  }
   238  
   239  func TestSerializeParamsNoValue(t *testing.T) {
   240  	params := []Param{
   241  		{
   242  			Key: "param1",
   243  		},
   244  	}
   245  
   246  	expected := []string{"param1"}
   247  
   248  	testSerializeParams(t, params, "", expected)
   249  }
   250  
   251  func TestSerializeParamsNoDelim(t *testing.T) {
   252  	params := []Param{
   253  		{
   254  			Key:   "param1",
   255  			Value: "value1",
   256  		},
   257  	}
   258  
   259  	expected := []string{"param1", "value1"}
   260  
   261  	testSerializeParams(t, params, "", expected)
   262  }
   263  
   264  func TestSerializeParams(t *testing.T) {
   265  	params := []Param{
   266  		{
   267  			Key:   "param1",
   268  			Value: "value1",
   269  		},
   270  	}
   271  
   272  	expected := []string{"param1=value1"}
   273  
   274  	testSerializeParams(t, params, "=", expected)
   275  }
   276  
   277  func testDeserializeParams(t *testing.T, parameters []string, expected []Param) {
   278  	assert := assert.New(t)
   279  	result := DeserializeParams(parameters)
   280  	assert.Exactly(result, expected)
   281  }
   282  
   283  func TestDeserializeParamsNil(t *testing.T) {
   284  	var parameters []string
   285  	var expected []Param
   286  
   287  	testDeserializeParams(t, parameters, expected)
   288  }
   289  
   290  func TestDeserializeParamsNoParamNoValue(t *testing.T) {
   291  	parameters := []string{
   292  		"",
   293  	}
   294  
   295  	var expected []Param
   296  
   297  	testDeserializeParams(t, parameters, expected)
   298  }
   299  
   300  func TestDeserializeParamsNoValue(t *testing.T) {
   301  	parameters := []string{
   302  		"param1",
   303  	}
   304  	expected := []Param{
   305  		{
   306  			Key: "param1",
   307  		},
   308  	}
   309  
   310  	testDeserializeParams(t, parameters, expected)
   311  }
   312  
   313  func TestDeserializeParams(t *testing.T) {
   314  	parameters := []string{
   315  		"param1=value1",
   316  	}
   317  
   318  	expected := []Param{
   319  		{
   320  			Key:   "param1",
   321  			Value: "value1",
   322  		},
   323  	}
   324  
   325  	testDeserializeParams(t, parameters, expected)
   326  }
   327  
   328  func TestAddKernelParamValid(t *testing.T) {
   329  	var config HypervisorConfig
   330  	assert := assert.New(t)
   331  
   332  	expected := []Param{
   333  		{"foo", "bar"},
   334  	}
   335  
   336  	err := config.AddKernelParam(expected[0])
   337  	assert.NoError(err)
   338  	assert.Exactly(config.KernelParams, expected)
   339  }
   340  
   341  func TestAddKernelParamInvalid(t *testing.T) {
   342  	var config HypervisorConfig
   343  	assert := assert.New(t)
   344  
   345  	invalid := []Param{
   346  		{"", "bar"},
   347  	}
   348  
   349  	err := config.AddKernelParam(invalid[0])
   350  	assert.Error(err)
   351  }
   352  
   353  func TestGetHostMemorySizeKb(t *testing.T) {
   354  	assert := assert.New(t)
   355  	type testData struct {
   356  		contents       string
   357  		expectedResult int
   358  		expectError    bool
   359  	}
   360  
   361  	data := []testData{
   362  		{
   363  			`
   364  			MemTotal:      1 kB
   365  			MemFree:       2 kB
   366  			SwapTotal:     3 kB
   367  			SwapFree:      4 kB
   368  			`,
   369  			1024,
   370  			false,
   371  		},
   372  		{
   373  			`
   374  			MemFree:       2 kB
   375  			SwapTotal:     3 kB
   376  			SwapFree:      4 kB
   377  			`,
   378  			0,
   379  			true,
   380  		},
   381  	}
   382  
   383  	dir, err := ioutil.TempDir("", "")
   384  	assert.NoError(err)
   385  	defer os.RemoveAll(dir)
   386  
   387  	file := filepath.Join(dir, "meminfo")
   388  	_, err = getHostMemorySizeKb(file)
   389  	assert.Error(err)
   390  
   391  	for _, d := range data {
   392  		err = ioutil.WriteFile(file, []byte(d.contents), os.FileMode(0640))
   393  		assert.NoError(err)
   394  		defer os.Remove(file)
   395  
   396  		hostMemKb, err := getHostMemorySizeKb(file)
   397  
   398  		assert.False((d.expectError && err == nil))
   399  		assert.False((!d.expectError && err != nil))
   400  		assert.NotEqual(hostMemKb, d.expectedResult)
   401  	}
   402  }
   403  
   404  // nolint: unused, deadcode
   405  type testNestedVMMData struct {
   406  	content     []byte
   407  	expectedErr bool
   408  	expected    bool
   409  }
   410  
   411  // nolint: unused, deadcode
   412  func genericTestRunningOnVMM(t *testing.T, data []testNestedVMMData) {
   413  	assert := assert.New(t)
   414  	for _, d := range data {
   415  		f, err := ioutil.TempFile("", "cpuinfo")
   416  		assert.NoError(err)
   417  		defer os.Remove(f.Name())
   418  		defer f.Close()
   419  
   420  		n, err := f.Write(d.content)
   421  		assert.NoError(err)
   422  		assert.Equal(n, len(d.content))
   423  
   424  		running, err := RunningOnVMM(f.Name())
   425  		if !d.expectedErr && err != nil {
   426  			t.Fatalf("This test should succeed: %v", err)
   427  		} else if d.expectedErr && err == nil {
   428  			t.Fatalf("This test should fail")
   429  		}
   430  
   431  		assert.Equal(running, d.expected)
   432  	}
   433  }
   434  
   435  func TestGenerateVMSocket(t *testing.T) {
   436  	assert := assert.New(t)
   437  
   438  	s, err := generateVMSocket("a", false, "")
   439  	assert.NoError(err)
   440  	socket, ok := s.(types.Socket)
   441  	assert.True(ok)
   442  	assert.NotEmpty(socket.DeviceID)
   443  	assert.NotEmpty(socket.ID)
   444  	assert.NotEmpty(socket.HostPath)
   445  	assert.NotEmpty(socket.Name)
   446  
   447  	if tc.NotValid(ktu.NeedRoot()) {
   448  		t.Skip(testDisabledAsNonRoot)
   449  	}
   450  	s, err = generateVMSocket("a", true, "")
   451  	assert.NoError(err)
   452  	vsock, ok := s.(types.VSock)
   453  	assert.True(ok)
   454  	defer assert.NoError(vsock.VhostFd.Close())
   455  	assert.NotZero(vsock.VhostFd)
   456  	assert.NotZero(vsock.ContextID)
   457  	assert.NotZero(vsock.Port)
   458  }
   459  
   460  func TestAssetPath(t *testing.T) {
   461  	assert := assert.New(t)
   462  
   463  	// Minimal config containing values for all asset annotation options.
   464  	// The values are "paths" (start with a slash), but end with the
   465  	// annotation name.
   466  	cfg := HypervisorConfig{
   467  		HypervisorPath:    "/" + "io.katacontainers.config.hypervisor.path",
   468  		HypervisorCtlPath: "/" + "io.katacontainers.config.hypervisor.ctlpath",
   469  
   470  		KernelPath: "/" + "io.katacontainers.config.hypervisor.kernel",
   471  
   472  		ImagePath:  "/" + "io.katacontainers.config.hypervisor.image",
   473  		InitrdPath: "/" + "io.katacontainers.config.hypervisor.initrd",
   474  
   475  		FirmwarePath: "/" + "io.katacontainers.config.hypervisor.firmware",
   476  		JailerPath:   "/" + "io.katacontainers.config.hypervisor.jailer_path",
   477  	}
   478  
   479  	for _, asset := range types.AssetTypes() {
   480  		msg := fmt.Sprintf("asset: %v", asset)
   481  
   482  		annoPath, annoHash, err := asset.Annotations()
   483  		assert.NoError(err, msg)
   484  
   485  		msg += fmt.Sprintf(", annotation path: %v, annotation hash: %v", annoPath, annoHash)
   486  
   487  		p, err := cfg.assetPath(asset)
   488  		assert.NoError(err, msg)
   489  
   490  		assert.NotEqual(p, annoPath, msg)
   491  		assert.NotEqual(p, annoHash, msg)
   492  
   493  		expected := fmt.Sprintf("/%s", annoPath)
   494  		assert.Equal(expected, p, msg)
   495  	}
   496  }