Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

testreporter rewrite to python #1299

Merged
merged 6 commits into from
Apr 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
228 changes: 228 additions & 0 deletions scripts/Tools/testreporter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
#!/usr/bin/env python
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow the template of other python scripts in cime. Each script has a test to see if it was called directly
or from another python, and it has a parse_command_line subroutine which includes code for the standard cime options. I think that create_clone provides a simple example.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Followed the template for python scripts. create_clone was a good simple example.


"""

Simple script to populate CESM test database with test results.

"""

from standard_script_setup import *

from CIME.XML.env_build import EnvBuild
from CIME.XML.env_case import EnvCase
from CIME.XML.env_test import EnvTest
from CIME.XML.test_reporter import TestReporter
from CIME.utils import expect
from CIME.XML.generic_xml import GenericXML


import glob



###############################################################################
def parse_command_line(args):
###############################################################################
parser = argparse.ArgumentParser()

CIME.utils.setup_standard_logging_options(parser)

# Parse command line options

# parser = argparse.ArgumentParser(description='Arguements for testreporter')
parser.add_argument("--tagname",
help="Name of the tag being tested.")
parser.add_argument("--testid",
help="Test id, ie c2_0_a6g_ing,c2_0_b6g_gnu.")
parser.add_argument("--testroot",
help="Root directory for tests to populate the database.")
parser.add_argument("--testtype",
help="Type of test, prealpha or prebeta.")
parser.add_argument("--dryrun",action="store_true",
help="Do a dry run, database will not be populated.")
parser.add_argument("--dumpxml",action="store_true",
help="Dump XML test results to sceen.")
args = parser.parse_args()
CIME.utils.handle_standard_logging_options(args)


return args.testroot, args.testid, args.tagname, args.testtype, args.dryrun, args.dumpxml

###############################################################################
def get_testreporter_xml(testroot, testid, tagname, testtype):
###############################################################################
os.chdir(testroot)

#
# Retrieve compiler name and mpi library
#
xml_file=glob.glob("*"+testid+"/env_build.xml")
expect(len(xml_file) > 0, "Tests not found. It's possible your testid, %s is wrong." %testid )
envxml=(EnvBuild(".",infile=xml_file[0]))
compiler=envxml.get_value("COMPILER")
mpilib=envxml.get_value("MPILIB")

#
# Retrieve machine name
#
xml_file=glob.glob("*"+testid+"/env_case.xml")
envxml=(EnvCase(".",infile=xml_file[0]))
machine=envxml.get_value("MACH")

#
# Retrieve baseline tag to compare to
#
xml_file=glob.glob("*"+testid+"/env_test.xml")
envxml=(EnvTest(".",infile=xml_file[0]))
baseline = envxml.get_value("BASELINE_NAME_CMP")

#
# Create XML header
#

testxml=TestReporter()
testxml.setup_header(tagname,machine,compiler,mpilib,testroot,testtype,baseline)

