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

     1  package local
     2  
     3  import (
     4  	"context"
     5  	"io/ioutil"
     6  	"os"
     7  	"path"
     8  	"path/filepath"
     9  	"runtime"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/rclone/rclone/fs"
    14  	"github.com/rclone/rclone/fs/config/configmap"
    15  	"github.com/rclone/rclone/fs/hash"
    16  	"github.com/rclone/rclone/fstest"
    17  	"github.com/rclone/rclone/lib/file"
    18  	"github.com/rclone/rclone/lib/readers"
    19  	"github.com/stretchr/testify/assert"
    20  	"github.com/stretchr/testify/require"
    21  )
    22  
    23  // TestMain drives the tests
    24  func TestMain(m *testing.M) {
    25  	fstest.TestMain(m)
    26  }
    27  
    28  // Test copy with source file that's updating
    29  func TestUpdatingCheck(t *testing.T) {
    30  	r := fstest.NewRun(t)
    31  	defer r.Finalise()
    32  	filePath := "sub dir/local test"
    33  	r.WriteFile(filePath, "content", time.Now())
    34  
    35  	fd, err := file.Open(path.Join(r.LocalName, filePath))
    36  	if err != nil {
    37  		t.Fatalf("failed opening file %q: %v", filePath, err)
    38  	}
    39  	defer func() {
    40  		require.NoError(t, fd.Close())
    41  	}()
    42  
    43  	fi, err := fd.Stat()
    44  	require.NoError(t, err)
    45  	o := &Object{size: fi.Size(), modTime: fi.ModTime(), fs: &Fs{}}
    46  	wrappedFd := readers.NewLimitedReadCloser(fd, -1)
    47  	hash, err := hash.NewMultiHasherTypes(hash.Supported())
    48  	require.NoError(t, err)
    49  	in := localOpenFile{
    50  		o:    o,
    51  		in:   wrappedFd,
    52  		hash: hash,
    53  		fd:   fd,
    54  	}
    55  
    56  	buf := make([]byte, 1)
    57  	_, err = in.Read(buf)
    58  	require.NoError(t, err)
    59  
    60  	r.WriteFile(filePath, "content updated", time.Now())
    61  	_, err = in.Read(buf)
    62  	require.Errorf(t, err, "can't copy - source file is being updated")
    63  
    64  	// turn the checking off and try again
    65  	in.o.fs.opt.NoCheckUpdated = true
    66  
    67  	r.WriteFile(filePath, "content updated", time.Now())
    68  	_, err = in.Read(buf)
    69  	require.NoError(t, err)
    70  
    71  }
    72  
    73  func TestSymlink(t *testing.T) {
    74  	ctx := context.Background()
    75  	r := fstest.NewRun(t)
    76  	defer r.Finalise()
    77  	f := r.Flocal.(*Fs)
    78  	dir := f.root
    79  
    80  	// Write a file
    81  	modTime1 := fstest.Time("2001-02-03T04:05:10.123123123Z")
    82  	file1 := r.WriteFile("file.txt", "hello", modTime1)
    83  
    84  	// Write a symlink
    85  	modTime2 := fstest.Time("2002-02-03T04:05:10.123123123Z")
    86  	symlinkPath := filepath.Join(dir, "symlink.txt")
    87  	require.NoError(t, os.Symlink("file.txt", symlinkPath))
    88  	require.NoError(t, lChtimes(symlinkPath, modTime2, modTime2))
    89  
    90  	// Object viewed as symlink
    91  	file2 := fstest.NewItem("symlink.txt"+linkSuffix, "file.txt", modTime2)
    92  	if runtime.GOOS == "windows" {
    93  		file2.Size = 0 // symlinks are 0 length under Windows
    94  	}
    95  
    96  	// Object viewed as destination
    97  	file2d := fstest.NewItem("symlink.txt", "hello", modTime1)
    98  
    99  	// Check with no symlink flags
   100  	fstest.CheckItems(t, r.Flocal, file1)
   101  	fstest.CheckItems(t, r.Fremote)
   102  
   103  	// Set fs into "-L" mode
   104  	f.opt.FollowSymlinks = true
   105  	f.opt.TranslateSymlinks = false
   106  	f.lstat = os.Stat
   107  
   108  	fstest.CheckItems(t, r.Flocal, file1, file2d)
   109  	fstest.CheckItems(t, r.Fremote)
   110  
   111  	// Set fs into "-l" mode
   112  	f.opt.FollowSymlinks = false
   113  	f.opt.TranslateSymlinks = true
   114  	f.lstat = os.Lstat
   115  
   116  	fstest.CheckListingWithPrecision(t, r.Flocal, []fstest.Item{file1, file2}, nil, fs.ModTimeNotSupported)
   117  	if haveLChtimes {
   118  		fstest.CheckItems(t, r.Flocal, file1, file2)
   119  	}
   120  
   121  	// Create a symlink
   122  	modTime3 := fstest.Time("2002-03-03T04:05:10.123123123Z")
   123  	file3 := r.WriteObjectTo(ctx, r.Flocal, "symlink2.txt"+linkSuffix, "file.txt", modTime3, false)
   124  	if runtime.GOOS == "windows" {
   125  		file3.Size = 0 // symlinks are 0 length under Windows
   126  	}
   127  	fstest.CheckListingWithPrecision(t, r.Flocal, []fstest.Item{file1, file2, file3}, nil, fs.ModTimeNotSupported)
   128  	if haveLChtimes {
   129  		fstest.CheckItems(t, r.Flocal, file1, file2, file3)
   130  	}
   131  
   132  	// Check it got the correct contents
   133  	symlinkPath = filepath.Join(dir, "symlink2.txt")
   134  	fi, err := os.Lstat(symlinkPath)
   135  	require.NoError(t, err)
   136  	assert.False(t, fi.Mode().IsRegular())
   137  	linkText, err := os.Readlink(symlinkPath)
   138  	require.NoError(t, err)
   139  	assert.Equal(t, "file.txt", linkText)
   140  
   141  	// Check that NewObject gets the correct object
   142  	o, err := r.Flocal.NewObject(ctx, "symlink2.txt"+linkSuffix)
   143  	require.NoError(t, err)
   144  	assert.Equal(t, "symlink2.txt"+linkSuffix, o.Remote())
   145  	if runtime.GOOS != "windows" {
   146  		assert.Equal(t, int64(8), o.Size())
   147  	}
   148  
   149  	// Check that NewObject doesn't see the non suffixed version
   150  	_, err = r.Flocal.NewObject(ctx, "symlink2.txt")
   151  	require.Equal(t, fs.ErrorObjectNotFound, err)
   152  
   153  	// Check reading the object
   154  	in, err := o.Open(ctx)
   155  	require.NoError(t, err)
   156  	contents, err := ioutil.ReadAll(in)
   157  	require.NoError(t, err)
   158  	require.Equal(t, "file.txt", string(contents))
   159  	require.NoError(t, in.Close())
   160  
   161  	// Check reading the object with range
   162  	in, err = o.Open(ctx, &fs.RangeOption{Start: 2, End: 5})
   163  	require.NoError(t, err)
   164  	contents, err = ioutil.ReadAll(in)
   165  	require.NoError(t, err)
   166  	require.Equal(t, "file.txt"[2:5+1], string(contents))
   167  	require.NoError(t, in.Close())
   168  }
   169  
   170  func TestSymlinkError(t *testing.T) {
   171  	m := configmap.Simple{
   172  		"links":      "true",
   173  		"copy_links": "true",
   174  	}
   175  	_, err := NewFs("local", "/", m)
   176  	assert.Equal(t, errLinksAndCopyLinks, err)
   177  }