Switch the database from LevelDB to SQLite, for greater stability and simpler code. Co-authored-by: Tommy van der Vorst <tommy@pixelspark.nl> Co-authored-by: bt90 <btom1990@googlemail.com>
This commit is contained in:
co-authored by
Tommy van der Vorst
bt90
parent
b1c8f88a44
commit
025905fcdf
+132
-218
@@ -13,6 +13,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"iter"
|
||||
mrand "math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -24,10 +25,10 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/internal/db"
|
||||
"github.com/syncthing/syncthing/internal/itererr"
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/db/backend"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/ignore"
|
||||
@@ -77,7 +78,7 @@ func addFolderDevicesToClusterConfig(cc *protocol.ClusterConfig, remote protocol
|
||||
|
||||
func TestRequest(t *testing.T) {
|
||||
wrapper, fcfg, cancel := newDefaultCfgWrapper()
|
||||
ffs := fcfg.Filesystem(nil)
|
||||
ffs := fcfg.Filesystem()
|
||||
defer cancel()
|
||||
m := setupModel(t, wrapper)
|
||||
defer cleanupModel(m)
|
||||
@@ -165,7 +166,7 @@ func BenchmarkIndex_100(b *testing.B) {
|
||||
func benchmarkIndex(b *testing.B, nfiles int) {
|
||||
m, _, fcfg, wcfgCancel := setupModelWithConnection(b)
|
||||
defer wcfgCancel()
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem(nil).URI())
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem().URI())
|
||||
|
||||
files := genFiles(nfiles)
|
||||
must(b, m.Index(device1Conn, &protocol.Index{Folder: fcfg.ID, Files: files}))
|
||||
@@ -192,7 +193,7 @@ func BenchmarkIndexUpdate_10000_1(b *testing.B) {
|
||||
func benchmarkIndexUpdate(b *testing.B, nfiles, nufiles int) {
|
||||
m, _, fcfg, wcfgCancel := setupModelWithConnection(b)
|
||||
defer wcfgCancel()
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem(nil).URI())
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem().URI())
|
||||
|
||||
files := genFiles(nfiles)
|
||||
ufiles := genFiles(nufiles)
|
||||
@@ -235,7 +236,7 @@ func BenchmarkRequestOut(b *testing.B) {
|
||||
func BenchmarkRequestInSingleFile(b *testing.B) {
|
||||
w, cancel := newConfigWrapper(defaultCfg)
|
||||
defer cancel()
|
||||
ffs := w.FolderList()[0].Filesystem(nil)
|
||||
ffs := w.FolderList()[0].Filesystem()
|
||||
m := setupModel(b, w)
|
||||
defer cleanupModel(m)
|
||||
|
||||
@@ -1195,7 +1196,7 @@ func TestAutoAcceptPrefersLabel(t *testing.T) {
|
||||
func TestAutoAcceptFallsBackToID(t *testing.T) {
|
||||
// Prefers label, falls back to ID.
|
||||
m, cancel := newState(t, defaultAutoAcceptCfg)
|
||||
ffs := defaultFolderConfig.Filesystem(nil)
|
||||
ffs := defaultFolderConfig.Filesystem()
|
||||
id := srand.String(8)
|
||||
label := srand.String(8)
|
||||
if err := ffs.MkdirAll(label, 0o777); err != nil {
|
||||
@@ -1488,7 +1489,7 @@ func changeIgnores(t *testing.T, m *testModel, expected []string) {
|
||||
func TestIgnores(t *testing.T) {
|
||||
w, cancel := newConfigWrapper(defaultCfg)
|
||||
defer cancel()
|
||||
ffs := w.FolderList()[0].Filesystem(nil)
|
||||
ffs := w.FolderList()[0].Filesystem()
|
||||
m := setupModel(t, w)
|
||||
defer cleanupModel(m)
|
||||
|
||||
@@ -1523,7 +1524,7 @@ func TestIgnores(t *testing.T) {
|
||||
ID: "fresh", Path: "XXX",
|
||||
FilesystemType: config.FilesystemTypeFake,
|
||||
}
|
||||
ignores := ignore.New(fcfg.Filesystem(nil), ignore.WithCache(m.cfg.Options().CacheIgnoredFiles))
|
||||
ignores := ignore.New(fcfg.Filesystem(), ignore.WithCache(m.cfg.Options().CacheIgnoredFiles))
|
||||
m.mut.Lock()
|
||||
m.folderCfgs[fcfg.ID] = fcfg
|
||||
m.folderIgnores[fcfg.ID] = ignores
|
||||
@@ -1555,7 +1556,7 @@ func TestIgnores(t *testing.T) {
|
||||
func TestEmptyIgnores(t *testing.T) {
|
||||
w, cancel := newConfigWrapper(defaultCfg)
|
||||
defer cancel()
|
||||
ffs := w.FolderList()[0].Filesystem(nil)
|
||||
ffs := w.FolderList()[0].Filesystem()
|
||||
m := setupModel(t, w)
|
||||
defer cleanupModel(m)
|
||||
|
||||
@@ -1628,12 +1629,11 @@ func TestROScanRecovery(t *testing.T) {
|
||||
defer cancel()
|
||||
m := newModel(t, cfg, myID, nil)
|
||||
|
||||
set := newFileSet(t, "default", m.db)
|
||||
set.Update(protocol.LocalDeviceID, []protocol.FileInfo{
|
||||
m.sdb.Update("default", protocol.LocalDeviceID, []protocol.FileInfo{
|
||||
{Name: "dummyfile", Version: protocol.Vector{Counters: []protocol.Counter{{ID: 42, Value: 1}}}},
|
||||
})
|
||||
|
||||
ffs := fcfg.Filesystem(nil)
|
||||
ffs := fcfg.Filesystem()
|
||||
|
||||
// Remove marker to generate an error
|
||||
ffs.Remove(fcfg.MarkerName)
|
||||
@@ -1675,12 +1675,11 @@ func TestRWScanRecovery(t *testing.T) {
|
||||
defer cancel()
|
||||
m := newModel(t, cfg, myID, nil)
|
||||
|
||||
set := newFileSet(t, "default", m.db)
|
||||
set.Update(protocol.LocalDeviceID, []protocol.FileInfo{
|
||||
m.sdb.Update("default", protocol.LocalDeviceID, []protocol.FileInfo{
|
||||
{Name: "dummyfile", Version: protocol.Vector{Counters: []protocol.Counter{{ID: 42, Value: 1}}}},
|
||||
})
|
||||
|
||||
ffs := fcfg.Filesystem(nil)
|
||||
ffs := fcfg.Filesystem()
|
||||
|
||||
// Generate error
|
||||
if err := ffs.Remove(config.DefaultMarkerName); err != nil {
|
||||
@@ -1706,8 +1705,9 @@ func TestRWScanRecovery(t *testing.T) {
|
||||
func TestGlobalDirectoryTree(t *testing.T) {
|
||||
m, conn, fcfg, wCancel := setupModelWithConnection(t)
|
||||
defer wCancel()
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem(nil).URI())
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem().URI())
|
||||
|
||||
var seq int64
|
||||
b := func(isfile bool, path ...string) protocol.FileInfo {
|
||||
typ := protocol.FileInfoTypeDirectory
|
||||
var blocks []protocol.BlockInfo
|
||||
@@ -1716,12 +1716,14 @@ func TestGlobalDirectoryTree(t *testing.T) {
|
||||
typ = protocol.FileInfoTypeFile
|
||||
blocks = []protocol.BlockInfo{{Offset: 0x0, Size: 0xa, Hash: []uint8{0x2f, 0x72, 0xcc, 0x11, 0xa6, 0xfc, 0xd0, 0x27, 0x1e, 0xce, 0xf8, 0xc6, 0x10, 0x56, 0xee, 0x1e, 0xb1, 0x24, 0x3b, 0xe3, 0x80, 0x5b, 0xf9, 0xa9, 0xdf, 0x98, 0xf9, 0x2f, 0x76, 0x36, 0xb0, 0x5c}}}
|
||||
}
|
||||
seq++
|
||||
return protocol.FileInfo{
|
||||
Name: filepath.Join(path...),
|
||||
Type: typ,
|
||||
ModifiedS: 0x666,
|
||||
Blocks: blocks,
|
||||
Size: 0xa,
|
||||
Sequence: seq,
|
||||
}
|
||||
}
|
||||
f := func(name string) *TreeEntry {
|
||||
@@ -1813,13 +1815,13 @@ func TestGlobalDirectoryTree(t *testing.T) {
|
||||
result, _ := m.GlobalDirectoryTree("default", "", -1, false)
|
||||
|
||||
if mm(result) != mm(expectedResult) {
|
||||
t.Errorf("Does not match:\n%s\n============\n%s", mm(result), mm(expectedResult))
|
||||
t.Fatalf("Does not match:\n%s\n============\n%s", mm(result), mm(expectedResult))
|
||||
}
|
||||
|
||||
result, _ = m.GlobalDirectoryTree("default", "another", -1, false)
|
||||
|
||||
if mm(result) != mm(findByName(expectedResult, "another").Children) {
|
||||
t.Errorf("Does not match:\n%s\n============\n%s", mm(result), mm(findByName(expectedResult, "another").Children))
|
||||
t.Fatalf("Does not match:\n%s\n============\n%s", mm(result), mm(findByName(expectedResult, "another").Children))
|
||||
}
|
||||
|
||||
result, _ = m.GlobalDirectoryTree("default", "", 0, false)
|
||||
@@ -1831,7 +1833,7 @@ func TestGlobalDirectoryTree(t *testing.T) {
|
||||
}
|
||||
|
||||
if mm(result) != mm(currentResult) {
|
||||
t.Errorf("Does not match:\n%s\n============\n%s", mm(result), mm(currentResult))
|
||||
t.Fatalf("Does not match:\n%s\n============\n%s", mm(result), mm(currentResult))
|
||||
}
|
||||
|
||||
result, _ = m.GlobalDirectoryTree("default", "", 1, false)
|
||||
@@ -1852,7 +1854,7 @@ func TestGlobalDirectoryTree(t *testing.T) {
|
||||
}
|
||||
|
||||
if mm(result) != mm(currentResult) {
|
||||
t.Errorf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
t.Fatalf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
}
|
||||
|
||||
result, _ = m.GlobalDirectoryTree("default", "", -1, true)
|
||||
@@ -1882,7 +1884,7 @@ func TestGlobalDirectoryTree(t *testing.T) {
|
||||
}
|
||||
|
||||
if mm(result) != mm(currentResult) {
|
||||
t.Errorf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
t.Fatalf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
}
|
||||
|
||||
result, _ = m.GlobalDirectoryTree("default", "", 1, true)
|
||||
@@ -1901,7 +1903,7 @@ func TestGlobalDirectoryTree(t *testing.T) {
|
||||
}
|
||||
|
||||
if mm(result) != mm(currentResult) {
|
||||
t.Errorf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
t.Fatalf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
}
|
||||
|
||||
result, _ = m.GlobalDirectoryTree("default", "another", 0, false)
|
||||
@@ -1911,7 +1913,7 @@ func TestGlobalDirectoryTree(t *testing.T) {
|
||||
}
|
||||
|
||||
if mm(result) != mm(currentResult) {
|
||||
t.Errorf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
t.Fatalf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
}
|
||||
|
||||
result, _ = m.GlobalDirectoryTree("default", "some/directory", 0, false)
|
||||
@@ -1920,7 +1922,7 @@ func TestGlobalDirectoryTree(t *testing.T) {
|
||||
}
|
||||
|
||||
if mm(result) != mm(currentResult) {
|
||||
t.Errorf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
t.Fatalf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
}
|
||||
|
||||
result, _ = m.GlobalDirectoryTree("default", "some/directory", 1, false)
|
||||
@@ -1931,7 +1933,7 @@ func TestGlobalDirectoryTree(t *testing.T) {
|
||||
}
|
||||
|
||||
if mm(result) != mm(currentResult) {
|
||||
t.Errorf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
t.Fatalf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
}
|
||||
|
||||
result, _ = m.GlobalDirectoryTree("default", "some/directory", 2, false)
|
||||
@@ -1944,7 +1946,7 @@ func TestGlobalDirectoryTree(t *testing.T) {
|
||||
}
|
||||
|
||||
if mm(result) != mm(currentResult) {
|
||||
t.Errorf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
t.Fatalf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
}
|
||||
|
||||
result, _ = m.GlobalDirectoryTree("default", "another", -1, true)
|
||||
@@ -1957,7 +1959,7 @@ func TestGlobalDirectoryTree(t *testing.T) {
|
||||
}
|
||||
|
||||
if mm(result) != mm(currentResult) {
|
||||
t.Errorf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
t.Fatalf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
}
|
||||
|
||||
// No prefix matching!
|
||||
@@ -1965,7 +1967,7 @@ func TestGlobalDirectoryTree(t *testing.T) {
|
||||
currentResult = []*TreeEntry{}
|
||||
|
||||
if mm(result) != mm(currentResult) {
|
||||
t.Errorf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
t.Fatalf("Does not match:\n%s\n%s", mm(result), mm(currentResult))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2010,7 +2012,7 @@ func BenchmarkTree_100_10(b *testing.B) {
|
||||
func benchmarkTree(b *testing.B, n1, n2 int) {
|
||||
m, _, fcfg, wcfgCancel := setupModelWithConnection(b)
|
||||
defer wcfgCancel()
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem(nil).URI())
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem().URI())
|
||||
|
||||
m.ScanFolder(fcfg.ID)
|
||||
files := genDeepFiles(n1, n2)
|
||||
@@ -2027,7 +2029,7 @@ func benchmarkTree(b *testing.B, n1, n2 int) {
|
||||
func TestIssue3028(t *testing.T) {
|
||||
w, cancel := newConfigWrapper(defaultCfg)
|
||||
defer cancel()
|
||||
ffs := w.FolderList()[0].Filesystem(nil)
|
||||
ffs := w.FolderList()[0].Filesystem()
|
||||
m := setupModel(t, w)
|
||||
defer cleanupModel(m)
|
||||
|
||||
@@ -2039,8 +2041,8 @@ func TestIssue3028(t *testing.T) {
|
||||
// Scan, and get a count of how many files are there now
|
||||
|
||||
m.ScanFolderSubdirs("default", []string{"testrm", "testrm2"})
|
||||
locorigfiles := localSize(t, m, "default").Files
|
||||
globorigfiles := globalSize(t, m, "default").Files
|
||||
locorigfiles := mustV(m.LocalSize("default", protocol.LocalDeviceID)).Files
|
||||
globorigfiles := mustV(m.GlobalSize("default")).Files
|
||||
|
||||
// Delete
|
||||
|
||||
@@ -2051,8 +2053,8 @@ func TestIssue3028(t *testing.T) {
|
||||
// deleted files increases by two
|
||||
|
||||
m.ScanFolderSubdirs("default", []string{"testrm", "testrm2"})
|
||||
loc := localSize(t, m, "default")
|
||||
glob := globalSize(t, m, "default")
|
||||
loc := mustV(m.LocalSize("default", protocol.LocalDeviceID))
|
||||
glob := mustV(m.GlobalSize("default"))
|
||||
|
||||
if loc.Files != locorigfiles-2 {
|
||||
t.Errorf("Incorrect local accounting; got %d current files, expected %d", loc.Files, locorigfiles-2)
|
||||
@@ -2127,24 +2129,22 @@ func TestIssue4357(t *testing.T) {
|
||||
func TestIndexesForUnknownDevicesDropped(t *testing.T) {
|
||||
m := newModel(t, defaultCfgWrapper, myID, nil)
|
||||
|
||||
files := newFileSet(t, "default", m.db)
|
||||
files.Drop(device1)
|
||||
files.Update(device1, genFiles(1))
|
||||
files.Drop(device2)
|
||||
files.Update(device2, genFiles(1))
|
||||
m.sdb.DropAllFiles("default", device1)
|
||||
m.sdb.Update("default", device1, genFiles(1))
|
||||
m.sdb.DropAllFiles("default", device2)
|
||||
m.sdb.Update("default", device2, genFiles(1))
|
||||
|
||||
if len(files.ListDevices()) != 2 {
|
||||
if devs, err := m.sdb.ListDevicesForFolder("default"); err != nil || len(devs) != 2 {
|
||||
t.Log(devs, err)
|
||||
t.Error("expected two devices")
|
||||
}
|
||||
|
||||
m.newFolder(defaultFolderConfig, false)
|
||||
defer cleanupModel(m)
|
||||
|
||||
// Remote sequence is cached, hence need to recreated.
|
||||
files = newFileSet(t, "default", m.db)
|
||||
|
||||
if l := len(files.ListDevices()); l != 1 {
|
||||
t.Errorf("Expected one device got %v", l)
|
||||
if devs, err := m.sdb.ListDevicesForFolder("default"); err != nil || len(devs) != 1 {
|
||||
t.Log(devs, err)
|
||||
t.Error("expected one device")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2270,7 +2270,7 @@ func TestIssue3829(t *testing.T) {
|
||||
func TestIssue4573(t *testing.T) {
|
||||
w, fcfg, wCancel := newDefaultCfgWrapper()
|
||||
defer wCancel()
|
||||
testFs := fcfg.Filesystem(nil)
|
||||
testFs := fcfg.Filesystem()
|
||||
defer os.RemoveAll(testFs.URI())
|
||||
|
||||
must(t, testFs.MkdirAll("inaccessible", 0o755))
|
||||
@@ -2300,7 +2300,7 @@ func TestIssue4573(t *testing.T) {
|
||||
func TestInternalScan(t *testing.T) {
|
||||
w, fcfg, wCancel := newDefaultCfgWrapper()
|
||||
defer wCancel()
|
||||
testFs := fcfg.Filesystem(nil)
|
||||
testFs := fcfg.Filesystem()
|
||||
defer os.RemoveAll(testFs.URI())
|
||||
|
||||
testCases := map[string]func(protocol.FileInfo) bool{
|
||||
@@ -2372,12 +2372,11 @@ func TestCustomMarkerName(t *testing.T) {
|
||||
})
|
||||
defer cancel()
|
||||
|
||||
ffs := fcfg.Filesystem(nil)
|
||||
ffs := fcfg.Filesystem()
|
||||
|
||||
m := newModel(t, cfg, myID, nil)
|
||||
|
||||
set := newFileSet(t, "default", m.db)
|
||||
set.Update(protocol.LocalDeviceID, []protocol.FileInfo{
|
||||
m.sdb.Update("default", protocol.LocalDeviceID, []protocol.FileInfo{
|
||||
{Name: "dummyfile"},
|
||||
})
|
||||
|
||||
@@ -2401,7 +2400,7 @@ func TestCustomMarkerName(t *testing.T) {
|
||||
func TestRemoveDirWithContent(t *testing.T) {
|
||||
m, conn, fcfg, wcfgCancel := setupModelWithConnection(t)
|
||||
defer wcfgCancel()
|
||||
tfs := fcfg.Filesystem(nil)
|
||||
tfs := fcfg.Filesystem()
|
||||
defer cleanupModelAndRemoveDir(m, tfs.URI())
|
||||
|
||||
tfs.MkdirAll("dirwith", 0o755)
|
||||
@@ -2463,7 +2462,7 @@ func TestIssue4475(t *testing.T) {
|
||||
m, conn, fcfg, wcfgCancel := setupModelWithConnection(t)
|
||||
defer wcfgCancel()
|
||||
defer cleanupModel(m)
|
||||
testFs := fcfg.Filesystem(nil)
|
||||
testFs := fcfg.Filesystem()
|
||||
|
||||
// Scenario: Dir is deleted locally and before syncing/index exchange
|
||||
// happens, a file is create in that dir on the remote.
|
||||
@@ -2525,7 +2524,7 @@ func TestVersionRestore(t *testing.T) {
|
||||
fcfg := newFolderConfiguration(defaultCfgWrapper, "default", "default", config.FilesystemTypeFake, srand.String(32))
|
||||
fcfg.Versioning.Type = "simple"
|
||||
fcfg.FSWatcherEnabled = false
|
||||
filesystem := fcfg.Filesystem(nil)
|
||||
filesystem := fcfg.Filesystem()
|
||||
|
||||
rawConfig := config.Configuration{
|
||||
Version: config.CurrentVersion,
|
||||
@@ -2759,7 +2758,7 @@ func TestIssue4094(t *testing.T) {
|
||||
t.Fatalf("failed setting ignores: %v", err)
|
||||
}
|
||||
|
||||
if _, err := fcfg.Filesystem(nil).Lstat(".stignore"); err != nil {
|
||||
if _, err := fcfg.Filesystem().Lstat(".stignore"); err != nil {
|
||||
t.Fatalf("failed stating .stignore: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -2788,7 +2787,7 @@ func TestIssue4903(t *testing.T) {
|
||||
t.Fatalf("expected path missing error, got: %v, debug: %s", err, fcfg.CheckPath())
|
||||
}
|
||||
|
||||
if _, err := fcfg.Filesystem(nil).Lstat("."); !fs.IsNotExist(err) {
|
||||
if _, err := fcfg.Filesystem().Lstat("."); !fs.IsNotExist(err) {
|
||||
t.Fatalf("Expected missing path error, got: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -2798,7 +2797,7 @@ func TestIssue5002(t *testing.T) {
|
||||
|
||||
w, fcfg, wCancel := newDefaultCfgWrapper()
|
||||
defer wCancel()
|
||||
ffs := fcfg.Filesystem(nil)
|
||||
ffs := fcfg.Filesystem()
|
||||
|
||||
fd, err := ffs.Create("foo")
|
||||
must(t, err)
|
||||
@@ -2827,7 +2826,7 @@ func TestIssue5002(t *testing.T) {
|
||||
func TestParentOfUnignored(t *testing.T) {
|
||||
w, fcfg, wCancel := newDefaultCfgWrapper()
|
||||
defer wCancel()
|
||||
ffs := fcfg.Filesystem(nil)
|
||||
ffs := fcfg.Filesystem()
|
||||
|
||||
must(t, ffs.Mkdir("bar", 0o755))
|
||||
must(t, ffs.Mkdir("baz", 0o755))
|
||||
@@ -2906,7 +2905,7 @@ func TestFolderRestartZombies(t *testing.T) {
|
||||
|
||||
func TestRequestLimit(t *testing.T) {
|
||||
wrapper, fcfg, cancel := newDefaultCfgWrapper()
|
||||
ffs := fcfg.Filesystem(nil)
|
||||
ffs := fcfg.Filesystem()
|
||||
|
||||
file := "tmpfile"
|
||||
fd, err := ffs.Create(file)
|
||||
@@ -2966,7 +2965,7 @@ func TestConnCloseOnRestart(t *testing.T) {
|
||||
w, fcfg, wCancel := newDefaultCfgWrapper()
|
||||
defer wCancel()
|
||||
m := setupModel(t, w)
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem(nil).URI())
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem().URI())
|
||||
|
||||
br := &testutil.BlockingRW{}
|
||||
nw := &testutil.NoopRW{}
|
||||
@@ -3009,7 +3008,7 @@ func TestModTimeWindow(t *testing.T) {
|
||||
defer wCancel()
|
||||
tfs := modtimeTruncatingFS{
|
||||
trunc: 0,
|
||||
Filesystem: fcfg.Filesystem(nil),
|
||||
Filesystem: fcfg.Filesystem(),
|
||||
}
|
||||
// fcfg.RawModTimeWindowS = 2
|
||||
setFolder(t, w, fcfg)
|
||||
@@ -3069,7 +3068,7 @@ func TestModTimeWindow(t *testing.T) {
|
||||
func TestDevicePause(t *testing.T) {
|
||||
m, _, fcfg, wcfgCancel := setupModelWithConnection(t)
|
||||
defer wcfgCancel()
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem(nil).URI())
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem().URI())
|
||||
|
||||
sub := m.evLogger.Subscribe(events.DevicePaused)
|
||||
defer sub.Unsubscribe()
|
||||
@@ -3099,7 +3098,7 @@ func TestDevicePause(t *testing.T) {
|
||||
func TestDeviceWasSeen(t *testing.T) {
|
||||
m, _, fcfg, wcfgCancel := setupModelWithConnection(t)
|
||||
defer wcfgCancel()
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem(nil).URI())
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem().URI())
|
||||
|
||||
m.deviceWasSeen(device1)
|
||||
|
||||
@@ -3194,7 +3193,7 @@ func TestRenameSequenceOrder(t *testing.T) {
|
||||
|
||||
numFiles := 20
|
||||
|
||||
ffs := fcfg.Filesystem(nil)
|
||||
ffs := fcfg.Filesystem()
|
||||
for i := 0; i < numFiles; i++ {
|
||||
v := fmt.Sprintf("%d", i)
|
||||
writeFile(t, ffs, v, []byte(v))
|
||||
@@ -3202,14 +3201,7 @@ func TestRenameSequenceOrder(t *testing.T) {
|
||||
|
||||
m.ScanFolders()
|
||||
|
||||
count := 0
|
||||
snap := dbSnapshot(t, m, "default")
|
||||
snap.WithHave(protocol.LocalDeviceID, func(i protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
snap.Release()
|
||||
|
||||
count := countIterator[protocol.FileInfo](t)(m.LocalFiles("default", protocol.LocalDeviceID))
|
||||
if count != numFiles {
|
||||
t.Errorf("Unexpected count: %d != %d", count, numFiles)
|
||||
}
|
||||
@@ -3229,14 +3221,11 @@ func TestRenameSequenceOrder(t *testing.T) {
|
||||
// Scan
|
||||
m.ScanFolders()
|
||||
|
||||
// Verify sequence of a appearing is followed by c disappearing.
|
||||
snap = dbSnapshot(t, m, "default")
|
||||
defer snap.Release()
|
||||
|
||||
var firstExpectedSequence int64
|
||||
var secondExpectedSequence int64
|
||||
failed := false
|
||||
snap.WithHaveSequence(0, func(i protocol.FileInfo) bool {
|
||||
it, errFn := m.LocalFilesSequenced("default", protocol.LocalDeviceID, 0)
|
||||
for i := range it {
|
||||
t.Log(i)
|
||||
if i.FileName() == "17" {
|
||||
firstExpectedSequence = i.SequenceNo() + 1
|
||||
@@ -3250,8 +3239,10 @@ func TestRenameSequenceOrder(t *testing.T) {
|
||||
if i.FileName() == "16" {
|
||||
failed = i.SequenceNo() != secondExpectedSequence || failed
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
if err := errFn(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if failed {
|
||||
t.Fail()
|
||||
}
|
||||
@@ -3263,19 +3254,12 @@ func TestRenameSameFile(t *testing.T) {
|
||||
m := setupModel(t, wcfg)
|
||||
defer cleanupModel(m)
|
||||
|
||||
ffs := fcfg.Filesystem(nil)
|
||||
ffs := fcfg.Filesystem()
|
||||
writeFile(t, ffs, "file", []byte("file"))
|
||||
|
||||
m.ScanFolders()
|
||||
|
||||
count := 0
|
||||
snap := dbSnapshot(t, m, "default")
|
||||
snap.WithHave(protocol.LocalDeviceID, func(i protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
snap.Release()
|
||||
|
||||
count := countIterator[protocol.FileInfo](t)(m.LocalFiles("default", protocol.LocalDeviceID))
|
||||
if count != 1 {
|
||||
t.Errorf("Unexpected count: %d != %d", count, 1)
|
||||
}
|
||||
@@ -3288,12 +3272,10 @@ func TestRenameSameFile(t *testing.T) {
|
||||
|
||||
m.ScanFolders()
|
||||
|
||||
snap = dbSnapshot(t, m, "default")
|
||||
defer snap.Release()
|
||||
|
||||
prevSeq := int64(0)
|
||||
seen := false
|
||||
snap.WithHaveSequence(0, func(i protocol.FileInfo) bool {
|
||||
it, errFn := m.LocalFilesSequenced("default", protocol.LocalDeviceID, 0)
|
||||
for i := range it {
|
||||
if i.SequenceNo() <= prevSeq {
|
||||
t.Fatalf("non-increasing sequences: %d <= %d", i.SequenceNo(), prevSeq)
|
||||
}
|
||||
@@ -3304,84 +3286,9 @@ func TestRenameSameFile(t *testing.T) {
|
||||
seen = true
|
||||
}
|
||||
prevSeq = i.SequenceNo()
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func TestRenameEmptyFile(t *testing.T) {
|
||||
wcfg, fcfg, wcfgCancel := newDefaultCfgWrapper()
|
||||
defer wcfgCancel()
|
||||
m := setupModel(t, wcfg)
|
||||
defer cleanupModel(m)
|
||||
|
||||
ffs := fcfg.Filesystem(nil)
|
||||
|
||||
writeFile(t, ffs, "file", []byte("data"))
|
||||
writeFile(t, ffs, "empty", nil)
|
||||
|
||||
m.ScanFolders()
|
||||
|
||||
snap := dbSnapshot(t, m, "default")
|
||||
defer snap.Release()
|
||||
empty, eok := snap.Get(protocol.LocalDeviceID, "empty")
|
||||
if !eok {
|
||||
t.Fatal("failed to find empty file")
|
||||
}
|
||||
file, fok := snap.Get(protocol.LocalDeviceID, "file")
|
||||
if !fok {
|
||||
t.Fatal("failed to find non-empty file")
|
||||
}
|
||||
|
||||
count := 0
|
||||
snap.WithBlocksHash(empty.BlocksHash, func(_ protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
|
||||
if count != 0 {
|
||||
t.Fatalf("Found %d entries for empty file, expected 0", count)
|
||||
}
|
||||
|
||||
count = 0
|
||||
snap.WithBlocksHash(file.BlocksHash, func(_ protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
|
||||
if count != 1 {
|
||||
t.Fatalf("Found %d entries for non-empty file, expected 1", count)
|
||||
}
|
||||
|
||||
must(t, ffs.Rename("file", "new-file"))
|
||||
must(t, ffs.Rename("empty", "new-empty"))
|
||||
|
||||
// Scan
|
||||
m.ScanFolders()
|
||||
|
||||
snap = dbSnapshot(t, m, "default")
|
||||
defer snap.Release()
|
||||
|
||||
count = 0
|
||||
snap.WithBlocksHash(empty.BlocksHash, func(_ protocol.FileInfo) bool {
|
||||
count++
|
||||
return true
|
||||
})
|
||||
|
||||
if count != 0 {
|
||||
t.Fatalf("Found %d entries for empty file, expected 0", count)
|
||||
}
|
||||
|
||||
count = 0
|
||||
snap.WithBlocksHash(file.BlocksHash, func(i protocol.FileInfo) bool {
|
||||
count++
|
||||
if i.FileName() != "new-file" {
|
||||
t.Fatalf("unexpected file name %s, expected new-file", i.FileName())
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
if count != 1 {
|
||||
t.Fatalf("Found %d entries for non-empty file, expected 1", count)
|
||||
if err := errFn(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3391,7 +3298,7 @@ func TestBlockListMap(t *testing.T) {
|
||||
m := setupModel(t, wcfg)
|
||||
defer cleanupModel(m)
|
||||
|
||||
ffs := fcfg.Filesystem(nil)
|
||||
ffs := fcfg.Filesystem()
|
||||
writeFile(t, ffs, "one", []byte("content"))
|
||||
writeFile(t, ffs, "two", []byte("content"))
|
||||
writeFile(t, ffs, "three", []byte("content"))
|
||||
@@ -3400,23 +3307,25 @@ func TestBlockListMap(t *testing.T) {
|
||||
|
||||
m.ScanFolders()
|
||||
|
||||
snap := dbSnapshot(t, m, "default")
|
||||
defer snap.Release()
|
||||
fi, ok := snap.Get(protocol.LocalDeviceID, "one")
|
||||
fi, ok, err := m.model.CurrentFolderFile("default", "one")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !ok {
|
||||
t.Error("failed to find existing file")
|
||||
}
|
||||
var paths []string
|
||||
|
||||
snap.WithBlocksHash(fi.BlocksHash, func(fi protocol.FileInfo) bool {
|
||||
paths = append(paths, fi.FileName())
|
||||
return true
|
||||
})
|
||||
snap.Release()
|
||||
for fi, err := range itererr.Zip(m.model.AllForBlocksHash(fcfg.ID, fi.BlocksHash)) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
paths = append(paths, fi.Name)
|
||||
}
|
||||
|
||||
expected := []string{"one", "two", "three", "four", "five"}
|
||||
if !equalStringsInAnyOrder(paths, expected) {
|
||||
t.Errorf("expected %q got %q", expected, paths)
|
||||
t.Fatalf("expected %q got %q", expected, paths)
|
||||
}
|
||||
|
||||
// Fudge the files around
|
||||
@@ -3437,19 +3346,18 @@ func TestBlockListMap(t *testing.T) {
|
||||
m.ScanFolders()
|
||||
|
||||
// Check we're left with 2 of the 5
|
||||
snap = dbSnapshot(t, m, "default")
|
||||
defer snap.Release()
|
||||
|
||||
paths = paths[:0]
|
||||
snap.WithBlocksHash(fi.BlocksHash, func(fi protocol.FileInfo) bool {
|
||||
paths = append(paths, fi.FileName())
|
||||
return true
|
||||
})
|
||||
snap.Release()
|
||||
for fi, err := range itererr.Zip(m.model.AllForBlocksHash(fcfg.ID, fi.BlocksHash)) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
paths = append(paths, fi.Name)
|
||||
}
|
||||
|
||||
expected = []string{"new-three", "five"}
|
||||
if !equalStringsInAnyOrder(paths, expected) {
|
||||
t.Errorf("expected %q got %q", expected, paths)
|
||||
t.Fatalf("expected %q got %q", expected, paths)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3459,16 +3367,17 @@ func TestScanRenameCaseOnly(t *testing.T) {
|
||||
m := setupModel(t, wcfg)
|
||||
defer cleanupModel(m)
|
||||
|
||||
ffs := fcfg.Filesystem(nil)
|
||||
ffs := fcfg.Filesystem()
|
||||
name := "foo"
|
||||
writeFile(t, ffs, name, []byte("contents"))
|
||||
|
||||
m.ScanFolders()
|
||||
|
||||
snap := dbSnapshot(t, m, fcfg.ID)
|
||||
defer snap.Release()
|
||||
found := false
|
||||
snap.WithHave(protocol.LocalDeviceID, func(i protocol.FileInfo) bool {
|
||||
for i, err := range itererr.Zip(m.LocalFiles(fcfg.ID, protocol.LocalDeviceID)) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if found {
|
||||
t.Fatal("got more than one file")
|
||||
}
|
||||
@@ -3476,21 +3385,20 @@ func TestScanRenameCaseOnly(t *testing.T) {
|
||||
t.Fatalf("got file %v, expected %v", i.FileName(), name)
|
||||
}
|
||||
found = true
|
||||
return true
|
||||
})
|
||||
snap.Release()
|
||||
}
|
||||
|
||||
upper := strings.ToUpper(name)
|
||||
must(t, ffs.Rename(name, upper))
|
||||
m.ScanFolders()
|
||||
|
||||
snap = dbSnapshot(t, m, fcfg.ID)
|
||||
defer snap.Release()
|
||||
found = false
|
||||
snap.WithHave(protocol.LocalDeviceID, func(i protocol.FileInfo) bool {
|
||||
for i, err := range itererr.Zip(m.LocalFiles(fcfg.ID, protocol.LocalDeviceID)) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i.FileName() == name {
|
||||
if i.IsDeleted() {
|
||||
return true
|
||||
continue
|
||||
}
|
||||
t.Fatal("renamed file not deleted")
|
||||
}
|
||||
@@ -3501,8 +3409,7 @@ func TestScanRenameCaseOnly(t *testing.T) {
|
||||
t.Fatal("got more than the expected files")
|
||||
}
|
||||
found = true
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestClusterConfigOnFolderAdd(t *testing.T) {
|
||||
@@ -3577,7 +3484,7 @@ func TestAddFolderCompletion(t *testing.T) {
|
||||
|
||||
func TestScanDeletedROChangedOnSR(t *testing.T) {
|
||||
m, conn, fcfg, wCancel := setupModelWithConnection(t)
|
||||
ffs := fcfg.Filesystem(nil)
|
||||
ffs := fcfg.Filesystem()
|
||||
defer wCancel()
|
||||
defer cleanupModelAndRemoveDir(m, ffs.URI())
|
||||
fcfg.Type = config.FolderTypeReceiveOnly
|
||||
@@ -3599,7 +3506,7 @@ func TestScanDeletedROChangedOnSR(t *testing.T) {
|
||||
must(t, ffs.Remove(name))
|
||||
m.ScanFolders()
|
||||
|
||||
if receiveOnlyChangedSize(t, m, fcfg.ID).Deleted != 1 {
|
||||
if mustV(m.ReceiveOnlySize(fcfg.ID)).Deleted != 1 {
|
||||
t.Fatal("expected one receive only changed deleted item")
|
||||
}
|
||||
|
||||
@@ -3607,10 +3514,10 @@ func TestScanDeletedROChangedOnSR(t *testing.T) {
|
||||
setFolder(t, m.cfg, fcfg)
|
||||
m.ScanFolders()
|
||||
|
||||
if receiveOnlyChangedSize(t, m, fcfg.ID).Deleted != 0 {
|
||||
if mustV(m.ReceiveOnlySize(fcfg.ID)).Deleted != 0 {
|
||||
t.Fatal("expected no receive only changed deleted item")
|
||||
}
|
||||
if localSize(t, m, fcfg.ID).Deleted != 1 {
|
||||
if mustV(m.LocalSize(fcfg.ID, protocol.LocalDeviceID)).Deleted != 1 {
|
||||
t.Fatal("expected one local deleted item")
|
||||
}
|
||||
}
|
||||
@@ -3682,7 +3589,7 @@ func testConfigChangeTriggersClusterConfigs(t *testing.T, expectFirst, expectSec
|
||||
func TestIssue6961(t *testing.T) {
|
||||
wcfg, fcfg, wcfgCancel := newDefaultCfgWrapper()
|
||||
defer wcfgCancel()
|
||||
tfs := fcfg.Filesystem(nil)
|
||||
tfs := fcfg.Filesystem()
|
||||
waiter, err := wcfg.Modify(func(cfg *config.Configuration) {
|
||||
cfg.SetDevice(newDeviceConfiguration(cfg.Defaults.Device, device2, "device2"))
|
||||
fcfg.Type = config.FolderTypeReceiveOnly
|
||||
@@ -3693,11 +3600,6 @@ func TestIssue6961(t *testing.T) {
|
||||
waiter.Wait()
|
||||
// Always recalc/repair when opening a fileset.
|
||||
m := newModel(t, wcfg, myID, nil)
|
||||
m.db.Close()
|
||||
m.db, err = db.NewLowlevel(backend.OpenMemory(), m.evLogger, db.WithRecheckInterval(time.Millisecond))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.ServeBackground()
|
||||
defer cleanupModelAndRemoveDir(m, tfs.URI())
|
||||
conn1 := addFakeConn(m, device1, fcfg.ID)
|
||||
@@ -3752,11 +3654,9 @@ func TestIssue6961(t *testing.T) {
|
||||
func TestCompletionEmptyGlobal(t *testing.T) {
|
||||
m, conn, fcfg, wcfgCancel := setupModelWithConnection(t)
|
||||
defer wcfgCancel()
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem(nil).URI())
|
||||
defer cleanupModelAndRemoveDir(m, fcfg.Filesystem().URI())
|
||||
files := []protocol.FileInfo{{Name: "foo", Version: protocol.Vector{}.Update(myID.Short()), Sequence: 1}}
|
||||
m.mut.Lock()
|
||||
m.folderFiles[fcfg.ID].Update(protocol.LocalDeviceID, files)
|
||||
m.mut.Unlock()
|
||||
m.sdb.Update(fcfg.ID, protocol.LocalDeviceID, files)
|
||||
files[0].Deleted = true
|
||||
files[0].Version = files[0].Version.Update(device1.Short())
|
||||
must(t, m.IndexUpdate(conn, &protocol.IndexUpdate{Folder: fcfg.ID, Files: files}))
|
||||
@@ -3953,7 +3853,7 @@ func TestCCFolderNotRunning(t *testing.T) {
|
||||
// Create the folder, but don't start it.
|
||||
w, fcfg, wCancel := newDefaultCfgWrapper()
|
||||
defer wCancel()
|
||||
tfs := fcfg.Filesystem(nil)
|
||||
tfs := fcfg.Filesystem()
|
||||
m := newModel(t, w, myID, nil)
|
||||
defer cleanupModelAndRemoveDir(m, tfs.URI())
|
||||
|
||||
@@ -3990,7 +3890,7 @@ func TestPendingFolder(t *testing.T) {
|
||||
Time: time.Now().Truncate(time.Second),
|
||||
Label: pfolder,
|
||||
}
|
||||
if err := m.db.AddOrUpdatePendingFolder(pfolder, of, device2); err != nil {
|
||||
if err := m.observed.AddOrUpdatePendingFolder(pfolder, of, device2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
deviceFolders, err := m.PendingFolders(protocol.EmptyDeviceID)
|
||||
@@ -4009,7 +3909,7 @@ func TestPendingFolder(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
setDevice(t, w, config.DeviceConfiguration{DeviceID: device3})
|
||||
if err := m.db.AddOrUpdatePendingFolder(pfolder, of, device3); err != nil {
|
||||
if err := m.observed.AddOrUpdatePendingFolder(pfolder, of, device3); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
deviceFolders, err = m.PendingFolders(device2)
|
||||
@@ -4060,7 +3960,7 @@ func TestDeletedNotLocallyChangedReceiveEncrypted(t *testing.T) {
|
||||
|
||||
func deletedNotLocallyChanged(t *testing.T, ft config.FolderType) {
|
||||
w, fcfg, wCancel := newDefaultCfgWrapper()
|
||||
tfs := fcfg.Filesystem(nil)
|
||||
tfs := fcfg.Filesystem()
|
||||
fcfg.Type = ft
|
||||
setFolder(t, w, fcfg)
|
||||
defer wCancel()
|
||||
@@ -4141,3 +4041,17 @@ type modtimeTruncatingFileInfo struct {
|
||||
func (fi modtimeTruncatingFileInfo) ModTime() time.Time {
|
||||
return fi.FileInfo.ModTime().Truncate(fi.trunc)
|
||||
}
|
||||
|
||||
func countIterator[T any](t *testing.T) func(it iter.Seq[T], errFn func() error) int {
|
||||
return func(it iter.Seq[T], errFn func() error) int {
|
||||
t.Helper()
|
||||
count := 0
|
||||
for range it {
|
||||
count++
|
||||
}
|
||||
if err := errFn(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return count
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user