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

Jgfouca/scripts/support easy updating of any acme test category #87

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
72 changes: 72 additions & 0 deletions scripts/acme/acme_util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"""
Common functions used by acme python scripts
"""

import sys

_VERBOSE = False

###############################################################################
def expect(condition, error_msg):
###############################################################################
"""
Similar to assert except doesn't generate an ugly stacktrace. Useful for
checking user error, not programming error.
"""
if (not condition):
raise SystemExit(error_msg)

###############################################################################
def warning(msg):
###############################################################################
print >> sys.stderr, "WARNING:", msg

###############################################################################
def verbose_print(msg, override=None):
###############################################################################
if ( (_VERBOSE and not override is False) or override):
print msg

###############################################################################
def set_verbosity(verbose):
###############################################################################
global _VERBOSE
_VERBOSE = verbose

###############################################################################
def run_cmd(cmd, ok_to_fail=False, input_str=None, from_dir=None, verbose=None):
###############################################################################
import subprocess # Not safe to do globally, module not available in older pythons

verbose_print("RUN: %s" % cmd, verbose)

if (input_str is not None):
stdin = subprocess.PIPE
else:
stdin = None

proc = subprocess.Popen(cmd,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=stdin,
cwd=from_dir)
output, errput = proc.communicate()
stat = proc.wait()

verbose_print(" stat: %d\n" % stat, verbose)
verbose_print(" output: %s\n" % output, verbose)
verbose_print(" errput: %s\n" % errput, verbose)

if (ok_to_fail):
return stat, output, errput
else:
expect(stat == 0, "Command: '%s' failed with error '%s'" % (cmd, errput))
return output

###############################################################################
def check_minimum_python_version(major, minor):
###############################################################################
expect(sys.version_info.major == major and sys.version_info.minor >= minor,
"Python %d.%d+ is required, you have %d.%d" %
(major, minor, sys.version_info.major, sys.version_info.minor))
123 changes: 0 additions & 123 deletions scripts/acme/update_acme_developer

This file was deleted.

156 changes: 156 additions & 0 deletions scripts/acme/update_acme_tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#!/usr/bin/env python

"""This script recreates and acme suite within the CESM testlist.xml
file, which should be given as the only argument. It deletes any
existing category from the XML file, draws from information within
this file to create new test entries, and then inserts these entries
into the XML file."""

import acme_util
acme_util.check_minimum_python_version(2, 7)

import sys, argparse, os, shutil, tempfile, subprocess

from acme_util import expect, warning, verbose_print

# Here are the tests belonging to acme suites. Format is
# <test>.<grid>.<compset>
TEST_SUITES = {
"acme_developer" :
['ERS.f19_g16_rx1.A',
'ERS.f45_g37.B1850C5',
'ERS.f45_g37_rx1.DTEST',
'ERS.ne30_g16_rx1.A',
'ERS_D.f45_g37.B1850C5',
'ERS_IOP.f19_g16_rx1.A',
'ERS_IOP.f45_g37_rx1.DTEST',
'ERS_IOP.ne30_g16_rx1.A',
'ERS_IOP4c.f19_g16_rx1.A',
'ERS_IOP4c.ne30_g16_rx1.A',
'ERS_IOP4p.f19_g16_rx1.A',
'ERS_IOP4p.ne30_g16_rx1.A',
'ERS_Ly21.f09_g16.TG',
'NCK.f19_g16_rx1.A',
'PEA_P1_M.f45_g37_rx1.A',
'SMS.ne30_f19_g16_rx1.A'],
"acme_integration" :
["ERB.f19_g16.B1850C5",
"ERB.f45_g37.B1850C5",
"ERH.f45_g37.B1850C5",
"ERS.f09_g16.B1850C5",
"ERS.f19_f19.FAMIPC5",
"ERS.f19_g16.B1850C5",
"ERS.f45_g37.B1850C5",
"ERS_D.f45_g37.B1850C5",
"ERS_IOP.f19_g16_rx1.A",
"ERS_IOP.f45_g37_rx1.DTEST",
"ERS_IOP.ne30_g16_rx1.A",
"ERS_IOP4c.f19_g16_rx1.A",
"ERS_IOP4c.ne30_g16_rx1.A",
"ERS_IOP4p.f19_g16_rx1.A",
"ERS_IOP4p.ne30_g16_rx1.A",
"ERS_IOP_Ld3.f19_f19.FAMIPC5",
"ERS_Ld3.f19_g16.FC5",
"ERS_Ld3.ne30_ne30.FC5",
"ERS_Ly21.f09_g16.TG",
"ERT.f19_g16.B1850C5",
"NCK.f19_g16_rx1.A",
"PEA_P1_M.f45_g37_rx1.A",
"PET_PT.f19_g16.X",
"PET_PT.f45_g37_rx1.A",
"PFS.ne30_ne30.FC5",
"SEQ_IOP_PFC.f19_g16.X",
"SEQ_PFC.f45_g37.B1850C5",
"SMS.ne16_ne16.FC5AQUAP",
"SMS.ne30_f19_g16_rx1.A",
"SMS_D.f19_g16.B20TRC5",
"SMS_D_Ld3.f19_f19.FC5"]
}

