Code

Made the email checking spit out a diff - much easier to spot the problem!
[roundup.git] / test / test_mailgw.py
1 #
2 # Copyright (c) 2001 Richard Jones, richard@bofh.asn.au.
3 # This module is free software, and you may redistribute it and/or modify
4 # under the same terms as Python, so long as this copyright message and
5 # disclaimer are retained in their original form.
6 #
7 # This module is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 #
11 # $Id: test_mailgw.py,v 1.15 2002-03-19 06:37:00 richard Exp $
13 import unittest, cStringIO, tempfile, os, shutil, errno, imp, sys, difflib
15 from roundup.mailgw import MailGW
16 from roundup import init, instance
18 # TODO: make this output only enough equal lines for context, not all of
19 # them
20 class DiffHelper:
21     def compareStrings(self, s2, s1):
22         '''Note the reversal of s2 and s1 - difflib.SequenceMatcher wants
23            the first to be the "original" but in the calls in this file,
24            the second arg is the original. Ho hum.
25         '''
26         if s1 == s2:
27             return
28         l1=s1.split('\n')
29         l2=s2.split('\n')
30         s = difflib.SequenceMatcher(None, l1, l2)
31         res = ['Generated message not correct (diff follows):']
32         for value, s1s, s1e, s2s, s2e in s.get_opcodes():
33             if value == 'equal':
34                 for i in range(s1s, s1e):
35                     res.append('  %s'%l1[i])
36             elif value == 'delete':
37                 for i in range(s1s, s1e):
38                     res.append('- %s'%l1[i])
39             elif value == 'insert':
40                 for i in range(s2s, s2e):
41                     res.append('+ %s'%l2[i])
42             elif value == 'replace':
43                 for i, j in zip(range(s1s, s1e), range(s2s, s2e)):
44                     res.append('- %s'%l1[i])
45                     res.append('+ %s'%l2[j])
47         raise AssertionError, '\n'.join(res)
49 class MailgwTestCase(unittest.TestCase, DiffHelper):
50     count = 0
51     schema = 'classic'
52     def setUp(self):
53         MailgwTestCase.count = MailgwTestCase.count + 1
54         self.dirname = '_test_%s'%self.count
55         try:
56             shutil.rmtree(self.dirname)
57         except OSError, error:
58             if error.errno not in (errno.ENOENT, errno.ESRCH): raise
59         # create the instance
60         init.init(self.dirname, self.schema, 'anydbm', 'sekrit')
61         # check we can load the package
62         self.instance = instance.open(self.dirname)
63         # and open the database
64         self.db = self.instance.open('sekrit')
65         self.db.user.create(username='Chef', address='chef@bork.bork.bork')
66         self.db.user.create(username='richard', address='richard@test')
67         self.db.user.create(username='mary', address='mary@test')
68         self.db.user.create(username='john', address='john@test',
69             alternate_addresses='jondoe@test\njohn.doe@test')
71     def tearDown(self):
72         if os.path.exists(os.environ['SENDMAILDEBUG']):
73             os.remove(os.environ['SENDMAILDEBUG'])
74         try:
75             shutil.rmtree(self.dirname)
76         except OSError, error:
77             if error.errno not in (errno.ENOENT, errno.ESRCH): raise
79     def testNewIssue(self):
80         message = cStringIO.StringIO('''Content-Type: text/plain;
81   charset="iso-8859-1"
82 From: Chef <chef@bork.bork.bork
83 To: issue_tracker@fill.me.in.
84 Cc: richard@test
85 Message-Id: <dummy_test_message_id>
86 Subject: [issue] Testing...
88 This is a test submission of a new issue.
89 ''')
90         handler = self.instance.MailGW(self.instance, self.db)
91         handler.main(message)
92         if os.path.exists(os.environ['SENDMAILDEBUG']):
93             error = open(os.environ['SENDMAILDEBUG']).read()
94             self.assertEqual('no error', error)
96     def testAlternateAddress(self):
97         message = cStringIO.StringIO('''Content-Type: text/plain;
98   charset="iso-8859-1"
99 From: John Doe <john.doe@test>
100 To: issue_tracker@fill.me.in.
101 Message-Id: <dummy_test_message_id>
102 Subject: [issue] Testing...
104 This is a test submission of a new issue.
105 ''')
106         userlist = self.db.user.list()
107         handler = self.instance.MailGW(self.instance, self.db)
108         handler.main(message)
109         if os.path.exists(os.environ['SENDMAILDEBUG']):
110             error = open(os.environ['SENDMAILDEBUG']).read()
111             self.assertEqual('no error', error)
112         self.assertEqual(userlist, self.db.user.list(),
113             "user created when it shouldn't have been")
115     def testNewIssueNoClass(self):
116         message = cStringIO.StringIO('''Content-Type: text/plain;
117   charset="iso-8859-1"
118 From: Chef <chef@bork.bork.bork
119 To: issue_tracker@fill.me.in.
120 Cc: richard@test
121 Message-Id: <dummy_test_message_id>
122 Subject: Testing...
124 This is a test submission of a new issue.
125 ''')
126         handler = self.instance.MailGW(self.instance, self.db)
127         handler.main(message)
128         if os.path.exists(os.environ['SENDMAILDEBUG']):
129             error = open(os.environ['SENDMAILDEBUG']).read()
130             self.assertEqual('no error', error)
132     def testNewIssueAuthMsg(self):
133         message = cStringIO.StringIO('''Content-Type: text/plain;
134   charset="iso-8859-1"
135 From: Chef <chef@bork.bork.bork
136 To: issue_tracker@fill.me.in.
137 Message-Id: <dummy_test_message_id>
138 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
140 This is a test submission of a new issue.
141 ''')
142         handler = self.instance.MailGW(self.instance, self.db)
143         # TODO: fix the damn config - this is apalling
144         self.db.config.MESSAGES_TO_AUTHOR = 'yes'
145         handler.main(message)
147         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
148 '''FROM: roundup-admin@fill.me.in.
149 TO: chef@bork.bork.bork, mary@test, richard@test
150 Content-Type: text/plain
151 Subject: [issue1] Testing...
152 To: chef@bork.bork.bork, mary@test, richard@test
153 From: Chef <issue_tracker@fill.me.in.>
154 Reply-To: Roundup issue tracker <issue_tracker@fill.me.in.>
155 MIME-Version: 1.0
156 Message-Id: <dummy_test_message_id>
157 X-Roundup-Name: Roundup issue tracker
158 Content-Transfer-Encoding: quoted-printable
161 New submission from Chef <chef@bork.bork.bork>:
163 This is a test submission of a new issue.
166 ----------
167 assignedto: richard
168 messages: 1
169 nosy: mary, Chef, richard
170 status: unread
171 title: Testing...
172 ___________________________________________________
173 "Roundup issue tracker" <issue_tracker@fill.me.in.>
174 http://some.useful.url/issue1
175 ___________________________________________________
176 ''')
178     # BUG
179     # def testMultipart(self):
180     #         '''With more than one part'''
181     #        see MultipartEnc tests: but if there is more than one part
182     #        we return a multipart/mixed and the boundary contains
183     #        the ip address of the test machine. 
185     # BUG should test some binary attamchent too.
187     def testFollowup(self):
188         self.testNewIssue()
189         message = cStringIO.StringIO('''Content-Type: text/plain;
190   charset="iso-8859-1"
191 From: richard <richard@test>
192 To: issue_tracker@fill.me.in.
193 Message-Id: <followup_dummy_id>
194 In-Reply-To: <dummy_test_message_id>
195 Subject: [issue1] Testing... [assignedto=mary; nosy=john]
197 This is a followup
198 ''')
199         handler = self.instance.MailGW(self.instance, self.db)
200         handler.main(message)
202         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
203 '''FROM: roundup-admin@fill.me.in.
204 TO: chef@bork.bork.bork, mary@test, john@test
205 Content-Type: text/plain
206 Subject: [issue1] Testing...
207 To: chef@bork.bork.bork, mary@test, john@test
208 From: richard <issue_tracker@fill.me.in.>
209 Reply-To: Roundup issue tracker <issue_tracker@fill.me.in.>
210 MIME-Version: 1.0
211 Message-Id: <followup_dummy_id>
212 In-Reply-To: <dummy_test_message_id>
213 X-Roundup-Name: Roundup issue tracker
214 Content-Transfer-Encoding: quoted-printable
217 richard <richard@test> added the comment:
219 This is a followup
222 ----------
223 assignedto:  -> mary
224 nosy: +mary, john
225 status: unread -> chatting
226 ___________________________________________________
227 "Roundup issue tracker" <issue_tracker@fill.me.in.>
228 http://some.useful.url/issue1
229 ___________________________________________________
230 ''')
232     def testFollowup2(self):
233         self.testNewIssue()
234         message = cStringIO.StringIO('''Content-Type: text/plain;
235   charset="iso-8859-1"
236 From: mary <mary@test>
237 To: issue_tracker@fill.me.in.
238 Message-Id: <followup_dummy_id>
239 In-Reply-To: <dummy_test_message_id>
240 Subject: [issue1] Testing...
242 This is a second followup
243 ''')
244         handler = self.instance.MailGW(self.instance, self.db)
245         handler.main(message)
246         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
247 '''FROM: roundup-admin@fill.me.in.
248 TO: chef@bork.bork.bork, richard@test
249 Content-Type: text/plain
250 Subject: [issue1] Testing...
251 To: chef@bork.bork.bork, richard@test
252 From: mary <issue_tracker@fill.me.in.>
253 Reply-To: Roundup issue tracker <issue_tracker@fill.me.in.>
254 MIME-Version: 1.0
255 Message-Id: <followup_dummy_id>
256 In-Reply-To: <dummy_test_message_id>
257 X-Roundup-Name: Roundup issue tracker
258 Content-Transfer-Encoding: quoted-printable
261 mary <mary@test> added the comment:
263 This is a second followup
266 ----------
267 status: unread -> chatting
268 ___________________________________________________
269 "Roundup issue tracker" <issue_tracker@fill.me.in.>
270 http://some.useful.url/issue1
271 ___________________________________________________
272 ''')
274     def testFollowupTitleMatch(self):
275         self.testNewIssue()
276         message = cStringIO.StringIO('''Content-Type: text/plain;
277   charset="iso-8859-1"
278 From: richard <richard@test>
279 To: issue_tracker@fill.me.in.
280 Message-Id: <followup_dummy_id>
281 In-Reply-To: <dummy_test_message_id>
282 Subject: Re: Testing... [assignedto=mary; nosy=john]
284 This is a followup
285 ''')
286         handler = self.instance.MailGW(self.instance, self.db)
287         handler.main(message)
289         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
290 '''FROM: roundup-admin@fill.me.in.
291 TO: chef@bork.bork.bork, mary@test, john@test
292 Content-Type: text/plain
293 Subject: [issue1] Testing...
294 To: chef@bork.bork.bork, mary@test, john@test
295 From: richard <issue_tracker@fill.me.in.>
296 Reply-To: Roundup issue tracker <issue_tracker@fill.me.in.>
297 MIME-Version: 1.0
298 Message-Id: <followup_dummy_id>
299 In-Reply-To: <dummy_test_message_id>
300 X-Roundup-Name: Roundup issue tracker
301 Content-Transfer-Encoding: quoted-printable
304 richard <richard@test> added the comment:
306 This is a followup
309 ----------
310 assignedto:  -> mary
311 nosy: +mary, john
312 status: unread -> chatting
313 ___________________________________________________
314 "Roundup issue tracker" <issue_tracker@fill.me.in.>
315 http://some.useful.url/issue1
316 ___________________________________________________
317 ''')
319     def testEnc01(self):
320         self.testNewIssue()
321         message = cStringIO.StringIO('''Content-Type: text/plain;
322   charset="iso-8859-1"
323 From: mary <mary@test>
324 To: issue_tracker@fill.me.in.
325 Message-Id: <followup_dummy_id>
326 In-Reply-To: <dummy_test_message_id>
327 Subject: [issue1] Testing...
328 Content-Type: text/plain;
329         charset="iso-8859-1"
330 Content-Transfer-Encoding: quoted-printable
332 A message with encoding (encoded oe =F6)
334 ''')
335         handler = self.instance.MailGW(self.instance, self.db)
336         handler.main(message)
337         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
338 '''FROM: roundup-admin@fill.me.in.
339 TO: chef@bork.bork.bork, richard@test
340 Content-Type: text/plain
341 Subject: [issue1] Testing...
342 To: chef@bork.bork.bork, richard@test
343 From: mary <issue_tracker@fill.me.in.>
344 Reply-To: Roundup issue tracker <issue_tracker@fill.me.in.>
345 MIME-Version: 1.0
346 Message-Id: <followup_dummy_id>
347 In-Reply-To: <dummy_test_message_id>
348 X-Roundup-Name: Roundup issue tracker
349 Content-Transfer-Encoding: quoted-printable
352 mary <mary@test> added the comment:
354 A message with encoding (encoded oe =F6)
356 ----------
357 status: unread -> chatting
358 ___________________________________________________
359 "Roundup issue tracker" <issue_tracker@fill.me.in.>
360 http://some.useful.url/issue1
361 ___________________________________________________
362 ''')
365     def testMultipartEnc01(self):
366         self.testNewIssue()
367         message = cStringIO.StringIO('''Content-Type: text/plain;
368   charset="iso-8859-1"
369 From: mary <mary@test>
370 To: issue_tracker@fill.me.in.
371 Message-Id: <followup_dummy_id>
372 In-Reply-To: <dummy_test_message_id>
373 Subject: [issue1] Testing...
374 Content-Type: multipart/mixed;
375         boundary="----_=_NextPart_000_01"
377 This message is in MIME format. Since your mail reader does not understand
378 this format, some or all of this message may not be legible.
380 ------_=_NextPart_000_01
381 Content-Type: text/plain;
382         charset="iso-8859-1"
383 Content-Transfer-Encoding: quoted-printable
385 A message with first part encoded (encoded oe =F6)
387 ''')
388         handler = self.instance.MailGW(self.instance, self.db)
389         handler.main(message)
390         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
391 '''FROM: roundup-admin@fill.me.in.
392 TO: chef@bork.bork.bork, richard@test
393 Content-Type: text/plain
394 Subject: [issue1] Testing...
395 To: chef@bork.bork.bork, richard@test
396 From: mary <issue_tracker@fill.me.in.>
397 Reply-To: Roundup issue tracker <issue_tracker@fill.me.in.>
398 MIME-Version: 1.0
399 Message-Id: <followup_dummy_id>
400 In-Reply-To: <dummy_test_message_id>
401 X-Roundup-Name: Roundup issue tracker
402 Content-Transfer-Encoding: quoted-printable
405 mary <mary@test> added the comment:
407 A message with first part encoded (encoded oe =F6)
409 ----------
410 status: unread -> chatting
411 ___________________________________________________
412 "Roundup issue tracker" <issue_tracker@fill.me.in.>
413 http://some.useful.url/issue1
414 ___________________________________________________
415 ''')
417 class ExtMailgwTestCase(MailgwTestCase):
418     schema = 'extended'
420 def suite():
421     l = [unittest.makeSuite(MailgwTestCase, 'test'),
422 #         unittest.makeSuite(ExtMailgwTestCase, 'test')
423     ]
424     return unittest.TestSuite(l)
428 # $Log: not supported by cvs2svn $
429 # Revision 1.14  2002/03/18 18:32:00  rochecompaan
430 # All messages sent to the nosy list are now encoded as quoted-printable.
432 # Revision 1.13  2002/02/15 07:08:45  richard
433 #  . Alternate email addresses are now available for users. See the MIGRATION
434 #    file for info on how to activate the feature.
436 # Revision 1.12  2002/02/15 00:13:38  richard
437 #  . #503204 ] mailgw needs a default class
438 #     - partially done - the setting of additional properties can wait for a
439 #       better configuration system.
441 # Revision 1.11  2002/02/14 23:38:12  richard
442 # Fixed the unit tests for the mailgw re: the x-roundup-name header.
443 # Also made the test runner more user-friendly:
444 #   ./run_tests            - detect all tests in test/test_<name>.py and run them
445 #   ./run_tests <name>     - run only test/test_<name>.py
446 # eg ./run_tests mailgw    - run the mailgw test from test/test_mailgw.py
448 # Revision 1.10  2002/02/12 08:08:55  grubert
449 #  . Clean up mail handling, multipart handling.
451 # Revision 1.9  2002/02/05 14:15:29  grubert
452 #  . respect encodings in non multipart messages.
454 # Revision 1.8  2002/02/04 09:40:21  grubert
455 #  . add test for multipart messages with first part being encoded.
457 # Revision 1.7  2002/01/22 11:54:45  rochecompaan
458 # Fixed status change in mail gateway.
460 # Revision 1.6  2002/01/21 10:05:48  rochecompaan
461 # Feature:
462 #  . the mail gateway now responds with an error message when invalid
463 #    values for arguments are specified for link or multilink properties
464 #  . modified unit test to check nosy and assignedto when specified as
465 #    arguments
467 # Fixed:
468 #  . fixed setting nosy as argument in subject line
470 # Revision 1.5  2002/01/15 00:12:40  richard
471 # #503340 ] creating issue with [asignedto=p.ohly]
473 # Revision 1.4  2002/01/14 07:12:15  richard
474 # removed file writing from tests...
476 # Revision 1.3  2002/01/14 02:20:15  richard
477 #  . changed all config accesses so they access either the instance or the
478 #    config attriubute on the db. This means that all config is obtained from
479 #    instance_config instead of the mish-mash of classes. This will make
480 #    switching to a ConfigParser setup easier too, I hope.
482 # At a minimum, this makes migration a _little_ easier (a lot easier in the
483 # 0.5.0 switch, I hope!)
485 # Revision 1.2  2002/01/11 23:22:29  richard
486 #  . #502437 ] rogue reactor and unittest
487 #    in short, the nosy reactor was modifying the nosy list. That code had
488 #    been there for a long time, and I suspsect it was there because we
489 #    weren't generating the nosy list correctly in other places of the code.
490 #    We're now doing that, so the nosy-modifying code can go away from the
491 #    nosy reactor.
493 # Revision 1.1  2002/01/02 02:31:38  richard
494 # Sorry for the huge checkin message - I was only intending to implement #496356
495 # but I found a number of places where things had been broken by transactions:
496 #  . modified ROUNDUPDBSENDMAILDEBUG to be SENDMAILDEBUG and hold a filename
497 #    for _all_ roundup-generated smtp messages to be sent to.
498 #  . the transaction cache had broken the roundupdb.Class set() reactors
499 #  . newly-created author users in the mailgw weren't being committed to the db
501 # Stuff that made it into CHANGES.txt (ie. the stuff I was actually working
502 # on when I found that stuff :):
503 #  . #496356 ] Use threading in messages
504 #  . detectors were being registered multiple times
505 #  . added tests for mailgw
506 #  . much better attaching of erroneous messages in the mail gateway
511 # vim: set filetype=python ts=4 sw=4 et si