Compare commits

..

14 Commits

Author SHA1 Message Date
Miroslav Lichvar
5828426977 doc: update installation instructions 2016-02-16 14:25:38 +01:00
Miroslav Lichvar
d04fb4b7fa doc: improve description of trust option 2016-02-16 13:43:33 +01:00
Miroslav Lichvar
f5fe3ab4a1 test/unit: add sources unit test 2016-02-16 13:43:33 +01:00
Miroslav Lichvar
6b6b097fe8 test/unit: include microseconds in default random seed 2016-02-16 13:43:28 +01:00
Miroslav Lichvar
4998afc9bb test/unit: add more helper functions 2016-02-16 13:43:07 +01:00
Miroslav Lichvar
80f4d75968 test/unit: follow chrony function naming convention 2016-02-15 16:09:05 +01:00
Miroslav Lichvar
910663c37b test: add ntp_sources unit test 2016-02-05 15:20:40 +01:00
Miroslav Lichvar
34a4695e81 test: add clientlog unit test 2016-02-05 15:20:40 +01:00
Miroslav Lichvar
fe00319f45 addrfilt: remove TEST code
A test of the address filter is now included in unit tests.
2016-02-05 15:20:40 +01:00
Miroslav Lichvar
4c77d18416 test: add addrfilt unit test 2016-02-05 15:20:40 +01:00
Miroslav Lichvar
a63e18edb8 test: specify files with path in source commands
This should prevent sourcing of an unrelated file found in $PATH.
2016-02-05 15:20:40 +01:00
Miroslav Lichvar
8b676502de test: don't download files in tests
Remove automatic download and compilation of clknetsim. If clknetsim is
not found, skip all simulation tests, but don't fail "make check".
Also, respect the CLKNETSIM_PATH environment variable.
2016-02-05 15:20:40 +01:00
Miroslav Lichvar
cf5b344ea8 git: update .gitignore 2016-02-05 15:20:40 +01:00
Miroslav Lichvar
4ab98f62e9 test: add support for unit testing 2016-02-05 15:20:40 +01:00
47 changed files with 720 additions and 185 deletions

3
.gitignore vendored
View File

@@ -22,3 +22,6 @@ tags
/version.h /version.h
/test/simulation/clknetsim /test/simulation/clknetsim
/test/simulation/tmp /test/simulation/tmp
/test/unit/Makefile
/test/unit/*.test
/test/unit/*.o

View File

@@ -120,6 +120,7 @@ install: chronyd chronyc
$(CC) $(CFLAGS) $(CPPFLAGS) -S $< $(CC) $(CFLAGS) $(CPPFLAGS) -S $<
check : chronyd chronyc check : chronyd chronyc
$(MAKE) -C test/unit check
cd test/simulation && ./run cd test/simulation && ./run
install-docs : docs install-docs : docs

View File

@@ -401,117 +401,3 @@ ADF_IsAnyAllowed(ADF_AuthTable table, int family)
return 0; return 0;
} }
} }
/* ================================================== */
#if defined TEST
static void print_node(TableNode *node, uint32_t *addr, int ip_len, int shift, int subnet_bits)
{
uint32_t new_addr[4];
int i;
TableNode *sub_node;
for (i=0; i<subnet_bits; i++) putchar(' ');
if (ip_len == 1)
printf("%d.%d.%d.%d",
((addr[0] >> 24) & 255),
((addr[0] >> 16) & 255),
((addr[0] >> 8) & 255),
((addr[0] ) & 255));
else {
for (i=0; i<4; i++) {
if (addr[i])
printf("%d.%d.%d.%d",
((addr[i] >> 24) & 255),
((addr[i] >> 16) & 255),
((addr[i] >> 8) & 255),
((addr[i] ) & 255));
putchar(i < 3 ? ':' : '\0');
}
}
printf("/%d : %s\n",
subnet_bits,
(node->state == ALLOW) ? "allow" :
(node->state == DENY) ? "deny" : "as parent");
if (node->extended) {
for (i=0; i<16; i++) {
sub_node = &(node->extended[i]);
new_addr[0] = addr[0];
new_addr[1] = addr[1];
new_addr[2] = addr[2];
new_addr[3] = addr[3];
new_addr[ip_len - 1 - shift / 32] |= ((uint32_t)i << (shift % 32));
print_node(sub_node, new_addr, ip_len, shift - 4, subnet_bits + 4);
}
}
}
static void print_table(ADF_AuthTable table)
{
uint32_t addr[4];
memset(addr, 0, sizeof (addr));
printf("IPv4 table:\n");
print_node(&table->base4, addr, 1, 28, 0);
memset(addr, 0, sizeof (addr));
printf("IPv6 table:\n");
print_node(&table->base6, addr, 4, 124, 0);
}
/* ================================================== */
int main (int argc, char **argv)
{
IPAddr ip;
ADF_AuthTable table;
table = ADF_CreateTable();
ip.family = IPADDR_INET4;
ip.addr.in4 = 0x7e800000;
ADF_Allow(table, &ip, 9);
ip.addr.in4 = 0x7ecc0000;
ADF_Deny(table, &ip, 14);
#if 0
ip.addr.in4 = 0x7f000001;
ADF_Deny(table, &ip, 32);
ip.addr.in4 = 0x7f000000;
ADF_Allow(table, &ip, 8);
#endif
printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
ip.addr.in4 ^= 1;
printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
ip.family = IPADDR_INET6;
memcpy(ip.addr.in6, "abcdefghijklmnop", 16);
ADF_Deny(table, &ip, 66);
ADF_Allow(table, &ip, 59);
memcpy(ip.addr.in6, "xbcdefghijklmnop", 16);
ADF_Deny(table, &ip, 128);
ip.addr.in6[15] ^= 3;
ADF_Allow(table, &ip, 127);
printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
ip.addr.in4 ^= 1;
printf("allowed: %d\n", ADF_IsAllowed(table, &ip));
print_table(table);
ADF_DestroyTable(table);
return 0;
}
#endif /* defined TEST */

