diff options
Diffstat (limited to 'test/simulation')
58 files changed, 2772 insertions, 0 deletions
diff --git a/test/simulation/001-defaults b/test/simulation/001-defaults new file mode 100755 index 0000000..541cdad --- /dev/null +++ b/test/simulation/001-defaults @@ -0,0 +1,13 @@ +#!/bin/bash + +. ./test.common + +test_start "default test settings" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/002-largenetwork b/test/simulation/002-largenetwork new file mode 100755 index 0000000..fd41106 --- /dev/null +++ b/test/simulation/002-largenetwork @@ -0,0 +1,22 @@ +#!/bin/bash + +. ./test.common + +test_start "large network" + +time_rms_limit=5e-4 + +server_strata=3 +servers=4 +clients=5 + +client_start=2000 +min_sync_time=2100 +max_sync_time=2300 + +run_test || test_fail +check_chronyd_exit || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/003-largefreqoffset b/test/simulation/003-largefreqoffset new file mode 100755 index 0000000..7210662 --- /dev/null +++ b/test/simulation/003-largefreqoffset @@ -0,0 +1,19 @@ +#!/bin/bash + +. ./test.common + +test_start "large frequency offset" + +max_sync_time=1000 + +for freq_offset in -5e-2 -5e-3 5e-3 5e-2; do + # Adjust offset so it's close to 0 on first clock update + time_offset=$(awk "BEGIN {print -($freq_offset * 130)}") + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_packet_interval || test_fail + check_sync || test_fail +done + +test_pass diff --git a/test/simulation/004-largetimeoffset b/test/simulation/004-largetimeoffset new file mode 100755 index 0000000..5d8e2b6 --- /dev/null +++ b/test/simulation/004-largetimeoffset @@ -0,0 +1,18 @@ +#!/bin/bash + +. ./test.common + +test_start "large time offset" + +min_sync_time=1300 +max_sync_time=1400 + +for time_offset in -1e2 1e2; do + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_packet_interval || test_fail + check_sync || test_fail +done + +test_pass diff --git a/test/simulation/005-externalstep b/test/simulation/005-externalstep new file mode 100755 index 0000000..709c8a8 --- /dev/null +++ b/test/simulation/005-externalstep @@ -0,0 +1,46 @@ +#!/bin/bash + +. ./test.common + +test_start "external time step" + +min_sync_time=1500 +max_sync_time=1550 + +for step in -1e2 1e2; do + # Make one step in 150th second + client_step="(* $step (equal 0.1 (sum 1.0) 150))" + run_test || test_fail + check_chronyd_exit || test_fail + check_packet_interval || test_fail + check_sync || test_fail +done + +min_sync_time=5120 +max_sync_time=6200 +client_conf="makestep 1 -1" + +for step in -1e8 -1e5 1e5 1e8; do + # Make one step in 5000th second + client_step="(* $step (equal 0.1 (sum 1.0) 5000))" + run_test || test_fail + check_chronyd_exit || test_fail + check_packet_interval || test_fail + check_sync || test_fail +done + +min_sync_time=$default_min_sync_time +max_sync_time=$default_max_sync_time +time_max_limit=2e4 +time_rms_limit=8e3 + +for step in -1e4 1e4; do + # Make a step every 500 seconds + client_step="(* $step (equal 0.1 (% (sum 1.0) 500) 0))" + run_test || test_fail + check_chronyd_exit || test_fail + check_packet_interval || test_fail + check_sync || test_fail +done + +test_pass diff --git a/test/simulation/006-largejitter b/test/simulation/006-largejitter new file mode 100755 index 0000000..f70e63c --- /dev/null +++ b/test/simulation/006-largejitter @@ -0,0 +1,21 @@ +#!/bin/bash + +. ./test.common + +test_start "large jitter" + +time_offset=1e0 +jitter=1e-1 + +time_max_limit=5e-1 +freq_max_limit=2e-1 +time_rms_limit=1e-1 +freq_rms_limit=5e-3 + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/007-largewander b/test/simulation/007-largewander new file mode 100755 index 0000000..5572cbc --- /dev/null +++ b/test/simulation/007-largewander @@ -0,0 +1,20 @@ +#!/bin/bash + +. ./test.common + +test_start "large wander" + +wander=1e-7 + +time_max_limit=5e-3 +freq_max_limit=5e-3 +time_rms_limit=1e-3 +freq_rms_limit=1e-4 + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/008-ntpera b/test/simulation/008-ntpera new file mode 100755 index 0000000..360a97d --- /dev/null +++ b/test/simulation/008-ntpera @@ -0,0 +1,40 @@ +#!/bin/bash + +. ./test.common +test_start "NTP eras" + +# Assume NTP_ERA_SPLIT is between years 1960 and 1990 + +# Set date to 500 seconds before NTP second overflows, this should +# work correctly with both 32-bit and 64-bit time_t +export CLKNETSIM_START_DATE=$(date -d 'Feb 7 06:19:56 UTC 2036' +'%s') + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +# The following tests need 64-bit time_t +check_config_h 'HAVE_LONG_TIME_T 1' || test_skip + +for year in 1990 2090; do + export CLKNETSIM_START_DATE=$(date -d "Jan 1 00:00:00 UTC $year" +'%s') + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_packet_interval || test_fail + check_sync || test_fail +done + +for year in 1950 2130; do + export CLKNETSIM_START_DATE=$(date -d "Jan 1 00:00:00 UTC $year" +'%s') + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_packet_interval || test_fail + # This check is expected to fail + check_sync && test_fail +done + +test_pass diff --git a/test/simulation/009-sourceselection b/test/simulation/009-sourceselection new file mode 100755 index 0000000..7e60931 --- /dev/null +++ b/test/simulation/009-sourceselection @@ -0,0 +1,40 @@ +#!/bin/bash + +. ./test.common + +test_start "source selection" + +# Falsetickers should be detected if their number is less than half of all + +base_delay=1e-3 +servers=5 + +for falsetickers in 1 2; do + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_packet_interval || test_fail + check_sync || test_fail +done + +for falsetickers in 3 4; do + run_test || test_fail + check_chronyd_exit || test_fail + check_packet_interval || test_fail + # These check are expected to fail + check_source_selection && test_fail + check_sync && test_fail +done + +# Sources with large asymmetric delay should be excluded + +servers=3 +falsetickers=0 +base_delay="(+ 1e-3 (equal 0.1 to 2) (equal 0.1 to 3))" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/010-multrecv b/test/simulation/010-multrecv new file mode 100755 index 0000000..8adfab6 --- /dev/null +++ b/test/simulation/010-multrecv @@ -0,0 +1,17 @@ +#!/bin/bash + +. ./test.common + +export CLKNETSIM_RECV_MULTIPLY=4 + +test_start "multiple received packets" + +limit=50000 +client_server_options="minpoll 6 maxpoll 6" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/011-asymjitter b/test/simulation/011-asymjitter new file mode 100755 index 0000000..18e6ec1 --- /dev/null +++ b/test/simulation/011-asymjitter @@ -0,0 +1,18 @@ +#!/bin/bash + +. ./test.common + +test_start "asymmetric jitter" + +jitter=5e-4 +jitter_asymmetry=0.47 +limit=100000 +max_sync_time=2000 + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/012-daemonts b/test/simulation/012-daemonts new file mode 100755 index 0000000..b883516 --- /dev/null +++ b/test/simulation/012-daemonts @@ -0,0 +1,15 @@ +#!/bin/bash + +. ./test.common + +test_start "daemon timestamping" + +export CLKNETSIM_TIMESTAMPING=0 + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/013-nameserv b/test/simulation/013-nameserv new file mode 100755 index 0000000..84f0c8d --- /dev/null +++ b/test/simulation/013-nameserv @@ -0,0 +1,15 @@ +#!/bin/bash + +. ./test.common + +test_start "name resolving" + +dns=1 + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/101-poll b/test/simulation/101-poll new file mode 100755 index 0000000..cb3647f --- /dev/null +++ b/test/simulation/101-poll @@ -0,0 +1,30 @@ +#!/bin/bash + +. ./test.common +test_start "minpoll/maxpoll options" + +wander=0.0 +jitter=1e-6 + +time_max_limit=1e-5 +freq_max_limit=1e-5 +time_rms_limit=5e-6 +freq_rms_limit=5e-6 +client_conf="makestep 1e-2 1" + +for poll in $(seq 1 14); do + client_server_options="minpoll $poll maxpoll $poll" + limit=$[2**$poll * 10] + min_sync_time=$[2**$poll * 2] + max_sync_time=$[2**$poll * 21 / 10 + 1] + client_max_min_out_interval=$(awk "BEGIN {print 2^$poll * 1.1}") + client_min_mean_out_interval=$(awk "BEGIN {print 2^$poll * 0.99}") + + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_packet_interval || test_fail + check_sync || test_fail +done + +test_pass diff --git a/test/simulation/102-iburst b/test/simulation/102-iburst new file mode 100755 index 0000000..bd82530 --- /dev/null +++ b/test/simulation/102-iburst @@ -0,0 +1,23 @@ +#!/bin/bash + +. ./test.common +test_start "iburst option" + +freq_offset=1e-4 + +client_conf="makestep 1e-2 1 +driftfile tmp/drift" +client_server_options="iburst" + +min_sync_time=4 +max_sync_time=6 + +echo "100 1.0" > tmp/drift + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/103-initstepslew b/test/simulation/103-initstepslew new file mode 100755 index 0000000..303020e --- /dev/null +++ b/test/simulation/103-initstepslew @@ -0,0 +1,32 @@ +#!/bin/bash + +. ./test.common +test_start "initstepslew directive" + +freq_offset=0.0 +wander=0.0 +time_rms_limit=1e-3 +limit=100 + +client_conf="initstepslew 5 192.168.123.1" + +min_sync_time=6 +max_sync_time=35 + +for time_offset in -2.0 -0.2 0.2 2.0; do + run_test || test_fail + check_chronyd_exit || test_fail + check_packet_interval || test_fail + check_sync || test_fail +done + +min_sync_time=5 +max_sync_time=5 + +for time_offset in -1e8 -1e2 1e2 1e8; do + run_test || test_fail + check_packet_interval || test_fail + check_sync || test_fail +done + +test_pass diff --git a/test/simulation/104-driftfile b/test/simulation/104-driftfile new file mode 100755 index 0000000..703dad7 --- /dev/null +++ b/test/simulation/104-driftfile @@ -0,0 +1,23 @@ +#!/bin/bash + +. ./test.common +test_start "driftfile directive" + +servers=0 +time_offset=0.0 +wander=0.0 +limit=10 +freq_max_limit=1e-9 +min_sync_time=1 +max_sync_time=1 +client_conf="driftfile tmp/drift" + +for freq_offset in -5e-2 -5e-4 -5e-6 5e-6 5e-4 5e-2; do + awk "BEGIN {printf \"%.9e 1\", 1e6 - 1 / (1 + $freq_offset) * 1e6}" > tmp/drift + run_test || test_fail + check_chronyd_exit || test_fail + check_packet_interval || test_fail + check_sync || test_fail +done + +test_pass diff --git a/test/simulation/105-ntpauth b/test/simulation/105-ntpauth new file mode 100755 index 0000000..9503138 --- /dev/null +++ b/test/simulation/105-ntpauth @@ -0,0 +1,96 @@ +#!/bin/bash + +. ./test.common + +test_start "NTP authentication" + +server_conf="keyfile tmp/server.keys" +client_conf="keyfile tmp/client.keys" + +cat > tmp/server.keys <<-EOF +1 MD5 HEX:6B5D3C6A2E4A74775E4F6F3B7A35453E6E5C5F302D783D2979505C663C295A5E +2 MD5 HEX:6B5D3C6A2E4A74775E4F6F3B7A35453E6E5C5F302D783D2979505C663C295A5E +3 MD5 HEX:6B5D3C6A2E4A74775E4F6F3B7A35453E6E5C5F302D783D2979505C663C295A5E +4 MD5 HEX:6B5D3C6A2E4A74775E4F6F3B7A35453E6E5C5F302D783D2979505C663C295A5E +EOF + +cat > tmp/client.keys <<-EOF +1 k]<j.Jtw^Oo;z5E>n\_0-x=)yP\f<)Z^ +2 ASCII:k]<j.Jtw^Oo;z5E>n\_0-x=)yP\f<)Z^ +3 MD5 ASCII:k]<j.Jtw^Oo;z5E>n\_0-x=)yP\f<)Z^ +4 MD5 HEX:6B5D3C6A2E4A74775E4F6F3B7A35453E6E5C5F302D783D2979505C663C295A5E +EOF + +keys=4 + +types="MD5" +check_config_h 'FEAT_SECHASH 1' && types="$types SHA1 SHA256 SHA384 SHA512" +check_config_h 'HAVE_CMAC 1' && types="$types AES128 AES256" + +for type in $types; do + keys=$[$keys + 1] + case $type in + AES128) length=16;; + AES256) length=32;; + *) length=$[$RANDOM % 32 + 1];; + esac + + key=$(echo $keys $type HEX:$(tr -c -d '0-9A-F' < /dev/urandom 2> /dev/null | \ + head -c $[$length * 2])) + echo "$key" >> tmp/server.keys + echo "$key" >> tmp/client.keys +done + +for version in 3 4; do + for key in $(seq $keys); do + client_server_options="version $version key $key" + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_packet_interval || test_fail + check_sync || test_fail + done +done + +server_conf="" + +run_test || test_fail +check_chronyd_exit || test_fail +# This check must fail as the server doesn't know the key +check_sync && test_fail +check_packet_interval || test_fail + +server_conf="keyfile tmp/server.keys" +client_conf="" + +run_test || test_fail +check_chronyd_exit || test_fail +# This check must fail as the client doesn't know the key +check_sync && test_fail +check_packet_interval || test_fail + +client_conf="keyfile tmp/client.keys" +clients=2 +peers=2 +max_sync_time=500 +base_delay="$default_base_delay (* -1 (equal 0.1 from 3) (equal 0.1 to 1))" + +for versions in "3 3" "3 4" "4 3" "4 4"; do + for key in 1 $keys; do + client_lpeer_options="version ${versions% *} key $key" + client_rpeer_options="version ${versions#* } key $key" + run_test || test_fail + check_chronyd_exit || test_fail + check_sync || test_fail + done +done + +client_lpeer_options="key 1" +client_rpeer_options="key 2" + +run_test || test_fail +check_chronyd_exit || test_fail +# This check must fail as the peers are using different keys" +check_sync && test_fail + +test_pass diff --git a/test/simulation/106-refclock b/test/simulation/106-refclock new file mode 100755 index 0000000..c4cec20 --- /dev/null +++ b/test/simulation/106-refclock @@ -0,0 +1,34 @@ +#!/bin/bash + +. ./test.common +test_start "SHM refclock" + +check_config_h 'FEAT_REFCLOCK 1' || test_skip +check_config_h 'FEAT_PHC 1' || test_skip +check_config_h 'FEAT_CMDMON 1' || test_skip + +servers=0 +limit=1000 +refclock_jitter=$jitter +min_sync_time=45 +max_sync_time=70 +chronyc_start=70 +chronyc_conf="tracking" + +for refclock in "SHM 0" "PHC /dev/ptp0"; do + client_conf="refclock $refclock stratum 3 delay 1e-3 refid GPS" + + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_sync || test_fail + check_chronyc_output "^Reference ID.*47505300 \(GPS\) +Stratum.*: 4 +.* +Root delay : 0.001000000 seconds +.* +Update interval : 16\.. seconds +.*$" || test_fail +done + +test_pass diff --git a/test/simulation/107-allowdeny b/test/simulation/107-allowdeny new file mode 100755 index 0000000..3ab83ff --- /dev/null +++ b/test/simulation/107-allowdeny @@ -0,0 +1,48 @@ +#!/bin/bash + +. ./test.common + +test_start "allow/deny directives" + +check_config_h 'FEAT_CMDMON 1' || test_skip + +limit=500 + +# Note that start_client in clknetsim.bash always adds allow to the config + +for server_conf in \ + "deny" \ + "deny all" \ + "deny 192.168.0.0/16" \ + "deny 192.168.123" \ + "deny 192.168.123.2" \ + "deny all +allow 192.168.124.0/24" +do + run_test || test_fail + check_chronyd_exit || test_fail + check_packet_interval || test_fail + # These checks are expected to fail + check_source_selection && test_fail + check_sync && test_fail +done + +for server_conf in \ + "deny all +allow" \ + "deny all +allow all" \ + "deny all +allow 192.168.123" \ + "deny all +allow 192.168.123/24" \ + "deny 192.168.124.0/24" +do + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_packet_interval || test_fail + check_sync || test_fail +done + +test_pass diff --git a/test/simulation/108-peer b/test/simulation/108-peer new file mode 100755 index 0000000..20e2254 --- /dev/null +++ b/test/simulation/108-peer @@ -0,0 +1,54 @@ +#!/bin/bash + +. ./test.common + +test_start "NTP peers" + +# Allow and drop packets to the server in 1000 second intervals, so only one +# client has access to it and the other is forced to switch to the peer. +base_delay=$(cat <<-EOF | tr -d '\n' + (+ 1e-4 + (* -1 + (equal 0.1 from 2) + (equal 0.1 to 1) + (equal 0.1 (min (% time 2000) 1000) 1000)) + (* -1 + (equal 0.1 from 3) + (equal 0.1 to 1) + (equal 0.1 (max (% time 2000) 1000) 1000))) +EOF +) + +clients=2 +peers=2 +max_sync_time=1000 +client_server_options="minpoll 6 maxpoll 6" +client_peer_options="minpoll 6 maxpoll 6" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_sync || test_fail + +base_delay="(+ 1e-4 (* -1 (equal 0.1 from 3) (equal 0.1 to 1)))" +client_peer_options="" + +while read lminpoll lmaxpoll rminpoll rmaxpoll max_sync_time; do + client_lpeer_options="minpoll $lminpoll maxpoll $lmaxpoll" + client_rpeer_options="minpoll $rminpoll maxpoll $rmaxpoll" + limit=$[$max_sync_time * 10] + + run_test || test_fail + check_chronyd_exit || test_fail + check_sync || test_fail +done <<-EOF + 3 6 3 6 400 + 3 3 6 6 450 + 6 6 3 3 450 + 3 6 6 6 450 + 6 6 3 6 450 + -2 -2 2 2 220 + 2 2 -2 -2 220 +EOF + +test_pass diff --git a/test/simulation/109-makestep b/test/simulation/109-makestep new file mode 100755 index 0000000..f984f72 --- /dev/null +++ b/test/simulation/109-makestep @@ -0,0 +1,41 @@ +#!/bin/bash + +. ./test.common +test_start "makestep directive" + +client_conf="makestep 0 -1 +corrtimeratio 1e10" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +limit=200 +jitter=1e-5 +client_conf="makestep 2 1" + +min_sync_time=130 +max_sync_time=150 + +for time_offset in -1.0 -0.1 0.1 1.0; do + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_packet_interval || test_fail + check_sync || test_fail +done + +min_sync_time=120 +max_sync_time=140 + +for time_offset in -1e8 -1e2 1e2 1e8; do + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_packet_interval || test_fail + check_sync || test_fail +done + +test_pass diff --git a/test/simulation/110-chronyc b/test/simulation/110-chronyc new file mode 100755 index 0000000..d578bf2 --- /dev/null +++ b/test/simulation/110-chronyc @@ -0,0 +1,226 @@ +#!/bin/bash + +. ./test.common + +test_start "chronyc" + +check_config_h 'FEAT_REFCLOCK 1' || test_skip +check_config_h 'FEAT_CMDMON 1' || test_skip + +refclock_jitter=$jitter +client_server_conf=" +server node1.net1.clk +server 192.168.123.2" +client_conf=" +refclock SHM 0 noselect +smoothtime 400 0.001 leaponly" + +chronyc_conf="activity +tracking +sourcename 192.168.123.1 +sourcename 192.168.123.2 +sources +sourcestats +manual list +smoothing +waitsync +rtcdata" + +run_test || test_fail +check_chronyd_exit || test_fail + +check_chronyc_output "^200 OK +2 sources online +0 sources offline +0 sources doing burst \(return to online\) +0 sources doing burst \(return to offline\) +0 sources with unknown address +Reference ID : C0A87B01 \(192\.168\.123\.1\) +Stratum : 2 +Ref time \(UTC\) : Fri Jan 01 00:1.:.. 2010 +System time : 0\.0000..... seconds (slow|fast) of NTP time +Last offset : [+-]0\.000...... seconds +RMS offset : 0\.000...... seconds +Frequency : (99|100)\.... ppm fast +Residual freq : [+-][0-9]\.... ppm +Skew : [0-9]\.... ppm +Root delay : 0\.000...... seconds +Root dispersion : 0\.000...... seconds +Update interval : [0-9]+\.. seconds +Leap status : Normal +node1\.net1\.clk +192\.168\.123\.2 +MS Name/IP address Stratum Poll Reach LastRx Last sample +=============================================================================== +#\? SHM0 0 4 377 [0-9]+ [0-9 +-]+[un]s\[[0-9 +-]+[un]s\] \+/-[ 0-9]+[un]s +\^\* 192\.168\.123\.1 1 [67] 377 [0-9]+ [0-9 +-]+[un]s\[[0-9 +-]+[un]s\] \+/-[ 0-9]+[un]s +\^\? 192\.168\.123\.2 0 [0-9]+ 0 - \+0ns\[ \+0ns\] \+/- 0ns +Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev +============================================================================== +SHM0 [0-9 ]+ [0-9 ]+ [0-9 ]+ [ +-][01]\.... [0-9 ]+\.... [0-9 +-]+[un]s [0-9 ]+[un]s +192\.168\.123\.1 [0-9 ]+ [0-9 ]+ [0-9 ]+ [ +-][01]\.... [0-9 ]+\.... [0-9 +-]+[un]s [0-9 ]+[un]s +192\.168\.123\.2 0 0 0 \+0\.000 2000\.000 \+0ns 4000ms +210 n_samples = 0 +# Date Time\(UTC\) Slewed Original Residual +======================================================= +Active : Yes \(leap second only\) +Offset : \+0\.000000000 seconds +Frequency : \+0\.000000 ppm +Wander : \+0\.000000 ppm per second +Last update : [0-9]+\.. seconds ago +Remaining time : 0\.0 seconds +try: 1, refid: C0A87B01, correction: 0\.000......, skew: .\.... +513 RTC driver not running$" \ +|| test_fail + +chronyc_conf="tracking" +dns=1 + +run_test || test_fail +check_chronyd_exit || test_fail + +check_chronyc_output "^Reference ID : C0A87B01 \(node1\.net1\.clk\)" \ + || test_fail + +chronyc_options="-c" + +run_test || test_fail +check_chronyd_exit || test_fail + +check_chronyc_output "^C0A87B01,192\.168\.123\.1,2,12623049..\..........,-?0\.0000.....,-?0\.000......,0\.000......,(99|100)\....,-?[0-9]\....,[0-9]\....,0\.000......,0\.000......,[0-9]+\..,Normal$" \ + || test_fail + +chronyc_options="" +server_strata=0 +chronyc_start=0 +client_server_conf="" +client_conf="" +server_conf="server 192.168.123.1" +limit=1 + +for chronyc_conf in \ + "accheck 1.2.3.4" \ + "add peer 10.0.0.0 minpoll 2 maxpoll 6" \ + "add server 10.0.0.0 minpoll 6 maxpoll 10 iburst burst key 1 maxdelay 1e-3 maxdelayratio 10.0 maxdelaydevratio 10.0 mindelay 1e-4 asymmetry 0.5 offset 1e-5 minsamples 6 maxsamples 6 filter 3 offline auto_offline prefer noselect trust require xleave polltarget 20 port 123 presend 7 minstratum 3 version 4" \ + "add server node1.net1.clk" \ + "allow 1.2.3.4" \ + "allow 1.2" \ + "allow 3.4.5" \ + "allow 6.7.8/22" \ + "allow 6.7.8.9/22" \ + "allow 2001:db8::/32" \ + "allow 0/0" \ + "allow ::/0" \ + "allow" \ + "allow all 10/24" \ + "authdata" \ + "burst 5/10" \ + "burst 3/5 255.255.255.0/1.2.3.0" \ + "burst 1/2 1.2.3.0/24" \ + "clients" \ + "clients -k" \ + "clients -p 100" \ + "clients -r" \ + "cmdaccheck 1.2.3.4" \ + "cmdallow 1.2.3.4" \ + "cmdallow all 1.2.3.0/24" \ + "cmddeny 1.2.3.4" \ + "cmddeny all 1.2.3.0/24" \ + "cyclelogs" \ + "delete 10.0.0.0" \ + "delete ID#0000000001" \ + "deny 1.2.3.4" \ + "deny all 1.2.3.0/24" \ + "dfreq 1.0e-3" \ + "doffset -1.0" \ + "dump" \ + "local stratum 5 distance 1.0 orphan" \ + "local off" \ + "makestep 10.0 3" \ + "makestep" \ + "manual delete 0" \ + "manual off" \ + "manual on" \ + "manual reset" \ + "maxdelay 1.2.3.4 1e-2" \ + "maxdelaydevratio 1.2.3.4 5.0" \ + "maxdelayratio 1.2.3.4 3.0" \ + "maxpoll 1.2.3.4 5" \ + "maxupdateskew 1.2.3.4 10.0" \ + "minpoll 1.2.3.4 3" \ + "minstratum 1.2.3.4 1" \ + "minstratum ID#0000000001 1" \ + "ntpdata 1.2.3.4" \ + "offline" \ + "offline 255.255.255.0/1.2.3.0" \ + "offline 1.2.3.0/24" \ + "online" \ + "online 1.2.3.0/24" \ + "onoffline" \ + "polltarget 1.2.3.4 10" \ + "refresh" \ + "rekey" \ + "reload sources" \ + "reselect" \ + "reselectdist 1e-3" \ + "reset sources" \ + "selectdata" \ + "settime 16:30" \ + "settime 16:30:05" \ + "settime Nov 21, 2015 16:30:05" \ + "serverstats" \ + "shutdown" \ + "smoothtime reset" \ + "smoothtime activate" \ + "trimrtc" \ + "writertc" +do + run_test || test_fail + check_chronyd_exit || test_fail + check_chronyc_output "501 Not authorised$" || test_fail +done + +chronyc_conf="dns -n +dns +n +dns -4 +dns -6 +dns -46 +timeout 200 +retries 1 +keygen +keygen 10 MD5 128 +keygen 11 MD5 40 +help +quit +nosuchcommand" + +run_test || test_fail + +check_chronyc_output "^1 (MD5|SHA1) HEX:........................................ +10 MD5 HEX:................................ +11 MD5 HEX:.................... +System clock:.*this help + *$" || test_fail + +chronyc_conf="keygen 10 NOSUCHTYPE 128 +help" +run_test || test_fail +check_chronyc_output "^Unknown hash function or cipher NOSUCHTYPE\$" || test_fail + +if check_config_h 'FEAT_SECHASH 1'; then + for hash in MD5 SHA1 SHA256 SHA384 SHA512; do + chronyc_conf="keygen 5 $hash" + run_test || test_fail + check_chronyc_output "^5 $hash HEX:........................................\$" || test_fail + done +fi + +if check_config_h 'HAVE_CMAC 1'; then + chronyc_conf="keygen 6 AES128 +keygen 7 AES256" + run_test || test_fail + check_chronyc_output "^6 AES128 HEX:................................ +7 AES256 HEX:................................................................\$" || test_fail +fi + +test_pass diff --git a/test/simulation/111-knownclient b/test/simulation/111-knownclient new file mode 100755 index 0000000..3d3fd87 --- /dev/null +++ b/test/simulation/111-knownclient @@ -0,0 +1,17 @@ +#!/bin/bash + +. ./test.common + +test_start "reply to client configured as server" + +server_conf="server 192.168.123.2 noselect +acquisitionport 123" +client_conf="acquisitionport 123" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_port || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/112-port b/test/simulation/112-port new file mode 100755 index 0000000..a8efabd --- /dev/null +++ b/test/simulation/112-port @@ -0,0 +1,57 @@ +#!/bin/bash + +. ./test.common + +test_start "port and acquisitionport directives" + +check_config_h 'FEAT_CMDMON 1' || test_skip + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail +# This check is expected to fail +check_packet_port && test_fail + +client_conf="acquisitionport 123" +run_test || test_fail +check_chronyd_exit || test_fail +check_packet_port || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +client_conf="" +for server_conf in \ + "port 0" \ + "acquisitionport 123 +port 0" +do + run_test || test_fail + check_chronyd_exit || test_fail + check_packet_port || test_fail + check_packet_interval || test_fail + # These checks are expected to fail + check_source_selection && test_fail + check_sync && test_fail +done + +server_conf="port 124 +acquisitionport 123" +client_server_options="port 124" +for client_conf in \ + "acquisitionport 0" \ + "acquisitionport 123" \ + "acquisitionport 124" +do + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_packet_interval || test_fail + check_sync || test_fail + # This check is expected to fail + check_packet_port && test_fail +done + +test_pass diff --git a/test/simulation/113-leapsecond b/test/simulation/113-leapsecond new file mode 100755 index 0000000..2fb81b8 --- /dev/null +++ b/test/simulation/113-leapsecond @@ -0,0 +1,61 @@ +#!/bin/bash + +. ./test.common + +test_start "leap second" + +check_config_h 'FEAT_REFCLOCK 1' || test_skip + +export CLKNETSIM_START_DATE=$(TZ=UTC date -d 'Dec 30 2008 0:00:00' +'%s') + +leap=$[2 * 24 * 3600] +limit=$[4 * 24 * 3600] +client_start=$[2 * 3600] +server_conf="refclock SHM 0 dpoll 10 poll 10 +leapsectz right/UTC" +refclock_jitter=1e-9 +refclock_offset="(* -1.0 (equal 0.1 (max (sum 1.0) $leap) $leap))" + +for leapmode in system step slew; do + client_conf="leapsecmode $leapmode" + if [ $leapmode = slew ]; then + max_sync_time=$[$leap + 12] + else + max_sync_time=$[$leap] + fi + + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_packet_interval || test_fail + check_sync || test_fail +done + +client_server_options="trust" +client_conf="refclock SHM 0 dpoll 10 poll 10 delay 1e-3" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +client_server_options="" +client_conf="leapsecmode system" +min_sync_time=230000 +max_sync_time=240000 + +for smoothmode in "" "leaponly"; do + server_conf="refclock SHM 0 dpoll 10 poll 10 + leapsectz right/UTC + leapsecmode slew + smoothtime 400 0.001 $smoothmode" + + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_packet_interval || test_fail + check_sync || test_fail +done + +test_pass diff --git a/test/simulation/114-presend b/test/simulation/114-presend new file mode 100755 index 0000000..3113253 --- /dev/null +++ b/test/simulation/114-presend @@ -0,0 +1,25 @@ +#!/bin/bash + +. ./test.common +test_start "presend option" + +min_sync_time=136 +max_sync_time=260 +client_server_options="presend 6 maxdelay 16" +client_conf="maxdistance 10" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +base_delay=5 + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/115-cmdmontime b/test/simulation/115-cmdmontime new file mode 100755 index 0000000..ea79b26 --- /dev/null +++ b/test/simulation/115-cmdmontime @@ -0,0 +1,24 @@ +#!/bin/bash + +. ./test.common + +test_start "cmdmon timestamps" + +# The following tests need 64-bit time_t +check_config_h 'HAVE_LONG_TIME_T 1' || test_skip +check_config_h 'FEAT_CMDMON 1' || test_skip + +limit=2 +client_server_options="noselect" +client_conf="local stratum 1" +chronyc_start="1.5" +chronyc_conf="tracking" + +for year in `seq 1850 100 2300`; do + export CLKNETSIM_START_DATE=$(date -d "Jan 01 00:00:05 $year UTC" +'%s') + run_test || test_fail + check_chronyd_exit || test_fail + check_chronyc_output "^.*Ref time \(UTC\).*Jan 01 00:00:0. $year.*$" || test_fail +done + +test_pass diff --git a/test/simulation/116-minsources b/test/simulation/116-minsources new file mode 100755 index 0000000..392f360 --- /dev/null +++ b/test/simulation/116-minsources @@ -0,0 +1,24 @@ +#!/bin/bash + +. ./test.common + +test_start "minsources directive" + +client_conf="minsources 3" + +run_test || test_fail +check_chronyd_exit || test_fail +check_packet_interval || test_fail +# These check are expected to fail +check_source_selection && test_fail +check_sync && test_fail + +servers=3 + +run_test || test_fail +check_chronyd_exit || test_fail +check_packet_interval || test_fail +check_source_selection || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/117-fallbackdrift b/test/simulation/117-fallbackdrift new file mode 100755 index 0000000..22270c9 --- /dev/null +++ b/test/simulation/117-fallbackdrift @@ -0,0 +1,24 @@ +#!/bin/bash + +. ./test.common +test_start "fallback drift" + +limit=100000 +wander=0.0 +jitter=1e-6 +time_offset=10 +freq_offset="(* 1e-4 (sine 1000))" +base_delay="(* -1.0 (equal 0.1 (min time 4250) 4250))" +client_server_options="minpoll 4 maxpoll 4" +client_conf="fallbackdrift 6 10" +max_sync_time=4500 +time_max_limit=1e0 +time_rms_limit=1e0 +freq_max_limit=2e-4 +freq_rms_limit=1e-4 + +run_test || test_fail +check_chronyd_exit || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/118-maxdelay b/test/simulation/118-maxdelay new file mode 100755 index 0000000..22b9a50 --- /dev/null +++ b/test/simulation/118-maxdelay @@ -0,0 +1,28 @@ +#!/bin/bash + +. ./test.common +test_start "maxdelay options" + +max_sync_time=2000 +base_delay=1e-5 +jitter=1e-5 +wander=0.0 +freq_offset="(sum 1e-10)" +time_rms_limit=2e-4 + +client_server_options="maxpoll 6 maxdelay 3e-5 maxdelayratio 2.0 maxdelaydevratio 2.0" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +for client_server_options in "maxpoll 6 maxdelay 2e-5"; do + run_test || test_fail + check_chronyd_exit || test_fail + check_packet_interval || test_fail + check_sync && test_fail +done + +test_pass diff --git a/test/simulation/119-smoothtime b/test/simulation/119-smoothtime new file mode 100755 index 0000000..3f90715 --- /dev/null +++ b/test/simulation/119-smoothtime @@ -0,0 +1,82 @@ +#!/bin/bash + +. ./test.common + +test_start "smoothtime option" + +check_config_h 'FEAT_REFCLOCK 1' || test_skip + +server_strata=2 +server_conf="smoothtime 400 0.001" +server_server_options="minpoll 8" +min_sync_time=600 +max_sync_time=800 + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_sync || test_fail + +limit=10000 +refclock_jitter=1e-4 +refclock_offset="(* 10.0 (equal 0.1 (max (sum 1.0) 1000) 1000))" +server_step="(* -10.0 (equal 0.1 (sum 1.0) 1))" +server_strata=1 +server_conf="refclock SHM 0 dpoll 4 poll 6 +smoothtime 2000 1 +maxjitter 10.0" +time_offset=-10 +server_server_options="" +client_server_options="minpoll 6 maxpoll 6" +client_conf="corrtimeratio 100" +min_sync_time=8000 +max_sync_time=9000 + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_sync || test_fail + +client_server_options="minpoll 6 maxpoll 6 xleave maxdelay 1e-1" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_sync || test_fail + +client_server_options="minpoll 6 maxpoll 6" +min_sync_time=$default_min_sync_time +max_sync_time=$default_max_sync_time +time_max_limit=11 +time_rms_limit=11 +freq_max_limit=1e-2 +freq_rms_limit=2e-3 + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_sync || test_fail + +refclock_jitter=1e-9 +refclock_offset="(* 1e-1 (triangle 1000) (+ -1.0 (pulse 1000 10000)))" +server_step="" +server_conf="refclock SHM 0 dpoll 4 poll 6 minsamples 4 maxsamples 4 +smoothtime 1e4 1e-6" +client_server_options="minpoll 4 maxpoll 4" +time_offset=0.1 +jitter=1e-6 +wander=0.0 +min_sync_time=30 +max_sync_time=40 +time_max_limit=1e-5 +time_rms_limit=5e-6 +freq_max_limit=1e-6 +freq_rms_limit=1e-7 + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/120-selectoptions b/test/simulation/120-selectoptions new file mode 100755 index 0000000..a6b1e14 --- /dev/null +++ b/test/simulation/120-selectoptions @@ -0,0 +1,92 @@ +#!/bin/bash + +. ./test.common + +test_start "source selection options" + +servers=3 +falsetickers=2 + +base_delay=0.6 +client_server_conf=" +server 192.168.123.1 +server 192.168.123.2 +server 192.168.123.3 trust" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +client_server_conf=" +server 192.168.123.1 +server 192.168.123.2 +server 192.168.123.3 prefer" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +# This check is expected to fail +check_sync && test_fail + +base_delay=1.1 + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +base_delay=$default_base_delay +falsetickers=1 + +client_server_conf=" +server 192.168.123.1 +server 192.168.123.2 +server 192.168.123.3 require" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +client_server_conf=" +server 192.168.123.1 require +server 192.168.123.2 +server 192.168.123.3" + +run_test || test_fail +check_chronyd_exit || test_fail +check_packet_interval || test_fail +# These checks are expected to fail +check_source_selection && test_fail +check_sync && test_fail + +cat > tmp/keys <<-EOF +1 MD5 HEX:1B81CBF88D4A73F2E8CE59647F6E5C1719B6CAF5 +EOF + +server_conf="keyfile tmp/keys" +client_server_conf=" +server 192.168.123.1 key 1 +server 192.168.123.2 +server 192.168.123.3" + +for authselectmode in require prefer mix ignore; do + client_conf="keyfile tmp/keys + authselectmode $authselectmode" + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_packet_interval || test_fail + if [ $authselectmode = ignore ]; then + check_sync || test_fail + else + check_sync && test_fail + fi +done + +test_pass diff --git a/test/simulation/121-orphan b/test/simulation/121-orphan new file mode 100755 index 0000000..c3d043f --- /dev/null +++ b/test/simulation/121-orphan @@ -0,0 +1,26 @@ +#!/bin/bash + +. ./test.common + +test_start "orphan option" + +check_config_h 'FEAT_CMDMON 1' || test_skip + +server_strata=3 +server_conf="local stratum 5 orphan +server 192.168.123.1 +server 192.168.123.2 +server 192.168.123.3" +max_sync_time=900 +client_start=140 +chronyc_start=700 +chronyc_conf="tracking" +time_rms_limit=5e-4 + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_sync || test_fail +check_chronyc_output "^.*Stratum *: 7.*$" || test_fail + +test_pass diff --git a/test/simulation/122-xleave b/test/simulation/122-xleave new file mode 100755 index 0000000..66eef5c --- /dev/null +++ b/test/simulation/122-xleave @@ -0,0 +1,55 @@ +#!/bin/bash + +. ./test.common +test_start "interleaved mode" + +client_server_options="xleave" +client_conf=" +logdir tmp +log rawmeasurements" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +check_file_messages "111 111 1111.* 4B [DKH] [DKH]\$" 2 2 measurements.log || test_fail +check_file_messages "111 111 1111.* 4I [DKH] [DKH]\$" 30 200 measurements.log || test_fail +rm -f tmp/measurements.log + +clients=2 +peers=2 +max_sync_time=500 +base_delay="(+ 1e-4 (* -1 (equal 0.1 from 2) (equal 0.1 to 1)))" + +client_lpeer_options="xleave minpoll 5 maxpoll 5" +client_rpeer_options="minpoll 5 maxpoll 5" + +run_test || test_fail +check_chronyd_exit || test_fail +# These checks are expected to fail +check_source_selection && test_fail +check_sync && test_fail + +rm -f tmp/measurements.log + +for rpoll in 4 5 6; do + client_rpeer_options="xleave minpoll $rpoll maxpoll $rpoll" + + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_sync || test_fail + + if [ $rpoll -le 5 ]; then + check_file_messages "111 111 1111.* 1B [DKH] [DKH]\$" 0 0 measurements.log || test_fail + check_file_messages "111 111 1111.* 1I [DKH] [DKH]\$" 200 310 measurements.log || test_fail + else + check_file_messages "111 111 1111.* 1B [DKH] [DKH]\$" 125 135 measurements.log || test_fail + check_file_messages "111 111 1111.* 1I [DKH] [DKH]\$" 20 30 measurements.log || test_fail + fi + rm -f tmp/measurements.log +done + +test_pass diff --git a/test/simulation/123-mindelay b/test/simulation/123-mindelay new file mode 100755 index 0000000..cde214a --- /dev/null +++ b/test/simulation/123-mindelay @@ -0,0 +1,27 @@ +#!/bin/bash + +. ./test.common + +test_start "mindelay and asymmetry options" + +jitter_asymmetry=0.499 +time_rms_limit=1e-6 +time_freq_limit=1e-9 +wander=1e-12 + +for client_server_options in "mindelay 2e-4 asymmetry 0.499"; do + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_packet_interval || test_fail + check_sync || test_fail +done + +for client_server_options in "mindelay 1e-4 asymmetry 0.499" "mindelay 2e-4 asymmetry 0.0"; do + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_sync && test_fail +done + +test_pass diff --git a/test/simulation/124-tai b/test/simulation/124-tai new file mode 100755 index 0000000..d41d29d --- /dev/null +++ b/test/simulation/124-tai @@ -0,0 +1,45 @@ +#!/bin/bash + +. ./test.common + +test_start "tai option" + +check_config_h 'FEAT_REFCLOCK 1' || test_skip + +export CLKNETSIM_START_DATE=$(TZ=UTC date -d 'Dec 31 2008 23:50:00' +'%s') + +leap=$[10 * 60] +limit=$[20 * 60] +min_sync_time=2 +max_sync_time=15 +refclock_jitter=1e-6 +servers=0 + +refclock_offset="(+ -34 (equal 0.1 (max (sum 1.0) $leap) $leap))" +client_conf=" +refclock SHM 0 dpoll 0 poll 0 tai +leapsectz right/UTC +leapsecmode ignore +maxchange 1e-3 1 0" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_sync || test_fail + +export CLKNETSIM_START_DATE=$(TZ=UTC date -d 'Jan 01 2009 00:10:00' +'%s') + +time_offset=-1000 +refclock_offset="(+ -34)" +client_conf=" +refclock SHM 0 dpoll 0 poll 0 tai +leapsectz right/UTC +makestep 1 1 +maxchange 1e-3 1 0" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/125-packetloss b/test/simulation/125-packetloss new file mode 100755 index 0000000..95604da --- /dev/null +++ b/test/simulation/125-packetloss @@ -0,0 +1,29 @@ +#!/bin/bash + +. ./test.common + +test_start "packet loss" + +# Drop 33% of packets by default and 100% on the 3->1 path +base_delay=$(cat <<-EOF | tr -d '\n' + (+ 1e-4 + (* -1 (equal 0.33 (uniform) 1.0)) + (* -1 (equal 0.1 from 3) (equal 0.1 to 1))) +EOF +) +clients=2 +peers=2 +jitter=1e-5 +limit=20000 +max_sync_time=10000 + +for options in "maxpoll 8" "maxpoll 8 xleave"; do + client_server_options=$options + client_peer_options=$options + + run_test || test_fail + check_chronyd_exit || test_fail + check_sync || test_fail +done + +test_pass diff --git a/test/simulation/126-burst b/test/simulation/126-burst new file mode 100755 index 0000000..d63f290 --- /dev/null +++ b/test/simulation/126-burst @@ -0,0 +1,45 @@ +#!/bin/bash + +. ./test.common + +test_start "burst option" + +# Pass every fourth packet on the 2->1 path +base_delay=$(cat <<-EOF | tr -d '\n' + (+ 1e-4 + (* -1 + (equal 0.1 from 2) + (equal 0.1 to 1) + (equal 0.1 (min (% (sum 1) 4) 1) 1))) +EOF +) + +client_server_options="burst polltarget 1" +min_sync_time=700 +max_sync_time=730 +client_max_min_out_interval=2.2 +client_min_mean_out_interval=150.0 + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +# Add a significant delay to 70% of packets on the 2->1 path after 6th packet +base_delay=$(cat <<-EOF | tr -d '\n' + (+ 1e-4 + (* 0.15 + (equal 0.1 from 2) + (equal 0.1 to 1) + (equal 0.1 (min (sum 1) 7) 7) + (equal 0.7 (uniform) 0.0))) +EOF +) + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail + +test_pass diff --git a/test/simulation/127-filter b/test/simulation/127-filter new file mode 100755 index 0000000..737d1f9 --- /dev/null +++ b/test/simulation/127-filter @@ -0,0 +1,19 @@ +#!/bin/bash + +. ./test.common + +test_start "filter option" + +client_server_options="minpoll 4 maxpoll 4 filter 15" +min_sync_time=710 +max_sync_time=720 +client_max_min_out_interval=16.1 +client_min_mean_out_interval=15.9 + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/128-nocontrol b/test/simulation/128-nocontrol new file mode 100755 index 0000000..cca82f4 --- /dev/null +++ b/test/simulation/128-nocontrol @@ -0,0 +1,27 @@ +#!/bin/bash + +. ./test.common + +test_start "-x option" + +check_config_h 'FEAT_CMDMON 1' || test_skip + +wander=0.0 +time_offset=0.0 +freq_offset=0.0 +time_max_limit=1e-6 +freq_max_limit=1e-9 +min_sync_time=0 +max_sync_time=0 +client_chronyd_options="-x" +chronyc_start=300 +chronyc_conf="tracking" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail +check_chronyc_output "^.*Stratum *: 2.*$" || test_fail + +test_pass diff --git a/test/simulation/129-reload b/test/simulation/129-reload new file mode 100755 index 0000000..7a346a4 --- /dev/null +++ b/test/simulation/129-reload @@ -0,0 +1,26 @@ +#!/bin/bash + +. ./test.common + +test_start "-r option" + +wander=0.0 +limit=100 +min_sync_time=100 +max_sync_time=104 +client_chronyd_options="-r" +client_conf="dumpdir tmp +maxupdateskew 10000" + +run_test || test_fail + +client_start=$limit +limit=1000 + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/130-quit b/test/simulation/130-quit new file mode 100755 index 0000000..f5f7766 --- /dev/null +++ b/test/simulation/130-quit @@ -0,0 +1,31 @@ +#!/bin/bash + +. ./test.common + +test_start "-q/-Q option" + +wander=0.0 +freq_offset=0.0 +min_sync_time=5 +max_sync_time=10 +client_chronyd_options="-q" +client_server_options="iburst" + +run_test || test_fail +check_chronyd_exit || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +min_sync_time=1 +max_sync_time=1 +client_server_options="iburst maxsamples 1" + +run_test || test_fail +check_chronyd_exit || test_fail +check_sync || test_fail + +client_chronyd_options="-Q" +run_test || test_fail +check_sync && test_fail + +test_pass diff --git a/test/simulation/131-maxchange b/test/simulation/131-maxchange new file mode 100755 index 0000000..969f71f --- /dev/null +++ b/test/simulation/131-maxchange @@ -0,0 +1,20 @@ +#!/bin/bash + +. ./test.common + +test_start "maxchange directive" + +time_offset=2 +max_sync_time=5000 +client_conf="maxchange 0.1 1 3" +client_step="(* $step (equal 0.1 (sum 1.0) 300))" + +run_test || test_fail +check_chronyd_exit && test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync && test_fail +check_log_messages "seconds exceeds.*ignored" 3 3 || test_fail +check_log_messages "seconds exceeds.*exiting" 1 1 || test_fail + +test_pass diff --git a/test/simulation/132-logchange b/test/simulation/132-logchange new file mode 100755 index 0000000..8db1741 --- /dev/null +++ b/test/simulation/132-logchange @@ -0,0 +1,21 @@ +#!/bin/bash + +. ./test.common + +test_start "logchange directive" + +time_offset=2 +min_sync_time=590 +max_sync_time=700 +client_server_options="maxsamples 6" +client_conf="logchange 0.1" +client_step="(* $step (equal 0.1 (sum 1.0) 300))" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail +check_log_messages "clock wrong by" 4 8 || test_fail + +test_pass diff --git a/test/simulation/133-hwtimestamp b/test/simulation/133-hwtimestamp new file mode 100755 index 0000000..e4896fc --- /dev/null +++ b/test/simulation/133-hwtimestamp @@ -0,0 +1,39 @@ +#!/bin/bash + +. ./test.common + +test_start "hwtimestamp directive" + +check_config_h 'HAVE_LINUX_TIMESTAMPING 1' || test_skip + +export CLKNETSIM_TIMESTAMPING=2 + +refclock_jitter=1e-8 +refclock_offset=10.0 +min_sync_time=4 +max_sync_time=20 +limit=200 +server_conf="hwtimestamp eth0" +client_server_options="minpoll 0 maxpoll 0 minsamples 32 xleave" +client_chronyd_options="-d" + +for client_conf in "hwtimestamp eth0" "hwtimestamp eth0 +acquisitionport 123"; do + run_test || test_fail + check_chronyd_exit || test_fail + check_source_selection || test_fail + check_sync || test_fail + + if check_config_h 'FEAT_DEBUG 1'; then + check_log_messages "HW clock samples" 190 200 || test_fail + check_log_messages "HW clock reset" 0 0 || test_fail + check_log_messages "Received message.*tss=KH" 195 200 || test_fail + check_log_messages "Received error.*message.*tss=KH" 195 200 || test_fail + check_log_messages "Updated RX timestamp.*tss=1" 1 1 || test_fail + check_log_messages "Updated RX timestamp.*tss=2" 195 200 || test_fail + check_log_messages "update_tx_timestamp.*Updated" 50 140 || test_fail + check_log_messages "update_tx_timestamp.*Unacceptable" 50 140 || test_fail + fi +done + +test_pass diff --git a/test/simulation/134-log b/test/simulation/134-log new file mode 100755 index 0000000..0a6ef76 --- /dev/null +++ b/test/simulation/134-log @@ -0,0 +1,33 @@ +#!/bin/bash + +. ./test.common + +test_start "log directive" + +check_config_h 'FEAT_PHC 1' || test_skip + +refclock_jitter=$jitter +client_server_options="maxpoll 6" +client_conf="refclock PHC /dev/ptp0 dpoll 4 poll 6 noselect +logbanner 10 +logdir tmp +log tracking rawmeasurements measurements statistics rtc refclocks tempcomp +tempcomp tmp/tempcomp 64 0.0 0.0 0.0 0.0" + +echo 0.0 > tmp/tempcomp + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +check_file_messages "=============" 31 33 \ + tracking.log measurements.log tempcomp.log || test_fail +check_file_messages "20.*192\.168\.123\.1" 150 160 \ + tracking.log measurements.log statistics.log || test_fail +check_file_messages "20.*PHC0" 150 160 statistics.log || test_fail +check_file_messages "20.*PHC0" 750 800 refclocks.log || test_fail +check_file_messages "20.* 0\.0000" 150 160 tempcomp.log || test_fail + +test_pass diff --git a/test/simulation/135-ratelimit b/test/simulation/135-ratelimit new file mode 100755 index 0000000..cfa5eab --- /dev/null +++ b/test/simulation/135-ratelimit @@ -0,0 +1,18 @@ +#!/bin/bash + +. ./test.common +test_start "ratelimit directive" + +server_conf="ratelimit interval 6 burst 2 leak 4" +client_server_options="minpoll 3 maxpoll 3" +min_sync_time=16 + +run_test || test_fail +check_chronyd_exit || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +check_file_messages " 2 1 " 1200 1300 log.packets || test_fail +check_file_messages " 1 2 " 180 220 log.packets || test_fail + +test_pass diff --git a/test/simulation/136-broadcast b/test/simulation/136-broadcast new file mode 100755 index 0000000..d60d678 --- /dev/null +++ b/test/simulation/136-broadcast @@ -0,0 +1,16 @@ +#!/bin/bash + +. ./test.common + +test_start "broadcast directive" + +server_conf="broadcast 64 192.168.123.255" +client_server_options="offline" + +run_test || test_fail +check_chronyd_exit || test_fail +check_packet_interval && test_fail + +check_file_messages " 1 2 " 150 160 log.packets || test_fail + +test_pass diff --git a/test/simulation/137-pool b/test/simulation/137-pool new file mode 100755 index 0000000..32f44ec --- /dev/null +++ b/test/simulation/137-pool @@ -0,0 +1,49 @@ +#!/bin/bash + +. ./test.common + +test_start "pool directive" + +limit=500 +client_conf="logdir tmp +log measurements" + +servers=3 +client_server_conf="pool nodes-1-2-3.net1.clk" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +check_file_messages "20.*192.168.123.1" 5 10 measurements.log || test_fail +check_file_messages "20.*192.168.123.2" 5 10 measurements.log || test_fail +check_file_messages "20.*192.168.123.3" 5 10 measurements.log || test_fail +rm -f tmp/measurements.log + +servers=6 +client_server_conf="pool nodes-1-2-3-4-5-6.net1.clk minpoll 6 maxpoll 6" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +check_file_messages "20.*192.168.123.*" 30 35 measurements.log || test_fail +rm -f tmp/measurements.log + +servers=6 +client_server_conf="pool nodes-1-2-3-4-5-6.net1.clk maxsources 2 minpoll 6 maxpoll 6" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +check_file_messages "20.*192.168.123.*" 15 17 measurements.log || test_fail +rm -f tmp/measurements.log + +test_pass diff --git a/test/simulation/138-syncloop b/test/simulation/138-syncloop new file mode 100755 index 0000000..8edeec6 --- /dev/null +++ b/test/simulation/138-syncloop @@ -0,0 +1,34 @@ +#!/bin/bash + +. ./test.common + +test_start "loop prevention" + +mkdir tmp/logdir1 tmp/logdir2 + +server_conf=" +server 192.168.123.1 +server 192.168.123.2 +logdir tmp/logdir1 +log measurements" +client_server_conf=" +server 192.168.123.1 +server 192.168.123.2 +logdir tmp/logdir2 +log measurements +allow" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_sync || test_fail + +check_file_messages "20.*123\.1.* 111 111 1110" 30 200 logdir1/measurements.log || test_fail +check_file_messages "20.*123\.2.* 111 111 1110" 30 200 logdir1/measurements.log || test_fail +check_file_messages "20.*123\...* 111 111 1111" 0 0 logdir1/measurements.log || test_fail +check_file_messages "20.*123\.1.* 111 111 1111" 30 200 logdir2/measurements.log || test_fail +check_file_messages "20.*123\.1.* 111 111 1110" 0 0 logdir2/measurements.log || test_fail +check_file_messages "20.*123\.2.* 111 111 1110" 30 200 logdir2/measurements.log || test_fail +check_file_messages "20.*123\.2.* 111 111 1111" 0 0 logdir1/measurements.log || test_fail + +test_pass diff --git a/test/simulation/139-nts b/test/simulation/139-nts new file mode 100755 index 0000000..74b8981 --- /dev/null +++ b/test/simulation/139-nts @@ -0,0 +1,173 @@ +#!/bin/bash + +. ./test.common + +test_start "NTP authentication with NTS" + +check_config_h 'FEAT_NTS 1' || test_skip +certtool --help &> /dev/null || test_skip + +export CLKNETSIM_START_DATE=$(date -d 'Jan 1 00:00:00 UTC 2010' +'%s') + +cat > tmp/cert.cfg <<EOF +cn = "node1.net1.clk" +serial = 001 +activation_date = "2010-01-01 00:00:00 UTC" +expiration_date = "2010-01-02 00:00:00 UTC" +#dns_name = "node1.net1.clk" +signing_key +encryption_key +EOF + +certtool --generate-privkey --key-type=ed25519 --outfile tmp/server.key &> tmp/log.certtool +certtool --generate-self-signed --load-privkey tmp/server.key \ + --template tmp/cert.cfg --outfile tmp/server.crt &>> tmp/log.certtool + +max_sync_time=400 +dns=1 +server_conf=" +ntsserverkey tmp/server.key +ntsservercert tmp/server.crt +ntsprocesses 0 +ntsrotate 66 +ntsdumpdir tmp +" +client_server_options="minpoll 6 maxpoll 6 nts" +client_conf=" +nosystemcert +ntstrustedcerts tmp/server.crt +logdir tmp +log rawmeasurements" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_sync || test_fail + +check_file_messages "20.*123\.1.* 111 111 1111" 75 80 measurements.log || test_fail +check_file_messages "20.*123\.1.* 111 001 0000" 37 39 measurements.log || test_fail +check_file_messages " 2 1 .* 4460 " 260 300 log.packets || test_fail +check_file_messages "." 6 6 ntskeys || test_fail +rm -f tmp/measurements.log + +client_conf+=" +ntsrefresh 120 +ntsdumpdir tmp" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_sync || test_fail + +check_file_messages "20.*123\.1.* 111 111 1111" 99 103 measurements.log || test_fail +check_file_messages "20.*123\.1.* 111 001 0000" 0 0 measurements.log || test_fail +check_file_messages " 2 1 .* 4460 " 350 390 log.packets || test_fail +check_file_messages "." 6 6 ntskeys || test_fail +check_file_messages "." 12 13 192.168.123.1.nts || test_fail +rm -f tmp/measurements.log + +export CLKNETSIM_START_DATE=$(date -d 'Jan 1 00:00:00 UTC 2010 + 40000 sec' +'%s') + +server_conf+=" +ntsrotate 100000" +client_conf+=" +ntsrefresh 39500" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_sync || test_fail + +check_file_messages "20.*123\.1.* 111 111 1111" 150 160 measurements.log || test_fail +check_file_messages "20.*123\.1.* 111 001 0000" 0 0 measurements.log || test_fail +check_file_messages " 2 1 .* 4460 " 6 10 log.packets || test_fail +check_file_messages "^9\.......e+03 2 1 .* 4460 " 6 10 log.packets || test_fail +check_file_messages "." 6 6 ntskeys || test_fail +check_file_messages "." 12 13 192.168.123.1.nts || test_fail +rm -f tmp/measurements.log + +client_conf=" +nosystemcert" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection && test_fail +check_sync && test_fail + +check_file_messages " 2 1 .* 123 " 0 0 log.packets || test_fail +check_file_messages " 2 1 .* 4460 " 10 20 log.packets || test_fail + +export CLKNETSIM_START_DATE=$(date -d 'Jan 2 00:00:01 UTC 2010' +'%s') + +client_conf=" +nosystemcert +ntstrustedcerts tmp/server.crt" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection && test_fail +check_sync && test_fail + +check_file_messages " 2 1 .* 123 " 0 0 log.packets || test_fail +check_file_messages " 2 1 .* 4460 " 10 20 log.packets || test_fail +check_log_messages "expired certificate" 4 4 || test_fail + +client_conf+=" +nocerttimecheck 1" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_sync || test_fail + +export CLKNETSIM_START_DATE=$(date -d 'Jan 1 00:00:00 UTC 2010' +'%s') + +server_conf=" +ntsserverkey tmp/server.key +ntsservercert tmp/server.crt +ntsprocesses 0 +ntsrotate 0 +ntsdumpdir tmp +ntsntpserver 192.168.123.2" +client_conf=" +nosystemcert +ntstrustedcerts tmp/server.crt +ntsrefresh 500" +client_server_conf="server node1.net1.clk $client_server_options" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection && test_fail +check_sync && test_fail + +check_file_messages " 2 1 .* 4460 " 50 100 log.packets || test_fail +check_file_messages " 2 2 .* 4460 " 0 0 log.packets || test_fail +check_log_messages "Source 192.168.123.1 changed to 192.168.123.2" 6 8 || test_fail +check_log_messages "Source 192.168.123.2 replaced with 192.168.123.1" 6 8 || test_fail + +servers=2 + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_sync || test_fail + +check_file_messages " 3 1 .* 4460 " 100 150 log.packets || test_fail +check_file_messages " 3 2 .* 4460 " 0 0 log.packets || test_fail +check_log_messages "Source 192.168.123.1 changed to 192.168.123.2" 1 1 || test_fail +check_log_messages "Source 192.168.123.2 replaced with 192.168.123.1" 0 0 || test_fail + +server_conf+=" +ntsratelimit interval 12 burst 1 leak 4" + +client_chronyd_options="-d -d" +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection && test_fail + +check_file_messages " 3 1 .* 4460 1 0 2" 25 50 log.packets || test_fail +check_file_messages " 3 2 .* 4460 " 0 0 log.packets || test_fail +check_log_messages "Source 192.168.123.1 changed to 192.168.123.2" 2 6 || test_fail +check_log_messages "Source 192.168.123.2 replaced with 192.168.123.1" 1 6 || test_fail + +test_pass diff --git a/test/simulation/140-noclientlog b/test/simulation/140-noclientlog new file mode 100755 index 0000000..c456647 --- /dev/null +++ b/test/simulation/140-noclientlog @@ -0,0 +1,21 @@ +#!/bin/bash + +. ./test.common +test_start "noclientlog option" + +server_conf="noclientlog" +client_server_options="xleave" +client_conf=" +logdir tmp +log rawmeasurements" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +check_file_messages "111 111 1111.* 4B " 30 200 measurements.log || test_fail +check_file_messages "111 111 1111.* 4I " 0 0 measurements.log || test_fail + +test_pass diff --git a/test/simulation/201-freqaccumulation b/test/simulation/201-freqaccumulation new file mode 100755 index 0000000..7a9c22c --- /dev/null +++ b/test/simulation/201-freqaccumulation @@ -0,0 +1,35 @@ +#!/bin/bash + +. ./test.common + +# Test fix in commit 60d0fa299307076143da94d36deb7b908fa9bdb7 + +test_start "frequency accumulation" + +time_offset=100.0 +jitter=1e-6 +base_delay=1e-6 +wander=0.0 + +limit=180 +time_max_limit=1e-5 +freq_max_limit=1e-7 +time_rms_limit=1e-5 +freq_rms_limit=1e-7 +min_sync_time=120 +max_sync_time=140 + +client_server_options="minpoll 6 maxpoll 6" +client_conf="driftfile tmp/drift +makestep 1 1" + +for freq_offset in -5e-2 -5e-4 5e-4 5e-2; do + for drift in -1e+4 -1e+2 1e+2 1e+4; do + echo "$drift 100000" > tmp/drift + run_test || test_fail + check_chronyd_exit || test_fail + check_sync || test_fail + done +done + +test_pass diff --git a/test/simulation/202-prefer b/test/simulation/202-prefer new file mode 100755 index 0000000..ae24848 --- /dev/null +++ b/test/simulation/202-prefer @@ -0,0 +1,21 @@ +#!/bin/bash + +. ./test.common + +# Test fix in commit 4253075a97141edfa62043ab71bd0673587e6629 + +test_start "prefer option" + +servers=3 +client_server_conf=" +server 192.168.123.1 +server 192.168.123.2 +server 192.168.123.3 prefer" + +run_test || test_fail +check_chronyd_exit || test_fail +check_source_selection || test_fail +check_packet_interval || test_fail +check_sync || test_fail + +test_pass diff --git a/test/simulation/README b/test/simulation/README new file mode 100644 index 0000000..e174500 --- /dev/null +++ b/test/simulation/README @@ -0,0 +1,11 @@ +This is a collection of simulation tests using the clknetsim simulator +(supported on Linux only). + +https://github.com/mlichvar/clknetsim + +The CLKNETSIM_PATH environment variable should point to the directory where +clknetsim was downloaded and compiled. If the variable is not set, the tests +will look for clknetsim in ./clknetsim in the current directory. + +The tests are written in bash and they can be run directly. The ./run script +runs all tests. diff --git a/test/simulation/run b/test/simulation/run new file mode 100755 index 0000000..463e8dd --- /dev/null +++ b/test/simulation/run @@ -0,0 +1,90 @@ +#!/bin/bash + +print_help() { + echo "$1 [-a] [-i ITERATIONS] [-m MAXFAILS] [-s SEED] [TEST]..." +} + +run_test() { + local result name=$1 seed=$2 + + CLKNETSIM_RANDOM_SEED=$seed ./$name + result=$? + + if [ $result -ne 0 -a $result -ne 9 ]; then + if [ $abort_on_fail -ne 0 ]; then + echo 1>&2 + echo Failed with random seed $seed 1>&2 + exit 1 + fi + failed_seeds=(${failed_seeds[@]} $seed) + fi + + return $result +} + +abort_on_fail=0 +iterations=1 +max_fails=0 +random_seed=${CLKNETSIM_RANDOM_SEED:-$RANDOM} + +while getopts ":ai:m:s:" opt; do + case $opt in + a) abort_on_fail=1;; + i) iterations=$OPTARG;; + m) max_fails=$OPTARG;; + s) random_seed=$OPTARG;; + *) print_help "$0"; exit 3;; + esac +done + +shift $[$OPTIND - 1] + +passed=() failed=() skipped=() failed_seeds=() + +[ $# -gt 0 ] && tests=($@) || tests=([0-9]*-*[^_]) + +for test in "${tests[@]}"; do + if [ $iterations -gt 1 ]; then + printf "%-30s" "$test" + fails=0 + for i in $(seq 1 $iterations); do + run_test $test $[$random_seed + $i - 1] > /dev/null + case $? in + 0) echo -n ".";; + 9) break;; + *) echo -n "x"; fails=$[$fails + 1];; + esac + done + if [ $i -lt $iterations ]; then + printf "%${iterations}s" "" + echo " SKIP" + result=9 + elif [ $fails -gt $max_fails ]; then + echo " FAIL" + result=1 + else + echo " PASS" + result=0 + fi + else + printf "%s " "$test" + run_test $test $random_seed + result=$? + echo + fi + + case $result in + 0) passed=(${passed[@]} $test);; + 9) skipped=(${skipped[@]} $test);; + *) failed=(${failed[@]} $test);; + esac +done + +echo +echo "SUMMARY:" +echo " TOTAL $[${#passed[@]} + ${#failed[@]} + ${#skipped[@]}]" +echo " PASSED ${#passed[@]}" +echo " FAILED ${#failed[@]} (${failed[@]}) (${failed_seeds[@]})" +echo " SKIPPED ${#skipped[@]} (${skipped[@]})" + +[ ${#failed[@]} -eq 0 ] diff --git a/test/simulation/test.common b/test/simulation/test.common new file mode 100644 index 0000000..9d85a5c --- /dev/null +++ b/test/simulation/test.common @@ -0,0 +1,516 @@ +# Copyright (C) 2013-2014 Miroslav Lichvar <mlichvar@redhat.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# 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, see <http://www.gnu.org/licenses/>. + +export LC_ALL=C +export PATH=../../:$PATH +export CLKNETSIM_PATH=${CLKNETSIM_PATH:-clknetsim} + +if [ ! -x $CLKNETSIM_PATH/clknetsim ]; then + echo "SKIP (clknetsim not found)" + exit 9 +fi + +. $CLKNETSIM_PATH/clknetsim.bash + +# Default test testings + +default_limit=10000 +default_time_offset=1e-1 +default_freq_offset=1e-4 +default_base_delay=1e-4 +default_jitter=1e-4 +default_jitter_asymmetry=0.0 +default_wander=1e-9 +default_refclock_jitter="" +default_refclock_offset=0.0 + +default_update_interval=0 +default_shift_pll=2 + +default_server_strata=1 +default_servers=1 +default_clients=1 +default_peers=0 +default_falsetickers=0 +default_server_start=0.0 +default_client_start=0.0 +default_chronyc_start=1000.0 +default_server_step="" +default_client_step="" + +default_client_server_conf="" +default_server_server_options="" +default_client_server_options="" +default_server_peer_options="" +default_server_lpeer_options="" +default_server_rpeer_options="" +default_client_peer_options="" +default_client_lpeer_options="" +default_client_rpeer_options="" +default_server_conf="" +default_client_conf="" +default_chronyc_conf="" +default_server_chronyd_options="" +default_client_chronyd_options="" +default_chronyc_options="" + +default_time_max_limit=1e-3 +default_freq_max_limit=5e-4 +default_time_rms_limit=3e-4 +default_freq_rms_limit=1e-5 +default_min_sync_time=120 +default_max_sync_time=210 + +default_client_min_mean_out_interval=0.0 +default_client_max_min_out_interval=inf + +default_dns=0 + +# Initialize test settings from their defaults +for defoptname in ${!default_*}; do + optname=${defoptname#default_} + [ -z "${!optname}" ] && declare "$optname"="${!defoptname}" +done + +test_start() { + rm -rf tmp/* + echo "Testing $@:" + + check_config_h 'FEAT_NTP 1' || test_skip +} + +test_pass() { + echo "PASS" + exit 0 +} + +test_fail() { + echo "FAIL" + exit 1 +} + +test_skip() { + echo "SKIP" + exit 9 +} + +test_ok() { + pad_line + echo -e "\tOK" + return 0 +} + +test_bad() { + pad_line + echo -e "\tBAD" + return 1 +} + +test_error() { + pad_line + echo -e "\tERROR" + return 1 +} + +msg_length=0 +pad_line() { + local line_length=56 + [ $msg_length -lt $line_length ] && \ + printf "%$[$line_length - $msg_length]s" "" + msg_length=0 +} + +# Print aligned message +test_message() { + local level=$1 eol=$2 + shift 2 + local msg="$*" + + while [ $level -gt 0 ]; do + echo -n " " + level=$[$level - 1] + msg_length=$[$msg_length + 2] + done + echo -n "$msg" + + msg_length=$[$msg_length + ${#msg}] + if [ $eol -ne 0 ]; then + echo + msg_length=0 + fi +} + +get_wander_expr() { + local scaled_wander + + scaled_wander=$(awk "BEGIN {print $wander / \ + sqrt($update_interval < 0 ? 2^-($update_interval) : 1)}") + + echo "(+ $freq_offset (sum (* $scaled_wander (normal))))" +} + + +get_delay_expr() { + local direction=$1 asym + + if [ $jitter_asymmetry == "0.0" ]; then + asym="" + elif [ $direction = "up" ]; then + asym=$(awk "BEGIN {print 1 - 2 * $jitter_asymmetry}") + elif [ $direction = "down" ]; then + asym=$(awk "BEGIN {print 1 + 2 * $jitter_asymmetry}") + fi + echo "(+ $base_delay (* $asym $jitter (exponential)))" +} + +get_refclock_expr() { + echo "(+ $refclock_offset (* $refclock_jitter (normal)))" +} + +get_chronyd_nodes() { + echo $[$servers * $server_strata + $clients] +} + +get_node_name() { + local index=$1 + + if [ $dns -ne 0 ]; then + echo "node$index.net1.clk" + else + echo "192.168.123.$index" + fi +} + +get_chronyd_conf() { + local i stratum=$1 peer=$2 + + if [ $stratum -eq 1 ]; then + echo "local stratum 1" + echo "$server_conf" + elif [ $stratum -le $server_strata ]; then + for i in $(seq 1 $servers); do + echo "server $(get_node_name $[$servers * ($stratum - 2) + $i]) $server_server_options" + done + for i in $(seq 1 $peers); do + [ $i -eq $peer -o $i -gt $servers ] && continue + echo -n "peer $(get_node_name $[$servers * ($stratum - 1) + $i]) $server_peer_options " + [ $i -lt $peer ] && echo "$server_lpeer_options" || echo "$server_rpeer_options" + done + echo "$server_conf" + else + echo "deny" + if [ -n "$client_server_conf" ]; then + echo "$client_server_conf" + else + for i in $(seq 1 $servers); do + echo "server $(get_node_name $[$servers * ($stratum - 2) + $i]) $client_server_options" + done + fi + for i in $(seq 1 $peers); do + [ $i -eq $peer -o $i -gt $clients ] && continue + echo -n "peer $(get_node_name $[$servers * ($stratum - 1) + $i]) $client_peer_options " + [ $i -lt $peer ] && echo "$client_lpeer_options" || echo "$client_rpeer_options" + done + echo "$client_conf" + fi +} + +# Check if chrony was built with specified option in config.h +check_config_h() { + local pattern=$1 + grep -q "^#define $pattern" ../../config.h +} + +# Check if the clock was well synchronized +check_sync() { + local i sync_time max_time_error max_freq_error ret=0 + local rms_time_error rms_freq_error + + test_message 2 1 "checking clock sync time, max/rms time/freq error:" + + for i in $(seq 1 $(get_chronyd_nodes)); do + [ $i -gt $[$servers * $server_strata] ] || continue + + sync_time=$(find_sync tmp/log.offset tmp/log.freq $i \ + $time_max_limit $freq_max_limit 1.0) + max_time_error=$(get_stat 'Maximum absolute offset' $i) + max_freq_error=$(get_stat 'Maximum absolute frequency' $i) + rms_time_error=$(get_stat 'RMS offset' $i) + rms_freq_error=$(get_stat 'RMS frequency' $i) + + test_message 3 0 "node $i: $sync_time $(printf '%.2e %.2e %.2e %.2e' \ + $max_time_error $max_freq_error $rms_time_error $rms_freq_error)" + + check_stat $sync_time $min_sync_time $max_sync_time && \ + check_stat $max_time_error 0.0 $time_max_limit && \ + check_stat $max_freq_error 0.0 $freq_max_limit && \ + check_stat $rms_time_error 0.0 $time_rms_limit && \ + check_stat $rms_freq_error 0.0 $freq_rms_limit && \ + test_ok || test_bad + + [ $? -eq 0 ] || ret=1 + done + + return $ret +} + +# Check if chronyd exited properly +check_chronyd_exit() { + local i ret=0 + + test_message 2 1 "checking chronyd exit:" + + for i in $(seq 1 $(get_chronyd_nodes)); do + test_message 3 0 "node $i:" + + grep -q 'chronyd exiting' tmp/log.$i && \ + ! grep -q 'Adjustment.*exceeds.*exiting' tmp/log.$i && \ + ! grep -q 'Assertion.*failed' tmp/log.$i && \ + test_ok || test_bad + [ $? -eq 0 ] || ret=1 + done + + return $ret +} + +# Check for problems in source selection +check_source_selection() { + local i ret=0 + + test_message 2 1 "checking source selection:" + + for i in $(seq $[$servers * $server_strata + 1] $(get_chronyd_nodes)); do + test_message 3 0 "node $i:" + + ! grep -q 'no majority\|no selectable sources' tmp/log.$i && \ + grep -q 'Selected source' tmp/log.$i && \ + test_ok || test_bad + [ $? -eq 0 ] || ret=1 + done + + return $ret +} + +# Check if incoming and outgoing packet intervals are sane +check_packet_interval() { + local i ret=0 mean_in_interval mean_out_interval min_in_interval min_out_interval + + test_message 2 1 "checking mean/min incoming/outgoing packet interval:" + + for i in $(seq 1 $(get_chronyd_nodes)); do + mean_in_interval=$(get_stat 'Mean incoming packet interval' $i) + mean_out_interval=$(get_stat 'Mean outgoing packet interval' $i) + min_in_interval=$(get_stat 'Minimum incoming packet interval' $i) + min_out_interval=$(get_stat 'Minimum outgoing packet interval' $i) + + test_message 3 0 "node $i: $(printf '%.2e %.2e %.2e %.2e' \ + $mean_in_interval $mean_out_interval $min_in_interval $min_out_interval)" + + # Check that the mean intervals are non-zero and shorter than + # limit, incoming is not longer than outgoing for stratum 1 + # servers, outgoing is not longer than incoming for clients, + # and the minimum outgoing interval is not shorter than the NTP + # sampling separation or iburst interval for clients + nodes=$[$servers * $server_strata + $clients] + check_stat $mean_in_interval 0.1 inf && \ + check_stat $mean_out_interval 0.1 inf && \ + ([ $i -gt $servers ] || \ + check_stat $mean_in_interval 0.0 $mean_out_interval 10*$jitter) && \ + ([ $i -le $[$servers * $server_strata] ] || \ + check_stat $mean_out_interval $client_min_mean_out_interval \ + $mean_in_interval 10*$jitter) && \ + ([ $i -le $[$servers * $server_strata] ] || \ + check_stat $min_out_interval \ + $([ $servers -gt 1 ] && echo 0.18 || echo 1.8) \ + $client_max_min_out_interval) && \ + test_ok || test_bad + + [ $? -eq 0 ] || ret=1 + done + + return $ret +} + +# Compare chronyc output with specified pattern +check_chronyc_output() { + local i ret=0 pattern=$1 + + test_message 2 1 "checking chronyc output:" + + for i in $(seq $[$(get_chronyd_nodes) + 1] $[$(get_chronyd_nodes) + $clients]); do + test_message 3 0 "node $i:" + + [[ "$(cat tmp/log.$i)" =~ $pattern ]] && \ + test_ok || test_bad + [ $? -eq 0 ] || ret=1 + done + + return $ret +} + +# Check the number of messages matching a pattern in the client logs +check_log_messages() { + local i count ret=0 pattern=$1 min=$2 max=$3 + + test_message 2 1 "checking number of messages \"$pattern\":" + + for i in $(seq $[$servers * $server_strata + 1] $(get_chronyd_nodes)); do + count=$(grep "$pattern" tmp/log.$i | wc -l) + test_message 3 0 "node $i: $count" + + [ "$min" -le "$count" ] && [ "$count" -le "$max" ] && \ + test_ok || test_bad + [ $? -eq 0 ] || ret=1 + done + + return $ret +} + +# Check the number of messages matching a pattern in a specified file +check_file_messages() { + local i count ret=0 pattern=$1 min=$2 max=$3 + shift 3 + + test_message 2 1 "checking number of messages \"$pattern\":" + + for i; do + count=$(grep "$pattern" tmp/$i | wc -l) + test_message 3 0 "$i: $count" + + [ "$min" -le "$count" ] && [ "$count" -le "$max" ] && \ + test_ok || test_bad + [ $? -eq 0 ] || ret=1 + done + + return $ret +} + +# Check if only NTP port (123) was used +check_packet_port() { + local i ret=0 port=123 + + test_message 2 1 "checking port numbers in packet log:" + + for i in $(seq 1 $(get_chronyd_nodes)); do + test_message 3 0 "node $i:" + + grep -E -q "^([0-9e.+-]+ ){5}$port " tmp/log.packets && \ + ! grep -E "^[0-9e.+-]+ $i " tmp/log.packets | \ + grep -E -q -v "^([0-9e.+-]+ ){5}$port " && \ + test_ok || test_bad + [ $? -eq 0 ] || ret=1 + done + + return $ret +} + +# Print test settings which differ from default value +print_nondefaults() { + local defoptname optname + + test_message 2 1 "non-default settings:" + for defoptname in ${!default_*}; do + optname=${defoptname#default_} + [ "${!defoptname}" = "${!optname}" ] || \ + test_message 3 1 $optname=${!optname} + done +} + +run_simulation() { + local nodes=$1 + + test_message 2 0 "running simulation:" + + start_server $nodes \ + -o tmp/log.offset -f tmp/log.freq -p tmp/log.packets \ + -R $(awk "BEGIN {print $update_interval < 0 ? 2^-($update_interval) : 1}") \ + -r $(awk "BEGIN {print $max_sync_time * 2^$update_interval}") \ + -l $(awk "BEGIN {print $limit * 2^$update_interval}") && test_ok || test_error +} + +run_test() { + local i j n stratum node nodes step start freq offset conf options + + test_message 1 1 "network with $servers*$server_strata servers and $clients clients:" + print_nondefaults + + nodes=$(get_chronyd_nodes) + [ -n "$chronyc_conf" ] && nodes=$[$nodes + $clients] + + for i in $(seq 1 $nodes); do + echo "node${i}_shift_pll = $shift_pll" + for j in $(seq 1 $nodes); do + echo "node${i}_delay${j} = $(get_delay_expr up)" + echo "node${j}_delay${i} = $(get_delay_expr down)" + done + done > tmp/conf + + node=1 + + for stratum in $(seq 1 $[$server_strata + 1]); do + [ $stratum -le $server_strata ] && n=$servers || n=$clients + + for i in $(seq 1 $n); do + test_message 2 0 "starting node $node:" + if [ $stratum -eq 1 ]; then + step=$server_step + start=$server_start + freq="" + [ $i -le $falsetickers ] && offset=$i.0 || offset=0.0 + options=$server_chronyd_options + elif [ $stratum -le $server_strata ]; then + step=$server_step + start=$server_start + freq=$(get_wander_expr) + offset=0.0 + options=$server_chronyd_options + else + step=$client_step + start=$client_start + freq=$(get_wander_expr) + offset=$time_offset + options=$client_chronyd_options + fi + + conf=$(get_chronyd_conf $stratum $i $n) + + [ -z "$freq" ] || echo "node${node}_freq = $freq" >> tmp/conf + [ -z "$step" ] || echo "node${node}_step = $step" >> tmp/conf + [ -z "$refclock_jitter" ] || \ + echo "node${node}_refclock = $(get_refclock_expr)" >> tmp/conf + echo "node${node}_offset = $offset" >> tmp/conf + echo "node${node}_start = $start" >> tmp/conf + start_client $node chronyd "$conf" "" "$options" && \ + test_ok || test_error + + [ $? -ne 0 ] && return 1 + node=$[$node + 1] + done + done + + for i in $(seq 1 $[$nodes - $node + 1]); do + test_message 2 0 "starting node $node:" + + echo "node${node}_start = $chronyc_start" >> tmp/conf + start_client $node chronyc "$chronyc_conf" "" \ + "$([ $dns -eq 0 ] && printf "%s" "-n") -h $(get_node_name $[$node - $clients]) $chronyc_options" && \ + test_ok || test_error + + [ $? -ne 0 ] && return 1 + node=$[$node + 1] + done + + run_simulation $nodes +} |