xref: /netbsd-src/tests/bin/sh/t_arith.sh (revision 8d48762db3b5cc8b9524f0a670569c9f7fe840a0)
1# $NetBSD: t_arith.sh,v 1.8 2017/07/15 18:50:42 kre Exp $
2#
3# Copyright (c) 2016 The NetBSD Foundation, Inc.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25# POSSIBILITY OF SUCH DAMAGE.
26#
27# the implementation of "sh" to test
28: ${TEST_SH:="/bin/sh"}
29
30# Requirement is to support at least "signed long" whatever that means
31# (number of bits in "long" is not specified - but should be at least 32).
32
33# These tests use -o inline:"..." rather than -o match:'...' as we have
34# only digits to examine, and it is good to be sure that 1 + 1 really gives 2
35# and that 42 or 123 don't look like success because there is a 2 in them.
36
37ARITH_BITS='?'
38discover_range()
39{
40	# cannot use arithmetic "test" operators, range of test in
41	# ATF_SHELL (or even TEST_SH) might not be as big as that
42	# supported by $(( )) in TEST_SH
43
44	if ! ${TEST_SH} -c ': $(( 0x10000 ))' 2>/dev/null
45	then
46		# 16 bits or less, or hex unsupported, just give up...
47		return
48	fi
49	test $( ${TEST_SH} -c 'echo $(( 0x1FFFF ))' ) = 131071 || return
50
51	# when attempting to exceed the number of available bits
52	# the shell may react in any of 3 (rational) ways
53	# 1. syntax error (maybe even core dump...) and fail
54	# 2. represent a positive number input as negative value
55	# 3. keep the number positive, but not the value expected
56	#    (perhaps pegged at the max possible value)
57	# any of those may be accompanied by a message to stderr
58
59	# Must check all 3 possibilities for each plausible size
60	# Tests do not use 0x8000... because that value can have weird
61	# other side effects that are not relevant to discover here.
62	# But we do want to try and force the sign bit set.
63
64	if ! ${TEST_SH} -c ': $(( 0xC0000000 ))' 2>/dev/null
65	then
66		# proobably shell detected overflow and complained
67		ARITH_BITS=32
68		return
69	fi
70	if ${TEST_SH} 2>/dev/null \
71	    -c 'case $(( 0xC0000000 )); in (-*) exit 0;; esac; exit 1'
72	then
73		ARITH_BITS=32
74		return
75	fi
76	if ${TEST_SH} -c '[ $(( 0xC0000000 )) != 3221225472 ]' 2>/dev/null
77	then
78		ARITH_BITS=32
79		return
80	fi
81
82	if ! ${TEST_SH} -c ': $(( 0xC000000000000000 ))' 2>/dev/null
83	then
84		ARITH_BITS=64
85		return
86	fi
87	if ${TEST_SH} 2>/dev/null \
88	    -c 'case $(( 0xC000000000000000 )); in (-*) exit 0;; esac; exit 1'
89	then
90		ARITH_BITS=64
91		return
92	fi
93	if ${TEST_SH} 2>/dev/null \
94	    -c '[ $((0xC000000000000000)) != 13835058055282163712 ]'
95	then
96		ARITH_BITS=64
97		return
98	fi
99
100	if ${TEST_SH} 2>/dev/null -c \
101	   '[ $((0x123456781234567812345678)) = 5634002657842756053938493048 ]'
102	then
103		# just assume... (for now anyway, revisit when it happens...)
104		ARITH_BITS=96
105		return
106	fi
107}
108
109atf_test_case constants
110constants_head()
111{
112        atf_set "descr" "Tests that arithmetic expansion can handle constants"
113}
114constants_body()
115{
116	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
117		'echo $(( 1 ))'
118	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
119		'echo $(( 0 ))'
120	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
121		'echo $((0x0))'
122
123	# atf_expect_fail "PR bin/50959"
124	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
125		'echo $((0X0))'
126	# atf_expect_pass
127
128	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
129		'echo $((000))'
130
131	atf_check -s exit:0 -o inline:'1\n' -e empty \
132		${TEST_SH} -c 'echo $(( 000000001 ))'
133	atf_check -s exit:0 -o inline:'0\n' -e empty \
134		${TEST_SH} -c 'echo $(( 0x000000 ))'
135
136	atf_check -s exit:0 -o inline:'99999\n' -e empty \
137		${TEST_SH} -c 'echo $((99999))'
138
139	[ ${ARITH_BITS} -gt 44 ] &&
140		atf_check -s exit:0 -o inline:'9191919191919\n' -e empty \
141			${TEST_SH} -c 'echo $((9191919191919))'
142
143	atf_check -s exit:0 -o inline:'13\n' -e empty ${TEST_SH} -c \
144		'echo $(( 0xD ))'
145	atf_check -s exit:0 -o inline:'11\n' -e empty ${TEST_SH} -c \
146		'echo $(( 013 ))'
147	atf_check -s exit:0 -o inline:'7\n' -e empty ${TEST_SH} -c \
148		'x=7;echo $(($x))'
149	atf_check -s exit:0 -o inline:'9\n' -e empty ${TEST_SH} -c \
150		'x=9;echo $((x))'
151
152	atf_check -s exit:0 -o inline:'11\n' -e empty \
153		${TEST_SH} -c 'x=0xB; echo $(( $x ))'
154	atf_check -s exit:0 -o inline:'27\n' -e empty \
155		${TEST_SH} -c 'x=0X1B; echo $(( x ))'
156	atf_check -s exit:0 -o inline:'27\n' -e empty \
157		${TEST_SH} -c 'X=033; echo $(( $X ))'
158	atf_check -s exit:0 -o inline:'219\n' -e empty \
159		${TEST_SH} -c 'X=0333; echo $(( X ))'
160	atf_check -s exit:0 -o inline:'0\n' -e empty \
161		${TEST_SH} -c 'NULL=; echo $(( NULL ))'
162
163	# Not clear if this is 0, nothing, or an error, so omit for now
164	# atf_check -s exit:0 -o inline:'0\n' -e empty \
165	# 	${TEST_SH} -c 'echo $(( ))'
166
167	# not clear whether this should return 0 or an error, so omit for now
168	# atf_check -s exit:0 -o inline:'0\n' -e empty \
169	# 	${TEST_SH} -c 'echo $(( UNDEFINED_VAR ))'
170}
171
172
173atf_test_case do_unary_plus
174do_unary_plus_head()
175{
176        atf_set "descr" "Tests that unary plus works as expected"
177}
178do_unary_plus_body()
179{
180	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
181		'echo $(( +0 ))'
182	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
183		'echo $(( +1 ))'
184	atf_check -s exit:0 -o inline:'6\n' -e empty ${TEST_SH} -c \
185		'echo $(( + 6 ))'
186	atf_check -s exit:0 -o inline:'4321\n' -e empty ${TEST_SH} -c \
187		'echo $(( + 4321 ))'
188	atf_check -s exit:0 -o inline:'17185\n' -e empty ${TEST_SH} -c \
189		'echo $(( + 0x4321 ))'
190}
191
192atf_test_case do_unary_minus
193do_unary_minus_head()
194{
195        atf_set "descr" "Tests that unary minus works as expected"
196}
197do_unary_minus_body()
198{
199	atf_check -s exit:0 -o inline:'-1\n' -e empty ${TEST_SH} -c \
200		'echo $(( -1 ))'
201	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
202		'echo $(( - 0 ))'
203	atf_check -s exit:0 -o inline:'-1\n' -e empty ${TEST_SH} -c \
204		'echo $(( - 1 ))'
205	atf_check -s exit:0 -o inline:'-6\n' -e empty ${TEST_SH} -c \
206		'echo $(( - 6 ))'
207	atf_check -s exit:0 -o inline:'-4321\n' -e empty ${TEST_SH} -c \
208		'echo $(( - 4321 ))'
209	atf_check -s exit:0 -o inline:'-2257\n' -e empty ${TEST_SH} -c \
210		'echo $(( - 04321 ))'
211	atf_check -s exit:0 -o inline:'-7\n' -e empty ${TEST_SH} -c \
212		'echo $((-7))'
213}
214
215atf_test_case do_unary_not
216do_unary_not_head()
217{
218        atf_set "descr" "Tests that unary not (boolean) works as expected"
219}
220do_unary_not_body()
221{
222	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
223		'echo $(( ! 1 ))'
224	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
225		'echo $(( ! 0 ))'
226
227	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
228		'echo $(( !1234 ))'
229	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
230		'echo $(( !0xFFFF ))'
231	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
232		'echo $(( ! 000000 ))'
233}
234
235atf_test_case do_unary_tilde
236do_unary_tilde_head()
237{
238        atf_set "descr" "Tests that unary not (bitwise) works as expected"
239}
240do_unary_tilde_body()
241{
242	# definitely 2's complement arithmetic here...
243
244	atf_check -s exit:0 -o inline:'-1\n' -e empty ${TEST_SH} -c \
245		'echo $(( ~ 0 ))'
246	atf_check -s exit:0 -o inline:'-2\n' -e empty ${TEST_SH} -c \
247		'echo $(( ~ 1 ))'
248
249	atf_check -s exit:0 -o inline:'-1235\n' -e empty ${TEST_SH} -c \
250		'echo $(( ~1234 ))'
251	atf_check -s exit:0 -o inline:'-256\n' -e empty ${TEST_SH} -c \
252		'echo $(( ~0xFF ))'
253}
254
255atf_test_case elementary_add
256elementary_add_head()
257{
258        atf_set "descr" "Tests that simple addition works as expected"
259}
260elementary_add_body()
261{
262	# some of these tests actually test unary ops &  op precedence...
263
264	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
265		'echo $(( 0 + 0 ))'
266	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
267		'echo $(( 1 + 0 ))'
268	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
269		'echo $(( 0 + 1 ))'
270	atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \
271		'echo $(( 1 + 1 ))'
272	atf_check -s exit:0 -o inline:'10\n' -e empty ${TEST_SH} -c \
273		'echo $(( 4 + 6 ))'
274	atf_check -s exit:0 -o inline:'10\n' -e empty ${TEST_SH} -c \
275		'echo $(( 6 + 4 ))'
276	atf_check -s exit:0 -o inline:'5555\n' -e empty ${TEST_SH} -c \
277		'echo $(( 1234 + 4321 ))'
278	atf_check -s exit:0 -o inline:'3333\n' -e empty ${TEST_SH} -c \
279		'echo $((1111+2222))'
280	atf_check -s exit:0 -o inline:'5555\n' -e empty ${TEST_SH} -c \
281		'echo $((+3333+2222))'
282	atf_check -s exit:0 -o inline:'7777\n' -e empty ${TEST_SH} -c \
283		'echo $((+3333 + +4444))'
284	atf_check -s exit:0 -o inline:'-7777\n' -e empty ${TEST_SH} -c \
285		'echo -$((+4125+ +3652))'
286}
287
288atf_test_case elementary_sub
289elementary_sub_head()
290{
291        atf_set "descr" "Tests that simple subtraction works as expected"
292}
293elementary_sub_body()
294{
295	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
296		'echo $(( 0 - 0 ))'
297	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
298		'echo $(( 1 - 0 ))'
299	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
300		'echo $(( 1 - 1 ))'
301	atf_check -s exit:0 -o inline:'-1\n' -e empty ${TEST_SH} -c \
302		'echo $(( 0 - 1 ))'
303	atf_check -s exit:0 -o inline:'488\n' -e empty ${TEST_SH} -c \
304		'echo $(( 1066 - 578 ))'
305	atf_check -s exit:0 -o inline:'-3662\n' -e empty ${TEST_SH} -c \
306		'echo $(( 2016-5678 ))'
307	atf_check -s exit:0 -o inline:'-3662\n' -e empty ${TEST_SH} -c \
308		'echo $(( 2016+-5678 ))'
309	atf_check -s exit:0 -o inline:'-3662\n' -e empty ${TEST_SH} -c \
310		'echo $(( 2016-+5678 ))'
311	atf_check -s exit:0 -o inline:'-7694\n' -e empty ${TEST_SH} -c \
312		'echo $(( -2016-5678 ))'
313	atf_check -s exit:0 -o inline:'--1\n' -e empty ${TEST_SH} -c \
314		'echo -$(( -1018 - -1017 ))'
315}
316
317atf_test_case elementary_mul
318elementary_mul_head()
319{
320        atf_set "descr" "Tests that simple multiplication works as expected"
321}
322elementary_mul_body()
323{
324	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
325		'echo $(( 0 * 0 ))'
326	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
327		'echo $(( 1 * 0 ))'
328	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
329		'echo $(( 0 * 1 ))'
330	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
331		'echo $(( 1 * 1 ))'
332	atf_check -s exit:0 -o inline:'-1\n' -e empty ${TEST_SH} -c \
333		'echo $(( -1 * 1 ))'
334	atf_check -s exit:0 -o inline:'-1\n' -e empty ${TEST_SH} -c \
335		'echo $(( 1 * -1 ))'
336	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
337		'echo $(( -1 * -1 ))'
338	atf_check -s exit:0 -o inline:'391\n' -e empty ${TEST_SH} -c \
339		'echo $(( 17 * 23 ))'
340	atf_check -s exit:0 -o inline:'169\n' -e empty ${TEST_SH} -c \
341		'echo $(( 13*13 ))'
342	atf_check -s exit:0 -o inline:'-11264\n' -e empty ${TEST_SH} -c \
343		'echo $(( -11 *1024 ))'
344	atf_check -s exit:0 -o inline:'-16983\n' -e empty ${TEST_SH} -c \
345		'echo $(( 17* -999 ))'
346	atf_check -s exit:0 -o inline:'9309\n' -e empty ${TEST_SH} -c \
347		'echo $(( -29*-321 ))'
348}
349
350atf_test_case elementary_div
351elementary_div_head()
352{
353        atf_set "descr" "Tests that simple division works as expected"
354}
355elementary_div_body()
356{
357	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
358		'echo $(( 0 / 1 ))'
359	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
360		'echo $(( 1 / 1 ))'
361	test ${ARITH_BITS} -ge 38 &&
362	    atf_check -s exit:0 -o inline:'99999999999\n' -e empty \
363		${TEST_SH} -c 'echo $(( 99999999999 / 1 ))'
364	atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \
365		'echo $(( 2 / 1 ))'
366
367	atf_check -s exit:0 -o inline:'3\n' -e empty ${TEST_SH} -c \
368		'echo $(( 3 / 1 ))'
369	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
370		'echo $(( 3 / 2 ))'
371	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
372		'echo $(( 3 / 3 ))'
373	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
374		'echo $(( 3 / 4 ))'
375
376	atf_check -s exit:0 -o inline:'173\n' -e empty ${TEST_SH} -c \
377		'echo $(( 123456 / 713 ))'
378	atf_check -s exit:0 -o inline:'13\n' -e empty ${TEST_SH} -c \
379		'echo $(( 169 / 13 ))'
380}
381
382atf_test_case elementary_rem
383elementary_rem_head()
384{
385        atf_set "descr" "Tests that simple modulus works as expected"
386}
387elementary_rem_body()
388{
389	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
390		'echo $(( 0 % 1 ))'
391	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
392		'echo $(( 1 % 1 ))'
393	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
394		'echo $(( 2 % 1 ))'
395	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
396		'echo $(( 9999 % 1 ))'
397
398	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
399		'echo $(( 0 % 2 ))'
400	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
401		'echo $(( 1 % 2 ))'
402	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
403		'echo $(( 2 % 2 ))'
404	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
405		'echo $(( 0xFFFF % 2 ))'
406
407	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
408		'echo $(( 0 % 3 ))'
409	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
410		'echo $(( 1 % 3 ))'
411	atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \
412		'echo $(( 2 % 3 ))'
413	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
414		'echo $(( 3 % 3 ))'
415	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
416		'echo $(( 3123 % 3 ))'
417
418	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
419		'echo $(( 9999 % 2 ))'
420
421	atf_check -s exit:0 -o inline:'107\n' -e empty ${TEST_SH} -c \
422		'echo $(( 123456%173 ))'
423	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
424		'echo $((169%13))'
425}
426
427atf_test_case elementary_shl
428elementary_shl_head()
429{
430        atf_set "descr" "Tests that simple shift left works as expected"
431}
432elementary_shl_body()
433{
434	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
435		'echo $(( 0 << 0 ))'
436	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
437		'echo $(( 0 << 1 ))'
438	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
439		'echo $(( 0 << 17 ))'
440
441	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
442		'echo $(( 1 << 0 ))'
443	atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \
444		'echo $(( 1 << 1 ))'
445	atf_check -s exit:0 -o inline:'131072\n' -e empty ${TEST_SH} -c \
446		'echo $(( 1 << 17 ))'
447
448	atf_check -s exit:0 -o inline:'2021161080\n' -e empty ${TEST_SH} -c \
449		'echo $(( 0x3C3C3C3C << 1 ))'
450
451	test "${ARITH_BITS}" -ge 40 &&
452	    atf_check -s exit:0 -o inline:'129354309120\n' -e empty \
453		${TEST_SH} -c 'echo $(( 0x3C3C3C3C << 7 ))'
454	test "${ARITH_BITS}" -ge 72 &&
455	    atf_check -s exit:0 -o inline:'1111145054534149079040\n' \
456		-e empty ${TEST_SH} -c 'echo $(( 0x3C3C3C3C << 40 ))'
457
458	return 0
459}
460
461atf_test_case elementary_shr
462elementary_shr_head()
463{
464        atf_set "descr" "Tests that simple shift right works as expected"
465}
466elementary_shr_body()
467{
468	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
469		'echo $(( 0 >> 0 ))'
470	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
471		'echo $(( 0 >> 1 ))'
472	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
473		'echo $(( 0 >> 17 ))'
474
475	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
476		'echo $(( 1 >> 0 ))'
477	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
478		'echo $(( 1 >> 1 ))'
479	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
480		'echo $(( 2 >> 1 ))'
481	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
482		'echo $(( 3 >> 1 ))'
483
484	atf_check -s exit:0 -o inline:'4\n' -e empty ${TEST_SH} -c \
485		'echo $(( 0x10 >> 2 ))'
486	atf_check -s exit:0 -o inline:'4\n' -e empty ${TEST_SH} -c \
487		'echo $(( 022 >> 2 ))'
488
489	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
490		'echo $(( 131072 >> 17 ))'
491
492	test ${ARITH_BITS} -ge 40 &&
493		atf_check -s exit:0 -o inline:'8\n' -e empty ${TEST_SH} -c \
494			'echo $(( 0x4000000000 >> 35 ))'
495	test ${ARITH_BITS} -ge 80 &&
496		atf_check -s exit:0 -o inline:'4464\n' -e empty ${TEST_SH} -c \
497			'echo $(( 0x93400FACE005C871000 >> 64 ))'
498
499	return 0
500}
501
502atf_test_case elementary_eq
503elementary_eq_head()
504{
505        atf_set "descr" "Tests that simple equality test works as expected"
506}
507elementary_eq_body()
508{
509	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
510		'echo $(( 0 == 0 ))'
511	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
512		'echo $(( 0 == 0000 ))'
513	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
514		'echo $(( 0 == 0x00 ))'
515	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
516		'echo $(( 1 == 1 ))'
517	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
518		'X=30; Y=0x1E; echo $(( X == Y ))'
519	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
520		'echo $(( 0x1234 == 4660 ))'
521	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
522		'echo $(( 0x1234 == 011064 ))'
523
524	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
525		'echo $(( 0 == 1 ))'
526	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
527		'echo $(( 0 == 0000000000000001 ))'
528	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
529		'echo $(( 0 == 0x10000000000000 ))'
530	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
531		'echo $(( 1 == 2 ))'
532	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
533		'X=3; Y=7; echo $(( X == Y ))'
534	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
535		'echo $(( 1234 == 0x4660 ))'
536	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
537		'echo $(( 01234 == 0x11064 ))'
538}
539atf_test_case elementary_ne
540elementary_ne_head()
541{
542        atf_set "descr" "Tests that simple inequality test works as expected"
543}
544elementary_ne_body()
545{
546	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
547		'echo $(( 1 != 0 ))'
548	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
549		'echo $(( 0x71 != 17 ))'
550	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
551		'echo $(( 1234 != 01234 ))'
552	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
553		'echo $(( 0x1234 != 01234 ))'
554	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
555		'X=3; echo $(( X != 0 ))'
556	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
557		'X=3; Y=0x11; echo $(( X != Y ))'
558
559	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
560		'echo $(( 3 != 3 ))'
561	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
562		'echo $(( 0 != 0x0 ))'
563	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
564		'echo $(( 0xA != 012 ))'
565	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
566		'X=1; echo $(( X != 1 ))'
567	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
568		'X=0xC; Y=014; echo $(( X != Y ))'
569}
570atf_test_case elementary_lt
571elementary_lt_head()
572{
573        atf_set "descr" "Tests that simple less than test works as expected"
574}
575elementary_lt_body()
576{
577	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
578		'echo $(( 0 < 1 ))'
579	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
580		'echo $(( -1 < 0 ))'
581	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
582		'echo $(( 0 < 10 ))'
583	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
584		'echo $(( 100 < 101 ))'
585	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
586		'echo $(( 0xA1 < 200 ))'
587
588	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
589		'echo $(( 0 < 0 ))'
590	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
591		'echo $(( 1 < 0 ))'
592
593	test ${ARITH_BITS} -ge 40 &&
594	    atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
595		'echo $(( 0x1BEEFF00D < 0x1FACECAFE ))'
596
597	return 0
598}
599atf_test_case elementary_le
600elementary_le_head()
601{
602        atf_set "descr" "Tests that simple less or equal test works as expected"
603}
604elementary_le_body()
605{
606	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
607		'echo $(( 0 <= 1 ))'
608	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
609		'echo $(( -1 <= 0 ))'
610	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
611		'echo $(( 0 <= 0 ))'
612	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
613		'echo $(( 0 <= 10 ))'
614	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
615		'echo $(( 100 <= 101 ))'
616	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
617		'echo $(( 0xA1 <= 161 ))'
618
619	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
620		'echo $(( 1 <= 0 ))'
621	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
622		'echo $(( -100 <= -200 ))'
623
624	test ${ARITH_BITS} -ge 40 &&
625	    atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
626		'cost=; AUD=; echo $(( $cost 0x2FEEDBABE <= $AUD 12866927294 ))'
627
628	return 0
629}
630atf_test_case elementary_gt
631elementary_gt_head()
632{
633        atf_set "descr" "Tests that simple greater than works as expected"
634}
635elementary_gt_body()
636{
637	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
638		'echo $(( 1 > 0 ))'
639	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
640		'echo $(( 1 > -1 ))'
641	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
642		'echo $(( 11 > 012 ))'
643
644	# atf_expect_fail "PR bin/50959"
645	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
646		'echo $(( 2147483647 > 0X7FFFFF0 ))'
647	# atf_expect_pass
648
649	test ${ARITH_BITS} -gt 32 &&
650	    atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
651		'echo $(( 0x80000000 > 0x7FFFFFFF ))'
652
653	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
654		'echo $(( 0 > 0 ))'
655	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
656		'echo $(( 0 > 1 ))'
657	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
658		'echo $(( -1 > 0 ))'
659	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
660		'echo $(( 0 > 10 ))'
661	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
662		'echo $(( 2015 > 2016 ))'
663	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
664		'echo $(( 0xA1 > 200 ))'
665
666	test ${ARITH_BITS} -ge 44 &&
667	    atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
668		'echo $(( 0x7F07F07F0 > 34099628014 ))'
669
670	return 0
671}
672atf_test_case elementary_ge
673elementary_ge_head()
674{
675        atf_set "descr" "Tests that simple greater or equal works as expected"
676}
677elementary_ge_body()
678{
679	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
680		'echo $(( 0 >= 0 ))'
681	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
682		'echo $(( 1 >= 0 ))'
683	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
684		'echo $(( -100 >= -101 ))'
685
686	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
687		'echo $(( -1 >= 0 ))'
688}
689
690atf_test_case fiddle_bits_and
691fiddle_bits_and_head()
692{
693	atf_set "descr" "Test bitwise and operations in arithmetic expressions"
694}
695fiddle_bits_and_body()
696{
697	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
698		'echo $(( 0 & 0 ))'
699	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
700		'echo $(( 1 & 0 ))'
701	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
702		'echo $(( 0 & 1 ))'
703	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
704		'echo $(( 1 & 1 ))'
705
706	atf_check -s exit:0 -o inline:'255\n' -e empty ${TEST_SH} -c \
707		'echo $(( 0xFF & 0xFF ))'
708	atf_check -s exit:0 -o inline:'255\n' -e empty ${TEST_SH} -c \
709		'echo $(( 0xFFFF & 0377 ))'
710
711	test "${ARITH_BITS}" -ge 48 &&
712	    atf_check -s exit:0 -o inline:'70377641607203\n' -e empty \
713		${TEST_SH} -c 'echo $(( 0x5432FEDC0123 & 0x42871357BAB3 ))'
714
715	return 0
716}
717atf_test_case fiddle_bits_or
718fiddle_bits_or_head()
719{
720	atf_set "descr" "Test bitwise or operations in arithmetic expressions"
721}
722fiddle_bits_or_body()
723{
724	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
725		'echo $(( 0 | 0 ))'
726	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
727		'echo $(( 1 | 0 ))'
728	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
729		'echo $(( 0 | 1 ))'
730	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
731		'echo $(( 1 | 1 ))'
732
733	atf_check -s exit:0 -o inline:'4369\n' -e empty ${TEST_SH} -c \
734		'echo $(( 0x1111 | 0x1111 ))'
735	atf_check -s exit:0 -o inline:'255\n' -e empty ${TEST_SH} -c \
736		'echo $(( 0xAA | 0125 ))'
737
738	test "${ARITH_BITS}" -ge 48 &&
739	    atf_check -s exit:0 -o inline:'95348271856563\n' -e empty \
740		${TEST_SH} -c 'echo $(( 0x5432FEDC0123 | 0x42871357BAB3 ))'
741
742	return 0
743}
744atf_test_case fiddle_bits_xor
745fiddle_bits_xor_head()
746{
747	atf_set "descr" "Test bitwise xor operations in arithmetic expressions"
748}
749fiddle_bits_xor_body()
750{
751	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
752		'echo $(( 0 ^ 0 ))'
753	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
754		'echo $(( 1 ^ 0 ))'
755	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
756		'echo $(( 0 ^ 1 ))'
757	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
758		'echo $(( 1 ^ 1 ))'
759
760	atf_check -s exit:0 -o inline:'255\n' -e empty ${TEST_SH} -c \
761		'echo $(( 0xF0 ^ 0x0F ))'
762	atf_check -s exit:0 -o inline:'15\n' -e empty ${TEST_SH} -c \
763		'echo $(( 0xF0 ^ 0xFF ))'
764
765	test "${ARITH_BITS}" -ge 48 &&
766	    atf_check -s exit:0 -o inline:'24970630249360\n' -e empty \
767		${TEST_SH} -c 'echo $(( 0x5432FEDC0123 ^ 0x42871357BAB3 ))'
768
769	return 0
770}
771
772atf_test_case logical_and
773logical_and_head()
774{
775	atf_set "descr" "Test logical and operations in arithmetic expressions"
776}
777logical_and_body()
778{
779	# cannot test short-circuit eval until sh implements side effects...
780
781	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
782		'echo $(( 0 && 0 ))'
783	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
784		'echo $(( 1 && 0 ))'
785	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
786		'echo $(( 0 && 1 ))'
787	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
788		'echo $(( 1 && 1 ))'
789
790	# atf_expect_fail "PR bin/50960"
791	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
792		'echo $(( 0x1111 && 01234 ))'
793	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
794		'echo $(( 0xFFFF && 0xF0F0 ))'
795}
796atf_test_case logical_or
797logical_or_head()
798{
799	atf_set "descr" "Test logical or operations in arithmetic expressions"
800}
801logical_or_body()
802{
803	# cannot test short-circuit eval until sh implements side effects...
804
805	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
806		'echo $(( 0 || 0 ))'
807	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
808		'echo $(( 1 || 0 ))'
809	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
810		'echo $(( 0 || 1 ))'
811	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
812		'echo $(( 1 || 1 ))'
813
814	# atf_expect_fail "PR bin/50960"
815	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
816		'echo $(( 0x1111 || 01234 ))'
817	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
818		'echo $(( 0x33 || 0xF0F0 ))'
819}
820
821atf_test_case nested_arith
822nested_arith_head()
823{
824	atf_set "descr" 'Test nested arithmetic $(( $(( )) ))'
825}
826nested_arith_body()
827{
828	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
829		'echo $(( $(( 0 )) ))'
830	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
831		'echo $(( 1 + $(( 2 - 2 )) ))'
832	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
833		'echo $(( $(( 3 / 3 )) + $((1*1*1)) - $(( 7 % 6 ))))'
834	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
835		'echo $(($(($(($(($((1))))))))))'
836
837	atf_check -s exit:0 -o inline:'246\n' -e empty ${TEST_SH} -c \
838		'echo $(( 2$((2 * 2))6 ))'
839	atf_check -s exit:0 -o inline:'291117\n' -e empty ${TEST_SH} -c \
840		'echo $(( $((1 + 1))$((3 * 3))$(( 99-88 ))$(( 17))))'
841	atf_check -s exit:0 -o inline:'123456789\n' -e empty ${TEST_SH} -c \
842	  'echo $(( 1$((2$((1+2))4$((2 + 2 + 1))6))7$((4 * 2))$(($((81/9))))))'
843}
844
845atf_test_case make_selection
846make_selection_head()
847{
848	atf_set "descr" "Test ?: operator in arithmetic expressions"
849}
850make_selection_body()
851{
852	# atf_expect_fail "PR bin/50958"
853
854	atf_check -s exit:0 -o inline:'3\n' -e empty ${TEST_SH} -c \
855		'echo $(( 0 ? 2 : 3 ))'
856	atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \
857		'echo $(( 1 ? 2 : 3 ))'
858
859	atf_check -s exit:0 -o inline:'111\n' -e empty ${TEST_SH} -c \
860		'echo $(( 0x1234 ? 111 : 222 ))'
861
862	atf_check -s exit:0 -o inline:'-1\n' -e empty ${TEST_SH} -c \
863		'echo $(( 1 < 2 ? -1 : 1 > 2 ? 1 : 0 ))'
864	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
865		'echo $(( 1 < 1 ? -1 : 1 > 1 ? 1 : 0 ))'
866	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
867		'echo $(( 2 < 1 ? -1 : 2 > 1 ? 1 : 0 ))'
868}
869
870atf_test_case operator_precedence
871operator_precedence_head()
872{
873	atf_set "descr" "Test operator precedence without parentheses"
874}
875operator_precedence_body()
876{
877	# NB: apart from $(( ))  ** NO ** parentheses in the expressions.
878
879	atf_check -s exit:0 -o inline:'6\n' -e empty ${TEST_SH} -c \
880		'echo $(( 1 + 2 + 3 ))'
881	atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \
882		'echo $(( 1 - 2 + 3 ))'
883	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
884		'echo $(( 3 - 2 - 1 ))'
885	atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \
886		'echo $(( 3 - 2 + 1 ))'
887
888	atf_check -s exit:0 -o inline:'-1\n' -e empty ${TEST_SH} -c \
889		'echo $(( - 2 + 1 ))'
890	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
891		'echo $(( 2 + -1 ))'
892
893	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
894		'echo $(( ! 2 + 1 ))'
895	atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \
896		'echo $(( 2 + !1 ))'
897
898	atf_check -s exit:0 -o inline:'8\n' -e empty ${TEST_SH} -c \
899		'echo $(( 3 * 2 + 2 ))'
900	atf_check -s exit:0 -o inline:'7\n' -e empty ${TEST_SH} -c \
901		'echo $(( 3 + 2 * 2 ))'
902	atf_check -s exit:0 -o inline:'12\n' -e empty ${TEST_SH} -c \
903		'echo $(( 3 * 2 * 2 ))'
904
905	atf_check -s exit:0 -o inline:'5\n' -e empty ${TEST_SH} -c \
906		'echo $(( 9 / 3 + 2 ))'
907	atf_check -s exit:0 -o inline:'10\n' -e empty ${TEST_SH} -c \
908		'echo $(( 9 + 3 / 2 ))'
909	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
910		'echo $(( 9 / 3 / 2 ))'
911
912	atf_check -s exit:0 -o inline:'72\n' -e empty ${TEST_SH} -c \
913		'echo $(( 9 << 1 + 2 ))'
914	atf_check -s exit:0 -o inline:'48\n' -e empty ${TEST_SH} -c \
915		'echo $(( 9 + 3 << 2 ))'
916	atf_check -s exit:0 -o inline:'288\n' -e empty ${TEST_SH} -c \
917		'echo $(( 9 << 3 << 2 ))'
918
919	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
920		'echo $(( 9 >> 1 + 2 ))'
921	atf_check -s exit:0 -o inline:'3\n' -e empty ${TEST_SH} -c \
922		'echo $(( 9 + 3 >> 2 ))'
923	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
924		'echo $(( 19 >> 3 >> 1 ))'
925
926	atf_check -s exit:0 -o inline:'4\n' -e empty ${TEST_SH} -c \
927		'echo $(( 19 >> 3 << 1 ))'
928	atf_check -s exit:0 -o inline:'76\n' -e empty ${TEST_SH} -c \
929		'echo $(( 19 << 3 >> 1 ))'
930
931	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
932		'echo $(( 2 + 3 < 3 * 2 ))'
933	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
934		'echo $(( 2 << 3 >= 3 << 2 ))'
935
936	# sh inherits C's crazy operator precedence...
937
938	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
939		'echo $(( 0xfD & 0xF == 0xF ))'
940
941	${TEST_SH} -c ': $(( 1 , 2 , 3 ))' 2>/dev/null  && {
942		atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \
943			'echo $(( 3 * 7 , 2 << 8 ,  9 - 7 ))'
944		atf_check -s exit:0 -o inline:'4\n' -e empty ${TEST_SH} -c \
945			'echo $(( 1 ? 2 : 3 , 0 ? 1 : 4 ))'
946	}
947
948	return 0
949}
950
951atf_test_case optional_comma
952optional_comma_head()
953{
954	atf_set "descr" "Test the optional comma operator"
955}
956optional_comma_body()
957{
958	# First, see if it is supported or not.
959	${TEST_SH} -c ': $(( 1 , 2 , 3 ))' 2>/dev/null  || atf_skip \
960	    "${TEST_SH} does not implement the ',' operator in"' $(( ))'
961
962
963	# Note ',' should be set off from numbers by spaces, as in some
964	# locales it is a valid chacacter in a number, and we want to
965	# avoid any possibility of confusing the parser.
966
967	atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \
968		'echo $(( 1 , 2 ))'
969	atf_check -s exit:0 -o inline:'3\n' -e empty ${TEST_SH} -c \
970		'echo $(( 1 , 2 , 3 ))'
971	atf_check -s exit:0 -o inline:'4\n' -e empty ${TEST_SH} -c \
972		'echo $(( 1 , 2 , 3 , 4 ))'
973
974	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
975		'echo $(( , 2 ))'
976	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
977		'echo $(( 2 , ))'
978	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
979		'echo $(( 1 , , 2 ))'
980}
981
982parentheses_head()
983{
984	atf_set "descr" "Test use of () to group sub-expressions"
985}
986parentheses_body()
987{
988	atf_check -s exit:0 -o inline:'6\n' -e empty ${TEST_SH} -c \
989		'echo $(( (1 + 2) + 3 ))'
990	atf_check -s exit:0 -o inline:'-4\n' -e empty ${TEST_SH} -c \
991		'echo $(( 1 - (2 + 3) ))'
992	atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \
993		'echo $(( 3 - (2 - 1) ))'
994	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
995		'echo $(( 3 - ( 2 + 1 ) ))'
996
997	atf_check -s exit:0 -o inline:'-3\n' -e empty ${TEST_SH} -c \
998		'echo $(( - (2 + 1) ))'
999
1000	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
1001		'echo $(( ! (2 + 1) ))'
1002
1003	atf_check -s exit:0 -o inline:'12\n' -e empty ${TEST_SH} -c \
1004		'echo $(( 3 * (2 + 2) ))'
1005	atf_check -s exit:0 -o inline:'10\n' -e empty ${TEST_SH} -c \
1006		'echo $(( (3 + 2) * 2 ))'
1007	atf_check -s exit:0 -o inline:'12\n' -e empty ${TEST_SH} -c \
1008		'echo $(( 3 * (2 * 2) ))'
1009
1010	atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
1011		'echo $(( 9 / (3 + 2) ))'
1012	atf_check -s exit:0 -o inline:'6\n' -e empty ${TEST_SH} -c \
1013		'echo $(( ( 9 + 3 ) / 2 ))'
1014	atf_check -s exit:0 -o inline:'9\n' -e empty ${TEST_SH} -c \
1015		'echo $(( 9 / ( 3 / 2 ) ))'
1016
1017	atf_check -s exit:0 -o inline:'20\n' -e empty ${TEST_SH} -c \
1018		'echo $(( ( 9 << 1 ) + 2 ))'
1019	atf_check -s exit:0 -o inline:'21\n' -e empty ${TEST_SH} -c \
1020		'echo $(( 9 + (3 << 2) ))'
1021	atf_check -s exit:0 -o inline:'36864\n' -e empty ${TEST_SH} -c \
1022		'echo $(( 9 << (3 << 2) ))'
1023
1024	atf_check -s exit:0 -o inline:'6\n' -e empty ${TEST_SH} -c \
1025		'echo $(( (9 >> 1) + 2 ))'
1026	atf_check -s exit:0 -o inline:'9\n' -e empty ${TEST_SH} -c \
1027		'echo $(( 9 + (3 >> 2) ))'
1028	atf_check -s exit:0 -o inline:'9\n' -e empty ${TEST_SH} -c \
1029		'echo $(( 19 >> (3 >> 1) ))'
1030
1031	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
1032		'echo $(( 19 >> (3 << 1) ))'
1033	atf_check -s exit:0 -o inline:'38\n' -e empty ${TEST_SH} -c \
1034		'echo $(( 19 << (3 >> 1) ))'
1035
1036	atf_check -s exit:0 -o inline:'2\n' -e empty ${TEST_SH} -c \
1037		'echo $(( 2 + (3 < 3) * 2 ))'
1038	atf_check -s exit:0 -o inline:'32\n' -e empty ${TEST_SH} -c \
1039		'echo $(( 2 << ((3 >= 3) << 2) ))'
1040
1041	# sh inherits C's crazy operator precedence...
1042	atf_check -s exit:0 -o inline:'0\n' -e empty ${TEST_SH} -c \
1043		'echo $(( (0xfD & 0xF) == 0xF ))'
1044
1045	${TEST_SH} -c ': $(( 1 , 2 , 3 ))' 2>/dev/null  && {
1046		atf_check -s exit:0 -o inline:'24\n' -e empty ${TEST_SH} -c \
1047			'echo $(( 3 * (7 , 2) << (8 ,  9 - 7) ))'
1048		atf_check -s exit:0 -o inline:'1\n' -e empty ${TEST_SH} -c \
1049			'echo $(( 0 ? 2 : ( ( 0 , 3 ) ? 1 : 4) ))'
1050	}
1051	return 0
1052}
1053
1054atf_test_case var_assign
1055var_assign_head()
1056{
1057	atf_set "descr" "Test assignment operators in arithmetic expressions"
1058}
1059var_assign_body()
1060{
1061	atf_check -s exit:0 -o inline:'3\n3\n' -e empty ${TEST_SH} -c \
1062		'unset x; echo $(( x = 3 )); echo $x'
1063	atf_check -s exit:0 -o inline:'3\n3\n' -e empty ${TEST_SH} -c \
1064		'unset x; echo $((x=3)); echo $x'
1065	atf_check -s exit:0 -o inline:'3\n3\n' -e empty ${TEST_SH} -c \
1066		'x=5; echo $((x=3)); echo $x'
1067
1068	atf_check -s exit:0 -o inline:'3\n3\n' -e empty ${TEST_SH} -c \
1069		'set +u;unset x; echo $((x+=3)); echo $x'
1070	atf_check -s exit:0 -o inline:'3\n3\n' -e empty ${TEST_SH} -c \
1071		'x=2; echo $((x+=1)); echo $x'
1072	atf_check -s exit:0 -o inline:'3\n3\n' -e empty ${TEST_SH} -c \
1073		'x=4; echo $((x-=1)); echo $x'
1074	atf_check -s exit:0 -o inline:'3\n3\n' -e empty ${TEST_SH} -c \
1075		'x=3; echo $((x*=1)); echo $x'
1076	atf_check -s exit:0 -o inline:'3\n3\n' -e empty ${TEST_SH} -c \
1077		'x=3; echo $((x/=1)); echo $x'
1078	atf_check -s exit:0 -o inline:'3\n3\n' -e empty ${TEST_SH} -c \
1079		'x=28; echo $((x%=5)); echo $x'
1080	atf_check -s exit:0 -o inline:'3\n3\n' -e empty ${TEST_SH} -c \
1081		'x=7; echo $((x&=3)); echo $x'
1082	atf_check -s exit:0 -o inline:'3\n3\n' -e empty ${TEST_SH} -c \
1083		'x=2; echo $((x|=1)); echo $x'
1084	atf_check -s exit:0 -o inline:'3\n3\n' -e empty ${TEST_SH} -c \
1085		'x=6; echo $((x^=5)); echo $x'
1086	atf_check -s exit:0 -o inline:'3\n3\n' -e empty ${TEST_SH} -c \
1087		'x=7; echo $((x>>=1)); echo $x'
1088	atf_check -s exit:0 -o inline:'2\n2\n' -e empty ${TEST_SH} -c \
1089		'x=1; echo $((x<<=1)); echo $x'
1090
1091	atf_check -s exit:0 -o inline:'2\n3\n' -e empty ${TEST_SH} -c \
1092		'x=2; echo $(( (x+=1)-1 )); echo $x'
1093	atf_check -s exit:0 -o inline:'4\n3\n' -e empty ${TEST_SH} -c \
1094		'x=4; echo $(( (x-=1)+1 )); echo $x'
1095
1096	atf_check -s exit:0 -o inline:'36\n5 7\n' -e empty ${TEST_SH} -c \
1097		'unset x y; echo $(( (x=5) * (y=7) + 1 )); echo $x $y'
1098	atf_check -s exit:0 -o inline:'36\n5 7\n' -e empty ${TEST_SH} -c \
1099		'x=99; y=17; echo $(( (x=5) * (y=7) + 1 )); echo $x $y'
1100	atf_check -s exit:0 -o inline:'36\n5 7\n' -e empty ${TEST_SH} -c \
1101		'x=4; y=9; echo $(( (x+=1) * (y-=2) + 1 )); echo $x $y'
1102
1103	atf_check -s exit:0 -o inline:'3\n3\n' -e empty ${TEST_SH} -c \
1104		'set -u; unset x; echo $(( x = 3 )); echo $x'
1105	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
1106		'set -u; unset x; echo $(( x + 3 )); echo $x'
1107	atf_check -s not-exit:0 -o ignore -e not-empty ${TEST_SH} -c \
1108		'set -u; unset x; echo $(( x+=3 )); echo $x'
1109
1110	${TEST_SH} -c ': $(( 1 , 2 , 3 ))' 2>/dev/null  && {
1111		atf_check -s exit:0 -o inline:'3\n3\n' -e empty ${TEST_SH} -c \
1112			'echo $((x=2 , x|=1)); echo $x'
1113		atf_check -s exit:0 -o inline:'3\n3\n' -e empty ${TEST_SH} -c \
1114			'set -u; echo $((x = 2   ,x |= 1)); echo $x'
1115		atf_check -s exit:0 -o inline:'6\n1:2:3:6\n' -e empty \
1116			${TEST_SH} -c \
1117		    'echo $((a=1 , b=2 , c = 3 , x=a+b + c)); echo $a:$b:$c:$x'
1118		atf_check -s exit:0 -o inline:'6\n1:2:3:6\n' -e empty \
1119			${TEST_SH} -c \
1120		    'set -u;echo $((a=1 ,b=2 ,c=3 ,x=a+b+c)); echo $a:$b:$c:$x'
1121	}
1122	return 0
1123}
1124
1125atf_test_case var_postinc
1126var_postinc_head()
1127{
1128	atf_set "descr" "Test suffix ++ operator"
1129}
1130var_postinc_body()
1131{
1132	${TEST_SH} -c 'X=1; : $(( X++ ))' 2>/dev/null ||
1133		atf_skip "${TEST_SH} does not support the suffix ++ operator"
1134
1135	unset X		; # just in case ...
1136
1137	atf_check -s exit:0 -o inline:'1\n2\n' -e empty ${TEST_SH} -c \
1138		'X=1; echo $(( X++ )); echo $X'
1139	atf_check -s exit:0 -o inline:'0\n1\n' -e empty ${TEST_SH} -c \
1140		'echo $(( X++ )); echo $X'
1141
1142	atf_check -s exit:0 -o inline:'0\n1:0\n' -e empty ${TEST_SH} -c \
1143		'unset Y; echo $(( Y = X++ )); echo $X:$Y'
1144	atf_check -s exit:0 -o inline:'12\n4:5\n' -e empty ${TEST_SH} -c \
1145		'X=3 Y=4; echo $(( Y++*X++ )); echo $X:$Y'
1146
1147	atf_check -s exit:0 -o inline:'1\n2\n' -e empty ${TEST_SH} -c \
1148		'set -u; X=1; echo $(( X++ )); echo $X'
1149	atf_check -s exit:0 -o inline:'0\n1:0\n' -e empty ${TEST_SH} -c \
1150		'set -u; X=0; unset Y; echo $(( Y = X++ )); echo $X:$Y'
1151	atf_check -s exit:0 -o inline:'12\n4:5\n' -e empty ${TEST_SH} -c \
1152		'set -u; X=3 Y=4; echo $(( Y++*X++ )); echo $X:$Y'
1153
1154	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
1155		'set -u; echo $(( X++ ))'
1156	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
1157		'set -u; unset Y; echo $(( X = Y++ ))'
1158
1159	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
1160		'X=3; readonly X; echo $(( X++ ))'
1161
1162}
1163atf_test_case var_postdec
1164var_postdec_head()
1165{
1166	atf_set "descr" "Test suffix -- operator"
1167}
1168var_postdec_body()
1169{
1170	${TEST_SH} -c 'X=1; : $(( X-- ))' 2>/dev/null ||
1171		atf_skip "${TEST_SH} does not support the suffix -- operator"
1172
1173	unset X		; # just in case ...
1174
1175	atf_check -s exit:0 -o inline:'1\n0\n' -e empty ${TEST_SH} -c \
1176		'X=1; echo $(( X-- )); echo $X'
1177	atf_check -s exit:0 -o inline:'0\n-1\n' -e empty ${TEST_SH} -c \
1178		'echo $(( X-- )); echo $X'
1179
1180	atf_check -s exit:0 -o inline:'0\n-1:0\n' -e empty ${TEST_SH} -c \
1181		'unset Y; echo $(( Y = X-- )); echo $X:$Y'
1182	atf_check -s exit:0 -o inline:'12\n2:3\n' -e empty ${TEST_SH} -c \
1183		'X=3 Y=4; echo $(( Y--*X-- )); echo $X:$Y'
1184
1185	atf_check -s exit:0 -o inline:'1\n0\n' -e empty ${TEST_SH} -c \
1186		'set -u; X=1; echo $(( X-- )); echo $X'
1187	atf_check -s exit:0 -o inline:'0\n-1:0\n' -e empty ${TEST_SH} -c \
1188		'set -u; X=0; unset Y; echo $(( Y = X-- )); echo $X:$Y'
1189	atf_check -s exit:0 -o inline:'12\n2:3\n' -e empty ${TEST_SH} -c \
1190		'set -u; X=3 Y=4; echo $(( Y--*X-- )); echo $X:$Y'
1191
1192	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
1193		'set -u; echo $(( X-- ))'
1194	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
1195		'set -u; unset Y; echo $(( X = Y-- ))'
1196
1197	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
1198		'X=3; readonly X; echo $(( X-- ))'
1199
1200}
1201atf_test_case var_preinc
1202var_preinc_head()
1203{
1204	atf_set "descr" "Test prefix ++ operator"
1205}
1206var_preinc_body()
1207{
1208	${TEST_SH} -c 'X=1; : $(( ++X ))' 2>/dev/null ||
1209		atf_skip "${TEST_SH} does not support the prefix ++ operator"
1210
1211	unset X		; # just in case ...
1212
1213	atf_check -s exit:0 -o inline:'2\n2\n' -e empty ${TEST_SH} -c \
1214		'X=1; echo $(( ++X )); echo $X'
1215	atf_check -s exit:0 -o inline:'1\n1\n' -e empty ${TEST_SH} -c \
1216		'echo $(( ++X )); echo $X'
1217
1218	atf_check -s exit:0 -o inline:'1\n1:1\n' -e empty ${TEST_SH} -c \
1219		'unset Y; echo $(( Y = ++X )); echo $X:$Y'
1220	atf_check -s exit:0 -o inline:'20\n4:5\n' -e empty ${TEST_SH} -c \
1221		'X=3 Y=4; echo $(( ++Y*++X )); echo $X:$Y'
1222
1223	atf_check -s exit:0 -o inline:'2\n2\n' -e empty ${TEST_SH} -c \
1224		'set -u; X=1; echo $(( ++X )); echo $X'
1225	atf_check -s exit:0 -o inline:'1\n1:1\n' -e empty ${TEST_SH} -c \
1226		'set -u; X=0; unset Y; echo $(( Y = ++X )); echo $X:$Y'
1227	atf_check -s exit:0 -o inline:'20\n4:5\n' -e empty ${TEST_SH} -c \
1228		'set -u; X=3 Y=4; echo $(( ++Y*++X )); echo $X:$Y'
1229
1230	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
1231		'set -u; echo $(( ++X ))'
1232	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
1233		'set -u; unset Y; echo $(( X = ++Y ))'
1234
1235	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
1236		'X=3; readonly X; echo $(( ++X ))'
1237
1238}
1239atf_test_case var_predec
1240var_predec_head()
1241{
1242	atf_set "descr" "Test prefix -- operator"
1243}
1244var_predec_body()
1245{
1246	${TEST_SH} -c 'X=1; : $(( --X ))' 2>/dev/null ||
1247		atf_skip "${TEST_SH} does not support the prefix -- operator"
1248
1249	unset X		; # just in case ...
1250
1251	atf_check -s exit:0 -o inline:'0\n0\n' -e empty ${TEST_SH} -c \
1252		'X=1; echo $(( --X )); echo $X'
1253	atf_check -s exit:0 -o inline:'-1\n-1\n' -e empty ${TEST_SH} -c \
1254		'echo $(( --X )); echo $X'
1255
1256	atf_check -s exit:0 -o inline:'-1\n-1:-1\n' -e empty ${TEST_SH} -c \
1257		'unset Y; echo $(( Y = --X )); echo $X:$Y'
1258	atf_check -s exit:0 -o inline:'6\n2:3\n' -e empty ${TEST_SH} -c \
1259		'X=3 Y=4; echo $(( --Y*--X )); echo $X:$Y'
1260
1261	atf_check -s exit:0 -o inline:'0\n0\n' -e empty ${TEST_SH} -c \
1262		'set -u; X=1; echo $(( --X )); echo $X'
1263	atf_check -s exit:0 -o inline:'-1\n-1:-1\n' -e empty ${TEST_SH} -c \
1264		'set -u; X=0; unset Y; echo $(( Y = --X )); echo $X:$Y'
1265	atf_check -s exit:0 -o inline:'6\n2:3\n' -e empty ${TEST_SH} -c \
1266		'set -u; X=3 Y=4; echo $(( --Y*--X )); echo $X:$Y'
1267
1268	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
1269		'set -u; echo $(( --X ))'
1270	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
1271		'set -u; unset Y; echo $(( X = --Y ))'
1272
1273	atf_check -s not-exit:0 -o empty -e not-empty ${TEST_SH} -c \
1274		'X=3; readonly X; echo $(( --X ))'
1275
1276}
1277
1278atf_test_case arithmetic_fails
1279arithmetic_fails_head()
1280{
1281	atf_set "descr" "Dummy test to force failure"
1282}
1283arithmetic_fails_body()
1284{
1285	atf_fail "Cannot estimate number of bits supported by $(( ))"
1286}
1287
1288atf_init_test_cases() {
1289
1290	discover_range
1291
1292	test "${ARITH_BITS}" = '?' && {
1293		atf_add_test_case arithmetic_fails
1294		return 0
1295	}
1296
1297	# odd names are to get atf's sort order semi-rational
1298
1299	atf_add_test_case constants
1300	atf_add_test_case do_unary_plus
1301	atf_add_test_case do_unary_minus
1302	atf_add_test_case do_unary_not
1303	atf_add_test_case do_unary_tilde
1304	atf_add_test_case elementary_add
1305	atf_add_test_case elementary_sub
1306	atf_add_test_case elementary_mul
1307	atf_add_test_case elementary_div
1308	atf_add_test_case elementary_rem
1309	atf_add_test_case elementary_shl
1310	atf_add_test_case elementary_shr
1311	atf_add_test_case elementary_eq
1312	atf_add_test_case elementary_ne
1313	atf_add_test_case elementary_lt
1314	atf_add_test_case elementary_le
1315	atf_add_test_case elementary_gt
1316	atf_add_test_case elementary_ge
1317	atf_add_test_case fiddle_bits_and
1318	atf_add_test_case fiddle_bits_or
1319	atf_add_test_case fiddle_bits_xor
1320	atf_add_test_case logical_and
1321	atf_add_test_case logical_or
1322	atf_add_test_case make_selection
1323	atf_add_test_case nested_arith
1324	atf_add_test_case operator_precedence
1325	atf_add_test_case optional_comma
1326	atf_add_test_case parentheses
1327	# atf_add_test_case progressive			# build up big expr
1328	# atf_add_test_case test_errors			# erroneous input
1329	# atf_add_test_case torture		# hard stuff (if there is any)
1330	atf_add_test_case var_assign			# assignment ops
1331	atf_add_test_case var_postinc			# var++
1332	atf_add_test_case var_postdec			# var--
1333	atf_add_test_case var_preinc			# ++var
1334	atf_add_test_case var_predec			# --var
1335	# atf_add_test_case vulgarity	# truly evil inputs (syntax in vars...)
1336}
1337