1+ from test import support
2+ # If we end up with a significant number of tests that don't require
3+ # threading, this test module should be split. Right now we skip
4+ # them all if we don't have threading.
5+ threading = support .import_module ('threading' )
6+
7+ from contextlib import contextmanager
18import imaplib
9+ import os .path
10+ import select
11+ import socket
12+ import socketserver
13+ import sys
214import time
315
4- from test import support
16+ from test . support import reap_threads , verbose
517import unittest
618
19+ try :
20+ import ssl
21+ except ImportError :
22+ ssl = None
23+
24+ CERTFILE = None
25+
726
827class TestImaplib (unittest .TestCase ):
28+
929 def test_that_Time2Internaldate_returns_a_result (self ):
1030 # We can check only that it successfully produces a result,
1131 # not the correctness of the result itself, since the result
@@ -17,9 +37,180 @@ def test_that_Time2Internaldate_returns_a_result(self):
1737 imaplib .Time2Internaldate (t )
1838
1939
40+ if ssl :
41+
42+ class SecureTCPServer (socketserver .TCPServer ):
43+
44+ def get_request (self ):
45+ newsocket , fromaddr = self .socket .accept ()
46+ connstream = ssl .wrap_socket (newsocket ,
47+ server_side = True ,
48+ certfile = CERTFILE )
49+ return connstream , fromaddr
50+
51+ IMAP4_SSL = imaplib .IMAP4_SSL
52+
53+ else :
54+
55+ class SecureTCPServer :
56+ pass
57+
58+ IMAP4_SSL = None
59+
60+
61+ class SimpleIMAPHandler (socketserver .StreamRequestHandler ):
62+
63+ timeout = 1
64+
65+ def _send (self , message ):
66+ if verbose : print ("SENT:" , message .strip ())
67+ self .wfile .write (message )
68+
69+ def handle (self ):
70+ # Send a welcome message.
71+ self ._send (b'* OK IMAP4rev1\r \n ' )
72+ while 1 :
73+ # Gather up input until we receive a line terminator or we timeout.
74+ # Accumulate read(1) because it's simpler to handle the differences
75+ # between naked sockets and SSL sockets.
76+ line = b''
77+ while 1 :
78+ try :
79+ part = self .rfile .read (1 )
80+ if part == b'' :
81+ # Naked sockets return empty strings..
82+ return
83+ line += part
84+ except IOError :
85+ # ..but SSLSockets throw exceptions.
86+ return
87+ if line .endswith (b'\r \n ' ):
88+ break
89+
90+ if verbose : print ('GOT:' , line .strip ())
91+ splitline = line .split ()
92+ tag = splitline [0 ].decode ('ASCII' )
93+ cmd = splitline [1 ].decode ('ASCII' )
94+ args = splitline [2 :]
95+
96+ if hasattr (self , 'cmd_' + cmd ):
97+ getattr (self , 'cmd_' + cmd )(tag , args )
98+ else :
99+ self ._send ('{} BAD {} unknown\r \n ' .format (tag , cmd ).encode ('ASCII' ))
100+
101+ def cmd_CAPABILITY (self , tag , args ):
102+ self ._send (b'* CAPABILITY IMAP4rev1\r \n ' )
103+ self ._send ('{} OK CAPABILITY completed\r \n ' .format (tag ).encode ('ASCII' ))
104+
105+
106+ class BaseThreadedNetworkedTests (unittest .TestCase ):
107+
108+ def make_server (self , addr , hdlr ):
109+
110+ class MyServer (self .server_class ):
111+ def handle_error (self , request , client_address ):
112+ self .close_request (request )
113+ self .server_close ()
114+ raise
115+
116+ if verbose : print ("creating server" )
117+ server = MyServer (addr , hdlr )
118+ self .assertEquals (server .server_address , server .socket .getsockname ())
119+
120+ if verbose :
121+ print ("server created" )
122+ print ("ADDR =" , addr )
123+ print ("CLASS =" , self .server_class )
124+ print ("HDLR =" , server .RequestHandlerClass )
125+
126+ t = threading .Thread (
127+ name = '%s serving' % self .server_class ,
128+ target = server .serve_forever ,
129+ # Short poll interval to make the test finish quickly.
130+ # Time between requests is short enough that we won't wake
131+ # up spuriously too many times.
132+ kwargs = {'poll_interval' :0.01 })
133+ t .daemon = True # In case this function raises.
134+ t .start ()
135+ if verbose : print ("server running" )
136+ return server , t
137+
138+ def reap_server (self , server , thread ):
139+ if verbose : print ("waiting for server" )
140+ server .shutdown ()
141+ thread .join ()
142+ if verbose : print ("done" )
143+
144+ @contextmanager
145+ def reaped_server (self , hdlr ):
146+ server , thread = self .make_server ((support .HOST , 0 ), hdlr )
147+ try :
148+ yield server
149+ finally :
150+ self .reap_server (server , thread )
151+
152+ @reap_threads
153+ def test_connect (self ):
154+ with self .reaped_server (SimpleIMAPHandler ) as server :
155+ client = self .imap_class (* server .server_address )
156+ client .shutdown ()
157+
158+ @reap_threads
159+ def test_issue5949 (self ):
160+
161+ class EOFHandler (socketserver .StreamRequestHandler ):
162+ def handle (self ):
163+ # EOF without sending a complete welcome message.
164+ self .wfile .write (b'* OK' )
165+
166+ with self .reaped_server (EOFHandler ) as server :
167+ self .assertRaises (imaplib .IMAP4 .abort ,
168+ self .imap_class , * server .server_address )
169+
170+ @reap_threads
171+ def test_line_termination (self ):
172+
173+ class BadNewlineHandler (SimpleIMAPHandler ):
174+
175+ def cmd_CAPABILITY (self , tag , args ):
176+ self ._send (b'* CAPABILITY IMAP4rev1 AUTH\n ' )
177+ self ._send ('{} OK CAPABILITY completed\r \n ' .format (tag ).encode ('ASCII' ))
178+
179+ with self .reaped_server (BadNewlineHandler ) as server :
180+ self .assertRaises (imaplib .IMAP4 .abort ,
181+ self .imap_class , * server .server_address )
182+
183+
184+
185+ class ThreadedNetworkedTests (BaseThreadedNetworkedTests ):
186+
187+ server_class = socketserver .TCPServer
188+ imap_class = imaplib .IMAP4
189+
190+
191+ @unittest .skipUnless (ssl , "SSL not available" )
192+ class ThreadedNetworkedTestsSSL (BaseThreadedNetworkedTests ):
193+
194+ server_class = SecureTCPServer
195+ imap_class = IMAP4_SSL
196+
197+
20198def test_main ():
21- support .run_unittest (TestImaplib )
199+
200+ tests = [TestImaplib ]
201+
202+ if support .is_resource_enabled ('network' ):
203+ if ssl :
204+ global CERTFILE
205+ CERTFILE = os .path .join (os .path .dirname (__file__ ) or os .curdir ,
206+ "keycert.pem" )
207+ if not os .path .exists (CERTFILE ):
208+ raise support .TestFailed ("Can't read certificate files!" )
209+ tests .extend ([ThreadedNetworkedTests , ThreadedNetworkedTestsSSL ])
210+
211+ support .run_unittest (* tests )
22212
23213
24214if __name__ == "__main__" :
25- unittest .main ()
215+ support .use_resources = ['network' ]
216+ test_main ()
0 commit comments