blob: b2ec7c620ef19808f0f4f524516d730cfc3e0ccc [file] [log] [blame]
cliechticb65c682008-06-22 22:47:02 +00001#! /usr/bin/env python
2# Python Serial Port Extension for Win32, Linux, BSD, Jython
3# see __init__.py
cliechtid6bf52c2003-10-01 02:28:12 +00004#
Chris Liechtid73344d2015-08-06 17:52:51 +02005# (C) 2001-2015 Chris Liechti <cliechti@gmx.net>
cliechtid6bf52c2003-10-01 02:28:12 +00006# this is distributed under a free software license, see license.txt
cliechti1e95baa2002-06-04 22:46:50 +00007
cliechticb65c682008-06-22 22:47:02 +00008"""\
9Some tests for the serial module.
Chris Liechtid73344d2015-08-06 17:52:51 +020010Part of pyserial (http://pyserial.sf.net) (C)2001-2015 cliechti@gmx.net
cliechtid6bf52c2003-10-01 02:28:12 +000011
12Intended to be run on different platforms, to ensure portability of
cliechti1e95baa2002-06-04 22:46:50 +000013the code.
14
cliechtid6bf52c2003-10-01 02:28:12 +000015For all these tests a simple hardware is required.
cliechti1e95baa2002-06-04 22:46:50 +000016Loopback HW adapter:
cliechtid6bf52c2003-10-01 02:28:12 +000017Shortcut these pin pairs:
cliechtia135a672002-06-11 15:10:46 +000018 TX <-> RX
19 RTS <-> CTS
20 DTR <-> DSR
cliechti1e95baa2002-06-04 22:46:50 +000021
cliechtid6bf52c2003-10-01 02:28:12 +000022On a 9 pole DSUB these are the pins (2-3) (4-6) (7-8)
cliechti1e95baa2002-06-04 22:46:50 +000023"""
24
cliechtif16c7702009-08-02 00:00:55 +000025import unittest
26import threading
27import time
cliechtia75900c2009-07-28 00:12:52 +000028import sys
cliechti1e95baa2002-06-04 22:46:50 +000029import serial
cliechtic813b212002-06-04 21:12:10 +000030
cliechti58a3efe2009-07-21 20:56:52 +000031# on which port should the tests be performed:
cliechtif16c7702009-08-02 00:00:55 +000032PORT = 0
cliechtic813b212002-06-04 21:12:10 +000033
cliechtia75900c2009-07-28 00:12:52 +000034if sys.version_info >= (3, 0):
35 def data(string):
36 return bytes(string, 'latin1')
cliechti782d04d2010-05-20 22:36:20 +000037 bytes_0to255 = bytes(range(256))
cliechtia75900c2009-07-28 00:12:52 +000038else:
39 def data(string): return string
cliechti54c534e2009-08-06 23:24:26 +000040 bytes_0to255 = ''.join([chr(x) for x in range(256)])
41
42
43def segments(data, size=16):
44 for a in range(0, len(data), size):
45 yield data[a:a+size]
cliechtia75900c2009-07-28 00:12:52 +000046
cliechtic813b212002-06-04 21:12:10 +000047
cliechtia135a672002-06-11 15:10:46 +000048class Test4_Nonblocking(unittest.TestCase):
cliechtic813b212002-06-04 21:12:10 +000049 """Test with timeouts"""
cliechtia75900c2009-07-28 00:12:52 +000050 timeout = 0
51
cliechtic813b212002-06-04 21:12:10 +000052 def setUp(self):
cliechtie3ab3532009-08-05 12:40:38 +000053 self.s = serial.serial_for_url(PORT, timeout=self.timeout)
cliechti58a3efe2009-07-21 20:56:52 +000054
cliechtic813b212002-06-04 21:12:10 +000055 def tearDown(self):
56 self.s.close()
57
cliechtia135a672002-06-11 15:10:46 +000058 def test0_Messy(self):
59 """NonBlocking (timeout=0)"""
cliechti58a3efe2009-07-21 20:56:52 +000060 # this is only here to write out the message in verbose mode
61 # because Test3 and Test4 print the same messages
cliechtia135a672002-06-11 15:10:46 +000062
cliechtic813b212002-06-04 21:12:10 +000063 def test1_ReadEmpty(self):
cliechtia135a672002-06-11 15:10:46 +000064 """timeout: After port open, the input buffer must be empty"""
cliechtia75900c2009-07-28 00:12:52 +000065 self.failUnlessEqual(self.s.read(1), data(''), "expected empty buffer")
cliechti58a3efe2009-07-21 20:56:52 +000066
cliechtic813b212002-06-04 21:12:10 +000067 def test2_Loopback(self):
cliechtia135a672002-06-11 15:10:46 +000068 """timeout: each sent character should return (binary test).
cliechti1e95baa2002-06-04 22:46:50 +000069 this is also a test for the binary capability of a port."""
cliechti54c534e2009-08-06 23:24:26 +000070 for block in segments(bytes_0to255):
71 length = len(block)
72 self.s.write(block)
cliechtia75900c2009-07-28 00:12:52 +000073 # there might be a small delay until the character is ready (especially on win32)
cliechtif16c7702009-08-02 00:00:55 +000074 time.sleep(0.05)
cliechti54c534e2009-08-06 23:24:26 +000075 self.failUnlessEqual(self.s.inWaiting(), length, "expected exactly %d character for inWainting()" % length)
76 self.failUnlessEqual(self.s.read(length), block)#, "expected a %r which was written before" % block)
cliechtia75900c2009-07-28 00:12:52 +000077 self.failUnlessEqual(self.s.read(1), data(''), "expected empty buffer after all sent chars are read")
cliechti58a3efe2009-07-21 20:56:52 +000078
cliechtic813b212002-06-04 21:12:10 +000079 def test2_LoopbackTimeout(self):
cliechtia135a672002-06-11 15:10:46 +000080 """timeout: test the timeout/immediate return.
81 partial results should be returned."""
cliechtia75900c2009-07-28 00:12:52 +000082 self.s.write(data("HELLO"))
cliechtif16c7702009-08-02 00:00:55 +000083 time.sleep(0.1) # there might be a small delay until the character is ready (especially on win32 and rfc2217)
cliechti58a3efe2009-07-21 20:56:52 +000084 # read more characters as are available to run in the timeout
cliechtia75900c2009-07-28 00:12:52 +000085 self.failUnlessEqual(self.s.read(10), data('HELLO'), "expected the 'HELLO' which was written before")
86 self.failUnlessEqual(self.s.read(1), data(''), "expected empty buffer after all sent chars are read")
cliechtic813b212002-06-04 21:12:10 +000087
88
cliechtia135a672002-06-11 15:10:46 +000089class Test3_Timeout(Test4_Nonblocking):
cliechtic813b212002-06-04 21:12:10 +000090 """Same tests as the NonBlocking ones but this time with timeout"""
cliechtia75900c2009-07-28 00:12:52 +000091 timeout = 1
cliechti58a3efe2009-07-21 20:56:52 +000092
cliechtia135a672002-06-11 15:10:46 +000093 def test0_Messy(self):
94 """Blocking (timeout=1)"""
cliechti58a3efe2009-07-21 20:56:52 +000095 # this is only here to write out the message in verbose mode
96 # because Test3 and Test4 print the same messages
cliechtic813b212002-06-04 21:12:10 +000097
cliechtif16c7702009-08-02 00:00:55 +000098
cliechti1e95baa2002-06-04 22:46:50 +000099class SendEvent(threading.Thread):
cliechtif16c7702009-08-02 00:00:55 +0000100 def __init__(self, serial, delay=3):
cliechti1e95baa2002-06-04 22:46:50 +0000101 threading.Thread.__init__(self)
102 self.serial = serial
103 self.delay = delay
104 self.x = threading.Event()
105 self.stopped = 0
106 self.start()
cliechti58a3efe2009-07-21 20:56:52 +0000107
cliechti1e95baa2002-06-04 22:46:50 +0000108 def run(self):
109 time.sleep(self.delay)
cliechti8b599c92011-08-15 13:12:09 +0000110 self.x.set()
cliechti1e95baa2002-06-04 22:46:50 +0000111 if not self.stopped:
cliechtia75900c2009-07-28 00:12:52 +0000112 self.serial.write(data("E"))
cliechti7fc7da02009-08-03 23:49:02 +0000113 self.serial.flush()
cliechti58a3efe2009-07-21 20:56:52 +0000114
cliechti1e95baa2002-06-04 22:46:50 +0000115 def isSet(self):
116 return self.x.isSet()
cliechti58a3efe2009-07-21 20:56:52 +0000117
cliechti1e95baa2002-06-04 22:46:50 +0000118 def stop(self):
119 self.stopped = 1
120 self.x.wait()
121
122class Test1_Forever(unittest.TestCase):
123 """Tests a port with no timeout. These tests require that a
124 character is sent after some time to stop the test, this is done
125 through the SendEvent class and the Loopback HW."""
126 def setUp(self):
cliechtie3ab3532009-08-05 12:40:38 +0000127 self.s = serial.serial_for_url(PORT, timeout=None)
cliechti1e95baa2002-06-04 22:46:50 +0000128 self.event = SendEvent(self.s)
cliechti58a3efe2009-07-21 20:56:52 +0000129
cliechti1e95baa2002-06-04 22:46:50 +0000130 def tearDown(self):
131 self.event.stop()
132 self.s.close()
133
134 def test2_ReadEmpty(self):
cliechtia135a672002-06-11 15:10:46 +0000135 """no timeout: after port open, the input buffer must be empty (read).
136 a character is sent after some time to terminate the test (SendEvent)."""
cliechti1e95baa2002-06-04 22:46:50 +0000137 c = self.s.read(1)
cliechtia75900c2009-07-28 00:12:52 +0000138 if not (self.event.isSet() and c == data('E')):
cliechti8b599c92011-08-15 13:12:09 +0000139 self.fail("expected marker (evt=%r, c=%r)" % (self.event.isSet(), c))
cliechti1e95baa2002-06-04 22:46:50 +0000140
cliechtif16c7702009-08-02 00:00:55 +0000141
cliechti1e95baa2002-06-04 22:46:50 +0000142class Test2_Forever(unittest.TestCase):
143 """Tests a port with no timeout"""
144 def setUp(self):
cliechtie3ab3532009-08-05 12:40:38 +0000145 self.s = serial.serial_for_url(PORT, timeout=None)
cliechti58a3efe2009-07-21 20:56:52 +0000146
cliechti1e95baa2002-06-04 22:46:50 +0000147 def tearDown(self):
148 self.s.close()
149
150 def test1_inWaitingEmpty(self):
cliechtia135a672002-06-11 15:10:46 +0000151 """no timeout: after port open, the input buffer must be empty (inWaiting)"""
cliechtia75900c2009-07-28 00:12:52 +0000152 self.failUnlessEqual(self.s.inWaiting(), 0, "expected empty buffer")
cliechti1e95baa2002-06-04 22:46:50 +0000153
154 def test2_Loopback(self):
cliechtia135a672002-06-11 15:10:46 +0000155 """no timeout: each sent character should return (binary test).
cliechti1e95baa2002-06-04 22:46:50 +0000156 this is also a test for the binary capability of a port."""
cliechti54c534e2009-08-06 23:24:26 +0000157 for block in segments(bytes_0to255):
158 length = len(block)
159 self.s.write(block)
cliechtif16c7702009-08-02 00:00:55 +0000160 # there might be a small delay until the character is ready (especially on win32 and rfc2217)
161 time.sleep(0.05)
cliechti54c534e2009-08-06 23:24:26 +0000162 self.failUnlessEqual(self.s.inWaiting(), length)#, "expected exactly %d character for inWainting()" % length)
163 self.failUnlessEqual(self.s.read(length), block) #, "expected %r which was written before" % block)
cliechtia75900c2009-07-28 00:12:52 +0000164 self.failUnlessEqual(self.s.inWaiting(), 0, "expected empty buffer after all sent chars are read")
cliechtic813b212002-06-04 21:12:10 +0000165
166
cliechtia135a672002-06-11 15:10:46 +0000167class Test0_DataWires(unittest.TestCase):
cliechtic813b212002-06-04 21:12:10 +0000168 """Test modem control lines"""
169 def setUp(self):
cliechtie3ab3532009-08-05 12:40:38 +0000170 self.s = serial.serial_for_url(PORT)
cliechti58a3efe2009-07-21 20:56:52 +0000171
cliechtic813b212002-06-04 21:12:10 +0000172 def tearDown(self):
173 self.s.close()
174
175 def test1_RTS(self):
cliechtia135a672002-06-11 15:10:46 +0000176 """Test RTS/CTS"""
cliechtic813b212002-06-04 21:12:10 +0000177 self.s.setRTS(0)
cliechti7fc7da02009-08-03 23:49:02 +0000178 time.sleep(1.1)
cliechticb65c682008-06-22 22:47:02 +0000179 self.failUnless(not self.s.getCTS(), "CTS -> 0")
cliechtic813b212002-06-04 21:12:10 +0000180 self.s.setRTS(1)
cliechti7fc7da02009-08-03 23:49:02 +0000181 time.sleep(1.1)
cliechticb65c682008-06-22 22:47:02 +0000182 self.failUnless(self.s.getCTS(), "CTS -> 1")
cliechtic813b212002-06-04 21:12:10 +0000183
184 def test2_DTR(self):
cliechtia135a672002-06-11 15:10:46 +0000185 """Test DTR/DSR"""
cliechtic813b212002-06-04 21:12:10 +0000186 self.s.setDTR(0)
cliechti7fc7da02009-08-03 23:49:02 +0000187 time.sleep(1.1)
cliechticb65c682008-06-22 22:47:02 +0000188 self.failUnless(not self.s.getDSR(), "DSR -> 0")
cliechtic813b212002-06-04 21:12:10 +0000189 self.s.setDTR(1)
cliechti7fc7da02009-08-03 23:49:02 +0000190 time.sleep(1.1)
cliechticb65c682008-06-22 22:47:02 +0000191 self.failUnless(self.s.getDSR(), "DSR -> 1")
cliechtic813b212002-06-04 21:12:10 +0000192
cliechtia135a672002-06-11 15:10:46 +0000193 def test3_RI(self):
194 """Test RI"""
cliechticb65c682008-06-22 22:47:02 +0000195 self.failUnless(not self.s.getRI(), "RI -> 0")
cliechtic813b212002-06-04 21:12:10 +0000196
cliechtif16c7702009-08-02 00:00:55 +0000197
cliechti62611612004-04-20 01:55:43 +0000198class Test_MoreTimeouts(unittest.TestCase):
199 """Test with timeouts"""
200 def setUp(self):
cliechtif16c7702009-08-02 00:00:55 +0000201 # create an closed serial port
cliechtie3ab3532009-08-05 12:40:38 +0000202 self.s = serial.serial_for_url(PORT, do_not_open=True)
cliechti58a3efe2009-07-21 20:56:52 +0000203
cliechti62611612004-04-20 01:55:43 +0000204 def tearDown(self):
Chris Liechtia6f0b762015-08-03 15:48:56 +0200205 #~ self.s.write(serial.XON)
Chris Liechtid73344d2015-08-06 17:52:51 +0200206 self.s.close()
207 # reopen... some faulty USB-serial adapter make next test fail otherwise...
208 self.s.timeout = 1
209 self.s.xonxoff = False
210 self.s.open()
211 self.s.read(10)
cliechti62611612004-04-20 01:55:43 +0000212 self.s.close()
213
214 def test_WriteTimeout(self):
215 """Test write() timeout."""
cliechti58a3efe2009-07-21 20:56:52 +0000216 # use xonxoff setting and the loop-back adapter to switch traffic on hold
cliechti62611612004-04-20 01:55:43 +0000217 self.s.port = PORT
Chris Liechtid73344d2015-08-06 17:52:51 +0200218 self.s.writeTimeout = True
219 self.s.xonxoff = True
cliechti62611612004-04-20 01:55:43 +0000220 self.s.open()
221 self.s.write(serial.XOFF)
cliechti58a3efe2009-07-21 20:56:52 +0000222 time.sleep(0.5) # some systems need a little delay so that they can react on XOFF
cliechti62611612004-04-20 01:55:43 +0000223 t1 = time.time()
cliechtie8f2b322009-08-07 00:18:42 +0000224 self.failUnlessRaises(serial.SerialTimeoutException, self.s.write, data("timeout please"*200))
cliechti62611612004-04-20 01:55:43 +0000225 t2 = time.time()
cliechti42007d32009-07-30 17:21:26 +0000226 self.failUnless( 0.9 <= (t2-t1) < 2.1, "Timeout not in the given interval (%s)" % (t2-t1))
227
cliechti62611612004-04-20 01:55:43 +0000228
cliechtic813b212002-06-04 21:12:10 +0000229if __name__ == '__main__':
cliechtia135a672002-06-11 15:10:46 +0000230 import sys
cliechti8f9e5772009-02-07 00:30:53 +0000231 sys.stdout.write(__doc__)
cliechti764c88c2008-06-24 11:56:48 +0000232 if len(sys.argv) > 1:
233 PORT = sys.argv[1]
cliechti58a3efe2009-07-21 20:56:52 +0000234 sys.stdout.write("Testing port: %r\n" % PORT)
cliechti764c88c2008-06-24 11:56:48 +0000235 sys.argv[1:] = ['-v']
cliechtid6bf52c2003-10-01 02:28:12 +0000236 # When this module is executed from the command-line, it runs all its tests
cliechtic813b212002-06-04 21:12:10 +0000237 unittest.main()