-
Notifications
You must be signed in to change notification settings - Fork 1
/
simple_test.go
190 lines (171 loc) · 5.46 KB
/
simple_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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
package fsdiffer
import (
"archive/tar"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"strings"
"testing"
"time"
)
const tstprefix = "simplefsdiffer-test"
type buildFileInfo struct {
path string
typeflag byte
size int64
mode os.FileMode
atime time.Time
mtime time.Time
contents string
}
func buildFS(dir string, files []*buildFileInfo) error {
if err := os.MkdirAll(dir, 0755); err != nil {
return err
}
dirs := []*buildFileInfo{}
for _, f := range files {
p := filepath.Join(dir, f.path)
switch f.typeflag {
case tar.TypeDir:
dirs = append(dirs, f)
if err := os.MkdirAll(p, f.mode); err != nil {
return err
}
dir, err := os.Open(p)
if err != nil {
return err
}
if err := dir.Chmod(f.mode); err != nil {
dir.Close()
return err
}
dir.Close()
case tar.TypeReg:
err := ioutil.WriteFile(p, []byte(f.contents), f.mode)
if err != nil {
return err
}
}
if err := os.Chtimes(p, f.atime, f.mtime); err != nil {
return err
}
}
// Restore dirs atime and mtime. This has to be done after extracting
// as a file extraction will change its parent directory's times.
for _, d := range dirs {
p := filepath.Join(dir, d.path)
if err := os.Chtimes(p, d.atime, d.mtime); err != nil {
return err
}
}
defaultTime := time.Unix(0, 0)
// Restore the base dir time as it will be changed by the previous extractions
if err := os.Chtimes(dir, defaultTime, defaultTime); err != nil {
return err
}
return nil
}
func fixeDirTimes(dir string) {
}
// Do not test (at the moment) symlinks as every os needs a special syscall to set symlink times
func TestSimpleFSDiffer(t *testing.T) {
time1 := time.Now()
time2 := time.Now().Add(1 * time.Microsecond)
sourceFiles := []*buildFileInfo{
&buildFileInfo{path: "file01", typeflag: tar.TypeReg, mode: 0644, atime: time1, mtime: time1, contents: "hello"},
&buildFileInfo{path: "dir01", typeflag: tar.TypeDir, mode: 0755, atime: time1, mtime: time1},
&buildFileInfo{path: "dir01/file01", typeflag: tar.TypeReg, mode: 0644, atime: time1, mtime: time1, contents: "hello"},
}
tests := []struct {
sourceFiles []*buildFileInfo
destFiles []*buildFileInfo
expectedChanges FSChangesMap
}{
{
sourceFiles: sourceFiles,
destFiles: []*buildFileInfo{
&buildFileInfo{path: "file01", typeflag: tar.TypeReg, mode: 0644, atime: time1, mtime: time1, contents: "hello"},
&buildFileInfo{path: "dir01", typeflag: tar.TypeDir, mode: 0755, atime: time1, mtime: time1},
&buildFileInfo{path: "dir01/file01", typeflag: tar.TypeReg, mode: 0644, atime: time1, mtime: time1, contents: "hello"},
},
expectedChanges: FSChangesMap{},
},
{
sourceFiles: sourceFiles,
// dir01 mtime changed
destFiles: []*buildFileInfo{
&buildFileInfo{path: "file01", typeflag: tar.TypeReg, mode: 0644, atime: time1, mtime: time1, contents: "hello"},
&buildFileInfo{path: "dir01", typeflag: tar.TypeDir, mode: 0755, atime: time1, mtime: time2},
&buildFileInfo{path: "dir01/file01", typeflag: tar.TypeReg, mode: 0644, atime: time1, mtime: time1, contents: "hello"},
},
expectedChanges: FSChangesMap{"dir01": Modified},
},
{
sourceFiles: sourceFiles,
// file01 contents changed
destFiles: []*buildFileInfo{
&buildFileInfo{path: "file01", typeflag: tar.TypeReg, mode: 0644, atime: time1, mtime: time1, contents: "hellohello"},
&buildFileInfo{path: "dir01", typeflag: tar.TypeDir, mode: 0755, atime: time1, mtime: time1},
&buildFileInfo{path: "dir01/file01", typeflag: tar.TypeReg, mode: 0644, atime: time1, mtime: time1, contents: "hello"},
},
expectedChanges: FSChangesMap{"file01": Modified},
},
{
sourceFiles: sourceFiles,
// new dir and file dir02/file01, dir01/file01 removed
destFiles: []*buildFileInfo{
&buildFileInfo{path: "file01", typeflag: tar.TypeReg, mode: 0644, atime: time1, mtime: time1, contents: "hello"},
&buildFileInfo{path: "dir02", typeflag: tar.TypeDir, mode: 0755, atime: time1, mtime: time1},
&buildFileInfo{path: "dir02/file01", typeflag: tar.TypeReg, mode: 0644, atime: time1, mtime: time1, contents: "hello"},
},
expectedChanges: FSChangesMap{
"dir01": Deleted,
"dir01/file01": Deleted,
"dir02": Added,
"dir02/file01": Added,
},
},
}
dir, err := ioutil.TempDir("", tstprefix)
if err != nil {
t.Fatalf("error creating tempdir: %v", err)
}
defer os.RemoveAll(dir)
sourceDir := filepath.Join(dir, "source")
destDir := filepath.Join(dir, "dest")
for _, tt := range tests {
err = os.RemoveAll(sourceDir)
err = os.RemoveAll(destDir)
err = buildFS(sourceDir, tt.sourceFiles)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
err = buildFS(destDir, tt.destFiles)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
s := NewSimpleFSDiffer(sourceDir, destDir)
changes, err := s.Diff()
changesMap := changes.ToMap()
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if len(changesMap) != len(tt.expectedChanges) {
t.Errorf("wrong changes size: want: %d, got: %d", len(tt.expectedChanges), len(changesMap))
}
if !reflect.DeepEqual(changesMap, tt.expectedChanges) {
t.Errorf("changes differs: want: %q, got: %q", printChanges(tt.expectedChanges), printChanges(changesMap))
}
}
}
func printChanges(changes FSChangesMap) string {
changesStr := make([]string, len(changes))
i := 0
for p, c := range changes {
changesStr[i] = fmt.Sprintf("%s: %d ", p, c)
i++
}
return strings.Join(changesStr, ", ")
}