github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/vfs/vfs_test.go (about)

     1  // Test suite for vfs
     2  
     3  package vfs
     4  
     5  import (
     6  	"context"
     7  	"fmt"
     8  	"io"
     9  	"os"
    10  	"testing"
    11  
    12  	"github.com/pkg/errors"
    13  	_ "github.com/rclone/rclone/backend/all" // import all the backends
    14  	"github.com/rclone/rclone/fs"
    15  	"github.com/rclone/rclone/fstest"
    16  	"github.com/rclone/rclone/vfs/vfscommon"
    17  	"github.com/stretchr/testify/assert"
    18  	"github.com/stretchr/testify/require"
    19  )
    20  
    21  // Some times used in the tests
    22  var (
    23  	t1 = fstest.Time("2001-02-03T04:05:06.499999999Z")
    24  	t2 = fstest.Time("2011-12-25T12:59:59.123456789Z")
    25  	t3 = fstest.Time("2011-12-30T12:59:59.000000000Z")
    26  )
    27  
    28  // TestMain drives the tests
    29  func TestMain(m *testing.M) {
    30  	fstest.TestMain(m)
    31  }
    32  
    33  // Check baseHandle performs as advertised
    34  func TestVFSbaseHandle(t *testing.T) {
    35  	fh := baseHandle{}
    36  
    37  	err := fh.Chdir()
    38  	assert.Equal(t, ENOSYS, err)
    39  
    40  	err = fh.Chmod(0)
    41  	assert.Equal(t, ENOSYS, err)
    42  
    43  	err = fh.Chown(0, 0)
    44  	assert.Equal(t, ENOSYS, err)
    45  
    46  	err = fh.Close()
    47  	assert.Equal(t, ENOSYS, err)
    48  
    49  	fd := fh.Fd()
    50  	assert.Equal(t, uintptr(0), fd)
    51  
    52  	name := fh.Name()
    53  	assert.Equal(t, "", name)
    54  
    55  	_, err = fh.Read(nil)
    56  	assert.Equal(t, ENOSYS, err)
    57  
    58  	_, err = fh.ReadAt(nil, 0)
    59  	assert.Equal(t, ENOSYS, err)
    60  
    61  	_, err = fh.Readdir(0)
    62  	assert.Equal(t, ENOSYS, err)
    63  
    64  	_, err = fh.Readdirnames(0)
    65  	assert.Equal(t, ENOSYS, err)
    66  
    67  	_, err = fh.Seek(0, io.SeekStart)
    68  	assert.Equal(t, ENOSYS, err)
    69  
    70  	_, err = fh.Stat()
    71  	assert.Equal(t, ENOSYS, err)
    72  
    73  	err = fh.Sync()
    74  	assert.Equal(t, nil, err)
    75  
    76  	err = fh.Truncate(0)
    77  	assert.Equal(t, ENOSYS, err)
    78  
    79  	_, err = fh.Write(nil)
    80  	assert.Equal(t, ENOSYS, err)
    81  
    82  	_, err = fh.WriteAt(nil, 0)
    83  	assert.Equal(t, ENOSYS, err)
    84  
    85  	_, err = fh.WriteString("")
    86  	assert.Equal(t, ENOSYS, err)
    87  
    88  	err = fh.Flush()
    89  	assert.Equal(t, ENOSYS, err)
    90  
    91  	err = fh.Release()
    92  	assert.Equal(t, ENOSYS, err)
    93  
    94  	node := fh.Node()
    95  	assert.Nil(t, node)
    96  }
    97  
    98  // TestNew sees if the New command works properly
    99  func TestVFSNew(t *testing.T) {
   100  	r := fstest.NewRun(t)
   101  	defer r.Finalise()
   102  
   103  	// Check making a VFS with nil options
   104  	vfs := New(r.Fremote, nil)
   105  	var defaultOpt = vfscommon.DefaultOpt
   106  	defaultOpt.DirPerms |= os.ModeDir
   107  	assert.Equal(t, vfs.Opt, defaultOpt)
   108  	assert.Equal(t, vfs.f, r.Fremote)
   109  
   110  	// Check the initialisation
   111  	var opt = vfscommon.DefaultOpt
   112  	opt.DirPerms = 0777
   113  	opt.FilePerms = 0666
   114  	opt.Umask = 0002
   115  	vfs = New(r.Fremote, &opt)
   116  	assert.Equal(t, os.FileMode(0775)|os.ModeDir, vfs.Opt.DirPerms)
   117  	assert.Equal(t, os.FileMode(0664), vfs.Opt.FilePerms)
   118  }
   119  
   120  // TestRoot checks root directory is present and correct
   121  func TestVFSRoot(t *testing.T) {
   122  	r := fstest.NewRun(t)
   123  	defer r.Finalise()
   124  	vfs := New(r.Fremote, nil)
   125  
   126  	root, err := vfs.Root()
   127  	require.NoError(t, err)
   128  	assert.Equal(t, vfs.root, root)
   129  	assert.True(t, root.IsDir())
   130  	assert.Equal(t, vfs.Opt.DirPerms.Perm(), root.Mode().Perm())
   131  }
   132  
   133  func TestVFSStat(t *testing.T) {
   134  	r := fstest.NewRun(t)
   135  	defer r.Finalise()
   136  	vfs := New(r.Fremote, nil)
   137  
   138  	file1 := r.WriteObject(context.Background(), "file1", "file1 contents", t1)
   139  	file2 := r.WriteObject(context.Background(), "dir/file2", "file2 contents", t2)
   140  	fstest.CheckItems(t, r.Fremote, file1, file2)
   141  
   142  	node, err := vfs.Stat("file1")
   143  	require.NoError(t, err)
   144  	assert.True(t, node.IsFile())
   145  	assert.Equal(t, "file1", node.Name())
   146  
   147  	node, err = vfs.Stat("dir")
   148  	require.NoError(t, err)
   149  	assert.True(t, node.IsDir())
   150  	assert.Equal(t, "dir", node.Name())
   151  
   152  	node, err = vfs.Stat("dir/file2")
   153  	require.NoError(t, err)
   154  	assert.True(t, node.IsFile())
   155  	assert.Equal(t, "file2", node.Name())
   156  
   157  	_, err = vfs.Stat("not found")
   158  	assert.Equal(t, os.ErrNotExist, err)
   159  
   160  	_, err = vfs.Stat("dir/not found")
   161  	assert.Equal(t, os.ErrNotExist, err)
   162  
   163  	_, err = vfs.Stat("not found/not found")
   164  	assert.Equal(t, os.ErrNotExist, err)
   165  
   166  	_, err = vfs.Stat("file1/under a file")
   167  	assert.Equal(t, os.ErrNotExist, err)
   168  }
   169  
   170  func TestVFSStatParent(t *testing.T) {
   171  	r := fstest.NewRun(t)
   172  	defer r.Finalise()
   173  	vfs := New(r.Fremote, nil)
   174  
   175  	file1 := r.WriteObject(context.Background(), "file1", "file1 contents", t1)
   176  	file2 := r.WriteObject(context.Background(), "dir/file2", "file2 contents", t2)
   177  	fstest.CheckItems(t, r.Fremote, file1, file2)
   178  
   179  	node, leaf, err := vfs.StatParent("file1")
   180  	require.NoError(t, err)
   181  	assert.True(t, node.IsDir())
   182  	assert.Equal(t, "/", node.Name())
   183  	assert.Equal(t, "file1", leaf)
   184  
   185  	node, leaf, err = vfs.StatParent("dir/file2")
   186  	require.NoError(t, err)
   187  	assert.True(t, node.IsDir())
   188  	assert.Equal(t, "dir", node.Name())
   189  	assert.Equal(t, "file2", leaf)
   190  
   191  	node, leaf, err = vfs.StatParent("not found")
   192  	require.NoError(t, err)
   193  	assert.True(t, node.IsDir())
   194  	assert.Equal(t, "/", node.Name())
   195  	assert.Equal(t, "not found", leaf)
   196  
   197  	_, _, err = vfs.StatParent("not found dir/not found")
   198  	assert.Equal(t, os.ErrNotExist, err)
   199  
   200  	_, _, err = vfs.StatParent("file1/under a file")
   201  	assert.Equal(t, os.ErrExist, err)
   202  }
   203  
   204  func TestVFSOpenFile(t *testing.T) {
   205  	r := fstest.NewRun(t)
   206  	defer r.Finalise()
   207  	vfs := New(r.Fremote, nil)
   208  
   209  	file1 := r.WriteObject(context.Background(), "file1", "file1 contents", t1)
   210  	file2 := r.WriteObject(context.Background(), "dir/file2", "file2 contents", t2)
   211  	fstest.CheckItems(t, r.Fremote, file1, file2)
   212  
   213  	fd, err := vfs.OpenFile("file1", os.O_RDONLY, 0777)
   214  	require.NoError(t, err)
   215  	assert.NotNil(t, fd)
   216  	require.NoError(t, fd.Close())
   217  
   218  	fd, err = vfs.OpenFile("dir", os.O_RDONLY, 0777)
   219  	require.NoError(t, err)
   220  	assert.NotNil(t, fd)
   221  	require.NoError(t, fd.Close())
   222  
   223  	fd, err = vfs.OpenFile("dir/new_file.txt", os.O_RDONLY, 0777)
   224  	assert.Equal(t, os.ErrNotExist, err)
   225  	assert.Nil(t, fd)
   226  
   227  	fd, err = vfs.OpenFile("dir/new_file.txt", os.O_WRONLY|os.O_CREATE, 0777)
   228  	require.NoError(t, err)
   229  	assert.NotNil(t, fd)
   230  	err = fd.Close()
   231  	if errors.Cause(err) != fs.ErrorCantUploadEmptyFiles {
   232  		require.NoError(t, err)
   233  	}
   234  
   235  	fd, err = vfs.OpenFile("not found/new_file.txt", os.O_WRONLY|os.O_CREATE, 0777)
   236  	assert.Equal(t, os.ErrNotExist, err)
   237  	assert.Nil(t, fd)
   238  }
   239  
   240  func TestVFSRename(t *testing.T) {
   241  	r := fstest.NewRun(t)
   242  	defer r.Finalise()
   243  	features := r.Fremote.Features()
   244  	if features.Move == nil && features.Copy == nil {
   245  		return // skip as can't rename files
   246  	}
   247  	vfs := New(r.Fremote, nil)
   248  
   249  	file1 := r.WriteObject(context.Background(), "dir/file2", "file2 contents", t2)
   250  	fstest.CheckItems(t, r.Fremote, file1)
   251  
   252  	err := vfs.Rename("dir/file2", "dir/file1")
   253  	require.NoError(t, err)
   254  	file1.Path = "dir/file1"
   255  	fstest.CheckItems(t, r.Fremote, file1)
   256  
   257  	err = vfs.Rename("dir/file1", "file0")
   258  	require.NoError(t, err)
   259  	file1.Path = "file0"
   260  	fstest.CheckItems(t, r.Fremote, file1)
   261  
   262  	err = vfs.Rename("not found/file0", "file0")
   263  	assert.Equal(t, os.ErrNotExist, err)
   264  
   265  	err = vfs.Rename("file0", "not found/file0")
   266  	assert.Equal(t, os.ErrNotExist, err)
   267  }
   268  
   269  func TestVFSStatfs(t *testing.T) {
   270  	r := fstest.NewRun(t)
   271  	defer r.Finalise()
   272  	vfs := New(r.Fremote, nil)
   273  
   274  	// pre-conditions
   275  	assert.Nil(t, vfs.usage)
   276  	assert.True(t, vfs.usageTime.IsZero())
   277  
   278  	aboutSupported := r.Fremote.Features().About != nil
   279  
   280  	// read
   281  	total, used, free := vfs.Statfs()
   282  	if !aboutSupported {
   283  		assert.Equal(t, int64(unknownFreeBytes), total)
   284  		assert.Equal(t, int64(unknownFreeBytes), free)
   285  		assert.Equal(t, int64(0), used)
   286  		return // can't test anything else if About not supported
   287  	}
   288  	require.NotNil(t, vfs.usage)
   289  	assert.False(t, vfs.usageTime.IsZero())
   290  	if vfs.usage.Total != nil {
   291  		assert.Equal(t, *vfs.usage.Total, total)
   292  	} else {
   293  		assert.True(t, total >= int64(unknownFreeBytes))
   294  	}
   295  	if vfs.usage.Free != nil {
   296  		assert.Equal(t, *vfs.usage.Free, free)
   297  	} else {
   298  		if vfs.usage.Total != nil && vfs.usage.Used != nil {
   299  			assert.Equal(t, free, total-used)
   300  		} else {
   301  			assert.True(t, free >= int64(unknownFreeBytes))
   302  		}
   303  	}
   304  	if vfs.usage.Used != nil {
   305  		assert.Equal(t, *vfs.usage.Used, used)
   306  	} else {
   307  		assert.Equal(t, int64(0), used)
   308  	}
   309  
   310  	// read cached
   311  	oldUsage := vfs.usage
   312  	oldTime := vfs.usageTime
   313  	total2, used2, free2 := vfs.Statfs()
   314  	assert.Equal(t, oldUsage, vfs.usage)
   315  	assert.Equal(t, total, total2)
   316  	assert.Equal(t, used, used2)
   317  	assert.Equal(t, free, free2)
   318  	assert.Equal(t, oldTime, vfs.usageTime)
   319  }
   320  
   321  func TestFillInMissingSizes(t *testing.T) {
   322  	const unknownFree = 10
   323  	for _, test := range []struct {
   324  		total, free, used             int64
   325  		wantTotal, wantUsed, wantFree int64
   326  	}{
   327  		{
   328  			total: 20, free: 5, used: 15,
   329  			wantTotal: 20, wantFree: 5, wantUsed: 15,
   330  		},
   331  		{
   332  			total: 20, free: 5, used: -1,
   333  			wantTotal: 20, wantFree: 5, wantUsed: 15,
   334  		},
   335  		{
   336  			total: 20, free: -1, used: 15,
   337  			wantTotal: 20, wantFree: 5, wantUsed: 15,
   338  		},
   339  		{
   340  			total: 20, free: -1, used: -1,
   341  			wantTotal: 20, wantFree: 20, wantUsed: 0,
   342  		},
   343  		{
   344  			total: -1, free: 5, used: 15,
   345  			wantTotal: 20, wantFree: 5, wantUsed: 15,
   346  		},
   347  		{
   348  			total: -1, free: 15, used: -1,
   349  			wantTotal: 15, wantFree: 15, wantUsed: 0,
   350  		},
   351  		{
   352  			total: -1, free: -1, used: 15,
   353  			wantTotal: 25, wantFree: 10, wantUsed: 15,
   354  		},
   355  		{
   356  			total: -1, free: -1, used: -1,
   357  			wantTotal: 10, wantFree: 10, wantUsed: 0,
   358  		},
   359  	} {
   360  		t.Run(fmt.Sprintf("total=%d,free=%d,used=%d", test.total, test.free, test.used), func(t *testing.T) {
   361  			gotTotal, gotUsed, gotFree := fillInMissingSizes(test.total, test.used, test.free, unknownFree)
   362  			assert.Equal(t, test.wantTotal, gotTotal, "total")
   363  			assert.Equal(t, test.wantUsed, gotUsed, "used")
   364  			assert.Equal(t, test.wantFree, gotFree, "free")
   365  		})
   366  	}
   367  }