#
# Create lists on tests based on the testid in the testroot directory.
#
test_names=glob.glob("*"+testid)
#
# Loop over all tests and parse the test results
#
test_status={}
for test_name in test_names:
if not os.path.isfile(test_name+"/TestStatus"):
continue
test_status['COMMENT']=""
test_status['BASELINE']='----'
test_status['MEMCOMP']='----'
test_status['MEMLEAK']='----'
test_status['NLCOMP']='----'
test_status['STATUS']='----'
test_status['TPUTCOMP']='----'
#
# Check to see if TestStatus is present, if not then continue
# I might want to set the status to fail
#
try:
lines = [line.rstrip('\n') for line in open(test_name+"/TestStatus")]
except:
test_status['STATUS']="FAIL"
test_status['COMMENT']="TestStatus missing. "
continue
#
# Loop over each line of TestStatus, and check for different types of failures.
#
for line in lines:
if "NLCOMP" in line:
test_status['NLCOMP']=line[0:4]
if "MEMLEAK" in line:
test_status['MEMLEAK']=line[0:4]
if "MEMCOMP" in line:
test_status['MEMCOMP']=line[0:4]
if "BASELINE" in line:
test_status['BASELINE']=line[0:4]
if "TPUTCOMP" in line:
test_status['TPUTCOMP']=line[0:4]
if "INIT" in line:
test_status['INIT']=line[0:4]
if line[0:4] == "FAIL":
test_status['STATUS']="SFAIL"
test_status['COMMENT']+="INIT fail! "
break
if "CREATE_NEWCASE" in line:
test_status['CREATE_NEWCASE']=line[0:4]
if line[0:4] == "FAIL":
test_status['STATUS']="SFAIL"
test_status['COMMENT']+="CREATE_NEWCASE fail! "
break
if "XML" in line:
test_status['XML']=line[0:4]
if line[0:4] == "FAIL":
test_status['STATUS']="SFAIL"
test_status['COMMENT']+="XML fail! "
break
if "SETUP" in line:
test_status['SETUP']=line[0:4]
if line[0:4] == "FAIL":
test_status['STATUS']="SFAIL"
test_status['COMMENT']+="SETUP fail! "
break
if "SHAREDLIB_BUILD" in line:
test_status['SHAREDLIB_BUILD']=line[0:4]
if line[0:4] == "FAIL":
test_status['STATUS']="CFAIL"
test_status['COMMENT']+="SHAREDLIB_BUILD fail! "
break
if "MODEL_BUILD" in line:
test_status['MODEL_BUILD']=line[0:4]
if line[0:4] == "FAIL":
test_status['STATUS']="CFAIL"
test_status['COMMENT']+="MODEL_BUILD fail! "
break
if "SUBMIT" in line:
test_status['STATUS']=line[0:4]
if line[0:4] == "FAIL":
test_status['COMMENT']+="SUBMIT fail! "
break
if "RUN" in line:
test_status['STATUS']=line[0:4]
if line[0:4] == "FAIL":
test_status['COMMENT']+="RUN fail! "
break
if "COMPARE_base_rest" in line:
test_status['STATUS']=line[0:4]
if line[0:4] == "FAIL":
test_status['COMMENT']+="Restart fail! "
break
if "COMPARE_base_hybrid" in line:
test_status['STATUS']=line[0:4]
if line[0:4] == "FAIL":
test_status['COMMENT']+="Hybrid fail! "
break

#
# Do not include time comments. Just a preference to have cleaner comments in the test database
#
try:
if 'time=' not in line:
test_status['COMMENT']+=line.split(' ',3)[3]+' '
except:
pass

#
# Fill in the xml with the test results
#
testxml.add_result(test_name,test_status)

return testxml


##############################################################################
def _main_func():
###############################################################################

testroot, testid, tagname, testtype, dryrun, dumpxml = parse_command_line(sys.argv)

testxml = get_testreporter_xml(testroot, testid, tagname, testtype)

#
# Dump xml to a file.
#
if dumpxml:
GenericXML.write(testxml,outfile="TestRecord.xml")


#
# Prompt for username and password, then post the XML string to the test database website
#
if not dryrun:
testxml.push2testdb()

###############################################################################

if __name__ == "__main__":
_main_func()


113 changes: 113 additions & 0 deletions scripts/lib/CIME/XML/test_reporter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
"""
Interface to the testreporter xml. This class inherits from GenericXML.py

"""

from CIME.XML.standard_module_setup import *
from CIME.XML.generic_xml import GenericXML
from CIME.utils import expect,get_model

import urllib



class TestReporter(GenericXML):

def __init__(self):
"""
initialize an object
"""

expect(get_model() == 'cesm', "testreport is only meant to populate the CESM test database." )
self.root = None

GenericXML.__init__(self)

