mirror of
https://github.com/octoleo/syncthing.git
synced 2025-01-03 07:12:27 +00:00
lib/protocol: Test for IsEquivalent (#4996)
This commit is contained in:
parent
9fc20b41c6
commit
a467f6908c
@ -9,6 +9,7 @@ import (
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"testing/quick"
|
||||
@ -389,3 +390,164 @@ func BenchmarkBlockSize(b *testing.B) {
|
||||
blockSize = BlockSize(16 << 30)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsEquivalent(t *testing.T) {
|
||||
b := func(v bool) *bool {
|
||||
return &v
|
||||
}
|
||||
|
||||
type testCase struct {
|
||||
a FileInfo
|
||||
b FileInfo
|
||||
ignPerms *bool // nil means should not matter, we'll test both variants
|
||||
ignBlocks *bool
|
||||
eq bool
|
||||
}
|
||||
cases := []testCase{
|
||||
// Empty FileInfos are equivalent
|
||||
{eq: true},
|
||||
|
||||
// Various basic attributes, all of which cause ineqality when
|
||||
// they differ
|
||||
{
|
||||
a: FileInfo{Name: "foo"},
|
||||
b: FileInfo{Name: "bar"},
|
||||
eq: false,
|
||||
},
|
||||
{
|
||||
a: FileInfo{Type: FileInfoTypeFile},
|
||||
b: FileInfo{Type: FileInfoTypeDirectory},
|
||||
eq: false,
|
||||
},
|
||||
{
|
||||
a: FileInfo{Size: 1234},
|
||||
b: FileInfo{Size: 2345},
|
||||
eq: false,
|
||||
},
|
||||
{
|
||||
a: FileInfo{Deleted: false},
|
||||
b: FileInfo{Deleted: true},
|
||||
eq: false,
|
||||
},
|
||||
{
|
||||
a: FileInfo{Invalid: false},
|
||||
b: FileInfo{Invalid: true},
|
||||
eq: false,
|
||||
},
|
||||
{
|
||||
a: FileInfo{ModifiedS: 1234},
|
||||
b: FileInfo{ModifiedS: 2345},
|
||||
eq: false,
|
||||
},
|
||||
{
|
||||
a: FileInfo{ModifiedNs: 1234},
|
||||
b: FileInfo{ModifiedNs: 2345},
|
||||
eq: false,
|
||||
},
|
||||
|
||||
// Difference in blocks is not OK
|
||||
{
|
||||
a: FileInfo{Blocks: []BlockInfo{{Hash: []byte{1, 2, 3, 4}}}},
|
||||
b: FileInfo{Blocks: []BlockInfo{{Hash: []byte{2, 3, 4, 5}}}},
|
||||
ignBlocks: b(false),
|
||||
eq: false,
|
||||
},
|
||||
|
||||
// ... unless we say it is
|
||||
{
|
||||
a: FileInfo{Blocks: []BlockInfo{{Hash: []byte{1, 2, 3, 4}}}},
|
||||
b: FileInfo{Blocks: []BlockInfo{{Hash: []byte{2, 3, 4, 5}}}},
|
||||
ignBlocks: b(true),
|
||||
eq: true,
|
||||
},
|
||||
|
||||
// Difference in permissions is not OK.
|
||||
{
|
||||
a: FileInfo{Permissions: 0444},
|
||||
b: FileInfo{Permissions: 0666},
|
||||
ignPerms: b(false),
|
||||
eq: false,
|
||||
},
|
||||
|
||||
// ... unless we say it is
|
||||
{
|
||||
a: FileInfo{Permissions: 0666},
|
||||
b: FileInfo{Permissions: 0444},
|
||||
ignPerms: b(true),
|
||||
eq: true,
|
||||
},
|
||||
|
||||
// These attributes are not checked at all
|
||||
{
|
||||
a: FileInfo{NoPermissions: false},
|
||||
b: FileInfo{NoPermissions: true},
|
||||
eq: true,
|
||||
},
|
||||
{
|
||||
a: FileInfo{Version: Vector{Counters: []Counter{{ID: 1, Value: 42}}}},
|
||||
b: FileInfo{Version: Vector{Counters: []Counter{{ID: 42, Value: 1}}}},
|
||||
eq: true,
|
||||
},
|
||||
{
|
||||
a: FileInfo{Sequence: 1},
|
||||
b: FileInfo{Sequence: 2},
|
||||
eq: true,
|
||||
},
|
||||
|
||||
// The block size is not checked (but this would fail the blocks
|
||||
// check in real world)
|
||||
{
|
||||
a: FileInfo{RawBlockSize: 1},
|
||||
b: FileInfo{RawBlockSize: 2},
|
||||
eq: true,
|
||||
},
|
||||
|
||||
// The symlink target is checked for symlinks
|
||||
{
|
||||
a: FileInfo{Type: FileInfoTypeSymlink, SymlinkTarget: "a"},
|
||||
b: FileInfo{Type: FileInfoTypeSymlink, SymlinkTarget: "b"},
|
||||
eq: false,
|
||||
},
|
||||
|
||||
// ... but not for non-symlinks
|
||||
{
|
||||
a: FileInfo{Type: FileInfoTypeFile, SymlinkTarget: "a"},
|
||||
b: FileInfo{Type: FileInfoTypeFile, SymlinkTarget: "b"},
|
||||
eq: true,
|
||||
},
|
||||
}
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
// On windows we only check the user writable bit of the permission
|
||||
// set, so these are equivalent.
|
||||
cases = append(cases, testCase{
|
||||
a: FileInfo{Permissions: 0777},
|
||||
b: FileInfo{Permissions: 0600},
|
||||
ignPerms: b(false),
|
||||
eq: true,
|
||||
})
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
// Check the standard attributes with all permutations of the
|
||||
// special ignore flags, unless the value of those flags are given
|
||||
// in the tests.
|
||||
for _, ignPerms := range []bool{true, false} {
|
||||
for _, ignBlocks := range []bool{true, false} {
|
||||
if tc.ignPerms != nil && *tc.ignPerms != ignPerms {
|
||||
continue
|
||||
}
|
||||
if tc.ignBlocks != nil && *tc.ignBlocks != ignBlocks {
|
||||
continue
|
||||
}
|
||||
|
||||
if res := tc.a.IsEquivalent(tc.b, ignPerms, ignBlocks); res != tc.eq {
|
||||
t.Errorf("Case %d:\na: %v\nb: %v\na.IsEquivalent(b, %v, %v) => %v, expected %v", i, tc.a, tc.b, ignPerms, ignBlocks, res, tc.eq)
|
||||
}
|
||||
if res := tc.b.IsEquivalent(tc.a, ignPerms, ignBlocks); res != tc.eq {
|
||||
t.Errorf("Case %d:\na: %v\nb: %v\nb.IsEquivalent(a, %v, %v) => %v, expected %v", i, tc.a, tc.b, ignPerms, ignBlocks, res, tc.eq)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user