#!/usr/bin/env python
# utils/rth - Resilience test helper
#
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See https://swift.org/LICENSE.txt for license information
# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors

from __future__ import print_function

import argparse
import os
import pipes
import shlex
import shutil
import subprocess
import sys

VERBOSE = True


def verbose_print_command(command):
    if VERBOSE:
        print(" ".join(pipes.quote(c) for c in command))
        sys.stdout.flush()


class ResilienceTest(object):

    def __init__(self, target_build_swift, target_run, target_codesign,
                 tmp_dir, test_dir, test_src, lib_prefix, lib_suffix,
                 additional_compile_flags_library,
                 no_backward_deployment):
        self.target_build_swift = shlex.split(target_build_swift)
        self.target_run = shlex.split(target_run)
        self.target_codesign = shlex.split(target_codesign)
        self.tmp_dir = tmp_dir
        self.test_dir = test_dir
        self.test_src = test_src
        self.lib_prefix = lib_prefix
        self.lib_suffix = lib_suffix
        self.additional_compile_flags_library = \
            shlex.split(additional_compile_flags_library)

        self.before_dir = os.path.join(self.tmp_dir, 'before')
        self.after_dir = os.path.join(self.tmp_dir, 'after')
        self.config_dir_map = {'BEFORE': self.before_dir,
                               'AFTER': self.after_dir}

        self.lib_src_name = os.path.basename(self.test_src)[5:]
        self.lib_name = self.lib_src_name[:-6]
        self.lib_src = os.path.join(self.test_dir, 'Inputs', self.lib_src_name)

        self.no_backward_deployment = no_backward_deployment

    def run(self):
        self.set_up()
        self.compile_library()
        self.compile_main()
        self.link()
        self.execute()
        return 0

    def set_up(self):
        shutil.rmtree(self.tmp_dir, ignore_errors=True)
        os.makedirs(self.after_dir)
        os.makedirs(self.before_dir)

    def is_apple_platform(self):
        return any('-apple-' in arg for arg in self.target_build_swift)

    def compile_library(self):
        for config in self.config_dir_map:
            lib_file = self.lib_prefix + self.lib_name + self.lib_suffix
            output_dylib = os.path.join(self.config_dir_map[config],
                                        lib_file)
            compiler_flags = ['-emit-library', '-emit-module',
                              '-swift-version', '4',
                              '-Xfrontend', '-enable-resilience',
                              '-Xfrontend', '-enable-class-resilience',
                              '-D', config,
                              self.lib_src,
                              '-o', output_dylib]
            if self.is_apple_platform():
                compiler_flags += ['-Xlinker',
                                   '-install_name',
                                   '-Xlinker',
                                   os.path.join('@rpath', lib_file)]

            command = self.target_build_swift + \
                self.additional_compile_flags_library + compiler_flags
            verbose_print_command(command)
            returncode = subprocess.call(command)
            assert returncode == 0, str(command)

            codesign_cmd = self.target_codesign + [output_dylib]
            verbose_print_command(codesign_cmd)
            returncode = subprocess.call(codesign_cmd)
            assert returncode == 0, str(codesign_cmd)

    def compile_main(self):
        for config in self.config_dir_map:
            output_obj = os.path.join(self.config_dir_map[config], 'main.o')
            compiler_flags = ['-D', config, '-c', self.test_src,
                              '-Xfrontend', '-enable-class-resilience',
                              '-I', self.config_dir_map[config],
                              '-o', output_obj]
            command = self.target_build_swift + compiler_flags
            verbose_print_command(command)
            returncode = subprocess.call(command)
            assert returncode == 0, str(command)

    def configs(self):
        for config1 in self.config_dir_map:
            for config2 in self.config_dir_map:
                # --no-backward-deployment skips testing a new application
                # linked against an old library.
                if config1 == "BEFORE" and \
                   config2 == "AFTER" and \
                   self.no_backward_deployment:
                    continue

                yield (config1, config2)

    def link(self):
        for config1, config2 in self.configs():
            config1_lower = config1.lower()
            config2_lower = config2.lower()
            output_obj = os.path.join(self.tmp_dir,
                                      config1_lower + '_' + config2_lower)
            if self.is_apple_platform():
                rpath_origin = '@executable_path'
            else:
                rpath_origin = '$ORIGIN'

            compiler_flags = [
                '-L', self.config_dir_map[config2],
                '-l' + self.lib_name,
                os.path.join(self.config_dir_map[config2],
                             'main.o'),
                '-Xlinker', '-rpath', '-Xlinker',
                os.path.join(rpath_origin,
                             os.path.relpath(self.config_dir_map[config1],
                                             self.tmp_dir)),
                '-o', output_obj
            ]

            command = self.target_build_swift + compiler_flags
            verbose_print_command(command)
            returncode = subprocess.call(command)
            assert returncode == 0, str(command)

    def execute(self):
        for config1, config2 in self.configs():
            config1_lower = config1.lower()
            config2_lower = config2.lower()
            output_obj = os.path.join(self.tmp_dir,
                                      config1_lower + '_' + config2_lower)
            command = self.target_run + [output_obj, self.tmp_dir]
            verbose_print_command(command)
            returncode = subprocess.call(command)
            assert returncode == 0, str(command)


def main():
    parser = argparse.ArgumentParser(description='Resilience test helper')
    parser.add_argument('--target-build-swift', required=True)
    parser.add_argument('--target-run', required=True)
    parser.add_argument('--target-codesign', default='echo')
    parser.add_argument('--t', required=True)
    parser.add_argument('--S', required=True)
    parser.add_argument('--s', required=True)
    parser.add_argument('--lib-prefix', required=True)
    parser.add_argument('--lib-suffix', required=True)
    parser.add_argument('--additional-compile-flags-library', default='')
    parser.add_argument('--no-backward-deployment', default=False,
                        action='store_true')

    args = parser.parse_args()

    resilience_test = ResilienceTest(args.target_build_swift, args.target_run,
                                     args.target_codesign,
                                     args.t, args.S, args.s, args.lib_prefix,
                                     args.lib_suffix,
                                     args.additional_compile_flags_library,
                                     args.no_backward_deployment)

    return resilience_test.run()


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