summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/PexpectTestCase.py36
-rw-r--r--tests/README18
-rw-r--r--tests/TESTDATA.txt8
-rwxr-xr-xtests/__init__.py25
-rwxr-xr-xtests/adhoc.py34
-rw-r--r--tests/bambi.vt417
-rwxr-xr-xtests/depricated_test_filedescriptor.py83
-rwxr-xr-xtests/echo_wait.py39
-rwxr-xr-xtests/exit1.py24
-rw-r--r--tests/exit667.c26
-rwxr-xr-xtests/getch.py39
-rw-r--r--tests/globe.vt690
-rwxr-xr-xtests/interact.py23
-rwxr-xr-xtests/pexpectTest.py67
-rw-r--r--tests/platform_tests/CSIGNALTEST/test.c90
-rw-r--r--tests/platform_tests/README4
-rw-r--r--tests/platform_tests/pexqa.py39
-rwxr-xr-xtests/platform_tests/test.py74
-rwxr-xr-xtests/platform_tests/test2.py42
-rwxr-xr-xtests/platform_tests/test_badfork.py15
-rwxr-xr-xtests/platform_tests/test_control_terminal.py19
-rwxr-xr-xtests/platform_tests/test_handler.py54
-rwxr-xr-xtests/platform_tests/test_killed_pid.py17
-rwxr-xr-xtests/platform_tests/test_middle_buffer.py30
-rwxr-xr-xtests/platform_tests/test_read.py35
-rwxr-xr-xtests/platform_tests/test_signals.py63
-rwxr-xr-xtests/qa.py26
-rwxr-xr-xtests/sigwinch_report.py46
-rwxr-xr-xtests/swapcase_echo.py26
-rwxr-xr-xtests/test_ansi.py133
-rwxr-xr-xtests/test_command_list_split.py39
-rwxr-xr-xtests/test_constructor.py49
-rwxr-xr-xtests/test_ctrl_chars.py109
-rwxr-xr-xtests/test_destructor.py78
-rwxr-xr-xtests/test_dotall.py44
-rwxr-xr-xtests/test_expect.py424
-rwxr-xr-xtests/test_filedescriptor.py84
-rwxr-xr-xtests/test_interact.py81
-rwxr-xr-xtests/test_isalive.py105
-rwxr-xr-xtests/test_log.py102
-rwxr-xr-xtests/test_misc.py217
-rwxr-xr-xtests/test_missing_command.py38
-rwxr-xr-xtests/test_performance.py91
-rwxr-xr-xtests/test_run.py61
-rwxr-xr-xtests/test_run_out_of_pty.py52
-rwxr-xr-xtests/test_screen.py191
-rwxr-xr-xtests/test_timeout_pattern.py86
-rwxr-xr-xtests/test_winsize.py66
-rw-r--r--tests/tetris.data3
-rwxr-xr-xtests/ticker.py28
-rw-r--r--tests/torturet.vt61
51 files changed, 4251 insertions, 0 deletions
diff --git a/tests/PexpectTestCase.py b/tests/PexpectTestCase.py
new file mode 100644
index 0000000..f6dff60
--- /dev/null
+++ b/tests/PexpectTestCase.py
@@ -0,0 +1,36 @@
+
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+import unittest
+import sys
+import os
+
+class PexpectTestCase(unittest.TestCase):
+ def setUp(self):
+ self.PYTHONBIN = sys.executable
+ self.original_path = os.getcwd()
+ newpath = os.path.join (os.environ['PROJECT_PEXPECT_HOME'], 'tests')
+ os.chdir (newpath)
+ print '\n', self.id(),
+ unittest.TestCase.setUp(self)
+ def tearDown(self):
+ os.chdir (self.original_path)
+
diff --git a/tests/README b/tests/README
new file mode 100644
index 0000000..295632b
--- /dev/null
+++ b/tests/README
@@ -0,0 +1,18 @@
+
+The best way to run these tests is from the directory above this one. Source
+the test.env environment file. This will make sure that you are using the
+correct pexpect.py file otherwise Python might try to import a different
+version if it is already installed in this environment. Then run the testall.py
+script in the tools/ directory. This script will automatically build a test
+suite from all the test scripts in the tests/ directory. This allows you to add
+new test scripts simply by dropping them in the tests/ directory. You don't
+have to register the test or do anything else to integrate it into the test
+suite.
+
+For example, this is the normal set of commands you would use to run all tests
+in the tests/ directory:
+
+ $ cd /home/user/pexpect_dev/
+ $ . test.env
+ $ ./tools/testall.py
+
diff --git a/tests/TESTDATA.txt b/tests/TESTDATA.txt
new file mode 100644
index 0000000..adb9c01
--- /dev/null
+++ b/tests/TESTDATA.txt
@@ -0,0 +1,8 @@
+This is test data.
+ One
+ 2
+ THREE
+ IV
+ .....
+ 110
+This is the end of test data: END
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100755
index 0000000..f717d82
--- /dev/null
+++ b/tests/__init__.py
@@ -0,0 +1,25 @@
+
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+# __init__.py
+# The mere presence of this file makes the dir a package.
+pass
+
diff --git a/tests/adhoc.py b/tests/adhoc.py
new file mode 100755
index 0000000..8567a71
--- /dev/null
+++ b/tests/adhoc.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import time
+
+p = pexpect.spawn ('./a.out')
+print p.exitstatus
+p.expect (pexpect.EOF)
+print p.before
+time.sleep(1)
+print 'exitstatus:', p.exitstatus
+print 'isalive',p.isalive()
+print 'exitstatus',p.exitstatus
+print 'isalive',p.isalive()
+print 'exitstatus',p.exitstatus
+
diff --git a/tests/bambi.vt b/tests/bambi.vt
new file mode 100644
index 0000000..853f099
--- /dev/null
+++ b/tests/bambi.vt
@@ -0,0 +1,417 @@
+[?25l
+
+
+ The
+ The Adventures
+ The Adventures of
+ The Adventures of BAMBI
+
+ Number
+ Number One :
+ Number One : BAMBI
+ Number One : BAMBI versus
+ Number One : BAMBI versus GODZILLA
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ,| *./\|(/|/
+ /| |/`|',/| \|/
+ \/_,| /| /, /<|\\/\|/|\
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::. . /
+ \___________/
+ |\ |\
+ | > | \
+ / / | \
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::. . /
+ \___________/
+ \| |\
+ \ | \
+ / \ / |
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::. . /
+ \___________/
+ \\ \|
+ \\ \
+ | \ |\
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::. . /
+ \___________/
+ \\ \|
+ >\ \
+ / | /|
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ |\ |\
+ | > | \
+ / / | \
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ \| |\
+ \ | \
+ / \ / |
+
+
+--,_^_
+. .\
+__--___o
+--_
+. \
+__ \/|
+|\( .|
+| \\ /
+ | "
+--_
+. \
+__ \/|
+|\( .|
+| \\ /
+ | "
+--_
+. \
+__ \/|
+|\( .|
+| \\ /
+ | "
+--_
+. \
+__ \/|
+|\( .|
+| \\ /
+ | "
+--,_^_
+. .\
+__--___o
+|\
+| \
+ |
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ \\ \|
+ \\ \
+ | \ |\
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ \\ \|
+ >\ \
+ / | /|
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ |\ |\
+ | > | \
+ / / | \
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ \| |\
+ \ | \
+ / \ / |
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ \\ \|
+ \\ \
+ | \ |\
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ \\ \|
+ >\ \
+ / | /|
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ |\ |\
+ | > | \
+ / / | \
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ \| |\
+ \ | \
+ / \ / |
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ \\ \|
+ \\ \
+ | \ |\
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ \\ \|
+ >\ \
+ / | /|
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ |\ |\
+ | > | \
+ / / | \
+
+
+--,_^_
+. .\
+__--___o
+--_
+. \
+__ \/|
+|\( .|
+| \\ /
+| \"
+--_
+. \
+__ \/|
+|\( .|
+| \\ /
+| \"
+--,_^_
+. .\
+__--___o
+|\
+| \
+| \
+--,_^_
+. .\
+__--___o
+|\
+| \
+| \
+--_
+. \
+__ \/|
+|\( .|
+| \\ /
+| \"
+--_
+. \
+__ \/|
+|\( .|
+| \\ /
+| \"
+--_
+. \
+__ \/|
+|\( .|
+| \\ /
+| \"
+--,_^_
+. .\
+__--___o
+|\
+| \
+| \
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ \| |\
+ \ | \
+ / \ / |
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ \\ \|
+ \\ \
+ | \ |\
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ \\ \|
+ >\ \
+ / | /|
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ |\ |\
+ | > | \
+ / / | \
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ \| |\
+ \ | \
+ / \ / |
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ \\ \|
+ \\ \
+ | \ |\
+ _^_
+ o / .\
+ \,--------; __o
+ / .:::.. . /
+ \___________/
+ \\ \|
+ >\ \
+ / | /|
+
+ o
+ \,----------,_^_
+ / .:::.. . .\
+ \___________--___o
+ \\ \|
+ >\ \
+ / | /|
+
+ o
+ \,----------_
+ / .:::.. . \
+ \___________ \/|
+ \\ \|( .|
+ >\ \ \ /
+ / | /| "
+
+`' `.__________________________________/M
+( / (/M
+(-.___)M
+/ \/)M
+_______.--'\M
+,____________/\M
+( / )M
+( ) /M
+\ \ )M
+( )M
+( ( /M
+\ ( )M
+( \ )M
+( ( /M
+
+\ ( ) )M
+
+( ( / )M
+
+( \ ) /M
+
+\ ( ) )M
+
+( ) )M
+
+( ) /M
+
+\ / )M
+
+( ) )
+ / > | \
+
+
+ T T T
+ T H T H T H
+ T H E T H E T H E  T H E
+ T H E E T H E E T H E E
+ T H E E N T H E E N T H E E N
+ T H E E N D T H E E N D
+ ===============
+
+[?25h
diff --git a/tests/depricated_test_filedescriptor.py b/tests/depricated_test_filedescriptor.py
new file mode 100755
index 0000000..f5223f4
--- /dev/null
+++ b/tests/depricated_test_filedescriptor.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import PexpectTestCase
+import sys
+import os
+
+class ExpectTestCase(PexpectTestCase.PexpectTestCase):
+ def setUp(self):
+ print self.id()
+ PexpectTestCase.PexpectTestCase.setUp(self)
+
+ def test_fd (self):
+ fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+ s = pexpect.spawn (fd)
+ s.expect ('This is the end of test data:')
+ s.expect (pexpect.EOF)
+ assert s.before == ' END\n'
+
+ def test_maxread (self):
+ fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+ s = pexpect.spawn (fd)
+ s.maxread = 100
+ s.expect('2')
+ s.expect ('This is the end of test data:')
+ s.expect (pexpect.EOF)
+ assert s.before == ' END\n'
+
+ def test_fd_isalive (self):
+ fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+ s = pexpect.spawn (fd)
+ assert s.isalive()
+ os.close (fd)
+ assert not s.isalive()
+
+ def test_fd_isatty (self):
+ fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+ s = pexpect.spawn (fd)
+ assert not s.isatty()
+ os.close(fd)
+
+### def test_close_does_not_close_fd (self):
+### '''Calling close() on a pexpect.spawn object should not
+### close the underlying file descriptor.
+### '''
+### fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+### s = pexpect.spawn (fd)
+### try:
+### s.close()
+### self.fail('Expected an Exception.')
+### except pexpect.ExceptionPexpect, e:
+### pass
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(ExpectTestCase, 'test')
+
+#fout = open('delete_me_1','wb')
+#fout.write(the_old_way)
+#fout.close
+#fout = open('delete_me_2', 'wb')
+#fout.write(the_new_way)
+#fout.close
diff --git a/tests/echo_wait.py b/tests/echo_wait.py
new file mode 100755
index 0000000..db940de
--- /dev/null
+++ b/tests/echo_wait.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import signal, time, struct, fcntl, termios, os, sys
+
+# a dumb PAM will print the password prompt first then set ECHO
+# False. What it should do it set ECHO False first then print the
+# prompt. Otherwise, if we see the password prompt and type out
+# password real fast before it turns off ECHO then some or all of
+# our password might be visibly echod back to us. Sounds unlikely?
+# It happens.
+
+print "fake password:"
+sys.stdout.flush()
+time.sleep(3)
+attr = termios.tcgetattr(sys.stdout)
+attr[3] = attr[3] & ~termios.ECHO
+termios.tcsetattr(sys.stdout, termios.TCSANOW, attr)
+time.sleep(12)
+attr[3] = attr[3] | termios.ECHO
+termios.tcsetattr(sys.stdout, termios.TCSANOW, attr)
+time.sleep(2)
diff --git a/tests/exit1.py b/tests/exit1.py
new file mode 100755
index 0000000..4e07377
--- /dev/null
+++ b/tests/exit1.py
@@ -0,0 +1,24 @@
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import os, sys
+
+print "Hello"
+sys.stdout.flush()
+os._exit(1)
diff --git a/tests/exit667.c b/tests/exit667.c
new file mode 100644
index 0000000..962b9fd
--- /dev/null
+++ b/tests/exit667.c
@@ -0,0 +1,26 @@
+/*
+ PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+#include <stdio.h>
+int main ()
+{
+ printf ("Hello world!\n");
+ exit(7);
+}
diff --git a/tests/getch.py b/tests/getch.py
new file mode 100755
index 0000000..53ff2c7
--- /dev/null
+++ b/tests/getch.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import sys, tty, termios
+def getch():
+ fd = sys.stdin.fileno()
+ old_settings = termios.tcgetattr(fd)
+ try:
+ tty.setraw(sys.stdin.fileno())
+ ch = sys.stdin.read(1)
+ finally:
+ termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
+ return ch
+
+#for i in range(256):
+# Current Python unicode support was too hard to figure out.
+# This only tests the true ASCII characters now:
+for i in range(126):
+ c = getch()
+ a = ord(c) # chr(a)
+ print a
+
diff --git a/tests/globe.vt b/tests/globe.vt
new file mode 100644
index 0000000..85dc78d
--- /dev/null
+++ b/tests/globe.vt
@@ -0,0 +1,690 @@
+ _-o#&&*''''?d:>b\_
+ _o/"`'' '',, dMF9MMMMMHo_
+ .o&#' `"MbHMMMMMMMMMMMHo.
+ .o"" ' vodM*$&&HMMMMMMMMMM?.
+ ,' $M&ood,~'`(&##MMMMMMH\
+ / ,MMMMMMM#b?#bobMMMMHMMML
+ & ?MMMMMMMMMMMMMMMMM7MMM$R*Hk
+ ?$. :MMMMMMMMMMMMMMMMMMM/HMMM|`*L
+| |MMMMMMMMMMMMMMMMMMMMbMH' T,
+$H#: `*MMMMMMMMMMMMMMMMMMMMb#}' `?
+]MMH# ""*""""*#MMMMMMMMMMMMM' -
+MMMMMb_ |MMMMMMMMMMMP' :
+HMMMMMMMHo `MMMMMMMMMT .
+?MMMMMMMMP 9MMMMMMMM} -
+-?MMMMMMM |MMMMMMMMM?,d- '
+ :|MMMMMM- `MMMMMMMT .M|. :
+ .9MMM[ &MMMMM*' `' .
+ :9MMk `MMM#" -
+ &M} ` .-
+ `&. .
+ `~, . ./
+ . _ .-
+ '`--._,dd###pp=""'
+ _v->#H#P? "':o<>\_
+ .,dP` `'' "'-o.+H6&MMMHo_
+ oHMH9' `?&bHMHMMMMMMHo.
+ oMP"' ' ooMP*#&HMMMMMMM?.
+ ,M* - `*MSdob//`^&##MMMH\
+ d*' .,MMMMMMH#o>#ooMMMMMb
+ HM- :HMMMMMMMMMMMMMMM&HM[R\
+ d"Z\. 9MMMMMMMMMMMMMMMMM[HMM|:
+-H - MMMMMMMMMMMMMMMMMMMbMP' :
+:??Mb# `9MMMMMMMMMMMMMMMMMMH#! .
+: MMMMH#, "*""""`#HMMMMMMMMMMH -
+||MMMMMM6\. {MMMMMMMMMH' :
+:|MMMMMMMMMMHo `9MMMMMMMM' .
+. HMMMMMMMMMMP' !MMMMMMMM `
+- `#MMMMMMMMM HMMMMMMM*,/ :
+ : ?MMMMMMMF HMMMMMM',P' :
+ . HMMMMR' {MMMMP' ^' -
+ : `HMMMT iMMH' .'
+ -.`HMH .
+ -:*H . '
+ -`\,, . .-
+ ' . _ .-`
+ '`~\.__,obb#q==~'''
+ .ovr:HMM#?:`' >b\_
+ .,:&Hi' `' "' \\|&bSMHo_
+ oHMMM#*} `?&dMMMMMMHo.
+ .dMMMH"'''' ,oHH*&&9MMMM?.
+ ,MMM*' `*M\bd<|"*&#MH\
+ dHH?' :MMMMMM#bd#odMML
+ H' |\ `dMMMMMMMMMMMMMM9Mk
+ JL/"7+,. `MMMMMMMMMMMMMMMH9ML
+-`Hp ' |MMMMMMMMMMMMMMMMHH|:
+: \\#M#d? `HMMMMMMMMMMMMMMMMH.
+. JMMMMM##, ``*""'"*#MMMMMMMMH
+-. ,MMMMMMMM6o_ |MMMMMMMM':
+: |MMMMMMMMMMMMMb\ TMMMMMMT :
+. ?MMMMMMMMMMMMM' :MMMMMM|.`
+- ?HMMMMMMMMMM: HMMMMMM\|:
+ : 9MMMMMMMMH' `MMMMMP.P.
+ . `MMMMMMT'' HMMM*''-
+ - TMMMMM' MM*' -
+ '. HMM# -
+ -. `9M: .'
+ -. `b,, . . '
+ '-\ ., .-`
+ '-:b~\\_,oddq==--"
+ _oo##'9MMHb':'-,o_
+ .oH":HH$' ""' "' -\7*R&o_
+ .oHMMMHMH#9: "\bMMMMHo.
+ dMMMMMM*""'`' .oHM"H9MM?.
+ ,MMMMMM' "HLbd<|?&H\
+ JMMH#H' |MMMMM#b>bHb
+ :MH ."\ `|MMMMMMMMMMMM&
+ .:M:d-"|:b.. 9MMMMMMMMMMMMM+
+: "*H| - &MMMMMMMMMMMMMH:
+. `LvdHH#d? `?MMMMMMMMMMMMMb
+: iMMMMMMH#b `"*"'"#HMMMMMM
+. . ,MMMMMMMMMMb\. {MMMMMH
+- |MMMMMMMMMMMMMMHb, `MMMMM|
+: |MMMMMMMMMMMMMMH' &MMMM,
+- `#MMMMMMMMMMMM |MMMM6-
+ : `MMMMMMMMMM+ ]MMMT/
+ . `MMMMMMMP" HMM*`
+ - |MMMMMH' ,M#'-
+ '. :MMMH| .-
+ . |MM -
+ ` . `#?.. . ..'
+ -. _. .-
+ '-|.#qo__,,ob=~~-''
+ _ooppH[`MMMD::--\_
+ _oHMR":&M&. ""' "' /&\\_
+ oHMMMMMHMMH#9, `"<MMHo.
+ oHMMMMMMMM*""'`` .dMP#M?.
+ .dMMMMMMMM* `H\do?&\
+ -iMMMHH#H' &MMMHb#?
+ : ZMM' 7-. `{MMMMMMMMH
+ . .M6_d|"`$|v.. 9MMMMMMMMML
+- `'*H# : |MMMMMMMMMM:
+: *\\dHM#dd. ?MMMMMMMMMb
+- |MMMMMMM##\ `"*""?HMMM
+: . |MMMMMMMMMMMo\. {MMM
+. {MMMMMMMMMMMMMMMHo. `MMM
+- ?MMMMMMMMMMMMMMM*' -MMP
+: `#MMMMMMMMMMMMT dMM'
+ - |MMMMMMMMMMH' -MMT
+ : `MMMMMMMM"' JMP
+ - MMMMMMH' ,H?
+ '. HMMM#' :
+ . ?MM- . '
+ -. *M:.. .-
+ - . _. .-
+ '-.~-dHb__\ov+~~-`
+ .oo>#&H6?*MMH:-.._
+ .oHMMMR:"&MZ\ `"' " |$-_
+ ..dMMMMMMMMdMMM#9\ `'HHo.
+ . ,dMMMMMMMMMMM"`' ` ?MP?.
+ . |MMMMMMMMMMM' `"$b&\
+ - |MMMMHH##M' HMMH?
+ - TTMM| >.. \MMMMMH
+ : |MM\,#-""$~b\. `MMMMMM+
+. ``"H&# - &MMMMMM|
+: *\v,#MHddc. `9MMMMMb
+. MMMMMMMM##\ `"":HM
+- . .HMMMMMMMMMMRo_. |M
+: |MMMMMMMMMMMMMMMM#\ :M
+- `HMMMMMMMMMMMMMMM' |T
+: `*HMMMMMMMMMMMM' H'
+ : MMMMMMMMMMM| |T
+ . MMMMMMMM?' ./
+ `. MMMMMMH' ./
+ -. |MMMH#' .
+ . `MM* . '
+ -. #M: . . .-
+ ` . ., .-
+ '-.-~ooHH__,,v~--`
+ _ood>H&H&Z?#M#b-\.
+ .\HMMMMMR?`\M6b."`' ''``v.
+ .. .MMMMMMMMMMHMMM#&. ``~o.
+ . ,HMMMMMMMMMMMM*"'-` &b.
+ . .MMMMMMMMMMMMH' `"&\
+ - RMMMMM#H##R' 4Mb
+ - |7MMM' ?:: `|MMb
+ / HMM__#|`"\>?v.. `MMML
+. `"'#Hd| ` 9MMM:
+- |\,\?HH#bbL `9MMb
+: !MMMMMMMH#b, `""T
+. . ,MMMMMMMMMMMbo. |
+: 4MMMMMMMMMMMMMMMHo |
+: ?MMMMMMMMMMMMMMM? :
+-. `#MMMMMMMMMMMM: .-
+ : |MMMMMMMMMM? .
+ - JMMMMMMMT' :
+ `. MMMMMMH' -
+ -. |MMM#*` -
+ . HMH' . '
+ -. #H:. .-
+ ` . .\ .-
+ '-..-+oodHL_,--/-`
+ _,\?dZkMHF&$*q#b..
+ .//9MMMMMMM?:'HM\\"`-''`..
+ ..` :MMMMMMMMMMHMMMMH?_ `-\
+ . .dMMMMMMMMMMMMMM'"'" `\.
+ . |MMMMMMMMMMMMMR \\
+ - T9MMMMMHH##M" `?
+ : (9MMM' !':. &k
+ .: HMM\_?p "":-b\. `ML
+- "'"H&#, : |M|
+: ?\,\dMH#b#. 9b
+: |MMMMMMM##, `*
+: . +MMMMMMMMMMMo_ -
+: HMMMMMMMMMMMMMM#, :
+: 9MMMMMMMMMMMMMH' .
+: . *HMMMMMMMMMMP .'
+ : MMMMMMMMMH' .
+ - :MMMMMMM'` .
+ `. 9MMMMM*' -
+ -. {MMM#' :
+ - |MM" .'
+ `. &M'.. . ..'
+ ' . ._ .-
+ '-. -voboo#&:,-.-`
+ _oo:\bk99M[<$$+b\.
+ .$*"MMMMMMMM[:"\Mb\?^" .
+ . '` HMMMMMMMMMMHMMMM+?. `.
+ . .HMMMMMMMMMMMMMMP"'' .
+ . `MMMMMMMMMMMMMM| -`.
+ - `&MMMMMMHH##H: :
+ : `(*MMM} `|\ |
+ : `- ?MMb__#|""`|+v.. \
+. `''*H#b - :|
+: `*\v,#M#b#, \
+. 9MMMMMMHb. :
+: . #MMMMMMMMMb\ -
+- .HMMMMMMMMMMMMb :
+: `MMMMMMMMMMMMH .
+-: . `#MMMMMMMMMP '
+ : ]MMMMMMMH' :
+ - ,MMMMMM?' .
+ `: HMMMMH" -
+ -. .HMM#* .-
+ `. .HH*' .
+ `-. &R". .-
+ -. ._ .-
+ '-. .voodoodc?..-`
+ _\oo\?ddk9MRbS>v\_
+ ..:>*""MMMMMMMMM:?|H?$?-.
+ ..- - "HMMMMMMMMMMHMMMH\_-.
+ . dMMMMMMMMMMMMMMT" .
+ . TMMMMMMMMMMMMMM `.
+ - `&HMMMMMM#H#H: .
+ - `\7HMMH |\. .
+ : ` HMM\_?c`""+?\.. :
+- "``#&#| . -
+: `?,\#MHdb. .
+: |MMMMMH#. :
+: . ,HMMMMMMMb, -
+: ' 4MMMMMMMMMMH`
+: . 9MMMMMMMMMT-
+:.` `#MMMMMMMH '
+ : ' HMMMMMH':
+ - |MMMMH" -
+ `: |MMMH*' .'
+ '? dMM#' .
+ \. .dH" .'
+ -. ,M'- ..'
+ ` . .. ..-`
+ '-. .\ooooboo<^.-`
+ _o,:o?\?dM&MHcc~,.
+ ..^':&#""HMMMMMMMM$:?&&?.
+ .` -` 'HMMMMMMMMMHMMMp\.
+ . ' |MMMMMMMMMMMMMM"' .
+ . `9MMMMMMMMMMMMM -.
+ - `*9MMMMMHH##[ .
+ - `\Z9MMM `~\ .
+ : '| ?MMb_?p""-?v.. :
+- `"'*&#, - .
+: `?,oHH#? .
+-- |MMMMH,:
+: . |MMMMMM6,
+: - |MMMMMMMM
+? HMMMMMMP
+-- . ' |HMMMMM'
+ :.` . ' JMMMM+
+ \ ,MMMP:
+ : |MMH?:
+ -:\. dM#" .
+ \ ,H*' .'
+ -. d':..'
+ ` . .,.-
+ '-.. .\oooodov~^-`
+ _o\:,??\??MR9#cb\_
+ .v/''':&#""#HMMMMMMM$?*d\.
+ ..~' - -` `"#MMMMMMMMMMMHv.
+ .-' HMMMMMMMMMMMR!.
+ : `9MMMMMMMMMMM| -.
+ . `*9MMMMMH##| .
+ - `(#MMH `:, .
+ : '| `HMb_>/"|\,.:
+.' `"'#&b - .
+: ?\oHH?.
+: !MMM&
+: . . HMMMM
+/. - -MMMMM
+\`. 9MMMP
+:. . . - |MMM'
+ \... ' .MMT
+ &. .dMP
+ \, .HM*
+ \. `\. ,H&'
+ `- `| - ,&':
+ `. ,/\ '
+ '-.. _.-
+ "---.._\o,oov+--'"
+ _,d?,:?o?:?HM>#b\_
+ ..H*"''`'H#*"**MMMMMM6$$v_
+ v//" - `` `'#MMMMMMMMHo.
+ /"` |MMMMMMMMMM:.
+ ,> `HMMMMMMMMH:.
+ : `#HMMMMHH\ -
+ ' `Z#MM, `,:
+ : '\ ?HH_>:`\,
+: "'*&| `:
+. <\Hb
+: MM
+: . iMM
+Mb\. {MM
+::.`- - !MP
+`&. . . - :M'
+ 9H, \ ' |T
+ HM? ,P
+ *ML ??
+ :&. `o .d'
+ ': |T /"
+ -. .<''
+ `... ..-
+ "`-=.,_,,,oov-~.-`
+ _,oc>?_:b?o?HH#b\_
+ .v/99*""" '*H#""*HMMMMMZ,_
+ oH* /" - ' "`#MMMMM#o.
+ ./*>- `MMMMMMMb
+ ,b/' `#MMMMMMM\
+ :' ``HMMMMb:
+ /- `|&MH `\
+ / `-. |Hb??\
+,- ' "`&,.
+1 \}
+!. T
+$,. . 1
+?`M??. M
+?.::| '\ - ?
+ M?&. . . - ,'
+ 9MMH\ .. ' ` .
+ HMMM#. :'
+ 9#MMb ..
+ -:"# `b. .-
+ . ` {! /
+ - ,-'
+ ' . .-
+ ```^==\_.,,,ov--\-`
+ _\o##??,:io??$#b\_
+ .oH#"H9*""" "`#H*"*#MMMHo_
+ oHMM- -' - '' ``*HMMHo.
+ dM#S>-` ?MMMM?.
+ ,&&,/' "#MMMH\
+ d?-" `*HMMb
+ H? "ZHb:
+ /: \ H?L
+|:| . `*:
+:?: \
+>" :
+M|\,_ |
+!|":HH?-'. :
+:^'_:?"\ `-- - .
+- |ML?b . .. - -
+ :HMMMMH\ \ ` :
+ >MMMMMM#. .
+ ^M*HMMM| -
+ `. `"#+ `?v .`
+ . `- +?' -
+ ` . ..'
+ - . .-
+ "`\b=p?.._\\vv---`
+ _,o#bH\??::?o?cbo_
+ .o#MH#**SH""' "`*H#"*#MHo_
+ oHMMMH^ ^" - ` '*HHo.
+ .dMMM#">>- `HM?.
+ ,MH:R_o/ `*MH\
+ dMM' ' "ML
+ HMR! ' `#k
+ d&'. -. `L
+:M :: ` `-
+/| !| -
+k.$-" :
+}9R:!,,_. .
+\::\':`*M#\-'. -
+: "''..:"!`\ '- - `
+- ,HMb.H| . _ - .'
+ : ,MMMMMMMb. .. .
+ .`HMMMMMMMM? .
+ `.`9M#*HMMMM :
+ -.' "##* `b, .
+ . ` ,/' .'
+ ` . ..'
+ - . ..-
+ "`*#d##c.._\v----`
+ _,o#&oHb?\o::d?>\_
+ .oHHMMM#**$M""` "`*HH"#&o_
+ oHMMMMMMD' .'' - ' ``bo.
+ .dMMMMMH*'/|- `\b.
+ ,MMMM?T|_o/ `\\
+ dMMMMP '' `|
+ HMMMH& - `\
+ /MH7' : -- :
+-:MM {. . .
+:i?' .!& .
+:{, o| ' :
+-T?9M\:-'o,_ .
+: \?::``"`?9MHo./.. -
+. '"`'^ _.`"!"^. `- - `
+- ,bMM?.M\ . . - . .'
+ : .oMMMMMMMMb. .. ` .
+ . `HMMMMMMMMMMb -
+ - 9MH*#HMMMMH .'
+ '. ' `"*##' `b. :
+ . ` .d'' .'
+ -. . '
+ -. .-`
+ "`*##H###:._\--.-`
+ _oo#H&d#b?\b:_>>\_
+ .oHMMMMMMH*"*9R"'-``*#P\-_
+ oHMMMMMMMMM$ ." ' `^-
+ .dMMMMMMMMH*",?- '\.
+ ,MMMMMMM:?}.,d' `.
+ dMMMMMMMH /'' :
+ HMMMMMMM&' - -
+ dPTMMP>' : -. :
+|? -MM} .\ .
+J' ::*' -$L .
+: ?b .,H- ' :
+- |6.&MP:: !.,_. -
+: `\:: "' "`:"MM#,-^, - :
+- ````:' _.:"?``\ `- .
+: .?bMML.]# - _ ` . .'
+ - .o#MMMMMMMMH\ \. . .
+ - `HMMMMMMMMMMMH :
+ `. `HMM#*#MMMMMH' -
+ -. ' ``##*' i+ :
+ - `' v/' .'
+ `- ..'
+ ' . .-
+ "`*##HMH##:__,-.-`
+ _oo##Mbb&bo??o_>\_
+ .oHMMMMMMMMM**#?M*' "?*&..
+ oHMMMMMMMMMMMM4 `" - `.
+ .dMMMMMMMMMMMM#"\?.- .
+ ,MMMMMMMMMM}"9:_,d' -.
+ dMMMMMMMMMMM| ^'' .
+ &MMMMMMMMMMH\ - .
+ :{M*"MMMPT"' : `-. :
+.'M' 'MMM. -T, . .
+- k i:?'' -|& .
+: ` -o& .,H- " :
+- `M:`HMP|:'!.o._. .
+: "<:::'<^ '"``9MH#,-^ . -
+- '''``''._.`"?`^| ^ - :
+: ?#dMM_.M? . . - ..'
+ : ,ddMMMMMMMMMb. .. ' .
+ . TMMMMMMMMMMMMM, :
+ - ?MMH**#MMMMMH' :
+ '. ' "`##*' &. :
+ -. `' ,~" .'
+ -. ..'
+ ` . .-
+ ```*##HMMMH#<:,..-`
+ _,dd#HMb&dHo?\?:\_
+ .oHMMMMMMMMMMMH***9P'`"\v.
+ oHMMMMMMMMMMMMMMM> `' -.
+ .dMMMMMMMMMMMMMMMH*'|~-' .
+ ,MMMMMMMMMMMMM6>`H._,& -.
+ dMMMMMMMMMMMMMMM| `" .
+ H*MMMMMMMMMMMMMH&. - .
+ d' HMM""&MMMPT'' :. `.-
+,' MP `TMMM, |: . -
+| #: ? *" : &L :
+! `' /?H ,#r `' :
+. ?M: HMM^<~->,o._ :
+: `9:::'`*-``':`9MHb,|-, ' :
+. `"''':' :_ ""!"^. `| :
+`. _dbHM6_|H. . . ' .'
+ \ _odHMMMMMMMMH, .. ` :
+ `- |MMMMMMMMMMMMM| :
+ `. 9MMH**#MMMMMH' :
+ -. ' "?##" d :
+ . ' ,/" .'
+ `.. ..'
+ ` . .-
+ '`"#HHMMMMM#<>..-`
+ _oo##bHMb&d#bd,>\_
+ .oHMMMMMMMMMMMMMM***9R"-..
+ oHMMMMMMMMMMMMMMMMMH\ ? `-.
+ .dMMMMMMMMMMMMMMMMMMM#".}-' .
+ ,MMMMMMMMMMMMMMMMM6/`H _o} -.
+ dMMMMMMMMMMMMMMMMMMML `'' .
+ HbP*HMMMMMMMMMMMMMMM*: - ,
+ dMH' `MMMP'"HMMMR'T" : :
+|H' -MR' `?MMMb P, . .
+1& *| |.`*" .-`&| .
+M' " |\&| .,#~ "' :
+T :HL.|HMH\c~`|v,\_ :
+| `"|:::':`-`` '"MM#\-'. -:
+% ``'``'`' :_ '?'`| ``. :
+||, ,#dMM?.M? . .` -
+ ?\ .,odMMMMMMMMM? \ ` :
+ / |MMMMMMMMMMMMM: .'
+ `. TMMH#*9MMMMM* :
+ -. ` "*#*' ,: .
+ . ` .v'' .'
+ `. ..'
+ '- . .-
+ "`\+HHMMMMMMHr~.-`
+ _,,>#b&HMHd&&bb>\_
+ _oHMMMMMMMMMMMMMMMMH**H:.
+ oHMMMMMMMMMMMMMMMMMMMM#v`? `.
+ .dMMMMMMMMMMMMMMMMMMMMMMH*`+| .
+ ,MMMMMMMMMMMMMMMMMMMMMb|?+.,H -.
+ ddHMMMMMMMMMMMMMMMMMMMMMb `' .
+ HMMkZ**HMMMMMMMMMMMMMMMMH\ - . :
+ dTMMM* `9MMMP'"*MMMMPT"` .. :
+|M6H'' 4MP' `"HMMM| !|. . .
+1MHp' #L $ *"' .-:&. .
+MMM' " q:H. .o#-``' :
+MM' ?H?.|MMH::::-o,_. -
+M[ `*?:::'|` `"`:9MH\~-. `
+&M. ""'`'^'.:.`?'`. '| -:
+`M|d, .dbHM[.1? .. :
+ 9||| . _obMMMMMMMMH, . :
+ H.^ MMMMMMMMMMMM} -
+ \ |MMH#*HMMMMH' .'
+ . ` `#*' ,:-
+ ` '' .-'.
+ `. .-
+ '- . .-`
+ '`\bqHMMMMMMHHb--`
+ .,:,#&6dHHHb&##o\_
+ .oHHMMMMMMMMMMMMMMMMMH*\,.
+ oHMMMMMMMMMMMMMMMMMMMMMMHb:'-.
+ .dMMMMMMMMMMMMMMMMMMMMMMMMMH|\/' .
+ ,&HMMMMMMMMMMMMMMMMMMMMMMM/"&.,d. -.
+ dboMMHMMMMMMMMMMMMMMMMMMMMMML `' .
+ HMHMMM$Z***MMMMMMMMMMMMMMMMMM|.- .
+ dMM}MMMM#' `9MMMH?"`MMMMR'T' _ :
+|MMMbM#'' |MM" ``MMMH. <_ .
+dMMMM#& *&. .?`*" .'&: .
+MMMMMH- `' -v/H .dD "' ' :
+MMMM* `*M: 4MM*::-!v,_ :
+MMMM `*?::" "'``"?9Mb::. :
+&MMM, `"'"'|"._ "?`| - :
+`MMM}.H ,#dM[_H ..:
+ 9MMi`M: . .ooHMMMMMMM, ..
+ 9Mb `- 1MMMMMMMMMM| :
+ ?M |MM#*#MMMM* .
+ -. ` |#"' ,'
+ . -" v`
+ -. .-
+ - . . `
+ '-*#d#HHMMMMHH#"-'
+ _,<_:&S6dHHHb&bb\_
+ .odHMMMMMMMMMMMMMMMMMMM}-_
+ .oHMMMMMMMMMMMMMMMMMMMMMMMM#d:.
+ ?9MMMMMMMMMMMMMMMMMMMMMMMMMMMH-$ .
+ ,::dHMMMMMMMMMMMMMMMMMMMMMMMMH:\.?? -.
+ dMdboHMMHMMMMMMMMMMMMMMMMMMMMMMH, ' .
+ HMMMM7MMMb$R***MMMMMMMMMMMMMMMMMH\ - .
+ dMMMMM/MMMMM* `$MMMM*'"*MMMM?&' . :
+|MMMMMMb1H*' HMP' '9MMM| &. . .
+dMMMMMMM##~` `#\ |.`*" .-9. :
+9MMMMMMMM* ` |v7? .,H `' ` :
+SMMMMMMH' '9M_-MMH::-\v_ :
+:HMMMMM `\_:"'|'`':9Mv\.
+-|MMMMM, ""`'`':.`?\ \
+`:MMMMM}.d} .?bM6,| |
+ :?MMM6 M| . .,oHMMMMM| /
+ .?MMM- `' &MMMMMMMM|.
+ -`HM- HMH#*MMM?:
+ '. ' `#*:`
+ - -'/
+ ` . . '
+ ` . . `
+ '--##HH#HMMMHH#""`
+ _o,d_?dZdoHHHb#b\_
+ .vdMMMMMMMMMMMMMMMMMMMMH\.
+ .,HHMMMMMMMMMMMMMMMMMMMMMMMMH&,.
+ /?RMMMMMMMMMMMMMMMMMMMMMMMMMMMMH|..
+ ,\?>`T#RMMMMMMMMMMMMMMMMMMMMMMMM6`\|/
+ dMMbd#ooHMMMHMMMMMMMMMMMMMMMMMMMMMH,`' '
+ HMMMMMMMTMMMMb$ZP**HMMMMMMMMMMMMMMMM|. :
+ dMMMMMMMM}$MMMMMH' `HMMMH?"`MMMM?T' . :
+|MMMMMMMMMMoMH*'' `MM? ``MMM| +\ .
+1MMMMMMMMMMMb#/ ?#? |`#" -T: :
+*'HMMMMMMMMMM*' " ~?& .?} ' ' .
+- 4MMMMMMMMP" `M? HMTc:\\.:
+: `MMMMMMM[ "#:::`>`"?M{
+. |MMMMMMH. ``'``'_`:-
+- |MMMMMMM|.dD ,#Mb\'
+ : *MMMMM: iM| . _oHMMMM:
+ . ?MMMM' "' ,MMMMMMP
+ : `HMH JM#*MMT
+ -. ' ` #'
+ . /
+ -. - .'
+ -. . `
+ '--=&&MH##HMHH#"""
+ .-:?,Z?:&$dHH##b\_
+ ,:bqRMMMMMMMMMMMMMMMMMHo.
+ .?HHHMMMMMMMMMMMMMMMMMMMMMMMHo.
+ -o/*M9MMMMMMMMMMMMMMMMMMMMMMMMMMMv
+ .:H\b\'|?#HHMMMMMMMMMMMMMMMMMMMMMM6?Z\
+ .?MMMHbdbbodMMMMHMMMMMMMMMMMMMMMMMMMM\':
+ :MMMMMMMMMMM7MMMMb?6P**#MMMMMMMMMMMMMMM_ :
+ \MMMMMMMMMMMMb^MMMMMM? `*MMMM*"`MMMR<' . -
+.1MMMMMMMMMMMMMb]M#"" 9MR' `?MMb \. :
+-MMMMMMMMMMMMMMMH##|` *&. |`*' .\ .
+-?""*MMMMMMMMMMMMM' ' |?b ,}" :
+: MMMMMMMMMMH' `M_|M}r\?
+. `MMMMMMMMM' `$_:`'"H
+- TMMMMMMMM, '"``::
+: {MMMMMMMM| oH| .#M-
+ : `9MMMMMM' .MP . ,oMMT
+ . HMMMMP' `' ,MMMP
+ - `MMH' HH9*
+ '. ` ` .'
+ - . '
+ ` . - .-
+ ` . .-
+ ' -==pHMMH##HH#"""
+ _..-:b&::&?&&##bo_
+ ...?-#&9MMMMMMMMMMMMMMMHo_
+ .. .1&#MMHMMMMMMMMMMMMMMMMMMMHo.
+ . .o/##R9MMMMMMMMMMMMMMMMMMMMMMMM?.
+ .- |MSd?|'`$?#HMMMMMMMMMMMMMMMMMMMMMH\
+ - dMMMMHbd##oodMMMM#MMMMMMMMMMMMMMMMMH:
+ - JMMMMMMMMMMMMM7HMMMH$SR***MMMMMMMMMMMMb>
+ : {MMMMMMMMMMMMMMM`9MMMMMH' ``HMMM?"*MM[| :
+- |MMMMMMMMMMMMMMMMM<MH*'' `MM' 'HM? |.
+: `MMMMMMMMMMMMMMMMMM##H-' `#, ` |`? /|
+. ?"""?HMMMMMMMMMMMMMH' " v& .}?
+- |MMMMMMMMMMMP' `H:&H&
+i `9MMMMMMMMMT `|?"?
+: MMMMMMMMMH "`\
+: MMMMMMMMMH-.dH ,|
+ : ?MMMMMMM? {M' . .dT
+ . ?MMMMMR' `' ,MP
+ - `HMM#' .&*
+ '. ' `.
+ - . '
+ `.. .-
+ -. .-
+ '-.==p##HMMHp&#"""
+ _v---:?&?:?&?&#b\_
+ ..' i: #M$MMMMMMMMMMMMMHo_
+ .. -]M#HMHMMMMMMMMMMMMMMMMMHo.
+ . ooP*&6&MMMMMMMMMMMMMMMMMMMMM?.
+ . - &Rbbd-/`?:##HMMMMMMMMMMMMMMMMMH?
+ - ,HMMMMM#od#boodMMMMHMMMMMMMMMMMMMMb
+ - iMMMMMMMMMMMMMMM[*MMMH&$R***MMMMMMMMMb
+ : |MMMMMMMMMMMMMMMMML"MMMMMM' ``MMMP"HMM:
+. HMMMMMMMMMMMMMMMMMMb/MH"" `MR *M,|
+: TMMMMMMMMMMMMMMMMMMMMd#&` `D. ?|\
+. `*"'"*HMMMMMMMMMMMMMMP' ' -d,J
+: |MMMMMMMMMMMMP' ||M
+M, ?MMMMMMMMMM| `\?
+&| HMMMMMMMMM} ``
+`L .MMMMMMMMMMP ,d| :
+ *. ?MMMMMMMF' .MP /
+ | TMMMMMM' `"' /
+ `. `MMMP' ./
+ -. ` .
+ . . '
+ - . .-
+ -\ ..-
+ '-..=p####HMH&="""
+ _vo~^'':&b::d,#b\_
+ ..`" `:v +9P]MMMMMMMMMMHo_
+ ,- ?Mb#MMMMMMMMMMMMMMMMMHo.
+ . " ,ooM*&&&HMMMMMMMMMMMMMMMMHb.
+ . - 99Soo?|'`*?##HMMMMMMMMMMMMMH\
+ - .HMMMMMM#od#boodMMMMHMMMMMMMMMMb
+ - :MMMMMMMMMMMMMMMM67HMMH&$R**HMMMMMb
+ : .MMMMMMMMMMMMMMMMMMM/HMMMMM| `9MM'HL
+: {MMMMMMMMMMMMMMMMMMMM\MM*'' `H[ `9|
+| `HMMMMMMMMMMMMMMMMMMMMb##| `F. :?
+H `"*"'"`#MMMMMMMMMMMMMMM? ' k
+M. MMMMMMMMMMMMM"' H
+MMH. `HMMMMMMMMMM: |
+&MM| `MMMMMMMMMM, -
+`MM| dMMMMMMMMMM|.oH :
+ 9ML `HMMMMMMM? dH' -
+ Hi |MMMMMMP "' .'
+ T. `MMM#' -
+ `. ` .`
+ ` -
+ `.. . ..'
+ ... .-
+ '-. //######M#b~""
+ _ooq=""''$b$_&?b\_
+ .-`^" "'o |&M:MMMMMMMMHo_
+ o/' -$Mb#MMMMMMMMMMMMMMHo.
+ /' .ooHP*&R&MMMMMMMMMMMMMM?.
+ .' `MRbod?|'`+?##9MMMMMMMMMH\
+ .` .,MMMMMMH#od##obdMMMMHMMMMMMb
+ - ?MMMMMMMMMMMMMMMMM$HMMH$ZP*HMMb
+ ? |MMMMMMMMMMMMMMMMMMM|9MMMMP "M6\
+.- dMMMMMMMMMMMMMMMMMMMMb]M*' |R |
+1| `HMMMMMMMMMMMMMMMMMMMMMd#| ?,:
+MH, ``*""'"*#MMMMMMMMMMMMMM* '`
+MM6_ |MMMMMMMMMMMMH" :
+MMMMMb. "MMMMMMMMMMT -
+&MMMMM' |MMMMMMMMMH `
+!MMMMb .HMMMMMMMMM+.?& :
+ TMMMM *MMMMMMMP dH' . :
+ 9MM' `MMMMMMP' "' .
+ 9ML `MMM#' -
+ `H ` :
+ `\. .'
+ `-\ . .-
+ ' ._ .-`
+ '-\. ,b#####p&**^`
diff --git a/tests/interact.py b/tests/interact.py
new file mode 100755
index 0000000..c37c6d9
--- /dev/null
+++ b/tests/interact.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+p = pexpect.spawn('cat')
+p.interact()
diff --git a/tests/pexpectTest.py b/tests/pexpectTest.py
new file mode 100755
index 0000000..62ac422
--- /dev/null
+++ b/tests/pexpectTest.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+import os, time, pexpect, sys
+
+def getProcessResults(cmd, timeLimit=20):
+ '''
+ executes 'cmd' as a child process and returns the child's output,
+ the duration of execution, and the process exit status. Aborts if
+ child process does not generate output for 'timeLimit' seconds.
+ '''
+ output = ""
+ startTime = time.time()
+ child = pexpect.spawn(cmd, timeout=10)
+ child.logfile = sys.stdout
+
+ while 1:
+ try:
+ # read_nonblocking will add to 'outout' one byte at a time
+ # newlines can show up as '\r\n' so we kill any '\r's which
+ # will mess up the formatting for the viewer
+ output += child.read_nonblocking(timeout=timeLimit).replace("\r","")
+ except pexpect.EOF, e:
+ print str(e)
+ # process terminated normally
+ break
+ except pexpect.TIMEOUT, e:
+ print str(e)
+ output += "\nProcess aborted by FlashTest after %s seconds.\n" % timeLimit
+ print child.isalive()
+ child.kill(9)
+ break
+
+ endTime = time.time()
+ child.close(force=True)
+
+ duration = endTime - startTime
+ exitStatus = child.exitstatus
+
+ return (output, duration, exitStatus)
+
+cmd = "./ticker.py"
+
+result, duration, exitStatus = getProcessResults(cmd)
+
+print "result: %s" % result
+print "duration: %s" % duration
+print "exit-status: %s" % exitStatus
+
diff --git a/tests/platform_tests/CSIGNALTEST/test.c b/tests/platform_tests/CSIGNALTEST/test.c
new file mode 100644
index 0000000..86bcc17
--- /dev/null
+++ b/tests/platform_tests/CSIGNALTEST/test.c
@@ -0,0 +1,90 @@
+/* I built this with "gcc -lutil test.c -otest" */
+#include <sys/types.h> /* include this before any other sys headers */
+#include <sys/wait.h> /* header for waitpid() and various macros */
+#include <signal.h> /* header for signal functions */
+#include <stdio.h> /* header for fprintf() */
+#include <unistd.h> /* header for fork() */
+#ifdef LINUX
+#include <pty.h>
+#else
+#include <util.h> /* header for forkpty, compile with -lutil */
+#endif
+
+void sig_chld(int); /* prototype for our SIGCHLD handler */
+
+int main()
+{
+ struct sigaction act;
+ int pid;
+ int fdm;
+ char slave_name [20];
+
+
+ /* Assign sig_chld as our SIGCHLD handler.
+ We don't want to block any other signals in this example
+ We're only interested in children that have terminated, not ones
+ which have been stopped (eg user pressing control-Z at terminal).
+ Finally, make these values effective. If we were writing a real
+ application, we would save the old value instead of passing NULL.
+ */
+ act.sa_handler = sig_chld;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_NOCLDSTOP;
+ if (sigaction(SIGCHLD, &act, NULL) < 0)
+ {
+ fprintf(stderr, "sigaction failed\n");
+ return 1;
+ }
+
+ /* Do the Fork thing.
+ */
+ pid = forkpty (&fdm, slave_name, NULL, NULL);
+ /* pid = fork(); */
+
+ switch (pid)
+ {
+ case -1:
+ fprintf(stderr, "fork failed\n");
+ return 1;
+ break;
+
+ case 0: /* Child process. */
+ printf ("This child output will cause trouble.\n");
+ _exit(7);
+ break;
+
+ default: /* Parent process. */
+ sleep(1);
+ printf ("Child pid: %d\n", pid);
+ sleep(10); /* let child finish -- crappy way to avoid race. */
+ break;
+ }
+
+ return 0;
+}
+
+void sig_chld(int signo)
+{
+ int status, wpid, child_val;
+
+ printf ("In sig_chld signal handler.\n");
+
+ /* Wait for any child without blocking */
+ wpid = waitpid (-1, & status, WNOHANG);
+ printf ("\tWaitpid found status for pid: %d\n", wpid);
+ if (wpid < 0)
+ {
+ fprintf(stderr, "\twaitpid failed\n");
+ return;
+ }
+ printf("\tWaitpid status: %d\n", status);
+
+ if (WIFEXITED(status)) /* did child exit normally? */
+ {
+ child_val = WEXITSTATUS(status);
+ printf("\tchild exited normally with status %d\n", child_val);
+ }
+ printf ("End of sig_chld.\n");
+}
+
+
diff --git a/tests/platform_tests/README b/tests/platform_tests/README
new file mode 100644
index 0000000..c4b0564
--- /dev/null
+++ b/tests/platform_tests/README
@@ -0,0 +1,4 @@
+These are tests that are not yet pyunit tests
+or are not intended to be pyunit tests.
+Anything not part of the Python unittest framework
+should go here.
diff --git a/tests/platform_tests/pexqa.py b/tests/platform_tests/pexqa.py
new file mode 100644
index 0000000..0ba1412
--- /dev/null
+++ b/tests/platform_tests/pexqa.py
@@ -0,0 +1,39 @@
+import os, sys
+import select
+import signal
+import traceback
+import time
+import re
+import struct
+from types import *
+import posix
+
+import pty
+import tty
+import termios
+import fcntl
+class s:
+ def __init__(self, command, args=None, timeout=30):
+
+ self.pid = self.child_fd = None
+ try:
+ #self.pid, self.child_fd = posix.forkpty()
+ self.pid, self.child_fd = pty.fork()
+ except OSError, e:
+ raise Exception('pty fork() failed: ' + str(e))
+
+ if self.pid == 0: # Child
+ os.execvp(command, args)
+
+ # Parent
+
+
+print '1'
+x = s('ls', ['ls'])
+time.sleep(5)
+print '2'
+result = os.read (x.child_fd, 5555)
+print '3'
+print result
+print '4'
+
diff --git a/tests/platform_tests/test.py b/tests/platform_tests/test.py
new file mode 100755
index 0000000..f80263b
--- /dev/null
+++ b/tests/platform_tests/test.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+import signal, os, time, errno, pty
+
+def signal_handler (signum, frame):
+ print 'Signal handler called with signal:', signum
+ print 'signal.SIGCHLD=', signal.SIGKILL
+
+# First thing we do is set up a handler for SIGCHLD.
+signal.signal (signal.SIGCHLD, signal.SIG_IGN)
+
+print 'PART 1 -- Test signal handling with empty pipe.'
+# Create a child process for us to kill.
+try:
+ pid, fd = pty.fork()
+except Exception, e:
+ print str(e)
+
+if pid == 0:
+# os.write (sys.stdout.fileno(), 'This is a test.\n This is a test.')
+ time.sleep(10000)
+
+print 'Sending SIGKILL to child pid:', pid
+os.kill (pid, signal.SIGKILL)
+
+# SIGCHLD should interrupt sleep.
+# Note that this is a race.
+# It is possible that the signal handler will get called
+# before we try to sleep, but this has not happened yet.
+# But in that case we can only tell by order of printed output.
+print 'Entering sleep...'
+try:
+ time.sleep(10)
+except:
+ print 'sleep was interrupted by signal.'
+
+# Just for fun let's see if the process is alive.
+try:
+ os.kill(pid, 0)
+ print 'Child is alive. This is ambiguous because it may be a Zombie.'
+except OSError, e:
+ print 'Child appears to be dead.'
+
+print 'PART 2 -- Test signal handling with full pipe.'
+# Create a child process for us to kill.
+try:
+ pid, fd = pty.fork()
+except Exception, e:
+ print str(e)
+
+if pid == 0:
+ os.write (sys.stdout.fileno(), 'This is a test.\n This is a test.')
+ time.sleep(10000)
+
+print 'Sending SIGKILL to child pid:', pid
+os.kill (pid, signal.SIGKILL)
+
+# SIGCHLD should interrupt sleep.
+# Note that this is a race.
+# It is possible that the signal handler will get called
+# before we try to sleep, but this has not happened yet.
+# But in that case we can only tell by order of printed output.
+print 'Entering sleep...'
+try:
+ time.sleep(10)
+except:
+ print 'sleep was interrupted by signal.'
+
+# Just for fun let's see if the process is alive.
+try:
+ os.kill(pid, 0)
+ print 'Child is alive. This is ambiguous because it may be a Zombie.'
+except OSError, e:
+ print 'Child appears to be dead.'
+
diff --git a/tests/platform_tests/test2.py b/tests/platform_tests/test2.py
new file mode 100755
index 0000000..9611f39
--- /dev/null
+++ b/tests/platform_tests/test2.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+import signal, os, time, errno
+
+def signal_handler (signum, frame):
+ print 'Signal handler called with signal:', signum
+ print 'signal.SIGCHLD=', signal.SIGKILL
+
+# Create a child process for us to kill.
+pid = os.fork()
+if pid == 0:
+ time.sleep(10000)
+
+#signal.signal (signal.SIGCHLD, signal.SIG_IGN)
+signal.signal (signal.SIGCHLD, signal_handler)
+
+print 'Sending SIGKILL to child pid:', pid
+os.kill (pid, signal.SIGKILL)
+
+# SIGCHLD should interrupt sleep.
+# Note that this is a race.
+# It is possible that the signal handler will get called
+# before we try to sleep, but this has not happened yet.
+# But in that case we can only tell by order of printed output.
+interrupted = 0
+try:
+ time.sleep(10)
+except:
+ print 'sleep was interrupted by signal.'
+ interrupted = 1
+
+if not interrupted:
+ print 'ERROR. Signal did not interrupt sleep.'
+else:
+ print 'Signal interrupted sleep. This is good.'
+
+# Let's see if the process is alive.
+try:
+ os.kill(pid, 0)
+ print 'Child is alive. This is ambiguous because it may be a Zombie.'
+except OSError, e:
+ print 'Child appears to be dead.'
+
diff --git a/tests/platform_tests/test_badfork.py b/tests/platform_tests/test_badfork.py
new file mode 100755
index 0000000..c0768a4
--- /dev/null
+++ b/tests/platform_tests/test_badfork.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+import pexpect
+import pyunit
+
+def main ():
+ pid, fd = fooork ('aThelaDSjd','-i')
+ print 'pid', pid
+ print 'fd', fd
+ Xexpect(fd, 'bash.*#',10)
+ os.write(fd, 'scp -P 6666 *.py noah@gw.tiered.com:pexpect/\n')
+ Xexpect(fd, 'bash.*#',10)
+ os.write(fd, 'exit\n')
+ print _my_read (fd, 1000, 5)
+ sys.exit (1)
+
diff --git a/tests/platform_tests/test_control_terminal.py b/tests/platform_tests/test_control_terminal.py
new file mode 100755
index 0000000..9598fd7
--- /dev/null
+++ b/tests/platform_tests/test_control_terminal.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+
+import termios, fcntl, struct, os, sys
+
+def getwinsize():
+ s = struct.pack("HHHH", 0, 0, 0, 0)
+ x = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, s)
+ rows, cols = struct.unpack("HHHH", x)[:2]
+ return rows, cols
+
+def setwinsize(r,c):
+ # Assume ws_xpixel and ws_ypixel are zero.
+ s = struct.pack("HHHH", r,c,0,0)
+ x = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCSWINSZ, s)
+print 'stdin tty:', os.ttyname(0)
+print 'stdout tty:', os.ttyname(1)
+print 'controlling terminal:', os.ctermid()
+print 'winsize %d,%d' % getwinsize()
+print 'ENDTEST'
diff --git a/tests/platform_tests/test_handler.py b/tests/platform_tests/test_handler.py
new file mode 100755
index 0000000..d9239b6
--- /dev/null
+++ b/tests/platform_tests/test_handler.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+import signal, os, time, errno, pty, sys, fcntl, tty
+GLOBAL_SIGCHLD_RECEIVED = 0
+
+def nonblock (fd):
+ # if O_NDELAY is set read() returns 0 (ambiguous with EOF).
+ # if O_NONBLOCK is set read() returns -1 and sets errno to EAGAIN
+ original_flags = fcntl.fcntl (fd, fcntl.F_GETFL, 0)
+ flags = original_flags | os.O_NONBLOCK
+ fcntl.fcntl(fd, fcntl.F_SETFL, flags)
+ return original_flags
+
+def signal_handler (signum, frame):
+ print '<HANDLER>'
+ global GLOBAL_SIGCHLD_RECEIVED
+ status = os.waitpid (-1, os.WNOHANG)
+ if status[0] == 0:
+ print 'No process for waitpid:', status
+ else:
+ print 'Status:', status
+ print 'WIFEXITED(status):', os.WIFEXITED(status[1])
+ print 'WEXITSTATUS(status):', os.WEXITSTATUS(status[1])
+ GLOBAL_SIGCHLD_RECEIVED = 1
+
+def main ():
+ signal.signal (signal.SIGCHLD, signal_handler)
+ pid, fd = pty.fork()
+ if pid == 0:
+ os.write (sys.stdout.fileno(), 'This is a test.\nThis is a test.')
+ time.sleep(10000)
+ nonblock (fd)
+ tty.setraw(fd) #STDIN_FILENO)
+ print 'Sending SIGKILL to child pid:', pid
+ time.sleep(2)
+ os.kill (pid, signal.SIGKILL)
+
+ print 'Entering to sleep...'
+ try:
+ time.sleep(2)
+ except:
+ print 'Sleep interrupted'
+ try:
+ os.kill(pid, 0)
+ print '\tChild is alive. This is ambiguous because it may be a Zombie.'
+ except OSError, e:
+ print '\tChild appears to be dead.'
+# print str(e)
+ print
+ print 'Reading from master fd:', os.read (fd, 1000)
+
+
+
+if __name__ == '__main__':
+ main ()
diff --git a/tests/platform_tests/test_killed_pid.py b/tests/platform_tests/test_killed_pid.py
new file mode 100755
index 0000000..ff2fe5e
--- /dev/null
+++ b/tests/platform_tests/test_killed_pid.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+import os, time, signal
+import expyct
+
+e = expyct.expyct ('/bin/sh', '-i')
+print 'pid,fd:', e.pid, e.fd
+print 'isAlive:', e.isAlive()
+# Treat it brusquely.
+print 'sending SIGKILL...'
+os.kill (e.pid, signal.SIGKILL)
+time.sleep (1)
+print os.read(e.fd, 1000)
+print 'isAlive:', e.isAlive()
+e.expect('\#')
+e.send ('ls -la /\n')
+r,m,i = e.expect ('\#')
+print r
diff --git a/tests/platform_tests/test_middle_buffer.py b/tests/platform_tests/test_middle_buffer.py
new file mode 100755
index 0000000..ccb8302
--- /dev/null
+++ b/tests/platform_tests/test_middle_buffer.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python2
+import expyct
+import time
+
+e = expyct.expyct ('/bin/sh -i')
+e.timeout=60
+e.expect(['#', '\$'])
+e.send ('ls -la /\n')
+
+i = e.expect (['foo','(d[aeiou]v)'])
+print '\nRead before match>%s<' % e.before
+print 'Matched:>%s<' % e.matched
+print 'index:', i
+
+i = e.expect(['#', '\$'])
+print '\nRead before match>%s<' % e.before
+print 'Matched:>%s<' % e.matched
+print 'index:', i
+e.send('exit\n')
+print 'Sent exit'
+time.sleep(2)
+print 'isAlive:', e.isAlive()
+
+# This should test timeout...
+i = e.expect ('#####')
+print '\nRead before match>%s<' % e.before
+print 'Matched:>%s<' % e.matched
+print 'index:', i
+
+
diff --git a/tests/platform_tests/test_read.py b/tests/platform_tests/test_read.py
new file mode 100755
index 0000000..1e16ed4
--- /dev/null
+++ b/tests/platform_tests/test_read.py
@@ -0,0 +1,35 @@
+import os, sys
+
+filename = os.tmpnam()
+print 'filename:', filename
+
+fd_out = os.open(filename, os.O_CREAT | os.O_WRONLY)
+print 'fd_out:', fd_out
+os.write (fd_out, 'This is a test.\n')
+os.close(fd_out)
+print
+print 'testing read on good fd...'
+fd_in = os.open (filename, os.O_RDONLY)
+print 'fd_in:', fd_in
+while 1:
+ data_in = os.read(fd_in, 1)
+ print 'data_in:', data_in
+ if data_in == '':
+ print 'data_in was empty'
+ break #sys.exit(1)
+os.close(fd_in)
+print
+print
+print 'testing read on closed fd...'
+fd_in = os.open ('test_read.py', os.O_RDONLY)
+print 'fd_in:', fd_in
+while 1:
+ data_in = os.read(fd_in, 1)
+ print 'data_in:', data_in
+ if data_in == '':
+ print 'data_in was empty'
+ break
+os.close(fd_in)
+d = os.read(fd_in, 1) # fd_in should be closed now...
+if s == '':
+ print 'd is empty. good.'
diff --git a/tests/platform_tests/test_signals.py b/tests/platform_tests/test_signals.py
new file mode 100755
index 0000000..cd1a6da
--- /dev/null
+++ b/tests/platform_tests/test_signals.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+import signal, os, time, errno, pty, sys
+GLOBAL_SIGCHLD_RECEIVED = 0
+
+def signal_handler (signum, frame):
+ print '<HANDLER>'
+ global GLOBAL_SIGCHLD_RECEIVED
+ status = os.waitpid (-1, os.WNOHANG)
+ print 'WIFEXITED(status):', os.WIFEXITED(status)
+ print 'WEXITSTATUS(status):', os.WEXITSTATUS(status)
+ GLOBAL_SIGCHLD_RECEIVED = 1
+
+def main ():
+# sig_test ('SIG_IGN', 'ptyfork', 'yes')
+ sig_test ('handler', 'ptyfork', 'yes')
+# sig_test ('SIG_IGN', 'ptyfork', 'no')
+# sig_test ('handler', 'ptyfork', 'no')
+# sig_test ('SIG_IGN', 'osfork', 'yes')
+# sig_test ('handler', 'osfork', 'yes')
+# sig_test ('SIG_IGN', 'osfork', 'no')
+# sig_test ('handler', 'osfork', 'no')
+
+def sig_test (sig_handler_type, fork_type, child_output):
+ print 'Testing with:'
+ print '\tsig_handler_type:', sig_handler_type
+ print '\tfork_type:', fork_type
+ print '\tchild_output:', child_output
+
+ if sig_handler_type == 'SIG_IGN':
+ signal.signal (signal.SIGCHLD, signal.SIG_IGN)
+ else:
+ signal.signal (signal.SIGCHLD, signal_handler)
+ pid = -1
+ fd = -1
+ if fork_type == 'ptyfork':
+ pid, fd = pty.fork()
+ else:
+ pid = os.fork()
+
+ if pid == 0:
+ if child_output == 'yes':
+ os.write (sys.stdout.fileno(), 'This is a test.\nThis is a test.')
+ time.sleep(10000)
+
+ #print 'Sending SIGKILL to child pid:', pid
+ time.sleep(2)
+ os.kill (pid, signal.SIGKILL)
+
+ #print 'Entering to sleep...'
+ try:
+ time.sleep(2)
+ except:
+ pass
+ try:
+ os.kill(pid, 0)
+ print '\tChild is alive. This is ambiguous because it may be a Zombie.'
+ except OSError, e:
+ print '\tChild appears to be dead.'
+# print str(e)
+ print
+
+if __name__ == '__main__':
+ main ()
diff --git a/tests/qa.py b/tests/qa.py
new file mode 100755
index 0000000..eb11946
--- /dev/null
+++ b/tests/qa.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import commands
+import signal
+
+signal.signal(signal.SIGCHLD, signal.SIG_IGN)
+print commands.getoutput('/bin/ls -l')
+
diff --git a/tests/sigwinch_report.py b/tests/sigwinch_report.py
new file mode 100755
index 0000000..26030cb
--- /dev/null
+++ b/tests/sigwinch_report.py
@@ -0,0 +1,46 @@
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import signal, time, struct, fcntl, termios, os, sys
+
+def getwinsize():
+ '''This returns the window size of the child tty.
+ The return value is a tuple of (rows, cols).
+ '''
+ if 'TIOCGWINSZ' in dir(termios):
+ TIOCGWINSZ = termios.TIOCGWINSZ
+ else:
+ TIOCGWINSZ = 1074295912L # Assume
+ s = struct.pack('HHHH', 0, 0, 0, 0)
+ x = fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s)
+ return struct.unpack('HHHH', x)[0:2]
+
+def handler(signum, frame):
+ print 'signal'
+ sys.stdout.flush()
+ print 'SIGWINCH:', getwinsize ()
+ sys.stdout.flush()
+
+print "setting handler for SIGWINCH"
+signal.signal(signal.SIGWINCH, handler)
+
+while 1:
+ sys.stdout.flush()
+ time.sleep(1)
+
diff --git a/tests/swapcase_echo.py b/tests/swapcase_echo.py
new file mode 100755
index 0000000..344cfaf
--- /dev/null
+++ b/tests/swapcase_echo.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import sys, time
+while True:
+ x = raw_input ()
+ time.sleep(1) # without this delay the test would fail about 75% of the time. Why?
+ print x.swapcase()
+ sys.stdout.flush()
diff --git a/tests/test_ansi.py b/tests/test_ansi.py
new file mode 100755
index 0000000..4ac7b9a
--- /dev/null
+++ b/tests/test_ansi.py
@@ -0,0 +1,133 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+import ANSI
+import unittest
+import PexpectTestCase
+
+write_target = 'I\'ve got a ferret sticking up my nose. \n' +\
+'(He\'s got a ferret sticking up his nose.) \n' +\
+'How it got there I can\'t tell \n' +\
+'But now it\'s there it hurts like hell \n' +\
+'And what is more it radically affects my sense of smell. \n' +\
+'(His sense of smell.) '
+
+write_text = 'I\'ve got a ferret sticking up my nose.\n' + \
+'(He\'s got a ferret sticking up his nose.)\n' + \
+'How it got there I can\'t tell\n' + \
+'But now it\'s there it hurts like hell\n' + \
+'And what is more it radically affects my sense of smell.\n' + \
+'(His sense of smell.)\n' + \
+'I can see a bare-bottomed mandril.\n' + \
+'(Slyly eyeing his other nostril.)\n' + \
+'If it jumps inside there too I really don\'t know what to do\n' + \
+'I\'ll be the proud posessor of a kind of nasal zoo.\n' + \
+'(A nasal zoo.)\n' + \
+'I\'ve got a ferret sticking up my nose.\n' + \
+'(And what is worst of all it constantly explodes.)\n' + \
+'"Ferrets don\'t explode," you say\n' + \
+'But it happened nine times yesterday\n' + \
+'And I should know for each time I was standing in the way.\n' + \
+'I\'ve got a ferret sticking up my nose.\n' + \
+'(He\'s got a ferret sticking up his nose.)\n' + \
+'How it got there I can\'t tell\n' + \
+'But now it\'s there it hurts like hell\n' + \
+'And what is more it radically affects my sense of smell.\n' + \
+'(His sense of smell.)'
+
+tetris_target=' XX XXXX XX \n' +\
+' XXXXXX XXXXXXXX XX \n' +\
+' XXXXXX XXXXXXXX XX \n' +\
+' XX XX XX XXXX XX \n' +\
+' XXXXXX XXXX XXXX XX \n' +\
+' XXXXXXXXXX XXXX XX \n' +\
+' XX XXXXXX XX XX \n' +\
+' XXXXXX XX XX \n' +\
+' XXXX XXXXXX XX XX \n' +\
+' XXXXXX XXXX XX XX \n' +\
+' XX XX XXXX XX XX \n' +\
+' XX XX XX XX XX \n' +\
+' XX XX XXXX XXXX XX \n' +\
+' XXXXXXXX XXXX XXXX XX \n' +\
+' XXXXXXXXXXXXXX XXXXXXXX \n' +\
+' XX XXXXXXXX XX XX \n' +\
+' XXXXXXXXXXXXXX XX XX \n' +\
+' XX XXXX XXXXXX XX \n' +\
+' XXXXXX XXXXXXXX \n' +\
+' XXXXXXXXXX XX XX \n' +\
+' XXXXXXXXXXXXXXXXXXXXXXXX \n' +\
+' \n' +\
+' J->LEFT K->ROTATE L->RIGHT SPACE->DROP P->PAUSE Q->QUIT \n' +\
+' '
+
+torture_target='+--------------------------------------------------------------------------------+\n' +\
+'|a`opqrs` This is the `srqpo`a |\n' +\
+'|VT100 series Torture Test Demonstration. |\n' +\
+'|VT100 series Torture Test Demonstration. |\n' +\
+'|This is a normal line __________________________________________________y_ |\n' +\
+'|This is a bold line (normal unless the Advanced Video Option is installed) |\n' +\
+'|This line is underlined _ " " " " " " _y_ |\n' +\
+'|This is a blinking line _ " " " " " " _y_ |\n' +\
+'|This is inverse video _ (underlined if no AVO and cursor is underline) _y_ |\n' +\
+'|Normal gjpqy Underline Blink Underline+Blink gjpqy |\n' +\
+'|Bold gjpqy Underline Blink Underline+Blink gjpqy |\n' +\
+'|Inverse Underline Blink Underline+Blink |\n' +\
+'|Bold+Inverse Underline Blink Underline+Blink |\n' +\
+'|This is double width |\n' +\
+'|This is double height |\n' +\
+'|This is double height |\n' +\
+'|_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy |\n' +\
+'|_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy |\n' +\
+'|_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy |\n' +\
+'|`abcdefghijklmnopqrstuvwxyz{|}~ lqwqk |\n' +\
+'|`abcdefghijklmnopqrstuvwxyz{|}~ tqnqu |\n' +\
+'|`abcdefghijklmnopqrstuvwxyz{|}~ tqnqu |\n' +\
+'|`abcdefghijklmnopqrstuvwxyz{|}~ mqvqj |\n' +\
+'| This test created by Joe Smith, 8-May-85 |\n' +\
+'| |\n' +\
+'+--------------------------------------------------------------------------------+\n'
+
+class ansiTestCase (PexpectTestCase.PexpectTestCase):
+ def test_write (self):
+ s = ANSI.ANSI (6,65)
+ s.fill('.')
+ s.cursor_home()
+ for c in write_text:
+ s.write (c)
+ assert str(s) == write_target
+ def test_torturet (self):
+ s = ANSI.ANSI (24,80)
+ sample_text = open ('torturet.vt').read()
+ for c in sample_text:
+ s.process (c)
+ assert s.pretty() == torture_target, 'processed: \n' + s.pretty() + '\nexpected:\n' + torture_target
+ def test_tetris (self):
+ s = ANSI.ANSI (24,80)
+ tetris_text = open ('tetris.data').read()
+ for c in tetris_text:
+ s.process (c)
+ assert str(s) == tetris_target
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(ansiTestCase,'test')
+
diff --git a/tests/test_command_list_split.py b/tests/test_command_list_split.py
new file mode 100755
index 0000000..2213b45
--- /dev/null
+++ b/tests/test_command_list_split.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import PexpectTestCase
+class SplitCommandLineTestCase(PexpectTestCase.PexpectTestCase):
+ def testSplitSizes(self):
+ assert len(pexpect.split_command_line(r'')) == 0
+ assert len(pexpect.split_command_line(r'one')) == 1
+ assert len(pexpect.split_command_line(r'one two')) == 2
+ assert len(pexpect.split_command_line(r'one two')) == 2
+ assert len(pexpect.split_command_line(r'one two')) == 2
+ assert len(pexpect.split_command_line(r'one\ one')) == 1
+ assert len(pexpect.split_command_line('\'one one\'')) == 1
+ assert len(pexpect.split_command_line(r'one\"one')) == 1
+ assert len(pexpect.split_command_line(r'This\' is a\'\ test')) == 3
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(SplitCommandLineTestCase,'test')
diff --git a/tests/test_constructor.py b/tests/test_constructor.py
new file mode 100755
index 0000000..8a98c28
--- /dev/null
+++ b/tests/test_constructor.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import time
+import PexpectTestCase
+
+class TestCaseConstructor(PexpectTestCase.PexpectTestCase):
+ def test_constructor (self):
+ '''This tests that the constructor will work and give
+ the same results for different styles of invoking __init__().
+ This assumes that the root directory / is static during the test.
+ '''
+ p1 = pexpect.spawn('/bin/ls -l /bin')
+ p2 = pexpect.spawn('/bin/ls' ,['-l', '/bin'])
+ p1.expect (pexpect.EOF)
+ p2.expect (pexpect.EOF)
+ assert (p1.before == p2.before)
+
+ def test_named_parameters (self):
+ '''This tests that named parameters work.
+ '''
+ p = pexpect.spawn ('/bin/ls',timeout=10)
+ p = pexpect.spawn (timeout=10, command='/bin/ls')
+ p = pexpect.spawn (args=[], command='/bin/ls')
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(TestCaseConstructor,'test')
+
diff --git a/tests/test_ctrl_chars.py b/tests/test_ctrl_chars.py
new file mode 100755
index 0000000..c679609
--- /dev/null
+++ b/tests/test_ctrl_chars.py
@@ -0,0 +1,109 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import PexpectTestCase
+import time
+import os
+
+class TestCtrlChars(PexpectTestCase.PexpectTestCase):
+
+ def test_control_chars (self):
+
+ '''FIXME: Python unicode was too hard to figure out, so
+ this tests only the true ASCII characters. This is lame
+ and should be fixed. I'm leaving this script here as a
+ placeholder so that it will remind me to fix this one day.
+ This is what it used to do:
+ This tests that we can send all 256 8-bit ASCII characters
+ to a child process.'''
+
+ # FIXME: Getting this to support Python's Unicode was
+ # too hard, so I disabled this. I should fix this one day.
+ return 0
+ child = pexpect.spawn('python getch.py')
+ try:
+ for i in range(256):
+# child.send(unicode('%d'%i, encoding='utf-8'))
+ child.send(chr(i))
+ child.expect ('%d\r\n' % i)
+ except Exception, e:
+ msg = "Did not echo character value: " + str(i) + "\n"
+ msg = msg + str(e)
+ self.fail(msg)
+
+ def test_sendintr (self):
+ try:
+ child = pexpect.spawn('python getch.py')
+ child.sendintr()
+ child.expect ('3\r\n')
+ except Exception, e:
+ msg = "Did not echo character value: 3\n"
+ msg = msg + str(e)
+ self.fail(msg)
+
+ def test_bad_sendcontrol_chars (self):
+
+ '''This tests that sendcontrol will return 0 for an unknown char. '''
+
+ child = pexpect.spawn('python getch.py')
+ retval = child.sendcontrol('1')
+ assert retval == 0, "sendcontrol() should have returned 0 because there is no such thing as ctrl-1."
+
+ def test_sendcontrol(self):
+
+ '''This tests that we can send all special control codes by name.
+ '''
+
+ child = pexpect.spawn('python getch.py')
+ #child.delaybeforesend = 0.1
+ for i in 'abcdefghijklmnopqrstuvwxyz':
+ child.sendcontrol(i)
+ child.expect ('[0-9]+\r\n')
+ #print child.after
+
+ child.sendcontrol('@')
+ child.expect ('0\r\n')
+ #print child.after
+ child.sendcontrol('[')
+ child.expect ('27\r\n')
+ #print child.after
+ child.sendcontrol('\\')
+ child.expect ('28\r\n')
+ #print child.after
+ child.sendcontrol(']')
+ child.expect ('29\r\n')
+ #print child.after
+ child.sendcontrol('^')
+ child.expect ('30\r\n')
+ #print child.after
+ child.sendcontrol('_')
+ child.expect ('31\r\n')
+ #print child.after
+ child.sendcontrol('?')
+ child.expect ('127\r\n')
+ #print child.after
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(TestCtrlChars,'test')
+
diff --git a/tests/test_destructor.py b/tests/test_destructor.py
new file mode 100755
index 0000000..d6b176c
--- /dev/null
+++ b/tests/test_destructor.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import PexpectTestCase
+import gc
+import time
+
+class TestCaseDestructor(PexpectTestCase.PexpectTestCase):
+ def test_destructor (self):
+ p1 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p2 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p3 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p4 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ fd_t1 = (p1.child_fd,p2.child_fd,p3.child_fd,p4.child_fd)
+ p1.expect(pexpect.EOF)
+ p2.expect(pexpect.EOF)
+ p3.expect(pexpect.EOF)
+ p4.expect(pexpect.EOF)
+ p1.kill(9)
+ p2.kill(9)
+ p3.kill(9)
+ p4.kill(9)
+ p1 = None
+ p2 = None
+ p3 = None
+ p4 = None
+ gc.collect()
+ time.sleep(3) # Some platforms are slow at gc... Solaris!
+
+ p1 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p2 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p3 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p4 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ fd_t2 = (p1.child_fd,p2.child_fd,p3.child_fd,p4.child_fd)
+ p1.kill(9)
+ p2.kill(9)
+ p3.kill(9)
+ p4.kill(9)
+ del (p1)
+ del (p2)
+ del (p3)
+ del (p4)
+ gc.collect()
+ time.sleep(3)
+
+ p1 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p2 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p3 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ p4 = pexpect.spawn('%s hello_world.py' % self.PYTHONBIN)
+ fd_t3 = (p1.child_fd,p2.child_fd,p3.child_fd,p4.child_fd)
+
+ assert (fd_t1 == fd_t2 == fd_t3), "pty file descriptors not properly garbage collected (fd_t1,fd_t2,fd_t3)=(%s,%s,%s)" % (str(fd_t1),str(fd_t2),str(fd_t3))
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(TestCaseDestructor,'test')
+
diff --git a/tests/test_dotall.py b/tests/test_dotall.py
new file mode 100755
index 0000000..46577da
--- /dev/null
+++ b/tests/test_dotall.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import os
+import re
+import PexpectTestCase
+
+testdata = 'BEGIN\nHello world\nEND'
+class TestCaseDotall(PexpectTestCase.PexpectTestCase):
+ def test_dotall (self):
+ p = pexpect.spawn('echo "%s"' % testdata)
+ i = p.expect (['BEGIN(.*)END', pexpect.EOF])
+ assert i==0, 'DOTALL does not seem to be working.'
+
+ def test_precompiled (self):
+ p = pexpect.spawn('echo "%s"' % testdata)
+ pat = re.compile('BEGIN(.*)END') # This overrides the default DOTALL.
+ i = p.expect ([pat, pexpect.EOF])
+ assert i==1, 'Precompiled pattern to override DOTALL does not seem to be working.'
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(TestCaseDotall,'test')
+
diff --git a/tests/test_expect.py b/tests/test_expect.py
new file mode 100755
index 0000000..7075aa0
--- /dev/null
+++ b/tests/test_expect.py
@@ -0,0 +1,424 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import commands
+import sys, time
+import PexpectTestCase
+#import pdb
+
+# Many of these test cases blindly assume that sequential directory
+# listings of the /bin directory will yield the same results.
+# This may not be true, but seems adequate for testing now.
+# I should fix this at some point.
+
+FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.' for x in range(256)])
+def hex_dump(src, length=16):
+ result=[]
+ for i in xrange(0, len(src), length):
+ s = src[i:i+length]
+ hexa = ' '.join(["%02X"%ord(x) for x in s])
+ printable = s.translate(FILTER)
+ result.append("%04X %-*s %s\n" % (i, length*3, hexa, printable))
+ return ''.join(result)
+
+class ExpectTestCase (PexpectTestCase.PexpectTestCase):
+
+ def test_expect_basic (self):
+ p = pexpect.spawn('cat')
+ p.sendline ('Hello')
+ p.sendline ('there')
+ p.sendline ('Mr. Python')
+ p.expect ('Hello')
+ p.expect ('there')
+ p.expect ('Mr. Python')
+ p.sendeof ()
+ p.expect (pexpect.EOF)
+
+ def test_expect_exact_basic (self):
+ p = pexpect.spawn('cat')
+ p.sendline ('Hello')
+ p.sendline ('there')
+ p.sendline ('Mr. Python')
+ p.expect_exact ('Hello')
+ p.expect_exact ('there')
+ p.expect_exact ('Mr. Python')
+ p.sendeof ()
+ p.expect_exact (pexpect.EOF)
+
+ def test_expect_ignore_case(self):
+ '''This test that the ignorecase flag will match patterns
+ even if case is different using the regex (?i) directive.
+ '''
+ p = pexpect.spawn('cat')
+ p.sendline ('HELLO')
+ p.sendline ('there')
+ p.expect ('(?i)hello')
+ p.expect ('(?i)THERE')
+ p.sendeof ()
+ p.expect (pexpect.EOF)
+
+ def test_expect_ignore_case_flag(self):
+ '''This test that the ignorecase flag will match patterns
+ even if case is different using the ignorecase flag.
+ '''
+ p = pexpect.spawn('cat')
+ p.ignorecase = True
+ p.sendline ('HELLO')
+ p.sendline ('there')
+ p.expect ('hello')
+ p.expect ('THERE')
+ p.sendeof ()
+ p.expect (pexpect.EOF)
+
+ def test_expect_order (self):
+ '''This tests that patterns are matched in the same order as given in the pattern_list.
+
+ (Or does it? Doesn't it also pass if expect() always chooses
+ (one of the) the leftmost matches in the input? -- grahn)
+ '''
+ p = pexpect.spawn('cat')
+ self._expect_order(p)
+
+ def test_expect_order_exact (self):
+ '''Like test_expect_order(), but using expect_exact().
+ '''
+ p = pexpect.spawn('cat')
+ p.expect = p.expect_exact
+ self._expect_order(p)
+
+ def _expect_order (self, p):
+ p.sendline ('1234')
+ p.sendline ('abcd')
+ p.sendline ('wxyz')
+ p.sendline ('7890')
+ p.sendeof ()
+ index = p.expect (['1234','abcd','wxyz',pexpect.EOF,'7890'])
+ assert index == 0, "index="+str(index)
+ index = p.expect (['1234','abcd','wxyz',pexpect.EOF,'7890'])
+ assert index == 0, "index="+str(index)
+ index = p.expect ([pexpect.EOF,pexpect.TIMEOUT,'wxyz','abcd','1234'])
+ assert index == 3, "index="+str(index)
+ index = p.expect (['54321',pexpect.TIMEOUT,'1234','abcd','wxyz',pexpect.EOF], timeout=5)
+ assert index == 3, "index="+str(index)
+ index = p.expect (['54321',pexpect.TIMEOUT,'1234','abcd','wxyz',pexpect.EOF], timeout=5)
+ assert index == 4, "index="+str(index)
+ index = p.expect (['54321',pexpect.TIMEOUT,'1234','abcd','wxyz',pexpect.EOF], timeout=5)
+ assert index == 4, "index="+str(index)
+ index = p.expect ([pexpect.EOF,'abcd','wxyz','7890'])
+ assert index == 3, "index="+str(index)
+ index = p.expect ([pexpect.EOF,'abcd','wxyz','7890'])
+ assert index == 3, "index="+str(index)
+
+ def test_waitnoecho (self):
+
+ ''' This tests that we can wait on a child process to set echo mode.
+ For example, this tests that we could wait for SSH to set ECHO False
+ when asking of a password. This makes use of an external script
+ echo_wait.py. '''
+
+ p1 = pexpect.spawn('%s echo_wait.py' % self.PYTHONBIN)
+ start = time.time()
+ p1.waitnoecho(timeout=10)
+ end_time = time.time() - start
+ assert end_time < 10 and end_time > 2, "waitnoecho did not set ECHO off in the expected window of time."
+
+ # test that we actually timeout and return False if ECHO is never set off.
+ p1 = pexpect.spawn('cat')
+ start = time.time()
+ retval = p1.waitnoecho(timeout=4)
+ end_time = time.time() - start
+ assert end_time > 3, "waitnoecho should have waited longer than 2 seconds. retval should be False, retval=%d"%retval
+ assert retval==False, "retval should be False, retval=%d"%retval
+
+ # This one is mainly here to test default timeout for code coverage.
+ p1 = pexpect.spawn('%s echo_wait.py' % self.PYTHONBIN)
+ start = time.time()
+ p1.waitnoecho()
+ end_time = time.time() - start
+ assert end_time < 10, "waitnoecho did not set ECHO off in the expected window of time."
+
+ def test_expect_echo (self):
+ '''This tests that echo can be turned on and off.
+ '''
+ p = pexpect.spawn('cat', timeout=10)
+ self._expect_echo(p)
+
+ def test_expect_echo_exact (self):
+ '''Like test_expect_echo(), but using expect_exact().
+ '''
+ p = pexpect.spawn('cat', timeout=10)
+ p.expect = p.expect_exact
+ self._expect_echo(p)
+
+ def _expect_echo (self, p):
+ p.sendline ('1234') # Should see this twice (once from tty echo and again from cat).
+ index = p.expect (['1234','abcd','wxyz',pexpect.EOF,pexpect.TIMEOUT])
+ assert index == 0, "index="+str(index)+"\n"+p.before
+ index = p.expect (['1234','abcd','wxyz',pexpect.EOF])
+ assert index == 0, "index="+str(index)
+ p.setecho(0) # Turn off tty echo
+ p.sendline ('abcd') # Now, should only see this once.
+ p.sendline ('wxyz') # Should also be only once.
+ index = p.expect ([pexpect.EOF,pexpect.TIMEOUT,'abcd','wxyz','1234'])
+ assert index == 2, "index="+str(index)
+ index = p.expect ([pexpect.EOF,'abcd','wxyz','7890'])
+ assert index == 2, "index="+str(index)
+ p.setecho(1) # Turn on tty echo
+ p.sendline ('7890') # Should see this twice.
+ index = p.expect ([pexpect.EOF,'abcd','wxyz','7890'])
+ assert index == 3, "index="+str(index)
+ index = p.expect ([pexpect.EOF,'abcd','wxyz','7890'])
+ assert index == 3, "index="+str(index)
+ p.sendeof()
+
+ def test_expect_index (self):
+ '''This tests that mixed list of regex strings, TIMEOUT, and EOF all
+ return the correct index when matched.
+ '''
+ #pdb.set_trace()
+ p = pexpect.spawn('cat')
+ self._expect_index(p)
+
+ def test_expect_index_exact (self):
+ '''Like test_expect_index(), but using expect_exact().
+ '''
+ p = pexpect.spawn('cat')
+ p.expect = p.expect_exact
+ self._expect_index(p)
+
+ def _expect_index (self, p):
+ p.setecho(0)
+ p.sendline ('1234')
+ index = p.expect (['abcd','wxyz','1234',pexpect.EOF])
+ assert index == 2, "index="+str(index)
+ p.sendline ('abcd')
+ index = p.expect ([pexpect.TIMEOUT,'abcd','wxyz','1234',pexpect.EOF])
+ assert index == 1, "index="+str(index)
+ p.sendline ('wxyz')
+ index = p.expect (['54321',pexpect.TIMEOUT,'abcd','wxyz','1234',pexpect.EOF], timeout=5)
+ assert index == 3, "index="+str(index) # Expect 'wxyz'
+ p.sendline ('$*!@?')
+ index = p.expect (['54321',pexpect.TIMEOUT,'abcd','wxyz','1234',pexpect.EOF], timeout=5)
+ assert index == 1, "index="+str(index) # Expect TIMEOUT
+ p.sendeof ()
+ index = p.expect (['54321',pexpect.TIMEOUT,'abcd','wxyz','1234',pexpect.EOF], timeout=5)
+ assert index == 5, "index="+str(index) # Expect EOF
+
+ def test_expect (self):
+ the_old_way = commands.getoutput('ls -l /bin')
+ p = pexpect.spawn('ls -l /bin')
+ the_new_way = ''
+ while 1:
+ i = p.expect (['\n', pexpect.EOF])
+ the_new_way = the_new_way + p.before
+ if i == 1:
+ break
+ the_new_way = the_new_way[:-1]
+ the_new_way = the_new_way.replace('\r','\n')
+ # For some reason I get an extra newline under OS X evey once in a while.
+ # I found it by looking through the hex_dump().
+ assert the_old_way == the_new_way, hex_dump(the_new_way) + "\n" + hex_dump(the_old_way)
+
+ def test_expect_exact (self):
+ the_old_way = commands.getoutput('ls -l /bin')
+ p = pexpect.spawn('ls -l /bin')
+ the_new_way = ''
+ while 1:
+ i = p.expect_exact (['\n', pexpect.EOF])
+ the_new_way = the_new_way + p.before
+ if i == 1:
+ break
+ the_new_way = the_new_way[:-1]
+ the_new_way = the_new_way.replace('\r','\n')
+ assert the_old_way == the_new_way, repr(the_old_way) + '\n' + repr(the_new_way)
+ p = pexpect.spawn('echo hello.?world')
+ i = p.expect_exact('.?')
+ assert p.before == 'hello' and p.after == '.?'
+
+ def test_expect_eof (self):
+ the_old_way = commands.getoutput('/bin/ls -l /bin')
+ p = pexpect.spawn('/bin/ls -l /bin')
+ p.expect(pexpect.EOF) # This basically tells it to read everything. Same as pexpect.run() function.
+ the_new_way = p.before
+ the_new_way = the_new_way.replace('\r','') # Remember, pty line endings are '\r\n'.
+ the_new_way = the_new_way[:-1]
+ assert the_old_way == the_new_way
+
+ def test_expect_timeout (self):
+ p = pexpect.spawn('ed', timeout=10)
+ i = p.expect(pexpect.TIMEOUT) # This tells it to wait for timeout.
+ assert p.after == pexpect.TIMEOUT
+
+ def test_unexpected_eof (self):
+ p = pexpect.spawn('ls -l /bin')
+ try:
+ p.expect('_Z_XY_XZ') # Probably never see this in ls output.
+ except pexpect.EOF, e:
+ pass
+ else:
+ self.fail ('Expected an EOF exception.')
+
+ def _before_after(self, p):
+ p.timeout = 5
+
+ p.expect('>>> ')
+ self.assertEqual(p.after, '>>> ')
+ self.assert_(p.before.startswith('Python '))
+
+ p.sendline('range(4*3)')
+
+ p.expect('5')
+ self.assertEqual(p.after, '5')
+ self.assert_(p.before.startswith('range(4*3)'))
+
+ p.expect('>>> ')
+ self.assertEqual(p.after, '>>> ')
+ self.assert_(p.before.startswith(', 6, 7, 8'))
+
+ def test_before_after(self):
+ '''This tests expect() for some simple before/after things.
+ '''
+ p = pexpect.spawn(self.PYTHONBIN)
+ self._before_after(p)
+
+ def test_before_after_exact(self):
+ '''This tests some simple before/after things, for
+ expect_exact(). (Grahn broke it at one point.)
+ '''
+ p = pexpect.spawn(self.PYTHONBIN)
+ # mangle the spawn so we test expect_exact() instead
+ p.expect = p.expect_exact
+ self._before_after(p)
+
+ def _ordering(self, p):
+ p.timeout = 5
+ p.expect('>>> ')
+
+ p.sendline('range(4*3)')
+ self.assertEqual(p.expect(['5,', '5,']), 0)
+ p.expect('>>> ')
+
+ p.sendline('range(4*3)')
+ self.assertEqual(p.expect(['7,', '5,']), 1)
+ p.expect('>>> ')
+
+ p.sendline('range(4*3)')
+ self.assertEqual(p.expect(['5,', '7,']), 0)
+ p.expect('>>> ')
+
+ p.sendline('range(4*5)')
+ self.assertEqual(p.expect(['2,', '12,']), 0)
+ p.expect('>>> ')
+
+ p.sendline('range(4*5)')
+ self.assertEqual(p.expect(['12,', '2,']), 1)
+
+ def test_ordering(self):
+ '''This tests expect() for which pattern is returned
+ when many may eventually match. I (Grahn) am a bit
+ confused about what should happen, but this test passes
+ with pexpect 2.1.
+ '''
+ p = pexpect.spawn(self.PYTHONBIN)
+ self._ordering(p)
+
+ def test_ordering_exact(self):
+ '''This tests expect_exact() for which pattern is returned
+ when many may eventually match. I (Grahn) am a bit
+ confused about what should happen, but this test passes
+ for the expect() method with pexpect 2.1.
+ '''
+ p = pexpect.spawn(self.PYTHONBIN)
+ # mangle the spawn so we test expect_exact() instead
+ p.expect = p.expect_exact
+ self._ordering(p)
+
+ def _greed(self, p):
+ p.timeout = 5
+ p.expect('>>> ')
+ p.sendline('import time')
+ p.expect('>>> ')
+ # the newline and sleep will (I hope) guarantee that
+ # pexpect is fed two distinct batches of data,
+ # "foo\r\n" + "bar\r\n".
+ foo_then_bar = 'print "f"+"o"+"o" ; time.sleep(3); print "b"+"a"+"r"'
+
+ p.sendline(foo_then_bar)
+ self.assertEqual(p.expect(['foo\r\nbar']), 0)
+ p.expect('>>> ')
+
+ p.sendline(foo_then_bar)
+ self.assertEqual(p.expect(['\r\nbar']), 0)
+ p.expect('>>> ')
+
+ p.sendline(foo_then_bar)
+ self.assertEqual(p.expect(['foo\r\nbar', 'foo', 'bar']), 1)
+ p.expect('>>> ')
+
+ p.sendline(foo_then_bar)
+ self.assertEqual(p.expect(['foo', 'foo\r\nbar', 'foo', 'bar']), 0)
+ p.expect('>>> ')
+
+ p.sendline(foo_then_bar)
+ self.assertEqual(p.expect(['bar', 'foo\r\nbar']), 1)
+ p.expect('>>> ')
+
+ # If the expect works as if we rematch for every new character,
+ # 'o\r\nb' should win over 'oo\r\nba'. The latter is longer and
+ # matches earlier in the input, but isn't satisfied until the 'a'
+ # arrives.
+ # However, pexpect doesn't do that (version 2.1 didn't).
+ p.sendline(foo_then_bar)
+ self.assertEqual(p.expect(['oo\r\nba', 'o\r\nb']), 0)
+ p.expect('>>> ')
+
+ # distinct patterns, but both suddenly match when the 'r' arrives.
+ p.sendline(foo_then_bar)
+ self.assertEqual(p.expect(['foo\r\nbar', 'ar']), 0)
+ p.expect('>>> ')
+
+ p.sendline(foo_then_bar)
+ self.assertEqual(p.expect(['ar', 'foo\r\nbar']), 1)
+ p.expect('>>> ')
+
+ def test_greed(self):
+ p = pexpect.spawn(self.PYTHONBIN)
+ self._greed(p)
+
+ def test_greed_exact(self):
+ p = pexpect.spawn(self.PYTHONBIN)
+ # mangle the spawn so we test expect_exact() instead
+ p.expect = p.expect_exact
+ self._greed(p)
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(ExpectTestCase,'test')
+
+#fout = open('delete_me_1','wb')
+#fout.write(the_old_way)
+#fout.close
+#fout = open('delete_me_2', 'wb')
+#fout.write(the_new_way)
+#fout.close
+
diff --git a/tests/test_filedescriptor.py b/tests/test_filedescriptor.py
new file mode 100755
index 0000000..9eb553b
--- /dev/null
+++ b/tests/test_filedescriptor.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import fdpexpect, pexpect
+import unittest
+import PexpectTestCase
+import sys
+import os
+
+class ExpectTestCase(PexpectTestCase.PexpectTestCase):
+ def setUp(self):
+ print self.id()
+ PexpectTestCase.PexpectTestCase.setUp(self)
+
+ def test_fd (self):
+ fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+ s = fdpexpect.fdspawn (fd)
+ s.expect ('This is the end of test data:')
+ s.expect (pexpect.EOF)
+ assert s.before == ' END\n'
+
+ def test_maxread (self):
+ fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+ s = fdpexpect.fdspawn (fd)
+ s.maxread = 100
+ s.expect('2')
+ s.expect ('This is the end of test data:')
+ s.expect (pexpect.EOF)
+ assert s.before == ' END\n'
+
+ def test_fd_isalive (self):
+ fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+ s = fdpexpect.fdspawn (fd)
+ assert s.isalive()
+ os.close (fd)
+ assert not s.isalive(), "Should not be alive after close()"
+
+ def test_fd_isatty (self):
+ fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+ s = fdpexpect.fdspawn (fd)
+ assert not s.isatty()
+ #os.close(fd)
+ s.close()
+
+### def test_close_does_not_close_fd (self):
+### '''Calling close() on a fdpexpect.fdspawn object should not
+### close the underlying file descriptor.
+### '''
+### fd = os.open ('TESTDATA.txt', os.O_RDONLY)
+### s = fdpexpect.fdspawn (fd)
+### try:
+### s.close()
+### self.fail('Expected an Exception.')
+### except pexpect.ExceptionPexpect, e:
+### pass
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(ExpectTestCase, 'test')
+
+#fout = open('delete_me_1','wb')
+#fout.write(the_old_way)
+#fout.close
+#fout = open('delete_me_2', 'wb')
+#fout.write(the_new_way)
+#fout.close
diff --git a/tests/test_interact.py b/tests/test_interact.py
new file mode 100755
index 0000000..bbdb681
--- /dev/null
+++ b/tests/test_interact.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import commands
+import sys, os, time, tty
+import PexpectTestCase
+import thread
+import threading
+
+def start_interact (p):
+ p.interact()
+
+class InteractTestCase (PexpectTestCase.PexpectTestCase):
+
+ def test_interact_thread (self):
+ # I can't believe this actually works...
+ # Note that I had to add a delay in the swapcase_echo.py script.
+ # I'm not sure why this helped.
+ p = pexpect.spawn('%s swapcase_echo.py' % self.PYTHONBIN)
+ mode = tty.tcgetattr(p.STDIN_FILENO)
+ t = threading.Thread (target=start_interact, args=(p,))
+ t.start()
+ #thread.start_new_thread (start_interact, (p,))
+ time.sleep(1)
+ p.sendline ('Hello')
+ #time.sleep(1)
+ try:
+ p.expect ('hELLO', timeout=4)
+ except Exception, e:
+ p.close(force = False)
+ tty.tcsetattr(p.STDIN_FILENO, tty.TCSAFLUSH, mode)
+ print str(p)
+ raise e
+ p.close(force = True)
+ tty.tcsetattr(p.STDIN_FILENO, tty.TCSAFLUSH, mode)
+# def test_interact_thread (self):
+# # I can't believe this actually works...
+# p = pexpect.spawn('%s swapcase_echo.py' % self.PYTHONBIN)
+# mode = tty.tcgetattr(p.STDIN_FILENO)
+# thread.start_new_thread (start_interact, (p,))
+# time.sleep(1)
+# p.sendline ('Hello')
+# time.sleep(2)
+# p.close(force = False)
+# tty.tcsetattr(p.STDIN_FILENO, tty.TCSAFLUSH, mode)
+
+ def test_interact (self):
+ p = pexpect.spawn('%s interact.py' % self.PYTHONBIN)
+ p.sendline ('Hello')
+ p.sendline ('there')
+ p.sendline ('Mr. Python')
+ p.expect ('Hello')
+ p.expect ('there')
+ p.expect ('Mr. Python')
+ p.sendeof ()
+ p.expect (pexpect.EOF)
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(InteractTestCase,'test')
+
diff --git a/tests/test_isalive.py b/tests/test_isalive.py
new file mode 100755
index 0000000..4c7e85e
--- /dev/null
+++ b/tests/test_isalive.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import sys, os, time
+import PexpectTestCase
+
+class IsAliveTestCase(PexpectTestCase.PexpectTestCase):
+
+ def test_expect_wait (self):
+ '''This tests that calling wait on a finished process works as expected.
+ '''
+ p = pexpect.spawn('sleep 3')
+ if not p.isalive():
+ self.fail ('Child process is not alive. It should be.')
+ time.sleep(1)
+ p.wait()
+ if p.isalive():
+ self.fail ('Child process is not dead. It should be.')
+ p = pexpect.spawn('sleep 3')
+ if not p.isalive():
+ self.fail ('Child process is not alive. It should be.')
+ p.kill(9)
+ time.sleep(1)
+ try:
+ p.wait()
+ except pexpect.ExceptionPexpect, e:
+ pass
+ else:
+ self.fail ('Should have raised ExceptionPython because you can\'t call wait on a dead process.')
+
+ def test_expect_isalive_dead_after_normal_termination (self):
+ p = pexpect.spawn('ls')
+ p.expect(pexpect.EOF)
+ time.sleep(1) # allow kernel status time to catch up with state.
+ if p.isalive():
+ self.fail ('Child process is not dead. It should be.')
+
+ def test_expect_isalive_dead_after_SIGINT (self):
+ p = pexpect.spawn('cat', timeout=5)
+ if not p.isalive():
+ self.fail ('Child process is not alive. It should be.')
+ p.terminate()
+ # Solaris is kind of slow.
+ # Without this delay then p.expect(...) will not see
+ # that the process is dead and it will timeout.
+ time.sleep(1)
+ p.expect(pexpect.EOF)
+ if p.isalive():
+ self.fail ('Child process is not dead. It should be.')
+
+ def test_expect_isalive_dead_after_SIGKILL (self):
+ p = pexpect.spawn('cat', timeout=3)
+ if not p.isalive():
+ self.fail ('Child process is not alive. It should be.')
+ p.kill(9)
+ # Solaris is kind of slow.
+ # Without this delay then p.expect(...) will not see
+ # that the process is dead and it will timeout.
+ time.sleep(1)
+ p.expect(pexpect.EOF)
+ if p.isalive():
+ self.fail ('Child process is not dead. It should be.')
+
+### Some platforms allow this. Some reset status after call to waitpid.
+ def test_expect_isalive_consistent_multiple_calls (self):
+
+ '''This tests that multiple calls to isalive() return same value.
+ '''
+
+ p = pexpect.spawn('cat')
+ if not p.isalive():
+ self.fail ('Child process is not alive. It should be.')
+ if not p.isalive():
+ self.fail ('Second call. Child process is not alive. It should be.')
+ p.kill(9)
+ p.expect(pexpect.EOF)
+ if p.isalive():
+ self.fail ('Child process is not dead. It should be.')
+ if p.isalive():
+ self.fail ('Second call. Child process is not dead. It should be.')
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(IsAliveTestCase, 'test')
+
diff --git a/tests/test_log.py b/tests/test_log.py
new file mode 100755
index 0000000..c3af9a7
--- /dev/null
+++ b/tests/test_log.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import os
+import tempfile
+import PexpectTestCase
+
+class TestCaseLog(PexpectTestCase.PexpectTestCase):
+
+ def test_log (self):
+ log_message = 'This is a test.'
+ filename = tempfile.mktemp()
+ mylog = open (filename, 'w')
+ p = pexpect.spawn('echo', [log_message])
+ p.logfile = mylog
+ p.expect (pexpect.EOF)
+ p.logfile = None
+ mylog.close()
+ lf = open(filename).read()
+ lf = lf[:-2]
+ os.unlink (filename)
+ assert lf == log_message
+
+ def test_log_logfile_read (self):
+ log_message = 'This is a test.'
+ filename = tempfile.mktemp()
+ mylog = open (filename, 'w')
+ p = pexpect.spawn('cat')
+ p.logfile_read = mylog
+ p.sendline(log_message)
+ p.sendeof()
+ p.expect (pexpect.EOF)
+ p.logfile = None
+ mylog.close()
+ lf = open(filename).read()
+ lf = lf[:-2]
+ os.unlink (filename)
+ lf = lf.replace(chr(4),'')
+ assert lf == 'This is a test.\r\nThis is a test.', "The read log file has bad data. Note logfile_read should only record what we read from child and nothing else.\n" + repr(lf)
+
+ def test_log_logfile_send (self):
+ log_message = 'This is a test.'
+ filename = tempfile.mktemp()
+ mylog = open (filename, 'w')
+ p = pexpect.spawn('cat')
+ p.logfile_send = mylog
+ p.sendline(log_message)
+ p.sendeof()
+ p.expect (pexpect.EOF)
+ p.logfile = None
+ mylog.close()
+ lf = open(filename).read()
+ lf = lf[:-2]
+ os.unlink (filename)
+ assert lf == log_message, "The send log file has bad data. Note logfile_send should only record what we sent to child and nothing else."
+
+ def test_log_send_and_received (self):
+
+ '''The logfile should have the test message three time -- once for the
+ data we sent. Once for the data that cat echos back as characters are
+ typed. And once for the data that cat prints after we send a linefeed
+ (sent by sendline). '''
+
+ log_message = 'This is a test.'
+ filename = tempfile.mktemp()
+ mylog = open (filename, 'w')
+ p = pexpect.spawn('cat')
+ p.logfile = mylog
+ p.sendline(log_message)
+ p.sendeof()
+ p.expect (pexpect.EOF)
+ p.logfile = None
+ mylog.close()
+ lf = open(filename).read()
+ os.unlink (filename)
+ lf = lf.replace(chr(4),'')
+ assert lf == 'This is a test.\nThis is a test.\r\nThis is a test.\r\n', repr(lf)
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(TestCaseLog,'test')
+
diff --git a/tests/test_misc.py b/tests/test_misc.py
new file mode 100755
index 0000000..61abfde
--- /dev/null
+++ b/tests/test_misc.py
@@ -0,0 +1,217 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import PexpectTestCase
+import time
+import os
+import re
+
+class TestCaseMisc(PexpectTestCase.PexpectTestCase):
+
+ def test_isatty (self):
+ child = pexpect.spawn('cat')
+ assert child.isatty(), "Not returning True. Should always be True."
+ def test_read (self):
+ child = pexpect.spawn('cat')
+ child.sendline ("abc")
+ child.sendeof()
+ assert child.read(0) == '', "read(0) did not return ''"
+ assert child.read(1) == 'a', "read(1) did not return 'a'"
+ assert child.read(1) == 'b', "read(1) did not return 'b'"
+ assert child.read(1) == 'c', "read(1) did not return 'c'"
+ assert child.read(2) == '\r\n', "read(2) did not return '\\r\\n'"
+ assert child.read() == 'abc\r\n', "read() did not return 'abc\\r\\n'"
+ def test_readline (self):
+ '''See the note in test_readlines() for an explaination as to why
+ I allow line3 and line4 to return multiple patterns.
+ Basically, this is done to handle a valid condition on slow systems.
+ '''
+ child = pexpect.spawn('cat')
+ child.sendline ("abc")
+ child.sendline ("123")
+ child.sendeof()
+ line1 = child.readline(0)
+ line2 = child.readline()
+ line3 = child.readline(2)
+ line4 = child.readline(1)
+ line5 = child.readline()
+ assert line1 == '', "readline(0) did not return ''. Returned: " + repr(line1)
+ assert line2 == 'abc\r\n', "readline() did not return 'abc\\r\\n'. Returned: " + repr(line2)
+ assert ( (line3 == 'abc\r\n' or line3 == '123\r\n'),
+ "readline(2) did not return 'abc\\r\\n'. Returned: "
+ + repr(line3) )
+ assert ( (line4 == '123\r\n' or line4 == 'abc\r\n'),
+ "readline(1) did not return '123\\r\\n'. Returned: "
+ + repr(line4) )
+ assert line5 == '123\r\n', "readline() did not return '123\\r\\n'. Returned: " + repr(line5)
+ def test_iter (self):
+ '''See the note in test_readlines() for an explaination as to why
+ I allow line3 and line4 to return multiple patterns.
+ Basically, this is done to handle a valid condition on slow systems.
+ '''
+ child = pexpect.spawn('cat')
+ child.sendline ("abc")
+ child.sendline ("123")
+ child.sendeof()
+ # Don't use ''.join() because we want to test the ITERATOR.
+ page = ""
+ for line in child:
+ page = page + line
+ assert ( (page == 'abc\r\nabc\r\n123\r\n123\r\n' or
+ page == 'abc\r\n123\r\nabc\r\n123\r\n') ,
+ "iterator did not work. page=%s"%repr(page) )
+ def test_readlines(self):
+ '''Note that on some slow or heavily loaded systems that the lines
+ coming back from 'cat' may come even after the EOF.
+ We except to see two copies of the lines we send 'cat'.
+ The first line is the TTY echo, the second line is from 'cat'.
+ Usually 'cat' will respond with 'abc' before we have a chance to
+ send the second line, '123'. If this does not happen then the
+ lines may appear out of order. This is technically not an error.
+ That's just the nature of asynchronous communication.
+ This is why the assert will allow either of the two possible
+ patterns to be returned by lineslined(). The (lame) alternative is
+ to put a long sleep between the two sendline() calls, but then
+ I have to make assumptions about how fast 'cat' can reply.
+ '''
+ child = pexpect.spawn('cat')
+ child.sendline ("abc")
+ child.sendline ("123")
+ child.sendeof()
+ page = child.readlines()
+ page = ''.join(page)
+ assert ( (page == 'abc\r\nabc\r\n123\r\n123\r\n' or
+ page == 'abc\r\n123\r\nabc\r\n123\r\n'),
+ "readlines() did not work. page=%s"%repr(page) )
+ def test_write (self):
+ child = pexpect.spawn('cat')
+ child.write('a')
+ child.write('\r')
+ assert child.readline() == 'a\r\n', "write() did not work"
+ def test_writelines (self):
+ child = pexpect.spawn('cat')
+ child.writelines(['abc','123','xyz','\r'])
+ child.sendeof()
+ line = child.readline()
+ assert line == 'abc123xyz\r\n', "writelines() did not work. line=%s"%repr(line)
+ def test_eof(self):
+ child = pexpect.spawn('cat')
+ child.sendeof()
+ try:
+ child.expect ('the unexpected')
+ except:
+ pass
+ assert child.eof(), "child.eof() did not return True"
+ def test_terminate(self):
+ child = pexpect.spawn('cat')
+ child.terminate(force=1)
+ assert child.terminated, "child.terminated is not True"
+ def test_bad_child_pid(self):
+ child = pexpect.spawn('cat')
+ child.terminate(force=1)
+ child.terminated = 0 # Force invalid state to test code
+ try:
+ child.isalive()
+ except pexpect.ExceptionPexpect, e:
+ pass
+ else:
+ self.fail ("child.isalive() should have raised a pexpect.ExceptionPexpect")
+ child.terminated = 1 # Force back to valid state so __del__ won't complain
+ def test_bad_arguments (self):
+ '''This tests that we get a graceful error when passing bad arguments.'''
+ try:
+ p = pexpect.spawn(1)
+ except pexpect.ExceptionPexpect, e:
+ pass
+ else:
+ self.fail ("pexpect.spawn(1) should have raised a pexpect.ExceptionPexpect.")
+ try:
+ p = pexpect.spawn('ls', '-la') # should really use pexpect.spawn('ls', ['-ls'])
+ except TypeError, e:
+ pass
+ else:
+ self.fail ("pexpect.spawn('ls', '-la') should have raised a TypeError.")
+ try:
+ p = pexpect.spawn('cat')
+ p.close()
+ p.read_nonblocking(size=1, timeout=3)
+ except ValueError, e:
+ pass
+ else:
+ self.fail ("read_nonblocking on closed spawn object should have raised a ValueError.")
+ def test_isalive(self):
+ child = pexpect.spawn('cat')
+ assert child.isalive(), "child.isalive() did not return True"
+ child.sendeof()
+ child.expect(pexpect.EOF)
+ assert not child.isalive(), "child.isalive() did not return False"
+ def test_bad_type_in_expect(self):
+ child = pexpect.spawn('cat')
+ try:
+ child.expect({}) # We don't support dicts yet. Should give TypeError
+ except TypeError, e:
+ pass
+ else:
+ self.fail ("child.expect({}) should have raised a TypeError")
+ def test_winsize(self):
+ child = pexpect.spawn('cat')
+ child.setwinsize(10,13)
+ assert child.getwinsize()==(10,13), "getwinsize() did not return (10,13)"
+ def test_env(self):
+ default = pexpect.run('env')
+ userenv = pexpect.run('env', env={'foo':'pexpect'})
+ assert default!=userenv, "'default' and 'userenv' should be different"
+ assert 'foo' in userenv and 'pexpect' in userenv, "'foo' and 'pexpect' should be in 'userenv'"
+ def test_cwd (self): # This assumes 'pwd' and '/tmp' exist on this platform.
+ default = pexpect.run('pwd')
+ tmpdir = pexpect.run('pwd', cwd='/tmp')
+ assert default!=tmpdir, "'default' and 'tmpdir' should be different"
+ assert ('tmp' in tmpdir), "'tmp' should be returned by 'pwd' command"
+ def test_which (self):
+ p = os.defpath
+ ep = os.environ['PATH']
+ os.defpath = ":/tmp"
+ os.environ['PATH'] = ":/tmp"
+ wp = pexpect.which ("ticker.py")
+ assert wp == 'ticker.py', "Should return a string. Returned %s" % wp
+ os.defpath = "/tmp"
+ os.environ['PATH'] = "/tmp"
+ wp = pexpect.which ("ticker.py")
+ assert wp == None, "Executable should not be found. Returned %s" % wp
+ os.defpath = p
+ os.environ['PATH'] = ep
+ def test_searcher_re (self):
+ ss = pexpect.searcher_re ([re.compile('this'),re.compile('that'),re.compile('and'),re.compile('the'),re.compile('other')])
+ assert ss.__str__() == 'searcher_re:\n 0: re.compile("this")\n 1: re.compile("that")\n 2: re.compile("and")\n 3: re.compile("the")\n 4: re.compile("other")'
+ ss = pexpect.searcher_re ([pexpect.TIMEOUT,re.compile('this'),re.compile('that'),re.compile('and'),pexpect.EOF,re.compile('other')])
+ assert ss.__str__() == 'searcher_re:\n 0: TIMEOUT\n 1: re.compile("this")\n 2: re.compile("that")\n 3: re.compile("and")\n 4: EOF\n 5: re.compile("other")'
+ def test_searcher_string (self):
+ ss = pexpect.searcher_string (['this','that','and','the','other'])
+ assert ss.__str__() == 'searcher_string:\n 0: "this"\n 1: "that"\n 2: "and"\n 3: "the"\n 4: "other"', repr(ss.__str__())
+ ss = pexpect.searcher_string (['this',pexpect.EOF,'that','and','the','other',pexpect.TIMEOUT])
+ assert ss.__str__() == 'searcher_string:\n 0: "this"\n 1: EOF\n 2: "that"\n 3: "and"\n 4: "the"\n 5: "other"\n 6: TIMEOUT'
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(TestCaseMisc,'test')
+
diff --git a/tests/test_missing_command.py b/tests/test_missing_command.py
new file mode 100755
index 0000000..fea9218
--- /dev/null
+++ b/tests/test_missing_command.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import PexpectTestCase
+
+class MissingCommandTestCase (PexpectTestCase.PexpectTestCase):
+ def testMissingCommand(self):
+ try:
+ i = pexpect.spawn ('ZXQYQZX')
+ except Exception:
+ pass
+ else:
+ self.fail('Expected an Exception.')
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(MissingCommandTestCase,'test')
+
diff --git a/tests/test_performance.py b/tests/test_performance.py
new file mode 100755
index 0000000..50bb12f
--- /dev/null
+++ b/tests/test_performance.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+import unittest, time
+import pexpect
+import PexpectTestCase
+
+# This isn't exactly a unit test, but it fits in nicely with the rest of the tests.
+
+class PerformanceTestCase (PexpectTestCase.PexpectTestCase):
+
+ '''Testing the performance of expect, with emphasis on wading through long
+ inputs. '''
+
+ def plain_range(self, n):
+ e = pexpect.spawn('python')
+ self.assertEqual(e.expect('>>>'), 0)
+ e.sendline('for n in range(1, %d+1): print n' % n)
+ self.assertEqual(e.expect(r'\.{3}'), 0)
+ e.sendline('')
+ self.assertEqual(e.expect(['inquisition', '%d' % n]), 1)
+
+ def window_range(self, n):
+ e = pexpect.spawn('python')
+ self.assertEqual(e.expect('>>>'), 0)
+ e.sendline('for n in range(1, %d+1): print n' % n)
+ self.assertEqual(e.expect(r'\.{3}'), 0)
+ e.sendline('')
+ self.assertEqual(e.expect(['inquisition', '%d' % n], searchwindowsize=10), 1)
+
+ def exact_range(self, n):
+ e = pexpect.spawn('python')
+ self.assertEqual(e.expect_exact(['>>>']), 0)
+ e.sendline('for n in range(1, %d+1): print n' % n)
+ self.assertEqual(e.expect_exact(['...']), 0)
+ e.sendline('')
+ self.assertEqual(e.expect_exact(['inquisition', '%d' % n],timeout=520), 1)
+
+ def ewin_range(self, n):
+ e = pexpect.spawn('python')
+ self.assertEqual(e.expect_exact(['>>>']), 0)
+ e.sendline('for n in range(1, %d+1): print n' % n)
+ self.assertEqual(e.expect_exact(['...']), 0)
+ e.sendline('')
+ self.assertEqual(e.expect_exact(['inquisition', '%d' % n], searchwindowsize=10), 1)
+
+ def faster_range(self, n):
+ e = pexpect.spawn('python')
+ self.assertEqual(e.expect('>>>'), 0)
+ e.sendline('range(1, %d+1)' % n)
+ self.assertEqual(e.expect(['inquisition', '%d' % n]), 1)
+
+ def test_100000(self):
+ start_time = time.time()
+ self.plain_range (100000)
+ print "100000 calls to plain_range:", (time.time() - start_time)
+ start_time = time.time()
+ self.window_range(100000)
+ print "100000 calls to window_range:", (time.time() - start_time)
+ start_time = time.time()
+ self.exact_range (100000)
+ print "100000 calls to exact_range:", (time.time() - start_time)
+ start_time = time.time()
+ self.ewin_range (100000)
+ print "100000 calls to ewin_range:", (time.time() - start_time)
+ start_time = time.time()
+ self.faster_range(100000)
+ print "100000 calls to faster_range:", (time.time() - start_time)
+
+if __name__ == "__main__":
+ unittest.main()
+
+suite = unittest.makeSuite(PerformanceTestCase,'test')
diff --git a/tests/test_run.py b/tests/test_run.py
new file mode 100755
index 0000000..261bcb0
--- /dev/null
+++ b/tests/test_run.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import commands
+import sys
+import PexpectTestCase
+
+# TODO Many of these test cases blindly assume that sequential
+# TODO listing of the /bin directory will yield the same results.
+# TODO This may not always be true, but seems adequate for testing for now.
+# TODO I should fix this at some point.
+
+def timeout_callback (d):
+# print d["event_count"],
+ if d["event_count"]>5:
+ return 1
+ return 0
+
+class ExpectTestCase(PexpectTestCase.PexpectTestCase):
+ def test_run_exit (self):
+ (data, exitstatus) = pexpect.run ('python exit1.py', withexitstatus=1)
+ assert exitstatus == 1, "Exit status of 'python exit1.py' should be 1."
+
+ def test_run (self):
+ the_old_way = commands.getoutput('ls -l /bin')
+ (the_new_way, exitstatus) = pexpect.run ('ls -l /bin', withexitstatus=1)
+ the_new_way = the_new_way.replace('\r','')[:-1]
+ assert the_old_way == the_new_way
+ assert exitstatus == 0
+
+ def test_run_callback (self): # TODO it seems like this test could block forever if run fails...
+ pexpect.run("cat", timeout=1, events={pexpect.TIMEOUT:timeout_callback})
+
+ def test_run_bad_exitstatus (self):
+ (the_new_way, exitstatus) = pexpect.run ('ls -l /najoeufhdnzkxjd', withexitstatus=1)
+ assert exitstatus != 0
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(ExpectTestCase,'test')
+
diff --git a/tests/test_run_out_of_pty.py b/tests/test_run_out_of_pty.py
new file mode 100755
index 0000000..b6b9e6c
--- /dev/null
+++ b/tests/test_run_out_of_pty.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import commands
+import sys
+import PexpectTestCase
+
+class ExpectTestCase(PexpectTestCase.PexpectTestCase):
+ # This takes too long to run and isn't all that interesting of a test.
+ def OFF_test_run_out_of_pty (self):
+ '''This assumes that the tested platform has < 10000 pty devices.
+ This test currently does not work under Solaris.
+ Under Solaris it runs out of file descriptors first and
+ ld.so starts to barf:
+ ld.so.1: pt_chmod: fatal: /usr/lib/libc.so.1: Too many open files
+ '''
+ plist=[]
+ for count in range (0,10000):
+ try:
+ plist.append (pexpect.spawn('ls -l'))
+ except pexpect.ExceptionPexpect, e:
+ for c in range (0,count):
+ plist[c].close()
+ return
+ except Exception, e:
+ self.fail ('Expected ExceptionPexpect. ' + str(e))
+ self.fail ('Could not run out of pty devices. This may be OK.')
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(ExpectTestCase,'test')
+
diff --git a/tests/test_screen.py b/tests/test_screen.py
new file mode 100755
index 0000000..714f85e
--- /dev/null
+++ b/tests/test_screen.py
@@ -0,0 +1,191 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+import screen
+import unittest
+import PexpectTestCase
+
+fill1_target='XXXXXXXXXX\n' + \
+'XOOOOOOOOX\n' + \
+'XO::::::OX\n' + \
+'XO:oooo:OX\n' + \
+'XO:o..o:OX\n' + \
+'XO:o..o:OX\n' + \
+'XO:oooo:OX\n' + \
+'XO::::::OX\n' + \
+'XOOOOOOOOX\n' + \
+'XXXXXXXXXX'
+fill2_target = 'XXXXXXXXXXX\n' + \
+'XOOOOOOOOOX\n' + \
+'XO:::::::OX\n' + \
+'XO:ooooo:OX\n' + \
+'XO:o...o:OX\n' + \
+'XO:o.+.o:OX\n' + \
+'XO:o...o:OX\n' + \
+'XO:ooooo:OX\n' + \
+'XO:::::::OX\n' + \
+'XOOOOOOOOOX\n' + \
+'XXXXXXXXXXX'
+put_target = '\\.3.5.7.9/\n' + \
+'.........2\n' + \
+'3.........\n' + \
+'.........4\n' + \
+'5...\\/....\n' + \
+'..../\\...6\n' + \
+'7.........\n' + \
+'.........8\n' + \
+'9.........\n' + \
+'/2.4.6.8.\\'
+scroll_target = '\\.3.5.7.9/\n' + \
+'\\.3.5.7.9/\n' + \
+'\\.3.5.7.9/\n' + \
+'\\.3.5.7.9/\n' + \
+'5...\\/....\n' + \
+'..../\\...6\n' + \
+'/2.4.6.8.\\\n' + \
+'/2.4.6.8.\\\n' + \
+'/2.4.6.8.\\\n' + \
+'/2.4.6.8.\\'
+insert_target = 'ZXZZZZZZXZ\n' +\
+'.........2\n' +\
+'3.........\n' +\
+'.........4\n' +\
+'Z5...\\/...\n' +\
+'..../Z\\...\n' +\
+'7.........\n' +\
+'.........8\n' +\
+'9.........\n' +\
+'ZZ/2.4.6ZZ'
+get_region_target = ['......', '.\\/...', './\\...', '......']
+
+class screenTestCase (PexpectTestCase.PexpectTestCase):
+ def make_screen_with_put (self):
+ s = screen.screen(10,10)
+ s.fill ('.')
+ for r in range (1,s.rows + 1):
+ if r % 2:
+ s.put_abs (r, 1, str(r))
+ else:
+ s.put_abs (r, s.cols, str(r))
+ for c in range (1,s.cols + 1):
+ if c % 2:
+ s.put_abs (1, c, str(c))
+ else:
+ s.put_abs (s.rows, c, str(c))
+ s.put_abs(1,1, '\\')
+ s.put_abs(1,s.cols, '/')
+ s.put_abs(s.rows,1,'/')
+ s.put_abs(s.rows, s.cols, '\\')
+ s.put_abs(5,5,'\\')
+ s.put_abs(5,6,'/')
+ s.put_abs(6,5,'/')
+ s.put_abs(6,6,'\\')
+ return s
+
+ def test_fill (self):
+ s = screen.screen (10,10)
+ s.fill_region (10,1,1,10,'X')
+ s.fill_region (2,2,9,9,'O')
+ s.fill_region (8,8,3,3,':')
+ s.fill_region (4,7,7,4,'o')
+ s.fill_region (6,5,5,6,'.')
+ assert str(s) == fill1_target
+
+ s = screen.screen (11,11)
+ s.fill_region (1,1,11,11,'X')
+ s.fill_region (2,2,10,10,'O')
+ s.fill_region (9,9,3,3,':')
+ s.fill_region (4,8,8,4,'o')
+ s.fill_region (7,5,5,7,'.')
+ s.fill_region (6,6,6,6,'+')
+ assert str(s) == fill2_target
+ def test_put (self):
+ s = self.make_screen_with_put()
+ assert str(s) == put_target
+ def test_get_region (self):
+ s = self.make_screen_with_put()
+ r = s.get_region (4,4,7,9)
+ assert r == get_region_target
+
+ def test_cursor_save (self):
+ s = self.make_screen_with_put()
+ s.cursor_home (5,5)
+ c = s.get()
+ s.cursor_save()
+ s.cursor_home()
+ s.cursor_forward()
+ s.cursor_down()
+ s.cursor_unsave()
+ assert s.cur_r == 5 and s.cur_c == 5
+ assert c == s.get()
+ def test_scroll (self):
+ s = self.make_screen_with_put()
+ s.scroll_screen_rows (1,4)
+ s.scroll_down(); s.scroll_down(); s.scroll_down()
+ s.scroll_down(); s.scroll_down(); s.scroll_down()
+ s.scroll_screen_rows (7,10)
+ s.scroll_up(); s.scroll_up(); s.scroll_up()
+ s.scroll_up(); s.scroll_up(); s.scroll_up()
+ assert str(s) == scroll_target
+ def test_insert (self):
+ s = self.make_screen_with_put()
+ s.insert_abs (10,1,'Z')
+ s.insert_abs (1,1,'Z')
+ s.insert_abs (1,1,'Z')
+ s.insert_abs (1,1,'Z')
+ s.insert_abs (1,1,'Z')
+ s.insert_abs (1,1,'Z')
+ s.insert_abs (10,1,'Z')
+ s.insert_abs (1,1,'Z')
+ s.insert_abs (1,1,'Z')
+ s.insert_abs (5,1,'Z')
+ s.insert_abs (6,6,'Z')
+ s.cursor_home (1,1) # Also test relative insert.
+ s.insert ('Z')
+ s.insert ('Z')
+ s.insert ('Z')
+ s.insert ('Z')
+ s.insert_abs (1,8,'X')
+ s.insert_abs (1,2,'X')
+ s.insert_abs (10,9,'Z')
+ s.insert_abs (10,9,'Z')
+ assert str(s) == insert_target
+ # def test_write (self):
+ # s = screen.screen (6,65)
+ # s.fill('.')
+ # s.cursor_home()
+ # for c in write_text:
+ # s.write (c)
+ # print str(s)
+ # assert str(s) == write_target
+ # def test_tetris (self):
+ # s = screen.screen (24,80)
+ # tetris_text = open ('tetris.data').read()
+ # for c in tetris_text:
+ # s.write (c)
+ # assert str(s) == tetris_target
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(screenTestCase,'test')
+
+
diff --git a/tests/test_timeout_pattern.py b/tests/test_timeout_pattern.py
new file mode 100755
index 0000000..606b045
--- /dev/null
+++ b/tests/test_timeout_pattern.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import sys, os, time
+import PexpectTestCase
+
+class Exp_TimeoutTestCase(PexpectTestCase.PexpectTestCase):
+ def test_matches_exp_timeout (self):
+ '''This tests that we can raise and catch TIMEOUT.
+ '''
+ try:
+ raise pexpect.TIMEOUT("TIMEOUT match test")
+ except pexpect.TIMEOUT:
+ pass
+ #print "Correctly caught TIMEOUT when raising TIMEOUT."
+ else:
+ self.fail('TIMEOUT not caught by an except TIMEOUT clause.')
+
+ def test_pattern_printout (self):
+ '''Verify that a TIMEOUT returns the proper patterns it is trying to match against.
+ Make sure it is returning the pattern from the correct call.'''
+ try:
+ p = pexpect.spawn('cat')
+ p.sendline('Hello')
+ p.expect('Hello')
+ p.expect('Goodbye',timeout=5)
+ except pexpect.TIMEOUT, expTimeoutInst:
+ assert p.match_index == None
+ else:
+ self.fail("Did not generate a TIMEOUT exception.")
+
+ def test_exp_timeout_notThrown (self):
+ '''Verify that a TIMEOUT is not thrown when we match what we expect.'''
+ try:
+ p = pexpect.spawn('cat')
+ p.sendline('Hello')
+ p.expect('Hello')
+ except pexpect.TIMEOUT:
+ self.fail("TIMEOUT caught when it shouldn't be raised because we match the proper pattern.")
+
+ def test_stacktraceMunging (self):
+ '''Verify that the stack trace returned with a TIMEOUT instance does not contain references to pexpect.'''
+ try:
+ p = pexpect.spawn('cat')
+ p.sendline('Hello')
+ p.expect('Goodbye',timeout=5)
+ except pexpect.TIMEOUT, e:
+ if e.get_trace().count("pexpect.py") != 0:
+ self.fail("The TIMEOUT get_trace() referenced pexpect.py. It should only reference the caller.\n"+e.get_trace())
+
+ def test_correctStackTrace (self):
+ '''Verify that the stack trace returned with a TIMEOUT instance correctly handles function calls.'''
+ def nestedFunction (spawnInstance):
+ spawnInstance.expect("junk", timeout=3)
+
+ try:
+ p = pexpect.spawn('cat')
+ p.sendline('Hello')
+ nestedFunction(p)
+ except pexpect.TIMEOUT, e:
+ if e.get_trace().count("nestedFunction") == 0:
+ self.fail("The TIMEOUT get_trace() did not show the call to the nestedFunction function.\n" + str(e) + "\n" + e.get_trace())
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(Exp_TimeoutTestCase,'test')
diff --git a/tests/test_winsize.py b/tests/test_winsize.py
new file mode 100755
index 0000000..4888641
--- /dev/null
+++ b/tests/test_winsize.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+import pexpect
+import unittest
+import PexpectTestCase
+import time
+import sys, os, signal
+
+class TestCaseWinsize(PexpectTestCase.PexpectTestCase):
+
+ def test_winsize (self):
+ '''
+ This tests that the child process can set and get the windows size.
+ This makes use of an external script sigwinch_report.py.
+ '''
+ p1 = pexpect.spawn('%s sigwinch_report.py' % self.PYTHONBIN)
+ time.sleep(10)
+ p1.setwinsize (11,22)
+ time.sleep(3)
+ index = p1.expect ([pexpect.TIMEOUT, 'SIGWINCH: \(([0-9]*), ([0-9]*)\)'], timeout=30)
+ if index == 0:
+ self.fail ("TIMEOUT -- this platform may not support sigwinch properly.\n" + str(p1))
+ r = p1.match.group(1)
+ c = p1.match.group(2)
+ assert (r=="11" and c=="22")
+ time.sleep(1)
+ p1.setwinsize (24,80)
+ index = p1.expect ([pexpect.TIMEOUT, 'SIGWINCH: \(([0-9]*), ([0-9]*)\)'], timeout=10)
+ if index == 0:
+ self.fail ("TIMEOUT -- this platform may not support sigwinch properly.\n" + str(p1))
+ r = p1.match.group(1)
+ c = p1.match.group(2)
+ assert (r=="24" and c=="80")
+ p1.close()
+
+# def test_parent_resize (self):
+# pid = os.getpid()
+# p1 = pexpect.spawn('%s sigwinch_report.py' % self.PYTHONBIN)
+# time.sleep(10)
+# p1.setwinsize (11,22)
+# os.kill (pid, signal.SIGWINCH)
+
+if __name__ == '__main__':
+ unittest.main()
+
+suite = unittest.makeSuite(TestCaseWinsize,'test')
+
+
diff --git a/tests/tetris.data b/tests/tetris.data
new file mode 100644
index 0000000..06b6ce6
--- /dev/null
+++ b/tests/tetris.data
@@ -0,0 +1,3 @@
+
+ J->LEFT K->ROTATE L->RIGHT SPACE->DROP P->PAUSE Q->QUIT
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXX XXXXXXXXXX XXXXXXXXXX XXXXXXXXXXXX XX XXXXXXXXXXXX XXXX XX XXXXXXXXXXXXXXXX XXXXXXXXXX XXXXXXXXXXXXXXXXXXXX XXXXXXXX XX XXXX XXXXXXXX XX XXXX XX XXXX XX XXXXXXXXXXXXXXXX XXXXXXXX XXXXXXXX  XXXXXXXXXXXXXXXXXXXX XXXXXXXX XX XXXX XX XXXX XXXXXXXXXX   XXXXXX XXXXXX XX  XXXXXXXX  XXXXXXXXXXXXXXXX XXXXXXXXXX XX XX  XXXXXXXXXX XX XXXX XX XXXX  XXXXXXXXXX  XXXXXXXXXXXXXXXXXXXX XX XXXX XXXXXXXX XX XXXX XX XXXX XX XXXX XXXXXXXXXXXX  XXXXXXXXXXXXXXXXXXXXXX XX XXXXXXXXXXXX XXXX XXXXXXXXXX XXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXX XXXXXXXXXX XX XXXX XX XXXX XX XXXX XXXXXX  XXXXXXXXXXXXXXXXXXXXXX XX XX XXXXXXXXXX XX XXXX XX XXXXXXXX  XXXXXXXXXXXXXXXXXXXX XXXX XXXXXXXXXXXX  XXXXXX XXXX XXXXXX  XXXX  XXXXXX XXXX    XXXXXXXXXXXXXXXXXXXXXX XX XXXX XX XX XX XXXXXXXX XX XX XXXX XX   XXXXXXXX  XXXXXXXXXXXXXXXXXXXX XXXX  XXXXXX XX XX XXXXXXXX XXXXXX  XX XXXXXX  XXXXXX XXXX    XXXXXXXXXXXXXXXXXXXX   XXXXXXXX XX XXXXXX XX XXXXXXXXXX XX XXXXXX   XXXXXX XX XX XX XXXXXX   XXXXXXXXXXXXXXXXXXXX  XX XXXXXX XX XXXXXXXX XX  XXXXXX   XXXXXXXXXXXXXXXXXXXX XX XXXX XXXXXXXXXX   XXXXXX XX XX XXXX XXXXXX XX XX XXXX  XXXXXXXXXXXX   XXXX   XXXXXXXXXXXXXXXXXX XXXXXX XX XX XXXXXXXX XX XXXX XX XX XX XXXXXX XX XX XX  XXXXXX   XXXXXXXXXXXXXXXXXX XXXXXXXXXXXX XX XXXXXX XX XXXXXX XXXXXX  XXXXXXXXXXXXXXXX XXXXXXXX  XX XXXXXX XXXXXX   XXXXXXXXXXXXXXXXXXXX  XXXXXXXXXXXXXXXXXXXX XXXXXX XX XX XXXXXXXX XX XXXX XX XX  XXXXXXXXXXXXXXXXXXXX XX XXXX  XX XX XX XXXXXXXX XX XXXXXXXX XX XXXX XX  XXXXXXXXXXXXXXXX XXXX XXXXXXXX XX XX XXXX XX XXXX XX XX XX XXXX  XXXXXXXX XX XX XX   XXXXXXXXXXXXXXXXXXXX XX XXXX  XX XX XX XXXXXXXXXXXXXXXX XXXX  XXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXX XX XXXXXX XX XX XXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXX
diff --git a/tests/ticker.py b/tests/ticker.py
new file mode 100755
index 0000000..5ecc1c2
--- /dev/null
+++ b/tests/ticker.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+'''
+PEXPECT LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2012, Noah Spurrier <noah@noah.org>
+ PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY
+ PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE
+ COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES.
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''
+
+import time, sys
+
+for i in range(5):
+ print "tick"
+ time.sleep(1)
+
+sys.exit(0)
diff --git a/tests/torturet.vt b/tests/torturet.vt
new file mode 100644
index 0000000..65f965b
--- /dev/null
+++ b/tests/torturet.vt
@@ -0,0 +1,61 @@
+\<>PrEM1\[?4h
+#6(0a`opqrs`(B This is the (0`srqpo`a(B
+#3VT100 series Torture Test Demonstration.
+#4VT100 series Torture Test Demonstration.
+#6 Watch the blinking lights 
+
+
+
+PrEM0\
+
+This file is a VT100-series Torture Test. It demonstrates all the visual
+attributes of the VT100 terminal.
+
+The top line is double-width/single-height with inverse-video line-drawing
+characters. The 2nd and 3rd lines are double-width/double-height in bold
+inverse video. They also show the limited scrolling region.
+
+The remaining lines will show NORMAL, BOLD, BLINK, INVERSE, and all 16
+combinations of those 4 attributes. They show that there is a difference
+between an underscore character and the underline attribute, and that
+lower-case decenders go below the underline.
+
+A window pane is drawn in the lower right to show how the line-drawing set
+can be used. At the lower left is the character set double-wide/double-high
+to show the dot-matrix used. Upper-case characters are 8 by 7 in a 10 by 10
+character cell, with 1 blank row on top and 2 on the bottom. The underline
+attribute uses the first bottom blank row, lower-case decenders use both.
+
+
+
+This is a normal line __________________________________________________y_
+This is a bold line (normal unless the Advanced Video Option is installed)
+This line is underlined _ " " " " " " _y_
+This is a blinking line _ " " " " " " _y_
+This is inverse video _ (underlined if no AVO and cursor is underline) _y_
+Normal gjpqy Underline  Blink Underline+Blink gjpqy
+Bold gjpqy Underline  Blink Underline+Blink gjpqy
+Inverse Underline  Blink Underline+Blink
+Bold+Inverse Underline  Blink Underline+Blink
+PrEM1\
+#6This is double width
+#3This is double height
+#4This is double height
+#6_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy
+#3_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy
+#4_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ioy
+ACEGIKMOQSUWY02468iy
+_BDFHJLNPRTVXZ13579o
+_BDFHJLNPRTVXZ13579o
+(0#6`abcdefghijklmnopqrstuvwxyz{|}~ lqwqk
+#3`abcdefghijklmnopqrstuvwxyz{|}~ tqnqu
+#4`abcdefghijklmnopqrstuvwxyz{|}~ tqnqu
+acegikmoqsuwy{}
+`bdfhjlnprtvxz|~
+`bdfhjlnprtvxz|~(B
+#6`abcdefghijklmnopqrstuvwxyz{|}~(0 mqvqj(B
+acegikmoqsuwy{}
+PrEM0\ $PrEM0 works on GIGI 
+ This test created by Joe Smith, 8-May-85 
+
+