Esempio n. 1
0
def run(dirname, envgetter):
    # Run all the tests to be found in directory dirname.
    # This is not recursive into other directories.
    #
    # return 1 if there was an error, 0 otherwise; try to
    # do as much as possible, though.
    #
    printed_dirname = 0

    was_error = 0

    dirname = os.path.abspath(dirname)

    try:
        dir_list = os.listdir(dirname)
    except Exception as e:
        print("Cannot search for tests in %s" % dirname)
        print(e)
        print("")
        return 1, {}

    dir_list.sort()

    # As we run each file, we will get a count of status values of each type.
    # t_stat keeps a running sum for the current directory.
    t_stat = {}

    for basename in dir_list:

        full_name = os.path.join(dirname, basename)
        try:
            file_stat = os.stat(full_name)
        except OSError as e:
            if e.errno == errno.ENOENT:
                # not an error for somebody to delete a file between when
                # we start the test and end the test.  most commonly,
                # this is a temp file or something, not a test.
                continue
            print("Cannot stat file %s" % full_name)
            print(e)
            was_error = 1
            continue
        except Exception as e:
            print("Cannot stat file %s" % full_name)
            print(e)
            was_error = 1
            continue

        if not stat.S_ISREG(file_stat.st_mode):
            # we skip any thing that is not a file
            continue

        # Decide which test runner this file wants to use.  If the
        # answer is None, this file does not contain tests.
        runner = pandokia.run_file.select_runner(dirname, basename)

        # if runner comes back None, that means that select_runner is
        # saying "this is not a test"
        if runner is None:
            continue

        # Don't print the directory name until it looks like we are
        # actually going to do anything here.  This suppresses all
        # output completely for directories that do not have any tests.
        if not printed_dirname:
            print("directory %s" % dirname)
            printed_dirname = 1

        # If the file is disabled, skip it
        if file_disabled(dirname, basename):
            print("Disabled : %s/%s" % (dirname, basename))
            m = pandokia.run_file.get_runner_mod(runner)

            env = {}
            env.update(envgetter.envdir(dirname))
            env['PDK_TESTPREFIX'] = pandokia.run_file.get_prefix(
                envgetter, dirname)

            env['PDK_FILE'] = basename

            # ask the runner what disabled tests are in that file.
            save_dir = os.getcwd()
            os.chdir(dirname)

            # flush the output file because m.list() might start a new process.
            # really, m.list() should do that itself, but I don't trust every
            # author of every new runner to do it.
            sys.stdout.flush()
            sys.stderr.flush()
            l = m.lst(env)

            os.chdir(save_dir)

            if l is not None:
                # l is a list of the names of tests that were in that file.
                # We will write a status=D record for each disabled test.
                write_disabled_list(env, l, dirname, basename, runner)
            else:
                pass
                # If the function returns None, it means that it does not
                # know how to report the disabled tests.  That's too bad,
                # but we can at least go on.
            continue

        # not disabled - run it
        try:
            (err, lstat) = pandokia.run_file.run(dirname, basename, envgetter,
                                                 runner)
            was_error |= err
            for x in lstat:
                t_stat[x] = t_stat.get(x, 0) + lstat[x]
        except Exception as e:
            xstr = traceback.format_exc()
            print("Exception running file %s/%s: %s" % (dirname, basename, e))
            print(xstr)
            print('')
            was_error = 1

    # print the status summary for the directory.
    print("")
    print("%s:" % dirname)
    common.print_stat_dict(t_stat)

    return (was_error, t_stat)
Esempio n. 2
0
                continue
            raise
        for line in f:
            line = line.strip()
            if line == 'START':
                continue
            if line.startswith('.'):
                continue
            if line == '':
                continue
            line = line.split('=')
            status = line[0]
            count = line[1]
            stat_summary[status] = stat_summary.get(status, 0) + int(count)
        f.close()

        # we are the only consumer for this file, so toss it (but don't
        # get too excited if it doesn't work)
        try:
            os.unlink(fn)
        except:
            pass

    print ""
    print "Summary of entire run:"
    common.print_stat_dict(stat_summary)

    # bug: multirun is not reporting exit status back to us, so we have no
    # error status to return.
    return (0, stat_summary)
