#include "test.h" #include #include #include #include #include #include #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); }