xref: /freebsd/contrib/bc/tests/history.py (revision 4fca8e0f)
144d4804dSStefan Eßer#! /usr/bin/python
244d4804dSStefan Eßer#
344d4804dSStefan Eßer# SPDX-License-Identifier: BSD-2-Clause
444d4804dSStefan Eßer#
5d101cdd6SStefan Eßer# Copyright (c) 2018-2023 Gavin D. Howard and contributors.
644d4804dSStefan Eßer#
744d4804dSStefan Eßer# Redistribution and use in source and binary forms, with or without
844d4804dSStefan Eßer# modification, are permitted provided that the following conditions are met:
944d4804dSStefan Eßer#
1044d4804dSStefan Eßer# * Redistributions of source code must retain the above copyright notice, this
1144d4804dSStefan Eßer#   list of conditions and the following disclaimer.
1244d4804dSStefan Eßer#
1344d4804dSStefan Eßer# * Redistributions in binary form must reproduce the above copyright notice,
1444d4804dSStefan Eßer#   this list of conditions and the following disclaimer in the documentation
1544d4804dSStefan Eßer#   and/or other materials provided with the distribution.
1644d4804dSStefan Eßer#
1744d4804dSStefan Eßer# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1844d4804dSStefan Eßer# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1944d4804dSStefan Eßer# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2044d4804dSStefan Eßer# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
2144d4804dSStefan Eßer# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2244d4804dSStefan Eßer# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2344d4804dSStefan Eßer# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2444d4804dSStefan Eßer# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2544d4804dSStefan Eßer# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2644d4804dSStefan Eßer# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2744d4804dSStefan Eßer# POSSIBILITY OF SUCH DAMAGE.
2844d4804dSStefan Eßer#
2944d4804dSStefan Eßer
3044d4804dSStefan Eßerimport os, sys
3144d4804dSStefan Eßerimport time
3244d4804dSStefan Eßerimport signal
33d43fa8efSStefan Eßerimport traceback
3444d4804dSStefan Eßer
3544d4804dSStefan Eßertry:
3644d4804dSStefan Eßer	import pexpect
3744d4804dSStefan Eßerexcept ImportError:
3844d4804dSStefan Eßer	print("Could not find pexpect. Skipping...")
3944d4804dSStefan Eßer	sys.exit(0)
4044d4804dSStefan Eßer
4144d4804dSStefan Eßer# Housekeeping.
4244d4804dSStefan Eßerscript = sys.argv[0]
4344d4804dSStefan Eßertestdir = os.path.dirname(script)
4444d4804dSStefan Eßer
45662087dfSStefan Eßerif "BC_TEST_OUTPUT_DIR" in os.environ:
46662087dfSStefan Eßer	outputdir = os.environ["BC_TEST_OUTPUT_DIR"]
47662087dfSStefan Eßerelse:
48662087dfSStefan Eßer	outputdir = testdir
49662087dfSStefan Eßer
5044d4804dSStefan Eßerprompt = ">>> "
5144d4804dSStefan Eßer
5244d4804dSStefan Eßer# This array is for escaping characters that are necessary to escape when
5344d4804dSStefan Eßer# outputting to pexpect. Since pexpect takes regexes, these characters confuse
5444d4804dSStefan Eßer# it unless we escape them.
5544d4804dSStefan Eßerescapes = [
5644d4804dSStefan Eßer	']',
5744d4804dSStefan Eßer	'[',
5844d4804dSStefan Eßer	'+',
5944d4804dSStefan Eßer]
6044d4804dSStefan Eßer
6144d4804dSStefan Eßer# UTF-8 stress tests.
6244d4804dSStefan Eßerutf8_stress1 = "ᆬḰ䋔䗅㜲ತ咡䒢岤䳰稨⣡嶣㷡嶏ⵐ䄺嵕ਅ奰痚㆜䊛拂䅙૩➋䛿ቬ竳Ϳᅠ❄产翷䮊௷Ỉ䷒䳜㛠➕傎ᗋᏯਕ䆐悙癐㺨"
6344d4804dSStefan Eßerutf8_stress2 = "韠싧돳넨큚ꉿ뮴픷ꉲ긌�최릙걆鳬낽ꪁ퍼鈴핐黙헶ꪈ뮩쭀锻끥鉗겉욞며뛯꬐�ﻼ�度錐�"
6444d4804dSStefan Eßerutf8_stress3 = "곻�䣹昲蜴Ὓ桢㎏⚦珢畣갴ﭱ鶶ๅ⶛뀁彻ꖒ䔾ꢚﱤ햔햞㐹�鼳뵡▿ⶾ꠩�纞⊐佧�ⵟ霘紳㱔籠뎼⊓搧硤"
6544d4804dSStefan Eßerutf8_stress4 = "ᄀ������"
6644d4804dSStefan Eßer
6744d4804dSStefan Eßer# An easy array for UTF-8 tests.
6844d4804dSStefan Eßerutf8_stress_strs = [
6944d4804dSStefan Eßer	utf8_stress1,
7044d4804dSStefan Eßer	utf8_stress2,
7144d4804dSStefan Eßer	utf8_stress3,
7244d4804dSStefan Eßer	utf8_stress4,
7344d4804dSStefan Eßer]
7444d4804dSStefan Eßer
7544d4804dSStefan Eßer
76d43fa8efSStefan Eßerdef expect(child, data):
77d43fa8efSStefan Eßer	child.expect(data)
78d43fa8efSStefan Eßer
79d43fa8efSStefan Eßer
80d43fa8efSStefan Eßer# Eats all of the child's data.
81d43fa8efSStefan Eßer# @param child  The child whose data should be eaten.
82d43fa8efSStefan Eßerdef eat(child):
83d43fa8efSStefan Eßer	while child.buffer is not None and len(child.buffer) > 0:
84d43fa8efSStefan Eßer		expect(child, ".+")
85d43fa8efSStefan Eßer
86d43fa8efSStefan Eßer
87d43fa8efSStefan Eßer# Send data to a child. This makes sure the buffers are empty first.
88d43fa8efSStefan Eßer# @param child  The child to send data to.
89d43fa8efSStefan Eßer# @param data   The data to send.
90d43fa8efSStefan Eßerdef send(child, data):
91d43fa8efSStefan Eßer	eat(child)
92d43fa8efSStefan Eßer	child.send(data)
93d43fa8efSStefan Eßer
94d43fa8efSStefan Eßer
95d43fa8efSStefan Eßerdef wait(child):
96d43fa8efSStefan Eßer	if child.isalive():
97d43fa8efSStefan Eßer		child.sendeof()
98d43fa8efSStefan Eßer		time.sleep(1)
99d43fa8efSStefan Eßer		if child.isalive():
100d43fa8efSStefan Eßer			child.kill(signal.SIGTERM)
101d43fa8efSStefan Eßer			time.sleep(1)
102d43fa8efSStefan Eßer			if child.isalive():
103d43fa8efSStefan Eßer				child.kill(signal.SIGKILL)
104d43fa8efSStefan Eßer	child.wait()
105d43fa8efSStefan Eßer
106d43fa8efSStefan Eßer
10744d4804dSStefan Eßer# Check that the child output the expected line. If history is false, then
10844d4804dSStefan Eßer# the output should change.
10944d4804dSStefan Eßerdef check_line(child, expected, prompt=">>> ", history=True):
110d43fa8efSStefan Eßer	send(child, "\n")
11144d4804dSStefan Eßer	prefix = "\r\n" if history else ""
112d43fa8efSStefan Eßer	expect(child, prefix + expected + "\r\n" + prompt)
11344d4804dSStefan Eßer
11444d4804dSStefan Eßer
11544d4804dSStefan Eßer# Write a string to output, checking all of the characters are output,
11644d4804dSStefan Eßer# one-by-one.
11744d4804dSStefan Eßerdef write_str(child, s):
11844d4804dSStefan Eßer	for c in s:
119d43fa8efSStefan Eßer		send(child, c)
12044d4804dSStefan Eßer		if c in escapes:
121d43fa8efSStefan Eßer			expect(child, "\\{}".format(c))
12244d4804dSStefan Eßer		else:
123d43fa8efSStefan Eßer			expect(child, c)
12444d4804dSStefan Eßer
12544d4804dSStefan Eßer
12644d4804dSStefan Eßer# Check the bc banner.
12744d4804dSStefan Eßer# @param child  The child process.
12844d4804dSStefan Eßerdef bc_banner(child):
12944d4804dSStefan Eßer	bc_banner1 = "bc [0-9]+\.[0-9]+\.[0-9]+\r\n"
13044d4804dSStefan Eßer	bc_banner2 = "Copyright \(c\) 2018-[2-9][0-9][0-9][0-9] Gavin D. Howard and contributors\r\n"
1314fca8e0fSStefan Eßer	bc_banner3 = "Report bugs at: https://git.gavinhoward.com/gavin/bc\r\n\r\n"
13244d4804dSStefan Eßer	bc_banner4 = "This is free software with ABSOLUTELY NO WARRANTY.\r\n\r\n"
133d43fa8efSStefan Eßer	expect(child, bc_banner1)
134d43fa8efSStefan Eßer	expect(child, bc_banner2)
135d43fa8efSStefan Eßer	expect(child, bc_banner3)
136d43fa8efSStefan Eßer	expect(child, bc_banner4)
137d43fa8efSStefan Eßer	expect(child, prompt)
13844d4804dSStefan Eßer
13944d4804dSStefan Eßer
14044d4804dSStefan Eßer# Common UTF-8 testing function. The index is the index into utf8_stress_strs
14144d4804dSStefan Eßer# for which stress string to use.
14244d4804dSStefan Eßer# @param exe   The executable.
14344d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
14444d4804dSStefan Eßer# @param env   The environment.
14544d4804dSStefan Eßer# @param idx   The index of the UTF-8 stress string.
14644d4804dSStefan Eßerdef test_utf8(exe, args, env, idx, bc=True):
14744d4804dSStefan Eßer
14844d4804dSStefan Eßer	# Because both bc and dc use this, make sure the banner doesn't pop.
14944d4804dSStefan Eßer	env["BC_BANNER"] = "0"
15044d4804dSStefan Eßer
15144d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env, encoding='utf-8', codec_errors='ignore')
15244d4804dSStefan Eßer
15344d4804dSStefan Eßer	try:
15444d4804dSStefan Eßer
15544d4804dSStefan Eßer		# Write the stress string.
156d43fa8efSStefan Eßer		send(child, utf8_stress_strs[idx])
157d43fa8efSStefan Eßer		send(child, "\n")
15844d4804dSStefan Eßer
15944d4804dSStefan Eßer		if bc:
160d43fa8efSStefan Eßer			send(child, "quit")
16144d4804dSStefan Eßer		else:
162d43fa8efSStefan Eßer			send(child, "q")
16344d4804dSStefan Eßer
164d43fa8efSStefan Eßer		send(child, "\n")
16544d4804dSStefan Eßer
166d43fa8efSStefan Eßer		wait(child)
16744d4804dSStefan Eßer
16844d4804dSStefan Eßer	except pexpect.TIMEOUT:
169d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
17044d4804dSStefan Eßer		print("timed out")
17144d4804dSStefan Eßer		print(str(child))
17244d4804dSStefan Eßer		sys.exit(2)
17344d4804dSStefan Eßer	except pexpect.EOF:
17444d4804dSStefan Eßer		print("EOF")
17544d4804dSStefan Eßer		print(str(child))
17644d4804dSStefan Eßer		print(str(child.buffer))
17744d4804dSStefan Eßer		print(str(child.before))
17844d4804dSStefan Eßer		sys.exit(2)
17944d4804dSStefan Eßer
18044d4804dSStefan Eßer	return child
18144d4804dSStefan Eßer
18244d4804dSStefan Eßer# A random UTF-8 test with insert.
18344d4804dSStefan Eßer# @param exe   The executable.
18444d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
18544d4804dSStefan Eßer# @param env   The environment.
18644d4804dSStefan Eßerdef test_utf8_0(exe, args, env, bc=True):
18744d4804dSStefan Eßer
18844d4804dSStefan Eßer	# Because both bc and dc use this, make sure the banner doesn't pop.
18944d4804dSStefan Eßer	env["BC_BANNER"] = "0"
19044d4804dSStefan Eßer
19144d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env, encoding='utf-8', codec_errors='ignore')
19244d4804dSStefan Eßer
19344d4804dSStefan Eßer	try:
19444d4804dSStefan Eßer
19544d4804dSStefan Eßer		# Just random UTF-8 I generated somewhow, plus ensuring that insert works.
19644d4804dSStefan Eßer		write_str(child, "ﴪáá̵̗��ã")
197d43fa8efSStefan Eßer		send(child, "\x1b[D\x1b[D\x1b[D\x1b\x1b[Aℐ")
198d43fa8efSStefan Eßer		send(child, "\n")
19944d4804dSStefan Eßer
20044d4804dSStefan Eßer		if bc:
201d43fa8efSStefan Eßer			send(child, "quit")
20244d4804dSStefan Eßer		else:
203d43fa8efSStefan Eßer			send(child, "q")
20444d4804dSStefan Eßer
205d43fa8efSStefan Eßer		send(child, "\n")
206d43fa8efSStefan Eßer		eat(child)
20744d4804dSStefan Eßer
208d43fa8efSStefan Eßer		wait(child)
20944d4804dSStefan Eßer
21044d4804dSStefan Eßer	except pexpect.TIMEOUT:
211d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
21244d4804dSStefan Eßer		print("timed out")
21344d4804dSStefan Eßer		print(str(child))
21444d4804dSStefan Eßer		sys.exit(2)
21544d4804dSStefan Eßer	except pexpect.EOF:
21644d4804dSStefan Eßer		print("EOF")
21744d4804dSStefan Eßer		print(str(child))
21844d4804dSStefan Eßer		print(str(child.buffer))
21944d4804dSStefan Eßer		print(str(child.before))
22044d4804dSStefan Eßer		sys.exit(2)
22144d4804dSStefan Eßer
22244d4804dSStefan Eßer	return child
22344d4804dSStefan Eßer
22444d4804dSStefan Eßer
22544d4804dSStefan Eßerdef test_utf8_1(exe, args, env, bc=True):
22644d4804dSStefan Eßer	return test_utf8(exe, args, env, 0, bc)
22744d4804dSStefan Eßer
22844d4804dSStefan Eßer
22944d4804dSStefan Eßerdef test_utf8_2(exe, args, env, bc=True):
23044d4804dSStefan Eßer	return test_utf8(exe, args, env, 1, bc)
23144d4804dSStefan Eßer
23244d4804dSStefan Eßer
23344d4804dSStefan Eßerdef test_utf8_3(exe, args, env, bc=True):
23444d4804dSStefan Eßer	return test_utf8(exe, args, env, 2, bc)
23544d4804dSStefan Eßer
23644d4804dSStefan Eßer
23744d4804dSStefan Eßerdef test_utf8_4(exe, args, env, bc=True):
23844d4804dSStefan Eßer	return test_utf8(exe, args, env, 3, bc)
23944d4804dSStefan Eßer
24044d4804dSStefan Eßer
24144d4804dSStefan Eßer# This tests a SIGINT with reset followed by a SIGQUIT.
24244d4804dSStefan Eßer# @param exe   The executable.
24344d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
24444d4804dSStefan Eßer# @param env   The environment.
24544d4804dSStefan Eßerdef test_sigint_sigquit(exe, args, env):
24644d4804dSStefan Eßer
247d43fa8efSStefan Eßer	# Because both bc and dc use this, make sure the banner doesn't pop.
248d43fa8efSStefan Eßer	env["BC_BANNER"] = "0"
249d43fa8efSStefan Eßer
25044d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
25144d4804dSStefan Eßer
25244d4804dSStefan Eßer	try:
253d43fa8efSStefan Eßer		send(child, "\t")
25478bc019dSStefan Eßer		expect(child, "\t")
255d43fa8efSStefan Eßer		send(child, "\x03")
25610041e99SStefan Eßer		# send(child, "\x1c")
257d43fa8efSStefan Eßer		wait(child)
25844d4804dSStefan Eßer	except pexpect.TIMEOUT:
259d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
26044d4804dSStefan Eßer		print("timed out")
26144d4804dSStefan Eßer		print(str(child))
26244d4804dSStefan Eßer		sys.exit(2)
26344d4804dSStefan Eßer	except pexpect.EOF:
26444d4804dSStefan Eßer		print("EOF")
26544d4804dSStefan Eßer		print(str(child))
26644d4804dSStefan Eßer		print(str(child.buffer))
26744d4804dSStefan Eßer		print(str(child.before))
26844d4804dSStefan Eßer		sys.exit(2)
26944d4804dSStefan Eßer
27044d4804dSStefan Eßer	return child
27144d4804dSStefan Eßer
27244d4804dSStefan Eßer
27344d4804dSStefan Eßer# Test for EOF.
27444d4804dSStefan Eßer# @param exe   The executable.
27544d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
27644d4804dSStefan Eßer# @param env   The environment.
27744d4804dSStefan Eßerdef test_eof(exe, args, env):
27844d4804dSStefan Eßer
279d43fa8efSStefan Eßer	# Because both bc and dc use this, make sure the banner doesn't pop.
280d43fa8efSStefan Eßer	env["BC_BANNER"] = "0"
281d43fa8efSStefan Eßer
28244d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
28344d4804dSStefan Eßer
28444d4804dSStefan Eßer	try:
285bbd60e2cSStefan Eßer		send(child, "123")
286bbd60e2cSStefan Eßer		expect(child, "123")
287bbd60e2cSStefan Eßer		send(child, "\x01")
288bbd60e2cSStefan Eßer		send(child, "\x04")
289bbd60e2cSStefan Eßer		send(child, "\x04")
290d43fa8efSStefan Eßer		send(child, "\x04")
291d43fa8efSStefan Eßer		wait(child)
29244d4804dSStefan Eßer	except pexpect.TIMEOUT:
293d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
29444d4804dSStefan Eßer		print("timed out")
29544d4804dSStefan Eßer		print(str(child))
29644d4804dSStefan Eßer		sys.exit(2)
29744d4804dSStefan Eßer	except pexpect.EOF:
29844d4804dSStefan Eßer		print("EOF")
29944d4804dSStefan Eßer		print(str(child))
30044d4804dSStefan Eßer		print(str(child.buffer))
30144d4804dSStefan Eßer		print(str(child.before))
30244d4804dSStefan Eßer		sys.exit(2)
30344d4804dSStefan Eßer
30444d4804dSStefan Eßer	return child
30544d4804dSStefan Eßer
30644d4804dSStefan Eßer
30744d4804dSStefan Eßer# Test for quiting SIGINT.
30844d4804dSStefan Eßer# @param exe   The executable.
30944d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
31044d4804dSStefan Eßer# @param env   The environment.
31144d4804dSStefan Eßerdef test_sigint(exe, args, env):
31244d4804dSStefan Eßer
313d43fa8efSStefan Eßer	# Because both bc and dc use this, make sure the banner doesn't pop.
314d43fa8efSStefan Eßer	env["BC_BANNER"] = "0"
315d43fa8efSStefan Eßer
31644d4804dSStefan Eßer	env["BC_SIGINT_RESET"] = "0"
31744d4804dSStefan Eßer	env["DC_SIGINT_RESET"] = "0"
31844d4804dSStefan Eßer
31944d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
32044d4804dSStefan Eßer
32144d4804dSStefan Eßer	try:
322d43fa8efSStefan Eßer		send(child, "\t")
32378bc019dSStefan Eßer		expect(child, "\t")
324d43fa8efSStefan Eßer		send(child, "\x03")
325d43fa8efSStefan Eßer		wait(child)
32644d4804dSStefan Eßer	except pexpect.TIMEOUT:
327d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
32844d4804dSStefan Eßer		print("timed out")
32944d4804dSStefan Eßer		print(str(child))
33044d4804dSStefan Eßer		sys.exit(2)
33144d4804dSStefan Eßer	except pexpect.EOF:
33244d4804dSStefan Eßer		print("EOF")
33344d4804dSStefan Eßer		print(str(child))
33444d4804dSStefan Eßer		print(str(child.buffer))
33544d4804dSStefan Eßer		print(str(child.before))
33644d4804dSStefan Eßer		sys.exit(2)
33744d4804dSStefan Eßer
33844d4804dSStefan Eßer	return child
33944d4804dSStefan Eßer
34044d4804dSStefan Eßer
34144d4804dSStefan Eßer# Test for SIGTSTP.
34244d4804dSStefan Eßer# @param exe   The executable.
34344d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
34444d4804dSStefan Eßer# @param env   The environment.
34544d4804dSStefan Eßerdef test_sigtstp(exe, args, env):
34644d4804dSStefan Eßer
347d43fa8efSStefan Eßer	# This test does not work on FreeBSD, so skip.
348d43fa8efSStefan Eßer	if sys.platform.startswith("freebsd"):
349d43fa8efSStefan Eßer		sys.exit(0)
350d43fa8efSStefan Eßer
351d43fa8efSStefan Eßer	# Because both bc and dc use this, make sure the banner doesn't pop.
352d43fa8efSStefan Eßer	env["BC_BANNER"] = "0"
353d43fa8efSStefan Eßer
35444d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
35544d4804dSStefan Eßer
35644d4804dSStefan Eßer	try:
357d43fa8efSStefan Eßer		send(child, "\t")
35878bc019dSStefan Eßer		expect(child, "\t")
359d43fa8efSStefan Eßer		send(child, "\x13")
36044d4804dSStefan Eßer		time.sleep(1)
36144d4804dSStefan Eßer		if not child.isalive():
36244d4804dSStefan Eßer			print("child exited early")
36344d4804dSStefan Eßer			print(str(child))
36444d4804dSStefan Eßer			print(str(child.buffer))
36544d4804dSStefan Eßer			sys.exit(1)
36644d4804dSStefan Eßer		child.kill(signal.SIGCONT)
367d43fa8efSStefan Eßer		send(child, "quit")
368d43fa8efSStefan Eßer		send(child, "\n")
369d43fa8efSStefan Eßer		wait(child)
37044d4804dSStefan Eßer	except pexpect.TIMEOUT:
371d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
37244d4804dSStefan Eßer		print("timed out")
37344d4804dSStefan Eßer		print(str(child))
37444d4804dSStefan Eßer		sys.exit(2)
37544d4804dSStefan Eßer	except pexpect.EOF:
37644d4804dSStefan Eßer		print("EOF")
37744d4804dSStefan Eßer		print(str(child))
37844d4804dSStefan Eßer		print(str(child.buffer))
37944d4804dSStefan Eßer		print(str(child.before))
38044d4804dSStefan Eßer		sys.exit(2)
38144d4804dSStefan Eßer
38244d4804dSStefan Eßer	return child
38344d4804dSStefan Eßer
38444d4804dSStefan Eßer
38544d4804dSStefan Eßer# Test for SIGSTOP.
38644d4804dSStefan Eßer# @param exe   The executable.
38744d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
38844d4804dSStefan Eßer# @param env   The environment.
38944d4804dSStefan Eßerdef test_sigstop(exe, args, env):
39044d4804dSStefan Eßer
391d43fa8efSStefan Eßer	# Because both bc and dc use this, make sure the banner doesn't pop.
392d43fa8efSStefan Eßer	env["BC_BANNER"] = "0"
393d43fa8efSStefan Eßer
39444d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
39544d4804dSStefan Eßer
39644d4804dSStefan Eßer	try:
397d43fa8efSStefan Eßer		send(child, "\t")
39878bc019dSStefan Eßer		expect(child, "\t")
399d43fa8efSStefan Eßer		send(child, "\x14")
40044d4804dSStefan Eßer		time.sleep(1)
40144d4804dSStefan Eßer		if not child.isalive():
40244d4804dSStefan Eßer			print("child exited early")
40344d4804dSStefan Eßer			print(str(child))
40444d4804dSStefan Eßer			print(str(child.buffer))
40544d4804dSStefan Eßer			sys.exit(1)
406d43fa8efSStefan Eßer		send(child, "\x13")
40744d4804dSStefan Eßer		time.sleep(1)
40844d4804dSStefan Eßer		if not child.isalive():
40944d4804dSStefan Eßer			print("child exited early")
41044d4804dSStefan Eßer			print(str(child))
41144d4804dSStefan Eßer			print(str(child.buffer))
41244d4804dSStefan Eßer			sys.exit(1)
41344d4804dSStefan Eßer		child.kill(signal.SIGCONT)
414d43fa8efSStefan Eßer		send(child, "quit")
415d43fa8efSStefan Eßer		send(child, "\n")
416d43fa8efSStefan Eßer		wait(child)
41744d4804dSStefan Eßer	except pexpect.TIMEOUT:
418d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
41944d4804dSStefan Eßer		print("timed out")
42044d4804dSStefan Eßer		print(str(child))
42144d4804dSStefan Eßer		sys.exit(2)
42244d4804dSStefan Eßer	except pexpect.EOF:
42344d4804dSStefan Eßer		print("EOF")
42444d4804dSStefan Eßer		print(str(child))
42544d4804dSStefan Eßer		print(str(child.buffer))
42644d4804dSStefan Eßer		print(str(child.before))
42744d4804dSStefan Eßer		sys.exit(2)
42844d4804dSStefan Eßer
42944d4804dSStefan Eßer	return child
43044d4804dSStefan Eßer
43144d4804dSStefan Eßer
43244d4804dSStefan Eßerdef test_bc_utf8_0(exe, args, env):
43344d4804dSStefan Eßer	return test_utf8_0(exe, args, env, True)
43444d4804dSStefan Eßer
43544d4804dSStefan Eßer
43644d4804dSStefan Eßerdef test_bc_utf8_1(exe, args, env):
43744d4804dSStefan Eßer	return test_utf8_1(exe, args, env, True)
43844d4804dSStefan Eßer
43944d4804dSStefan Eßer
44044d4804dSStefan Eßerdef test_bc_utf8_2(exe, args, env):
44144d4804dSStefan Eßer	return test_utf8_2(exe, args, env, True)
44244d4804dSStefan Eßer
44344d4804dSStefan Eßer
44444d4804dSStefan Eßerdef test_bc_utf8_3(exe, args, env):
44544d4804dSStefan Eßer	return test_utf8_3(exe, args, env, True)
44644d4804dSStefan Eßer
44744d4804dSStefan Eßer
44844d4804dSStefan Eßerdef test_bc_utf8_4(exe, args, env):
44944d4804dSStefan Eßer	return test_utf8_4(exe, args, env, True)
45044d4804dSStefan Eßer
45144d4804dSStefan Eßer
45244d4804dSStefan Eßer# Basic bc test.
45344d4804dSStefan Eßer# @param exe   The executable.
45444d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
45544d4804dSStefan Eßer# @param env   The environment.
45644d4804dSStefan Eßerdef test_bc1(exe, args, env):
45744d4804dSStefan Eßer
45844d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
45944d4804dSStefan Eßer
46044d4804dSStefan Eßer	try:
46144d4804dSStefan Eßer		bc_banner(child)
46244d4804dSStefan Eßer		write_str(child, "1")
46344d4804dSStefan Eßer		check_line(child, "1")
46444d4804dSStefan Eßer		write_str(child, "1")
46544d4804dSStefan Eßer		check_line(child, "1")
466d43fa8efSStefan Eßer		send(child, "quit")
467d43fa8efSStefan Eßer		send(child, "\n")
468d43fa8efSStefan Eßer		wait(child)
46944d4804dSStefan Eßer	except pexpect.TIMEOUT:
470d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
47144d4804dSStefan Eßer		print("timed out")
47244d4804dSStefan Eßer		print(str(child))
47344d4804dSStefan Eßer		sys.exit(2)
47444d4804dSStefan Eßer	except pexpect.EOF:
47544d4804dSStefan Eßer		print("EOF")
47644d4804dSStefan Eßer		print(str(child))
47744d4804dSStefan Eßer		print(str(child.buffer))
47844d4804dSStefan Eßer		print(str(child.before))
47944d4804dSStefan Eßer		sys.exit(2)
48044d4804dSStefan Eßer
48144d4804dSStefan Eßer	return child
48244d4804dSStefan Eßer
48344d4804dSStefan Eßer
48444d4804dSStefan Eßer# SIGINT with no history.
48544d4804dSStefan Eßer# @param exe   The executable.
48644d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
48744d4804dSStefan Eßer# @param env   The environment.
48844d4804dSStefan Eßerdef test_bc2(exe, args, env):
48944d4804dSStefan Eßer
49044d4804dSStefan Eßer	env["TERM"] = "dumb"
49144d4804dSStefan Eßer
49244d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
49344d4804dSStefan Eßer
49444d4804dSStefan Eßer	try:
49544d4804dSStefan Eßer		bc_banner(child)
49644d4804dSStefan Eßer		child.sendline("1")
49744d4804dSStefan Eßer		check_line(child, "1", history=False)
49844d4804dSStefan Eßer		time.sleep(1)
49944d4804dSStefan Eßer		child.sendintr()
50044d4804dSStefan Eßer		child.sendline("quit")
501d43fa8efSStefan Eßer		wait(child)
50244d4804dSStefan Eßer	except pexpect.TIMEOUT:
503d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
50444d4804dSStefan Eßer		print("timed out")
50544d4804dSStefan Eßer		print(str(child))
50644d4804dSStefan Eßer		sys.exit(2)
50744d4804dSStefan Eßer	except pexpect.EOF:
50844d4804dSStefan Eßer		print("EOF")
50944d4804dSStefan Eßer		print(str(child))
51044d4804dSStefan Eßer		print(str(child.buffer))
51144d4804dSStefan Eßer		print(str(child.before))
51244d4804dSStefan Eßer		sys.exit(2)
51344d4804dSStefan Eßer
51444d4804dSStefan Eßer	return child
51544d4804dSStefan Eßer
51644d4804dSStefan Eßer
51744d4804dSStefan Eßer# Left and right arrows.
51844d4804dSStefan Eßer# @param exe   The executable.
51944d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
52044d4804dSStefan Eßer# @param env   The environment.
52144d4804dSStefan Eßerdef test_bc3(exe, args, env):
52244d4804dSStefan Eßer
52344d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
52444d4804dSStefan Eßer
52544d4804dSStefan Eßer	try:
52644d4804dSStefan Eßer		bc_banner(child)
527d43fa8efSStefan Eßer		send(child, "\x1b[D\x1b[D\x1b[C\x1b[C")
528d43fa8efSStefan Eßer		send(child, "\n")
529d43fa8efSStefan Eßer		expect(child, prompt)
530d43fa8efSStefan Eßer		send(child, "12\x1b[D3\x1b[C4\x1bOD5\x1bOC6")
531d43fa8efSStefan Eßer		send(child, "\n")
53244d4804dSStefan Eßer		check_line(child, "132546")
533d43fa8efSStefan Eßer		send(child, "12\x023\x064")
534d43fa8efSStefan Eßer		send(child, "\n")
53544d4804dSStefan Eßer		check_line(child, "1324")
536d43fa8efSStefan Eßer		send(child, "12\x1b[H3\x1bOH\x01\x1b[H45\x1bOF6\x05\x1b[F7\x1bOH8")
537d43fa8efSStefan Eßer		send(child, "\n")
53844d4804dSStefan Eßer		check_line(child, "84531267")
539d43fa8efSStefan Eßer		send(child, "quit")
540d43fa8efSStefan Eßer		send(child, "\n")
541d43fa8efSStefan Eßer		wait(child)
54244d4804dSStefan Eßer	except pexpect.TIMEOUT:
543d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
54444d4804dSStefan Eßer		print("timed out")
54544d4804dSStefan Eßer		print(str(child))
54644d4804dSStefan Eßer		sys.exit(2)
54744d4804dSStefan Eßer	except pexpect.EOF:
54844d4804dSStefan Eßer		print("EOF")
54944d4804dSStefan Eßer		print(str(child))
55044d4804dSStefan Eßer		print(str(child.buffer))
55144d4804dSStefan Eßer		print(str(child.before))
55244d4804dSStefan Eßer		sys.exit(2)
55344d4804dSStefan Eßer
55444d4804dSStefan Eßer	return child
55544d4804dSStefan Eßer
55644d4804dSStefan Eßer
55744d4804dSStefan Eßer# Up and down arrows.
55844d4804dSStefan Eßer# @param exe   The executable.
55944d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
56044d4804dSStefan Eßer# @param env   The environment.
56144d4804dSStefan Eßerdef test_bc4(exe, args, env):
56244d4804dSStefan Eßer
56344d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
56444d4804dSStefan Eßer
56544d4804dSStefan Eßer	try:
56644d4804dSStefan Eßer		bc_banner(child)
567d43fa8efSStefan Eßer		send(child, "\x1b[A\x1bOA\x1b[B\x1bOB")
568d43fa8efSStefan Eßer		send(child, "\n")
569d43fa8efSStefan Eßer		expect(child, prompt)
57044d4804dSStefan Eßer		write_str(child, "15")
57144d4804dSStefan Eßer		check_line(child, "15")
57244d4804dSStefan Eßer		write_str(child, "2^16")
57344d4804dSStefan Eßer		check_line(child, "65536")
574d43fa8efSStefan Eßer		send(child, "\x1b[A\x1bOA")
575d43fa8efSStefan Eßer		send(child, "\n")
57644d4804dSStefan Eßer		check_line(child, "15")
577d43fa8efSStefan Eßer		send(child, "\x1b[A\x1bOA\x1b[A\x1b[B")
57844d4804dSStefan Eßer		check_line(child, "65536")
579d43fa8efSStefan Eßer		send(child, "\x1b[A\x1bOA\x0e\x1b[A\x1b[A\x1b[A\x1b[B\x10\x1b[B\x1b[B\x1bOB\x1b[B\x1bOA")
580d43fa8efSStefan Eßer		send(child, "\n")
58144d4804dSStefan Eßer		check_line(child, "65536")
582d43fa8efSStefan Eßer		send(child, "quit")
583d43fa8efSStefan Eßer		send(child, "\n")
584d43fa8efSStefan Eßer		wait(child)
58544d4804dSStefan Eßer	except pexpect.TIMEOUT:
586d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
58744d4804dSStefan Eßer		print("timed out")
58844d4804dSStefan Eßer		print(str(child))
58944d4804dSStefan Eßer		sys.exit(2)
59044d4804dSStefan Eßer	except pexpect.EOF:
59144d4804dSStefan Eßer		print("EOF")
59244d4804dSStefan Eßer		print(str(child))
59344d4804dSStefan Eßer		print(str(child.buffer))
59444d4804dSStefan Eßer		print(str(child.before))
59544d4804dSStefan Eßer		sys.exit(2)
59644d4804dSStefan Eßer
59744d4804dSStefan Eßer	return child
59844d4804dSStefan Eßer
59944d4804dSStefan Eßer
60044d4804dSStefan Eßer# Clear screen.
60144d4804dSStefan Eßer# @param exe   The executable.
60244d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
60344d4804dSStefan Eßer# @param env   The environment.
60444d4804dSStefan Eßerdef test_bc5(exe, args, env):
60544d4804dSStefan Eßer
60644d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
60744d4804dSStefan Eßer
60844d4804dSStefan Eßer	try:
60944d4804dSStefan Eßer		bc_banner(child)
610d43fa8efSStefan Eßer		send(child, "\x0c")
611d43fa8efSStefan Eßer		send(child, "quit")
612d43fa8efSStefan Eßer		send(child, "\n")
613d43fa8efSStefan Eßer		wait(child)
61444d4804dSStefan Eßer	except pexpect.TIMEOUT:
615d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
61644d4804dSStefan Eßer		print("timed out")
61744d4804dSStefan Eßer		print(str(child))
61844d4804dSStefan Eßer		sys.exit(2)
61944d4804dSStefan Eßer	except pexpect.EOF:
62044d4804dSStefan Eßer		print("EOF")
62144d4804dSStefan Eßer		print(str(child))
62244d4804dSStefan Eßer		print(str(child.buffer))
62344d4804dSStefan Eßer		print(str(child.before))
62444d4804dSStefan Eßer		sys.exit(2)
62544d4804dSStefan Eßer
62644d4804dSStefan Eßer	return child
62744d4804dSStefan Eßer
62844d4804dSStefan Eßer
62944d4804dSStefan Eßer# Printed material without a newline.
63044d4804dSStefan Eßer# @param exe   The executable.
63144d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
63244d4804dSStefan Eßer# @param env   The environment.
63344d4804dSStefan Eßerdef test_bc6(exe, args, env):
63444d4804dSStefan Eßer
63544d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
63644d4804dSStefan Eßer
63744d4804dSStefan Eßer	try:
63844d4804dSStefan Eßer		bc_banner(child)
639d43fa8efSStefan Eßer		send(child, "print \"Enter number: \"")
640d43fa8efSStefan Eßer		send(child, "\n")
641d43fa8efSStefan Eßer		expect(child, "Enter number: ")
642d43fa8efSStefan Eßer		send(child, "4\x1b[A\x1b[A")
643d43fa8efSStefan Eßer		send(child, "\n")
644d43fa8efSStefan Eßer		send(child, "quit")
645d43fa8efSStefan Eßer		send(child, "\n")
646d43fa8efSStefan Eßer		wait(child)
64744d4804dSStefan Eßer	except pexpect.TIMEOUT:
648d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
64944d4804dSStefan Eßer		print("timed out")
65044d4804dSStefan Eßer		print(str(child))
65144d4804dSStefan Eßer		sys.exit(2)
65244d4804dSStefan Eßer	except pexpect.EOF:
65344d4804dSStefan Eßer		print("EOF")
65444d4804dSStefan Eßer		print(str(child))
65544d4804dSStefan Eßer		print(str(child.buffer))
65644d4804dSStefan Eßer		print(str(child.before))
65744d4804dSStefan Eßer		sys.exit(2)
65844d4804dSStefan Eßer
65944d4804dSStefan Eßer	return child
66044d4804dSStefan Eßer
66144d4804dSStefan Eßer
66244d4804dSStefan Eßer# Word start and word end.
66344d4804dSStefan Eßer# @param exe   The executable.
66444d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
66544d4804dSStefan Eßer# @param env   The environment.
66644d4804dSStefan Eßerdef test_bc7(exe, args, env):
66744d4804dSStefan Eßer
66844d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
66944d4804dSStefan Eßer
67044d4804dSStefan Eßer	try:
67144d4804dSStefan Eßer		bc_banner(child)
672d43fa8efSStefan Eßer		send(child, "\x1bb\x1bb\x1bf\x1bf")
673d43fa8efSStefan Eßer		send(child, "\n")
674d43fa8efSStefan Eßer		expect(child, prompt)
675d43fa8efSStefan Eßer		send(child, "\x1b[0~\x1b[3a")
676d43fa8efSStefan Eßer		send(child, "\n")
677d43fa8efSStefan Eßer		expect(child, prompt)
678d43fa8efSStefan Eßer		send(child, "\x1b[0;4\x1b[0A")
679d43fa8efSStefan Eßer		send(child, "\n")
680d43fa8efSStefan Eßer		expect(child, prompt)
68178bc019dSStefan Eßer		send(child, "\t")
682d43fa8efSStefan Eßer		send(child, "\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb")
683d43fa8efSStefan Eßer		send(child, "\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf")
684d43fa8efSStefan Eßer		send(child, "\n")
685d43fa8efSStefan Eßer		expect(child, prompt)
68644d4804dSStefan Eßer		write_str(child, "12 + 34 + 56 + 78 + 90")
68744d4804dSStefan Eßer		check_line(child, "270")
688d43fa8efSStefan Eßer		send(child, "\x1b[A")
689d43fa8efSStefan Eßer		send(child, "\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb")
690d43fa8efSStefan Eßer		send(child, "\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf")
69144d4804dSStefan Eßer		check_line(child, "270")
692d43fa8efSStefan Eßer		send(child, "\x1b[A")
693d43fa8efSStefan Eßer		send(child, "\x1bh\x1bh\x1bf + 14 ")
694d43fa8efSStefan Eßer		send(child, "\n")
69544d4804dSStefan Eßer		check_line(child, "284")
696d43fa8efSStefan Eßer		send(child, "quit")
697d43fa8efSStefan Eßer		send(child, "\n")
698d43fa8efSStefan Eßer		wait(child)
69944d4804dSStefan Eßer	except pexpect.TIMEOUT:
700d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
70144d4804dSStefan Eßer		print("timed out")
70244d4804dSStefan Eßer		print(str(child))
70344d4804dSStefan Eßer		sys.exit(2)
70444d4804dSStefan Eßer	except pexpect.EOF:
70544d4804dSStefan Eßer		print("EOF")
70644d4804dSStefan Eßer		print(str(child))
70744d4804dSStefan Eßer		print(str(child.buffer))
70844d4804dSStefan Eßer		print(str(child.before))
70944d4804dSStefan Eßer		sys.exit(2)
71044d4804dSStefan Eßer
71144d4804dSStefan Eßer	return child
71244d4804dSStefan Eßer
71344d4804dSStefan Eßer
71444d4804dSStefan Eßer# Backspace.
71544d4804dSStefan Eßer# @param exe   The executable.
71644d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
71744d4804dSStefan Eßer# @param env   The environment.
71844d4804dSStefan Eßerdef test_bc8(exe, args, env):
71944d4804dSStefan Eßer
72044d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
72144d4804dSStefan Eßer
72244d4804dSStefan Eßer	try:
72344d4804dSStefan Eßer		bc_banner(child)
724d43fa8efSStefan Eßer		send(child, "12\x1b[D3\x1b[C4\x08\x7f")
725d43fa8efSStefan Eßer		send(child, "\n")
72644d4804dSStefan Eßer		check_line(child, "13")
727d43fa8efSStefan Eßer		send(child, "quit")
728d43fa8efSStefan Eßer		send(child, "\n")
729d43fa8efSStefan Eßer		wait(child)
73044d4804dSStefan Eßer	except pexpect.TIMEOUT:
731d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
73244d4804dSStefan Eßer		print("timed out")
73344d4804dSStefan Eßer		print(str(child))
73444d4804dSStefan Eßer		sys.exit(2)
73544d4804dSStefan Eßer	except pexpect.EOF:
73644d4804dSStefan Eßer		print("EOF")
73744d4804dSStefan Eßer		print(str(child))
73844d4804dSStefan Eßer		print(str(child.buffer))
73944d4804dSStefan Eßer		print(str(child.before))
74044d4804dSStefan Eßer		sys.exit(2)
74144d4804dSStefan Eßer
74244d4804dSStefan Eßer	return child
74344d4804dSStefan Eßer
74444d4804dSStefan Eßer
74544d4804dSStefan Eßer# Backspace and delete words.
74644d4804dSStefan Eßer# @param exe   The executable.
74744d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
74844d4804dSStefan Eßer# @param env   The environment.
74944d4804dSStefan Eßerdef test_bc9(exe, args, env):
75044d4804dSStefan Eßer
75144d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
75244d4804dSStefan Eßer
75344d4804dSStefan Eßer	try:
75444d4804dSStefan Eßer		bc_banner(child)
755d43fa8efSStefan Eßer		send(child, "\x1b[0;5D\x1b[0;5D\x1b[0;5D\x1b[0;5C\x1b[0;5D\x1bd\x1b[3~\x1b[d\x1b[d\x1b[d\x1b[d\x7f\x7f\x7f")
756d43fa8efSStefan Eßer		send(child, "\n")
757d43fa8efSStefan Eßer		expect(child, prompt)
75844d4804dSStefan Eßer		write_str(child, "12 + 34 + 56 + 78 + 90")
75944d4804dSStefan Eßer		check_line(child, "270")
760d43fa8efSStefan Eßer		send(child, "\x1b[A")
761d43fa8efSStefan Eßer		send(child, "\x1b[0;5D\x1b[0;5D\x1b[0;5D\x1b[0;5C\x1b[0;5D\x1bd\x1b[3~\x1b[d\x1b[d\x1b[d\x1b[d\x7f\x7f\x7f")
762d43fa8efSStefan Eßer		send(child, "\n")
76344d4804dSStefan Eßer		check_line(child, "102")
764d43fa8efSStefan Eßer		send(child, "\x1b[A")
765d43fa8efSStefan Eßer		send(child, "\x17\x17")
766d43fa8efSStefan Eßer		send(child, "\n")
76744d4804dSStefan Eßer		check_line(child, "46")
768d43fa8efSStefan Eßer		send(child, "\x17\x17")
769d43fa8efSStefan Eßer		send(child, "\n")
770d43fa8efSStefan Eßer		expect(child, prompt)
771d43fa8efSStefan Eßer		send(child, "quit")
772d43fa8efSStefan Eßer		send(child, "\n")
773d43fa8efSStefan Eßer		wait(child)
77444d4804dSStefan Eßer	except pexpect.TIMEOUT:
775d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
77644d4804dSStefan Eßer		print("timed out")
77744d4804dSStefan Eßer		print(str(child))
77844d4804dSStefan Eßer		sys.exit(2)
77944d4804dSStefan Eßer	except pexpect.EOF:
78044d4804dSStefan Eßer		print("EOF")
78144d4804dSStefan Eßer		print(str(child))
78244d4804dSStefan Eßer		print(str(child.buffer))
78344d4804dSStefan Eßer		print(str(child.before))
78444d4804dSStefan Eßer		sys.exit(2)
78544d4804dSStefan Eßer
78644d4804dSStefan Eßer	return child
78744d4804dSStefan Eßer
78844d4804dSStefan Eßer
78944d4804dSStefan Eßer# Backspace and delete words 2.
79044d4804dSStefan Eßer# @param exe   The executable.
79144d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
79244d4804dSStefan Eßer# @param env   The environment.
79344d4804dSStefan Eßerdef test_bc10(exe, args, env):
79444d4804dSStefan Eßer
79544d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
79644d4804dSStefan Eßer
79744d4804dSStefan Eßer	try:
79844d4804dSStefan Eßer		bc_banner(child)
799d43fa8efSStefan Eßer		send(child, "\x1b[3~\x1b[3~")
800d43fa8efSStefan Eßer		send(child, "\n")
801d43fa8efSStefan Eßer		expect(child, prompt)
802d43fa8efSStefan Eßer		send(child, "    \x1b[3~\x1b[3~")
803d43fa8efSStefan Eßer		send(child, "\n")
804d43fa8efSStefan Eßer		expect(child, prompt)
80544d4804dSStefan Eßer		write_str(child, "12 + 34 + 56 + 78 + 90")
80644d4804dSStefan Eßer		check_line(child, "270")
807d43fa8efSStefan Eßer		send(child, "\x1b[A\x1b[A\x1b[A\x1b[B\x1b[B\x1b[B\x1b[A")
808d43fa8efSStefan Eßer		send(child, "\n")
80944d4804dSStefan Eßer		check_line(child, "270")
810d43fa8efSStefan Eßer		send(child, "\x1b[A\x1b[0;5D\x1b[0;5D\x0b")
811d43fa8efSStefan Eßer		send(child, "\n")
81244d4804dSStefan Eßer		check_line(child, "180")
813d43fa8efSStefan Eßer		send(child, "\x1b[A\x1521")
81444d4804dSStefan Eßer		check_line(child, "21")
815d43fa8efSStefan Eßer		send(child, "quit")
816d43fa8efSStefan Eßer		send(child, "\n")
817d43fa8efSStefan Eßer		wait(child)
81844d4804dSStefan Eßer	except pexpect.TIMEOUT:
819d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
82044d4804dSStefan Eßer		print("timed out")
82144d4804dSStefan Eßer		print(str(child))
82244d4804dSStefan Eßer		sys.exit(2)
82344d4804dSStefan Eßer	except pexpect.EOF:
82444d4804dSStefan Eßer		print("EOF")
82544d4804dSStefan Eßer		print(str(child))
82644d4804dSStefan Eßer		print(str(child.buffer))
82744d4804dSStefan Eßer		print(str(child.before))
82844d4804dSStefan Eßer		sys.exit(2)
82944d4804dSStefan Eßer
83044d4804dSStefan Eßer	return child
83144d4804dSStefan Eßer
83244d4804dSStefan Eßer
83344d4804dSStefan Eßer# Swap.
83444d4804dSStefan Eßer# @param exe   The executable.
83544d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
83644d4804dSStefan Eßer# @param env   The environment.
83744d4804dSStefan Eßerdef test_bc11(exe, args, env):
83844d4804dSStefan Eßer
83944d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
84044d4804dSStefan Eßer
84144d4804dSStefan Eßer	try:
84244d4804dSStefan Eßer		bc_banner(child)
843d43fa8efSStefan Eßer		send(child, "\x1b[A\x02\x14")
844d43fa8efSStefan Eßer		send(child, "\n")
845d43fa8efSStefan Eßer		expect(child, prompt)
84644d4804dSStefan Eßer		write_str(child, "12 + 34 + 56 + 78")
84744d4804dSStefan Eßer		check_line(child, "180")
848d43fa8efSStefan Eßer		send(child, "\x1b[A\x02\x14")
84944d4804dSStefan Eßer		check_line(child, "189")
850d43fa8efSStefan Eßer		send(child, "quit")
851d43fa8efSStefan Eßer		send(child, "\n")
852d43fa8efSStefan Eßer		wait(child)
85344d4804dSStefan Eßer	except pexpect.TIMEOUT:
854d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
85544d4804dSStefan Eßer		print("timed out")
85644d4804dSStefan Eßer		print(str(child))
85744d4804dSStefan Eßer		sys.exit(2)
85844d4804dSStefan Eßer	except pexpect.EOF:
85944d4804dSStefan Eßer		print("EOF")
86044d4804dSStefan Eßer		print(str(child))
86144d4804dSStefan Eßer		print(str(child.buffer))
86244d4804dSStefan Eßer		print(str(child.before))
86344d4804dSStefan Eßer		sys.exit(2)
86444d4804dSStefan Eßer
86544d4804dSStefan Eßer	return child
86644d4804dSStefan Eßer
86744d4804dSStefan Eßer
86844d4804dSStefan Eßer# Non-fatal error.
86944d4804dSStefan Eßer# @param exe   The executable.
87044d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
87144d4804dSStefan Eßer# @param env   The environment.
87244d4804dSStefan Eßerdef test_bc12(exe, args, env):
87344d4804dSStefan Eßer
87444d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
87544d4804dSStefan Eßer
87644d4804dSStefan Eßer	try:
87744d4804dSStefan Eßer		bc_banner(child)
878d43fa8efSStefan Eßer		send(child, "12 +")
879d43fa8efSStefan Eßer		send(child, "\n")
88044d4804dSStefan Eßer		time.sleep(1)
88144d4804dSStefan Eßer		if not child.isalive():
88244d4804dSStefan Eßer			print("child exited early")
88344d4804dSStefan Eßer			print(str(child))
88444d4804dSStefan Eßer			print(str(child.buffer))
88544d4804dSStefan Eßer			sys.exit(1)
886d43fa8efSStefan Eßer		send(child, "quit")
887d43fa8efSStefan Eßer		send(child, "\n")
888d43fa8efSStefan Eßer		wait(child)
88944d4804dSStefan Eßer	except pexpect.TIMEOUT:
890d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
89144d4804dSStefan Eßer		print("timed out")
89244d4804dSStefan Eßer		print(str(child))
89344d4804dSStefan Eßer		sys.exit(2)
89444d4804dSStefan Eßer	except pexpect.EOF:
89544d4804dSStefan Eßer		print("EOF")
89644d4804dSStefan Eßer		print(str(child))
89744d4804dSStefan Eßer		print(str(child.buffer))
89844d4804dSStefan Eßer		print(str(child.before))
89944d4804dSStefan Eßer		sys.exit(2)
90044d4804dSStefan Eßer
90144d4804dSStefan Eßer	return child
90244d4804dSStefan Eßer
90344d4804dSStefan Eßer
90444d4804dSStefan Eßerdef test_dc_utf8_0(exe, args, env):
90544d4804dSStefan Eßer	return test_utf8_0(exe, args, env, False)
90644d4804dSStefan Eßer
90744d4804dSStefan Eßer
90844d4804dSStefan Eßerdef test_dc_utf8_1(exe, args, env):
90944d4804dSStefan Eßer	return test_utf8_1(exe, args, env, False)
91044d4804dSStefan Eßer
91144d4804dSStefan Eßer
91244d4804dSStefan Eßerdef test_dc_utf8_2(exe, args, env):
91344d4804dSStefan Eßer	return test_utf8_2(exe, args, env, False)
91444d4804dSStefan Eßer
91544d4804dSStefan Eßer
91644d4804dSStefan Eßerdef test_dc_utf8_3(exe, args, env):
91744d4804dSStefan Eßer	return test_utf8_3(exe, args, env, False)
91844d4804dSStefan Eßer
91944d4804dSStefan Eßer
92044d4804dSStefan Eßerdef test_dc_utf8_4(exe, args, env):
92144d4804dSStefan Eßer	return test_utf8_4(exe, args, env, False)
92244d4804dSStefan Eßer
92344d4804dSStefan Eßer
92444d4804dSStefan Eßer# Basic dc test.
92544d4804dSStefan Eßer# @param exe   The executable.
92644d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
92744d4804dSStefan Eßer# @param env   The environment.
92844d4804dSStefan Eßerdef test_dc1(exe, args, env):
92944d4804dSStefan Eßer
93044d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
93144d4804dSStefan Eßer
93244d4804dSStefan Eßer	try:
93344d4804dSStefan Eßer		write_str(child, "1pR")
93444d4804dSStefan Eßer		check_line(child, "1")
93544d4804dSStefan Eßer		write_str(child, "1pR")
93644d4804dSStefan Eßer		check_line(child, "1")
93744d4804dSStefan Eßer		write_str(child, "q")
938d43fa8efSStefan Eßer		send(child, "\n")
939d43fa8efSStefan Eßer		wait(child)
94044d4804dSStefan Eßer	except pexpect.TIMEOUT:
941d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
94244d4804dSStefan Eßer		print("timed out")
94344d4804dSStefan Eßer		print(str(child))
94444d4804dSStefan Eßer		sys.exit(2)
94544d4804dSStefan Eßer	except pexpect.EOF:
94644d4804dSStefan Eßer		print("EOF")
94744d4804dSStefan Eßer		print(str(child))
94844d4804dSStefan Eßer		print(str(child.buffer))
94944d4804dSStefan Eßer		print(str(child.before))
95044d4804dSStefan Eßer		sys.exit(2)
95144d4804dSStefan Eßer
95244d4804dSStefan Eßer	return child
95344d4804dSStefan Eßer
95444d4804dSStefan Eßer
95544d4804dSStefan Eßer# SIGINT with quit.
95644d4804dSStefan Eßer# @param exe   The executable.
95744d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
95844d4804dSStefan Eßer# @param env   The environment.
95944d4804dSStefan Eßerdef test_dc2(exe, args, env):
96044d4804dSStefan Eßer
96144d4804dSStefan Eßer	env["TERM"] = "dumb"
96244d4804dSStefan Eßer
96344d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
96444d4804dSStefan Eßer
96544d4804dSStefan Eßer	try:
96644d4804dSStefan Eßer		child.sendline("1pR")
96744d4804dSStefan Eßer		check_line(child, "1", history=False)
96844d4804dSStefan Eßer		time.sleep(1)
96944d4804dSStefan Eßer		child.sendintr()
97044d4804dSStefan Eßer		child.sendline("q")
971d43fa8efSStefan Eßer		wait(child)
97244d4804dSStefan Eßer	except pexpect.TIMEOUT:
973d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
97444d4804dSStefan Eßer		print("timed out")
97544d4804dSStefan Eßer		print(str(child))
97644d4804dSStefan Eßer		sys.exit(2)
97744d4804dSStefan Eßer	except pexpect.EOF:
97844d4804dSStefan Eßer		print("EOF")
97944d4804dSStefan Eßer		print(str(child))
98044d4804dSStefan Eßer		print(str(child.buffer))
98144d4804dSStefan Eßer		print(str(child.before))
98244d4804dSStefan Eßer		sys.exit(2)
98344d4804dSStefan Eßer
98444d4804dSStefan Eßer	return child
98544d4804dSStefan Eßer
98644d4804dSStefan Eßer
98744d4804dSStefan Eßer# Execute string.
98844d4804dSStefan Eßer# @param exe   The executable.
98944d4804dSStefan Eßer# @param args  The arguments to pass to the executable.
99044d4804dSStefan Eßer# @param env   The environment.
99144d4804dSStefan Eßerdef test_dc3(exe, args, env):
99244d4804dSStefan Eßer
99344d4804dSStefan Eßer	child = pexpect.spawn(exe, args=args, env=env)
99444d4804dSStefan Eßer
99544d4804dSStefan Eßer	try:
99644d4804dSStefan Eßer		write_str(child, "[1 15+pR]x")
99744d4804dSStefan Eßer		check_line(child, "16")
99844d4804dSStefan Eßer		write_str(child, "1pR")
99944d4804dSStefan Eßer		check_line(child, "1")
100044d4804dSStefan Eßer		write_str(child, "q")
1001d43fa8efSStefan Eßer		send(child, "\n")
1002d43fa8efSStefan Eßer		wait(child)
100344d4804dSStefan Eßer	except pexpect.TIMEOUT:
1004d43fa8efSStefan Eßer		traceback.print_tb(sys.exc_info()[2])
100544d4804dSStefan Eßer		print("timed out")
100644d4804dSStefan Eßer		print(str(child))
100744d4804dSStefan Eßer		sys.exit(2)
100844d4804dSStefan Eßer	except pexpect.EOF:
100944d4804dSStefan Eßer		print("EOF")
101044d4804dSStefan Eßer		print(str(child))
101144d4804dSStefan Eßer		print(str(child.buffer))
101244d4804dSStefan Eßer		print(str(child.before))
101344d4804dSStefan Eßer		sys.exit(2)
101444d4804dSStefan Eßer
101544d4804dSStefan Eßer	return child
101644d4804dSStefan Eßer
101744d4804dSStefan Eßer
101844d4804dSStefan Eßer# The array of bc tests.
101944d4804dSStefan Eßerbc_tests = [
102044d4804dSStefan Eßer	test_bc_utf8_0,
102144d4804dSStefan Eßer	test_bc_utf8_1,
102244d4804dSStefan Eßer	test_bc_utf8_2,
102344d4804dSStefan Eßer	test_bc_utf8_3,
102444d4804dSStefan Eßer	test_bc_utf8_4,
102544d4804dSStefan Eßer	test_sigint_sigquit,
102644d4804dSStefan Eßer	test_eof,
102744d4804dSStefan Eßer	test_sigint,
102844d4804dSStefan Eßer	test_sigtstp,
102944d4804dSStefan Eßer	test_sigstop,
103044d4804dSStefan Eßer	test_bc1,
103144d4804dSStefan Eßer	test_bc2,
103244d4804dSStefan Eßer	test_bc3,
103344d4804dSStefan Eßer	test_bc4,
103444d4804dSStefan Eßer	test_bc5,
103544d4804dSStefan Eßer	test_bc6,
103644d4804dSStefan Eßer	test_bc7,
103744d4804dSStefan Eßer	test_bc8,
103844d4804dSStefan Eßer	test_bc9,
103944d4804dSStefan Eßer	test_bc10,
104044d4804dSStefan Eßer	test_bc11,
104144d4804dSStefan Eßer	test_bc12,
104244d4804dSStefan Eßer]
104344d4804dSStefan Eßer
104444d4804dSStefan Eßer# The array of dc tests.
104544d4804dSStefan Eßerdc_tests = [
104644d4804dSStefan Eßer	test_dc_utf8_0,
104744d4804dSStefan Eßer	test_dc_utf8_1,
104844d4804dSStefan Eßer	test_dc_utf8_2,
104944d4804dSStefan Eßer	test_dc_utf8_3,
105010041e99SStefan Eßer	test_dc_utf8_4,
105144d4804dSStefan Eßer	test_sigint_sigquit,
105244d4804dSStefan Eßer	test_eof,
105344d4804dSStefan Eßer	test_sigint,
105444d4804dSStefan Eßer	test_dc1,
105544d4804dSStefan Eßer	test_dc2,
105644d4804dSStefan Eßer	test_dc3,
105744d4804dSStefan Eßer]
105844d4804dSStefan Eßer
105944d4804dSStefan Eßer
106044d4804dSStefan Eßer# Print the usage and exit with an error.
106144d4804dSStefan Eßerdef usage():
106244d4804dSStefan Eßer	print("usage: {} [-t] dir [-a] test_idx [exe options...]".format(script))
106344d4804dSStefan Eßer	print("       The valid values for dir are: 'bc' and 'dc'.")
106444d4804dSStefan Eßer	print("       The max test_idx for bc is {}.".format(len(bc_tests) - 1))
106544d4804dSStefan Eßer	print("       The max test_idx for dc is {}.".format(len(dc_tests) - 1))
1066d43fa8efSStefan Eßer	print("       If -a is given, the number of tests for dir is printed.")
106744d4804dSStefan Eßer	print("       No tests are run.")
106844d4804dSStefan Eßer	sys.exit(1)
106944d4804dSStefan Eßer
107044d4804dSStefan Eßer
107144d4804dSStefan Eßer# Must run this script alone.
107244d4804dSStefan Eßerif __name__ != "__main__":
107344d4804dSStefan Eßer	usage()
107444d4804dSStefan Eßer
107544d4804dSStefan Eßerif len(sys.argv) < 2:
107644d4804dSStefan Eßer	usage()
107744d4804dSStefan Eßer
107844d4804dSStefan Eßeridx = 1
107944d4804dSStefan Eßer
108044d4804dSStefan Eßerexedir = sys.argv[idx]
108144d4804dSStefan Eßer
108244d4804dSStefan Eßeridx += 1
108344d4804dSStefan Eßer
108444d4804dSStefan Eßerif exedir == "-t":
108544d4804dSStefan Eßer	do_test = True
108644d4804dSStefan Eßer	exedir = sys.argv[idx]
108744d4804dSStefan Eßer	idx += 1
108844d4804dSStefan Eßerelse:
108944d4804dSStefan Eßer	do_test = False
109044d4804dSStefan Eßer
109144d4804dSStefan Eßertest_idx = sys.argv[idx]
109244d4804dSStefan Eßer
109344d4804dSStefan Eßeridx += 1
109444d4804dSStefan Eßer
109544d4804dSStefan Eßerif test_idx == "-a":
109644d4804dSStefan Eßer	if exedir == "bc":
109744d4804dSStefan Eßer		l = len(bc_tests)
109844d4804dSStefan Eßer	else:
109944d4804dSStefan Eßer		l = len(dc_tests)
110044d4804dSStefan Eßer	print("{}".format(l))
110144d4804dSStefan Eßer	sys.exit(0)
110244d4804dSStefan Eßer
110344d4804dSStefan Eßertest_idx = int(test_idx)
110444d4804dSStefan Eßer
110544d4804dSStefan Eßer# Set a default executable unless we have one.
110644d4804dSStefan Eßerif len(sys.argv) >= idx + 1:
110744d4804dSStefan Eßer	exe = sys.argv[idx]
110844d4804dSStefan Eßerelse:
110944d4804dSStefan Eßer	exe = testdir + "/../bin/" + exedir
111044d4804dSStefan Eßer
111144d4804dSStefan Eßerexebase = os.path.basename(exe)
111244d4804dSStefan Eßer
111344d4804dSStefan Eßer# Use the correct options.
111444d4804dSStefan Eßerif exebase == "bc":
111544d4804dSStefan Eßer	halt = "halt\n"
1116d43fa8efSStefan Eßer	options = "-l"
111744d4804dSStefan Eßer	test_array = bc_tests
111844d4804dSStefan Eßerelse:
111944d4804dSStefan Eßer	halt = "q\n"
112044d4804dSStefan Eßer	options = "-x"
112144d4804dSStefan Eßer	test_array = dc_tests
112244d4804dSStefan Eßer
112344d4804dSStefan Eßer# More command-line processing.
112444d4804dSStefan Eßerif len(sys.argv) > idx + 1:
112544d4804dSStefan Eßer	exe = [ exe, sys.argv[idx + 1:], options ]
112644d4804dSStefan Eßerelse:
112744d4804dSStefan Eßer	exe = [ exe, options ]
112844d4804dSStefan Eßer
112944d4804dSStefan Eßer# This is the environment necessary for most tests.
113044d4804dSStefan Eßerenv = {
113144d4804dSStefan Eßer	"BC_BANNER": "1",
113244d4804dSStefan Eßer	"BC_PROMPT": "1",
113344d4804dSStefan Eßer	"DC_PROMPT": "1",
113444d4804dSStefan Eßer	"BC_TTY_MODE": "1",
113544d4804dSStefan Eßer	"DC_TTY_MODE": "1",
113644d4804dSStefan Eßer	"BC_SIGINT_RESET": "1",
113744d4804dSStefan Eßer	"DC_SIGINT_RESET": "1",
113844d4804dSStefan Eßer}
113944d4804dSStefan Eßer
114044d4804dSStefan Eßer# Make sure to include the outside environment.
114144d4804dSStefan Eßerenv.update(os.environ)
114244d4804dSStefan Eßerenv.pop("BC_ENV_ARGS", None)
114344d4804dSStefan Eßerenv.pop("BC_LINE_LENGTH", None)
114444d4804dSStefan Eßerenv.pop("DC_ENV_ARGS", None)
114544d4804dSStefan Eßerenv.pop("DC_LINE_LENGTH", None)
114644d4804dSStefan Eßer
114744d4804dSStefan Eßer# Run the correct test.
114844d4804dSStefan Eßerchild = test_array[test_idx](exe[0], exe[1:], env)
114944d4804dSStefan Eßer
115044d4804dSStefan Eßerchild.close()
115144d4804dSStefan Eßer
115244d4804dSStefan Eßerexit = child.exitstatus
115344d4804dSStefan Eßer
1154d43fa8efSStefan Eßerif exit is not None and exit != 0:
115544d4804dSStefan Eßer	print("child failed; expected exit code 0, got {}".format(exit))
115644d4804dSStefan Eßer	print(str(child))
115744d4804dSStefan Eßer	sys.exit(1)
1158