github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/lib/file/file_test.go (about)

     1  package file
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"path"
     8  	"runtime"
     9  	"testing"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  // This lists dir and checks the listing is as expected without checking the size
    16  func checkListingNoSize(t *testing.T, dir string, want []string) {
    17  	var got []string
    18  	nodes, err := os.ReadDir(dir)
    19  	require.NoError(t, err)
    20  	for _, node := range nodes {
    21  		got = append(got, fmt.Sprintf("%s,%v", node.Name(), node.IsDir()))
    22  	}
    23  	assert.Equal(t, want, got)
    24  }
    25  
    26  // This lists dir and checks the listing is as expected
    27  func checkListing(t *testing.T, dir string, want []string) {
    28  	var got []string
    29  	nodes, err := os.ReadDir(dir)
    30  	require.NoError(t, err)
    31  	for _, node := range nodes {
    32  		info, err := node.Info()
    33  		assert.NoError(t, err)
    34  		got = append(got, fmt.Sprintf("%s,%d,%v", node.Name(), info.Size(), node.IsDir()))
    35  	}
    36  	assert.Equal(t, want, got)
    37  }
    38  
    39  // Test we can rename an open file
    40  func TestOpenFileRename(t *testing.T) {
    41  	dir := t.TempDir()
    42  
    43  	filepath := path.Join(dir, "file1")
    44  	f, err := Create(filepath)
    45  	require.NoError(t, err)
    46  
    47  	_, err = f.Write([]byte("hello"))
    48  	assert.NoError(t, err)
    49  
    50  	checkListingNoSize(t, dir, []string{
    51  		"file1,false",
    52  	})
    53  
    54  	// Delete the file first
    55  	assert.NoError(t, os.Remove(filepath))
    56  
    57  	// .. then close it
    58  	assert.NoError(t, f.Close())
    59  
    60  	checkListing(t, dir, nil)
    61  }
    62  
    63  // Test we can delete an open file
    64  func TestOpenFileDelete(t *testing.T) {
    65  	dir := t.TempDir()
    66  
    67  	filepath := path.Join(dir, "file1")
    68  	f, err := Create(filepath)
    69  	require.NoError(t, err)
    70  
    71  	_, err = f.Write([]byte("hello"))
    72  	assert.NoError(t, err)
    73  
    74  	checkListingNoSize(t, dir, []string{
    75  		"file1,false",
    76  	})
    77  
    78  	// Rename the file while open
    79  	filepath2 := path.Join(dir, "file2")
    80  	assert.NoError(t, os.Rename(filepath, filepath2))
    81  
    82  	checkListingNoSize(t, dir, []string{
    83  		"file2,false",
    84  	})
    85  
    86  	// .. then close it
    87  	assert.NoError(t, f.Close())
    88  
    89  	checkListing(t, dir, []string{
    90  		"file2,5,false",
    91  	})
    92  }
    93  
    94  // Smoke test the Open, OpenFile and Create functions
    95  func TestOpenFileOperations(t *testing.T) {
    96  	dir := t.TempDir()
    97  
    98  	filepath := path.Join(dir, "file1")
    99  
   100  	// Create the file
   101  
   102  	f, err := Create(filepath)
   103  	require.NoError(t, err)
   104  
   105  	_, err = f.Write([]byte("hello"))
   106  	assert.NoError(t, err)
   107  
   108  	assert.NoError(t, f.Close())
   109  
   110  	checkListing(t, dir, []string{
   111  		"file1,5,false",
   112  	})
   113  
   114  	// Append onto the file
   115  
   116  	f, err = OpenFile(filepath, os.O_RDWR|os.O_APPEND, 0666)
   117  	require.NoError(t, err)
   118  
   119  	_, err = f.Write([]byte("HI"))
   120  	assert.NoError(t, err)
   121  
   122  	assert.NoError(t, f.Close())
   123  
   124  	checkListing(t, dir, []string{
   125  		"file1,7,false",
   126  	})
   127  
   128  	// Read it back in
   129  
   130  	f, err = Open(filepath)
   131  	require.NoError(t, err)
   132  	var b = make([]byte, 10)
   133  	n, err := f.Read(b)
   134  	assert.True(t, err == io.EOF || err == nil)
   135  	assert.Equal(t, 7, n)
   136  	assert.Equal(t, "helloHI", string(b[:n]))
   137  
   138  	assert.NoError(t, f.Close())
   139  
   140  	checkListing(t, dir, []string{
   141  		"file1,7,false",
   142  	})
   143  
   144  }
   145  
   146  // Smoke test the IsReserved function
   147  func TestIsReserved(t *testing.T) {
   148  	if runtime.GOOS != "windows" {
   149  		t.Skip("Skipping test on !windows")
   150  	}
   151  	// Regular name
   152  	require.NoError(t, IsReserved("readme.txt"))
   153  	require.NoError(t, IsReserved("some/path/readme.txt"))
   154  	// Empty
   155  	require.Error(t, IsReserved(""))
   156  	// Separators only
   157  	require.Error(t, IsReserved("/"))
   158  	require.Error(t, IsReserved("////"))
   159  	require.Error(t, IsReserved("./././././"))
   160  	// Legacy device name
   161  	require.Error(t, IsReserved("NUL"))
   162  	require.Error(t, IsReserved("nul"))
   163  	require.Error(t, IsReserved("Nul"))
   164  	require.Error(t, IsReserved("NUL.txt"))
   165  	require.Error(t, IsReserved("some/path/to/nul.txt"))
   166  	require.NoError(t, IsReserved("NULL"))
   167  	// Name end with a space or a period
   168  	require.Error(t, IsReserved("test."))
   169  	require.Error(t, IsReserved("test "))
   170  }