diff --git a/lib/db/set_test.go b/lib/db/set_test.go index 2a45e19cf..e9563dadc 100644 --- a/lib/db/set_test.go +++ b/lib/db/set_test.go @@ -127,6 +127,14 @@ func (l fileList) String() string { return b.String() } +func setSequence(seq int64, files fileList) int64 { + for i := range files { + seq++ + files[i].Sequence = seq + } + return seq +} + func TestGlobalSet(t *testing.T) { ldb := db.NewLowlevel(backend.OpenMemory()) defer ldb.Close() @@ -134,12 +142,13 @@ func TestGlobalSet(t *testing.T) { m := db.NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), ldb) local0 := fileList{ - protocol.FileInfo{Name: "a", Sequence: 1, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)}, - protocol.FileInfo{Name: "b", Sequence: 2, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(2)}, - protocol.FileInfo{Name: "c", Sequence: 3, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(3)}, - protocol.FileInfo{Name: "d", Sequence: 4, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(4)}, - protocol.FileInfo{Name: "z", Sequence: 5, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(8)}, + protocol.FileInfo{Name: "a", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)}, + protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(2)}, + protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(3)}, + protocol.FileInfo{Name: "d", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(4)}, + protocol.FileInfo{Name: "z", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(8)}, } + localSeq := setSequence(0, local0) local1 := fileList{ protocol.FileInfo{Name: "a", Sequence: 6, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(1)}, protocol.FileInfo{Name: "b", Sequence: 7, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(2)}, @@ -147,6 +156,7 @@ func TestGlobalSet(t *testing.T) { protocol.FileInfo{Name: "d", Sequence: 9, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(4)}, protocol.FileInfo{Name: "z", Sequence: 10, Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1001}}}, Deleted: true}, } + setSequence(localSeq, local1) localTot := fileList{ local1[0], local1[1], @@ -160,10 +170,12 @@ func TestGlobalSet(t *testing.T) { protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(2)}, protocol.FileInfo{Name: "c", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1001}}}, Blocks: genBlocks(5)}, } + remoteSeq := setSequence(0, remote0) remote1 := fileList{ protocol.FileInfo{Name: "b", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1001}}}, Blocks: genBlocks(6)}, protocol.FileInfo{Name: "e", Version: protocol.Vector{Counters: []protocol.Counter{{ID: myID, Value: 1000}}}, Blocks: genBlocks(7)}, } + setSequence(remoteSeq, remote1) remoteTot := fileList{ remote0[0], remote1[0], @@ -195,140 +207,148 @@ func TestGlobalSet(t *testing.T) { replace(m, remoteDevice0, remote0) m.Update(remoteDevice0, remote1) - g := fileList(globalList(m)) - sort.Sort(g) + check := func() { + t.Helper() - if fmt.Sprint(g) != fmt.Sprint(expectedGlobal) { - t.Errorf("Global incorrect;\n A: %v !=\n E: %v", g, expectedGlobal) - } + g := fileList(globalList(m)) + sort.Sort(g) - globalFiles, globalDirectories, globalDeleted, globalBytes := int32(0), int32(0), int32(0), int64(0) - for _, f := range g { - if f.IsInvalid() { - continue + if fmt.Sprint(g) != fmt.Sprint(expectedGlobal) { + t.Errorf("Global incorrect;\n A: %v !=\n E: %v", g, expectedGlobal) } - switch { - case f.IsDeleted(): - globalDeleted++ - case f.IsDirectory(): - globalDirectories++ - default: - globalFiles++ + + globalFiles, globalDirectories, globalDeleted, globalBytes := int32(0), int32(0), int32(0), int64(0) + for _, f := range g { + if f.IsInvalid() { + continue + } + switch { + case f.IsDeleted(): + globalDeleted++ + case f.IsDirectory(): + globalDirectories++ + default: + globalFiles++ + } + globalBytes += f.FileSize() } - globalBytes += f.FileSize() - } - gs := globalSize(m) - if gs.Files != globalFiles { - t.Errorf("Incorrect GlobalSize files; %d != %d", gs.Files, globalFiles) - } - if gs.Directories != globalDirectories { - t.Errorf("Incorrect GlobalSize directories; %d != %d", gs.Directories, globalDirectories) - } - if gs.Deleted != globalDeleted { - t.Errorf("Incorrect GlobalSize deleted; %d != %d", gs.Deleted, globalDeleted) - } - if gs.Bytes != globalBytes { - t.Errorf("Incorrect GlobalSize bytes; %d != %d", gs.Bytes, globalBytes) - } - - h := fileList(haveList(m, protocol.LocalDeviceID)) - sort.Sort(h) - - if fmt.Sprint(h) != fmt.Sprint(localTot) { - t.Errorf("Have incorrect;\n A: %v !=\n E: %v", h, localTot) - } - - haveFiles, haveDirectories, haveDeleted, haveBytes := int32(0), int32(0), int32(0), int64(0) - for _, f := range h { - if f.IsInvalid() { - continue + gs := globalSize(m) + if gs.Files != globalFiles { + t.Errorf("Incorrect GlobalSize files; %d != %d", gs.Files, globalFiles) } - switch { - case f.IsDeleted(): - haveDeleted++ - case f.IsDirectory(): - haveDirectories++ - default: - haveFiles++ + if gs.Directories != globalDirectories { + t.Errorf("Incorrect GlobalSize directories; %d != %d", gs.Directories, globalDirectories) + } + if gs.Deleted != globalDeleted { + t.Errorf("Incorrect GlobalSize deleted; %d != %d", gs.Deleted, globalDeleted) + } + if gs.Bytes != globalBytes { + t.Errorf("Incorrect GlobalSize bytes; %d != %d", gs.Bytes, globalBytes) + } + + h := fileList(haveList(m, protocol.LocalDeviceID)) + sort.Sort(h) + + if fmt.Sprint(h) != fmt.Sprint(localTot) { + t.Errorf("Have incorrect (local);\n A: %v !=\n E: %v", h, localTot) + } + + haveFiles, haveDirectories, haveDeleted, haveBytes := int32(0), int32(0), int32(0), int64(0) + for _, f := range h { + if f.IsInvalid() { + continue + } + switch { + case f.IsDeleted(): + haveDeleted++ + case f.IsDirectory(): + haveDirectories++ + default: + haveFiles++ + } + haveBytes += f.FileSize() + } + ls := localSize(m) + if ls.Files != haveFiles { + t.Errorf("Incorrect LocalSize files; %d != %d", ls.Files, haveFiles) + } + if ls.Directories != haveDirectories { + t.Errorf("Incorrect LocalSize directories; %d != %d", ls.Directories, haveDirectories) + } + if ls.Deleted != haveDeleted { + t.Errorf("Incorrect LocalSize deleted; %d != %d", ls.Deleted, haveDeleted) + } + if ls.Bytes != haveBytes { + t.Errorf("Incorrect LocalSize bytes; %d != %d", ls.Bytes, haveBytes) + } + + h = fileList(haveList(m, remoteDevice0)) + sort.Sort(h) + + if fmt.Sprint(h) != fmt.Sprint(remoteTot) { + t.Errorf("Have incorrect (remote);\n A: %v !=\n E: %v", h, remoteTot) + } + + n := fileList(needList(m, protocol.LocalDeviceID)) + sort.Sort(n) + + if fmt.Sprint(n) != fmt.Sprint(expectedLocalNeed) { + t.Errorf("Need incorrect (local);\n A: %v !=\n E: %v", n, expectedLocalNeed) + } + + n = fileList(needList(m, remoteDevice0)) + sort.Sort(n) + + if fmt.Sprint(n) != fmt.Sprint(expectedRemoteNeed) { + t.Errorf("Need incorrect (remote);\n A: %v !=\n E: %v", n, expectedRemoteNeed) + } + + snap := m.Snapshot() + defer snap.Release() + f, ok := snap.Get(protocol.LocalDeviceID, "b") + if !ok { + t.Error("Unexpectedly not OK") + } + if fmt.Sprint(f) != fmt.Sprint(localTot[1]) { + t.Errorf("Get incorrect;\n A: %v !=\n E: %v", f, localTot[1]) + } + + f, ok = snap.Get(remoteDevice0, "b") + if !ok { + t.Error("Unexpectedly not OK") + } + if fmt.Sprint(f) != fmt.Sprint(remote1[0]) { + t.Errorf("Get incorrect (remote);\n A: %v !=\n E: %v", f, remote1[0]) + } + + f, ok = snap.GetGlobal("b") + if !ok { + t.Error("Unexpectedly not OK") + } + if fmt.Sprint(f) != fmt.Sprint(expectedGlobal[1]) { + t.Errorf("GetGlobal incorrect;\n A: %v !=\n E: %v", f, remote1[0]) + } + + f, ok = snap.Get(protocol.LocalDeviceID, "zz") + if ok { + t.Error("Unexpectedly OK") + } + if f.Name != "" { + t.Errorf("Get incorrect (local);\n A: %v !=\n E: %v", f, protocol.FileInfo{}) + } + + f, ok = snap.GetGlobal("zz") + if ok { + t.Error("Unexpectedly OK") + } + if f.Name != "" { + t.Errorf("GetGlobal incorrect;\n A: %v !=\n E: %v", f, protocol.FileInfo{}) } - haveBytes += f.FileSize() - } - ls := localSize(m) - if ls.Files != haveFiles { - t.Errorf("Incorrect LocalSize files; %d != %d", ls.Files, haveFiles) - } - if ls.Directories != haveDirectories { - t.Errorf("Incorrect LocalSize directories; %d != %d", ls.Directories, haveDirectories) - } - if ls.Deleted != haveDeleted { - t.Errorf("Incorrect LocalSize deleted; %d != %d", ls.Deleted, haveDeleted) - } - if ls.Bytes != haveBytes { - t.Errorf("Incorrect LocalSize bytes; %d != %d", ls.Bytes, haveBytes) } - h = fileList(haveList(m, remoteDevice0)) - sort.Sort(h) - - if fmt.Sprint(h) != fmt.Sprint(remoteTot) { - t.Errorf("Have incorrect;\n A: %v !=\n E: %v", h, remoteTot) - } - - n := fileList(needList(m, protocol.LocalDeviceID)) - sort.Sort(n) - - if fmt.Sprint(n) != fmt.Sprint(expectedLocalNeed) { - t.Errorf("Need incorrect;\n A: %v !=\n E: %v", n, expectedLocalNeed) - } - - n = fileList(needList(m, remoteDevice0)) - sort.Sort(n) - - if fmt.Sprint(n) != fmt.Sprint(expectedRemoteNeed) { - t.Errorf("Need incorrect;\n A: %v !=\n E: %v", n, expectedRemoteNeed) - } + check() snap := m.Snapshot() - defer snap.Release() - f, ok := snap.Get(protocol.LocalDeviceID, "b") - if !ok { - t.Error("Unexpectedly not OK") - } - if fmt.Sprint(f) != fmt.Sprint(localTot[1]) { - t.Errorf("Get incorrect;\n A: %v !=\n E: %v", f, localTot[1]) - } - - f, ok = snap.Get(remoteDevice0, "b") - if !ok { - t.Error("Unexpectedly not OK") - } - if fmt.Sprint(f) != fmt.Sprint(remote1[0]) { - t.Errorf("Get incorrect;\n A: %v !=\n E: %v", f, remote1[0]) - } - - f, ok = snap.GetGlobal("b") - if !ok { - t.Error("Unexpectedly not OK") - } - if fmt.Sprint(f) != fmt.Sprint(remote1[0]) { - t.Errorf("GetGlobal incorrect;\n A: %v !=\n E: %v", f, remote1[0]) - } - - f, ok = snap.Get(protocol.LocalDeviceID, "zz") - if ok { - t.Error("Unexpectedly OK") - } - if f.Name != "" { - t.Errorf("Get incorrect;\n A: %v !=\n E: %v", f, protocol.FileInfo{}) - } - - f, ok = snap.GetGlobal("zz") - if ok { - t.Error("Unexpectedly OK") - } - if f.Name != "" { - t.Errorf("GetGlobal incorrect;\n A: %v !=\n E: %v", f, protocol.FileInfo{}) - } av := []protocol.DeviceID{protocol.LocalDeviceID, remoteDevice0} a := snap.Availability("a") @@ -343,6 +363,70 @@ func TestGlobalSet(t *testing.T) { if len(a) != 1 || a[0] != protocol.LocalDeviceID { t.Errorf("Availability incorrect;\n A: %v !=\n E: %v", a, protocol.LocalDeviceID) } + + snap.Release() + + // Now bring another remote into play + + secRemote := fileList{ + local1[0], // a + remote1[0], // b + local1[3], // d + remote1[1], // e + local1[4], // z + } + secRemote[0].Version = secRemote[0].Version.Update(remoteDevice1.Short()) + secRemote[1].Version = secRemote[1].Version.Update(remoteDevice1.Short()) + secRemote[4].Version = secRemote[4].Version.Update(remoteDevice1.Short()) + secRemote[4].Deleted = false + secRemote[4].Blocks = genBlocks(1) + setSequence(0, secRemote) + + expectedGlobal = fileList{ + secRemote[0], // a + secRemote[1], // b + remote0[2], // c + localTot[3], // d + secRemote[3], // e + secRemote[4], // z + } + + expectedLocalNeed = fileList{ + secRemote[0], // a + secRemote[1], // b + remote0[2], // c + secRemote[3], // e + secRemote[4], // z + } + + expectedRemoteNeed = fileList{ + secRemote[0], // a + secRemote[1], // b + local0[3], // d + secRemote[4], // z + } + + expectedSecRemoteNeed := fileList{ + remote0[2], // c + } + + m.Update(remoteDevice1, secRemote) + + check() + + h := fileList(haveList(m, remoteDevice1)) + sort.Sort(h) + + if fmt.Sprint(h) != fmt.Sprint(secRemote) { + t.Errorf("Have incorrect (secRemote);\n A: %v !=\n E: %v", h, secRemote) + } + + n := fileList(needList(m, remoteDevice1)) + sort.Sort(n) + + if fmt.Sprint(n) != fmt.Sprint(expectedSecRemoteNeed) { + t.Errorf("Need incorrect (secRemote);\n A: %v !=\n E: %v", n, expectedSecRemoteNeed) + } } func TestNeedWithInvalid(t *testing.T) {