Testcases for statfs()

This commit is contained in:
Sebastian Messmer 2014-11-28 22:11:26 +01:00
parent 8249fb14fe
commit 4ec3c7b82d
13 changed files with 350 additions and 1 deletions

View File

@ -31,9 +31,9 @@ public:
virtual void unlink(const boost::filesystem::path &path) = 0;
virtual void rename(const boost::filesystem::path &from, const boost::filesystem::path &to) = 0;
virtual void utimens(const boost::filesystem::path &path, const timespec times[2]) = 0;
virtual void statfs(const boost::filesystem::path &path, struct statvfs *fsstat) = 0;
//TODO Unit-Tests for all functions below
virtual std::unique_ptr<std::vector<std::string>> readDir(const boost::filesystem::path &path) = 0;
virtual void statfs(const boost::filesystem::path &path, struct statvfs *fsstat) = 0;
};
//TODO Test error cases handled by libfuse (e.g. mkdir: Already exists, rmdir: Doesn't exist, ...)

View File

@ -0,0 +1,34 @@
#include "testutils/FuseStatfsTest.h"
#include "fspp/fuse/FuseErrnoException.h"
using ::testing::StrEq;
using ::testing::_;
using ::testing::Throw;
using ::testing::Return;
using ::testing::WithParamInterface;
using ::testing::Values;
using fspp::fuse::FuseErrnoException;
class FuseStatfsErrorTest: public FuseStatfsTest, public WithParamInterface<int> {
public:
};
INSTANTIATE_TEST_CASE_P(FuseStatfsErrorTest, FuseStatfsErrorTest, Values(EACCES, EBADF, EFAULT, EINTR, EIO, ELOOP, ENAMETOOLONG, ENOENT, ENOMEM, ENOSYS, ENOTDIR, EOVERFLOW));
TEST_F(FuseStatfsErrorTest, ReturnNoError) {
ReturnIsFileOnLstat(FILENAME);
EXPECT_CALL(fsimpl, statfs(StrEq(FILENAME), _)).Times(1).WillOnce(Return());
errno = 0;
int retval = StatfsAllowErrors(FILENAME);
EXPECT_EQ(errno, 0);
EXPECT_EQ(retval, 0);
}
TEST_P(FuseStatfsErrorTest, ReturnError) {
ReturnIsFileOnLstat(FILENAME);
EXPECT_CALL(fsimpl, statfs(StrEq(FILENAME), _)).Times(1).WillOnce(Throw(FuseErrnoException(GetParam())));
int retval = StatfsAllowErrors(FILENAME);
EXPECT_EQ(retval, -1);
EXPECT_EQ(GetParam(), errno);
}

View File

@ -0,0 +1,41 @@
#include "testutils/FuseStatfsTest.h"
using ::testing::_;
using ::testing::StrEq;
using ::testing::Return;
class FuseStatfsPathParameterTest: public FuseStatfsTest {
};
TEST_F(FuseStatfsPathParameterTest, PathParameterIsCorrectRoot) {
EXPECT_CALL(fsimpl, statfs(StrEq("/"), _)).Times(1).WillOnce(Return());
Statfs("/");
}
TEST_F(FuseStatfsPathParameterTest, PathParameterIsCorrectSimpleFile) {
ReturnIsFileOnLstat("/myfile");
EXPECT_CALL(fsimpl, statfs(StrEq("/myfile"), _)).Times(1).WillOnce(Return());
Statfs("/myfile");
}
TEST_F(FuseStatfsPathParameterTest, PathParameterIsCorrectSimpleDir) {
ReturnIsDirOnLstat("/mydir");
EXPECT_CALL(fsimpl, statfs(StrEq("/mydir"), _)).Times(1).WillOnce(Return());
Statfs("/mydir");
}
TEST_F(FuseStatfsPathParameterTest, PathParameterIsCorrectNestedFile) {
ReturnIsDirOnLstat("/mydir");
ReturnIsDirOnLstat("/mydir/mydir2");
ReturnIsFileOnLstat("/mydir/mydir2/myfile");
EXPECT_CALL(fsimpl, statfs(StrEq("/mydir/mydir2/myfile"), _)).Times(1).WillOnce(Return());
Statfs("/mydir/mydir2/myfile");
}
TEST_F(FuseStatfsPathParameterTest, PathParameterIsCorrectNestedDir) {
ReturnIsDirOnLstat("/mydir");
ReturnIsDirOnLstat("/mydir/mydir2");
ReturnIsDirOnLstat("/mydir/mydir2/mydir3");
EXPECT_CALL(fsimpl, statfs(StrEq("/mydir/mydir2/mydir3"), _)).Times(1).WillOnce(Return());
Statfs("/mydir/mydir2/mydir3");
}

View File

