#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# File: test-interrupts
# Author: Lorenz Stechauner <e12119052@student.tuwien.ac.at>
#         Lorenz Stechauner <lorenz.stechauner@necronda.net>

import os
import sys
import argparse
import threading
import subprocess

import intercept
import intercept.standard


def neutral(text: str) -> None:
    print(text, file=sys.stderr)

def color(text: str, col: str) -> None:
    print(('\x1B[' + col + 'm' if sys.stderr.isatty() else '')
          + text
          + ('\x1B[0m' if sys.stderr.isatty() else ''),
          file=sys.stderr)

def bold(text: str) -> None:
    color(text, '1')

def test_result(test: list[str], result: bool or None) -> None:
    text = ':: TEST :: ' + ' :: '.join(test)
    esc = '\x1B[' + ({True: '32', False: '31', None: ''}[result]) + 'm' if sys.stderr.isatty() else ''
    result = {True: 'PASSED', False: 'FAILED', None: 'SKIPPED'}[result]
    bold(f'{text} {"." * (80 - len(text))} {esc}{result}')


def socket_thread(socket: str, handler: type[intercept.Handler]) -> None:
    intercept.intercept(socket, handler)


def main() -> None:
    parser = argparse.ArgumentParser()
    args, extra = parser.parse_known_args()
    if len(extra) > 0 and extra[0] == '--':
        extra.pop(0)
    if len(extra) == 0:
        parser.error("command expected after arguments or '--'")

    socket_name = f'/tmp/intercept.interrupts.{os.getpid()}.sock'
    ctx, handler = intercept.standard.init_with_ctx(intercept.standard.InterruptedCheckTester)
    t1 = threading.Thread(target=socket_thread, args=(socket_name, handler))
    t1.daemon = True
    t1.start()
    try:
        subprocess.run(extra, env={
            'LD_PRELOAD': os.getcwd() + '/../../intercept/intercept.so',
            'INTERCEPT': 'unix:' + socket_name,
            'INTERCEPT_VERBOSE': '1',
            'INTERCEPT_FUNCTIONS': '*',
            'INTERCEPT_LIBRARIES': ','.join(['*', '-/lib*', '-/usr/lib*']),
        })
    except KeyboardInterrupt:
        pass

    bold(':: REPORT ::')
    for call, status in ctx['results'].items():
        if status == 'passed':
            test_result(['Interrupt handling', str(call)], True)
        else:
            test_result(['Interrupt handling', str(call)], False)



if __name__ == '__main__':
    main()
