123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- // Copyright (C) 2018 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 (
- "path/filepath"
- "testing"
- "github.com/d4l3k/messagediff"
- "github.com/syncthing/syncthing/lib/build"
- "github.com/syncthing/syncthing/lib/config"
- "github.com/syncthing/syncthing/lib/fs"
- "github.com/syncthing/syncthing/lib/protocol"
- "github.com/syncthing/syncthing/lib/rand"
- )
- type unifySubsCase struct {
- in []string // input to unifySubs
- exists []string // paths that exist in the database
- out []string // expected output
- }
- func unifySubsCases() []unifySubsCase {
- cases := []unifySubsCase{
- {
- // 0. trailing slashes are cleaned, known paths are just passed on
- []string{"foo/", "bar//"},
- []string{"foo", "bar"},
- []string{"bar", "foo"}, // the output is sorted
- },
- {
- // 1. "foo/bar" gets trimmed as it's covered by foo
- []string{"foo", "bar/", "foo/bar/"},
- []string{"foo", "bar"},
- []string{"bar", "foo"},
- },
- {
- // 2. "" gets simplified to the empty list; ie scan all
- []string{"foo", ""},
- []string{"foo"},
- nil,
- },
- {
- // 3. "foo/bar" is unknown, but it's kept
- // because its parent is known
- []string{"foo/bar"},
- []string{"foo"},
- []string{"foo/bar"},
- },
- {
- // 4. two independent known paths, both are kept
- // "usr/lib" is not a prefix of "usr/libexec"
- []string{"usr/lib", "usr/libexec"},
- []string{"usr", "usr/lib", "usr/libexec"},
- []string{"usr/lib", "usr/libexec"},
- },
- {
- // 5. "usr/lib" is a prefix of "usr/lib/exec"
- []string{"usr/lib", "usr/lib/exec"},
- []string{"usr", "usr/lib", "usr/libexec"},
- []string{"usr/lib"},
- },
- {
- // 6. .stignore and .stfolder are special and are passed on
- // verbatim even though they are unknown
- []string{config.DefaultMarkerName, ".stignore"},
- []string{},
- []string{config.DefaultMarkerName, ".stignore"},
- },
- {
- // 7. but the presence of something else unknown forces an actual
- // scan
- []string{config.DefaultMarkerName, ".stignore", "foo/bar"},
- []string{},
- []string{config.DefaultMarkerName, ".stignore", "foo"},
- },
- {
- // 8. explicit request to scan all
- nil,
- []string{"foo"},
- nil,
- },
- {
- // 9. empty list of subs
- []string{},
- []string{"foo"},
- nil,
- },
- {
- // 10. absolute path
- []string{"/foo"},
- []string{"foo"},
- []string{"foo"},
- },
- }
- if build.IsWindows {
- // 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)
- }
- }
- }
- return cases
- }
- func unifyExists(f string, tc unifySubsCase) bool {
- for _, e := range tc.exists {
- if f == e {
- return true
- }
- }
- return false
- }
- func TestUnifySubs(t *testing.T) {
- cases := unifySubsCases()
- for i, tc := range cases {
- exists := func(f string) bool {
- return unifyExists(f, tc)
- }
- 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)
- }
- }
- }
- func BenchmarkUnifySubs(b *testing.B) {
- cases := unifySubsCases()
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- for _, tc := range cases {
- exists := func(f string) bool {
- return unifyExists(f, tc)
- }
- unifySubs(tc.in, exists)
- }
- }
- }
- func TestSetPlatformData(t *testing.T) {
- // Checks that setPlatformData runs without error when applied to a temp
- // file, named differently than the given FileInfo.
- fs := fs.NewFilesystem(fs.FilesystemTypeFake, rand.String(32))
- if fd, err := fs.Create("file.tmp"); err != nil {
- t.Fatal(err)
- } else {
- fd.Close()
- }
- xattr := []protocol.Xattr{{Name: "user.foo", Value: []byte("bar")}}
- fi := &protocol.FileInfo{
- Name: "should be ignored",
- Permissions: 0o400,
- ModifiedS: 1234567890,
- Platform: protocol.PlatformData{
- Linux: &protocol.XattrData{Xattrs: xattr},
- Darwin: &protocol.XattrData{Xattrs: xattr},
- FreeBSD: &protocol.XattrData{Xattrs: xattr},
- NetBSD: &protocol.XattrData{Xattrs: xattr},
- },
- }
- // Minimum required to support setPlatformData
- sr := &sendReceiveFolder{
- folder: folder{
- FolderConfiguration: config.FolderConfiguration{
- SyncXattrs: true,
- },
- mtimefs: fs,
- },
- }
- if err := sr.setPlatformData(fi, "file.tmp"); err != nil {
- t.Error(err)
- }
- }
|