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

import argparse
import getpass
import logging
import sys

import common
from autotest_lib.client.common_lib import utils


def setup_logging(log_level):
    """Sets up direct logging to stdout for unittests.

    @param log_level: Level of logging to redirect to stdout, default to INFO.
    """
    # Lifted from client.common_lib.logging_config.
    FORMAT = ('%(asctime)s.%(msecs)03d %(levelname)-5.5s|%(module)18.18s:'
              '%(lineno)4.4d| %(threadName)16.16s(%(thread)d)| %(message)s')

    logger = logging.getLogger()
    logger.setLevel(log_level)
    handler = logging.StreamHandler(sys.stdout)
    handler.setLevel(log_level)
    formatter = logging.Formatter(FORMAT)
    handler.setFormatter(formatter)
    logger.handlers = []
    logger.addHandler(handler)


def verify_user(require_sudo=True):
    """Checks that the current user is not root, but has sudo.

    Running unit tests as root can mask permissions problems, as not all the
    code runs as root in production.
    """
    # Ensure this process is not running as root.
    if getpass.getuser() == 'root':
        raise EnvironmentError('Unittests should not be run as root.')

    # However, most of the unit tests do require sudo.
    # TODO(dshi): crbug.com/459344 Set remove this enforcement when test
    # container can be unprivileged container.
    if require_sudo and utils.sudo_require_password():
        logging.warning('SSP requires root privilege to run commands, please '
                     'grant root access to this process.')
        utils.run('sudo true')


class Config(object):
    """A class for parsing and storing command line options.

    A convenience class for helping with unit test setup.  A global instance of
    this class is set up by the setup function.  Clients can then check this
    object for flags set on the command line.
    """
    def parse_options(self):
        """Parses command line flags for unittests."""
        parser = argparse.ArgumentParser()
        parser.add_argument('-v', '--verbose', action='store_true',
                            default=False,
                            help='Print out ALL entries.')
        parser.add_argument('-s', '--skip_cleanup', action='store_true',
                            default=False,
                            help='Skip deleting test containers.')
        args, argv = parser.parse_known_args()

        for attr, value in vars(args).items():
            setattr(self, attr, value)

        # Hack: python unittest also processes args.  Construct an argv to pass
        # to it, that filters out the options it won't recognize.  Then replace
        # sys.argv with the constructed argv so that calling unittest.main "just
        # works".
        if args.verbose:
            argv.insert(0, '-v')
        argv.insert(0, sys.argv[0])
        sys.argv = argv


# Global namespace object for storing unittest options specified on the command
# line.
config = Config()

def setup(require_sudo=True):
    """Performs global setup for unit-tests."""
    global setup_run
    config.parse_options()

    verify_user(require_sudo)

    log_level = logging.DEBUG if config.verbose else logging.INFO
    setup_logging(log_level)
