Add test cases that fspp::Node operations correctly modify the timestamps
This commit is contained in:
parent
183b9cf74b
commit
514de8794e
@ -9,6 +9,7 @@
|
||||
#include "FsppSymlinkTest.h"
|
||||
#include "FsppNodeTest_Rename.h"
|
||||
#include "FsppNodeTest_Stat.h"
|
||||
#include "FsppNodeTest_Timestamps.h"
|
||||
#include "FsppOpenFileTest.h"
|
||||
|
||||
#define FSPP_ADD_FILESYTEM_TESTS(FS_NAME, FIXTURE) \
|
||||
@ -18,9 +19,11 @@
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppSymlinkTest, FIXTURE); \
|
||||
INSTANTIATE_NODE_TEST_CASE( FS_NAME, FsppNodeTest_Rename, FIXTURE); \
|
||||
INSTANTIATE_NODE_TEST_CASE( FS_NAME, FsppNodeTest_Stat, FIXTURE); \
|
||||
INSTANTIATE_NODE_TEST_CASE( FS_NAME, FsppNodeTest_Timestamps, FIXTURE); \
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppNodeTest_Stat_FileOnly, FIXTURE); \
|
||||
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); \
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -80,5 +80,3 @@ REGISTER_TYPED_TEST_CASE_P(FsppNodeTest_Stat_SymlinkOnly,
|
||||
#endif
|
||||
|
||||
//TODO More test cases
|
||||
|
||||
//TODO Test all operations do (or don't) affect timestamps correctly
|
||||
|
100
src/fspp/fstest/FsppNodeTest_Timestamps.h
Normal file
100
src/fspp/fstest/FsppNodeTest_Timestamps.h
Normal file
@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
#ifndef MESSMER_FSPP_FSTEST_FSPPNODETEST_TIMESTAMPS_H_
|
||||
#define MESSMER_FSPP_FSTEST_FSPPNODETEST_TIMESTAMPS_H_
|
||||
|
||||
#include "testutils/FsppNodeTest.h"
|
||||
#include "../fuse/FuseErrnoException.h"
|
||||
#include "testutils/TimestampTestUtils.h"
|
||||
|
||||
using namespace cpputils::time;
|
||||
using std::function;
|
||||
|
||||
template<class ConcreteFileSystemTestFixture>
|
||||
class FsppNodeTest_Timestamps: public FsppNodeTest<ConcreteFileSystemTestFixture>, public TimestampTestUtils {
|
||||
public:
|
||||
|
||||
void Test_Create() {
|
||||
timespec lowerBound = now();
|
||||
auto node = this->CreateNode("/mynode");
|
||||
timespec upperBound = now();
|
||||
EXPECT_ACCESS_TIMESTAMP_BETWEEN (lowerBound, upperBound, *node);
|
||||
EXPECT_MODIFICATION_TIMESTAMP_BETWEEN (lowerBound, upperBound, *node);
|
||||
EXPECT_METADATACHANGE_TIMESTAMP_BETWEEN(lowerBound, upperBound, *node);
|
||||
}
|
||||
|
||||
void Test_Stat() {
|
||||
auto node = this->CreateNode("/mynode");
|
||||
auto operation = [&node] () {
|
||||
struct stat st;
|
||||
node->stat(&st);
|
||||
};
|
||||
EXPECT_OPERATION_DOESNT_UPDATE_TIMESTAMPS(*node, operation);
|
||||
}
|
||||
|
||||
void Test_Chmod() {
|
||||
auto node = this->CreateNode("/mynode");
|
||||
mode_t mode = stat(*node).st_mode;
|
||||
auto operation = [&node, mode] () {
|
||||
node->chmod(mode);
|
||||
};
|
||||
EXPECT_OPERATION_DOESNT_UPDATE_ACCESS_TIMESTAMP(*node, operation);
|
||||
EXPECT_OPERATION_DOESNT_UPDATE_MODIFICATION_TIMESTAMP(*node, operation);
|
||||
EXPECT_OPERATION_UPDATES_METADATACHANGE_TIMESTAMP(*node, operation);
|
||||
}
|
||||
|
||||
void Test_Chown() {
|
||||
auto node = this->CreateNode("/mynode");
|
||||
uid_t uid = stat(*node).st_uid;
|
||||
gid_t gid = stat(*node).st_gid;
|
||||
auto operation = [&node, uid, gid] () {
|
||||
node->chown(uid, gid);
|
||||
};
|
||||
EXPECT_OPERATION_DOESNT_UPDATE_ACCESS_TIMESTAMP(*node, operation);
|
||||
EXPECT_OPERATION_DOESNT_UPDATE_MODIFICATION_TIMESTAMP(*node, operation);
|
||||
EXPECT_OPERATION_UPDATES_METADATACHANGE_TIMESTAMP(*node, operation);
|
||||
}
|
||||
|
||||
void Test_Access() {
|
||||
auto node = this->CreateNode("/mynode");
|
||||
auto operation = [&node] () {
|
||||
node->access(0);
|
||||
};
|
||||
EXPECT_OPERATION_DOESNT_UPDATE_TIMESTAMPS(*node, operation);
|
||||
}
|
||||
|
||||
void Test_Rename() {
|
||||
auto node = this->CreateNode("/mynode");
|
||||
auto operation = [&node] () {
|
||||
node->rename("newnodename");
|
||||
};
|
||||
EXPECT_OPERATION_DOESNT_UPDATE_ACCESS_TIMESTAMP(*node, operation);
|
||||
EXPECT_OPERATION_DOESNT_UPDATE_MODIFICATION_TIMESTAMP(*node, operation);
|
||||
EXPECT_OPERATION_UPDATES_METADATACHANGE_TIMESTAMP(*node, operation);
|
||||
}
|
||||
|
||||
// TODO Other rename cases (e.g. failed renames/error paths, moving to different dir, ...) from FsppNodeTest_Rename
|
||||
|
||||
void Test_Utimens() {
|
||||
auto node = this->CreateNode("/mynode");
|
||||
timespec atime = xSecondsAgo(100);
|
||||
timespec mtime = xSecondsAgo(200);
|
||||
auto operation = [&node, atime, mtime] () {
|
||||
node->utimens(atime, mtime);
|
||||
};
|
||||
EXPECT_OPERATION_UPDATES_METADATACHANGE_TIMESTAMP(*node, operation);
|
||||
EXPECT_EQ(atime, stat(*node).st_atim);
|
||||
EXPECT_EQ(mtime, stat(*node).st_mtim);
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_NODE_TEST_CASE(FsppNodeTest_Timestamps,
|
||||
Create,
|
||||
Stat,
|
||||
Chmod,
|
||||
Chown,
|
||||
Access,
|
||||
Rename,
|
||||
Utimens
|
||||
);
|
||||
|
||||
#endif
|
107
src/fspp/fstest/testutils/TimestampTestUtils.h
Normal file
107
src/fspp/fstest/testutils/TimestampTestUtils.h
Normal file
@ -0,0 +1,107 @@
|
||||
#pragma once
|
||||
#ifndef MESSMER_FSPP_FSTEST_TESTUTILS_TIMESTAMPTESTUTILS_H_
|
||||
#define MESSMER_FSPP_FSTEST_TESTUTILS_TIMESTAMPTESTUTILS_H_
|
||||
|
||||
#include <cpp-utils/system/time.h>
|
||||
|
||||
class TimestampTestUtils {
|
||||
public:
|
||||
void EXPECT_ACCESS_TIMESTAMP_BETWEEN(timespec lowerBound, timespec upperBound, const fspp::Node &node) {
|
||||
EXPECT_LE(lowerBound, stat(node).st_atim);
|
||||
EXPECT_GE(upperBound, stat(node).st_atim);
|
||||
}
|
||||
|
||||
void EXPECT_MODIFICATION_TIMESTAMP_BETWEEN(timespec lowerBound, timespec upperBound, const fspp::Node &node) {
|
||||
EXPECT_LE(lowerBound, stat(node).st_mtim);
|
||||
EXPECT_GE(upperBound, stat(node).st_mtim);
|
||||
}
|
||||
|
||||
void EXPECT_METADATACHANGE_TIMESTAMP_BETWEEN(timespec lowerBound, timespec upperBound, const fspp::Node &node) {
|
||||
EXPECT_LE(lowerBound, stat(node).st_ctim);
|
||||
EXPECT_GE(upperBound, stat(node).st_ctim);
|
||||
}
|
||||
|
||||
void EXPECT_OPERATION_DOESNT_UPDATE_ACCESS_TIMESTAMP(const fspp::Node &node, std::function<void()> operation) {
|
||||
ensureNodeTimestampsAreOld(node);
|
||||
timespec oldTime = stat(node).st_atim;
|
||||
operation();
|
||||
timespec newTime = stat(node).st_atim;
|
||||
EXPECT_EQ(oldTime, newTime);
|
||||
}
|
||||
|
||||
void EXPECT_OPERATION_DOESNT_UPDATE_MODIFICATION_TIMESTAMP(const fspp::Node &node, std::function<void()> operation) {
|
||||
ensureNodeTimestampsAreOld(node);
|
||||
timespec oldTime = stat(node).st_mtim;
|
||||
operation();
|
||||
timespec newTime = stat(node).st_mtim;
|
||||
EXPECT_EQ(oldTime, newTime);
|
||||
}
|
||||
|
||||
void EXPECT_OPERATION_DOESNT_UPDATE_METADATACHANGE_TIMESTAMP(const fspp::Node &node, std::function<void()> operation) {
|
||||
ensureNodeTimestampsAreOld(node);
|
||||
timespec oldTime = stat(node).st_ctim;
|
||||
operation();
|
||||
timespec newTime = stat(node).st_ctim;
|
||||
EXPECT_EQ(oldTime, newTime);
|
||||
}
|
||||
|
||||
void EXPECT_OPERATION_UPDATES_ACCESS_TIMESTAMP(const fspp::Node &node, std::function<void()> operation) {
|
||||
ensureNodeTimestampsAreOld(node);
|
||||
timespec lowerBound = cpputils::time::now();
|
||||
operation();
|
||||
timespec upperBound = cpputils::time::now();
|
||||
EXPECT_ACCESS_TIMESTAMP_BETWEEN(lowerBound, upperBound, node);
|
||||
}
|
||||
|
||||
void EXPECT_OPERATION_UPDATES_MODIFICATION_TIMESTAMP(const fspp::Node &node, std::function<void()> operation) {
|
||||
ensureNodeTimestampsAreOld(node);
|
||||
timespec lowerBound = cpputils::time::now();
|
||||
operation();
|
||||
timespec upperBound = cpputils::time::now();
|
||||
EXPECT_MODIFICATION_TIMESTAMP_BETWEEN(lowerBound, upperBound, node);
|
||||
}
|
||||
|
||||
void EXPECT_OPERATION_UPDATES_METADATACHANGE_TIMESTAMP(const fspp::Node &node, std::function<void()> operation) {
|
||||
ensureNodeTimestampsAreOld(node);
|
||||
timespec lowerBound = cpputils::time::now();
|
||||
operation();
|
||||
timespec upperBound = cpputils::time::now();
|
||||
EXPECT_METADATACHANGE_TIMESTAMP_BETWEEN(lowerBound, upperBound, node);
|
||||
}
|
||||
|
||||
void EXPECT_OPERATION_DOESNT_UPDATE_TIMESTAMPS(const fspp::Node &node, std::function<void()> operation) {
|
||||
EXPECT_OPERATION_DOESNT_UPDATE_ACCESS_TIMESTAMP(node, operation);
|
||||
EXPECT_OPERATION_DOESNT_UPDATE_MODIFICATION_TIMESTAMP(node, operation);
|
||||
EXPECT_OPERATION_DOESNT_UPDATE_METADATACHANGE_TIMESTAMP(node, operation);
|
||||
}
|
||||
|
||||
struct stat stat(const fspp::Node &node) {
|
||||
struct stat st;
|
||||
node.stat(&st);
|
||||
return st;
|
||||
}
|
||||
|
||||
timespec xSecondsAgo(int sec) {
|
||||
timespec result = cpputils::time::now();
|
||||
result.tv_sec -= sec;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void ensureNodeTimestampsAreOld(const fspp::Node &node) {
|
||||
waitUntilClockProgresses();
|
||||
EXPECT_LT(stat(node).st_atim, cpputils::time::now());
|
||||
EXPECT_LT(stat(node).st_mtim, cpputils::time::now());
|
||||
EXPECT_LT(stat(node).st_ctim, cpputils::time::now());
|
||||
}
|
||||
|
||||
void waitUntilClockProgresses() {
|
||||
auto start = cpputils::time::now();
|
||||
while (start == cpputils::time::now()) {
|
||||
// busy waiting is the fastest, we only have to wait for a nanosecond increment.
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user