blob: db03907eaa0e605f88cc356c406cbc0da29d6fa2 [file] [log] [blame]
cliechticb65c682008-06-22 22:47:02 +00001#! /usr/bin/env python
cliechtid6bf52c2003-10-01 02:28:12 +00002#
Chris Liechti7c032f12015-10-27 23:02:00 +01003# This file is part of pySerial - Cross platform serial port support for Python
Chris Liechtid73344d2015-08-06 17:52:51 +02004# (C) 2001-2015 Chris Liechti <cliechti@gmx.net>
Chris Liechti7c032f12015-10-27 23:02:00 +01005#
6# SPDX-License-Identifier: BSD-3-Clause
cliechticb65c682008-06-22 22:47:02 +00007"""\
8Some tests for the serial module.
Chris Liechtid73344d2015-08-06 17:52:51 +02009Part of pyserial (http://pyserial.sf.net) (C)2001-2015 cliechti@gmx.net
cliechtid6bf52c2003-10-01 02:28:12 +000010
11Intended to be run on different platforms, to ensure portability of
cliechti1e95baa2002-06-04 22:46:50 +000012the code.
13
cliechtid6bf52c2003-10-01 02:28:12 +000014For all these tests a simple hardware is required.
cliechti1e95baa2002-06-04 22:46:50 +000015Loopback HW adapter:
cliechtid6bf52c2003-10-01 02:28:12 +000016Shortcut these pin pairs:
cliechtia135a672002-06-11 15:10:46 +000017 TX <-> RX
18 RTS <-> CTS
19 DTR <-> DSR
cliechti1e95baa2002-06-04 22:46:50 +000020
cliechtid6bf52c2003-10-01 02:28:12 +000021On a 9 pole DSUB these are the pins (2-3) (4-6) (7-8)
cliechti1e95baa2002-06-04 22:46:50 +000022"""
23
cliechtif16c7702009-08-02 00:00:55 +000024import unittest
25import threading
26import time
cliechtia75900c2009-07-28 00:12:52 +000027import sys
cliechti1e95baa2002-06-04 22:46:50 +000028import serial
cliechtic813b212002-06-04 21:12:10 +000029
cliechti58a3efe2009-07-21 20:56:52 +000030# on which port should the tests be performed:
Chris Liechti6ed12e02015-09-18 21:23:42 +020031PORT = 'loop://'
cliechtic813b212002-06-04 21:12:10 +000032
Chris Liechti6ed12e02015-09-18 21:23:42 +020033# indirection via bytearray b/c bytes(range(256)) does something else in Pyhton 2.7
34bytes_0to255 = bytes(bytearray(range(256)))
cliechti54c534e2009-08-06 23:24:26 +000035
36
37def segments(data, size=16):
38 for a in range(0, len(data), size):
Chris Liechti8e37ba92016-02-03 01:22:22 +010039 yield data[a:a + size]
cliechtia75900c2009-07-28 00:12:52 +000040
cliechtic813b212002-06-04 21:12:10 +000041
cliechtia135a672002-06-11 15:10:46 +000042class Test4_Nonblocking(unittest.TestCase):
cliechtic813b212002-06-04 21:12:10 +000043 """Test with timeouts"""
cliechtia75900c2009-07-28 00:12:52 +000044 timeout = 0
45
cliechtic813b212002-06-04 21:12:10 +000046 def setUp(self):
cliechtie3ab3532009-08-05 12:40:38 +000047 self.s = serial.serial_for_url(PORT, timeout=self.timeout)
cliechti58a3efe2009-07-21 20:56:52 +000048
cliechtic813b212002-06-04 21:12:10 +000049 def tearDown(self):
50 self.s.close()
51
cliechtia135a672002-06-11 15:10:46 +000052 def test0_Messy(self):
53 """NonBlocking (timeout=0)"""
cliechti58a3efe2009-07-21 20:56:52 +000054 # this is only here to write out the message in verbose mode
55 # because Test3 and Test4 print the same messages
cliechtia135a672002-06-11 15:10:46 +000056
cliechtic813b212002-06-04 21:12:10 +000057 def test1_ReadEmpty(self):
cliechtia135a672002-06-11 15:10:46 +000058 """timeout: After port open, the input buffer must be empty"""
Chris Liechtidedd3b72015-12-11 20:44:22 +010059 self.assertEqual(self.s.read(1), b'', "expected empty buffer")
cliechti58a3efe2009-07-21 20:56:52 +000060
cliechtic813b212002-06-04 21:12:10 +000061 def test2_Loopback(self):
cliechtia135a672002-06-11 15:10:46 +000062 """timeout: each sent character should return (binary test).
cliechti1e95baa2002-06-04 22:46:50 +000063 this is also a test for the binary capability of a port."""
cliechti54c534e2009-08-06 23:24:26 +000064 for block in segments(bytes_0to255):
65 length = len(block)
66 self.s.write(block)
cliechtia75900c2009-07-28 00:12:52 +000067 # there might be a small delay until the character is ready (especially on win32)
cliechtif16c7702009-08-02 00:00:55 +000068 time.sleep(0.05)
Chris Liechti3debab22016-06-20 22:52:22 +020069 self.assertEqual(self.s.in_waiting, length, "expected exactly {} character for inWainting()".format(length))
Chris Liechti8e37ba92016-02-03 01:22:22 +010070 self.assertEqual(self.s.read(length), block) #, "expected a %r which was written before" % block)
Chris Liechtidedd3b72015-12-11 20:44:22 +010071 self.assertEqual(self.s.read(1), b'', "expected empty buffer after all sent chars are read")
cliechti58a3efe2009-07-21 20:56:52 +000072
cliechtic813b212002-06-04 21:12:10 +000073 def test2_LoopbackTimeout(self):
cliechtia135a672002-06-11 15:10:46 +000074 """timeout: test the timeout/immediate return.
75 partial results should be returned."""
Chris Liechti6ed12e02015-09-18 21:23:42 +020076 self.s.write(b"HELLO")
cliechtif16c7702009-08-02 00:00:55 +000077 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 +000078 # read more characters as are available to run in the timeout
Chris Liechtidedd3b72015-12-11 20:44:22 +010079 self.assertEqual(self.s.read(10), b'HELLO', "expected the 'HELLO' which was written before")
80 self.assertEqual(self.s.read(1), b'', "expected empty buffer after all sent chars are read")
cliechtic813b212002-06-04 21:12:10 +000081
82
cliechtia135a672002-06-11 15:10:46 +000083class Test3_Timeout(Test4_Nonblocking):
cliechtic813b212002-06-04 21:12:10 +000084 """Same tests as the NonBlocking ones but this time with timeout"""
cliechtia75900c2009-07-28 00:12:52 +000085 timeout = 1
cliechti58a3efe2009-07-21 20:56:52 +000086
cliechtia135a672002-06-11 15:10:46 +000087 def test0_Messy(self):
88 """Blocking (timeout=1)"""
cliechti58a3efe2009-07-21 20:56:52 +000089 # this is only here to write out the message in verbose mode
90 # because Test3 and Test4 print the same messages
cliechtic813b212002-06-04 21:12:10 +000091
cliechtif16c7702009-08-02 00:00:55 +000092
cliechti1e95baa2002-06-04 22:46:50 +000093class SendEvent(threading.Thread):
cliechtif16c7702009-08-02 00:00:55 +000094 def __init__(self, serial, delay=3):
cliechti1e95baa2002-06-04 22:46:50 +000095 threading.Thread.__init__(self)
96 self.serial = serial
97 self.delay = delay
98 self.x = threading.Event()
99 self.stopped = 0
100 self.start()
cliechti58a3efe2009-07-21 20:56:52 +0000101
cliechti1e95baa2002-06-04 22:46:50 +0000102 def run(self):
103 time.sleep(self.delay)
cliechti8b599c92011-08-15 13:12:09 +0000104 self.x.set()
cliechti1e95baa2002-06-04 22:46:50 +0000105 if not self.stopped:
Chris Liechti6ed12e02015-09-18 21:23:42 +0200106 self.serial.write(b"E")
cliechti7fc7da02009-08-03 23:49:02 +0000107 self.serial.flush()
cliechti58a3efe2009-07-21 20:56:52 +0000108
cliechti1e95baa2002-06-04 22:46:50 +0000109 def isSet(self):
110 return self.x.isSet()
cliechti58a3efe2009-07-21 20:56:52 +0000111
cliechti1e95baa2002-06-04 22:46:50 +0000112 def stop(self):
113 self.stopped = 1
114 self.x.wait()
115
Chris Liechti8e37ba92016-02-03 01:22:22 +0100116
cliechti1e95baa2002-06-04 22:46:50 +0000117class Test1_Forever(unittest.TestCase):
118 """Tests a port with no timeout. These tests require that a
119 character is sent after some time to stop the test, this is done
120 through the SendEvent class and the Loopback HW."""
121 def setUp(self):
cliechtie3ab3532009-08-05 12:40:38 +0000122 self.s = serial.serial_for_url(PORT, timeout=None)
cliechti1e95baa2002-06-04 22:46:50 +0000123 self.event = SendEvent(self.s)
cliechti58a3efe2009-07-21 20:56:52 +0000124
cliechti1e95baa2002-06-04 22:46:50 +0000125 def tearDown(self):
126 self.event.stop()
127 self.s.close()
128
129 def test2_ReadEmpty(self):
cliechtia135a672002-06-11 15:10:46 +0000130 """no timeout: after port open, the input buffer must be empty (read).
131 a character is sent after some time to terminate the test (SendEvent)."""
cliechti1e95baa2002-06-04 22:46:50 +0000132 c = self.s.read(1)
Chris Liechti6ed12e02015-09-18 21:23:42 +0200133 if not (self.event.isSet() and c == b'E'):
Chris Liechti3debab22016-06-20 22:52:22 +0200134 self.fail("expected marker (evt={!r}, c={!r})".format(self.event.isSet(), c))
cliechti1e95baa2002-06-04 22:46:50 +0000135
cliechtif16c7702009-08-02 00:00:55 +0000136
cliechti1e95baa2002-06-04 22:46:50 +0000137class Test2_Forever(unittest.TestCase):
138 """Tests a port with no timeout"""
139 def setUp(self):
cliechtie3ab3532009-08-05 12:40:38 +0000140 self.s = serial.serial_for_url(PORT, timeout=None)
cliechti58a3efe2009-07-21 20:56:52 +0000141
cliechti1e95baa2002-06-04 22:46:50 +0000142 def tearDown(self):
143 self.s.close()
144
145 def test1_inWaitingEmpty(self):
Chris Liechti20ed5fd2015-09-02 02:48:51 +0200146 """no timeout: after port open, the input buffer must be empty (in_waiting)"""
Chris Liechtidedd3b72015-12-11 20:44:22 +0100147 self.assertEqual(self.s.in_waiting, 0, "expected empty buffer")
cliechti1e95baa2002-06-04 22:46:50 +0000148
149 def test2_Loopback(self):
cliechtia135a672002-06-11 15:10:46 +0000150 """no timeout: each sent character should return (binary test).
cliechti1e95baa2002-06-04 22:46:50 +0000151 this is also a test for the binary capability of a port."""
cliechti54c534e2009-08-06 23:24:26 +0000152 for block in segments(bytes_0to255):
153 length = len(block)
154 self.s.write(block)
cliechtif16c7702009-08-02 00:00:55 +0000155 # there might be a small delay until the character is ready (especially on win32 and rfc2217)
156 time.sleep(0.05)
Chris Liechti8e37ba92016-02-03 01:22:22 +0100157 self.assertEqual(self.s.in_waiting, length) #, "expected exactly %d character for inWainting()" % length)
158 self.assertEqual(self.s.read(length), block) #, "expected %r which was written before" % block)
Chris Liechtidedd3b72015-12-11 20:44:22 +0100159 self.assertEqual(self.s.in_waiting, 0, "expected empty buffer after all sent chars are read")
cliechtic813b212002-06-04 21:12:10 +0000160
161
cliechtia135a672002-06-11 15:10:46 +0000162class Test0_DataWires(unittest.TestCase):
cliechtic813b212002-06-04 21:12:10 +0000163 """Test modem control lines"""
164 def setUp(self):
cliechtie3ab3532009-08-05 12:40:38 +0000165 self.s = serial.serial_for_url(PORT)
cliechti58a3efe2009-07-21 20:56:52 +0000166
cliechtic813b212002-06-04 21:12:10 +0000167 def tearDown(self):
168 self.s.close()
169
170 def test1_RTS(self):
cliechtia135a672002-06-11 15:10:46 +0000171 """Test RTS/CTS"""
Chris Liechti20ed5fd2015-09-02 02:48:51 +0200172 self.s.rts = False
cliechti7fc7da02009-08-03 23:49:02 +0000173 time.sleep(1.1)
Chris Liechtidedd3b72015-12-11 20:44:22 +0100174 self.assertTrue(not self.s.cts, "CTS -> 0")
Chris Liechti20ed5fd2015-09-02 02:48:51 +0200175 self.s.rts = True
cliechti7fc7da02009-08-03 23:49:02 +0000176 time.sleep(1.1)
Chris Liechtidedd3b72015-12-11 20:44:22 +0100177 self.assertTrue(self.s.cts, "CTS -> 1")
cliechtic813b212002-06-04 21:12:10 +0000178
179 def test2_DTR(self):
cliechtia135a672002-06-11 15:10:46 +0000180 """Test DTR/DSR"""
Chris Liechti20ed5fd2015-09-02 02:48:51 +0200181 self.s.dtr = False
cliechti7fc7da02009-08-03 23:49:02 +0000182 time.sleep(1.1)
Chris Liechtidedd3b72015-12-11 20:44:22 +0100183 self.assertTrue(not self.s.dsr, "DSR -> 0")
Chris Liechti20ed5fd2015-09-02 02:48:51 +0200184 self.s.dtr = True
cliechti7fc7da02009-08-03 23:49:02 +0000185 time.sleep(1.1)
Chris Liechtidedd3b72015-12-11 20:44:22 +0100186 self.assertTrue(self.s.dsr, "DSR -> 1")
cliechtic813b212002-06-04 21:12:10 +0000187
cliechtia135a672002-06-11 15:10:46 +0000188 def test3_RI(self):
189 """Test RI"""
Chris Liechtidedd3b72015-12-11 20:44:22 +0100190 self.assertTrue(not self.s.ri, "RI -> 0")
cliechtic813b212002-06-04 21:12:10 +0000191
cliechtif16c7702009-08-02 00:00:55 +0000192
cliechti62611612004-04-20 01:55:43 +0000193class Test_MoreTimeouts(unittest.TestCase):
194 """Test with timeouts"""
195 def setUp(self):
cliechtif16c7702009-08-02 00:00:55 +0000196 # create an closed serial port
cliechtie3ab3532009-08-05 12:40:38 +0000197 self.s = serial.serial_for_url(PORT, do_not_open=True)
cliechti58a3efe2009-07-21 20:56:52 +0000198
cliechti62611612004-04-20 01:55:43 +0000199 def tearDown(self):
Chris Liechtif89cf8e2016-05-22 20:50:59 +0200200 self.s.reset_output_buffer()
201 self.s.flush()
Chris Liechtia6f0b762015-08-03 15:48:56 +0200202 #~ self.s.write(serial.XON)
Chris Liechtid73344d2015-08-06 17:52:51 +0200203 self.s.close()
204 # reopen... some faulty USB-serial adapter make next test fail otherwise...
205 self.s.timeout = 1
206 self.s.xonxoff = False
207 self.s.open()
Chris Liechtif89cf8e2016-05-22 20:50:59 +0200208 self.s.read(3000)
cliechti62611612004-04-20 01:55:43 +0000209 self.s.close()
210
211 def test_WriteTimeout(self):
212 """Test write() timeout."""
cliechti58a3efe2009-07-21 20:56:52 +0000213 # use xonxoff setting and the loop-back adapter to switch traffic on hold
cliechti62611612004-04-20 01:55:43 +0000214 self.s.port = PORT
Chris Liechtif89cf8e2016-05-22 20:50:59 +0200215 self.s.write_timeout = 1.0
Chris Liechtid73344d2015-08-06 17:52:51 +0200216 self.s.xonxoff = True
cliechti62611612004-04-20 01:55:43 +0000217 self.s.open()
218 self.s.write(serial.XOFF)
Chris Liechti8e37ba92016-02-03 01:22:22 +0100219 time.sleep(0.5) # some systems need a little delay so that they can react on XOFF
cliechti62611612004-04-20 01:55:43 +0000220 t1 = time.time()
Chris Liechti8e37ba92016-02-03 01:22:22 +0100221 self.assertRaises(serial.SerialTimeoutException, self.s.write, b"timeout please" * 200)
cliechti62611612004-04-20 01:55:43 +0000222 t2 = time.time()
Chris Liechti3debab22016-06-20 22:52:22 +0200223 self.assertTrue(0.9 <= (t2 - t1) < 2.1, "Timeout not in the given interval ({})".format(t2 - t1))
cliechti42007d32009-07-30 17:21:26 +0000224
cliechti62611612004-04-20 01:55:43 +0000225
cliechtic813b212002-06-04 21:12:10 +0000226if __name__ == '__main__':
cliechti8f9e5772009-02-07 00:30:53 +0000227 sys.stdout.write(__doc__)
cliechti764c88c2008-06-24 11:56:48 +0000228 if len(sys.argv) > 1:
229 PORT = sys.argv[1]
Chris Liechti3debab22016-06-20 22:52:22 +0200230 sys.stdout.write("Testing port: {!r}\n".format(PORT))
cliechti764c88c2008-06-24 11:56:48 +0000231 sys.argv[1:] = ['-v']
cliechtid6bf52c2003-10-01 02:28:12 +0000232 # When this module is executed from the command-line, it runs all its tests
cliechtic813b212002-06-04 21:12:10 +0000233 unittest.main()