walk_test.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
  2. // All rights reserved. Use of this source code is governed by an MIT-style
  3. // license that can be found in the LICENSE file.
  4. package scanner
  5. import (
  6. "bytes"
  7. "fmt"
  8. "path/filepath"
  9. "reflect"
  10. "sort"
  11. "testing"
  12. "github.com/syncthing/syncthing/protocol"
  13. )
  14. type testfile struct {
  15. name string
  16. size int
  17. hash string
  18. }
  19. type testfileList []testfile
  20. var testdata = testfileList{
  21. {"afile", 4, "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c"},
  22. {"dir1", 128, ""},
  23. {"dir1/dfile", 5, "49ae93732fcf8d63fe1cce759664982dbd5b23161f007dba8561862adc96d063"},
  24. {"dir2", 128, ""},
  25. {"dir2/cfile", 4, "bf07a7fbb825fc0aae7bf4a1177b2b31fcf8a3feeaf7092761e18c859ee52a9c"},
  26. {"excludes", 78, "1f5ac95d9e6fb2516629a029d788d27953c7bb2f4dc09184b660fdda0c8f2f04"},
  27. {"further-excludes", 5, "7eb0a548094fa6295f7fd9200d69973e5f5ec5c04f2a86d998080ac43ecf89f1"},
  28. {"loop-excludes", 18, "2db057aa82a8b8fe4b1367ccc875259ed4b8020255820d4e3d4bfe78f0dd3f2a"},
  29. }
  30. var correctIgnores = map[string][]string{
  31. ".": {".*", "quux"},
  32. }
  33. func TestWalkSub(t *testing.T) {
  34. w := Walker{
  35. Dir: "testdata",
  36. Sub: "dir2",
  37. BlockSize: 128 * 1024,
  38. IgnoreFile: ".stignore",
  39. }
  40. fchan, err := w.Walk()
  41. var files []protocol.FileInfo
  42. for f := range fchan {
  43. files = append(files, f)
  44. }
  45. if err != nil {
  46. t.Fatal(err)
  47. }
  48. // The directory contains two files, where one is ignored from a higher
  49. // level. We should see only the directory and one of the files.
  50. if len(files) != 2 {
  51. t.Fatalf("Incorrect length %d != 2", len(files))
  52. }
  53. if files[0].Name != "dir2" {
  54. t.Errorf("Incorrect file %v != dir2", files[0])
  55. }
  56. if files[1].Name != "dir2/cfile" {
  57. t.Errorf("Incorrect file %v != dir2/cfile", files[1])
  58. }
  59. }
  60. func TestWalk(t *testing.T) {
  61. w := Walker{
  62. Dir: "testdata",
  63. BlockSize: 128 * 1024,
  64. IgnoreFile: ".stignore",
  65. }
  66. fchan, err := w.Walk()
  67. if err != nil {
  68. t.Fatal(err)
  69. }
  70. var tmp []protocol.FileInfo
  71. for f := range fchan {
  72. tmp = append(tmp, f)
  73. }
  74. sort.Sort(fileList(tmp))
  75. files := fileList(tmp).testfiles()
  76. if !reflect.DeepEqual(files, testdata) {
  77. t.Errorf("Walk returned unexpected data\nExpected: %v\nActual: %v", testdata, files)
  78. }
  79. }
  80. func TestWalkError(t *testing.T) {
  81. w := Walker{
  82. Dir: "testdata-missing",
  83. BlockSize: 128 * 1024,
  84. IgnoreFile: ".stignore",
  85. }
  86. _, err := w.Walk()
  87. if err == nil {
  88. t.Error("no error from missing directory")
  89. }
  90. w = Walker{
  91. Dir: "testdata/bar",
  92. BlockSize: 128 * 1024,
  93. IgnoreFile: ".stignore",
  94. }
  95. _, err = w.Walk()
  96. if err == nil {
  97. t.Error("no error from non-directory")
  98. }
  99. }
  100. func TestIgnore(t *testing.T) {
  101. patStr := bytes.NewBufferString(`
  102. t2
  103. /t3
  104. sub/dir/*
  105. */other/test
  106. **/deep
  107. `)
  108. patterns := parseIgnoreFile(patStr, "", "")
  109. patStr = bytes.NewBufferString(`
  110. bar
  111. z*
  112. q[abc]x
  113. `)
  114. patterns = append(patterns, parseIgnoreFile(patStr, "foo", "")...)
  115. patStr = bytes.NewBufferString(`
  116. quux
  117. .*
  118. `)
  119. patterns = append(patterns, parseIgnoreFile(patStr, "foo/baz", "")...)
  120. var tests = []struct {
  121. f string
  122. r bool
  123. }{
  124. {filepath.Join("foo", "bar"), true},
  125. {filepath.Join("t3"), true},
  126. {filepath.Join("foofoo"), false},
  127. {filepath.Join("foo", "quux"), false},
  128. {filepath.Join("foo", "zuux"), true},
  129. {filepath.Join("foo", "qzuux"), false},
  130. {filepath.Join("foo", "baz", "t1"), false},
  131. {filepath.Join("foo", "baz", "t2"), true},
  132. {filepath.Join("foo", "baz", "t3"), false},
  133. {filepath.Join("foo", "baz", "bar"), true},
  134. {filepath.Join("foo", "baz", "quuxa"), false},
  135. {filepath.Join("foo", "baz", "aquux"), false},
  136. {filepath.Join("foo", "baz", ".quux"), true},
  137. {filepath.Join("foo", "baz", "zquux"), true},
  138. {filepath.Join("foo", "baz", "quux"), true},
  139. {filepath.Join("foo", "bazz", "quux"), false},
  140. {filepath.Join("sub", "dir", "hej"), true},
  141. {filepath.Join("deeper", "sub", "dir", "hej"), true},
  142. {filepath.Join("other", "test"), false},
  143. {filepath.Join("sub", "other", "test"), true},
  144. {filepath.Join("deeper", "sub", "other", "test"), true},
  145. {filepath.Join("deep"), true},
  146. {filepath.Join("deeper", "deep"), true},
  147. {filepath.Join("deeper", "deeper", "deep"), true},
  148. }
  149. w := Walker{}
  150. for i, tc := range tests {
  151. if r := w.ignoreFile(patterns, tc.f); r != tc.r {
  152. t.Errorf("Incorrect ignoreFile() #%d (%s); E: %v, A: %v", i, tc.f, tc.r, r)
  153. }
  154. }
  155. }
  156. type fileList []protocol.FileInfo
  157. func (f fileList) Len() int {
  158. return len(f)
  159. }
  160. func (f fileList) Less(a, b int) bool {
  161. return f[a].Name < f[b].Name
  162. }
  163. func (f fileList) Swap(a, b int) {
  164. f[a], f[b] = f[b], f[a]
  165. }
  166. func (l fileList) testfiles() testfileList {
  167. testfiles := make(testfileList, len(l))
  168. for i, f := range l {
  169. if len(f.Blocks) > 1 {
  170. panic("simple test case stuff only supports a single block per file")
  171. }
  172. testfiles[i] = testfile{name: f.Name, size: int(f.Size())}
  173. if len(f.Blocks) == 1 {
  174. testfiles[i].hash = fmt.Sprintf("%x", f.Blocks[0].Hash)
  175. }
  176. }
  177. return testfiles
  178. }
  179. func (l testfileList) String() string {
  180. var b bytes.Buffer
  181. b.WriteString("{\n")
  182. for _, f := range l {
  183. fmt.Fprintf(&b, " %s (%d bytes): %s\n", f.name, f.size, f.hash)
  184. }
  185. b.WriteString("}")
  186. return b.String()
  187. }