benchmark.py 3.76 KB
Newer Older
1 2 3 4 5 6 7 8 9 10

import sys
import email
import smtplib
import optparse
import platform
import datetime
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText

11
from neo.lib import logger
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

MAIL_SERVER = '127.0.0.1:25'

class AttributeDict(dict):

    def __getattr__(self, item):
        return self.__getitem__(item)

class BenchmarkRunner(object):
    """
        Base class for a command-line benchmark test runner.
    """

    def __init__(self):
        self._successful = True
        self._status = []
        parser = optparse.OptionParser()
        # register common options
        parser.add_option('', '--title')
        parser.add_option('-v', '--verbose', action='store_true')
        parser.add_option('', '--mail-to', action='append')
        parser.add_option('', '--mail-from')
        parser.add_option('', '--mail-server')
35
        parser.add_option('', '--repeat', type='int', default=1)
36 37 38 39 40 41 42 43 44
        self.add_options(parser)
        # check common arguments
        options, self._args = parser.parse_args()
        if bool(options.mail_to) ^ bool(options.mail_from):
            sys.exit('Need a sender and recipients to mail report')
        mail_server = options.mail_server or MAIL_SERVER
        # check specifics arguments
        self._config = AttributeDict()
        self._config.update(self.load_options(options, self._args))
45
        self._config.update(
46
            title = options.title or self.__class__.__name__,
47
            verbose = bool(options.verbose),
48 49 50
            mail_from = options.mail_from,
            mail_to = options.mail_to,
            mail_server = mail_server.split(':'),
51
            repeat = options.repeat,
52
        )
53 54 55 56 57

    def add_status(self, key, value):
        self._status.append((key, value))

    def build_report(self, content):
58
        fmt = "%-25s : %s"
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
        status = "\n".join([fmt % item for item in [
            ('Title', self._config.title),
            ('Date', datetime.date.today().isoformat()),
            ('Node', platform.node()),
            ('Machine', platform.machine()),
            ('System', platform.system()),
            ('Python', platform.python_version()),
        ]])
        status += '\n\n'
        status += "\n".join([fmt % item for item in self._status])
        return "%s\n\n%s" % (status, content)

    def send_report(self, subject, report):
        # build report
        # build email
        msg = MIMEMultipart()
        msg['Subject'] = '%s: %s' % (self._config.title, subject)
        msg['From'] = self._config.mail_from
        msg['To'] = ', '.join(self._config.mail_to)
        msg['X-ERP5-Tests'] = 'NEO'
        if self._successful:
            msg['X-ERP5-Tests-Status'] = 'OK'
        msg.epilogue = ''
        msg.attach(MIMEText(report))

        # send it
        s = smtplib.SMTP()
        s.connect(*self._config.mail_server)
        mail = msg.as_string()
        for recipient in self._config.mail_to:
            try:
                s.sendmail(self._config.mail_from, recipient, mail)
            except smtplib.SMTPRecipientsRefused:
                print "Mail for %s fails" % recipient
        s.close()

    def run(self):
96
        logger.PACKET_LOGGER.enable(self._config.verbose)
97 98 99 100 101
        subject, report = self.start()
        report = self.build_report(report)
        if self._config.mail_to:
            self.send_report(subject, report)
        print subject
102
        print
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
        print report

    def was_successful(self):
        return self._successful

    def add_options(self, parser):
        """ Append options to command line parser """
        raise NotImplementedError

    def load_options(self, options, args):
        """ Check options and return a configuration dict """
        raise NotImplementedError

    def start(self):
        """ Run the test """
        raise NotImplementedError