def create_system_yaml(name): """ create YAML configuration for binary test for system package """ BUILDTEST_CONFIGS_REPO = config_opts['BUILDTEST_CONFIGS_REPO'] destdir = os.path.join(BUILDTEST_CONFIGS_REPO, "system", name) yamlfile = os.path.join(destdir, "command.yaml") # if yaml file exists then exit out if os.path.isfile(yamlfile): print "YAML file already exists, please check: ", yamlfile sys.exit(0) # if directory is not present then create it create_dir(destdir) # if package is not installed if check_system_package_installed(name) == False: print "Please install system package:", name, " before creating YAML file" sys.exit(0) # get binary from system package binary = get_binaries_from_systempackage(name) # no test, then stop immediately if len(binary) == 0: print "There are no binaries found in package: ", name sys.exit(0) fd = open(yamlfile, "w") binarydict = {"binaries": binary} with open(yamlfile, 'a') as outfile: yaml.dump(binarydict, outfile, default_flow_style=False) print "Please check YAML file", yamlfile, " and fix test accordingly" sys.exit(0)
def setup_system_cmake(pkg): BUILDTEST_TESTDIR = config_opts['BUILDTEST_TESTDIR'] # top level system directory and system package directory test_system_dir=os.path.join(BUILDTEST_TESTDIR,"system") test_destdir=os.path.join(BUILDTEST_TESTDIR,"system",pkg) # top level CMakeLists.txt in testing directory test_cmakelist = os.path.join(BUILDTEST_TESTDIR,"CMakeLists.txt") # CMakeLists.txt that contains all system package directories to process test_cmakelist_pkg = os.path.join(BUILDTEST_TESTDIR,"system","CMakeLists.txt") # CMakeLists.txt that contais the actual tests (add_test) test_cmakelist_destdir=os.path.join(test_destdir,"CMakeLists.txt") logger = logging.getLogger(logID) logger.debug("Variables Assignments") logger.debug("----------------------------------") logger.debug("SYSTEM Test Directory: %s ", test_system_dir) logger.debug("Testscript Destination Directory: %s", test_destdir) logger.debug("CMakeList for BUILDTEST_TESTDIR: %s ", test_cmakelist) logger.debug("CMakeList for $BUILDTEST_TESTDIR/system: %s", test_cmakelist_pkg) logger.debug("CMakeList for $BUILDTEST_TESTDIR/system/%s: %s" , pkg, test_cmakelist_destdir) # if testdirectory exist, delete and recreate it inorder for reproducible test builds if os.path.isdir(test_destdir): shutil.rmtree(test_destdir) logger.debug("Removing directory: %s before creating tests ", test_destdir) # create the directories if they don't exist create_dir(test_system_dir) create_dir(test_destdir) # create CMakeLists.txt files if they are not present create_file(test_cmakelist) create_file(test_cmakelist_pkg) create_file(test_cmakelist_destdir) # update the CMakeLists.txt with the tag add_subdirectory(system) update_CMakeLists(test_cmakelist,"system") logger.debug("Updating %s with add_subdirectory(system)", test_cmakelist) logger.debug("Updating %s with add_subdirectory(%s)", test_cmakelist_pkg,pkg) # update CMakeLists.txt with the tag add_subdirectory(pkg) where pkg is the application name update_CMakeLists(test_cmakelist_pkg,pkg) return test_destdir,test_cmakelist_destdir
def setup_software_cmake(): logger = logging.getLogger(logID) BUILDTEST_TESTDIR = config_opts['BUILDTEST_TESTDIR'] name = get_appname() version = get_appversion() toolchain_name = get_toolchain_name() toolchain_version = get_toolchain_version() # if top level software directory is not present, create it test_ebapp_dir=os.path.join(BUILDTEST_TESTDIR,"ebapp") # variables to reference each subdirectory in <software>/<version>/<toolchain-name>/<toolchain-version> test_name_dir=os.path.join(test_ebapp_dir,name) test_version_dir=os.path.join(test_name_dir,version) test_toolchain_name_dir=os.path.join(test_version_dir,toolchain_name) test_toolchain_version_dir=os.path.join(test_toolchain_name_dir,toolchain_version) # BUILDTEST_TESTDIR/CMakeLists.txt test_cmakelist = os.path.join(BUILDTEST_TESTDIR,"CMakeLists.txt") # BUILDTEST_TESTDIR/ebapps/CMakeLists.txt test_ebapp_cmakelist = os.path.join(test_ebapp_dir,"CMakeLists.txt") # CMakeLists.txt files in <software>/<version>/<toolchain-name>/<toolchain-version> test_name_cmakelist = os.path.join(test_name_dir,"CMakeLists.txt") test_version_cmakelist = os.path.join(test_version_dir,"CMakeLists.txt") test_toolchain_name_cmakelist = os.path.join(test_toolchain_name_dir,"CMakeLists.txt") test_toolchain_version_cmakelist = os.path.join(test_toolchain_version_dir,"CMakeLists.txt") test_destdir=test_toolchain_version_dir logger.debug("----------------------------------------") logger.debug("EB Directory Assignments") logger.debug("----------------------------------------") logger.debug("EB Directory in $BUILDTEST_TESTDIR: %s ", test_ebapp_dir) logger.debug("EB Application Directory: %s", test_name_dir) logger.debug("EB Application Version Directory: %s", test_version_dir) logger.debug("EB Toolchain Name Directory: %s", test_toolchain_name_dir) logger.debug("EB Toolchain Version Directory: %s", test_toolchain_version_dir) logger.debug("\n") logger.debug("Test Directory for EB Application: %s ", test_destdir) logger.debug("\n\n") logger.debug("----------------------------------------") logger.debug("EB CMakeList Assignments") logger.debug("----------------------------------------") logger.debug("$BUILDTEST_TESTDIR CMakeList Path: %s ", test_cmakelist) logger.debug("EB Application CMakeList Path: %s ", test_name_cmakelist) logger.debug("EB Application Version CMakeList Path: %s", test_version_cmakelist) logger.debug("EB Toolchain Name CMakeList Path: %s", test_toolchain_name_cmakelist) logger.debug("EB Toolchain Version CMakeList Path: %s", test_toolchain_version_cmakelist) # if test directory exist, delete and recreate it inorder for reproducible test builds if os.path.isdir(test_destdir): shutil.rmtree(test_destdir) logger.debug("Removing test directory before creating test: %s", test_destdir) # create directories if they don't exist # Directory Format: <software>/<version>/toolchain-name>/<toolchain-version> create_dir(test_ebapp_dir) create_dir(test_name_dir) create_dir(test_version_dir) if len(toolchain_name) != 0: create_dir(test_toolchain_name_dir) create_dir(test_toolchain_version_dir) # create CMakeList.txt file in each directory of <software>/<version>/<toolchain-name>/<toolchain-version> if it doesn't exist create_file(test_ebapp_cmakelist) create_file(test_name_cmakelist) create_file(test_version_cmakelist) if len(toolchain_name) != 0: create_file(test_toolchain_name_cmakelist) create_file(test_toolchain_version_cmakelist) # update CMakeLists.txt with tags add_subdirectory(ebapp) update_CMakeLists(test_cmakelist,"ebapp") # update CMakeLists.txt with tags add_subdirectory(X) where X=name|version|toolchain-name|toolchain-version update_CMakeLists(test_ebapp_cmakelist,name) update_CMakeLists(test_name_cmakelist,version) if len(toolchain_name) != 0: update_CMakeLists(test_version_cmakelist,toolchain_name) update_CMakeLists(test_toolchain_name_cmakelist,toolchain_version) return test_destdir,test_toolchain_version_cmakelist
def main(): """ entry point to buildtest """ IGNORE_EASYBUILD = False override_configuration() check_configuration() BUILDTEST_CONFIGS_REPO = config_opts['BUILDTEST_CONFIGS_REPO'] print BUILDTEST_CONFIGS_REPO parser = buildtest_menu() bt_opts = parser.parse_options() if config_opts.get('BUILDTEST_IGNORE_EASYBUILD'): IGNORE_EASYBUILD = config_opts['BUILDTEST_IGNORE_EASYBUILD'] if bt_opts.version: buildtest_version() sys.exit(0) if bt_opts.show: show_configuration() if bt_opts.logdir: config_opts['BUILDTEST_LOGDIR'] = bt_opts.logdir if bt_opts.testdir: config_opts['BUILDTEST_TESTDIR'] = bt_opts.testdir if bt_opts.ignore_easybuild: IGNORE_EASYBUILD = True if bt_opts.enable_job: config_opts['BUILDTEST_ENABLE_JOB'] = True if bt_opts.clean_logs: clean_logs() if bt_opts.clean_tests: clean_tests() if bt_opts.module_naming_scheme: config_opts[ 'BUILDTEST_MODULE_NAMING_SCHEME'] = bt_opts.module_naming_scheme if bt_opts.runtest: runtest_menu() if bt_opts.scantest: scantest() if bt_opts.list_toolchain is True: toolchain_set = list_toolchain() print_toolchain(toolchain_set) sys.exit(0) if bt_opts.list_unique_software: software_set = get_unique_software() print_software(software_set) sys.exit(0) if bt_opts.software_version_relation: software_dict = software_version_relation() print_software_version_relation(software_dict) sys.exit(0) if bt_opts.easyconfigs_in_moduletrees: find_easyconfigs() sys.exit(0) if bt_opts.diff_trees: args_trees = bt_opts.diff_trees diff_trees(args_trees) sys.exit(0) # when no argument is specified to -fc then output all yaml files if bt_opts.findconfig == "all": find_all_yaml_configs() sys.exit(0) # find yaml configs by argument instead of reporting all yaml files elif bt_opts.findconfig is not None: find_yaml_configs_by_arg(bt_opts.findconfig) sys.exit(0) # report all buildtest generated test scripts if bt_opts.findtest == "all": find_all_tests() sys.exit(0) # find test by argument instead of all tests elif bt_opts.findtest is not None: find_tests_by_arg(bt_opts.findtest) sys.exit(0) if bt_opts.shell: config_opts['BUILDTEST_SHELL'] = bt_opts.shell if bt_opts.job_template is not None: update_job_template(bt_opts.job_template) if bt_opts.submitjob is not None: submit_job_to_scheduler(bt_opts.submitjob) sys.exit(0) if bt_opts.sysyaml is not None: create_system_yaml(bt_opts.sysyaml) if bt_opts.ebyaml != None: raise NotImplementedError logger, logpath, logfile = init_log() BUILDTEST_LOGDIR = config_opts['BUILDTEST_LOGDIR'] BUILDTEST_TESTDIR = config_opts['BUILDTEST_TESTDIR'] create_dir(BUILDTEST_LOGDIR) create_dir(BUILDTEST_TESTDIR) cmd = "env | grep BUILDTEST" ret = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output = ret.communicate()[0] output = output.split("\n") for line in output: logger.debug(line) # generate system pkg test if bt_opts.system is not None: if bt_opts.system == "all": systempkg = bt_opts.system logger.info( "Generating all system package tests from YAML files in %s", os.path.join(BUILDTEST_CONFIGS_REPO, "system")) BUILDTEST_LOGDIR = os.path.join(BUILDTEST_LOGDIR, "system", "all") systempkg_list = os.listdir( os.path.join(BUILDTEST_CONFIGS_REPO, "system")) logger.info("List of system packages to test: %s ", systempkg_list) for pkg in systempkg_list: generate_binary_test(bt_opts, pkg) else: systempkg = bt_opts.system BUILDTEST_LOGDIR = os.path.join(BUILDTEST_LOGDIR, "system", systempkg) generate_binary_test(bt_opts, systempkg) create_dir(BUILDTEST_LOGDIR) logger.warning("Creating directory %s, to write log file", BUILDTEST_LOGDIR) destpath = os.path.join(BUILDTEST_LOGDIR, logfile) os.rename(logpath, destpath) logger.info("Moving log file from %s to %s", logpath, destpath) print "Writing Log file to:", destpath sys.exit(0) # when -s is specified if bt_opts.software is not None: software = bt_opts.software.split("/") if bt_opts.toolchain is None: toolchain = "dummy/dummy".split("/") else: toolchain = bt_opts.toolchain.split("/") appname = get_appname() appversion = get_appversion() tcname = get_toolchain_name() tcversion = get_toolchain_version() print "Detecting Software: ", os.path.join(appname, appversion) logger.debug("Generating Test from EB Application") logger.debug("Software: %s", appname) logger.debug("Software Version: %s", appversion) logger.debug("Toolchain: %s", tcname) logger.debug("Toolchain Version: %s", tcversion) logger.debug("Checking if software: %s/%s exists", appname, appversion) # check if software is an easybuild applicationa if IGNORE_EASYBUILD == False: is_easybuild_app() source_app_dir = os.path.join(BUILDTEST_CONFIGS_REPO, "ebapps", appname.lower()) configdir = os.path.join(source_app_dir, "config") codedir = os.path.join(source_app_dir, "code") BUILDTEST_LOGDIR = os.path.join(BUILDTEST_LOGDIR, appname, appversion, tcname, tcversion) # if directory tree for software log is not present, create the directory create_dir(BUILDTEST_LOGDIR) logger.debug("Source App Directory: %s", source_app_dir) logger.debug("Config Directory: %s ", configdir) logger.debug("Code Directory: %s", codedir) generate_binary_test(bt_opts, None) # this generates all the compilation tests found in application directory ($BUILDTEST_CONFIGS_REPO/ebapps/<software>) recursive_gen_test(configdir, codedir) # if flag --testset is set, then if bt_opts.testset is not None: run_testset(bt_opts) # moving log file from $BUILDTEST_LOGDIR/buildtest_%H_%M_%d_%m_%Y.log to $BUILDTEST_LOGDIR/app/appver/tcname/tcver/buildtest_%H_%M_%d_%m_%Y.log os.rename(logpath, os.path.join(BUILDTEST_LOGDIR, logfile)) logger.debug("Writing Log file to %s", os.path.join(BUILDTEST_LOGDIR, logfile)) print "Writing Log file: ", os.path.join(BUILDTEST_LOGDIR, logfile)
def generate_source_test(configmap, codedir, subdir): """ This function generates the tests that requires compilation for EB apps. The tests are written <software>/<version>/<toolchain-name>/<toolchain-version>. The test script is named according to "name" key tag with the shell extension CMakeLists.txt has an entry for each test that executes the shell-script. Most test requires a compilation step, while every test requires a execution stage. This is done via buildcmd and runcmd tags in YAML for explicit builds. buildtest will try to generate this automatically if nothing is provided. """ appname = get_appname() appver = get_appversion() tcname = get_toolchain_name() tcver = get_toolchain_version() logger = logging.getLogger(logID) BUILDTEST_TESTDIR = config_opts['BUILDTEST_TESTDIR'] testname = "" testpath = "" sourcefilepath = "" executable = "" buildopts = "" envvars = "" env_msg = [] # app_destdir is root of test directory app_destdir = os.path.join(BUILDTEST_TESTDIR, "ebapp", appname, appver, tcname, tcver) # destdir is where test script and CMakeLists.txt will be generated. # If there is a subdirectory then testscript will reside in subdir destdir = os.path.join(app_destdir, subdir) cmakelist = os.path.join(destdir, "CMakeLists.txt") # if subdirectory exists, create subdirectory in destdir so we can write test script #if subdir != "": # if sub directory does not exist, then create all directories and its parents directories create_dir(destdir) shell_type = config_opts['BUILDTEST_SHELL'] BUILDTEST_JOB_TEMPLATE = config_opts['BUILDTEST_JOB_TEMPLATE'] BUILDTEST_ENABLE_JOB = config_opts['BUILDTEST_ENABLE_JOB'] # testname is key value "name" with .sh extension testname = configmap["name"] + "." + shell_type testpath = os.path.join(destdir, testname) sourcefilepath = os.path.join(codedir, configmap["source"]) # name of the executable is the value of source tag with ".exe" extension executable = configmap["source"] + ".exe" flags = "" # if buildopts key exists in dictionary, then add flags to compilation step (buildcmd) if "buildopts" in configmap: flags = configmap["buildopts"] if "envvars" in configmap: envvars = configmap["envvars"] for key in envvars.keys(): # append value from function openmp_env_string into env_msg that sets OpenMP environment variable according to shell env_msg.append(openmp_env_string(shell_type, envvars[key])) if "procrange" in configmap: procrange = configmap["procrange"] startproc = int(procrange.split(",")[0]) endproc = int(procrange.split(",")[1]) procinterval = int(procrange.split(",")[2]) testname = configmap["name"] + "_nproc_" + str( startproc) + "." + shell_type testpath = os.path.join(destdir, testname) mpi_proc_list = range(startproc, endproc + 1, procinterval) if "threadrange" in configmap: threadrange = configmap["threadrange"] startthread = int(threadrange.split(",")[0]) endthread = int(threadrange.split(",")[1]) threadinterval = int(threadrange.split(",")[2]) testname = configmap["name"] + "_nthread_" + str( startthread) + "." + shell_type testpath = os.path.join(destdir, testname) thread_list = range(startthread, endthread + 1, threadinterval) openmp_env_str = openmp_env_string(shell_type, startthread) logger.debug("Test Name: %s", testname) logger.debug("Test Path: %s", testpath) logger.debug("Source File: %s", sourcefilepath) logger.debug("Executable Name: %s", executable) logger.debug("Build Flags: %s", flags) # write the preamble to test-script to initialize app environment using module cmds fd = open(testpath, 'w') header = load_modules(shell_type) fd.write(header) # string used for generating the compilation step buildcmd = "" # string used for running the executable and used for injecting commands at pre/post test runcmd = "" # string to decide the compiler wrapper to use based on application and file extension compiler = "" # used for parallel processing to specify # of procs with mpirun -np nproc = "" logger.debug("""Checking for YAML key "buildcmd" and "runcmd" """) # if there is a buildcmd & runcmd in yaml file, place this directly in test script if "buildcmd" in configmap and "runcmd" in configmap: logger.debug("YAML file found buildcmd and runcmd.") logger.debug( "buildtest will generate explicit build/run commands from buildcmd and runcmd field" ) # only process buildcmd if there is a value specified for buildcmd key if configmap["buildcmd"] != None: # for each element from dictionary configmap["buildcmd"], write # each instruction in buildcmd separated by newline for cmd in configmap["buildcmd"]: buildcmd += cmd + "\n" else: msg = "buildcmd is declared but value is not specified \n" logger.debug("%s", msg) if configmap["runcmd"] != None: # process the runcmd tag similar same as buildcmd and store in variable # runcmd except if no value is specified for runcmd in YAML then throw # an error for cmd in configmap["runcmd"]: runcmd += cmd + "\n" else: msg = "runcmd is declared but value is not specified. Need runcmd to run executable \n" print msg logger.debug.append("%s", msg) logging.warning( "Unable to create test from YAML config, skipping test generation" ) return fd.write(buildcmd) fd.write(runcmd) # otherwise generate the buildcmd and runcmd automatically else: # checking if either buildcmd or runcmd specified but not both, then report an error. if "buildcmd" in configmap and "runcmd" not in configmap or "buildcmd" not in configmap and "runcmd" in configmap: print "Need to specify both key: buildcmd and runcmd" logger.warning( "Need to declare both key: buildcmd and runcmd. Skipping to next YAML config \n" ) return # get the compiler tag and type based on application and toolchain compiler, compiler_type = get_compiler(configmap, appname, tcname) logger.debug("buildtest will auto-generate buildcmd & runcmd") logger.debug("Compiler: %s", compiler) logger.debug("Compiler Type: %s", compiler_type) # set buildcmd based on compiler_type. compiler is either nvcc,gcc,icc,mpicc, or mpiicc for intel if compiler_type == "gnu" or compiler_type == "intel" or compiler_type == "cuda": buildcmd = compiler + " -o " + executable + " " + sourcefilepath + " " + flags + "\n" #print buildcmd # set runcmd for mpi tags using mpirun otherwise just run executable if compiler in [ "mpicc", "mpic++", "mpifort", "mpiicc", "mpiic++", "mpiifort" ]: # if nproc is defined in yaml, store value in nproc which will use it in mpirun command if "nproc" in configmap: nproc = str(configmap["nproc"]) logger.debug("nproc key found in YAML config file") logger.debug("nproc: %s", nproc) # check for procrange in case nproc is not defined elif "procrange" in configmap: nproc = str(startproc) # if nproc is not specified set it to 1 when building mpi apps else: nproc = "1" logger.debug( "nproc key not found in YAML config file, will set nproc = 1" ) # add argument to runcmd in MPI jobs if "args" in configmap: arglist = configmap["args"] runcmd = "mpirun -np " + nproc + " ./" + executable runcmd = add_arg_to_runcmd(runcmd, arglist) else: runcmd = "mpirun -np " + nproc + " ./" + executable else: # add argument to runcmd in general jobs if "args" in configmap: arglist = configmap["args"] runcmd = "./" + executable runcmd = add_arg_to_runcmd(runcmd, arglist) else: runcmd = "./" + executable # Scripting languages like Python, R, Perl no compilation stage, just run script. So we just need to update runcmd string elif compiler_type == "python" or compiler_type == "perl" or compiler_type == "R": if "args" in configmap: arglist = configmap["args"] runcmd = compiler + " " + sourcefilepath runcmd = add_arg_to_runcmd(runcmd, arglist) else: runcmd = compiler + " " + sourcefilepath # java programs need "javac" to compile and "java" to run program. This works best if you are # in current directory where source file exists. elif compiler_type == "java": buildcmd = compiler + " " + sourcefilepath + "\n" java_codedir = os.path.dirname(sourcefilepath) filename = os.path.basename(os.path.splitext(sourcefilepath)[0]) # need to be directory where java files reside runcmd = "cd " + java_codedir + "\n" runcmd += "java " + filename + "\n" # would like to remove .class files that are generated due to javac runcmd += "rm -v " + filename + ".class" # if inputfile key is found, add this as part of runcmd if "inputfile" in configmap: runcmd += " < " + os.path.join(codedir, configmap["inputfile"]) # if output of program needs to be written to file instead of STDOUT if "outputfile" in configmap: runcmd += " > " + configmap["outputfile"] if "envvars" in configmap: for key in env_msg: fd.write(key) if "threadrange" in configmap: fd.write(openmp_env_str) fd.write(buildcmd) fd.write(runcmd) # runextracmd is used when you want buildtest to generate compilation and execution step # automatically but need to add extra commands after execution. if "runextracmd" in configmap: for cmd in configmap["runextracmd"]: fd.write(cmd + "\n") logger.debug("runextracmd found in YAML config file") logger.debug("runextracmd: %s", str(configmap["runextracmd"])) fd.close() if BUILDTEST_ENABLE_JOB: if "scheduler" in configmap: generate_job_by_config(testpath, shell_type, configmap) else: # generate job script based on template, if "scheduler" found in # then module below will do nothing and taken care off by # generate_job_by_config generate_job(testpath, shell_type, BUILDTEST_JOB_TEMPLATE, configmap) # by default run the commands below which will add the test to CMakeLists.txt and update the logfile if "iter" not in configmap: add_test_to_CMakeLists(app_destdir, subdir, cmakelist, testname) # print "Creating Test: " + testpath logger.debug("Creating Test: %s ", testpath) logger.debug("[TEST START-BLOCK]") fd = open(testpath, 'r') content = fd.read().splitlines() for line in content: logger.debug(line) fd.close() logger.debug("[TEST END-BLOCK]") if "procrange" in configmap: create_procrange_test(testpath, startproc, mpi_proc_list, subdir) if "threadrange" in configmap: create_threadrange_test(testpath, startthread, thread_list, subdir) # if keyword iter is found in YAML, lets try to recreate N tests by renaming test such as # hello.sh to hello_1.sh and create N-1 copies with file names hello_2.sh, hello_3.sh, ... if "iter" in configmap: filename = os.path.basename(os.path.splitext(sourcefilepath)[0]) testname = filename + "_1." + shell_type testpath_testname = os.path.join(destdir, testname).replace("\n", '') os.rename(testpath, testpath_testname) out = "Rename Iteration Test: " + testpath + " -> " + testpath_testname logger.debug("%s", out) # writing test to CMakeLists.txt add_test_to_CMakeLists(app_destdir, subdir, cmakelist, testname) logger.debug("Content of Test file: %s", testpath_testname) logger.debug("[START TEST-BLOCK]") fd = open(testpath_testname, 'r') content = fd.read() logger.debug("%s", content) fd.close() logger.debug("[END TEST-BLOCK]") numiter = int(configmap["iter"]) logger.debug("Making %s copy of test: %s", numiter, testpath_testname) # creating N-1 copies of tests for index in range(1, numiter): testname = filename + "_" + str(index + 1) + "." + shell_type src_testpath = testpath_testname dest_testpathname = os.path.join(destdir, testname).replace('\n', '') copyfile(src_testpath, dest_testpathname) out = "Iteration Test: " + dest_testpathname logger.info("%s", out) logger.debug("Adding test: %s to CMakeList", testname) add_test_to_CMakeLists(app_destdir, subdir, cmakelist, testname)