github.com/ncw/rclone@v1.48.1-0.20190724201158-a35aa1360e3e/fs/operations/rc_test.go (about)

     1  package operations_test
     2  
     3  import (
     4  	"context"
     5  	"net/http"
     6  	"net/http/httptest"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/ncw/rclone/fs"
    11  	"github.com/ncw/rclone/fs/cache"
    12  	"github.com/ncw/rclone/fs/operations"
    13  	"github.com/ncw/rclone/fs/rc"
    14  	"github.com/ncw/rclone/fstest"
    15  	"github.com/stretchr/testify/assert"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  func rcNewRun(t *testing.T, method string) (*fstest.Run, *rc.Call) {
    20  	if *fstest.RemoteName != "" {
    21  		t.Skip("Skipping test on non local remote")
    22  	}
    23  	r := fstest.NewRun(t)
    24  	call := rc.Calls.Get(method)
    25  	assert.NotNil(t, call)
    26  	cache.Put(r.LocalName, r.Flocal)
    27  	cache.Put(r.FremoteName, r.Fremote)
    28  	return r, call
    29  }
    30  
    31  // operations/about: Return the space used on the remote
    32  func TestRcAbout(t *testing.T) {
    33  	r, call := rcNewRun(t, "operations/about")
    34  	defer r.Finalise()
    35  	r.Mkdir(context.Background(), r.Fremote)
    36  
    37  	// Will get an error if remote doesn't support About
    38  	expectedErr := r.Fremote.Features().About == nil
    39  
    40  	in := rc.Params{
    41  		"fs": r.FremoteName,
    42  	}
    43  	out, err := call.Fn(context.Background(), in)
    44  	if expectedErr {
    45  		assert.Error(t, err)
    46  		return
    47  	}
    48  	require.NoError(t, err)
    49  
    50  	// Can't really check the output much!
    51  	assert.NotEqual(t, int64(0), out["Total"])
    52  }
    53  
    54  // operations/cleanup: Remove trashed files in the remote or path
    55  func TestRcCleanup(t *testing.T) {
    56  	r, call := rcNewRun(t, "operations/cleanup")
    57  	defer r.Finalise()
    58  
    59  	in := rc.Params{
    60  		"fs": r.LocalName,
    61  	}
    62  	out, err := call.Fn(context.Background(), in)
    63  	require.Error(t, err)
    64  	assert.Equal(t, rc.Params(nil), out)
    65  	assert.Contains(t, err.Error(), "doesn't support cleanup")
    66  }
    67  
    68  // operations/copyfile: Copy a file from source remote to destination remote
    69  func TestRcCopyfile(t *testing.T) {
    70  	r, call := rcNewRun(t, "operations/copyfile")
    71  	defer r.Finalise()
    72  	file1 := r.WriteFile("file1", "file1 contents", t1)
    73  	r.Mkdir(context.Background(), r.Fremote)
    74  	fstest.CheckItems(t, r.Flocal, file1)
    75  	fstest.CheckItems(t, r.Fremote)
    76  
    77  	in := rc.Params{
    78  		"srcFs":     r.LocalName,
    79  		"srcRemote": "file1",
    80  		"dstFs":     r.FremoteName,
    81  		"dstRemote": "file1-renamed",
    82  	}
    83  	out, err := call.Fn(context.Background(), in)
    84  	require.NoError(t, err)
    85  	assert.Equal(t, rc.Params(nil), out)
    86  
    87  	fstest.CheckItems(t, r.Flocal, file1)
    88  	file1.Path = "file1-renamed"
    89  	fstest.CheckItems(t, r.Fremote, file1)
    90  }
    91  
    92  // operations/copyurl: Copy the URL to the object
    93  func TestRcCopyurl(t *testing.T) {
    94  	r, call := rcNewRun(t, "operations/copyurl")
    95  	defer r.Finalise()
    96  	contents := "file1 contents\n"
    97  	file1 := r.WriteFile("file1", contents, t1)
    98  	r.Mkdir(context.Background(), r.Fremote)
    99  	fstest.CheckItems(t, r.Fremote)
   100  
   101  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   102  		_, err := w.Write([]byte(contents))
   103  		assert.NoError(t, err)
   104  	}))
   105  	defer ts.Close()
   106  
   107  	in := rc.Params{
   108  		"fs":     r.FremoteName,
   109  		"remote": "file1",
   110  		"url":    ts.URL,
   111  	}
   112  	out, err := call.Fn(context.Background(), in)
   113  	require.NoError(t, err)
   114  	assert.Equal(t, rc.Params(nil), out)
   115  
   116  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{file1}, nil, fs.ModTimeNotSupported)
   117  }
   118  
   119  // operations/delete: Remove files in the path
   120  func TestRcDelete(t *testing.T) {
   121  	r, call := rcNewRun(t, "operations/delete")
   122  	defer r.Finalise()
   123  
   124  	file1 := r.WriteObject(context.Background(), "small", "1234567890", t2)                                                                                           // 10 bytes
   125  	file2 := r.WriteObject(context.Background(), "medium", "------------------------------------------------------------", t1)                                        // 60 bytes
   126  	file3 := r.WriteObject(context.Background(), "large", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", t1) // 100 bytes
   127  	fstest.CheckItems(t, r.Fremote, file1, file2, file3)
   128  
   129  	in := rc.Params{
   130  		"fs": r.FremoteName,
   131  	}
   132  	out, err := call.Fn(context.Background(), in)
   133  	require.NoError(t, err)
   134  	assert.Equal(t, rc.Params(nil), out)
   135  
   136  	fstest.CheckItems(t, r.Fremote)
   137  }
   138  
   139  // operations/deletefile: Remove the single file pointed to
   140  func TestRcDeletefile(t *testing.T) {
   141  	r, call := rcNewRun(t, "operations/deletefile")
   142  	defer r.Finalise()
   143  
   144  	file1 := r.WriteObject(context.Background(), "small", "1234567890", t2)                                                    // 10 bytes
   145  	file2 := r.WriteObject(context.Background(), "medium", "------------------------------------------------------------", t1) // 60 bytes
   146  	fstest.CheckItems(t, r.Fremote, file1, file2)
   147  
   148  	in := rc.Params{
   149  		"fs":     r.FremoteName,
   150  		"remote": "small",
   151  	}
   152  	out, err := call.Fn(context.Background(), in)
   153  	require.NoError(t, err)
   154  	assert.Equal(t, rc.Params(nil), out)
   155  
   156  	fstest.CheckItems(t, r.Fremote, file2)
   157  }
   158  
   159  // operations/list: List the given remote and path in JSON format
   160  func TestRcList(t *testing.T) {
   161  	r, call := rcNewRun(t, "operations/list")
   162  	defer r.Finalise()
   163  
   164  	file1 := r.WriteObject(context.Background(), "a", "a", t1)
   165  	file2 := r.WriteObject(context.Background(), "subdir/b", "bb", t2)
   166  
   167  	fstest.CheckItems(t, r.Fremote, file1, file2)
   168  
   169  	in := rc.Params{
   170  		"fs":     r.FremoteName,
   171  		"remote": "",
   172  	}
   173  	out, err := call.Fn(context.Background(), in)
   174  	require.NoError(t, err)
   175  
   176  	list := out["list"].([]*operations.ListJSONItem)
   177  	assert.Equal(t, 2, len(list))
   178  
   179  	checkFile1 := func(got *operations.ListJSONItem) {
   180  		assert.WithinDuration(t, t1, got.ModTime.When, time.Second)
   181  		assert.Equal(t, "a", got.Path)
   182  		assert.Equal(t, "a", got.Name)
   183  		assert.Equal(t, int64(1), got.Size)
   184  		assert.Equal(t, "application/octet-stream", got.MimeType)
   185  		assert.Equal(t, false, got.IsDir)
   186  	}
   187  	checkFile1(list[0])
   188  
   189  	checkSubdir := func(got *operations.ListJSONItem) {
   190  		assert.Equal(t, "subdir", got.Path)
   191  		assert.Equal(t, "subdir", got.Name)
   192  		assert.Equal(t, int64(-1), got.Size)
   193  		assert.Equal(t, "inode/directory", got.MimeType)
   194  		assert.Equal(t, true, got.IsDir)
   195  	}
   196  	checkSubdir(list[1])
   197  
   198  	in = rc.Params{
   199  		"fs":     r.FremoteName,
   200  		"remote": "",
   201  		"opt": rc.Params{
   202  			"recurse": true,
   203  		},
   204  	}
   205  	out, err = call.Fn(context.Background(), in)
   206  	require.NoError(t, err)
   207  
   208  	list = out["list"].([]*operations.ListJSONItem)
   209  	assert.Equal(t, 3, len(list))
   210  	checkFile1(list[0])
   211  	checkSubdir(list[1])
   212  
   213  	checkFile2 := func(got *operations.ListJSONItem) {
   214  		assert.WithinDuration(t, t2, got.ModTime.When, time.Second)
   215  		assert.Equal(t, "subdir/b", got.Path)
   216  		assert.Equal(t, "b", got.Name)
   217  		assert.Equal(t, int64(2), got.Size)
   218  		assert.Equal(t, "application/octet-stream", got.MimeType)
   219  		assert.Equal(t, false, got.IsDir)
   220  	}
   221  	checkFile2(list[2])
   222  }
   223  
   224  // operations/mkdir: Make a destination directory or container
   225  func TestRcMkdir(t *testing.T) {
   226  	r, call := rcNewRun(t, "operations/mkdir")
   227  	defer r.Finalise()
   228  	r.Mkdir(context.Background(), r.Fremote)
   229  
   230  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{}, fs.GetModifyWindow(r.Fremote))
   231  
   232  	in := rc.Params{
   233  		"fs":     r.FremoteName,
   234  		"remote": "subdir",
   235  	}
   236  	out, err := call.Fn(context.Background(), in)
   237  	require.NoError(t, err)
   238  	assert.Equal(t, rc.Params(nil), out)
   239  
   240  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{"subdir"}, fs.GetModifyWindow(r.Fremote))
   241  }
   242  
   243  // operations/movefile: Move a file from source remote to destination remote
   244  func TestRcMovefile(t *testing.T) {
   245  	r, call := rcNewRun(t, "operations/movefile")
   246  	defer r.Finalise()
   247  	file1 := r.WriteFile("file1", "file1 contents", t1)
   248  	r.Mkdir(context.Background(), r.Fremote)
   249  	fstest.CheckItems(t, r.Flocal, file1)
   250  	fstest.CheckItems(t, r.Fremote)
   251  
   252  	in := rc.Params{
   253  		"srcFs":     r.LocalName,
   254  		"srcRemote": "file1",
   255  		"dstFs":     r.FremoteName,
   256  		"dstRemote": "file1-renamed",
   257  	}
   258  	out, err := call.Fn(context.Background(), in)
   259  	require.NoError(t, err)
   260  	assert.Equal(t, rc.Params(nil), out)
   261  
   262  	fstest.CheckItems(t, r.Flocal)
   263  	file1.Path = "file1-renamed"
   264  	fstest.CheckItems(t, r.Fremote, file1)
   265  }
   266  
   267  // operations/purge: Remove a directory or container and all of its contents
   268  func TestRcPurge(t *testing.T) {
   269  	r, call := rcNewRun(t, "operations/purge")
   270  	defer r.Finalise()
   271  	file1 := r.WriteObject(context.Background(), "subdir/file1", "subdir/file1 contents", t1)
   272  
   273  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{file1}, []string{"subdir"}, fs.GetModifyWindow(r.Fremote))
   274  
   275  	in := rc.Params{
   276  		"fs":     r.FremoteName,
   277  		"remote": "subdir",
   278  	}
   279  	out, err := call.Fn(context.Background(), in)
   280  	require.NoError(t, err)
   281  	assert.Equal(t, rc.Params(nil), out)
   282  
   283  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{}, fs.GetModifyWindow(r.Fremote))
   284  }
   285  
   286  // operations/rmdir: Remove an empty directory or container
   287  func TestRcRmdir(t *testing.T) {
   288  	r, call := rcNewRun(t, "operations/rmdir")
   289  	defer r.Finalise()
   290  	r.Mkdir(context.Background(), r.Fremote)
   291  	assert.NoError(t, r.Fremote.Mkdir(context.Background(), "subdir"))
   292  
   293  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{"subdir"}, fs.GetModifyWindow(r.Fremote))
   294  
   295  	in := rc.Params{
   296  		"fs":     r.FremoteName,
   297  		"remote": "subdir",
   298  	}
   299  	out, err := call.Fn(context.Background(), in)
   300  	require.NoError(t, err)
   301  	assert.Equal(t, rc.Params(nil), out)
   302  
   303  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{}, fs.GetModifyWindow(r.Fremote))
   304  }
   305  
   306  // operations/rmdirs: Remove all the empty directories in the path
   307  func TestRcRmdirs(t *testing.T) {
   308  	r, call := rcNewRun(t, "operations/rmdirs")
   309  	defer r.Finalise()
   310  	r.Mkdir(context.Background(), r.Fremote)
   311  	assert.NoError(t, r.Fremote.Mkdir(context.Background(), "subdir"))
   312  	assert.NoError(t, r.Fremote.Mkdir(context.Background(), "subdir/subsubdir"))
   313  
   314  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{"subdir", "subdir/subsubdir"}, fs.GetModifyWindow(r.Fremote))
   315  
   316  	in := rc.Params{
   317  		"fs":     r.FremoteName,
   318  		"remote": "subdir",
   319  	}
   320  	out, err := call.Fn(context.Background(), in)
   321  	require.NoError(t, err)
   322  	assert.Equal(t, rc.Params(nil), out)
   323  
   324  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{}, fs.GetModifyWindow(r.Fremote))
   325  
   326  	assert.NoError(t, r.Fremote.Mkdir(context.Background(), "subdir"))
   327  	assert.NoError(t, r.Fremote.Mkdir(context.Background(), "subdir/subsubdir"))
   328  
   329  	in = rc.Params{
   330  		"fs":        r.FremoteName,
   331  		"remote":    "subdir",
   332  		"leaveRoot": true,
   333  	}
   334  	out, err = call.Fn(context.Background(), in)
   335  	require.NoError(t, err)
   336  	assert.Equal(t, rc.Params(nil), out)
   337  
   338  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{"subdir"}, fs.GetModifyWindow(r.Fremote))
   339  
   340  }
   341  
   342  // operations/size: Count the number of bytes and files in remote
   343  func TestRcSize(t *testing.T) {
   344  	r, call := rcNewRun(t, "operations/size")
   345  	defer r.Finalise()
   346  	file1 := r.WriteObject(context.Background(), "small", "1234567890", t2)                                                           // 10 bytes
   347  	file2 := r.WriteObject(context.Background(), "subdir/medium", "------------------------------------------------------------", t1) // 60 bytes
   348  	file3 := r.WriteObject(context.Background(), "subdir/subsubdir/large", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", t1)  // 50 bytes
   349  	fstest.CheckItems(t, r.Fremote, file1, file2, file3)
   350  
   351  	in := rc.Params{
   352  		"fs": r.FremoteName,
   353  	}
   354  	out, err := call.Fn(context.Background(), in)
   355  	require.NoError(t, err)
   356  	assert.Equal(t, rc.Params{
   357  		"count": int64(3),
   358  		"bytes": int64(120),
   359  	}, out)
   360  }
   361  
   362  // operations/publiclink: Create or retrieve a public link to the given file or folder.
   363  func TestRcPublicLink(t *testing.T) {
   364  	r, call := rcNewRun(t, "operations/publiclink")
   365  	defer r.Finalise()
   366  	in := rc.Params{
   367  		"fs":     r.FremoteName,
   368  		"remote": "",
   369  	}
   370  	_, err := call.Fn(context.Background(), in)
   371  	require.Error(t, err)
   372  	assert.Contains(t, err.Error(), "doesn't support public links")
   373  }
   374  
   375  // operations/fsinfo: Return information about the remote
   376  func TestRcFsInfo(t *testing.T) {
   377  	r, call := rcNewRun(t, "operations/fsinfo")
   378  	defer r.Finalise()
   379  	in := rc.Params{
   380  		"fs": r.FremoteName,
   381  	}
   382  	got, err := call.Fn(context.Background(), in)
   383  	require.NoError(t, err)
   384  	want := operations.GetFsInfo(r.Fremote)
   385  	assert.Equal(t, want.Name, got["Name"])
   386  	assert.Equal(t, want.Root, got["Root"])
   387  	assert.Equal(t, want.String, got["String"])
   388  	assert.Equal(t, float64(want.Precision), got["Precision"])
   389  	var hashes []interface{}
   390  	for _, hash := range want.Hashes {
   391  		hashes = append(hashes, hash)
   392  	}
   393  	assert.Equal(t, hashes, got["Hashes"])
   394  	var features = map[string]interface{}{}
   395  	for k, v := range want.Features {
   396  		features[k] = v
   397  	}
   398  	assert.Equal(t, features, got["Features"])
   399  
   400  }