def fork_for_tests(concurrency_num, suite): result = [] if 'BUILDDIR' in os.environ: selftestdir = get_test_layer() test_blocks = partition_tests(suite, concurrency_num) # Clear the tests from the original suite so it doesn't keep them alive suite._tests[:] = [] totaltests = sum(len(x) for x in test_blocks) for process_tests in test_blocks: numtests = len(process_tests) process_suite = unittest.TestSuite(process_tests) # Also clear each split list so new suite has only reference process_tests[:] = [] c2pread, c2pwrite = os.pipe() # Clear buffers before fork to avoid duplicate output sys.stdout.flush() sys.stderr.flush() pid = os.fork() if pid == 0: ourpid = os.getpid() try: newbuilddir = None stream = os.fdopen(c2pwrite, 'wb', 1) os.close(c2pread) # Create a new separate BUILDDIR for each group of tests if 'BUILDDIR' in os.environ: builddir = os.environ['BUILDDIR'] newbuilddir = builddir + "-st-" + str(ourpid) newselftestdir = newbuilddir + "/meta-selftest" bb.utils.mkdirhier(newbuilddir) oe.path.copytree(builddir + "/conf", newbuilddir + "/conf") oe.path.copytree(builddir + "/cache", newbuilddir + "/cache") oe.path.copytree(selftestdir, newselftestdir) for e in os.environ: if builddir in os.environ[e]: os.environ[e] = os.environ[e].replace(builddir, newbuilddir) subprocess.check_output("git init; git add *; git commit -a -m 'initial'", cwd=newselftestdir, shell=True) # Tried to used bitbake-layers add/remove but it requires recipe parsing and hence is too slow subprocess.check_output("sed %s/conf/bblayers.conf -i -e 's#%s#%s#g'" % (newbuilddir, selftestdir, newselftestdir), cwd=newbuilddir, shell=True) os.chdir(newbuilddir) for t in process_suite: if not hasattr(t, "tc"): continue cp = t.tc.config_paths for p in cp: if selftestdir in cp[p] and newselftestdir not in cp[p]: cp[p] = cp[p].replace(selftestdir, newselftestdir) if builddir in cp[p] and newbuilddir not in cp[p]: cp[p] = cp[p].replace(builddir, newbuilddir) # Leave stderr and stdout open so we can see test noise # Close stdin so that the child goes away if it decides to # read from stdin (otherwise its a roulette to see what # child actually gets keystrokes for pdb etc). newsi = os.open(os.devnull, os.O_RDWR) os.dup2(newsi, sys.stdin.fileno()) subunit_client = TestProtocolClient(stream) # Force buffering of stdout/stderr so the console doesn't get corrupted by test output # as per default in parent code subunit_client.buffer = True subunit_result = AutoTimingTestResultDecorator(subunit_client) process_suite.run(subunit_result) if ourpid != os.getpid(): os._exit(0) if newbuilddir: removebuilddir(newbuilddir) except: # Don't do anything with process children if ourpid != os.getpid(): os._exit(1) # Try and report traceback on stream, but exit with error # even if stream couldn't be created or something else # goes wrong. The traceback is formatted to a string and # written in one go to avoid interleaving lines from # multiple failing children. try: stream.write(traceback.format_exc().encode('utf-8')) except: sys.stderr.write(traceback.format_exc()) finally: if newbuilddir: removebuilddir(newbuilddir) stream.flush() os._exit(1) stream.flush() os._exit(0) else: os.close(c2pwrite) stream = os.fdopen(c2pread, 'rb', 1) test = ProtocolTestCase(stream) result.append((test, numtests)) return result, totaltests
def fork_for_tests(concurrency_num, suite): result = [] if 'BUILDDIR' in os.environ: selftestdir = get_test_layer() test_blocks = partition_tests(suite, concurrency_num) # Clear the tests from the original suite so it doesn't keep them alive suite._tests[:] = [] totaltests = sum(len(x) for x in test_blocks) for process_tests in test_blocks: numtests = len(process_tests) process_suite = unittest.TestSuite(process_tests) # Also clear each split list so new suite has only reference process_tests[:] = [] c2pread, c2pwrite = os.pipe() # Clear buffers before fork to avoid duplicate output sys.stdout.flush() sys.stderr.flush() pid = os.fork() if pid == 0: ourpid = os.getpid() try: newbuilddir = None stream = os.fdopen(c2pwrite, 'wb', 1) os.close(c2pread) (builddir, newbuilddir) = suite.setupfunc("-st-" + str(ourpid), selftestdir, process_suite) # Leave stderr and stdout open so we can see test noise # Close stdin so that the child goes away if it decides to # read from stdin (otherwise its a roulette to see what # child actually gets keystrokes for pdb etc). newsi = os.open(os.devnull, os.O_RDWR) os.dup2(newsi, sys.stdin.fileno()) subunit_client = TestProtocolClient(stream) # Force buffering of stdout/stderr so the console doesn't get corrupted by test output # as per default in parent code subunit_client.buffer = True subunit_result = AutoTimingTestResultDecorator(subunit_client) process_suite.run( ExtraResultsEncoderTestResult(subunit_result)) if ourpid != os.getpid(): os._exit(0) if newbuilddir: removebuilddir(newbuilddir) except: # Don't do anything with process children if ourpid != os.getpid(): os._exit(1) # Try and report traceback on stream, but exit with error # even if stream couldn't be created or something else # goes wrong. The traceback is formatted to a string and # written in one go to avoid interleaving lines from # multiple failing children. try: stream.write(traceback.format_exc().encode('utf-8')) except: sys.stderr.write(traceback.format_exc()) finally: if newbuilddir: removebuilddir(newbuilddir) stream.flush() os._exit(1) stream.flush() os._exit(0) else: os.close(c2pwrite) stream = os.fdopen(c2pread, 'rb', 1) test = ProtocolTestCase(stream) result.append((test, numtests)) return result, totaltests
def fork_for_tests(concurrency_num, suite): result = [] test_blocks = partition_tests(suite, concurrency_num) # Clear the tests from the original suite so it doesn't keep them alive suite._tests[:] = [] totaltests = sum(len(x) for x in test_blocks) for process_tests in test_blocks: numtests = len(process_tests) process_suite = unittest.TestSuite(process_tests) # Also clear each split list so new suite has only reference process_tests[:] = [] c2pread, c2pwrite = os.pipe() # Clear buffers before fork to avoid duplicate output sys.stdout.flush() sys.stderr.flush() pid = os.fork() if pid == 0: ourpid = os.getpid() try: newbuilddir = None stream = os.fdopen(c2pwrite, 'wb', 1) os.close(c2pread) # Create a new separate BUILDDIR for each group of tests if 'BUILDDIR' in os.environ: builddir = os.environ['BUILDDIR'] newbuilddir = builddir + "-st-" + str(ourpid) selftestdir = os.path.abspath(builddir + "/../meta-selftest") newselftestdir = newbuilddir + "/meta-selftest" bb.utils.mkdirhier(newbuilddir) oe.path.copytree(builddir + "/conf", newbuilddir + "/conf") oe.path.copytree(builddir + "/cache", newbuilddir + "/cache") oe.path.copytree(selftestdir, newselftestdir) for e in os.environ: if builddir in os.environ[e]: os.environ[e] = os.environ[e].replace(builddir, newbuilddir) subprocess.check_output("git init; git add *; git commit -a -m 'initial'", cwd=newselftestdir, shell=True) # Tried to used bitbake-layers add/remove but it requires recipe parsing and hence is too slow subprocess.check_output("sed %s/conf/bblayers.conf -i -e 's#%s#%s#g'" % (newbuilddir, selftestdir, newselftestdir), cwd=newbuilddir, shell=True) os.chdir(newbuilddir) for t in process_suite: if not hasattr(t, "tc"): continue cp = t.tc.config_paths for p in cp: if selftestdir in cp[p] and newselftestdir not in cp[p]: cp[p] = cp[p].replace(selftestdir, newselftestdir) if builddir in cp[p] and newbuilddir not in cp[p]: cp[p] = cp[p].replace(builddir, newbuilddir) # Leave stderr and stdout open so we can see test noise # Close stdin so that the child goes away if it decides to # read from stdin (otherwise its a roulette to see what # child actually gets keystrokes for pdb etc). newsi = os.open(os.devnull, os.O_RDWR) os.dup2(newsi, sys.stdin.fileno()) subunit_client = TestProtocolClient(stream) # Force buffering of stdout/stderr so the console doesn't get corrupted by test output # as per default in parent code subunit_client.buffer = True subunit_result = AutoTimingTestResultDecorator(subunit_client) process_suite.run(subunit_result) if ourpid != os.getpid(): os._exit(0) if newbuilddir: removebuilddir(newbuilddir) except: # Don't do anything with process children if ourpid != os.getpid(): os._exit(1) # Try and report traceback on stream, but exit with error # even if stream couldn't be created or something else # goes wrong. The traceback is formatted to a string and # written in one go to avoid interleaving lines from # multiple failing children. try: stream.write(traceback.format_exc().encode('utf-8')) except: sys.stderr.write(traceback.format_exc()) finally: if newbuilddir: removebuilddir(newbuilddir) stream.flush() os._exit(1) stream.flush() os._exit(0) else: os.close(c2pwrite) stream = os.fdopen(c2pread, 'rb', 1) test = ProtocolTestCase(stream) result.append((test, numtests)) return result, totaltests