Esempio n. 3
0
def run(dirs, envgetter, max_procs=None):

    # The basic command to run tests in a directory is
    #   pdk run --dir --environment_already_set $directory
    cmd = ['pdkrun', '--dir', '--environment_already_set']

    # We use multirun to runs up to max_procs concurrent processes.
    # In each process, we run tests in one directory.  We don't
    # know max_procs in advance, or even if it is the same through
    # the whole run.  So, remember which slots were used.  Later,
    # will will look for a status file from each slot.
    slots_used = {}

    # loop over the directories they gave us; recurse into each.
    for x in dirs:

        x = os.path.abspath(x)

        # Declare the maximum processes to the parallel runner.
        # Each process can run tests in one directory at a time.
        # This is inside the loop because we are not certain of
        # the value for PDK_PARALLEL until we have a directory
        # where we look for pdk_environment.
        d = envgetter.envdir(x)
        if max_procs is not None:
            pass
        elif 'PDK_PARALLEL' in d:
            max_procs = d['PDK_PARALLEL']
        else:
            max_procs = 1
        try:
            max_procs = int(max_procs)
        except ValueError:
            print(
                "cannot convert %d to integer - running one process at a time" %
                maxprocs)
            max_procs = 1
        pandokia.multirun.set_max_procs(max_procs)

        # x is a directory; y is a loop over all nested subdirectories
        # that may be of interest.
        for y in generate_directories(x):

            # For max_procs=N, we have slots 0 to N-1 to
            # run test processes in.  We wait for a process
            # slot to open up because we want to tell the
            # new process which slot it is in.  (It can use that
            # for things like file names.)
            n = pandokia.multirun.await_process_slot()

            # remember that we used this slot at least once
            slots_used[n] = 1

            # Get the environment to use for this directory.
            # We will pass this in as the process's inherited
            # environment.  (That's why we say --environment_already_set.)
            d = envgetter.envdir(y)

            # Add the process slot number to the environment.  The
            # test runners can use this, but it is now way too late
            # to define other environment variables in terms of
            # PDK_PROCESS_SLOT.
            #
            # run_dir uses PDK_PROCESS_SLOT to choose a pdk log file
            # to report results into.
            d['PDK_PROCESS_SLOT'] = str(n)

            # Start the actual process to run the tests in that directory.
            pandokia.multirun.start(cmd + [y], d)

    # multirun starts several concurrent processes, but we don't want
    # to say we are finished until they are all done.
    pandokia.multirun.wait_all()

    # ensure that all the slots are reporting empty by the time we
    # are finished.
    for slot in slots_used:
        pandokia.run_status.pdkrun_status('', slot)

    # collect the summary of how many tests had each status
    stat_summary = {}
    for x in slots_used:
        fn = "%s.%s.summary" % (os.environ['PDK_LOG'], str(x))
        try:
            f = open(fn, "r")
        except IOError as e:
            # It is possible for a process slot to run a process without
            # creating a log file.  (e.g. when there is a directory that
            # does not contain any tests.)  So, if there is no file, that
            # is not an errr.
            if e.errno == errno.ENOENT:
                continue
            raise
        for line in f:
            line = line.strip()
            if line == 'START':
                continue
            if line.startswith('.'):
                continue
            if line == '':
                continue
            line = line.split('=')
            status = line[0]
            count = line[1]
            stat_summary[status] = stat_summary.get(status, 0) + int(count)
        f.close()

        # we are the only consumer for this file, so toss it (but don't
        # get too excited if it doesn't work)
        try:
            os.unlink(fn)
        except:
            pass

    print("")
    print("Summary of entire run:")
    common.print_stat_dict(stat_summary)

    # bug: multirun is not reporting exit status back to us, so we have no
    # error status to return.
    return (0, stat_summary)
Esempio n. 4
0
def run(dirname, envgetter):
    # Run all the tests to be found in directory dirname.
    # This is not recursive into other directories.
    #
    # return 1 if there was an error, 0 otherwise; try to
    # do as much as possible, though.
    #
    printed_dirname = 0

    was_error = 0

    dirname = os.path.abspath(dirname)

    try:
        dir_list = os.listdir(dirname)
    except Exception as e:
        print("Cannot search for tests in %s" % dirname)
        print(e)
        print("")
        return 1, {}

    dir_list.sort()

    # As we run each file, we will get a count of status values of each type.
    # t_stat keeps a running sum for the current directory.
    t_stat = {}

    for basename in dir_list:

        full_name = os.path.join(dirname, basename)
        try:
            file_stat = os.stat(full_name)
        except OSError as e:
            if e.errno == errno.ENOENT:
                # not an error for somebody to delete a file between when
                # we start the test and end the test.  most commonly,
                # this is a temp file or something, not a test.
                continue
            print("Cannot stat file %s" % full_name)
            print(e)
            was_error = 1
            continue
        except Exception as e:
            print("Cannot stat file %s" % full_name)
            print(e)
            was_error = 1
            continue

        if not stat.S_ISREG(file_stat.st_mode):
            # we skip any thing that is not a file
            continue

        # Decide which test runner this file wants to use.  If the
        # answer is None, this file does not contain tests.
        runner = pandokia.run_file.select_runner(dirname, basename)

        # if runner comes back None, that means that select_runner is
        # saying "this is not a test"
        if runner is None:
            continue

        # Don't print the directory name until it looks like we are
        # actually going to do anything here.  This suppresses all
        # output completely for directories that do not have any tests.
        if not printed_dirname:
            print("directory %s" % dirname)
            printed_dirname = 1

        # If the file is disabled, skip it
        if file_disabled(dirname, basename):
            print("Disabled : %s/%s" % (dirname, basename))
            m = pandokia.run_file.get_runner_mod(runner)

            env = {}
            env.update(envgetter.envdir(dirname))
            env['PDK_TESTPREFIX'] = pandokia.run_file.get_prefix(
                envgetter, dirname)

            env['PDK_FILE'] = basename

            # ask the runner what disabled tests are in that file.
            save_dir = os.getcwd()
            os.chdir(dirname)

            # flush the output file because m.list() might start a new process.
            # really, m.list() should do that itself, but I don't trust every
            # author of every new runner to do it.
            sys.stdout.flush()
            sys.stderr.flush()
            l = m.lst(env)

            os.chdir(save_dir)

            if l is not None:
                # l is a list of the names of tests that were in that file.
                # We will write a status=D record for each disabled test.
                write_disabled_list(env, l, dirname, basename, runner)
            else:
                pass
                # If the function returns None, it means that it does not
                # know how to report the disabled tests.  That's too bad,
                # but we can at least go on.
            continue

        # not disabled - run it
        try:
            (err, lstat) = pandokia.run_file.run(
                dirname, basename, envgetter, runner)
            was_error |= err
            for x in lstat:
                t_stat[x] = t_stat.get(x, 0) + lstat[x]
        except Exception as e:
            xstr = traceback.format_exc()
            print("Exception running file %s/%s: %s" % (dirname, basename, e))
            print(xstr)
            print('')
            was_error = 1

    # print the status summary for the directory.
    print("")
    print("%s:" % dirname)
    common.print_stat_dict(t_stat)

    return (was_error, t_stat)
