#!/usr/bin/env python3
"""
Script containing CIME python regression test suite. This suite should be run
to confirm overall CIME correctness.
"""
import glob, os, re, shutil, signal, sys, tempfile, threading, time, logging, unittest, getpass, filecmp, time, atexit, functools
CIMEROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
sys.path.insert(0, CIMEROOT)
from xml.etree.ElementTree import ParseError
import subprocess, argparse
subprocess.call('/bin/rm -f $(find . -name "*.pyc")', shell=True, cwd=CIMEROOT)
import stat as osstat
import collections
from CIME.utils import (
run_cmd,
run_cmd_no_fail,
get_lids,
get_current_commit,
safe_copy,
CIMEError,
get_cime_root,
get_src_root,
Timeout,
import_from_file,
get_model,
)
import CIME.test_scheduler, CIME.wait_for_tests
from CIME import get_tests
from CIME.test_scheduler import TestScheduler
from CIME.XML.env_run import EnvRun
from CIME.XML.machines import Machines
from CIME.XML.files import Files
from CIME.case import Case
from CIME.code_checker import check_code, get_all_checkable_files
from CIME.test_status import *
from CIME.provenance import get_test_success, save_test_success
from CIME import utils
from CIME.tests.base import BaseTestCase
from CIME.config import Config
os.environ["CIME_GLOBAL_WALLTIME"] = "0:05:00"
TEST_RESULT = None
[docs]
def write_provenance_info(machine, test_compiler, test_mpilib, test_root):
curr_commit = get_current_commit(repo=CIMEROOT)
logging.info("Testing commit %s" % curr_commit)
cime_model = get_model()
logging.info("Using cime_model = %s" % cime_model)
logging.info("Testing machine = %s" % machine.get_machine_name())
if test_compiler is not None:
logging.info("Testing compiler = %s" % test_compiler)
if test_mpilib is not None:
logging.info("Testing mpilib = %s" % test_mpilib)
logging.info("Test root: %s" % test_root)
logging.info("Test driver: %s" % CIME.utils.get_cime_default_driver())
logging.info("Python version {}\n".format(sys.version))
[docs]
def cleanup(test_root):
if (
os.path.exists(test_root)
and TEST_RESULT is not None
and TEST_RESULT.wasSuccessful()
):
testreporter = os.path.join(test_root, "testreporter")
files = os.listdir(test_root)
if len(files) == 1 and os.path.isfile(testreporter):
os.unlink(testreporter)
if not os.listdir(test_root):
print("All pass, removing directory:", test_root)
os.rmdir(test_root)
[docs]
def setup_arguments(parser):
parser.add_argument(
"--fast",
action="store_true",
help="Skip full system tests, which saves a lot of time",
)
parser.add_argument(
"--no-batch",
action="store_true",
help="Do not submit jobs to batch system, run locally."
" If false, will default to machine setting.",
)
parser.add_argument(
"--no-fortran-run",
action="store_true",
help="Do not run any fortran jobs. Implies --fast" " Used for github actions",
)
parser.add_argument(
"--no-cmake", action="store_true", help="Do not run cmake tests"
)
parser.add_argument(
"--no-teardown",
action="store_true",
help="Do not delete directories left behind by testing",
)
parser.add_argument(
"--machine", help="Select a specific machine setting for cime", default=None
)
parser.add_argument(
"--compiler", help="Select a specific compiler setting for cime", default=None
)
parser.add_argument(
"--mpilib", help="Select a specific compiler setting for cime", default=None
)
parser.add_argument(
"--test-root",
help="Select a specific test root for all cases created by the testing",
default=None,
)
parser.add_argument(
"--timeout",
type=int,
help="Select a specific timeout for all tests",
default=None,
)
def _main_func(description):
help_str = """
{0} [TEST] [TEST]
OR
{0} --help
\033[1mEXAMPLES:\033[0m
\033[1;32m# Run the full suite \033[0m
> {0}
\033[1;32m# Run single test file (with or without extension) \033[0m
> {0} test_unit_doctest
\033[1;32m# Run single test class from a test file \033[0m
> {0} test_unit_doctest.TestDocs
\033[1;32m# Run single test case from a test class \033[0m
> {0} test_unit_doctest.TestDocs.test_lib_docs
""".format(
os.path.basename(sys.argv[0])
)
parser = argparse.ArgumentParser(
usage=help_str,
description=description,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
setup_arguments(parser)
parser.add_argument("--verbose", action="store_true", help="Enable verbose logging")
parser.add_argument("--debug", action="store_true", help="Enable debug logging")
parser.add_argument("--silent", action="store_true", help="Disable all logging")
parser.add_argument(
"tests", nargs="*", help="Specific tests to run e.g. test_unit*"
)
ns, args = parser.parse_known_args()
# Now set the sys.argv to the unittest_args (leaving sys.argv[0] alone)
sys.argv[1:] = args
utils.configure_logging(ns.verbose, ns.debug, ns.silent)
configure_tests(**vars(ns))
os.chdir(CIMEROOT)
if len(ns.tests) == 0:
test_root = os.path.join(CIMEROOT, "CIME", "tests")
test_suite = unittest.defaultTestLoader.discover(test_root)
else:
# Fixes handling shell expansion e.g. test_unit_*, by removing python extension
tests = [x.replace(".py", "").replace("/", ".") for x in ns.tests]
# Try to load tests by just names
test_suite = unittest.defaultTestLoader.loadTestsFromNames(tests)
test_runner = unittest.TextTestRunner(verbosity=2)
global TEST_RESULT
TEST_RESULT = test_runner.run(test_suite)
# Implements same behavior as unittesst.main
# https://github.com/python/cpython/blob/b6d68aa08baebb753534a26d537ac3c0d2c21c79/Lib/unittest/main.py#L272-L273
sys.exit(not TEST_RESULT.wasSuccessful())
if __name__ == "__main__":
_main_func(__doc__)