def run_tests(tests, test_input, timeout = 60, waittime = 0.1):
    """
    Runs all the tests given by directly executing them. If they return
    with a non-zero exit code, it adds them to the dictionary returned.

    Keyword arguments:
        tests -- a list of paths to executable test files
        test_input -- dictionary of key value pairs to provide to the test
        timeout -- how many seconds to let the tests run
        waittime -- how many seconds to wait in between test polls
    """
    failed_tests = {}
    for t in tests:
        log.debug("Executing test %s", t)

        p = subprocess.Popen(t, stdin=subprocess.PIPE)

        to_send = json.dumps(test_input)
        log.debug("Sending test_input to test: %s", to_send)

        # Using write here instead of communicate because communicate
        # blocks on reading output
        try:
            p.stdin.write(to_send + os.linesep)
            p.stdin.close()

            countdown = int(timeout / waittime)
            while countdown:
                retcode = p.poll()
                
                if retcode is not None:
                    break

                time.sleep(waittime)
                countdown = countdown - 1
            else:
                p.terminate()
                log.warn("Test %s timed out", t)
                p.wait()
                retcode = 'TIMEOUT'
        except __HOLE__ as e:
            log.warn("Caught IOError from process: %s", e)
            retcode = e

        if retcode:
            failed_tests[t] = retcode
            log.error("Test %s failed with code %s", t, retcode)

    return failed_tests
dataset/ETHPy150Open gosquadron/squadron/squadron/tests.py/run_tests