Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/bc/tests/history.py
39534 views
1
#! /usr/bin/python
2
#
3
# SPDX-License-Identifier: BSD-2-Clause
4
#
5
# Copyright (c) 2018-2025 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://github.com/gavinhoward/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, "\t")
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, "123")
286
expect(child, "123")
287
send(child, "\x01")
288
send(child, "\x04")
289
send(child, "\x04")
290
send(child, "\x04")
291
wait(child)
292
except pexpect.TIMEOUT:
293
traceback.print_tb(sys.exc_info()[2])
294
print("timed out")
295
print(str(child))
296
sys.exit(2)
297
except pexpect.EOF:
298
print("EOF")
299
print(str(child))
300
print(str(child.buffer))
301
print(str(child.before))
302
sys.exit(2)
303
304
return child
305
306
307
# Test for quiting SIGINT.
308
# @param exe The executable.
309
# @param args The arguments to pass to the executable.
310
# @param env The environment.
311
def test_sigint(exe, args, env):
312
313
# Because both bc and dc use this, make sure the banner doesn't pop.
314
env["BC_BANNER"] = "0"
315
316
env["BC_SIGINT_RESET"] = "0"
317
env["DC_SIGINT_RESET"] = "0"
318
319
child = pexpect.spawn(exe, args=args, env=env)
320
321
try:
322
send(child, "\t")
323
expect(child, "\t")
324
send(child, "\x03")
325
wait(child)
326
except pexpect.TIMEOUT:
327
traceback.print_tb(sys.exc_info()[2])
328
print("timed out")
329
print(str(child))
330
sys.exit(2)
331
except pexpect.EOF:
332
print("EOF")
333
print(str(child))
334
print(str(child.buffer))
335
print(str(child.before))
336
sys.exit(2)
337
338
return child
339
340
341
# Test for SIGTSTP.
342
# @param exe The executable.
343
# @param args The arguments to pass to the executable.
344
# @param env The environment.
345
def test_sigtstp(exe, args, env):
346
347
# This test does not work on FreeBSD, so skip.
348
if sys.platform.startswith("freebsd"):
349
sys.exit(0)
350
351
# Because both bc and dc use this, make sure the banner doesn't pop.
352
env["BC_BANNER"] = "0"
353
354
child = pexpect.spawn(exe, args=args, env=env)
355
356
try:
357
send(child, "\t")
358
expect(child, "\t")
359
send(child, "\x13")
360
time.sleep(1)
361
if not child.isalive():
362
print("child exited early")
363
print(str(child))
364
print(str(child.buffer))
365
sys.exit(1)
366
child.kill(signal.SIGCONT)
367
send(child, "quit")
368
send(child, "\n")
369
wait(child)
370
except pexpect.TIMEOUT:
371
traceback.print_tb(sys.exc_info()[2])
372
print("timed out")
373
print(str(child))
374
sys.exit(2)
375
except pexpect.EOF:
376
print("EOF")
377
print(str(child))
378
print(str(child.buffer))
379
print(str(child.before))
380
sys.exit(2)
381
382
return child
383
384
385
# Test for SIGSTOP.
386
# @param exe The executable.
387
# @param args The arguments to pass to the executable.
388
# @param env The environment.
389
def test_sigstop(exe, args, env):
390
391
# Because both bc and dc use this, make sure the banner doesn't pop.
392
env["BC_BANNER"] = "0"
393
394
child = pexpect.spawn(exe, args=args, env=env)
395
396
try:
397
send(child, "\t")
398
expect(child, "\t")
399
send(child, "\x14")
400
time.sleep(1)
401
if not child.isalive():
402
print("child exited early")
403
print(str(child))
404
print(str(child.buffer))
405
sys.exit(1)
406
send(child, "\x13")
407
time.sleep(1)
408
if not child.isalive():
409
print("child exited early")
410
print(str(child))
411
print(str(child.buffer))
412
sys.exit(1)
413
child.kill(signal.SIGCONT)
414
send(child, "quit")
415
send(child, "\n")
416
wait(child)
417
except pexpect.TIMEOUT:
418
traceback.print_tb(sys.exc_info()[2])
419
print("timed out")
420
print(str(child))
421
sys.exit(2)
422
except pexpect.EOF:
423
print("EOF")
424
print(str(child))
425
print(str(child.buffer))
426
print(str(child.before))
427
sys.exit(2)
428
429
return child
430
431
432
def test_bc_utf8_0(exe, args, env):
433
return test_utf8_0(exe, args, env, True)
434
435
436
def test_bc_utf8_1(exe, args, env):
437
return test_utf8_1(exe, args, env, True)
438
439
440
def test_bc_utf8_2(exe, args, env):
441
return test_utf8_2(exe, args, env, True)
442
443
444
def test_bc_utf8_3(exe, args, env):
445
return test_utf8_3(exe, args, env, True)
446
447
448
def test_bc_utf8_4(exe, args, env):
449
return test_utf8_4(exe, args, env, True)
450
451
452
# Basic bc test.
453
# @param exe The executable.
454
# @param args The arguments to pass to the executable.
455
# @param env The environment.
456
def test_bc1(exe, args, env):
457
458
child = pexpect.spawn(exe, args=args, env=env)
459
460
try:
461
bc_banner(child)
462
write_str(child, "1")
463
check_line(child, "1")
464
write_str(child, "1")
465
check_line(child, "1")
466
send(child, "quit")
467
send(child, "\n")
468
wait(child)
469
except pexpect.TIMEOUT:
470
traceback.print_tb(sys.exc_info()[2])
471
print("timed out")
472
print(str(child))
473
sys.exit(2)
474
except pexpect.EOF:
475
print("EOF")
476
print(str(child))
477
print(str(child.buffer))
478
print(str(child.before))
479
sys.exit(2)
480
481
return child
482
483
484
# SIGINT with no history.
485
# @param exe The executable.
486
# @param args The arguments to pass to the executable.
487
# @param env The environment.
488
def test_bc2(exe, args, env):
489
490
env["TERM"] = "dumb"
491
492
child = pexpect.spawn(exe, args=args, env=env)
493
494
try:
495
bc_banner(child)
496
child.sendline("1")
497
check_line(child, "1", history=False)
498
time.sleep(1)
499
child.sendintr()
500
child.sendline("quit")
501
wait(child)
502
except pexpect.TIMEOUT:
503
traceback.print_tb(sys.exc_info()[2])
504
print("timed out")
505
print(str(child))
506
sys.exit(2)
507
except pexpect.EOF:
508
print("EOF")
509
print(str(child))
510
print(str(child.buffer))
511
print(str(child.before))
512
sys.exit(2)
513
514
return child
515
516
517
# Left and right arrows.
518
# @param exe The executable.
519
# @param args The arguments to pass to the executable.
520
# @param env The environment.
521
def test_bc3(exe, args, env):
522
523
child = pexpect.spawn(exe, args=args, env=env)
524
525
try:
526
bc_banner(child)
527
send(child, "\x1b[D\x1b[D\x1b[C\x1b[C")
528
send(child, "\n")
529
expect(child, prompt)
530
send(child, "12\x1b[D3\x1b[C4\x1bOD5\x1bOC6")
531
send(child, "\n")
532
check_line(child, "132546")
533
send(child, "12\x023\x064")
534
send(child, "\n")
535
check_line(child, "1324")
536
send(child, "12\x1b[H3\x1bOH\x01\x1b[H45\x1bOF6\x05\x1b[F7\x1bOH8")
537
send(child, "\n")
538
check_line(child, "84531267")
539
send(child, "quit")
540
send(child, "\n")
541
wait(child)
542
except pexpect.TIMEOUT:
543
traceback.print_tb(sys.exc_info()[2])
544
print("timed out")
545
print(str(child))
546
sys.exit(2)
547
except pexpect.EOF:
548
print("EOF")
549
print(str(child))
550
print(str(child.buffer))
551
print(str(child.before))
552
sys.exit(2)
553
554
return child
555
556
557
# Up and down arrows.
558
# @param exe The executable.
559
# @param args The arguments to pass to the executable.
560
# @param env The environment.
561
def test_bc4(exe, args, env):
562
563
child = pexpect.spawn(exe, args=args, env=env)
564
565
try:
566
bc_banner(child)
567
send(child, "\x1b[A\x1bOA\x1b[B\x1bOB")
568
send(child, "\n")
569
expect(child, prompt)
570
write_str(child, "15")
571
check_line(child, "15")
572
write_str(child, "2^16")
573
check_line(child, "65536")
574
send(child, "\x1b[A\x1bOA")
575
send(child, "\n")
576
check_line(child, "15")
577
send(child, "\x1b[A\x1bOA\x1b[A\x1b[B")
578
check_line(child, "65536")
579
send(child, "\x1b[A\x1bOA\x0e\x1b[A\x1b[A\x1b[A\x1b[B\x10\x1b[B\x1b[B\x1bOB\x1b[B\x1bOA")
580
send(child, "\n")
581
check_line(child, "65536")
582
send(child, "quit")
583
send(child, "\n")
584
wait(child)
585
except pexpect.TIMEOUT:
586
traceback.print_tb(sys.exc_info()[2])
587
print("timed out")
588
print(str(child))
589
sys.exit(2)
590
except pexpect.EOF:
591
print("EOF")
592
print(str(child))
593
print(str(child.buffer))
594
print(str(child.before))
595
sys.exit(2)
596
597
return child
598
599
600
# Clear screen.
601
# @param exe The executable.
602
# @param args The arguments to pass to the executable.
603
# @param env The environment.
604
def test_bc5(exe, args, env):
605
606
child = pexpect.spawn(exe, args=args, env=env)
607
608
try:
609
bc_banner(child)
610
send(child, "\x0c")
611
send(child, "quit")
612
send(child, "\n")
613
wait(child)
614
except pexpect.TIMEOUT:
615
traceback.print_tb(sys.exc_info()[2])
616
print("timed out")
617
print(str(child))
618
sys.exit(2)
619
except pexpect.EOF:
620
print("EOF")
621
print(str(child))
622
print(str(child.buffer))
623
print(str(child.before))
624
sys.exit(2)
625
626
return child
627
628
629
# Printed material without a newline.
630
# @param exe The executable.
631
# @param args The arguments to pass to the executable.
632
# @param env The environment.
633
def test_bc6(exe, args, env):
634
635
child = pexpect.spawn(exe, args=args, env=env)
636
637
try:
638
bc_banner(child)
639
send(child, "print \"Enter number: \"")
640
send(child, "\n")
641
expect(child, "Enter number: ")
642
send(child, "4\x1b[A\x1b[A")
643
send(child, "\n")
644
send(child, "quit")
645
send(child, "\n")
646
wait(child)
647
except pexpect.TIMEOUT:
648
traceback.print_tb(sys.exc_info()[2])
649
print("timed out")
650
print(str(child))
651
sys.exit(2)
652
except pexpect.EOF:
653
print("EOF")
654
print(str(child))
655
print(str(child.buffer))
656
print(str(child.before))
657
sys.exit(2)
658
659
return child
660
661
662
# Word start and word end.
663
# @param exe The executable.
664
# @param args The arguments to pass to the executable.
665
# @param env The environment.
666
def test_bc7(exe, args, env):
667
668
child = pexpect.spawn(exe, args=args, env=env)
669
670
try:
671
bc_banner(child)
672
send(child, "\x1bb\x1bb\x1bf\x1bf")
673
send(child, "\n")
674
expect(child, prompt)
675
send(child, "\x1b[0~\x1b[3a")
676
send(child, "\n")
677
expect(child, prompt)
678
send(child, "\x1b[0;4\x1b[0A")
679
send(child, "\n")
680
expect(child, prompt)
681
send(child, "\t")
682
send(child, "\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb")
683
send(child, "\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf")
684
send(child, "\n")
685
expect(child, prompt)
686
write_str(child, "12 + 34 + 56 + 78 + 90")
687
check_line(child, "270")
688
send(child, "\x1b[A")
689
send(child, "\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb\x1bb")
690
send(child, "\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf\x1bf")
691
check_line(child, "270")
692
send(child, "\x1b[A")
693
send(child, "\x1bh\x1bh\x1bf + 14 ")
694
send(child, "\n")
695
check_line(child, "284")
696
send(child, "quit")
697
send(child, "\n")
698
wait(child)
699
except pexpect.TIMEOUT:
700
traceback.print_tb(sys.exc_info()[2])
701
print("timed out")
702
print(str(child))
703
sys.exit(2)
704
except pexpect.EOF:
705
print("EOF")
706
print(str(child))
707
print(str(child.buffer))
708
print(str(child.before))
709
sys.exit(2)
710
711
return child
712
713
714
# Backspace.
715
# @param exe The executable.
716
# @param args The arguments to pass to the executable.
717
# @param env The environment.
718
def test_bc8(exe, args, env):
719
720
child = pexpect.spawn(exe, args=args, env=env)
721
722
try:
723
bc_banner(child)
724
send(child, "12\x1b[D3\x1b[C4\x08\x7f")
725
send(child, "\n")
726
check_line(child, "13")
727
send(child, "quit")
728
send(child, "\n")
729
wait(child)
730
except pexpect.TIMEOUT:
731
traceback.print_tb(sys.exc_info()[2])
732
print("timed out")
733
print(str(child))
734
sys.exit(2)
735
except pexpect.EOF:
736
print("EOF")
737
print(str(child))
738
print(str(child.buffer))
739
print(str(child.before))
740
sys.exit(2)
741
742
return child
743
744
745
# Backspace and delete words.
746
# @param exe The executable.
747
# @param args The arguments to pass to the executable.
748
# @param env The environment.
749
def test_bc9(exe, args, env):
750
751
child = pexpect.spawn(exe, args=args, env=env)
752
753
try:
754
bc_banner(child)
755
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")
756
send(child, "\n")
757
expect(child, prompt)
758
write_str(child, "12 + 34 + 56 + 78 + 90")
759
check_line(child, "270")
760
send(child, "\x1b[A")
761
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")
762
send(child, "\n")
763
check_line(child, "102")
764
send(child, "\x1b[A")
765
send(child, "\x17\x17")
766
send(child, "\n")
767
check_line(child, "46")
768
send(child, "\x17\x17")
769
send(child, "\n")
770
expect(child, prompt)
771
send(child, "quit")
772
send(child, "\n")
773
wait(child)
774
except pexpect.TIMEOUT:
775
traceback.print_tb(sys.exc_info()[2])
776
print("timed out")
777
print(str(child))
778
sys.exit(2)
779
except pexpect.EOF:
780
print("EOF")
781
print(str(child))
782
print(str(child.buffer))
783
print(str(child.before))
784
sys.exit(2)
785
786
return child
787
788
789
# Backspace and delete words 2.
790
# @param exe The executable.
791
# @param args The arguments to pass to the executable.
792
# @param env The environment.
793
def test_bc10(exe, args, env):
794
795
child = pexpect.spawn(exe, args=args, env=env)
796
797
try:
798
bc_banner(child)
799
send(child, "\x1b[3~\x1b[3~")
800
send(child, "\n")
801
expect(child, prompt)
802
send(child, " \x1b[3~\x1b[3~")
803
send(child, "\n")
804
expect(child, prompt)
805
write_str(child, "12 + 34 + 56 + 78 + 90")
806
check_line(child, "270")
807
send(child, "\x1b[A\x1b[A\x1b[A\x1b[B\x1b[B\x1b[B\x1b[A")
808
send(child, "\n")
809
check_line(child, "270")
810
send(child, "\x1b[A\x1b[0;5D\x1b[0;5D\x0b")
811
send(child, "\n")
812
check_line(child, "180")
813
send(child, "\x1b[A\x1521")
814
check_line(child, "21")
815
send(child, "quit")
816
send(child, "\n")
817
wait(child)
818
except pexpect.TIMEOUT:
819
traceback.print_tb(sys.exc_info()[2])
820
print("timed out")
821
print(str(child))
822
sys.exit(2)
823
except pexpect.EOF:
824
print("EOF")
825
print(str(child))
826
print(str(child.buffer))
827
print(str(child.before))
828
sys.exit(2)
829
830
return child
831
832
833
# Swap.
834
# @param exe The executable.
835
# @param args The arguments to pass to the executable.
836
# @param env The environment.
837
def test_bc11(exe, args, env):
838
839
child = pexpect.spawn(exe, args=args, env=env)
840
841
try:
842
bc_banner(child)
843
send(child, "\x1b[A\x02\x14")
844
send(child, "\n")
845
expect(child, prompt)
846
write_str(child, "12 + 34 + 56 + 78")
847
check_line(child, "180")
848
send(child, "\x1b[A\x02\x14")
849
check_line(child, "189")
850
send(child, "quit")
851
send(child, "\n")
852
wait(child)
853
except pexpect.TIMEOUT:
854
traceback.print_tb(sys.exc_info()[2])
855
print("timed out")
856
print(str(child))
857
sys.exit(2)
858
except pexpect.EOF:
859
print("EOF")
860
print(str(child))
861
print(str(child.buffer))
862
print(str(child.before))
863
sys.exit(2)
864
865
return child
866
867
868
# Non-fatal error.
869
# @param exe The executable.
870
# @param args The arguments to pass to the executable.
871
# @param env The environment.
872
def test_bc12(exe, args, env):
873
874
child = pexpect.spawn(exe, args=args, env=env)
875
876
try:
877
bc_banner(child)
878
send(child, "12 +")
879
send(child, "\n")
880
time.sleep(1)
881
if not child.isalive():
882
print("child exited early")
883
print(str(child))
884
print(str(child.buffer))
885
sys.exit(1)
886
send(child, "quit")
887
send(child, "\n")
888
wait(child)
889
except pexpect.TIMEOUT:
890
traceback.print_tb(sys.exc_info()[2])
891
print("timed out")
892
print(str(child))
893
sys.exit(2)
894
except pexpect.EOF:
895
print("EOF")
896
print(str(child))
897
print(str(child.buffer))
898
print(str(child.before))
899
sys.exit(2)
900
901
return child
902
903
904
def test_dc_utf8_0(exe, args, env):
905
return test_utf8_0(exe, args, env, False)
906
907
908
def test_dc_utf8_1(exe, args, env):
909
return test_utf8_1(exe, args, env, False)
910
911
912
def test_dc_utf8_2(exe, args, env):
913
return test_utf8_2(exe, args, env, False)
914
915
916
def test_dc_utf8_3(exe, args, env):
917
return test_utf8_3(exe, args, env, False)
918
919
920
def test_dc_utf8_4(exe, args, env):
921
return test_utf8_4(exe, args, env, False)
922
923
924
# Basic dc test.
925
# @param exe The executable.
926
# @param args The arguments to pass to the executable.
927
# @param env The environment.
928
def test_dc1(exe, args, env):
929
930
child = pexpect.spawn(exe, args=args, env=env)
931
932
try:
933
write_str(child, "1pR")
934
check_line(child, "1")
935
write_str(child, "1pR")
936
check_line(child, "1")
937
write_str(child, "q")
938
send(child, "\n")
939
wait(child)
940
except pexpect.TIMEOUT:
941
traceback.print_tb(sys.exc_info()[2])
942
print("timed out")
943
print(str(child))
944
sys.exit(2)
945
except pexpect.EOF:
946
print("EOF")
947
print(str(child))
948
print(str(child.buffer))
949
print(str(child.before))
950
sys.exit(2)
951
952
return child
953
954
955
# SIGINT with quit.
956
# @param exe The executable.
957
# @param args The arguments to pass to the executable.
958
# @param env The environment.
959
def test_dc2(exe, args, env):
960
961
env["TERM"] = "dumb"
962
963
child = pexpect.spawn(exe, args=args, env=env)
964
965
try:
966
child.sendline("1pR")
967
check_line(child, "1", history=False)
968
time.sleep(1)
969
child.sendintr()
970
child.sendline("q")
971
wait(child)
972
except pexpect.TIMEOUT:
973
traceback.print_tb(sys.exc_info()[2])
974
print("timed out")
975
print(str(child))
976
sys.exit(2)
977
except pexpect.EOF:
978
print("EOF")
979
print(str(child))
980
print(str(child.buffer))
981
print(str(child.before))
982
sys.exit(2)
983
984
return child
985
986
987
# Execute string.
988
# @param exe The executable.
989
# @param args The arguments to pass to the executable.
990
# @param env The environment.
991
def test_dc3(exe, args, env):
992
993
child = pexpect.spawn(exe, args=args, env=env)
994
995
try:
996
write_str(child, "[1 15+pR]x")
997
check_line(child, "16")
998
write_str(child, "1pR")
999
check_line(child, "1")
1000
write_str(child, "q")
1001
send(child, "\n")
1002
wait(child)
1003
except pexpect.TIMEOUT:
1004
traceback.print_tb(sys.exc_info()[2])
1005
print("timed out")
1006
print(str(child))
1007
sys.exit(2)
1008
except pexpect.EOF:
1009
print("EOF")
1010
print(str(child))
1011
print(str(child.buffer))
1012
print(str(child.before))
1013
sys.exit(2)
1014
1015
return child
1016
1017
1018
# The array of bc tests.
1019
bc_tests = [
1020
test_bc_utf8_0,
1021
test_bc_utf8_1,
1022
test_bc_utf8_2,
1023
test_bc_utf8_3,
1024
test_bc_utf8_4,
1025
test_sigint_sigquit,
1026
test_eof,
1027
test_sigint,
1028
test_sigtstp,
1029
test_sigstop,
1030
test_bc1,
1031
test_bc2,
1032
test_bc3,
1033
test_bc4,
1034
test_bc5,
1035
test_bc6,
1036
test_bc7,
1037
test_bc8,
1038
test_bc9,
1039
test_bc10,
1040
test_bc11,
1041
test_bc12,
1042
]
1043
1044
# The array of dc tests.
1045
dc_tests = [
1046
test_dc_utf8_0,
1047
test_dc_utf8_1,
1048
test_dc_utf8_2,
1049
test_dc_utf8_3,
1050
test_dc_utf8_4,
1051
test_sigint_sigquit,
1052
test_eof,
1053
test_sigint,
1054
test_dc1,
1055
test_dc2,
1056
test_dc3,
1057
]
1058
1059
1060
# Print the usage and exit with an error.
1061
def usage():
1062
print("usage: {} [-t] dir [-a] test_idx [exe options...]".format(script))
1063
print(" The valid values for dir are: 'bc' and 'dc'.")
1064
print(" The max test_idx for bc is {}.".format(len(bc_tests) - 1))
1065
print(" The max test_idx for dc is {}.".format(len(dc_tests) - 1))
1066
print(" If -a is given, the number of tests for dir is printed.")
1067
print(" No tests are run.")
1068
sys.exit(1)
1069
1070
1071
# Must run this script alone.
1072
if __name__ != "__main__":
1073
usage()
1074
1075
if len(sys.argv) < 2:
1076
usage()
1077
1078
idx = 1
1079
1080
exedir = sys.argv[idx]
1081
1082
idx += 1
1083
1084
if exedir == "-t":
1085
do_test = True
1086
exedir = sys.argv[idx]
1087
idx += 1
1088
else:
1089
do_test = False
1090
1091
test_idx = sys.argv[idx]
1092
1093
idx += 1
1094
1095
if test_idx == "-a":
1096
if exedir == "bc":
1097
l = len(bc_tests)
1098
else:
1099
l = len(dc_tests)
1100
print("{}".format(l))
1101
sys.exit(0)
1102
1103
test_idx = int(test_idx)
1104
1105
# Set a default executable unless we have one.
1106
if len(sys.argv) >= idx + 1:
1107
exe = sys.argv[idx]
1108
else:
1109
exe = testdir + "/../bin/" + exedir
1110
1111
exebase = os.path.basename(exe)
1112
1113
# Use the correct options.
1114
if exebase == "bc":
1115
halt = "halt\n"
1116
options = "-l"
1117
test_array = bc_tests
1118
else:
1119
halt = "q\n"
1120
options = "-x"
1121
test_array = dc_tests
1122
1123
# More command-line processing.
1124
if len(sys.argv) > idx + 1:
1125
exe = [ exe, sys.argv[idx + 1:], options ]
1126
else:
1127
exe = [ exe, options ]
1128
1129
# This is the environment necessary for most tests.
1130
env = {
1131
"BC_BANNER": "1",
1132
"BC_PROMPT": "1",
1133
"DC_PROMPT": "1",
1134
"BC_TTY_MODE": "1",
1135
"DC_TTY_MODE": "1",
1136
"BC_SIGINT_RESET": "1",
1137
"DC_SIGINT_RESET": "1",
1138
}
1139
1140
# Make sure to include the outside environment.
1141
env.update(os.environ)
1142
env.pop("BC_ENV_ARGS", None)
1143
env.pop("BC_LINE_LENGTH", None)
1144
env.pop("DC_ENV_ARGS", None)
1145
env.pop("DC_LINE_LENGTH", None)
1146
1147
# Run the correct test.
1148
child = test_array[test_idx](exe[0], exe[1:], env)
1149
1150
child.close()
1151
1152
exit = child.exitstatus
1153
1154
if exit is not None and exit != 0:
1155
print("child failed; expected exit code 0, got {}".format(exit))
1156
print(str(child))
1157
sys.exit(1)
1158
1159