# Copyright 2014 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Script to mount a built image and run tests on it."""

import contextlib
import os
import unittest

from chromite.lib import commandline
from chromite.lib import constants
from chromite.lib import image_lib
from chromite.lib import image_test_lib
from chromite.lib import osutils
from chromite.lib import path_util


def ParseArgs(args):
    """Return parsed commandline arguments."""

    parser = commandline.ArgumentParser(description=__doc__)
    parser.add_argument(
        "--test_results_root",
        type="str_path",
        help="Directory to store test results",
    )
    parser.add_argument("--board", type=str, help="Board (wolf, beaglebone...)")
    parser.add_argument(
        "image",
        type="str_path",
        help="Image directory or file to test",
    )

    parser.add_argument(
        "-l",
        "--list",
        default=False,
        action="store_true",
        help="List all the available tests",
    )
    parser.add_bool_argument(
        "--bind-mount",
        default=False,
        enabled_desc="bind mount the image path as ROOT-A",
        disabled_desc="mount ROOT-A and STATE from the image file",
    )
    parser.add_argument(
        "tests",
        nargs="*",
        metavar="test",
        help="Specific tests to run (default runs all)",
    )

    opts = parser.parse_args(args)
    opts.Freeze()
    return opts


def FindImage(image_path):
    """Return the path to the image file.

    Args:
        image_path: A path to the image file, or a directory containing the base
            image.

    Returns:
        ImageFileAndMountScripts containing absolute paths to the image,
        the mount and umount invocation commands
    """

    if os.path.isdir(image_path):
        # Assume base image.
        image_file = os.path.join(
            image_path, constants.BASE_IMAGE_NAME + ".bin"
        )
        if not os.path.exists(image_file):
            raise ValueError("Cannot find base image %s" % image_file)
    elif os.path.isfile(image_path):
        image_file = image_path
    else:
        raise ValueError("%s is neither a directory nor a file" % image_path)

    return image_file


def main(args):
    opts = ParseArgs(args)

    # Build up test suites.
    loader = unittest.TestLoader()
    loader.suiteClass = image_test_lib.ImageTestSuite
    # We use a different prefix here so that unittest DO NOT pick up the
    # image tests automatically because they depend on a proper environment.
    loader.testMethodPrefix = "Test"
    tests_namespace = "chromite.cros.test.image_test"
    if opts.tests:
        tests = ["%s.%s" % (tests_namespace, x) for x in opts.tests]
    else:
        tests = (tests_namespace,)
    all_tests = loader.loadTestsFromNames(tests)

    # If they just want to see the lists of tests, show them now.
    if opts.list:

        def _WalkSuite(suite):
            for test in suite:
                if isinstance(test, unittest.BaseTestSuite):
                    for result in _WalkSuite(test):
                        yield result
                else:
                    yield (
                        test.id()[len(tests_namespace) + 1 :],
                        test.shortDescription() or "",
                    )

        test_list = list(_WalkSuite(all_tests))
        maxlen = max(len(x[0]) for x in test_list)
        for name, desc in test_list:
            print("%-*s  %s" % (maxlen, name, desc))
        return

    # Run them in the image directory.
    runner = image_test_lib.ImageTestRunner()
    runner.SetBoard(opts.board)
    runner.SetResultDir(opts.test_results_root)
    tmp_in_chroot = path_util.FromChrootPath("/tmp")

    with contextlib.ExitStack() as stack:
        temp_dir = stack.enter_context(osutils.TempDir(base_dir=tmp_in_chroot))

        if opts.bind_mount:
            runner.SetImageType(image_test_lib.ImageType.BIND_MOUNT)
            mount_path = temp_dir + "/dir-" + constants.PART_ROOT_A
            stack.enter_context(
                osutils.MountDirContext(
                    opts.image, mount_path, mount_opts=("bind", "ro")
                )
            )
        else:
            runner.SetImageType(image_test_lib.ImageType.BIN_FILE)
            image_file = FindImage(opts.image)
            stack.enter_context(
                image_lib.LoopbackPartitions(
                    image_file,
                    temp_dir,
                    (constants.PART_ROOT_A, constants.PART_STATE),
                )
            )

        with osutils.ChdirContext(temp_dir):
            result = runner.run(all_tests)

    if result and not result.wasSuccessful():
        return 1
    return 0
