#!/usr/bin/python3
#
# Build performance test script
#
# Copyright (c) 2016, Intel Corporation.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
# more details.
#
"""Build performance test script"""
import argparse
import errno
import fcntl
import logging
import os
import shutil
import sys
import unittest
from datetime import datetime

sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '/lib')
import scriptpath
scriptpath.add_oe_lib_path()
import oeqa.buildperf
from oeqa.buildperf import (BuildPerfTestLoader, BuildPerfTestResult,
                            BuildPerfTestRunner, KernelDropCaches)
from oeqa.utils.commands import runCmd
from oeqa.utils.git import GitRepo, GitError


# Set-up logging
LOG_FORMAT = '[%(asctime)s] %(levelname)s: %(message)s'
logging.basicConfig(level=logging.INFO, format=LOG_FORMAT,
                    datefmt='%Y-%m-%d %H:%M:%S')
log = logging.getLogger()


def acquire_lock(lock_f):
    """Acquire flock on file"""
    log.debug("Acquiring lock %s", os.path.abspath(lock_f.name))
    try:
        fcntl.flock(lock_f, fcntl.LOCK_EX | fcntl.LOCK_NB)
    except IOError as err:
        if err.errno == errno.EAGAIN:
            return False
        raise
    log.debug("Lock acquired")
    return True


def pre_run_sanity_check():
    """Sanity check of build environment"""
    build_dir = os.environ.get("BUILDDIR")
    if not build_dir:
        log.error("BUILDDIR not set. Please run the build environmnent setup "
                  "script.")
        return False
    if os.getcwd() != build_dir:
        log.error("Please run this script under BUILDDIR (%s)", build_dir)
        return False

    ret = runCmd('which bitbake', ignore_status=True)
    if ret.status:
        log.error("bitbake command not found")
        return False
    return True

def init_git_repo(path):
    """Check/create Git repository where to store results"""
    path = os.path.abspath(path)
    if os.path.isfile(path):
        log.error("Invalid Git repo %s: path exists but is not a directory", path)
        return False
    if not os.path.isdir(path):
        try:
            os.mkdir(path)
        except (FileNotFoundError, PermissionError) as err:
            log.error("Failed to mkdir %s: %s", path, err)
            return False
    if not os.listdir(path):
        log.info("Initializing a new Git repo at %s", path)
        GitRepo.init(path)
    try:
        GitRepo(path, is_topdir=True)
    except GitError:
        log.error("No Git repository but a non-empty directory found at %s.\n"
                  "Please specify a Git repository, an empty directory or "
                  "a non-existing directory", path)
        return False
    return True


def setup_file_logging(log_file):
    """Setup loggin to file"""
    log_dir = os.path.dirname(log_file)
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)
    formatter = logging.Formatter(LOG_FORMAT)
    handler = logging.FileHandler(log_file)
    handler.setFormatter(formatter)
    log.addHandler(handler)


def archive_build_conf(out_dir):
    """Archive build/conf to test results"""
    src_dir = os.path.join(os.environ['BUILDDIR'], 'conf')
    tgt_dir = os.path.join(out_dir, 'build', 'conf')
    os.makedirs(os.path.dirname(tgt_dir))
    shutil.copytree(src_dir, tgt_dir)


def parse_args(argv):
    """Parse command line arguments"""
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument('-D', '--debug', action='store_true',
                        help='Enable debug level logging')
    parser.add_argument('--globalres-file',
                        type=os.path.abspath,
                        help="Append results to 'globalres' csv file")
    parser.add_argument('--lock-file', default='./oe-build-perf.lock',
                        metavar='FILENAME', type=os.path.abspath,
                        help="Lock file to use")
    parser.add_argument('-o', '--out-dir', default='results-{date}',
                        type=os.path.abspath,
                        help="Output directory for test results")
    parser.add_argument('--log-file',
                        default='{out_dir}/oe-build-perf-test.log',
                        help="Log file of this script")
    parser.add_argument('--run-tests', nargs='+', metavar='TEST',
                        help="List of tests to run")
    parser.add_argument('--commit-results', metavar='GIT_DIR',
                        type=os.path.abspath,
                        help="Commit result data to a (local) git repository")
    parser.add_argument('--commit-results-branch', metavar='BRANCH',
                        default="{git_branch}",
                        help="Commit results to branch BRANCH.")
    parser.add_argument('--commit-results-tag', metavar='TAG',
                        default="{git_branch}/{git_commit_count}-g{git_commit}/{tag_num}",
                        help="Tag results commit with TAG.")

    return parser.parse_args(argv)


def main(argv=None):
    """Script entry point"""
    args = parse_args(argv)

    # Set-up log file
    out_dir = args.out_dir.format(date=datetime.now().strftime('%Y%m%d%H%M%S'))
    setup_file_logging(args.log_file.format(out_dir=out_dir))

    if args.debug:
        log.setLevel(logging.DEBUG)

    lock_f = open(args.lock_file, 'w')
    if not acquire_lock(lock_f):
        log.error("Another instance of this script is running, exiting...")
        return 1

    if not pre_run_sanity_check():
        return 1
    if args.commit_results:
        if not init_git_repo(args.commit_results):
            return 1

    # Check our capability to drop caches and ask pass if needed
    KernelDropCaches.check()

    # Load build perf tests
    loader = BuildPerfTestLoader()
    if args.run_tests:
        suite = loader.loadTestsFromNames(args.run_tests, oeqa.buildperf)
    else:
        suite = loader.loadTestsFromModule(oeqa.buildperf)

    archive_build_conf(out_dir)
    runner = BuildPerfTestRunner(out_dir, verbosity=2)

    # Suppress logger output to stderr so that the output from unittest
    # is not mixed with occasional logger output
    log.handlers[0].setLevel(logging.CRITICAL)

    # Run actual tests
    result = runner.run(suite)

    # Restore logger output to stderr
    log.handlers[0].setLevel(log.level)

    if args.globalres_file:
        result.update_globalres_file(args.globalres_file)
    if args.commit_results:
        result.git_commit_results(args.commit_results,
                                  args.commit_results_branch,
                                  args.commit_results_tag)
    if result.wasSuccessful():
        return 0

    return 2


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

