#!/usr/bin/env python3
import argparse
import multiprocessing
import os
import sys

import nose2

from infra.basetest import BRConfigTest


def main():
    parser = argparse.ArgumentParser(description='Run Buildroot tests')
    parser.add_argument('testname', nargs='*',
                        help='list of test cases to execute')
    parser.add_argument('-l', '--list', action='store_true',
                        help='list of available test cases')
    parser.add_argument('-a', '--all', action='store_true',
                        help='execute all test cases')
    parser.add_argument('-s', '--stdout', action='store_true',
                        help='log everything to stdout')
    parser.add_argument('-o', '--output',
                        help='output directory')
    parser.add_argument('-d', '--download',
                        help='download directory')
    parser.add_argument('-k', '--keep',
                        help='keep build directories',
                        action='store_true')
    parser.add_argument('-t', '--testcases', type=int, default=1,
                        help='number of testcases to run simultaneously')
    parser.add_argument('-j', '--jlevel', type=int,
                        help='BR2_JLEVEL to use for each testcase')
    parser.add_argument('--timeout-multiplier', type=int, default=1,
                        help='increase timeouts (useful for slow machines)')

    args = parser.parse_args()

    script_path = os.path.realpath(__file__)
    test_dir = os.path.dirname(script_path)

    if args.stdout:
        BRConfigTest.logtofile = False

    if args.list:
        print("List of tests")
        nose2.discover(argv=[script_path,
                             "-s", test_dir,
                             "-v",
                             "--collect-only"],
                       plugins=["nose2.plugins.collect"])
        return 0

    if args.download is None:
        args.download = os.getenv("BR2_DL_DIR")
        if args.download is None:
            print("Missing download directory, please use -d/--download")
            print("")
            parser.print_help()
            return 1

    BRConfigTest.downloaddir = os.path.abspath(args.download)

    if args.output is None:
        print("Missing output directory, please use -o/--output")
        print("")
        parser.print_help()
        return 1

    if not os.path.exists(args.output):
        os.mkdir(args.output)

    BRConfigTest.outputdir = os.path.abspath(args.output)

    if args.all is False and not args.testname:
        print("No test selected")
        print("")
        parser.print_help()
        return 1

    BRConfigTest.keepbuilds = args.keep

    if args.testcases != 1:
        if args.testcases < 1:
            print("Invalid number of testcases to run simultaneously")
            print("")
            parser.print_help()
            return 1
        # same default BR2_JLEVEL as package/Makefile.in
        br2_jlevel = 1 + multiprocessing.cpu_count()
        each_testcase = br2_jlevel / args.testcases
        if each_testcase < 1:
            each_testcase = 1
        BRConfigTest.jlevel = each_testcase

    if args.jlevel:
        if args.jlevel < 0:
            print("Invalid BR2_JLEVEL to use for each testcase")
            print("")
            parser.print_help()
            return 1
        # the user can override the auto calculated value
        BRConfigTest.jlevel = args.jlevel

    if args.timeout_multiplier < 1:
        print("Invalid multiplier for timeout values")
        print("")
        parser.print_help()
        return 1
    BRConfigTest.timeout_multiplier = args.timeout_multiplier

    nose2_args = ["-v",
                  "-N", str(args.testcases),
                  "-s", test_dir,
                  "-c", os.path.join(test_dir, "conf/unittest.cfg")]

    if args.testname:
        nose2_args += args.testname

    nose2.discover(argv=nose2_args)


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