#
# Copyright(c) 2001-2003, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
# Written by Gary Kumfert <kumfert@llnl.gov>.
# UCRL-CODE-2002-043.
# All rights reserved.
#
# This file is part of Gantlet.  For details, see 
# http://www.llnl.gov/CASC/components/software.html or contact the author.
#
# Gantlet is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License (as published by 
# the Free Software Foundation) version 2.1 dated February 1999.
#
# Gantlet is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even IMPLIED WARRANTY OF MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the terms and conditions of
# the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this software; if not, write to the Free Software Foundation, 
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# ADDITIONAL NOTICE:
# 
# A. This notice is required to be provided under our contract with the
#    U.S. Department of Energy (DOE).  This work was produced at the 
#    University of California, Lawrence Livermore National Laboratory
#    under Contract No. W-7405-ENG-48 with the DOE.
#
# B. Neither the United States Government nor the University of California
#    nor any of their employees make any warranty, express or implied, or
#    assumes any liability or responsibility for the accuracy, completeness, 
#    or usefulness of any information, apparatus, product, or process 
#    disclosed, or represents that its use would not infringe on 
#    privately-owned rights.
# 
# C. Also, reference herein to any specific commercial products, process, or
#    services by trade name, trademark, manufacturer or otherwise does not
#    necessarily constitute or imply its endoresement, recommendation, or
#    favoring by the United States Government or the University of California.
#    The views and opinions of authors expressed herein do not necessarily 
#    state or reflect those of the United States Government or the University
#    of California, and shall not be used for advertising or product 
#    endorsement purposes.

import string
import sys
import getopt
import os
import socket # to get hostname

import gantlet
from gantlet.session_archiver import session_archiver, EntrySort
from email_display import email_display, rfc822time
from sys import maxint
from time import strptime, mktime, time

html_begin='''
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Gantlet Test Results</title>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  </head>
  <body>
'''

col_head = {
    'date':'<th width="100" rowspan="2">date</th>',
    'profile':'<th width="150" rowspan="2">profile</th>',
    'session':'<th width="100" rowspan="2">session</th>',
    'package':'<th width="100" rowspan="2">package</th>',
    'time':'<th width="100" rowspan="2">time</th>',
    'path':'<th rowspan="2">path</th>'}

table_begin='''
    <table border="3">
      <tr>
        %s
        <th colspan="5">Tests</th>
        <th colspan="4">Parts</th>
      </tr>
      <tr>
        <th width="50">Total</th>
        <th width="50">Pass</th>
        <th width="50">Xfail</th>
        <th width="50">Fail</th>
        <th width="50">Broken</th>
        <th width="50">Total</th>
        <th width="50">Pass</th>
        <th width="50">Xfail</th>
        <th width="50">Fail</th>
      </tr>      
'''

table_end="""
    </table><hr>
"""

html_end="""
    <address>Generated By Gantlet %s<br>
             Gary Kumfert, Ph.D. &lt;<a href=\"mailto:kumfert@llnl.gov\">kumfert@llnl.gov</a>&gt;<br>
             Lawrence Livermore National Laboratory <a href=\"http://www.llnl.gov\">http://www.llnl.gov</a>
    </address>  
  </body>
</html>
"""%gantlet.VERSION

color = { 'none':'',
          'green':' bgcolor="#aaffaa"',
          'yellow':' bgcolor="#ffffaa"',
          'red':' bgcolor="#ffaaaa"'}
data = [ 'total_tests', 'passed_tests', 'xfailed_tests', 'failed_tests', \
         'broken_tests', 'total_parts', 'passed_parts', 'xfailed_parts', \
         'failed_parts' ]

class html_viewer:
    def __init__( self, sort_order=['profile','session','date'],
                  break_tables_on='package', display_order=['date','profile','session'] ):
        self.rev_sort_order = []
        self.rev_sort_order.extend(sort_order)
        self.rev_sort_order.reverse()
        self.break_tables_on = break_tables_on
        self.display_order = display_order

    def sort_msgs(self, msgs ):
        foo = None
        for key in self.rev_sort_order:
            foo = EntrySort( key, foo )        
        msgs.sort( foo )
        return msgs
        
    def html_page(self, f, msgs):
        """write an HTML page"""
        f.write(html_begin)
        table = {}
        for msg in msgs:
            if not table.has_key( msg[ self.break_tables_on ]):
                table[ msg[ self.break_tables_on ] ] = []
            table[ msg[ self.break_tables_on ]].append(msg)

        msgnames = table.keys()
        msgnames.sort()
        for msgname in msgnames:
            msgs = self.sort_msgs( table[ msgname ] )            
            self.html_table( f, msgname, msgs )
        f.write(html_end)
                      
    def html_table( self, f, tablehead, msgs ):
        """ write an HTML table"""
        
        f.write("  <h1>%s test results</h1>\n" % tablehead )
        str = ""
        for cat in self.display_order:
            if col_head.has_key( cat ):
                str = str + col_head[ cat ]
            else:
                str = str + '<th width="100" rowspan="2">' + cat + '</th>'
        f.write(table_begin%str)
        for msg in msgs:
            f.write(self.html_line( f, msg ))
        f.write(table_end)
    
    def html_line( self, f, msg ):
        colormap = { 'total_tests':color['none'], \
                     'passed_tests':color['green'], \
                     'xfailed_tests':color['yellow'], \
                     'failed_tests':color['red'], \
                     'broken_tests':color['red'], \
                     'total_parts':color['none'], \
                     'passed_parts':color['green'], \
                     'xfailed_parts':color['yellow'], \
                     'failed_parts':color['red'] }
        front=[]
        cells=[]
        sum = 0
        for cat in self.display_order:
            if cat == 'path':
                front.append('<td><a href="%s">[File]</a></td>'%msg[cat])
            else:
                front.append("<td>%s</td>"%msg[cat])
        for test in data:
            i=int(msg[test])    
            if i>0:
                cells.append('<td align="right"%s>%d</td>'%(colormap[test],i) )
            else:
                cells.append('<td align="right">0</td>')
            sum = sum+i
        if sum==0:
            cells=[]
            cells.append("<th colspan=9%s>BROKEN</th>" % color['red'] )
        cells = front + cells
        line = "      <tr>\n        %s      </tr>\n" % string.join(cells,'\n        ')
        return line
    