Esempio n. 5
0
def run(dirs, envgetter, max_procs=None):

    # The basic command to run tests in a directory is
    #   pdk run --dir --environment_already_set $directory
    cmd = ['pdkrun', '--dir', '--environment_already_set']

    # We use multirun to runs up to max_procs concurrent processes.
    # In each process, we run tests in one directory.  We don't
    # know max_procs in advance, or even if it is the same through
    # the whole run.  So, remember which slots were used.  Later,
    # will will look for a status file from each slot.
    slots_used = {}

    # loop over the directories they gave us; recurse into each.
    for x in dirs:

        x = os.path.abspath(x)

        # Declare the maximum processes to the parallel runner.
        # Each process can run tests in one directory at a time.
        # This is inside the loop because we are not certain of
        # the value for PDK_PARALLEL until we have a directory
        # where we look for pdk_environment.
        d = envgetter.envdir(x)
        if max_procs is not None:
            pass
        elif 'PDK_PARALLEL' in d:
            max_procs = d['PDK_PARALLEL']
        else:
            max_procs = 1
        try:
            max_procs = int(max_procs)
        except ValueError:
            print(
                "cannot convert %d to integer - running one process at a time"
                % maxprocs)
            max_procs = 1
        pandokia.multirun.set_max_procs(max_procs)

        # x is a directory; y is a loop over all nested subdirectories
        # that may be of interest.
        for y in generate_directories(x):

            # For max_procs=N, we have slots 0 to N-1 to
            # run test processes in.  We wait for a process
            # slot to open up because we want to tell the
            # new process which slot it is in.  (It can use that
            # for things like file names.)
            n = pandokia.multirun.await_process_slot()

            # remember that we used this slot at least once
            slots_used[n] = 1

            # Get the environment to use for this directory.
            # We will pass this in as the process's inherited
            # environment.  (That's why we say --environment_already_set.)
            d = envgetter.envdir(y)

            # Add the process slot number to the environment.  The
            # test runners can use this, but it is now way too late
            # to define other environment variables in terms of
            # PDK_PROCESS_SLOT.
            #
            # run_dir uses PDK_PROCESS_SLOT to choose a pdk log file
            # to report results into.
            d['PDK_PROCESS_SLOT'] = str(n)

            # Start the actual process to run the tests in that directory.
            pandokia.multirun.start(cmd + [y], d)

    # multirun starts several concurrent processes, but we don't want
    # to say we are finished until they are all done.
    pandokia.multirun.wait_all()

    # ensure that all the slots are reporting empty by the time we
    # are finished.
    for slot in slots_used:
        pandokia.run_status.pdkrun_status('', slot)

    # collect the summary of how many tests had each status
    stat_summary = {}
    for x in slots_used:
        fn = "%s.%s.summary" % (os.environ['PDK_LOG'], str(x))
        try:
            f = open(fn, "r")
        except IOError as e:
            # It is possible for a process slot to run a process without
            # creating a log file.  (e.g. when there is a directory that
            # does not contain any tests.)  So, if there is no file, that
            # is not an errr.
            if e.errno == errno.ENOENT:
                continue
            raise
        for line in f:
            line = line.strip()
            if line == 'START':
                continue
            if line.startswith('.'):
                continue
            if line == '':
                continue
            line = line.split('=')
            status = line[0]
            count = line[1]
            stat_summary[status] = stat_summary.get(status, 0) + int(count)
        f.close()

        # we are the only consumer for this file, so toss it (but don't
        # get too excited if it doesn't work)
        try:
            os.unlink(fn)
        except:
            pass

    print("")
    print("Summary of entire run:")
    common.print_stat_dict(stat_summary)

    # bug: multirun is not reporting exit status back to us, so we have no
    # error status to return.
    return (0, stat_summary)
