Run test: Do output post-processing on device.

Run the various 'sed' commands on device.

Also move the adb push/pull commands from default_run.py
(which may be executed several times for multi-pass tests)
to run-test (which is executed just once).

This is a step towards being able to create runner bash file,
so that all tests are executed using the same common pattern:
adb push <inputs>; adb shell sh <runner>; adb pull <outputs>

Test: ./art/test.py -b -r --optimizing --64
Change-Id: I4e1862ab4dc853175ec85c712e452420e91bc6b7
diff --git a/test/default_run.py b/test/default_run.py
index c6d6563..c30b651 100755
--- a/test/default_run.py
+++ b/test/default_run.py
@@ -1146,16 +1146,6 @@
   ANDROID_LOG_TAGS = args.android_log_tags
 
   if not HOST:
-    adb.root()
-    adb.wait_for_device()
-    adb.shell(f"rm -rf {CHROOT_DEX_LOCATION} && mkdir -p {CHROOT_DEX_LOCATION}")
-    adb.push(f"{TEST_NAME}*.jar", CHROOT_DEX_LOCATION)
-    if PROFILE or RANDOM_PROFILE:
-      adb.push("profile", CHROOT_DEX_LOCATION, check=False)
-    # Copy resource folder
-    if isdir("res"):
-      adb.push("res", CHROOT_DEX_LOCATION)
-
     # Populate LD_LIBRARY_PATH.
     LD_LIBRARY_PATH = ""
     if ANDROID_ROOT != "/system":
@@ -1243,10 +1233,7 @@
     if USE_GDB or USE_GDBSERVER:
       print(f"Forward {GDBSERVER_PORT} to local port and connect GDB")
 
-    run_cmd(f"rm -rf {DEX_LOCATION}/dalvik-cache/ && mkdir -p {mkdir_locations}")
-    # Restore stdout/stderr from previous run (the directory might have been cleared).
-    adb.push(args.stdout_file, f"{CHROOT}{DEX_LOCATION}/{basename(args.stdout_file)}")
-    adb.push(args.stderr_file, f"{CHROOT}{DEX_LOCATION}/{basename(args.stderr_file)}")
+    run_cmd(f"rm -rf {DEX_LOCATION}/{{oat,dalvik-cache}}/ && mkdir -p {mkdir_locations}")
     run_cmd(f"{profman_cmdline}", env)
     run_cmd(f"{dex2oat_cmdline}", env)
     run_cmd(f"{dm_cmdline}", env)
@@ -1256,9 +1243,6 @@
     run_cmd(tee(f"{timeout_prefix} {dalvikvm_cmdline}"),
             env,
             expected_exit_code=args.expected_exit_code)
-    # Copy the on-device stdout/stderr to host.
-    adb.pull(f"{CHROOT}{DEX_LOCATION}/{basename(args.stdout_file)}", args.stdout_file)
-    adb.pull(f"{CHROOT}{DEX_LOCATION}/{basename(args.stderr_file)}", args.stderr_file)
   else:
     # Host run.
     if USE_ZIPAPEX or USE_EXRACTED_ZIPAPEX:
diff --git a/test/run-test b/test/run-test
index c8827c5..b405de1 100755
--- a/test/run-test
+++ b/test/run-test
@@ -46,20 +46,27 @@
 # Context passed to individual tests to let them customize the behaviour.
 class RunTestContext:
 
-  def __init__(self, tmp_dir: Path) -> None:
+  def __init__(self, tmp_dir: Path, target: bool, chroot, dex_location) -> None:
     self.env = Environment()
+    self.target = target
+    self.chroot = chroot
+    self.dex_location = dex_location
 
     # Note: The expected path can be modified by the tests.
     self.expected_stdout = tmp_dir / "expected-stdout.txt"
     self.expected_stderr = tmp_dir / "expected-stderr.txt"
 
   def echo(self, text):
-    with open(test_stdout, "a") as f:
-      f.write(text + "\n")
+    self.run(f"echo {text} > {test_stdout}")
 
   # Let the test execute arbitrary bash command.
+  # The command is executed in the test directory (on device for target tests).
   def run(self, cmd, check=True):
-    subprocess.run(cmd, shell=True, cwd=tmp_dir, check=check)
+    if self.target:
+      cmd = "sh -c 'cd {}; {}'".format(self.dex_location, cmd.replace("'", r"'\''"))
+      cmd = "adb shell 'chroot {} {}'".format(self.chroot, cmd.replace("'", r"'\''"))
+    print(f"{COLOR_BLUE}$ {cmd}{COLOR_NORMAL}", flush=True)
+    subprocess.run(cmd, shell=True, cwd=tmp_dir, stderr=subprocess.STDOUT, check=check)
 
   # Execute the default runner (possibly with modified arguments).
   def default_run(self, args, **kwargs):
@@ -963,7 +970,7 @@
   # TODO: Run this in global try-finally once the script is more refactored.
   atexit.register(clean_up, passed=False)
 
-  ctx = RunTestContext(Path(tmp_dir))
+  ctx = RunTestContext(Path(tmp_dir), target_mode == "yes", chroot, DEX_LOCATION)
   td_info = f"{test_dir}/{info}"
   for td_file in [td_info, ctx.expected_stdout, ctx.expected_stderr]:
     assert os.access(td_file, os.R_OK)
@@ -974,8 +981,8 @@
   # Execute the "run" method in the per-test specific script file.
   def run_test_script():
     parsed_args = default_run_module.parse_args(shlex.split(" ".join(run_args + args)))
-    parsed_args.stdout_file = os.path.join(tmp_dir, test_stdout)
-    parsed_args.stderr_file = os.path.join(tmp_dir, test_stderr)
+    parsed_args.stdout_file = os.path.join(DEX_LOCATION, test_stdout)
+    parsed_args.stderr_file = os.path.join(DEX_LOCATION, test_stderr)
 
     script = os.path.join(tmp_dir, "run.py")
     if os.path.exists(script):
@@ -991,7 +998,26 @@
   export("TEST_RUNTIME", runtime)
 
   print(f"{test_dir}: running...")
-  run_test_script()
+  if target_mode == "yes":
+    # Prepare the on-device test directory
+    run("adb root")
+    run("adb wait-for-device")
+    run(f"adb shell 'rm -rf {chroot_dex_location} && mkdir -p {chroot_dex_location}'")
+    push_files = list(Path(".").glob(f"{TEST_NAME}*.jar"))
+    push_files += list(Path(".").glob(f"expected-*.txt"))
+    push_files += [p for p in [Path("profile"), Path("res")] if p.exists()]
+    if push_files:
+      run("adb push {} {}".format(" ".join(map(str, push_files)), chroot_dex_location))
+    run(f"adb shell 'echo -n > {chroot_dex_location}/{test_stdout}'")  # Empty file.
+    run(f"adb shell 'echo -n > {chroot_dex_location}/{test_stderr}'")  # Empty file.
+
+    run_test_script()
+
+    # Copy the on-device stdout/stderr to host.
+    pull_files = [test_stdout, test_stderr, "expected-stdout.txt", "expected-stderr.txt"]
+    run("adb pull {} .".format(" ".join(f"{chroot_dex_location}/{f}" for f in pull_files)))
+  else:
+    run_test_script()
   # NB: There is no exit code or return value.
   # Failing tests just raise python exception.
   os.chdir(tmp_dir)