github.com/openebs/node-disk-manager@v1.9.1-0.20230225014141-4531f06ffa1e/cmd/ndm_daemonset/probe/mountprobe_test.go (about)

     1  /*
     2  Copyright 2019 The OpenEBS Authors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package probe
    18  
    19  import (
    20  	"io/ioutil"
    21  	"os"
    22  	"path"
    23  	"syscall"
    24  	"testing"
    25  
    26  	"github.com/openebs/node-disk-manager/blockdevice"
    27  	"github.com/openebs/node-disk-manager/pkg/mount"
    28  )
    29  
    30  const (
    31  	mountsFilePath   = "/proc/1/mounts"
    32  	sampleMountsFile = `
    33  sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0
    34  proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
    35  udev /dev devtmpfs rw,nosuid,noexec,relatime,size=4027936k,nr_inodes=1006984,mode=755 0 0
    36  devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0
    37  tmpfs /run tmpfs rw,nosuid,nodev,noexec,relatime,size=811944k,mode=755 0 0
    38  /dev/sda1 / ext4 rw,relatime,errors=remount-ro 0 0
    39  none /sys/fs/bpf bpf rw,nosuid,nodev,noexec,relatime,mode=700 0 0
    40  cgroup /sys/fs/cgroup/rdma cgroup rw,nosuid,nodev,noexec,relatime,rdma 0 0
    41  cgroup /sys/fs/cgroup/freezer cgroup rw,nosuid,nodev,noexec,relatime,freezer 0 0
    42  /dev/loop4 /snap/core18/1988 squashfs ro,nodev,relatime 0 0
    43  /dev/loop0 /snap/core/10823 squashfs ro,nodev,relatime 0 0
    44  /dev/loop3 /snap/gnome-3-28-1804/145 squashfs ro,nodev,relatime 0 0
    45  /dev/loop1 /snap/core/10859 squashfs ro,nodev,relatime 0 0
    46  /dev/loop2 /snap/core18/1944 squashfs ro,nodev,relatime 0 0
    47  /dev/sda4 /boot/efi vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro 0 0
    48  /dev/sda2 /home ext4 rw,relatime 0 0
    49  `
    50  )
    51  
    52  func TestMountProbeFillBlockDeviceDetails(t *testing.T) {
    53  	mp := &mountProbe{}
    54  
    55  	t.Run("DevPath empty", func(t *testing.T) {
    56  		bd := blockdevice.BlockDevice{}
    57  		mp.FillBlockDeviceDetails(&bd)
    58  		if len(bd.FSInfo.MountPoint) > 0 {
    59  			t.Errorf("Expected mountpoints to be empty, found %v",
    60  				bd.FSInfo.MountPoint)
    61  		}
    62  	})
    63  
    64  	t.Run("Device not mounted", func(t *testing.T) {
    65  		// Chroot into a tmp dir
    66  		err := enterFakeRoot(t)
    67  		if err != nil {
    68  			t.Fatal(err)
    69  		}
    70  		defer exitFakeRoot()
    71  
    72  		bd := blockdevice.BlockDevice{
    73  			Identifier: blockdevice.Identifier{
    74  				DevPath: "/dev/sda5",
    75  			},
    76  		}
    77  		mp.FillBlockDeviceDetails(&bd)
    78  		if len(bd.FSInfo.MountPoint) > 0 {
    79  			t.Errorf("Expected mountpoints to be empty, found %v",
    80  				bd.FSInfo.MountPoint)
    81  		}
    82  	})
    83  
    84  	t.Run("Device mounted", func(t *testing.T) {
    85  		err := enterFakeRoot(t)
    86  		if err != nil {
    87  			t.Fatal(err)
    88  		}
    89  		defer exitFakeRoot()
    90  
    91  		bd := blockdevice.BlockDevice{
    92  			Identifier: blockdevice.Identifier{
    93  				DevPath: "/dev/sda1",
    94  			}}
    95  		mp.FillBlockDeviceDetails(&bd)
    96  		if len(bd.FSInfo.MountPoint) <= 0 || bd.FSInfo.MountPoint[0] != "/" {
    97  			t.Errorf("Expected mountpoint to be %v, found %v",
    98  				"/", bd.FSInfo.MountPoint)
    99  		}
   100  	})
   101  }
   102  
   103  // enterFakeRoot creates a fake root in a tmp folder and
   104  // chroots to that folder.
   105  func enterFakeRoot(t *testing.T) error {
   106  	fakeRootPath := t.TempDir()
   107  	realMountsPath := path.Join(fakeRootPath, mount.HostMountsFilePath[1:])
   108  
   109  	t.Helper()
   110  
   111  	// Create the mounts file at the expected path in the tmp dir
   112  	err := os.MkdirAll(path.Dir(realMountsPath), 0755)
   113  	if err != nil {
   114  		return err
   115  	}
   116  	err = createMountsFile(realMountsPath)
   117  	if err != nil {
   118  		return err
   119  	}
   120  
   121  	// Change dir to current root to get chroot back later
   122  	err = os.Chdir("/")
   123  	if err != nil {
   124  		return err
   125  	}
   126  
   127  	// Chroot into the tmp dir
   128  	err = syscall.Chroot(fakeRootPath)
   129  	return err
   130  }
   131  
   132  // exitFakeRoot exits from the chrooted environment
   133  func exitFakeRoot() error {
   134  	// We need to chroot to the original root. The current dir
   135  	// is the actual root since we changed dir to / while
   136  	// entering fake root
   137  	if err := syscall.Chroot("."); err != nil {
   138  		return err
   139  	}
   140  	return nil
   141  }
   142  
   143  func createMountsFile(dest string) error {
   144  	return ioutil.WriteFile(dest, []byte(sampleMountsFile), 0444)
   145  }