all: Check files on disk/in db when deleting/renaming (fixes #5194) (#5195)

This commit is contained in:
Simon Frei
2018-09-16 09:48:14 +02:00
committed by Jakob Borg
parent 84494edab4
commit c8652222ef
6 changed files with 385 additions and 45 deletions

View File

@@ -740,3 +740,238 @@ func equalContents(path string, contents []byte) error {
}
return nil
}
func TestRequestRemoteRenameChanged(t *testing.T) {
m, fc, tmpDir, w := setupModelWithConnection()
defer func() {
m.Stop()
os.RemoveAll(tmpDir)
os.Remove(w.ConfigPath())
}()
tfs := fs.NewFilesystem(fs.FilesystemTypeBasic, tmpDir)
done := make(chan struct{})
fc.mut.Lock()
fc.indexFn = func(folder string, fs []protocol.FileInfo) {
if len(fs) != 2 {
t.Fatalf("Received index with %v indexes instead of 2", len(fs))
}
close(done)
}
fc.mut.Unlock()
// setup
a := "a"
b := "b"
data := map[string][]byte{
a: []byte("aData"),
b: []byte("bData"),
}
for _, n := range [2]string{a, b} {
fc.addFile(n, 0644, protocol.FileInfoTypeFile, data[n])
}
fc.sendIndexUpdate()
select {
case <-done:
done = make(chan struct{})
fc.mut.Lock()
fc.indexFn = func(folder string, fs []protocol.FileInfo) {
close(done)
}
fc.mut.Unlock()
case <-time.After(10 * time.Second):
t.Fatal("timed out")
}
for _, n := range [2]string{a, b} {
if err := equalContents(filepath.Join(tmpDir, n), data[n]); err != nil {
t.Fatal(err)
}
}
fd, err := tfs.OpenFile(b, fs.OptReadWrite, 0644)
if err != nil {
t.Fatal(err)
}
otherData := []byte("otherData")
if _, err = fd.Write(otherData); err != nil {
t.Fatal(err)
}
fd.Close()
// rename
fc.deleteFile(a)
fc.updateFile(b, 0644, protocol.FileInfoTypeFile, data[a])
fc.sendIndexUpdate()
select {
case <-done:
case <-time.After(10 * time.Second):
t.Fatal("timed out")
}
// Check outcome
tfs.Walk(".", func(path string, info fs.FileInfo, err error) error {
switch {
case path == a:
t.Errorf(`File "a" was not removed`)
case path == b:
if err := equalContents(filepath.Join(tmpDir, b), otherData); err != nil {
t.Errorf(`Modified file "b" was overwritten`)
}
}
return nil
})
}
func TestRequestRemoteRenameConflict(t *testing.T) {
m, fc, tmpDir, w := setupModelWithConnection()
defer func() {
m.Stop()
os.RemoveAll(tmpDir)
os.Remove(w.ConfigPath())
}()
tfs := fs.NewFilesystem(fs.FilesystemTypeBasic, tmpDir)
recv := make(chan int)
fc.mut.Lock()
fc.indexFn = func(folder string, fs []protocol.FileInfo) {
recv <- len(fs)
}
fc.mut.Unlock()
// setup
a := "a"
b := "b"
data := map[string][]byte{
a: []byte("aData"),
b: []byte("bData"),
}
for _, n := range [2]string{a, b} {
fc.addFile(n, 0644, protocol.FileInfoTypeFile, data[n])
}
fc.sendIndexUpdate()
select {
case i := <-recv:
if i != 2 {
t.Fatalf("received %v items in index, expected 1", i)
}
case <-time.After(10 * time.Second):
t.Fatal("timed out")
}
for _, n := range [2]string{a, b} {
if err := equalContents(filepath.Join(tmpDir, n), data[n]); err != nil {
t.Fatal(err)
}
}
fd, err := tfs.OpenFile(b, fs.OptReadWrite, 0644)
if err != nil {
t.Fatal(err)
}
otherData := []byte("otherData")
if _, err = fd.Write(otherData); err != nil {
t.Fatal(err)
}
fd.Close()
m.ScanFolders()
select {
case i := <-recv:
if i != 1 {
t.Fatalf("received %v items in index, expected 1", i)
}
case <-time.After(10 * time.Second):
t.Fatal("timed out")
}
// make sure the following rename is more recent (not concurrent)
time.Sleep(2 * time.Second)
// rename
fc.deleteFile(a)
fc.updateFile(b, 0644, protocol.FileInfoTypeFile, data[a])
fc.sendIndexUpdate()
select {
case <-recv:
case <-time.After(10 * time.Second):
t.Fatal("timed out")
}
// Check outcome
foundB := false
foundBConfl := false
tfs.Walk(".", func(path string, info fs.FileInfo, err error) error {
switch {
case path == a:
t.Errorf(`File "a" was not removed`)
case path == b:
foundB = true
case strings.HasPrefix(path, b) && strings.Contains(path, ".sync-conflict-"):
foundBConfl = true
}
return nil
})
if !foundB {
t.Errorf(`File "b" was removed`)
}
if !foundBConfl {
t.Errorf(`No conflict file for "b" was created`)
}
}
func TestRequestDeleteChanged(t *testing.T) {
m, fc, tmpDir, w := setupModelWithConnection()
defer func() {
m.Stop()
os.RemoveAll(tmpDir)
os.Remove(w.ConfigPath())
}()
tfs := fs.NewFilesystem(fs.FilesystemTypeBasic, tmpDir)
done := make(chan struct{})
fc.mut.Lock()
fc.indexFn = func(folder string, fs []protocol.FileInfo) {
close(done)
}
fc.mut.Unlock()
// setup
a := "a"
data := []byte("aData")
fc.addFile(a, 0644, protocol.FileInfoTypeFile, data)
fc.sendIndexUpdate()
select {
case <-done:
done = make(chan struct{})
case <-time.After(10 * time.Second):
t.Fatal("timed out")
}
fd, err := tfs.OpenFile(a, fs.OptReadWrite, 0644)
if err != nil {
t.Fatal(err)
}
otherData := []byte("otherData")
if _, err = fd.Write(otherData); err != nil {
t.Fatal(err)
}
fd.Close()
// rename
fc.deleteFile(a)
fc.sendIndexUpdate()
select {
case <-done:
case <-time.After(10 * time.Second):
t.Fatal("timed out")
}
// Check outcome
if _, err := tfs.Lstat(a); err != nil {
if os.IsNotExist(err) {
t.Error(`Modified file "a" was removed`)
} else {
t.Error(`Error stating file "a":`, err)
}
}
}