1
0
mirror of https://github.com/falk-werner/webfused synced 2026-03-02 04:09:19 +00:00

increased test coverage

This commit is contained in:
Falk Werner
2020-03-20 10:26:41 +01:00
parent 7553846629
commit ba270f1d0d
11 changed files with 414 additions and 16 deletions

27
test/mock_libconfig.cc Normal file
View File

@@ -0,0 +1,27 @@
#include "mock_libconfig.hpp"
#include "wrap_utils.hpp"
extern "C"
{
static webfused_test::ILibConfig * wfd_MockLibConfig = nullptr;
WFD_WRAP_FUNC2(wfd_MockLibConfig, config_setting_t *, config_setting_get_elem,
config_setting_t const *, unsigned int);
}
namespace webfused_test
{
MockLibConfig::MockLibConfig()
{
wfd_MockLibConfig = this;
}
MockLibConfig::~MockLibConfig()
{
wfd_MockLibConfig = nullptr;
}
}

32
test/mock_libconfig.hpp Normal file
View File

@@ -0,0 +1,32 @@
#ifndef WFD_MOCK_LIBCONFIG_HPP
#define WFD_MOCK_LIBCONFIG_HPP
#include <libconfig.h>
#include <gmock/gmock.h>
namespace webfused_test
{
class ILibConfig
{
public:
virtual ~ILibConfig() = default;
virtual config_setting_t * config_setting_get_elem(
config_setting_t const * setting,
unsigned int i) = 0;
};
class MockLibConfig: public ILibConfig
{
public:
MockLibConfig();
~MockLibConfig() override;
MOCK_METHOD2(config_setting_get_elem, config_setting_t * (
config_setting_t const * setting,
unsigned int i));
};
}
#endif

31
test/mock_linux.cc Normal file
View File

@@ -0,0 +1,31 @@
#include "mock_linux.hpp"
#include "wrap_utils.hpp"
extern "C"
{
static webfused_test::ILinux * wfd_MockLinux = nullptr;
WFD_WRAP_FUNC0( wfd_MockLinux, uid_t, getuid);
WFD_WRAP_FUNC1( wfd_MockLinux, struct group *, getgrnam, char const *);
WFD_WRAP_FUNC1( wfd_MockLinux, int, setgid, gid_t);
WFD_WRAP_FUNC2( wfd_MockLinux, int, setgroups, int, gid_t *);
WFD_WRAP_FUNC1( wfd_MockLinux, struct passwd *, getpwnam, char const *);
WFD_WRAP_FUNC1( wfd_MockLinux, int, setuid, uid_t);
}
namespace webfused_test
{
MockLinux::MockLinux()
{
wfd_MockLinux = this;
}
MockLinux::~MockLinux()
{
wfd_MockLinux = nullptr;
}
}

41
test/mock_linux.hpp Normal file
View File

@@ -0,0 +1,41 @@
#ifndef WFD_MOCK_LINUX_HPP
#define WFD_MOCK_LINUX_HPP
#include <unistd.h>
#include <sys/types.h>
#include <grp.h>
#include <pwd.h>
#include <gmock/gmock.h>
namespace webfused_test
{
class ILinux
{
public:
virtual ~ILinux() = default;
virtual uid_t getuid() = 0;
virtual struct group * getgrnam(char const * name) = 0;
virtual int setgid(gid_t gid) = 0;
virtual int setgroups(int size, gid_t * list) = 0;
virtual struct passwd * getpwnam(char const * name) = 0;
virtual int setuid(uid_t uid) = 0;
};
class MockLinux: public ILinux
{
public:
MockLinux();
~MockLinux();
MOCK_METHOD0(getuid, uid_t());
MOCK_METHOD1(getgrnam, struct group * (char const * name));
MOCK_METHOD1(setgid, int (gid_t gid));
MOCK_METHOD2(setgroups, int (int size, gid_t * list));
MOCK_METHOD1(getpwnam, struct passwd * (char const * name));
MOCK_METHOD1(setuid, int (uid_t uid));
};
}
#endif

154
test/test_change_user.cc Normal file
View File

