increased test coverage

pull/5/head
Falk Werner 4 years ago
parent 7553846629
commit ba270f1d0d

@ -124,6 +124,8 @@ add_executable(alltests
test/mock_credentials.cc
test/mock_settings.cc
test/mock_pam.cc
test/mock_libconfig.cc
test/mock_linux.cc
test/test_config_factory.cc
test/test_config.cc
test/test_settings.cc
@ -136,6 +138,7 @@ add_executable(alltests
test/test_stderr_logger.cc
test/test_syslog_logger.cc
test/test_daemon.cc
test/test_change_user.cc
)
target_include_directories(alltests PRIVATE
@ -172,6 +175,15 @@ target_link_libraries(alltests PRIVATE
-Wl,--wrap=pam_authenticate
-Wl,--wrap=pam_acct_mgmt
-Wl,--wrap=config_setting_get_elem
-Wl,--wrap=getuid
-Wl,--wrap=getgrnam
-Wl,--wrap=setgid
-Wl,--wrap=setgroups
-Wl,--wrap=getpwnam
-Wl,--wrap=setuid
webfused-static
userdb
${LIBCONFIG_LIBRARIES}

@ -94,7 +94,7 @@ wfd_change_user(
if (is_root)
{
result = ((NULL != user) || (NULL != group));
result = ((NULL != user) && (NULL != group));
if (!result)
{
WFD_ERROR("webfuse daemon cannot be run as root: specify user and group in config");

@ -71,7 +71,7 @@ wfd_config_read_logger(
int rc = config_lookup_string(config, "log.provider", &provider);
if (CONFIG_TRUE != rc)
{
WFD_ERROR("missing log provider");
WFD_ERROR("failed to load config: missing log provider");
result = false;
}
@ -81,7 +81,7 @@ wfd_config_read_logger(
rc = config_lookup_string(config, "log.level", &level_str);
if (CONFIG_TRUE != rc)
{
WFD_ERROR("missing log level");
WFD_ERROR("failed to load config: missing log level");
result = false;
}
}
@ -92,7 +92,7 @@ wfd_config_read_logger(
bool success = wfd_log_level_parse(level_str, &level);
if (!success)
{
WFD_ERROR("failed to parse log level: unknown valuie \'%s\'", level_str);
WFD_ERROR("failed to parse log level: unknown value \'%s\'", level_str);
result = false;
}
}
@ -110,7 +110,7 @@ wfd_config_read_logger(
return result;
}
static bool
static void
wfd_config_read_server(
config_t * config,
struct wfd_config * builder)
@ -149,8 +149,6 @@ wfd_config_read_server(
{
wfd_config_set_server_document_root(builder, doc_root);
}
return true;
}
static bool
@ -159,6 +157,10 @@ wfd_config_read_authenticator(
struct wfd_config * builder)
{
bool result = (NULL != authenticator);
if (!result)
{
WFD_ERROR("failed to load config: invalid authentication section");
}
char const * provider_name = NULL;
if (result)
@ -166,7 +168,7 @@ wfd_config_read_authenticator(
int rc = config_setting_lookup_string(authenticator, "provider", &provider_name);
if (CONFIG_TRUE != rc)
{
WFD_ERROR("missing authentication provider");
WFD_ERROR("failed to load config: missing authentication provider");
result = false;
}
}
@ -177,7 +179,7 @@ wfd_config_read_authenticator(
settings = config_setting_lookup(authenticator, "settings");
if (NULL == settings)
{
WFD_ERROR("missing authentication settings");
WFD_ERROR("failed to load config: missing authentication settings");
result = false;
}
}
@ -312,12 +314,16 @@ wfd_config_load(
bool success = wfd_config_check_version(config)
&& wfd_config_read_logger(config, result)
&& wfd_config_read_server(config, result)
&& wfd_config_read_authentication(config, result)
&& wfd_config_read_filesystems(config, result)
&& wfd_config_read_user(config, result)
;
if (success)
{
wfd_config_read_server(config, result);
}
if (!success)
{
wfd_config_dispose(result);

@ -141,10 +141,6 @@ wfd_mountpoint_factory_create_mountpoint(
wf_mountpoint_set_userdata(result,
&fs->in_use, &wfd_mountpoint_factory_release_mountpoint);
WFD_INFO("create mountpoint \'%s\' at path \'%s\': %s",
filesystem,
fs->mount_point,
result ? "success" : "failure");
WFD_INFO("created mountpoint \'%s\' at path \'%s\'", filesystem, fs->mount_point);
return result;
}

@ -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;
}
}

@ -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

@ -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;
}
}

@ -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

@ -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);
}

@ -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;

@ -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
Loading…
Cancel
Save