View File

@@ -339,9 +339,16 @@ for C-family shells.
If the software cannot (yet) be built on your system, an error message If the software cannot (yet) be built on your system, an error message
will be shown. Otherwise, @file{Makefile} will be generated. will be shown. Otherwise, @file{Makefile} will be generated.
If editline or readline library is available, chronyc will be built with line On Linux, if development files for the libcap library are available,
editing support. If you don't want this, specify the --disable-readline flag @code{chronyd} will be built with support for dropping root privileges.
to configure. Please refer to @pxref{line editing support} for more information. On other systems no extra library is needed. The default user which
@code{chronyd} should run as can be specified with the @code{--with-user}
option of the configure script.
If development files for the editline or readline library are available,
@code{chronyc} will be built with line editing support. If you don't want
this, specify the --disable-readline flag to configure. Please refer to
@pxref{line editing support} for more information.
If a @file{timepps.h} header is available (e.g. from the If a @file{timepps.h} header is available (e.g. from the
@uref{http://linuxpps.org/, LinuxPPS project}), @code{chronyd} will be built with PPS API @uref{http://linuxpps.org/, LinuxPPS project}), @code{chronyd} will be built with PPS API
@@ -407,7 +414,11 @@ makestep 1.0 3
rtcsync rtcsync
@end example @end example
Then, @code{chronyd} can be run. Then, @code{chronyd} can be run. For security reasons, it's recommended to
create an unprivileged user for @code{chronyd} and specify it with the
@code{-u} command-line option or the @code{user} directive in the configuration
file, or set the default user with the @code{--with-user} configure option
before building.
@c }}} @c }}}
@menu @menu
* line editing support:: If libraries are in a non-standard place * line editing support:: If libraries are in a non-standard place
@@ -2790,9 +2801,9 @@ Prefer this source over sources without prefer option.
Never select this source. This is useful for monitoring or with sources Never select this source. This is useful for monitoring or with sources
which are not very accurate, but are locked with a PPS refclock. which are not very accurate, but are locked with a PPS refclock.
@item trust @item trust
Assume time from this source is always true. It can't be rejected as a Assume time from this source is always true. It can be rejected as a
falseticker in the source selection if sources that are specified without this falseticker in the source selection only if another source with this option
option don't agree with it. doesn't agree with it.
@item require @item require
Require that at least one of the sources specified with this option is Require that at least one of the sources specified with this option is
selectable (i.e. recently reachable and not a falseticker) before updating the selectable (i.e. recently reachable and not a falseticker) before updating the
@@ -3106,9 +3117,9 @@ Prefer this source over sources without prefer option.
Never select this source. This is particularly useful for monitoring. Never select this source. This is particularly useful for monitoring.
@item trust @item trust
Assume time from this source is always true. It can't be rejected as a Assume time from this source is always true. It can be rejected as a
falseticker in the source selection if sources that are specified without this falseticker in the source selection only if another source with this option
option don't agree with it. doesn't agree with it.
@item require @item require
Require that at least one of the sources specified with this option is Require that at least one of the sources specified with this option is

