Index: test/lit.cfg =================================================================== --- test/lit.cfg +++ test/lit.cfg @@ -18,6 +18,47 @@ import lit.formats import lit.util +class GuardedTempFilename(object): + """ + GuardedTempFilename - A utility class that allows temporary files to be used + in a python 'with' statement. + ex. + with GuardedTempFilename(suffix='.exe') as temp_file_name: + pass + """ + def __init__(self, suffix='', prefix='tmp', dir=None): + # Store the options for later. Don't create the tempfile outside of a + # with statement. + self.suffix = suffix + self.prefix = prefix + self.dir = dir + self.name = None + + def __enter__(self): + try: + tmp_file = tempfile.NamedTemporaryFile(suffix=self.suffix, prefix=self.prefix, dir=self.dir, delete=False) + self.name = tmp_file.name + tmp_file.close() + return self.name + except: + self.delete() + raise + + def __exit__(self, type, value, traceback): + self.delete() + return False + + def delete(self): + if self.name is not None: + try: + os.remove(self.name) + except: + pass + self.name = None + + def __repr__(self): + return self.name + class LibcxxTestFormat(lit.formats.FileBasedTest): """ Custom test format handler for use with the test format use by libc++. @@ -90,7 +131,9 @@ ', '.join(unsupported_features),)) # Evaluate the test. - return self._evaluate_test(test, use_verify, lit_config) + res = self._evaluate_test(test, use_verify, lit_config) + self._clean() + return res def _make_report(self, cmd, out, err, rc): report = "Command: %s\n" % cmd @@ -119,19 +162,11 @@ return cmd, out, err, rc def _compile_and_link(self, exec_path, source_path): - object_file = tempfile.NamedTemporaryFile(suffix=".o", delete=False) - object_path = object_file.name - object_file.close() - try: + with GuardedTempFilename(suffix='.o') as object_path: cmd, out, err, rc = self._compile(object_path, source_path) if rc != 0: return cmd, out, err, rc return self._link(exec_path, object_path) - finally: - try: - os.remove(object_path) - except: - pass def _build(self, exec_path, source_path, compile_only=False, use_verify=False): @@ -142,8 +177,8 @@ cmd, out, err, rc = self._compile_and_link(exec_path, source_path) return self._make_report(cmd, out, err, rc) - def _clean(self, exec_path): - os.remove(exec_path) + def _clean(self): + pass def _run(self, exec_path, lit_config, in_dir=None): cmd = [] @@ -177,11 +212,7 @@ else: return lit.Test.FAIL, report + 'Expected compilation to fail!\n' else: - exec_file = tempfile.NamedTemporaryFile(suffix="exe", delete=False) - exec_path = exec_file.name - exec_file.close() - - try: + with GuardedTempFilename(suffix='.exe') as exec_path: cmd, report, rc = self._build(exec_path, source_path) compile_cmd = cmd if rc != 0: @@ -194,13 +225,6 @@ report = "Compiled With: %s\n%s" % (compile_cmd, report) report += "Compiled test failed unexpectedly!" return lit.Test.FAIL, report - finally: - try: - # Note that cleanup of exec_file happens in `_clean()`. If - # you override this, cleanup is your reponsibility. - self._clean(exec_path) - except: - pass return lit.Test.PASS, ""