github.com/dennwc/btrfs@v0.0.0-20221026161108-3097362dc072/test/btrfstest.go (about)

     1  package btrfstest
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"io/ioutil"
     7  	"log"
     8  	"os"
     9  	"os/exec"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  )
    14  
    15  func run(name string, args ...string) error {
    16  	buf := bytes.NewBuffer(nil)
    17  	cmd := exec.Command(name, args...)
    18  	cmd.Stdout = buf
    19  	cmd.Stderr = buf
    20  	err := cmd.Run()
    21  	if err == nil {
    22  		return nil
    23  	} else if buf.Len() == 0 {
    24  		return err
    25  	}
    26  	return errors.New("error: " + strings.TrimSpace(string(buf.Bytes())))
    27  }
    28  
    29  func Mkfs(file string, size int64) error {
    30  	f, err := os.Create(file)
    31  	if err != nil {
    32  		return err
    33  	}
    34  	if err = f.Truncate(size); err != nil {
    35  		f.Close()
    36  		return err
    37  	}
    38  	if err = f.Close(); err != nil {
    39  		return err
    40  	}
    41  	if err = run("mkfs.btrfs", file); err != nil {
    42  		os.Remove(file)
    43  		return err
    44  	}
    45  	return err
    46  }
    47  
    48  func Mount(mount string, file string) error {
    49  	if err := run("mount", file, mount); err != nil {
    50  		return err
    51  	}
    52  	return nil
    53  }
    54  
    55  func Unmount(mount string) error {
    56  	for i := 0; i < 5; i++ {
    57  		if err := run("umount", mount); err == nil {
    58  			break
    59  		} else {
    60  			if strings.Contains(err.Error(), "busy") {
    61  				time.Sleep(time.Second)
    62  			} else {
    63  				break
    64  			}
    65  		}
    66  	}
    67  	return nil
    68  }
    69  
    70  func New(t testing.TB, size int64) (string, func()) {
    71  	f, err := ioutil.TempFile("", "btrfs_vol")
    72  	if err != nil {
    73  		t.Fatal(err)
    74  	}
    75  	name := f.Name()
    76  	f.Close()
    77  	rm := func() {
    78  		os.Remove(name)
    79  	}
    80  	if err = Mkfs(name, size); err != nil {
    81  		rm()
    82  	}
    83  	mount, err := ioutil.TempDir("", "btrfs_mount")
    84  	if err != nil {
    85  		rm()
    86  		t.Fatal(err)
    87  	}
    88  	if err = Mount(mount, name); err != nil {
    89  		rm()
    90  		os.RemoveAll(mount)
    91  		if txt := err.Error(); strings.Contains(txt, "permission denied") ||
    92  			strings.Contains(txt, "only root") {
    93  			t.Skip(err)
    94  		} else {
    95  			t.Fatal(err)
    96  		}
    97  	}
    98  	done := false
    99  	return mount, func() {
   100  		if done {
   101  			return
   102  		}
   103  		if err := Unmount(mount); err != nil {
   104  			log.Println("umount failed:", err)
   105  		}
   106  		if err := os.Remove(mount); err != nil {
   107  			log.Println("cleanup failed:", err)
   108  		}
   109  		rm()
   110  		done = true
   111  	}
   112  }