help_string="""
HELP

 -h   | --help                       Display this message
 -v   | --verbose                    Verbose
 -r<> | --repository=<>              <>=string, path to where Gantlet sessions
                                      are stored (default=\".\")
 -o<> | --output=<>                  <>=string, path to where html is generated
                                      (default=\"index.html\"
 -e<> | --email=<>                   <>=string, send email to this address
 -m<> | --mailserver=<>              <>=string, domain name of SMTP server
 -d<> | --display-order=<>           <>=comma separated list of attributes
 -s<> | --sort-order=<>              <>=comma separated list of attributes
 -l<> | --select=<>                  <>=attributes (see below)
 -b<> | --break-tables-on=<>         <>=attribute
 -t   | --today                      select only todays tests

 attributes = { time, package, session, profile, date,path }
 NOTE: --select works by regex on package, profile, session, and
         date attributes.  Default is
         --select=package=.*,profile=.*,session=.*,date=.*
 """

shortopts="hvr:o:d:s:e:m:b:tl:"
longopts=["help","verbose","repository","output","display-order","sort-order","email","mailserver","break-tables-on","today","select"]

std_header = 'From: %s\nTo: %s\nDate: %s\nSubject: %s\nMIME-Version: 1.0\nContent-Type: text/html; charset=iso-8859-1\n'

def parse_date(datestr):
    if (datestr):
        if (datestr == "24 hours"):
            now = time()
            return (now - 24*60*60, now)
        else:
            tm = strptime(datestr,"%Y-%m-%d")
            if (tm):
                t = mktime(tm)
                return (t, t + 24*60*60)
    return (0, maxint)

def _test():
    verbose=0
    repository = "."
    output = "index.html"
    display=['session','profile','hostname','date','time','path']
    sort=['session','profile']
    breakon='package'
    email=None
    mailserver=None
    selectdate=None
    selectpackage=".*"
    selectprofile=".*"
    selectsession=".*"
    selects=[]
    (opts,args)=getopt.getopt(sys.argv[1:],shortopts,longopts)
    for (o,v) in opts:
        if o in ("-h","--help"):
            print help_string
            sys.exit(0)
        elif o in ("-v", "--verbose"):
            verbose=1
        elif o in ("-r","--repository"):
            repository=v
        elif o in ("-o","--output"):
            output=v
        elif o in ("-d","--display"):
            display=v.split(',')
        elif o in ("-s","--sort-order"):
            sort=v.split(',')
        elif o in ("-b","--break-tables-on"):
            breakon=v
        elif o in ("-e","--email"):
            email=v
        elif o in ("-m","--mailserver"):
            mailserver=v
        elif o in ("-b","--break-tables-on"):
            breakon=v
        elif o in ("-t","--today"):
            selectdate="24 hours"
        elif o in ("-l","--select"):
            selects = v.split(',')
            for s in selects:
                (x,y)=s.split('=')
                if x == "package":
                    selectpackage=y
                elif x == "profile":
                    selectprofile=y
                elif x == "session":
                    selectsession=y
                elif x == "date":
                    selectdate=y
                else:
                    print "Unrecognized select option:", x

    mgr = session_archiver( repository )
    daterange = parse_date(selectdate)
    msgs = mgr.select(package=selectpackage,profile=selectprofile,
                      session=selectsession,
                      starttime=daterange[0], endtime=daterange[1])
    f = open(output,'w')
    viewer = html_viewer(break_tables_on=breakon,
                         display_order=display,
                         sort_order=sort
                         )
    viewer.html_page( f, msgs )
    f.close()
    
    if not( email == None or mailserver == None):
        f = open(output,'r')
        e = email_display( None, email, mailserver)
        e.file = f
        e.verbose = verbose
        whoami = 'unknown'
        try:
            whoami = os.getlogin()
        except:
            pass
        hostname = socket.getfqdn()
        email_from = whoami + "@" + hostname
        date = rfc822time()
        subject="Gantlet Results"
        header=std_header %( email_from, email, date, subject )
        e.email_from = email_from
        e.email_to = email
        e.email_file_via_SMTP(header)

    f.close()

if __name__ == '__main__': _test()

