2019-01-07 22:47:19 +08:00
|
|
|
package file
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path"
|
2021-04-09 02:59:15 +08:00
|
|
|
"runtime"
|
2019-01-07 22:47:19 +08:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Create a test directory then tidy up
|
|
|
|
func testDir(t *testing.T) (string, func()) {
|
|
|
|
dir, err := ioutil.TempDir("", "rclone-test")
|
|
|
|
require.NoError(t, err)
|
|
|
|
return dir, func() {
|
|
|
|
assert.NoError(t, os.RemoveAll(dir))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// This lists dir and checks the listing is as expected without checking the size
|
|
|
|
func checkListingNoSize(t *testing.T, dir string, want []string) {
|
|
|
|
var got []string
|
|
|
|
nodes, err := ioutil.ReadDir(dir)
|
|
|
|
require.NoError(t, err)
|
|
|
|
for _, node := range nodes {
|
|
|
|
got = append(got, fmt.Sprintf("%s,%v", node.Name(), node.IsDir()))
|
|
|
|
}
|
|
|
|
assert.Equal(t, want, got)
|
|
|
|
}
|
|
|
|
|
|
|
|
// This lists dir and checks the listing is as expected
|
|
|
|
func checkListing(t *testing.T, dir string, want []string) {
|
|
|
|
var got []string
|
|
|
|
nodes, err := ioutil.ReadDir(dir)
|
|
|
|
require.NoError(t, err)
|
|
|
|
for _, node := range nodes {
|
|
|
|
got = append(got, fmt.Sprintf("%s,%d,%v", node.Name(), node.Size(), node.IsDir()))
|
|
|
|
}
|
|
|
|
assert.Equal(t, want, got)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test we can rename an open file
|
|
|
|
func TestOpenFileRename(t *testing.T) {
|
|
|
|
dir, tidy := testDir(t)
|
|
|
|
defer tidy()
|
|
|
|
|
|
|
|
filepath := path.Join(dir, "file1")
|
|
|
|
f, err := Create(filepath)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = f.Write([]byte("hello"))
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
checkListingNoSize(t, dir, []string{
|
|
|
|
"file1,false",
|
|
|
|
})
|
|
|
|
|
|
|
|
// Delete the file first
|
|
|
|
assert.NoError(t, os.Remove(filepath))
|
|
|
|
|
|
|
|
// .. then close it
|
|
|
|
assert.NoError(t, f.Close())
|
|
|
|
|
|
|
|
checkListing(t, dir, nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test we can delete an open file
|
|
|
|
func TestOpenFileDelete(t *testing.T) {
|
|
|
|
dir, tidy := testDir(t)
|
|
|
|
defer tidy()
|
|
|
|
|
|
|
|
filepath := path.Join(dir, "file1")
|
|
|
|
f, err := Create(filepath)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = f.Write([]byte("hello"))
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
checkListingNoSize(t, dir, []string{
|
|
|
|
"file1,false",
|
|
|
|
})
|
|
|
|
|
|
|
|
// Rename the file while open
|
|
|
|
filepath2 := path.Join(dir, "file2")
|
|
|
|
assert.NoError(t, os.Rename(filepath, filepath2))
|
|
|
|
|
|
|
|
checkListingNoSize(t, dir, []string{
|
|
|
|
"file2,false",
|
|
|
|
})
|
|
|
|
|
|
|
|
// .. then close it
|
|
|
|
assert.NoError(t, f.Close())
|
|
|
|
|
|
|
|
checkListing(t, dir, []string{
|
|
|
|
"file2,5,false",
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Smoke test the Open, OpenFile and Create functions
|
|
|
|
func TestOpenFileOperations(t *testing.T) {
|
|
|
|
dir, tidy := testDir(t)
|
|
|
|
defer tidy()
|
|
|
|
|
|
|
|
filepath := path.Join(dir, "file1")
|
|
|
|
|
|
|
|
// Create the file
|
|
|
|
|
|
|
|
f, err := Create(filepath)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = f.Write([]byte("hello"))
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
assert.NoError(t, f.Close())
|
|
|
|
|
|
|
|
checkListing(t, dir, []string{
|
|
|
|
"file1,5,false",
|
|
|
|
})
|
|
|
|
|
|
|
|
// Append onto the file
|
|
|
|
|
|
|
|
f, err = OpenFile(filepath, os.O_RDWR|os.O_APPEND, 0666)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = f.Write([]byte("HI"))
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
assert.NoError(t, f.Close())
|
|
|
|
|
|
|
|
checkListing(t, dir, []string{
|
|
|
|
"file1,7,false",
|
|
|
|
})
|
|
|
|
|
|
|
|
// Read it back in
|
|
|
|
|
|
|
|
f, err = Open(filepath)
|
|
|
|
require.NoError(t, err)
|
|
|
|
var b = make([]byte, 10)
|
|
|
|
n, err := f.Read(b)
|
|
|
|
assert.True(t, err == io.EOF || err == nil)
|
|
|
|
assert.Equal(t, 7, n)
|
|
|
|
assert.Equal(t, "helloHI", string(b[:n]))
|
|
|
|
|
|
|
|
assert.NoError(t, f.Close())
|
|
|
|
|
|
|
|
checkListing(t, dir, []string{
|
|
|
|
"file1,7,false",
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
2021-04-09 02:59:15 +08:00
|
|
|
|
|
|
|
// Smoke test the IsReserved function
|
|
|
|
func TestIsReserved(t *testing.T) {
|
|
|
|
if runtime.GOOS != "windows" {
|
|
|
|
t.Skip("Skipping test on !windows")
|
|
|
|
}
|
|
|
|
// Regular name
|
|
|
|
require.NoError(t, IsReserved("readme.txt"))
|
|
|
|
require.NoError(t, IsReserved("some/path/readme.txt"))
|
|
|
|
// Empty
|
|
|
|
require.Error(t, IsReserved(""))
|
|
|
|
// Separators only
|
|
|
|
require.Error(t, IsReserved("/"))
|
|
|
|
require.Error(t, IsReserved("////"))
|
|
|
|
require.Error(t, IsReserved("./././././"))
|
|
|
|
// Legacy device name
|
|
|
|
require.Error(t, IsReserved("NUL"))
|
|
|
|
require.Error(t, IsReserved("nul"))
|
|
|
|
require.Error(t, IsReserved("Nul"))
|
|
|
|
require.Error(t, IsReserved("NUL.txt"))
|
|
|
|
require.Error(t, IsReserved("some/path/to/nul.txt"))
|
|
|
|
require.NoError(t, IsReserved("NULL"))
|
|
|
|
// Name end with a space or a period
|
|
|
|
require.Error(t, IsReserved("test."))
|
|
|
|
require.Error(t, IsReserved("test "))
|
|
|
|
}
|