From db5382ec111ba1080cf7a5b2d6a4c881ec04bc5d Mon Sep 17 00:00:00 2001 From: Arthur de Jong Date: Mon, 2 Sep 2013 23:07:33 +0200 Subject: Add a test for clock_gettime() supported clocks This probes the system for available clocks to see if they can be reliably used to get a monotonic-like timer (the test doesn't verify the monotonic part, just usability). --- tests/Makefile.am | 6 +- tests/test_clock.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 tests/test_clock.c (limited to 'tests') diff --git a/tests/Makefile.am b/tests/Makefile.am index 441af73..45f73fc 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -20,7 +20,7 @@ TESTS = test_dict test_set test_tio test_expr test_getpeercred test_cfg \ test_myldap.sh test_common test_nsscmds.sh test_pamcmds.sh \ - test_manpages.sh + test_manpages.sh test_clock if HAVE_PYTHON TESTS += test_pycompile.sh test_pylint.sh endif @@ -31,7 +31,7 @@ endif AM_TESTS_ENVIRONMENT = PYTHON='@PYTHON@'; export PYTHON; check_PROGRAMS = test_dict test_set test_tio test_expr test_getpeercred \ - test_cfg test_myldap test_common \ + test_cfg test_myldap test_common test_clock \ lookup_netgroup lookup_shadow EXTRA_DIST = nslcd-test.conf usernames.txt in_testenv.sh test_myldap.sh \ @@ -85,6 +85,8 @@ test_myldap_LDADD = ../nslcd/cfg.o $(common_nslcd_LDADD) test_common_SOURCES = test_common.c ../nslcd/common.h test_common_LDADD = ../nslcd/cfg.o $(common_nslcd_LDADD) +test_clock_SOURCES = test_clock.c + lookup_netgroup_SOURCES = lookup_netgroup.c lookup_shadow_SOURCES = lookup_shadow.c diff --git a/tests/test_clock.c b/tests/test_clock.c new file mode 100644 index 0000000..8d55f93 --- /dev/null +++ b/tests/test_clock.c @@ -0,0 +1,158 @@ +/* + test_clock.c - tests for finding usable system clocks + This file is part of the nss-pam-ldapd library. + + Copyright (C) 2013 Arthur de Jong + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "compat/attrs.h" + +/* use clock_gettime() to see if the specified clock is supported */ +static int test_clock_gettime(clockid_t c, const char *cname) +{ + struct timespec t1 = {0, 0}; + struct timespec t2 = {0, 0}; + struct timespec t3 = {0, 50 * 1000 * 1000}; /* 50 msec */ + struct timespec t4 = {0, 0}; + long diff; + int result = 0; + /* see if we can get resolution (not important so ignore any failures) */ + errno = 0; + if (clock_getres(c, &t1)) + printf(" clock %s resolution not supported: %s\n", cname, strerror(errno)); + if ((t1.tv_sec != 0) || (t1.tv_nsec != 0)) + printf(" clock %s resolution: %ld.%09ld\n", cname, (long)t1.tv_sec, (long)t1.tv_nsec); + /* see if we can get the time */ + errno = 0; + if (clock_gettime(c, &t2)) + { + printf("FAIL clock %s get time not supported: %s\n", + cname, strerror(errno)); + if ((t2.tv_sec != 0) || (t2.tv_nsec != 0)) + printf(" clock %s time: %ld.%09ld\n", cname, (long)t2.tv_sec, (long)t2.tv_nsec); + return -1; + } + else + printf("OK clock %s time: %ld.%09ld\n", cname, (long)t2.tv_sec, (long)t2.tv_nsec); + /* quick sleep (assume we're not interrupted) */ + (void)nanosleep(&t3, NULL); + /* see if we can get the time again */ + errno = 0; + if (clock_gettime(c, &t4)) + { + printf("FAIL clock %s get time twice not supported: %s\n", + cname, strerror(errno)); + if ((t4.tv_sec != 0) || (t4.tv_nsec != 0)) + printf(" clock %s time: %ld.%09ld\n", cname, (long)t4.tv_sec, (long)t4.tv_nsec); + return -1; + } + else + printf("OK clock %s time: %ld.%09ld\n", cname, (long)t4.tv_sec, (long)t4.tv_nsec); + /* calculate difference */ + diff = ((long)t4.tv_sec - (long)t2.tv_sec - (long)t3.tv_sec) * (long)1000000000 + + ((long)t4.tv_nsec - (long)t2.tv_nsec - (long)t3.tv_nsec); + if ((diff < (-10 * 1000 * 1000)) || (diff > (20 * 1000 * 1000))) + { + result = -1; + printf("FAIL "); + } + else + printf("OK "); + printf("clock %s time diff: %s%ld.%09ld %.1f%%\n", cname, (diff < 0) ? "-" : "", + (labs(diff) / 1000000000L), (labs(diff) % 1000000000L), + labs(100L * diff) / (float)((long)t3.tv_sec * 1000000000L + (long)t3.tv_nsec)); + return result; +} + +/* wrapper for test_clock_gettime() that passes the clock name */ +#define TEST_CLOCK_GETTIME(clock) test_clock_gettime(clock, #clock) + +int main(int UNUSED(argc), char UNUSED(*argv[])) +{ + int found_clocks = 0; +#ifdef CLOCK_MONOTONIC_RAW + if (!TEST_CLOCK_GETTIME(CLOCK_MONOTONIC_RAW)) + found_clocks++; +#endif +#ifdef CLOCK_MONOTONIC_FAST + if (!TEST_CLOCK_GETTIME(CLOCK_MONOTONIC_FAST)) + found_clocks++; +#endif +#ifdef CLOCK_MONOTONIC_COARSE + if (!TEST_CLOCK_GETTIME(CLOCK_MONOTONIC_COARSE)) + found_clocks++; +#endif +#ifdef CLOCK_MONOTONIC + if (!TEST_CLOCK_GETTIME(CLOCK_MONOTONIC)) + found_clocks++; +#endif +#ifdef CLOCK_UPTIME_FAST + if (!TEST_CLOCK_GETTIME(CLOCK_UPTIME_FAST)) + found_clocks++; +#endif +#ifdef CLOCK_UPTIME + if (!TEST_CLOCK_GETTIME(CLOCK_UPTIME)) + found_clocks++; +#endif +#ifdef CLOCK_BOOTTIME + if (!TEST_CLOCK_GETTIME(CLOCK_BOOTTIME)) + found_clocks++; +#endif +#ifdef CLOCK_MONOTONIC_PRECISE + if (!TEST_CLOCK_GETTIME(CLOCK_MONOTONIC_PRECISE)) + found_clocks++; +#endif +#ifdef CLOCK_UPTIME_PRECISE + if (!TEST_CLOCK_GETTIME(CLOCK_UPTIME_PRECISE)) + found_clocks++; +#endif +#ifdef CLOCK_HIGHRES +#if CLOCK_HIGHRES == CLOCK_MONOTONIC + printf(" CLOCK_HIGHRES == CLOCK_MONOTONIC\n"); +#else + /* for Solaris, should be similar to CLOCK_MONOTONIC (it may be an alias) */ + if (!TEST_CLOCK_GETTIME(CLOCK_HIGHRES)) + found_clocks++; +#endif +#endif +#ifdef CLOCK_REALTIME_FAST + if (!TEST_CLOCK_GETTIME(CLOCK_REALTIME_FAST)) + found_clocks++; +#endif +#ifdef CLOCK_REALTIME_COARSE + if (!TEST_CLOCK_GETTIME(CLOCK_REALTIME_COARSE)) + found_clocks++; +#endif + if (!TEST_CLOCK_GETTIME(CLOCK_REALTIME)) + found_clocks++; +#ifdef CLOCK_REALTIME_PRECISE + if (!TEST_CLOCK_GETTIME(CLOCK_REALTIME_PRECISE)) + found_clocks++; +#endif + printf("%d usable clocks found\n", found_clocks); + return !(found_clocks > 0); +} -- cgit v1.2.3