lib/model: Correct handling of multiple subs when scanning (fixes #2851)

Previously the code failed in that it would return top-level plus a sub,
i.e. ["", "foo"], and it would consider "usr/lib" a prefix of
"usr/libexec" which it is not.
This commit is contained in:
Jakob Borg
2016-03-18 08:28:44 +00:00
committed by Audrius Butkevicius
parent a49b8a2608
commit 2df001fe5c
2 changed files with 135 additions and 22 deletions

View File

@@ -15,10 +15,12 @@ import (
"net"
"os"
"path/filepath"
"runtime"
"strconv"
"testing"
"time"
"github.com/d4l3k/messagediff"
"github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/db"
"github.com/syncthing/syncthing/lib/protocol"
@@ -1210,3 +1212,89 @@ func TestIgnoreDelete(t *testing.T) {
t.Fatal("foo should not be marked for deletion")
}
}
func TestUnifySubs(t *testing.T) {
cases := []struct {
in []string // input to unifySubs
exists []string // paths that exist in the database
out []string // expected output
}{
{
// trailing slashes are cleaned, known paths are just passed on
[]string{"foo/", "bar//"},
[]string{"foo", "bar"},
[]string{"bar", "foo"}, // the output is sorted
},
{
// "foo/bar" gets trimmed as it's covered by foo
[]string{"foo", "bar/", "foo/bar/"},
[]string{"foo", "bar"},
[]string{"bar", "foo"},
},
{
// "bar" gets trimmed to "" as it's unknown,
// "" gets simplified to the empty list
[]string{"foo", "bar", "foo/bar"},
[]string{"foo"},
nil,
},
{
// two independent known paths, both are kept
// "usr/lib" is not a prefix of "usr/libexec"
[]string{"usr/lib", "usr/libexec"},
[]string{"usr/lib", "usr/libexec"},
[]string{"usr/lib", "usr/libexec"},
},
{
// "usr/lib" is a prefix of "usr/lib/exec"
[]string{"usr/lib", "usr/lib/exec"},
[]string{"usr/lib", "usr/libexec"},
[]string{"usr/lib"},
},
{
// .stignore and .stfolder are special and are passed on
// verbatim even though they are unknown
[]string{".stfolder", ".stignore"},
[]string{},
[]string{".stfolder", ".stignore"},
},
{
// but the presense of something else unknown forces an actual
// scan
[]string{".stfolder", ".stignore", "foo/bar"},
[]string{},
nil,
},
}
if runtime.GOOS == "windows" {
// Fixup path separators
for i := range cases {
for j, p := range cases[i].in {
cases[i].in[j] = filepath.FromSlash(p)
}
for j, p := range cases[i].exists {
cases[i].exists[j] = filepath.FromSlash(p)
}
for j, p := range cases[i].out {
cases[i].out[j] = filepath.FromSlash(p)
}
}
}
for i, tc := range cases {
exists := func(f string) bool {
for _, e := range tc.exists {
if f == e {
return true
}
}
return false
}
out := unifySubs(tc.in, exists)
if diff, equal := messagediff.PrettyDiff(tc.out, out); !equal {
t.Errorf("Case %d failed; got %v, expected %v, diff:\n%s", i, out, tc.out, diff)
}
}
}