@ -0,0 +1,23 @@
#include "testutils/FuseStatfsReturnTest.h"
using ::testing::WithParamInterface;
using ::testing::Values;
class FuseStatfsReturnBavailTest: public FuseStatfsReturnTest<fsblkcnt_t>, public WithParamInterface<fsblkcnt_t> {
private:
void set(struct ::statvfs *stat, fsblkcnt_t value) override {
stat->f_bavail = value;
}
};
INSTANTIATE_TEST_CASE_P(FuseStatfsReturnBavailTest, FuseStatfsReturnBavailTest, Values(
0,
10,
256,
1024,
4096
));
TEST_P(FuseStatfsReturnBavailTest, ReturnedBavailIsCorrect) {
struct ::statvfs result = CallStatfsWithValue(GetParam());
EXPECT_EQ(GetParam(), result.f_bavail);
}

View File

@ -0,0 +1,23 @@
#include "testutils/FuseStatfsReturnTest.h"
using ::testing::WithParamInterface;
using ::testing::Values;
class FuseStatfsReturnBfreeTest: public FuseStatfsReturnTest<fsblkcnt_t>, public WithParamInterface<fsblkcnt_t> {
private:
void set(struct ::statvfs *stat, fsblkcnt_t value) override {
stat->f_bfree = value;
}
};
INSTANTIATE_TEST_CASE_P(FuseStatfsReturnBfreeTest, FuseStatfsReturnBfreeTest, Values(
0,
10,
256,
1024,
4096
));
TEST_P(FuseStatfsReturnBfreeTest, ReturnedBfreeIsCorrect) {
struct ::statvfs result = CallStatfsWithValue(GetParam());
EXPECT_EQ(GetParam(), result.f_bfree);
}

View File

@ -0,0 +1,23 @@
#include "testutils/FuseStatfsReturnTest.h"
using ::testing::WithParamInterface;
using ::testing::Values;
class FuseStatfsReturnBlocksTest: public FuseStatfsReturnTest<fsblkcnt_t>, public WithParamInterface<fsblkcnt_t> {
private:
void set(struct ::statvfs *stat, fsblkcnt_t value) override {
stat->f_blocks = value;
}
};
INSTANTIATE_TEST_CASE_P(FuseStatfsReturnBlocksTest, FuseStatfsReturnBlocksTest, Values(
0,
10,
256,
1024,
4096
));
TEST_P(FuseStatfsReturnBlocksTest, ReturnedBlocksIsCorrect) {
struct ::statvfs result = CallStatfsWithValue(GetParam());
EXPECT_EQ(GetParam(), result.f_blocks);
}

View File

@ -0,0 +1,23 @@
#include "testutils/FuseStatfsReturnTest.h"
using ::testing::WithParamInterface;
using ::testing::Values;
class FuseStatfsReturnBsizeTest: public FuseStatfsReturnTest<unsigned long>, public WithParamInterface<unsigned long> {
private:
void set(struct ::statvfs *stat, unsigned long value) override {
stat->f_bsize = value;
}
};
INSTANTIATE_TEST_CASE_P(FuseStatfsReturnBsizeTest, FuseStatfsReturnBsizeTest, Values(
0,
10,
256,
1024,
4096
));
TEST_P(FuseStatfsReturnBsizeTest, ReturnedBsizeIsCorrect) {
struct ::statvfs result = CallStatfsWithValue(GetParam());
EXPECT_EQ(GetParam(), result.f_bsize);
}

View File

@ -0,0 +1,23 @@
#include "testutils/FuseStatfsReturnTest.h"
using ::testing::WithParamInterface;
using ::testing::Values;
class FuseStatfsReturnFfreeTest: public FuseStatfsReturnTest<fsfilcnt_t>, public WithParamInterface<fsfilcnt_t> {
private:
void set(struct ::statvfs *stat, fsfilcnt_t value) override {
stat->f_ffree = value;
}
};
INSTANTIATE_TEST_CASE_P(FuseStatfsReturnFfreeTest, FuseStatfsReturnFfreeTest, Values(
0,
10,
256,
1024,
4096
));
TEST_P(FuseStatfsReturnFfreeTest, ReturnedFfreeIsCorrect) {
struct ::statvfs result = CallStatfsWithValue(GetParam());
EXPECT_EQ(GetParam(), result.f_ffree);
}

View File

@ -0,0 +1,23 @@
#include "testutils/FuseStatfsReturnTest.h"
using ::testing::WithParamInterface;
using ::testing::Values;
class FuseStatfsReturnFilesTest: public FuseStatfsReturnTest<fsfilcnt_t>, public WithParamInterface<fsfilcnt_t> {
private:
void set(struct ::statvfs *stat, fsfilcnt_t value) override {
stat->f_files = value;
}
};
INSTANTIATE_TEST_CASE_P(FuseStatfsReturnFilesTest, FuseStatfsReturnFilesTest, Values(
0,
10,
256,
1024,
4096
));
TEST_P(FuseStatfsReturnFilesTest, ReturnedFilesIsCorrect) {
struct ::statvfs result = CallStatfsWithValue(GetParam());
EXPECT_EQ(GetParam(), result.f_files);
}

View File