2
configure vendored
View File

@@ -848,7 +848,7 @@ fi
add_def CHRONY_VERSION "\"${CHRONY_VERSION}\"" add_def CHRONY_VERSION "\"${CHRONY_VERSION}\""
for f in Makefile chrony.conf.5 chrony.texi chronyc.1 chronyd.8 for f in Makefile test/unit/Makefile chrony.conf.5 chrony.texi chronyc.1 chronyd.8
do do
echo Creating $f echo Creating $f
sed -e "s%@EXTRA_OBJECTS@%${EXTRA_OBJECTS}%;\ sed -e "s%@EXTRA_OBJECTS@%${EXTRA_OBJECTS}%;\

View File

@@ -51,7 +51,7 @@ awk '/^[1-9] Installation$/{p=1}
/^[1-9]\.. Support for line editing/{exit}; p' chrony.txt | \ /^[1-9]\.. Support for line editing/{exit}; p' chrony.txt | \
tail -n +4 > INSTALL tail -n +4 > INSTALL
if [ $(wc -l < INSTALL) -gt 100 -o $(wc -l < INSTALL) -lt 85 ]; then if [ $(wc -l < INSTALL) -gt 120 -o $(wc -l < INSTALL) -lt 85 ]; then
echo "INSTALL generated incorrectly?" echo "INSTALL generated incorrectly?"
exit 3 exit 3
fi fi

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "default test settings" test_start "default test settings"

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "large network" test_start "large network"

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "large frequency offset" test_start "large frequency offset"

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "large time offset" test_start "large time offset"

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "external time step" test_start "external time step"

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "large jitter" test_start "large jitter"

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "large wander" test_start "large wander"

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "NTP eras" test_start "NTP eras"
# Assume NTP_ERA_SPLIT is between years 1960 and 1990 # Assume NTP_ERA_SPLIT is between years 1960 and 1990

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "source selection" test_start "source selection"

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "minpoll/maxpoll options" test_start "minpoll/maxpoll options"
wander=0.0 wander=0.0

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "iburst option" test_start "iburst option"
freq_offset=1e-4 freq_offset=1e-4

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "initstepslew directive" test_start "initstepslew directive"
freq_offset=0.0 freq_offset=0.0

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "driftfile directive" test_start "driftfile directive"
servers=0 servers=0

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "NTP authentication" test_start "NTP authentication"

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "SHM refclock" test_start "SHM refclock"
servers=0 servers=0

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "allow/deny directives" test_start "allow/deny directives"

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "NTP peers" test_start "NTP peers"

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "makestep directive" test_start "makestep directive"
client_conf="makestep 0 -1 client_conf="makestep 0 -1

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "chronyc" test_start "chronyc"

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "reply to client configured as server" test_start "reply to client configured as server"

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "port and acquisitionport directives" test_start "port and acquisitionport directives"

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "leap second" test_start "leap second"
export CLKNETSIM_START_DATE=$(TZ=UTC date -d 'Dec 30 2008 0:00:00' +'%s') export CLKNETSIM_START_DATE=$(TZ=UTC date -d 'Dec 30 2008 0:00:00' +'%s')

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "presend option" test_start "presend option"
min_sync_time=140 min_sync_time=140

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "cmdmon timestamps" test_start "cmdmon timestamps"

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "minsources directive" test_start "minsources directive"

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "fallback drift" test_start "fallback drift"
limit=100000 limit=100000

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "maxdelay options" test_start "maxdelay options"
max_sync_time=2000 max_sync_time=2000

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "smoothtime option" test_start "smoothtime option"
server_strata=2 server_strata=2

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
test_start "source selection options" test_start "source selection options"

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
# Test fix in commit 60d0fa299307076143da94d36deb7b908fa9bdb7 # Test fix in commit 60d0fa299307076143da94d36deb7b908fa9bdb7

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
. test.common . ./test.common
# Test fix in commit 4253075a97141edfa62043ab71bd0673587e6629 # Test fix in commit 4253075a97141edfa62043ab71bd0673587e6629

