OpenFile updates timestamps correctly, i.e. on read(), write() and truncate(). Also added test cases for it.
This commit is contained in:
parent
06a5faf2f8
commit
6448110975
@ -34,7 +34,7 @@ unique_ref<parallelaccessfsblobstore::FileBlobRef> CryFile::LoadBlob() const {
|
||||
return std::move(*file_blob);
|
||||
}
|
||||
|
||||
unique_ref<fspp::OpenFile> CryFile::open(int flags) const {
|
||||
unique_ref<fspp::OpenFile> CryFile::open(int flags) {
|
||||
// TODO Should we honor open flags?
|
||||
UNUSED(flags);
|
||||
device()->callFsActionCallbacks();
|
||||
@ -42,7 +42,7 @@ unique_ref<fspp::OpenFile> CryFile::open(int flags) const {
|
||||
return make_unique_ref<CryOpenFile>(device(), parent(), std::move(blob));
|
||||
}
|
||||
|
||||
void CryFile::truncate(off_t size) const {
|
||||
void CryFile::truncate(off_t size) {
|
||||
device()->callFsActionCallbacks();
|
||||
auto blob = LoadBlob();
|
||||
blob->resize(size);
|
||||
|
@ -14,8 +14,8 @@ public:
|
||||
CryFile(CryDevice *device, cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> parent, const blockstore::Key &key);
|
||||
~CryFile();
|
||||
|
||||
cpputils::unique_ref<fspp::OpenFile> open(int flags) const override;
|
||||
void truncate(off_t size) const override;
|
||||
cpputils::unique_ref<fspp::OpenFile> open(int flags) override;
|
||||
void truncate(off_t size) override;
|
||||
fspp::Dir::EntryType getType() const override;
|
||||
void remove() override;
|
||||
|
||||
|
@ -52,6 +52,11 @@ shared_ptr<const DirBlobRef> CryNode::parent() const {
|
||||
return *_parent;
|
||||
}
|
||||
|
||||
shared_ptr<DirBlobRef> CryNode::parent() {
|
||||
ASSERT(_parent != none, "We are the root directory and can't get the parent of the root directory");
|
||||
return *_parent;
|
||||
}
|
||||
|
||||
void CryNode::rename(const bf::path &to) {
|
||||
device()->callFsActionCallbacks();
|
||||
if (_parent == none) {
|
||||
|
@ -29,6 +29,7 @@ protected:
|
||||
const CryDevice *device() const;
|
||||
cpputils::unique_ref<parallelaccessfsblobstore::FsBlobRef> LoadBlob() const;
|
||||
std::shared_ptr<const parallelaccessfsblobstore::DirBlobRef> parent() const;
|
||||
std::shared_ptr<parallelaccessfsblobstore::DirBlobRef> parent();
|
||||
|
||||
virtual fspp::Dir::EntryType getType() const = 0;
|
||||
|
||||
|
@ -19,7 +19,7 @@ using fspp::fuse::FuseErrnoException;
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
CryOpenFile::CryOpenFile(const CryDevice *device, shared_ptr<const DirBlobRef> parent, unique_ref<FileBlobRef> fileBlob)
|
||||
CryOpenFile::CryOpenFile(const CryDevice *device, shared_ptr<DirBlobRef> parent, unique_ref<FileBlobRef> fileBlob)
|
||||
: _device(device), _parent(parent), _fileBlob(std::move(fileBlob)) {
|
||||
}
|
||||
|
||||
@ -41,15 +41,18 @@ void CryOpenFile::stat(struct ::stat *result) const {
|
||||
void CryOpenFile::truncate(off_t size) const {
|
||||
_device->callFsActionCallbacks();
|
||||
_fileBlob->resize(size);
|
||||
_parent->updateModificationTimestampForChild(_fileBlob->key());
|
||||
}
|
||||
|
||||
size_t CryOpenFile::read(void *buf, size_t count, off_t offset) const {
|
||||
_device->callFsActionCallbacks();
|
||||
_parent->updateAccessTimestampForChild(_fileBlob->key());
|
||||
return _fileBlob->read(buf, offset, count);
|
||||
}
|
||||
|
||||
void CryOpenFile::write(const void *buf, size_t count, off_t offset) {
|
||||
_device->callFsActionCallbacks();
|
||||
_parent->updateModificationTimestampForChild(_fileBlob->key());
|
||||
_fileBlob->write(buf, offset, count);
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ class CryDevice;
|
||||
|
||||
class CryOpenFile final: public fspp::OpenFile {
|
||||
public:
|
||||
explicit CryOpenFile(const CryDevice *device, std::shared_ptr<const parallelaccessfsblobstore::DirBlobRef> parent, cpputils::unique_ref<parallelaccessfsblobstore::FileBlobRef> fileBlob);
|
||||
explicit CryOpenFile(const CryDevice *device, std::shared_ptr<parallelaccessfsblobstore::DirBlobRef> parent, cpputils::unique_ref<parallelaccessfsblobstore::FileBlobRef> fileBlob);
|
||||
~CryOpenFile();
|
||||
|
||||
void stat(struct ::stat *result) const override;
|
||||
@ -24,7 +24,7 @@ public:
|
||||
|
||||
private:
|
||||
const CryDevice *_device;
|
||||
std::shared_ptr<const parallelaccessfsblobstore::DirBlobRef> _parent;
|
||||
std::shared_ptr<parallelaccessfsblobstore::DirBlobRef> _parent;
|
||||
cpputils::unique_ref<parallelaccessfsblobstore::FileBlobRef> _fileBlob;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CryOpenFile);
|
||||
|
@ -60,6 +60,14 @@ public:
|
||||
return _base->statChildExceptSize(key, result);
|
||||
}
|
||||
|
||||
void updateAccessTimestampForChild(const blockstore::Key &key) {
|
||||
return _base->updateAccessTimestampForChild(key);
|
||||
}
|
||||
|
||||
void updateModificationTimestampForChild(const blockstore::Key &key) {
|
||||
return _base->updateModificationTimestampForChild(key);
|
||||
}
|
||||
|
||||
void chmodChild(const blockstore::Key &key, mode_t mode) {
|
||||
return _base->chmodChild(key, mode);
|
||||
}
|
||||
|
@ -158,6 +158,16 @@ void DirBlob::statChildExceptSize(const Key &key, struct ::stat *result) const {
|
||||
result->st_blksize = _fsBlobStore->virtualBlocksizeBytes();
|
||||
}
|
||||
|
||||
void DirBlob::updateAccessTimestampForChild(const Key &key) {
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
_entries.updateAccessTimestampForChild(key);
|
||||
}
|
||||
|
||||
void DirBlob::updateModificationTimestampForChild(const Key &key) {
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
_entries.updateModificationTimestampForChild(key);
|
||||
}
|
||||
|
||||
void DirBlob::chmodChild(const Key &key, mode_t mode) {
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
_entries.setMode(key, mode);
|
||||
|
@ -59,6 +59,10 @@ namespace cryfs {
|
||||
|
||||
void statChildExceptSize(const blockstore::Key &key, struct ::stat *result) const;
|
||||
|
||||
void updateAccessTimestampForChild(const blockstore::Key &key);
|
||||
|
||||
void updateModificationTimestampForChild(const blockstore::Key &key);
|
||||
|
||||
void chmodChild(const blockstore::Key &key, mode_t mode);
|
||||
|
||||
void chownChild(const blockstore::Key &key, uid_t uid, gid_t gid);
|
||||
|
@ -228,5 +228,15 @@ void DirEntryList::setAccessTimes(const blockstore::Key &key, timespec lastAcces
|
||||
found->setLastModificationTime(lastModificationTime);
|
||||
}
|
||||
|
||||
void DirEntryList::updateAccessTimestampForChild(const blockstore::Key &key) {
|
||||
auto found = _findByKey(key);
|
||||
found->setLastAccessTime(cpputils::time::now());
|
||||
}
|
||||
|
||||
void DirEntryList::updateModificationTimestampForChild(const blockstore::Key &key) {
|
||||
auto found = _findByKey(key);
|
||||
found->setLastModificationTime(cpputils::time::now());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,8 @@ namespace cryfs {
|
||||
void setMode(const blockstore::Key &key, mode_t mode);
|
||||
bool setUidGid(const blockstore::Key &key, uid_t uid, gid_t gid);
|
||||
void setAccessTimes(const blockstore::Key &key, timespec lastAccessTime, timespec lastModificationTime);
|
||||
void updateAccessTimestampForChild(const blockstore::Key &key);
|
||||
void updateModificationTimestampForChild(const blockstore::Key &key);
|
||||
|
||||
private:
|
||||
uint64_t _serializedSize() const;
|
||||
|
@ -56,6 +56,14 @@ public:
|
||||
return _base->statChildExceptSize(key, result);
|
||||
}
|
||||
|
||||
void updateAccessTimestampForChild(const blockstore::Key &key) {
|
||||
return _base->updateAccessTimestampForChild(key);
|
||||
}
|
||||
|
||||
void updateModificationTimestampForChild(const blockstore::Key &key) {
|
||||
return _base->updateModificationTimestampForChild(key);
|
||||
}
|
||||
|
||||
void chmodChild(const blockstore::Key &key, mode_t mode) {
|
||||
return _base->chmodChild(key, mode);
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ class File: public virtual Node {
|
||||
public:
|
||||
virtual ~File() {}
|
||||
|
||||
virtual cpputils::unique_ref<OpenFile> open(int flags) const = 0;
|
||||
virtual void truncate(off_t size) const = 0;
|
||||
virtual cpputils::unique_ref<OpenFile> open(int flags) = 0;
|
||||
virtual void truncate(off_t size) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -9,9 +9,10 @@
|
||||
#include "FsppSymlinkTest.h"
|
||||
#include "FsppNodeTest_Rename.h"
|
||||
#include "FsppNodeTest_Stat.h"
|
||||
#include "FsppNodeTest_Timestamps.h"
|
||||
#include "FsppOpenFileTest.h"
|
||||
#include "FsppDeviceTest_Timestamps.h"
|
||||
#include "FsppNodeTest_Timestamps.h"
|
||||
#include "FsppOpenFileTest_Timestamps.h"
|
||||
|
||||
#define FSPP_ADD_FILESYTEM_TESTS(FS_NAME, FIXTURE) \
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppDeviceTest, FIXTURE); \
|
||||
@ -26,5 +27,7 @@
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppNodeTest_Stat_DirOnly, FIXTURE); \
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppNodeTest_Stat_SymlinkOnly, FIXTURE); \
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppOpenFileTest, FIXTURE); \
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppOpenFileTest_Timestamps, FIXTURE); \
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -24,54 +24,54 @@ public:
|
||||
|
||||
void Test_Truncate_DontChange1(fspp::File *file) {
|
||||
file->truncate(0);
|
||||
this->EXPECT_SIZE(0, *file);
|
||||
this->EXPECT_SIZE(0, file);
|
||||
}
|
||||
|
||||
void Test_Truncate_GrowTo1(fspp::File *file) {
|
||||
file->truncate(1);
|
||||
this->EXPECT_SIZE(1, *file);
|
||||
this->EXPECT_SIZE(1, file);
|
||||
}
|
||||
|
||||
void Test_Truncate_Grow(fspp::File *file) {
|
||||
file->truncate(10*1024*1024);
|
||||
this->EXPECT_SIZE(10*1024*1024, *file);
|
||||
this->EXPECT_SIZE(10*1024*1024, file);
|
||||
}
|
||||
|
||||
void Test_Truncate_DontChange2(fspp::File *file) {
|
||||
file->truncate(10*1024*1024);
|
||||
file->truncate(10*1024*1024);
|
||||
this->EXPECT_SIZE(10*1024*1024, *file);
|
||||
this->EXPECT_SIZE(10*1024*1024, file);
|
||||
}
|
||||
|
||||
void Test_Truncate_Shrink(fspp::File *file) {
|
||||
file->truncate(10*1024*1024);
|
||||
file->truncate(5*1024*1024);
|
||||
this->EXPECT_SIZE(5*1024*1024, *file);
|
||||
this->EXPECT_SIZE(5*1024*1024, file);
|
||||
}
|
||||
|
||||
void Test_Truncate_ShrinkTo0(fspp::File *file) {
|
||||
file->truncate(10*1024*1024);
|
||||
file->truncate(0);
|
||||
this->EXPECT_SIZE(0, *file);
|
||||
this->EXPECT_SIZE(0, file);
|
||||
}
|
||||
|
||||
void Test_Chown_Uid(fspp::File *file) {
|
||||
file->chown(100, 200);
|
||||
this->IN_STAT(*file, [] (struct stat st){
|
||||
this->IN_STAT(file, [] (struct stat st){
|
||||
EXPECT_EQ(100u, st.st_uid);
|
||||
});
|
||||
}
|
||||
|
||||
void Test_Chown_Gid(fspp::File *file) {
|
||||
file->chown(100, 200);
|
||||
this->IN_STAT(*file, [] (struct stat st){
|
||||
this->IN_STAT(file, [] (struct stat st){
|
||||
EXPECT_EQ(200u, st.st_gid);
|
||||
});
|
||||
}
|
||||
|
||||
void Test_Chmod(fspp::File *file) {
|
||||
file->chmod(S_IFREG | S_IRUSR | S_IWOTH);
|
||||
this->IN_STAT(*file, [] (struct stat st){
|
||||
this->IN_STAT(file, [] (struct stat st){
|
||||
EXPECT_EQ((mode_t)(S_IFREG | S_IRUSR | S_IWOTH), st.st_mode);
|
||||
});
|
||||
}
|
||||
@ -80,7 +80,7 @@ public:
|
||||
struct timespec ATIME; ATIME.tv_sec = 1458086400; ATIME.tv_nsec = 34525;
|
||||
struct timespec MTIME; MTIME.tv_sec = 1458086300; MTIME.tv_nsec = 48293;
|
||||
file->utimens(ATIME, MTIME);
|
||||
this->IN_STAT(*file, [this, ATIME, MTIME] (struct stat st) {
|
||||
this->IN_STAT(file, [this, ATIME, MTIME] (struct stat st) {
|
||||
this->EXPECT_ATIME_EQ(ATIME, st);
|
||||
this->EXPECT_MTIME_EQ(MTIME, st);
|
||||
});
|
||||
|
@ -10,7 +10,7 @@ class FsppNodeTest_Stat: public FsppNodeTest<ConcreteFileSystemTestFixture> {
|
||||
public:
|
||||
void Test_Nlink() {
|
||||
auto node = this->CreateNode("/mynode");
|
||||
this->IN_STAT(*node, [] (struct stat st) {
|
||||
this->IN_STAT(node.get(), [] (struct stat st) {
|
||||
EXPECT_EQ(1u, st.st_nlink);
|
||||
});
|
||||
}
|
||||
@ -24,12 +24,12 @@ TYPED_TEST_CASE_P(FsppNodeTest_Stat_FileOnly);
|
||||
|
||||
TYPED_TEST_P(FsppNodeTest_Stat_FileOnly, CreatedFileIsEmpty) {
|
||||
auto file = this->CreateFile("/myfile");
|
||||
this->EXPECT_SIZE(0, *file);
|
||||
this->EXPECT_SIZE(0, file.get());
|
||||
}
|
||||
|
||||
TYPED_TEST_P(FsppNodeTest_Stat_FileOnly, FileIsFile) {
|
||||
auto file = this->CreateFile("/myfile");
|
||||
this->IN_STAT(*file, [] (struct stat st) {
|
||||
this->IN_STAT(file.get(), [] (struct stat st) {
|
||||
EXPECT_TRUE(S_ISREG(st.st_mode));
|
||||
});
|
||||
}
|
||||
@ -42,7 +42,7 @@ TYPED_TEST_CASE_P(FsppNodeTest_Stat_DirOnly);
|
||||
|
||||
TYPED_TEST_P(FsppNodeTest_Stat_DirOnly, DirIsDir) {
|
||||
auto file = this->CreateDir("/mydir");
|
||||
this->IN_STAT(*file, [] (struct stat st) {
|
||||
this->IN_STAT(file.get(), [] (struct stat st) {
|
||||
EXPECT_TRUE(S_ISDIR(st.st_mode));
|
||||
});
|
||||
}
|
||||
@ -55,7 +55,7 @@ TYPED_TEST_CASE_P(FsppNodeTest_Stat_SymlinkOnly);
|
||||
|
||||
TYPED_TEST_P(FsppNodeTest_Stat_SymlinkOnly, SymlinkIsSymlink) {
|
||||
auto file = this->CreateSymlink("/mysymlink");
|
||||
this->IN_STAT(*file, [] (struct stat st) {
|
||||
this->IN_STAT(file.get(), [] (struct stat st) {
|
||||
EXPECT_TRUE(S_ISLNK(st.st_mode));
|
||||
});
|
||||
}
|
||||
|
149
src/fspp/fstest/FsppOpenFileTest_Timestamps.h
Normal file
149
src/fspp/fstest/FsppOpenFileTest_Timestamps.h
Normal file
@ -0,0 +1,149 @@
|
||||
#pragma once
|
||||
#ifndef MESSMER_FSPP_FSTEST_FSPPOPENFILETEST_TIMESTAMPS_H_
|
||||
#define MESSMER_FSPP_FSTEST_FSPPOPENFILETEST_TIMESTAMPS_H_
|
||||
|
||||
#include "testutils/TimestampTestUtils.h"
|
||||
|
||||
template<class ConcreteFileSystemTestFixture>
|
||||
class FsppOpenFileTest_Timestamps: public FileSystemTest<ConcreteFileSystemTestFixture>, public TimestampTestUtils<fspp::OpenFile> {
|
||||
public:
|
||||
cpputils::unique_ref<fspp::OpenFile> CreateAndOpenFile(const boost::filesystem::path &path) {
|
||||
return this->CreateFile(path)->open(O_RDWR);
|
||||
}
|
||||
cpputils::unique_ref<fspp::OpenFile> CreateAndOpenFileWithSize(const boost::filesystem::path &path, off_t size) {
|
||||
auto file = this->CreateFile(path);
|
||||
file->truncate(size);
|
||||
auto openFile = file->open(O_RDWR);
|
||||
assert(stat(*openFile).st_size == size);
|
||||
return openFile;
|
||||
}
|
||||
};
|
||||
TYPED_TEST_CASE_P(FsppOpenFileTest_Timestamps);
|
||||
|
||||
TYPED_TEST_P(FsppOpenFileTest_Timestamps, stat) {
|
||||
auto openFile = this->CreateAndOpenFile("/mynode");
|
||||
auto operation = [&openFile] () {
|
||||
struct ::stat st;
|
||||
openFile->stat(&st);
|
||||
};
|
||||
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAnyTimestamps});
|
||||
}
|
||||
|
||||
TYPED_TEST_P(FsppOpenFileTest_Timestamps, truncate_empty_to_empty) {
|
||||
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 0);
|
||||
auto operation = [&openFile] () {
|
||||
openFile->truncate(0);
|
||||
};
|
||||
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAccessTimestamp, this->ExpectUpdatesModificationTimestamp, this->ExpectUpdatesMetadataTimestamp});
|
||||
}
|
||||
|
||||
TYPED_TEST_P(FsppOpenFileTest_Timestamps, truncate_empty_to_nonempty) {
|
||||
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 0);
|
||||
auto operation = [&openFile] () {
|
||||
openFile->truncate(10);
|
||||
};
|
||||
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAccessTimestamp, this->ExpectUpdatesModificationTimestamp, this->ExpectUpdatesMetadataTimestamp});
|
||||
}
|
||||
|
||||
TYPED_TEST_P(FsppOpenFileTest_Timestamps, truncate_nonempty_to_empty) {
|
||||
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 10);
|
||||
auto operation = [&openFile] () {
|
||||
openFile->truncate(0);
|
||||
};
|
||||
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAccessTimestamp, this->ExpectUpdatesModificationTimestamp, this->ExpectUpdatesMetadataTimestamp});
|
||||
}
|
||||
|
||||
TYPED_TEST_P(FsppOpenFileTest_Timestamps, truncate_nonempty_to_nonempty_shrink) {
|
||||
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 10);
|
||||
auto operation = [&openFile] () {
|
||||
openFile->truncate(5);
|
||||
};
|
||||
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAccessTimestamp, this->ExpectUpdatesModificationTimestamp, this->ExpectUpdatesMetadataTimestamp});
|
||||
}
|
||||
|
||||
TYPED_TEST_P(FsppOpenFileTest_Timestamps, truncate_nonempty_to_nonempty_grow) {
|
||||
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 10);
|
||||
auto operation = [&openFile] () {
|
||||
openFile->truncate(20);
|
||||
};
|
||||
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAccessTimestamp, this->ExpectUpdatesModificationTimestamp, this->ExpectUpdatesMetadataTimestamp});
|
||||
}
|
||||
|
||||
TYPED_TEST_P(FsppOpenFileTest_Timestamps, read_inbounds) {
|
||||
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 10);
|
||||
auto operation = [&openFile] () {
|
||||
char buffer[5];
|
||||
openFile->read(buffer, 5, 0);
|
||||
};
|
||||
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectUpdatesAccessTimestamp, this->ExpectDoesntUpdateModificationTimestamp, this->ExpectDoesntUpdateMetadataTimestamp});
|
||||
}
|
||||
|
||||
TYPED_TEST_P(FsppOpenFileTest_Timestamps, read_outofbounds) {
|
||||
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 0);
|
||||
auto operation = [&openFile] () {
|
||||
char buffer[5];
|
||||
openFile->read(buffer, 5, 2);
|
||||
};
|
||||
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectUpdatesAccessTimestamp, this->ExpectDoesntUpdateModificationTimestamp, this->ExpectDoesntUpdateMetadataTimestamp});
|
||||
}
|
||||
|
||||
TYPED_TEST_P(FsppOpenFileTest_Timestamps, write_inbounds) {
|
||||
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 10);
|
||||
auto operation = [&openFile] () {
|
||||
openFile->write("content", 7, 0);
|
||||
};
|
||||
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAccessTimestamp, this->ExpectUpdatesModificationTimestamp, this->ExpectUpdatesMetadataTimestamp});
|
||||
}
|
||||
|
||||
TYPED_TEST_P(FsppOpenFileTest_Timestamps, write_outofbounds) {
|
||||
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 0);
|
||||
auto operation = [&openFile] () {
|
||||
openFile->write("content", 7, 2);
|
||||
};
|
||||
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAccessTimestamp, this->ExpectUpdatesModificationTimestamp, this->ExpectUpdatesMetadataTimestamp});
|
||||
}
|
||||
|
||||
TYPED_TEST_P(FsppOpenFileTest_Timestamps, flush) {
|
||||
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 10);
|
||||
openFile->write("content", 7, 0);
|
||||
auto operation = [&openFile] () {
|
||||
openFile->flush();
|
||||
};
|
||||
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAnyTimestamps});
|
||||
}
|
||||
|
||||
TYPED_TEST_P(FsppOpenFileTest_Timestamps, fsync) {
|
||||
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 10);
|
||||
openFile->write("content", 7, 0);
|
||||
auto operation = [&openFile] () {
|
||||
openFile->fsync();
|
||||
};
|
||||
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAnyTimestamps});
|
||||
}
|
||||
|
||||
TYPED_TEST_P(FsppOpenFileTest_Timestamps, fdatasync) {
|
||||
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 10);
|
||||
openFile->write("content", 7, 0);
|
||||
auto operation = [&openFile] () {
|
||||
openFile->fdatasync();
|
||||
};
|
||||
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAnyTimestamps});
|
||||
}
|
||||
|
||||
REGISTER_TYPED_TEST_CASE_P(FsppOpenFileTest_Timestamps,
|
||||
stat,
|
||||
truncate_empty_to_empty,
|
||||
truncate_empty_to_nonempty,
|
||||
truncate_nonempty_to_empty,
|
||||
truncate_nonempty_to_nonempty_shrink,
|
||||
truncate_nonempty_to_nonempty_grow,
|
||||
read_inbounds,
|
||||
read_outofbounds,
|
||||
write_inbounds,
|
||||
write_outofbounds,
|
||||
flush,
|
||||
fsync,
|
||||
fdatasync
|
||||
);
|
||||
|
||||
#endif
|
@ -24,15 +24,15 @@ public:
|
||||
std::unique_ptr<fspp::File> file_nested;
|
||||
|
||||
//TODO IN_STAT still needed after moving it to FsppNodeTest?
|
||||
void IN_STAT(const fspp::File &file, std::function<void (struct stat)> callback) {
|
||||
void IN_STAT(fspp::File *file, std::function<void (struct stat)> callback) {
|
||||
struct stat st1, st2;
|
||||
file.stat(&st1);
|
||||
file->stat(&st1);
|
||||
callback(st1);
|
||||
file.open(O_RDONLY)->stat(&st2);
|
||||
file->open(O_RDONLY)->stat(&st2);
|
||||
callback(st2);
|
||||
}
|
||||
|
||||
void EXPECT_SIZE(uint64_t expectedSize, const fspp::File &file) {
|
||||
void EXPECT_SIZE(uint64_t expectedSize, fspp::File *file) {
|
||||
IN_STAT(file, [expectedSize] (struct stat st) {
|
||||
EXPECT_EQ(expectedSize, (uint64_t)st.st_size);
|
||||
});
|
||||
@ -40,8 +40,8 @@ public:
|
||||
EXPECT_NUMBYTES_READABLE(expectedSize, file);
|
||||
}
|
||||
|
||||
void EXPECT_NUMBYTES_READABLE(uint64_t expectedSize, const fspp::File &file) {
|
||||
auto openFile = file.open(O_RDONLY);
|
||||
void EXPECT_NUMBYTES_READABLE(uint64_t expectedSize, fspp::File *file) {
|
||||
auto openFile = file->open(O_RDONLY);
|
||||
cpputils::Data data(expectedSize);
|
||||
//Try to read one byte more than the expected size
|
||||
ssize_t readBytes = openFile->read(data.data(), expectedSize+1, 0);
|
||||
|
@ -9,8 +9,8 @@
|
||||
|
||||
class FsppNodeTestBase {
|
||||
public:
|
||||
virtual void IN_STAT(const fspp::Node &node, std::function<void (struct stat)> callback) = 0;
|
||||
virtual void EXPECT_SIZE(uint64_t expectedSize, const fspp::Node &node) = 0;
|
||||
virtual void IN_STAT(fspp::Node *node, std::function<void (struct stat)> callback) = 0;
|
||||
virtual void EXPECT_SIZE(uint64_t expectedSize, fspp::Node *node) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -29,24 +29,24 @@ public:
|
||||
|
||||
class FsppNodeTest_File_Helper: public virtual FsppNodeTestBase {
|
||||
public:
|
||||
void IN_STAT(const fspp::Node &file, std::function<void (struct stat)> callback) override {
|
||||
void IN_STAT(fspp::Node *file, std::function<void (struct stat)> callback) override {
|
||||
struct stat st1, st2;
|
||||
file.stat(&st1);
|
||||
file->stat(&st1);
|
||||
callback(st1);
|
||||
dynamic_cast<const fspp::File &>(file).open(O_RDONLY)->stat(&st2);
|
||||
dynamic_cast<fspp::File &>(*file).open(O_RDONLY)->stat(&st2);
|
||||
callback(st2);
|
||||
}
|
||||
|
||||
void EXPECT_SIZE(uint64_t expectedSize, const fspp::Node &node) override {
|
||||
void EXPECT_SIZE(uint64_t expectedSize, fspp::Node *node) override {
|
||||
IN_STAT(node, [expectedSize] (struct stat st) {
|
||||
EXPECT_EQ(expectedSize, (uint64_t)st.st_size);
|
||||
});
|
||||
|
||||
EXPECT_NUMBYTES_READABLE(expectedSize, dynamic_cast<const fspp::File&>(node));
|
||||
EXPECT_NUMBYTES_READABLE(expectedSize, dynamic_cast<fspp::File*>(node));
|
||||
}
|
||||
|
||||
void EXPECT_NUMBYTES_READABLE(uint64_t expectedSize, const fspp::File &file) {
|
||||
auto openFile = file.open(O_RDONLY);
|
||||
void EXPECT_NUMBYTES_READABLE(uint64_t expectedSize, fspp::File *file) {
|
||||
auto openFile = file->open(O_RDONLY);
|
||||
cpputils::Data data(expectedSize);
|
||||
//Try to read one byte more than the expected size
|
||||
ssize_t readBytes = openFile->read(data.data(), expectedSize+1, 0);
|
||||
@ -57,13 +57,13 @@ public:
|
||||
|
||||
class FsppNodeTest_Dir_Helper: public virtual FsppNodeTestBase {
|
||||
public:
|
||||
void IN_STAT(const fspp::Node &file, std::function<void (struct stat)> callback) override {
|
||||
void IN_STAT(fspp::Node *file, std::function<void (struct stat)> callback) override {
|
||||
struct stat st;
|
||||
file.stat(&st);
|
||||
file->stat(&st);
|
||||
callback(st);
|
||||
}
|
||||
|
||||
void EXPECT_SIZE(uint64_t expectedSize, const fspp::Node &node) override {
|
||||
void EXPECT_SIZE(uint64_t expectedSize, fspp::Node *node) override {
|
||||
IN_STAT(node, [expectedSize] (struct stat st) {
|
||||
EXPECT_EQ(expectedSize, (uint64_t)st.st_size);
|
||||
});
|
||||
@ -72,13 +72,13 @@ public:
|
||||
|
||||
class FsppNodeTest_Symlink_Helper: public virtual FsppNodeTestBase {
|
||||
public:
|
||||
void IN_STAT(const fspp::Node &file, std::function<void (struct stat)> callback) override {
|
||||
void IN_STAT(fspp::Node *file, std::function<void (struct stat)> callback) override {
|
||||
struct stat st;
|
||||
file.stat(&st);
|
||||
file->stat(&st);
|
||||
callback(st);
|
||||
}
|
||||
|
||||
void EXPECT_SIZE(uint64_t expectedSize, const fspp::Node &node) override {
|
||||
void EXPECT_SIZE(uint64_t expectedSize, fspp::Node *node) override {
|
||||
IN_STAT(node, [expectedSize] (struct stat st) {
|
||||
EXPECT_EQ(expectedSize, (uint64_t)st.st_size);
|
||||
});
|
||||
|
@ -151,12 +151,12 @@ unique_ref<Node> FilesystemImpl::LoadFileOrSymlink(const bf::path &path) {
|
||||
|
||||
int FilesystemImpl::openFile(const bf::path &path, int flags) {
|
||||
auto file = LoadFile(path);
|
||||
return openFile(*file, flags);
|
||||
return openFile(file.get(), flags);
|
||||
}
|
||||
|
||||
int FilesystemImpl::openFile(const File &file, int flags) {
|
||||
int FilesystemImpl::openFile(File *file, int flags) {
|
||||
PROFILE(_openFileNanosec);
|
||||
return _open_files.open(file.open(flags));
|
||||
return _open_files.open(file->open(flags));
|
||||
}
|
||||
|
||||
void FilesystemImpl::flush(int descriptor) {
|
||||
|
@ -54,7 +54,7 @@ private:
|
||||
cpputils::unique_ref<Dir> LoadDir(const boost::filesystem::path &path);
|
||||
cpputils::unique_ref<Symlink> LoadSymlink(const boost::filesystem::path &path);
|
||||
cpputils::unique_ref<Node> LoadFileOrSymlink(const boost::filesystem::path &path);
|
||||
int openFile(const File &file, int flags);
|
||||
int openFile(File *file, int flags);
|
||||
|
||||
#ifdef FSPP_PROFILE
|
||||
std::atomic<uint64_t> _loadFileNanosec;
|
||||
|
Loading…
x
Reference in New Issue
Block a user