Esempio n. 6
0
def run(dirname, basename, envgetter, runner):
    cause = "unknown"
    return_status = 0
    dirname = os.path.abspath(dirname)
    save_dir = os.getcwd()
    os.chdir(dirname)

    if runner is None:
        runner = select_runner(dirname, basename)

    if runner is not None:
        # copy of the environment because we will mess with it
        env = dict(envgetter.envdir(dirname))

        env['PDK_TESTPREFIX'] = get_prefix(envgetter, dirname)

        env['PDK_TOP'] = envgetter.gettop()

        runner_mod = get_runner_mod(runner)

        env['PDK_FILE'] = basename

        env['PDK_LOG'] = pdk_log_name(env)

        stat_summary = {}
        for x in pandokia.cfg.statuses:
            stat_summary[x] = 0

        # We will write a count of statuses to a summary file.  But where?
        # If no PDK_PROCESS_SLOT, we do not need a summary -- we just return
        # it to our caller.  Otherwise, we use a file based on the log file
        # name.
        if 'PDK_PROCESS_SLOT' in env:
            summary_file = env['PDK_LOG'] + '.summary'
            slot_id = env['PDK_PROCESS_SLOT']
        else:
            summary_file = None
            slot_id = '0'

        f = open(env['PDK_LOG'], 'a+')
        # 2 == os.SEEK_END, but not in python 2.4
        f.seek(0, 2)
        end_of_log = f.tell()
        f.close()

        env['PDK_DIRECTORY'] = dirname

        full_filename = dirname + "/" + env['PDK_FILE']

        f = open(env['PDK_LOG'], "a")
        f.write("\n\nSTART\n")
        f.write('test_run=%s\n' % env['PDK_TESTRUN'])
        f.write('project=%s\n' % env['PDK_PROJECT'])
        f.write('host=%s\n' % env['PDK_HOST'])
        f.write('location=%s\n' % full_filename)
        f.write('test_runner=%s\n' % runner)
        f.write('context=%s\n' % env['PDK_CONTEXT'])
        f.write("SETDEFAULT\n")
        f.close()

        # fetch the command that executes the tests
        cmd = runner_mod.command(env)
        output_buffer = ''

        if cmd is not None:
            # run the command -- To understand how we do it, see
            # "Replacing os.system()" in the docs for the subprocess module,
            # then consider the source code for subprocess.call()
            if not isinstance(cmd, list):
                cmd = [cmd]
            for thiscmd in cmd:
                print('COMMAND : %s (for file %s) %s' %
                      (repr(thiscmd), full_filename, datetime.datetime.now()))
                sys.stdout.flush()
                sys.stderr.flush()
                if windows:
                    # on Windows, we dare not let the child process have access to the stdout/stderr
                    # that we are using.  Apparently, the child process closes stderr and it somehow
                    # ends up closed for us too.  So, stuff it into a temp file and then copy the
                    # temp file to our stdout/stderr.
                    f = open("stdout.%s.tmp" % slot_id, "w")
                    p = subprocess.Popen(
                        thiscmd,
                        stdout=f,
                        stderr=f,
                        shell=True,
                        env=env,
                        creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
                    # bug: implement timeouts
                    status = p.wait()
                    f.close()

                    f = open("stdout.%s.tmp" % slot_id, "r")
                    output_buffer = f.read()
                    sys.stdout.write(output_buffer)
                    f.close()

                    os.unlink("stdout.%s.tmp" % slot_id)
                else:
                    # on unix, just do it
                    with NamedTemporaryFile(mode='r+b') as f:
                        p = subprocess.Popen(thiscmd.split(),
                                             stdout=f,
                                             stderr=f,
                                             shell=False,
                                             env=env,
                                             preexec_fn=unix_preexec)

                        if 'PDK_TIMEOUT' in env:
                            proc_timeout_start(env['PDK_TIMEOUT'], p)
                            status = p.wait()
                            print("return from wait, status=%d" % status)
                            proc_timeout_terminate()
                            if timeout_proc_kills > 0:
                                # we tried to kill it for taking too long -
                                # report an error even if it managed to exit 0
                                status = -15
                        else:
                            status = p.wait()

                        f.seek(0)
                        output_buffer = f.read().decode()
                        sys.stdout.write(output_buffer)

                # subprocess gives you weird status values
                if status >= 0:
                    cause = "exit"
                    return_status = status
                elif status < 0:
                    cause = "signal"
                    return_status = -status

                print("COMMAND EXIT: %s %s %s" %
                      (cause, return_status, datetime.datetime.now()))

        else:
            # BUG: no timeout! - fortunately, this is a minor issue
            # because we don't currently have anything that uses
            # run_internally() except to cough out errors about
            # unsupported runners on Windows

            # There is no command, so we run it by calling a function.
            # This runs the test in the same python interpreter that
            # this file is executing in, which is normally not
            # preferred because a problem in the test runner, or even
            # in the test, could potentially kill the pandokia meta-runner.
            print("RUNNING INTERNALLY (for file %s)" % full_filename)
            runner_mod.run_internally(env)
            print("DONE RUNNING INTERNALLY")

        #
        # A test runner that only works within pandokia can assume
        # that we made all of these log entries for it.
        pdkrun_status(full_filename)

        # Trap unhandled exit information
        if return_status > 1 or return_status < 0:
            f = open(env['PDK_LOG'], "a")
            f.write('\n')
            f.write('test_name=%s\n' % full_filename)
            f.write('status=E\n')
            if output_buffer:
                f.write('log:\n')
                f.write('.[PANDOKIA]\n')
                f.write('.FATAL: NON-STANDARD EXIT VALUE DETECTED! '
                        '({})\n'.format(return_status))
                f.write('.\n')
                f.write('.[STDOUT/STDERR STREAM]\n')
                for line in output_buffer.splitlines():
                    f.write('.{}\n'.format(line))
                f.write('\n')
            f.write('END\n')
            f.close()

        if 1:
            # if the runner did not provide a status summary, collect it from
            # the log file.
            # [ This is "if 1" because no runners currently know how to do it.
            #   Later, some of them will leave behind a status summary file; we
            #   will read that instead.   ]
            f = open(env['PDK_LOG'], 'r')
            # 0 == os.SEEK_SET, but not in python 2.4
            f.seek(end_of_log, 0)
            while True:
                l = f.readline()
                if l == '':
                    break
                l = l.strip()
                if l.startswith('status='):
                    l = l[7:].strip()
                    stat_summary[l] = stat_summary.get(l, 0) + 1
            f.close()

        common.print_stat_dict(stat_summary)
        print("")
        if summary_file:
            # The summary file has a similar format to the log, but there is
            # a "START" line after each record.   If somebody accidentally
            # tries to import it, the importer can never find any data.
            f = open(summary_file, 'a')
            for x in stat_summary:
                f.write("%s=%s\n" % (x, stat_summary[x]))
            # ".file" can never look like a valid status
            f.write(".file=%s\n" % full_filename)
            f.write("START\n\n")
            f.close()

    else:
        print("NO RUNNER FOR %s\n" % (dirname + "/" + basename))

    os.chdir(save_dir)

    pdkrun_status('')

    return (return_status, stat_summary)
Esempio n. 7
0
        try :
            ( err, lstat ) = pandokia.run_file.run(dirname, basename, envgetter, runner )
            was_error |= err
            for x in lstat :
                t_stat[x] = t_stat.get(x,0) + lstat[x]
        except Exception, e:
            xstr=traceback.format_exc()
            print "Exception running file %s/%s: %s"%(dirname, basename, e)
            print xstr
            print ''
            was_error = 1

    # print the status summary for the directory.
    print ""
    print "%s:"%dirname
    common.print_stat_dict(t_stat)

    return ( was_error, t_stat )


#
# check for a disable file, indicating that we should not run tests in a file
#
def file_disabled(dirname, basename) :
    # dirname = engine/spider/stis/spec/stellar-ext
    # basename = s_stis_spec_stellar-ext_10759.peng

    n=basename.rfind(".")
    if n >= 0 :
        disable_name = basename[:n]
    else :
Esempio n. 8
0
def run(args):
    import pandokia.envgetter

    recursive = False
    environment_already_set = False
    directory = False
    log = os.environ.get("PDK_LOG", None)
    project = os.environ.get("PDK_PROJECT", None)
    test_run = os.environ.get("PDK_TESTRUN", None)
    test_prefix = os.environ.get("PDK_TESTPREFIX", None)
    context = os.environ.get("PDK_CONTEXT", 'default')
    custom = os.environ.get("PDK_CUSTOM", "")
    parallel = os.environ.get("PDK_PARALLEL", None)
    tmpdir = os.environ.get("PDK_TMP", None)
    host = os.environ.get("PDK_HOST", None)
    verbose = 0  # not implemented
    dry_run = 0  # not implemented

    if args == []:
        args = ['-r', '.']
    opts, args = getopt.gnu_getopt(args, "rvpsw", [
        "recursive",
        "environment_already_set",
        "dir",
        "log=",
        "project=",
        "test_run=",
        "test_prefix=",
        "show-command",
        "verbose",
        "parallel=",
        "help",
        "context=",
    ])
    for (opt, optarg) in opts:
        if opt == '-r' or opt == '--recursive':
            recursive = True
        elif opt == '--environment_already_set':
            environment_already_set = True
        elif opt == '--dir':
            # we don't do anything with --dir, but it is there to see
            # when you run ps
            pass
        elif opt == '--help':
            print(helpstr)
            return (0, {})
        elif opt == '--log':
            log = optarg
        elif opt == '--test_run':
            test_run = optarg
        elif opt == '--test_prefix':
            test_prefix = optarg
        elif opt == '--project':
            project = optarg
        elif opt == '--context':
            context = optarg
        elif opt == '--verbose' or opt == '-v':
            verbose = 1
        elif opt == '--dry-run':
            dry_run = 1
        elif opt == '-' or opt == '--parallel':
            parallel = str(int(optarg))
        elif opt == '--host':
            host = optarg
        elif opt == '--custom':
            custom = optarg

    if project is None:
        project = default_project()
    if test_run is None:
        test_run = default_test_run()
    if log is None:
        log = "PDK_DEFAULT.LOG." + test_run
    if host is None:
        host = common.gethostname()

    if parallel is not None:
        os.environ['PDK_PARALLEL'] = parallel

    log = os.path.abspath(log)

    os.environ['PDK_LOG'] = log
    os.environ['PDK_PROJECT'] = project
    os.environ['PDK_TESTRUN'] = test_run
    os.environ['PDK_CONTEXT'] = context
    os.environ['PDK_CUSTOM'] = custom
    os.environ['PDK_HOST'] = host

    initialized_status_file = 0
    if 'PDK_STATUSFILE' not in os.environ:
        status_file_name = os.getcwd() + '/pdk_statusfile'
        import pandokia.run_status
        if parallel is None:
            n_status_records = 1
        else:
            n_status_records = int(parallel)
        f = pandokia.run_status.init_status(filename=status_file_name,
                                            n_records=n_status_records)
        if f:
            os.environ['PDK_STATUSFILE'] = os.getcwd() + '/pdk_statusfile'
            initialized_status_file = 1

    if test_prefix is not None:
        os.environ['PDK_TESTPREFIX'] = test_prefix

    if tmpdir is None:
        tmpdir = os.getcwd()
    os.environ['PDK_TMP'] = tmpdir

    envgetter = pandokia.envgetter.EnvGetter(context=context)
    # environment_already_set=environment_already_set )     bug: we need to
    # get this optimization in some how

    if recursive:
        import pandokia.run_recursive
        (was_error, t_stat) = pandokia.run_recursive.run(args, envgetter)
    else:
        # t_stat is a count of status values of each type.  The counts were printed at the end
        # of each file/dir that we ran, but if there are more than one file/dir, we will print
        # the total in t_stat.
        t_stat = {}
        was_error = 0
        n_things_run = 0
        for x in args:
            try:
                file_stat = os.stat(x)
            except OSError as e:
                print("%s %s" % (x, e))
                continue

            lstat = {}
            if stat.S_ISDIR(file_stat.st_mode):
                import pandokia.run_dir
                n_things_run += 1
                (err, lstat) = pandokia.run_dir.run(x, envgetter)
            elif stat.S_ISREG(file_stat.st_mode):
                import pandokia.run_file
                n_things_run += 1

                basename = os.path.basename(x)
                dirname = os.path.dirname(x)
                if dirname == '':
                    dirname = '.'
                runner = pandokia.run_file.select_runner(dirname, basename)
                if runner is not None:
                    (err,
                     lstat) = pandokia.run_file.run(dirname, basename,
                                                    envgetter, runner)
                else:
                    print("no runner for %s" % x)
                    err = 1
            else:
                lstat = {}
                err = 0
            was_error |= err
            for y in lstat:
                t_stat[y] = t_stat.get(y, 0) + lstat[y]

        if n_things_run > 1:
            print("")
            print("Summary:")
            common.print_stat_dict(t_stat)

    if initialized_status_file:
        for x in range(0, n_status_records):
            pandokia.run_status.pdkrun_status('', slot=x)
        os.unlink(os.environ['PDK_STATUSFILE'])

    return (was_error, t_stat)
Esempio n. 9
0
def run(args):
    import pandokia.envgetter

    recursive = False
    environment_already_set = False
    directory = False
    log = os.environ.get("PDK_LOG", None)
    project = os.environ.get("PDK_PROJECT", None)
    test_run = os.environ.get("PDK_TESTRUN", None)
    test_prefix = os.environ.get("PDK_TESTPREFIX", None)
    context = os.environ.get("PDK_CONTEXT", 'default')
    custom = os.environ.get("PDK_CUSTOM", None)
    parallel = os.environ.get("PDK_PARALLEL", None)
    tmpdir = os.environ.get("PDK_TMP", None)
    host = os.environ.get("PDK_HOST", None)
    verbose = 0  # not implemented
    dry_run = 0  # not implemented

    if args == []:
        args = ['-r', '.']
    opts, args = getopt.gnu_getopt(args, "rvpsw",
                                   ["recursive", "environment_already_set", "dir", "log=",
                                    "project=", "test_run=", "test_prefix=",
                                    "show-command", "verbose", "parallel=", "help", "context=",
                                    ])
    for (opt, optarg) in opts:
        if opt == '-r' or opt == '--recursive':
            recursive = True
        elif opt == '--environment_already_set':
            environment_already_set = True
        elif opt == '--dir':
            # we don't do anything with --dir, but it is there to see
            # when you run ps
            pass
        elif opt == '--help':
            print(helpstr)
            return (0, {})
        elif opt == '--log':
            log = optarg
        elif opt == '--test_run':
            test_run = optarg
        elif opt == '--test_prefix':
            test_prefix = optarg
        elif opt == '--project':
            project = optarg
        elif opt == '--context':
            context = optarg
        elif opt == '--verbose' or opt == '-v':
            verbose = 1
        elif opt == '--dry-run':
            dry_run = 1
        elif opt == '-' or opt == '--parallel':
            parallel = str(int(optarg))
        elif opt == '--host':
            host = optarg
        elif opt == '--custom':
            custom = optarg

    if project is None:
        project = default_project()
    if test_run is None:
        test_run = default_test_run()
    if log is None:
        log = "PDK_DEFAULT.LOG." + test_run
    if host is None:
        host = common.gethostname()

    if parallel is not None:
        os.environ['PDK_PARALLEL'] = parallel

    log = os.path.abspath(log)

    os.environ['PDK_LOG'] = log
    os.environ['PDK_PROJECT'] = project
    os.environ['PDK_TESTRUN'] = test_run
    os.environ['PDK_CONTEXT'] = context
    os.environ['PDK_CUSTOM'] = custom
    os.environ['PDK_HOST'] = host

    initialized_status_file = 0
    if 'PDK_STATUSFILE' not in os.environ:
        status_file_name = os.getcwd() + '/pdk_statusfile'
        import pandokia.run_status
        if parallel is None:
            n_status_records = 1
        else:
            n_status_records = int(parallel)
        f = pandokia.run_status.init_status(
            filename=status_file_name, n_records=n_status_records)
        if f:
            os.environ['PDK_STATUSFILE'] = os.getcwd() + '/pdk_statusfile'
            initialized_status_file = 1

    if test_prefix is not None:
        os.environ['PDK_TESTPREFIX'] = test_prefix

    if tmpdir is None:
        tmpdir = os.getcwd()
    os.environ['PDK_TMP'] = tmpdir

    envgetter = pandokia.envgetter.EnvGetter(context=context)
    # environment_already_set=environment_already_set )     bug: we need to
    # get this optimization in some how

    if recursive:
        import pandokia.run_recursive
        (was_error, t_stat) = pandokia.run_recursive.run(args, envgetter)
    else:
        # t_stat is a count of status values of each type.  The counts were printed at the end
        # of each file/dir that we ran, but if there are more than one file/dir, we will print
        # the total in t_stat.
        t_stat = {}
        was_error = 0
        n_things_run = 0
        for x in args:
            try:
                file_stat = os.stat(x)
            except OSError as e:
                print("%s %s" % (x, e))
                continue

            lstat = {}
            if stat.S_ISDIR(file_stat.st_mode):
                import pandokia.run_dir
                n_things_run += 1
                (err, lstat) = pandokia.run_dir.run(x, envgetter)
            elif stat.S_ISREG(file_stat.st_mode):
                import pandokia.run_file
                n_things_run += 1

                basename = os.path.basename(x)
                dirname = os.path.dirname(x)
                if dirname == '':
                    dirname = '.'
                runner = pandokia.run_file.select_runner(dirname, basename)
                if runner is not None:
                    (err, lstat) = pandokia.run_file.run(
                        dirname, basename, envgetter, runner)
                else:
                    print("no runner for %s" % x)
                    err = 1
            else:
                lstat = {}
                err = 0
            was_error |= err
            for y in lstat:
                t_stat[y] = t_stat.get(y, 0) + lstat[y]

        if n_things_run > 1:
            print("")
            print("Summary:")
            common.print_stat_dict(t_stat)

    if initialized_status_file:
        for x in range(0, n_status_records):
            pandokia.run_status.pdkrun_status('', slot=x)
        os.unlink(os.environ['PDK_STATUSFILE'])

    return (was_error, t_stat)
Esempio n. 10
0
def run(dirname, basename, envgetter, runner):
    cause = "unknown"
    return_status = 0
    dirname = os.path.abspath(dirname)
    save_dir = os.getcwd()
    os.chdir(dirname)

    if runner is None:
        runner = select_runner(dirname, basename)

    if runner is not None:
        # copy of the environment because we will mess with it
        env = dict(envgetter.envdir(dirname))

        env['PDK_TESTPREFIX'] = get_prefix(envgetter, dirname)

        env['PDK_TOP'] = envgetter.gettop()

        runner_mod = get_runner_mod(runner)

        env['PDK_FILE'] = basename

        env['PDK_LOG'] = pdk_log_name(env)

        stat_summary = {}
        for x in pandokia.cfg.statuses:
            stat_summary[x] = 0

        # We will write a count of statuses to a summary file.  But where?
        # If no PDK_PROCESS_SLOT, we do not need a summary -- we just return
        # it to our caller.  Otherwise, we use a file based on the log file
        # name.
        if 'PDK_PROCESS_SLOT' in env:
            summary_file = env['PDK_LOG'] + '.summary'
            slot_id = env['PDK_PROCESS_SLOT']
        else:
            summary_file = None
            slot_id = '0'

        f = open(env['PDK_LOG'], 'a+')
        # 2 == os.SEEK_END, but not in python 2.4
        f.seek(0, 2)
        end_of_log = f.tell()
        f.close()

        env['PDK_DIRECTORY'] = dirname

        full_filename = dirname + "/" + env['PDK_FILE']

        f = open(env['PDK_LOG'], "a")
        f.write("\n\nSTART\n")
        f.write('test_run=%s\n' % env['PDK_TESTRUN'])
        f.write('project=%s\n' % env['PDK_PROJECT'])
        f.write('host=%s\n' % env['PDK_HOST'])
        f.write('location=%s\n' % full_filename)
        f.write('test_runner=%s\n' % runner)
        f.write('context=%s\n' % env['PDK_CONTEXT'])
        f.write('custom=%s\n' % env['PDK_CUSTOM'])
        f.write("SETDEFAULT\n")
        f.close()

        # fetch the command that executes the tests
        cmd = runner_mod.command(env)
        output_buffer = ''

        if cmd is not None:
            # run the command -- To understand how we do it, see
            # "Replacing os.system()" in the docs for the subprocess module,
            # then consider the source code for subprocess.call()
            if not isinstance(cmd, list):
                cmd = [cmd]
            for thiscmd in cmd:
                print('COMMAND : %s (for file %s) %s' %
                      (repr(thiscmd), full_filename, datetime.datetime.now()))
                sys.stdout.flush()
                sys.stderr.flush()
                if windows:
                    # on Windows, we dare not let the child process have access to the stdout/stderr
                    # that we are using.  Apparently, the child process closes stderr and it somehow
                    # ends up closed for us too.  So, stuff it into a temp file and then copy the
                    # temp file to our stdout/stderr.
                    f = open("stdout.%s.tmp" % slot_id, "w")
                    p = subprocess.Popen(
                        thiscmd,
                        stdout=f,
                        stderr=f,
                        shell=True,
                        env=env,
                        creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
                    # bug: implement timeouts
                    status = p.wait()
                    f.close()

                    f = open("stdout.%s.tmp" % slot_id, "r")
                    output_buffer = f.read()
                    sys.stdout.write(output_buffer)
                    f.close()

                    os.unlink("stdout.%s.tmp" % slot_id)
                else:
                    # on unix, just do it
                    with NamedTemporaryFile(mode='r+b') as f:
                        p = subprocess.Popen(
                            thiscmd.split(),
                            stdout=f,
                            stderr=f,
                            shell=False,
                            env=env,
                            preexec_fn=unix_preexec)

                        if 'PDK_TIMEOUT' in env:
                            proc_timeout_start(env['PDK_TIMEOUT'], p)
                            status = p.wait()
                            print("return from wait, status=%d" % status)
                            proc_timeout_terminate()
                            if timeout_proc_kills > 0:
                                # we tried to kill it for taking too long -
                                # report an error even if it managed to exit 0
                                status = -15
                        else:
                            status = p.wait()

                        f.seek(0)
                        output_buffer = f.read().decode()
                        sys.stdout.write(output_buffer)


                # subprocess gives you weird status values
                if status >= 0:
                    cause="exit"
                    return_status = status
                elif status < 0:
                    cause = "signal"
                    return_status = -status

                print("COMMAND EXIT: %s %s %s" %
                     (cause, return_status, datetime.datetime.now()))

        else:
            # BUG: no timeout! - fortunately, this is a minor issue
            # because we don't currently have anything that uses
            # run_internally() except to cough out errors about
            # unsupported runners on Windows

            # There is no command, so we run it by calling a function.
            # This runs the test in the same python interpreter that
            # this file is executing in, which is normally not
            # preferred because a problem in the test runner, or even
            # in the test, could potentially kill the pandokia meta-runner.
            print("RUNNING INTERNALLY (for file %s)" % full_filename)
            runner_mod.run_internally(env)
            print("DONE RUNNING INTERNALLY")

        #
        # A test runner that only works within pandokia can assume
        # that we made all of these log entries for it.
        pdkrun_status(full_filename)


        # Trap unhandled exit information
        if return_status > 1 or return_status < 0:
            f = open(env['PDK_LOG'], "a")
            f.write('\n')
            f.write('test_name=%s\n' % full_filename)
            f.write('status=E\n')
            if output_buffer:
                f.write('log:\n')
                f.write('.[PANDOKIA]\n')
                f.write('.FATAL: NON-STANDARD EXIT VALUE DETECTED! '
                        '({})\n'.format(return_status))
                f.write('.\n')
                f.write('.[STDOUT/STDERR STREAM]\n')
                for line in output_buffer.splitlines():
                    f.write('.{}\n'.format(line))
                f.write('\n')
            f.write('END\n')
            f.close()

        if 1:
            # if the runner did not provide a status summary, collect it from
            # the log file.
            # [ This is "if 1" because no runners currently know how to do it.
            #   Later, some of them will leave behind a status summary file; we
            #   will read that instead.   ]
            f = open(env['PDK_LOG'], 'r')
            # 0 == os.SEEK_SET, but not in python 2.4
            f.seek(end_of_log, 0)
            while True:
                l = f.readline()
                if l == '':
                    break
                l = l.strip()
                if l.startswith('status='):
                    l = l[7:].strip()
                    stat_summary[l] = stat_summary.get(l, 0) + 1
            f.close()

        common.print_stat_dict(stat_summary)
        print("")
        if summary_file:
            # The summary file has a similar format to the log, but there is
            # a "START" line after each record.   If somebody accidentally
            # tries to import it, the importer can never find any data.
            f = open(summary_file, 'a')
            for x in stat_summary:
                f.write("%s=%s\n" % (x, stat_summary[x]))
            # ".file" can never look like a valid status
            f.write(".file=%s\n" % full_filename)
            f.write("START\n\n")
            f.close()

    else:
        print("NO RUNNER FOR %s\n" % (dirname + "/" + basename))

    os.chdir(save_dir)

    pdkrun_status('')

    return (return_status, stat_summary)