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