github.com/rhatdan/storage@v1.12.13/drivers/devmapper/devmapper_test.go (about)

     1  // +build linux
     2  
     3  package devmapper
     4  
     5  import (
     6  	"fmt"
     7  	"os"
     8  	"syscall"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/containers/storage/drivers"
    13  	"github.com/containers/storage/drivers/graphtest"
    14  )
    15  
    16  func init() {
    17  	// Reduce the size of the base fs and loopback for the tests
    18  	defaultDataLoopbackSize = 300 * 1024 * 1024
    19  	defaultMetaDataLoopbackSize = 200 * 1024 * 1024
    20  	defaultBaseFsSize = 300 * 1024 * 1024
    21  	defaultUdevSyncOverride = true
    22  	if err := initLoopbacks(); err != nil {
    23  		panic(err)
    24  	}
    25  }
    26  
    27  // initLoopbacks ensures that the loopback devices are properly created within
    28  // the system running the device mapper tests.
    29  func initLoopbacks() error {
    30  	statT, err := getBaseLoopStats()
    31  	if err != nil {
    32  		return err
    33  	}
    34  	// create at least 8 loopback files, ya, that is a good number
    35  	for i := 0; i < 8; i++ {
    36  		loopPath := fmt.Sprintf("/dev/loop%d", i)
    37  		// only create new loopback files if they don't exist
    38  		if _, err := os.Stat(loopPath); err != nil {
    39  			if mkerr := syscall.Mknod(loopPath,
    40  				uint32(statT.Mode|syscall.S_IFBLK), int((7<<8)|(i&0xff)|((i&0xfff00)<<12))); mkerr != nil {
    41  				return mkerr
    42  			}
    43  			os.Chown(loopPath, int(statT.Uid), int(statT.Gid))
    44  		}
    45  	}
    46  	return nil
    47  }
    48  
    49  // getBaseLoopStats inspects /dev/loop0 to collect uid,gid, and mode for the
    50  // loop0 device on the system.  If it does not exist we assume 0,0,0660 for the
    51  // stat data
    52  func getBaseLoopStats() (*syscall.Stat_t, error) {
    53  	loop0, err := os.Stat("/dev/loop0")
    54  	if err != nil {
    55  		if os.IsNotExist(err) {
    56  			return &syscall.Stat_t{
    57  				Uid:  0,
    58  				Gid:  0,
    59  				Mode: 0660,
    60  			}, nil
    61  		}
    62  		return nil, err
    63  	}
    64  	return loop0.Sys().(*syscall.Stat_t), nil
    65  }
    66  
    67  // This avoids creating a new driver for each test if all tests are run
    68  // Make sure to put new tests between TestDevmapperSetup and TestDevmapperTeardown
    69  func TestDevmapperSetup(t *testing.T) {
    70  	graphtest.GetDriver(t, "devicemapper", "test=1")
    71  }
    72  
    73  func TestDevmapperCreateEmpty(t *testing.T) {
    74  	graphtest.DriverTestCreateEmpty(t, "devicemapper", "test=1")
    75  }
    76  
    77  func TestDevmapperCreateBase(t *testing.T) {
    78  	graphtest.DriverTestCreateBase(t, "devicemapper", "test=1")
    79  }
    80  
    81  func TestDevmapperCreateSnap(t *testing.T) {
    82  	graphtest.DriverTestCreateSnap(t, "devicemapper", "test=1")
    83  }
    84  
    85  func TestDevmapperCreateFromTemplate(t *testing.T) {
    86  	graphtest.DriverTestCreateFromTemplate(t, "devicemapper", "test=1")
    87  }
    88  
    89  func TestDevmapperTeardown(t *testing.T) {
    90  	graphtest.PutDriver(t)
    91  }
    92  
    93  func TestDevmapperEcho(t *testing.T) {
    94  	graphtest.DriverTestEcho(t, "devicemapper", "test=1")
    95  }
    96  
    97  func TestDevmapperReduceLoopBackSize(t *testing.T) {
    98  	tenMB := int64(10 * 1024 * 1024)
    99  	testChangeLoopBackSize(t, -tenMB, defaultDataLoopbackSize, defaultMetaDataLoopbackSize)
   100  }
   101  
   102  func TestDevmapperIncreaseLoopBackSize(t *testing.T) {
   103  	tenMB := int64(10 * 1024 * 1024)
   104  	testChangeLoopBackSize(t, tenMB, defaultDataLoopbackSize+tenMB, defaultMetaDataLoopbackSize+tenMB)
   105  }
   106  
   107  func testChangeLoopBackSize(t *testing.T, delta, expectDataSize, expectMetaDataSize int64) {
   108  	driver := graphtest.GetDriver(t, "devicemapper", "test=1").(*graphtest.Driver).Driver.(*graphdriver.NaiveDiffDriver).ProtoDriver.(*Driver)
   109  	defer graphtest.PutDriver(t)
   110  	// make sure data or metadata loopback size are the default size
   111  	if s := driver.DeviceSet.Status(); s.Data.Total != uint64(defaultDataLoopbackSize) || s.Metadata.Total != uint64(defaultMetaDataLoopbackSize) {
   112  		t.Fatal("data or metadata loop back size is incorrect")
   113  	}
   114  	if err := driver.Cleanup(); err != nil {
   115  		t.Fatal(err)
   116  	}
   117  	//Reload
   118  	d, err := Init(driver.home, graphdriver.Options{DriverOptions: []string{
   119  		fmt.Sprintf("dm.loopdatasize=%d", defaultDataLoopbackSize+delta),
   120  		fmt.Sprintf("dm.loopmetadatasize=%d", defaultMetaDataLoopbackSize+delta),
   121  		"test=1",
   122  	}})
   123  	if err != nil {
   124  		t.Fatalf("error creating devicemapper driver: %v", err)
   125  	}
   126  	driver = d.(*graphdriver.NaiveDiffDriver).ProtoDriver.(*Driver)
   127  	if s := driver.DeviceSet.Status(); s.Data.Total != uint64(expectDataSize) || s.Metadata.Total != uint64(expectMetaDataSize) {
   128  		t.Fatal("data or metadata loop back size is incorrect")
   129  	}
   130  	if err := driver.Cleanup(); err != nil {
   131  		t.Fatal(err)
   132  	}
   133  }
   134  
   135  // Make sure devices.Lock() has been release upon return from cleanupDeletedDevices() function
   136  func TestDevmapperLockReleasedDeviceDeletion(t *testing.T) {
   137  	driver := graphtest.GetDriver(t, "devicemapper", "test=1").(*graphtest.Driver).Driver.(*graphdriver.NaiveDiffDriver).ProtoDriver.(*Driver)
   138  	defer graphtest.PutDriver(t)
   139  
   140  	// Call cleanupDeletedDevices() and after the call take and release
   141  	// DeviceSet Lock. If lock has not been released, this will hang.
   142  	driver.DeviceSet.cleanupDeletedDevices()
   143  
   144  	doneChan := make(chan bool)
   145  
   146  	go func() {
   147  		driver.DeviceSet.Lock()
   148  		defer driver.DeviceSet.Unlock()
   149  		doneChan <- true
   150  	}()
   151  
   152  	select {
   153  	case <-time.After(time.Second * 5):
   154  		// Timer expired. That means lock was not released upon
   155  		// function return and we are deadlocked. Release lock
   156  		// here so that cleanup could succeed and fail the test.
   157  		driver.DeviceSet.Unlock()
   158  		t.Fatal("Could not acquire devices lock after call to cleanupDeletedDevices()")
   159  	case <-doneChan:
   160  	}
   161  }