func (t *AttributeCachingTest) StatStat() { fooBefore, dirBefore, barBefore := t.statAll() fooAfter, dirAfter, barAfter := t.statAll() // Make sure everything matches. ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(fooBefore.ModTime())) ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(dirBefore.ModTime())) ExpectThat(barAfter.ModTime(), timeutil.TimeEq(barBefore.ModTime())) ExpectEq(getInodeID(fooBefore), getInodeID(fooAfter)) ExpectEq(getInodeID(dirBefore), getInodeID(dirAfter)) ExpectEq(getInodeID(barBefore), getInodeID(barAfter)) }
func (t *EntryCachingTest) StatMtimeStat() { newMtime := t.initialMtime.Add(time.Second) t.statAll() t.fs.SetMtime(newMtime) fooAfter, dirAfter, barAfter := t.statAll() // We should see the new mtimes, because the attributes should not have been // cached. ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(newMtime)) ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(newMtime)) ExpectThat(barAfter.ModTime(), timeutil.TimeEq(newMtime)) }
func (t *FileTest) InitialAttributes() { attrs, err := t.in.Attributes(t.ctx) AssertEq(nil, err) ExpectEq(len(t.initialContents), attrs.Size) ExpectEq(1, attrs.Nlink) ExpectEq(uid, attrs.Uid) ExpectEq(gid, attrs.Gid) ExpectEq(fileMode, attrs.Mode) ExpectThat(attrs.Atime, timeutil.TimeEq(t.backingObj.Updated)) ExpectThat(attrs.Ctime, timeutil.TimeEq(t.backingObj.Updated)) ExpectThat(attrs.Mtime, timeutil.TimeEq(t.backingObj.Updated)) }
func (t *TempFileTest) SetMtime() { mtime := time.Date(2015, 4, 5, 2, 15, 0, 0, time.Local) AssertThat(mtime, Not(timeutil.TimeEq(t.clock.Now()))) // Set. t.tf.SetMtime(mtime) // Check. sr, err := t.tf.Stat() AssertEq(nil, err) ExpectThat(sr.Mtime, Pointee(timeutil.TimeEq(mtime))) }
func (t *StatObjectTest) WrappedSucceeds() { const name = "taco" // LookUp ExpectCall(t.cache, "LookUp")(Any(), Any()). WillOnce(Return(false, nil)) // Wrapped obj := &gcs.Object{ Name: name, } ExpectCall(t.wrapped, "StatObject")(Any(), Any()). WillOnce(Return(obj, nil)) // Insert ExpectCall(t.cache, "Insert")(obj, timeutil.TimeEq(t.clock.Now().Add(ttl))) // Call req := &gcs.StatObjectRequest{ Name: name, } o, err := t.bucket.StatObject(nil, req) AssertEq(nil, err) ExpectEq(obj, o) }
func (t *AttributeCachingTest) StatMtimeStat_ViaPath() { newMtime := t.initialMtime.Add(time.Second) t.statAll() t.fs.SetMtime(newMtime) fooAfter, dirAfter, barAfter := t.statAll() // Since we don't have entry caching enabled, the call above had to look up // the entry again. With the lookup we returned new attributes, so it's // possible that the mtime will be fresh. On Linux it appears to be, and on // OS X it appears to not be. m := AnyOf(timeutil.TimeEq(newMtime), timeutil.TimeEq(t.initialMtime)) ExpectThat(fooAfter.ModTime(), m) ExpectThat(dirAfter.ModTime(), m) ExpectThat(barAfter.ModTime(), m) }
func (t *UpdateObjectTest) WrappedSucceeds() { const name = "taco" var err error // Erase ExpectCall(t.cache, "Erase")(Any()) // Wrapped obj := &gcs.Object{ Name: name, Generation: 1234, } ExpectCall(t.wrapped, "UpdateObject")(Any(), Any()). WillOnce(Return(obj, nil)) // Insert ExpectCall(t.cache, "Insert")(obj, timeutil.TimeEq(t.clock.Now().Add(ttl))) // Call o, err := t.bucket.UpdateObject(nil, &gcs.UpdateObjectRequest{}) AssertEq(nil, err) ExpectEq(obj, o) }
func (t *FileTest) Write() { var data []byte var err error AssertEq("taco", t.initialContents) // Overwite a byte. err = t.in.Write(t.ctx, []byte("p"), 0) AssertEq(nil, err) // Add some data at the end. t.clock.AdvanceTime(time.Second) writeTime := t.clock.Now() err = t.in.Write(t.ctx, []byte("burrito"), 4) AssertEq(nil, err) t.clock.AdvanceTime(time.Second) // Read back the content. data, err = t.in.Read(t.ctx, 0, 1024) AssertEq(nil, err) ExpectEq("pacoburrito", string(data)) // Check attributes. attrs, err := t.in.Attributes(t.ctx) AssertEq(nil, err) ExpectEq(len("pacoburrito"), attrs.Size) ExpectThat(attrs.Mtime, timeutil.TimeEq(writeTime)) }
func (t *FileTest) TruncateUpwardThenSync() { var attrs fuseops.InodeAttributes var err error AssertEq(4, len(t.initialContents)) // Truncate upward. err = t.in.Truncate(t.ctx, 6) AssertEq(nil, err) t.clock.AdvanceTime(time.Second) // Sync. err = t.in.Sync(t.ctx) AssertEq(nil, err) // The generation should have advanced. ExpectLt(t.backingObj.Generation, t.in.SourceGeneration()) // Stat the current object in the bucket. statReq := &gcs.StatObjectRequest{Name: t.in.Name()} o, err := t.bucket.StatObject(t.ctx, statReq) AssertEq(nil, err) ExpectEq(t.in.SourceGeneration(), o.Generation) ExpectEq(6, o.Size) // Check attributes. attrs, err = t.in.Attributes(t.ctx) AssertEq(nil, err) ExpectEq(6, attrs.Size) ExpectThat(attrs.Mtime, timeutil.TimeEq(o.Updated)) }
func (t *FileTest) Truncate() { var attrs fuseops.InodeAttributes var err error AssertEq("taco", t.initialContents) // Truncate downward. t.clock.AdvanceTime(time.Second) truncateTime := t.clock.Now() err = t.in.Truncate(t.ctx, 2) AssertEq(nil, err) t.clock.AdvanceTime(time.Second) // Read the contents. var buf [1024]byte n, err := t.in.Read(t.ctx, buf[:], 0) if err == io.EOF { err = nil } AssertEq(nil, err) ExpectEq("ta", string(buf[:n])) // Check attributes. attrs, err = t.in.Attributes(t.ctx) AssertEq(nil, err) ExpectEq(len("ta"), attrs.Size) ExpectThat(attrs.Mtime, timeutil.TimeEq(truncateTime)) }
func (t *FileTest) SetMtime_ContentClean() { var err error var attrs fuseops.InodeAttributes // Cause the content to be faulted in. _, err = t.in.Read(t.ctx, make([]byte, 1), 0) AssertEq(nil, err) // Set mtime. mtime := time.Now().UTC().Add(123 * time.Second) err = t.in.SetMtime(t.ctx, mtime) AssertEq(nil, err) // The inode should agree about the new mtime. attrs, err = t.in.Attributes(t.ctx) AssertEq(nil, err) ExpectThat(attrs.Mtime, timeutil.TimeEq(mtime)) // The inode should have added the mtime to the backing object's metadata. statReq := &gcs.StatObjectRequest{Name: t.in.Name()} o, err := t.bucket.StatObject(t.ctx, statReq) AssertEq(nil, err) ExpectEq( mtime.UTC().Format(time.RFC3339Nano), o.Metadata["gcsfuse_mtime"]) }
func (t *StatObjectTest) WrappedSaysNotFound() { const name = "taco" // LookUp ExpectCall(t.cache, "LookUp")(Any(), Any()). WillOnce(Return(false, nil)) // Wrapped ExpectCall(t.wrapped, "StatObject")(Any(), Any()). WillOnce(Return(nil, &gcs.NotFoundError{Err: errors.New("burrito")})) // AddNegativeEntry ExpectCall(t.cache, "AddNegativeEntry")( name, timeutil.TimeEq(t.clock.Now().Add(ttl))) // Call req := &gcs.StatObjectRequest{ Name: name, } _, err := t.bucket.StatObject(nil, req) ExpectThat(err, HasSameTypeAs(&gcs.NotFoundError{})) ExpectThat(err, Error(HasSubstr("burrito"))) }
func (t *ComposeObjectsTest) WrappedSucceeds() { const srcName = "taco" const dstName = "burrito" var err error // Erase ExpectCall(t.cache, "Erase")(Any()) // Wrapped obj := &gcs.Object{ Name: dstName, Generation: 1234, } ExpectCall(t.wrapped, "ComposeObjects")(Any(), Any()). WillOnce(Return(obj, nil)) // Insert ExpectCall(t.cache, "Insert")(obj, timeutil.TimeEq(t.clock.Now().Add(ttl))) // Call o, err := t.bucket.ComposeObjects(nil, &gcs.ComposeObjectsRequest{}) AssertEq(nil, err) ExpectEq(obj, o) }
func (t *FileTest) SetMtime_ContentDirty() { var err error var attrs fuseops.InodeAttributes // Dirty the content. err = t.in.Write(t.ctx, []byte("a"), 0) AssertEq(nil, err) // Set mtime. mtime := time.Now().UTC().Add(123 * time.Second) err = t.in.SetMtime(t.ctx, mtime) AssertEq(nil, err) // The inode should agree about the new mtime. attrs, err = t.in.Attributes(t.ctx) AssertEq(nil, err) ExpectThat(attrs.Mtime, timeutil.TimeEq(mtime)) // Sync. err = t.in.Sync(t.ctx) AssertEq(nil, err) // Now the object in the bucket should have the appropriate mtime. statReq := &gcs.StatObjectRequest{Name: t.in.Name()} o, err := t.bucket.StatObject(t.ctx, statReq) AssertEq(nil, err) ExpectEq( mtime.UTC().Format(time.RFC3339Nano), o.Metadata["gcsfuse_mtime"]) }
func (t *TempFileTest) WriteAt() { // Call p := []byte("fo") n, err := t.tf.WriteAt(p, 1) ExpectEq(2, n) ExpectEq(nil, err) // Check Stat. sr, err := t.tf.Stat() AssertEq(nil, err) ExpectEq(initialContentSize, sr.Size) ExpectEq(1, sr.DirtyThreshold) ExpectThat(sr.Mtime, Pointee(timeutil.TimeEq(t.clock.Now()))) // Read back. expected := []byte(initialContent) expected[1] = 'f' expected[2] = 'o' actual, err := readAll(&t.tf) AssertEq(nil, err) ExpectEq(string(expected), string(actual)) }
func (t *NoCachingTest) StatRenumberMtimeStat() { newMtime := t.initialMtime.Add(time.Second) t.statAll() t.fs.RenumberInodes() t.fs.SetMtime(newMtime) fooAfter, dirAfter, barAfter := t.statAll() // We should see the new inode IDs and mtimes, because nothing should have // been cached. ExpectEq(t.fs.FooID(), getInodeID(fooAfter)) ExpectEq(t.fs.DirID(), getInodeID(dirAfter)) ExpectEq(t.fs.BarID(), getInodeID(barAfter)) ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(newMtime)) ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(newMtime)) ExpectThat(barAfter.ModTime(), timeutil.TimeEq(newMtime)) }
func (t *AttributeCachingTest) StatRenumberMtimeStat_ViaPath() { newMtime := t.initialMtime.Add(time.Second) t.statAll() t.fs.RenumberInodes() t.fs.SetMtime(newMtime) fooAfter, dirAfter, barAfter := t.statAll() // We should see new everything, because this is the first time the new // inodes have been encountered. Entries for the old ones should not have // been cached, because we have entry caching disabled. ExpectEq(t.fs.FooID(), getInodeID(fooAfter)) ExpectEq(t.fs.DirID(), getInodeID(dirAfter)) ExpectEq(t.fs.BarID(), getInodeID(barAfter)) ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(newMtime)) ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(newMtime)) ExpectThat(barAfter.ModTime(), timeutil.TimeEq(newMtime)) }
func (t *BasicsTest) StatDir() { fi, err := os.Stat(path.Join(t.Dir, "dir")) AssertEq(nil, err) ExpectEq("dir", fi.Name()) ExpectEq(os.ModeDir|0777, fi.Mode()) ExpectThat(fi.ModTime(), timeutil.TimeEq(t.initialMtime)) ExpectTrue(fi.IsDir()) ExpectEq(t.fs.DirID(), getInodeID(fi)) ExpectEq(1, fi.Sys().(*syscall.Stat_t).Nlink) }
func (t *BasicsTest) StatBar() { fi, err := os.Stat(path.Join(t.Dir, "dir/bar")) AssertEq(nil, err) ExpectEq("bar", fi.Name()) ExpectEq(cachingfs.BarSize, fi.Size()) ExpectEq(0777, fi.Mode()) ExpectThat(fi.ModTime(), timeutil.TimeEq(t.initialMtime)) ExpectFalse(fi.IsDir()) ExpectEq(t.fs.BarID(), getInodeID(fi)) ExpectEq(1, fi.Sys().(*syscall.Stat_t).Nlink) }
func (t *AttributeCachingTest) StatMtimeStat_ViaFileDescriptor() { newMtime := t.initialMtime.Add(time.Second) // Open everything, fixing a particular inode number for each. foo, dir, bar := t.openFiles() defer func() { foo.Close() dir.Close() bar.Close() }() fooBefore, dirBefore, barBefore := t.statFiles(foo, dir, bar) t.fs.SetMtime(newMtime) fooAfter, dirAfter, barAfter := t.statFiles(foo, dir, bar) // We should still see the old cached mtime. ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(fooBefore.ModTime())) ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(dirBefore.ModTime())) ExpectThat(barAfter.ModTime(), timeutil.TimeEq(barBefore.ModTime())) // After waiting for the attribute cache to expire, we should see the fresh // mtime. time.Sleep(2 * t.getattrTimeout) fooAfter, dirAfter, barAfter = t.statFiles(foo, dir, bar) ExpectThat(fooAfter.ModTime(), timeutil.TimeEq(newMtime)) ExpectThat(dirAfter.ModTime(), timeutil.TimeEq(newMtime)) ExpectThat(barAfter.ModTime(), timeutil.TimeEq(newMtime)) }
func (t *ListObjectsTest) NonEmptyListing() { // Wrapped o0 := &gcs.Object{Name: "taco"} o1 := &gcs.Object{Name: "burrito"} expected := &gcs.Listing{ Objects: []*gcs.Object{o0, o1}, } ExpectCall(t.wrapped, "ListObjects")(Any(), Any()). WillOnce(Return(expected, nil)) // Insert ExpectCall(t.cache, "Insert")(o0, timeutil.TimeEq(t.clock.Now().Add(ttl))) ExpectCall(t.cache, "Insert")(o1, timeutil.TimeEq(t.clock.Now().Add(ttl))) // Call listing, err := t.bucket.ListObjects(nil, &gcs.ListObjectsRequest{}) AssertEq(nil, err) ExpectEq(expected, listing) }
func (t *DirtyTest) Stat_LeaseSucceeds() { // Lease ExpectCall(t.rwl, "Size")(). WillOnce(Return(17, nil)) // Call sr, err := t.mc.Stat() AssertEq(nil, err) // Check the initial state. ExpectEq(17, sr.Size) ExpectEq(initialContentSize, sr.DirtyThreshold) ExpectThat(sr.Mtime, Pointee(timeutil.TimeEq(t.setUpTime))) }
func (t *StatObjectTest) CallsCache() { const name = "taco" // LookUp ExpectCall(t.cache, "LookUp")(name, timeutil.TimeEq(t.clock.Now())). WillOnce(Return(true, &gcs.Object{})) // Call req := &gcs.StatObjectRequest{ Name: name, } _, _ = t.bucket.StatObject(nil, req) }
func (t *FileTest) AppendThenSync() { var attrs fuseops.InodeAttributes var err error AssertEq("taco", t.initialContents) // Append some data. t.clock.AdvanceTime(time.Second) writeTime := t.clock.Now() err = t.in.Write(t.ctx, []byte("burrito"), int64(len("taco"))) AssertEq(nil, err) t.clock.AdvanceTime(time.Second) // Sync. err = t.in.Sync(t.ctx) AssertEq(nil, err) // The generation should have advanced. ExpectLt(t.backingObj.Generation, t.in.SourceGeneration().Object) // Stat the current object in the bucket. statReq := &gcs.StatObjectRequest{Name: t.in.Name()} o, err := t.bucket.StatObject(t.ctx, statReq) AssertEq(nil, err) ExpectEq(t.in.SourceGeneration().Object, o.Generation) ExpectEq(t.in.SourceGeneration().Metadata, o.MetaGeneration) ExpectEq(len("tacoburrito"), o.Size) ExpectEq( writeTime.UTC().Format(time.RFC3339Nano), o.Metadata["gcsfuse_mtime"]) // Read the object's contents. contents, err := gcsutil.ReadObject(t.ctx, t.bucket, t.in.Name()) AssertEq(nil, err) ExpectEq("tacoburrito", string(contents)) // Check attributes. attrs, err = t.in.Attributes(t.ctx) AssertEq(nil, err) ExpectEq(len("tacoburrito"), attrs.Size) ExpectThat(attrs.Mtime, timeutil.TimeEq(writeTime.UTC())) }
func (t *FileTest) InitialAttributes_MtimeFromObjectMetadata() { // Set up an explicit mtime on the backing object and re-create the inode. if t.backingObj.Metadata == nil { t.backingObj.Metadata = make(map[string]string) } mtime := time.Now().Add(123 * time.Second).UTC() t.backingObj.Metadata["gcsfuse_mtime"] = mtime.Format(time.RFC3339Nano) t.createInode() // Ask it for its attributes. attrs, err := t.in.Attributes(t.ctx) AssertEq(nil, err) ExpectThat(attrs.Mtime, timeutil.TimeEq(mtime)) }
func (t *DirtyTest) Truncate_LeaseSucceeds() { // Lease ExpectCall(t.rwl, "Truncate")(Any()). WillOnce(Return(nil)) // Call err := t.mc.Truncate(1) ExpectEq(nil, err) // The dirty threshold and mtime should have been updated. ExpectCall(t.rwl, "Size")(). WillRepeatedly(Return(0, nil)) sr, err := t.mc.Stat() AssertEq(nil, err) ExpectEq(1, sr.DirtyThreshold) ExpectThat(sr.Mtime, Pointee(timeutil.TimeEq(t.clock.Now()))) }
func (t *IntegrationTest) BackingObjectHasBeenOverwritten_AfterReading() { // Create. o, err := gcsutil.CreateObject(t.ctx, t.bucket, "foo", "taco") AssertEq(nil, err) t.create(o) // Fault in the contents. _, err = t.mc.ReadAt(t.ctx, []byte{}, 0) AssertEq(nil, err) // Overwrite the backing object. _, err = gcsutil.CreateObject(t.ctx, t.bucket, "foo", "burrito") AssertEq(nil, err) // Reading and modications should still work. _, err = t.mc.ReadAt(t.ctx, []byte{}, 0) AssertEq(nil, err) _, err = t.mc.WriteAt(t.ctx, []byte("a"), 0) AssertEq(nil, err) truncateTime := t.clock.Now() err = t.mc.Truncate(t.ctx, 3) AssertEq(nil, err) t.clock.AdvanceTime(time.Second) // Stat should see the current state. sr, err := t.mc.Stat(t.ctx) AssertEq(nil, err) ExpectEq(3, sr.Size) ExpectEq(0, sr.DirtyThreshold) ExpectThat(sr.Mtime, Pointee(timeutil.TimeEq(truncateTime))) // Sync should fail with a precondition error. _, _, err = t.sync(o) ExpectThat(err, HasSameTypeAs(&gcs.PreconditionError{})) // The newer version should still be present. contents, err := gcsutil.ReadObject(t.ctx, t.bucket, o.Name) AssertEq(nil, err) ExpectEq("burrito", string(contents)) }
func (t *IntegrationTest) BackingObjectHasBeenDeleted_AfterReading() { // Create. o, err := gcsutil.CreateObject(t.ctx, t.bucket, "foo", "taco") AssertEq(nil, err) t.create(o) // Fault in the contents. _, err = t.mc.ReadAt(t.ctx, []byte{}, 0) AssertEq(nil, err) // Delete the backing object. err = t.bucket.DeleteObject(t.ctx, &gcs.DeleteObjectRequest{Name: o.Name}) AssertEq(nil, err) // Reading and modications should still work. _, err = t.mc.ReadAt(t.ctx, []byte{}, 0) AssertEq(nil, err) _, err = t.mc.WriteAt(t.ctx, []byte("a"), 0) AssertEq(nil, err) truncateTime := t.clock.Now() err = t.mc.Truncate(t.ctx, 1) AssertEq(nil, err) t.clock.AdvanceTime(time.Second) // Stat should see the current state. sr, err := t.mc.Stat(t.ctx) AssertEq(nil, err) ExpectEq(1, sr.Size) ExpectEq(0, sr.DirtyThreshold) ExpectThat(sr.Mtime, Pointee(timeutil.TimeEq(truncateTime))) // Sync should fail with a precondition error. _, _, err = t.sync(o) ExpectThat(err, HasSameTypeAs(&gcs.PreconditionError{})) // Nothing should have been created. _, err = gcsutil.ReadObject(t.ctx, t.bucket, o.Name) ExpectThat(err, HasSameTypeAs(&gcs.NotFoundError{})) }
func (t *SyncerTest) CallsAppendCreator() { var err error // Append some data. _, err = t.content.WriteAt([]byte("burrito"), int64(t.srcObject.Size)) AssertEq(nil, err) // Set up an expected mtime. mtime := time.Now().Add(123 * time.Second) t.content.SetMtime(mtime) // Call t.call() AssertTrue(t.appendCreator.called) ExpectEq(t.srcObject, t.appendCreator.srcObject) ExpectThat(t.appendCreator.mtime, timeutil.TimeEq(mtime.UTC())) ExpectEq("burrito", string(t.appendCreator.contents)) }
func (t *SyncerTest) CallsFullCreator() { var err error AssertLt(2, t.srcObject.Size) // Ready the content. err = t.content.Truncate(2) AssertEq(nil, err) mtime := time.Now().Add(123 * time.Second) t.content.SetMtime(mtime) // Call t.call() AssertTrue(t.fullCreator.called) ExpectEq(t.srcObject, t.fullCreator.srcObject) ExpectThat(t.fullCreator.mtime, timeutil.TimeEq(mtime.UTC())) ExpectEq(srcObjectContents[:2], string(t.fullCreator.contents)) }