github.com/xhghs/rclone@v1.51.1-0.20200430155106-e186a28cced8/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/rclone/rclone/fs"
    11  	"github.com/rclone/rclone/fs/cache"
    12  	"github.com/rclone/rclone/fs/operations"
    13  	"github.com/rclone/rclone/fs/rc"
    14  	"github.com/rclone/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  		"autoFilename": false,
   112  	}
   113  	out, err := call.Fn(context.Background(), in)
   114  	require.NoError(t, err)
   115  	assert.Equal(t, rc.Params(nil), out)
   116  
   117  	urlFileName := "filename.txt"
   118  	in = rc.Params{
   119  		"fs":           r.FremoteName,
   120  		"remote":       "",
   121  		"url":          ts.URL + "/" + urlFileName,
   122  		"autoFilename": true,
   123  	}
   124  	out, err = call.Fn(context.Background(), in)
   125  	require.NoError(t, err)
   126  	assert.Equal(t, rc.Params(nil), out)
   127  
   128  	in = rc.Params{
   129  		"fs":           r.FremoteName,
   130  		"remote":       "",
   131  		"url":          ts.URL,
   132  		"autoFilename": true,
   133  	}
   134  	out, err = call.Fn(context.Background(), in)
   135  	require.Error(t, err)
   136  	assert.Equal(t, rc.Params(nil), out)
   137  
   138  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{file1, fstest.NewItem(urlFileName, contents, t1)}, nil, fs.ModTimeNotSupported)
   139  }
   140  
   141  // operations/delete: Remove files in the path
   142  func TestRcDelete(t *testing.T) {
   143  	r, call := rcNewRun(t, "operations/delete")
   144  	defer r.Finalise()
   145  
   146  	file1 := r.WriteObject(context.Background(), "small", "1234567890", t2)                                                                                           // 10 bytes
   147  	file2 := r.WriteObject(context.Background(), "medium", "------------------------------------------------------------", t1)                                        // 60 bytes
   148  	file3 := r.WriteObject(context.Background(), "large", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", t1) // 100 bytes
   149  	fstest.CheckItems(t, r.Fremote, file1, file2, file3)
   150  
   151  	in := rc.Params{
   152  		"fs": r.FremoteName,
   153  	}
   154  	out, err := call.Fn(context.Background(), in)
   155  	require.NoError(t, err)
   156  	assert.Equal(t, rc.Params(nil), out)
   157  
   158  	fstest.CheckItems(t, r.Fremote)
   159  }
   160  
   161  // operations/deletefile: Remove the single file pointed to
   162  func TestRcDeletefile(t *testing.T) {
   163  	r, call := rcNewRun(t, "operations/deletefile")
   164  	defer r.Finalise()
   165  
   166  	file1 := r.WriteObject(context.Background(), "small", "1234567890", t2)                                                    // 10 bytes
   167  	file2 := r.WriteObject(context.Background(), "medium", "------------------------------------------------------------", t1) // 60 bytes
   168  	fstest.CheckItems(t, r.Fremote, file1, file2)
   169  
   170  	in := rc.Params{
   171  		"fs":     r.FremoteName,
   172  		"remote": "small",
   173  	}
   174  	out, err := call.Fn(context.Background(), in)
   175  	require.NoError(t, err)
   176  	assert.Equal(t, rc.Params(nil), out)
   177  
   178  	fstest.CheckItems(t, r.Fremote, file2)
   179  }
   180  
   181  // operations/list: List the given remote and path in JSON format
   182  func TestRcList(t *testing.T) {
   183  	r, call := rcNewRun(t, "operations/list")
   184  	defer r.Finalise()
   185  
   186  	file1 := r.WriteObject(context.Background(), "a", "a", t1)
   187  	file2 := r.WriteObject(context.Background(), "subdir/b", "bb", t2)
   188  
   189  	fstest.CheckItems(t, r.Fremote, file1, file2)
   190  
   191  	in := rc.Params{
   192  		"fs":     r.FremoteName,
   193  		"remote": "",
   194  	}
   195  	out, err := call.Fn(context.Background(), in)
   196  	require.NoError(t, err)
   197  
   198  	list := out["list"].([]*operations.ListJSONItem)
   199  	assert.Equal(t, 2, len(list))
   200  
   201  	checkFile1 := func(got *operations.ListJSONItem) {
   202  		assert.WithinDuration(t, t1, got.ModTime.When, time.Second)
   203  		assert.Equal(t, "a", got.Path)
   204  		assert.Equal(t, "a", got.Name)
   205  		assert.Equal(t, int64(1), got.Size)
   206  		assert.Equal(t, "application/octet-stream", got.MimeType)
   207  		assert.Equal(t, false, got.IsDir)
   208  	}
   209  	checkFile1(list[0])
   210  
   211  	checkSubdir := func(got *operations.ListJSONItem) {
   212  		assert.Equal(t, "subdir", got.Path)
   213  		assert.Equal(t, "subdir", got.Name)
   214  		assert.Equal(t, int64(-1), got.Size)
   215  		assert.Equal(t, "inode/directory", got.MimeType)
   216  		assert.Equal(t, true, got.IsDir)
   217  	}
   218  	checkSubdir(list[1])
   219  
   220  	in = rc.Params{
   221  		"fs":     r.FremoteName,
   222  		"remote": "",
   223  		"opt": rc.Params{
   224  			"recurse": true,
   225  		},
   226  	}
   227  	out, err = call.Fn(context.Background(), in)
   228  	require.NoError(t, err)
   229  
   230  	list = out["list"].([]*operations.ListJSONItem)
   231  	assert.Equal(t, 3, len(list))
   232  	checkFile1(list[0])
   233  	checkSubdir(list[1])
   234  
   235  	checkFile2 := func(got *operations.ListJSONItem) {
   236  		assert.WithinDuration(t, t2, got.ModTime.When, time.Second)
   237  		assert.Equal(t, "subdir/b", got.Path)
   238  		assert.Equal(t, "b", got.Name)
   239  		assert.Equal(t, int64(2), got.Size)
   240  		assert.Equal(t, "application/octet-stream", got.MimeType)
   241  		assert.Equal(t, false, got.IsDir)
   242  	}
   243  	checkFile2(list[2])
   244  }
   245  
   246  // operations/mkdir: Make a destination directory or container
   247  func TestRcMkdir(t *testing.T) {
   248  	r, call := rcNewRun(t, "operations/mkdir")
   249  	defer r.Finalise()
   250  	r.Mkdir(context.Background(), r.Fremote)
   251  
   252  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{}, fs.GetModifyWindow(r.Fremote))
   253  
   254  	in := rc.Params{
   255  		"fs":     r.FremoteName,
   256  		"remote": "subdir",
   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.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{"subdir"}, fs.GetModifyWindow(r.Fremote))
   263  }
   264  
   265  // operations/movefile: Move a file from source remote to destination remote
   266  func TestRcMovefile(t *testing.T) {
   267  	r, call := rcNewRun(t, "operations/movefile")
   268  	defer r.Finalise()
   269  	file1 := r.WriteFile("file1", "file1 contents", t1)
   270  	r.Mkdir(context.Background(), r.Fremote)
   271  	fstest.CheckItems(t, r.Flocal, file1)
   272  	fstest.CheckItems(t, r.Fremote)
   273  
   274  	in := rc.Params{
   275  		"srcFs":     r.LocalName,
   276  		"srcRemote": "file1",
   277  		"dstFs":     r.FremoteName,
   278  		"dstRemote": "file1-renamed",
   279  	}
   280  	out, err := call.Fn(context.Background(), in)
   281  	require.NoError(t, err)
   282  	assert.Equal(t, rc.Params(nil), out)
   283  
   284  	fstest.CheckItems(t, r.Flocal)
   285  	file1.Path = "file1-renamed"
   286  	fstest.CheckItems(t, r.Fremote, file1)
   287  }
   288  
   289  // operations/purge: Remove a directory or container and all of its contents
   290  func TestRcPurge(t *testing.T) {
   291  	r, call := rcNewRun(t, "operations/purge")
   292  	defer r.Finalise()
   293  	file1 := r.WriteObject(context.Background(), "subdir/file1", "subdir/file1 contents", t1)
   294  
   295  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{file1}, []string{"subdir"}, fs.GetModifyWindow(r.Fremote))
   296  
   297  	in := rc.Params{
   298  		"fs":     r.FremoteName,
   299  		"remote": "subdir",
   300  	}
   301  	out, err := call.Fn(context.Background(), in)
   302  	require.NoError(t, err)
   303  	assert.Equal(t, rc.Params(nil), out)
   304  
   305  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{}, fs.GetModifyWindow(r.Fremote))
   306  }
   307  
   308  // operations/rmdir: Remove an empty directory or container
   309  func TestRcRmdir(t *testing.T) {
   310  	r, call := rcNewRun(t, "operations/rmdir")
   311  	defer r.Finalise()
   312  	r.Mkdir(context.Background(), r.Fremote)
   313  	assert.NoError(t, r.Fremote.Mkdir(context.Background(), "subdir"))
   314  
   315  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{"subdir"}, fs.GetModifyWindow(r.Fremote))
   316  
   317  	in := rc.Params{
   318  		"fs":     r.FremoteName,
   319  		"remote": "subdir",
   320  	}
   321  	out, err := call.Fn(context.Background(), in)
   322  	require.NoError(t, err)
   323  	assert.Equal(t, rc.Params(nil), out)
   324  
   325  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{}, fs.GetModifyWindow(r.Fremote))
   326  }
   327  
   328  // operations/rmdirs: Remove all the empty directories in the path
   329  func TestRcRmdirs(t *testing.T) {
   330  	r, call := rcNewRun(t, "operations/rmdirs")
   331  	defer r.Finalise()
   332  	r.Mkdir(context.Background(), r.Fremote)
   333  	assert.NoError(t, r.Fremote.Mkdir(context.Background(), "subdir"))
   334  	assert.NoError(t, r.Fremote.Mkdir(context.Background(), "subdir/subsubdir"))
   335  
   336  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{"subdir", "subdir/subsubdir"}, fs.GetModifyWindow(r.Fremote))
   337  
   338  	in := rc.Params{
   339  		"fs":     r.FremoteName,
   340  		"remote": "subdir",
   341  	}
   342  	out, err := call.Fn(context.Background(), in)
   343  	require.NoError(t, err)
   344  	assert.Equal(t, rc.Params(nil), out)
   345  
   346  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{}, fs.GetModifyWindow(r.Fremote))
   347  
   348  	assert.NoError(t, r.Fremote.Mkdir(context.Background(), "subdir"))
   349  	assert.NoError(t, r.Fremote.Mkdir(context.Background(), "subdir/subsubdir"))
   350  
   351  	in = rc.Params{
   352  		"fs":        r.FremoteName,
   353  		"remote":    "subdir",
   354  		"leaveRoot": true,
   355  	}
   356  	out, err = call.Fn(context.Background(), in)
   357  	require.NoError(t, err)
   358  	assert.Equal(t, rc.Params(nil), out)
   359  
   360  	fstest.CheckListingWithPrecision(t, r.Fremote, []fstest.Item{}, []string{"subdir"}, fs.GetModifyWindow(r.Fremote))
   361  
   362  }
   363  
   364  // operations/size: Count the number of bytes and files in remote
   365  func TestRcSize(t *testing.T) {
   366  	r, call := rcNewRun(t, "operations/size")
   367  	defer r.Finalise()
   368  	file1 := r.WriteObject(context.Background(), "small", "1234567890", t2)                                                           // 10 bytes
   369  	file2 := r.WriteObject(context.Background(), "subdir/medium", "------------------------------------------------------------", t1) // 60 bytes
   370  	file3 := r.WriteObject(context.Background(), "subdir/subsubdir/large", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", t1)  // 50 bytes
   371  	fstest.CheckItems(t, r.Fremote, file1, file2, file3)
   372  
   373  	in := rc.Params{
   374  		"fs": r.FremoteName,
   375  	}
   376  	out, err := call.Fn(context.Background(), in)
   377  	require.NoError(t, err)
   378  	assert.Equal(t, rc.Params{
   379  		"count": int64(3),
   380  		"bytes": int64(120),
   381  	}, out)
   382  }
   383  
   384  // operations/publiclink: Create or retrieve a public link to the given file or folder.
   385  func TestRcPublicLink(t *testing.T) {
   386  	r, call := rcNewRun(t, "operations/publiclink")
   387  	defer r.Finalise()
   388  	in := rc.Params{
   389  		"fs":     r.FremoteName,
   390  		"remote": "",
   391  	}
   392  	_, err := call.Fn(context.Background(), in)
   393  	require.Error(t, err)
   394  	assert.Contains(t, err.Error(), "doesn't support public links")
   395  }
   396  
   397  // operations/fsinfo: Return information about the remote
   398  func TestRcFsInfo(t *testing.T) {
   399  	r, call := rcNewRun(t, "operations/fsinfo")
   400  	defer r.Finalise()
   401  	in := rc.Params{
   402  		"fs": r.FremoteName,
   403  	}
   404  	got, err := call.Fn(context.Background(), in)
   405  	require.NoError(t, err)
   406  	want := operations.GetFsInfo(r.Fremote)
   407  	assert.Equal(t, want.Name, got["Name"])
   408  	assert.Equal(t, want.Root, got["Root"])
   409  	assert.Equal(t, want.String, got["String"])
   410  	assert.Equal(t, float64(want.Precision), got["Precision"])
   411  	var hashes []interface{}
   412  	for _, hash := range want.Hashes {
   413  		hashes = append(hashes, hash)
   414  	}
   415  	assert.Equal(t, hashes, got["Hashes"])
   416  	var features = map[string]interface{}{}
   417  	for k, v := range want.Features {
   418  		features[k] = v
   419  	}
   420  	assert.Equal(t, features, got["Features"])
   421  
   422  }