def setup_header(self, tagname,machine,compiler,mpilib,testroot,testtype,baseline):
#
# Create the XML header that the testdb is expecting to recieve
#
tlelem = ET.Element("testrecord")
elem = ET.Element('tag_name')
elem.text = tagname
tlelem.append(elem)
elem = ET.Element('mach')
elem.text = machine
tlelem.append(elem)
elem = ET.Element('compiler',attrib={"version":""})
elem.text = compiler
tlelem.append(elem)
elem = ET.Element('mpilib',attrib={"version":""})
elem.text = mpilib
tlelem.append(elem)
elem = ET.Element('testroot')
elem.text = testroot
tlelem.append(elem)
elem = ET.Element('testtype')
elem.text = testtype
tlelem.append(elem)
elem = ET.Element('baselinetag')
elem.text = baseline
tlelem.append(elem)

self.root=tlelem


def add_result(self,test_name,test_status):
#
# Add a test result to the XML structure.
#
tlelem = ET.Element('tests',attrib={"testname":test_name})
elem=ET.Element('category',attrib={"name":"casestatus"})
tlelem.append(elem)
elem=ET.Element('category',attrib={"name":"comment"})
elem.text= test_status['COMMENT']
tlelem.append(elem)

elem=ET.Element('category',attrib={"name":"compare"})
elem.text= test_status['BASELINE']
tlelem.append(elem)

elem=ET.Element('category',attrib={"name":"memcomp"})
elem.text= test_status['MEMCOMP']
tlelem.append(elem)

elem=ET.Element('category',attrib={"name":"memleak"})
elem.text= test_status['MEMLEAK']
tlelem.append(elem)

elem=ET.Element('category',attrib={"name":"nlcomp"})
elem.text= test_status['NLCOMP']
tlelem.append(elem)

elem=ET.Element('category',attrib={"name":"status"})
elem.text= test_status['STATUS']
tlelem.append(elem)

elem=ET.Element('category',attrib={"name":"tputcomp"})
elem.text= test_status['TPUTCOMP']
tlelem.append(elem)

self.root.append(tlelem)



def push2testdb(self):
#
# Post test result XML to CESM test database
#
xmlstr = ET.tostring(self.root,method="xml",encoding="UTF-8")
username=raw_input("Username:")
os.system("stty -echo")
password=raw_input("Password:")
os.system("stty echo")
params={'username':username,'password':password,'testXML':xmlstr}
url="https://csegweb.cgd.ucar.edu/testdb/cgi-bin/processXMLtest.cgi"
params = urllib.urlencode(params)
f = urllib.urlopen(url, params)
#
# Print any messages from the post command
#
print f.read()
print f.code

17 changes: 11 additions & 6 deletions scripts/lib/CIME/test_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
they can be run outside the context of TestScheduler.
"""

import shutil, traceback, stat, threading, time, glob
import traceback, stat, threading, time, glob
from CIME.XML.standard_module_setup import *
import CIME.compare_namelists
import CIME.utils
Expand Down Expand Up @@ -774,11 +774,16 @@ def _setup_cs_files(self):
os.chmod(cs_submit_file,
os.stat(cs_submit_file).st_mode | stat.S_IXUSR | stat.S_IXGRP)

if get_model == "cesm":
testreporter = os.path.join(self._test_root,"testreporter.pl")
shutil.copy(os.path.join(self._cime_root,"scripts","Testing","testreporter.pl"),
testreporter)
os.chmod(testreporter, os.stat(testreporter).st_mode | stat.S_IXUSR | stat.S_IXGRP)
if get_model() == "cesm":
template_file = os.path.join(python_libs_root, "testreporter.template")
template = open(template_file, "r").read()
template = template.replace("<PATH>",
os.path.join(self._cime_root, "scripts", "Tools"))
testreporter_file = os.path.join(self._test_root, "testreporter")
with open(testreporter_file, "w") as fd:
fd.write(template)
os.chmod(testreporter_file, os.stat(testreporter_file).st_mode
| stat.S_IXUSR | stat.S_IXGRP)

except Exception as e:
logger.warning("FAILED to set up cs files: %s" % str(e))
Expand Down
3 changes: 3 additions & 0 deletions scripts/lib/testreporter.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#! /bin/bash

<PATH>/testreporter.py "$@"