Copy data files to the remote runner.

Summary:
The data files for any given test will be in the same directory as the
source with a file name that matches *.dat. To make these available to
tests running remotely (such as over adb or ssh), copy them into the
test's remote working directory.

Note that we will perform more copies than we actually need. The data
files in the directory may only be used by one of the tests, but will
be copied for all tests in the same directory.

This patch also moves the remote test binary into the working
directory (previously it was only invoked from the working directory
rather than existing in it).

Reviewers: EricWF, jroelofs

Reviewed By: jroelofs

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D8118

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@231864 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Albert
2015-03-10 22:31:49 +00:00
parent 07a4bec1dd
commit 761d98d2f7
2 changed files with 30 additions and 18 deletions

View File

@@ -6,15 +6,16 @@ from lit.util import executeCommand # pylint: disable=import-error
class Executor(object): class Executor(object):
def run(self, exe_path, cmd, local_cwd, env=None): def run(self, exe_path, cmd, local_cwd, file_deps=None, env=None):
"""Execute a command. """Execute a command.
Be very careful not to change shared state in this function. Be very careful not to change shared state in this function.
Executor objects are shared between python processes in `lit -jN`. Executor objects are shared between python processes in `lit -jN`.
Args: Args:
exe_path: str: Local path to the executable to be run exe_path: str: Local path to the executable to be run
cmd: [str]: subprocess.call style command cmd: [str]: subprocess.call style command
local_cwd: str: Local path to the working directory local_cwd: str: Local path to the working directory
env: {str: str}: Environment variables to execute under file_deps: [str]: Files required by the test
env: {str: str}: Environment variables to execute under
Returns: Returns:
out, err, exitCode out, err, exitCode
""" """
@@ -25,7 +26,7 @@ class LocalExecutor(Executor):
def __init__(self): def __init__(self):
super(LocalExecutor, self).__init__() super(LocalExecutor, self).__init__()
def run(self, exe_path, cmd=None, work_dir='.', env=None): def run(self, exe_path, cmd=None, work_dir='.', file_deps=None, env=None):
cmd = cmd or [exe_path] cmd = cmd or [exe_path]
env_cmd = [] env_cmd = []
if env: if env:
@@ -48,10 +49,10 @@ class PrefixExecutor(Executor):
self.commandPrefix = commandPrefix self.commandPrefix = commandPrefix
self.chain = chain self.chain = chain
def run(self, exe_path, cmd=None, work_dir='.', env=None): def run(self, exe_path, cmd=None, work_dir='.', file_deps=None, env=None):
cmd = cmd or [exe_path] cmd = cmd or [exe_path]
return self.chain.run(exe_path, self.commandPrefix + cmd, work_dir, return self.chain.run(exe_path, self.commandPrefix + cmd, work_dir,
env=env) file_deps, env=env)
class PostfixExecutor(Executor): class PostfixExecutor(Executor):
@@ -62,9 +63,10 @@ class PostfixExecutor(Executor):
self.commandPostfix = commandPostfix self.commandPostfix = commandPostfix
self.chain = chain self.chain = chain
def run(self, exe_path, cmd=None, work_dir='.', env=None): def run(self, exe_path, cmd=None, work_dir='.', file_deps=None, env=None):
cmd = cmd or [exe_path] cmd = cmd or [exe_path]
return self.chain.run(cmd + self.commandPostfix, work_dir, env=env) return self.chain.run(cmd + self.commandPostfix, work_dir, file_deps,
env=env)
@@ -107,24 +109,28 @@ class RemoteExecutor(Executor):
# TODO: Log failure to delete? # TODO: Log failure to delete?
pass pass
def run(self, exe_path, cmd=None, work_dir='.', env=None): def run(self, exe_path, cmd=None, work_dir='.', file_deps=None, env=None):
target_exe_path = None target_exe_path = None
target_cwd = None target_cwd = None
try: try:
target_exe_path = self.remote_temp_file()
target_cwd = self.remote_temp_dir() target_cwd = self.remote_temp_dir()
target_exe_path = os.path.join(target_cwd, 'libcxx_test.exe')
if cmd: if cmd:
# Replace exe_path with target_exe_path. # Replace exe_path with target_exe_path.
cmd = [c if c != exe_path else target_exe_path for c in cmd] cmd = [c if c != exe_path else target_exe_path for c in cmd]
else: else:
cmd = [target_exe_path] cmd = [target_exe_path]
self.copy_in([exe_path], [target_exe_path])
srcs = [exe_path]
dsts = [target_exe_path]
if file_deps is not None:
dev_paths = [os.path.join(target_cwd, os.path.basename(f))
for f in file_deps]
srcs.extend(file_deps)
dsts.extend(dev_paths)
self.copy_in(srcs, dsts)
return self._execute_command_remote(cmd, target_cwd, env) return self._execute_command_remote(cmd, target_cwd, env)
except:
raise
finally: finally:
if target_exe_path:
self.delete_remote(target_exe_path)
if target_cwd: if target_cwd:
self.delete_remote(target_cwd) self.delete_remote(target_cwd)

View File

@@ -115,8 +115,14 @@ class LibcxxTestFormat(object):
env = None env = None
if self.exec_env: if self.exec_env:
env = self.exec_env env = self.exec_env
# TODO: Only list actually needed files in file_deps.
# Right now we just mark all of the .dat files in the same
# directory as dependencies, but it's likely less than that. We
# should add a `// FILE-DEP: foo.dat` to each test to track this.
data_files = [os.path.join(local_cwd, f)
for f in os.listdir(local_cwd) if f.endswith('.dat')]
out, err, rc = self.executor.run(exec_path, [exec_path], out, err, rc = self.executor.run(exec_path, [exec_path],
local_cwd, env) local_cwd, data_files, env)
if rc != 0: if rc != 0:
report = libcxx.util.makeReport(cmd, out, err, rc) report = libcxx.util.makeReport(cmd, out, err, rc)
report = "Compiled With: %s\n%s" % (compile_cmd, report) report = "Compiled With: %s\n%s" % (compile_cmd, report)