5 ### (c) 2024 Straylight/Edgeware
8 ###----- Licensing notice ---------------------------------------------------
10 ### This file is part of Xyla, a library of binary trees.
12 ### Xyla is free software: you can redistribute it and/or modify it under
13 ### the terms of the GNU Lesser General Public License as published by the
14 ### Free Software Foundation; either version 3 of the License, or (at your
15 ### option) any later version.
17 ### Xyla is distributed in the hope that it will be useful, but WITHOUT
18 ### ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 ### FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
20 ### License for more details.
22 ### You should have received a copy of the GNU Lesser General Public
23 ### License along with Xyla. If not, see <https://www.gnu.org/licenses/>.
25 m4_define([TESTINPUT_PATH], [$abs_top_srcdir/t])
26 m4_define([TESTPROG_PATH], [$abs_top_builddir/t])
27 m4_define([LTRUN], [$abs_top_builddir/libtool --mode=execute])
29 m4_define([_FOREACH], [dnl
30 m4_if([$#], [1], [_foreach_func($1)],
31 [_foreach_func($1)[]_FOREACH(m4_shift($@))])])
32 m4_define([FOREACH], [dnl
33 m4_pushdef([_foreach_func], [$2])dnl
35 m4_popdef([_foreach_func])])
39 m4_define([VALGRIND_DEFAULTS],
40 [--leak-check=full --show-leak-kinds=all dnl
41 --errors-for-leak-kinds=all --track-origins=yes --error-exitcode=3])
42 m4_define([DIRECT_NSTEPS], [1000000])
43 m4_define([VALGRIND_NSTEPS], [100000])
45 m4_define([TREES], [avl, rb, splay, treap])
46 m4_define([COMMON_TESTS], [commontest])
47 m4_define([avl_TESTS], [avltest, avlregress])
48 m4_define([rb_TESTS], [rbtest, rbregress])
49 m4_define([splay_TESTS], [splaytest])
50 m4_define([treap_TESTS], [treaptest])
52 ###--------------------------------------------------------------------------
55 AT_ARG_OPTION_ARG([xyla-launder],
56 [AS_HELP_STRING([--xyla-launder=FILTER],
57 [apply FILTER for test output])],
58 [AS_CASE([$at_optarg],
62 [filter="sed 's/@%:@0x@<:@0-9a-f@:>@*/@%:@0x......../g'"],
63 [AS_ECHO([unknown launder]) >&2; AS_EXIT([2])])],
66 AT_ARG_OPTION_ARG([xyla-runner],
67 [AS_HELP_STRING([--xyla-runner=WRAPPER],
68 [apply WRAPPER around test programs])],
69 [AS_CASE([$at_optarg],
71 [adverb= dflt_steps=DIRECT_NSTEPS],
73 [adverb="valgrind ${VALGRIND_OPTS-VALGRIND_DEFAULTS} \
74 --log-file=valgrind.out"
75 dflt_steps=VALGRIND_NSTEPS],
77 [adverb="valgrind ${VALGRIND_OPTS-VALGRIND_DEFAULTS} \
78 --vgdb=full --vgdb-error=1 --vgdb-shadow-registers=yes"
79 dflt_steps=VALGRIND_NSTEPS],
80 [AS_ECHO([unknown runner]) >&2; AS_EXIT([2])])],
81 [adverb= dflt_steps=DIRECT_NSTEPS])
83 AT_ARG_OPTION([xyla-setref],
84 [AS_HELP_STRING([--xyla-setref],
85 [set reference file from test output])])
87 AT_ARG_OPTION([xyla-soak],
88 [AS_HELP_STRING([--xyla-soak], [run soak tests])])
90 AT_ARG_OPTION_ARG([xyla-soak-seed],
91 [AS_HELP_STRING([--xyla-soak-seed=SEED],
92 [force soak-test seed])],
93 [soak_seed=$at_optarg],
96 AT_ARG_OPTION_ARG([xyla-soak-steps],
97 [AS_HELP_STRING([--xyla-soak-steps=NSTEPS],
98 [run NSTEPS soak steps])],
99 [soak_steps=$at_optarg],
102 ###--------------------------------------------------------------------------
103 m4_define([DEF_KAT1], [AT_SETUP([$1-$2])
105 AT_KEYWORDS([$1 $2 kat $1-$2])
107 cp TESTINPUT_PATH/$2.in in
108 AT_CHECK([LTRUN $adverb TESTPROG_PATH/$1test -oout in], [0], [], [])
109 if test -r TESTINPUT_PATH/$1-$2.ref; then
110 eval $filter <out >out.filtered
111 eval $filter <TESTINPUT_PATH/$1-$2.ref >ref.filtered
112 AT_CHECK([diff -u out.filtered ref.filtered], [0], [], [])
114 AS_CASE([$at_arg_xyla_setref],
115 [:], [cp out TESTINPUT_PATH/$1-$2.ref],
116 [AT_CHECK([echo missing ref file TESTINPUT_PATH/$1-$2.ref; AS_EXIT([99])])])
122 [FOREACH([COMMON_TESTS, $1_TESTS],
123 [DEF_KAT1([$1], ]DOL()1[)])])
125 ###--------------------------------------------------------------------------
126 ### Verify checking is working properly.
128 AT_SETUP([avl-check])
129 AT_KEYWORDS([avl avl-check])
130 AT_DATA([in], [= (_ -4 (_ =3 _)) !
132 XYLA_REDACT_ADDRESSES=t; export XYLA_REDACT_ADDRESSES
133 AT_CHECK([LTRUN TESTPROG_PATH/avltest in], [2],
135 @%:@0x00000001 (n = 2) (-) 4
136 @%:@0x00000000 (n = 1) (=) 3
138 [XYLA-BT @%:@<root @<:@ADDR@:>@> BUG: @%:@<node @%:@0x00000000 3> key not above lower bound
139 XYLA-AVL @%:@<root @<:@ADDR@:>@> BUG: @%:@<node @%:@0x00000001 4> incorrect balance annotation `-' /= left 0 - 1 right
140 BUG: check failed: tree structure invalid (input pos = 19)
145 AT_KEYWORDS([rb rb-check])
146 AT_DATA([in], [= ((_ 2 _) 4 (_ *3 _)) !
148 XYLA_REDACT_ADDRESSES=t; export XYLA_REDACT_ADDRESSES
149 AT_CHECK([LTRUN TESTPROG_PATH/rbtest in], [2],
151 @%:@0x00000000 (n = 1) ( ) 2
152 @%:@0x00000002 (n = 3) ( ) 4
153 @%:@0x00000001 (n = 1) (*) 3
155 [XYLA-RB @%:@<root @<:@ADDR@:>@> BUG: root @%:@<node @%:@0x00000002 4> is red
156 XYLA-RB @%:@<root @<:@ADDR@:>@> BUG: red @%:@<node @%:@0x00000000 2> has red parent @%:@<node @%:@0x00000002 4>
157 XYLA-BT @%:@<root @<:@ADDR@:>@> BUG: @%:@<node @%:@0x00000001 3> key not above lower bound
158 XYLA-RB @%:@<root @<:@ADDR@:>@> BUG: @%:@<node @%:@0x00000002 4> left black-height 0 /= 1 right black-height
159 BUG: check failed: tree structure invalid (input pos = 24)
163 AT_SETUP([splay-check])
164 AT_KEYWORDS([splay splay-check])
165 AT_DATA([in], [= (_ 4 (_ 3 _)) !
167 XYLA_REDACT_ADDRESSES=t; export XYLA_REDACT_ADDRESSES
168 AT_CHECK([LTRUN TESTPROG_PATH/splaytest in], [2],
170 @%:@0x00000001 (n = 2) (*) 4
171 @%:@0x00000000 (n = 1) (*) 3
173 [XYLA-BT @%:@<root @<:@ADDR@:>@> BUG: @%:@<node @%:@0x00000000 3> key not above lower bound
174 BUG: check failed: tree structure invalid (input pos = 17)
178 AT_SETUP([treap-check])
179 AT_KEYWORDS([treap treap-check])
180 AT_DATA([in], [= (_ 2$ 4 (_ 1$ 3 _)) !
182 XYLA_REDACT_ADDRESSES=t; export XYLA_REDACT_ADDRESSES
183 AT_CHECK([LTRUN TESTPROG_PATH/treaptest in], [2],
185 @%:@0x00000001 (n = 2) (*) 0x00000002$ 4
186 @%:@0x00000000 (n = 1) (*) 0x00000001$ 3
188 [XYLA-TREAP @%:@<root @<:@ADDR@:>@> BUG: @%:@<node @%:@0x00000000 0x00000001$ 3> weight 1 < 2 weight of parent @%:@<node @%:@0x00000001 0x00000002$ 4>
189 XYLA-BT @%:@<root @<:@ADDR@:>@> BUG: @%:@<node @%:@0x00000000 0x00000001$ 3> key not above lower bound
190 BUG: check failed: tree structure invalid (input pos = 23)
194 ###--------------------------------------------------------------------------
195 AT_SETUP([treap-bounds])
197 AT_KEYWORDS([treap treap-bounds])
199 ## A 64-bit host has space to cope with a treap with weight 538, following
200 ## the analysis in <xyla/treap.h>. So we'll blow the path structure if we
201 ## make a tree with height 539. The test program starts with a fixed seed to
202 ## make the tests reproducible, so we can `predict' the RNG output by just
204 AT_DATA([setup], [@%:@539 D
206 AT_CHECK([LTRUN $adverb TESTPROG_PATH/treaptest -oout setup], [0], [], [])
207 ## Extract the sequence of weights. Attach their initial ordering. Sort by
208 ## the weights, lightest first. Attach /this/ ordering too: those are going
209 ## to be the keys associated with each weight; since weights and keys both
210 ## increase monotonically, we'll end up with a vine. Restore the initial
211 ## ordering by sorting. Trim off everything other than the keys, and attach
212 ## the insertion command to each line. Finally, find the last node and
213 ## descend to one of its nil links.
214 sed '1d; s/^.*\(0x@<:@0-9a-f@:>@*\)\$.*$/\1/' out |
215 nl | sort -k2 | nl | sort -k2n |
216 sed 's/^.@<:@@<:@:space:@:>@@:>@*//; s/@<:@@<:@:space:@:>@@:>@.*$/+/; $a\
218 AT_CHECK([LTRUN $adverb TESTPROG_PATH/treaptest killme],
219 [ignore], [stdout], [stderr],
221 if test $rc -gt 128; then sig=$(kill -l $rc); else sig=nil; fi
225 *) echo "unexpected exit status $rc (sig = $sig)"; exit 1 ;;
231 ###--------------------------------------------------------------------------
232 m4_define([DEF_SOAK], [AT_SETUP([$1-soak])
234 AT_KEYWORDS([soak $1 $1-soak])
235 AT_SKIP_IF([test $at_arg_xyla_soak != :])
236 AT_SKIP_IF([test $PYTHON = :])
239 AS_CASE([$soak_steps], [nil], [soak_steps=$dflt_steps])
240 args=${args+$args }-n$soak_steps
241 AS_CASE([$soak_seed], [nil], [], [args="${args+$args }-s '$soak_seed'"])
242 AT_CHECK([$PYTHON TESTINPUT_PATH/soak $args dnl
243 LTRUN $adverb TESTPROG_PATH/$1test], [0], [], [])
247 FOREACH([TREES], [DEF_SOAK([$1])])
249 ###----- That's all, folks --------------------------------------------------