github.com/ncw/rclone@v1.48.1-0.20190724201158-a35aa1360e3e/backend/cache/cache_mount_windows_test.go (about)

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