Home | History | Annotate | Download | only in test
      1 #!/usr/bin/env python
      2 
      3 """
      4 Run the test suite and send the result as an email message.
      5 
      6 The code for sending of the directory is copied from
      7 http://docs.python.org/library/email-examples.html.
      8 """
      9 
     10 import os
     11 import sys
     12 import shutil
     13 import smtplib
     14 # For guessing MIME type based on file name extension
     15 import mimetypes
     16 
     17 from optparse import OptionParser
     18 
     19 from email import encoders
     20 from email.message import Message
     21 from email.mime.audio import MIMEAudio
     22 from email.mime.base import MIMEBase
     23 from email.mime.image import MIMEImage
     24 from email.mime.multipart import MIMEMultipart
     25 from email.mime.text import MIMEText
     26 
     27 def runTestsuite(testDir, sessDir, envs = None):
     28     """Run the testsuite and return a (summary, output) tuple."""
     29     os.chdir(testDir)
     30 
     31     for env in envs:
     32         list = env.split('=')
     33         var = list[0].strip()
     34         val = list[1].strip()
     35         print var + "=" + val
     36         os.environ[var] = val
     37 
     38     import shlex, subprocess
     39 
     40     command_line = "./dotest.py -w -s %s" % sessDir
     41     # Apply correct tokenization for subprocess.Popen().
     42     args = shlex.split(command_line)
     43 
     44     # Use subprocess module to spawn a new process.
     45     process = subprocess.Popen(args,
     46                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     47     # Wait for subprocess to terminate.
     48     stdout, stderr = process.communicate()
     49     
     50     # This will be used as the subject line of our email about this test.
     51     cmd = "%s %s" % (' '.join(envs) if envs else "", command_line)
     52 
     53     return (cmd, stderr)
     54 
     55 
     56 COMMASPACE = ', '
     57 
     58 def main():
     59     parser = OptionParser(usage="""\
     60 Run lldb test suite and send the results as a MIME message.
     61 
     62 Usage: %prog [options]
     63 
     64 Unless the -o option is given, the email is sent by forwarding to the specified
     65 SMTP server, which then does the normal delivery process.
     66 """)
     67     parser.add_option('-d', '--directory',
     68                       type='string', action='store',
     69                       dest='testDir',
     70                       help="""The LLDB test directory directly under the top dir.
     71                       Otherwise use the current directory.""")
     72     #
     73     # This is similar to TestBase.getRunSpec(self) from lldbtest.py.
     74     #
     75     parser.add_option('-e', '--environment',
     76                       type='string', action='append', metavar='ENVIRONMENT',
     77                       default=[], dest='environments',
     78                       help="""The environment setting as prefix to the test driver.
     79                       Example: -e 'CC=clang' -e 'ARCH=x86_64'""")
     80     parser.add_option('-m', '--mailserver',
     81                       type='string', action='store', metavar='MAILSERVER',
     82                       dest='mailserver',
     83                       help="""The outgoing SMTP server.""")
     84     parser.add_option('-o', '--output',
     85                       type='string', action='store', metavar='FILE',
     86                       help="""Print the composed message to FILE instead of
     87                       sending the message to the SMTP server.""")
     88     parser.add_option('-s', '--sender',
     89                       type='string', action='store', metavar='SENDER',
     90                       help='The value of the From: header (required)')
     91     parser.add_option('-r', '--recipient',
     92                       type='string', action='append', metavar='RECIPIENT',
     93                       default=[], dest='recipients',
     94                       help='A To: header value (at least one required)')
     95     opts, args = parser.parse_args()
     96     if not opts.sender or not opts.recipients:
     97         parser.print_help()
     98         sys.exit(1)
     99     testDir = opts.testDir
    100     if not testDir:
    101         testDir = '.'
    102 
    103     sessDir = 'tmp-lldb-session'
    104     if os.path.exists(sessDir):
    105         shutil.rmtree(sessDir)
    106     #print "environments:", opts.environments
    107     summary, output = runTestsuite(testDir, sessDir, opts.environments)
    108 
    109     # Create the enclosing (outer) message
    110     outer = MIMEMultipart()
    111     outer['Subject'] = summary
    112     outer['To'] = COMMASPACE.join(opts.recipients)
    113     outer['From'] = opts.sender
    114     outer.preamble = 'You will not see this in a MIME-aware mail reader.\n'
    115 
    116     # The sessDir contains all the session logs for failed/errored tests.
    117     # Attach them all if it exists!
    118 
    119     if not os.path.exists(sessDir):
    120         outer.attach(MIMEText(output, 'plain'))
    121     else:
    122         outer.attach(MIMEText("%s\n%s\n\n" % (output,
    123                                               "Session logs of test failures/errors:"),
    124                               'plain'))
    125 
    126     for filename in (os.listdir(sessDir) if os.path.exists(sessDir) else []):
    127         path = os.path.join(sessDir, filename)
    128         if not os.path.isfile(path):
    129             continue
    130         # Guess the content type based on the file's extension.  Encoding
    131         # will be ignored, although we should check for simple things like
    132         # gzip'd or compressed files.
    133         ctype, encoding = mimetypes.guess_type(path)
    134         if ctype is None or encoding is not None:
    135             # No guess could be made, or the file is encoded (compressed), so
    136             # use a generic bag-of-bits type.
    137             ctype = 'application/octet-stream'
    138         maintype, subtype = ctype.split('/', 1)
    139         if maintype == 'text':
    140             fp = open(path)
    141             # Note: we should handle calculating the charset
    142             msg = MIMEText(fp.read(), _subtype=subtype)
    143             fp.close()
    144         elif maintype == 'image':
    145             fp = open(path, 'rb')
    146             msg = MIMEImage(fp.read(), _subtype=subtype)
    147             fp.close()
    148         elif maintype == 'audio':
    149             fp = open(path, 'rb')
    150             msg = MIMEAudio(fp.read(), _subtype=subtype)
    151             fp.close()
    152         else:
    153             fp = open(path, 'rb')
    154             msg = MIMEBase(maintype, subtype)
    155             msg.set_payload(fp.read())
    156             fp.close()
    157             # Encode the payload using Base64
    158             encoders.encode_base64(msg)
    159         # Set the filename parameter
    160         msg.add_header('Content-Disposition', 'attachment', filename=filename)
    161         outer.attach(msg)
    162 
    163     # Now send or store the message
    164     composed = outer.as_string()
    165     if opts.output:
    166         fp = open(opts.output, 'w')
    167         fp.write(composed)
    168         fp.close()
    169     else:
    170         s = smtplib.SMTP(opts.mailserver)
    171         s.sendmail(opts.sender, opts.recipients, composed)
    172         s.quit()
    173 
    174 
    175 if __name__ == '__main__':
    176     main()
    177