all: Grand test refactor (fixes #8779, fixes #8799)

This fixes various test issues with Go 1.20.

- Most tests rewritten to use fakefs where possible
- Some tests that were already skipped, or dubious (invasive,
  unmaintainable, unclear what they even tested) have been removed
- Some actual code rewritten to better support testing in fakefs

Co-authored-by: Eric P <eric@kastelo.net>
This commit is contained in:
Jakob Borg
2023-05-09 10:01:57 +00:00
co-authored by Eric P
parent ddce692f72
commit 1103a27337
54 changed files with 1133 additions and 1594 deletions
+6 -4
View File
@@ -329,10 +329,12 @@ func (f *folder) getHealthErrorWithoutIgnores() error {
return err
}
dbPath := locations.Get(locations.Database)
if usage, err := fs.NewFilesystem(fs.FilesystemTypeBasic, dbPath).Usage("."); err == nil {
if err = config.CheckFreeSpace(f.model.cfg.Options().MinHomeDiskFree, usage); err != nil {
return fmt.Errorf("insufficient space on disk for database (%v): %w", dbPath, err)
if minFree := f.model.cfg.Options().MinHomeDiskFree; minFree.Value > 0 {
dbPath := locations.Get(locations.Database)
if usage, err := fs.NewFilesystem(fs.FilesystemTypeBasic, dbPath).Usage("."); err == nil {
if err = config.CheckFreeSpace(minFree, usage); err != nil {
return fmt.Errorf("insufficient space on disk for database (%v): %w", dbPath, err)
}
}
}
+22 -22
View File
@@ -35,11 +35,11 @@ func TestRecvOnlyRevertDeletes(t *testing.T) {
// Create some test data
for _, dir := range []string{".stfolder", "ignDir", "unknownDir"} {
must(t, ffs.MkdirAll(dir, 0755))
must(t, ffs.MkdirAll(dir, 0o755))
}
writeFilePerm(t, ffs, "ignDir/ignFile", []byte("hello\n"), 0644)
writeFilePerm(t, ffs, "unknownDir/unknownFile", []byte("hello\n"), 0644)
writeFilePerm(t, ffs, ".stignore", []byte("ignDir\n"), 0644)
writeFilePerm(t, ffs, "ignDir/ignFile", []byte("hello\n"), 0o644)
writeFilePerm(t, ffs, "unknownDir/unknownFile", []byte("hello\n"), 0o644)
writeFilePerm(t, ffs, ".stignore", []byte("ignDir\n"), 0o644)
knownFiles := setupKnownFiles(t, ffs, []byte("hello\n"))
@@ -116,7 +116,7 @@ func TestRecvOnlyRevertNeeds(t *testing.T) {
// Create some test data
must(t, ffs.MkdirAll(".stfolder", 0755))
must(t, ffs.MkdirAll(".stfolder", 0o755))
oldData := []byte("hello\n")
knownFiles := setupKnownFiles(t, ffs, oldData)
@@ -151,7 +151,7 @@ func TestRecvOnlyRevertNeeds(t *testing.T) {
// Update the file.
newData := []byte("totally different data\n")
writeFilePerm(t, ffs, "knownDir/knownFile", newData, 0644)
writeFilePerm(t, ffs, "knownDir/knownFile", newData, 0o644)
// Rescan.
@@ -206,7 +206,7 @@ func TestRecvOnlyUndoChanges(t *testing.T) {
// Create some test data
must(t, ffs.MkdirAll(".stfolder", 0755))
must(t, ffs.MkdirAll(".stfolder", 0o755))
oldData := []byte("hello\n")
knownFiles := setupKnownFiles(t, ffs, oldData)
@@ -241,8 +241,8 @@ func TestRecvOnlyUndoChanges(t *testing.T) {
// Create a file and modify another
const file = "foo"
writeFilePerm(t, ffs, file, []byte("hello\n"), 0644)
writeFilePerm(t, ffs, "knownDir/knownFile", []byte("bye\n"), 0644)
writeFilePerm(t, ffs, file, []byte("hello\n"), 0o644)
writeFilePerm(t, ffs, "knownDir/knownFile", []byte("bye\n"), 0o644)
must(t, m.ScanFolder("ro"))
@@ -254,7 +254,7 @@ func TestRecvOnlyUndoChanges(t *testing.T) {
// Remove the file again and undo the modification
must(t, ffs.Remove(file))
writeFilePerm(t, ffs, "knownDir/knownFile", oldData, 0644)
writeFilePerm(t, ffs, "knownDir/knownFile", oldData, 0o644)
must(t, ffs.Chtimes("knownDir/knownFile", knownFiles[1].ModTime(), knownFiles[1].ModTime()))
must(t, m.ScanFolder("ro"))
@@ -276,7 +276,7 @@ func TestRecvOnlyDeletedRemoteDrop(t *testing.T) {
// Create some test data
must(t, ffs.MkdirAll(".stfolder", 0755))
must(t, ffs.MkdirAll(".stfolder", 0o755))
oldData := []byte("hello\n")
knownFiles := setupKnownFiles(t, ffs, oldData)
@@ -341,7 +341,7 @@ func TestRecvOnlyRemoteUndoChanges(t *testing.T) {
// Create some test data
must(t, ffs.MkdirAll(".stfolder", 0755))
must(t, ffs.MkdirAll(".stfolder", 0o755))
oldData := []byte("hello\n")
knownFiles := setupKnownFiles(t, ffs, oldData)
@@ -377,8 +377,8 @@ func TestRecvOnlyRemoteUndoChanges(t *testing.T) {
const file = "foo"
knownFile := filepath.Join("knownDir", "knownFile")
writeFilePerm(t, ffs, file, []byte("hello\n"), 0644)
writeFilePerm(t, ffs, knownFile, []byte("bye\n"), 0644)
writeFilePerm(t, ffs, file, []byte("hello\n"), 0o644)
writeFilePerm(t, ffs, knownFile, []byte("bye\n"), 0o644)
must(t, m.ScanFolder("ro"))
@@ -431,10 +431,10 @@ func TestRecvOnlyRevertOwnID(t *testing.T) {
// Create some test data
must(t, ffs.MkdirAll(".stfolder", 0755))
must(t, ffs.MkdirAll(".stfolder", 0o755))
data := []byte("hello\n")
name := "foo"
writeFilePerm(t, ffs, name, data, 0644)
writeFilePerm(t, ffs, name, data, 0o644)
// Make sure the file is scanned and locally changed
must(t, m.ScanFolder("ro"))
@@ -483,8 +483,8 @@ func TestRecvOnlyRevertOwnID(t *testing.T) {
func setupKnownFiles(t *testing.T, ffs fs.Filesystem, data []byte) []protocol.FileInfo {
t.Helper()
must(t, ffs.MkdirAll("knownDir", 0755))
writeFilePerm(t, ffs, "knownDir/knownFile", data, 0644)
must(t, ffs.MkdirAll("knownDir", 0o755))
writeFilePerm(t, ffs, "knownDir/knownFile", data, 0o644)
t0 := time.Now().Add(-1 * time.Minute)
must(t, ffs.Chtimes("knownDir/knownFile", t0, t0))
@@ -498,14 +498,14 @@ func setupKnownFiles(t *testing.T, ffs fs.Filesystem, data []byte) []protocol.Fi
{
Name: "knownDir",
Type: protocol.FileInfoTypeDirectory,
Permissions: 0755,
Permissions: 0o755,
Version: protocol.Vector{Counters: []protocol.Counter{{ID: 42, Value: 42}}},
Sequence: 42,
},
{
Name: "knownDir/knownFile",
Type: protocol.FileInfoTypeFile,
Permissions: 0644,
Permissions: 0o644,
Size: fi.Size(),
ModifiedS: fi.ModTime().Unix(),
ModifiedNs: int(fi.ModTime().UnixNano() % 1e9),
@@ -521,9 +521,9 @@ func setupKnownFiles(t *testing.T, ffs fs.Filesystem, data []byte) []protocol.Fi
func setupROFolder(t *testing.T) (*testModel, *receiveOnlyFolder, context.CancelFunc) {
t.Helper()
w, cancel := createTmpWrapper(defaultCfg)
w, cancel := newConfigWrapper(defaultCfg)
cfg := w.RawCopy()
fcfg := testFolderConfigFake()
fcfg := newFolderConfig()
fcfg.ID = "ro"
fcfg.Label = "ro"
fcfg.Type = config.FolderTypeReceiveOnly
+155 -162
View File
@@ -9,7 +9,6 @@ package model
import (
"bytes"
"context"
"crypto/rand"
"errors"
"fmt"
"io"
@@ -25,8 +24,8 @@ import (
"github.com/syncthing/syncthing/lib/events"
"github.com/syncthing/syncthing/lib/fs"
"github.com/syncthing/syncthing/lib/ignore"
"github.com/syncthing/syncthing/lib/osutil"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/rand"
"github.com/syncthing/syncthing/lib/scanner"
"github.com/syncthing/syncthing/lib/sync"
)
@@ -43,6 +42,28 @@ var blocks = []protocol.BlockInfo{
{Offset: 917504, Size: 0x20000, Hash: []uint8{0x96, 0x6b, 0x15, 0x6b, 0xc4, 0xf, 0x19, 0x18, 0xca, 0xbb, 0x5f, 0xd6, 0xbb, 0xa2, 0xc6, 0x2a, 0xac, 0xbb, 0x8a, 0xb9, 0xce, 0xec, 0x4c, 0xdb, 0x78, 0xec, 0x57, 0x5d, 0x33, 0xf9, 0x8e, 0xaf}},
}
func prepareTmpFile(to fs.Filesystem) (string, error) {
tmpName := fs.TempName("file")
in, err := os.Open("testdata/tmpfile")
if err != nil {
return "", err
}
defer in.Close()
out, err := to.Create(tmpName)
if err != nil {
return "", err
}
defer out.Close()
if _, err = io.Copy(out, in); err != nil {
return "", err
}
future := time.Now().Add(time.Hour)
if err := to.Chtimes(tmpName, future, future); err != nil {
return "", err
}
return tmpName, nil
}
var folders = []string{"default"}
var diffTestData = []struct {
@@ -91,7 +112,7 @@ func createEmptyFileInfo(t *testing.T, name string, fs fs.Filesystem) protocol.F
// Sets up a folder and model, but makes sure the services aren't actually running.
func setupSendReceiveFolder(t testing.TB, files ...protocol.FileInfo) (*testModel, *sendReceiveFolder, context.CancelFunc) {
w, fcfg, wCancel := tmpDefaultWrapper(t)
w, fcfg, wCancel := newDefaultCfgWrapper()
// Initialise model and stop immediately.
model := setupModel(t, w)
model.cancel()
@@ -108,12 +129,6 @@ func setupSendReceiveFolder(t testing.TB, files ...protocol.FileInfo) (*testMode
return model, f, wCancel
}
func cleanupSRFolder(f *sendReceiveFolder, m *testModel, wrapperCancel context.CancelFunc) {
wrapperCancel()
os.Remove(m.cfg.ConfigPath())
os.RemoveAll(f.Filesystem(nil).URI())
}
// Layout of the files: (indexes from the above array)
// 12345678 - Required file
// 02005008 - Existing file (currently in the index)
@@ -129,8 +144,8 @@ func TestHandleFile(t *testing.T) {
requiredFile := existingFile
requiredFile.Blocks = blocks[1:]
m, f, wcfgCancel := setupSendReceiveFolder(t, existingFile)
defer cleanupSRFolder(f, m, wcfgCancel)
_, f, wcfgCancel := setupSendReceiveFolder(t, existingFile)
defer wcfgCancel()
copyChan := make(chan copyBlocksState, 1)
@@ -171,8 +186,8 @@ func TestHandleFileWithTemp(t *testing.T) {
requiredFile := existingFile
requiredFile.Blocks = blocks[1:]
m, f, wcfgCancel := setupSendReceiveFolder(t, existingFile)
defer cleanupSRFolder(f, m, wcfgCancel)
_, f, wcfgCancel := setupSendReceiveFolder(t, existingFile)
defer wcfgCancel()
if _, err := prepareTmpFile(f.Filesystem(nil)); err != nil {
t.Fatal(err)
@@ -205,111 +220,101 @@ func TestHandleFileWithTemp(t *testing.T) {
}
func TestCopierFinder(t *testing.T) {
methods := []fs.CopyRangeMethod{fs.CopyRangeMethodStandard, fs.CopyRangeMethodAllWithFallback}
if build.IsLinux {
methods = append(methods, fs.CopyRangeMethodSendFile)
// After diff between required and existing we should:
// Copy: 1, 2, 3, 4, 6, 7, 8
// Since there is no existing file, nor a temp file
// After dropping out blocks found locally:
// Pull: 1, 5, 6, 8
tempFile := fs.TempName("file2")
existingBlocks := []int{0, 2, 3, 4, 0, 0, 7, 0}
existingFile := setupFile(fs.TempName("file"), existingBlocks)
existingFile.Size = 1
requiredFile := existingFile
requiredFile.Blocks = blocks[1:]
requiredFile.Name = "file2"
_, f, wcfgCancel := setupSendReceiveFolder(t, existingFile)
defer wcfgCancel()
if _, err := prepareTmpFile(f.Filesystem(nil)); err != nil {
t.Fatal(err)
}
for _, method := range methods {
t.Run(method.String(), func(t *testing.T) {
// After diff between required and existing we should:
// Copy: 1, 2, 3, 4, 6, 7, 8
// Since there is no existing file, nor a temp file
// After dropping out blocks found locally:
// Pull: 1, 5, 6, 8
copyChan := make(chan copyBlocksState)
pullChan := make(chan pullBlockState, 4)
finisherChan := make(chan *sharedPullerState, 1)
tempFile := fs.TempName("file2")
// Run a single fetcher routine
go f.copierRoutine(copyChan, pullChan, finisherChan)
defer close(copyChan)
existingBlocks := []int{0, 2, 3, 4, 0, 0, 7, 0}
existingFile := setupFile(fs.TempName("file"), existingBlocks)
existingFile.Size = 1
requiredFile := existingFile
requiredFile.Blocks = blocks[1:]
requiredFile.Name = "file2"
f.handleFile(requiredFile, fsetSnapshot(t, f.fset), copyChan)
m, f, wcfgCancel := setupSendReceiveFolder(t, existingFile)
f.CopyRangeMethod = method
timeout := time.After(10 * time.Second)
pulls := make([]pullBlockState, 4)
for i := 0; i < 4; i++ {
select {
case pulls[i] = <-pullChan:
case <-timeout:
t.Fatalf("Timed out before receiving all 4 states on pullChan (already got %v)", i)
}
}
var finish *sharedPullerState
select {
case finish = <-finisherChan:
case <-timeout:
t.Fatal("Timed out before receiving 4 states on pullChan")
}
defer cleanupSRFolder(f, m, wcfgCancel)
defer cleanupSharedPullerState(finish)
if _, err := prepareTmpFile(f.Filesystem(nil)); err != nil {
t.Fatal(err)
select {
case <-pullChan:
t.Fatal("Pull channel has data to be read")
case <-finisherChan:
t.Fatal("Finisher channel has data to be read")
default:
}
// Verify that the right blocks went into the pull list.
// They are pulled in random order.
for _, idx := range []int{1, 5, 6, 8} {
found := false
block := blocks[idx]
for _, pulledBlock := range pulls {
if bytes.Equal(pulledBlock.block.Hash, block.Hash) {
found = true
break
}
}
if !found {
t.Errorf("Did not find block %s", block.String())
}
if !bytes.Equal(finish.file.Blocks[idx-1].Hash, blocks[idx].Hash) {
t.Errorf("Block %d mismatch: %s != %s", idx, finish.file.Blocks[idx-1].String(), blocks[idx].String())
}
}
copyChan := make(chan copyBlocksState)
pullChan := make(chan pullBlockState, 4)
finisherChan := make(chan *sharedPullerState, 1)
// Verify that the fetched blocks have actually been written to the temp file
blks, err := scanner.HashFile(context.TODO(), f.Filesystem(nil), tempFile, protocol.MinBlockSize, nil, false)
if err != nil {
t.Log(err)
}
// Run a single fetcher routine
go f.copierRoutine(copyChan, pullChan, finisherChan)
defer close(copyChan)
f.handleFile(requiredFile, fsetSnapshot(t, f.fset), copyChan)
timeout := time.After(10 * time.Second)
pulls := make([]pullBlockState, 4)
for i := 0; i < 4; i++ {
select {
case pulls[i] = <-pullChan:
case <-timeout:
t.Fatalf("Timed out before receiving all 4 states on pullChan (already got %v)", i)
}
}
var finish *sharedPullerState
select {
case finish = <-finisherChan:
case <-timeout:
t.Fatal("Timed out before receiving 4 states on pullChan")
}
defer cleanupSharedPullerState(finish)
select {
case <-pullChan:
t.Fatal("Pull channel has data to be read")
case <-finisherChan:
t.Fatal("Finisher channel has data to be read")
default:
}
// Verify that the right blocks went into the pull list.
// They are pulled in random order.
for _, idx := range []int{1, 5, 6, 8} {
found := false
block := blocks[idx]
for _, pulledBlock := range pulls {
if bytes.Equal(pulledBlock.block.Hash, block.Hash) {
found = true
break
}
}
if !found {
t.Errorf("Did not find block %s", block.String())
}
if !bytes.Equal(finish.file.Blocks[idx-1].Hash, blocks[idx].Hash) {
t.Errorf("Block %d mismatch: %s != %s", idx, finish.file.Blocks[idx-1].String(), blocks[idx].String())
}
}
// Verify that the fetched blocks have actually been written to the temp file
blks, err := scanner.HashFile(context.TODO(), f.Filesystem(nil), tempFile, protocol.MinBlockSize, nil, false)
if err != nil {
t.Log(err)
}
for _, eq := range []int{2, 3, 4, 7} {
if !bytes.Equal(blks[eq-1].Hash, blocks[eq].Hash) {
t.Errorf("Block %d mismatch: %s != %s", eq, blks[eq-1].String(), blocks[eq].String())
}
}
})
for _, eq := range []int{2, 3, 4, 7} {
if !bytes.Equal(blks[eq-1].Hash, blocks[eq].Hash) {
t.Errorf("Block %d mismatch: %s != %s", eq, blks[eq-1].String(), blocks[eq].String())
}
}
}
func TestWeakHash(t *testing.T) {
// Setup the model/pull environment
model, fo, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(fo, model, wcfgCancel)
_, fo, wcfgCancel := setupSendReceiveFolder(t)
defer wcfgCancel()
ffs := fo.Filesystem(nil)
tempFile := fs.TempName("weakhash")
@@ -438,7 +443,7 @@ func TestCopierCleanup(t *testing.T) {
file := setupFile("test", []int{0})
file.Size = 1
m, f, wcfgCancel := setupSendReceiveFolder(t, file)
defer cleanupSRFolder(f, m, wcfgCancel)
defer wcfgCancel()
file.Blocks = []protocol.BlockInfo{blocks[1]}
file.Version = file.Version.Update(myID.Short())
@@ -471,7 +476,7 @@ func TestDeregisterOnFailInCopy(t *testing.T) {
file := setupFile("filex", []int{0, 2, 0, 0, 5, 0, 0, 8})
m, f, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(f, m, wcfgCancel)
defer wcfgCancel()
// Set up our evet subscription early
s := m.evLogger.Subscribe(events.ItemFinished)
@@ -571,7 +576,7 @@ func TestDeregisterOnFailInPull(t *testing.T) {
file := setupFile("filex", []int{0, 2, 0, 0, 5, 0, 0, 8})
m, f, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(f, m, wcfgCancel)
defer wcfgCancel()
// Set up our evet subscription early
s := m.evLogger.Subscribe(events.ItemFinished)
@@ -673,16 +678,15 @@ func TestDeregisterOnFailInPull(t *testing.T) {
}
func TestIssue3164(t *testing.T) {
m, f, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(f, m, wcfgCancel)
_, f, wcfgCancel := setupSendReceiveFolder(t)
defer wcfgCancel()
ffs := f.Filesystem(nil)
tmpDir := ffs.URI()
ignDir := filepath.Join("issue3164", "oktodelete")
subDir := filepath.Join(ignDir, "foobar")
must(t, ffs.MkdirAll(subDir, 0777))
must(t, os.WriteFile(filepath.Join(tmpDir, subDir, "file"), []byte("Hello"), 0644))
must(t, os.WriteFile(filepath.Join(tmpDir, ignDir, "file"), []byte("Hello"), 0644))
must(t, ffs.MkdirAll(subDir, 0o777))
must(t, fs.WriteFile(ffs, filepath.Join(subDir, "file"), []byte("Hello"), 0o644))
must(t, fs.WriteFile(ffs, filepath.Join(ignDir, "file"), []byte("Hello"), 0o644))
file := protocol.FileInfo{
Name: "issue3164",
}
@@ -764,8 +768,8 @@ func TestDiffEmpty(t *testing.T) {
// option is true and the permissions do not match between the file on disk and
// in the db.
func TestDeleteIgnorePerms(t *testing.T) {
m, f, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(f, m, wcfgCancel)
_, f, wcfgCancel := setupSendReceiveFolder(t)
defer wcfgCancel()
ffs := f.Filesystem(nil)
f.IgnorePerms = true
@@ -780,7 +784,7 @@ func TestDeleteIgnorePerms(t *testing.T) {
must(t, err)
fi, err := scanner.CreateFileInfo(stat, name, ffs, false, false, config.XattrFilter{})
must(t, err)
ffs.Chmod(name, 0600)
ffs.Chmod(name, 0o600)
if info, err := ffs.Stat(name); err == nil {
fi.InodeChangeNs = info.InodeChangeTime().UnixNano()
}
@@ -806,7 +810,7 @@ func TestCopyOwner(t *testing.T) {
// filesystem.
m, f, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(f, m, wcfgCancel)
defer wcfgCancel()
f.folder.FolderConfiguration = newFolderConfiguration(m.cfg, f.ID, f.Label, fs.FilesystemTypeFake, "/TestCopyOwner")
f.folder.FolderConfiguration.CopyOwnershipFromParent = true
@@ -815,13 +819,13 @@ func TestCopyOwner(t *testing.T) {
// Create a parent dir with a certain owner/group.
f.mtimefs.Mkdir("foo", 0755)
f.mtimefs.Mkdir("foo", 0o755)
f.mtimefs.Lchown("foo", strconv.Itoa(expOwner), strconv.Itoa(expGroup))
dir := protocol.FileInfo{
Name: "foo/bar",
Type: protocol.FileInfoTypeDirectory,
Permissions: 0755,
Permissions: 0o755,
}
// Have the folder create a subdirectory, verify that it's the correct
@@ -851,7 +855,7 @@ func TestCopyOwner(t *testing.T) {
file := protocol.FileInfo{
Name: "foo/bar/baz",
Type: protocol.FileInfoTypeFile,
Permissions: 0644,
Permissions: 0o644,
}
// Wire some stuff. The flow here is handleFile() -[copierChan]->
@@ -885,7 +889,7 @@ func TestCopyOwner(t *testing.T) {
symlink := protocol.FileInfo{
Name: "foo/bar/sym",
Type: protocol.FileInfoTypeSymlink,
Permissions: 0644,
Permissions: 0o644,
SymlinkTarget: "over the rainbow",
}
@@ -908,8 +912,8 @@ func TestCopyOwner(t *testing.T) {
// TestSRConflictReplaceFileByDir checks that a conflict is created when an existing file
// is replaced with a directory and versions are conflicting
func TestSRConflictReplaceFileByDir(t *testing.T) {
m, f, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(f, m, wcfgCancel)
_, f, wcfgCancel := setupSendReceiveFolder(t)
defer wcfgCancel()
ffs := f.Filesystem(nil)
name := "foo"
@@ -940,8 +944,8 @@ func TestSRConflictReplaceFileByDir(t *testing.T) {
// TestSRConflictReplaceFileByLink checks that a conflict is created when an existing file
// is replaced with a link and versions are conflicting
func TestSRConflictReplaceFileByLink(t *testing.T) {
m, f, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(f, m, wcfgCancel)
_, f, wcfgCancel := setupSendReceiveFolder(t)
defer wcfgCancel()
ffs := f.Filesystem(nil)
name := "foo"
@@ -973,30 +977,19 @@ func TestSRConflictReplaceFileByLink(t *testing.T) {
// TestDeleteBehindSymlink checks that we don't delete or schedule a scan
// when trying to delete a file behind a symlink.
func TestDeleteBehindSymlink(t *testing.T) {
m, f, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(f, m, wcfgCancel)
_, f, wcfgCancel := setupSendReceiveFolder(t)
defer wcfgCancel()
ffs := f.Filesystem(nil)
destDir := t.TempDir()
destFs := fs.NewFilesystem(fs.FilesystemTypeBasic, destDir)
link := "link"
file := filepath.Join(link, "file")
linkFile := filepath.Join(link, "file")
must(t, ffs.MkdirAll(link, 0755))
fi := createEmptyFileInfo(t, file, ffs)
must(t, ffs.MkdirAll(link, 0o755))
fi := createEmptyFileInfo(t, linkFile, ffs)
f.updateLocalsFromScanning([]protocol.FileInfo{fi})
must(t, osutil.RenameOrCopy(fs.CopyRangeMethodStandard, ffs, destFs, file, "file"))
must(t, ffs.Rename(linkFile, "file"))
must(t, ffs.RemoveAll(link))
if err := fs.DebugSymlinkForTestsOnly(destFs, ffs, "", link); err != nil {
if build.IsWindows {
// Probably we require permissions we don't have.
t.Skip("Need admin permissions or developer mode to run symlink test on Windows: " + err.Error())
} else {
t.Fatal(err)
}
}
must(t, ffs.CreateSymlink("/", link))
fi.Deleted = true
fi.Version = fi.Version.Update(device1.Short())
@@ -1016,15 +1009,15 @@ func TestDeleteBehindSymlink(t *testing.T) {
default:
t.Fatalf("No db update received")
}
if _, err := destFs.Stat("file"); err != nil {
if _, err := ffs.Stat("file"); err != nil {
t.Errorf("Expected no error when stating file behind symlink, got %v", err)
}
}
// Reproduces https://github.com/syncthing/syncthing/issues/6559
func TestPullCtxCancel(t *testing.T) {
m, f, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(f, m, wcfgCancel)
_, f, wcfgCancel := setupSendReceiveFolder(t)
defer wcfgCancel()
pullChan := make(chan pullBlockState)
finisherChan := make(chan *sharedPullerState)
@@ -1065,12 +1058,12 @@ func TestPullCtxCancel(t *testing.T) {
}
func TestPullDeleteUnscannedDir(t *testing.T) {
m, f, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(f, m, wcfgCancel)
_, f, wcfgCancel := setupSendReceiveFolder(t)
defer wcfgCancel()
ffs := f.Filesystem(nil)
dir := "foobar"
must(t, ffs.MkdirAll(dir, 0777))
must(t, ffs.MkdirAll(dir, 0o777))
fi := protocol.FileInfo{
Name: dir,
}
@@ -1095,7 +1088,7 @@ func TestPullDeleteUnscannedDir(t *testing.T) {
func TestPullCaseOnlyPerformFinish(t *testing.T) {
m, f, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(f, m, wcfgCancel)
defer wcfgCancel()
ffs := f.Filesystem(nil)
name := "foo"
@@ -1157,12 +1150,12 @@ func TestPullCaseOnlySymlink(t *testing.T) {
func testPullCaseOnlyDirOrSymlink(t *testing.T, dir bool) {
m, f, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(f, m, wcfgCancel)
defer wcfgCancel()
ffs := f.Filesystem(nil)
name := "foo"
if dir {
must(t, ffs.Mkdir(name, 0777))
must(t, ffs.Mkdir(name, 0o777))
} else {
must(t, ffs.CreateSymlink("target", name))
}
@@ -1212,8 +1205,8 @@ func testPullCaseOnlyDirOrSymlink(t *testing.T, dir bool) {
}
func TestPullTempFileCaseConflict(t *testing.T) {
m, f, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(f, m, wcfgCancel)
_, f, wcfgCancel := setupSendReceiveFolder(t)
defer wcfgCancel()
copyChan := make(chan copyBlocksState, 1)
@@ -1241,7 +1234,7 @@ func TestPullTempFileCaseConflict(t *testing.T) {
func TestPullCaseOnlyRename(t *testing.T) {
m, f, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(f, m, wcfgCancel)
defer wcfgCancel()
// tempNameConfl := fs.TempName(confl)
@@ -1284,7 +1277,7 @@ func TestPullSymlinkOverExistingWindows(t *testing.T) {
}
m, f, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(f, m, wcfgCancel)
defer wcfgCancel()
addFakeConn(m, device1, f.ID)
name := "foo"
@@ -1325,8 +1318,8 @@ func TestPullSymlinkOverExistingWindows(t *testing.T) {
}
func TestPullDeleteCaseConflict(t *testing.T) {
m, f, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(f, m, wcfgCancel)
_, f, wcfgCancel := setupSendReceiveFolder(t)
defer wcfgCancel()
name := "foo"
fi := protocol.FileInfo{Name: "Foo"}
@@ -1359,8 +1352,8 @@ func TestPullDeleteCaseConflict(t *testing.T) {
}
func TestPullDeleteIgnoreChildDir(t *testing.T) {
m, f, wcfgCancel := setupSendReceiveFolder(t)
defer cleanupSRFolder(f, m, wcfgCancel)
_, f, wcfgCancel := setupSendReceiveFolder(t)
defer wcfgCancel()
parent := "parent"
del := "ignored"
@@ -1372,9 +1365,9 @@ func TestPullDeleteIgnoreChildDir(t *testing.T) {
`, child, del)), ""))
f.ignores = matcher
must(t, f.mtimefs.Mkdir(parent, 0777))
must(t, f.mtimefs.Mkdir(filepath.Join(parent, del), 0777))
must(t, f.mtimefs.Mkdir(filepath.Join(parent, del, child), 0777))
must(t, f.mtimefs.Mkdir(parent, 0o777))
must(t, f.mtimefs.Mkdir(filepath.Join(parent, del), 0o777))
must(t, f.mtimefs.Mkdir(filepath.Join(parent, del, child), 0o777))
scanChan := make(chan string, 2)
+3 -3
View File
@@ -16,6 +16,7 @@ import (
"github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/fs"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/rand"
)
type unifySubsCase struct {
@@ -156,8 +157,7 @@ func TestSetPlatformData(t *testing.T) {
// Checks that setPlatformData runs without error when applied to a temp
// file, named differently than the given FileInfo.
dir := t.TempDir()
fs := fs.NewFilesystem(fs.FilesystemTypeBasic, dir)
fs := fs.NewFilesystem(fs.FilesystemTypeFake, rand.String(32))
if fd, err := fs.Create("file.tmp"); err != nil {
t.Fatal(err)
} else {
@@ -167,7 +167,7 @@ func TestSetPlatformData(t *testing.T) {
xattr := []protocol.Xattr{{Name: "user.foo", Value: []byte("bar")}}
fi := &protocol.FileInfo{
Name: "should be ignored",
Permissions: 0400,
Permissions: 0o400,
ModifiedS: 1234567890,
Platform: protocol.PlatformData{
Linux: &protocol.XattrData{Xattrs: xattr},
+5 -5
View File
@@ -1220,7 +1220,7 @@ func (m *model) ClusterConfig(deviceID protocol.DeviceID, cm protocol.ClusterCon
haveFcfg := cfg.FolderMap()
for _, folder := range cm.Folders {
from, ok := haveFcfg[folder.ID]
if to, changed := m.handleAutoAccepts(deviceID, folder, ccDeviceInfos[folder.ID], from, ok, cfg.Defaults.Folder.Path); changed {
if to, changed := m.handleAutoAccepts(deviceID, folder, ccDeviceInfos[folder.ID], from, ok, cfg.Defaults.Folder); changed {
changedFcfg[folder.ID] = to
}
}
@@ -1664,9 +1664,9 @@ func (*model) handleDeintroductions(introducerCfg config.DeviceConfiguration, fo
// handleAutoAccepts handles adding and sharing folders for devices that have
// AutoAcceptFolders set to true.
func (m *model) handleAutoAccepts(deviceID protocol.DeviceID, folder protocol.Folder, ccDeviceInfos *clusterConfigDeviceInfo, cfg config.FolderConfiguration, haveCfg bool, defaultPath string) (config.FolderConfiguration, bool) {
func (m *model) handleAutoAccepts(deviceID protocol.DeviceID, folder protocol.Folder, ccDeviceInfos *clusterConfigDeviceInfo, cfg config.FolderConfiguration, haveCfg bool, defaultFolderCfg config.FolderConfiguration) (config.FolderConfiguration, bool) {
if !haveCfg {
defaultPathFs := fs.NewFilesystem(fs.FilesystemTypeBasic, defaultPath)
defaultPathFs := fs.NewFilesystem(defaultFolderCfg.FilesystemType, defaultFolderCfg.Path)
var pathAlternatives []string
if alt := fs.SanitizePath(folder.Label); alt != "" {
pathAlternatives = append(pathAlternatives, alt)
@@ -1685,13 +1685,13 @@ func (m *model) handleAutoAccepts(deviceID protocol.DeviceID, folder protocol.Fo
}
// Attempt to create it to make sure it does, now.
fullPath := filepath.Join(defaultPath, path)
fullPath := filepath.Join(defaultFolderCfg.Path, path)
if err := defaultPathFs.MkdirAll(path, 0o700); err != nil {
l.Warnf("Failed to create path for auto-accepted folder %s at path %s: %v", folder.Description(), fullPath, err)
continue
}
fcfg := newFolderConfiguration(m.cfg, folder.ID, folder.Label, fs.FilesystemTypeBasic, fullPath)
fcfg := newFolderConfiguration(m.cfg, folder.ID, folder.Label, defaultFolderCfg.FilesystemType, fullPath)
fcfg.Devices = append(fcfg.Devices, config.FolderDeviceConfiguration{
DeviceID: deviceID,
})
+322 -559
View File
File diff suppressed because it is too large Load Diff
+4 -5
View File
@@ -60,7 +60,7 @@ func TestProgressEmitter(t *testing.T) {
w := evLogger.Subscribe(events.DownloadProgress)
c, cfgCancel := createTmpWrapper(config.Configuration{})
c, cfgCancel := newConfigWrapper(config.Configuration{Version: config.CurrentVersion})
defer os.Remove(c.ConfigPath())
defer cfgCancel()
waiter, err := c.Modify(func(cfg *config.Configuration) {
@@ -110,11 +110,10 @@ func TestProgressEmitter(t *testing.T) {
expectEvent(w, t, 0)
expectTimeout(w, t)
}
func TestSendDownloadProgressMessages(t *testing.T) {
c, cfgCancel := createTmpWrapper(config.Configuration{})
c, cfgCancel := newConfigWrapper(config.Configuration{Version: config.CurrentVersion})
defer os.Remove(c.ConfigPath())
defer cfgCancel()
waiter, err := c.Modify(func(cfg *config.Configuration) {
@@ -455,8 +454,8 @@ func TestSendDownloadProgressMessages(t *testing.T) {
// See progressemitter.go for explanation why this is commented out.
// Search for state.cleanup
//expect(-1, state2, protocol.FileDownloadProgressUpdateTypeForget, v1, nil, false)
//expect(-1, state4, protocol.FileDownloadProgressUpdateTypeForget, v1, nil, true)
// expect(-1, state2, protocol.FileDownloadProgressUpdateTypeForget, v1, nil, false)
// expect(-1, state4, protocol.FileDownloadProgressUpdateTypeForget, v1, nil, true)
expectEmpty()
+27 -96
View File
@@ -10,7 +10,7 @@ import (
"bytes"
"context"
"errors"
"os"
"io"
"path/filepath"
"strconv"
"strings"
@@ -56,6 +56,7 @@ func TestRequestSimple(t *testing.T) {
// Send an update for the test file, wait for it to sync and be reported back.
contents := []byte("test file contents\n")
fc.addFile("testfile", 0o644, protocol.FileInfoTypeFile, contents)
fc.addFile("testfile", 0o644, protocol.FileInfoTypeFile, contents)
fc.sendIndexUpdate()
select {
case <-done:
@@ -64,7 +65,7 @@ func TestRequestSimple(t *testing.T) {
}
// Verify the contents
if err := equalContents(filepath.Join(tfs.URI(), "testfile"), contents); err != nil {
if err := equalContents(tfs, "testfile", contents); err != nil {
t.Error("File did not sync correctly:", err)
}
}
@@ -213,76 +214,6 @@ func TestRequestCreateTmpSymlink(t *testing.T) {
}
}
func TestRequestVersioningSymlinkAttack(t *testing.T) {
if build.IsWindows {
t.Skip("no symlink support on Windows")
}
// Sets up a folder with trashcan versioning and tries to use a
// deleted symlink to escape
w, fcfg, wCancel := tmpDefaultWrapper(t)
defer wCancel()
defer func() {
os.RemoveAll(fcfg.Filesystem(nil).URI())
os.Remove(w.ConfigPath())
}()
fcfg.Versioning = config.VersioningConfiguration{Type: "trashcan"}
setFolder(t, w, fcfg)
m, fc := setupModelWithConnectionFromWrapper(t, w)
defer cleanupModel(m)
// Create a temporary directory that we will use as target to see if
// we can escape to it
tmpdir := t.TempDir()
// We listen for incoming index updates and trigger when we see one for
// the expected test file.
idx := make(chan int)
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
idx <- len(fs)
return nil
})
waitForIdx := func() {
select {
case c := <-idx:
if c == 0 {
t.Fatal("Got empty index update")
}
case <-time.After(5 * time.Second):
t.Fatal("timed out before receiving index update")
}
}
// Send an update for the test file, wait for it to sync and be reported back.
fc.addFile("foo", 0o644, protocol.FileInfoTypeSymlink, []byte(tmpdir))
fc.sendIndexUpdate()
waitForIdx()
// Delete the symlink, hoping for it to get versioned
fc.deleteFile("foo")
fc.sendIndexUpdate()
waitForIdx()
// Recreate foo and a file in it with some data
fc.updateFile("foo", 0o755, protocol.FileInfoTypeDirectory, nil)
fc.addFile("foo/test", 0o644, protocol.FileInfoTypeFile, []byte("testtesttest"))
fc.sendIndexUpdate()
waitForIdx()
// Remove the test file and see if it escaped
fc.deleteFile("foo/test")
fc.sendIndexUpdate()
waitForIdx()
path := filepath.Join(tmpdir, "test")
if _, err := os.Lstat(path); !os.IsNotExist(err) {
t.Fatal("File escaped to", path)
}
}
func TestPullInvalidIgnoredSO(t *testing.T) {
t.Skip("flaky")
pullInvalidIgnored(t, config.FolderTypeSendOnly)
@@ -295,9 +226,9 @@ func TestPullInvalidIgnoredSR(t *testing.T) {
// This test checks that (un-)ignored/invalid/deleted files are treated as expected.
func pullInvalidIgnored(t *testing.T, ft config.FolderType) {
w, wCancel := createTmpWrapper(defaultCfgWrapper.RawCopy())
w, wCancel := newConfigWrapper(defaultCfgWrapper.RawCopy())
defer wCancel()
fcfg := testFolderConfig(t.TempDir())
fcfg := w.FolderList()[0]
fss := fcfg.Filesystem(nil)
fcfg.Type = ft
setFolder(t, w, fcfg)
@@ -676,10 +607,17 @@ func TestRequestSymlinkWindows(t *testing.T) {
}
}
func equalContents(path string, contents []byte) error {
if bs, err := os.ReadFile(path); err != nil {
func equalContents(fs fs.Filesystem, path string, contents []byte) error {
fd, err := fs.Open(path)
defer fd.Close()
if err != nil {
return err
} else if !bytes.Equal(bs, contents) {
}
bs, err := io.ReadAll(fd)
if err != nil {
return err
}
if !bytes.Equal(bs, contents) {
return errors.New("incorrect data")
}
return nil
@@ -691,8 +629,7 @@ func TestRequestRemoteRenameChanged(t *testing.T) {
m, fc, fcfg, wcfgCancel := setupModelWithConnection(t)
defer wcfgCancel()
tfs := fcfg.Filesystem(nil)
tmpDir := tfs.URI()
defer cleanupModelAndRemoveDir(m, tfs.URI())
defer cleanupModel(m)
received := make(chan []protocol.FileInfo)
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
@@ -727,7 +664,7 @@ func TestRequestRemoteRenameChanged(t *testing.T) {
}
for _, n := range [2]string{a, b} {
must(t, equalContents(filepath.Join(tmpDir, n), data[n]))
must(t, equalContents(tfs, n, data[n]))
}
var gotA, gotB, gotConfl bool
@@ -806,11 +743,11 @@ func TestRequestRemoteRenameChanged(t *testing.T) {
case path == a:
t.Errorf(`File "a" was not removed`)
case path == b:
if err := equalContents(filepath.Join(tmpDir, b), data[a]); err != nil {
if err := equalContents(tfs, b, data[a]); err != nil {
t.Error(`File "b" has unexpected content (renamed from a on remote)`)
}
case strings.HasPrefix(path, b+".sync-conflict-"):
if err := equalContents(filepath.Join(tmpDir, path), otherData); err != nil {
if err := equalContents(tfs, path, otherData); err != nil {
t.Error(`Sync conflict of "b" has unexptected content`)
}
case path == "." || strings.HasPrefix(path, ".stfolder"):
@@ -825,8 +762,7 @@ func TestRequestRemoteRenameConflict(t *testing.T) {
m, fc, fcfg, wcfgCancel := setupModelWithConnection(t)
defer wcfgCancel()
tfs := fcfg.Filesystem(nil)
tmpDir := tfs.URI()
defer cleanupModelAndRemoveDir(m, tmpDir)
defer cleanupModel(m)
recv := make(chan int)
fc.setIndexFn(func(_ context.Context, folder string, fs []protocol.FileInfo) error {
@@ -855,7 +791,7 @@ func TestRequestRemoteRenameConflict(t *testing.T) {
}
for _, n := range [2]string{a, b} {
must(t, equalContents(filepath.Join(tmpDir, n), data[n]))
must(t, equalContents(tfs, n, data[n]))
}
fd, err := tfs.OpenFile(b, fs.OptReadWrite, 0o644)
@@ -983,9 +919,7 @@ func TestRequestDeleteChanged(t *testing.T) {
func TestNeedFolderFiles(t *testing.T) {
m, fc, fcfg, wcfgCancel := setupModelWithConnection(t)
defer wcfgCancel()
tfs := fcfg.Filesystem(nil)
tmpDir := tfs.URI()
defer cleanupModelAndRemoveDir(m, tmpDir)
defer cleanupModel(m)
sub := m.evLogger.Subscribe(events.RemoteIndexUpdated)
defer sub.Unsubscribe()
@@ -1028,12 +962,11 @@ func TestNeedFolderFiles(t *testing.T) {
// propagated upon un-ignoring.
// https://github.com/syncthing/syncthing/issues/6038
func TestIgnoreDeleteUnignore(t *testing.T) {
w, fcfg, wCancel := tmpDefaultWrapper(t)
w, fcfg, wCancel := newDefaultCfgWrapper()
defer wCancel()
m := setupModel(t, w)
fss := fcfg.Filesystem(nil)
tmpDir := fss.URI()
defer cleanupModelAndRemoveDir(m, tmpDir)
defer cleanupModel(m)
folderIgnoresAlwaysReload(t, m, fcfg)
m.ScanFolders()
@@ -1272,7 +1205,7 @@ func TestRequestIndexSenderPause(t *testing.T) {
}
func TestRequestIndexSenderClusterConfigBeforeStart(t *testing.T) {
w, fcfg, wCancel := tmpDefaultWrapper(t)
w, fcfg, wCancel := newDefaultCfgWrapper()
defer wCancel()
tfs := fcfg.Filesystem(nil)
dir1 := "foo"
@@ -1339,15 +1272,13 @@ func TestRequestReceiveEncrypted(t *testing.T) {
t.Skip("skipping on short testing - scrypt is too slow")
}
w, fcfg, wCancel := tmpDefaultWrapper(t)
w, fcfg, wCancel := newDefaultCfgWrapper()
defer wCancel()
tfs := fcfg.Filesystem(nil)
fcfg.Type = config.FolderTypeReceiveEncrypted
setFolder(t, w, fcfg)
keyGen := protocol.NewKeyGenerator()
encToken := protocol.PasswordToken(keyGen, fcfg.ID, "pw")
must(t, tfs.Mkdir(config.DefaultMarkerName, 0o777))
encToken := protocol.PasswordToken(protocol.NewKeyGenerator(), fcfg.ID, "pw")
must(t, writeEncryptionToken(encToken, fcfg))
m := setupModel(t, w)
+5 -9
View File
@@ -7,25 +7,21 @@
package model
import (
"os"
"testing"
"github.com/syncthing/syncthing/lib/fs"
"github.com/syncthing/syncthing/lib/rand"
"github.com/syncthing/syncthing/lib/sync"
)
// Test creating temporary file inside read-only directory
func TestReadOnlyDir(t *testing.T) {
// Create a read only directory, clean it up afterwards.
tmpDir := t.TempDir()
if err := os.Chmod(tmpDir, 0555); err != nil {
t.Fatal(err)
}
defer os.Chmod(tmpDir, 0755)
ffs := fs.NewFilesystem(fs.FilesystemTypeFake, rand.String(32))
ffs.Mkdir("testdir", 0o555)
s := sharedPullerState{
fs: fs.NewFilesystem(fs.FilesystemTypeBasic, tmpDir),
tempName: ".temp_name",
fs: ffs,
tempName: "testdir/.temp_name",
mut: sync.NewRWMutex(),
}
-1
View File
@@ -1 +0,0 @@
foobarbaz
-1
View File
@@ -1 +0,0 @@
baazquux
View File
-1
View File
@@ -1 +0,0 @@
foobar
-60
View File
@@ -7,9 +7,6 @@
package model
import (
"os"
"time"
"github.com/syncthing/syncthing/lib/fs"
)
@@ -19,10 +16,6 @@ type fatal interface {
Helper()
}
type fatalOs struct {
fatal
}
func must(f fatal, err error) {
f.Helper()
if err != nil {
@@ -36,56 +29,3 @@ func mustRemove(f fatal, err error) {
f.Fatal(err)
}
}
func (f *fatalOs) Chmod(name string, mode os.FileMode) {
f.Helper()
must(f, os.Chmod(name, mode))
}
func (f *fatalOs) Chtimes(name string, atime time.Time, mtime time.Time) {
f.Helper()
must(f, os.Chtimes(name, atime, mtime))
}
func (f *fatalOs) Create(name string) *os.File {
f.Helper()
file, err := os.Create(name)
must(f, err)
return file
}
func (f *fatalOs) Mkdir(name string, perm os.FileMode) {
f.Helper()
must(f, os.Mkdir(name, perm))
}
func (f *fatalOs) MkdirAll(name string, perm os.FileMode) {
f.Helper()
must(f, os.MkdirAll(name, perm))
}
func (f *fatalOs) Remove(name string) {
f.Helper()
if err := os.Remove(name); err != nil && !os.IsNotExist(err) {
f.Fatal(err)
}
}
func (f *fatalOs) RemoveAll(name string) {
f.Helper()
if err := os.RemoveAll(name); err != nil && !os.IsNotExist(err) {
f.Fatal(err)
}
}
func (f *fatalOs) Rename(oldname, newname string) {
f.Helper()
must(f, os.Rename(oldname, newname))
}
func (f *fatalOs) Stat(name string) os.FileInfo {
f.Helper()
info, err := os.Stat(name)
must(f, err)
return info
}
+16 -24
View File
@@ -27,7 +27,6 @@ var (
defaultCfgWrapper config.Wrapper
defaultCfgWrapperCancel context.CancelFunc
defaultFolderConfig config.FolderConfiguration
defaultFs fs.Filesystem
defaultCfg config.Configuration
defaultAutoAcceptCfg config.Configuration
)
@@ -37,10 +36,11 @@ func init() {
device1, _ = protocol.DeviceIDFromString("AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR")
device2, _ = protocol.DeviceIDFromString("GYRZZQB-IRNPV4Z-T7TC52W-EQYJ3TT-FDQW6MW-DFLMU42-SSSU6EM-FBK2VAY")
defaultCfgWrapper, defaultCfgWrapperCancel = createTmpWrapper(config.New(myID))
cfg := config.New(myID)
cfg.Options.MinHomeDiskFree.Value = 0 // avoids unnecessary free space checks
defaultCfgWrapper, defaultCfgWrapperCancel = newConfigWrapper(cfg)
defaultFolderConfig = testFolderConfig("testdata")
defaultFs = defaultFolderConfig.Filesystem(nil)
defaultFolderConfig = newFolderConfig()
waiter, _ := defaultCfgWrapper.Modify(func(cfg *config.Configuration) {
cfg.SetDevice(newDeviceConfiguration(cfg.Defaults.Device, device1, "device1"))
@@ -68,41 +68,33 @@ func init() {
},
Defaults: config.Defaults{
Folder: config.FolderConfiguration{
Path: ".",
FilesystemType: fs.FilesystemTypeFake,
Path: rand.String(32),
},
},
Options: config.OptionsConfiguration{
MinHomeDiskFree: config.Size{}, // avoids unnecessary free space checks
},
}
}
func createTmpWrapper(cfg config.Configuration) (config.Wrapper, context.CancelFunc) {
tmpFile, err := os.CreateTemp("", "syncthing-testConfig-")
if err != nil {
panic(err)
}
wrapper := config.Wrap(tmpFile.Name(), cfg, myID, events.NoopLogger)
tmpFile.Close()
func newConfigWrapper(cfg config.Configuration) (config.Wrapper, context.CancelFunc) {
wrapper := config.Wrap("", cfg, myID, events.NoopLogger)
ctx, cancel := context.WithCancel(context.Background())
go wrapper.Serve(ctx)
return wrapper, cancel
}
func tmpDefaultWrapper(t testing.TB) (config.Wrapper, config.FolderConfiguration, context.CancelFunc) {
w, cancel := createTmpWrapper(defaultCfgWrapper.RawCopy())
fcfg := testFolderConfig(t.TempDir())
func newDefaultCfgWrapper() (config.Wrapper, config.FolderConfiguration, context.CancelFunc) {
w, cancel := newConfigWrapper(defaultCfgWrapper.RawCopy())
fcfg := newFolderConfig()
_, _ = w.Modify(func(cfg *config.Configuration) {
cfg.SetFolder(fcfg)
})
return w, fcfg, cancel
}
func testFolderConfig(path string) config.FolderConfiguration {
cfg := newFolderConfiguration(defaultCfgWrapper, "default", "default", fs.FilesystemTypeBasic, path)
cfg.FSWatcherEnabled = false
cfg.Devices = append(cfg.Devices, config.FolderDeviceConfiguration{DeviceID: device1})
return cfg
}
func testFolderConfigFake() config.FolderConfiguration {
func newFolderConfig() config.FolderConfiguration {
cfg := newFolderConfiguration(defaultCfgWrapper, "default", "default", fs.FilesystemTypeFake, rand.String(32)+"?content=true")
cfg.FSWatcherEnabled = false
cfg.Devices = append(cfg.Devices, config.FolderDeviceConfiguration{DeviceID: device1})
@@ -111,7 +103,7 @@ func testFolderConfigFake() config.FolderConfiguration {
func setupModelWithConnection(t testing.TB) (*testModel, *fakeConnection, config.FolderConfiguration, context.CancelFunc) {
t.Helper()
w, fcfg, cancel := tmpDefaultWrapper(t)
w, fcfg, cancel := newDefaultCfgWrapper()
m, fc := setupModelWithConnectionFromWrapper(t, w)
return m, fc, fcfg, cancel
}
+20 -34
View File
@@ -11,16 +11,15 @@ import (
"github.com/syncthing/syncthing/lib/build"
"github.com/syncthing/syncthing/lib/fs"
"github.com/syncthing/syncthing/lib/rand"
)
func TestInWriteableDir(t *testing.T) {
dir := t.TempDir()
fs := fs.NewFilesystem(fs.FilesystemTypeFake, rand.String(32))
fs := fs.NewFilesystem(fs.FilesystemTypeBasic, dir)
fs.Mkdir("testdata", 0700)
fs.Mkdir("testdata/rw", 0700)
fs.Mkdir("testdata/ro", 0500)
fs.Mkdir("testdata", 0o700)
fs.Mkdir("testdata/rw", 0o700)
fs.Mkdir("testdata/ro", 0o500)
create := func(name string) error {
fd, err := fs.Create(name)
@@ -68,17 +67,12 @@ func TestInWriteableDir(t *testing.T) {
}
func TestOSWindowsRemove(t *testing.T) {
// os.Remove should remove read only things on windows
if !build.IsWindows {
t.Skipf("Tests not required")
return
}
dir := t.TempDir()
fs := fs.NewFilesystem(fs.FilesystemTypeBasic, dir)
defer fs.Chmod("testdata/windows/ro/readonlynew", 0700)
fs := fs.NewFilesystem(fs.FilesystemTypeFake, rand.String(32))
create := func(name string) error {
fd, err := fs.Create(name)
@@ -89,12 +83,12 @@ func TestOSWindowsRemove(t *testing.T) {
return nil
}
fs.Mkdir("testdata", 0700)
fs.Mkdir("testdata", 0o700)
fs.Mkdir("testdata/windows", 0500)
fs.Mkdir("testdata/windows/ro", 0500)
fs.Mkdir("testdata/windows", 0o500)
fs.Mkdir("testdata/windows/ro", 0o500)
create("testdata/windows/ro/readonly")
fs.Chmod("testdata/windows/ro/readonly", 0500)
fs.Chmod("testdata/windows/ro/readonly", 0o500)
for _, path := range []string{"testdata/windows/ro/readonly", "testdata/windows/ro", "testdata/windows"} {
err := inWritableDir(fs.Remove, fs, path, false)
@@ -105,17 +99,12 @@ func TestOSWindowsRemove(t *testing.T) {
}
func TestOSWindowsRemoveAll(t *testing.T) {
// os.RemoveAll should remove read only things on windows
if !build.IsWindows {
t.Skipf("Tests not required")
return
}
dir := t.TempDir()
fs := fs.NewFilesystem(fs.FilesystemTypeBasic, dir)
defer fs.Chmod("testdata/windows/ro/readonlynew", 0700)
fs := fs.NewFilesystem(fs.FilesystemTypeFake, rand.String(32))
create := func(name string) error {
fd, err := fs.Create(name)
@@ -126,12 +115,12 @@ func TestOSWindowsRemoveAll(t *testing.T) {
return nil
}
fs.Mkdir("testdata", 0700)
fs.Mkdir("testdata", 0o700)
fs.Mkdir("testdata/windows", 0500)
fs.Mkdir("testdata/windows/ro", 0500)
fs.Mkdir("testdata/windows", 0o500)
fs.Mkdir("testdata/windows/ro", 0o500)
create("testdata/windows/ro/readonly")
fs.Chmod("testdata/windows/ro/readonly", 0500)
fs.Chmod("testdata/windows/ro/readonly", 0o500)
if err := fs.RemoveAll("testdata/windows"); err != nil {
t.Errorf("Unexpected error: %s", err)
@@ -144,10 +133,7 @@ func TestInWritableDirWindowsRename(t *testing.T) {
return
}
dir := t.TempDir()
fs := fs.NewFilesystem(fs.FilesystemTypeBasic, dir)
defer fs.Chmod("testdata/windows/ro/readonlynew", 0700)
fs := fs.NewFilesystem(fs.FilesystemTypeFake, rand.String(32))
create := func(name string) error {
fd, err := fs.Create(name)
@@ -158,12 +144,12 @@ func TestInWritableDirWindowsRename(t *testing.T) {
return nil
}
fs.Mkdir("testdata", 0700)
fs.Mkdir("testdata", 0o700)
fs.Mkdir("testdata/windows", 0500)
fs.Mkdir("testdata/windows/ro", 0500)
fs.Mkdir("testdata/windows", 0o500)
fs.Mkdir("testdata/windows/ro", 0o500)
create("testdata/windows/ro/readonly")
fs.Chmod("testdata/windows/ro/readonly", 0500)
fs.Chmod("testdata/windows/ro/readonly", 0o500)
for _, path := range []string{"testdata/windows/ro/readonly", "testdata/windows/ro", "testdata/windows"} {
err := fs.Rename(path, path+"new")