@@ -0,0 +1,154 @@
#include "webfused/change_user.h"
#include "mock_linux.hpp"
#include <gtest/gtest.h>
using ::webfused_test::MockLinux;
using ::testing::StrictMock;
using ::testing::Return;
using ::testing::StrEq;
TEST(change_user, nop_id_not_root)
{
StrictMock<MockLinux> sys;
EXPECT_CALL(sys, getuid).Times(1).WillOnce(Return(42));
bool success = wfd_change_user("webfused", "daemons");
ASSERT_TRUE(success);
}
TEST(change_user, change_successfully)
{
struct group group;
group.gr_gid = 23;
struct passwd userinfo;
userinfo.pw_uid = 42;
StrictMock<MockLinux> sys;
EXPECT_CALL(sys, getuid).Times(1).WillOnce(Return(0));
EXPECT_CALL(sys, getgrnam(StrEq("daemons"))).Times(1).WillOnce(Return(&group));
EXPECT_CALL(sys, setgid(23)).Times(1).WillOnce(Return(0));
EXPECT_CALL(sys, setgroups(0, nullptr)).Times(1).WillOnce(Return(0));
EXPECT_CALL(sys, getpwnam("webfused")).Times(1).WillOnce(Return(&userinfo));
EXPECT_CALL(sys, setuid(42)).Times(1).WillOnce(Return(0));
bool success = wfd_change_user("webfused", "daemons");
ASSERT_TRUE(success);
}
TEST(change_user, fail_no_username_or_password)
{
StrictMock<MockLinux> sys;
EXPECT_CALL(sys, getuid).WillRepeatedly(Return(0));
ASSERT_FALSE(wfd_change_user(nullptr, "daemons"));
ASSERT_FALSE(wfd_change_user("webfused", nullptr));
ASSERT_FALSE(wfd_change_user(nullptr, nullptr));
}
TEST(change_user, fail_setuid)
{
struct group group;
group.gr_gid = 23;
struct passwd userinfo;
userinfo.pw_uid = 42;
StrictMock<MockLinux> sys;
EXPECT_CALL(sys, getuid).Times(1).WillOnce(Return(0));
EXPECT_CALL(sys, getgrnam(StrEq("daemons"))).Times(1).WillOnce(Return(&group));
EXPECT_CALL(sys, setgid(23)).Times(1).WillOnce(Return(0));
EXPECT_CALL(sys, setgroups(0, nullptr)).Times(1).WillOnce(Return(0));
EXPECT_CALL(sys, getpwnam("webfused")).Times(1).WillOnce(Return(&userinfo));
EXPECT_CALL(sys, setuid(42)).Times(1).WillOnce(Return(-1));
bool success = wfd_change_user("webfused", "daemons");
ASSERT_FALSE(success);
}
TEST(change_user, fail_getpwnam)
{
struct group group;
group.gr_gid = 23;
StrictMock<MockLinux> sys;
EXPECT_CALL(sys, getuid).Times(1).WillOnce(Return(0));
EXPECT_CALL(sys, getgrnam(StrEq("daemons"))).Times(1).WillOnce(Return(&group));
EXPECT_CALL(sys, setgid(23)).Times(1).WillOnce(Return(0));
EXPECT_CALL(sys, setgroups(0, nullptr)).Times(1).WillOnce(Return(0));
EXPECT_CALL(sys, getpwnam("webfused")).Times(1).WillOnce(Return(nullptr));
bool success = wfd_change_user("webfused", "daemons");
ASSERT_FALSE(success);
}
TEST(change_user, fail_setgroups)
{
struct group group;
group.gr_gid = 23;
StrictMock<MockLinux> sys;
EXPECT_CALL(sys, getuid).Times(1).WillOnce(Return(0));
EXPECT_CALL(sys, getgrnam(StrEq("daemons"))).Times(1).WillOnce(Return(&group));
EXPECT_CALL(sys, setgid(23)).Times(1).WillOnce(Return(0));
EXPECT_CALL(sys, setgroups(0, nullptr)).Times(1).WillOnce(Return(-1));
bool success = wfd_change_user("webfused", "daemons");
ASSERT_FALSE(success);
}
TEST(change_user, fail_setgid)
{
struct group group;
group.gr_gid = 23;
StrictMock<MockLinux> sys;
EXPECT_CALL(sys, getuid).Times(1).WillOnce(Return(0));
EXPECT_CALL(sys, getgrnam(StrEq("daemons"))).Times(1).WillOnce(Return(&group));
EXPECT_CALL(sys, setgid(23)).Times(1).WillOnce(Return(-1));
bool success = wfd_change_user("webfused", "daemons");
ASSERT_FALSE(success);
}
TEST(change_user, fail_getgrpnam)
{
StrictMock<MockLinux> sys;
EXPECT_CALL(sys, getuid).Times(1).WillOnce(Return(0));
EXPECT_CALL(sys, getgrnam(StrEq("daemons"))).Times(1).WillOnce(Return(nullptr));
bool success = wfd_change_user("webfused", "daemons");
ASSERT_FALSE(success);
}
TEST(change_user, fail_switch_to_root)
{
struct group group;
group.gr_gid = 23;
struct passwd userinfo;
userinfo.pw_uid = 0;
StrictMock<MockLinux> sys;
EXPECT_CALL(sys, getuid).Times(1).WillOnce(Return(0));
EXPECT_CALL(sys, getgrnam(StrEq("daemons"))).Times(1).WillOnce(Return(&group));
EXPECT_CALL(sys, setgid(23)).Times(1).WillOnce(Return(0));
EXPECT_CALL(sys, setgroups(0, nullptr)).Times(1).WillOnce(Return(0));
EXPECT_CALL(sys, getpwnam("webfused")).Times(1).WillOnce(Return(&userinfo));
bool success = wfd_change_user("webfused", "daemons");
ASSERT_FALSE(success);
}
TEST(change_user, fail_switch_to_root_group)
{
struct group group;
group.gr_gid = 0;
StrictMock<MockLinux> sys;
EXPECT_CALL(sys, getuid).Times(1).WillOnce(Return(0));
EXPECT_CALL(sys, getgrnam(StrEq("daemons"))).Times(1).WillOnce(Return(&group));
bool success = wfd_change_user("webfused", "daemons");
ASSERT_FALSE(success);
}

