-
Notifications
You must be signed in to change notification settings - Fork 3
/
sync_test.go
161 lines (147 loc) · 4.45 KB
/
sync_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package fssync
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestMain(m *testing.M) {
err := os.MkdirAll(".tmp", 0700)
if err != nil {
panic(err)
}
defer os.RemoveAll(".tmp")
m.Run()
}
func TestFsSyncer_Sync(t *testing.T) {
tests := map[string]struct {
fixtureSrc string
fixtureDst string
expectedChanges []string
syncOptions []func(*FsSyncer)
additionalSpecs func(t *testing.T, src, dst string)
}{
"it should copy a file": {
fixtureSrc: "src/file",
},
"it should copy a directory": {
fixtureSrc: "src/dir",
},
"it should copy a symlink": {
fixtureSrc: "src/symlink",
},
"it should change target of symlink if relative to src dir": {
fixtureSrc: "src/local-symlink",
},
"it should keep the symlink to a relative path": {
fixtureSrc: "src/relative-symlink",
},
"it should not replace a file with the same content but not the same mtime if checksum checks are enabled": {
fixtureSrc: "src/file",
fixtureDst: "dst/cp-file",
expectedChanges: []string{},
syncOptions: []func(*FsSyncer){WithChecksum},
},
"it should not replace a file with the same size and mtime": {
fixtureSrc: "src/file",
fixtureDst: "dst/rsync-file",
expectedChanges: []string{},
},
"it should replace a file with the same mtime but not the same size": {
fixtureSrc: "src/file",
fixtureDst: "dst/mtime-file",
expectedChanges: []string{"a"},
},
"it should replace a file by a directory": {
fixtureSrc: "src/dir",
fixtureDst: "dst/replace-dir",
expectedChanges: []string{"dir1"},
},
"it should replace a directory by a file": {
fixtureSrc: "src/file",
fixtureDst: "dst/replace-file",
expectedChanges: []string{"a"},
},
"it should delete extraneous files": {
fixtureSrc: "src/file",
fixtureDst: "dst/extraneous-files",
expectedChanges: []string{"b", "dir", "dir/c"},
additionalSpecs: func(t *testing.T, src, dst string) {
_, err := os.Stat(filepath.Join(dst, "b"))
assert.True(t, os.IsNotExist(err))
_, err = os.Stat(filepath.Join(dst, "dir"))
assert.True(t, os.IsNotExist(err))
_, err = os.Stat(filepath.Join(dst, "c"))
assert.True(t, os.IsNotExist(err))
},
},
}
for msg, test := range tests {
t.Run(msg, func(t *testing.T) {
if test.syncOptions == nil {
test.syncOptions = []func(*FsSyncer){}
}
syncer := New(test.syncOptions...)
dst, err := ioutil.TempDir("./.tmp", "fssync-test")
assert.NoError(t, err)
defer assert.NoError(t, os.RemoveAll(dst))
if test.fixtureDst != "" {
fixtureDst := filepath.Join("test-fixtures", test.fixtureDst)
fixtureSyncer := New()
_, err := fixtureSyncer.Sync(dst, fixtureDst)
if err != nil {
assert.NoError(t, err)
}
}
src := filepath.Join("test-fixtures", test.fixtureSrc)
report, err := syncer.Sync(dst, src)
assert.NoError(t, err)
if test.expectedChanges != nil {
// Check that if there is no change expected, there should be no change in report
if len(test.expectedChanges) == 0 {
assert.Equal(t, report.ChangeCount(), 0)
}
for _, path := range test.expectedChanges {
t.Run(fmt.Sprintf("file %s has changed", path), func(t *testing.T) {
assert.True(t, report.HasChanged(filepath.Join(dst, path)))
})
}
}
err = filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
t.Run("with file "+path, func(t *testing.T) {
dstPath := strings.Replace(path, src, dst, 1)
dstStat, err := os.Lstat(dstPath)
assert.NoError(t, err)
assert.Equal(t, info.IsDir(), dstStat.IsDir())
assert.Equal(t, info.Mode(), dstStat.Mode())
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
srcLink, err := os.Readlink(path)
assert.NoError(t, err)
dstLink, err := os.Readlink(dstPath)
assert.NoError(t, err)
// If link is mentioning src path, replace it with dst
expectedLink := srcLink
if strings.Contains(expectedLink, src) {
expectedLink = strings.Replace(dstLink, src, dst, 1)
}
assert.Equal(t, expectedLink, dstLink)
} else {
assert.Equal(t, info.Size(), dstStat.Size())
assert.Equal(t, info.ModTime(), dstStat.ModTime())
}
})
return nil
})
assert.NoError(t, err)
if test.additionalSpecs != nil {
test.additionalSpecs(t, src, dst)
}
})
}
}