Generalize timestamp expectations

This commit is contained in:
Sebastian Messmer 2016-06-07 20:48:29 -07:00
parent 9bb2e2e89a
commit 06a5faf2f8
3 changed files with 97 additions and 107 deletions

View File

@ -12,7 +12,7 @@ public:
auto operation = [this, &node] () {
this->device->Load("/mynode");
};
this->EXPECT_OPERATION_DOESNT_UPDATE_TIMESTAMPS(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAnyTimestamps});
}
void Test_Load_While_Not_Loaded() {

View File

@ -29,7 +29,7 @@ public:
struct stat st;
node->stat(&st);
};
EXPECT_OPERATION_DOESNT_UPDATE_TIMESTAMPS(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAnyTimestamps});
}
void Test_Chmod() {
@ -38,9 +38,7 @@ public:
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);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAccessTimestamp, ExpectDoesntUpdateModificationTimestamp, ExpectUpdatesMetadataTimestamp});
}
void Test_Chown() {
@ -50,9 +48,7 @@ public:
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);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAccessTimestamp, ExpectDoesntUpdateModificationTimestamp, ExpectUpdatesMetadataTimestamp});
}
void Test_Access() {
@ -60,7 +56,7 @@ public:
auto operation = [&node] () {
node->access(0);
};
EXPECT_OPERATION_DOESNT_UPDATE_TIMESTAMPS(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAnyTimestamps});
}
void Test_Rename_Error_TargetParentDirDoesntExist() {
@ -73,7 +69,7 @@ public:
EXPECT_EQ(ENOENT, e.getErrno()); //Rename fails, everything is ok.
}
};
EXPECT_OPERATION_DOESNT_UPDATE_TIMESTAMPS(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAnyTimestamps});
}
void Test_Rename_Error_TargetParentDirIsFile() {
@ -87,7 +83,7 @@ public:
EXPECT_EQ(ENOTDIR, e.getErrno()); //Rename fails, everything is ok.
}
};
EXPECT_OPERATION_DOESNT_UPDATE_TIMESTAMPS(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAnyTimestamps});
}
void Test_Rename_Error_RootDir() {
@ -102,7 +98,7 @@ public:
EXPECT_EQ(EBUSY, e.getErrno()); //Rename fails, everything is ok.
}
};
EXPECT_OPERATION_DOESNT_UPDATE_TIMESTAMPS(*root, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAnyTimestamps});
*/
}
@ -111,7 +107,7 @@ public:
auto operation = [&node] () {
node->rename("/newname");
};
EXPECT_OPERATION_ONLY_UPDATES_METADATACHANGE_TIMESTAMP(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAccessTimestamp, ExpectDoesntUpdateModificationTimestamp, ExpectUpdatesMetadataTimestamp});
}
void Test_Rename_InNested() {
@ -120,7 +116,7 @@ public:
auto operation = [&node] () {
node->rename("/mydir/newname");
};
EXPECT_OPERATION_ONLY_UPDATES_METADATACHANGE_TIMESTAMP(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAccessTimestamp, ExpectDoesntUpdateModificationTimestamp, ExpectUpdatesMetadataTimestamp});
}
void Test_Rename_RootToNested_SameName() {
@ -129,7 +125,7 @@ public:
auto operation = [&node] () {
node->rename("/mydir/oldname");
};
EXPECT_OPERATION_ONLY_UPDATES_METADATACHANGE_TIMESTAMP(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAccessTimestamp, ExpectDoesntUpdateModificationTimestamp, ExpectUpdatesMetadataTimestamp});
}
void Test_Rename_RootToNested_NewName() {
@ -138,7 +134,7 @@ public:
auto operation = [&node] () {
node->rename("/mydir/newname");
};
EXPECT_OPERATION_ONLY_UPDATES_METADATACHANGE_TIMESTAMP(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAccessTimestamp, ExpectDoesntUpdateModificationTimestamp, ExpectUpdatesMetadataTimestamp});
}
void Test_Rename_NestedToRoot_SameName() {
@ -147,7 +143,7 @@ public:
auto operation = [&node] () {
node->rename("/oldname");
};
EXPECT_OPERATION_ONLY_UPDATES_METADATACHANGE_TIMESTAMP(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAccessTimestamp, ExpectDoesntUpdateModificationTimestamp, ExpectUpdatesMetadataTimestamp});
}
void Test_Rename_NestedToRoot_NewName() {
@ -156,7 +152,7 @@ public:
auto operation = [&node] () {
node->rename("/newname");
};
EXPECT_OPERATION_ONLY_UPDATES_METADATACHANGE_TIMESTAMP(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAccessTimestamp, ExpectDoesntUpdateModificationTimestamp, ExpectUpdatesMetadataTimestamp});
}
void Test_Rename_NestedToNested_SameName() {
@ -166,7 +162,7 @@ public:
auto operation = [&node] () {
node->rename("/mydir2/oldname");
};
EXPECT_OPERATION_ONLY_UPDATES_METADATACHANGE_TIMESTAMP(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAccessTimestamp, ExpectDoesntUpdateModificationTimestamp, ExpectUpdatesMetadataTimestamp});
}
void Test_Rename_NestedToNested_NewName() {
@ -176,7 +172,7 @@ public:
auto operation = [&node] () {
node->rename("/mydir2/newname");
};
EXPECT_OPERATION_ONLY_UPDATES_METADATACHANGE_TIMESTAMP(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAccessTimestamp, ExpectDoesntUpdateModificationTimestamp, ExpectUpdatesMetadataTimestamp});
}
void Test_Rename_ToItself() {
@ -184,7 +180,7 @@ public:
auto operation = [&node] () {
node->rename("/oldname");
};
EXPECT_OPERATION_ONLY_UPDATES_METADATACHANGE_TIMESTAMP(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAccessTimestamp, ExpectDoesntUpdateModificationTimestamp, ExpectUpdatesMetadataTimestamp});
}
void Test_Rename_Overwrite_InSameDir() {
@ -193,7 +189,7 @@ public:
auto operation = [&node] () {
node->rename("/newname");
};
EXPECT_OPERATION_ONLY_UPDATES_METADATACHANGE_TIMESTAMP(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAccessTimestamp, ExpectDoesntUpdateModificationTimestamp, ExpectUpdatesMetadataTimestamp});
}
void Test_Rename_Overwrite_InDifferentDir() {
@ -204,7 +200,7 @@ public:
auto operation = [&node] () {
node->rename("/mydir2/newname");
};
EXPECT_OPERATION_ONLY_UPDATES_METADATACHANGE_TIMESTAMP(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAccessTimestamp, ExpectDoesntUpdateModificationTimestamp, ExpectUpdatesMetadataTimestamp});
}
void Test_Rename_Overwrite_Error_DirWithFile_InSameDir() {
@ -218,7 +214,7 @@ public:
EXPECT_EQ(EISDIR, e.getErrno()); //Rename fails, everything is ok.
}
};
EXPECT_OPERATION_DOESNT_UPDATE_TIMESTAMPS(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAnyTimestamps});
}
void Test_Rename_Overwrite_Error_DirWithFile_InDifferentDir() {
@ -234,7 +230,7 @@ public:
EXPECT_EQ(EISDIR, e.getErrno());//Rename fails, everything is ok.
}
};
EXPECT_OPERATION_DOESNT_UPDATE_TIMESTAMPS(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAnyTimestamps});
}
void Test_Rename_Overwrite_Error_FileWithDir_InSameDir() {
@ -248,7 +244,7 @@ public:
EXPECT_EQ(ENOTDIR, e.getErrno()); //Rename fails, everything is ok.
}
};
EXPECT_OPERATION_DOESNT_UPDATE_TIMESTAMPS(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAnyTimestamps});
}
void Test_Rename_Overwrite_Error_FileWithDir_InDifferentDir() {
@ -264,7 +260,7 @@ public:
EXPECT_EQ(ENOTDIR, e.getErrno()); //Rename fails, everything is ok.
}
};
EXPECT_OPERATION_DOESNT_UPDATE_TIMESTAMPS(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectDoesntUpdateAnyTimestamps});
}
void Test_Utimens() {
@ -274,7 +270,7 @@ public:
auto operation = [&node, atime, mtime] () {
node->utimens(atime, mtime);
};
EXPECT_OPERATION_UPDATES_METADATACHANGE_TIMESTAMP(*node, operation);
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*node, operation, {ExpectUpdatesMetadataTimestamp});
EXPECT_EQ(atime, stat(*node).st_atim);
EXPECT_EQ(mtime, stat(*node).st_mtim);
}

