Add column info to all index script diagnostics
[xapian.git] / xapian-applications / omega / omegatest
blobabcadab1dcf09c1eb0e5a233015487485c591241
1 #!/bin/sh
2 # omegatest: Test omega CGI
4 # Copyright (C) 2015-2022 Olly Betts
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License as
8 # published by the Free Software Foundation; either version 2 of the
9 # License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19 # USA
20 set -e
22 : ${OMEGA=./omega}
23 : ${SCRIPTINDEX=./scriptindex}
24 : ${FAKETIME=faketime}
26 # Suppress HTTP Content-Type header.
27 SERVER_PROTOCOL=INCLUDED
28 export SERVER_PROTOCOL
30 # Don't complain about memory left allocated on exit - the OS will reclaim
31 # all memory at that point.
32 LSAN_OPTIONS=leak_check_at_exit=0
33 export LSAN_OPTIONS
35 # Set up an empty database.
36 TEST_DB=test-db
37 rm -rf "$TEST_DB"
38 echo 'inmemory' > "$TEST_DB"
40 # Simple template which just shows the parsed query.
41 TEST_TEMPLATE=test-template
42 printf '$querydescription' > "$TEST_TEMPLATE"
44 TEST_INDEXSCRIPT=test-indexscript
46 OMEGA_CONFIG_FILE=test-omega.conf
47 export OMEGA_CONFIG_FILE
48 cat > "$OMEGA_CONFIG_FILE" <<__END__
49 database_dir .
50 template_dir .
51 log_dir tmplog
52 default_template $TEST_TEMPLATE
53 default_db $TEST_DB
54 __END__
56 failed=0
58 testcase() {
59 expected=$1
60 shift
61 # If there are no positional parameters, pass one as otherwise omega will
62 # wait for parameters on stdin.
63 [ "$#" != 0 ] || { set x dummy; shift; }
65 if [ -n "$FAKE_NOW" ] ; then
66 if [ -n "${TZ+set}" ] ; then
67 output=`TZ=$TZ $FAKETIME -f "$FAKE_NOW" "$OMEGA" "$@"`
68 else
69 output=`$FAKETIME -f "$FAKE_NOW" "$OMEGA" "$@"`
71 else
72 output=`"$OMEGA" "$@"`
75 if [ "$output" != "$expected" ] ; then
76 echo "$OMEGA $@:"
77 printf '%s\n' " expected: «${expected}»"
78 printf '%s\n' " received: «${output}»"
79 failed=`expr $failed + 1`
83 qtestcase() {
84 expected="Query($1)"
85 shift
86 testcase "$expected" "$@"
89 # Test scriptindex gives expected error.
91 # Parameters:
92 # * what: text to report to describe situation
93 # * expect: expected glob pattern stdout+stderr should match
94 # * (optional) input: input to feed scriptindex; can contain \n, etc escapes
95 # (default: /dev/null)
97 # Uses database $TEST_DB and index script $TEST_INDEXSCRIPT.
98 test_scriptindex_error() {
99 what=$1
100 expect=$2
101 input=$3
102 rm -rf "$TEST_DB"
103 rc=0
104 case $input in
106 out=`$SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" < /dev/null 2>&1` || rc=$?
108 *%*)
109 # Escape any % by doubling.
110 input=`printf '%s' "$input"|sed 's/%/%%/g'`
111 out=`printf "$input"|$SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" 2>&1` || rc=$?
114 out=`printf "$input"|$SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" 2>&1` || rc=$?
116 esac
117 if [ $rc -eq 0 ] ; then
118 printf "scriptindex didn't exit with non-zero return code for %s"'\n' "$what"
119 printf 'Output: %s\n' "$out"
120 failed=`expr $failed + 1`
121 else
122 case $out in
123 $expect) ;; # OK
125 printf "scriptindex didn't give expected error for %s"'\n' "$what"
126 printf 'Expect: %s\n' "$expect"
127 printf 'Output: %s\n' "$out"
128 failed=`expr $failed + 1`
130 esac
134 # Test scriptindex gives expected warning.
136 # Parameters:
137 # * what: text to report to describe situation
138 # * expect: expected glob pattern stdout+stderr should match
139 # * (optional) input: input to feed scriptindex; can contain \n, etc escapes
140 # (default: /dev/null)
142 # Uses database $TEST_DB and index script $TEST_INDEXSCRIPT.
143 test_scriptindex_warning() {
144 what=$1
145 expect="$2
146 records (added, replaced, deleted) = (*, *, *)"
147 input=$3
148 rm -rf "$TEST_DB"
149 rc=0
150 case $input in
152 out=`$SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" < /dev/null 2>&1` || rc=$?
154 *%*)
155 # Escape any % by doubling.
156 input=`printf '%s' "$input"|sed 's/%/%%/g'`
157 out=`printf "$input"|$SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" 2>&1` || rc=$?
160 out=`printf "$input"|$SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" 2>&1` || rc=$?
162 esac
163 if [ $rc -ne 0 ] ; then
164 printf "scriptindex gave an error rather than the expected warning for %s"'\n' "$what"
165 printf 'Output: %s\n' "$out"
166 failed=`expr $failed + 1`
167 else
168 case $out in
169 $expect) ;; # OK
171 printf "scriptindex didn't give expected warning for %s"'\n' "$what"
172 printf 'Expect: %s\n' "$expect"
173 printf 'Output: %s\n' "$out"
174 failed=`expr $failed + 1`
176 esac
180 unset FAKE_NOW
182 # Test a few simple things.
183 qtestcase 'Zsimpl@1' P=simple
184 qtestcase '(chocolate@1 FILTER Tconfectionary/fudge)' P=Chocolate B=Tconfectionary/fudge
186 # Test date value ranges.
187 qtestcase 'VALUE_RANGE 0 2 ~' DATEVALUE=0 START=2000
188 qtestcase 'VALUE_RANGE 0 2 ~' DATEVALUE=0 START=200001
189 qtestcase 'VALUE_RANGE 0 2 ~' DATEVALUE=0 START=20000101
190 qtestcase 'VALUE_LE 1 1~' DATEVALUE=1 END=1999
191 qtestcase 'VALUE_LE 1 1~' DATEVALUE=1 END=199912
192 qtestcase 'VALUE_LE 1 1~' DATEVALUE=1 END=19991231
193 qtestcase 'VALUE_RANGE 2 201 ~' DATEVALUE=2 START=2010
194 qtestcase 'VALUE_RANGE 2 201 ~' DATEVALUE=2 START=201001
195 qtestcase 'VALUE_RANGE 2 201 ~' DATEVALUE=2 START=20100101
196 qtestcase 'VALUE_LE 3 198~' DATEVALUE=3 END=1989
197 qtestcase 'VALUE_LE 3 198~' DATEVALUE=3 END=198912
198 qtestcase 'VALUE_LE 3 198~' DATEVALUE=3 END=19891231
199 qtestcase 'VALUE_RANGE 4 1974 ~' DATEVALUE=4 START=1974
200 qtestcase 'VALUE_RANGE 4 1974 ~' DATEVALUE=4 START=197401
201 qtestcase 'VALUE_RANGE 4 1974 ~' DATEVALUE=4 START=19740101
202 qtestcase 'VALUE_LE 5 1974~' DATEVALUE=5 END=1974
203 qtestcase 'VALUE_LE 5 1974~' DATEVALUE=5 END=197412
204 qtestcase 'VALUE_LE 5 1974~' DATEVALUE=5 END=19741231
205 qtestcase 'VALUE_RANGE 6 20151 ~' DATEVALUE=6 START=201510
206 qtestcase 'VALUE_RANGE 6 20151 ~' DATEVALUE=6 START=20151001
207 qtestcase 'VALUE_LE 7 19870~' DATEVALUE=7 END=198709
208 qtestcase 'VALUE_LE 7 19870~' DATEVALUE=7 END=19870930
209 qtestcase 'VALUE_RANGE 8 201512 ~' DATEVALUE=8 START=201512
210 qtestcase 'VALUE_RANGE 8 201512 ~' DATEVALUE=8 START=20151201
211 qtestcase 'VALUE_LE 9 201511~' DATEVALUE=9 END=201511
212 qtestcase 'VALUE_LE 9 201511~' DATEVALUE=9 END=20151130
213 qtestcase 'VALUE_RANGE 10 2015021 ~' DATEVALUE=10 START=20150210
214 qtestcase 'VALUE_RANGE 10 2000022 ~' DATEVALUE=10 START=20000220
215 qtestcase 'VALUE_LE 11 19840401~' DATEVALUE=11 END=19840401
216 qtestcase 'VALUE_LE 11 19881128~' DATEVALUE=11 END=19881128
218 # Leap year tests:
219 qtestcase 'VALUE_LE 1 201502~' DATEVALUE=1 END=20150228
220 qtestcase 'VALUE_LE 1 198802~' DATEVALUE=1 END=19880229
221 qtestcase 'VALUE_LE 1 19880228~' DATEVALUE=1 END=19880228
222 qtestcase 'VALUE_LE 1 200002~' DATEVALUE=1 END=20000229
223 qtestcase 'VALUE_LE 1 20000228~' DATEVALUE=1 END=20000228
224 # FIXME: These two currently require 64-bit time_t:
225 #qtestcase 'VALUE_LE 1 190002~' DATEVALUE=1 END=19000228
226 #qtestcase 'VALUE_LE 1 210002~' DATEVALUE=1 END=21000228
228 # Month starts and ends:
229 qtestcase 'VALUE_RANGE 0 2015 201501~' DATEVALUE=0 START=20150101 END=20150131
230 qtestcase 'VALUE_RANGE 0 2015 20150130~' DATEVALUE=0 START=20150101 END=20150130
231 qtestcase 'VALUE_RANGE 0 201502 201502~' DATEVALUE=0 START=20150201 END=20150228
232 qtestcase 'VALUE_RANGE 0 201502 20150227~' DATEVALUE=0 START=20150201 END=20150227
233 qtestcase 'VALUE_RANGE 0 201503 201503~' DATEVALUE=0 START=20150301 END=20150331
234 qtestcase 'VALUE_RANGE 0 201503 20150330~' DATEVALUE=0 START=20150301 END=20150330
235 qtestcase 'VALUE_RANGE 0 201504 201504~' DATEVALUE=0 START=20150401 END=20150430
236 qtestcase 'VALUE_RANGE 0 201504 2015042~' DATEVALUE=0 START=20150401 END=20150429
237 qtestcase 'VALUE_RANGE 0 201505 201505~' DATEVALUE=0 START=20150501 END=20150531
238 qtestcase 'VALUE_RANGE 0 201505 20150530~' DATEVALUE=0 START=20150501 END=20150530
239 qtestcase 'VALUE_RANGE 0 201506 201506~' DATEVALUE=0 START=20150601 END=20150630
240 qtestcase 'VALUE_RANGE 0 201506 2015062~' DATEVALUE=0 START=20150601 END=20150629
241 qtestcase 'VALUE_RANGE 0 201507 201507~' DATEVALUE=0 START=20150701 END=20150731
242 qtestcase 'VALUE_RANGE 0 201507 20150730~' DATEVALUE=0 START=20150701 END=20150730
243 qtestcase 'VALUE_RANGE 0 201508 201508~' DATEVALUE=0 START=20150801 END=20150831
244 qtestcase 'VALUE_RANGE 0 201508 20150830~' DATEVALUE=0 START=20150801 END=20150830
245 qtestcase 'VALUE_RANGE 0 201509 20150~' DATEVALUE=0 START=20150901 END=20150930
246 qtestcase 'VALUE_RANGE 0 201509 2015092~' DATEVALUE=0 START=20150901 END=20150929
247 qtestcase 'VALUE_RANGE 0 20151 201510~' DATEVALUE=0 START=20151001 END=20151031
248 qtestcase 'VALUE_RANGE 0 20151 20151030~' DATEVALUE=0 START=20151001 END=20151030
249 qtestcase 'VALUE_RANGE 0 201511 201511~' DATEVALUE=0 START=20151101 END=20151130
250 qtestcase 'VALUE_RANGE 0 201511 2015112~' DATEVALUE=0 START=20151101 END=20151129
251 qtestcase 'VALUE_RANGE 0 201512 2015~' DATEVALUE=0 START=20151201 END=20151231
252 qtestcase 'VALUE_RANGE 0 201512 20151230~' DATEVALUE=0 START=20151201 END=20151230
254 # Forward spans:
255 qtestcase 'VALUE_RANGE 0 20151104 20151106~' DATEVALUE=0 START=20151104 SPAN=3
256 qtestcase 'VALUE_RANGE 0 20141104 20151103~' DATEVALUE=0 START=20141104 SPAN=365
258 # Backward spans:
259 qtestcase 'VALUE_RANGE 0 20151104 20151106~' DATEVALUE=0 END=20151106 SPAN=3
260 qtestcase 'VALUE_RANGE 0 20141104 20151103~' DATEVALUE=0 END=20151103 SPAN=365
262 # Check that if START, END and SPAN are all passed, START is ignored:
263 qtestcase 'VALUE_RANGE 0 20151104 20151106~' DATEVALUE=0 START=19700101 END=20151106 SPAN=3
265 # Test date value ranges using newer ".SLOT" parameters.
266 qtestcase 'VALUE_RANGE 0 2 ~' START.0=2000
267 qtestcase 'VALUE_RANGE 0 2 ~' START.0=200001
268 qtestcase 'VALUE_RANGE 0 2 ~' START.0=20000101
269 qtestcase 'VALUE_LE 1 1~' END.1=1999
270 qtestcase 'VALUE_LE 1 1~' END.1=199912
271 qtestcase 'VALUE_LE 1 1~' END.1=19991231
272 qtestcase 'VALUE_RANGE 2 201 ~' START.2=2010
273 qtestcase 'VALUE_RANGE 2 201 ~' START.2=201001
274 qtestcase 'VALUE_RANGE 2 201 ~' START.2=20100101
275 qtestcase 'VALUE_LE 3 198~' END.3=1989
276 qtestcase 'VALUE_LE 3 198~' END.3=198912
277 qtestcase 'VALUE_LE 3 198~' END.3=19891231
278 qtestcase 'VALUE_RANGE 4 1974 ~' START.4=1974
279 qtestcase 'VALUE_RANGE 4 1974 ~' START.4=197401
280 qtestcase 'VALUE_RANGE 4 1974 ~' START.4=19740101
281 qtestcase 'VALUE_LE 5 1974~' END.5=1974
282 qtestcase 'VALUE_LE 5 1974~' END.5=197412
283 qtestcase 'VALUE_LE 5 1974~' END.5=19741231
284 qtestcase 'VALUE_RANGE 6 20151 ~' START.6=201510
285 qtestcase 'VALUE_RANGE 6 20151 ~' START.6=20151001
286 qtestcase 'VALUE_LE 7 19870~' END.7=198709
287 qtestcase 'VALUE_LE 7 19870~' END.7=19870930
288 qtestcase 'VALUE_RANGE 8 201512 ~' START.8=201512
289 qtestcase 'VALUE_RANGE 8 201512 ~' START.8=20151201
290 qtestcase 'VALUE_LE 9 201511~' END.9=201511
291 qtestcase 'VALUE_LE 9 201511~' END.9=20151130
292 qtestcase 'VALUE_RANGE 10 2015021 ~' START.10=20150210
293 qtestcase 'VALUE_RANGE 10 2000022 ~' START.10=20000220
294 qtestcase 'VALUE_LE 11 19840401~' END.11=19840401
295 qtestcase 'VALUE_LE 11 19881128~' END.11=19881128
297 # Leap year tests:
298 qtestcase 'VALUE_LE 1 201502~' END.1=20150228
299 qtestcase 'VALUE_LE 1 198802~' END.1=19880229
300 qtestcase 'VALUE_LE 1 19880228~' END.1=19880228
301 qtestcase 'VALUE_LE 1 200002~' END.1=20000229
302 qtestcase 'VALUE_LE 1 20000228~' END.1=20000228
303 # FIXME: These two currently require 64-bit time_t:
304 #qtestcase 'VALUE_LE 1 190002~' END.1=19000228
305 #qtestcase 'VALUE_LE 1 210002~' END.1=21000228
307 # Month starts and ends:
308 qtestcase 'VALUE_RANGE 0 2015 201501~' START.0=20150101 END.0=20150131
309 qtestcase 'VALUE_RANGE 0 2015 20150130~' START.0=20150101 END.0=20150130
310 qtestcase 'VALUE_RANGE 0 201502 201502~' START.0=20150201 END.0=20150228
311 qtestcase 'VALUE_RANGE 0 201502 20150227~' START.0=20150201 END.0=20150227
312 qtestcase 'VALUE_RANGE 0 201503 201503~' START.0=20150301 END.0=20150331
313 qtestcase 'VALUE_RANGE 0 201503 20150330~' START.0=20150301 END.0=20150330
314 qtestcase 'VALUE_RANGE 0 201504 201504~' START.0=20150401 END.0=20150430
315 qtestcase 'VALUE_RANGE 0 201504 2015042~' START.0=20150401 END.0=20150429
316 qtestcase 'VALUE_RANGE 0 201505 201505~' START.0=20150501 END.0=20150531
317 qtestcase 'VALUE_RANGE 0 201505 20150530~' START.0=20150501 END.0=20150530
318 qtestcase 'VALUE_RANGE 0 201506 201506~' START.0=20150601 END.0=20150630
319 qtestcase 'VALUE_RANGE 0 201506 2015062~' START.0=20150601 END.0=20150629
320 qtestcase 'VALUE_RANGE 0 201507 201507~' START.0=20150701 END.0=20150731
321 qtestcase 'VALUE_RANGE 0 201507 20150730~' START.0=20150701 END.0=20150730
322 qtestcase 'VALUE_RANGE 0 201508 201508~' START.0=20150801 END.0=20150831
323 qtestcase 'VALUE_RANGE 0 201508 20150830~' START.0=20150801 END.0=20150830
324 qtestcase 'VALUE_RANGE 0 201509 20150~' START.0=20150901 END.0=20150930
325 qtestcase 'VALUE_RANGE 0 201509 2015092~' START.0=20150901 END.0=20150929
326 qtestcase 'VALUE_RANGE 0 20151 201510~' START.0=20151001 END.0=20151031
327 qtestcase 'VALUE_RANGE 0 20151 20151030~' START.0=20151001 END.0=20151030
328 qtestcase 'VALUE_RANGE 0 201511 201511~' START.0=20151101 END.0=20151130
329 qtestcase 'VALUE_RANGE 0 201511 2015112~' START.0=20151101 END.0=20151129
330 qtestcase 'VALUE_RANGE 0 201512 2015~' START.0=20151201 END.0=20151231
331 qtestcase 'VALUE_RANGE 0 201512 20151230~' START.0=20151201 END.0=20151230
333 # Forward spans:
334 qtestcase 'VALUE_RANGE 0 20151104 20151106~' START.0=20151104 SPAN.0=3
335 qtestcase 'VALUE_RANGE 0 20141104 20151103~' START.0=20141104 SPAN.0=365
337 # Backward spans:
338 qtestcase 'VALUE_RANGE 0 20151104 20151106~' END.0=20151106 SPAN.0=3
339 qtestcase 'VALUE_RANGE 0 20141104 20151103~' END.0=20151103 SPAN.0=365
341 # Empty spans:
342 qtestcase '' START.0=20180919 END.0=19991225
343 # Check that the empty span dominates other spans:
344 qtestcase '' START.0=20180919 END.0=19991225 START.1=20180901
345 # Check that the empty span dominates a filter term:
346 qtestcase '' START.0=20180919 END.0=19991225 B=Ktag
347 # Check that the empty span dominates a negated filter term:
348 qtestcase '' START.0=20180919 END.0=19991225 N=Kneg
349 # Check that the empty span dominates a term-based date range filter:
350 qtestcase '' START.0=20180919 END.0=19991225 START=20000101 END=20001231
352 # Check that if START, END and SPAN are all passed, START is ignored:
353 qtestcase 'VALUE_RANGE 0 20151104 20151106~' START.0=19700101 END.0=20151106 SPAN.0=3
355 # Check multiple .SLOT filters:
356 qtestcase '(VALUE_RANGE 0 201512 2015~ AND VALUE_LE 5 1974~)' START.0=20151201 END.0=20151231 END.5=1974
357 qtestcase '(VALUE_RANGE 0 201512 20151207~ AND VALUE_RANGE 5 19740102 1974~)' START.0=20151201 SPAN.0=7 END.5=1974 SPAN.5=364
359 # Check .SLOT and old-style value date range filter:
360 qtestcase '(VALUE_RANGE 0 201512 2015~ AND VALUE_LE 5 1974~)' START.0=20151201 END.0=20151231 DATEVALUE=5 END=1974
362 # Check .SLOT and old-style value date range filter on same slot.
363 # (We don't promise anything for this case, but it shouldn't crash).
364 qtestcase '(VALUE_RANGE 0 201512 2015~ AND VALUE_LE 0 1974~)' START.0=20151201 END.0=20151231 DATEVALUE=0 END=1974
366 # Tests of term-based date range filtering:
368 qtestcase '(Y1970 OR Y1971 OR Y1972 OR Y1973 OR Y1974 OR Y1975 OR Y1976 OR Y1977 OR Y1978 OR Y1979 OR Y1980 OR Y1981 OR Y1982 OR Y1983 OR Y1984 OR Y1985 OR Y1986 OR Y1987 OR Y1988 OR Y1989 OR Y1990 OR Y1991 OR Y1992 OR Y1993 OR Y1994 OR Y1995 OR Y1996 OR Y1997 OR Y1998 OR Y1999 OR Dlatest)' END=19991231
369 qtestcase '(Y1970 OR Y1971 OR Y1972 OR Y1973 OR Y1974 OR Y1975 OR Y1976 OR Y1977 OR Y1978 OR Y1979 OR Y1980 OR Y1981 OR Y1982 OR Y1983 OR Y1984 OR Y1985 OR Y1986 OR Y1987 OR Y1988 OR Y1989 OR Dlatest)' END=19891231
370 qtestcase '(Y1970 OR Y1971 OR Y1972 OR Y1973 OR Y1974 OR Dlatest)' END=19741231
371 qtestcase '(Y1970 OR Y1971 OR Y1972 OR Y1973 OR Y1974 OR Y1975 OR Y1976 OR Y1977 OR Y1978 OR Y1979 OR Y1980 OR Y1981 OR Y1982 OR Y1983 OR Y1984 OR Y1985 OR Y1986 OR M198701 OR M198702 OR M198703 OR M198704 OR M198705 OR M198706 OR M198707 OR M198708 OR M198709 OR Dlatest)' END=19870930
372 qtestcase '(Y1970 OR Y1971 OR Y1972 OR Y1973 OR Y1974 OR Y1975 OR Y1976 OR Y1977 OR Y1978 OR Y1979 OR Y1980 OR Y1981 OR Y1982 OR Y1983 OR Y1984 OR Y1985 OR Y1986 OR Y1987 OR Y1988 OR Y1989 OR Y1990 OR Y1991 OR Y1992 OR Y1993 OR Y1994 OR Y1995 OR Y1996 OR Y1997 OR Y1998 OR Y1999 OR Y2000 OR Y2001 OR Y2002 OR Y2003 OR Y2004 OR Y2005 OR Y2006 OR Y2007 OR Y2008 OR Y2009 OR Y2010 OR Y2011 OR Y2012 OR Y2013 OR Y2014 OR M201501 OR M201502 OR M201503 OR M201504 OR M201505 OR M201506 OR M201507 OR M201508 OR M201509 OR M201510 OR M201511 OR Dlatest)' END=20151130
373 qtestcase '(Y1970 OR Y1971 OR Y1972 OR Y1973 OR Y1974 OR Y1975 OR Y1976 OR Y1977 OR Y1978 OR Y1979 OR Y1980 OR Y1981 OR Y1982 OR Y1983 OR M198401 OR M198402 OR M198403 OR D19840401 OR Dlatest)' END=19840401
374 qtestcase '(Y1970 OR Y1971 OR Y1972 OR Y1973 OR Y1974 OR Y1975 OR Y1976 OR Y1977 OR Y1978 OR Y1979 OR Y1980 OR Y1981 OR Y1982 OR Y1983 OR Y1984 OR Y1985 OR Y1986 OR Y1987 OR M198801 OR M198802 OR M198803 OR M198804 OR M198805 OR M198806 OR M198807 OR M198808 OR M198809 OR M198810 OR D19881101 OR D19881102 OR D19881103 OR D19881104 OR D19881105 OR D19881106 OR D19881107 OR D19881108 OR D19881109 OR D19881110 OR D19881111 OR D19881112 OR D19881113 OR D19881114 OR D19881115 OR D19881116 OR D19881117 OR D19881118 OR D19881119 OR D19881120 OR D19881121 OR D19881122 OR D19881123 OR D19881124 OR D19881125 OR D19881126 OR D19881127 OR D19881128 OR Dlatest)' END=19881128
376 # Leap year tests:
377 qtestcase '(Y1970 OR Y1971 OR Y1972 OR Y1973 OR Y1974 OR Y1975 OR Y1976 OR Y1977 OR Y1978 OR Y1979 OR Y1980 OR Y1981 OR Y1982 OR Y1983 OR Y1984 OR Y1985 OR Y1986 OR Y1987 OR Y1988 OR Y1989 OR Y1990 OR Y1991 OR Y1992 OR Y1993 OR Y1994 OR Y1995 OR Y1996 OR Y1997 OR Y1998 OR Y1999 OR Y2000 OR Y2001 OR Y2002 OR Y2003 OR Y2004 OR Y2005 OR Y2006 OR Y2007 OR Y2008 OR Y2009 OR Y2010 OR Y2011 OR Y2012 OR Y2013 OR Y2014 OR M201501 OR M201502 OR Dlatest)' END=20150228
378 qtestcase '(Y1970 OR Y1971 OR Y1972 OR Y1973 OR Y1974 OR Y1975 OR Y1976 OR Y1977 OR Y1978 OR Y1979 OR Y1980 OR Y1981 OR Y1982 OR Y1983 OR Y1984 OR Y1985 OR Y1986 OR Y1987 OR M198801 OR M198802 OR Dlatest)' END=19880229
379 qtestcase '(Y1970 OR Y1971 OR Y1972 OR Y1973 OR Y1974 OR Y1975 OR Y1976 OR Y1977 OR Y1978 OR Y1979 OR Y1980 OR Y1981 OR Y1982 OR Y1983 OR Y1984 OR Y1985 OR Y1986 OR Y1987 OR M198801 OR D19880201 OR D19880202 OR D19880203 OR D19880204 OR D19880205 OR D19880206 OR D19880207 OR D19880208 OR D19880209 OR D19880210 OR D19880211 OR D19880212 OR D19880213 OR D19880214 OR D19880215 OR D19880216 OR D19880217 OR D19880218 OR D19880219 OR D19880220 OR D19880221 OR D19880222 OR D19880223 OR D19880224 OR D19880225 OR D19880226 OR D19880227 OR D19880228 OR Dlatest)' END=19880228
380 qtestcase '(Y1970 OR Y1971 OR Y1972 OR Y1973 OR Y1974 OR Y1975 OR Y1976 OR Y1977 OR Y1978 OR Y1979 OR Y1980 OR Y1981 OR Y1982 OR Y1983 OR Y1984 OR Y1985 OR Y1986 OR Y1987 OR Y1988 OR Y1989 OR Y1990 OR Y1991 OR Y1992 OR Y1993 OR Y1994 OR Y1995 OR Y1996 OR Y1997 OR Y1998 OR Y1999 OR M200001 OR M200002 OR Dlatest)' END=20000229
381 qtestcase '(Y1970 OR Y1971 OR Y1972 OR Y1973 OR Y1974 OR Y1975 OR Y1976 OR Y1977 OR Y1978 OR Y1979 OR Y1980 OR Y1981 OR Y1982 OR Y1983 OR Y1984 OR Y1985 OR Y1986 OR Y1987 OR Y1988 OR Y1989 OR Y1990 OR Y1991 OR Y1992 OR Y1993 OR Y1994 OR Y1995 OR Y1996 OR Y1997 OR Y1998 OR Y1999 OR M200001 OR D20000201 OR D20000202 OR D20000203 OR D20000204 OR D20000205 OR D20000206 OR D20000207 OR D20000208 OR D20000209 OR D20000210 OR D20000211 OR D20000212 OR D20000213 OR D20000214 OR D20000215 OR D20000216 OR D20000217 OR D20000218 OR D20000219 OR D20000220 OR D20000221 OR D20000222 OR D20000223 OR D20000224 OR D20000225 OR D20000226 OR D20000227 OR D20000228 OR Dlatest)' END=20000228
382 # FIXME: These two currently require 64-bit time_t:
383 #qtestcase 'Dlatest' END=19000228 # Assumed start is 19700101
384 #qtestcase '(Y1970 OR Y1971 OR Y1972 OR Y1973 OR Y1974 OR Y1975 OR Y1976 OR Y1977 OR Y1978 OR Y1979 OR Y1980 OR Y1981 OR Y1982 OR Y1983 OR Y1984 OR Y1985 OR Y1986 OR Y1987 OR Y1988 OR Y1989 OR Y1990 OR Y1991 OR Y1992 OR Y1993 OR Y1994 OR Y1995 OR Y1996 OR Y1997 OR Y1998 OR Y1999 OR Y2000 OR Y2001 OR Y2002 OR Y2003 OR Y2004 OR Y2005 OR Y2006 OR Y2007 OR Y2008 OR Y2009 OR Y2010 OR Y2011 OR Y2012 OR Y2013 OR Y2014 OR Y2015 OR Y2016 OR Y2017 OR Y2018 OR Y2019 OR Y2020 OR Y2021 OR Y2022 OR Y2023 OR Y2024 OR Y2025 OR Y2026 OR Y2027 OR Y2028 OR Y2029 OR Y2030 OR Y2031 OR Y2032 OR Y2033 OR Y2034 OR Y2035 OR Y2036 OR Y2037 OR Y2038 OR Y2039 OR Y2040 OR Y2041 OR Y2042 OR Y2043 OR Y2044 OR Y2045 OR Y2046 OR Y2047 OR Y2048 OR Y2049 OR Y2050 OR Y2051 OR Y2052 OR Y2053 OR Y2054 OR Y2055 OR Y2056 OR Y2057 OR Y2058 OR Y2059 OR Y2060 OR Y2061 OR Y2062 OR Y2063 OR Y2064 OR Y2065 OR Y2066 OR Y2067 OR Y2068 OR Y2069 OR Y2070 OR Y2071 OR Y2072 OR Y2073 OR Y2074 OR Y2075 OR Y2076 OR Y2077 OR Y2078 OR Y2079 OR Y2080 OR Y2081 OR Y2082 OR Y2083 OR Y2084 OR Y2085 OR Y2086 OR Y2087 OR Y2088 OR Y2089 OR Y2090 OR Y2091 OR Y2092 OR Y2093 OR Y2094 OR Y2095 OR Y2096 OR Y2097 OR Y2098 OR Y2099 OR M210001 OR M210002 OR Dlatest)' END=21000228
386 # Month starts and ends:
387 qtestcase '(M201501 OR Dlatest)' START=20150101 END=20150131
388 qtestcase '(D20150101 OR D20150102 OR D20150103 OR D20150104 OR D20150105 OR D20150106 OR D20150107 OR D20150108 OR D20150109 OR D20150110 OR D20150111 OR D20150112 OR D20150113 OR D20150114 OR D20150115 OR D20150116 OR D20150117 OR D20150118 OR D20150119 OR D20150120 OR D20150121 OR D20150122 OR D20150123 OR D20150124 OR D20150125 OR D20150126 OR D20150127 OR D20150128 OR D20150129 OR D20150130 OR Dlatest)' START=20150101 END=20150130
389 qtestcase '(M201502 OR Dlatest)' START=20150201 END=20150228
390 qtestcase '(D20150201 OR D20150202 OR D20150203 OR D20150204 OR D20150205 OR D20150206 OR D20150207 OR D20150208 OR D20150209 OR D20150210 OR D20150211 OR D20150212 OR D20150213 OR D20150214 OR D20150215 OR D20150216 OR D20150217 OR D20150218 OR D20150219 OR D20150220 OR D20150221 OR D20150222 OR D20150223 OR D20150224 OR D20150225 OR D20150226 OR D20150227 OR Dlatest)' START=20150201 END=20150227
391 qtestcase '(M201503 OR Dlatest)' START=20150301 END=20150331
392 qtestcase '(D20150301 OR D20150302 OR D20150303 OR D20150304 OR D20150305 OR D20150306 OR D20150307 OR D20150308 OR D20150309 OR D20150310 OR D20150311 OR D20150312 OR D20150313 OR D20150314 OR D20150315 OR D20150316 OR D20150317 OR D20150318 OR D20150319 OR D20150320 OR D20150321 OR D20150322 OR D20150323 OR D20150324 OR D20150325 OR D20150326 OR D20150327 OR D20150328 OR D20150329 OR D20150330 OR Dlatest)' START=20150301 END=20150330
393 qtestcase '(M201504 OR Dlatest)' START=20150401 END=20150430
394 qtestcase '(D20150401 OR D20150402 OR D20150403 OR D20150404 OR D20150405 OR D20150406 OR D20150407 OR D20150408 OR D20150409 OR D20150410 OR D20150411 OR D20150412 OR D20150413 OR D20150414 OR D20150415 OR D20150416 OR D20150417 OR D20150418 OR D20150419 OR D20150420 OR D20150421 OR D20150422 OR D20150423 OR D20150424 OR D20150425 OR D20150426 OR D20150427 OR D20150428 OR D20150429 OR Dlatest)' START=20150401 END=20150429
395 qtestcase '(M201505 OR Dlatest)' START=20150501 END=20150531
396 qtestcase '(D20150501 OR D20150502 OR D20150503 OR D20150504 OR D20150505 OR D20150506 OR D20150507 OR D20150508 OR D20150509 OR D20150510 OR D20150511 OR D20150512 OR D20150513 OR D20150514 OR D20150515 OR D20150516 OR D20150517 OR D20150518 OR D20150519 OR D20150520 OR D20150521 OR D20150522 OR D20150523 OR D20150524 OR D20150525 OR D20150526 OR D20150527 OR D20150528 OR D20150529 OR D20150530 OR Dlatest)' START=20150501 END=20150530
397 qtestcase '(M201506 OR Dlatest)' START=20150601 END=20150630
398 qtestcase '(D20150601 OR D20150602 OR D20150603 OR D20150604 OR D20150605 OR D20150606 OR D20150607 OR D20150608 OR D20150609 OR D20150610 OR D20150611 OR D20150612 OR D20150613 OR D20150614 OR D20150615 OR D20150616 OR D20150617 OR D20150618 OR D20150619 OR D20150620 OR D20150621 OR D20150622 OR D20150623 OR D20150624 OR D20150625 OR D20150626 OR D20150627 OR D20150628 OR D20150629 OR Dlatest)' START=20150601 END=20150629
399 qtestcase '(M201507 OR Dlatest)' START=20150701 END=20150731
400 qtestcase '(D20150701 OR D20150702 OR D20150703 OR D20150704 OR D20150705 OR D20150706 OR D20150707 OR D20150708 OR D20150709 OR D20150710 OR D20150711 OR D20150712 OR D20150713 OR D20150714 OR D20150715 OR D20150716 OR D20150717 OR D20150718 OR D20150719 OR D20150720 OR D20150721 OR D20150722 OR D20150723 OR D20150724 OR D20150725 OR D20150726 OR D20150727 OR D20150728 OR D20150729 OR D20150730 OR Dlatest)' START=20150701 END=20150730
401 qtestcase '(M201508 OR Dlatest)' START=20150801 END=20150831
402 qtestcase '(D20150801 OR D20150802 OR D20150803 OR D20150804 OR D20150805 OR D20150806 OR D20150807 OR D20150808 OR D20150809 OR D20150810 OR D20150811 OR D20150812 OR D20150813 OR D20150814 OR D20150815 OR D20150816 OR D20150817 OR D20150818 OR D20150819 OR D20150820 OR D20150821 OR D20150822 OR D20150823 OR D20150824 OR D20150825 OR D20150826 OR D20150827 OR D20150828 OR D20150829 OR D20150830 OR Dlatest)' START=20150801 END=20150830
403 qtestcase '(M201509 OR Dlatest)' START=20150901 END=20150930
404 qtestcase '(D20150901 OR D20150902 OR D20150903 OR D20150904 OR D20150905 OR D20150906 OR D20150907 OR D20150908 OR D20150909 OR D20150910 OR D20150911 OR D20150912 OR D20150913 OR D20150914 OR D20150915 OR D20150916 OR D20150917 OR D20150918 OR D20150919 OR D20150920 OR D20150921 OR D20150922 OR D20150923 OR D20150924 OR D20150925 OR D20150926 OR D20150927 OR D20150928 OR D20150929 OR Dlatest)' START=20150901 END=20150929
405 qtestcase '(M201510 OR Dlatest)' START=20151001 END=20151031
406 qtestcase '(D20151001 OR D20151002 OR D20151003 OR D20151004 OR D20151005 OR D20151006 OR D20151007 OR D20151008 OR D20151009 OR D20151010 OR D20151011 OR D20151012 OR D20151013 OR D20151014 OR D20151015 OR D20151016 OR D20151017 OR D20151018 OR D20151019 OR D20151020 OR D20151021 OR D20151022 OR D20151023 OR D20151024 OR D20151025 OR D20151026 OR D20151027 OR D20151028 OR D20151029 OR D20151030 OR Dlatest)' START=20151001 END=20151030
407 qtestcase '(M201511 OR Dlatest)' START=20151101 END=20151130
408 qtestcase '(D20151101 OR D20151102 OR D20151103 OR D20151104 OR D20151105 OR D20151106 OR D20151107 OR D20151108 OR D20151109 OR D20151110 OR D20151111 OR D20151112 OR D20151113 OR D20151114 OR D20151115 OR D20151116 OR D20151117 OR D20151118 OR D20151119 OR D20151120 OR D20151121 OR D20151122 OR D20151123 OR D20151124 OR D20151125 OR D20151126 OR D20151127 OR D20151128 OR D20151129 OR Dlatest)' START=20151101 END=20151129
409 qtestcase '(M201512 OR Dlatest)' START=20151201 END=20151231
410 qtestcase '(D20151201 OR D20151202 OR D20151203 OR D20151204 OR D20151205 OR D20151206 OR D20151207 OR D20151208 OR D20151209 OR D20151210 OR D20151211 OR D20151212 OR D20151213 OR D20151214 OR D20151215 OR D20151216 OR D20151217 OR D20151218 OR D20151219 OR D20151220 OR D20151221 OR D20151222 OR D20151223 OR D20151224 OR D20151225 OR D20151226 OR D20151227 OR D20151228 OR D20151229 OR D20151230 OR Dlatest)' START=20151201 END=20151230
412 # Forward spans:
413 qtestcase '(D20151104 OR D20151105 OR D20151106 OR D20151107 OR Dlatest)' START=20151104 SPAN=3
414 qtestcase '(D20141104 OR D20141105 OR D20141106 OR D20141107 OR D20141108 OR D20141109 OR D20141110 OR D20141111 OR D20141112 OR D20141113 OR D20141114 OR D20141115 OR D20141116 OR D20141117 OR D20141118 OR D20141119 OR D20141120 OR D20141121 OR D20141122 OR D20141123 OR D20141124 OR D20141125 OR D20141126 OR D20141127 OR D20141128 OR D20141129 OR D20141130 OR M201412 OR M201501 OR M201502 OR M201503 OR M201504 OR M201505 OR M201506 OR M201507 OR M201508 OR M201509 OR M201510 OR D20151101 OR D20151102 OR D20151103 OR D20151104 OR Dlatest)' START=20141104 SPAN=365
416 # Backward spans:
417 qtestcase '(D20151103 OR D20151104 OR D20151105 OR D20151106 OR Dlatest)' END=20151106 SPAN=3
418 qtestcase '(D20141103 OR D20141104 OR D20141105 OR D20141106 OR D20141107 OR D20141108 OR D20141109 OR D20141110 OR D20141111 OR D20141112 OR D20141113 OR D20141114 OR D20141115 OR D20141116 OR D20141117 OR D20141118 OR D20141119 OR D20141120 OR D20141121 OR D20141122 OR D20141123 OR D20141124 OR D20141125 OR D20141126 OR D20141127 OR D20141128 OR D20141129 OR D20141130 OR M201412 OR M201501 OR M201502 OR M201503 OR M201504 OR M201505 OR M201506 OR M201507 OR M201508 OR M201509 OR M201510 OR D20151101 OR D20151102 OR D20151103 OR Dlatest)' END=20151103 SPAN=365
420 # Check that if START, END and SPAN are all passed, START is ignored:
421 qtestcase '(D20151103 OR D20151104 OR D20151105 OR D20151106 OR Dlatest)' START=19700101 END=20151106 SPAN=3
423 # Check that YYYYMM and YYYY are accepted and handled appropriately:
424 qtestcase '(Y1980 OR Y1981 OR Dlatest)' START=1980 END=1981
425 qtestcase '(M198012 OR M198101 OR M198102 OR Dlatest)' START=198012 END=198102
427 # Check .SLOT combined with term based date range filter:
428 qtestcase '(VALUE_RANGE 0 201512 2015~ AND (Y1970 OR Y1971 OR Y1972 OR Y1973 OR Y1974 OR Dlatest))' START.0=20151201 END.0=20151231 END=19741231
430 # Check combining of filter terms:
431 qtestcase '(Horg AND Len)' B=Len B=Horg
432 qtestcase '(Len OR Lde)' B=Len B=Lde
433 qtestcase '((Horg OR Hcom) AND (Len OR Lfr))' B=Len B=Lfr B=Horg B=Hcom
435 # Check combining of filter terms with filter_op set:
436 printf '$setmap{nonexclusiveprefix,L,1,XAND,1}$setmap{boolprefix,lang,L,and,XAND,host,H,year,Y}$querydescription' > "$TEST_TEMPLATE"
437 qtestcase 'Len' B=Len
438 qtestcase '0 * Len' P=lang:en
439 qtestcase 'XANDtest' B=XANDtest
440 qtestcase '0 * XANDtest' P=and:test
441 qtestcase '(Len AND XANDtest)' B=Len B=XANDtest
442 qtestcase '0 * (Len AND XANDtest)' P='lang:en and:test'
443 qtestcase '(Len AND Lde)' B=Len B=Lde
444 qtestcase '0 * (Len AND Lde)' P='lang:en lang:de'
445 qtestcase '((Horg OR Hcom) AND (Len AND Lfr))' B=Len B=Lfr B=Horg B=Hcom
446 qtestcase '0 * ((Len AND Lfr) AND (Horg OR Hcom))' P='lang:en lang:fr host:org host:com'
447 qtestcase '((XANDa AND XANDb AND XANDc) AND (Y1998 OR Y2001))' B=Y1998 B=Y2001 B=XANDa B=XANDb B=XANDc
448 qtestcase '0 * ((XANDa AND XANDb AND XANDc) AND (Y1998 OR Y2001))' P='year:1998 year:2001 and:a and:b and:c'
450 # Check combining of filters around CGI parameter 'N':
451 qtestcase '(Ztruth@1 AND_NOT Epdf)' P=truth N=Epdf
452 qtestcase '(Ztruth@1 AND_NOT (Ehtm OR Epdf))' P=truth N=Epdf N=Ehtm
453 qtestcase '(Ztruth@1 AND_NOT (Ehtm OR Epdf OR Lde OR Lfr))' P=truth N=Lfr N=Epdf N=Ehtm N=Lde
454 qtestcase '((Ztruth@1 FILTER (Lfr AND Lzh)) AND_NOT (Lde OR Len))' P=truth N=Lde N=Len B=Lfr B=Lzh
455 qtestcase '((Ztruth@1 FILTER Lfr) AND_NOT (Ehtm OR Epdf))' P=truth N=Epdf N=Ehtm B=Lfr
456 qtestcase '(<alldocuments> AND_NOT (Len OR Lfr))' N=Lfr N=Len
457 qtestcase '(VALUE_RANGE 0 2015 201501~ AND_NOT Len)' DATEVALUE=0 START=20150101 END=20150131 N=Len
459 # If faketime is available and works, test cases where the output depends on
460 # "now".
461 rc=0
462 out=`[ -n "$FAKETIME" ] && $FAKETIME -f '1980-12-08 00:00:00' date +%Y 2>&1` || rc=$?
463 if [ "$rc:$out" = "0:1980" ] ; then
464 FAKE_NOW='2015-11-28 06:07:08'
465 TZ=UTC qtestcase 'VALUE_RANGE 0 20151127060709 20151128060708' DATEVALUE=0 SPAN=1
467 # Tests of term-based date range filtering:
468 qtestcase '(Y2000 OR Y2001 OR Y2002 OR Y2003 OR Y2004 OR Y2005 OR Y2006 OR Y2007 OR Y2008 OR Y2009 OR Y2010 OR Y2011 OR Y2012 OR Y2013 OR Y2014 OR M201501 OR M201502 OR M201503 OR M201504 OR M201505 OR M201506 OR M201507 OR M201508 OR M201509 OR M201510 OR D20151101 OR D20151102 OR D20151103 OR D20151104 OR D20151105 OR D20151106 OR D20151107 OR D20151108 OR D20151109 OR D20151110 OR D20151111 OR D20151112 OR D20151113 OR D20151114 OR D20151115 OR D20151116 OR D20151117 OR D20151118 OR D20151119 OR D20151120 OR D20151121 OR D20151122 OR D20151123 OR D20151124 OR D20151125 OR D20151126 OR D20151127 OR D20151128 OR Dlatest)' START=20000101
469 qtestcase '(Y2010 OR Y2011 OR Y2012 OR Y2013 OR Y2014 OR M201501 OR M201502 OR M201503 OR M201504 OR M201505 OR M201506 OR M201507 OR M201508 OR M201509 OR M201510 OR D20151101 OR D20151102 OR D20151103 OR D20151104 OR D20151105 OR D20151106 OR D20151107 OR D20151108 OR D20151109 OR D20151110 OR D20151111 OR D20151112 OR D20151113 OR D20151114 OR D20151115 OR D20151116 OR D20151117 OR D20151118 OR D20151119 OR D20151120 OR D20151121 OR D20151122 OR D20151123 OR D20151124 OR D20151125 OR D20151126 OR D20151127 OR D20151128 OR Dlatest)' START=20100101
470 qtestcase '(Y1974 OR Y1975 OR Y1976 OR Y1977 OR Y1978 OR Y1979 OR Y1980 OR Y1981 OR Y1982 OR Y1983 OR Y1984 OR Y1985 OR Y1986 OR Y1987 OR Y1988 OR Y1989 OR Y1990 OR Y1991 OR Y1992 OR Y1993 OR Y1994 OR Y1995 OR Y1996 OR Y1997 OR Y1998 OR Y1999 OR Y2000 OR Y2001 OR Y2002 OR Y2003 OR Y2004 OR Y2005 OR Y2006 OR Y2007 OR Y2008 OR Y2009 OR Y2010 OR Y2011 OR Y2012 OR Y2013 OR Y2014 OR M201501 OR M201502 OR M201503 OR M201504 OR M201505 OR M201506 OR M201507 OR M201508 OR M201509 OR M201510 OR D20151101 OR D20151102 OR D20151103 OR D20151104 OR D20151105 OR D20151106 OR D20151107 OR D20151108 OR D20151109 OR D20151110 OR D20151111 OR D20151112 OR D20151113 OR D20151114 OR D20151115 OR D20151116 OR D20151117 OR D20151118 OR D20151119 OR D20151120 OR D20151121 OR D20151122 OR D20151123 OR D20151124 OR D20151125 OR D20151126 OR D20151127 OR D20151128 OR Dlatest)' START=19740101
471 qtestcase '(M201510 OR D20151101 OR D20151102 OR D20151103 OR D20151104 OR D20151105 OR D20151106 OR D20151107 OR D20151108 OR D20151109 OR D20151110 OR D20151111 OR D20151112 OR D20151113 OR D20151114 OR D20151115 OR D20151116 OR D20151117 OR D20151118 OR D20151119 OR D20151120 OR D20151121 OR D20151122 OR D20151123 OR D20151124 OR D20151125 OR D20151126 OR D20151127 OR D20151128 OR Dlatest)' START=20151001
472 # Date range with start after end:
473 qtestcase 'Dlatest' START=201512
474 qtestcase 'Dlatest' START=20151201
475 qtestcase '(D20150210 OR D20150211 OR D20150212 OR D20150213 OR D20150214 OR D20150215 OR D20150216 OR D20150217 OR D20150218 OR D20150219 OR D20150220 OR D20150221 OR D20150222 OR D20150223 OR D20150224 OR D20150225 OR D20150226 OR D20150227 OR D20150228 OR M201503 OR M201504 OR M201505 OR M201506 OR M201507 OR M201508 OR M201509 OR M201510 OR D20151101 OR D20151102 OR D20151103 OR D20151104 OR D20151105 OR D20151106 OR D20151107 OR D20151108 OR D20151109 OR D20151110 OR D20151111 OR D20151112 OR D20151113 OR D20151114 OR D20151115 OR D20151116 OR D20151117 OR D20151118 OR D20151119 OR D20151120 OR D20151121 OR D20151122 OR D20151123 OR D20151124 OR D20151125 OR D20151126 OR D20151127 OR D20151128 OR Dlatest)' START=20150210
476 qtestcase '(D20000220 OR D20000221 OR D20000222 OR D20000223 OR D20000224 OR D20000225 OR D20000226 OR D20000227 OR D20000228 OR D20000229 OR M200003 OR M200004 OR M200005 OR M200006 OR M200007 OR M200008 OR M200009 OR M200010 OR M200011 OR M200012 OR Y2001 OR Y2002 OR Y2003 OR Y2004 OR Y2005 OR Y2006 OR Y2007 OR Y2008 OR Y2009 OR Y2010 OR Y2011 OR Y2012 OR Y2013 OR Y2014 OR M201501 OR M201502 OR M201503 OR M201504 OR M201505 OR M201506 OR M201507 OR M201508 OR M201509 OR M201510 OR D20151101 OR D20151102 OR D20151103 OR D20151104 OR D20151105 OR D20151106 OR D20151107 OR D20151108 OR D20151109 OR D20151110 OR D20151111 OR D20151112 OR D20151113 OR D20151114 OR D20151115 OR D20151116 OR D20151117 OR D20151118 OR D20151119 OR D20151120 OR D20151121 OR D20151122 OR D20151123 OR D20151124 OR D20151125 OR D20151126 OR D20151127 OR D20151128 OR Dlatest)' START=20000220
477 unset FAKE_NOW
478 else
479 if [ "$rc" = 127 ] ; then
480 echo "Skipping testcases which need 'faketime' tool installed"
481 elif [ -z "$FAKETIME" ] ; then
482 echo "Skipping testcases which need 'faketime' tool - \$FAKETIME is empty"
483 else
484 echo "Skipping testcases which need 'faketime' tool - it's installed but doesn't work"
488 # Check clamping of out of range dates:
489 printf '%s\n' 'DATE : field valuepacked=0' > "$TEST_INDEXSCRIPT"
490 rm -rf "$TEST_DB"
491 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
492 DATE=0
494 DATE=1617069804
496 qtestcase 'VALUE_LE 0 V\x84o\xff' START.0=10010101 END.0=20151230
497 qtestcase 'VALUE_RANGE 0 V\x83\x1e\x80 \xff\xff\xff\xff' START.0=20151230 END.0=21060301
498 qtestcase 'VALUE_LE 0 \xff\xff\xff\xff' START.0=19691230 END.0=21060301
500 # Test stem_all and stem_strategy.
501 printf '$if{$cgi{stem_all},$set{stem_all,$cgi{stem_all}}}$if{$cgi{stem_strategy},$set{stem_strategy,$cgi{stem_strategy}}}$querydescription' > "$TEST_TEMPLATE"
502 qtestcase '(capitalised@1 AND tests@2 AND Zstem@3)' P='Capitalised "tests" stemmed'
503 qtestcase '(nearing@1 NEAR 11 distances@2)' P='nearing NEAR distances'
504 qtestcase '(capitalis@1 AND test@2 AND stem@3)' P='Capitalised "tests" stemmed' stem_all=true
505 qtestcase '(near@1 NEAR 11 distanc@2)' P='nearing NEAR distances' stem_all=true
506 qtestcase '(capitalis@1 AND test@2 AND stem@3)' P='Capitalised "tests" stemmed' stem_strategy=all
507 qtestcase '(near@1 NEAR 11 distanc@2)' P='nearing NEAR distances' stem_strategy=all
508 qtestcase '(Zcapitalis@1 AND Ztest@2 AND Zstem@3)' P='Capitalised "tests" stemmed' stem_strategy=all_z
509 qtestcase '(Znear@1 NEAR 11 Zdistanc@2)' P='nearing NEAR distances' stem_strategy=all_z
510 qtestcase '(capitalised@1 AND tests@2 AND stemmed@3)' P='Capitalised "tests" stemmed' stem_strategy=none
511 qtestcase '(nearing@1 NEAR 11 distances@2)' P='nearing NEAR distances' stem_strategy=none
512 qtestcase '(capitalised@1 AND tests@2 AND Zstem@3)' P='Capitalised "tests" stemmed' stem_strategy=some
513 qtestcase '(nearing@1 NEAR 11 distances@2)' P='nearing NEAR distances' stem_strategy=some
514 qtestcase '(capitalised@1 AND tests@2 AND Zstem@3)' P='Capitalised "tests" stemmed' stem_strategy=some_full_pos
515 qtestcase '(Znear@1 NEAR 11 Zdistanc@2)' P='nearing NEAR distances' stem_strategy=some_full_pos
516 qtestcase '(capitalised@1 AND tests@2 AND Zstem@3)' P='Capitalised "tests" stemmed' stem_strategy=some stem_all=true
517 qtestcase '(nearing@1 NEAR 11 distances@2)' P='nearing NEAR distances' stem_strategy=some stem_all=true
519 # Feature tests for $contains.
520 printf '$contains{$cgi{a},$cgi{b}}' > "$TEST_TEMPLATE"
521 testcase '6' P=text a=fish b="Hello fish"
522 testcase '' P=text a="Example" b="random"
524 NEWLINE='
527 # Feature tests for boolprefix and prefix maps.
528 printf '$set{stemmer,}$setmap{boolprefix,lang,L,host,H}$setmap{prefix,,XDEFAULT}$querydescription' > "$TEST_TEMPLATE"
529 qtestcase '((XDEFAULTfoo@1 AND XDEFAULTbar@2) FILTER (Hexample.org AND Lzh))' P='host:example.org foo bar lang:zh'
531 # Feature tests for $addfilter.
532 printf '$addfilter{Hexample.org}$addfilter{Hexample.com,}$addfilter{XFOObar,B}$querydescription' > "$TEST_TEMPLATE"
533 qtestcase '((Hexample.org OR Hexample.com) AND XFOObar)' P=
534 printf '$addfilter{Hexample.org}$addfilter{Hexample.com,N}$addfilter{Hexample.net,N}$querydescription' > "$TEST_TEMPLATE"
535 qtestcase '(Hexample.org AND_NOT (Hexample.com OR Hexample.net))' P=
537 # Feature tests for $if.
538 printf '$if{$set{w,1}}$if{a,$set{x,1}}$if{b,$set{y,1},$set{y,2}}$if{,$set{x,0}}$if{,$set{z,2},$set{z,1}}$opt{w}$opt{x}$opt{y}$opt{z}' > "$TEST_TEMPLATE"
539 testcase '1111'
541 # Feature tests for $cond.
542 printf '$cond{$cgi{one},1,$cgi{two},2,$cgi{three},3}' > "$TEST_TEMPLATE"
543 testcase '1' one=true
544 testcase '2' two=true
545 testcase '3' three=true
546 testcase '' nothing=true
547 testcase '1' one=true two=true three=true
548 testcase '2' two=true three=true
549 printf '$cond{$cgi{one},1,$cgi{two},2,$cgi{alt}}' > "$TEST_TEMPLATE"
550 testcase '1' one=true
551 testcase '2' two=true
552 testcase 'none' alt=none
553 # Check evaluation is lazy.
554 printf '$cond{$cgi{one},$seterror{err1},$cgi{two},2,$cgi{alt}}$error' > "$TEST_TEMPLATE"
555 testcase 'err1' one=true
556 testcase '2' two=true
557 testcase 'none' alt=none
558 printf '$cond{$cgi{one},1,$cgi{two},$seterror{err2},$cgi{alt}}$error' > "$TEST_TEMPLATE"
559 testcase '1' one=true
560 testcase 'err2' two=true
561 testcase 'none' alt=none
562 printf '$cond{$cgi{one},1,$cgi{two},2,$seterror{erralt}}$error' > "$TEST_TEMPLATE"
563 testcase '1' one=true
564 testcase '2' two=true
565 testcase 'erralt' alt=none
567 # Feature tests for $switch.
568 printf '$switch{$cgi{x},1,one,2,two}' > "$TEST_TEMPLATE"
569 testcase 'one' x=1
570 testcase 'two' x=2
571 testcase '' x=3
572 printf '$switch{$cgi{x},1,one,2,two,default}' > "$TEST_TEMPLATE"
573 testcase 'one' x=1
574 testcase 'two' x=2
575 testcase 'default' x=3
576 # Check evaluation is lazy.
577 printf '$switch{$cgi{x},1,$seterror{err1},2,two}$error' > "$TEST_TEMPLATE"
578 testcase 'err1' x=1
579 testcase 'two' x=2
580 testcase '' x=3
581 printf '$switch{$cgi{x},1,one,2,$seterror{err2},default}$error' > "$TEST_TEMPLATE"
582 testcase 'one' x=1
583 testcase 'err2' x=2
584 testcase 'default' x=3
585 printf '$switch{$cgi{x},1,one,2,two,$seterror{errdefault}}$error' > "$TEST_TEMPLATE"
586 testcase 'one' x=1
587 testcase 'two' x=2
588 testcase 'errdefault' x=3
590 # Feature tests for $include.
591 # Test inclusion works and evaluates the included file.
592 printf '$set{c,$add{$or{$opt{c},0},1}}$opt{c},$if{$lt{$opt{c},10},$include{'"$TEST_TEMPLATE"'}}X' > "$TEST_TEMPLATE"
593 testcase '1,2,3,4,5,6,7,8,9,10,XXXXXXXXXX'
594 # Test fallback action when trying to $include a file which doesn't exist or
595 # with a prohibited name.
596 printf '$include{$cgi{template},foo$set{data,bar}}-$opt{data}' > "$TEST_TEMPLATE"
597 testcase 'foo-bar' template=non_existent.template
598 testcase 'foo-bar' template=../secret/file
599 # Test exception is thrown when there's no fallback action when trying to
600 # $include a file which doesn't exist or with a prohibited name.
601 printf '$include{$cgi{template}}-$opt{data}' > "$TEST_TEMPLATE"
602 testcase "Exception: Couldn't read format template 'non_existent.template' (No such file or directory)" template=non_existent.template
603 testcase "Exception: Couldn't read format template '../secret/file' (name contains '..')" template=../secret/file
605 # Feature tests for $foreach.
606 printf '$foreach{$split{.,$cgi{a}},$chr{$add{$_,64}}}' > "$TEST_TEMPLATE"
607 testcase 'OMEGA' a=15.13.5.7.1
608 # Check that the outer $_ is restored after the inner $foreach.
609 printf '$foreach{$split{.,$cgi{a}},$foreach{$split{.,$cgi{$_}},$chr{$add{$_,64}}}$_}' > "$TEST_TEMPLATE"
610 testcase 'OMbEGcAd' a=b.c.d b=15.13 c=5.7 d=1
612 # Feature tests for $map.
613 printf '$list{$map{$split{-,$cgi{a}},$list{$map{$split{,$cgi{b}},$_},-}},|}' > "$TEST_TEMPLATE"
614 testcase '1-2-3|1-2-3' P=text a=ab-cd b=123
615 printf '$list{$map{$split{-,$cgi{a}},$set{__,$_}$list{$map{$split{,$cgi{b}},$opt{__}$_},-}},|}' > "$TEST_TEMPLATE"
616 testcase 'a1-a2-a3|b1-b2-b3' P=text a=a-b b=123
617 printf '$list{$map{$split{-,$cgi{a}},$list{$map{$split{$_,$cgi{b}},$_},-}},|}' > "$TEST_TEMPLATE"
618 testcase '1-2,3|1:2-3' P=text a=':-,' b='1:2,3'
619 # Check that the outer $_ is restored after the inner $map.
620 printf '$list{$map{$split{-,$cgi{a}},$list{$map{$split{,$cgi{b}},$_},-}$_},|}' > "$TEST_TEMPLATE"
621 testcase '1-2-3a|1-2-3b' P=text a='a-b' b='123'
623 # Feature tests for $match.
624 printf '$match{$cgi{a},$cgi{b},$cgi{c}}' > "$TEST_TEMPLATE"
625 testcase 'true' P=text a="ab*c+" b="ac"
626 testcase '' P=text a="acb" b="abc"
627 testcase 'true' P=text a="[A-Z]bcD" b="abcd" c="i"
628 testcase '' P=text a="[A-Z]bcD" b="abcd"
629 testcase 'true' P=text a="^abc$" b="${NEWLINE}abc${NEWLINE}def" c="m"
630 testcase '' P=text a="^abc$" b="${NEWLINE}abc${NEWLINE}def"
631 testcase 'true' P=text a="abc." b="abc${NEWLINE}" c="s"
632 testcase '' P=text a="abc." b="abc${NEWLINE}"
633 testcase 'true' P=text a=" ABC #test_comment " b="ABC" c="x"
634 testcase '' P=text a=" ABC #test_comment " b="ABC"
636 # Feature tests for $sort.
637 printf '$list{$sort{$split{|,$cgi{input}}},|}' > "$TEST_TEMPLATE"
638 testcase 'pineapple' input="pineapple"
639 testcase 'apple|banana|coconut' input="coconut|banana|apple"
640 testcase '1|b|b|c' input="b|c|b|1"
641 printf '$list{$sort{$split{|,$cgi{input}},$cgi{opt}},|}' > "$TEST_TEMPLATE"
642 testcase 'pineapple' input="pineapple" opt=
643 testcase 'pineapple' input="pineapple" opt=r
644 testcase 'pineapple' input="pineapple" opt=ru
645 testcase '1|b|c' input="b|c|b|1" opt=u
646 testcase 'c|b|b|1' input="b|c|b|1" opt=r
647 testcase 'c|b|1' input="b|c|b|1" opt=ur
648 testcase '-2|-.01|+99.99|+999|.0|0.0|.1|1|2|3|3.0|3.01|12|23|30' input='+999|2|1|12|23|3|30|3.01|3.0|.1|.0|0.0|-2|-.01|+99.99' opt=n
649 testcase '-2|-.01|+999|.1|1|2|3|3.01|12|23|30' input='+999|2|1|12|23|3|30|3.01|3.0|.1|.0|0.0|-2|-.01|+99.99' opt=nu
650 testcase '-2|-.01|+99.99|.1|1|2|3.0|3.01|12|23|30' input='+99.99|-.01|-2|0.0|.0|.1|3.0|3.01|30|3|23|12|1|2|+999' opt=nu
651 testcase '30|23|12|3.01|3.0|3|2|1|.1|0.0|.0|+999|+99.99|-.01|-2' input='+999|2|1|12|23|3|30|3.01|3.0|.1|.0|0.0|-2|-.01|+99.99' opt=nr
652 testcase '30|23|12|3.01|3|2|1|.1|+999|-.01|-2' input='+999|2|1|12|23|3|30|3.01|3.0|.1|.0|0.0|-2|-.01|+99.99' opt=nur
653 testcase '30|23|12|3.01|3.0|2|1|.1|+99.99|-.01|-2' input='+99.99|-.01|-2|0.0|.0|.1|3.0|3.01|30|3|23|12|1|2|+999' opt=nur
654 testcase 't 42|t 42:|t 42:1|t 42:09|t 42:9|t 42:11|t 42~' input='t 42:1|t 42|t 42:11|t 42:9|t 42~|t 42:|t 42:09' opt='#'
655 testcase 'A7R1:2|A7R2:6|A7R2:9|A7R2:11|A7R2:19|A7R2:47A|A7R11:1|AA|R7:1.09|R7:4A|R7:6|R7:7A|R7:404|R7:444-10|R7:1521' \
656 input='A7R1:2|R7:1521|AA|R7:4A|R7:7A|A7R2:9|R7:444-10|A7R2:6|R7:1.09|A7R2:47A|A7R11:1|R7:6|A7R2:11|R7:404|A7R2:19' \
657 opt='#'
658 testcase '30|23|12|3|03|2|1|01|0|00' input='2|1|23|12|23|3|30|0|00|0|01|03' opt='#ru'
659 testcase 'Exception: Unknown $sort option: x' input="b|c|b|1" opt=urx
660 testcase 'Exception: Invalid $sort option combination: n#' input="b|c" opt='n#'
661 testcase 'Exception: Invalid $sort option combination: #rn' input="b|1" opt='#rn'
663 # Regression test to test suppression of Content-Type header for early
664 # exception.
665 rm -rf "$TEST_DB"
666 echo 'inmemory' > "$TEST_DB"
667 testcase 'Exception: DocNotFoundError: Docid 1 not found' MORELIKE=1
669 # Regression test for $sort bug fixed in 1.4.12.
670 # Check $sort doesn't ensure_match (or ensure_query).
671 printf '$sort{test} $addfilter{Test}$querydescription' > "$TEST_TEMPLATE"
672 testcase 'test Query(Test)'
674 # Feature tests for $keys.
675 printf '$setmap{x,bee,1,eel,6,dog,4,ant,2,fox,5,cat,3}/$list{$keys{x},|}/$keys{nosuch}/' > "$TEST_TEMPLATE"
676 testcase '/ant|bee|cat|dog|eel|fox//'
678 # Feature tests for $terms.
679 printf 'text : index\nhost : boolean=H\nfoo : boolean=XFOO' > "$TEST_INDEXSCRIPT"
680 rm -rf "$TEST_DB"
681 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
682 text=This is some text.
683 host=example.org
684 foo=bar
686 printf '$hitlist{$list{$if{$eq{$cgi{prefix},null},$terms,$terms{$cgi{prefix}}},|}}' > "$TEST_TEMPLATE"
687 testcase 'Ztext' P=text B=Hexample.org B=Hexample.com prefix=null
688 testcase 'Hexample.org|Ztext' P=text B=Hexample.org B=Hexample.com prefix=
689 testcase 'Hexample.org' P=text B=Hexample.org B=Hexample.com prefix=H
690 testcase 'Ztext' P=text B=Hexample.org B=Hexample.com prefix=Z
691 testcase '' P=text B=Hexample.org B=Hexample.com prefix=E
693 printf '$msizelower $msize $msizeupper $msizeexact' > "$TEST_TEMPLATE"
694 testcase '1 1 1 true' P=this
695 testcase '1 1 1 true' P='Some text'
696 testcase '0 0 0 true' P=potato
698 printf '$set{weighting,coord}$hitlist{$weight.}' > "$TEST_TEMPLATE"
699 testcase '' P=aardvark
700 testcase '1.000000.' P=texting
701 testcase '' P='texting while driving'
702 testcase '' P='texting while driving' DEFAULTOP=AND
703 testcase '1.000000.' P='texting while driving' DEFAULTOP=OR
704 testcase '2.000000.' P='Some text'
705 # "this" and "is" are stopwords.
706 testcase '2.000000.' P='This is some text'
707 testcase '4.000000.' P='"This" "is" some text'
708 testcase '4.000000.' P='+This +is some text'
709 testcase '4.000000.' P='"This is some text"'
711 printf '$set{weightingpurefilter,coord}$hitlist{$weight.}' > "$TEST_TEMPLATE"
712 testcase '' B=XFOOfoo
713 testcase '1.000000.' B=Hexample.org
714 testcase '' B=Hexample.org B=XFOOfoo
715 testcase '1.000000.' B=Hexample.org B=Hexample.net
716 testcase '2.000000.' B=Hexample.org B=XFOObar
717 testcase '3.000000.' B=Hexample.org B=XFOObar B=XFOObar
719 printf '$filters' > "$TEST_TEMPLATE"
720 testcase 'Hexample.net~Hexample.org~.~~' B=Hexample.org B=Hexample.net
721 testcase '!Gmisc.test~.~~' N=Gmisc.test
722 testcase 'Hexample.net~Hexample.org~!Gmisc.test~.~~' B=Hexample.org B=Hexample.net N=Gmisc.test
723 testcase '.20040612~~~1~' DATEVALUE=1 START=20040612
724 testcase '.20040612~~~1~2' DATEVALUE=1 START=20040612 COLLAPSE=2
725 testcase '.20040612~~30~2' START=20040612 SPAN=30 COLLAPSE=2
726 testcase '.20040612~20160412~' START=20040612 END=20160412
727 testcase '.~~~2' COLLAPSE=2
728 testcase '.~~'
729 testcase '.~~1' SORT=1
730 testcase '.~~1f' SORT=+1
731 testcase '.~~1' SORT=-1
732 testcase '.~~1-2+3-27' SORT=+1-2+03,-27
733 testcase '.~~' SORTREVERSE=1
734 testcase '.~~1f' SORT=1 SORTREVERSE=1
735 testcase '.~~1' SORT=+1 SORTREVERSE=1
736 testcase '.~~1f' SORT=-1 SORTREVERSE=1
737 testcase '.~~1-2+3-27f' SORT=+1-2+03,-27 SORTREVERSE=1
738 testcase '.~~' SORTAFTER=1
739 testcase '.~~1R' SORT=1 SORTAFTER=1
740 testcase '.~~1F' SORT=+1 SORTAFTER=1
741 testcase '.~~1R' SORT=-1 SORTAFTER=1
742 testcase '.~~1-2+3-27R' SORT=+1-2+03,-27 SORTAFTER=1
743 testcase '.~~' SORTREVERSE=1 SORTAFTER=1
744 testcase '.~~1F' SORT=1 SORTREVERSE=1 SORTAFTER=1
745 testcase '.~~1R' SORT=+1 SORTREVERSE=1 SORTAFTER=1
746 testcase '.~~1F' SORT=-1 SORTREVERSE=1 SORTAFTER=1
747 testcase '.~~1-2+3-27F' SORT=+1-2+03,-27 SORTREVERSE=1 SORTAFTER=1
748 testcase '.~~X' DOCIDORDER=A # Buggy, but kept for compatibility.
749 testcase '.~~D' DOCIDORDER=D
750 testcase '.~~' DOCIDORDER=X # Buggy, but kept for compatibility.
751 testcase '.~~' DOCIDORDER=x # Buggy, but kept for compatibility.
753 tab=`printf '\t'`
754 printf '$cgi{AZ}|$cgi{AZ B}|$cgi{AZ.x}|$cgi{AZ.y}|$cgi{[}|$cgi{#}' > "$TEST_TEMPLATE"
755 testcase 'AZ|||||' AZ.x=3 AZ.y=4
756 testcase 'B|||||' 'AZ B.x=5' 'AZ B.y=12'
757 testcase 'B|||||' "AZ${tab}B.x=5" "AZ${tab}B.y=12"
758 testcase '||||2 ]|' '[ 2 ].x=123'
759 testcase '||||2 ]|' "[${tab}2 ].x=123"
760 testcase "||||2${tab}]|" "[ 2${tab}].x=123"
761 testcase "||||2${tab}]|" "[${tab}2${tab}].x=123"
762 testcase '|||||12' '12.x=37'
763 testcase 'DE|||||' 'AZ BC=DE'
764 testcase 'DE|||||' 'AZ B C=DE'
765 testcase 'DE|||||' "AZ${tab}BC=DE"
766 testcase 'DE|||||' "AZ B${tab}C=DE"
767 testcase 'DE|||||' "AZ${tab}B C=DE"
768 testcase 'DE|||||' "AZ${tab}B${tab}C=DE"
770 printf '$cgi{Search}|$cgi{Type}|$cgi{Search Type}' > "$TEST_TEMPLATE"
771 testcase 'Discover-List||' 'Search Type=Discover-List'
773 printf '$cgiparams' > "$TEST_TEMPLATE"
774 # We can't test the "no cgi parameters" case via testcase, as it passes a
775 # "dummy" parameter if there aren't any real ones.
776 #testcase ""
777 testcase "" =1
778 testcase "ABC" ABC=1
779 testcase "ABC" ABC=1 ABC=2
780 testcase "A${tab}AZ${tab}Z" A=1 A=2 A=3 AZ=1 AZ=2 Z=xxx
781 testcase "${tab}abc" =1 abc=1
782 testcase "${tab}abc${tab}def" =1 abc=1 def=7
784 # Feature tests for $highlight{}.
785 printf '$highlight{$cgi{text},$cgi{list}}' > "$TEST_TEMPLATE"
786 testcase 'A <b style="color:black;background-color:#ffff66">list</b> of <b style="color:black;background-color:#99ff99">words</b>' list="list${tab}words" text="A list of words"
788 printf '$highlight{$cgi{text},$cgi{list},$cgi{open}}' > "$TEST_TEMPLATE"
789 testcase 'A list of <b>words</b>' list="words" text="A list of words" open="<b>"
790 testcase 'A list of <span>words</span>' list="words" text="A list of words" open="<span>"
792 printf '$highlight{$cgi{text},$cgi{list},$cgi{open},$cgi{close}}' > "$TEST_TEMPLATE"
793 testcase 'A list of <b>words</b>' list="words" text="A list of words" open="<b>" close="</b>"
794 testcase 'A *list* of *words*' list="words${tab}list" text="A list of words" open="*" close="*"
796 # Test setting seterror and mset size, should not run the query after setting error.
797 printf '$if{$cgi{ERR},$seterror{$cgi{ERR}}}$msize$if{$error,!$error!}' > "$TEST_TEMPLATE"
798 testcase '1' P=text
799 testcase '0!boo!' P=text ERR=boo
801 # Test arguments inside seterror are evaluated
802 printf '$set{error,sample error}$seterror{$opt{error}}$msize$if{$error,!$error!}' > "$TEST_TEMPLATE"
803 testcase '0!sample error!' P=text
805 # Test error message doesn't get sent through HTML entity encoding.
806 printf '$seterror{{ "error": true, "error_message": "Parameter cannot be > 9" }}$if{$error,$error}' > "$TEST_TEMPLATE"
807 testcase '{ "error": true, "error_message": "Parameter cannot be > 9" }' P=text
809 # Test msize when error set after running query, should not affect running of query.
810 printf '$last$if{$cgi{ERR},$seterror{$cgi{ERR}}}$msize$if{$error,!$error!}' > "$TEST_TEMPLATE"
811 testcase '11' P=text
812 testcase '11!boo!' P=text ERR=boo
814 # Feature tests for $base64{}
815 printf '$base64{$cgi{in}}' > "$TEST_TEMPLATE"
816 testcase '' in=""
817 testcase 'IQ==' in='!'
818 testcase 'T2s=' in='Ok'
819 testcase 'aGA+aGA/' in='h`>h`?'
820 testcase 'YmFzZTY0IHRlc3Q=' in='base64 test'
822 # Regression test: $setrelevant crashed with no argument list prior to 1.4.16.
823 printf '$setrelevant$or{$error,No error}' > "$TEST_TEMPLATE"
824 testcase 'Exception: too few arguments to $setrelevant' P=text
825 printf '$setrelevant{}$or{$error,No error}' > "$TEST_TEMPLATE"
826 testcase 'No error' P=text
828 # Feature tests for $uniq and $unique{}.
829 printf '$list{$uniq{$split{$cgi{text}}},:}|$list{$unique{$split{$cgi{text}}},:}' > "$TEST_TEMPLATE"
830 testcase '|' text=''
831 testcase 'foo|foo' text='foo'
832 testcase 'apple:banana:cherry|apple:banana:cherry' text='apple apple banana banana banana cherry'
833 testcase 'a:b:r:a:c:a:d:a:b:r:a|a:b:r:c:d' text='a b r a c a d a b r a'
834 testcase 'x:y:z:y|x:y:z' text='x y z z y'
836 # Regression test - $map with one argument wasn't rejected cleanly.
837 printf '$map{foo}' > "$TEST_TEMPLATE"
838 testcase 'Exception: too few arguments to $map'
840 # Omit trailing \n on dump file as regression test for bug fixed in 1.4.20
841 # where a final line without a newline was ignored.
842 printf 'a b : index field' > "$TEST_INDEXSCRIPT"
843 rm -rf "$TEST_DB"
844 printf 'a=1\nb=2' | $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null
845 printf '$record{1}' > "$TEST_TEMPLATE"
846 testcase 'a=1
847 b=2'
849 # Test MORELIKE CGI parameter.
850 printf '%s\n' 'id : boolean=Q' 'text : index field' > "$TEST_INDEXSCRIPT"
851 rm -rf "$TEST_DB"
852 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
853 id=a1
854 text=First document
856 id=b2
857 text=Second article
859 id=c3
860 text=Piece of writing three
862 id=dummy
863 text=Inflating termfreqs since Omega excludes terms with termfreq of one
864 =first document second piece of writing three
866 printf '$querydescription|$query' > "$TEST_TEMPLATE"
867 testcase 'Query((Zfirst@1 OR Zdocument@2))|first document' MORELIKE='Qa1' DEFAULTOP=or
868 testcase 'Query((Zfirst@1 OR Zdocument@2))|first OR document' MORELIKE='Qa1'
869 testcase 'Query((Zfirst@1 OR Zdocument@2))|first OR document' MORELIKE='Qa1' DEFAULTOP=and
870 # Test with docid.
871 testcase 'Query((Zfirst@1 OR Zdocument@2))|first document' MORELIKE='1' DEFAULTOP=OR
872 testcase 'Query((Zfirst@1 OR Zdocument@2))|first OR document' MORELIKE='1'
873 testcase 'Query((Zfirst@1 OR Zdocument@2))|first OR document' MORELIKE='1' DEFAULTOP=phrase
874 # "article" is excluded by OmegaExpandDecider because it has termfreq 1.
875 testcase 'Query(Zsecond@1)|second' MORELIKE='Qb2' DEFAULTOP=or
876 testcase 'Query(Zsecond@1)|second' MORELIKE='Qb2'
877 # "of" is excluded because it's a stopword.
878 testcase 'Query((Zwrite@1 OR Zthree@2 OR Zpiec@3))|writing OR three OR piece' MORELIKE='Qc3'
879 # Test with absent term.
880 testcase 'Query()|' MORELIKE='Qx9'
881 # Test multiple MORELIKE parameters. We need to include the dummy document for
882 # any terms to get a positive weight and be returned.
883 testcase 'Query((Zsecond@1 OR Zfirst@2 OR Zdocument@3))|second OR first OR document' MORELIKE=1 MORELIKE=2 MORELIKE=4
884 testcase 'Query((Zsecond@1 OR Zfirst@2 OR Zdocument@3))|second OR first OR document' MORELIKE=Qa1 MORELIKE=2 MORELIKE=4
885 testcase 'Query((Zsecond@1 OR Zfirst@2 OR Zdocument@3))|second OR first OR document' MORELIKE=Qa1 MORELIKE=Qb2 MORELIKE=Qdummy
887 # Feature tests for scriptindex `index` and `indexnopos` actions.
888 printf '%s\n' 't : index=XT' 'n : indexnopos=XN' > "$TEST_INDEXSCRIPT"
889 rm -rf "$TEST_DB"
890 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
891 t=positional text
892 n=no pos here
894 printf '$msize' > "$TEST_TEMPLATE"
895 testcase '1' P.XT='"positional text"'
896 testcase '1' P.XN='no AND pos'
897 testcase '0' P.XN='"no pos"'
899 # Feature tests for scriptindex `split` action.
900 printf 'STATUS : field split=| field=SPLITSTATUS\nSTATUS : field=x' > "$TEST_INDEXSCRIPT"
901 rm -rf "$TEST_DB"
902 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
903 STATUS=PENDING|REVIEW
905 printf '$field{STATUS,1}/$field{x,1}/$list{$field{SPLITSTATUS,1},$.}' > "$TEST_TEMPLATE"
906 testcase 'PENDING|REVIEW/PENDING|REVIEW/PENDING,REVIEW' P=text
908 # Feature test for scriptindex `split` action with `dedup` operation.
909 printf 'STATUS : field split=|,dedup field=SPLITSTATUS\n' > "$TEST_INDEXSCRIPT"
910 rm -rf "$TEST_DB"
911 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
912 STATUS=REVIEW|PENDING|PENDING|REVIEW
914 printf '$field{STATUS,1}/$list{$field{SPLITSTATUS,1},$.}' > "$TEST_TEMPLATE"
915 testcase 'REVIEW|PENDING|PENDING|REVIEW/REVIEW,PENDING' P=text
917 # Feature test for scriptindex `split` action with `sort` operation.
918 printf 'STATUS : field split=|,sort field=SPLITSTATUS\n' > "$TEST_INDEXSCRIPT"
919 rm -rf "$TEST_DB"
920 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
921 STATUS=REVIEW|PENDING|PENDING|REVIEW
923 printf '$field{STATUS,1}/$list{$field{SPLITSTATUS,1},$.}' > "$TEST_TEMPLATE"
924 testcase 'REVIEW|PENDING|PENDING|REVIEW/PENDING,PENDING,REVIEW,REVIEW' P=text
926 # Feature test for scriptindex `split` action with `none` operation.
927 printf 'STATUS : field split=|,none field=SPLITSTATUS\n' > "$TEST_INDEXSCRIPT"
928 rm -rf "$TEST_DB"
929 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
930 STATUS=REVIEW|PENDING|PENDING|REVIEW
932 printf '$field{STATUS,1}/$list{$field{SPLITSTATUS,1},$.}' > "$TEST_TEMPLATE"
933 testcase 'REVIEW|PENDING|PENDING|REVIEW/REVIEW,PENDING,PENDING,REVIEW' P=text
935 # Feature test for scriptindex `split` action with `prefixes` operation.
936 printf 'STATUS : field split=|,prefixes field=SPLITSTATUS\n' > "$TEST_INDEXSCRIPT"
937 rm -rf "$TEST_DB"
938 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
939 STATUS=REVIEW|PENDING|PENDING|REVIEW
941 printf '$field{STATUS,1}/$list{$field{SPLITSTATUS,1},$.}' > "$TEST_TEMPLATE"
942 testcase 'REVIEW|PENDING|PENDING|REVIEW/REVIEW,REVIEW|PENDING,REVIEW|PENDING|PENDING,REVIEW|PENDING|PENDING|REVIEW' P=text
944 # Feature tests for scriptindex `split` action with no explicit operation.
945 printf 'STATUS : field split=| field=SPLITSTATUS\n' > "$TEST_INDEXSCRIPT"
946 rm -rf "$TEST_DB"
947 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
948 STATUS=PENDING|REVIEW|PENDING|REVIEW
950 printf '$field{STATUS,1}/$list{$field{SPLITSTATUS,1},$.}' > "$TEST_TEMPLATE"
951 testcase 'PENDING|REVIEW|PENDING|REVIEW/PENDING,REVIEW,PENDING,REVIEW' P=text
953 # Feature test for scriptindex `split` action with multi-character delimiter.
954 printf 'STATUS : field split=$. field=SPLITSTATUS\n' > "$TEST_INDEXSCRIPT"
955 rm -rf "$TEST_DB"
956 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
957 STATUS=PENDING$.$.REVIEW,PENDING$.REVIEW
959 printf '$field{STATUS,1}/$list{$field{SPLITSTATUS,1},|}' > "$TEST_TEMPLATE"
960 testcase 'PENDING$.$.REVIEW,PENDING$.REVIEW/PENDING|REVIEW,PENDING|REVIEW' P=text
962 # Feature test for scriptindex `split` action with multi-character delimiter
963 # with potential overlap.
964 printf 'STATUS : field split=:: field=SPLITSTATUS\n' > "$TEST_INDEXSCRIPT"
965 rm -rf "$TEST_DB"
966 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
967 STATUS=::Foo::::Bar:Baz:::Hello::
969 printf '$field{STATUS,1}/$list{$field{SPLITSTATUS,1},|}' > "$TEST_TEMPLATE"
970 testcase '::Foo::::Bar:Baz:::Hello::/Foo|Bar:Baz|:Hello' P=text
972 # Feature test for scriptindex `split` action with multi-character delimiter
973 # with `prefixes` operation.
974 printf 'STATUS : field split=::,prefixes field=SPLITSTATUS\n' > "$TEST_INDEXSCRIPT"
975 rm -rf "$TEST_DB"
976 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
977 STATUS=::Foo::::Bar:Baz:::Hello::
979 printf '$field{STATUS,1}/$list{$field{SPLITSTATUS,1},|}' > "$TEST_TEMPLATE"
980 testcase '::Foo::::Bar:Baz:::Hello::/::Foo|::Foo::|::Foo::::Bar:Baz|::Foo::::Bar:Baz:::Hello|::Foo::::Bar:Baz:::Hello::' P=text
982 # Feature test for scriptindex `split` action with quoted `,` delimiter.
983 printf 'STATUS : field split="," field=SPLITSTATUS\n' > "$TEST_INDEXSCRIPT"
984 rm -rf "$TEST_DB"
985 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
986 STATUS=PENDING,REVIEW,PENDING,REVIEW
988 printf '$field{STATUS,1}/$list{$field{SPLITSTATUS,1},|}' > "$TEST_TEMPLATE"
989 testcase 'PENDING,REVIEW,PENDING,REVIEW/PENDING|REVIEW|PENDING|REVIEW' P=text
991 # Feature test for nested scriptindex `split` action.
992 printf 'in : split=; field=one lower split="," field=two\nin : field' > "$TEST_INDEXSCRIPT"
993 rm -rf "$TEST_DB"
994 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
995 in=a,b,c;10,21,32;XY,YZ
997 printf '$field{in,1}/$list{$field{one,1},|}/$list{$field{two,1},|}' > "$TEST_TEMPLATE"
998 testcase 'a,b,c;10,21,32;XY,YZ/a,b,c|10,21,32|XY,YZ/a|b|c|10|21|32|xy|yz' P=text
1000 # Test scriptindex `split` action error cases.
1001 printf 'in : split="" field=one\nin : field' > "$TEST_INDEXSCRIPT"
1002 test_scriptindex_error "'split' error for empty separator" \
1003 "$TEST_INDEXSCRIPT:1:13: error: Split delimiter can't be empty"
1004 printf 'in : split=|,foo field=one\nin : field' > "$TEST_INDEXSCRIPT"
1005 test_scriptindex_error "'split' error for invalid operation" \
1006 "$TEST_INDEXSCRIPT:1:14: error: Bad split operation 'foo'"
1008 # Feature tests for scriptindex `hextobin` action.
1009 printf 'hex : hextobin value=0' > "$TEST_INDEXSCRIPT"
1010 rm -rf "$TEST_DB"
1011 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
1012 hex=
1014 hex=41
1016 hex=54657374
1018 hex=4b696C6c
1020 printf '$list{$map{$split{$cgi{DOCIDS}},$value{0,$_}},|}' > "$TEST_TEMPLATE"
1021 testcase '|A|Test|Kill' DOCIDS='1 2 3 4'
1023 # Feature test error cases for scriptindex `hextobin` action.
1024 rm -rf "$TEST_DB"
1025 echo hex=7g |\
1026 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" 2>&1 > /dev/null |\
1027 grep -q ":1: error: hextobin: input must be all hex digits" ||\
1028 { echo "scriptindex hextobin didn't give error for bad hex digit";\
1029 failed=`expr $failed + 1`; }
1030 echo hex=404 |\
1031 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" 2>&1 > /dev/null |\
1032 grep -q ":1: error: hextobin: input must have even length" ||\
1033 { echo "scriptindex hextobin didn't give error for odd length hex string";\
1034 failed=`expr $failed + 1`; }
1035 testcase '7g|404' DOCIDS='1 2'
1037 # Feature test for scriptindex `spell` action.
1038 printf '%s\n' 's : spell index' 'n : index' > "$TEST_INDEXSCRIPT"
1039 rm -rf "$TEST_DB"
1040 printf '%s\n\n' 's=some words test' 'n=tent'|$SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null
1041 printf '$set{flag_spelling_correction,true}$suggestion' > "$TEST_TEMPLATE"
1042 testcase 'some test' P='home nest'
1043 testcase 'a test' P='a tent'
1044 testcase '' P='gent'
1046 # Feature tests for scriptindex `squash` and `ltrim`/`rtrim`/`trim` actions.
1047 printf 'squash : squash field\nltrim : ltrim field\nrtrim : rtrim field\ntrim : trim field\n' > "$TEST_INDEXSCRIPT"
1048 rm -rf "$TEST_DB"
1049 whitespace_test=`printf "\t lots\v\fof\t whitespace\f "`
1050 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<END
1051 squash=$whitespace_test
1052 ltrim=$whitespace_test
1053 rtrim=$whitespace_test
1054 trim=$whitespace_test
1056 squash=a b
1057 ltrim=a b
1058 rtrim=a b
1059 trim=a b
1061 squash=xyz
1062 ltrim=xyz
1063 rtrim=xyz
1064 trim=xyz
1066 printf '$json{$field{$cgi{F},$cgi{ID}}}' > "$TEST_TEMPLATE"
1067 testcase 'lots of whitespace' F=squash ID=1
1068 testcase 'lots\u000b\fof\t whitespace\f ' F=ltrim ID=1
1069 testcase '\t lots\u000b\fof\t whitespace' F=rtrim ID=1
1070 testcase 'lots\u000b\fof\t whitespace' F=trim ID=1
1071 for f in squash ltrim rtrim trim ; do
1072 testcase 'a b' F=$f ID=2
1073 testcase 'xyz' F=$f ID=3
1074 done
1076 # Feature tests for scriptindex `truncate` action.
1077 printf 'x : field=x truncate=9 field=9 truncate=3 field=3 truncate=2 field=2 truncate=1 field=1 truncate=0 field=0\n' > "$TEST_INDEXSCRIPT"
1078 rm -rf "$TEST_DB"
1079 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<END
1080 x=really long field
1082 x=xö xxxxö x
1084 x=ö xxxxö x
1086 x=x x xx🥝 x
1088 x=a test
1090 x=tri
1092 x=du
1098 printf '$foreach{$split{1 2 3 4 5 6 7 8 9},$set{d,$_}$list{$map{$split{x 9 3 2 1 0},$field{$_,$opt{d}}},|}:}' > "$TEST_TEMPLATE"
1099 testcase 'really long field|really|rea|re|r|:xö xxxxö x|xö|xö|x|x|:ö xxxxö x|ö xxxxö|ö|ö||:x x xx🥝 x|x x|x x|x|x|:a test|a test|a|a|a|:tri|tri|tri|tr|t|:du|du|du|du|d|:1|1|1|1|1|:|||||:'
1101 # Feature tests for scriptindex `unhtml` action.
1102 printf '%s\n' 't : unhtml field=h' > "$TEST_INDEXSCRIPT"
1103 rm -rf "$TEST_DB"
1104 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
1105 t=<b>No</b>table
1107 t=<p>foo</p>d<p>bar<B>b</B></p>
1109 printf '$list{$map{$split{$cgi{DOCIDS}},$field{h,$_}},|}' > "$TEST_TEMPLATE"
1110 testcase "`printf 'Notable|foo\rd\rbarb'`" DOCIDS='1 2'
1112 # Feature test for scriptindex `weight` action.
1113 printf '%s\n' 't : index' 'w : weight=2 index' > "$TEST_INDEXSCRIPT"
1114 rm -rf "$TEST_DB"
1115 printf '%s\n\n' 't=test' 'w=test' 't=test test test'|$SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null
1116 printf '|$hitlist{$id|}' > "$TEST_TEMPLATE"
1117 testcase '|3|2|1|' P=test
1119 # Test bad parameter values to `weight` action.
1120 printf 'foo : index weight=-2' > "$TEST_INDEXSCRIPT"
1121 test_scriptindex_error "bad 'weight' parameter" \
1122 "$TEST_INDEXSCRIPT:1:20: error: Index action 'weight' takes a non-negative integer argument"
1123 printf 'foo : index weight=1.5' > "$TEST_INDEXSCRIPT"
1124 test_scriptindex_error "bad 'weight' parameter" \
1125 "$TEST_INDEXSCRIPT:1:21: error: Index action 'weight' takes an integer argument"
1127 # Test useless action warnings.
1128 printf 'foo : index weight=2' > "$TEST_INDEXSCRIPT"
1129 test_scriptindex_warning "useless 'weight' action" \
1130 "$TEST_INDEXSCRIPT:1:13: warning: Index action 'weight' has no effect*"
1132 printf 'foo : weight=2 weight=3 index' > "$TEST_INDEXSCRIPT"
1133 test_scriptindex_warning "useless 'weight' action" \
1134 "$TEST_INDEXSCRIPT:1:7: warning: Index action 'weight' has no effect*"
1136 printf 'foo : index lower' > "$TEST_INDEXSCRIPT"
1137 test_scriptindex_warning "useless 'lower' action" \
1138 "$TEST_INDEXSCRIPT:1:13: warning: Index action 'lower' has no effect*"
1140 # Test bad fieldname errors.
1141 printf 'foo *bar : index' > "$TEST_INDEXSCRIPT"
1142 test_scriptindex_error 'bad fieldname' \
1143 "$TEST_INDEXSCRIPT:1:5: error: field name must start with alphanumeric"
1145 printf 'foo b!ar : index' > "$TEST_INDEXSCRIPT"
1146 test_scriptindex_error 'bad fieldname' \
1147 "$TEST_INDEXSCRIPT:1:6: error: bad character '!' in fieldname"
1149 # Test unwanted action argument.
1150 printf 'foo : spell=test index' > "$TEST_INDEXSCRIPT"
1151 test_scriptindex_error 'unwanted action argument' \
1152 "$TEST_INDEXSCRIPT:1:12: error: Index action 'spell' doesn't take an argument"
1154 # Test missing closing quote.
1155 printf 'foo : index="XFOO' > "$TEST_INDEXSCRIPT"
1156 test_scriptindex_error 'missing closing quote' \
1157 "$TEST_INDEXSCRIPT:1:18: error: No closing quote"
1159 # Feature tests for scriptindex `termprefix` and `unprefix` actions.
1160 printf '$termprefix{$cgi{B}}|$unprefix{$cgi{B}}' > "$TEST_TEMPLATE"
1161 testcase '|' B=''
1162 testcase '|something' B='something'
1163 testcase '|42' B='42'
1164 testcase '|3bad' B='3bad'
1165 testcase '|&something' B='&something'
1166 testcase '|:something' B=':something'
1167 testcase 'H|example.org' B='Hexample.org'
1168 testcase 'K|tag' B='Ktag'
1169 testcase 'K|Capital' B='KCapital'
1170 testcase 'K|:colon-tag' B='K:colon-tag'
1171 testcase 'K|:Capital' B='K:Capital'
1172 testcase 'XCOLOUR|red' B='XCOLOURred'
1173 testcase 'XPUNC|:colon' B='XPUNC::colon'
1174 testcase 'XPUNC|internal:colon' B='XPUNC:internal:colon'
1175 testcase 'XPUNC|:Colon' B='XPUNC::Colon'
1176 testcase 'XCASE|Upper' B='XCASE:Upper'
1177 testcase 'XCASE|TITLE' B='XCASE:TITLE'
1178 testcase 'XNUM|42' B='XNUM42'
1179 testcase 'XNUM|3bad' B='XNUM3bad'
1181 # Regression test for $truncate with maxlen < the length of the indicator
1182 # string.
1183 printf '$truncate{$cgi{input},$cgi{maxlen},$cgi{ind},$cgi{ind2}}$seterror{$opt{error}}' > "$TEST_TEMPLATE"
1184 testcase 'w...' input='wwwwww' maxlen=4 ind='...' ind2='...'
1185 testcase '' input='s' maxlen=0 ind='...' ind2='...'
1187 # Feature tests for scriptindex unique action.
1188 rm -rf "$TEST_DB"
1189 printf '%s\n' 'id : boolean=Q unique=Q' 'id f : field' > "$TEST_INDEXSCRIPT"
1190 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
1191 id=1
1192 f=wan
1194 id=2
1195 f=too
1197 id=3
1198 f=free
1200 id=4
1201 f=fore
1203 id=1
1204 f=one
1206 id=2
1208 id=4
1211 id=3
1212 dummy=
1214 printf '$field{id,$cgi{id}}|$field{f,$cgi{id}}$error' > "$TEST_TEMPLATE"
1215 testcase '1|one' id=1
1216 # Since 1.5.0, document 2 gets deleted instead.
1217 testcase '2|' id=2
1218 testcase '3|' id=3
1219 testcase '4|' id=4
1220 exit 0
1222 # Test `unique` action warning.
1223 printf '%s\n' 'id : unique=Q boolean=W' 'id f : field' > "$TEST_INDEXSCRIPT"
1224 test_scriptindex_warning 'unique without boolean' \
1225 "$TEST_INDEXSCRIPT:1:6: warning: Index action 'unique=Q' without 'boolean=Q'
1226 $TEST_INDEXSCRIPT:1:6: note: 'unique' doesn't implicitly add a boolean term"
1228 # Test $subdb and $subid.
1229 rm -rf "$TEST_DB"
1230 printf 'inmemory' > "$TEST_DB"
1231 printf 'inmemory' > "${TEST_DB}2"
1232 printf 'inmemory\ninmemory\n' > "${TEST_DB}3"
1233 printf '$subdb{$cgi{ID}}|$subid{$cgi{ID}}' > "$TEST_TEMPLATE"
1234 testcase "$TEST_DB|1" ID=1
1235 testcase "$TEST_DB|1" ID=1 DB="$TEST_DB/${TEST_DB}2"
1236 testcase "${TEST_DB}2|1" ID=2 DB="$TEST_DB/${TEST_DB}2"
1237 testcase "${TEST_DB}|2" ID=3 DB="$TEST_DB/${TEST_DB}2"
1238 testcase "${TEST_DB}3|1" ID=1 DB="${TEST_DB}3"
1239 testcase "${TEST_DB}3|999" ID=999 DB="${TEST_DB}3"
1240 testcase "$TEST_DB|1" ID=1 DB="$TEST_DB" DB="${TEST_DB}3"
1241 testcase "${TEST_DB}3|1" ID=2 DB="$TEST_DB" DB="${TEST_DB}3"
1242 testcase "${TEST_DB}3|2" ID=3 DB="$TEST_DB" DB="${TEST_DB}3"
1243 testcase "$TEST_DB|2" ID=4 DB="$TEST_DB" DB="${TEST_DB}3"
1244 testcase "${TEST_DB}3|3" ID=5 DB="$TEST_DB" DB="${TEST_DB}3"
1245 rm -rf "${TEST_DB}2" "${TEST_DB}3"
1247 # Feature tests for $field.
1248 printf 'in : field="zer\0byte" hextobin field="field28\x02\x08"' > "$TEST_INDEXSCRIPT"
1249 rm -rf "$TEST_DB"
1250 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
1251 in=4071004f3456
1253 printf '$json{$field{zer$chr{0}byte,1}}|$json{$field{field28$chr{2}$chr{8},1}}|$error' > "$TEST_TEMPLATE"
1254 testcase '4071004f3456|@q\u0000O4V|'
1256 # Feature tests for $jsonarray.
1257 printf '%s, %s, %s, %s, %s' \
1258 '$jsonarray{}' \
1259 '$jsonarray{,$upper{$_}}' \
1260 '$jsonarray{$split{b4 k9},"$json{$upper{$_}}"}' \
1261 '$jsonarray{$split{a "b" c:\}}' \
1262 '$jsonarray{$split{2 3 5 7},$mul{$_,$_}}' > "$TEST_TEMPLATE"
1263 testcase '[], [], ["B4","K9"], ["a","\"b\"","c:\\"], [4,9,25,49]'
1265 # Feature tests for $jsonbool
1266 printf '%s' '$jsonbool{} $jsonbool{$eq{a,b}} $jsonbool{x} $jsonbool{0}' > "$TEST_TEMPLATE"
1267 testcase 'false false true true'
1269 # Feature tests for $jsonobject
1270 printf '%s' '$jsonobject{foo}' > "$TEST_TEMPLATE"
1271 testcase '{}'
1272 printf '%s' '$setmap{foo,Han,Solo}$jsonobject{foo}' > "$TEST_TEMPLATE"
1273 testcase '{"Han":"Solo"}'
1274 printf '%s' '$setmap{foo,key 1,value1,key"2,value\2,key3,value3}$jsonobject{foo}' > "$TEST_TEMPLATE"
1275 testcase '{"key 1":"value1","key\"2":"value\\2","key3":"value3"}'
1276 printf '%s' '$setmap{foo,key 1,1,key"2,$split{1 2},key3,$split{2 3 5}}$jsonobject{foo,,$jsonarray{$_,$add{$_,1}}}' > "$TEST_TEMPLATE"
1277 testcase '{"key 1":[2],"key\"2":[2,3],"key3":[3,4,6]}'
1278 printf '%s' '$setmap{foo,key 1,,key"2,1,key3,0}$jsonobject{foo,$upper{$_},$jsonarray{$_,$add{$_}}}' > "$TEST_TEMPLATE"
1279 testcase '{"KEY 1":[],"KEY\"2":[1],"KEY3":[0]}'
1281 # Feature tests for $stoplist
1282 printf '%s' '$setmap{prefix,foo,XFOO}[$list{$stoplist,|}]' > "$TEST_TEMPLATE"
1283 testcase '[a|the]' P.XFOO='the test' P='a test'
1285 # Feature tests for $unstem
1286 printf '%s' '$setmap{prefix,foo,XFOO}[$list{$unstem{$cgi{TERM}},|}]' > "$TEST_TEMPLATE"
1287 testcase '[pots|pot|potting]' P.XFOO='(foo:pot OR luck) (potting OR shed)' P='flower OR foo:pots' TERM=ZXFOOpot
1289 # Feature tests of scriptindex.
1291 # Regression test: non-zero exit status for unknown option.
1292 if $SCRIPTINDEX --to-be-or-not-to-be "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null < /dev/null 2>&1; then
1293 echo "scriptindex didn't give error for unknown option"
1294 failed=`expr $failed + 1`
1297 # Regression test: error given for multiple `unique` actions.
1298 printf 'uuid : boolean=Q unique=Q\nguid : boolean=G unique=G' > "$TEST_INDEXSCRIPT"
1299 rm -rf "$TEST_DB"
1300 if $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null < /dev/null 2>&1; then
1301 echo "scriptindex didn't reject 'unique' action being used more than once"
1302 failed=`expr $failed + 1`
1305 # Test we check for hash's argument being an integer (new in 1.4.6).
1306 printf 'url : hash=37.3 boolean=Q unique=Q' > "$TEST_INDEXSCRIPT"
1307 test_scriptindex_error "'hash' with a non-integer argument" \
1308 "$TEST_INDEXSCRIPT:1:14: error: Index action 'hash' takes an integer argument"
1310 # Test we give a helpful error for an action with a digit in (regression
1311 # test for fix in 1.4.6).
1313 # This used to give the confusing:
1314 # Unknown index action ''
1315 printf 'url : index4' > "$TEST_INDEXSCRIPT"
1316 test_scriptindex_error 'bad index action with a digit' \
1317 "$TEST_INDEXSCRIPT:1:7: error: Unknown index action 'index4'"
1319 # Test we give a helpful error if an = sign is missed out before an optional
1320 # numeric argument (regression test for fix in 1.4.6).
1322 # This used to give the confusing:
1323 # Unknown index action ''
1324 printf 'url : hash 42' > "$TEST_INDEXSCRIPT"
1325 test_scriptindex_error 'missing equals sign' \
1326 "$TEST_INDEXSCRIPT:1:12: error: Unknown index action '42'"
1328 # Test we warn about spaces before and after '='.
1330 # This has never been documented as supported, and was deprecated in 1.4.6
1331 # because it resulted in this quietly using `hash` as the field name, which is
1332 # probably not what was intended:
1334 # url : field= hash boolean=Q unique=Q
1335 printf 'url : field= hash boolean=Q unique=Q' > "$TEST_INDEXSCRIPT"
1336 test_scriptindex_warning 'space after "="' \
1337 "$TEST_INDEXSCRIPT:1:13: warning: putting spaces between '=' and the argument is deprecated"
1339 printf 'url : field =link' > "$TEST_INDEXSCRIPT"
1340 test_scriptindex_warning 'space before "="' \
1341 "$TEST_INDEXSCRIPT:1:12: warning: putting spaces between the action and '=' is deprecated"
1343 # Feature tests for scriptindex `date` action.
1344 printf '%s\n' 'd : date=unix' 'g : date=unixutc' > "$TEST_INDEXSCRIPT"
1345 rm -rf "$TEST_DB"
1346 # `date=unix` works in the current timezone, so set that explicitly so the
1347 # build doesn't fail if run in a timezone which is behind UTC.
1348 TZ=UTC $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
1353 d=1541478429
1355 printf '$list{$map{$range{1,3},$list{$allterms{$_}, }},|}' > "$TEST_TEMPLATE"
1356 testcase '|D19700101 M197001 Y1970|D20181106 M201811 Y2018'
1358 # `date=unixutc` should always work in UTC regardless of the current timezone.
1359 rm -rf "$TEST_DB"
1360 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
1365 g=1541478429
1367 testcase '|D19700101 M197001 Y1970|D20181106 M201811 Y2018'
1369 # Check nested $hitlist{} doesn't result in an infinite loop.
1370 # Regression test for bug fixed in 1.4.12.
1371 printf '<|$hitlist{$id(:$hitlist{$id:})|}>' > "$TEST_TEMPLATE"
1372 testcase '<|2(:2:3:)|3(:2:3:)|>' B=Y1970 B=Y2018
1374 # Feature tests for scriptindex `parsedate` action.
1375 printf '%s\n' 'DATE : field parsedate=%Y%m%d valuepacked=13' > "$TEST_INDEXSCRIPT"
1376 rm -rf "$TEST_DB"
1377 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
1378 DATE=19891204
1380 printf '$field{DATE,1}|$unpack{$value{13,1}}|$date{$unpack{$value{13,1}}}' > "$TEST_TEMPLATE"
1381 testcase '19891204|628732800|1989-12-04' P=text
1383 # Feature tests for scriptindex `parsedate` action.
1384 printf '%s\n' \
1385 'DATE: parsedate="%Y%m%d %T" field=time' \
1386 'TIME_T: parsedate=%s field=time' > "$TEST_INDEXSCRIPT"
1387 rm -rf "$TEST_DB"
1388 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null 2>&1 <<'END'
1389 DATE=20161202 12:04:22.000000
1391 TIME_T=1480680263
1393 printf '$field{time,$cgi{id}}' > "$TEST_TEMPLATE"
1394 # Test format which contains a space.
1395 testcase '1480680262' id=1
1396 # Regression test - we used to add on the local timezone offset.
1397 testcase '1480680263' id=2
1399 if grep -q 'define HAVE_STRUCT_TM_TM_GMTOFF 1' config.h ; then
1400 # Feature tests for scriptindex `parsedate` action.
1401 printf '%s\n' 'DATE: parsedate="%Y%m%d %T %z" field=time' > "$TEST_INDEXSCRIPT"
1402 rm -rf "$TEST_DB"
1403 echo 'DATE=20161202 21:34:22 +0930' | \
1404 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null 2>&1
1405 printf '$field{time,$cgi{id}}' > "$TEST_TEMPLATE"
1406 # Test that timezone adjustment is applied.
1407 testcase '1480680262' id=1
1408 else
1409 echo "Skipping testcases which need tm_gmtoff member in struct tm"
1412 # Feature tests for scriptindex `valuenumeric` action.
1413 printf '%s\n' 'n : field valuenumeric=0' > "$TEST_INDEXSCRIPT"
1414 rm -rf "$TEST_DB"
1415 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
1418 n=1.75
1420 n=-1000000000
1422 printf '$list{$map{$range{1,3},$url{$value{0,$_}}},:}' > "$TEST_TEMPLATE"
1423 testcase '%80:%A3:%1F%A4FS%60'
1425 # Feature tests for scriptindex `load` action.
1426 printf '%s\n' 'file : load field' > "$TEST_INDEXSCRIPT"
1427 test_scriptindex_warning 'empty filename in load action' \
1428 "<stdin>:1: warning: Empty filename in LOAD action" \
1429 'file='
1431 # Feature tests for quoted arguments.
1432 printf 'DATE : field=" spaces " date="yyyymmdd"\nTEXT: index="S"\n' > "$TEST_INDEXSCRIPT"
1433 rm -rf "$TEST_DB"
1434 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
1435 DATE=19891204
1436 TEXT=This is sample text.
1437 NEXT=work
1439 printf '$freq{D19891204}|$field{ spaces ,1}' > "$TEST_TEMPLATE"
1440 testcase '1|19891204' P.S=text
1441 # Use $time to force the match to run.
1442 printf '$if{x$time,$freq{D19891204}}|$field{ spaces ,1}' > "$TEST_TEMPLATE"
1443 testcase '1|19891204' P=
1445 # Feature tests for escaping in quoted arguments.
1446 printf '%s\n' 'esc : field="\tesca\x70e,test\\\""' > "$TEST_INDEXSCRIPT"
1447 rm -rf "$TEST_DB"
1448 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
1449 esc=test
1451 printf '$field{$chr{9}escape$.test\\",1}' > "$TEST_TEMPLATE"
1452 testcase 'test' P=
1453 # Ensure the location of the problem is always in the same column so we can
1454 # test against a fixed error message including line and column.
1455 for badesc in \
1456 '"xx\' \
1457 '"xx\q"' \
1458 '"\x"' \
1459 '"\x1"' \
1460 '"\xg"' \
1461 '"\x1g"' \
1462 '"\x1g"' \
1463 ; do
1464 printf '%s' "x: split=$badesc" > "$TEST_INDEXSCRIPT"
1465 test_scriptindex_error "bad escaping '$badesc'" \
1466 "$TEST_INDEXSCRIPT:1:14: error: Bad escaping in quoted action argument"
1467 done
1469 # Regression test that a closing " with junk after is flagged.
1470 printf 'date : field="test"index' > "$TEST_INDEXSCRIPT"
1471 rm -rf "$TEST_DB"
1472 rc=0
1473 out=`$SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" < /dev/null 2>&1` || rc=$?
1474 if [ $rc -eq 0 ] ; then
1475 echo "scriptindex didn't exit with non-zero return code for junk after closing quote"
1476 failed=`expr $failed + 1`
1477 elif printf '%s' "$out" \
1478 | grep -q ":1:20: error: Unexpected character 'i' after closing quote" ; then
1479 : # OK
1480 else
1481 echo "scriptindex didn't give expected error for junk after closing quote"
1482 failed=`expr $failed + 1`
1485 # Test we warn about useless actions.
1486 printf 'date : field parsedate=%%Y%%m%%d' > "$TEST_INDEXSCRIPT"
1487 test_scriptindex_warning "useless 'parsedate'" \
1488 "$TEST_INDEXSCRIPT:1:14: warning: Index action 'parsedate' has no effect*"
1490 # Test a `parsedate` format error.
1491 printf 'date : field parsedate="%%Y\t%%m\t%%d\t%%Z"' > "$TEST_INDEXSCRIPT"
1492 test_scriptindex_error "'%Z' in 'parsedate' format" \
1493 "$TEST_INDEXSCRIPT:1:34: error: Parsing timezone names with %Z is not supported"
1495 # Test scriptindex `gap` action inserts a termpos gap.
1496 printf 'text : index gap=5' > "$TEST_INDEXSCRIPT"
1497 rm -rf "$TEST_DB"
1498 printf 'text=%s\n' foo bar baz|$SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null
1499 echo '|$hitlist{$id|}' > "$TEST_TEMPLATE"
1500 testcase '|' 'P="foo bar"'
1501 testcase '|' 'P=foo NEAR/5 bar'
1502 testcase '|' 'P=foo NEAR/11 baz'
1503 testcase '|1|' 'P=foo NEAR/6 bar'
1504 testcase '|1|' 'P=foo NEAR/12 baz'
1506 # The scriptindex `hash` action should require its argument is >= 6, so test 5
1507 # is rejected.
1508 printf 'url : hash=5 boolean=Q unique=Q' > "$TEST_INDEXSCRIPT"
1509 rm -rf "$TEST_DB"
1510 if $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" < /dev/null > /dev/null 2>&1 ; then
1511 echo "scriptindex didn't reject 'hash=5'"
1512 failed=`expr $failed + 1`
1515 # And that 6 is accepted.
1516 printf 'url : hash=6 boolean=Q unique=Q' > "$TEST_INDEXSCRIPT"
1517 rm -rf "$TEST_DB"
1518 if echo 'url=http://xapian.org' | $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null 2>&1 ; then
1519 : # OK
1520 else
1521 echo "scriptindex rejected 'hash=6'"
1522 failed=`expr $failed + 1`
1525 # Regression test to check `hash` works without argument (it was failing with
1526 # an assertion in unreleased versions prior to 1.4.6).
1527 printf 'url : hash boolean=Q unique=Q' > "$TEST_INDEXSCRIPT"
1528 rm -rf "$TEST_DB"
1529 if echo 'url=http://xapian.org' | $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null 2>&1 ; then
1530 : # OK
1531 else
1532 echo "scriptindex rejected 'hash'"
1533 failed=`expr $failed + 1`
1536 # Test the same actions for multiple fields works (briefly broken in git master
1537 # before 1.5.0).
1538 printf 'tag1 tag2 tag3 : boolean=T field' > "$TEST_INDEXSCRIPT"
1539 rm -rf "$TEST_DB"
1540 $SCRIPTINDEX "$TEST_DB" "$TEST_INDEXSCRIPT" > /dev/null <<'END'
1541 tag1=one
1542 tag2=two
1543 tag3=three
1545 printf '$hitlist{$list{$terms{T},|}/$field{tag1}|$field{tag2}|$field{tag3}}' > "$TEST_TEMPLATE"
1546 testcase 'Tone/one|two|three' B=Tone
1547 testcase 'Tthree|Ttwo/one|two|three' B=Ttwo B=Tthree
1549 rm "$OMEGA_CONFIG_FILE" "$TEST_INDEXSCRIPT" "$TEST_TEMPLATE"
1550 rm -rf "$TEST_DB"
1551 if [ "$failed" = 0 ] ; then
1552 exit 0
1554 echo "Failed $failed test(s)"
1555 exit 1