#!/usr/bin/env python3.8

# Copyright 2021 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Compares previous output of all kazoo generation with current output.

The current golden state (vs. real syscalls) is saved in golden.txt.

A `cp` command will be printed to update golden.txt if the current
pipeline generates different output than previously checked in.
"""

import argparse
import datetime
import os
import shutil
import subprocess
import sys

SCRIPT_DIR = os.path.dirname(__file__)
GOLDEN = os.path.join(os.path.dirname(__file__), 'golden.txt')


def parse_args():
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument(
        '--fidlc', help='rspfile containing fidlc binary', required=True)
    parser.add_argument(
        '--kazoo', help='rspfile containing kazoo binary', required=True)
    parser.add_argument(
        '--syscalls',
        help='path to syscalls',
        default=os.path.normpath(
            os.path.join(SCRIPT_DIR, os.pardir, os.pardir, 'vdso')))
    parser.add_argument(
        '--p4merge',
        action='store_true',
        help='open diffs in p4merge if changes')
    parser.add_argument(
        '--output-touch', help='file to touch on success', required=True)
    parser.add_argument(
        '--tmp-base', help='location to use for temporary files', required=True)
    parser.add_argument(
        '--new-golden',
        help='path to output the new golden file',
        required=True)
    parser.add_argument(
        '--depfile',
        help='The path to write a depfile, see depfile from GN.',
        required=True)
    return parser.parse_args()


def generate_fidlc_json(fidlc_binary, syscall_dir, output_fidlc_json_path):
    fidl_files = []
    with os.scandir(syscall_dir) as it:
        for entry in it:
            if (not entry.name.startswith('.') and entry.is_file() and
                    entry.name.endswith('.fidl')):
                fidl_files.append(os.path.join(syscall_dir, entry.name))

    subprocess.check_call(
        [
            fidlc_binary, '--experimental', 'new_syntax_only', '--json',
            output_fidlc_json_path, '--files'
        ] + sorted(fidl_files))


def build_golden(input_files, output_combined):
    with open(output_combined, 'wb') as outf:
        for filename in input_files:
            outf.write(
                ('----- %s START -----\n' %
                 os.path.basename(filename)).encode('utf-8'))
            outf.write(open(filename, 'rb').read())
            outf.write(
                ('----- %s END -----\n\n\n' %
                 os.path.basename(filename)).encode('utf-8'))


def generate_kazoo_outputs(
        kazoo_binary, fidlc_json_path, all_output_styles, output_dir):

    def guess_ext(style):
        if style in ('go-vdso-arm64-calls', 'go-vdso-x86-calls'):
            return 's'
        if style.startswith('go'):
            return 'go'
        if style == 'rust':
            return 'rs'
        if style == 'json':
            return 'json'
        return 'h'

    style_args = []
    files = []
    for style in all_output_styles:
        filename = '%s.%s' % (os.path.join(output_dir, style), guess_ext(style))
        files.append(filename)
        style_args.append('--%s=%s' % (style, filename))
    subprocess.check_call([kazoo_binary] + style_args + [fidlc_json_path])
    return files


def read_rsp(path):
    with open(path, 'r') as f:
        return f.read().strip()


def main():
    args = parse_args()

    tmp_json = os.path.join(args.tmp_base, 'syscalls.json')
    fidlc = read_rsp(args.fidlc)
    generate_fidlc_json(fidlc, args.syscalls, tmp_json)

    tmp_kazoo_dir = os.path.join(args.tmp_base, 'kazoo-outputs')
    try:
        shutil.rmtree(tmp_kazoo_dir)
    except:
        pass
    os.makedirs(tmp_kazoo_dir)

    all_styles = (
        'c-ulib-header',
        'category',
        'next-public-header',
        'go-syscall-arm64-asm',
        'go-syscall-stubs',
        'go-syscall-x86-asm',
        'go-vdso-arm64-calls',
        'go-vdso-keys',
        'go-vdso-x86-calls',
        'json',
        'kernel-header',
        'kernel-wrappers',
        'private-header',
        'public-header',
        'rust',
        'syscall-numbers',
        'testonly-public-header',
    )
    kazoo = read_rsp(args.kazoo)
    files = generate_kazoo_outputs(kazoo, tmp_json, all_styles, tmp_kazoo_dir)

    build_golden(files, args.new_golden)
    result = subprocess.run(['diff', '-u', GOLDEN, args.new_golden], stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT)
    if result.returncode != 0:
        print('CHANGES DETECTED IN SYSCALL OUTPUT')
        print()
        print('Please run:')
        print(
            '  cp "$(fx get-build-dir)/%s" "$(fx get-build-dir)/%s"' %
            (args.new_golden, GOLDEN))
        print('to acknowledge these changes.')
        print()
        print(
            'Files can be found locally in %s for inspection.' % tmp_kazoo_dir)
        if args.p4merge:
            subprocess.call(['p4merge', GOLDEN, args.new_golden])

        # Print the diff after the instructions so the instructions are not truncated by the
        # buildbot if the output is long.
        print('Diff:')
        # Need to decode the stdout binary data to a string to write newlines properly.
        print(result.stdout.decode('ascii'));
    else:
        with open(args.output_touch, 'w') as f:
            f.write(str(datetime.datetime.utcnow()))
        with open(args.depfile, 'w') as f:
            f.write(f'{args.output_touch} {args.new_golden}: {fidlc} {kazoo}\n')

    shutil.rmtree(tmp_kazoo_dir)

    return result.returncode


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