# Lint as: python2, python3
# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import gzip, logging, os, re
from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error

class KernelConfig():
    """
    Parse the kernel config and enable us to query it.
    Used to verify the kernel config (see kernel_ConfigVerify).
    """

    def _passed(self, msg):
        logging.info('ok: %s', msg)

    def _failed(self, msg):
        logging.error('FAIL: %s', msg)
        self._failures.append(msg)

    def failures(self):
        """Return the list of failures that occured during the test.

        @return a list of string describing errors that occured since
                initialization.
        """
        return self._failures

    def _fatal(self, msg):
        logging.error('FATAL: %s', msg)
        raise error.TestError(msg)

    def get(self, key, default):
        """Get the value associated to key or default if it does not exist

        @param key: key to look for.
        @param default: value returned if key is not set in self._config
        """
        return self._config.get(key, default)

    def _config_required(self, name, wanted):
        value = self._config.get(name, None)
        if value in wanted:
            self._passed('"%s" was "%s" in kernel config' % (name, value))
        else:
            states = []
            for state in wanted:
                if state == None:
                    states.append("unset")
                else:
                    states.append(state)
            self._failed('"%s" was "%s" (wanted one of "%s") in kernel config' %
                         (name, value, '|'.join(states)))

    def has_value(self, name, value):
        """Determine if the name config item has a specific value.

        @param name: name of config item to test
        @param value: value expected for the given config name
        """
        self._config_required('CONFIG_%s' % (name), value)

    def has_builtin(self, name):
        """Check if the specific config item is built-in (present but not
        built as a module).

        @param name: name of config item to test
        """
        wanted = ['y']
        if name in self._missing_ok:
            wanted.append(None)
        self.has_value(name, wanted)

    def has_module(self, name):
        """Check if the specific config item is a module (present but not
        built-in).

        @param name: name of config item to test
        """
        wanted = ['m']
        if name in self._missing_ok:
            wanted.append(None)
        self.has_value(name, wanted)

    def is_enabled(self, name):
        """Check if the specific config item is present (either built-in or
        a module).

        @param name: name of config item to test
        """
        wanted = ['y', 'm']
        if name in self._missing_ok:
            wanted.append(None)
        self.has_value(name, wanted)

    def is_missing(self, name):
        """Check if the specific config item is not present (neither built-in
        nor a module).

        @param name: name of config item to test
        """
        self.has_value(name, [None])

    def is_exclusive(self, exclusive):
        """Given a config item regex, make sure only the expected items
        are present in the kernel configs.

        @param exclusive: hash containing "missing", "builtin", "module",
                          "enabled" each to be checked with the corresponding
                          has_* function based on config items matching the
                          "regex" value.
        """
        expected = set()
        for name in exclusive['missing']:
            self.is_missing(name)
        for name in exclusive['builtin']:
            self.has_builtin(name)
            expected.add('CONFIG_%s' % (name))
        for name in exclusive['module']:
            self.has_module(name)
            expected.add('CONFIG_%s' % (name))
        for name in exclusive['enabled']:
            self.is_enabled(name)
            expected.add('CONFIG_%s' % (name))

        # Now make sure nothing else with the specified regex exists.
        regex = r'CONFIG_%s' % (exclusive['regex'])
        for name in self._config:
            if not re.match(regex, name):
                continue
            if not name in expected:
                self._failed('"%s" found for "%s" when only "%s" allowed' %
                             (name, regex, "|".join(expected)))

    def _read_config(self):
        """Open the kernel's build config file. Attempt to use the built-in
        symbols from /proc first, then fall back to looking for a text file
        in /boot.

        @return readlines for fileobj
        """
        filename = '/proc/config.gz'
        if not os.path.exists(filename):
            utils.system("modprobe configs", ignore_status=True)
        if os.path.exists(filename):
            with gzip.open(filename, "rt") as rf:
                return rf.readlines()

        filename = '/boot/config-%s' % utils.system_output('uname -r')
        if os.path.exists(filename):
            logging.info('Falling back to reading %s', filename)
            with open(filename, "r") as rf:
                return rf.readlines()

        self._fatal("Cannot locate suitable kernel config file")

    def initialize(self, missing_ok=None):
        """Load the kernel configuration and parse it.
        """
        file_lines = self._read_config()
        # Import kernel config variables into a dictionary for each searching.
        config = dict()
        for item in file_lines:
            item = item.strip()
            if not '=' in item:
                continue
            key, value = item.split('=', 1)
            config[key] = value

        # Make sure we actually loaded something sensible.
        if len(config) == 0:
            self._fatal('No CONFIG variables found!')

        self._config = config
        self._failures = []
        self._missing_ok = set()
        if missing_ok:
            self._missing_ok |= set(missing_ok)
