Example #1
0
def load_params(args):
    """
    reads the parameter file and creates as list of test objects as well as
    the suite object
    """

    test_list = []

    cp = configparser.ConfigParser()    # note, need strict=False for Python3
    cp.optionxform = str

    log = test_util.Log()

    log.bold("loading " + args.input_file[0])

    try: cp.read(args.input_file[0])
    except:
        log.fail("ERROR: unable to read parameter file {}".format(file))

    # "main" is a special section containing the global suite parameters.
    mysuite = suite.Suite(args)

    mysuite.log = log

    valid_options = list(mysuite.__dict__.keys())

    for opt in cp.options("main"):

        # get the value of the current option
        value = convert_type(cp.get("main", opt))

        if opt in valid_options:

            if opt == "sourceTree":
                if not value in ["C_Src", "F_Src", "BoxLib"]:
                    mysuite.log.fail("ERROR: invalid sourceTree")
                else:
                    mysuite.sourceTree = value

            elif opt == "testTopDir": mysuite.testTopDir = mysuite.check_test_dir(value)
            elif opt == "webTopDir": mysuite.webTopDir = os.path.normpath(value) + "/"

            elif opt == "emailTo": mysuite.emailTo = value.split(",")

            else:
                # generic setting of the object attribute
                setattr(mysuite, opt, value)

        else:
            mysuite.log.warn("suite parameter {} not valid".format(opt))


    # BoxLib -- this will always be defined
    rdir = mysuite.check_test_dir(safe_get(cp, "BoxLib", "dir"))

    branch = convert_type(safe_get(cp, "BoxLib", "branch"))
    rhash = convert_type(safe_get(cp, "BoxLib", "hash"))

    mysuite.repos["BoxLib"] = repo.Repo(mysuite, rdir, "BoxLib",
                                        branch_wanted=branch, hash_wanted=rhash)


    # now all the other build and source directories
    other_srcs = [s for s in cp.sections() if s.startswith("extra-")]
    if not mysuite.sourceTree == "BoxLib": other_srcs.append("source")

    for s in other_srcs:
        if s.startswith("extra-"):
            k = s.split("-")[1]
        else:
            k = "source"

        rdir = mysuite.check_test_dir(safe_get(cp, s, "dir"))
        branch = convert_type(safe_get(cp, s, "branch"))
        rhash = convert_type(safe_get(cp, s, "hash"))

        build = convert_type(safe_get(cp, s, "build", default=0))
        if s == "source": build = 1

        comp_string = safe_get(cp, s, "comp_string")

        name = os.path.basename(os.path.normpath(rdir))

        mysuite.repos[k] = repo.Repo(mysuite, rdir, name,
                                     branch_wanted=branch, hash_wanted=rhash,
                                     build=build, comp_string=comp_string)


    # BoxLib-only tests don't have a sourceDir
    mysuite.boxlib_dir = mysuite.repos["BoxLib"].dir

    if mysuite.sourceTree == "BoxLib":
        mysuite.source_dir = mysuite.repos["BoxLib"].dir
    else:
        mysuite.source_dir = mysuite.repos["source"].dir


    # now flesh out the compile strings -- they may refer to either themselves
    # or the source dir
    for r in mysuite.repos.keys():
        s = mysuite.repos[r].comp_string
        if not s is None:
            mysuite.repos[r].comp_string = \
                s.replace("@self@", mysuite.repos[r].dir).replace("@source@", mysuite.repos["source"].dir)


    # the suite needs to know any ext_src_comp_string
    for r in mysuite.repos.keys():
        if not mysuite.repos[r].build == 1:
            if not mysuite.repos[r].comp_string is None:
                mysuite.extra_src_comp_string += "{} ".format(mysuite.repos[r].comp_string)

    # checks
    if mysuite.sendEmailWhenFail and not args.send_no_email:
        if mysuite.emailTo == [] or mysuite.emailBody == "":
            mysuite.log.fail("ERROR: when sendEmailWhenFail = 1, you must specify emailTo and emailBody\n")

        if mysuite.emailFrom == "":
            mysuite.emailFrom = '@'.join((getpass.getuser(), socket.getfqdn()))

        if mysuite.emailSubject == "":
            mysuite.emailSubject = mysuite.suiteName+" Regression Test Failed"

    if mysuite.slack_post:
        if not os.path.isfile(mysuite.slack_webhookfile):
            mysuite.log.warn("slack_webhookfile invalid")
            mysuite.slack_post = 0
        else:
            print(mysuite.slack_webhookfile)
            try: f = open(mysuite.slack_webhookfile)
            except:
                mysuite.log.warn("unable to open webhook file")
                mysuite.slack_post = 0
            else:
                mysuite.slack_webhook_url = str(f.readline())
                f.close()

    if (mysuite.sourceTree == "" or mysuite.boxlib_dir == "" or
        mysuite.source_dir == "" or mysuite.testTopDir == ""):
        mysuite.log.fail("ERROR: required suite-wide directory not specified\n" + \
                         "(sourceTree, boxLibDir, sourceDir, testTopDir)")

    # Make sure the web dir is valid (or use the default is none specified)
    if mysuite.webTopDir == "":
        mysuite.webTopDir = "{}/{}-web/".format(mysuite.testTopDir, mysuite.suiteName)

    if not os.path.isdir(mysuite.webTopDir):
        try: os.mkdir(mysuite.webTopDir)
        except:
            mysuite.log.fail("ERROR: unable to create the web directory: {}\n".format(
                mysuite.webTopDir))

    # all other sections are tests
    mysuite.log.skip()
    mysuite.log.bold("finding tests and checking parameters...")

    for sec in cp.sections():

        if sec in ["main", "BoxLib", "source"] or sec.startswith("extra-"): continue

        # maximum test name length -- used for HTML formatting
        mysuite.lenTestName = max(mysuite.lenTestName, len(sec))

        # create the test object for this test
        mytest = suite.Test(sec)
        mytest.log = log
        invalid = 0

        # set the test object data by looking at all the options in
        # the current section of the parameter file
        valid_options = list(mytest.__dict__.keys())
        valid_options += ["aux1File", "aux2File", "aux3File"]
        valid_options += ["link1File", "link2File", "link3File"]

        for opt in cp.options(sec):

            # get the value of the current option
            value = convert_type(cp.get(sec, opt))

            if opt in valid_options:

                if opt in ["aux1File", "aux2File", "aux3File"]:
                    mytest.auxFiles.append(value)

                elif opt in ["link1File", "link2File", "link3File"]:
                    mytest.linkFiles.append(value)

                else:
                    # generic setting of the object attribute
                    setattr(mytest, opt, value)

            else:
                mysuite.log.warn("unrecognized parameter {} for test {}".format(opt, sec))


        # make sure that the build directory actually exists
        if not mytest.extra_build_dir == "":
            bdir = mysuite.repos[mytest.extra_build_dir].dir + mytest.buildDir
        else:
            bdir = mysuite.source_dir + mytest.buildDir

        if not os.path.isdir(bdir):
            mysuite.log.warn("invalid build directory: {}".format(bdir))
            invalid = 1


        # make sure all the require parameters are present
        if mytest.compileTest:
            if mytest.buildDir == "":
                mysuite.log.warn("mandatory parameters for test {} not set".format(sec))
                invalid = 1

        else:
            if (mytest.buildDir == "" or mytest.inputFile == "" or
                (mysuite.sourceTree == "C_Src" and mytest.probinFile == "") or
                mytest.dim == -1):
                warn_msg = ["required params for test {} not set".format(sec),
                            "buildDir = {}".format(mytest.buildDir),
                            "inputFile = {}".format(mytest.inputFile)]
                if mysuite.sourceTree == "C_Src":
                    warn_msg += ["probinFile = {}".format(mytest.probinFile)]
                warn_msg += ["dim = {}".format(mytest.dim)]
                mysuite.log.warn(warn_msg)

                invalid = 1

        # check the optional parameters
        if mytest.restartTest and mytest.restartFileNum == -1:
            mysuite.log.warn("restart-test {} needs a restartFileNum".format(sec))
            invalid = 1

        if mytest.selfTest and mytest.stSuccessString == "":
            mysuite.log.warn("self-test {} needs a stSuccessString".format(sec))
            invalid = 1

        if mytest.useMPI and mytest.numprocs == -1:
            mysuite.log.warn("MPI parallel test {} needs numprocs".format(sec))
            invalid = 1

        if mytest.useOMP and mytest.numthreads == -1:
            mysuite.log.warn("OpenMP parallel test {} needs numthreads".format(sec))
            invalid = 1

        if mytest.doVis and mytest.visVar == "":
            mysuite.log.warn("test {} has visualization, needs visVar".format(sec))
            invalid = 1

        if mysuite.sourceTree == "BoxLib" and mytest.testSrcTree == "":
            mysuite.log.warn("testSrcTree not set for BoxLib test {}".format(sec))
            invalid = 1


        # add the current test object to the master list
        if not invalid:
            test_list.append(mytest)
        else:
            mysuite.log.warn("test {} will be skipped".format(sec))


    # if any runs are parallel, make sure that the MPIcommand is defined
    any_MPI = any([t.useMPI for t in test_list])

    if any_MPI and mysuite.MPIcommand == "":
        mysuite.log.fail("ERROR: some tests are MPI parallel, but MPIcommand not defined")

    test_list.sort()

    return mysuite, test_list
