file_test.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. // Copyright 2014 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package webdav
  5. import (
  6. "fmt"
  7. "io"
  8. "io/ioutil"
  9. "os"
  10. "path/filepath"
  11. "strconv"
  12. "strings"
  13. "testing"
  14. )
  15. func TestDir(t *testing.T) {
  16. testCases := []struct {
  17. dir, name, want string
  18. }{
  19. {"/", "", "/"},
  20. {"/", "/", "/"},
  21. {"/", ".", "/"},
  22. {"/", "./a", "/a"},
  23. {"/", "..", "/"},
  24. {"/", "..", "/"},
  25. {"/", "../", "/"},
  26. {"/", "../.", "/"},
  27. {"/", "../a", "/a"},
  28. {"/", "../..", "/"},
  29. {"/", "../bar/a", "/bar/a"},
  30. {"/", "../baz/a", "/baz/a"},
  31. {"/", "...", "/..."},
  32. {"/", ".../a", "/.../a"},
  33. {"/", ".../..", "/"},
  34. {"/", "a", "/a"},
  35. {"/", "a/./b", "/a/b"},
  36. {"/", "a/../../b", "/b"},
  37. {"/", "a/../b", "/b"},
  38. {"/", "a/b", "/a/b"},
  39. {"/", "a/b/c/../../d", "/a/d"},
  40. {"/", "a/b/c/../../../d", "/d"},
  41. {"/", "a/b/c/../../../../d", "/d"},
  42. {"/", "a/b/c/d", "/a/b/c/d"},
  43. {"/foo/bar", "", "/foo/bar"},
  44. {"/foo/bar", "/", "/foo/bar"},
  45. {"/foo/bar", ".", "/foo/bar"},
  46. {"/foo/bar", "./a", "/foo/bar/a"},
  47. {"/foo/bar", "..", "/foo/bar"},
  48. {"/foo/bar", "../", "/foo/bar"},
  49. {"/foo/bar", "../.", "/foo/bar"},
  50. {"/foo/bar", "../a", "/foo/bar/a"},
  51. {"/foo/bar", "../..", "/foo/bar"},
  52. {"/foo/bar", "../bar/a", "/foo/bar/bar/a"},
  53. {"/foo/bar", "../baz/a", "/foo/bar/baz/a"},
  54. {"/foo/bar", "...", "/foo/bar/..."},
  55. {"/foo/bar", ".../a", "/foo/bar/.../a"},
  56. {"/foo/bar", ".../..", "/foo/bar"},
  57. {"/foo/bar", "a", "/foo/bar/a"},
  58. {"/foo/bar", "a/./b", "/foo/bar/a/b"},
  59. {"/foo/bar", "a/../../b", "/foo/bar/b"},
  60. {"/foo/bar", "a/../b", "/foo/bar/b"},
  61. {"/foo/bar", "a/b", "/foo/bar/a/b"},
  62. {"/foo/bar", "a/b/c/../../d", "/foo/bar/a/d"},
  63. {"/foo/bar", "a/b/c/../../../d", "/foo/bar/d"},
  64. {"/foo/bar", "a/b/c/../../../../d", "/foo/bar/d"},
  65. {"/foo/bar", "a/b/c/d", "/foo/bar/a/b/c/d"},
  66. {"/foo/bar/", "", "/foo/bar"},
  67. {"/foo/bar/", "/", "/foo/bar"},
  68. {"/foo/bar/", ".", "/foo/bar"},
  69. {"/foo/bar/", "./a", "/foo/bar/a"},
  70. {"/foo/bar/", "..", "/foo/bar"},
  71. {"/foo//bar///", "", "/foo/bar"},
  72. {"/foo//bar///", "/", "/foo/bar"},
  73. {"/foo//bar///", ".", "/foo/bar"},
  74. {"/foo//bar///", "./a", "/foo/bar/a"},
  75. {"/foo//bar///", "..", "/foo/bar"},
  76. {"/x/y/z", "ab/c\x00d/ef", ""},
  77. {".", "", "."},
  78. {".", "/", "."},
  79. {".", ".", "."},
  80. {".", "./a", "a"},
  81. {".", "..", "."},
  82. {".", "..", "."},
  83. {".", "../", "."},
  84. {".", "../.", "."},
  85. {".", "../a", "a"},
  86. {".", "../..", "."},
  87. {".", "../bar/a", "bar/a"},
  88. {".", "../baz/a", "baz/a"},
  89. {".", "...", "..."},
  90. {".", ".../a", ".../a"},
  91. {".", ".../..", "."},
  92. {".", "a", "a"},
  93. {".", "a/./b", "a/b"},
  94. {".", "a/../../b", "b"},
  95. {".", "a/../b", "b"},
  96. {".", "a/b", "a/b"},
  97. {".", "a/b/c/../../d", "a/d"},
  98. {".", "a/b/c/../../../d", "d"},
  99. {".", "a/b/c/../../../../d", "d"},
  100. {".", "a/b/c/d", "a/b/c/d"},
  101. {"", "", "."},
  102. {"", "/", "."},
  103. {"", ".", "."},
  104. {"", "./a", "a"},
  105. {"", "..", "."},
  106. }
  107. for _, tc := range testCases {
  108. d := Dir(filepath.FromSlash(tc.dir))
  109. if got := filepath.ToSlash(d.resolve(tc.name)); got != tc.want {
  110. t.Errorf("dir=%q, name=%q: got %q, want %q", tc.dir, tc.name, got, tc.want)
  111. }
  112. }
  113. }
  114. func TestWalk(t *testing.T) {
  115. type walkStep struct {
  116. name, frag string
  117. final bool
  118. }
  119. testCases := []struct {
  120. dir string
  121. want []walkStep
  122. }{
  123. {"", []walkStep{
  124. {"", "", true},
  125. }},
  126. {"/", []walkStep{
  127. {"", "", true},
  128. }},
  129. {"/a", []walkStep{
  130. {"", "a", true},
  131. }},
  132. {"/a/", []walkStep{
  133. {"", "a", true},
  134. }},
  135. {"/a/b", []walkStep{
  136. {"", "a", false},
  137. {"a", "b", true},
  138. }},
  139. {"/a/b/", []walkStep{
  140. {"", "a", false},
  141. {"a", "b", true},
  142. }},
  143. {"/a/b/c", []walkStep{
  144. {"", "a", false},
  145. {"a", "b", false},
  146. {"b", "c", true},
  147. }},
  148. // The following test case is the one mentioned explicitly
  149. // in the method description.
  150. {"/foo/bar/x", []walkStep{
  151. {"", "foo", false},
  152. {"foo", "bar", false},
  153. {"bar", "x", true},
  154. }},
  155. }
  156. for _, tc := range testCases {
  157. fs := NewMemFS().(*memFS)
  158. parts := strings.Split(tc.dir, "/")
  159. for p := 2; p < len(parts); p++ {
  160. d := strings.Join(parts[:p], "/")
  161. if err := fs.Mkdir(d, 0666); err != nil {
  162. t.Errorf("tc.dir=%q: mkdir: %q: %v", tc.dir, d, err)
  163. }
  164. }
  165. i := 0
  166. err := fs.walk("test", tc.dir, func(dir *memFSNode, frag string, final bool) error {
  167. got := walkStep{
  168. name: dir.name,
  169. frag: frag,
  170. final: final,
  171. }
  172. want := tc.want[i]
  173. if got != want {
  174. return fmt.Errorf("got %+v, want %+v", got, want)
  175. }
  176. i++
  177. return nil
  178. })
  179. if err != nil {
  180. t.Errorf("tc.dir=%q: %v", tc.dir, err)
  181. }
  182. }
  183. }
  184. func TestMemFile(t *testing.T) {
  185. testCases := []string{
  186. "wantData ",
  187. "wantSize 0",
  188. "write abc",
  189. "wantData abc",
  190. "write de",
  191. "wantData abcde",
  192. "wantSize 5",
  193. "write 5*x",
  194. "write 4*y+2*z",
  195. "write 3*st",
  196. "wantData abcdexxxxxyyyyzzststst",
  197. "wantSize 22",
  198. "seek set 4 want 4",
  199. "write EFG",
  200. "wantData abcdEFGxxxyyyyzzststst",
  201. "wantSize 22",
  202. "seek set 2 want 2",
  203. "read cdEF",
  204. "read Gx",
  205. "seek cur 0 want 8",
  206. "seek cur 2 want 10",
  207. "seek cur -1 want 9",
  208. "write J",
  209. "wantData abcdEFGxxJyyyyzzststst",
  210. "wantSize 22",
  211. "seek cur -4 want 6",
  212. "write ghijk",
  213. "wantData abcdEFghijkyyyzzststst",
  214. "wantSize 22",
  215. "read yyyz",
  216. "seek cur 0 want 15",
  217. "write ",
  218. "seek cur 0 want 15",
  219. "read ",
  220. "seek cur 0 want 15",
  221. "seek end -3 want 19",
  222. "write ZZ",
  223. "wantData abcdEFghijkyyyzzstsZZt",
  224. "wantSize 22",
  225. "write 4*A",
  226. "wantData abcdEFghijkyyyzzstsZZAAAA",
  227. "wantSize 25",
  228. "seek end 0 want 25",
  229. "seek end -5 want 20",
  230. "read Z+4*A",
  231. "write 5*B",
  232. "wantData abcdEFghijkyyyzzstsZZAAAABBBBB",
  233. "wantSize 30",
  234. "seek end 10 want 40",
  235. "write C",
  236. "wantData abcdEFghijkyyyzzstsZZAAAABBBBB..........C",
  237. "wantSize 41",
  238. "seek set 43 want 43",
  239. "write D",
  240. "wantData abcdEFghijkyyyzzstsZZAAAABBBBB..........C..D",
  241. "wantSize 44",
  242. "seek set 0 want 0",
  243. "write 5*123456789_",
  244. "wantData 123456789_123456789_123456789_123456789_123456789_",
  245. "wantSize 50",
  246. "seek cur 0 want 50",
  247. "seek cur -99 want err",
  248. }
  249. const filename = "/foo"
  250. fs := NewMemFS()
  251. f, err := fs.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
  252. if err != nil {
  253. t.Fatalf("OpenFile: %v", err)
  254. }
  255. defer f.Close()
  256. for i, tc := range testCases {
  257. j := strings.IndexByte(tc, ' ')
  258. if j < 0 {
  259. t.Fatalf("test case #%d %q: invalid command", i, tc)
  260. }
  261. op, arg := tc[:j], tc[j+1:]
  262. // Expand an arg like "3*a+2*b" to "aaabb".
  263. parts := strings.Split(arg, "+")
  264. for j, part := range parts {
  265. if k := strings.IndexByte(part, '*'); k >= 0 {
  266. repeatCount, repeatStr := part[:k], part[k+1:]
  267. n, err := strconv.Atoi(repeatCount)
  268. if err != nil {
  269. t.Fatalf("test case #%d %q: invalid repeat count %q", i, tc, repeatCount)
  270. }
  271. parts[j] = strings.Repeat(repeatStr, n)
  272. }
  273. }
  274. arg = strings.Join(parts, "")
  275. switch op {
  276. default:
  277. t.Fatalf("test case #%d %q: invalid operation %q", i, tc, op)
  278. case "read":
  279. buf := make([]byte, len(arg))
  280. if _, err := io.ReadFull(f, buf); err != nil {
  281. t.Fatalf("test case #%d %q: ReadFull: %v", i, tc, err)
  282. }
  283. if got := string(buf); got != arg {
  284. t.Fatalf("test case #%d %q:\ngot %q\nwant %q", i, tc, got, arg)
  285. }
  286. case "seek":
  287. parts := strings.Split(arg, " ")
  288. if len(parts) != 4 {
  289. t.Fatalf("test case #%d %q: invalid seek", i, tc)
  290. }
  291. whence := 0
  292. switch parts[0] {
  293. default:
  294. t.Fatalf("test case #%d %q: invalid seek whence", i, tc)
  295. case "set":
  296. whence = os.SEEK_SET
  297. case "cur":
  298. whence = os.SEEK_CUR
  299. case "end":
  300. whence = os.SEEK_END
  301. }
  302. offset, err := strconv.Atoi(parts[1])
  303. if err != nil {
  304. t.Fatalf("test case #%d %q: invalid offset %q", i, tc, parts[1])
  305. }
  306. if parts[2] != "want" {
  307. t.Fatalf("test case #%d %q: invalid seek", i, tc)
  308. }
  309. if parts[3] == "err" {
  310. _, err := f.Seek(int64(offset), whence)
  311. if err == nil {
  312. t.Fatalf("test case #%d %q: Seek returned nil error, want non-nil", i, tc)
  313. }
  314. } else {
  315. got, err := f.Seek(int64(offset), whence)
  316. if err != nil {
  317. t.Fatalf("test case #%d %q: Seek: %v", i, tc, err)
  318. }
  319. want, err := strconv.Atoi(parts[3])
  320. if err != nil {
  321. t.Fatalf("test case #%d %q: invalid want %q", i, tc, parts[3])
  322. }
  323. if got != int64(want) {
  324. t.Fatalf("test case #%d %q: got %d, want %d", i, tc, got, want)
  325. }
  326. }
  327. case "write":
  328. n, err := f.Write([]byte(arg))
  329. if err != nil {
  330. t.Fatalf("test case #%d %q: write: %v", i, tc, err)
  331. }
  332. if n != len(arg) {
  333. t.Fatalf("test case #%d %q: write returned %d bytes, want %d", i, tc, n, len(arg))
  334. }
  335. case "wantData":
  336. g, err := fs.OpenFile(filename, os.O_RDONLY, 0666)
  337. if err != nil {
  338. t.Fatalf("test case #%d %q: OpenFile: %v", i, tc, err)
  339. }
  340. gotBytes, err := ioutil.ReadAll(g)
  341. if err != nil {
  342. t.Fatalf("test case #%d %q: ReadAll: %v", i, tc, err)
  343. }
  344. for i, c := range gotBytes {
  345. if c == '\x00' {
  346. gotBytes[i] = '.'
  347. }
  348. }
  349. got := string(gotBytes)
  350. if got != arg {
  351. t.Fatalf("test case #%d %q:\ngot %q\nwant %q", i, tc, got, arg)
  352. }
  353. if err := g.Close(); err != nil {
  354. t.Fatalf("test case #%d %q: Close: %v", i, tc, err)
  355. }
  356. case "wantSize":
  357. n, err := strconv.Atoi(arg)
  358. if err != nil {
  359. t.Fatalf("test case #%d %q: invalid size %q", i, tc, arg)
  360. }
  361. fi, err := fs.Stat(filename)
  362. if err != nil {
  363. t.Fatalf("test case #%d %q: Stat: %v", i, tc, err)
  364. }
  365. if got, want := fi.Size(), int64(n); got != want {
  366. t.Fatalf("test case #%d %q: got %d, want %d", i, tc, got, want)
  367. }
  368. }
  369. }
  370. }