Files
kata-containers/virtcontainers/mount_test.go
Samuel Ortiz 24eff72d82 virtcontainers: Initial import
This is a virtcontainers 1.0.8 import into Kata Containers runtime.

virtcontainers is a Go library designed to manage hardware virtualized
pods and containers. It is the core Clear Containers framework and will
become the core Kata Containers framework, as discussed at
https://github.com/kata-containers/runtime/issues/33

Some more more pointers:

virtcontainers README, including some design and architecure notes:
https://github.com/containers/virtcontainers/blob/master/README.md

virtcontainers 1.0 API:
https://github.com/containers/virtcontainers/blob/master/documentation/api/1.0/api.md

Fixes #40

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2018-03-13 00:49:46 +01:00

335 lines
6.4 KiB
Go

//
// Copyright (c) 2017 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package virtcontainers
import (
"bytes"
"fmt"
"github.com/stretchr/testify/assert"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"syscall"
"testing"
)
func TestIsSystemMount(t *testing.T) {
tests := []struct {
mnt string
expected bool
}{
{"/sys", true},
{"/sys/", true},
{"/sys//", true},
{"/sys/fs", true},
{"/sys/fs/", true},
{"/sys/fs/cgroup", true},
{"/sysfoo", false},
{"/home", false},
{"/dev/block/", true},
}
for _, test := range tests {
result := isSystemMount(test.mnt)
if result != test.expected {
t.Fatalf("Expected result for path %s : %v, got %v", test.mnt, test.expected, result)
}
}
}
func TestMajorMinorNumber(t *testing.T) {
devices := []string{"/dev/zero", "/dev/net/tun"}
for _, device := range devices {
cmdStr := fmt.Sprintf("ls -l %s | awk '{print $5$6}'", device)
cmd := exec.Command("sh", "-c", cmdStr)
output, err := cmd.Output()
if err != nil {
t.Fatal(err)
}
data := bytes.Split(output, []byte(","))
if len(data) < 2 {
t.Fatal()
}
majorStr := strings.TrimSpace(string(data[0]))
minorStr := strings.TrimSpace(string(data[1]))
majorNo, err := strconv.Atoi(majorStr)
if err != nil {
t.Fatal(err)
}
minorNo, err := strconv.Atoi(minorStr)
if err != nil {
t.Fatal(err)
}
stat := syscall.Stat_t{}
err = syscall.Stat(device, &stat)
if err != nil {
t.Fatal(err)
}
// Get major and minor numbers for the device itself. Note the use of stat.Rdev instead of Dev.
major := major(stat.Rdev)
minor := minor(stat.Rdev)
if minor != minorNo {
t.Fatalf("Expected minor number for device %s: %d, Got :%d", device, minorNo, minor)
}
if major != majorNo {
t.Fatalf("Expected major number for device %s : %d, Got :%d", device, majorNo, major)
}
}
}
func TestGetDeviceForPathRoot(t *testing.T) {
dev, err := getDeviceForPath("/")
if err != nil {
t.Fatal(err)
}
expected := "/"
if dev.mountPoint != expected {
t.Fatalf("Expected %s mountpoint, got %s", expected, dev.mountPoint)
}
}
func TestGetDeviceForPathValidMount(t *testing.T) {
dev, err := getDeviceForPath("/proc")
if err != nil {
t.Fatal(err)
}
expected := "/proc"
if dev.mountPoint != expected {
t.Fatalf("Expected %s mountpoint, got %s", expected, dev.mountPoint)
}
}
func TestGetDeviceForPathEmptyPath(t *testing.T) {
_, err := getDeviceForPath("")
if err == nil {
t.Fatal()
}
}
func TestGetDeviceForPath(t *testing.T) {
dev, err := getDeviceForPath("///")
if err != nil {
t.Fatal(err)
}
if dev.mountPoint != "/" {
t.Fatal(err)
}
_, err = getDeviceForPath("/../../.././././../.")
if err != nil {
t.Fatal(err)
}
_, err = getDeviceForPath("/root/file with spaces")
if err == nil {
t.Fatal()
}
}
func TestGetDeviceForPathBindMount(t *testing.T) {
if os.Geteuid() != 0 {
t.Skip(testDisabledAsNonRoot)
}
source := filepath.Join(testDir, "testDeviceDirSrc")
dest := filepath.Join(testDir, "testDeviceDirDest")
syscall.Unmount(dest, 0)
os.Remove(source)
os.Remove(dest)
err := os.MkdirAll(source, mountPerm)
if err != nil {
t.Fatal(err)
}
defer os.Remove(source)
err = os.MkdirAll(dest, mountPerm)
if err != nil {
t.Fatal(err)
}
defer os.Remove(dest)
err = bindMount(source, dest, false)
if err != nil {
t.Fatal(err)
}
defer syscall.Unmount(dest, 0)
destFile := filepath.Join(dest, "test")
_, err = os.Create(destFile)
if err != nil {
fmt.Println("Could not create test file:", err)
t.Fatal(err)
}
defer os.Remove(destFile)
sourceDev, _ := getDeviceForPath(source)
destDev, _ := getDeviceForPath(destFile)
if sourceDev != destDev {
t.Fatal()
}
}
func TestGetDevicePathAndFsTypeEmptyMount(t *testing.T) {
_, _, err := getDevicePathAndFsType("")
if err == nil {
t.Fatal()
}
}
func TestGetDevicePathAndFsTypeSuccessful(t *testing.T) {
path, fstype, err := getDevicePathAndFsType("/proc")
if err != nil {
t.Fatal(err)
}
if path != "proc" || fstype != "proc" {
t.Fatal(err)
}
}
func TestIsDeviceMapper(t *testing.T) {
// known major, minor for /dev/tty
major := 5
minor := 0
isDM, err := isDeviceMapper(major, minor)
if err != nil {
t.Fatal(err)
}
if isDM {
t.Fatal()
}
// fake the block device format
blockFormatTemplate = "/sys/dev/char/%d:%d"
isDM, err = isDeviceMapper(major, minor)
if err != nil {
t.Fatal(err)
}
if !isDM {
t.Fatal()
}
}
func TestGetVirtDriveNameInvalidIndex(t *testing.T) {
_, err := getVirtDriveName(-1)
if err == nil {
t.Fatal(err)
}
}
func TestGetVirtDriveName(t *testing.T) {
tests := []struct {
index int
expectedDrive string
}{
{0, "vda"},
{25, "vdz"},
{27, "vdab"},
{704, "vdaac"},
{18277, "vdzzz"},
}
for _, test := range tests {
driveName, err := getVirtDriveName(test.index)
if err != nil {
t.Fatal(err)
}
if driveName != test.expectedDrive {
t.Fatalf("Incorrect drive Name: Got: %s, Expecting :%s", driveName, test.expectedDrive)
}
}
}
func TestGetSCSIIdLun(t *testing.T) {
tests := []struct {
index int
expectedScsiID int
expectedLun int
}{
{0, 0, 0},
{1, 0, 1},
{2, 0, 2},
{255, 0, 255},
{256, 1, 0},
{257, 1, 1},
{258, 1, 2},
{512, 2, 0},
{513, 2, 1},
}
for _, test := range tests {
scsiID, lun, err := getSCSIIdLun(test.index)
assert.Nil(t, err)
if scsiID != test.expectedScsiID && lun != test.expectedLun {
t.Fatalf("Expecting scsi-id:lun %d:%d, Got %d:%d", test.expectedScsiID, test.expectedLun, scsiID, lun)
}
}
_, _, err := getSCSIIdLun(maxSCSIDevices + 1)
assert.NotNil(t, err)
}
func TestGetSCSIAddress(t *testing.T) {
tests := []struct {
index int
expectedSCSIAddress string
}{
{0, "0:0"},
{200, "0:200"},
{255, "0:255"},
{258, "1:2"},
{512, "2:0"},
}
for _, test := range tests {
scsiAddr, err := getSCSIAddress(test.index)
assert.Nil(t, err)
assert.Equal(t, scsiAddr, test.expectedSCSIAddress)
}
}