]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bc/tests/history.py
contrib/bc: merge version 5.1.0 from vendor branch
[FreeBSD/FreeBSD.git] / contrib / bc / tests / history.py
1 #! /usr/bin/python
2 #
3 # SPDX-License-Identifier: BSD-2-Clause
4 #
5 # Copyright (c) 2018-2021 Gavin D. Howard and contributors.
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions are met:
9 #
10 # * Redistributions of source code must retain the above copyright notice, this
11 #   list of conditions and the following disclaimer.
12 #
13 # * Redistributions in binary form must reproduce the above copyright notice,
14 #   this list of conditions and the following disclaimer in the documentation
15 #   and/or other materials provided with the distribution.
16 #
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 # POSSIBILITY OF SUCH DAMAGE.
28 #
29
30 import os, sys
31 import time
32 import signal
33 import traceback
34
35 try:
36         import pexpect
37 except ImportError:
38         print("Could not find pexpect. Skipping...")
39         sys.exit(0)
40
41 # Housekeeping.
42 script = sys.argv[0]
43 testdir = os.path.dirname(script)
44
45 if "BC_TEST_OUTPUT_DIR" in os.environ:
46         outputdir = os.environ["BC_TEST_OUTPUT_DIR"]
47 else:
48         outputdir = testdir
49
50 prompt = ">>> "
51
52 # This array is for escaping characters that are necessary to escape when
53 # outputting to pexpect. Since pexpect takes regexes, these characters confuse
54 # it unless we escape them.
55 escapes = [
56         ']',
57         '[',
58         '+',
59 ]
60
61 # UTF-8 stress tests.
62 utf8_stress1 = "ᆬḰ䋔䗅㜲ತ咡䒢岤䳰稨⣡嶣㷡嶏ⵐ䄺嵕ਅ奰痚㆜䊛拂䅙૩➋䛿ቬ竳Ϳᅠ❄产翷䮊௷Ỉ䷒䳜㛠➕傎ᗋᏯਕ䆐悙癐㺨"
63 utf8_stress2 = "韠싧돳넨큚ꉿ뮴픷ꉲ긌�최릙걆鳬낽ꪁ퍼鈴핐黙헶ꪈ뮩쭀锻끥鉗겉욞며뛯꬐�ﻼ�度錐�"
64 utf8_stress3 = "곻�䣹昲蜴Ὓ桢㎏⚦珢畣갴ﭱ鶶ๅ⶛뀁彻ꖒ䔾ꢚﱤ햔햞㐹�鼳뵡▿ⶾ꠩�纞⊐佧�ⵟ霘紳㱔籠뎼⊓搧硤"
65 utf8_stress4 = "ᄀ𖢾🏴��"
66
67 # An easy array for UTF-8 tests.
68 utf8_stress_strs = [
69         utf8_stress1,
70         utf8_stress2,
71         utf8_stress3,
72         utf8_stress4,
73 ]
74
75
76 def expect(child, data):
77         child.expect(data)
78
79
80 # Eats all of the child's data.
81 # @param child  The child whose data should be eaten.
82 def eat(child):
83         while child.buffer is not None and len(child.buffer) > 0:
84                 expect(child, ".+")
85
86
87 # Send data to a child. This makes sure the buffers are empty first.
88 # @param child  The child to send data to.
89 # @param data   The data to send.
90 def send(child, data):
91         eat(child)
92         child.send(data)
93
94
95 def wait(child):
96         if child.isalive():
97                 child.sendeof()
98                 time.sleep(1)
99                 if child.isalive():
100                         child.kill(signal.SIGTERM)
101                         time.sleep(1)
102                         if child.isalive():
103                                 child.kill(signal.SIGKILL)
104         child.wait()
105
106
107 # Check that the child output the expected line. If history is false, then
108 # the output should change.
109 def check_line(child, expected, prompt=">>> ", history=True):
110         send(child, "\n")
111         prefix = "\r\n" if history else ""
112         expect(child, prefix + expected + "\r\n" + prompt)
113
114
115 # Write a string to output, checking all of the characters are output,
116 # one-by-one.
117 def write_str(child, s):
118         for c in s:
119                 send(child, c)
120                 if c in escapes:
121                         expect(child, "\\{}".format(c))
122                 else:
123                         expect(child, c)
124
125
126 # Check the bc banner.
127 # @param child  The child process.
128 def bc_banner(child):
129         bc_banner1 = "bc [0-9]+\.[0-9]+\.[0-9]+\r\n"
130         bc_banner2 = "Copyright \(c\) 2018-[2-9][0-9][0-9][0-9] Gavin D. Howard and contributors\r\n"
131         bc_banner3 = "Report bugs at: https://git.yzena.com/gavin/bc\r\n\r\n"
132         bc_banner4 = "This is free software with ABSOLUTELY NO WARRANTY.\r\n\r\n"
133         expect(child, bc_banner1)
134         expect(child, bc_banner2)
135         expect(child, bc_banner3)
136         expect(child, bc_banner4)
137         expect(child, prompt)
138
139
140 # Common UTF-8 testing function. The index is the index into utf8_stress_strs
141 # for which stress string to use.
142 # @param exe   The executable.
143 # @param args  The arguments to pass to the executable.
144 # @param env   The environment.
145 # @param idx   The index of the UTF-8 stress string.
146 def test_utf8(exe, args, env, idx, bc=True):
147
148         # Because both bc and dc use this, make sure the banner doesn't pop.
149         env["BC_BANNER"] = "0"
150
151         child = pexpect.spawn(exe, args=args, env=env, encoding='utf-8', codec_errors='ignore')
152
153         try:
154
155                 # Write the stress string.
156                 send(child, utf8_stress_strs[idx])
157                 send(child, "\n")
158
159                 if bc:
160                         send(child, "quit")
161                 else:
162                         send(child, "q")
163
164                 send(child, "\n")
165
166                 wait(child)
167
168         except pexpect.TIMEOUT:
169                 traceback.print_tb(sys.exc_info()[2])
170                 print("timed out")
171                 print(str(child))
172                 sys.exit(2)
173         except pexpect.EOF:
174                 print("EOF")
175                 print(str(child))
176                 print(str(child.buffer))
177                 print(str(child.before))
178                 sys.exit(2)
179
180         return child
181
182 # A random UTF-8 test with insert.
183 # @param exe   The executable.
184 # @param args  The arguments to pass to the executable.
185 # @param env   The environment.
186 def test_utf8_0(exe, args, env, bc=True):
187
188         # Because both bc and dc use this, make sure the banner doesn't pop.
189         env["BC_BANNER"] = "0"
190
191         child = pexpect.spawn(exe, args=args, env=env, encoding='utf-8', codec_errors='ignore')
192
193         try:
194
195                 # Just random UTF-8 I generated somewhow, plus ensuring that insert works.
196                 write_str(child, "ﴪáá̵̗🈐ã")
197                 send(child, "\x1b[D\x1b[D\x1b[D\x1b\x1b[Aℐ")
198                 send(child, "\n")
199
200                 if bc:
201                         send(child, "quit")
202                 else:
203                         send(child, "q")
204
205                 send(child, "\n")
206                 eat(child)
207
208                 wait(child)
209
210         except pexpect.TIMEOUT:
211                 traceback.print_tb(sys.exc_info()[2])
212                 print("timed out")
213                 print(str(child))
214                 sys.exit(2)
215         except pexpect.EOF:
216                 print("EOF")
217                 print(str(child))
218                 print(str(child.buffer))
219                 print(str(child.before))
220                 sys.exit(2)
221
222         return child
223
224
225 def test_utf8_1(exe, args, env, bc=True):
226         return test_utf8(exe, args, env, 0, bc)
227
228
229 def test_utf8_2(exe, args, env, bc=True):
230         return test_utf8(exe, args, env, 1, bc)
231
232
233 def test_utf8_3(exe, args, env, bc=True):
234         return test_utf8(exe, args, env, 2, bc)
235
236
237 def test_utf8_4(exe, args, env, bc=True):
238         return test_utf8(exe, args, env, 3, bc)
239
240
241 # This tests a SIGINT with reset followed by a SIGQUIT.
242 # @param exe   The executable.
243 # @param args  The arguments to pass to the executable.
244 # @param env   The environment.
245 def test_sigint_sigquit(exe, args, env):
246
247         # Because both bc and dc use this, make sure the banner doesn't pop.
248         env["BC_BANNER"] = "0"
249
250         child = pexpect.spawn(exe, args=args, env=env)
251
252         try:
253                 send(child, "\t")
254                 expect(child, "        ")
255                 send(child, "\x03")
256                 send(child, "\x1c")
257                 wait(child)
258         except pexpect.TIMEOUT:
259                 traceback.print_tb(sys.exc_info()[2])
260                 print("timed out")
261                 print(str(child))
262                 sys.exit(2)
263         except pexpect.EOF:
264                 print("EOF")
265                 print(str(child))
266                 print(str(child.buffer))
267                 print(str(child.before))
268                 sys.exit(2)
269
270         return child
271
272
273 # Test for EOF.
274 # @param exe   The executable.
275 # @param args  The arguments to pass to the executable.
276 # @param env   The environment.
277 def test_eof(exe, args, env):
278
279         # Because both bc and dc use this, make sure the banner doesn't pop.
280         env["BC_BANNER"] = "0"
281
282         child = pexpect.spawn(exe, args=args, env=env)
283
284         try:
285                 send(child, "\t")
286                 expect(child, "        ")
287                 send(child, "\x04")
288                 wait(child)
289         except pexpect.TIMEOUT:
290                 traceback.print_tb(sys.exc_info()[2])
291                 print("timed out")
292                 print(str(child))
293                 sys.exit(2)
294         except pexpect.EOF:
295                 print("EOF")
296                 print(str(child))
297                 print(str(child.buffer))
298                 print(str(child.before))
299                 sys.exit(2)
300
301         return child
302
303
304 # Test for quiting SIGINT.
305 # @param exe   The executable.
306 # @param args  The arguments to pass to the executable.
307 # @param env   The environment.
308 def test_sigint(exe, args, env):
309
310         # Because both bc and dc use this, make sure the banner doesn't pop.
311         env["BC_BANNER"] = "0"
312
313         env["BC_SIGINT_RESET"] = "0"
314         env["DC_SIGINT_RESET"] = "0"
315
316         child = pexpect.spawn(exe, args=args, env=env)
317
318         try:
319                 send(child, "\t")
320                 expect(child, "        ")
321                 send(child, "\x03")
322                 wait(child)
323         except pexpect.TIMEOUT:
324                 traceback.print_tb(sys.exc_info()[2])
325                 print("timed out")
326                 print(str(child))
327                 sys.exit(2)
328         except pexpect.EOF:
329                 print("EOF")
330                 print(str(child))
331                 print(str(child.buffer))
332                 print(str(child.before))
333                 sys.exit(2)
334
335         return child
336
337
338 # Test for SIGTSTP.
339 # @param exe   The executable.
340 # @param args  The arguments to pass to the executable.
341 # @param env   The environment.
342 def test_sigtstp(exe, args, env):
343
344         # This test does not work on FreeBSD, so skip.
345         if sys.platform.startswith("freebsd"):
346                 sys.exit(0)
347
348         # Because both bc and dc use this, make sure the banner doesn't pop.
349         env["BC_BANNER"] = "0"
350
351         child = pexpect.spawn(exe, args=args, env=env)
352
353         try:
354                 send(child, "\t")
355                 expect(child, "        ")
356                 send(child, "\x13")
357                 time.sleep(1)
358                 if not child.isalive():
359                         print("child exited early")
360                         print(str(child))
361                         print(str(child.buffer))
362                         sys.exit(1)
363                 child.kill(signal.SIGCONT)
364                 send(child, "quit")
365                 send(child, "\n")
366                 wait(child)
367         except pexpect.TIMEOUT:
368                 traceback.print_tb(sys.exc_info()[2])
369                 print("timed out")
370                 print(str(child))
371                 sys.exit(2)
372         except pexpect.EOF:
373                 print("EOF")
374                 print(str(child))
375                 print(str(child.buffer))
376                 print(str(child.before))
377                 sys.exit(2)
378
379         return child
380
381
382 # Test for SIGSTOP.
383 # @param exe   The executable.
384 # @param args  The arguments to pass to the executable.
385 # @param env   The environment.
386 def test_sigstop(exe, args, env):
387
388         # Because both bc and dc use this, make sure the banner doesn't pop.
389         env["BC_BANNER"] = "0"
390
391         child = pexpect.spawn(exe, args=args, env=env)
392
393         try:
394                 send(child, "\t")
395                 expect(child, "        ")
396                 send(child, "\x14")
397                 time.sleep(1)
398                 if not child.isalive():
399                         print("child exited early")
400                         print(str(child))
401                         print(str(child.buffer))
402                         sys.exit(1)
403                 send(child, "\x13")
404                 time.sleep(1)
405                 if not child.isalive():
406                         print("child exited early")
407                         print(str(child))
408                         print(str(child.buffer))
409                         sys.exit(1)
410                 child.kill(signal.SIGCONT)
411                 send(child, "quit")
412                 send(child, "\n")
413                 wait(child)
414         except pexpect.TIMEOUT:
415                 traceback.print_tb(sys.exc_info()[2])
416                 print("timed out")
417                 print(str(child))
418                 sys.exit(2)
419         except pexpect.EOF:
420                 print("EOF")
421                 print(str(child))
422                 print(str(child.buffer))
423                 print(str(child.before))
424                 sys.exit(2)
425
426         return child
427
428
429 def test_bc_utf8_0(exe, args, env):
430         return test_utf8_0(exe, args, env, True)
431
432
433 def test_bc_utf8_1(exe, args, env):
434         return test_utf8_1(exe, args, env, True)
435
436
437 def test_bc_utf8_2(exe, args, env):
438         return test_utf8_2(exe, args, env, True)
439
440
441 def test_bc_utf8_3(exe, args, env):
442         return test_utf8_3(exe, args, env, True)
443
444
445 def test_bc_utf8_4(exe, args, env):
446         return test_utf8_4(exe, args, env, True)
447
448
449 # Basic bc test.
450 # @param exe   The executable.
451 # @param args  The arguments to pass to the executable.
452 # @param env   The environment.
453 def test_bc1(exe, args, env):
454
455         child = pexpect.spawn(exe, args=args, env=env)
456
457         try:
458                 bc_banner(child)
459                 write_str(child, "1")
460                 check_line(child, "1")
461                 write_str(child, "1")
462                 check_line(child, "1")
463                 send(child, "quit")
464                 send(child, "\n")
465                 wait(child)
466         except pexpect.TIMEOUT:
467                 traceback.print_tb(sys.exc_info()[2])
468                 print("timed out")
469                 print(str(child))
470                 sys.exit(2)
471         except pexpect.EOF:
472                 print("EOF")
473                 print(str(child))
474                 print(str(child.buffer))
475                 print(str(child.before))
476                 sys.exit(2)
477
478         return child
479
480
481 # SIGINT with no history.
482 # @param exe   The executable.
483 # @param args  The arguments to pass to the executable.
484 # @param env   The environment.
485 def test_bc2(exe, args, env):
486
487         env["TERM"] = "dumb"
488
489         child = pexpect.spawn(exe, args=args, env=env)
490
491         try:
492                 bc_banner(child)
493                 child.sendline("1")
494                 check_line(child, "1", history=False)
495                 time.sleep(1)
496                 child.sendintr()
497                 child.sendline("quit")
498                 wait(child)
499         except pexpect.TIMEOUT:
500                 traceback.print_tb(sys.exc_info()[2])
501                 print("timed out")
502                 print(str(child))
503                 sys.exit(2)
504         except pexpect.EOF:
505                 print("EOF")
506                 print(str(child))
507                 print(str(child.buffer))
508                 print(str(child.before))
509                 sys.exit(2)
510
511         return child
512
513
514 # Left and right arrows.
515 # @param exe   The executable.
516 # @param args  The arguments to pass to the executable.
517 # @param env   The environment.
518 def test_bc3(exe, args, env):
519
520         child = pexpect.spawn(exe, args=args, env=env)
521
522         try:
523                 bc_banner(child)
524                 send(child, "\x1b[D\x1b[D\x1b[C\x1b[C")
525                 send(child, "\n")
526                 expect(child, prompt)
527                 send(child, "12\x1b[D3\x1b[C4\x1bOD5\x1bOC6")
528                 send(child, "\n")
529                 check_line(child, "132546")
530                 send(child, "12\x023\x064")
531                 send(child, "\n")
532                 check_line(child, "1324")
533                 send(child, "12\x1b[H3\x1bOH\x01\x1b[H45\x1bOF6\x05\x1b[F7\x1bOH8")
534                 send(child, "\n")
535                 check_line(child, "84531267")
536                 send(child, "quit")
537                 send(child, "\n")
538                 wait(child)
539         except pexpect.TIMEOUT:
540                 traceback.print_tb(sys.exc_info()[2])
541                 print("timed out")
542                 print(str(child))
543                 sys.exit(2)
544         except pexpect.EOF:
545                 print("EOF")
546                 print(str(child))
547                 print(str(child.buffer))
548                 print(str(child.before))
549                 sys.exit(2)
550
551         return child
552
553
554 # Up and down arrows.
555 # @param exe   The executable.
556 # @param args  The arguments to pass to the executable.
557 # @param env   The environment.
558 def test_bc4(exe, args, env):
559
560         child = pexpect.spawn(exe, args=args, env=env)
561
562         try:
563                 bc_banner(child)
564                 send(child, "\x1b[A\x1bOA\x1b[B\x1bOB")
565                 send(child, "\n")
566                 expect(child, prompt)
567                 write_str(child, "15")
568                 check_line(child, "15")
569                 write_str(child, "2^16")
570                 check_line(child, "65536")
571                 send(child, "\x1b[A\x1bOA")
572                 send(child, "\n")
573                 check_line(child, "15")
574                 send(child, "\x1b[A\x1bOA\x1b[A\x1b[B")
575                 check_line(child, "65536")
576                 send(child, "\x1b[A\x1bOA\x0e\x1b[A\x1b[A\x1b[A\x1b[B\x10\x1b[B\x1b[B\x1bOB\x1b[B\x1bOA")
577                 send(child, "\n")
578                 check_line(child, "65536")
579                 send(child, "quit")
580                 send(child, "\n")
581                 wait(child)
582         except pexpect.TIMEOUT:
583                 traceback.print_tb(sys.exc_info()[2])
584                 print("timed out")
585                 print(str(child))
586                 sys.exit(2)
587         except pexpect.EOF:
588                 print("EOF")
589                 print(str(child))
590                 print(str(child.buffer))
591                 print(str(child.before))
592                 sys.exit(2)
593
594         return child
595
596
597 # Clear screen.
598 # @param exe   The executable.
599 # @param args  The arguments to pass to the executable.
600 # @param env   The environment.
601 def test_bc5(exe, args, env):
602
603         child = pexpect.spawn(exe, args=args, env=env)
604
605         try:
606                 bc_banner(child)
607                 send(child, "\x0c")
608                 send(child, "quit")
609                 send(child, "\n")
610                 wait(child)
611         except pexpect.TIMEOUT:
612                 traceback.print_tb(sys.exc_info()[2])
613                 print("timed out")
614                 print(str(child))
615                 sys.exit(2)
616         except pexpect.EOF:
617                 print("EOF")
618                 print(str(child))
619                 print(str(child.buffer))
620                 print(str(child.before))
621                 sys.exit(2)
622
623         return child
624
625
626 # Printed material without a newline.
627 # @param exe   The executable.
628 # @param args  The arguments to pass to the executable.
629 # @param env   The environment.
630 def test_bc6(exe, args, env):
631
632         child = pexpect.spawn(exe, args=args, env=env)
633
634         try:
635                 bc_banner(child)
636                 send(child, "print \"Enter number: \"")
637                 send(child, "\n")
638                 expect(child, "Enter number: ")
639                 send(child, "4\x1b[A\x1b[A")
640                 send(child, "\n")
641                 send(child, "quit")
642                 send(child, "\n")
643                 wait(child)
644         except pexpect.TIMEOUT:
645                 traceback.print_tb(sys.exc_info()[2])
646                 print("timed out")
647                 print(str(child))
648                 sys.exit(2)
649         except pexpect.EOF:
650                 print("EOF")
651                 print(str(child))
652                 print(str(child.buffer))
653                 print(str(child.before))
654                 sys.exit(2)
655
656         return child
657
658
659 # Word start and word end.
660 # @param exe   The executable.
661 # @param args  The arguments to pass to the executable.
662 # @param env   The environment.
663 def test_bc7(exe, args, env):
664
665         child = pexpect.spawn(exe, args=args, env=env)
666
667         try:
668                 bc_banner(child)
669                 send(child, "\x1bb\x1bb\x1bf\x1bf")
670                 send(child, "\n")
671                 expect(child, prompt)
672                 send(child, "\x1b[0~\x1b[3a")
673                 send(child, "\n")
674                 expect(child, prompt)
675                 send(child, "\x1b[0;4\x1b[0A")
676                 send(child, "\n")
677                 expect(child, prompt)
678                 send(child, "        ")
679                 send(child, "\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb")
680                 send(child, "\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf")
681                 send(child, "\n")
682                 expect(child, prompt)
683                 write_str(child, "12 + 34 + 56 + 78 + 90")
684                 check_line(child, "270")
685                 send(child, "\x1b[A")
686                 send(child, "\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb")
687                 send(child, "\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf")
688                 check_line(child, "270")
689                 send(child, "\x1b[A")
690                 send(child, "\x1bh\x1bh\x1bf + 14 ")
691                 send(child, "\n")
692                 check_line(child, "284")
693                 send(child, "quit")
694                 send(child, "\n")
695                 wait(child)
696         except pexpect.TIMEOUT:
697                 traceback.print_tb(sys.exc_info()[2])
698                 print("timed out")
699                 print(str(child))
700                 sys.exit(2)
701         except pexpect.EOF:
702                 print("EOF")
703                 print(str(child))
704                 print(str(child.buffer))
705                 print(str(child.before))
706                 sys.exit(2)
707
708         return child
709
710
711 # Backspace.
712 # @param exe   The executable.
713 # @param args  The arguments to pass to the executable.
714 # @param env   The environment.
715 def test_bc8(exe, args, env):
716
717         child = pexpect.spawn(exe, args=args, env=env)
718
719         try:
720                 bc_banner(child)
721                 send(child, "12\x1b[D3\x1b[C4\x08\x7f")
722                 send(child, "\n")
723                 check_line(child, "13")
724                 send(child, "quit")
725                 send(child, "\n")
726                 wait(child)
727         except pexpect.TIMEOUT:
728                 traceback.print_tb(sys.exc_info()[2])
729                 print("timed out")
730                 print(str(child))
731                 sys.exit(2)
732         except pexpect.EOF:
733                 print("EOF")
734                 print(str(child))
735                 print(str(child.buffer))
736                 print(str(child.before))
737                 sys.exit(2)
738
739         return child
740
741
742 # Backspace and delete words.
743 # @param exe   The executable.
744 # @param args  The arguments to pass to the executable.
745 # @param env   The environment.
746 def test_bc9(exe, args, env):
747
748         child = pexpect.spawn(exe, args=args, env=env)
749
750         try:
751                 bc_banner(child)
752                 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")
753                 send(child, "\n")
754                 expect(child, prompt)
755                 write_str(child, "12 + 34 + 56 + 78 + 90")
756                 check_line(child, "270")
757                 send(child, "\x1b[A")
758                 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")
759                 send(child, "\n")
760                 check_line(child, "102")
761                 send(child, "\x1b[A")
762                 send(child, "\x17\x17")
763                 send(child, "\n")
764                 check_line(child, "46")
765                 send(child, "\x17\x17")
766                 send(child, "\n")
767                 expect(child, prompt)
768                 send(child, "quit")
769                 send(child, "\n")
770                 wait(child)
771         except pexpect.TIMEOUT:
772                 traceback.print_tb(sys.exc_info()[2])
773                 print("timed out")
774                 print(str(child))
775                 sys.exit(2)
776         except pexpect.EOF:
777                 print("EOF")
778                 print(str(child))
779                 print(str(child.buffer))
780                 print(str(child.before))
781                 sys.exit(2)
782
783         return child
784
785
786 # Backspace and delete words 2.
787 # @param exe   The executable.
788 # @param args  The arguments to pass to the executable.
789 # @param env   The environment.
790 def test_bc10(exe, args, env):
791
792         child = pexpect.spawn(exe, args=args, env=env)
793
794         try:
795                 bc_banner(child)
796                 send(child, "\x1b[3~\x1b[3~")
797                 send(child, "\n")
798                 expect(child, prompt)
799                 send(child, "    \x1b[3~\x1b[3~")
800                 send(child, "\n")
801                 expect(child, prompt)
802                 write_str(child, "12 + 34 + 56 + 78 + 90")
803                 check_line(child, "270")
804                 send(child, "\x1b[A\x1b[A\x1b[A\x1b[B\x1b[B\x1b[B\x1b[A")
805                 send(child, "\n")
806                 check_line(child, "270")
807                 send(child, "\x1b[A\x1b[0;5D\x1b[0;5D\x0b")
808                 send(child, "\n")
809                 check_line(child, "180")
810                 send(child, "\x1b[A\x1521")
811                 check_line(child, "21")
812                 send(child, "quit")
813                 send(child, "\n")
814                 wait(child)
815         except pexpect.TIMEOUT:
816                 traceback.print_tb(sys.exc_info()[2])
817                 print("timed out")
818                 print(str(child))
819                 sys.exit(2)
820         except pexpect.EOF:
821                 print("EOF")
822                 print(str(child))
823                 print(str(child.buffer))
824                 print(str(child.before))
825                 sys.exit(2)
826
827         return child
828
829
830 # Swap.
831 # @param exe   The executable.
832 # @param args  The arguments to pass to the executable.
833 # @param env   The environment.
834 def test_bc11(exe, args, env):
835
836         child = pexpect.spawn(exe, args=args, env=env)
837
838         try:
839                 bc_banner(child)
840                 send(child, "\x1b[A\x02\x14")
841                 send(child, "\n")
842                 expect(child, prompt)
843                 write_str(child, "12 + 34 + 56 + 78")
844                 check_line(child, "180")
845                 send(child, "\x1b[A\x02\x14")
846                 check_line(child, "189")
847                 send(child, "quit")
848                 send(child, "\n")
849                 wait(child)
850         except pexpect.TIMEOUT:
851                 traceback.print_tb(sys.exc_info()[2])
852                 print("timed out")
853                 print(str(child))
854                 sys.exit(2)
855         except pexpect.EOF:
856                 print("EOF")
857                 print(str(child))
858                 print(str(child.buffer))
859                 print(str(child.before))
860                 sys.exit(2)
861
862         return child
863
864
865 # Non-fatal error.
866 # @param exe   The executable.
867 # @param args  The arguments to pass to the executable.
868 # @param env   The environment.
869 def test_bc12(exe, args, env):
870
871         child = pexpect.spawn(exe, args=args, env=env)
872
873         try:
874                 bc_banner(child)
875                 send(child, "12 +")
876                 send(child, "\n")
877                 time.sleep(1)
878                 if not child.isalive():
879                         print("child exited early")
880                         print(str(child))
881                         print(str(child.buffer))
882                         sys.exit(1)
883                 send(child, "quit")
884                 send(child, "\n")
885                 wait(child)
886         except pexpect.TIMEOUT:
887                 traceback.print_tb(sys.exc_info()[2])
888                 print("timed out")
889                 print(str(child))
890                 sys.exit(2)
891         except pexpect.EOF:
892                 print("EOF")
893                 print(str(child))
894                 print(str(child.buffer))
895                 print(str(child.before))
896                 sys.exit(2)
897
898         return child
899
900
901 def test_dc_utf8_0(exe, args, env):
902         return test_utf8_0(exe, args, env, False)
903
904
905 def test_dc_utf8_1(exe, args, env):
906         return test_utf8_1(exe, args, env, False)
907
908
909 def test_dc_utf8_2(exe, args, env):
910         return test_utf8_2(exe, args, env, False)
911
912
913 def test_dc_utf8_3(exe, args, env):
914         return test_utf8_3(exe, args, env, False)
915
916
917 def test_dc_utf8_4(exe, args, env):
918         return test_utf8_4(exe, args, env, False)
919
920
921 # Basic dc test.
922 # @param exe   The executable.
923 # @param args  The arguments to pass to the executable.
924 # @param env   The environment.
925 def test_dc1(exe, args, env):
926
927         child = pexpect.spawn(exe, args=args, env=env)
928
929         try:
930                 write_str(child, "1pR")
931                 check_line(child, "1")
932                 write_str(child, "1pR")
933                 check_line(child, "1")
934                 write_str(child, "q")
935                 send(child, "\n")
936                 wait(child)
937         except pexpect.TIMEOUT:
938                 traceback.print_tb(sys.exc_info()[2])
939                 print("timed out")
940                 print(str(child))
941                 sys.exit(2)
942         except pexpect.EOF:
943                 print("EOF")
944                 print(str(child))
945                 print(str(child.buffer))
946                 print(str(child.before))
947                 sys.exit(2)
948
949         return child
950
951
952 # SIGINT with quit.
953 # @param exe   The executable.
954 # @param args  The arguments to pass to the executable.
955 # @param env   The environment.
956 def test_dc2(exe, args, env):
957
958         env["TERM"] = "dumb"
959
960         child = pexpect.spawn(exe, args=args, env=env)
961
962         try:
963                 child.sendline("1pR")
964                 check_line(child, "1", history=False)
965                 time.sleep(1)
966                 child.sendintr()
967                 child.sendline("q")
968                 wait(child)
969         except pexpect.TIMEOUT:
970                 traceback.print_tb(sys.exc_info()[2])
971                 print("timed out")
972                 print(str(child))
973                 sys.exit(2)
974         except pexpect.EOF:
975                 print("EOF")
976                 print(str(child))
977                 print(str(child.buffer))
978                 print(str(child.before))
979                 sys.exit(2)
980
981         return child
982
983
984 # Execute string.
985 # @param exe   The executable.
986 # @param args  The arguments to pass to the executable.
987 # @param env   The environment.
988 def test_dc3(exe, args, env):
989
990         child = pexpect.spawn(exe, args=args, env=env)
991
992         try:
993                 write_str(child, "[1 15+pR]x")
994                 check_line(child, "16")
995                 write_str(child, "1pR")
996                 check_line(child, "1")
997                 write_str(child, "q")
998                 send(child, "\n")
999                 wait(child)
1000         except pexpect.TIMEOUT:
1001                 traceback.print_tb(sys.exc_info()[2])
1002                 print("timed out")
1003                 print(str(child))
1004                 sys.exit(2)
1005         except pexpect.EOF:
1006                 print("EOF")
1007                 print(str(child))
1008                 print(str(child.buffer))
1009                 print(str(child.before))
1010                 sys.exit(2)
1011
1012         return child
1013
1014
1015 # The array of bc tests.
1016 bc_tests = [
1017         test_bc_utf8_0,
1018         test_bc_utf8_1,
1019         test_bc_utf8_2,
1020         test_bc_utf8_3,
1021         test_bc_utf8_4,
1022         test_sigint_sigquit,
1023         test_eof,
1024         test_sigint,
1025         test_sigtstp,
1026         test_sigstop,
1027         test_bc1,
1028         test_bc2,
1029         test_bc3,
1030         test_bc4,
1031         test_bc5,
1032         test_bc6,
1033         test_bc7,
1034         test_bc8,
1035         test_bc9,
1036         test_bc10,
1037         test_bc11,
1038         test_bc12,
1039 ]
1040
1041 # The array of dc tests.
1042 dc_tests = [
1043         test_dc_utf8_0,
1044         test_dc_utf8_1,
1045         test_dc_utf8_2,
1046         test_dc_utf8_3,
1047         test_sigint_sigquit,
1048         test_eof,
1049         test_sigint,
1050         test_dc1,
1051         test_dc2,
1052         test_dc3,
1053 ]
1054
1055
1056 # Print the usage and exit with an error.
1057 def usage():
1058         print("usage: {} [-t] dir [-a] test_idx [exe options...]".format(script))
1059         print("       The valid values for dir are: 'bc' and 'dc'.")
1060         print("       The max test_idx for bc is {}.".format(len(bc_tests) - 1))
1061         print("       The max test_idx for dc is {}.".format(len(dc_tests) - 1))
1062         print("       If -a is given, the number of tests for dir is printed.")
1063         print("       No tests are run.")
1064         sys.exit(1)
1065
1066
1067 # Must run this script alone.
1068 if __name__ != "__main__":
1069         usage()
1070
1071 if len(sys.argv) < 2:
1072         usage()
1073
1074 idx = 1
1075
1076 exedir = sys.argv[idx]
1077
1078 idx += 1
1079
1080 if exedir == "-t":
1081         do_test = True
1082         exedir = sys.argv[idx]
1083         idx += 1
1084 else:
1085         do_test = False
1086
1087 test_idx = sys.argv[idx]
1088
1089 idx += 1
1090
1091 if test_idx == "-a":
1092         if exedir == "bc":
1093                 l = len(bc_tests)
1094         else:
1095                 l = len(dc_tests)
1096         print("{}".format(l))
1097         sys.exit(0)
1098
1099 test_idx = int(test_idx)
1100
1101 # Set a default executable unless we have one.
1102 if len(sys.argv) >= idx + 1:
1103         exe = sys.argv[idx]
1104 else:
1105         exe = testdir + "/../bin/" + exedir
1106
1107 exebase = os.path.basename(exe)
1108
1109 # Use the correct options.
1110 if exebase == "bc":
1111         halt = "halt\n"
1112         options = "-l"
1113         test_array = bc_tests
1114 else:
1115         halt = "q\n"
1116         options = "-x"
1117         test_array = dc_tests
1118
1119 # More command-line processing.
1120 if len(sys.argv) > idx + 1:
1121         exe = [ exe, sys.argv[idx + 1:], options ]
1122 else:
1123         exe = [ exe, options ]
1124
1125 # This is the environment necessary for most tests.
1126 env = {
1127         "BC_BANNER": "1",
1128         "BC_PROMPT": "1",
1129         "DC_PROMPT": "1",
1130         "BC_TTY_MODE": "1",
1131         "DC_TTY_MODE": "1",
1132         "BC_SIGINT_RESET": "1",
1133         "DC_SIGINT_RESET": "1",
1134 }
1135
1136 # Make sure to include the outside environment.
1137 env.update(os.environ)
1138 env.pop("BC_ENV_ARGS", None)
1139 env.pop("BC_LINE_LENGTH", None)
1140 env.pop("DC_ENV_ARGS", None)
1141 env.pop("DC_LINE_LENGTH", None)
1142
1143 # Run the correct test.
1144 child = test_array[test_idx](exe[0], exe[1:], env)
1145
1146 child.close()
1147
1148 exit = child.exitstatus
1149
1150 if exit is not None and exit != 0:
1151         print("child failed; expected exit code 0, got {}".format(exit))
1152         print(str(child))
1153         sys.exit(1)