test: Initial testing framework
Configure with --enable-testtools. BLD_ROOT is now the top build directory. Current test requires ttynvt to be started (by root) like # BLD_ROOT/src/ttynvt -d -E -S localhost:1234 -n ttyNVT99 Device and server name parameters must be as shown above. Run tests like $ make -C BLD_ROOT test # Builds the other programs too $ make -C BLD_ROOT/test # Only running tests $ make -C BLD_ROOT/test V=1 RUN_OPTS="--gtest_filter=Test1.t1"
This commit is contained in:
@@ -9,3 +9,11 @@ if BUILD_TESTTOOLS
|
|||||||
SUBDIRS += nvtsrv
|
SUBDIRS += nvtsrv
|
||||||
SUBDIRS += nvttest
|
SUBDIRS += nvttest
|
||||||
endif
|
endif
|
||||||
|
if BUILD_TEST
|
||||||
|
SUBDIRS += test
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: $(SUBDIRS) test
|
||||||
|
$(SUBDIRS) test:
|
||||||
|
$(MAKE) -C $@
|
||||||
|
test: $(SUBDIRS)
|
||||||
|
|||||||
+4
-1
@@ -6,10 +6,10 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
|||||||
AC_USE_SYSTEM_EXTENSIONS
|
AC_USE_SYSTEM_EXTENSIONS
|
||||||
|
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
AC_PROG_CXX
|
||||||
|
|
||||||
AC_PROG_INSTALL
|
AC_PROG_INSTALL
|
||||||
|
|
||||||
define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])dnl
|
|
||||||
define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl
|
define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl
|
||||||
define([AC_LIBTOOL_LANG_GCJ_CONFIG], [:])dnl
|
define([AC_LIBTOOL_LANG_GCJ_CONFIG], [:])dnl
|
||||||
|
|
||||||
@@ -31,6 +31,8 @@ AC_ARG_ENABLE(testtools,
|
|||||||
enable_testtools=no)
|
enable_testtools=no)
|
||||||
AM_CONDITIONAL([BUILD_TESTTOOLS], [test "x$enable_testtools" = "xyes"])
|
AM_CONDITIONAL([BUILD_TESTTOOLS], [test "x$enable_testtools" = "xyes"])
|
||||||
|
|
||||||
|
AM_CONDITIONAL(BUILD_TEST, false)
|
||||||
|
|
||||||
CFLAGS_WARN="$CFLAGS_WARN -Wall -Wextra -Werror -Wno-unused-parameter"
|
CFLAGS_WARN="$CFLAGS_WARN -Wall -Wextra -Werror -Wno-unused-parameter"
|
||||||
CFLAGS_WARN="$CFLAGS_WARN -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes"
|
CFLAGS_WARN="$CFLAGS_WARN -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes"
|
||||||
CFLAGS_WARN="$CFLAGS_WARN -Waggregate-return -Wpointer-arith -Wshadow -Wwrite-strings"
|
CFLAGS_WARN="$CFLAGS_WARN -Waggregate-return -Wpointer-arith -Wshadow -Wwrite-strings"
|
||||||
@@ -44,6 +46,7 @@ lib/Makefile
|
|||||||
src/Makefile
|
src/Makefile
|
||||||
nvtsrv/Makefile
|
nvtsrv/Makefile
|
||||||
nvttest/Makefile
|
nvttest/Makefile
|
||||||
|
test/Makefile
|
||||||
])
|
])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# Unit test makefile
|
||||||
|
#
|
||||||
|
.NOTPARALLEL:
|
||||||
|
|
||||||
|
noinst_PROGRAMS = $(GTESTS)
|
||||||
|
|
||||||
|
GTEST_LIBS = -lgtest -lstdc++
|
||||||
|
|
||||||
|
GTESTS = test_misc test_nvttest
|
||||||
|
|
||||||
|
AM_CFLAGS = -Wall -Wextra -Werror -Wno-unused-parameter
|
||||||
|
AM_CFLAGS += $(CFLAGS_ASAN)
|
||||||
|
|
||||||
|
AM_CXXFLAGS = $(AM_CFLAGS)
|
||||||
|
|
||||||
|
AM_CPPFLAGS = -I $(top_builddir)
|
||||||
|
AM_CPPFLAGS += -D TOP_SRC_DIR='"$(top_srcdir)"' -D TOP_BLD_DIR='"$(top_builddir)"'
|
||||||
|
AM_CPPFLAGS += -D BUILD_TEST=1
|
||||||
|
|
||||||
|
LIBS += $(GTEST_LIBS)
|
||||||
|
|
||||||
|
TEST_COMMON = test.cpp test.h
|
||||||
|
|
||||||
|
test_misc_SOURCES = $(TEST_COMMON) test_misc.cpp
|
||||||
|
test_misc_LDADD = $(LIBS)
|
||||||
|
|
||||||
|
test_nvttest_SOURCES = $(TEST_COMMON) test_nvttest.cpp
|
||||||
|
test_nvttest_LDADD = $(LIBS)
|
||||||
|
|
||||||
|
TESTS_RUN = $(addprefix run-, $(GTESTS))
|
||||||
|
|
||||||
|
VG_PROG = valgrind --leak-check=full
|
||||||
|
|
||||||
|
all-local: run
|
||||||
|
|
||||||
|
.PHONY: run $(TESTS_RUN)
|
||||||
|
run: $(TESTS_RUN)
|
||||||
|
$(TESTS_RUN): run-%: %
|
||||||
|
# $(TEST_ENV) ./.libs/$* $(RUN_OPTS)
|
||||||
|
$(TEST_ENV) ./$* $(RUN_OPTS)
|
||||||
|
|
||||||
|
TESTS_RUN_VG = $(addprefix run-vg-, $(GTESTS))
|
||||||
|
|
||||||
|
.PHONY: run-vg $(TESTS_RUN_VG)
|
||||||
|
run-vg: $(TESTS_RUN_VG)
|
||||||
|
$(TESTS_RUN_VG): run-vg-%: %
|
||||||
|
# $(TEST_ENV) $(VG_PROG) ./.libs/$* $(RUN_OPTS)
|
||||||
|
$(TEST_ENV) $(VG_PROG) ./$* $(RUN_OPTS)
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* General test stuff
|
||||||
|
*
|
||||||
|
* - The main() function
|
||||||
|
* - Some printing functions
|
||||||
|
*/
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
int debug = 0;
|
||||||
|
|
||||||
|
static bool ttyout = false;
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
ttyout = isatty(STDOUT_FILENO);
|
||||||
|
|
||||||
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
|
||||||
|
for (argc--, argv++; argc > 0; argc--, argv++)
|
||||||
|
{
|
||||||
|
s = argv[0];
|
||||||
|
if (*s++ != '-')
|
||||||
|
break;
|
||||||
|
again:
|
||||||
|
switch (*s++)
|
||||||
|
{
|
||||||
|
case 'd':
|
||||||
|
debug++;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
void _pr_text(const char *col, const char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
char fmtx[1024];
|
||||||
|
|
||||||
|
if (ttyout)
|
||||||
|
snprintf(fmtx, sizeof(fmtx), "%s[ ] - %s%s\n",
|
||||||
|
col, fmt, COL_RST);
|
||||||
|
else
|
||||||
|
snprintf(fmtx, sizeof(fmtx), "[ ] - %s\n", fmt);
|
||||||
|
fmt = fmtx;
|
||||||
|
|
||||||
|
vprintf(fmt, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pr_text(const char *col, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
_pr_text(col, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pr_info(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
_pr_text(COL_YEL, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef TEST_H
|
||||||
|
#define TEST_H 1
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#define D(...) do{ if (debug) printf(__VA_ARGS__); }while(0)
|
||||||
|
#define D2(...) do{ if (debug > 1) printf(__VA_ARGS__); }while(0)
|
||||||
|
|
||||||
|
extern int debug;
|
||||||
|
|
||||||
|
#define COL_RST "\x1B[0m"
|
||||||
|
#define COL_RED "\x1B[31m"
|
||||||
|
#define COL_GRN "\x1B[32m"
|
||||||
|
#define COL_YEL "\x1B[33m"
|
||||||
|
#define COL_BLU "\x1B[34m"
|
||||||
|
#define COL_MAG "\x1B[35m"
|
||||||
|
#define COL_CYN "\x1B[36m"
|
||||||
|
#define COL_WHT "\x1B[37m"
|
||||||
|
|
||||||
|
void pr_text(const char *col, const char *fmt, ...);
|
||||||
|
void pr_info(const char *fmt, ...);
|
||||||
|
|
||||||
|
#endif /* TEST_H */
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
TEST(Misc, dummy)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(1, 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,216 @@
|
|||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#define NVT_NAME "ttyNVT99"
|
||||||
|
#define NVT_DEV "/dev/" NVT_NAME
|
||||||
|
|
||||||
|
#define NVT_SRV TOP_BLD_DIR "/nvtsrv/nvtsrv"
|
||||||
|
#define NVT_TEST TOP_BLD_DIR "/nvttest/nvttest"
|
||||||
|
|
||||||
|
#define NVT_OPTS "-D" NVT_NAME
|
||||||
|
|
||||||
|
#define LAUNCH_NVTTEST(...) proc_launch(NVT_TEST, NVT_OPTS, __VA_ARGS__)
|
||||||
|
|
||||||
|
pid_t proc_spawn(char **argv)
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
for (int i = 0, len = 0; argv[i]; i++)
|
||||||
|
len += snprintf(buf + len, sizeof(buf) - len, "%s ", argv[i]);
|
||||||
|
pr_info("Launching: %s", buf);
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid > 0)
|
||||||
|
{
|
||||||
|
pr_info("... ok, pid = %d", pid);
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Child
|
||||||
|
|
||||||
|
execv(argv[0], argv);
|
||||||
|
|
||||||
|
pr_info("Launch failed: %m");
|
||||||
|
|
||||||
|
EXPECT_EQ(1, 0);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void proc_waitfor(const char *name, pid_t pid)
|
||||||
|
{
|
||||||
|
int err, wstatus;
|
||||||
|
|
||||||
|
pr_info("Wait for %s (pid %d) to finish", name, pid);
|
||||||
|
|
||||||
|
wstatus = 0;
|
||||||
|
err = waitpid(pid, &wstatus, 0);
|
||||||
|
if (err > 0)
|
||||||
|
pr_info("... ok, status = %x", wstatus);
|
||||||
|
else
|
||||||
|
pr_info("... error: %m");
|
||||||
|
|
||||||
|
EXPECT_GT(err, 0);
|
||||||
|
EXPECT_EQ(WEXITSTATUS(wstatus), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static pid_t proc_launch(const char *prog, ...)
|
||||||
|
{
|
||||||
|
char *argv[16], *arg;
|
||||||
|
int i;
|
||||||
|
pid_t pid;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, prog);
|
||||||
|
|
||||||
|
arg = (char *)prog;
|
||||||
|
i = 0;
|
||||||
|
argv[i++] = arg;
|
||||||
|
for (; arg != NULL;)
|
||||||
|
{
|
||||||
|
arg = va_arg(args, char *);
|
||||||
|
|
||||||
|
argv[i++] = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
pid = proc_spawn(argv);
|
||||||
|
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ttynvt_check()
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
ok = stat(NVT_DEV, &st) == 0 && S_ISCHR(st.st_mode);
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "\n%s"
|
||||||
|
"************************************************************\n"
|
||||||
|
"*** Invalid device file: '%s'\n"
|
||||||
|
"*** Ensure that ttynvt is launched correcly, e.g.:\n"
|
||||||
|
"# ttynvt -d -E -S localhost:1234 -n %s\n"
|
||||||
|
"*** ttynvt must run as root, and the device and server names\n"
|
||||||
|
"*** must be as shown above.\n"
|
||||||
|
"************************************************************\n"
|
||||||
|
"%s\n", COL_CYN, NVT_DEV, NVT_NAME, COL_RST);
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TEST(Test1, t1)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
pid_t pid_srv, pid;
|
||||||
|
|
||||||
|
ASSERT_TRUE(ttynvt_check());
|
||||||
|
|
||||||
|
pid_srv = proc_launch(NVT_SRV, "-de", "localhost:1234", NULL);
|
||||||
|
ASSERT_GT(pid_srv, 0);
|
||||||
|
|
||||||
|
usleep(100000);
|
||||||
|
|
||||||
|
pid = LAUNCH_NVTTEST(NULL);
|
||||||
|
ASSERT_GT(pid, 0);
|
||||||
|
|
||||||
|
proc_waitfor("nvttest", pid);
|
||||||
|
|
||||||
|
pr_info("Terminate nvtsrv");
|
||||||
|
err = kill(pid_srv, SIGTERM);
|
||||||
|
EXPECT_EQ(err, 0);
|
||||||
|
|
||||||
|
proc_waitfor("nvtsrv", pid_srv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Using fixture */
|
||||||
|
|
||||||
|
/**INDENT-OFF**/
|
||||||
|
class Test2:public::testing::Test {
|
||||||
|
pid_t pid_srv;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Test2() { }
|
||||||
|
virtual ~Test2() { }
|
||||||
|
|
||||||
|
virtual void SetUp() {
|
||||||
|
|
||||||
|
// Ensure ttynvt is running
|
||||||
|
ASSERT_TRUE(ttynvt_check());
|
||||||
|
|
||||||
|
// NB! Quiet nvtsrv
|
||||||
|
pid_srv = proc_launch(NVT_SRV, "-qe", "localhost:1234", NULL);
|
||||||
|
ASSERT_GT(pid_srv, 0);
|
||||||
|
|
||||||
|
usleep(100000);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void TearDown() {
|
||||||
|
int err;
|
||||||
|
|
||||||
|
pr_info("Terminate nvtsrv");
|
||||||
|
err = kill(pid_srv, SIGTERM);
|
||||||
|
EXPECT_EQ(err, 0);
|
||||||
|
|
||||||
|
proc_waitfor("nvtsrv", pid_srv);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**INDENT-ON**/
|
||||||
|
|
||||||
|
TEST_F(Test2, t1)
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
pid = LAUNCH_NVTTEST(NULL);
|
||||||
|
ASSERT_GT(pid, 0);
|
||||||
|
|
||||||
|
proc_waitfor("nvttest", pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiple threads
|
||||||
|
TEST_F(Test2, t2)
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
// NB! Quiet nvttest
|
||||||
|
pid = LAUNCH_NVTTEST("-t5", "-q", NULL);
|
||||||
|
ASSERT_GT(pid, 0);
|
||||||
|
|
||||||
|
proc_waitfor("nvttest", pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiple loops
|
||||||
|
TEST_F(Test2, t3)
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
// NB! Quiet nvttest
|
||||||
|
pid = LAUNCH_NVTTEST("-n5", "-q", NULL);
|
||||||
|
ASSERT_GT(pid, 0);
|
||||||
|
|
||||||
|
proc_waitfor("nvttest", pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiple threads and loops
|
||||||
|
TEST_F(Test2, t4)
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
// NB! Quiet nvttest
|
||||||
|
pid = LAUNCH_NVTTEST("-n5", "-t5", "-q", NULL);
|
||||||
|
ASSERT_GT(pid, 0);
|
||||||
|
|
||||||
|
proc_waitfor("nvttest", pid);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user