lib/model: Improve filesystem operations during tests (fixes #5422)

* lib/fs, lib/model: Improve filesystem operations during tests (fixes #5422)

Introduces MustFilesystem that panics on errors and should be used for operations
during testing which must never fail.
Create temporary directories outside of testdata.

* don't do a filesystem, just a wrapper around os for testing

* fix copyright
This commit is contained in:
Simon Frei 2019-01-11 13:56:05 +01:00 committed by Audrius Butkevicius
parent 24ffd8be99
commit 0b03b6a9ec
7 changed files with 380 additions and 236 deletions

View File

@ -22,29 +22,19 @@ import (
) )
func TestRecvOnlyRevertDeletes(t *testing.T) { func TestRecvOnlyRevertDeletes(t *testing.T) {
testOs := &fatalOs{t}
// Make sure that we delete extraneous files and directories when we hit // Make sure that we delete extraneous files and directories when we hit
// Revert. // Revert.
if err := os.RemoveAll("_recvonly"); err != nil && !os.IsNotExist(err) { testOs.RemoveAll("_recvonly")
t.Fatal(err) defer testOs.RemoveAll("_recvonly")
}
defer func() {
if err := os.RemoveAll("_recvonly"); err != nil && !os.IsNotExist(err) {
t.Fatal(err)
}
}()
// Create some test data // Create some test data
if err := os.MkdirAll("_recvonly/.stfolder", 0755); err != nil { testOs.MkdirAll("_recvonly/.stfolder", 0755)
t.Fatal(err) testOs.MkdirAll("_recvonly/ignDir", 0755)
} testOs.MkdirAll("_recvonly/unknownDir", 0755)
if err := os.MkdirAll("_recvonly/ignDir", 0755); err != nil {
t.Fatal(err)
}
if err := os.MkdirAll("_recvonly/unknownDir", 0755); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile("_recvonly/ignDir/ignFile", []byte("hello\n"), 0644); err != nil { if err := ioutil.WriteFile("_recvonly/ignDir/ignFile", []byte("hello\n"), 0644); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -125,23 +115,17 @@ func TestRecvOnlyRevertDeletes(t *testing.T) {
} }
func TestRecvOnlyRevertNeeds(t *testing.T) { func TestRecvOnlyRevertNeeds(t *testing.T) {
testOs := &fatalOs{t}
// Make sure that a new file gets picked up and considered latest, then // Make sure that a new file gets picked up and considered latest, then
// gets considered old when we hit Revert. // gets considered old when we hit Revert.
if err := os.RemoveAll("_recvonly"); err != nil && !os.IsNotExist(err) { testOs.RemoveAll("_recvonly")
t.Fatal(err) defer testOs.RemoveAll("_recvonly")
}
defer func() {
if err := os.RemoveAll("_recvonly"); err != nil && !os.IsNotExist(err) {
t.Fatal(err)
}
}()
// Create some test data // Create some test data
if err := os.MkdirAll("_recvonly/.stfolder", 0755); err != nil { testOs.MkdirAll("_recvonly/.stfolder", 0755)
t.Fatal(err)
}
oldData := []byte("hello\n") oldData := []byte("hello\n")
knownFiles := setupKnownFiles(t, oldData) knownFiles := setupKnownFiles(t, oldData)
@ -231,20 +215,14 @@ func TestRecvOnlyRevertNeeds(t *testing.T) {
} }
func TestRecvOnlyUndoChanges(t *testing.T) { func TestRecvOnlyUndoChanges(t *testing.T) {
if err := os.RemoveAll("_recvonly"); err != nil && !os.IsNotExist(err) { testOs := &fatalOs{t}
t.Fatal(err)
} testOs.RemoveAll("_recvonly")
defer func() { defer testOs.RemoveAll("_recvonly")
if err := os.RemoveAll("_recvonly"); err != nil && !os.IsNotExist(err) {
t.Fatal(err)
}
}()
// Create some test data // Create some test data
if err := os.MkdirAll("_recvonly/.stfolder", 0755); err != nil { testOs.MkdirAll("_recvonly/.stfolder", 0755)
t.Fatal(err)
}
oldData := []byte("hello\n") oldData := []byte("hello\n")
knownFiles := setupKnownFiles(t, oldData) knownFiles := setupKnownFiles(t, oldData)
@ -307,9 +285,7 @@ func TestRecvOnlyUndoChanges(t *testing.T) {
// Remove the file again and undo the modification // Remove the file again and undo the modification
if err := os.Remove(file); err != nil { testOs.Remove(file)
t.Fatal(err)
}
if err := ioutil.WriteFile("_recvonly/knownDir/knownFile", oldData, 0644); err != nil { if err := ioutil.WriteFile("_recvonly/knownDir/knownFile", oldData, 0644); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -324,22 +300,17 @@ func TestRecvOnlyUndoChanges(t *testing.T) {
} }
func setupKnownFiles(t *testing.T, data []byte) []protocol.FileInfo { func setupKnownFiles(t *testing.T, data []byte) []protocol.FileInfo {
if err := os.MkdirAll("_recvonly/knownDir", 0755); err != nil { testOs := &fatalOs{t}
t.Fatal(err)
} testOs.MkdirAll("_recvonly/knownDir", 0755)
if err := ioutil.WriteFile("_recvonly/knownDir/knownFile", data, 0644); err != nil { if err := ioutil.WriteFile("_recvonly/knownDir/knownFile", data, 0644); err != nil {
t.Fatal(err) t.Fatal(err)
} }
t0 := time.Now().Add(-1 * time.Minute) t0 := time.Now().Add(-1 * time.Minute)
if err := os.Chtimes("_recvonly/knownDir/knownFile", t0, t0); err != nil { testOs.Chtimes("_recvonly/knownDir/knownFile", t0, t0)
t.Fatal(err)
}
fi, err := os.Stat("_recvonly/knownDir/knownFile") fi, _ := testOs.Stat("_recvonly/knownDir/knownFile")
if err != nil {
t.Fatal(err)
}
blocks, _ := scanner.Blocks(context.TODO(), bytes.NewReader(data), protocol.BlockSize(int64(len(data))), int64(len(data)), nil, true) blocks, _ := scanner.Blocks(context.TODO(), bytes.NewReader(data), protocol.BlockSize(int64(len(data))), int64(len(data)), nil, true)
knownFiles := []protocol.FileInfo{ knownFiles := []protocol.FileInfo{
{ {

View File

@ -196,6 +196,8 @@ func TestHandleFileWithTemp(t *testing.T) {
} }
func TestCopierFinder(t *testing.T) { func TestCopierFinder(t *testing.T) {
testOs := &fatalOs{t}
// After diff between required and existing we should: // After diff between required and existing we should:
// Copy: 1, 2, 3, 4, 6, 7, 8 // Copy: 1, 2, 3, 4, 6, 7, 8
// Since there is no existing file, nor a temp file // Since there is no existing file, nor a temp file
@ -204,11 +206,8 @@ func TestCopierFinder(t *testing.T) {
// Pull: 1, 5, 6, 8 // Pull: 1, 5, 6, 8
tempFile := filepath.Join("testdata", fs.TempName("file2")) tempFile := filepath.Join("testdata", fs.TempName("file2"))
err := os.Remove(tempFile) testOs.Remove(tempFile)
if err != nil && !os.IsNotExist(err) { defer testOs.Remove(tempFile)
t.Error(err)
}
defer os.Remove(tempFile)
existingBlocks := []int{0, 2, 3, 4, 0, 0, 7, 0} existingBlocks := []int{0, 2, 3, 4, 0, 0, 7, 0}
existingFile := setUpFile(fs.TempName("file"), existingBlocks) existingFile := setUpFile(fs.TempName("file"), existingBlocks)
@ -273,6 +272,8 @@ func TestCopierFinder(t *testing.T) {
} }
func TestWeakHash(t *testing.T) { func TestWeakHash(t *testing.T) {
testOs := &fatalOs{t}
tempFile := filepath.Join("testdata", fs.TempName("weakhash")) tempFile := filepath.Join("testdata", fs.TempName("weakhash"))
var shift int64 = 10 var shift int64 = 10
var size int64 = 1 << 20 var size int64 = 1 << 20
@ -284,19 +285,16 @@ func TestWeakHash(t *testing.T) {
cleanup := func() { cleanup := func() {
for _, path := range []string{tempFile, "testdata/weakhash"} { for _, path := range []string{tempFile, "testdata/weakhash"} {
os.Remove(path) testOs.Remove(path)
} }
} }
cleanup() cleanup()
defer cleanup() defer cleanup()
f, err := os.Create("testdata/weakhash") f, _ := testOs.Create("testdata/weakhash")
if err != nil {
t.Error(err)
}
defer f.Close() defer f.Close()
_, err = io.CopyN(f, rand.Reader, size) _, err := io.CopyN(f, rand.Reader, size)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
@ -373,9 +371,7 @@ func TestWeakHash(t *testing.T) {
} }
finish.fd.Close() finish.fd.Close()
if err := os.Remove(tempFile); err != nil && !os.IsNotExist(err) { testOs.Remove(tempFile)
t.Error(err)
}
// Test 2 - using weak hash, expectPulls blocks pulled. // Test 2 - using weak hash, expectPulls blocks pulled.
fo.WeakHashThresholdPct = -1 fo.WeakHashThresholdPct = -1
@ -438,8 +434,10 @@ func TestCopierCleanup(t *testing.T) {
} }
func TestDeregisterOnFailInCopy(t *testing.T) { func TestDeregisterOnFailInCopy(t *testing.T) {
testOs := &fatalOs{t}
file := setUpFile("filex", []int{0, 2, 0, 0, 5, 0, 0, 8}) file := setUpFile("filex", []int{0, 2, 0, 0, 5, 0, 0, 8})
defer os.Remove("testdata/" + fs.TempName("filex")) defer testOs.Remove("testdata/" + fs.TempName("filex"))
db := db.OpenMemory() db := db.OpenMemory()
@ -530,8 +528,10 @@ func TestDeregisterOnFailInCopy(t *testing.T) {
} }
func TestDeregisterOnFailInPull(t *testing.T) { func TestDeregisterOnFailInPull(t *testing.T) {
testOs := &fatalOs{t}
file := setUpFile("filex", []int{0, 2, 0, 0, 5, 0, 0, 8}) file := setUpFile("filex", []int{0, 2, 0, 0, 5, 0, 0, 8})
defer os.Remove("testdata/" + fs.TempName("filex")) defer testOs.Remove("testdata/" + fs.TempName("filex"))
db := db.OpenMemory() db := db.OpenMemory()
m := NewModel(defaultCfgWrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil) m := NewModel(defaultCfgWrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil)

View File

@ -74,7 +74,7 @@ func init() {
}, },
}, },
Options: config.OptionsConfiguration{ Options: config.OptionsConfiguration{
DefaultFolderPath: "testdata", DefaultFolderPath: ".",
}, },
} }
} }
@ -114,7 +114,7 @@ func init() {
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
tmpLocation = "/tmp" tmpLocation = "/tmp"
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
tmpLocation = filepath.Join("testdata", "tmp") tmpLocation = "test-tmp"
if err := os.MkdirAll(tmpLocation, 0777); err != nil { if err := os.MkdirAll(tmpLocation, 0777); err != nil {
panic(err) panic(err)
} }
@ -515,6 +515,8 @@ func BenchmarkRequestOut(b *testing.B) {
} }
func BenchmarkRequestInSingleFile(b *testing.B) { func BenchmarkRequestInSingleFile(b *testing.B) {
testOs := &fatalOs{b}
db := db.OpenMemory() db := db.OpenMemory()
m := NewModel(defaultCfgWrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil) m := NewModel(defaultCfgWrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil)
m.AddFolder(defaultFolderConfig) m.AddFolder(defaultFolderConfig)
@ -524,9 +526,9 @@ func BenchmarkRequestInSingleFile(b *testing.B) {
buf := make([]byte, 128<<10) buf := make([]byte, 128<<10)
rand.Read(buf) rand.Read(buf)
os.RemoveAll("testdata/request") testOs.RemoveAll("testdata/request")
defer os.RemoveAll("testdata/request") defer testOs.RemoveAll("testdata/request")
os.MkdirAll("testdata/request/for/a/file/in/a/couple/of/dirs", 0755) testOs.MkdirAll("testdata/request/for/a/file/in/a/couple/of/dirs", 0755)
ioutil.WriteFile("testdata/request/for/a/file/in/a/couple/of/dirs/128k", buf, 0644) ioutil.WriteFile("testdata/request/for/a/file/in/a/couple/of/dirs/128k", buf, 0644)
b.ResetTimer() b.ResetTimer()
@ -541,11 +543,13 @@ func BenchmarkRequestInSingleFile(b *testing.B) {
} }
func TestDeviceRename(t *testing.T) { func TestDeviceRename(t *testing.T) {
testOs := &fatalOs{t}
hello := protocol.HelloResult{ hello := protocol.HelloResult{
ClientName: "syncthing", ClientName: "syncthing",
ClientVersion: "v0.9.4", ClientVersion: "v0.9.4",
} }
defer os.Remove("testdata/tmpconfig.xml") defer testOs.Remove("testdata/tmpconfig.xml")
rawCfg := config.New(device1) rawCfg := config.New(device1)
rawCfg.Devices = []config.DeviceConfiguration{ rawCfg.Devices = []config.DeviceConfiguration{
@ -613,6 +617,8 @@ func TestDeviceRename(t *testing.T) {
} }
func TestClusterConfig(t *testing.T) { func TestClusterConfig(t *testing.T) {
testOs := &fatalOs{t}
cfg := config.New(device1) cfg := config.New(device1)
cfg.Devices = []config.DeviceConfiguration{ cfg.Devices = []config.DeviceConfiguration{
{ {
@ -654,7 +660,7 @@ func TestClusterConfig(t *testing.T) {
db := db.OpenMemory() db := db.OpenMemory()
wrapper := createTmpWrapper(cfg) wrapper := createTmpWrapper(cfg)
defer os.Remove(wrapper.ConfigPath()) defer testOs.Remove(wrapper.ConfigPath())
m := NewModel(wrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil) m := NewModel(wrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil)
m.AddFolder(cfg.Folders[0]) m.AddFolder(cfg.Folders[0])
m.AddFolder(cfg.Folders[1]) m.AddFolder(cfg.Folders[1])
@ -709,6 +715,8 @@ func TestClusterConfig(t *testing.T) {
} }
func TestIntroducer(t *testing.T) { func TestIntroducer(t *testing.T) {
testOs := &fatalOs{t}
var introducedByAnyone protocol.DeviceID var introducedByAnyone protocol.DeviceID
// LocalDeviceID is a magic value meaning don't check introducer // LocalDeviceID is a magic value meaning don't check introducer
@ -748,7 +756,7 @@ func TestIntroducer(t *testing.T) {
}, },
}, },
}) })
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
m.ClusterConfig(device1, protocol.ClusterConfig{ m.ClusterConfig(device1, protocol.ClusterConfig{
Folders: []protocol.Folder{ Folders: []protocol.Folder{
{ {
@ -801,7 +809,7 @@ func TestIntroducer(t *testing.T) {
}, },
}, },
}) })
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
m.ClusterConfig(device1, protocol.ClusterConfig{ m.ClusterConfig(device1, protocol.ClusterConfig{
Folders: []protocol.Folder{ Folders: []protocol.Folder{
{ {
@ -860,7 +868,7 @@ func TestIntroducer(t *testing.T) {
}, },
}, },
}) })
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
m.ClusterConfig(device1, protocol.ClusterConfig{}) m.ClusterConfig(device1, protocol.ClusterConfig{})
if _, ok := wcfg.Device(device2); ok { if _, ok := wcfg.Device(device2); ok {
@ -908,7 +916,7 @@ func TestIntroducer(t *testing.T) {
}, },
}, },
}) })
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
m.ClusterConfig(device1, protocol.ClusterConfig{}) m.ClusterConfig(device1, protocol.ClusterConfig{})
if _, ok := wcfg.Device(device2); !ok { if _, ok := wcfg.Device(device2); !ok {
@ -955,7 +963,7 @@ func TestIntroducer(t *testing.T) {
}, },
}, },
}) })
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
m.ClusterConfig(device1, protocol.ClusterConfig{ m.ClusterConfig(device1, protocol.ClusterConfig{
Folders: []protocol.Folder{ Folders: []protocol.Folder{
{ {
@ -1015,7 +1023,7 @@ func TestIntroducer(t *testing.T) {
}, },
}, },
}) })
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
m.ClusterConfig(device1, protocol.ClusterConfig{}) m.ClusterConfig(device1, protocol.ClusterConfig{})
if _, ok := wcfg.Device(device2); !ok { if _, ok := wcfg.Device(device2); !ok {
@ -1062,7 +1070,7 @@ func TestIntroducer(t *testing.T) {
}, },
}, },
}) })
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
m.ClusterConfig(device1, protocol.ClusterConfig{}) m.ClusterConfig(device1, protocol.ClusterConfig{})
if _, ok := wcfg.Device(device2); !ok { if _, ok := wcfg.Device(device2); !ok {
@ -1079,6 +1087,8 @@ func TestIntroducer(t *testing.T) {
} }
func TestIssue4897(t *testing.T) { func TestIssue4897(t *testing.T) {
testOs := &fatalOs{t}
wcfg, m := newState(config.Configuration{ wcfg, m := newState(config.Configuration{
Devices: []config.DeviceConfiguration{ Devices: []config.DeviceConfiguration{
{ {
@ -1097,7 +1107,7 @@ func TestIssue4897(t *testing.T) {
}, },
}, },
}) })
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
cm := m.generateClusterConfig(device1) cm := m.generateClusterConfig(device1)
if l := len(cm.Folders); l != 1 { if l := len(cm.Folders); l != 1 {
@ -1106,8 +1116,10 @@ func TestIssue4897(t *testing.T) {
} }
func TestIssue5063(t *testing.T) { func TestIssue5063(t *testing.T) {
testOs := &fatalOs{t}
wcfg, m := newState(defaultAutoAcceptCfg) wcfg, m := newState(defaultAutoAcceptCfg)
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
addAndVerify := func(wg *sync.WaitGroup) { addAndVerify := func(wg *sync.WaitGroup) {
id := srand.String(8) id := srand.String(8)
@ -1119,7 +1131,7 @@ func TestIssue5063(t *testing.T) {
}, },
}, },
}) })
os.RemoveAll(filepath.Join("testdata", id)) testOs.RemoveAll(id)
wg.Done() wg.Done()
if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) { if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) {
t.Error("expected shared", id) t.Error("expected shared", id)
@ -1136,15 +1148,17 @@ func TestIssue5063(t *testing.T) {
} }
func TestAutoAcceptRejected(t *testing.T) { func TestAutoAcceptRejected(t *testing.T) {
testOs := &fatalOs{t}
// Nothing happens if AutoAcceptFolders not set // Nothing happens if AutoAcceptFolders not set
tcfg := defaultAutoAcceptCfg.Copy() tcfg := defaultAutoAcceptCfg.Copy()
for i := range tcfg.Devices { for i := range tcfg.Devices {
tcfg.Devices[i].AutoAcceptFolders = false tcfg.Devices[i].AutoAcceptFolders = false
} }
wcfg, m := newState(tcfg) wcfg, m := newState(tcfg)
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
id := srand.String(8) id := srand.String(8)
defer os.RemoveAll(filepath.Join("testdata", id)) defer testOs.RemoveAll(id)
m.ClusterConfig(device1, protocol.ClusterConfig{ m.ClusterConfig(device1, protocol.ClusterConfig{
Folders: []protocol.Folder{ Folders: []protocol.Folder{
{ {
@ -1160,11 +1174,13 @@ func TestAutoAcceptRejected(t *testing.T) {
} }
func TestAutoAcceptNewFolder(t *testing.T) { func TestAutoAcceptNewFolder(t *testing.T) {
testOs := &fatalOs{t}
// New folder // New folder
wcfg, m := newState(defaultAutoAcceptCfg) wcfg, m := newState(defaultAutoAcceptCfg)
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
id := srand.String(8) id := srand.String(8)
defer os.RemoveAll(filepath.Join("testdata", id)) defer testOs.RemoveAll(id)
m.ClusterConfig(device1, protocol.ClusterConfig{ m.ClusterConfig(device1, protocol.ClusterConfig{
Folders: []protocol.Folder{ Folders: []protocol.Folder{
{ {
@ -1179,10 +1195,12 @@ func TestAutoAcceptNewFolder(t *testing.T) {
} }
func TestAutoAcceptNewFolderFromTwoDevices(t *testing.T) { func TestAutoAcceptNewFolderFromTwoDevices(t *testing.T) {
testOs := &fatalOs{t}
wcfg, m := newState(defaultAutoAcceptCfg) wcfg, m := newState(defaultAutoAcceptCfg)
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
id := srand.String(8) id := srand.String(8)
defer os.RemoveAll(filepath.Join("testdata", id)) defer testOs.RemoveAll(id)
m.ClusterConfig(device1, protocol.ClusterConfig{ m.ClusterConfig(device1, protocol.ClusterConfig{
Folders: []protocol.Folder{ Folders: []protocol.Folder{
{ {
@ -1212,12 +1230,14 @@ func TestAutoAcceptNewFolderFromTwoDevices(t *testing.T) {
} }
func TestAutoAcceptNewFolderFromOnlyOneDevice(t *testing.T) { func TestAutoAcceptNewFolderFromOnlyOneDevice(t *testing.T) {
testOs := &fatalOs{t}
modifiedCfg := defaultAutoAcceptCfg.Copy() modifiedCfg := defaultAutoAcceptCfg.Copy()
modifiedCfg.Devices[2].AutoAcceptFolders = false modifiedCfg.Devices[2].AutoAcceptFolders = false
wcfg, m := newState(modifiedCfg) wcfg, m := newState(modifiedCfg)
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
id := srand.String(8) id := srand.String(8)
defer os.RemoveAll(filepath.Join("testdata", id)) defer testOs.RemoveAll(id)
m.ClusterConfig(device1, protocol.ClusterConfig{ m.ClusterConfig(device1, protocol.ClusterConfig{
Folders: []protocol.Folder{ Folders: []protocol.Folder{
{ {
@ -1250,6 +1270,9 @@ func TestAutoAcceptNewFolderPremutationsNoPanic(t *testing.T) {
if testing.Short() { if testing.Short() {
t.Skip("short tests only") t.Skip("short tests only")
} }
testOs := &fatalOs{t}
id := srand.String(8) id := srand.String(8)
label := srand.String(8) label := srand.String(8)
premutations := []protocol.Folder{ premutations := []protocol.Folder{
@ -1265,12 +1288,12 @@ func TestAutoAcceptNewFolderPremutationsNoPanic(t *testing.T) {
for _, dev2folder := range premutations { for _, dev2folder := range premutations {
cfg := defaultAutoAcceptCfg.Copy() cfg := defaultAutoAcceptCfg.Copy()
if localFolder.Label != "" { if localFolder.Label != "" {
fcfg := config.NewFolderConfiguration(protocol.LocalDeviceID, localFolder.ID, localFolder.Label, fs.FilesystemTypeBasic, filepath.Join("testdata", localFolder.ID)) fcfg := config.NewFolderConfiguration(protocol.LocalDeviceID, localFolder.ID, localFolder.Label, fs.FilesystemTypeBasic, localFolder.ID)
fcfg.Paused = localFolderPaused fcfg.Paused = localFolderPaused
cfg.Folders = append(cfg.Folders, fcfg) cfg.Folders = append(cfg.Folders, fcfg)
} }
wcfg, m := newState(cfg) wcfg, m := newState(cfg)
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
m.ClusterConfig(device1, protocol.ClusterConfig{ m.ClusterConfig(device1, protocol.ClusterConfig{
Folders: []protocol.Folder{dev1folder}, Folders: []protocol.Folder{dev1folder},
}) })
@ -1278,8 +1301,8 @@ func TestAutoAcceptNewFolderPremutationsNoPanic(t *testing.T) {
Folders: []protocol.Folder{dev2folder}, Folders: []protocol.Folder{dev2folder},
}) })
m.Stop() m.Stop()
os.RemoveAll(filepath.Join("testdata", id)) testOs.RemoveAll(id)
os.RemoveAll(filepath.Join("testdata", label)) testOs.RemoveAll(label)
} }
} }
} }
@ -1287,13 +1310,15 @@ func TestAutoAcceptNewFolderPremutationsNoPanic(t *testing.T) {
} }
func TestAutoAcceptMultipleFolders(t *testing.T) { func TestAutoAcceptMultipleFolders(t *testing.T) {
testOs := &fatalOs{t}
// Multiple new folders // Multiple new folders
wcfg, m := newState(defaultAutoAcceptCfg) wcfg, m := newState(defaultAutoAcceptCfg)
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
id1 := srand.String(8) id1 := srand.String(8)
defer os.RemoveAll(filepath.Join("testdata", id1)) defer testOs.RemoveAll(id1)
id2 := srand.String(8) id2 := srand.String(8)
defer os.RemoveAll(filepath.Join("testdata", id2)) defer testOs.RemoveAll(id2)
m.ClusterConfig(device1, protocol.ClusterConfig{ m.ClusterConfig(device1, protocol.ClusterConfig{
Folders: []protocol.Folder{ Folders: []protocol.Folder{
{ {
@ -1315,21 +1340,23 @@ func TestAutoAcceptMultipleFolders(t *testing.T) {
} }
func TestAutoAcceptExistingFolder(t *testing.T) { func TestAutoAcceptExistingFolder(t *testing.T) {
testOs := &fatalOs{t}
// Existing folder // Existing folder
id := srand.String(8) id := srand.String(8)
idOther := srand.String(8) // To check that path does not get changed. idOther := srand.String(8) // To check that path does not get changed.
defer os.RemoveAll(filepath.Join("testdata", id)) defer testOs.RemoveAll(id)
defer os.RemoveAll(filepath.Join("testdata", idOther)) defer testOs.RemoveAll(idOther)
tcfg := defaultAutoAcceptCfg.Copy() tcfg := defaultAutoAcceptCfg.Copy()
tcfg.Folders = []config.FolderConfiguration{ tcfg.Folders = []config.FolderConfiguration{
{ {
ID: id, ID: id,
Path: filepath.Join("testdata", idOther), // To check that path does not get changed. Path: idOther, // To check that path does not get changed.
}, },
} }
wcfg, m := newState(tcfg) wcfg, m := newState(tcfg)
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
if fcfg, ok := wcfg.Folder(id); !ok || fcfg.SharedWith(device1) { if fcfg, ok := wcfg.Folder(id); !ok || fcfg.SharedWith(device1) {
t.Error("missing folder, or shared", id) t.Error("missing folder, or shared", id)
} }
@ -1342,27 +1369,29 @@ func TestAutoAcceptExistingFolder(t *testing.T) {
}, },
}) })
if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) || fcfg.Path != filepath.Join("testdata", idOther) { if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) || fcfg.Path != idOther {
t.Error("missing folder, or unshared, or path changed", id) t.Error("missing folder, or unshared, or path changed", id)
} }
} }
func TestAutoAcceptNewAndExistingFolder(t *testing.T) { func TestAutoAcceptNewAndExistingFolder(t *testing.T) {
testOs := &fatalOs{t}
// New and existing folder // New and existing folder
id1 := srand.String(8) id1 := srand.String(8)
defer os.RemoveAll(filepath.Join("testdata", id1)) defer testOs.RemoveAll(id1)
id2 := srand.String(8) id2 := srand.String(8)
defer os.RemoveAll(filepath.Join("testdata", id2)) defer testOs.RemoveAll(id2)
tcfg := defaultAutoAcceptCfg.Copy() tcfg := defaultAutoAcceptCfg.Copy()
tcfg.Folders = []config.FolderConfiguration{ tcfg.Folders = []config.FolderConfiguration{
{ {
ID: id1, ID: id1,
Path: filepath.Join("testdata", id1), // from previous test case, to verify that path doesn't get changed. Path: id1, // from previous test case, to verify that path doesn't get changed.
}, },
} }
wcfg, m := newState(tcfg) wcfg, m := newState(tcfg)
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
if fcfg, ok := wcfg.Folder(id1); !ok || fcfg.SharedWith(device1) { if fcfg, ok := wcfg.Folder(id1); !ok || fcfg.SharedWith(device1) {
t.Error("missing folder, or shared", id1) t.Error("missing folder, or shared", id1)
} }
@ -1387,14 +1416,16 @@ func TestAutoAcceptNewAndExistingFolder(t *testing.T) {
} }
func TestAutoAcceptAlreadyShared(t *testing.T) { func TestAutoAcceptAlreadyShared(t *testing.T) {
testOs := &fatalOs{t}
// Already shared // Already shared
id := srand.String(8) id := srand.String(8)
defer os.RemoveAll(filepath.Join("testdata", id)) defer testOs.RemoveAll(id)
tcfg := defaultAutoAcceptCfg.Copy() tcfg := defaultAutoAcceptCfg.Copy()
tcfg.Folders = []config.FolderConfiguration{ tcfg.Folders = []config.FolderConfiguration{
{ {
ID: id, ID: id,
Path: filepath.Join("testdata", id), Path: id,
Devices: []config.FolderDeviceConfiguration{ Devices: []config.FolderDeviceConfiguration{
{ {
DeviceID: device1, DeviceID: device1,
@ -1403,7 +1434,7 @@ func TestAutoAcceptAlreadyShared(t *testing.T) {
}, },
} }
wcfg, m := newState(tcfg) wcfg, m := newState(tcfg)
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) { if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) {
t.Error("missing folder, or not shared", id) t.Error("missing folder, or not shared", id)
} }
@ -1422,14 +1453,16 @@ func TestAutoAcceptAlreadyShared(t *testing.T) {
} }
func TestAutoAcceptNameConflict(t *testing.T) { func TestAutoAcceptNameConflict(t *testing.T) {
testOs := &fatalOs{t}
id := srand.String(8) id := srand.String(8)
label := srand.String(8) label := srand.String(8)
os.MkdirAll(filepath.Join("testdata", id), 0777) testOs.MkdirAll(id, 0777)
os.MkdirAll(filepath.Join("testdata", label), 0777) testOs.MkdirAll(label, 0777)
defer os.RemoveAll(filepath.Join("testdata", id)) defer testOs.RemoveAll(id)
defer os.RemoveAll(filepath.Join("testdata", label)) defer testOs.RemoveAll(label)
wcfg, m := newState(defaultAutoAcceptCfg) wcfg, m := newState(defaultAutoAcceptCfg)
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
m.ClusterConfig(device1, protocol.ClusterConfig{ m.ClusterConfig(device1, protocol.ClusterConfig{
Folders: []protocol.Folder{ Folders: []protocol.Folder{
{ {
@ -1444,13 +1477,15 @@ func TestAutoAcceptNameConflict(t *testing.T) {
} }
func TestAutoAcceptPrefersLabel(t *testing.T) { func TestAutoAcceptPrefersLabel(t *testing.T) {
testOs := &fatalOs{t}
// Prefers label, falls back to ID. // Prefers label, falls back to ID.
wcfg, m := newState(defaultAutoAcceptCfg) wcfg, m := newState(defaultAutoAcceptCfg)
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
id := srand.String(8) id := srand.String(8)
label := srand.String(8) label := srand.String(8)
defer os.RemoveAll(filepath.Join("testdata", id)) defer testOs.RemoveAll(id)
defer os.RemoveAll(filepath.Join("testdata", label)) defer testOs.RemoveAll(label)
m.ClusterConfig(device1, protocol.ClusterConfig{ m.ClusterConfig(device1, protocol.ClusterConfig{
Folders: []protocol.Folder{ Folders: []protocol.Folder{
{ {
@ -1465,14 +1500,17 @@ func TestAutoAcceptPrefersLabel(t *testing.T) {
} }
func TestAutoAcceptFallsBackToID(t *testing.T) { func TestAutoAcceptFallsBackToID(t *testing.T) {
testOs := &fatalOs{t}
// Prefers label, falls back to ID. // Prefers label, falls back to ID.
wcfg, m := newState(defaultAutoAcceptCfg) wcfg, m := newState(defaultAutoAcceptCfg)
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
id := srand.String(8) id := srand.String(8)
label := srand.String(8) label := srand.String(8)
os.MkdirAll(filepath.Join("testdata", label), 0777) t.Log(id, label)
defer os.RemoveAll(filepath.Join("testdata", label)) testOs.MkdirAll(label, 0777)
defer os.RemoveAll(filepath.Join("testdata", id)) defer testOs.RemoveAll(label)
defer testOs.RemoveAll(id)
m.ClusterConfig(device1, protocol.ClusterConfig{ m.ClusterConfig(device1, protocol.ClusterConfig{
Folders: []protocol.Folder{ Folders: []protocol.Folder{
{ {
@ -1487,14 +1525,16 @@ func TestAutoAcceptFallsBackToID(t *testing.T) {
} }
func TestAutoAcceptPausedWhenFolderConfigChanged(t *testing.T) { func TestAutoAcceptPausedWhenFolderConfigChanged(t *testing.T) {
testOs := &fatalOs{t}
// Existing folder // Existing folder
id := srand.String(8) id := srand.String(8)
idOther := srand.String(8) // To check that path does not get changed. idOther := srand.String(8) // To check that path does not get changed.
defer os.RemoveAll(filepath.Join("testdata", id)) defer testOs.RemoveAll(id)
defer os.RemoveAll(filepath.Join("testdata", idOther)) defer testOs.RemoveAll(idOther)
tcfg := defaultAutoAcceptCfg.Copy() tcfg := defaultAutoAcceptCfg.Copy()
fcfg := config.NewFolderConfiguration(protocol.LocalDeviceID, id, "", fs.FilesystemTypeBasic, filepath.Join("testdata", idOther)) fcfg := config.NewFolderConfiguration(protocol.LocalDeviceID, id, "", fs.FilesystemTypeBasic, idOther)
fcfg.Paused = true fcfg.Paused = true
// The order of devices here is wrong (cfg.clean() sorts them), which will cause the folder to restart. // The order of devices here is wrong (cfg.clean() sorts them), which will cause the folder to restart.
// Because of the restart, folder gets removed from m.deviceFolder, which means that generateClusterConfig will not panic. // Because of the restart, folder gets removed from m.deviceFolder, which means that generateClusterConfig will not panic.
@ -1504,7 +1544,7 @@ func TestAutoAcceptPausedWhenFolderConfigChanged(t *testing.T) {
}) })
tcfg.Folders = []config.FolderConfiguration{fcfg} tcfg.Folders = []config.FolderConfiguration{fcfg}
wcfg, m := newState(tcfg) wcfg, m := newState(tcfg)
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) { if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) {
t.Error("missing folder, or not shared", id) t.Error("missing folder, or not shared", id)
} }
@ -1524,7 +1564,7 @@ func TestAutoAcceptPausedWhenFolderConfigChanged(t *testing.T) {
if fcfg, ok := wcfg.Folder(id); !ok { if fcfg, ok := wcfg.Folder(id); !ok {
t.Error("missing folder") t.Error("missing folder")
} else if fcfg.Path != filepath.Join("testdata", idOther) { } else if fcfg.Path != idOther {
t.Error("folder path changed") t.Error("folder path changed")
} else { } else {
for _, dev := range fcfg.DeviceIDs() { for _, dev := range fcfg.DeviceIDs() {
@ -1541,14 +1581,16 @@ func TestAutoAcceptPausedWhenFolderConfigChanged(t *testing.T) {
} }
func TestAutoAcceptPausedWhenFolderConfigNotChanged(t *testing.T) { func TestAutoAcceptPausedWhenFolderConfigNotChanged(t *testing.T) {
testOs := &fatalOs{t}
// Existing folder // Existing folder
id := srand.String(8) id := srand.String(8)
idOther := srand.String(8) // To check that path does not get changed. idOther := srand.String(8) // To check that path does not get changed.
defer os.RemoveAll(filepath.Join("testdata", id)) defer testOs.RemoveAll(id)
defer os.RemoveAll(filepath.Join("testdata", idOther)) defer testOs.RemoveAll(idOther)
tcfg := defaultAutoAcceptCfg.Copy() tcfg := defaultAutoAcceptCfg.Copy()
fcfg := config.NewFolderConfiguration(protocol.LocalDeviceID, id, "", fs.FilesystemTypeBasic, filepath.Join("testdata", idOther)) fcfg := config.NewFolderConfiguration(protocol.LocalDeviceID, id, "", fs.FilesystemTypeBasic, idOther)
fcfg.Paused = true fcfg.Paused = true
// The new folder is exactly the same as the one constructed by handleAutoAccept, which means // The new folder is exactly the same as the one constructed by handleAutoAccept, which means
// the folder will not be restarted (even if it's paused), yet handleAutoAccept used to add the folder // the folder will not be restarted (even if it's paused), yet handleAutoAccept used to add the folder
@ -1561,7 +1603,7 @@ func TestAutoAcceptPausedWhenFolderConfigNotChanged(t *testing.T) {
}, fcfg.Devices...) // Need to ensure this device order to avoid folder restart. }, fcfg.Devices...) // Need to ensure this device order to avoid folder restart.
tcfg.Folders = []config.FolderConfiguration{fcfg} tcfg.Folders = []config.FolderConfiguration{fcfg}
wcfg, m := newState(tcfg) wcfg, m := newState(tcfg)
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) { if fcfg, ok := wcfg.Folder(id); !ok || !fcfg.SharedWith(device1) {
t.Error("missing folder, or not shared", id) t.Error("missing folder, or not shared", id)
} }
@ -1581,7 +1623,7 @@ func TestAutoAcceptPausedWhenFolderConfigNotChanged(t *testing.T) {
if fcfg, ok := wcfg.Folder(id); !ok { if fcfg, ok := wcfg.Folder(id); !ok {
t.Error("missing folder") t.Error("missing folder")
} else if fcfg.Path != filepath.Join("testdata", idOther) { } else if fcfg.Path != idOther {
t.Error("folder path changed") t.Error("folder path changed")
} else { } else {
for _, dev := range fcfg.DeviceIDs() { for _, dev := range fcfg.DeviceIDs() {
@ -1658,9 +1700,11 @@ func changeIgnores(t *testing.T, m *Model, expected []string) {
} }
func TestIgnores(t *testing.T) { func TestIgnores(t *testing.T) {
testOs := &fatalOs{t}
// Assure a clean start state // Assure a clean start state
os.RemoveAll(filepath.Join("testdata", config.DefaultMarkerName)) testOs.RemoveAll(filepath.Join("testdata", config.DefaultMarkerName))
os.MkdirAll(filepath.Join("testdata", config.DefaultMarkerName), 0644) testOs.MkdirAll(filepath.Join("testdata", config.DefaultMarkerName), 0644)
ioutil.WriteFile("testdata/.stignore", []byte(".*\nquux\n"), 0644) ioutil.WriteFile("testdata/.stignore", []byte(".*\nquux\n"), 0644)
db := db.OpenMemory() db := db.OpenMemory()
@ -1719,12 +1763,16 @@ func TestIgnores(t *testing.T) {
changeIgnores(t, m, expected) changeIgnores(t, m, expected)
// Make sure no .stignore file is considered valid // Make sure no .stignore file is considered valid
os.Rename("testdata/.stignore", "testdata/.stignore.bak") defer func() {
testOs.Rename("testdata/.stignore.bak", "testdata/.stignore")
}()
testOs.Rename("testdata/.stignore", "testdata/.stignore.bak")
changeIgnores(t, m, []string{}) changeIgnores(t, m, []string{})
os.Rename("testdata/.stignore.bak", "testdata/.stignore")
} }
func TestROScanRecovery(t *testing.T) { func TestROScanRecovery(t *testing.T) {
testOs := &fatalOs{t}
ldb := db.OpenMemory() ldb := db.OpenMemory()
set := db.NewFileSet("default", defaultFs, ldb) set := db.NewFileSet("default", defaultFs, ldb)
set.Update(protocol.LocalDeviceID, []protocol.FileInfo{ set.Update(protocol.LocalDeviceID, []protocol.FileInfo{
@ -1733,7 +1781,7 @@ func TestROScanRecovery(t *testing.T) {
fcfg := config.FolderConfiguration{ fcfg := config.FolderConfiguration{
ID: "default", ID: "default",
Path: "testdata/rotestfolder", Path: "rotestfolder",
Type: config.FolderTypeSendOnly, Type: config.FolderTypeSendOnly,
RescanIntervalS: 1, RescanIntervalS: 1,
MarkerName: config.DefaultMarkerName, MarkerName: config.DefaultMarkerName,
@ -1746,9 +1794,9 @@ func TestROScanRecovery(t *testing.T) {
}, },
}, },
}) })
defer os.Remove(cfg.ConfigPath()) defer testOs.Remove(cfg.ConfigPath())
os.RemoveAll(fcfg.Path) testOs.RemoveAll(fcfg.Path)
m := NewModel(cfg, protocol.LocalDeviceID, "syncthing", "dev", ldb, nil) m := NewModel(cfg, protocol.LocalDeviceID, "syncthing", "dev", ldb, nil)
m.AddFolder(fcfg) m.AddFolder(fcfg)
@ -1779,18 +1827,14 @@ func TestROScanRecovery(t *testing.T) {
return return
} }
os.Mkdir(fcfg.Path, 0700) testOs.Mkdir(fcfg.Path, 0700)
if err := waitFor("folder marker missing"); err != nil { if err := waitFor("folder marker missing"); err != nil {
t.Error(err) t.Error(err)
return return
} }
fd, err := os.Create(filepath.Join(fcfg.Path, config.DefaultMarkerName)) fd, _ := testOs.Create(filepath.Join(fcfg.Path, config.DefaultMarkerName))
if err != nil {
t.Error(err)
return
}
fd.Close() fd.Close()
if err := waitFor(""); err != nil { if err := waitFor(""); err != nil {
@ -1798,14 +1842,14 @@ func TestROScanRecovery(t *testing.T) {
return return
} }
os.Remove(filepath.Join(fcfg.Path, config.DefaultMarkerName)) testOs.Remove(filepath.Join(fcfg.Path, config.DefaultMarkerName))
if err := waitFor("folder marker missing"); err != nil { if err := waitFor("folder marker missing"); err != nil {
t.Error(err) t.Error(err)
return return
} }
os.Remove(fcfg.Path) testOs.Remove(fcfg.Path)
if err := waitFor("folder path missing"); err != nil { if err := waitFor("folder path missing"); err != nil {
t.Error(err) t.Error(err)
@ -1814,6 +1858,8 @@ func TestROScanRecovery(t *testing.T) {
} }
func TestRWScanRecovery(t *testing.T) { func TestRWScanRecovery(t *testing.T) {
testOs := &fatalOs{t}
ldb := db.OpenMemory() ldb := db.OpenMemory()
set := db.NewFileSet("default", defaultFs, ldb) set := db.NewFileSet("default", defaultFs, ldb)
set.Update(protocol.LocalDeviceID, []protocol.FileInfo{ set.Update(protocol.LocalDeviceID, []protocol.FileInfo{
@ -1822,7 +1868,7 @@ func TestRWScanRecovery(t *testing.T) {
fcfg := config.FolderConfiguration{ fcfg := config.FolderConfiguration{
ID: "default", ID: "default",
Path: "testdata/rwtestfolder", Path: "rwtestfolder",
Type: config.FolderTypeSendReceive, Type: config.FolderTypeSendReceive,
RescanIntervalS: 1, RescanIntervalS: 1,
MarkerName: config.DefaultMarkerName, MarkerName: config.DefaultMarkerName,
@ -1835,9 +1881,9 @@ func TestRWScanRecovery(t *testing.T) {
}, },
}, },
}) })
defer os.Remove(cfg.ConfigPath()) defer testOs.Remove(cfg.ConfigPath())
os.RemoveAll(fcfg.Path) testOs.RemoveAll(fcfg.Path)
m := NewModel(cfg, protocol.LocalDeviceID, "syncthing", "dev", ldb, nil) m := NewModel(cfg, protocol.LocalDeviceID, "syncthing", "dev", ldb, nil)
m.AddFolder(fcfg) m.AddFolder(fcfg)
@ -1868,37 +1914,33 @@ func TestRWScanRecovery(t *testing.T) {
return return
} }
os.Mkdir(fcfg.Path, 0700) testOs.Mkdir(fcfg.Path, 0700)
if err := waitFor("folder marker missing"); err != nil { if err := waitFor("folder marker missing"); err != nil {
t.Error(err) t.Error(err)
return return
} }
fd, err := os.Create(filepath.Join(fcfg.Path, config.DefaultMarkerName)) fd, err := testOs.Create(filepath.Join(fcfg.Path, config.DefaultMarkerName))
if err != nil { if err != nil {
t.Error(err) t.Fatal(err)
return
} }
fd.Close() fd.Close()
if err := waitFor(""); err != nil { if err := waitFor(""); err != nil {
t.Error(err) t.Fatal(err)
return
} }
os.Remove(filepath.Join(fcfg.Path, config.DefaultMarkerName)) testOs.Remove(filepath.Join(fcfg.Path, config.DefaultMarkerName))
if err := waitFor("folder marker missing"); err != nil { if err := waitFor("folder marker missing"); err != nil {
t.Error(err) t.Fatal(err)
return
} }
os.Remove(fcfg.Path) testOs.Remove(fcfg.Path)
if err := waitFor("folder path missing"); err != nil { if err := waitFor("folder path missing"); err != nil {
t.Error(err) t.Fatal(err)
return
} }
} }
@ -2348,16 +2390,18 @@ func benchmarkTree(b *testing.B, n1, n2 int) {
} }
func TestIssue3028(t *testing.T) { func TestIssue3028(t *testing.T) {
testOs := &fatalOs{t}
// Create two files that we'll delete, one with a name that is a prefix of the other. // Create two files that we'll delete, one with a name that is a prefix of the other.
if err := ioutil.WriteFile("testdata/testrm", []byte("Hello"), 0644); err != nil { if err := ioutil.WriteFile("testdata/testrm", []byte("Hello"), 0644); err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer os.Remove("testdata/testrm") defer testOs.Remove("testdata/testrm")
if err := ioutil.WriteFile("testdata/testrm2", []byte("Hello"), 0644); err != nil { if err := ioutil.WriteFile("testdata/testrm2", []byte("Hello"), 0644); err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer os.Remove("testdata/testrm2") defer testOs.Remove("testdata/testrm2")
// Create a model and default folder // Create a model and default folder
@ -2379,8 +2423,8 @@ func TestIssue3028(t *testing.T) {
// Delete and rescan specifically these two // Delete and rescan specifically these two
os.Remove("testdata/testrm") testOs.Remove("testdata/testrm")
os.Remove("testdata/testrm2") testOs.Remove("testdata/testrm2")
m.ScanFolderSubdirs("default", []string{"testrm", "testrm2"}) m.ScanFolderSubdirs("default", []string{"testrm", "testrm2"})
// Verify that the number of files decreased by two and the number of // Verify that the number of files decreased by two and the number of
@ -2403,11 +2447,13 @@ func TestIssue3028(t *testing.T) {
} }
func TestIssue4357(t *testing.T) { func TestIssue4357(t *testing.T) {
testOs := &fatalOs{t}
db := db.OpenMemory() db := db.OpenMemory()
cfg := defaultCfgWrapper.RawCopy() cfg := defaultCfgWrapper.RawCopy()
// Create a separate wrapper not to pollute other tests. // Create a separate wrapper not to pollute other tests.
wrapper := createTmpWrapper(config.Configuration{}) wrapper := createTmpWrapper(config.Configuration{})
defer os.Remove(wrapper.ConfigPath()) defer testOs.Remove(wrapper.ConfigPath())
m := NewModel(wrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil) m := NewModel(wrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil)
m.ServeBackground() m.ServeBackground()
defer m.Stop() defer m.Stop()
@ -2480,6 +2526,8 @@ func TestIssue4357(t *testing.T) {
} }
func TestIssue2782(t *testing.T) { func TestIssue2782(t *testing.T) {
testOs := &fatalOs{t}
// CheckHealth should accept a symlinked folder, when using tilde-expanded path. // CheckHealth should accept a symlinked folder, when using tilde-expanded path.
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
@ -2509,7 +2557,7 @@ func TestIssue2782(t *testing.T) {
if err := os.Symlink("syncdir", testDir+"/synclink"); err != nil { if err := os.Symlink("syncdir", testDir+"/synclink"); err != nil {
t.Skip(err) t.Skip(err)
} }
defer os.RemoveAll(testDir) defer testOs.RemoveAll(testDir)
db := db.OpenMemory() db := db.OpenMemory()
m := NewModel(defaultCfgWrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil) m := NewModel(defaultCfgWrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil)
@ -2556,6 +2604,8 @@ func TestIndexesForUnknownDevicesDropped(t *testing.T) {
} }
func TestSharedWithClearedOnDisconnect(t *testing.T) { func TestSharedWithClearedOnDisconnect(t *testing.T) {
testOs := &fatalOs{t}
dbi := db.OpenMemory() dbi := db.OpenMemory()
fcfg := config.NewFolderConfiguration(protocol.LocalDeviceID, "default", "default", fs.FilesystemTypeBasic, "testdata") fcfg := config.NewFolderConfiguration(protocol.LocalDeviceID, "default", "default", fs.FilesystemTypeBasic, "testdata")
@ -2576,7 +2626,7 @@ func TestSharedWithClearedOnDisconnect(t *testing.T) {
} }
wcfg := createTmpWrapper(cfg) wcfg := createTmpWrapper(cfg)
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
m := NewModel(wcfg, protocol.LocalDeviceID, "syncthing", "dev", dbi, nil) m := NewModel(wcfg, protocol.LocalDeviceID, "syncthing", "dev", dbi, nil)
m.AddFolder(fcfg) m.AddFolder(fcfg)
@ -2794,6 +2844,8 @@ func TestIssue3829(t *testing.T) {
func TestNoRequestsFromPausedDevices(t *testing.T) { func TestNoRequestsFromPausedDevices(t *testing.T) {
t.Skip("broken, fails randomly, #3843") t.Skip("broken, fails randomly, #3843")
testOs := &fatalOs{t}
dbi := db.OpenMemory() dbi := db.OpenMemory()
fcfg := config.NewFolderConfiguration(protocol.LocalDeviceID, "default", "default", fs.FilesystemTypeBasic, "testdata") fcfg := config.NewFolderConfiguration(protocol.LocalDeviceID, "default", "default", fs.FilesystemTypeBasic, "testdata")
@ -2814,7 +2866,7 @@ func TestNoRequestsFromPausedDevices(t *testing.T) {
} }
wcfg := createTmpWrapper(cfg) wcfg := createTmpWrapper(cfg)
defer os.Remove(wcfg.ConfigPath()) defer testOs.Remove(wcfg.ConfigPath())
m := NewModel(wcfg, protocol.LocalDeviceID, "syncthing", "dev", dbi, nil) m := NewModel(wcfg, protocol.LocalDeviceID, "syncthing", "dev", dbi, nil)
m.AddFolder(fcfg) m.AddFolder(fcfg)
@ -3066,6 +3118,8 @@ func TestInternalScan(t *testing.T) {
} }
func TestCustomMarkerName(t *testing.T) { func TestCustomMarkerName(t *testing.T) {
testOs := &fatalOs{t}
ldb := db.OpenMemory() ldb := db.OpenMemory()
set := db.NewFileSet("default", defaultFs, ldb) set := db.NewFileSet("default", defaultFs, ldb)
set.Update(protocol.LocalDeviceID, []protocol.FileInfo{ set.Update(protocol.LocalDeviceID, []protocol.FileInfo{
@ -3074,7 +3128,7 @@ func TestCustomMarkerName(t *testing.T) {
fcfg := config.FolderConfiguration{ fcfg := config.FolderConfiguration{
ID: "default", ID: "default",
Path: "testdata/rwtestfolder", Path: "rwtestfolder",
Type: config.FolderTypeSendReceive, Type: config.FolderTypeSendReceive,
RescanIntervalS: 1, RescanIntervalS: 1,
MarkerName: "myfile", MarkerName: "myfile",
@ -3087,10 +3141,10 @@ func TestCustomMarkerName(t *testing.T) {
}, },
}, },
}) })
defer os.Remove(cfg.ConfigPath()) defer testOs.Remove(cfg.ConfigPath())
os.RemoveAll(fcfg.Path) testOs.RemoveAll(fcfg.Path)
defer os.RemoveAll(fcfg.Path) defer testOs.RemoveAll(fcfg.Path)
m := NewModel(cfg, protocol.LocalDeviceID, "syncthing", "dev", ldb, nil) m := NewModel(cfg, protocol.LocalDeviceID, "syncthing", "dev", ldb, nil)
m.AddFolder(fcfg) m.AddFolder(fcfg)
@ -3117,21 +3171,15 @@ func TestCustomMarkerName(t *testing.T) {
} }
if err := waitFor("folder path missing"); err != nil { if err := waitFor("folder path missing"); err != nil {
t.Error(err) t.Fatal(err)
return
} }
os.Mkdir(fcfg.Path, 0700) testOs.Mkdir(fcfg.Path, 0700)
fd, err := os.Create(filepath.Join(fcfg.Path, "myfile")) fd, _ := testOs.Create(filepath.Join(fcfg.Path, "myfile"))
if err != nil {
t.Error(err)
return
}
fd.Close() fd.Close()
if err := waitFor(""); err != nil { if err := waitFor(""); err != nil {
t.Error(err) t.Fatal(err)
return
} }
} }
@ -3277,6 +3325,8 @@ func TestIssue4475(t *testing.T) {
} }
func TestVersionRestore(t *testing.T) { func TestVersionRestore(t *testing.T) {
testOs := &fatalOs{t}
// We create a bunch of files which we restore // We create a bunch of files which we restore
// In each file, we write the filename as the content // In each file, we write the filename as the content
// We verify that the content matches at the expected filenames // We verify that the content matches at the expected filenames
@ -3285,7 +3335,7 @@ func TestVersionRestore(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer os.RemoveAll(dir) defer testOs.RemoveAll(dir)
dbi := db.OpenMemory() dbi := db.OpenMemory()
@ -3298,7 +3348,7 @@ func TestVersionRestore(t *testing.T) {
Folders: []config.FolderConfiguration{fcfg}, Folders: []config.FolderConfiguration{fcfg},
} }
cfg := createTmpWrapper(rawConfig) cfg := createTmpWrapper(rawConfig)
defer os.Remove(cfg.ConfigPath()) defer testOs.Remove(cfg.ConfigPath())
m := NewModel(cfg, protocol.LocalDeviceID, "syncthing", "dev", dbi, nil) m := NewModel(cfg, protocol.LocalDeviceID, "syncthing", "dev", dbi, nil)
m.AddFolder(fcfg) m.AddFolder(fcfg)
@ -3489,10 +3539,12 @@ func TestVersionRestore(t *testing.T) {
} }
func TestPausedFolders(t *testing.T) { func TestPausedFolders(t *testing.T) {
testOs := &fatalOs{t}
// Create a separate wrapper not to pollute other tests. // Create a separate wrapper not to pollute other tests.
cfg := defaultCfgWrapper.RawCopy() cfg := defaultCfgWrapper.RawCopy()
wrapper := createTmpWrapper(cfg) wrapper := createTmpWrapper(cfg)
defer os.Remove(wrapper.ConfigPath()) defer testOs.Remove(wrapper.ConfigPath())
db := db.OpenMemory() db := db.OpenMemory()
m := NewModel(wrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil) m := NewModel(wrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil)
@ -3523,17 +3575,19 @@ func TestPausedFolders(t *testing.T) {
} }
func TestIssue4094(t *testing.T) { func TestIssue4094(t *testing.T) {
testOs := &fatalOs{t}
db := db.OpenMemory() db := db.OpenMemory()
// Create a separate wrapper not to pollute other tests. // Create a separate wrapper not to pollute other tests.
wrapper := createTmpWrapper(config.Configuration{}) wrapper := createTmpWrapper(config.Configuration{})
defer os.Remove(wrapper.ConfigPath()) defer testOs.Remove(wrapper.ConfigPath())
m := NewModel(wrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil) m := NewModel(wrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil)
m.ServeBackground() m.ServeBackground()
defer m.Stop() defer m.Stop()
// Force the model to wire itself and add the folders // Force the model to wire itself and add the folders
folderPath := "testdata/nonexistent" folderPath := "nonexistent"
defer os.RemoveAll(folderPath) defer testOs.RemoveAll(folderPath)
cfg := defaultCfgWrapper.RawCopy() cfg := defaultCfgWrapper.RawCopy()
fcfg := config.FolderConfiguration{ fcfg := config.FolderConfiguration{
ID: "folder1", ID: "folder1",
@ -3560,17 +3614,19 @@ func TestIssue4094(t *testing.T) {
} }
func TestIssue4903(t *testing.T) { func TestIssue4903(t *testing.T) {
testOs := &fatalOs{t}
db := db.OpenMemory() db := db.OpenMemory()
// Create a separate wrapper not to pollute other tests. // Create a separate wrapper not to pollute other tests.
wrapper := createTmpWrapper(config.Configuration{}) wrapper := createTmpWrapper(config.Configuration{})
defer os.Remove(wrapper.ConfigPath()) defer testOs.Remove(wrapper.ConfigPath())
m := NewModel(wrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil) m := NewModel(wrapper, protocol.LocalDeviceID, "syncthing", "dev", db, nil)
m.ServeBackground() m.ServeBackground()
defer m.Stop() defer m.Stop()
// Force the model to wire itself and add the folders // Force the model to wire itself and add the folders
folderPath := "testdata/nonexistent" folderPath := "nonexistent"
defer os.RemoveAll(folderPath) defer testOs.RemoveAll(folderPath)
cfg := defaultCfgWrapper.RawCopy() cfg := defaultCfgWrapper.RawCopy()
fcfg := config.FolderConfiguration{ fcfg := config.FolderConfiguration{
ID: "folder1", ID: "folder1",
@ -3623,11 +3679,13 @@ func TestIssue5002(t *testing.T) {
} }
func TestParentOfUnignored(t *testing.T) { func TestParentOfUnignored(t *testing.T) {
testOs := &fatalOs{t}
wcfg, m := newState(defaultCfg) wcfg, m := newState(defaultCfg)
defer func() { defer func() {
m.Stop() m.Stop()
defaultFolderConfig.Filesystem().Remove(".stignore") defaultFolderConfig.Filesystem().Remove(".stignore")
os.Remove(wcfg.ConfigPath()) testOs.Remove(wcfg.ConfigPath())
}() }()
m.SetIgnores("default", []string{"!quux", "*"}) m.SetIgnores("default", []string{"!quux", "*"})
@ -3658,12 +3716,13 @@ func addFakeConn(m *Model, dev protocol.DeviceID) *fakeConnection {
return fc return fc
} }
// TestFolderRestartZombies reproduces issue 5233, where multiple concurrent folder
// restarts would leave more than one folder runner alive.
func TestFolderRestartZombies(t *testing.T) { func TestFolderRestartZombies(t *testing.T) {
// This is for issue 5233, where multiple concurrent folder restarts testOs := &fatalOs{t}
// would leave more than one folder runner alive.
wrapper := createTmpWrapper(defaultCfg.Copy()) wrapper := createTmpWrapper(defaultCfg.Copy())
defer os.Remove(wrapper.ConfigPath()) defer testOs.Remove(wrapper.ConfigPath())
folderCfg, _ := wrapper.Folder("default") folderCfg, _ := wrapper.Folder("default")
folderCfg.FilesystemType = fs.FilesystemTypeFake folderCfg.FilesystemType = fs.FilesystemTypeFake
wrapper.SetFolder(folderCfg) wrapper.SetFolder(folderCfg)
@ -3758,6 +3817,8 @@ func (c *alwaysChanged) Changed() bool {
} }
func TestRequestLimit(t *testing.T) { func TestRequestLimit(t *testing.T) {
testOs := &fatalOs{t}
cfg := defaultCfg.Copy() cfg := defaultCfg.Copy()
cfg.Devices = append(cfg.Devices, config.NewDeviceConfiguration(device2, "device2")) cfg.Devices = append(cfg.Devices, config.NewDeviceConfiguration(device2, "device2"))
cfg.Devices[1].MaxRequestKiB = 1 cfg.Devices[1].MaxRequestKiB = 1
@ -3767,7 +3828,7 @@ func TestRequestLimit(t *testing.T) {
} }
m, _, wrapper := setupModelWithConnectionManual(cfg) m, _, wrapper := setupModelWithConnectionManual(cfg)
defer m.Stop() defer m.Stop()
defer os.Remove(wrapper.ConfigPath()) defer testOs.Remove(wrapper.ConfigPath())
file := "tmpfile" file := "tmpfile"
befReq := time.Now() befReq := time.Now()

View File

@ -8,7 +8,6 @@ package model
import ( import (
"fmt" "fmt"
"os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"testing" "testing"
@ -52,10 +51,12 @@ func expectTimeout(w *events.Subscription, t *testing.T) {
} }
func TestProgressEmitter(t *testing.T) { func TestProgressEmitter(t *testing.T) {
testOs := &fatalOs{t}
w := events.Default.Subscribe(events.DownloadProgress) w := events.Default.Subscribe(events.DownloadProgress)
c := createTmpWrapper(config.Configuration{}) c := createTmpWrapper(config.Configuration{})
defer os.Remove(c.ConfigPath()) defer testOs.Remove(c.ConfigPath())
c.SetOptions(config.OptionsConfiguration{ c.SetOptions(config.OptionsConfiguration{
ProgressUpdateIntervalS: 0, ProgressUpdateIntervalS: 0,
}) })
@ -103,8 +104,10 @@ func TestProgressEmitter(t *testing.T) {
} }
func TestSendDownloadProgressMessages(t *testing.T) { func TestSendDownloadProgressMessages(t *testing.T) {
testOs := &fatalOs{t}
c := createTmpWrapper(config.Configuration{}) c := createTmpWrapper(config.Configuration{})
defer os.Remove(c.ConfigPath()) defer testOs.Remove(c.ConfigPath())
c.SetOptions(config.OptionsConfiguration{ c.SetOptions(config.OptionsConfiguration{
ProgressUpdateIntervalS: 0, ProgressUpdateIntervalS: 0,
TempIndexMinBlocks: 10, TempIndexMinBlocks: 10,

View File

@ -26,14 +26,16 @@ import (
) )
func TestRequestSimple(t *testing.T) { func TestRequestSimple(t *testing.T) {
testOs := &fatalOs{t}
// Verify that the model performs a request and creates a file based on // Verify that the model performs a request and creates a file based on
// an incoming index update. // an incoming index update.
m, fc, tmpDir, w := setupModelWithConnection() m, fc, tmpDir, w := setupModelWithConnection()
defer func() { defer func() {
m.Stop() m.Stop()
os.RemoveAll(tmpDir) testOs.RemoveAll(tmpDir)
os.Remove(w.ConfigPath()) testOs.Remove(w.ConfigPath())
}() }()
// We listen for incoming index updates and trigger when we see one for // We listen for incoming index updates and trigger when we see one for
@ -63,6 +65,8 @@ func TestRequestSimple(t *testing.T) {
} }
func TestSymlinkTraversalRead(t *testing.T) { func TestSymlinkTraversalRead(t *testing.T) {
testOs := &fatalOs{t}
// Verify that a symlink can not be traversed for reading. // Verify that a symlink can not be traversed for reading.
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
@ -73,8 +77,8 @@ func TestSymlinkTraversalRead(t *testing.T) {
m, fc, tmpDir, w := setupModelWithConnection() m, fc, tmpDir, w := setupModelWithConnection()
defer func() { defer func() {
m.Stop() m.Stop()
os.RemoveAll(tmpDir) testOs.RemoveAll(tmpDir)
os.Remove(w.ConfigPath()) testOs.Remove(w.ConfigPath())
}() }()
// We listen for incoming index updates and trigger when we see one for // We listen for incoming index updates and trigger when we see one for
@ -105,6 +109,8 @@ func TestSymlinkTraversalRead(t *testing.T) {
} }
func TestSymlinkTraversalWrite(t *testing.T) { func TestSymlinkTraversalWrite(t *testing.T) {
testOs := &fatalOs{t}
// Verify that a symlink can not be traversed for writing. // Verify that a symlink can not be traversed for writing.
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
@ -115,8 +121,8 @@ func TestSymlinkTraversalWrite(t *testing.T) {
m, fc, tmpDir, w := setupModelWithConnection() m, fc, tmpDir, w := setupModelWithConnection()
defer func() { defer func() {
m.Stop() m.Stop()
os.RemoveAll(tmpDir) testOs.RemoveAll(tmpDir)
os.Remove(w.ConfigPath()) testOs.Remove(w.ConfigPath())
}() }()
// We listen for incoming index updates and trigger when we see one for // We listen for incoming index updates and trigger when we see one for
@ -173,13 +179,15 @@ func TestSymlinkTraversalWrite(t *testing.T) {
} }
func TestRequestCreateTmpSymlink(t *testing.T) { func TestRequestCreateTmpSymlink(t *testing.T) {
testOs := &fatalOs{t}
// Test that an update for a temporary file is invalidated // Test that an update for a temporary file is invalidated
m, fc, tmpDir, w := setupModelWithConnection() m, fc, tmpDir, w := setupModelWithConnection()
defer func() { defer func() {
m.Stop() m.Stop()
os.RemoveAll(tmpDir) testOs.RemoveAll(tmpDir)
os.Remove(w.ConfigPath()) testOs.Remove(w.ConfigPath())
}() }()
// We listen for incoming index updates and trigger when we see one for // We listen for incoming index updates and trigger when we see one for
@ -213,6 +221,8 @@ func TestRequestCreateTmpSymlink(t *testing.T) {
} }
func TestRequestVersioningSymlinkAttack(t *testing.T) { func TestRequestVersioningSymlinkAttack(t *testing.T) {
testOs := &fatalOs{t}
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
t.Skip("no symlink support on Windows") t.Skip("no symlink support on Windows")
} }
@ -221,7 +231,7 @@ func TestRequestVersioningSymlinkAttack(t *testing.T) {
// deleted symlink to escape // deleted symlink to escape
tmpDir := createTmpDir() tmpDir := createTmpDir()
defer os.RemoveAll(tmpDir) defer testOs.RemoveAll(tmpDir)
cfg := defaultCfgWrapper.RawCopy() cfg := defaultCfgWrapper.RawCopy()
cfg.Devices = append(cfg.Devices, config.NewDeviceConfiguration(device2, "device2")) cfg.Devices = append(cfg.Devices, config.NewDeviceConfiguration(device2, "device2"))
@ -234,7 +244,7 @@ func TestRequestVersioningSymlinkAttack(t *testing.T) {
Type: "trashcan", Type: "trashcan",
} }
w := createTmpWrapper(cfg) w := createTmpWrapper(cfg)
defer os.Remove(w.ConfigPath()) defer testOs.Remove(w.ConfigPath())
db := db.OpenMemory() db := db.OpenMemory()
m := NewModel(w, device1, "syncthing", "dev", db, nil) m := NewModel(w, device1, "syncthing", "dev", db, nil)
@ -243,7 +253,7 @@ func TestRequestVersioningSymlinkAttack(t *testing.T) {
m.StartFolder("default") m.StartFolder("default")
defer m.Stop() defer m.Stop()
defer os.RemoveAll(tmpDir) defer testOs.RemoveAll(tmpDir)
fc := addFakeConn(m, device2) fc := addFakeConn(m, device2)
fc.folder = "default" fc.folder = "default"
@ -309,6 +319,8 @@ func TestPullInvalidIgnoredSR(t *testing.T) {
func pullInvalidIgnored(t *testing.T, ft config.FolderType) { func pullInvalidIgnored(t *testing.T, ft config.FolderType) {
t.Helper() t.Helper()
testOs := &fatalOs{t}
tmpDir := createTmpDir() tmpDir := createTmpDir()
cfg := defaultCfgWrapper.RawCopy() cfg := defaultCfgWrapper.RawCopy()
cfg.Devices = append(cfg.Devices, config.NewDeviceConfiguration(device2, "device2")) cfg.Devices = append(cfg.Devices, config.NewDeviceConfiguration(device2, "device2"))
@ -321,8 +333,8 @@ func pullInvalidIgnored(t *testing.T, ft config.FolderType) {
m, fc, w := setupModelWithConnectionManual(cfg) m, fc, w := setupModelWithConnectionManual(cfg)
defer func() { defer func() {
m.Stop() m.Stop()
os.RemoveAll(tmpDir) testOs.RemoveAll(tmpDir)
os.Remove(w.ConfigPath()) testOs.Remove(w.ConfigPath())
}() }()
// Reach in and update the ignore matcher to one that always does // Reach in and update the ignore matcher to one that always does
@ -440,11 +452,13 @@ func pullInvalidIgnored(t *testing.T, ft config.FolderType) {
} }
func TestIssue4841(t *testing.T) { func TestIssue4841(t *testing.T) {
testOs := &fatalOs{t}
m, fc, tmpDir, w := setupModelWithConnection() m, fc, tmpDir, w := setupModelWithConnection()
defer func() { defer func() {
m.Stop() m.Stop()
os.RemoveAll(tmpDir) testOs.RemoveAll(tmpDir)
os.Remove(w.ConfigPath()) testOs.Remove(w.ConfigPath())
}() }()
received := make(chan protocol.FileInfo) received := make(chan protocol.FileInfo)
@ -482,11 +496,13 @@ func TestIssue4841(t *testing.T) {
} }
func TestRescanIfHaveInvalidContent(t *testing.T) { func TestRescanIfHaveInvalidContent(t *testing.T) {
testOs := &fatalOs{t}
m, fc, tmpDir, w := setupModelWithConnection() m, fc, tmpDir, w := setupModelWithConnection()
defer func() { defer func() {
m.Stop() m.Stop()
os.RemoveAll(tmpDir) testOs.RemoveAll(tmpDir)
os.Remove(w.ConfigPath()) testOs.Remove(w.ConfigPath())
}() }()
payload := []byte("hello") payload := []byte("hello")
@ -551,11 +567,13 @@ func TestRescanIfHaveInvalidContent(t *testing.T) {
} }
func TestParentDeletion(t *testing.T) { func TestParentDeletion(t *testing.T) {
testOs := &fatalOs{t}
m, fc, tmpDir, w := setupModelWithConnection() m, fc, tmpDir, w := setupModelWithConnection()
defer func() { defer func() {
m.Stop() m.Stop()
os.RemoveAll(tmpDir) testOs.RemoveAll(tmpDir)
os.Remove(w.ConfigPath()) testOs.Remove(w.ConfigPath())
}() }()
parent := "foo" parent := "foo"
@ -637,11 +655,13 @@ func TestRequestSymlinkWindows(t *testing.T) {
t.Skip("windows specific test") t.Skip("windows specific test")
} }
testOs := &fatalOs{t}
m, fc, tmpDir, w := setupModelWithConnection() m, fc, tmpDir, w := setupModelWithConnection()
defer func() { defer func() {
m.Stop() m.Stop()
os.RemoveAll(tmpDir) testOs.RemoveAll(tmpDir)
os.Remove(w.ConfigPath()) testOs.Remove(w.ConfigPath())
}() }()
first := make(chan struct{}) first := make(chan struct{})
@ -724,7 +744,7 @@ func setupModelWithConnectionManual(cfg config.Configuration) (*Model, *fakeConn
} }
func createTmpDir() string { func createTmpDir() string {
tmpDir, err := ioutil.TempDir("testdata", "_request-") tmpDir, err := ioutil.TempDir("", "_request-")
if err != nil { if err != nil {
panic("Failed to create temporary testing dir") panic("Failed to create temporary testing dir")
} }
@ -741,11 +761,13 @@ func equalContents(path string, contents []byte) error {
} }
func TestRequestRemoteRenameChanged(t *testing.T) { func TestRequestRemoteRenameChanged(t *testing.T) {
testOs := &fatalOs{t}
m, fc, tmpDir, w := setupModelWithConnection() m, fc, tmpDir, w := setupModelWithConnection()
defer func() { defer func() {
m.Stop() m.Stop()
os.RemoveAll(tmpDir) testOs.RemoveAll(tmpDir)
os.Remove(w.ConfigPath()) testOs.Remove(w.ConfigPath())
}() }()
tfs := fs.NewFilesystem(fs.FilesystemTypeBasic, tmpDir) tfs := fs.NewFilesystem(fs.FilesystemTypeBasic, tmpDir)
@ -823,11 +845,13 @@ func TestRequestRemoteRenameChanged(t *testing.T) {
} }
func TestRequestRemoteRenameConflict(t *testing.T) { func TestRequestRemoteRenameConflict(t *testing.T) {
testOs := &fatalOs{t}
m, fc, tmpDir, w := setupModelWithConnection() m, fc, tmpDir, w := setupModelWithConnection()
defer func() { defer func() {
m.Stop() m.Stop()
os.RemoveAll(tmpDir) testOs.RemoveAll(tmpDir)
os.Remove(w.ConfigPath()) testOs.Remove(w.ConfigPath())
}() }()
tfs := fs.NewFilesystem(fs.FilesystemTypeBasic, tmpDir) tfs := fs.NewFilesystem(fs.FilesystemTypeBasic, tmpDir)
@ -919,11 +943,13 @@ func TestRequestRemoteRenameConflict(t *testing.T) {
} }
func TestRequestDeleteChanged(t *testing.T) { func TestRequestDeleteChanged(t *testing.T) {
testOs := &fatalOs{t}
m, fc, tmpDir, w := setupModelWithConnection() m, fc, tmpDir, w := setupModelWithConnection()
defer func() { defer func() {
m.Stop() m.Stop()
os.RemoveAll(tmpDir) testOs.RemoveAll(tmpDir)
os.Remove(w.ConfigPath()) testOs.Remove(w.ConfigPath())
}() }()
tfs := fs.NewFilesystem(fs.FilesystemTypeBasic, tmpDir) tfs := fs.NewFilesystem(fs.FilesystemTypeBasic, tmpDir)
@ -967,7 +993,7 @@ func TestRequestDeleteChanged(t *testing.T) {
// Check outcome // Check outcome
if _, err := tfs.Lstat(a); err != nil { if _, err := tfs.Lstat(a); err != nil {
if os.IsNotExist(err) { if fs.IsNotExist(err) {
t.Error(`Modified file "a" was removed`) t.Error(`Modified file "a" was removed`)
} else { } else {
t.Error(`Error stating file "a":`, err) t.Error(`Error stating file "a":`, err)

View File

@ -7,7 +7,6 @@
package model package model
import ( import (
"os"
"testing" "testing"
"github.com/syncthing/syncthing/lib/fs" "github.com/syncthing/syncthing/lib/fs"
@ -16,11 +15,13 @@ import (
// Test creating temporary file inside read-only directory // Test creating temporary file inside read-only directory
func TestReadOnlyDir(t *testing.T) { func TestReadOnlyDir(t *testing.T) {
testOs := &fatalOs{t}
// Create a read only directory, clean it up afterwards. // Create a read only directory, clean it up afterwards.
os.Mkdir("testdata/read_only_dir", 0555) testOs.Mkdir("testdata/read_only_dir", 0555)
defer func() { defer func() {
os.Chmod("testdata/read_only_dir", 0755) testOs.Chmod("testdata/read_only_dir", 0755)
os.RemoveAll("testdata/read_only_dir") testOs.RemoveAll("testdata/read_only_dir")
}() }()
s := sharedPullerState{ s := sharedPullerState{

82
lib/model/testos_test.go Normal file
View File

@ -0,0 +1,82 @@
// Copyright (C) 2019 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
package model
import (
"os"
"time"
)
// fatal is the required common interface between *testing.B and *testing.T
type fatal interface {
Fatal(...interface{})
}
type fatalOs struct {
fatal
}
func (f *fatalOs) must(fn func() error) {
if err := fn(); err != nil {
f.Fatal(err)
}
}
func (f *fatalOs) Chmod(name string, mode os.FileMode) error {
f.must(func() error { return os.Chmod(name, mode) })
return nil
}
func (f *fatalOs) Chtimes(name string, atime time.Time, mtime time.Time) error {
f.must(func() error { return os.Chtimes(name, atime, mtime) })
return nil
}
func (f *fatalOs) Create(name string) (*os.File, error) {
file, err := os.Create(name)
if err != nil {
f.Fatal(err)
}
return file, nil
}
func (f *fatalOs) Mkdir(name string, perm os.FileMode) error {
f.must(func() error { return os.Mkdir(name, perm) })
return nil
}
func (f *fatalOs) MkdirAll(name string, perm os.FileMode) error {
f.must(func() error { return os.MkdirAll(name, perm) })
return nil
}
func (f *fatalOs) Remove(name string) error {
if err := os.Remove(name); err != nil && !os.IsNotExist(err) {
f.Fatal(err)
}
return nil
}
func (f *fatalOs) RemoveAll(name string) error {
if err := os.RemoveAll(name); err != nil && !os.IsNotExist(err) {
f.Fatal(err)
}
return nil
}
func (f *fatalOs) Rename(oldname, newname string) error {
f.must(func() error { return os.Rename(oldname, newname) })
return nil
}
func (f *fatalOs) Stat(name string) (os.FileInfo, error) {
info, err := os.Stat(name)
if err != nil {
f.Fatal(err)
}
return info, nil
}