#!/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, tmp_dir, test_dir,
                 test_src, additional_compile_flags_library,
                 no_backward_deployment):
        self.target_build_swift = shlex.split(target_build_swift)
        self.target_run = shlex.split(target_run)
        self.tmp_dir = tmp_dir
        self.test_dir = test_dir
        self.test_src = test_src
        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_obj_name = self.lib_src_name[:-6] + '.o'
        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 compile_library(self):
        for config in self.config_dir_map:
            for emit_flag in ['-emit-library', '-emit-module']:
                output_obj = os.path.join(self.config_dir_map[config],
                                          self.lib_obj_name)
                compiler_flags = [emit_flag,
                                  '-swift-version', '4',
                                  '-Xfrontend', '-enable-resilience',
                                  '-D', config,
                                  '-c', self.lib_src,
                                  '-o', output_obj]
                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)

    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, '-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)
            compiler_flags = [
                os.path.join(self.config_dir_map[config1],
                             self.lib_obj_name),
                os.path.join(self.config_dir_map[config2],
                             'main.o'),
                '-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]
            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('--t', required=True)
    parser.add_argument('--S', required=True)
    parser.add_argument('--s', 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.t, args.S, args.s,
                                     args.additional_compile_flags_library,
                                     args.no_backward_deployment)

    return resilience_test.run()


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