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 30import os, sys 31import time 32import signal 33import traceback 34 35try: 36 import pexpect 37except ImportError: 38 print("Could not find pexpect. Skipping...") 39 sys.exit(0) 40 41# Housekeeping. 42script = sys.argv[0] 43testdir = os.path.dirname(script) 44 45if "BC_TEST_OUTPUT_DIR" in os.environ: 46 outputdir = os.environ["BC_TEST_OUTPUT_DIR"] 47else: 48 outputdir = testdir 49 50prompt = ">>> " 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. 55escapes = [ 56 ']', 57 '[', 58 '+', 59] 60 61# UTF-8 stress tests. 62utf8_stress1 = "ᆬḰ䋔䗅㜲ತ咡䒢岤䳰稨⣡嶣㷡嶏ⵐ䄺嵕ਅ奰痚㆜䊛拂䅙૩➋䛿ቬ竳Ϳᅠ❄产翷䮊௷Ỉ䷒䳜㛠➕傎ᗋᏯਕ䆐悙癐㺨" 63utf8_stress2 = "韠싧돳넨큚ꉿ뮴픷ꉲ긌�최릙걆鳬낽ꪁ퍼鈴핐黙헶ꪈ뮩쭀锻끥鉗겉욞며뛯�ﻼ�度錐�" 64utf8_stress3 = "곻�䣹昲蜴Ὓ桢㎏⚦珢畣갴ﭱ鶶ๅ뀁彻ꖒ䔾ꢚﱤ햔햞㐹�鼳뵡▿ⶾ꠩�纞⊐佧�ⵟ霘紳㱔籠뎼⊓搧硤" 65utf8_stress4 = "ᄀ��" 66 67# An easy array for UTF-8 tests. 68utf8_stress_strs = [ 69 utf8_stress1, 70 utf8_stress2, 71 utf8_stress3, 72 utf8_stress4, 73] 74 75 76def 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. 82def 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. 90def send(child, data): 91 eat(child) 92 child.send(data) 93 94 95def 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. 109def 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. 117def 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. 128def 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. 146def 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. 186def 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 225def test_utf8_1(exe, args, env, bc=True): 226 return test_utf8(exe, args, env, 0, bc) 227 228 229def test_utf8_2(exe, args, env, bc=True): 230 return test_utf8(exe, args, env, 1, bc) 231 232 233def test_utf8_3(exe, args, env, bc=True): 234 return test_utf8(exe, args, env, 2, bc) 235 236 237def 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. 245def 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. 277def 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. 308def 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. 342def 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. 386def 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 429def test_bc_utf8_0(exe, args, env): 430 return test_utf8_0(exe, args, env, True) 431 432 433def test_bc_utf8_1(exe, args, env): 434 return test_utf8_1(exe, args, env, True) 435 436 437def test_bc_utf8_2(exe, args, env): 438 return test_utf8_2(exe, args, env, True) 439 440 441def test_bc_utf8_3(exe, args, env): 442 return test_utf8_3(exe, args, env, True) 443 444 445def 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. 453def 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. 485def 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. 518def 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. 558def 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. 601def 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. 630def 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. 663def 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. 715def 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. 746def 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. 790def 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. 834def 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. 869def 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 901def test_dc_utf8_0(exe, args, env): 902 return test_utf8_0(exe, args, env, False) 903 904 905def test_dc_utf8_1(exe, args, env): 906 return test_utf8_1(exe, args, env, False) 907 908 909def test_dc_utf8_2(exe, args, env): 910 return test_utf8_2(exe, args, env, False) 911 912 913def test_dc_utf8_3(exe, args, env): 914 return test_utf8_3(exe, args, env, False) 915 916 917def 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. 925def 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. 956def 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. 988def 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. 1016bc_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. 1042dc_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. 1057def 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. 1068if __name__ != "__main__": 1069 usage() 1070 1071if len(sys.argv) < 2: 1072 usage() 1073 1074idx = 1 1075 1076exedir = sys.argv[idx] 1077 1078idx += 1 1079 1080if exedir == "-t": 1081 do_test = True 1082 exedir = sys.argv[idx] 1083 idx += 1 1084else: 1085 do_test = False 1086 1087test_idx = sys.argv[idx] 1088 1089idx += 1 1090 1091if 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 1099test_idx = int(test_idx) 1100 1101# Set a default executable unless we have one. 1102if len(sys.argv) >= idx + 1: 1103 exe = sys.argv[idx] 1104else: 1105 exe = testdir + "/../bin/" + exedir 1106 1107exebase = os.path.basename(exe) 1108 1109# Use the correct options. 1110if exebase == "bc": 1111 halt = "halt\n" 1112 options = "-l" 1113 test_array = bc_tests 1114else: 1115 halt = "q\n" 1116 options = "-x" 1117 test_array = dc_tests 1118 1119# More command-line processing. 1120if len(sys.argv) > idx + 1: 1121 exe = [ exe, sys.argv[idx + 1:], options ] 1122else: 1123 exe = [ exe, options ] 1124 1125# This is the environment necessary for most tests. 1126env = { 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. 1137env.update(os.environ) 1138env.pop("BC_ENV_ARGS", None) 1139env.pop("BC_LINE_LENGTH", None) 1140env.pop("DC_ENV_ARGS", None) 1141env.pop("DC_LINE_LENGTH", None) 1142 1143# Run the correct test. 1144child = test_array[test_idx](exe[0], exe[1:], env) 1145 1146child.close() 1147 1148exit = child.exitstatus 1149 1150if 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) 1154