View File

@ -8,6 +8,28 @@
template<typename NodeType>
class TimestampTestUtils {
public:
using TimestampUpdateBehavior = std::function<void (struct stat statBeforeOperation, struct stat statAfterOperation, timespec timeBeforeOperation, timespec timeAfterOperation)>;
static TimestampUpdateBehavior ExpectUpdatesAccessTimestamp;
static TimestampUpdateBehavior ExpectDoesntUpdateAccessTimestamp;
static TimestampUpdateBehavior ExpectUpdatesModificationTimestamp;
static TimestampUpdateBehavior ExpectDoesntUpdateModificationTimestamp;
static TimestampUpdateBehavior ExpectUpdatesMetadataTimestamp;
static TimestampUpdateBehavior ExpectDoesntUpdateMetadataTimestamp;
static TimestampUpdateBehavior ExpectDoesntUpdateAnyTimestamps;
void EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(const NodeType &node, std::function<void()> operation, std::initializer_list<TimestampUpdateBehavior> behaviorChecks) {
ensureNodeTimestampsAreOld(node);
struct stat oldStat = stat(node);
timespec timeBeforeOperation = cpputils::time::now();
operation();
timespec timeAfterOperation = cpputils::time::now();
struct stat newStat = stat(node);
for (auto behaviorCheck : behaviorChecks) {
behaviorCheck(oldStat, newStat, timeBeforeOperation, timeAfterOperation);
}
}
void EXPECT_ACCESS_TIMESTAMP_BETWEEN(timespec lowerBound, timespec upperBound, const NodeType &node) {
EXPECT_LE(lowerBound, stat(node).st_atim);
EXPECT_GE(upperBound, stat(node).st_atim);
@ -23,85 +45,6 @@ public:
EXPECT_GE(upperBound, stat(node).st_ctim);
}
void EXPECT_OPERATION_DOESNT_UPDATE_ACCESS_TIMESTAMP(const NodeType &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 NodeType &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 NodeType &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 NodeType &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 NodeType &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 NodeType &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 NodeType &node, std::function<void()> operation) {
// equivalent to the following, but implemented separately because operation() should only be called once.
// EXPECT_OPERATION_DOESNT_UPDATE_ACCESS_TIMESTAMP(node, operation);
// EXPECT_OPERATION_DOESNT_UPDATE_MODIFICATION_TIMESTAMP(node, operation);
// EXPECT_OPERATION_DOESNT_UPDATE_METADATACHANGE_TIMESTAMP(node, operation);
ensureNodeTimestampsAreOld(node);
struct stat oldStat = stat(node);
operation();
struct stat newStat = stat(node);
EXPECT_EQ(oldStat.st_atim, newStat.st_atim);
EXPECT_EQ(oldStat.st_mtim, newStat.st_mtim);
EXPECT_EQ(oldStat.st_ctim, newStat.st_ctim);
}
void EXPECT_OPERATION_ONLY_UPDATES_METADATACHANGE_TIMESTAMP(const NodeType &node, std::function<void()> operation) {
// equivalent to the following, but implemented separately because operation() should only be called once.
// EXPECT_OPERATION_DOESNT_UPDATE_ACCESS_TIMESTAMP(node, operation);
// EXPECT_OPERATION_DOESNT_UPDATE_MODIFICATION_TIMESTAMP(node, operation);
// EXPECT_OPERATION_UPDATES_METADATACHANGE_TIMESTAMP(node, operation);
ensureNodeTimestampsAreOld(node);
struct stat oldStat = stat(node);
timespec lowerBound = cpputils::time::now();
operation();
timespec upperBound = cpputils::time::now();
struct stat newStat = stat(node);
EXPECT_EQ(oldStat.st_atim, newStat.st_atim);
EXPECT_EQ(oldStat.st_mtim, newStat.st_mtim);
EXPECT_LE(lowerBound, newStat.st_ctim);
EXPECT_GE(upperBound, newStat.st_ctim);
}
struct stat stat(const NodeType &node) {
struct stat st;
node.stat(&st);
@ -131,4 +74,55 @@ private:
}
};
template<class NodeType>
typename TimestampTestUtils<NodeType>::TimestampUpdateBehavior TimestampTestUtils<NodeType>::ExpectUpdatesAccessTimestamp = [] (struct stat statBeforeOperation, struct stat statAfterOperation, timespec timeBeforeOperation, timespec timeAfterOperation) {
UNUSED(statBeforeOperation);
UNUSED(timeBeforeOperation);
UNUSED(timeAfterOperation);
EXPECT_LE(timeBeforeOperation, statAfterOperation.st_atim);
EXPECT_GE(timeAfterOperation, statAfterOperation.st_atim);
};
template<class NodeType>
typename TimestampTestUtils<NodeType>::TimestampUpdateBehavior TimestampTestUtils<NodeType>::ExpectDoesntUpdateAccessTimestamp = [] (struct stat statBeforeOperation, struct stat statAfterOperation, timespec timeBeforeOperation, timespec timeAfterOperation) {
UNUSED(timeBeforeOperation);
UNUSED(timeAfterOperation);
EXPECT_EQ(statBeforeOperation.st_atim, statAfterOperation.st_atim);
};
template<class NodeType>
typename TimestampTestUtils<NodeType>::TimestampUpdateBehavior TimestampTestUtils<NodeType>::ExpectUpdatesModificationTimestamp = [] (struct stat statBeforeOperation, struct stat statAfterOperation, timespec timeBeforeOperation, timespec timeAfterOperation) {
UNUSED(statBeforeOperation);
EXPECT_LE(timeBeforeOperation, statAfterOperation.st_mtim);
EXPECT_GE(timeAfterOperation, statAfterOperation.st_mtim);
};
template<class NodeType>
typename TimestampTestUtils<NodeType>::TimestampUpdateBehavior TimestampTestUtils<NodeType>::ExpectDoesntUpdateModificationTimestamp = [] (struct stat statBeforeOperation, struct stat statAfterOperation, timespec timeBeforeOperation, timespec timeAfterOperation) {
UNUSED(timeBeforeOperation);
UNUSED(timeAfterOperation);
EXPECT_EQ(statBeforeOperation.st_mtim, statAfterOperation.st_mtim);
};
template<class NodeType>
typename TimestampTestUtils<NodeType>::TimestampUpdateBehavior TimestampTestUtils<NodeType>::ExpectUpdatesMetadataTimestamp = [] (struct stat statBeforeOperation, struct stat statAfterOperation, timespec timeBeforeOperation, timespec timeAfterOperation) {
UNUSED(statBeforeOperation);
EXPECT_LE(timeBeforeOperation, statAfterOperation.st_ctim);
EXPECT_GE(timeAfterOperation, statAfterOperation.st_ctim);
};
template<class NodeType>
typename TimestampTestUtils<NodeType>::TimestampUpdateBehavior TimestampTestUtils<NodeType>::ExpectDoesntUpdateMetadataTimestamp = [] (struct stat statBeforeOperation, struct stat statAfterOperation, timespec timeBeforeOperation, timespec timeAfterOperation) {
UNUSED(timeBeforeOperation);
UNUSED(timeAfterOperation);
EXPECT_EQ(statBeforeOperation.st_ctim, statAfterOperation.st_ctim);
};
template<class NodeType>
typename TimestampTestUtils<NodeType>::TimestampUpdateBehavior TimestampTestUtils<NodeType>::ExpectDoesntUpdateAnyTimestamps = [] (struct stat statBeforeOperation, struct stat statAfterOperation, timespec timeBeforeOperation, timespec timeAfterOperation) {
TimestampTestUtils::ExpectDoesntUpdateAccessTimestamp(statBeforeOperation, statAfterOperation, timeBeforeOperation, timeAfterOperation);
TimestampTestUtils::ExpectDoesntUpdateModificationTimestamp(statBeforeOperation, statAfterOperation, timeBeforeOperation, timeAfterOperation);
TimestampTestUtils::ExpectDoesntUpdateMetadataTimestamp(statBeforeOperation, statAfterOperation, timeBeforeOperation, timeAfterOperation);
};
#endif