#!/usr/bin/env python
# ===----------------------------------------------------------------------===##
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# ===----------------------------------------------------------------------===##

"""
Runs an executable on a remote host.

This is meant to be used as an executor when running the C++ Standard Library
conformance test suite.
"""

import argparse
import os
import posixpath
import shlex
import subprocess
import sys
import tarfile
import tempfile


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--host", type=str, required=True)
    parser.add_argument("--execdir", type=str, required=True)
    parser.add_argument("--tempdir", type=str, required=False, default="/tmp")
    parser.add_argument("--extra-ssh-args", type=str, required=False)
    parser.add_argument("--extra-scp-args", type=str, required=False)
    parser.add_argument("--codesign_identity", type=str, required=False, default=None)
    parser.add_argument("--env", type=str, nargs="*", required=False, default=[])
    parser.add_argument("--prepend_env", type=str, nargs="*", required=False, default=[])
    parser.add_argument("-v", "--verbose", action='store_true')
    parser.add_argument("command", nargs=argparse.ONE_OR_MORE)
    args = parser.parse_args()
    commandLine = args.command

    def ssh(command):
        cmd = ["ssh", "-oBatchMode=yes"]
        if args.extra_ssh_args is not None:
            cmd.extend(shlex.split(args.extra_ssh_args))
        return cmd + [args.host, command]

    def scp(src, dst):
        cmd = ["scp", "-q", "-oBatchMode=yes"]
        if args.extra_scp_args is not None:
            cmd.extend(shlex.split(args.extra_scp_args))
        return cmd + [src, "{}:{}".format(args.host, dst)]

    def runCommand(command, *args_, **kwargs):
        if args.verbose:
            print(f"$ {' '.join(command)}", file=sys.stderr)
        return subprocess.run(command, *args_, **kwargs)

    # Create a temporary directory where the test will be run.
    # That is effectively the value of %{temp} on the remote host.
    tmp = runCommand(
        ssh("mktemp -d {}/libcxx.XXXXXXXXXX".format(args.tempdir)),
        universal_newlines=True,
        check=True,
        capture_output=True,
        stdin=subprocess.DEVNULL
    ).stdout.strip()

    # HACK:
    # If an argument is a file that ends in `.tmp.exe`, assume it is the name
    # of an executable generated by a test file. We call these test-executables
    # below. This allows us to do custom processing like codesigning test-executables
    # and changing their path when running on the remote host. It's also possible
    # for there to be no such executable, for example in the case of a .sh.cpp
    # test.
    isTestExe = lambda exe: exe.endswith(".tmp.exe") and os.path.exists(exe)
    pathOnRemote = lambda file: posixpath.join(tmp, os.path.basename(file))

    try:
        # Do any necessary codesigning of test-executables found in the command line.
        if args.codesign_identity:
            for exe in filter(isTestExe, commandLine):
                codesign = ["codesign", "-f", "-s", args.codesign_identity, exe]
                runCommand(codesign, env={}, check=True, stdin=subprocess.DEVNULL)

        # tar up the execution directory (which contains everything that's needed
        # to run the test), and copy the tarball over to the remote host.
        try:
            tmpTar = tempfile.NamedTemporaryFile(suffix=".tar", delete=False)
            with tarfile.open(fileobj=tmpTar, mode="w") as tarball:
                tarball.add(args.execdir, arcname=os.path.basename(args.execdir))

            # Make sure we close the file before we scp it, because accessing
            # the temporary file while still open doesn't work on Windows.
            tmpTar.close()
            remoteTarball = pathOnRemote(tmpTar.name)
            runCommand(scp(tmpTar.name, remoteTarball), check=True, stdin=subprocess.DEVNULL)
        finally:
            # Make sure we close the file in case an exception happens before
            # we've closed it above -- otherwise close() is idempotent.
            tmpTar.close()
            os.remove(tmpTar.name)

        # Untar the dependencies in the temporary directory and remove the tarball.
        remoteCommands = [
            "tar -xf {} -C {} --strip-components 1".format(remoteTarball, tmp),
            "rm {}".format(remoteTarball),
        ]

        # Make sure all test-executables in the remote command line have 'execute'
        # permissions on the remote host. The host that compiled the test-executable
        # might not have a notion of 'executable' permissions.
        for exe in map(pathOnRemote, filter(isTestExe, commandLine)):
            remoteCommands.append("chmod +x {}".format(exe))

        # Execute the command through SSH in the temporary directory, with the
        # correct environment. We tweak the command line to run it on the remote
        # host by transforming the path of test-executables to their path in the
        # temporary directory on the remote host.
        commandLine = (pathOnRemote(x) if isTestExe(x) else x for x in commandLine)
        remoteCommands.append("cd {}".format(tmp))

        if args.prepend_env:
            # We can't sensibly know the original value of the env vars
            # in order to prepend to them, so just overwrite these variables.
            args.env.extend(args.prepend_env)

        if args.env:
            env = list(map(shlex.quote, args.env))
            remoteCommands.append("export {}".format(" ".join(args.env)))
        remoteCommands.append(subprocess.list2cmdline(commandLine))

        # Finally, SSH to the remote host and execute all the commands.
        # Make sure to forward stdin to the process so that the test suite
        # can pipe stuff into the executor.
        rc = runCommand(ssh(" && ".join(remoteCommands))).returncode
        return rc

    finally:
        # Make sure the temporary directory is removed when we're done.
        runCommand(ssh("rm -r {}".format(tmp)), check=True)


if __name__ == "__main__":
    exit(main())