Example #2
0
def load_params(args):
    """
    reads the parameter file and creates as list of test objects as well as
    the suite object
    """

    test_list = []

    try:
        cp = configparser.ConfigParser(strict=False)
    except:
        cp = configparser.ConfigParser()

    cp.optionxform = str

    log = test_util.Log(output_file=args.log_file)

    log.bold("loading " + args.input_file[0])

    if not os.path.exists(args.input_file[0]):
        raise OSError(f"Parameter file {args.input_file[0]} does not exist")

    try:
        cp.read(args.input_file[0])
    except:
        log.fail(f"ERROR: unable to read parameter file {args.input_file[0]}")

    # "main" is a special section containing the global suite parameters.
    mysuite = suite.Suite(args)
    log.suite = mysuite
    mysuite.log = log

    valid_options = list(mysuite.__dict__.keys())

    for opt in cp.options("main"):

        # get the value of the current option
        value = convert_type(cp.get("main", opt))

        if opt in valid_options or "_" + opt in valid_options:

            if opt == "sourceTree":
                if not value in ["C_Src", "AMReX", "amrex"]:
                    mysuite.log.fail("ERROR: invalid sourceTree")
                else:
                    mysuite.sourceTree = value

            elif opt == "testTopDir":
                mysuite.testTopDir = mysuite.check_test_dir(value)
                print(f"just set testTopDir = {mysuite.testTopDir}")
            elif opt == "webTopDir":
                mysuite.init_web_dir(value)
            elif opt == "reportCoverage":
                mysuite.reportCoverage = mysuite.reportCoverage or value
            elif opt == "emailTo":
                mysuite.emailTo = value.split(",")
            elif opt == "ftools":
                mysuite.ftools = value.split()
            elif opt == "extra_tools":
                mysuite.extra_tools = value

            else:
                # generic setting of the object attribute
                setattr(mysuite, opt, value)

        else:
            mysuite.log.warn(f"suite parameter {opt} not valid")

    # AMReX -- this will always be defined
    rdir = mysuite.check_test_dir(safe_get(cp, "AMReX", "dir"))

    branch = safe_get(cp, "AMReX", "branch")  # note: always as string
    rhash = convert_type(safe_get(cp, "AMReX", "hash"))

    mysuite.repos["AMReX"] = repo.Repo(mysuite,
                                       rdir,
                                       "AMReX",
                                       branch_wanted=branch,
                                       hash_wanted=rhash)

    if args.amrex_pr is not None:
        mysuite.repos["AMReX"].pr_wanted = args.amrex_pr

    # Check for Cmake build options for both AMReX and Source
    for s in cp.sections():
        if s == "AMReX":
            mysuite.amrex_cmake_opts = safe_get(cp,
                                                s,
                                                "cmakeSetupOpts",
                                                default="")
        elif s == "source":
            mysuite.source_cmake_opts = safe_get(cp,
                                                 s,
                                                 "cmakeSetupOpts",
                                                 default="")

    # now all the other build and source directories
    other_srcs = [s for s in cp.sections() if s.startswith("extra-")]
    if not mysuite.sourceTree in ["AMReX", "amrex"]:
        other_srcs.append("source")

    for s in other_srcs:
        if s.startswith("extra-"):
            k = s.split("-", 1)[1]
        else:
            k = "source"

        rdir = mysuite.check_test_dir(safe_get(cp, s, "dir"))
        branch = safe_get(cp, s, "branch")  # note: always as string
        rhash = convert_type(safe_get(cp, s, "hash"))

        build = convert_type(safe_get(cp, s, "build", default=0))
        if s == "source": build = 1

        comp_string = safe_get(cp, s, "comp_string")

        name = os.path.basename(os.path.normpath(rdir))

        mysuite.repos[k] = repo.Repo(mysuite,
                                     rdir,
                                     name,
                                     branch_wanted=branch,
                                     hash_wanted=rhash,
                                     build=build,
                                     comp_string=comp_string)

    # AMReX-only tests don't have a sourceDir
    mysuite.amrex_dir = mysuite.repos["AMReX"].dir

    if mysuite.sourceTree in ["AMReX", "amrex"]:
        mysuite.source_dir = mysuite.repos["AMReX"].dir
    else:
        mysuite.source_dir = mysuite.repos["source"].dir

    # did we override the branch on the commandline?
    if args.source_branch is not None and args.source_pr is not None:
        mysuite.log.fail(
            "ERROR: cannot specify both source_branch and source_pr")

    if args.source_branch is not None:
        mysuite.repos["source"].branch_wanted = args.source_branch

    if args.source_pr is not None:
        mysuite.repos["source"].pr_wanted = args.source_pr

    # now flesh out the compile strings -- they may refer to either themselves
    # or the source dir
    for r in mysuite.repos.keys():
        s = mysuite.repos[r].comp_string
        if not s is None:
            mysuite.repos[r].comp_string = \
                s.replace("@self@", mysuite.repos[r].dir).replace("@source@", mysuite.repos["source"].dir)

    # the suite needs to know any ext_src_comp_string
    for r in mysuite.repos.keys():
        if not mysuite.repos[r].build == 1:
            if not mysuite.repos[r].comp_string is None:
                mysuite.extra_src_comp_string += f" {mysuite.repos[r].comp_string} "

    # checks
    if args.send_no_email:
        mysuite.sendEmailWhenFail = 0

    if mysuite.sendEmailWhenFail:
        if mysuite.emailTo == [] or mysuite.emailBody == "":
            mysuite.log.fail(
                "ERROR: when sendEmailWhenFail = 1, you must specify emailTo and emailBody\n"
            )

        if mysuite.emailFrom == "":
            mysuite.emailFrom = '@'.join((getpass.getuser(), socket.getfqdn()))

        if mysuite.emailSubject == "":
            mysuite.emailSubject = mysuite.suiteName + " Regression Test Failed"

    if mysuite.slack_post:
        if not os.path.isfile(mysuite.slack_webhookfile):
            mysuite.log.warn("slack_webhookfile invalid")
            mysuite.slack_post = 0
        else:
            print(mysuite.slack_webhookfile)
            try:
                f = open(mysuite.slack_webhookfile)
            except:
                mysuite.log.warn("unable to open webhook file")
                mysuite.slack_post = 0
            else:
                mysuite.slack_webhook_url = str(f.readline())
                f.close()

    if (mysuite.sourceTree == "" or mysuite.amrex_dir == ""
            or mysuite.source_dir == "" or mysuite.testTopDir == ""):
        mysuite.log.fail("ERROR: required suite-wide directory not specified\n" + \
                         "(sourceTree, amrexDir, sourceDir, testTopDir)")

    # Make sure the web dir is valid
    if not os.path.isdir(mysuite.webTopDir):
        try:
            os.mkdir(mysuite.webTopDir)
        except:
            mysuite.log.fail(
                "ERROR: unable to create the web directory: {}\n".format(
                    mysuite.webTopDir))

    # all other sections are tests
    mysuite.log.skip()
    mysuite.log.bold("finding tests and checking parameters...")

    for sec in cp.sections():

        if sec in ["main", "AMReX", "source"] or sec.startswith("extra-"):
            continue

        # maximum test name length -- used for HTML formatting
        mysuite.lenTestName = max(mysuite.lenTestName, len(sec))

        # create the test object for this test
        mytest = suite.Test(sec)
        mytest.log = log
        invalid = 0

        # set the test object data by looking at all the options in
        # the current section of the parameter file
        valid_options = list(mytest.__dict__.keys())
        aux_pat = re.compile(r"aux\d+File")
        link_pat = re.compile(r"link\d+File")

        for opt in cp.options(sec):

            # get the value of the current option
            value = convert_type(cp.get(sec, opt))

            if opt in valid_options or "_" + opt in valid_options:

                if opt == "keyword":
                    mytest.keywords = [k.strip() for k in value.split(",")]

                else:
                    # generic setting of the object attribute
                    setattr(mytest, opt, value)

            elif aux_pat.match(opt):

                mytest.auxFiles.append(value)

            elif link_pat.match(opt):

                mytest.linkFiles.append(value)

            else:

                mysuite.log.warn(
                    f"unrecognized parameter {opt} for test {sec}")

        # make sure that the build directory actually exists
        if not mytest.extra_build_dir == "":
            bdir = mysuite.repos[mytest.extra_build_dir].dir + mytest.buildDir
        else:
            bdir = mysuite.source_dir + mytest.buildDir

        if not os.path.isdir(bdir):
            mysuite.log.warn(f"invalid build directory: {bdir}")
            invalid = 1

        # make sure all the require parameters are present
        if mytest.compileTest:
            if mytest.buildDir == "":
                mysuite.log.warn(
                    f"mandatory parameters for test {sec} not set")
                invalid = 1

        else:

            input_file_invalid = mytest.inputFile == "" and not mytest.run_as_script
            if mytest.buildDir == "" or input_file_invalid or mytest.dim == -1:
                warn_msg = [
                    f"required params for test {sec} not set",
                    f"buildDir = {mytest.buildDir}",
                    f"inputFile = {mytest.inputFile}"
                ]
                warn_msg += [f"dim = {mytest.dim}"]
                mysuite.log.warn(warn_msg)

                invalid = 1

        # check the optional parameters
        if mytest.restartTest and mytest.restartFileNum == -1:
            mysuite.log.warn(f"restart-test {sec} needs a restartFileNum")
            invalid = 1

        if mytest.selfTest and mytest.stSuccessString == "":
            mysuite.log.warn(f"self-test {sec} needs a stSuccessString")
            invalid = 1

        if mytest.useMPI and mytest.numprocs == -1:
            mysuite.log.warn(f"MPI parallel test {sec} needs numprocs")
            invalid = 1

        if mytest.useOMP and mytest.numthreads == -1:
            mysuite.log.warn(f"OpenMP parallel test {sec} needs numthreads")
            invalid = 1

        if mytest.doVis and mytest.visVar == "":
            mysuite.log.warn(f"test {sec} has visualization, needs visVar")
            invalid = 1

        if mysuite.sourceTree in ["AMReX", "amrex"
                                  ] and mytest.testSrcTree == "":
            mysuite.log.warn(f"testSrcTree not set for AMReX test {sec}")
            invalid = 1

        # add the current test object to the master list
        if not invalid:
            test_list.append(mytest)
        else:
            mysuite.log.warn(f"test {sec} will be skipped")

    # if any runs are parallel, make sure that the MPIcommand is defined
    any_MPI = any([t.useMPI for t in test_list])

    if any_MPI and mysuite.MPIcommand == "":
        mysuite.log.fail(
            "ERROR: some tests are MPI parallel, but MPIcommand not defined")

    test_list.sort()

    return mysuite, test_list