You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

basic.go 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. package test
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "io/ioutil"
  7. "os"
  8. "path/filepath"
  9. . "gopkg.in/check.v1"
  10. . "gopkg.in/src-d/go-billy.v4"
  11. "gopkg.in/src-d/go-billy.v4/util"
  12. )
  13. // BasicSuite is a convenient test suite to validate any implementation of
  14. // billy.Basic
  15. type BasicSuite struct {
  16. FS Basic
  17. }
  18. func (s *BasicSuite) TestCreate(c *C) {
  19. f, err := s.FS.Create("foo")
  20. c.Assert(err, IsNil)
  21. c.Assert(f.Name(), Equals, "foo")
  22. c.Assert(f.Close(), IsNil)
  23. }
  24. func (s *BasicSuite) TestCreateDepth(c *C) {
  25. f, err := s.FS.Create("bar/foo")
  26. c.Assert(err, IsNil)
  27. c.Assert(f.Name(), Equals, s.FS.Join("bar", "foo"))
  28. c.Assert(f.Close(), IsNil)
  29. }
  30. func (s *BasicSuite) TestCreateDepthAbsolute(c *C) {
  31. f, err := s.FS.Create("/bar/foo")
  32. c.Assert(err, IsNil)
  33. c.Assert(f.Name(), Equals, s.FS.Join("bar", "foo"))
  34. c.Assert(f.Close(), IsNil)
  35. }
  36. func (s *BasicSuite) TestCreateOverwrite(c *C) {
  37. for i := 0; i < 3; i++ {
  38. f, err := s.FS.Create("foo")
  39. c.Assert(err, IsNil)
  40. l, err := f.Write([]byte(fmt.Sprintf("foo%d", i)))
  41. c.Assert(err, IsNil)
  42. c.Assert(l, Equals, 4)
  43. err = f.Close()
  44. c.Assert(err, IsNil)
  45. }
  46. f, err := s.FS.Open("foo")
  47. c.Assert(err, IsNil)
  48. wrote, err := ioutil.ReadAll(f)
  49. c.Assert(err, IsNil)
  50. c.Assert(string(wrote), DeepEquals, "foo2")
  51. c.Assert(f.Close(), IsNil)
  52. }
  53. func (s *BasicSuite) TestCreateAndClose(c *C) {
  54. f, err := s.FS.Create("foo")
  55. c.Assert(err, IsNil)
  56. _, err = f.Write([]byte("foo"))
  57. c.Assert(err, IsNil)
  58. c.Assert(f.Close(), IsNil)
  59. f, err = s.FS.Open(f.Name())
  60. c.Assert(err, IsNil)
  61. wrote, err := ioutil.ReadAll(f)
  62. c.Assert(err, IsNil)
  63. c.Assert(string(wrote), DeepEquals, "foo")
  64. c.Assert(f.Close(), IsNil)
  65. }
  66. func (s *BasicSuite) TestOpen(c *C) {
  67. f, err := s.FS.Create("foo")
  68. c.Assert(err, IsNil)
  69. c.Assert(f.Name(), Equals, "foo")
  70. c.Assert(f.Close(), IsNil)
  71. f, err = s.FS.Open("foo")
  72. c.Assert(err, IsNil)
  73. c.Assert(f.Name(), Equals, "foo")
  74. c.Assert(f.Close(), IsNil)
  75. }
  76. func (s *BasicSuite) TestOpenNotExists(c *C) {
  77. f, err := s.FS.Open("not-exists")
  78. c.Assert(err, NotNil)
  79. c.Assert(f, IsNil)
  80. }
  81. func (s *BasicSuite) TestOpenFile(c *C) {
  82. defaultMode := os.FileMode(0666)
  83. f, err := s.FS.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode)
  84. c.Assert(err, IsNil)
  85. s.testWriteClose(c, f, "foo1")
  86. // Truncate if it exists
  87. f, err = s.FS.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode)
  88. c.Assert(err, IsNil)
  89. c.Assert(f.Name(), Equals, "foo1")
  90. s.testWriteClose(c, f, "foo1overwritten")
  91. // Read-only if it exists
  92. f, err = s.FS.OpenFile("foo1", os.O_RDONLY, defaultMode)
  93. c.Assert(err, IsNil)
  94. c.Assert(f.Name(), Equals, "foo1")
  95. s.testReadClose(c, f, "foo1overwritten")
  96. // Create when it does exist
  97. f, err = s.FS.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode)
  98. c.Assert(err, IsNil)
  99. c.Assert(f.Name(), Equals, "foo1")
  100. s.testWriteClose(c, f, "bar")
  101. f, err = s.FS.OpenFile("foo1", os.O_RDONLY, defaultMode)
  102. c.Assert(err, IsNil)
  103. s.testReadClose(c, f, "bar")
  104. }
  105. func (s *BasicSuite) TestOpenFileNoTruncate(c *C) {
  106. defaultMode := os.FileMode(0666)
  107. // Create when it does not exist
  108. f, err := s.FS.OpenFile("foo1", os.O_CREATE|os.O_WRONLY, defaultMode)
  109. c.Assert(err, IsNil)
  110. c.Assert(f.Name(), Equals, "foo1")
  111. s.testWriteClose(c, f, "foo1")
  112. f, err = s.FS.OpenFile("foo1", os.O_RDONLY, defaultMode)
  113. c.Assert(err, IsNil)
  114. s.testReadClose(c, f, "foo1")
  115. // Create when it does exist
  116. f, err = s.FS.OpenFile("foo1", os.O_CREATE|os.O_WRONLY, defaultMode)
  117. c.Assert(err, IsNil)
  118. c.Assert(f.Name(), Equals, "foo1")
  119. s.testWriteClose(c, f, "bar")
  120. f, err = s.FS.OpenFile("foo1", os.O_RDONLY, defaultMode)
  121. c.Assert(err, IsNil)
  122. s.testReadClose(c, f, "bar1")
  123. }
  124. func (s *BasicSuite) TestOpenFileAppend(c *C) {
  125. defaultMode := os.FileMode(0666)
  126. f, err := s.FS.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_APPEND, defaultMode)
  127. c.Assert(err, IsNil)
  128. c.Assert(f.Name(), Equals, "foo1")
  129. s.testWriteClose(c, f, "foo1")
  130. f, err = s.FS.OpenFile("foo1", os.O_WRONLY|os.O_APPEND, defaultMode)
  131. c.Assert(err, IsNil)
  132. c.Assert(f.Name(), Equals, "foo1")
  133. s.testWriteClose(c, f, "bar1")
  134. f, err = s.FS.OpenFile("foo1", os.O_RDONLY, defaultMode)
  135. c.Assert(err, IsNil)
  136. s.testReadClose(c, f, "foo1bar1")
  137. }
  138. func (s *BasicSuite) TestOpenFileReadWrite(c *C) {
  139. defaultMode := os.FileMode(0666)
  140. f, err := s.FS.OpenFile("foo1", os.O_CREATE|os.O_TRUNC|os.O_RDWR, defaultMode)
  141. c.Assert(err, IsNil)
  142. c.Assert(f.Name(), Equals, "foo1")
  143. written, err := f.Write([]byte("foobar"))
  144. c.Assert(written, Equals, 6)
  145. c.Assert(err, IsNil)
  146. _, err = f.Seek(0, os.SEEK_SET)
  147. c.Assert(err, IsNil)
  148. written, err = f.Write([]byte("qux"))
  149. c.Assert(written, Equals, 3)
  150. c.Assert(err, IsNil)
  151. _, err = f.Seek(0, os.SEEK_SET)
  152. c.Assert(err, IsNil)
  153. s.testReadClose(c, f, "quxbar")
  154. }
  155. func (s *BasicSuite) TestOpenFileWithModes(c *C) {
  156. f, err := s.FS.OpenFile("foo", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, customMode)
  157. c.Assert(err, IsNil)
  158. c.Assert(f.Close(), IsNil)
  159. fi, err := s.FS.Stat("foo")
  160. c.Assert(err, IsNil)
  161. c.Assert(fi.Mode(), Equals, os.FileMode(customMode))
  162. }
  163. func (s *BasicSuite) testWriteClose(c *C, f File, content string) {
  164. written, err := f.Write([]byte(content))
  165. c.Assert(written, Equals, len(content))
  166. c.Assert(err, IsNil)
  167. c.Assert(f.Close(), IsNil)
  168. }
  169. func (s *BasicSuite) testReadClose(c *C, f File, content string) {
  170. read, err := ioutil.ReadAll(f)
  171. c.Assert(err, IsNil)
  172. c.Assert(string(read), Equals, content)
  173. c.Assert(f.Close(), IsNil)
  174. }
  175. func (s *BasicSuite) TestFileWrite(c *C) {
  176. f, err := s.FS.Create("foo")
  177. c.Assert(err, IsNil)
  178. n, err := f.Write([]byte("foo"))
  179. c.Assert(err, IsNil)
  180. c.Assert(n, Equals, 3)
  181. f.Seek(0, io.SeekStart)
  182. all, err := ioutil.ReadAll(f)
  183. c.Assert(err, IsNil)
  184. c.Assert(string(all), Equals, "foo")
  185. c.Assert(f.Close(), IsNil)
  186. }
  187. func (s *BasicSuite) TestFileWriteClose(c *C) {
  188. f, err := s.FS.Create("foo")
  189. c.Assert(err, IsNil)
  190. c.Assert(f.Close(), IsNil)
  191. _, err = f.Write([]byte("foo"))
  192. c.Assert(err, NotNil)
  193. }
  194. func (s *BasicSuite) TestFileRead(c *C) {
  195. err := util.WriteFile(s.FS, "foo", []byte("foo"), 0644)
  196. c.Assert(err, IsNil)
  197. f, err := s.FS.Open("foo")
  198. c.Assert(err, IsNil)
  199. all, err := ioutil.ReadAll(f)
  200. c.Assert(err, IsNil)
  201. c.Assert(string(all), Equals, "foo")
  202. c.Assert(f.Close(), IsNil)
  203. }
  204. func (s *BasicSuite) TestFileClosed(c *C) {
  205. err := util.WriteFile(s.FS, "foo", []byte("foo"), 0644)
  206. c.Assert(err, IsNil)
  207. f, err := s.FS.Open("foo")
  208. c.Assert(err, IsNil)
  209. c.Assert(f.Close(), IsNil)
  210. _, err = ioutil.ReadAll(f)
  211. c.Assert(err, NotNil)
  212. }
  213. func (s *BasicSuite) TestFileNonRead(c *C) {
  214. err := util.WriteFile(s.FS, "foo", []byte("foo"), 0644)
  215. c.Assert(err, IsNil)
  216. f, err := s.FS.OpenFile("foo", os.O_WRONLY, 0)
  217. c.Assert(err, IsNil)
  218. _, err = ioutil.ReadAll(f)
  219. c.Assert(err, NotNil)
  220. c.Assert(f.Close(), IsNil)
  221. }
  222. func (s *BasicSuite) TestFileSeekstart(c *C) {
  223. s.testFileSeek(c, 10, io.SeekStart)
  224. }
  225. func (s *BasicSuite) TestFileSeekCurrent(c *C) {
  226. s.testFileSeek(c, 5, io.SeekCurrent)
  227. }
  228. func (s *BasicSuite) TestFileSeekEnd(c *C) {
  229. s.testFileSeek(c, -26, io.SeekEnd)
  230. }
  231. func (s *BasicSuite) testFileSeek(c *C, offset int64, whence int) {
  232. err := util.WriteFile(s.FS, "foo", []byte("0123456789abcdefghijklmnopqrstuvwxyz"), 0644)
  233. c.Assert(err, IsNil)
  234. f, err := s.FS.Open("foo")
  235. c.Assert(err, IsNil)
  236. some := make([]byte, 5)
  237. _, err = f.Read(some)
  238. c.Assert(err, IsNil)
  239. c.Assert(string(some), Equals, "01234")
  240. p, err := f.Seek(offset, whence)
  241. c.Assert(err, IsNil)
  242. c.Assert(int(p), Equals, 10)
  243. all, err := ioutil.ReadAll(f)
  244. c.Assert(err, IsNil)
  245. c.Assert(all, HasLen, 26)
  246. c.Assert(string(all), Equals, "abcdefghijklmnopqrstuvwxyz")
  247. c.Assert(f.Close(), IsNil)
  248. }
  249. func (s *BasicSuite) TestSeekToEndAndWrite(c *C) {
  250. defaultMode := os.FileMode(0666)
  251. f, err := s.FS.OpenFile("foo1", os.O_CREATE|os.O_TRUNC|os.O_RDWR, defaultMode)
  252. c.Assert(err, IsNil)
  253. c.Assert(f.Name(), Equals, "foo1")
  254. _, err = f.Seek(10, io.SeekEnd)
  255. c.Assert(err, IsNil)
  256. n, err := f.Write([]byte(`TEST`))
  257. c.Assert(err, IsNil)
  258. c.Assert(n, Equals, 4)
  259. _, err = f.Seek(0, io.SeekStart)
  260. c.Assert(err, IsNil)
  261. s.testReadClose(c, f, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00TEST")
  262. }
  263. func (s *BasicSuite) TestFileSeekClosed(c *C) {
  264. err := util.WriteFile(s.FS, "foo", []byte("foo"), 0644)
  265. c.Assert(err, IsNil)
  266. f, err := s.FS.Open("foo")
  267. c.Assert(err, IsNil)
  268. c.Assert(f.Close(), IsNil)
  269. _, err = f.Seek(0, 0)
  270. c.Assert(err, NotNil)
  271. }
  272. func (s *BasicSuite) TestFileCloseTwice(c *C) {
  273. f, err := s.FS.Create("foo")
  274. c.Assert(err, IsNil)
  275. c.Assert(f.Close(), IsNil)
  276. c.Assert(f.Close(), NotNil)
  277. }
  278. func (s *BasicSuite) TestStat(c *C) {
  279. util.WriteFile(s.FS, "foo/bar", []byte("foo"), customMode)
  280. fi, err := s.FS.Stat("foo/bar")
  281. c.Assert(err, IsNil)
  282. c.Assert(fi.Name(), Equals, "bar")
  283. c.Assert(fi.Size(), Equals, int64(3))
  284. c.Assert(fi.Mode(), Equals, customMode)
  285. c.Assert(fi.ModTime().IsZero(), Equals, false)
  286. c.Assert(fi.IsDir(), Equals, false)
  287. }
  288. func (s *BasicSuite) TestStatNonExistent(c *C) {
  289. fi, err := s.FS.Stat("non-existent")
  290. comment := Commentf("error: %s", err)
  291. c.Assert(os.IsNotExist(err), Equals, true, comment)
  292. c.Assert(fi, IsNil)
  293. }
  294. func (s *BasicSuite) TestRename(c *C) {
  295. err := util.WriteFile(s.FS, "foo", nil, 0644)
  296. c.Assert(err, IsNil)
  297. err = s.FS.Rename("foo", "bar")
  298. c.Assert(err, IsNil)
  299. foo, err := s.FS.Stat("foo")
  300. c.Assert(foo, IsNil)
  301. c.Assert(os.IsNotExist(err), Equals, true)
  302. bar, err := s.FS.Stat("bar")
  303. c.Assert(err, IsNil)
  304. c.Assert(bar, NotNil)
  305. }
  306. func (s *BasicSuite) TestOpenAndWrite(c *C) {
  307. err := util.WriteFile(s.FS, "foo", nil, 0644)
  308. c.Assert(err, IsNil)
  309. foo, err := s.FS.Open("foo")
  310. c.Assert(foo, NotNil)
  311. c.Assert(err, IsNil)
  312. n, err := foo.Write([]byte("foo"))
  313. c.Assert(err, NotNil)
  314. c.Assert(n, Equals, 0)
  315. c.Assert(foo.Close(), IsNil)
  316. }
  317. func (s *BasicSuite) TestOpenAndStat(c *C) {
  318. err := util.WriteFile(s.FS, "foo", []byte("foo"), 0644)
  319. c.Assert(err, IsNil)
  320. foo, err := s.FS.Open("foo")
  321. c.Assert(foo, NotNil)
  322. c.Assert(foo.Name(), Equals, "foo")
  323. c.Assert(err, IsNil)
  324. c.Assert(foo.Close(), IsNil)
  325. stat, err := s.FS.Stat("foo")
  326. c.Assert(stat, NotNil)
  327. c.Assert(err, IsNil)
  328. c.Assert(stat.Name(), Equals, "foo")
  329. c.Assert(stat.Size(), Equals, int64(3))
  330. }
  331. func (s *BasicSuite) TestRemove(c *C) {
  332. f, err := s.FS.Create("foo")
  333. c.Assert(err, IsNil)
  334. c.Assert(f.Close(), IsNil)
  335. err = s.FS.Remove("foo")
  336. c.Assert(err, IsNil)
  337. }
  338. func (s *BasicSuite) TestRemoveNonExisting(c *C) {
  339. err := s.FS.Remove("NON-EXISTING")
  340. c.Assert(err, NotNil)
  341. c.Assert(os.IsNotExist(err), Equals, true)
  342. }
  343. func (s *BasicSuite) TestRemoveNotEmptyDir(c *C) {
  344. err := util.WriteFile(s.FS, "foo", nil, 0644)
  345. c.Assert(err, IsNil)
  346. err = s.FS.Remove("no-exists")
  347. c.Assert(err, NotNil)
  348. }
  349. func (s *BasicSuite) TestJoin(c *C) {
  350. c.Assert(s.FS.Join("foo", "bar"), Equals, fmt.Sprintf("foo%cbar", filepath.Separator))
  351. }
  352. func (s *BasicSuite) TestReadAtOnReadWrite(c *C) {
  353. f, err := s.FS.Create("foo")
  354. c.Assert(err, IsNil)
  355. _, err = f.Write([]byte("abcdefg"))
  356. c.Assert(err, IsNil)
  357. rf, ok := f.(io.ReaderAt)
  358. c.Assert(ok, Equals, true)
  359. b := make([]byte, 3)
  360. n, err := rf.ReadAt(b, 2)
  361. c.Assert(err, IsNil)
  362. c.Assert(n, Equals, 3)
  363. c.Assert(string(b), Equals, "cde")
  364. c.Assert(f.Close(), IsNil)
  365. }
  366. func (s *BasicSuite) TestReadAtOnReadOnly(c *C) {
  367. err := util.WriteFile(s.FS, "foo", []byte("abcdefg"), 0644)
  368. c.Assert(err, IsNil)
  369. f, err := s.FS.Open("foo")
  370. c.Assert(err, IsNil)
  371. rf, ok := f.(io.ReaderAt)
  372. c.Assert(ok, Equals, true)
  373. b := make([]byte, 3)
  374. n, err := rf.ReadAt(b, 2)
  375. c.Assert(err, IsNil)
  376. c.Assert(n, Equals, 3)
  377. c.Assert(string(b), Equals, "cde")
  378. c.Assert(f.Close(), IsNil)
  379. }
  380. func (s *BasicSuite) TestReadAtEOF(c *C) {
  381. err := util.WriteFile(s.FS, "foo", []byte("TEST"), 0644)
  382. c.Assert(err, IsNil)
  383. f, err := s.FS.Open("foo")
  384. c.Assert(err, IsNil)
  385. b := make([]byte, 5)
  386. n, err := f.ReadAt(b, 0)
  387. c.Assert(err, Equals, io.EOF)
  388. c.Assert(n, Equals, 4)
  389. c.Assert(string(b), Equals, "TEST\x00")
  390. err = f.Close()
  391. c.Assert(err, IsNil)
  392. }
  393. func (s *BasicSuite) TestReadAtOffset(c *C) {
  394. err := util.WriteFile(s.FS, "foo", []byte("TEST"), 0644)
  395. c.Assert(err, IsNil)
  396. f, err := s.FS.Open("foo")
  397. c.Assert(err, IsNil)
  398. rf, ok := f.(io.ReaderAt)
  399. c.Assert(ok, Equals, true)
  400. o, err := f.Seek(0, io.SeekCurrent)
  401. c.Assert(err, IsNil)
  402. c.Assert(o, Equals, int64(0))
  403. b := make([]byte, 4)
  404. n, err := rf.ReadAt(b, 0)
  405. c.Assert(err, IsNil)
  406. c.Assert(n, Equals, 4)
  407. c.Assert(string(b), Equals, "TEST")
  408. o, err = f.Seek(0, io.SeekCurrent)
  409. c.Assert(err, IsNil)
  410. c.Assert(o, Equals, int64(0))
  411. err = f.Close()
  412. c.Assert(err, IsNil)
  413. }
  414. func (s *BasicSuite) TestReadWriteLargeFile(c *C) {
  415. f, err := s.FS.Create("foo")
  416. c.Assert(err, IsNil)
  417. size := 1 << 20
  418. n, err := f.Write(bytes.Repeat([]byte("F"), size))
  419. c.Assert(err, IsNil)
  420. c.Assert(n, Equals, size)
  421. c.Assert(f.Close(), IsNil)
  422. f, err = s.FS.Open("foo")
  423. c.Assert(err, IsNil)
  424. b, err := ioutil.ReadAll(f)
  425. c.Assert(err, IsNil)
  426. c.Assert(len(b), Equals, size)
  427. c.Assert(f.Close(), IsNil)
  428. }
  429. func (s *BasicSuite) TestWriteFile(c *C) {
  430. err := util.WriteFile(s.FS, "foo", []byte("bar"), 0777)
  431. c.Assert(err, IsNil)
  432. f, err := s.FS.Open("foo")
  433. c.Assert(err, IsNil)
  434. wrote, err := ioutil.ReadAll(f)
  435. c.Assert(err, IsNil)
  436. c.Assert(string(wrote), DeepEquals, "bar")
  437. c.Assert(f.Close(), IsNil)
  438. }
  439. func (s *BasicSuite) TestTruncate(c *C) {
  440. f, err := s.FS.Create("foo")
  441. c.Assert(err, IsNil)
  442. for _, sz := range []int64{4, 7, 2, 30, 0, 1} {
  443. err = f.Truncate(sz)
  444. c.Assert(err, IsNil)
  445. bs, err := ioutil.ReadAll(f)
  446. c.Assert(err, IsNil)
  447. c.Assert(len(bs), Equals, int(sz))
  448. _, err = f.Seek(0, io.SeekStart)
  449. c.Assert(err, IsNil)
  450. }
  451. c.Assert(f.Close(), IsNil)
  452. }