###############################################################################
def find_all_machines(xml_file):
###############################################################################
f = open(xml_file, 'r')
lines = f.readlines()
f.close()
machine_set = set()
for line in lines:
if '<machine' in line:
i1 = line.index('compiler') + len('compiler="')
i2 = line.index('"', i1)
compiler = line[i1:i2]
j1 = line.index('>') + 1
j2 = line.index('<', j1)
machine = line[j1:j2]
machine_set.add((machine, compiler))
return [m for m in machine_set]

###############################################################################
def replace_testlist_xml(output, xml_file):
###############################################################################
# manage_xml_entries creates a temporary file intended for people to manually check the
# changes. This made sense before revision control, but not anymore.
if 'now writing the new test list to' in output:
i1 = output.index('now writing') + len('now writing the new test list to ')
i2 = output.index('xml') + 3
new_xml_file = output[i1:i2]
shutil.move(new_xml_file, xml_file)

###############################################################################
def generate_acme_test_entries(category, machines):
###############################################################################
tests = TEST_SUITES[category]
test_file = tempfile.NamedTemporaryFile(mode='w', delete = False)
for test in tests:
for machine, compiler in machines:
test_file.write('%s.%s_%s\n'%(test, machine, compiler))
name = test_file.name
test_file.close()
return name

###############################################################################
def update_acme_test(xml_file, category):
###############################################################################
# Fish all of the existing machine/compiler combos out of the XML file.
machines = find_all_machines(xml_file)

# Try to find the manage_xml_entries script. Assume sibling of xml_file
manage_xml_entries = os.path.join(os.path.dirname(xml_file), "manage_xml_entries")
expect(os.path.isfile(manage_xml_entries),
"Couldn't find manage_xml_entries, expect sibling of '%s'" % xml_file)

# Remove any existing acme test category from the file.
output = acme_util.run_cmd('%s -removetests -category %s' % (manage_xml_entries, category))
replace_testlist_xml(output, xml_file)

# Generate a list of test entries corresponding to our suite at the top
# of the file.
new_test_file = generate_acme_test_entries(category, machines)
output = acme_util.run_cmd("%s -addlist -file %s -category %s" %
(manage_xml_entries, new_test_file, category))
os.unlink(new_test_file)
replace_testlist_xml(output, xml_file)

###############################################################################
def _main_func(description):
###############################################################################
parser = argparse.ArgumentParser(
usage="\n%s <Test category> testlist.xml" % os.path.basename(sys.argv[0]),
description=description,
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)

parser.add_argument("category", choices=TEST_SUITES.keys(),
help="The test category to update")

parser.add_argument("test_list_path", help="The path to test lists XML file")

args = parser.parse_args()

expect(os.path.isfile(args.test_list_path),
"'%s' is not a valid file" % args.test_list_path)

update_acme_test(args.test_list_path, args.category)

if __name__ == "__main__":
_main_func(__doc__)
Loading