@ -0,0 +1,23 @@
#include "testutils/FuseStatfsReturnTest.h"
using ::testing::WithParamInterface;
using ::testing::Values;
class FuseStatfsReturnNamemaxTest: public FuseStatfsReturnTest<unsigned long>, public WithParamInterface<unsigned long> {
private:
void set(struct ::statvfs *stat, unsigned long value) override {
stat->f_namemax = value;
}
};
INSTANTIATE_TEST_CASE_P(FuseStatfsReturnNamemaxTest, FuseStatfsReturnNamemaxTest, Values(
0,
10,
256,
1024,
4096
));
TEST_P(FuseStatfsReturnNamemaxTest, ReturnedNamemaxIsCorrect) {
struct ::statvfs result = CallStatfsWithValue(GetParam());
EXPECT_EQ(GetParam(), result.f_namemax);
}

View File

@ -0,0 +1,36 @@
#pragma once
#ifndef TEST_FSPP_FUSE_STATFS_FUSESTATFSRETURNTEST_H_
#define TEST_FSPP_FUSE_STATFS_FUSESTATFSRETURNTEST_H_
#include "FuseStatfsTest.h"
// This class offers test helpers for testing (struct statfs) entries. We return them from
// our mock filesystem, set up a temporary filesystem, call statfs syscall on it, and
// then check the return value.
template<typename Property>
class FuseStatfsReturnTest: public FuseStatfsTest {
public:
// Set the specified (struct statfs) entry to the given value, and test whether it is correctly returned from the syscall.
struct ::statvfs CallStatfsWithValue(Property value);
private:
std::function<void(struct ::statvfs*)> SetPropertyImpl(Property value);
// Override this function to specify, how to set the specified (struct statfs) entry on the passed (struct statfs *) object.
virtual void set(struct ::statvfs *statfs, Property value) = 0;
};
template<typename Property>
struct ::statvfs FuseStatfsReturnTest<Property>::CallStatfsWithValue(Property value) {
return CallStatfsWithImpl(SetPropertyImpl(value));
}
template<typename Property>
std::function<void(struct ::statvfs*)> FuseStatfsReturnTest<Property>::SetPropertyImpl(Property value) {
return [this, value] (struct ::statvfs *stat) {
set(stat, value);
};
}
#endif

View File

@ -0,0 +1,41 @@
#include "FuseStatfsTest.h"
using std::function;
using ::testing::StrEq;
using ::testing::_;
using ::testing::Invoke;
void FuseStatfsTest::Statfs(const std::string &path) {
struct ::statvfs dummy;
Statfs(path, &dummy);
}
int FuseStatfsTest::StatfsAllowErrors(const std::string &path) {
struct ::statvfs dummy;
return StatfsAllowErrors(path, &dummy);
}
void FuseStatfsTest::Statfs(const std::string &path, struct ::statvfs *result) {
int retval = StatfsAllowErrors(path, result);
EXPECT_EQ(0, retval) << "lstat syscall failed. errno: " << errno;
}
int FuseStatfsTest::StatfsAllowErrors(const std::string &path, struct ::statvfs *result) {
auto fs = TestFS();
auto realpath = fs->mountDir() / path;
return ::statvfs(realpath.c_str(), result);
}
struct ::statvfs FuseStatfsTest::CallStatfsWithImpl(function<void(struct ::statvfs*)> implementation) {
ReturnIsFileOnLstat(FILENAME);
EXPECT_CALL(fsimpl, statfs(StrEq(FILENAME), _)).WillRepeatedly(Invoke([implementation](const char*, struct ::statvfs *stat) {
implementation(stat);
}));
struct ::statvfs result;
Statfs(FILENAME, &result);
return result;
}

View File

@ -0,0 +1,36 @@
#pragma once
#ifndef TEST_FSPP_FUSE_STATFS_FUSESTATFSTEST_H_
#define TEST_FSPP_FUSE_STATFS_FUSESTATFSTEST_H_
#include "gmock/gmock.h"
#include <string>
#include <functional>
#include <sys/statvfs.h>
#include "test/testutils/FuseTest.h"
// This class offers some utility functions for testing statfs().
class FuseStatfsTest: public FuseTest {
protected:
const char *FILENAME = "/myfile";
// Set up a temporary filesystem (using the fsimpl mock in FuseTest as filesystem implementation)
// and call the statfs syscall on the given (filesystem-relative) path.
void Statfs(const std::string &path);
// Same as Statfs above, but also return the result of the statfs syscall.
void Statfs(const std::string &path, struct ::statvfs *result);
// These two functions are the same as Statfs above, but they don't fail the test when the statfs syscall
// crashes. Instead, they return the result value of the statfs syscall.
int StatfsAllowErrors(const std::string &path);
int StatfsAllowErrors(const std::string &path, struct ::statvfs *result);
// You can specify an implementation, which can modify the (struct statfs *) result,
// our fuse mock filesystem implementation will then return this to fuse on an statfs call.
// This functions then set up a temporary filesystem with this mock, calls statfs on a filesystem node
// and returns the (struct statfs) returned from an statfs syscall to this filesystem.
struct ::statvfs CallStatfsWithImpl(std::function<void(struct ::statvfs*)> implementation);
};
#endif