From e7cfedd6dedab619603ddc3c3832a2b7a0f82f89 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 14 Oct 2009 13:14:43 -0700 Subject: [PATCH] Add test to ensure that time advances both normally and in a daemon. This commit adds a test to ensure that the fix that makes daemonize() reinitialize the periodic timer actually worked. --- lib/timeval.c | 3 +- lib/timeval.h | 2 + tests/automake.mk | 5 ++ tests/test-timeval.c | 118 +++++++++++++++++++++++++++++++++++++++++++ tests/testsuite.at | 1 + tests/timeval.at | 22 ++++++++ 6 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 tests/test-timeval.c create mode 100644 tests/timeval.at diff --git a/lib/timeval.c b/lib/timeval.c index 314b3f430..7df8a654f 100644 --- a/lib/timeval.c +++ b/lib/timeval.c @@ -51,7 +51,6 @@ static void block_sigalrm(sigset_t *); static void unblock_sigalrm(const sigset_t *); static void log_poll_interval(long long int last_wakeup, const struct rusage *last_rusage); -static long long int timeval_to_msec(const struct timeval *); /* Initializes the timetracking module. */ void @@ -255,7 +254,7 @@ unblock_sigalrm(const sigset_t *oldsigs) } } -static long long int +long long int timeval_to_msec(const struct timeval *tv) { return (long long int) tv->tv_sec * 1000 + tv->tv_usec / 1000; diff --git a/lib/timeval.h b/lib/timeval.h index 8567d7547..7da3b383b 100644 --- a/lib/timeval.h +++ b/lib/timeval.h @@ -49,4 +49,6 @@ void time_timeval(struct timeval *); void time_alarm(unsigned int secs); int time_poll(struct pollfd *, int n_pollfds, int timeout); +long long int timeval_to_msec(const struct timeval *); + #endif /* timeval.h */ diff --git a/tests/automake.mk b/tests/automake.mk index 7659a268f..933621979 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -8,6 +8,7 @@ TESTSUITE_AT = \ tests/testsuite.at \ tests/lcov-pre.at \ tests/library.at \ + tests/timeval.at \ tests/stp.at \ tests/ovs-vsctl.at \ tests/lcov-post.at @@ -66,6 +67,10 @@ noinst_PROGRAMS += tests/test-sha1 tests_test_sha1_SOURCES = tests/test-sha1.c tests_test_sha1_LDADD = lib/libopenvswitch.a +noinst_PROGRAMS += tests/test-timeval +tests_test_timeval_SOURCES = tests/test-timeval.c +tests_test_timeval_LDADD = lib/libopenvswitch.a + noinst_PROGRAMS += tests/test-type-props tests_test_type_props_SOURCES = tests/test-type-props.c diff --git a/tests/test-timeval.c b/tests/test-timeval.c new file mode 100644 index 000000000..ba8b3d39d --- /dev/null +++ b/tests/test-timeval.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2009 Nicira Networks. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "timeval.h" + +#include +#include +#include +#include +#include + +#include "daemon.h" +#include "util.h" + +#undef NDEBUG +#include + +static long long int +gettimeofday_in_msec(void) +{ + struct timeval tv; + + assert(!gettimeofday(&tv, NULL)); + return timeval_to_msec(&tv); +} + +static void +do_test(void) +{ + /* Wait until we are awakened by a signal (typically EINTR due to the + * setitimer()). Then ensure that, if time has really advanced by + * TIME_UPDATE_INTERVAL, then time_msec() reports that it advanced. + */ + long long int start_time_msec; + long long int start_gtod; + + start_time_msec = time_msec(); + start_gtod = gettimeofday_in_msec(); + for (;;) { + /* Wait up to 1 second. Using select() to do the timeout avoids + * interfering with the interval timer. */ + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + assert(select(0, NULL, NULL, NULL, &timeout) == -1 && errno == EINTR); + + if (gettimeofday_in_msec() - start_gtod >= TIME_UPDATE_INTERVAL) { + assert(time_msec() - start_time_msec >= TIME_UPDATE_INTERVAL); + break; + } + } +} + +static void +usage(void) +{ + ovs_fatal(0, "usage: %s TEST, where TEST is \"plain\" or \"daemon\"", + program_name); +} + +int +main(int argc, char *argv[]) +{ + set_program_name(argv[0]); + time_init(); + + if (argc != 2) { + usage(); + } else if (!strcmp(argv[1], "plain")) { + do_test(); + } else if (!strcmp(argv[1], "daemon")) { + /* Test that time still advances even in a daemon. This is an + * interesting test because fork() cancels the interval timer. */ + char cwd[1024]; + FILE *success; + + assert(getcwd(cwd, sizeof cwd) == cwd); + + unlink("test-timeval.success"); + + /* Daemonize, with a pidfile in the current directory. */ + set_detach(); + set_pidfile(xasprintf("%s/test-timeval.pid", cwd)); + set_no_chdir(); + daemonize(); + + /* Run the test. */ + do_test(); + + /* Report success by writing out a file, since the ultimate invoker of + * test-timeval can't wait on the daemonized process. */ + success = fopen("test-timeval.success", "w"); + if (!success) { + ovs_fatal(errno, "test-timeval.success: create failed"); + } + fprintf(success, "success\n"); + fclose(success); + } else { + usage(); + } + + return 0; +} diff --git a/tests/testsuite.at b/tests/testsuite.at index c232a8779..9edfdeed7 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -19,6 +19,7 @@ AT_TESTED([ovs-vsctl]) m4_include([tests/lcov-pre.at]) m4_include([tests/library.at]) +m4_include([tests/timeval.at]) m4_include([tests/stp.at]) m4_include([tests/ovs-vsctl.at]) m4_include([tests/lcov-post.at]) diff --git a/tests/timeval.at b/tests/timeval.at new file mode 100644 index 000000000..992706f7d --- /dev/null +++ b/tests/timeval.at @@ -0,0 +1,22 @@ +AT_BANNER([timeval unit tests]) + +AT_SETUP([check that time advances]) +AT_KEYWORDS([timeval]) +OVS_CHECK_LCOV([test-timeval plain], [0]) +AT_CLEANUP + +AT_SETUP([check that time advances after daemonize()]) +AT_KEYWORDS([timeval]) +OVS_CHECK_LCOV([test-timeval daemon], [0]) +AT_CHECK( + [# First try a quick sleep, so that the test completes very quickly + # in the normal case. POSIX doesn't require fractional times to + # work, so this might not work. + sleep 0.1; if test -e test-timeval.success; then echo success; exit 0; fi + # Then wait up to 2 seconds. + sleep 1; if test -e test-timeval.success; then echo success; exit 0; fi + sleep 1; if test -e test-timeval.success; then echo success; exit 0; fi + echo failure; exit 1], + [0], [success +], []) +AT_CLEANUP -- 2.45.2