View File

@@ -5,7 +5,7 @@
#include "webfused/log/log.h"
#include "mock_logger.hpp"
#include "mock_config_builder.hpp"
#include "mock_libconfig.hpp"
using ::testing::_;
using ::testing::Return;
@@ -13,6 +13,7 @@ using ::testing::StrictMock;
using ::testing::StrEq;
using ::webfused_test::MockLogger;
using ::webfused_test::MockConfigBuilder;
using ::webfused_test::MockLibConfig;
TEST(config, is_loadable)
{
@@ -372,6 +373,33 @@ TEST(config, failed_missing_auth_settings)
ASSERT_EQ(nullptr, config);
}
TEST(config, failed_auth_settings_get_elem)
{
MockLogger logger;
EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1);
EXPECT_CALL(logger, onclose()).Times(1);
StrictMock<MockConfigBuilder> builder;
EXPECT_CALL(builder, create).Times(1).WillOnce(Return(builder.getBuilder()));
EXPECT_CALL(builder, dispose(_)).Times(1);
MockLibConfig libconfig;
EXPECT_CALL(libconfig, config_setting_get_elem(_,_)).Times(1).WillOnce(Return(nullptr));
char const config_text[] =
"version = { major = 1, minor = 0 }\n"
"authentication:\n"
"(\n"
" {\n"
" provider = \"test\"\n"
" settings: { }\n"
" }\n"
")\n"
;
struct wfd_config * config = wfd_config_load_string(config_text);
ASSERT_EQ(nullptr, config);
}
TEST(config, filesystems)
{
MockLogger logger;
@@ -479,6 +507,31 @@ TEST(config, filesystems_failed_missing_mountpoint)
ASSERT_EQ(nullptr, config);
}
TEST(config, filesystems_failed_missing_elem)
{
MockLogger logger;
EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1);
EXPECT_CALL(logger, onclose()).Times(1);
StrictMock<MockConfigBuilder> builder;
EXPECT_CALL(builder, create).Times(1).WillOnce(Return(builder.getBuilder()));
EXPECT_CALL(builder, dispose(_)).Times(1);
EXPECT_CALL(builder, addFilesystem(_, _)).Times(0);
MockLibConfig libconfig;
EXPECT_CALL(libconfig, config_setting_get_elem(_,_)).Times(1).WillOnce(Return(nullptr));
char const config_text[] =
"version = { major = 1, minor = 0 }\n"
"filesystems:\n"
"(\n"
" {name = \"foo\", mount_point = \"/tmp/test\" }\n"
")\n"
;
struct wfd_config * config = wfd_config_load_string(config_text);
ASSERT_EQ(nullptr, config);
}
TEST(config, log)
{
MockLogger logger;

46
test/wrap_utils.hpp Normal file
View File

@@ -0,0 +1,46 @@
#ifndef WFD_WRAP_UTILS_HPP
#define WFD_WRAP_UTILS_HPP
#define WFD_WRAP_FUNC0( GLOBAL_VAR, RETURN_TYPE, FUNC_NAME ) \
extern RETURN_TYPE __real_ ## FUNC_NAME (); \
RETURN_TYPE __wrap_ ## FUNC_NAME () \
{ \
if (nullptr == GLOBAL_VAR ) \
{ \
return __real_ ## FUNC_NAME (); \
} \
else \
{ \
return GLOBAL_VAR -> FUNC_NAME(); \
} \
}
#define WFD_WRAP_FUNC1( GLOBAL_VAR, RETURN_TYPE, FUNC_NAME, ARG1_TYPE ) \
extern RETURN_TYPE __real_ ## FUNC_NAME (ARG1_TYPE); \
RETURN_TYPE __wrap_ ## FUNC_NAME (ARG1_TYPE arg1) \
{ \
if (nullptr == GLOBAL_VAR ) \
{ \
return __real_ ## FUNC_NAME (arg1); \
} \
else \
{ \
return GLOBAL_VAR -> FUNC_NAME(arg1); \
} \
}
#define WFD_WRAP_FUNC2( GLOBAL_VAR, RETURN_TYPE, FUNC_NAME, ARG1_TYPE, ARG2_TYPE ) \
extern RETURN_TYPE __real_ ## FUNC_NAME (ARG1_TYPE, ARG2_TYPE); \
RETURN_TYPE __wrap_ ## FUNC_NAME (ARG1_TYPE arg1, ARG2_TYPE arg2) \
{ \
if (nullptr == GLOBAL_VAR ) \
{ \
return __real_ ## FUNC_NAME (arg1, arg2); \
} \
else \
{ \
return GLOBAL_VAR -> FUNC_NAME(arg1, arg2); \
} \
}
#endif