blob: 0696fef586cb0ef44cc49f5e10a182618e9b4cad [file] [log] [blame]
Fred Drake0aaed272000-10-23 13:39:15 +00001import os
Neal Norwitz003c9e22006-08-11 06:09:41 +00002import sys
Fred Drakec02bc3e2001-05-21 20:23:21 +00003import time
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00004import stat
5import socket
6import email
Georg Brandl5a096e12007-01-22 19:40:21 +00007import email.message
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00008import re
Vinay Sajipda563bf2012-03-06 20:07:15 +00009import shutil
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +000010import StringIO
Petri Lehtinen2d44cee2012-08-15 14:22:46 +030011import tempfile
Barry Warsaw04f357c2002-07-23 19:04:11 +000012from test import test_support
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +000013import unittest
14import mailbox
15import glob
Guido van Rossum75ebb292001-04-10 15:01:20 +000016try:
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +000017 import fcntl
18except ImportError:
Guido van Rossum75ebb292001-04-10 15:01:20 +000019 pass
20
Ezio Melottia2d46532010-01-30 07:22:54 +000021# Silence Py3k warning
22rfc822 = test_support.import_module('rfc822', deprecated=True)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +000023
R David Murray088a8742012-04-08 18:34:36 -040024class TestBase:
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +000025
26 def _check_sample(self, msg):
27 # Inspect a mailbox.Message representation of the sample message
Antoine Pitrou0da5cb82009-10-31 23:19:52 +000028 self.assertIsInstance(msg, email.message.Message)
29 self.assertIsInstance(msg, mailbox.Message)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +000030 for key, value in _sample_headers.iteritems():
Antoine Pitrou0da5cb82009-10-31 23:19:52 +000031 self.assertIn(value, msg.get_all(key))
Benjamin Peterson5c8da862009-06-30 22:57:08 +000032 self.assertTrue(msg.is_multipart())
Antoine Pitrou0da5cb82009-10-31 23:19:52 +000033 self.assertEqual(len(msg.get_payload()), len(_sample_payloads))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +000034 for i, payload in enumerate(_sample_payloads):
35 part = msg.get_payload(i)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +000036 self.assertIsInstance(part, email.message.Message)
37 self.assertNotIsInstance(part, mailbox.Message)
38 self.assertEqual(part.get_payload(), payload)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +000039
40 def _delete_recursively(self, target):
41 # Delete a file or delete a directory recursively
42 if os.path.isdir(target):
Vinay Sajipda563bf2012-03-06 20:07:15 +000043 shutil.rmtree(target)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +000044 elif os.path.exists(target):
45 os.remove(target)
46
47
48class TestMailbox(TestBase):
49
50 _factory = None # Overridden by subclasses to reuse tests
Petri Lehtinenec2807c2012-09-25 21:48:51 +030051 _template = 'From: foo\n\n%s\n'
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +000052
53 def setUp(self):
54 self._path = test_support.TESTFN
Neal Norwitzb0a7d4e2007-03-20 06:16:26 +000055 self._delete_recursively(self._path)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +000056 self._box = self._factory(self._path)
57
58 def tearDown(self):
59 self._box.close()
60 self._delete_recursively(self._path)
61
62 def test_add(self):
63 # Add copies of a sample message
64 keys = []
65 keys.append(self._box.add(self._template % 0))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +000066 self.assertEqual(len(self._box), 1)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +000067 keys.append(self._box.add(mailbox.Message(_sample_message)))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +000068 self.assertEqual(len(self._box), 2)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +000069 keys.append(self._box.add(email.message_from_string(_sample_message)))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +000070 self.assertEqual(len(self._box), 3)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +000071 keys.append(self._box.add(StringIO.StringIO(_sample_message)))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +000072 self.assertEqual(len(self._box), 4)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +000073 keys.append(self._box.add(_sample_message))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +000074 self.assertEqual(len(self._box), 5)
75 self.assertEqual(self._box.get_string(keys[0]), self._template % 0)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +000076 for i in (1, 2, 3, 4):
77 self._check_sample(self._box[keys[i]])
78
Petri Lehtinen2d44cee2012-08-15 14:22:46 +030079 def test_add_file(self):
80 with tempfile.TemporaryFile('w+') as f:
81 f.write(_sample_message)
82 f.seek(0)
83 key = self._box.add(f)
84 self.assertEqual(self._box.get_string(key).split('\n'),
85 _sample_message.split('\n'))
86
87 def test_add_StringIO(self):
88 key = self._box.add(StringIO.StringIO(self._template % "0"))
89 self.assertEqual(self._box.get_string(key), self._template % "0")
90
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +000091 def test_remove(self):
92 # Remove messages using remove()
93 self._test_remove_or_delitem(self._box.remove)
94
95 def test_delitem(self):
96 # Remove messages using __delitem__()
97 self._test_remove_or_delitem(self._box.__delitem__)
98
99 def _test_remove_or_delitem(self, method):
100 # (Used by test_remove() and test_delitem().)
101 key0 = self._box.add(self._template % 0)
102 key1 = self._box.add(self._template % 1)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000103 self.assertEqual(len(self._box), 2)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000104 method(key0)
105 l = len(self._box)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000106 self.assertEqual(l, 1)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000107 self.assertRaises(KeyError, lambda: self._box[key0])
108 self.assertRaises(KeyError, lambda: method(key0))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000109 self.assertEqual(self._box.get_string(key1), self._template % 1)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000110 key2 = self._box.add(self._template % 2)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000111 self.assertEqual(len(self._box), 2)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000112 method(key2)
113 l = len(self._box)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000114 self.assertEqual(l, 1)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000115 self.assertRaises(KeyError, lambda: self._box[key2])
116 self.assertRaises(KeyError, lambda: method(key2))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000117 self.assertEqual(self._box.get_string(key1), self._template % 1)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000118 method(key1)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000119 self.assertEqual(len(self._box), 0)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000120 self.assertRaises(KeyError, lambda: self._box[key1])
121 self.assertRaises(KeyError, lambda: method(key1))
122
123 def test_discard(self, repetitions=10):
124 # Discard messages
125 key0 = self._box.add(self._template % 0)
126 key1 = self._box.add(self._template % 1)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000127 self.assertEqual(len(self._box), 2)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000128 self._box.discard(key0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000129 self.assertEqual(len(self._box), 1)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000130 self.assertRaises(KeyError, lambda: self._box[key0])
131 self._box.discard(key0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000132 self.assertEqual(len(self._box), 1)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000133 self.assertRaises(KeyError, lambda: self._box[key0])
134
135 def test_get(self):
136 # Retrieve messages using get()
137 key0 = self._box.add(self._template % 0)
138 msg = self._box.get(key0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000139 self.assertEqual(msg['from'], 'foo')
Petri Lehtinenec2807c2012-09-25 21:48:51 +0300140 self.assertEqual(msg.get_payload(), '0\n')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000141 self.assertIs(self._box.get('foo'), None)
142 self.assertFalse(self._box.get('foo', False))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000143 self._box.close()
144 self._box = self._factory(self._path, factory=rfc822.Message)
145 key1 = self._box.add(self._template % 1)
146 msg = self._box.get(key1)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000147 self.assertEqual(msg['from'], 'foo')
Petri Lehtinenfb2e8a72012-09-26 07:41:11 +0300148 self.assertEqual(msg.fp.read(), '1' + os.linesep)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000149
150 def test_getitem(self):
151 # Retrieve message using __getitem__()
152 key0 = self._box.add(self._template % 0)
153 msg = self._box[key0]
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000154 self.assertEqual(msg['from'], 'foo')
Petri Lehtinenec2807c2012-09-25 21:48:51 +0300155 self.assertEqual(msg.get_payload(), '0\n')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000156 self.assertRaises(KeyError, lambda: self._box['foo'])
157 self._box.discard(key0)
158 self.assertRaises(KeyError, lambda: self._box[key0])
159
160 def test_get_message(self):
161 # Get Message representations of messages
162 key0 = self._box.add(self._template % 0)
163 key1 = self._box.add(_sample_message)
164 msg0 = self._box.get_message(key0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000165 self.assertIsInstance(msg0, mailbox.Message)
166 self.assertEqual(msg0['from'], 'foo')
Petri Lehtinenec2807c2012-09-25 21:48:51 +0300167 self.assertEqual(msg0.get_payload(), '0\n')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000168 self._check_sample(self._box.get_message(key1))
169
170 def test_get_string(self):
171 # Get string representations of messages
172 key0 = self._box.add(self._template % 0)
173 key1 = self._box.add(_sample_message)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000174 self.assertEqual(self._box.get_string(key0), self._template % 0)
175 self.assertEqual(self._box.get_string(key1), _sample_message)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000176
177 def test_get_file(self):
178 # Get file representations of messages
179 key0 = self._box.add(self._template % 0)
180 key1 = self._box.add(_sample_message)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000181 self.assertEqual(self._box.get_file(key0).read().replace(os.linesep, '\n'),
182 self._template % 0)
183 self.assertEqual(self._box.get_file(key1).read().replace(os.linesep, '\n'),
184 _sample_message)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000185
R David Murrayf1138bb2011-06-17 22:23:04 -0400186 def test_get_file_can_be_closed_twice(self):
187 # Issue 11700
188 key = self._box.add(_sample_message)
189 f = self._box.get_file(key)
190 f.close()
191 f.close()
192
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000193 def test_iterkeys(self):
194 # Get keys using iterkeys()
195 self._check_iteration(self._box.iterkeys, do_keys=True, do_values=False)
196
197 def test_keys(self):
198 # Get keys using keys()
199 self._check_iteration(self._box.keys, do_keys=True, do_values=False)
200
201 def test_itervalues(self):
202 # Get values using itervalues()
203 self._check_iteration(self._box.itervalues, do_keys=False,
204 do_values=True)
205
206 def test_iter(self):
207 # Get values using __iter__()
208 self._check_iteration(self._box.__iter__, do_keys=False,
209 do_values=True)
210
211 def test_values(self):
212 # Get values using values()
213 self._check_iteration(self._box.values, do_keys=False, do_values=True)
214
215 def test_iteritems(self):
216 # Get keys and values using iteritems()
217 self._check_iteration(self._box.iteritems, do_keys=True,
218 do_values=True)
219
220 def test_items(self):
221 # Get keys and values using items()
222 self._check_iteration(self._box.items, do_keys=True, do_values=True)
223
224 def _check_iteration(self, method, do_keys, do_values, repetitions=10):
225 for value in method():
226 self.fail("Not empty")
227 keys, values = [], []
228 for i in xrange(repetitions):
229 keys.append(self._box.add(self._template % i))
230 values.append(self._template % i)
231 if do_keys and not do_values:
232 returned_keys = list(method())
233 elif do_values and not do_keys:
234 returned_values = list(method())
235 else:
236 returned_keys, returned_values = [], []
237 for key, value in method():
238 returned_keys.append(key)
239 returned_values.append(value)
240 if do_keys:
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000241 self.assertEqual(len(keys), len(returned_keys))
242 self.assertEqual(set(keys), set(returned_keys))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000243 if do_values:
244 count = 0
245 for value in returned_values:
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000246 self.assertEqual(value['from'], 'foo')
247 self.assertTrue(int(value.get_payload()) < repetitions,
248 (value.get_payload(), repetitions))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000249 count += 1
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000250 self.assertEqual(len(values), count)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000251
252 def test_has_key(self):
253 # Check existence of keys using has_key()
254 self._test_has_key_or_contains(self._box.has_key)
255
256 def test_contains(self):
257 # Check existence of keys using __contains__()
258 self._test_has_key_or_contains(self._box.__contains__)
259
260 def _test_has_key_or_contains(self, method):
261 # (Used by test_has_key() and test_contains().)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000262 self.assertFalse(method('foo'))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000263 key0 = self._box.add(self._template % 0)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000264 self.assertTrue(method(key0))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000265 self.assertFalse(method('foo'))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000266 key1 = self._box.add(self._template % 1)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000267 self.assertTrue(method(key1))
268 self.assertTrue(method(key0))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000269 self.assertFalse(method('foo'))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000270 self._box.remove(key0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000271 self.assertFalse(method(key0))
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000272 self.assertTrue(method(key1))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000273 self.assertFalse(method('foo'))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000274 self._box.remove(key1)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000275 self.assertFalse(method(key1))
276 self.assertFalse(method(key0))
277 self.assertFalse(method('foo'))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000278
279 def test_len(self, repetitions=10):
280 # Get message count
281 keys = []
282 for i in xrange(repetitions):
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000283 self.assertEqual(len(self._box), i)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000284 keys.append(self._box.add(self._template % i))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000285 self.assertEqual(len(self._box), i + 1)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000286 for i in xrange(repetitions):
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000287 self.assertEqual(len(self._box), repetitions - i)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000288 self._box.remove(keys[i])
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000289 self.assertEqual(len(self._box), repetitions - i - 1)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000290
291 def test_set_item(self):
292 # Modify messages using __setitem__()
293 key0 = self._box.add(self._template % 'original 0')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000294 self.assertEqual(self._box.get_string(key0),
295 self._template % 'original 0')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000296 key1 = self._box.add(self._template % 'original 1')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000297 self.assertEqual(self._box.get_string(key1),
298 self._template % 'original 1')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000299 self._box[key0] = self._template % 'changed 0'
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000300 self.assertEqual(self._box.get_string(key0),
301 self._template % 'changed 0')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000302 self._box[key1] = self._template % 'changed 1'
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000303 self.assertEqual(self._box.get_string(key1),
304 self._template % 'changed 1')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000305 self._box[key0] = _sample_message
306 self._check_sample(self._box[key0])
307 self._box[key1] = self._box[key0]
308 self._check_sample(self._box[key1])
309 self._box[key0] = self._template % 'original 0'
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000310 self.assertEqual(self._box.get_string(key0),
311 self._template % 'original 0')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000312 self._check_sample(self._box[key1])
313 self.assertRaises(KeyError,
314 lambda: self._box.__setitem__('foo', 'bar'))
315 self.assertRaises(KeyError, lambda: self._box['foo'])
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000316 self.assertEqual(len(self._box), 2)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000317
318 def test_clear(self, iterations=10):
319 # Remove all messages using clear()
320 keys = []
321 for i in xrange(iterations):
322 self._box.add(self._template % i)
323 for i, key in enumerate(keys):
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000324 self.assertEqual(self._box.get_string(key), self._template % i)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000325 self._box.clear()
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000326 self.assertEqual(len(self._box), 0)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000327 for i, key in enumerate(keys):
328 self.assertRaises(KeyError, lambda: self._box.get_string(key))
329
330 def test_pop(self):
331 # Get and remove a message using pop()
332 key0 = self._box.add(self._template % 0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000333 self.assertIn(key0, self._box)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000334 key1 = self._box.add(self._template % 1)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000335 self.assertIn(key1, self._box)
Petri Lehtinenec2807c2012-09-25 21:48:51 +0300336 self.assertEqual(self._box.pop(key0).get_payload(), '0\n')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000337 self.assertNotIn(key0, self._box)
338 self.assertIn(key1, self._box)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000339 key2 = self._box.add(self._template % 2)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000340 self.assertIn(key2, self._box)
Petri Lehtinenec2807c2012-09-25 21:48:51 +0300341 self.assertEqual(self._box.pop(key2).get_payload(), '2\n')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000342 self.assertNotIn(key2, self._box)
343 self.assertIn(key1, self._box)
Petri Lehtinenec2807c2012-09-25 21:48:51 +0300344 self.assertEqual(self._box.pop(key1).get_payload(), '1\n')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000345 self.assertNotIn(key1, self._box)
346 self.assertEqual(len(self._box), 0)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000347
348 def test_popitem(self, iterations=10):
349 # Get and remove an arbitrary (key, message) using popitem()
350 keys = []
351 for i in xrange(10):
352 keys.append(self._box.add(self._template % i))
353 seen = []
354 for i in xrange(10):
355 key, msg = self._box.popitem()
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000356 self.assertIn(key, keys)
357 self.assertNotIn(key, seen)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000358 seen.append(key)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000359 self.assertEqual(int(msg.get_payload()), keys.index(key))
360 self.assertEqual(len(self._box), 0)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000361 for key in keys:
362 self.assertRaises(KeyError, lambda: self._box[key])
363
364 def test_update(self):
365 # Modify multiple messages using update()
366 key0 = self._box.add(self._template % 'original 0')
367 key1 = self._box.add(self._template % 'original 1')
368 key2 = self._box.add(self._template % 'original 2')
369 self._box.update({key0: self._template % 'changed 0',
370 key2: _sample_message})
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000371 self.assertEqual(len(self._box), 3)
372 self.assertEqual(self._box.get_string(key0),
373 self._template % 'changed 0')
374 self.assertEqual(self._box.get_string(key1),
375 self._template % 'original 1')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000376 self._check_sample(self._box[key2])
377 self._box.update([(key2, self._template % 'changed 2'),
378 (key1, self._template % 'changed 1'),
379 (key0, self._template % 'original 0')])
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000380 self.assertEqual(len(self._box), 3)
381 self.assertEqual(self._box.get_string(key0),
382 self._template % 'original 0')
383 self.assertEqual(self._box.get_string(key1),
384 self._template % 'changed 1')
385 self.assertEqual(self._box.get_string(key2),
386 self._template % 'changed 2')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000387 self.assertRaises(KeyError,
388 lambda: self._box.update({'foo': 'bar',
389 key0: self._template % "changed 0"}))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000390 self.assertEqual(len(self._box), 3)
391 self.assertEqual(self._box.get_string(key0),
392 self._template % "changed 0")
393 self.assertEqual(self._box.get_string(key1),
394 self._template % "changed 1")
395 self.assertEqual(self._box.get_string(key2),
396 self._template % "changed 2")
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000397
398 def test_flush(self):
399 # Write changes to disk
Neal Norwitz22b3e3a2008-03-26 05:19:41 +0000400 self._test_flush_or_close(self._box.flush, True)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000401
Petri Lehtinen7cf66992012-06-15 20:50:51 +0300402 def test_popitem_and_flush_twice(self):
403 # See #15036.
404 self._box.add(self._template % 0)
405 self._box.add(self._template % 1)
406 self._box.flush()
407
408 self._box.popitem()
409 self._box.flush()
410 self._box.popitem()
411 self._box.flush()
412
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000413 def test_lock_unlock(self):
414 # Lock and unlock the mailbox
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000415 self.assertFalse(os.path.exists(self._get_lock_path()))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000416 self._box.lock()
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000417 self.assertTrue(os.path.exists(self._get_lock_path()))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000418 self._box.unlock()
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000419 self.assertFalse(os.path.exists(self._get_lock_path()))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000420
421 def test_close(self):
422 # Close mailbox and flush changes to disk
Neal Norwitz22b3e3a2008-03-26 05:19:41 +0000423 self._test_flush_or_close(self._box.close, False)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000424
Neal Norwitz22b3e3a2008-03-26 05:19:41 +0000425 def _test_flush_or_close(self, method, should_call_close):
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000426 contents = [self._template % i for i in xrange(3)]
427 self._box.add(contents[0])
428 self._box.add(contents[1])
429 self._box.add(contents[2])
430 method()
Neal Norwitz22b3e3a2008-03-26 05:19:41 +0000431 if should_call_close:
432 self._box.close()
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000433 self._box = self._factory(self._path)
434 keys = self._box.keys()
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000435 self.assertEqual(len(keys), 3)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000436 for key in keys:
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000437 self.assertIn(self._box.get_string(key), contents)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000438
439 def test_dump_message(self):
440 # Write message representations to disk
441 for input in (email.message_from_string(_sample_message),
442 _sample_message, StringIO.StringIO(_sample_message)):
443 output = StringIO.StringIO()
444 self._box._dump_message(input, output)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000445 self.assertEqual(output.getvalue(),
446 _sample_message.replace('\n', os.linesep))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000447 output = StringIO.StringIO()
448 self.assertRaises(TypeError,
449 lambda: self._box._dump_message(None, output))
450
451 def _get_lock_path(self):
452 # Return the path of the dot lock file. May be overridden.
453 return self._path + '.lock'
454
455
R David Murray088a8742012-04-08 18:34:36 -0400456class TestMailboxSuperclass(TestBase, unittest.TestCase):
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000457
458 def test_notimplemented(self):
459 # Test that all Mailbox methods raise NotImplementedException.
460 box = mailbox.Mailbox('path')
461 self.assertRaises(NotImplementedError, lambda: box.add(''))
462 self.assertRaises(NotImplementedError, lambda: box.remove(''))
463 self.assertRaises(NotImplementedError, lambda: box.__delitem__(''))
464 self.assertRaises(NotImplementedError, lambda: box.discard(''))
465 self.assertRaises(NotImplementedError, lambda: box.__setitem__('', ''))
466 self.assertRaises(NotImplementedError, lambda: box.iterkeys())
467 self.assertRaises(NotImplementedError, lambda: box.keys())
468 self.assertRaises(NotImplementedError, lambda: box.itervalues().next())
469 self.assertRaises(NotImplementedError, lambda: box.__iter__().next())
470 self.assertRaises(NotImplementedError, lambda: box.values())
471 self.assertRaises(NotImplementedError, lambda: box.iteritems().next())
472 self.assertRaises(NotImplementedError, lambda: box.items())
473 self.assertRaises(NotImplementedError, lambda: box.get(''))
474 self.assertRaises(NotImplementedError, lambda: box.__getitem__(''))
475 self.assertRaises(NotImplementedError, lambda: box.get_message(''))
476 self.assertRaises(NotImplementedError, lambda: box.get_string(''))
477 self.assertRaises(NotImplementedError, lambda: box.get_file(''))
478 self.assertRaises(NotImplementedError, lambda: box.has_key(''))
479 self.assertRaises(NotImplementedError, lambda: box.__contains__(''))
480 self.assertRaises(NotImplementedError, lambda: box.__len__())
481 self.assertRaises(NotImplementedError, lambda: box.clear())
482 self.assertRaises(NotImplementedError, lambda: box.pop(''))
483 self.assertRaises(NotImplementedError, lambda: box.popitem())
484 self.assertRaises(NotImplementedError, lambda: box.update((('', ''),)))
485 self.assertRaises(NotImplementedError, lambda: box.flush())
486 self.assertRaises(NotImplementedError, lambda: box.lock())
487 self.assertRaises(NotImplementedError, lambda: box.unlock())
488 self.assertRaises(NotImplementedError, lambda: box.close())
489
490
R David Murray088a8742012-04-08 18:34:36 -0400491class TestMaildir(TestMailbox, unittest.TestCase):
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000492
493 _factory = lambda self, path, factory=None: mailbox.Maildir(path, factory)
494
495 def setUp(self):
496 TestMailbox.setUp(self)
Neal Norwitz003c9e22006-08-11 06:09:41 +0000497 if os.name in ('nt', 'os2') or sys.platform == 'cygwin':
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000498 self._box.colon = '!'
499
500 def test_add_MM(self):
501 # Add a MaildirMessage instance
502 msg = mailbox.MaildirMessage(self._template % 0)
503 msg.set_subdir('cur')
504 msg.set_info('foo')
505 key = self._box.add(msg)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000506 self.assertTrue(os.path.exists(os.path.join(self._path, 'cur', '%s%sfoo' %
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000507 (key, self._box.colon))))
508
509 def test_get_MM(self):
510 # Get a MaildirMessage instance
511 msg = mailbox.MaildirMessage(self._template % 0)
512 msg.set_subdir('cur')
513 msg.set_flags('RF')
514 key = self._box.add(msg)
515 msg_returned = self._box.get_message(key)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000516 self.assertIsInstance(msg_returned, mailbox.MaildirMessage)
517 self.assertEqual(msg_returned.get_subdir(), 'cur')
518 self.assertEqual(msg_returned.get_flags(), 'FR')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000519
520 def test_set_MM(self):
521 # Set with a MaildirMessage instance
522 msg0 = mailbox.MaildirMessage(self._template % 0)
523 msg0.set_flags('TP')
524 key = self._box.add(msg0)
525 msg_returned = self._box.get_message(key)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000526 self.assertEqual(msg_returned.get_subdir(), 'new')
527 self.assertEqual(msg_returned.get_flags(), 'PT')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000528 msg1 = mailbox.MaildirMessage(self._template % 1)
529 self._box[key] = msg1
530 msg_returned = self._box.get_message(key)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000531 self.assertEqual(msg_returned.get_subdir(), 'new')
532 self.assertEqual(msg_returned.get_flags(), '')
Petri Lehtinenec2807c2012-09-25 21:48:51 +0300533 self.assertEqual(msg_returned.get_payload(), '1\n')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000534 msg2 = mailbox.MaildirMessage(self._template % 2)
535 msg2.set_info('2,S')
536 self._box[key] = msg2
537 self._box[key] = self._template % 3
538 msg_returned = self._box.get_message(key)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000539 self.assertEqual(msg_returned.get_subdir(), 'new')
540 self.assertEqual(msg_returned.get_flags(), 'S')
Petri Lehtinenec2807c2012-09-25 21:48:51 +0300541 self.assertEqual(msg_returned.get_payload(), '3\n')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000542
Andrew M. Kuchling15ce8802008-01-19 20:12:04 +0000543 def test_consistent_factory(self):
544 # Add a message.
545 msg = mailbox.MaildirMessage(self._template % 0)
546 msg.set_subdir('cur')
547 msg.set_flags('RF')
548 key = self._box.add(msg)
549
550 # Create new mailbox with
551 class FakeMessage(mailbox.MaildirMessage):
552 pass
553 box = mailbox.Maildir(self._path, factory=FakeMessage)
Amaury Forgeot d'Arc07974d72008-02-03 23:15:32 +0000554 box.colon = self._box.colon
Andrew M. Kuchling15ce8802008-01-19 20:12:04 +0000555 msg2 = box.get_message(key)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000556 self.assertIsInstance(msg2, FakeMessage)
Andrew M. Kuchling15ce8802008-01-19 20:12:04 +0000557
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000558 def test_initialize_new(self):
559 # Initialize a non-existent mailbox
560 self.tearDown()
561 self._box = mailbox.Maildir(self._path)
562 self._check_basics(factory=rfc822.Message)
563 self._delete_recursively(self._path)
564 self._box = self._factory(self._path, factory=None)
565 self._check_basics()
566
567 def test_initialize_existing(self):
568 # Initialize an existing mailbox
569 self.tearDown()
570 for subdir in '', 'tmp', 'new', 'cur':
Andrew MacIntyreafa358f2006-07-23 13:04:00 +0000571 os.mkdir(os.path.normpath(os.path.join(self._path, subdir)))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000572 self._box = mailbox.Maildir(self._path)
573 self._check_basics(factory=rfc822.Message)
574 self._box = mailbox.Maildir(self._path, factory=None)
575 self._check_basics()
576
577 def _check_basics(self, factory=None):
578 # (Used by test_open_new() and test_open_existing().)
579 self.assertEqual(self._box._path, os.path.abspath(self._path))
580 self.assertEqual(self._box._factory, factory)
581 for subdir in '', 'tmp', 'new', 'cur':
582 path = os.path.join(self._path, subdir)
583 mode = os.stat(path)[stat.ST_MODE]
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000584 self.assertTrue(stat.S_ISDIR(mode), "Not a directory: '%s'" % path)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000585
586 def test_list_folders(self):
587 # List folders
588 self._box.add_folder('one')
589 self._box.add_folder('two')
590 self._box.add_folder('three')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000591 self.assertEqual(len(self._box.list_folders()), 3)
592 self.assertEqual(set(self._box.list_folders()),
593 set(('one', 'two', 'three')))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000594
595 def test_get_folder(self):
596 # Open folders
597 self._box.add_folder('foo.bar')
598 folder0 = self._box.get_folder('foo.bar')
599 folder0.add(self._template % 'bar')
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000600 self.assertTrue(os.path.isdir(os.path.join(self._path, '.foo.bar')))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000601 folder1 = self._box.get_folder('foo.bar')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000602 self.assertEqual(folder1.get_string(folder1.keys()[0]),
603 self._template % 'bar')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000604
605 def test_add_and_remove_folders(self):
606 # Delete folders
607 self._box.add_folder('one')
608 self._box.add_folder('two')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000609 self.assertEqual(len(self._box.list_folders()), 2)
610 self.assertEqual(set(self._box.list_folders()), set(('one', 'two')))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000611 self._box.remove_folder('one')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000612 self.assertEqual(len(self._box.list_folders()), 1)
613 self.assertEqual(set(self._box.list_folders()), set(('two',)))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000614 self._box.add_folder('three')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000615 self.assertEqual(len(self._box.list_folders()), 2)
616 self.assertEqual(set(self._box.list_folders()), set(('two', 'three')))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000617 self._box.remove_folder('three')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000618 self.assertEqual(len(self._box.list_folders()), 1)
619 self.assertEqual(set(self._box.list_folders()), set(('two',)))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000620 self._box.remove_folder('two')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000621 self.assertEqual(len(self._box.list_folders()), 0)
622 self.assertEqual(self._box.list_folders(), [])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000623
624 def test_clean(self):
625 # Remove old files from 'tmp'
626 foo_path = os.path.join(self._path, 'tmp', 'foo')
627 bar_path = os.path.join(self._path, 'tmp', 'bar')
Brian Curtin04d8b222010-10-14 01:14:36 +0000628 with open(foo_path, 'w') as f:
629 f.write("@")
630 with open(bar_path, 'w') as f:
631 f.write("@")
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000632 self._box.clean()
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000633 self.assertTrue(os.path.exists(foo_path))
634 self.assertTrue(os.path.exists(bar_path))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000635 foo_stat = os.stat(foo_path)
Guido van Rossumb2045832006-05-02 20:47:36 +0000636 os.utime(foo_path, (time.time() - 129600 - 2,
637 foo_stat.st_mtime))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000638 self._box.clean()
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000639 self.assertFalse(os.path.exists(foo_path))
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000640 self.assertTrue(os.path.exists(bar_path))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000641
642 def test_create_tmp(self, repetitions=10):
643 # Create files in tmp directory
644 hostname = socket.gethostname()
645 if '/' in hostname:
646 hostname = hostname.replace('/', r'\057')
647 if ':' in hostname:
648 hostname = hostname.replace(':', r'\072')
649 pid = os.getpid()
650 pattern = re.compile(r"(?P<time>\d+)\.M(?P<M>\d{1,6})P(?P<P>\d+)"
651 r"Q(?P<Q>\d+)\.(?P<host>[^:/]+)")
652 previous_groups = None
653 for x in xrange(repetitions):
654 tmp_file = self._box._create_tmp()
655 head, tail = os.path.split(tmp_file.name)
656 self.assertEqual(head, os.path.abspath(os.path.join(self._path,
657 "tmp")),
658 "File in wrong location: '%s'" % head)
659 match = pattern.match(tail)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000660 self.assertTrue(match is not None, "Invalid file name: '%s'" % tail)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000661 groups = match.groups()
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000662 if previous_groups is not None:
Petri Lehtinen80f45532012-09-01 14:25:48 +0300663 self.assertGreaterEqual(int(groups[0]), int(previous_groups[0]),
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000664 "Non-monotonic seconds: '%s' before '%s'" %
665 (previous_groups[0], groups[0]))
Petri Lehtinen80f45532012-09-01 14:25:48 +0300666 if int(groups[0]) == int(previous_groups[0]):
667 self.assertGreaterEqual(int(groups[1]), int(previous_groups[1]),
668 "Non-monotonic milliseconds: '%s' before '%s'" %
669 (previous_groups[1], groups[1]))
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000670 self.assertTrue(int(groups[2]) == pid,
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000671 "Process ID mismatch: '%s' should be '%s'" %
672 (groups[2], pid))
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000673 self.assertTrue(int(groups[3]) == int(previous_groups[3]) + 1,
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000674 "Non-sequential counter: '%s' before '%s'" %
675 (previous_groups[3], groups[3]))
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000676 self.assertTrue(groups[4] == hostname,
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000677 "Host name mismatch: '%s' should be '%s'" %
678 (groups[4], hostname))
679 previous_groups = groups
680 tmp_file.write(_sample_message)
681 tmp_file.seek(0)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000682 self.assertTrue(tmp_file.read() == _sample_message)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000683 tmp_file.close()
684 file_count = len(os.listdir(os.path.join(self._path, "tmp")))
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000685 self.assertTrue(file_count == repetitions,
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000686 "Wrong file count: '%s' should be '%s'" %
687 (file_count, repetitions))
688
689 def test_refresh(self):
690 # Update the table of contents
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000691 self.assertEqual(self._box._toc, {})
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000692 key0 = self._box.add(self._template % 0)
693 key1 = self._box.add(self._template % 1)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000694 self.assertEqual(self._box._toc, {})
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000695 self._box._refresh()
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000696 self.assertEqual(self._box._toc, {key0: os.path.join('new', key0),
697 key1: os.path.join('new', key1)})
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000698 key2 = self._box.add(self._template % 2)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000699 self.assertEqual(self._box._toc, {key0: os.path.join('new', key0),
700 key1: os.path.join('new', key1)})
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000701 self._box._refresh()
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000702 self.assertEqual(self._box._toc, {key0: os.path.join('new', key0),
703 key1: os.path.join('new', key1),
704 key2: os.path.join('new', key2)})
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000705
Petri Lehtinen49aa72e2011-11-05 09:50:37 +0200706 def test_refresh_after_safety_period(self):
707 # Issue #13254: Call _refresh after the "file system safety
708 # period" of 2 seconds has passed; _toc should still be
709 # updated because this is the first call to _refresh.
710 key0 = self._box.add(self._template % 0)
711 key1 = self._box.add(self._template % 1)
712
713 self._box = self._factory(self._path)
714 self.assertEqual(self._box._toc, {})
715
716 # Emulate sleeping. Instead of sleeping for 2 seconds, use the
717 # skew factor to make _refresh think that the filesystem
718 # safety period has passed and re-reading the _toc is only
719 # required if mtimes differ.
Petri Lehtinenab42abd2011-11-12 21:02:42 +0200720 self._box._skewfactor = -3
Petri Lehtinen49aa72e2011-11-05 09:50:37 +0200721
722 self._box._refresh()
723 self.assertEqual(sorted(self._box._toc.keys()), sorted([key0, key1]))
724
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000725 def test_lookup(self):
726 # Look up message subpaths in the TOC
727 self.assertRaises(KeyError, lambda: self._box._lookup('foo'))
728 key0 = self._box.add(self._template % 0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000729 self.assertEqual(self._box._lookup(key0), os.path.join('new', key0))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000730 os.remove(os.path.join(self._path, 'new', key0))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000731 self.assertEqual(self._box._toc, {key0: os.path.join('new', key0)})
Antoine Pitroue4c6b162009-11-01 21:29:33 +0000732 # Be sure that the TOC is read back from disk (see issue #6896
733 # about bad mtime behaviour on some systems).
734 self._box.flush()
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000735 self.assertRaises(KeyError, lambda: self._box._lookup(key0))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000736 self.assertEqual(self._box._toc, {})
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000737
738 def test_lock_unlock(self):
739 # Lock and unlock the mailbox. For Maildir, this does nothing.
740 self._box.lock()
741 self._box.unlock()
742
Andrew M. Kuchlinga3e5d372006-11-09 13:27:07 +0000743 def test_folder (self):
744 # Test for bug #1569790: verify that folders returned by .get_folder()
745 # use the same factory function.
746 def dummy_factory (s):
747 return None
748 box = self._factory(self._path, factory=dummy_factory)
749 folder = box.add_folder('folder1')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000750 self.assertIs(folder._factory, dummy_factory)
Tim Petersf733abb2007-01-30 03:03:46 +0000751
Andrew M. Kuchlinga3e5d372006-11-09 13:27:07 +0000752 folder1_alias = box.get_folder('folder1')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000753 self.assertIs(folder1_alias._factory, dummy_factory)
Andrew M. Kuchlinga3e5d372006-11-09 13:27:07 +0000754
Andrew M. Kuchling2b09ef02007-07-14 21:56:19 +0000755 def test_directory_in_folder (self):
756 # Test that mailboxes still work if there's a stray extra directory
757 # in a folder.
758 for i in range(10):
759 self._box.add(mailbox.Message(_sample_message))
Tim Petersf733abb2007-01-30 03:03:46 +0000760
Andrew M. Kuchling2b09ef02007-07-14 21:56:19 +0000761 # Create a stray directory
762 os.mkdir(os.path.join(self._path, 'cur', 'stray-dir'))
763
764 # Check that looping still works with the directory present.
765 for msg in self._box:
766 pass
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000767
Andrew M. Kuchling10288e12008-08-05 01:00:57 +0000768 def test_file_permissions(self):
769 # Verify that message files are created without execute permissions
770 if not hasattr(os, "stat") or not hasattr(os, "umask"):
771 return
772 msg = mailbox.MaildirMessage(self._template % 0)
773 orig_umask = os.umask(0)
774 try:
775 key = self._box.add(msg)
776 finally:
777 os.umask(orig_umask)
778 path = os.path.join(self._path, self._box._lookup(key))
779 mode = os.stat(path).st_mode
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000780 self.assertEqual(mode & 0111, 0)
Andrew M. Kuchling10288e12008-08-05 01:00:57 +0000781
782 def test_folder_file_perms(self):
Andrew M. Kuchling70a6dbd2008-08-04 01:43:43 +0000783 # From bug #3228, we want to verify that the file created inside a Maildir
784 # subfolder isn't marked as executable.
Andrew M. Kuchling10288e12008-08-05 01:00:57 +0000785 if not hasattr(os, "stat") or not hasattr(os, "umask"):
786 return
787
788 orig_umask = os.umask(0)
789 try:
790 subfolder = self._box.add_folder('subfolder')
791 finally:
792 os.umask(orig_umask)
793
Andrew M. Kuchling70a6dbd2008-08-04 01:43:43 +0000794 path = os.path.join(subfolder._path, 'maildirfolder')
795 st = os.stat(path)
796 perms = st.st_mode
797 self.assertFalse((perms & 0111)) # Execute bits should all be off.
798
Andrew M. Kuchling420d4eb2009-05-02 19:17:28 +0000799 def test_reread(self):
Petri Lehtinen49aa72e2011-11-05 09:50:37 +0200800 # Do an initial unconditional refresh
801 self._box._refresh()
Andrew M. Kuchling420d4eb2009-05-02 19:17:28 +0000802
R David Murray8b26c4b2011-05-06 21:56:22 -0400803 # Put the last modified times more than two seconds into the past
804 # (because mtime may have only a two second granularity).
805 for subdir in ('cur', 'new'):
806 os.utime(os.path.join(self._box._path, subdir),
807 (time.time()-5,)*2)
Andrew M. Kuchling420d4eb2009-05-02 19:17:28 +0000808
R David Murray8b26c4b2011-05-06 21:56:22 -0400809 # Because mtime has a two second granularity in worst case (FAT), a
810 # refresh is done unconditionally if called for within
811 # two-second-plus-a-bit of the last one, just in case the mbox has
812 # changed; so now we have to wait for that interval to expire.
Petri Lehtinenab42abd2011-11-12 21:02:42 +0200813 #
814 # Because this is a test, emulate sleeping. Instead of
815 # sleeping for 2 seconds, use the skew factor to make _refresh
816 # think that 2 seconds have passed and re-reading the _toc is
817 # only required if mtimes differ.
818 self._box._skewfactor = -3
Andrew M. Kuchling420d4eb2009-05-02 19:17:28 +0000819
R David Murray8b26c4b2011-05-06 21:56:22 -0400820 # Re-reading causes the ._toc attribute to be assigned a new dictionary
821 # object, so we'll check that the ._toc attribute isn't a different
822 # object.
Andrew M. Kuchling420d4eb2009-05-02 19:17:28 +0000823 orig_toc = self._box._toc
824 def refreshed():
825 return self._box._toc is not orig_toc
826
Andrew M. Kuchling420d4eb2009-05-02 19:17:28 +0000827 self._box._refresh()
R David Murray8b26c4b2011-05-06 21:56:22 -0400828 self.assertFalse(refreshed())
Andrew M. Kuchling420d4eb2009-05-02 19:17:28 +0000829
830 # Now, write something into cur and remove it. This changes
Petri Lehtinenab42abd2011-11-12 21:02:42 +0200831 # the mtime and should cause a re-read. Note that "sleep
832 # emulation" is still in effect, as skewfactor is -3.
Andrew M. Kuchling420d4eb2009-05-02 19:17:28 +0000833 filename = os.path.join(self._path, 'cur', 'stray-file')
834 f = open(filename, 'w')
835 f.close()
836 os.unlink(filename)
837 self._box._refresh()
R David Murray8b26c4b2011-05-06 21:56:22 -0400838 self.assertTrue(refreshed())
Andrew M. Kuchling70a6dbd2008-08-04 01:43:43 +0000839
Petri Lehtinen45f0d982012-06-28 13:48:17 +0300840
841class _TestSingleFile(TestMailbox):
842 '''Common tests for single-file mailboxes'''
843
844 def test_add_doesnt_rewrite(self):
845 # When only adding messages, flush() should not rewrite the
846 # mailbox file. See issue #9559.
847
848 # Inode number changes if the contents are written to another
849 # file which is then renamed over the original file. So we
850 # must check that the inode number doesn't change.
851 inode_before = os.stat(self._path).st_ino
852
853 self._box.add(self._template % 0)
854 self._box.flush()
855
856 inode_after = os.stat(self._path).st_ino
857 self.assertEqual(inode_before, inode_after)
858
859 # Make sure the message was really added
860 self._box.close()
861 self._box = self._factory(self._path)
862 self.assertEqual(len(self._box), 1)
863
Petri Lehtinend07de402012-06-29 15:09:12 +0300864 def test_permissions_after_flush(self):
865 # See issue #5346
866
867 # Make the mailbox world writable. It's unlikely that the new
868 # mailbox file would have these permissions after flush(),
869 # because umask usually prevents it.
870 mode = os.stat(self._path).st_mode | 0o666
871 os.chmod(self._path, mode)
872
873 self._box.add(self._template % 0)
874 i = self._box.add(self._template % 1)
875 # Need to remove one message to make flush() create a new file
876 self._box.remove(i)
877 self._box.flush()
878
879 self.assertEqual(os.stat(self._path).st_mode, mode)
880
Petri Lehtinen45f0d982012-06-28 13:48:17 +0300881
882class _TestMboxMMDF(_TestSingleFile):
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000883
884 def tearDown(self):
885 self._box.close()
886 self._delete_recursively(self._path)
887 for lock_remnant in glob.glob(self._path + '.*'):
Neal Norwitz6cbd8de2007-03-20 06:53:17 +0000888 test_support.unlink(lock_remnant)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000889
890 def test_add_from_string(self):
891 # Add a string starting with 'From ' to the mailbox
Petri Lehtinenec2807c2012-09-25 21:48:51 +0300892 key = self._box.add('From foo@bar blah\nFrom: foo\n\n0\n')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000893 self.assertEqual(self._box[key].get_from(), 'foo@bar blah')
Petri Lehtinenec2807c2012-09-25 21:48:51 +0300894 self.assertEqual(self._box[key].get_payload(), '0\n')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000895
896 def test_add_mbox_or_mmdf_message(self):
897 # Add an mboxMessage or MMDFMessage
898 for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
Petri Lehtinenec2807c2012-09-25 21:48:51 +0300899 msg = class_('From foo@bar blah\nFrom: foo\n\n0\n')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000900 key = self._box.add(msg)
901
902 def test_open_close_open(self):
903 # Open and inspect previously-created mailbox
904 values = [self._template % i for i in xrange(3)]
905 for value in values:
906 self._box.add(value)
907 self._box.close()
908 mtime = os.path.getmtime(self._path)
909 self._box = self._factory(self._path)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000910 self.assertEqual(len(self._box), 3)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000911 for key in self._box.iterkeys():
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000912 self.assertIn(self._box.get_string(key), values)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000913 self._box.close()
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000914 self.assertEqual(mtime, os.path.getmtime(self._path))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000915
916 def test_add_and_close(self):
917 # Verifying that closing a mailbox doesn't change added items
918 self._box.add(_sample_message)
919 for i in xrange(3):
920 self._box.add(self._template % i)
921 self._box.add(_sample_message)
922 self._box._file.flush()
923 self._box._file.seek(0)
924 contents = self._box._file.read()
925 self._box.close()
Antoine Pitrou0da5cb82009-10-31 23:19:52 +0000926 with open(self._path, 'rb') as f:
927 self.assertEqual(contents, f.read())
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000928 self._box = self._factory(self._path)
929
Charles-François Natali52aa2602011-12-19 12:17:16 +0100930 @unittest.skipUnless(hasattr(os, 'fork'), "Test needs fork().")
Charles-François Natali8366b842011-12-20 11:47:23 +0100931 @unittest.skipUnless(hasattr(socket, 'socketpair'), "Test needs socketpair().")
Andrew M. Kuchling9afbace2006-06-26 13:23:10 +0000932 def test_lock_conflict(self):
Charles-François Natali52aa2602011-12-19 12:17:16 +0100933 # Fork off a child process that will lock the mailbox temporarily,
934 # unlock it and exit.
Charles-François Natali8366b842011-12-20 11:47:23 +0100935 c, p = socket.socketpair()
936 self.addCleanup(c.close)
937 self.addCleanup(p.close)
Charles-François Natali52aa2602011-12-19 12:17:16 +0100938
Andrew M. Kuchling9afbace2006-06-26 13:23:10 +0000939 pid = os.fork()
940 if pid == 0:
Charles-François Natali52aa2602011-12-19 12:17:16 +0100941 # child
942 try:
943 # lock the mailbox, and signal the parent it can proceed
944 self._box.lock()
Charles-François Natali8366b842011-12-20 11:47:23 +0100945 c.send(b'c')
Andrew M. Kuchling9afbace2006-06-26 13:23:10 +0000946
Charles-François Natali52aa2602011-12-19 12:17:16 +0100947 # wait until the parent is done, and unlock the mailbox
Charles-François Natali8366b842011-12-20 11:47:23 +0100948 c.recv(1)
Charles-François Natali52aa2602011-12-19 12:17:16 +0100949 self._box.unlock()
950 finally:
951 os._exit(0)
952
953 # In the parent, wait until the child signals it locked the mailbox.
Charles-François Natali8366b842011-12-20 11:47:23 +0100954 p.recv(1)
Neal Norwitz003c9e22006-08-11 06:09:41 +0000955 try:
956 self.assertRaises(mailbox.ExternalClashError,
957 self._box.lock)
958 finally:
Charles-François Natali52aa2602011-12-19 12:17:16 +0100959 # Signal the child it can now release the lock and exit.
Charles-François Natali8366b842011-12-20 11:47:23 +0100960 p.send(b'p')
Neal Norwitz003c9e22006-08-11 06:09:41 +0000961 # Wait for child to exit. Locking should now succeed.
962 exited_pid, status = os.waitpid(pid, 0)
Tim Peters3249d002006-06-27 11:52:49 +0000963
Andrew M. Kuchling9afbace2006-06-26 13:23:10 +0000964 self._box.lock()
965 self._box.unlock()
Tim Peters3249d002006-06-27 11:52:49 +0000966
Andrew M. Kuchling0f871832006-10-27 16:55:34 +0000967 def test_relock(self):
968 # Test case for bug #1575506: the mailbox class was locking the
969 # wrong file object in its flush() method.
970 msg = "Subject: sub\n\nbody\n"
971 key1 = self._box.add(msg)
972 self._box.flush()
973 self._box.close()
Tim Petersabd8a332006-11-03 02:32:46 +0000974
Andrew M. Kuchling0f871832006-10-27 16:55:34 +0000975 self._box = self._factory(self._path)
976 self._box.lock()
977 key2 = self._box.add(msg)
978 self._box.flush()
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000979 self.assertTrue(self._box._locked)
Andrew M. Kuchling0f871832006-10-27 16:55:34 +0000980 self._box.close()
Tim Petersabd8a332006-11-03 02:32:46 +0000981
982
R David Murray088a8742012-04-08 18:34:36 -0400983class TestMbox(_TestMboxMMDF, unittest.TestCase):
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +0000984
985 _factory = lambda self, path, factory=None: mailbox.mbox(path, factory)
986
Andrew M. Kuchling70a6dbd2008-08-04 01:43:43 +0000987 def test_file_perms(self):
988 # From bug #3228, we want to verify that the mailbox file isn't executable,
989 # even if the umask is set to something that would leave executable bits set.
990 # We only run this test on platforms that support umask.
Andrew M. Kuchling10288e12008-08-05 01:00:57 +0000991 if hasattr(os, 'umask') and hasattr(os, 'stat'):
Andrew M. Kuchling70a6dbd2008-08-04 01:43:43 +0000992 try:
993 old_umask = os.umask(0077)
994 self._box.close()
995 os.unlink(self._path)
996 self._box = mailbox.mbox(self._path, create=True)
997 self._box.add('')
998 self._box.close()
Andrew M. Kuchling70a6dbd2008-08-04 01:43:43 +0000999 finally:
1000 os.umask(old_umask)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001001
Andrew M. Kuchling10288e12008-08-05 01:00:57 +00001002 st = os.stat(self._path)
1003 perms = st.st_mode
1004 self.assertFalse((perms & 0111)) # Execute bits should all be off.
1005
Petri Lehtinena4fd0dc2012-09-25 21:57:59 +03001006 def test_terminating_newline(self):
1007 message = email.message.Message()
1008 message['From'] = 'john@example.com'
1009 message.set_payload('No newline at the end')
1010 i = self._box.add(message)
1011
1012 # A newline should have been appended to the payload
1013 message = self._box.get(i)
1014 self.assertEqual(message.get_payload(), 'No newline at the end\n')
1015
1016 def test_message_separator(self):
1017 # Check there's always a single blank line after each message
1018 self._box.add('From: foo\n\n0') # No newline at the end
1019 with open(self._path) as f:
1020 data = f.read()
1021 self.assertEqual(data[-3:], '0\n\n')
1022
1023 self._box.add('From: foo\n\n0\n') # Newline at the end
1024 with open(self._path) as f:
1025 data = f.read()
1026 self.assertEqual(data[-3:], '0\n\n')
1027
1028
R David Murray088a8742012-04-08 18:34:36 -04001029class TestMMDF(_TestMboxMMDF, unittest.TestCase):
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001030
1031 _factory = lambda self, path, factory=None: mailbox.MMDF(path, factory)
1032
1033
R David Murray088a8742012-04-08 18:34:36 -04001034class TestMH(TestMailbox, unittest.TestCase):
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001035
1036 _factory = lambda self, path, factory=None: mailbox.MH(path, factory)
1037
1038 def test_list_folders(self):
1039 # List folders
1040 self._box.add_folder('one')
1041 self._box.add_folder('two')
1042 self._box.add_folder('three')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001043 self.assertEqual(len(self._box.list_folders()), 3)
1044 self.assertEqual(set(self._box.list_folders()),
1045 set(('one', 'two', 'three')))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001046
1047 def test_get_folder(self):
1048 # Open folders
Andrew M. Kuchlinga3e5d372006-11-09 13:27:07 +00001049 def dummy_factory (s):
1050 return None
1051 self._box = self._factory(self._path, dummy_factory)
Tim Petersf733abb2007-01-30 03:03:46 +00001052
Andrew M. Kuchlinga3e5d372006-11-09 13:27:07 +00001053 new_folder = self._box.add_folder('foo.bar')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001054 folder0 = self._box.get_folder('foo.bar')
1055 folder0.add(self._template % 'bar')
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001056 self.assertTrue(os.path.isdir(os.path.join(self._path, 'foo.bar')))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001057 folder1 = self._box.get_folder('foo.bar')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001058 self.assertEqual(folder1.get_string(folder1.keys()[0]),
1059 self._template % 'bar')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001060
Andrew M. Kuchlinga3e5d372006-11-09 13:27:07 +00001061 # Test for bug #1569790: verify that folders returned by .get_folder()
1062 # use the same factory function.
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001063 self.assertIs(new_folder._factory, self._box._factory)
1064 self.assertIs(folder0._factory, self._box._factory)
Andrew M. Kuchlinga3e5d372006-11-09 13:27:07 +00001065
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001066 def test_add_and_remove_folders(self):
1067 # Delete folders
1068 self._box.add_folder('one')
1069 self._box.add_folder('two')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001070 self.assertEqual(len(self._box.list_folders()), 2)
1071 self.assertEqual(set(self._box.list_folders()), set(('one', 'two')))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001072 self._box.remove_folder('one')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001073 self.assertEqual(len(self._box.list_folders()), 1)
1074 self.assertEqual(set(self._box.list_folders()), set(('two', )))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001075 self._box.add_folder('three')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001076 self.assertEqual(len(self._box.list_folders()), 2)
1077 self.assertEqual(set(self._box.list_folders()), set(('two', 'three')))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001078 self._box.remove_folder('three')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001079 self.assertEqual(len(self._box.list_folders()), 1)
1080 self.assertEqual(set(self._box.list_folders()), set(('two', )))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001081 self._box.remove_folder('two')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001082 self.assertEqual(len(self._box.list_folders()), 0)
1083 self.assertEqual(self._box.list_folders(), [])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001084
1085 def test_sequences(self):
1086 # Get and set sequences
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001087 self.assertEqual(self._box.get_sequences(), {})
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001088 msg0 = mailbox.MHMessage(self._template % 0)
1089 msg0.add_sequence('foo')
1090 key0 = self._box.add(msg0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001091 self.assertEqual(self._box.get_sequences(), {'foo':[key0]})
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001092 msg1 = mailbox.MHMessage(self._template % 1)
1093 msg1.set_sequences(['bar', 'replied', 'foo'])
1094 key1 = self._box.add(msg1)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001095 self.assertEqual(self._box.get_sequences(),
1096 {'foo':[key0, key1], 'bar':[key1], 'replied':[key1]})
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001097 msg0.set_sequences(['flagged'])
1098 self._box[key0] = msg0
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001099 self.assertEqual(self._box.get_sequences(),
1100 {'foo':[key1], 'bar':[key1], 'replied':[key1],
1101 'flagged':[key0]})
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001102 self._box.remove(key1)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001103 self.assertEqual(self._box.get_sequences(), {'flagged':[key0]})
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001104
R. David Murray52720c52009-04-02 14:05:35 +00001105 def test_issue2625(self):
1106 msg0 = mailbox.MHMessage(self._template % 0)
1107 msg0.add_sequence('foo')
1108 key0 = self._box.add(msg0)
1109 refmsg0 = self._box.get_message(key0)
1110
Andrew M. Kuchlingb72b0eb2010-02-22 18:42:07 +00001111 def test_issue7627(self):
1112 msg0 = mailbox.MHMessage(self._template % 0)
1113 key0 = self._box.add(msg0)
1114 self._box.lock()
1115 self._box.remove(key0)
1116 self._box.unlock()
1117
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001118 def test_pack(self):
1119 # Pack the contents of the mailbox
1120 msg0 = mailbox.MHMessage(self._template % 0)
1121 msg1 = mailbox.MHMessage(self._template % 1)
1122 msg2 = mailbox.MHMessage(self._template % 2)
1123 msg3 = mailbox.MHMessage(self._template % 3)
1124 msg0.set_sequences(['foo', 'unseen'])
1125 msg1.set_sequences(['foo'])
1126 msg2.set_sequences(['foo', 'flagged'])
1127 msg3.set_sequences(['foo', 'bar', 'replied'])
1128 key0 = self._box.add(msg0)
1129 key1 = self._box.add(msg1)
1130 key2 = self._box.add(msg2)
1131 key3 = self._box.add(msg3)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001132 self.assertEqual(self._box.get_sequences(),
1133 {'foo':[key0,key1,key2,key3], 'unseen':[key0],
1134 'flagged':[key2], 'bar':[key3], 'replied':[key3]})
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001135 self._box.remove(key2)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001136 self.assertEqual(self._box.get_sequences(),
1137 {'foo':[key0,key1,key3], 'unseen':[key0], 'bar':[key3],
1138 'replied':[key3]})
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001139 self._box.pack()
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001140 self.assertEqual(self._box.keys(), [1, 2, 3])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001141 key0 = key0
1142 key1 = key0 + 1
1143 key2 = key1 + 1
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001144 self.assertEqual(self._box.get_sequences(),
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001145 {'foo':[1, 2, 3], 'unseen':[1], 'bar':[3], 'replied':[3]})
1146
Andrew M. Kuchling8c456f32006-11-17 13:30:25 +00001147 # Test case for packing while holding the mailbox locked.
1148 key0 = self._box.add(msg1)
1149 key1 = self._box.add(msg1)
1150 key2 = self._box.add(msg1)
1151 key3 = self._box.add(msg1)
1152
1153 self._box.remove(key0)
1154 self._box.remove(key2)
1155 self._box.lock()
1156 self._box.pack()
1157 self._box.unlock()
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001158 self.assertEqual(self._box.get_sequences(),
1159 {'foo':[1, 2, 3, 4, 5],
1160 'unseen':[1], 'bar':[3], 'replied':[3]})
Tim Petersf733abb2007-01-30 03:03:46 +00001161
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001162 def _get_lock_path(self):
1163 return os.path.join(self._path, '.mh_sequences.lock')
1164
1165
Petri Lehtinen45f0d982012-06-28 13:48:17 +03001166class TestBabyl(_TestSingleFile, unittest.TestCase):
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001167
1168 _factory = lambda self, path, factory=None: mailbox.Babyl(path, factory)
1169
1170 def tearDown(self):
1171 self._box.close()
1172 self._delete_recursively(self._path)
1173 for lock_remnant in glob.glob(self._path + '.*'):
Neal Norwitz6cbd8de2007-03-20 06:53:17 +00001174 test_support.unlink(lock_remnant)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001175
1176 def test_labels(self):
1177 # Get labels from the mailbox
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001178 self.assertEqual(self._box.get_labels(), [])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001179 msg0 = mailbox.BabylMessage(self._template % 0)
1180 msg0.add_label('foo')
1181 key0 = self._box.add(msg0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001182 self.assertEqual(self._box.get_labels(), ['foo'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001183 msg1 = mailbox.BabylMessage(self._template % 1)
1184 msg1.set_labels(['bar', 'answered', 'foo'])
1185 key1 = self._box.add(msg1)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001186 self.assertEqual(set(self._box.get_labels()), set(['foo', 'bar']))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001187 msg0.set_labels(['blah', 'filed'])
1188 self._box[key0] = msg0
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001189 self.assertEqual(set(self._box.get_labels()),
1190 set(['foo', 'bar', 'blah']))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001191 self._box.remove(key1)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001192 self.assertEqual(set(self._box.get_labels()), set(['blah']))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001193
1194
R David Murray088a8742012-04-08 18:34:36 -04001195class TestMessage(TestBase, unittest.TestCase):
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001196
1197 _factory = mailbox.Message # Overridden by subclasses to reuse tests
1198
1199 def setUp(self):
1200 self._path = test_support.TESTFN
1201
1202 def tearDown(self):
1203 self._delete_recursively(self._path)
1204
1205 def test_initialize_with_eMM(self):
Georg Brandl5a096e12007-01-22 19:40:21 +00001206 # Initialize based on email.message.Message instance
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001207 eMM = email.message_from_string(_sample_message)
1208 msg = self._factory(eMM)
1209 self._post_initialize_hook(msg)
1210 self._check_sample(msg)
1211
1212 def test_initialize_with_string(self):
1213 # Initialize based on string
1214 msg = self._factory(_sample_message)
1215 self._post_initialize_hook(msg)
1216 self._check_sample(msg)
1217
1218 def test_initialize_with_file(self):
1219 # Initialize based on contents of file
Brian Curtin04d8b222010-10-14 01:14:36 +00001220 with open(self._path, 'w+') as f:
1221 f.write(_sample_message)
1222 f.seek(0)
1223 msg = self._factory(f)
1224 self._post_initialize_hook(msg)
1225 self._check_sample(msg)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001226
1227 def test_initialize_with_nothing(self):
1228 # Initialize without arguments
1229 msg = self._factory()
1230 self._post_initialize_hook(msg)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001231 self.assertIsInstance(msg, email.message.Message)
1232 self.assertIsInstance(msg, mailbox.Message)
1233 self.assertIsInstance(msg, self._factory)
1234 self.assertEqual(msg.keys(), [])
1235 self.assertFalse(msg.is_multipart())
1236 self.assertEqual(msg.get_payload(), None)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001237
1238 def test_initialize_incorrectly(self):
1239 # Initialize with invalid argument
1240 self.assertRaises(TypeError, lambda: self._factory(object()))
1241
1242 def test_become_message(self):
1243 # Take on the state of another message
1244 eMM = email.message_from_string(_sample_message)
1245 msg = self._factory()
1246 msg._become_message(eMM)
1247 self._check_sample(msg)
1248
1249 def test_explain_to(self):
1250 # Copy self's format-specific data to other message formats.
1251 # This test is superficial; better ones are in TestMessageConversion.
1252 msg = self._factory()
1253 for class_ in (mailbox.Message, mailbox.MaildirMessage,
1254 mailbox.mboxMessage, mailbox.MHMessage,
1255 mailbox.BabylMessage, mailbox.MMDFMessage):
1256 other_msg = class_()
1257 msg._explain_to(other_msg)
Georg Brandl5a096e12007-01-22 19:40:21 +00001258 other_msg = email.message.Message()
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001259 self.assertRaises(TypeError, lambda: msg._explain_to(other_msg))
1260
1261 def _post_initialize_hook(self, msg):
1262 # Overridden by subclasses to check extra things after initialization
1263 pass
1264
1265
R David Murray088a8742012-04-08 18:34:36 -04001266class TestMaildirMessage(TestMessage, unittest.TestCase):
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001267
1268 _factory = mailbox.MaildirMessage
1269
1270 def _post_initialize_hook(self, msg):
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001271 self.assertEqual(msg._subdir, 'new')
1272 self.assertEqual(msg._info,'')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001273
1274 def test_subdir(self):
1275 # Use get_subdir() and set_subdir()
1276 msg = mailbox.MaildirMessage(_sample_message)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001277 self.assertEqual(msg.get_subdir(), 'new')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001278 msg.set_subdir('cur')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001279 self.assertEqual(msg.get_subdir(), 'cur')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001280 msg.set_subdir('new')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001281 self.assertEqual(msg.get_subdir(), 'new')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001282 self.assertRaises(ValueError, lambda: msg.set_subdir('tmp'))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001283 self.assertEqual(msg.get_subdir(), 'new')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001284 msg.set_subdir('new')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001285 self.assertEqual(msg.get_subdir(), 'new')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001286 self._check_sample(msg)
1287
1288 def test_flags(self):
1289 # Use get_flags(), set_flags(), add_flag(), remove_flag()
1290 msg = mailbox.MaildirMessage(_sample_message)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001291 self.assertEqual(msg.get_flags(), '')
1292 self.assertEqual(msg.get_subdir(), 'new')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001293 msg.set_flags('F')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001294 self.assertEqual(msg.get_subdir(), 'new')
1295 self.assertEqual(msg.get_flags(), 'F')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001296 msg.set_flags('SDTP')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001297 self.assertEqual(msg.get_flags(), 'DPST')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001298 msg.add_flag('FT')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001299 self.assertEqual(msg.get_flags(), 'DFPST')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001300 msg.remove_flag('TDRP')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001301 self.assertEqual(msg.get_flags(), 'FS')
1302 self.assertEqual(msg.get_subdir(), 'new')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001303 self._check_sample(msg)
1304
1305 def test_date(self):
1306 # Use get_date() and set_date()
1307 msg = mailbox.MaildirMessage(_sample_message)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001308 diff = msg.get_date() - time.time()
1309 self.assertTrue(abs(diff) < 60, diff)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001310 msg.set_date(0.0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001311 self.assertEqual(msg.get_date(), 0.0)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001312
1313 def test_info(self):
1314 # Use get_info() and set_info()
1315 msg = mailbox.MaildirMessage(_sample_message)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001316 self.assertEqual(msg.get_info(), '')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001317 msg.set_info('1,foo=bar')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001318 self.assertEqual(msg.get_info(), '1,foo=bar')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001319 self.assertRaises(TypeError, lambda: msg.set_info(None))
1320 self._check_sample(msg)
1321
1322 def test_info_and_flags(self):
1323 # Test interaction of info and flag methods
1324 msg = mailbox.MaildirMessage(_sample_message)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001325 self.assertEqual(msg.get_info(), '')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001326 msg.set_flags('SF')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001327 self.assertEqual(msg.get_flags(), 'FS')
1328 self.assertEqual(msg.get_info(), '2,FS')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001329 msg.set_info('1,')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001330 self.assertEqual(msg.get_flags(), '')
1331 self.assertEqual(msg.get_info(), '1,')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001332 msg.remove_flag('RPT')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001333 self.assertEqual(msg.get_flags(), '')
1334 self.assertEqual(msg.get_info(), '1,')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001335 msg.add_flag('D')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001336 self.assertEqual(msg.get_flags(), 'D')
1337 self.assertEqual(msg.get_info(), '2,D')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001338 self._check_sample(msg)
1339
1340
R David Murray088a8742012-04-08 18:34:36 -04001341class _TestMboxMMDFMessage:
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001342
1343 _factory = mailbox._mboxMMDFMessage
1344
1345 def _post_initialize_hook(self, msg):
1346 self._check_from(msg)
1347
1348 def test_initialize_with_unixfrom(self):
1349 # Initialize with a message that already has a _unixfrom attribute
1350 msg = mailbox.Message(_sample_message)
1351 msg.set_unixfrom('From foo@bar blah')
1352 msg = mailbox.mboxMessage(msg)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001353 self.assertEqual(msg.get_from(), 'foo@bar blah')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001354
1355 def test_from(self):
1356 # Get and set "From " line
1357 msg = mailbox.mboxMessage(_sample_message)
1358 self._check_from(msg)
1359 msg.set_from('foo bar')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001360 self.assertEqual(msg.get_from(), 'foo bar')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001361 msg.set_from('foo@bar', True)
1362 self._check_from(msg, 'foo@bar')
1363 msg.set_from('blah@temp', time.localtime())
1364 self._check_from(msg, 'blah@temp')
1365
1366 def test_flags(self):
1367 # Use get_flags(), set_flags(), add_flag(), remove_flag()
1368 msg = mailbox.mboxMessage(_sample_message)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001369 self.assertEqual(msg.get_flags(), '')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001370 msg.set_flags('F')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001371 self.assertEqual(msg.get_flags(), 'F')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001372 msg.set_flags('XODR')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001373 self.assertEqual(msg.get_flags(), 'RODX')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001374 msg.add_flag('FA')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001375 self.assertEqual(msg.get_flags(), 'RODFAX')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001376 msg.remove_flag('FDXA')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001377 self.assertEqual(msg.get_flags(), 'RO')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001378 self._check_sample(msg)
1379
1380 def _check_from(self, msg, sender=None):
1381 # Check contents of "From " line
1382 if sender is None:
1383 sender = "MAILER-DAEMON"
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001384 self.assertTrue(re.match(sender + r" \w{3} \w{3} [\d ]\d [\d ]\d:\d{2}:"
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001385 r"\d{2} \d{4}", msg.get_from()))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001386
1387
R David Murray088a8742012-04-08 18:34:36 -04001388class TestMboxMessage(_TestMboxMMDFMessage, TestMessage):
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001389
1390 _factory = mailbox.mboxMessage
1391
1392
R David Murray088a8742012-04-08 18:34:36 -04001393class TestMHMessage(TestMessage, unittest.TestCase):
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001394
1395 _factory = mailbox.MHMessage
1396
1397 def _post_initialize_hook(self, msg):
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001398 self.assertEqual(msg._sequences, [])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001399
1400 def test_sequences(self):
1401 # Get, set, join, and leave sequences
1402 msg = mailbox.MHMessage(_sample_message)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001403 self.assertEqual(msg.get_sequences(), [])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001404 msg.set_sequences(['foobar'])
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001405 self.assertEqual(msg.get_sequences(), ['foobar'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001406 msg.set_sequences([])
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001407 self.assertEqual(msg.get_sequences(), [])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001408 msg.add_sequence('unseen')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001409 self.assertEqual(msg.get_sequences(), ['unseen'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001410 msg.add_sequence('flagged')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001411 self.assertEqual(msg.get_sequences(), ['unseen', 'flagged'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001412 msg.add_sequence('flagged')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001413 self.assertEqual(msg.get_sequences(), ['unseen', 'flagged'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001414 msg.remove_sequence('unseen')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001415 self.assertEqual(msg.get_sequences(), ['flagged'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001416 msg.add_sequence('foobar')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001417 self.assertEqual(msg.get_sequences(), ['flagged', 'foobar'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001418 msg.remove_sequence('replied')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001419 self.assertEqual(msg.get_sequences(), ['flagged', 'foobar'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001420 msg.set_sequences(['foobar', 'replied'])
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001421 self.assertEqual(msg.get_sequences(), ['foobar', 'replied'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001422
1423
R David Murray088a8742012-04-08 18:34:36 -04001424class TestBabylMessage(TestMessage, unittest.TestCase):
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001425
1426 _factory = mailbox.BabylMessage
1427
1428 def _post_initialize_hook(self, msg):
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001429 self.assertEqual(msg._labels, [])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001430
1431 def test_labels(self):
1432 # Get, set, join, and leave labels
1433 msg = mailbox.BabylMessage(_sample_message)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001434 self.assertEqual(msg.get_labels(), [])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001435 msg.set_labels(['foobar'])
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001436 self.assertEqual(msg.get_labels(), ['foobar'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001437 msg.set_labels([])
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001438 self.assertEqual(msg.get_labels(), [])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001439 msg.add_label('filed')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001440 self.assertEqual(msg.get_labels(), ['filed'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001441 msg.add_label('resent')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001442 self.assertEqual(msg.get_labels(), ['filed', 'resent'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001443 msg.add_label('resent')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001444 self.assertEqual(msg.get_labels(), ['filed', 'resent'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001445 msg.remove_label('filed')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001446 self.assertEqual(msg.get_labels(), ['resent'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001447 msg.add_label('foobar')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001448 self.assertEqual(msg.get_labels(), ['resent', 'foobar'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001449 msg.remove_label('unseen')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001450 self.assertEqual(msg.get_labels(), ['resent', 'foobar'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001451 msg.set_labels(['foobar', 'answered'])
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001452 self.assertEqual(msg.get_labels(), ['foobar', 'answered'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001453
1454 def test_visible(self):
1455 # Get, set, and update visible headers
1456 msg = mailbox.BabylMessage(_sample_message)
1457 visible = msg.get_visible()
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001458 self.assertEqual(visible.keys(), [])
1459 self.assertIs(visible.get_payload(), None)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001460 visible['User-Agent'] = 'FooBar 1.0'
1461 visible['X-Whatever'] = 'Blah'
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001462 self.assertEqual(msg.get_visible().keys(), [])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001463 msg.set_visible(visible)
1464 visible = msg.get_visible()
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001465 self.assertEqual(visible.keys(), ['User-Agent', 'X-Whatever'])
1466 self.assertEqual(visible['User-Agent'], 'FooBar 1.0')
1467 self.assertEqual(visible['X-Whatever'], 'Blah')
1468 self.assertIs(visible.get_payload(), None)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001469 msg.update_visible()
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001470 self.assertEqual(visible.keys(), ['User-Agent', 'X-Whatever'])
1471 self.assertIs(visible.get_payload(), None)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001472 visible = msg.get_visible()
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001473 self.assertEqual(visible.keys(), ['User-Agent', 'Date', 'From', 'To',
1474 'Subject'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001475 for header in ('User-Agent', 'Date', 'From', 'To', 'Subject'):
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001476 self.assertEqual(visible[header], msg[header])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001477
1478
R David Murray088a8742012-04-08 18:34:36 -04001479class TestMMDFMessage(_TestMboxMMDFMessage, TestMessage):
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001480
1481 _factory = mailbox.MMDFMessage
1482
1483
R David Murray088a8742012-04-08 18:34:36 -04001484class TestMessageConversion(TestBase, unittest.TestCase):
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001485
1486 def test_plain_to_x(self):
1487 # Convert Message to all formats
1488 for class_ in (mailbox.Message, mailbox.MaildirMessage,
1489 mailbox.mboxMessage, mailbox.MHMessage,
1490 mailbox.BabylMessage, mailbox.MMDFMessage):
1491 msg_plain = mailbox.Message(_sample_message)
1492 msg = class_(msg_plain)
1493 self._check_sample(msg)
1494
1495 def test_x_to_plain(self):
1496 # Convert all formats to Message
1497 for class_ in (mailbox.Message, mailbox.MaildirMessage,
1498 mailbox.mboxMessage, mailbox.MHMessage,
1499 mailbox.BabylMessage, mailbox.MMDFMessage):
1500 msg = class_(_sample_message)
1501 msg_plain = mailbox.Message(msg)
1502 self._check_sample(msg_plain)
1503
1504 def test_x_to_invalid(self):
1505 # Convert all formats to an invalid format
1506 for class_ in (mailbox.Message, mailbox.MaildirMessage,
1507 mailbox.mboxMessage, mailbox.MHMessage,
1508 mailbox.BabylMessage, mailbox.MMDFMessage):
1509 self.assertRaises(TypeError, lambda: class_(False))
1510
1511 def test_maildir_to_maildir(self):
1512 # Convert MaildirMessage to MaildirMessage
1513 msg_maildir = mailbox.MaildirMessage(_sample_message)
1514 msg_maildir.set_flags('DFPRST')
1515 msg_maildir.set_subdir('cur')
1516 date = msg_maildir.get_date()
1517 msg = mailbox.MaildirMessage(msg_maildir)
1518 self._check_sample(msg)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001519 self.assertEqual(msg.get_flags(), 'DFPRST')
1520 self.assertEqual(msg.get_subdir(), 'cur')
1521 self.assertEqual(msg.get_date(), date)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001522
1523 def test_maildir_to_mboxmmdf(self):
1524 # Convert MaildirMessage to mboxmessage and MMDFMessage
1525 pairs = (('D', ''), ('F', 'F'), ('P', ''), ('R', 'A'), ('S', 'R'),
1526 ('T', 'D'), ('DFPRST', 'RDFA'))
1527 for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
1528 msg_maildir = mailbox.MaildirMessage(_sample_message)
1529 msg_maildir.set_date(0.0)
1530 for setting, result in pairs:
1531 msg_maildir.set_flags(setting)
1532 msg = class_(msg_maildir)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001533 self.assertEqual(msg.get_flags(), result)
1534 self.assertEqual(msg.get_from(), 'MAILER-DAEMON %s' %
1535 time.asctime(time.gmtime(0.0)))
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001536 msg_maildir.set_subdir('cur')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001537 self.assertEqual(class_(msg_maildir).get_flags(), 'RODFA')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001538
1539 def test_maildir_to_mh(self):
1540 # Convert MaildirMessage to MHMessage
1541 msg_maildir = mailbox.MaildirMessage(_sample_message)
1542 pairs = (('D', ['unseen']), ('F', ['unseen', 'flagged']),
1543 ('P', ['unseen']), ('R', ['unseen', 'replied']), ('S', []),
1544 ('T', ['unseen']), ('DFPRST', ['replied', 'flagged']))
1545 for setting, result in pairs:
1546 msg_maildir.set_flags(setting)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001547 self.assertEqual(mailbox.MHMessage(msg_maildir).get_sequences(),
1548 result)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001549
1550 def test_maildir_to_babyl(self):
1551 # Convert MaildirMessage to Babyl
1552 msg_maildir = mailbox.MaildirMessage(_sample_message)
1553 pairs = (('D', ['unseen']), ('F', ['unseen']),
1554 ('P', ['unseen', 'forwarded']), ('R', ['unseen', 'answered']),
1555 ('S', []), ('T', ['unseen', 'deleted']),
1556 ('DFPRST', ['deleted', 'answered', 'forwarded']))
1557 for setting, result in pairs:
1558 msg_maildir.set_flags(setting)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001559 self.assertEqual(mailbox.BabylMessage(msg_maildir).get_labels(),
1560 result)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001561
1562 def test_mboxmmdf_to_maildir(self):
1563 # Convert mboxMessage and MMDFMessage to MaildirMessage
1564 for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
1565 msg_mboxMMDF = class_(_sample_message)
1566 msg_mboxMMDF.set_from('foo@bar', time.gmtime(0.0))
1567 pairs = (('R', 'S'), ('O', ''), ('D', 'T'), ('F', 'F'), ('A', 'R'),
1568 ('RODFA', 'FRST'))
1569 for setting, result in pairs:
1570 msg_mboxMMDF.set_flags(setting)
1571 msg = mailbox.MaildirMessage(msg_mboxMMDF)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001572 self.assertEqual(msg.get_flags(), result)
1573 self.assertEqual(msg.get_date(), 0.0)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001574 msg_mboxMMDF.set_flags('O')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001575 self.assertEqual(mailbox.MaildirMessage(msg_mboxMMDF).get_subdir(),
1576 'cur')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001577
1578 def test_mboxmmdf_to_mboxmmdf(self):
1579 # Convert mboxMessage and MMDFMessage to mboxMessage and MMDFMessage
1580 for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
1581 msg_mboxMMDF = class_(_sample_message)
1582 msg_mboxMMDF.set_flags('RODFA')
1583 msg_mboxMMDF.set_from('foo@bar')
1584 for class2_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
1585 msg2 = class2_(msg_mboxMMDF)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001586 self.assertEqual(msg2.get_flags(), 'RODFA')
1587 self.assertEqual(msg2.get_from(), 'foo@bar')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001588
1589 def test_mboxmmdf_to_mh(self):
1590 # Convert mboxMessage and MMDFMessage to MHMessage
1591 for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
1592 msg_mboxMMDF = class_(_sample_message)
1593 pairs = (('R', []), ('O', ['unseen']), ('D', ['unseen']),
1594 ('F', ['unseen', 'flagged']),
1595 ('A', ['unseen', 'replied']),
1596 ('RODFA', ['replied', 'flagged']))
1597 for setting, result in pairs:
1598 msg_mboxMMDF.set_flags(setting)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001599 self.assertEqual(mailbox.MHMessage(msg_mboxMMDF).get_sequences(),
1600 result)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001601
1602 def test_mboxmmdf_to_babyl(self):
1603 # Convert mboxMessage and MMDFMessage to BabylMessage
1604 for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
1605 msg = class_(_sample_message)
1606 pairs = (('R', []), ('O', ['unseen']),
1607 ('D', ['unseen', 'deleted']), ('F', ['unseen']),
1608 ('A', ['unseen', 'answered']),
1609 ('RODFA', ['deleted', 'answered']))
1610 for setting, result in pairs:
1611 msg.set_flags(setting)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001612 self.assertEqual(mailbox.BabylMessage(msg).get_labels(), result)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001613
1614 def test_mh_to_maildir(self):
1615 # Convert MHMessage to MaildirMessage
1616 pairs = (('unseen', ''), ('replied', 'RS'), ('flagged', 'FS'))
1617 for setting, result in pairs:
1618 msg = mailbox.MHMessage(_sample_message)
1619 msg.add_sequence(setting)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001620 self.assertEqual(mailbox.MaildirMessage(msg).get_flags(), result)
1621 self.assertEqual(mailbox.MaildirMessage(msg).get_subdir(), 'cur')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001622 msg = mailbox.MHMessage(_sample_message)
1623 msg.add_sequence('unseen')
1624 msg.add_sequence('replied')
1625 msg.add_sequence('flagged')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001626 self.assertEqual(mailbox.MaildirMessage(msg).get_flags(), 'FR')
1627 self.assertEqual(mailbox.MaildirMessage(msg).get_subdir(), 'cur')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001628
1629 def test_mh_to_mboxmmdf(self):
1630 # Convert MHMessage to mboxMessage and MMDFMessage
1631 pairs = (('unseen', 'O'), ('replied', 'ROA'), ('flagged', 'ROF'))
1632 for setting, result in pairs:
1633 msg = mailbox.MHMessage(_sample_message)
1634 msg.add_sequence(setting)
1635 for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001636 self.assertEqual(class_(msg).get_flags(), result)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001637 msg = mailbox.MHMessage(_sample_message)
1638 msg.add_sequence('unseen')
1639 msg.add_sequence('replied')
1640 msg.add_sequence('flagged')
1641 for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001642 self.assertEqual(class_(msg).get_flags(), 'OFA')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001643
1644 def test_mh_to_mh(self):
1645 # Convert MHMessage to MHMessage
1646 msg = mailbox.MHMessage(_sample_message)
1647 msg.add_sequence('unseen')
1648 msg.add_sequence('replied')
1649 msg.add_sequence('flagged')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001650 self.assertEqual(mailbox.MHMessage(msg).get_sequences(),
1651 ['unseen', 'replied', 'flagged'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001652
1653 def test_mh_to_babyl(self):
1654 # Convert MHMessage to BabylMessage
1655 pairs = (('unseen', ['unseen']), ('replied', ['answered']),
1656 ('flagged', []))
1657 for setting, result in pairs:
1658 msg = mailbox.MHMessage(_sample_message)
1659 msg.add_sequence(setting)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001660 self.assertEqual(mailbox.BabylMessage(msg).get_labels(), result)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001661 msg = mailbox.MHMessage(_sample_message)
1662 msg.add_sequence('unseen')
1663 msg.add_sequence('replied')
1664 msg.add_sequence('flagged')
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001665 self.assertEqual(mailbox.BabylMessage(msg).get_labels(),
1666 ['unseen', 'answered'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001667
1668 def test_babyl_to_maildir(self):
1669 # Convert BabylMessage to MaildirMessage
1670 pairs = (('unseen', ''), ('deleted', 'ST'), ('filed', 'S'),
1671 ('answered', 'RS'), ('forwarded', 'PS'), ('edited', 'S'),
1672 ('resent', 'PS'))
1673 for setting, result in pairs:
1674 msg = mailbox.BabylMessage(_sample_message)
1675 msg.add_label(setting)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001676 self.assertEqual(mailbox.MaildirMessage(msg).get_flags(), result)
1677 self.assertEqual(mailbox.MaildirMessage(msg).get_subdir(), 'cur')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001678 msg = mailbox.BabylMessage(_sample_message)
1679 for label in ('unseen', 'deleted', 'filed', 'answered', 'forwarded',
1680 'edited', 'resent'):
1681 msg.add_label(label)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001682 self.assertEqual(mailbox.MaildirMessage(msg).get_flags(), 'PRT')
1683 self.assertEqual(mailbox.MaildirMessage(msg).get_subdir(), 'cur')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001684
1685 def test_babyl_to_mboxmmdf(self):
1686 # Convert BabylMessage to mboxMessage and MMDFMessage
1687 pairs = (('unseen', 'O'), ('deleted', 'ROD'), ('filed', 'RO'),
1688 ('answered', 'ROA'), ('forwarded', 'RO'), ('edited', 'RO'),
1689 ('resent', 'RO'))
1690 for setting, result in pairs:
1691 for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
1692 msg = mailbox.BabylMessage(_sample_message)
1693 msg.add_label(setting)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001694 self.assertEqual(class_(msg).get_flags(), result)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001695 msg = mailbox.BabylMessage(_sample_message)
1696 for label in ('unseen', 'deleted', 'filed', 'answered', 'forwarded',
1697 'edited', 'resent'):
1698 msg.add_label(label)
1699 for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001700 self.assertEqual(class_(msg).get_flags(), 'ODA')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001701
1702 def test_babyl_to_mh(self):
1703 # Convert BabylMessage to MHMessage
1704 pairs = (('unseen', ['unseen']), ('deleted', []), ('filed', []),
1705 ('answered', ['replied']), ('forwarded', []), ('edited', []),
1706 ('resent', []))
1707 for setting, result in pairs:
1708 msg = mailbox.BabylMessage(_sample_message)
1709 msg.add_label(setting)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001710 self.assertEqual(mailbox.MHMessage(msg).get_sequences(), result)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001711 msg = mailbox.BabylMessage(_sample_message)
1712 for label in ('unseen', 'deleted', 'filed', 'answered', 'forwarded',
1713 'edited', 'resent'):
1714 msg.add_label(label)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001715 self.assertEqual(mailbox.MHMessage(msg).get_sequences(),
1716 ['unseen', 'replied'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001717
1718 def test_babyl_to_babyl(self):
1719 # Convert BabylMessage to BabylMessage
1720 msg = mailbox.BabylMessage(_sample_message)
1721 msg.update_visible()
1722 for label in ('unseen', 'deleted', 'filed', 'answered', 'forwarded',
1723 'edited', 'resent'):
Tim Peters6d7cd7d2006-04-22 05:52:59 +00001724 msg.add_label(label)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001725 msg2 = mailbox.BabylMessage(msg)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001726 self.assertEqual(msg2.get_labels(), ['unseen', 'deleted', 'filed',
1727 'answered', 'forwarded', 'edited',
1728 'resent'])
1729 self.assertEqual(msg.get_visible().keys(), msg2.get_visible().keys())
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001730 for key in msg.get_visible().keys():
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001731 self.assertEqual(msg.get_visible()[key], msg2.get_visible()[key])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001732
1733
1734class TestProxyFileBase(TestBase):
1735
1736 def _test_read(self, proxy):
1737 # Read by byte
1738 proxy.seek(0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001739 self.assertEqual(proxy.read(), 'bar')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001740 proxy.seek(1)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001741 self.assertEqual(proxy.read(), 'ar')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001742 proxy.seek(0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001743 self.assertEqual(proxy.read(2), 'ba')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001744 proxy.seek(1)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001745 self.assertEqual(proxy.read(-1), 'ar')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001746 proxy.seek(2)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001747 self.assertEqual(proxy.read(1000), 'r')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001748
1749 def _test_readline(self, proxy):
1750 # Read by line
1751 proxy.seek(0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001752 self.assertEqual(proxy.readline(), 'foo' + os.linesep)
1753 self.assertEqual(proxy.readline(), 'bar' + os.linesep)
1754 self.assertEqual(proxy.readline(), 'fred' + os.linesep)
1755 self.assertEqual(proxy.readline(), 'bob')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001756 proxy.seek(2)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001757 self.assertEqual(proxy.readline(), 'o' + os.linesep)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001758 proxy.seek(6 + 2 * len(os.linesep))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001759 self.assertEqual(proxy.readline(), 'fred' + os.linesep)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001760 proxy.seek(6 + 2 * len(os.linesep))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001761 self.assertEqual(proxy.readline(2), 'fr')
1762 self.assertEqual(proxy.readline(-10), 'ed' + os.linesep)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001763
1764 def _test_readlines(self, proxy):
1765 # Read multiple lines
1766 proxy.seek(0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001767 self.assertEqual(proxy.readlines(), ['foo' + os.linesep,
1768 'bar' + os.linesep,
1769 'fred' + os.linesep, 'bob'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001770 proxy.seek(0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001771 self.assertEqual(proxy.readlines(2), ['foo' + os.linesep])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001772 proxy.seek(3 + len(os.linesep))
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001773 self.assertEqual(proxy.readlines(4 + len(os.linesep)),
1774 ['bar' + os.linesep, 'fred' + os.linesep])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001775 proxy.seek(3)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001776 self.assertEqual(proxy.readlines(1000), [os.linesep, 'bar' + os.linesep,
1777 'fred' + os.linesep, 'bob'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001778
1779 def _test_iteration(self, proxy):
1780 # Iterate by line
1781 proxy.seek(0)
1782 iterator = iter(proxy)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001783 self.assertEqual(list(iterator),
1784 ['foo' + os.linesep, 'bar' + os.linesep, 'fred' + os.linesep, 'bob'])
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001785
1786 def _test_seek_and_tell(self, proxy):
1787 # Seek and use tell to check position
1788 proxy.seek(3)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001789 self.assertEqual(proxy.tell(), 3)
1790 self.assertEqual(proxy.read(len(os.linesep)), os.linesep)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001791 proxy.seek(2, 1)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001792 self.assertEqual(proxy.read(1 + len(os.linesep)), 'r' + os.linesep)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001793 proxy.seek(-3 - len(os.linesep), 2)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001794 self.assertEqual(proxy.read(3), 'bar')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001795 proxy.seek(2, 0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001796 self.assertEqual(proxy.read(), 'o' + os.linesep + 'bar' + os.linesep)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001797 proxy.seek(100)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001798 self.assertEqual(proxy.read(), '')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001799
1800 def _test_close(self, proxy):
1801 # Close a file
1802 proxy.close()
R David Murrayf1138bb2011-06-17 22:23:04 -04001803 # Issue 11700 subsequent closes should be a no-op, not an error.
1804 proxy.close()
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001805
1806
R David Murray088a8742012-04-08 18:34:36 -04001807class TestProxyFile(TestProxyFileBase, unittest.TestCase):
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001808
1809 def setUp(self):
1810 self._path = test_support.TESTFN
Andrew M. Kuchling214db632006-05-02 21:44:33 +00001811 self._file = open(self._path, 'wb+')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001812
1813 def tearDown(self):
1814 self._file.close()
1815 self._delete_recursively(self._path)
1816
1817 def test_initialize(self):
1818 # Initialize and check position
1819 self._file.write('foo')
1820 pos = self._file.tell()
1821 proxy0 = mailbox._ProxyFile(self._file)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001822 self.assertEqual(proxy0.tell(), pos)
1823 self.assertEqual(self._file.tell(), pos)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001824 proxy1 = mailbox._ProxyFile(self._file, 0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001825 self.assertEqual(proxy1.tell(), 0)
1826 self.assertEqual(self._file.tell(), pos)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001827
1828 def test_read(self):
1829 self._file.write('bar')
1830 self._test_read(mailbox._ProxyFile(self._file))
1831
1832 def test_readline(self):
1833 self._file.write('foo%sbar%sfred%sbob' % (os.linesep, os.linesep,
1834 os.linesep))
1835 self._test_readline(mailbox._ProxyFile(self._file))
1836
1837 def test_readlines(self):
1838 self._file.write('foo%sbar%sfred%sbob' % (os.linesep, os.linesep,
1839 os.linesep))
1840 self._test_readlines(mailbox._ProxyFile(self._file))
1841
1842 def test_iteration(self):
1843 self._file.write('foo%sbar%sfred%sbob' % (os.linesep, os.linesep,
1844 os.linesep))
1845 self._test_iteration(mailbox._ProxyFile(self._file))
1846
1847 def test_seek_and_tell(self):
1848 self._file.write('foo%sbar%s' % (os.linesep, os.linesep))
1849 self._test_seek_and_tell(mailbox._ProxyFile(self._file))
1850
1851 def test_close(self):
1852 self._file.write('foo%sbar%s' % (os.linesep, os.linesep))
1853 self._test_close(mailbox._ProxyFile(self._file))
1854
1855
R David Murray088a8742012-04-08 18:34:36 -04001856class TestPartialFile(TestProxyFileBase, unittest.TestCase):
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001857
1858 def setUp(self):
1859 self._path = test_support.TESTFN
Andrew M. Kuchling214db632006-05-02 21:44:33 +00001860 self._file = open(self._path, 'wb+')
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001861
1862 def tearDown(self):
1863 self._file.close()
1864 self._delete_recursively(self._path)
1865
1866 def test_initialize(self):
1867 # Initialize and check position
1868 self._file.write('foo' + os.linesep + 'bar')
1869 pos = self._file.tell()
1870 proxy = mailbox._PartialFile(self._file, 2, 5)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001871 self.assertEqual(proxy.tell(), 0)
1872 self.assertEqual(self._file.tell(), pos)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00001873
1874 def test_read(self):
1875 self._file.write('***bar***')
1876 self._test_read(mailbox._PartialFile(self._file, 3, 6))
1877
1878 def test_readline(self):
1879 self._file.write('!!!!!foo%sbar%sfred%sbob!!!!!' %
1880 (os.linesep, os.linesep, os.linesep))
1881 self._test_readline(mailbox._PartialFile(self._file, 5,
1882 18 + 3 * len(os.linesep)))
1883
1884 def test_readlines(self):
1885 self._file.write('foo%sbar%sfred%sbob?????' %
1886 (os.linesep, os.linesep, os.linesep))
1887 self._test_readlines(mailbox._PartialFile(self._file, 0,
1888 13 + 3 * len(os.linesep)))
1889
1890 def test_iteration(self):
1891 self._file.write('____foo%sbar%sfred%sbob####' %
1892 (os.linesep, os.linesep, os.linesep))
1893 self._test_iteration(mailbox._PartialFile(self._file, 4,
1894 17 + 3 * len(os.linesep)))
1895
1896 def test_seek_and_tell(self):
1897 self._file.write('(((foo%sbar%s$$$' % (os.linesep, os.linesep))
1898 self._test_seek_and_tell(mailbox._PartialFile(self._file, 3,
1899 9 + 2 * len(os.linesep)))
1900
1901 def test_close(self):
1902 self._file.write('&foo%sbar%s^' % (os.linesep, os.linesep))
1903 self._test_close(mailbox._PartialFile(self._file, 1,
1904 6 + 3 * len(os.linesep)))
1905
1906
1907## Start: tests from the original module (for backward compatibility).
1908
Skip Montanaro5253da12004-07-24 19:56:03 +00001909FROM_ = "From some.body@dummy.domain Sat Jul 24 13:43:35 2004\n"
Fred Drakec02bc3e2001-05-21 20:23:21 +00001910DUMMY_MESSAGE = """\
1911From: some.body@dummy.domain
1912To: me@my.domain
Skip Montanaro5253da12004-07-24 19:56:03 +00001913Subject: Simple Test
Fred Drakec02bc3e2001-05-21 20:23:21 +00001914
1915This is a dummy message.
1916"""
1917
Fred Drakec02bc3e2001-05-21 20:23:21 +00001918class MaildirTestCase(unittest.TestCase):
1919
1920 def setUp(self):
1921 # create a new maildir mailbox to work with:
1922 self._dir = test_support.TESTFN
1923 os.mkdir(self._dir)
1924 os.mkdir(os.path.join(self._dir, "cur"))
1925 os.mkdir(os.path.join(self._dir, "tmp"))
1926 os.mkdir(os.path.join(self._dir, "new"))
1927 self._counter = 1
1928 self._msgfiles = []
1929
1930 def tearDown(self):
1931 map(os.unlink, self._msgfiles)
1932 os.rmdir(os.path.join(self._dir, "cur"))
1933 os.rmdir(os.path.join(self._dir, "tmp"))
1934 os.rmdir(os.path.join(self._dir, "new"))
1935 os.rmdir(self._dir)
1936
Skip Montanaro5253da12004-07-24 19:56:03 +00001937 def createMessage(self, dir, mbox=False):
Jack Jansen97df7b62001-06-19 20:20:05 +00001938 t = int(time.time() % 1000000)
Fred Drakec02bc3e2001-05-21 20:23:21 +00001939 pid = self._counter
1940 self._counter += 1
Guido van Rossume2ae77b2001-10-24 20:42:55 +00001941 filename = os.extsep.join((str(t), str(pid), "myhostname", "mydomain"))
Fred Drakec02bc3e2001-05-21 20:23:21 +00001942 tmpname = os.path.join(self._dir, "tmp", filename)
1943 newname = os.path.join(self._dir, dir, filename)
Brian Curtin04d8b222010-10-14 01:14:36 +00001944 with open(tmpname, "w") as fp:
1945 self._msgfiles.append(tmpname)
1946 if mbox:
1947 fp.write(FROM_)
1948 fp.write(DUMMY_MESSAGE)
Tim Peters6626c1f2001-05-22 16:29:01 +00001949 if hasattr(os, "link"):
1950 os.link(tmpname, newname)
1951 else:
Brian Curtin04d8b222010-10-14 01:14:36 +00001952 with open(newname, "w") as fp:
1953 fp.write(DUMMY_MESSAGE)
Fred Drakec02bc3e2001-05-21 20:23:21 +00001954 self._msgfiles.append(newname)
Skip Montanaro5253da12004-07-24 19:56:03 +00001955 return tmpname
Fred Drakec02bc3e2001-05-21 20:23:21 +00001956
1957 def test_empty_maildir(self):
1958 """Test an empty maildir mailbox"""
1959 # Test for regression on bug #117490:
1960 # Make sure the boxes attribute actually gets set.
1961 self.mbox = mailbox.Maildir(test_support.TESTFN)
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001962 #self.assertTrue(hasattr(self.mbox, "boxes"))
1963 #self.assertTrue(len(self.mbox.boxes) == 0)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001964 self.assertIs(self.mbox.next(), None)
1965 self.assertIs(self.mbox.next(), None)
Fred Drakec02bc3e2001-05-21 20:23:21 +00001966
1967 def test_nonempty_maildir_cur(self):
1968 self.createMessage("cur")
1969 self.mbox = mailbox.Maildir(test_support.TESTFN)
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001970 #self.assertTrue(len(self.mbox.boxes) == 1)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001971 self.assertIsNot(self.mbox.next(), None)
1972 self.assertIs(self.mbox.next(), None)
1973 self.assertIs(self.mbox.next(), None)
Fred Drakec02bc3e2001-05-21 20:23:21 +00001974
1975 def test_nonempty_maildir_new(self):
1976 self.createMessage("new")
1977 self.mbox = mailbox.Maildir(test_support.TESTFN)
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001978 #self.assertTrue(len(self.mbox.boxes) == 1)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001979 self.assertIsNot(self.mbox.next(), None)
1980 self.assertIs(self.mbox.next(), None)
1981 self.assertIs(self.mbox.next(), None)
Fred Drakec02bc3e2001-05-21 20:23:21 +00001982
1983 def test_nonempty_maildir_both(self):
1984 self.createMessage("cur")
1985 self.createMessage("new")
1986 self.mbox = mailbox.Maildir(test_support.TESTFN)
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001987 #self.assertTrue(len(self.mbox.boxes) == 2)
Antoine Pitrou0da5cb82009-10-31 23:19:52 +00001988 self.assertIsNot(self.mbox.next(), None)
1989 self.assertIsNot(self.mbox.next(), None)
1990 self.assertIs(self.mbox.next(), None)
1991 self.assertIs(self.mbox.next(), None)
Fred Drake0aaed272000-10-23 13:39:15 +00001992
Skip Montanaro5253da12004-07-24 19:56:03 +00001993 def test_unix_mbox(self):
1994 ### should be better!
Georg Brandl5a096e12007-01-22 19:40:21 +00001995 import email.parser
Skip Montanaro5253da12004-07-24 19:56:03 +00001996 fname = self.createMessage("cur", True)
1997 n = 0
1998 for msg in mailbox.PortableUnixMailbox(open(fname),
Georg Brandl5a096e12007-01-22 19:40:21 +00001999 email.parser.Parser().parse):
Skip Montanaro5253da12004-07-24 19:56:03 +00002000 n += 1
2001 self.assertEqual(msg["subject"], "Simple Test")
2002 self.assertEqual(len(str(msg)), len(FROM_)+len(DUMMY_MESSAGE))
2003 self.assertEqual(n, 1)
2004
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00002005## End: classes from the original module (for backward compatibility).
2006
2007
2008_sample_message = """\
2009Return-Path: <gkj@gregorykjohnson.com>
2010X-Original-To: gkj+person@localhost
2011Delivered-To: gkj+person@localhost
2012Received: from localhost (localhost [127.0.0.1])
Tim Peters6d7cd7d2006-04-22 05:52:59 +00002013 by andy.gregorykjohnson.com (Postfix) with ESMTP id 356ED9DD17
2014 for <gkj+person@localhost>; Wed, 13 Jul 2005 17:23:16 -0400 (EDT)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00002015Delivered-To: gkj@sundance.gregorykjohnson.com
2016Received: from localhost [127.0.0.1]
Tim Peters6d7cd7d2006-04-22 05:52:59 +00002017 by localhost with POP3 (fetchmail-6.2.5)
2018 for gkj+person@localhost (single-drop); Wed, 13 Jul 2005 17:23:16 -0400 (EDT)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00002019Received: from andy.gregorykjohnson.com (andy.gregorykjohnson.com [64.32.235.228])
Tim Peters6d7cd7d2006-04-22 05:52:59 +00002020 by sundance.gregorykjohnson.com (Postfix) with ESMTP id 5B056316746
2021 for <gkj@gregorykjohnson.com>; Wed, 13 Jul 2005 17:23:11 -0400 (EDT)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00002022Received: by andy.gregorykjohnson.com (Postfix, from userid 1000)
Tim Peters6d7cd7d2006-04-22 05:52:59 +00002023 id 490CD9DD17; Wed, 13 Jul 2005 17:23:11 -0400 (EDT)
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00002024Date: Wed, 13 Jul 2005 17:23:11 -0400
2025From: "Gregory K. Johnson" <gkj@gregorykjohnson.com>
2026To: gkj@gregorykjohnson.com
2027Subject: Sample message
2028Message-ID: <20050713212311.GC4701@andy.gregorykjohnson.com>
2029Mime-Version: 1.0
2030Content-Type: multipart/mixed; boundary="NMuMz9nt05w80d4+"
2031Content-Disposition: inline
2032User-Agent: Mutt/1.5.9i
2033
2034
2035--NMuMz9nt05w80d4+
2036Content-Type: text/plain; charset=us-ascii
2037Content-Disposition: inline
2038
2039This is a sample message.
2040
Tim Peters6d7cd7d2006-04-22 05:52:59 +00002041--
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00002042Gregory K. Johnson
2043
2044--NMuMz9nt05w80d4+
2045Content-Type: application/octet-stream
2046Content-Disposition: attachment; filename="text.gz"
2047Content-Transfer-Encoding: base64
2048
2049H4sICM2D1UIAA3RleHQAC8nILFYAokSFktSKEoW0zJxUPa7wzJIMhZLyfIWczLzUYj0uAHTs
20503FYlAAAA
2051
2052--NMuMz9nt05w80d4+--
2053"""
2054
2055_sample_headers = {
2056 "Return-Path":"<gkj@gregorykjohnson.com>",
2057 "X-Original-To":"gkj+person@localhost",
2058 "Delivered-To":"gkj+person@localhost",
2059 "Received":"""from localhost (localhost [127.0.0.1])
Tim Peters6d7cd7d2006-04-22 05:52:59 +00002060 by andy.gregorykjohnson.com (Postfix) with ESMTP id 356ED9DD17
2061 for <gkj+person@localhost>; Wed, 13 Jul 2005 17:23:16 -0400 (EDT)""",
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00002062 "Delivered-To":"gkj@sundance.gregorykjohnson.com",
2063 "Received":"""from localhost [127.0.0.1]
Tim Peters6d7cd7d2006-04-22 05:52:59 +00002064 by localhost with POP3 (fetchmail-6.2.5)
2065 for gkj+person@localhost (single-drop); Wed, 13 Jul 2005 17:23:16 -0400 (EDT)""",
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00002066 "Received":"""from andy.gregorykjohnson.com (andy.gregorykjohnson.com [64.32.235.228])
Tim Peters6d7cd7d2006-04-22 05:52:59 +00002067 by sundance.gregorykjohnson.com (Postfix) with ESMTP id 5B056316746
2068 for <gkj@gregorykjohnson.com>; Wed, 13 Jul 2005 17:23:11 -0400 (EDT)""",
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00002069 "Received":"""by andy.gregorykjohnson.com (Postfix, from userid 1000)
Tim Peters6d7cd7d2006-04-22 05:52:59 +00002070 id 490CD9DD17; Wed, 13 Jul 2005 17:23:11 -0400 (EDT)""",
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00002071 "Date":"Wed, 13 Jul 2005 17:23:11 -0400",
2072 "From":""""Gregory K. Johnson" <gkj@gregorykjohnson.com>""",
2073 "To":"gkj@gregorykjohnson.com",
2074 "Subject":"Sample message",
2075 "Mime-Version":"1.0",
2076 "Content-Type":"""multipart/mixed; boundary="NMuMz9nt05w80d4+\"""",
2077 "Content-Disposition":"inline",
2078 "User-Agent": "Mutt/1.5.9i" }
2079
2080_sample_payloads = ("""This is a sample message.
2081
Tim Peters6d7cd7d2006-04-22 05:52:59 +00002082--
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00002083Gregory K. Johnson
2084""",
2085"""H4sICM2D1UIAA3RleHQAC8nILFYAokSFktSKEoW0zJxUPa7wzJIMhZLyfIWczLzUYj0uAHTs
20863FYlAAAA
2087""")
Fred Drake0aaed272000-10-23 13:39:15 +00002088
Fred Drakec02bc3e2001-05-21 20:23:21 +00002089
Fred Drake2e2be372001-09-20 21:33:42 +00002090def test_main():
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00002091 tests = (TestMailboxSuperclass, TestMaildir, TestMbox, TestMMDF, TestMH,
2092 TestBabyl, TestMessage, TestMaildirMessage, TestMboxMessage,
2093 TestMHMessage, TestBabylMessage, TestMMDFMessage,
2094 TestMessageConversion, TestProxyFile, TestPartialFile,
2095 MaildirTestCase)
2096 test_support.run_unittest(*tests)
Neal Norwitzb15ac312006-06-29 04:10:08 +00002097 test_support.reap_children()
Fred Drake2e2be372001-09-20 21:33:42 +00002098
2099
Andrew M. Kuchling1da4a942006-04-22 02:32:43 +00002100if __name__ == '__main__':
Fred Drake2e2be372001-09-20 21:33:42 +00002101 test_main()