caching_fs_test.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. // Copyright 2015 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package cachingfs_test
  15. import (
  16. "bytes"
  17. "io/ioutil"
  18. "os"
  19. "path"
  20. "runtime"
  21. "syscall"
  22. "testing"
  23. "time"
  24. "github.com/jacobsa/fuse/fuseutil"
  25. "github.com/jacobsa/fuse/samples"
  26. "github.com/jacobsa/fuse/samples/cachingfs"
  27. . "github.com/jacobsa/oglematchers"
  28. . "github.com/jacobsa/ogletest"
  29. "github.com/jacobsa/timeutil"
  30. )
  31. func TestCachingFS(t *testing.T) { RunTests(t) }
  32. ////////////////////////////////////////////////////////////////////////
  33. // Boilerplate
  34. ////////////////////////////////////////////////////////////////////////
  35. type cachingFSTest struct {
  36. samples.SampleTest
  37. fs cachingfs.CachingFS
  38. initialMtime time.Time
  39. }
  40. var _ TearDownInterface = &cachingFSTest{}
  41. func (t *cachingFSTest) setUp(
  42. ti *TestInfo,
  43. lookupEntryTimeout time.Duration,
  44. getattrTimeout time.Duration) {
  45. var err error
  46. // We assert things about whether or not mtimes are cached, but writeback
  47. // caching causes them to always be cached. Turn it off.
  48. t.MountConfig.DisableWritebackCaching = true
  49. // Create the file system.
  50. t.fs, err = cachingfs.NewCachingFS(lookupEntryTimeout, getattrTimeout)
  51. AssertEq(nil, err)
  52. t.Server = fuseutil.NewFileSystemServer(t.fs)
  53. // Mount it.
  54. t.SampleTest.SetUp(ti)
  55. // Set up the mtime.
  56. t.initialMtime = time.Date(2012, 8, 15, 22, 56, 0, 0, time.Local)
  57. t.fs.SetMtime(t.initialMtime)
  58. }
  59. func (t *cachingFSTest) statAll() (foo, dir, bar os.FileInfo) {
  60. var err error
  61. foo, err = os.Stat(path.Join(t.Dir, "foo"))
  62. AssertEq(nil, err)
  63. dir, err = os.Stat(path.Join(t.Dir, "dir"))
  64. AssertEq(nil, err)
  65. bar, err = os.Stat(path.Join(t.Dir, "dir/bar"))
  66. AssertEq(nil, err)
  67. return
  68. }
  69. func (t *cachingFSTest) openFiles() (foo, dir, bar *os.File) {
  70. var err error
  71. foo, err = os.Open(path.Join(t.Dir, "foo"))
  72. AssertEq(nil, err)
  73. dir, err = os.Open(path.Join(t.Dir, "dir"))
  74. AssertEq(nil, err)
  75. bar, err = os.Open(path.Join(t.Dir, "dir/bar"))
  76. AssertEq(nil, err)
  77. return
  78. }
  79. func (t *cachingFSTest) statFiles(
  80. f, g, h *os.File) (foo, dir, bar os.FileInfo) {
  81. var err error
  82. foo, err = f.Stat()
  83. AssertEq(nil, err)
  84. dir, err = g.Stat()
  85. AssertEq(nil, err)
  86. bar, err = h.Stat()
  87. AssertEq(nil, err)
  88. return
  89. }
  90. func getInodeID(fi os.FileInfo) uint64 {
  91. return fi.Sys().(*syscall.Stat_t).Ino
  92. }
  93. ////////////////////////////////////////////////////////////////////////
  94. // Basics
  95. ////////////////////////////////////////////////////////////////////////
  96. type BasicsTest struct {
  97. cachingFSTest
  98. }
  99. var _ SetUpInterface = &BasicsTest{}
  100. func init() { RegisterTestSuite(&BasicsTest{}) }
  101. func (t *BasicsTest) SetUp(ti *TestInfo) {
  102. const (
  103. lookupEntryTimeout = 0
  104. getattrTimeout = 0
  105. )
  106. t.cachingFSTest.setUp(ti, lookupEntryTimeout, getattrTimeout)
  107. }
  108. func (t *BasicsTest) StatNonexistent() {
  109. names := []string{
  110. "blah",
  111. "bar",
  112. "dir/blah",
  113. "dir/dir",
  114. "dir/foo",
  115. }
  116. for _, n := range names {
  117. _, err := os.Stat(path.Join(t.Dir, n))
  118. AssertNe(nil, err)
  119. ExpectTrue(os.IsNotExist(err), "n: %s, err: %v", n, err)
  120. }
  121. }
  122. func (t *BasicsTest) StatFoo() {
  123. fi, err := os.Stat(path.Join(t.Dir, "foo"))
  124. AssertEq(nil, err)
  125. ExpectEq("foo", fi.Name())
  126. ExpectEq(cachingfs.FooSize, fi.Size())
  127. ExpectEq(0777, fi.Mode())
  128. ExpectThat(fi.ModTime(), timeutil.TimeEq(t.initialMtime))
  129. ExpectFalse(fi.IsDir())
  130. ExpectEq(t.fs.FooID(), getInodeID(fi))
  131. ExpectEq(1, fi.Sys().(*syscall.Stat_t).Nlink)
  132. }
  133. func (t *BasicsTest) StatDir() {
  134. fi, err := os.Stat(path.Join(t.Dir, "dir"))
  135. AssertEq(nil, err)
  136. ExpectEq("dir", fi.Name())
  137. ExpectEq(os.ModeDir|0777, fi.Mode())
  138. ExpectThat(fi.ModTime(), timeutil.TimeEq(t.initialMtime))
  139. ExpectTrue(fi.IsDir())
  140. ExpectEq(t.fs.DirID(), getInodeID(fi))
  141. ExpectEq(1, fi.Sys().(*syscall.Stat_t).Nlink)
  142. }
  143. func (t *BasicsTest) StatBar() {
  144. fi, err := os.Stat(path.Join(t.Dir, "dir/bar"))
  145. AssertEq(nil, err)
  146. ExpectEq("bar", fi.Name())
  147. ExpectEq(cachingfs.BarSize, fi.Size())
  148. ExpectEq(0777, fi.Mode())
  149. ExpectThat(fi.ModTime(), timeutil.TimeEq(t.initialMtime))
  150. ExpectFalse(fi.IsDir())
  151. ExpectEq(t.fs.BarID(), getInodeID(fi))
  152. ExpectEq(1, fi.Sys().(*syscall.Stat_t).Nlink)
  153. }
  154. ////////////////////////////////////////////////////////////////////////
  155. // No caching
  156. ////////////////////////////////////////////////////////////////////////
  157. type NoCachingTest struct {
  158. cachingFSTest
  159. }
  160. var _ SetUpInterface = &NoCachingTest{}
  161. func init() { RegisterTestSuite(&NoCachingTest{}) }
  162. func (t *NoCachingTest) SetUp(ti *TestInfo) {
  163. const (
  164. lookupEntryTimeout = 0
  165. getattrTimeout = 0
  166. )
  167. t.cachingFSTest.setUp(ti, lookupEntryTimeout, getattrTimeout)
  168. }
  169. func (t *NoCachingTest) StatStat() {
  170. fooBefore, dirBefore, barBefore := t.statAll()
  171. fooAfter, dirAfter, barAfter := t.statAll()
  172. // Make sure everything matches.
  173. ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(fooBefore.ModTime()))
  174. ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(dirBefore.ModTime()))
  175. ExpectThat(barAfter.ModTime(), timeutil.TimeEq(barBefore.ModTime()))
  176. ExpectEq(getInodeID(fooBefore), getInodeID(fooAfter))
  177. ExpectEq(getInodeID(dirBefore), getInodeID(dirAfter))
  178. ExpectEq(getInodeID(barBefore), getInodeID(barAfter))
  179. }
  180. func (t *NoCachingTest) StatRenumberStat() {
  181. t.statAll()
  182. t.fs.RenumberInodes()
  183. fooAfter, dirAfter, barAfter := t.statAll()
  184. // We should see the new inode IDs, because the entries should not have been
  185. // cached.
  186. ExpectEq(t.fs.FooID(), getInodeID(fooAfter))
  187. ExpectEq(t.fs.DirID(), getInodeID(dirAfter))
  188. ExpectEq(t.fs.BarID(), getInodeID(barAfter))
  189. }
  190. func (t *NoCachingTest) StatMtimeStat() {
  191. newMtime := t.initialMtime.Add(time.Second)
  192. t.statAll()
  193. t.fs.SetMtime(newMtime)
  194. fooAfter, dirAfter, barAfter := t.statAll()
  195. // We should see the new mtimes, because the attributes should not have been
  196. // cached.
  197. ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(newMtime))
  198. ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(newMtime))
  199. ExpectThat(barAfter.ModTime(), timeutil.TimeEq(newMtime))
  200. }
  201. func (t *NoCachingTest) StatRenumberMtimeStat() {
  202. newMtime := t.initialMtime.Add(time.Second)
  203. t.statAll()
  204. t.fs.RenumberInodes()
  205. t.fs.SetMtime(newMtime)
  206. fooAfter, dirAfter, barAfter := t.statAll()
  207. // We should see the new inode IDs and mtimes, because nothing should have
  208. // been cached.
  209. ExpectEq(t.fs.FooID(), getInodeID(fooAfter))
  210. ExpectEq(t.fs.DirID(), getInodeID(dirAfter))
  211. ExpectEq(t.fs.BarID(), getInodeID(barAfter))
  212. ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(newMtime))
  213. ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(newMtime))
  214. ExpectThat(barAfter.ModTime(), timeutil.TimeEq(newMtime))
  215. }
  216. ////////////////////////////////////////////////////////////////////////
  217. // Entry caching
  218. ////////////////////////////////////////////////////////////////////////
  219. type EntryCachingTest struct {
  220. cachingFSTest
  221. lookupEntryTimeout time.Duration
  222. }
  223. var _ SetUpInterface = &EntryCachingTest{}
  224. func init() { RegisterTestSuite(&EntryCachingTest{}) }
  225. func (t *EntryCachingTest) SetUp(ti *TestInfo) {
  226. t.lookupEntryTimeout = 250 * time.Millisecond
  227. t.SampleTest.MountConfig.EnableVnodeCaching = true
  228. t.cachingFSTest.setUp(ti, t.lookupEntryTimeout, 0)
  229. }
  230. func (t *EntryCachingTest) StatStat() {
  231. fooBefore, dirBefore, barBefore := t.statAll()
  232. fooAfter, dirAfter, barAfter := t.statAll()
  233. // Make sure everything matches.
  234. ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(fooBefore.ModTime()))
  235. ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(dirBefore.ModTime()))
  236. ExpectThat(barAfter.ModTime(), timeutil.TimeEq(barBefore.ModTime()))
  237. ExpectEq(getInodeID(fooBefore), getInodeID(fooAfter))
  238. ExpectEq(getInodeID(dirBefore), getInodeID(dirAfter))
  239. ExpectEq(getInodeID(barBefore), getInodeID(barAfter))
  240. }
  241. func (t *EntryCachingTest) StatRenumberStat() {
  242. fooBefore, dirBefore, barBefore := t.statAll()
  243. t.fs.RenumberInodes()
  244. fooAfter, dirAfter, barAfter := t.statAll()
  245. // We should still see the old inode IDs, because the inode entries should
  246. // have been cached.
  247. ExpectEq(getInodeID(fooBefore), getInodeID(fooAfter))
  248. ExpectEq(getInodeID(dirBefore), getInodeID(dirAfter))
  249. ExpectEq(getInodeID(barBefore), getInodeID(barAfter))
  250. // But after waiting for the entry cache to expire, we should see the new
  251. // IDs.
  252. //
  253. // Note that the cache is not guaranteed to expire on darwin. See notes on
  254. // fuse.MountConfig.EnableVnodeCaching.
  255. if runtime.GOOS != "darwin" {
  256. time.Sleep(2 * t.lookupEntryTimeout)
  257. fooAfter, dirAfter, barAfter = t.statAll()
  258. ExpectEq(t.fs.FooID(), getInodeID(fooAfter))
  259. ExpectEq(t.fs.DirID(), getInodeID(dirAfter))
  260. ExpectEq(t.fs.BarID(), getInodeID(barAfter))
  261. }
  262. }
  263. func (t *EntryCachingTest) StatMtimeStat() {
  264. newMtime := t.initialMtime.Add(time.Second)
  265. t.statAll()
  266. t.fs.SetMtime(newMtime)
  267. fooAfter, dirAfter, barAfter := t.statAll()
  268. // We should see the new mtimes, because the attributes should not have been
  269. // cached.
  270. ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(newMtime))
  271. ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(newMtime))
  272. ExpectThat(barAfter.ModTime(), timeutil.TimeEq(newMtime))
  273. }
  274. func (t *EntryCachingTest) StatRenumberMtimeStat() {
  275. newMtime := t.initialMtime.Add(time.Second)
  276. fooBefore, dirBefore, barBefore := t.statAll()
  277. t.fs.RenumberInodes()
  278. t.fs.SetMtime(newMtime)
  279. fooAfter, dirAfter, barAfter := t.statAll()
  280. // We should still see the old inode IDs, because the inode entries should
  281. // have been cached. But the attributes should not have been.
  282. ExpectEq(getInodeID(fooBefore), getInodeID(fooAfter))
  283. ExpectEq(getInodeID(dirBefore), getInodeID(dirAfter))
  284. ExpectEq(getInodeID(barBefore), getInodeID(barAfter))
  285. ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(newMtime))
  286. ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(newMtime))
  287. ExpectThat(barAfter.ModTime(), timeutil.TimeEq(newMtime))
  288. // After waiting for the entry cache to expire, we should see fresh
  289. // everything.
  290. //
  291. // Note that the cache is not guaranteed to expire on darwin. See notes on
  292. // fuse.MountConfig.EnableVnodeCaching.
  293. if runtime.GOOS != "darwin" {
  294. time.Sleep(2 * t.lookupEntryTimeout)
  295. fooAfter, dirAfter, barAfter = t.statAll()
  296. ExpectEq(t.fs.FooID(), getInodeID(fooAfter))
  297. ExpectEq(t.fs.DirID(), getInodeID(dirAfter))
  298. ExpectEq(t.fs.BarID(), getInodeID(barAfter))
  299. ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(newMtime))
  300. ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(newMtime))
  301. ExpectThat(barAfter.ModTime(), timeutil.TimeEq(newMtime))
  302. }
  303. }
  304. ////////////////////////////////////////////////////////////////////////
  305. // Attribute caching
  306. ////////////////////////////////////////////////////////////////////////
  307. type AttributeCachingTest struct {
  308. cachingFSTest
  309. getattrTimeout time.Duration
  310. }
  311. var _ SetUpInterface = &AttributeCachingTest{}
  312. func init() { RegisterTestSuite(&AttributeCachingTest{}) }
  313. func (t *AttributeCachingTest) SetUp(ti *TestInfo) {
  314. t.getattrTimeout = 250 * time.Millisecond
  315. t.cachingFSTest.setUp(ti, 0, t.getattrTimeout)
  316. }
  317. func (t *AttributeCachingTest) StatStat() {
  318. fooBefore, dirBefore, barBefore := t.statAll()
  319. fooAfter, dirAfter, barAfter := t.statAll()
  320. // Make sure everything matches.
  321. ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(fooBefore.ModTime()))
  322. ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(dirBefore.ModTime()))
  323. ExpectThat(barAfter.ModTime(), timeutil.TimeEq(barBefore.ModTime()))
  324. ExpectEq(getInodeID(fooBefore), getInodeID(fooAfter))
  325. ExpectEq(getInodeID(dirBefore), getInodeID(dirAfter))
  326. ExpectEq(getInodeID(barBefore), getInodeID(barAfter))
  327. }
  328. func (t *AttributeCachingTest) StatRenumberStat() {
  329. t.statAll()
  330. t.fs.RenumberInodes()
  331. fooAfter, dirAfter, barAfter := t.statAll()
  332. // We should see the new inode IDs, because the entries should not have been
  333. // cached.
  334. ExpectEq(t.fs.FooID(), getInodeID(fooAfter))
  335. ExpectEq(t.fs.DirID(), getInodeID(dirAfter))
  336. ExpectEq(t.fs.BarID(), getInodeID(barAfter))
  337. }
  338. func (t *AttributeCachingTest) StatMtimeStat_ViaPath() {
  339. newMtime := t.initialMtime.Add(time.Second)
  340. t.statAll()
  341. t.fs.SetMtime(newMtime)
  342. fooAfter, dirAfter, barAfter := t.statAll()
  343. // Since we don't have entry caching enabled, the call above had to look up
  344. // the entry again. With the lookup we returned new attributes, so it's
  345. // possible that the mtime will be fresh. On Linux it appears to be, and on
  346. // OS X it appears to not be.
  347. m := AnyOf(timeutil.TimeEq(newMtime), timeutil.TimeEq(t.initialMtime))
  348. ExpectThat(fooAfter.ModTime(), m)
  349. ExpectThat(dirAfter.ModTime(), m)
  350. ExpectThat(barAfter.ModTime(), m)
  351. }
  352. func (t *AttributeCachingTest) StatMtimeStat_ViaFileDescriptor() {
  353. newMtime := t.initialMtime.Add(time.Second)
  354. // Open everything, fixing a particular inode number for each.
  355. foo, dir, bar := t.openFiles()
  356. defer func() {
  357. foo.Close()
  358. dir.Close()
  359. bar.Close()
  360. }()
  361. fooBefore, dirBefore, barBefore := t.statFiles(foo, dir, bar)
  362. t.fs.SetMtime(newMtime)
  363. fooAfter, dirAfter, barAfter := t.statFiles(foo, dir, bar)
  364. // We should still see the old cached mtime.
  365. ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(fooBefore.ModTime()))
  366. ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(dirBefore.ModTime()))
  367. ExpectThat(barAfter.ModTime(), timeutil.TimeEq(barBefore.ModTime()))
  368. // After waiting for the attribute cache to expire, we should see the fresh
  369. // mtime.
  370. time.Sleep(2 * t.getattrTimeout)
  371. fooAfter, dirAfter, barAfter = t.statFiles(foo, dir, bar)
  372. ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(newMtime))
  373. ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(newMtime))
  374. ExpectThat(barAfter.ModTime(), timeutil.TimeEq(newMtime))
  375. }
  376. func (t *AttributeCachingTest) StatRenumberMtimeStat_ViaPath() {
  377. newMtime := t.initialMtime.Add(time.Second)
  378. t.statAll()
  379. t.fs.RenumberInodes()
  380. t.fs.SetMtime(newMtime)
  381. fooAfter, dirAfter, barAfter := t.statAll()
  382. // We should see new everything, because this is the first time the new
  383. // inodes have been encountered. Entries for the old ones should not have
  384. // been cached, because we have entry caching disabled.
  385. ExpectEq(t.fs.FooID(), getInodeID(fooAfter))
  386. ExpectEq(t.fs.DirID(), getInodeID(dirAfter))
  387. ExpectEq(t.fs.BarID(), getInodeID(barAfter))
  388. ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(newMtime))
  389. ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(newMtime))
  390. ExpectThat(barAfter.ModTime(), timeutil.TimeEq(newMtime))
  391. }
  392. func (t *AttributeCachingTest) StatRenumberMtimeStat_ViaFileDescriptor() {
  393. newMtime := t.initialMtime.Add(time.Second)
  394. // Open everything, fixing a particular inode number for each.
  395. foo, dir, bar := t.openFiles()
  396. defer func() {
  397. foo.Close()
  398. dir.Close()
  399. bar.Close()
  400. }()
  401. fooBefore, dirBefore, barBefore := t.statFiles(foo, dir, bar)
  402. t.fs.RenumberInodes()
  403. t.fs.SetMtime(newMtime)
  404. fooAfter, dirAfter, barAfter := t.statFiles(foo, dir, bar)
  405. // We should still see the old cached mtime with the old inode ID.
  406. ExpectEq(getInodeID(fooBefore), getInodeID(fooAfter))
  407. ExpectEq(getInodeID(dirBefore), getInodeID(dirAfter))
  408. ExpectEq(getInodeID(barBefore), getInodeID(barAfter))
  409. ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(fooBefore.ModTime()))
  410. ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(dirBefore.ModTime()))
  411. ExpectThat(barAfter.ModTime(), timeutil.TimeEq(barBefore.ModTime()))
  412. // After waiting for the attribute cache to expire, we should see the fresh
  413. // mtime, still with the old inode ID.
  414. time.Sleep(2 * t.getattrTimeout)
  415. fooAfter, dirAfter, barAfter = t.statFiles(foo, dir, bar)
  416. ExpectEq(getInodeID(fooBefore), getInodeID(fooAfter))
  417. ExpectEq(getInodeID(dirBefore), getInodeID(dirAfter))
  418. ExpectEq(getInodeID(barBefore), getInodeID(barAfter))
  419. ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(newMtime))
  420. ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(newMtime))
  421. ExpectThat(barAfter.ModTime(), timeutil.TimeEq(newMtime))
  422. }
  423. ////////////////////////////////////////////////////////////////////////
  424. // Page cache
  425. ////////////////////////////////////////////////////////////////////////
  426. type PageCacheTest struct {
  427. cachingFSTest
  428. }
  429. var _ SetUpInterface = &PageCacheTest{}
  430. func init() { RegisterTestSuite(&PageCacheTest{}) }
  431. func (t *PageCacheTest) SetUp(ti *TestInfo) {
  432. const (
  433. lookupEntryTimeout = 0
  434. getattrTimeout = 0
  435. )
  436. t.cachingFSTest.setUp(ti, lookupEntryTimeout, getattrTimeout)
  437. }
  438. func (t *PageCacheTest) SingleFileHandle_NoKeepCache() {
  439. t.fs.SetKeepCache(false)
  440. // Open the file.
  441. f, err := os.Open(path.Join(t.Dir, "foo"))
  442. AssertEq(nil, err)
  443. defer f.Close()
  444. // Read its contents once.
  445. f.Seek(0, 0)
  446. AssertEq(nil, err)
  447. c1, err := ioutil.ReadAll(f)
  448. AssertEq(nil, err)
  449. AssertEq(cachingfs.FooSize, len(c1))
  450. // And again.
  451. f.Seek(0, 0)
  452. AssertEq(nil, err)
  453. c2, err := ioutil.ReadAll(f)
  454. AssertEq(nil, err)
  455. AssertEq(cachingfs.FooSize, len(c2))
  456. // We should have seen the same contents each time.
  457. ExpectTrue(bytes.Equal(c1, c2))
  458. }
  459. func (t *PageCacheTest) SingleFileHandle_KeepCache() {
  460. t.fs.SetKeepCache(true)
  461. // Open the file.
  462. f, err := os.Open(path.Join(t.Dir, "foo"))
  463. AssertEq(nil, err)
  464. defer f.Close()
  465. // Read its contents once.
  466. f.Seek(0, 0)
  467. AssertEq(nil, err)
  468. c1, err := ioutil.ReadAll(f)
  469. AssertEq(nil, err)
  470. AssertEq(cachingfs.FooSize, len(c1))
  471. // And again.
  472. f.Seek(0, 0)
  473. AssertEq(nil, err)
  474. c2, err := ioutil.ReadAll(f)
  475. AssertEq(nil, err)
  476. AssertEq(cachingfs.FooSize, len(c2))
  477. // We should have seen the same contents each time.
  478. ExpectTrue(bytes.Equal(c1, c2))
  479. }
  480. func (t *PageCacheTest) TwoFileHandles_NoKeepCache() {
  481. t.fs.SetKeepCache(false)
  482. // SetKeepCache(false) doesn't work on OS X. See the notes on
  483. // OpenFileOp.KeepPageCache.
  484. if runtime.GOOS == "darwin" {
  485. return
  486. }
  487. // Open the file.
  488. f1, err := os.Open(path.Join(t.Dir, "foo"))
  489. AssertEq(nil, err)
  490. defer f1.Close()
  491. // Read its contents once.
  492. f1.Seek(0, 0)
  493. AssertEq(nil, err)
  494. c1, err := ioutil.ReadAll(f1)
  495. AssertEq(nil, err)
  496. AssertEq(cachingfs.FooSize, len(c1))
  497. // Open a second handle.
  498. f2, err := os.Open(path.Join(t.Dir, "foo"))
  499. AssertEq(nil, err)
  500. defer f2.Close()
  501. // We should see different contents if we read from that handle, due to the
  502. // cache being invalidated at the time of opening.
  503. f2.Seek(0, 0)
  504. AssertEq(nil, err)
  505. c2, err := ioutil.ReadAll(f2)
  506. AssertEq(nil, err)
  507. AssertEq(cachingfs.FooSize, len(c2))
  508. ExpectFalse(bytes.Equal(c1, c2))
  509. // Another read from the second handle should give the same result as the
  510. // first one from that handle.
  511. f2.Seek(0, 0)
  512. AssertEq(nil, err)
  513. c3, err := ioutil.ReadAll(f2)
  514. AssertEq(nil, err)
  515. AssertEq(cachingfs.FooSize, len(c3))
  516. ExpectTrue(bytes.Equal(c2, c3))
  517. // And another read from the first handle should give the same result yet
  518. // again.
  519. f1.Seek(0, 0)
  520. AssertEq(nil, err)
  521. c4, err := ioutil.ReadAll(f1)
  522. AssertEq(nil, err)
  523. AssertEq(cachingfs.FooSize, len(c4))
  524. ExpectTrue(bytes.Equal(c2, c4))
  525. }
  526. func (t *PageCacheTest) TwoFileHandles_KeepCache() {
  527. t.fs.SetKeepCache(true)
  528. // Open the file.
  529. f1, err := os.Open(path.Join(t.Dir, "foo"))
  530. AssertEq(nil, err)
  531. defer f1.Close()
  532. // Read its contents once.
  533. f1.Seek(0, 0)
  534. AssertEq(nil, err)
  535. c1, err := ioutil.ReadAll(f1)
  536. AssertEq(nil, err)
  537. AssertEq(cachingfs.FooSize, len(c1))
  538. // Open a second handle.
  539. f2, err := os.Open(path.Join(t.Dir, "foo"))
  540. AssertEq(nil, err)
  541. defer f2.Close()
  542. // We should see the same contents when we read via the second handle.
  543. f2.Seek(0, 0)
  544. AssertEq(nil, err)
  545. c2, err := ioutil.ReadAll(f2)
  546. AssertEq(nil, err)
  547. AssertEq(cachingfs.FooSize, len(c2))
  548. ExpectTrue(bytes.Equal(c1, c2))
  549. // Ditto if we read again from the first.
  550. f1.Seek(0, 0)
  551. AssertEq(nil, err)
  552. c3, err := ioutil.ReadAll(f1)
  553. AssertEq(nil, err)
  554. AssertEq(cachingfs.FooSize, len(c3))
  555. ExpectTrue(bytes.Equal(c1, c3))
  556. }