View File

@@ -1,12 +1,11 @@
This is a collection of simulation tests. They use clknetsim to simulate This is a collection of simulation tests using the clknetsim simulator
multiple systems connected in a network. It's available at (supported on Linux only).
https://github.com/mlichvar/clknetsim https://github.com/mlichvar/clknetsim
If this directory doesn't have a clknetsim subdirectory, a known working The CLKNETSIM_PATH environment variable should point to the directory where
revision will be downloaded and compiled automatically. clknetsim was downloaded and compiled. If the variable is not set, the tests
will look for clknetsim in ./clknetsim in the current directory.
Currently it runs only on Linux.
The tests are written in bash and they can be run directly. The ./run script The tests are written in bash and they can be run directly. The ./run script
runs all tests. runs all tests.

View File

@@ -1,7 +1,5 @@
#!/bin/bash #!/bin/bash
. test.common
passed=() failed=() skipped=() passed=() failed=() skipped=()
[ $# -gt 0 ] && tests=($@) || tests=([0-9]*-*[^_]) [ $# -gt 0 ] && tests=($@) || tests=([0-9]*-*[^_])

View File

@@ -15,27 +15,11 @@
export LC_ALL=C export LC_ALL=C
export PATH=../../:$PATH export PATH=../../:$PATH
export CLKNETSIM_PATH=clknetsim export CLKNETSIM_PATH=${CLKNETSIM_PATH:-clknetsim}
# Known working clknetsim revision if [ ! -x $CLKNETSIM_PATH/clknetsim ]; then
clknetsim_revision=1e56224dee1db69c0027e9bd63c2a202d4765959 echo "SKIP (clknetsim not found)"
clknetsim_url=https://github.com/mlichvar/clknetsim/archive/$clknetsim_revision.tar.gz exit 9
# Only Linux is supported
if [ "$(uname -s)" != Linux ]; then
echo "Simulation tests supported only on Linux"
exit 3
fi
# Try to download clknetsim if not found
if [ ! -e $CLKNETSIM_PATH ]; then
curl -L "$clknetsim_url" | tar xz || exit 3
ln -s clknetsim-$clknetsim_revision clknetsim || exit 3
fi
# Try to build clknetsim if not built
if [ ! -x $CLKNETSIM_PATH/clknetsim -o ! -e $CLKNETSIM_PATH/clknetsim.so ]; then
make -C clknetsim || exit 3
fi fi
. $CLKNETSIM_PATH/clknetsim.bash . $CLKNETSIM_PATH/clknetsim.bash

42
test/unit/Makefile.in Normal file
View File

@@ -0,0 +1,42 @@
TEST_WRAPPER =
CHRONY_SRCDIR = ../..
CC = @CC@
CFLAGS = @CFLAGS@
CPPFLAGS = -I$(CHRONY_SRCDIR) @CPPFLAGS@
LDFLAGS = @LDFLAGS@ @LIBS@ @EXTRA_LIBS@
SHARED_OBJS = test.o
TEST_OBJS := $(sort $(patsubst %.c,%.o,$(wildcard *.c)))
TESTS := $(patsubst %.o,%.test,$(filter-out $(SHARED_OBJS),$(TEST_OBJS)))
FILTER_OBJS = %/main.o %/client.o %/getdate.o
CHRONY_OBJS := $(filter-out $(FILTER_OBJS),$(wildcard $(CHRONY_SRCDIR)/*.o))
all: $(TESTS)
%.test: %.o $(SHARED_OBJS)
$(CC) $(CFLAGS) -o $@ $^ $(CHRONY_OBJS:%/$*.o=) $(LDFLAGS)
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c $<
check: $(TESTS)
@ret=0; \
for t in $^; do \
$(TEST_WRAPPER) ./$$t || ret=1; \
done; \
exit $$ret
clean:
rm -f *.o $(TESTS)
rm -rf .deps
.deps:
@mkdir .deps
.deps/%.d: %.c | .deps
@$(CC) -MM $(CPPFLAGS) -MT '$(<:%.c=%.o) $@' $< -o $@
-include $(TEST_OBJS:%.o=.deps/%.d)

83
test/unit/addrfilt.c Normal file
View File

@@ -0,0 +1,83 @@
/*
**********************************************************************
* Copyright (C) Miroslav Lichvar 2016
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
*/
#include <addrfilt.c>
#include <logging.h>
#include <util.h>
#include "test.h"
void
test_unit(void)
{
int i, j, sub, maxsub;
IPAddr ip;
ADF_AuthTable table;
table = ADF_CreateTable();
for (i = 0; i < 100; i++) {
for (j = 0; j < 1000; j++) {
if (j % 2) {
maxsub = 32;
TST_GetRandomAddress(&ip, IPADDR_INET4, -1);
} else {
maxsub = 128;
TST_GetRandomAddress(&ip, IPADDR_INET6, -1);
}
DEBUG_LOG(0, "address %s", UTI_IPToString(&ip));
sub = random() % (maxsub + 1);
TEST_CHECK(!ADF_IsAllowed(table, &ip));
ADF_Allow(table, &ip, sub);
TEST_CHECK(ADF_IsAllowed(table, &ip));
if (sub < maxsub) {
TST_SwapAddressBit(&ip, sub);
TEST_CHECK(ADF_IsAllowed(table, &ip));
}
if (sub > 0) {
TST_SwapAddressBit(&ip, sub - 1);
TEST_CHECK(!ADF_IsAllowed(table, &ip));
if (sub % 4 != 1) {
ADF_Deny(table, &ip, sub - 1);
TST_SwapAddressBit(&ip, sub - 1);
TEST_CHECK(!ADF_IsAllowed(table, &ip));
}
}
if (sub > 4) {
ADF_AllowAll(table, &ip, sub - 4);
TEST_CHECK(ADF_IsAllowed(table, &ip));
}
ADF_DenyAll(table, &ip, 0);
}
ip.family = IPADDR_INET4;
ADF_DenyAll(table, &ip, 0);
ip.family = IPADDR_INET6;
ADF_DenyAll(table, &ip, 0);
}
ADF_DestroyTable(table);
}

84
test/unit/clientlog.c Normal file
View File

@@ -0,0 +1,84 @@
/*
**********************************************************************
* Copyright (C) Miroslav Lichvar 2016
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
*/
#include <clientlog.c>
#include "test.h"
void
test_unit(void)
{
int i, j, index;
struct timeval tv;
IPAddr ip;
char conf[][100] = {
"clientloglimit 10000",
"ratelimit interval 3 burst 4 leak 3",
"cmdratelimit interval 3 burst 4 leak 3",
};
CNF_Initialise(0);
for (i = 0; i < sizeof conf / sizeof conf[0]; i++)
CNF_ParseLine(NULL, i + 1, conf[i]);
CLG_Initialise();
TEST_CHECK(ARR_GetSize(records) == 16);
for (i = 0; i < 500; i++) {
DEBUG_LOG(0, "iteration %d", i);
tv.tv_sec = (time_t)random() & 0x0fffffff;
tv.tv_usec = 0;
for (j = 0; j < 1000; j++) {
TST_GetRandomAddress(&ip, IPADDR_UNSPEC, i % 8 ? -1 : i / 8 % 9);
DEBUG_LOG(0, "address %s", UTI_IPToString(&ip));
if (random() % 2) {
index = CLG_LogNTPAccess(&ip, &tv);
TEST_CHECK(index >= 0);
CLG_LimitNTPResponseRate(index);
} else {
index = CLG_LogCommandAccess(&ip, &tv);
TEST_CHECK(index >= 0);
CLG_LimitCommandResponseRate(index);
}
UTI_AddDoubleToTimeval(&tv, (1 << random() % 14) / 100.0, &tv);
}
}
DEBUG_LOG(0, "records %d", ARR_GetSize(records));
TEST_CHECK(ARR_GetSize(records) == 128);
for (i = j = 0; i < 10000; i++) {
tv.tv_sec += 1;
index = CLG_LogNTPAccess(&ip, &tv);
TEST_CHECK(index >= 0);
if (!CLG_LimitNTPResponseRate(index))
j++;
}
DEBUG_LOG(0, "requests %u responses %u", i, j);
TEST_CHECK(j * 4 < i && j * 6 > i);
CLG_Finalise();
CNF_Finalise();
}

99
test/unit/ntp_sources.c Normal file
View File

@@ -0,0 +1,99 @@
/*
**********************************************************************
* Copyright (C) Miroslav Lichvar 2016
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
*/
#include <ntp_sources.c>
#include <conf.h>
#include <ntp_io.h>
#include "test.h"
void
test_unit(void)
{
int i, j, k, slot, found;
uint32_t hash = 0;
NTP_Remote_Address addrs[256], addr;
SourceParameters params;
char conf[] = "port 0";
memset(&params, 0, sizeof (params));
CNF_Initialise(0);
CNF_ParseLine(NULL, 1, conf);
LCL_Initialise();
SCH_Initialise();
SRC_Initialise();
NIO_Initialise(IPADDR_UNSPEC);
NCR_Initialise();
NSR_Initialise();
for (i = 0; i < 6; i++) {
TEST_CHECK(ARR_GetSize(records) == 1);
DEBUG_LOG(0, "collision mod %u", 1U << i);
for (j = 0; j < sizeof (addrs) / sizeof (addrs[0]); j++) {
do {
TST_GetRandomAddress(&addrs[j].ip_addr, IPADDR_UNSPEC, -1);
} while (UTI_IPToHash(&addrs[j].ip_addr) % (1U << i) != hash % (1U << i));
addrs[j].port = random() % 1024;
if (!j)
hash = UTI_IPToHash(&addrs[j].ip_addr);
DEBUG_LOG(0, "adding source %s hash %"PRIu32, UTI_IPToString(&addrs[j].ip_addr),
UTI_IPToHash(&addrs[j].ip_addr) % (1U << i));
NSR_AddSource(&addrs[j], random() % 2 ? NTP_SERVER : NTP_PEER, &params);
for (k = 0; k < j; k++) {
addr = addrs[k];
find_slot(&addr, &slot, &found);
TEST_CHECK(found == 2);
TEST_CHECK(!UTI_CompareIPs(&get_record(slot)->remote_addr->ip_addr,
&addr.ip_addr, NULL));
addr.port++;
find_slot(&addr, &slot, &found);
TEST_CHECK(found == 1);
TEST_CHECK(!UTI_CompareIPs(&get_record(slot)->remote_addr->ip_addr,
&addr.ip_addr, NULL));
}
}
for (j = 0; j < sizeof (addrs) / sizeof (addrs[0]); j++) {
DEBUG_LOG(0, "removing source %s", UTI_IPToString(&addrs[j].ip_addr));
NSR_RemoveSource(&addrs[j]);
for (k = 0; k < sizeof (addrs) / sizeof (addrs[0]); k++) {
find_slot(&addrs[k], &slot, &found);
TEST_CHECK(found == (k <= j ? 0 : 2));
}
}
}
NSR_Finalise();
NCR_Finalise();
NIO_Finalise();
SRC_Finalise();
SCH_Finalise();
LCL_Finalise();
CNF_Finalise();
}

137
test/unit/sources.c Normal file
View File

@@ -0,0 +1,137 @@
/*
**********************************************************************
* Copyright (C) Miroslav Lichvar 2016
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
*/
#include <sources.c>
#include "test.h"
void
test_unit(void)
{
SRC_Instance srcs[16];
RPT_SourceReport report;
IPAddr addr;
int i, j, k, l, samples, sel_options;
double offset, delay, disp;
struct timeval tv;
CNF_Initialise(0);
LCL_Initialise();
TST_RegisterDummyDrivers();
SCH_Initialise();
SRC_Initialise();
REF_Initialise();
REF_SetMode(REF_ModeIgnore);
for (i = 0; i < 1000; i++) {
DEBUG_LOG(0, "iteration %d", i);
for (j = 0; j < sizeof (srcs) / sizeof (srcs[0]); j++) {
TEST_CHECK(n_sources == j);
TST_GetRandomAddress(&addr, IPADDR_UNSPEC, -1);
sel_options = i & random() & (SRC_SELECT_NOSELECT | SRC_SELECT_PREFER |
SRC_SELECT_TRUST | SRC_SELECT_REQUIRE);
DEBUG_LOG(0, "added source %d options %d", j, sel_options);
srcs[j] = SRC_CreateNewInstance(UTI_IPToRefid(&addr), SRC_NTP, sel_options, &addr,
SRC_DEFAULT_MINSAMPLES, SRC_DEFAULT_MAXSAMPLES);
SRC_UpdateReachability(srcs[j], 1);
samples = (i + j) % 5 + 3;
offset = TST_GetRandomDouble(-1.0, 1.0);
for (k = 0; k < samples; k++) {
SCH_GetLastEventTime(&tv, NULL, NULL);
UTI_AddDoubleToTimeval(&tv, TST_GetRandomDouble(k - samples, k - samples + 1), &tv);
offset += TST_GetRandomDouble(-1.0e-2, 1.0e-2);
delay = TST_GetRandomDouble(1.0e-6, 1.0e-1);
disp = TST_GetRandomDouble(1.0e-6, 1.0e-1);
DEBUG_LOG(0, "source %d sample %d offset %f delay %f disp %f", j, k,
offset, delay, disp);
SRC_AccumulateSample(srcs[j], &tv, offset, delay, disp, delay, disp,
1, LEAP_Normal);
}
for (k = 0; k <= j; k++) {
int passed = 0, trusted = 0, trusted_passed = 0, required = 0, required_passed = 0;
double trusted_lo = DBL_MAX, trusted_hi = DBL_MIN;
double passed_lo = DBL_MAX, passed_hi = DBL_MIN;
SRC_SelectSource(srcs[k]);
DEBUG_LOG(0, "source %d status %d", k, sources[k]->status);
for (l = 0; l <= j; l++) {
TEST_CHECK(sources[l]->status > SRC_OK && sources[l]->status <= SRC_SELECTED);
if (sources[l]->sel_options & SRC_SELECT_NOSELECT) {
TEST_CHECK(sources[l]->status == SRC_UNSELECTABLE);
} else if (sources[l]->status != SRC_BAD_DISTANCE) {
if (sources[l]->status >= SRC_NONPREFERRED) {
passed++;
if (passed_lo > sources[l]->sel_info.lo_limit)
passed_lo = sources[l]->sel_info.lo_limit;
if (passed_hi < sources[l]->sel_info.hi_limit)
passed_hi = sources[l]->sel_info.hi_limit;
}
if (sources[l]->sel_options & SRC_SELECT_TRUST) {
trusted++;
if (trusted_lo > sources[l]->sel_info.lo_limit)
trusted_lo = sources[l]->sel_info.lo_limit;
if (trusted_hi < sources[l]->sel_info.hi_limit)
trusted_hi = sources[l]->sel_info.hi_limit;
if (sources[l]->status >= SRC_NONPREFERRED)
trusted_passed++;
}
if (sources[l]->sel_options & SRC_SELECT_REQUIRE) {
required++;
if (sources[l]->status >= SRC_NONPREFERRED)
required_passed++;
}
if (sources[l]->sel_options & SRC_SELECT_PREFER)
TEST_CHECK(sources[l]->status != SRC_NONPREFERRED);
}
}
DEBUG_LOG(0, "sources %d passed %d trusted %d/%d required %d/%d", j, passed,
trusted_passed, trusted, required_passed, required);
TEST_CHECK(!trusted || !passed || (passed_lo >= trusted_lo && passed_hi <= trusted_hi));
TEST_CHECK(!passed || trusted != 1 || (trusted == 1 && trusted_passed == 1));
TEST_CHECK(!passed || !required || required_passed > 0);
}
}
for (j = 0; j < sizeof (srcs) / sizeof (srcs[0]); j++) {
SRC_ReportSource(j, &report, &tv);
SRC_DestroyInstance(srcs[j]);
}
}
REF_Finalise();
SRC_Finalise();
SCH_Finalise();
LCL_Finalise();
CNF_Finalise();
}

165
test/unit/test.c Normal file
View File

@@ -0,0 +1,165 @@
/*
**********************************************************************
* Copyright (C) Miroslav Lichvar 2016
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
*/
#include <config.h>
#include <sysincl.h>
#include <logging.h>
#include <localp.h>
#include "test.h"
void
TST_Fail(int line)
{
printf("FAIL (on line %d)\n", line);
exit(1);
}
int
main(int argc, char **argv)
{
char *test_name, *s;
int i, seed = 0;
struct timeval tv;
test_name = argv[0];
s = strrchr(test_name, '.');
if (s)
*s = '\0';
s = strrchr(test_name, '/');
if (s)
test_name = s + 1;
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-d")) {
LOG_SetDebugLevel(2);
} else if (!strcmp(argv[i], "-s") && i + 1 < argc) {
seed = atoi(argv[++i]);
} else {
fprintf(stderr, "Unknown option\n");
exit(1);
}
}
gettimeofday(&tv, NULL);
srandom(seed ? seed : tv.tv_sec ^ (tv.tv_usec << 10));
printf("Testing %-30s ", test_name);
fflush(stdout);
test_unit();
printf("PASS\n");
return 0;
}
double
TST_GetRandomDouble(double min, double max)
{
return min + (double)random() / RAND_MAX * (max - min);
}
void
TST_GetRandomAddress(IPAddr *ip, int family, int bits)
{
if (family != IPADDR_INET4 && family != IPADDR_INET6)
family = random() % 2 ? IPADDR_INET4 : IPADDR_INET6;
ip->family = family;
if (family == IPADDR_INET4) {
if (bits < 0)
bits = 32;
assert(bits <= 32);
if (bits > 16)
ip->addr.in4 = (uint32_t)random() % (1U << (bits - 16)) << 16 |
(uint32_t)random() % (1U << 16);
else
ip->addr.in4 = (uint32_t)random() % (1U << bits);
} else {
int i, b;
if (bits < 0)
bits = 128;
assert(bits <= 128);
for (i = 0, b = 120; i < 16; i++, b -= 8) {
if (b >= bits) {
ip->addr.in6[i] = 0;
} else {
ip->addr.in6[i] = random() % (1U << MIN(bits - b, 8));
}
}
}
}
void
TST_SwapAddressBit(IPAddr *ip, unsigned int b)
{
if (ip->family == IPADDR_INET4) {
assert(b < 32);
ip->addr.in4 ^= 1U << (31 - b);
} else if (ip->family == IPADDR_INET6) {
assert(b < 128);
ip->addr.in6[b / 8] ^= 1U << (7 - b % 8);
} else {
assert(0);
}
}
static double
read_frequency(void)
{
return 0.0;
}
static double
set_frequency(double freq_ppm)
{
return 0.0;
}
static void
accrue_offset(double offset, double corr_rate)
{
}
static int
apply_step_offset(double offset)
{
return 0;
}
static void
offset_convert(struct timeval *raw, double *corr, double *err)
{
*corr = 0.0;
if (err)
*err = 0.0;
}
void
TST_RegisterDummyDrivers(void)
{
lcl_RegisterSystemDrivers(read_frequency, set_frequency, accrue_offset,
apply_step_offset, offset_convert, NULL, NULL);
}

43
test/unit/test.h Normal file
View File

@@ -0,0 +1,43 @@
/*
**********************************************************************
* Copyright (C) Miroslav Lichvar 2016
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
*/
#ifndef GOT_TEST_H
#define GOT_TEST_H
#include <addressing.h>
extern void test_unit(void);
#define TEST_CHECK(expr) \
do { \
if (!(expr)) { \
TST_Fail(__LINE__); \
exit(1); \
} \
} while (0)
extern void TST_Fail(int line);
extern double TST_GetRandomDouble(double min, double max);
extern void TST_GetRandomAddress(IPAddr *ip, int family, int bits);
extern void TST_SwapAddressBit(IPAddr *ip, unsigned int b);
extern void TST_RegisterDummyDrivers(void);
#endif