github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/backend/cache/cache_mount_windows_test.go (about)

     1  // +build windows
     2  // +build !race
     3  
     4  package cache_test
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/billziss-gh/cgofuse/fuse"
    13  	"github.com/pkg/errors"
    14  	"github.com/rclone/rclone/cmd/cmount"
    15  	"github.com/rclone/rclone/cmd/mountlib"
    16  	"github.com/rclone/rclone/fs"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  // waitFor runs fn() until it returns true or the timeout expires
    21  func waitFor(fn func() bool) (ok bool) {
    22  	const totalWait = 10 * time.Second
    23  	const individualWait = 10 * time.Millisecond
    24  	for i := 0; i < int(totalWait/individualWait); i++ {
    25  		ok = fn()
    26  		if ok {
    27  			return ok
    28  		}
    29  		time.Sleep(individualWait)
    30  	}
    31  	return false
    32  }
    33  
    34  func (r *run) mountFs(t *testing.T, f fs.Fs) {
    35  	// FIXME implement cmount
    36  	t.Skip("windows not supported yet")
    37  
    38  	device := f.Name() + ":" + f.Root()
    39  	options := []string{
    40  		"-o", "fsname=" + device,
    41  		"-o", "subtype=rclone",
    42  		"-o", fmt.Sprintf("max_readahead=%d", mountlib.MaxReadAhead),
    43  		"-o", "uid=-1",
    44  		"-o", "gid=-1",
    45  		"-o", "allow_other",
    46  		// This causes FUSE to supply O_TRUNC with the Open
    47  		// call which is more efficient for cmount.  However
    48  		// it does not work with cgofuse on Windows with
    49  		// WinFSP so cmount must work with or without it.
    50  		"-o", "atomic_o_trunc",
    51  		"--FileSystemName=rclone",
    52  	}
    53  
    54  	fsys := cmount.NewFS(f)
    55  	host := fuse.NewFileSystemHost(fsys)
    56  
    57  	// Serve the mount point in the background returning error to errChan
    58  	r.unmountRes = make(chan error, 1)
    59  	go func() {
    60  		var err error
    61  		ok := host.Mount(r.mntDir, options)
    62  		if !ok {
    63  			err = errors.New("mount failed")
    64  		}
    65  		r.unmountRes <- err
    66  	}()
    67  
    68  	// unmount
    69  	r.unmountFn = func() error {
    70  		// Shutdown the VFS
    71  		fsys.VFS.Shutdown()
    72  		if host.Unmount() {
    73  			if !waitFor(func() bool {
    74  				_, err := os.Stat(r.mntDir)
    75  				return err != nil
    76  			}) {
    77  				t.Fatalf("mountpoint %q didn't disappear after unmount - continuing anyway", r.mntDir)
    78  			}
    79  			return nil
    80  		}
    81  		return errors.New("host unmount failed")
    82  	}
    83  
    84  	// Wait for the filesystem to become ready, checking the file
    85  	// system didn't blow up before starting
    86  	select {
    87  	case err := <-r.unmountRes:
    88  		require.NoError(t, err)
    89  	case <-time.After(time.Second * 3):
    90  	}
    91  
    92  	// Wait for the mount point to be available on Windows
    93  	// On Windows the Init signal comes slightly before the mount is ready
    94  	if !waitFor(func() bool {
    95  		_, err := os.Stat(r.mntDir)
    96  		return err == nil
    97  	}) {
    98  		t.Errorf("mountpoint %q didn't became available on mount", r.mntDir)
    99  	}
   100  
   101  	r.vfs = fsys.VFS
   102  	r.isMounted = true
   103  }
   104  
   105  func (r *run) unmountFs(t *testing.T, f fs.Fs) {
   106  	// FIXME implement cmount
   107  	t.Skip("windows not supported yet")
   108  	var err error
   109  
   110  	for i := 0; i < 4; i++ {
   111  		err = r.unmountFn()
   112  		if err != nil {
   113  			//log.Printf("signal to umount failed - retrying: %v", err)
   114  			time.Sleep(3 * time.Second)
   115  			continue
   116  		}
   117  		break
   118  	}
   119  	require.NoError(t, err)
   120  	err = <-r.unmountRes
   121  	require.NoError(t, err)
   122  	err = r.vfs.CleanUp()
   123  	require.NoError(t, err)
   124  	r.isMounted = false
   125  }