# Lint as: python2, python3
# Copyright 2016 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.

"""Unit tests for the `repair` module."""

# pylint: disable=missing-docstring

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import functools
import logging
import unittest

import common
from autotest_lib.client.common_lib import hosts
from autotest_lib.client.common_lib.hosts import repair
from autotest_lib.server import constants
from autotest_lib.server.hosts import host_info
from six.moves import range


class _GoodVerifier(hosts.Verifier):
    """Verifier is always good"""
    def verify(self, host):
        pass


class _BadVerifier(hosts.Verifier):
    """Verifier is always fail"""
    def verify(self, host):
        raise Exception('Just not your day')


class _SkipVerifier(hosts.Verifier):
    """Verifier is always not applicable"""
    def verify(self, host):
        pass

    def _is_applicable(self, host):
        return False


class _StubHost(object):
    """
    Stub class to fill in the relevant methods of `Host`.

    This class provides mocking and stub behaviors for `Host` for use by
    tests within this module.  The class implements only those methods
    that `Verifier` and `RepairAction` actually use.
    """

    def __init__(self):
        self._record_sequence = []
        fake_board_name = constants.Labels.BOARD_PREFIX + 'fubar'
        info = host_info.HostInfo(labels=[fake_board_name])
        self.host_info_store = host_info.InMemoryHostInfoStore(info)
        self.hostname = 'unittest_host'


    def record(self, status_code, subdir, operation, status=''):
        """
        Mock method to capture records written to `status.log`.

        Each record is remembered in order to be checked for correctness
        by individual tests later.

        @param status_code  As for `Host.record()`.
        @param subdir       As for `Host.record()`.
        @param operation    As for `Host.record()`.
        @param status       As for `Host.record()`.
        """
        full_record = (status_code, subdir, operation, status)
        self._record_sequence.append(full_record)


    def get_log_records(self):
        """
        Return the records logged for this fake host.

        The returned list of records excludes records where the
        `operation` parameter is not in `tagset`.

        @param tagset   Only include log records with these tags.
        """
        return self._record_sequence


    def reset_log_records(self):
        """Clear our history of log records to allow re-testing."""
        self._record_sequence = []


class _StubVerifier(hosts.Verifier):
    """
    Stub implementation of `Verifier` for testing purposes.

    This is a full implementation of a concrete `Verifier` subclass
    designed to allow calling unit tests control over whether verify
    passes or fails.

    A `_StubVerifier()` will pass whenever the value of `_fail_count`
    is non-zero.  Calls to `try_repair()` (typically made by a
    `_StubRepairAction()`) will reduce this count, eventually
    "repairing" the verifier.

    @property verify_count  The number of calls made to the instance's
                            `verify()` method.
    @property message       If verification fails, the exception raised,
                            when converted to a string, will have this
                            value.
    @property _fail_count   The number of repair attempts required
                            before this verifier will succeed.  A
                            non-zero value means verification will fail.
    @property _description  The value of the `description` property.
    """

    def __init__(self, tag, deps, fail_count):
        super(_StubVerifier, self).__init__(tag, deps)
        self.verify_count = 0
        self.message = 'Failing "%s" by request' % tag
        self._fail_count = fail_count
        self._description = 'Testing verify() for "%s"' % tag
        self._log_record_map = {
            r[0]: r for r in [
                ('GOOD', None, self._record_tag, ''),
                ('FAIL', None, self._record_tag, self.message),
            ]
        }


    def __repr__(self):
        return '_StubVerifier(%r, %r, %r)' % (
                self.tag, self._dependency_list, self._fail_count)


    def verify(self, host):
        self.verify_count += 1
        if self._fail_count:
            raise hosts.AutoservVerifyError(self.message)


    def try_repair(self):
        """Bring ourselves one step closer to working."""
        if self._fail_count:
            self._fail_count -= 1


    def unrepair(self):
        """Make ourselves more broken."""
        self._fail_count += 1


    def get_log_record(self, status):
        """
        Return a host log record for this verifier.

        Calculates the arguments expected to be passed to
        `Host.record()` by `Verifier._verify_host()` when this verifier
        runs.  The passed in `status` corresponds to the argument of the
        same name to be passed to `Host.record()`.

        @param status   Status value of the log record.
        """
        return self._log_record_map[status]


    @property
    def description(self):
        return self._description


class _StubRepairFailure(Exception):
    """Exception to be raised by `_StubRepairAction.repair()`."""
    pass


class _StubRepairAction(hosts.RepairAction):
    """Stub implementation of `RepairAction` for testing purposes.

    This is a full implementation of a concrete `RepairAction` subclass
    designed to allow calling unit tests control over whether repair
    passes or fails.

    The behavior of `repair()` depends on the `_success` property of a
    `_StubRepairAction`.  When the property is true, repair will call
    `try_repair()` for all triggers, and then report success.  When the
    property is false, repair reports failure.

    @property repair_count  The number of calls made to the instance's
                            `repair()` method.
    @property message       If repair fails, the exception raised, when
                            converted to a string, will have this value.
    @property _success      Whether repair will follow its "success" or
                            "failure" paths.
    @property _description  The value of the `description` property.
    """

    def __init__(self, tag, deps, triggers, host_class, success):
        super(_StubRepairAction, self).__init__(tag, deps, triggers,
                                                host_class)
        self.repair_count = 0
        self.message = 'Failed repair for "%s"' % tag
        self._success = success
        self._description = 'Testing repair for "%s"' % tag
        self._log_record_map = {
            r[0]: r for r in [
                ('START', None, self._record_tag, ''),
                ('FAIL', None, self._record_tag, self.message),
                ('END FAIL', None, self._record_tag, ''),
                ('END GOOD', None, self._record_tag, ''),
            ]
        }


    def __repr__(self):
        return '_StubRepairAction(%r, %r, %r, %r)' % (
                self.tag, self._dependency_list,
                self._trigger_list, self._success)


    def repair(self, host):
        self.repair_count += 1
        if not self._success:
            raise _StubRepairFailure(self.message)
        for v in self._trigger_list:
            v.try_repair()


    def get_log_record(self, status):
        """
        Return a host log record for this repair action.

        Calculates the arguments expected to be passed to
        `Host.record()` by `RepairAction._repair_host()` when repair
        runs.  The passed in `status` corresponds to the argument of the
        same name to be passed to `Host.record()`.

        @param status   Status value of the log record.
        """
        return self._log_record_map[status]


    @property
    def description(self):
        return self._description


class _DependencyNodeTestCase(unittest.TestCase):
    """
    Abstract base class for `RepairAction` and `Verifier` test cases.

    This class provides `_make_verifier()` and `_make_repair_action()`
    methods to create `_StubVerifier` and `_StubRepairAction` instances,
    respectively, for testing.  Constructed verifiers and repair actions
    are remembered in `self.nodes`, a dictionary indexed by the tag
    used to construct the object.
    """

    def setUp(self):
        logging.disable(logging.CRITICAL)
        self._fake_host = _StubHost()
        self.nodes = {}


    def tearDown(self):
        logging.disable(logging.NOTSET)


    def _make_verifier(self, count, tag, deps):
        """
        Make a `_StubVerifier` and remember it in `self.nodes`.

        @param count  As for the `_StubVerifer` constructor.
        @param tag    As for the `_StubVerifer` constructor.
        @param deps   As for the `_StubVerifer` constructor.
        """
        verifier = _StubVerifier(tag, deps, count)
        self.nodes[tag] = verifier
        return verifier


    def _make_repair_action(self, success, tag, deps, triggers,
                            host_class='unittest'):
        """
        Make a `_StubRepairAction` and remember it in `self.nodes`.

        @param success    As for the `_StubRepairAction` constructor.
        @param tag        As for the `_StubRepairAction` constructor.
        @param deps       As for the `_StubRepairAction` constructor.
        @param triggers   As for the `_StubRepairAction` constructor.
        @param host_class As for the `_StubRepairAction` constructor.
        """
        repair_action = _StubRepairAction(tag, deps, triggers, host_class,
                                          success)
        self.nodes[tag] = repair_action
        return repair_action


    def _make_expected_failures(self, *verifiers):
        """
        Make a set of `_DependencyFailure` objects from `verifiers`.

        Return the set of `_DependencyFailure` objects that we would
        expect to see in the `failures` attribute of an
        `AutoservVerifyDependencyError` if all of the given verifiers
        report failure.

        @param verifiers  A list of `_StubVerifier` objects that are
                          expected to fail.

        @return A set of `_DependencyFailure` objects.
        """
        failures = [repair._DependencyFailure(v.description, v.message, v.tag)
                    for v in verifiers]
        return set(failures)


    def _generate_silent(self):
        """
        Iterator to test different settings of the `silent` parameter.

        This iterator exists to standardize testing assertions that
        This iterator exists to standardize testing common
        assertions about the `silent` parameter:
          * When the parameter is true, no calls are made to the
            `record()` method on the target host.
          * When the parameter is false, certain expected calls are made
            to the `record()` method on the target host.

        The iterator is meant to be used like this:

            for silent in self._generate_silent():
                # run test case that uses the silent parameter
                self._check_log_records(silent, ... expected records ... )

        The code above will run its test case twice, once with
        `silent=True` and once with `silent=False`.  In between the
        calls, log records are cleared.

        @yields A boolean setting for `silent`.
        """
        for silent in [False, True]:
            yield silent
            self._fake_host.reset_log_records()


    def _check_log_records(self, silent, *record_data):
        """
        Assert that log records occurred as expected.

        Elements of `record_data` should be tuples of the form
        `(tag, status)`, describing one expected log record.
        The verifier or repair action for `tag` provides the expected
        log record based on the status value.

        The `silent` parameter is the value that was passed to the
        verifier or repair action that did the logging.  When true,
        it indicates that no records should have been logged.

        @param record_data  List describing the expected record events.
        @param silent       When true, ignore `record_data` and assert
                            that nothing was logged.
        """
        expected_records = []
        if not silent:
            for tag, status in record_data:
                expected_records.append(
                        self.nodes[tag].get_log_record(status))
        actual_records = self._fake_host.get_log_records()
        self.assertEqual(expected_records, actual_records)


class VerifyTests(_DependencyNodeTestCase):
    """
    Unit tests for `Verifier`.

    The tests in this class test the fundamental behaviors of the
    `Verifier` class:
      * Results from the `verify()` method are cached; the method is
        only called the first time that `_verify_host()` is called.
      * The `_verify_host()` method makes the expected calls to
        `Host.record()` for every call to the `verify()` method.
      * When a dependency fails, the dependent verifier isn't called.
      * Verifier calls are made in the order required by the DAG.

    The test cases don't use `RepairStrategy` to build DAG structures,
    but instead rely on custom-built DAGs.
    """

    def _generate_verify_count(self, verifier):
        """
        Iterator to force a standard sequence with calls to `_reverify()`.

        This iterator exists to standardize testing two common
        assertions:
          * The side effects from calling `_verify_host()` only
            happen on the first call to the method, except...
          * Calling `_reverify()` resets a verifier so that the
            next call to `_verify_host()` will repeat the side
            effects.

        The iterator is meant to be used like this:

            for count in self._generate_verify_cases(verifier):
                # run a verifier._verify_host() test case
                self.assertEqual(verifier.verify_count, count)
                self._check_log_records(silent, ... expected records ... )

        The code above will run the `_verify_host()` test case twice,
        then call `_reverify()` to clear cached results, then re-run
        the test case two more times.

        @param verifier   The verifier to be tested and reverified.
        @yields Each iteration yields the number of times `_reverify()`
                has been called.
        """
        for i in range(1, 3):
            for _ in range(0, 2):
                yield i
            verifier._reverify()
            self._fake_host.reset_log_records()


    def test_success(self):
        """
        Test proper handling of a successful verification.

        Construct and call a simple, single-node verification that will
        pass.  Assert the following:
          * The `verify()` method is called once.
          * The expected 'GOOD' record is logged via `Host.record()`.
          * If `_verify_host()` is called more than once, there are no
            visible side-effects after the first call.
          * Calling `_reverify()` clears all cached results.
        """
        for silent in self._generate_silent():
            verifier = self._make_verifier(0, 'pass', [])
            for count in self._generate_verify_count(verifier):
                verifier._verify_host(self._fake_host, silent)
                self.assertEqual(verifier.verify_count, count)
                self._check_log_records(silent, ('pass', 'GOOD'))


    def test_fail(self):
        """
        Test proper handling of verification failure.

        Construct and call a simple, single-node verification that will
        fail.  Assert the following:
          * The failure is reported with the actual exception raised
            by the verifier.
          * The `verify()` method is called once.
          * The expected 'FAIL' record is logged via `Host.record()`.
          * If `_verify_host()` is called more than once, there are no
            visible side-effects after the first call.
          * Calling `_reverify()` clears all cached results.
        """
        for silent in self._generate_silent():
            verifier = self._make_verifier(1, 'fail', [])
            for count in self._generate_verify_count(verifier):
                with self.assertRaises(hosts.AutoservVerifyError) as e:
                    verifier._verify_host(self._fake_host, silent)
                self.assertEqual(verifier.verify_count, count)
                self.assertEqual(verifier.message, str(e.exception))
                self._check_log_records(silent, ('fail', 'FAIL'))


    def test_dependency_success(self):
        """
        Test proper handling of dependencies that succeed.

        Construct and call a two-node verification with one node
        dependent on the other, where both nodes will pass.  Assert the
        following:
          * The `verify()` method for both nodes is called once.
          * The expected 'GOOD' record is logged via `Host.record()`
            for both nodes.
          * If `_verify_host()` is called more than once, there are no
            visible side-effects after the first call.
          * Calling `_reverify()` clears all cached results.
        """
        for silent in self._generate_silent():
            child = self._make_verifier(0, 'pass', [])
            parent = self._make_verifier(0, 'parent', [child])
            for count in self._generate_verify_count(parent):
                parent._verify_host(self._fake_host, silent)
                self.assertEqual(parent.verify_count, count)
                self.assertEqual(child.verify_count, count)
                self._check_log_records(silent,
                                        ('pass', 'GOOD'),
                                        ('parent', 'GOOD'))


    def test_dependency_fail(self):
        """
        Test proper handling of dependencies that fail.

        Construct and call a two-node verification with one node
        dependent on the other, where the dependency will fail.  Assert
        the following:
          * The verification exception is `AutoservVerifyDependencyError`,
            and the exception argument is the description of the failed
            node.
          * The `verify()` method for the failing node is called once,
            and for the other node, not at all.
          * The expected 'FAIL' record is logged via `Host.record()`
            for the single failed node.
          * If `_verify_host()` is called more than once, there are no
            visible side-effects after the first call.
          * Calling `_reverify()` clears all cached results.
        """
        for silent in self._generate_silent():
            child = self._make_verifier(1, 'fail', [])
            parent = self._make_verifier(0, 'parent', [child])
            failures = self._make_expected_failures(child)
            for count in self._generate_verify_count(parent):
                expected_exception = hosts.AutoservVerifyDependencyError
                with self.assertRaises(expected_exception) as e:
                    parent._verify_host(self._fake_host, silent)
                self.assertEqual(e.exception.failures, failures)
                self.assertEqual(child.verify_count, count)
                self.assertEqual(parent.verify_count, 0)
                self._check_log_records(silent, ('fail', 'FAIL'))


    def test_two_dependencies_pass(self):
        """
        Test proper handling with two passing dependencies.

        Construct and call a three-node verification with one node
        dependent on the other two, where all nodes will pass.  Assert
        the following:
          * The `verify()` method for all nodes is called once.
          * The expected 'GOOD' records are logged via `Host.record()`
            for all three nodes.
          * If `_verify_host()` is called more than once, there are no
            visible side-effects after the first call.
          * Calling `_reverify()` clears all cached results.
        """
        for silent in self._generate_silent():
            left = self._make_verifier(0, 'left', [])
            right = self._make_verifier(0, 'right', [])
            top = self._make_verifier(0, 'top', [left, right])
            for count in self._generate_verify_count(top):
                top._verify_host(self._fake_host, silent)
                self.assertEqual(top.verify_count, count)
                self.assertEqual(left.verify_count, count)
                self.assertEqual(right.verify_count, count)
                self._check_log_records(silent,
                                        ('left', 'GOOD'),
                                        ('right', 'GOOD'),
                                        ('top', 'GOOD'))


    def test_two_dependencies_fail(self):
        """
        Test proper handling with two failing dependencies.

        Construct and call a three-node verification with one node
        dependent on the other two, where both dependencies will fail.
        Assert the following:
          * The verification exception is `AutoservVerifyDependencyError`,
            and the exception argument has the descriptions of both the
            failed nodes.
          * The `verify()` method for each failing node is called once,
            and for the parent node not at all.
          * The expected 'FAIL' records are logged via `Host.record()`
            for the failing nodes.
          * If `_verify_host()` is called more than once, there are no
            visible side-effects after the first call.
          * Calling `_reverify()` clears all cached results.
        """
        for silent in self._generate_silent():
            left = self._make_verifier(1, 'left', [])
            right = self._make_verifier(1, 'right', [])
            top = self._make_verifier(0, 'top', [left, right])
            failures = self._make_expected_failures(left, right)
            for count in self._generate_verify_count(top):
                expected_exception = hosts.AutoservVerifyDependencyError
                with self.assertRaises(expected_exception) as e:
                    top._verify_host(self._fake_host, silent)
                self.assertEqual(e.exception.failures, failures)
                self.assertEqual(top.verify_count, 0)
                self.assertEqual(left.verify_count, count)
                self.assertEqual(right.verify_count, count)
                self._check_log_records(silent,
                                        ('left', 'FAIL'),
                                        ('right', 'FAIL'))


    def test_two_dependencies_mixed(self):
        """
        Test proper handling with mixed dependencies.

        Construct and call a three-node verification with one node
        dependent on the other two, where one dependency will pass,
        and one will fail.  Assert the following:
          * The verification exception is `AutoservVerifyDependencyError`,
            and the exception argument has the descriptions of the
            single failed node.
          * The `verify()` method for each dependency is called once,
            and for the parent node not at all.
          * The expected 'GOOD' and 'FAIL' records are logged via
            `Host.record()` for the dependencies.
          * If `_verify_host()` is called more than once, there are no
            visible side-effects after the first call.
          * Calling `_reverify()` clears all cached results.
        """
        for silent in self._generate_silent():
            left = self._make_verifier(1, 'left', [])
            right = self._make_verifier(0, 'right', [])
            top = self._make_verifier(0, 'top', [left, right])
            failures = self._make_expected_failures(left)
            for count in self._generate_verify_count(top):
                expected_exception = hosts.AutoservVerifyDependencyError
                with self.assertRaises(expected_exception) as e:
                    top._verify_host(self._fake_host, silent)
                self.assertEqual(e.exception.failures, failures)
                self.assertEqual(top.verify_count, 0)
                self.assertEqual(left.verify_count, count)
                self.assertEqual(right.verify_count, count)
                self._check_log_records(silent,
                                        ('left', 'FAIL'),
                                        ('right', 'GOOD'))


    def test_diamond_pass(self):
        """
        Test a "diamond" structure DAG with all nodes passing.

        Construct and call a "diamond" structure DAG where all nodes
        will pass:

                TOP
               /   \
            LEFT   RIGHT
               \   /
               BOTTOM

       Assert the following:
          * The `verify()` method for all nodes is called once.
          * The expected 'GOOD' records are logged via `Host.record()`
            for all nodes.
          * If `_verify_host()` is called more than once, there are no
            visible side-effects after the first call.
          * Calling `_reverify()` clears all cached results.
        """
        for silent in self._generate_silent():
            bottom = self._make_verifier(0, 'bottom', [])
            left = self._make_verifier(0, 'left', [bottom])
            right = self._make_verifier(0, 'right', [bottom])
            top = self._make_verifier(0, 'top', [left, right])
            for count in self._generate_verify_count(top):
                top._verify_host(self._fake_host, silent)
                self.assertEqual(top.verify_count, count)
                self.assertEqual(left.verify_count, count)
                self.assertEqual(right.verify_count, count)
                self.assertEqual(bottom.verify_count, count)
                self._check_log_records(silent,
                                        ('bottom', 'GOOD'),
                                        ('left', 'GOOD'),
                                        ('right', 'GOOD'),
                                        ('top', 'GOOD'))


    def test_diamond_fail(self):
        """
        Test a "diamond" structure DAG with the bottom node failing.

        Construct and call a "diamond" structure DAG where the bottom
        node will fail:

                TOP
               /   \
            LEFT   RIGHT
               \   /
               BOTTOM

        Assert the following:
          * The verification exception is `AutoservVerifyDependencyError`,
            and the exception argument has the description of the
            "bottom" node.
          * The `verify()` method for the "bottom" node is called once,
            and for the other nodes not at all.
          * The expected 'FAIL' record is logged via `Host.record()`
            for the "bottom" node.
          * If `_verify_host()` is called more than once, there are no
            visible side-effects after the first call.
          * Calling `_reverify()` clears all cached results.
        """
        for silent in self._generate_silent():
            bottom = self._make_verifier(1, 'bottom', [])
            left = self._make_verifier(0, 'left', [bottom])
            right = self._make_verifier(0, 'right', [bottom])
            top = self._make_verifier(0, 'top', [left, right])
            failures = self._make_expected_failures(bottom)
            for count in self._generate_verify_count(top):
                expected_exception = hosts.AutoservVerifyDependencyError
                with self.assertRaises(expected_exception) as e:
                    top._verify_host(self._fake_host, silent)
                self.assertEqual(e.exception.failures, failures)
                self.assertEqual(top.verify_count, 0)
                self.assertEqual(left.verify_count, 0)
                self.assertEqual(right.verify_count, 0)
                self.assertEqual(bottom.verify_count, count)
                self._check_log_records(silent, ('bottom', 'FAIL'))


class RepairActionTests(_DependencyNodeTestCase):
    """
    Unit tests for `RepairAction`.

    The tests in this class test the fundamental behaviors of the
    `RepairAction` class:
      * Repair doesn't run unless all dependencies pass.
      * Repair doesn't run unless at least one trigger fails.
      * Repair reports the expected value of `status` for metrics.
      * The `_repair_host()` method makes the expected calls to
        `Host.record()` for every call to the `repair()` method.

    The test cases don't use `RepairStrategy` to build repair
    graphs, but instead rely on custom-built structures.
    """

    def test_repair_not_triggered(self):
        """
        Test a repair that doesn't trigger.

        Construct and call a repair action with a verification trigger
        that passes.  Assert the following:
          * The `verify()` method for the trigger is called.
          * The `repair()` method is not called.
          * The repair action's `status` field is 'untriggered'.
          * The verifier logs the expected 'GOOD' message with
            `Host.record()`.
          * The repair action logs no messages with `Host.record()`.
        """
        for silent in self._generate_silent():
            verifier = self._make_verifier(0, 'check', [])
            repair_action = self._make_repair_action(True, 'unneeded',
                                                     [], [verifier])
            repair_action._repair_host(self._fake_host, silent)
            self.assertEqual(verifier.verify_count, 1)
            self.assertEqual(repair_action.repair_count, 0)
            self.assertEqual(repair_action.status, 'skipped')
            self._check_log_records(silent, ('check', 'GOOD'))


    def test_repair_fails(self):
        """
        Test a repair that triggers and fails.

        Construct and call a repair action with a verification trigger
        that fails.  The repair fails by raising `_StubRepairFailure`.
        Assert the following:
          * The repair action fails with the `_StubRepairFailure` raised
            by `repair()`.
          * The `verify()` method for the trigger is called once.
          * The `repair()` method is called once.
          * The repair action's `status` field is 'failed-action'.
          * The expected 'START', 'FAIL', and 'END FAIL' messages are
            logged with `Host.record()` for the failed verifier and the
            failed repair.
        """
        for silent in self._generate_silent():
            verifier = self._make_verifier(1, 'fail', [])
            repair_action = self._make_repair_action(False, 'nofix',
                                                     [], [verifier])
            with self.assertRaises(_StubRepairFailure) as e:
                repair_action._repair_host(self._fake_host, silent)
            self.assertEqual(repair_action.message, str(e.exception))
            self.assertEqual(verifier.verify_count, 1)
            self.assertEqual(repair_action.repair_count, 1)
            self.assertEqual(repair_action.status, 'repair_failure')
            self._check_log_records(silent,
                                    ('fail', 'FAIL'),
                                    ('nofix', 'START'),
                                    ('nofix', 'FAIL'),
                                    ('nofix', 'END FAIL'))


    def test_repair_success(self):
        """
        Test a repair that fixes its trigger.

        Construct and call a repair action that raises no exceptions,
        using a repair trigger that fails first, then passes after
        repair.  Assert the following:
          * The `repair()` method is called once.
          * The trigger's `verify()` method is called twice.
          * The repair action's `status` field is 'repaired'.
          * The expected 'START', 'FAIL', 'GOOD', and 'END GOOD'
            messages are logged with `Host.record()` for the verifier
            and the repair.
        """
        for silent in self._generate_silent():
            verifier = self._make_verifier(1, 'fail', [])
            repair_action = self._make_repair_action(True, 'fix',
                                                     [], [verifier])
            repair_action._repair_host(self._fake_host, silent)
            self.assertEqual(repair_action.repair_count, 1)
            self.assertEqual(verifier.verify_count, 2)
            self.assertEqual(repair_action.status, 'repaired')
            self._check_log_records(silent,
                                    ('fail', 'FAIL'),
                                    ('fix', 'START'),
                                    ('fail', 'GOOD'),
                                    ('fix', 'END GOOD'))


    def test_repair_noop(self):
        """
        Test a repair that doesn't fix a failing trigger.

        Construct and call a repair action with a trigger that fails.
        The repair action raises no exceptions, and after repair, the
        trigger still fails.  Assert the following:
          * The `_repair_host()` call fails with `AutoservRepairError`.
          * The `repair()` method is called once.
          * The trigger's `verify()` method is called twice.
          * The repair action's `status` field is 'failed-trigger'.
          * The expected 'START', 'FAIL', and 'END FAIL' messages are
            logged with `Host.record()` for the verifier and the repair.
        """
        for silent in self._generate_silent():
            verifier = self._make_verifier(2, 'fail', [])
            repair_action = self._make_repair_action(True, 'nofix',
                                                     [], [verifier])
            with self.assertRaises(hosts.AutoservRepairError) as e:
                repair_action._repair_host(self._fake_host, silent)
            self.assertEqual(repair_action.repair_count, 1)
            self.assertEqual(verifier.verify_count, 2)
            self.assertEqual(repair_action.status, 'verify_failure')
            self._check_log_records(silent,
                                    ('fail', 'FAIL'),
                                    ('nofix', 'START'),
                                    ('fail', 'FAIL'),
                                    ('nofix', 'END FAIL'))


    def test_dependency_pass(self):
        """
        Test proper handling of repair dependencies that pass.

        Construct and call a repair action with a dependency and a
        trigger.  The dependency will pass and the trigger will fail and
        be repaired.  Assert the following:
          * Repair passes.
          * The `verify()` method for the dependency is called once.
          * The `verify()` method for the trigger is called twice.
          * The `repair()` method is called once.
          * The repair action's `status` field is 'repaired'.
          * The expected records are logged via `Host.record()`
            for the successful dependency, the failed trigger, and
            the successful repair.
        """
        for silent in self._generate_silent():
            dep = self._make_verifier(0, 'dep', [])
            trigger = self._make_verifier(1, 'trig', [])
            repair = self._make_repair_action(True, 'fixit',
                                              [dep], [trigger])
            repair._repair_host(self._fake_host, silent)
            self.assertEqual(dep.verify_count, 1)
            self.assertEqual(trigger.verify_count, 2)
            self.assertEqual(repair.repair_count, 1)
            self.assertEqual(repair.status, 'repaired')
            self._check_log_records(silent,
                                    ('dep', 'GOOD'),
                                    ('trig', 'FAIL'),
                                    ('fixit', 'START'),
                                    ('trig', 'GOOD'),
                                    ('fixit', 'END GOOD'))


    def test_dependency_fail(self):
        """
        Test proper handling of repair dependencies that fail.

        Construct and call a repair action with a dependency and a
        trigger, both of which fail.  Assert the following:
          * Repair fails with `AutoservVerifyDependencyError`,
            and the exception argument is the description of the failed
            dependency.
          * The `verify()` method for the failing dependency is called
            once.
          * The trigger and the repair action aren't invoked at all.
          * The repair action's `status` field is 'blocked'.
          * The expected 'FAIL' record is logged via `Host.record()`
            for the single failed dependency.
        """
        for silent in self._generate_silent():
            dep = self._make_verifier(1, 'dep', [])
            trigger = self._make_verifier(1, 'trig', [])
            repair = self._make_repair_action(True, 'fixit',
                                              [dep], [trigger])
            expected_exception = hosts.AutoservVerifyDependencyError
            with self.assertRaises(expected_exception) as e:
                repair._repair_host(self._fake_host, silent)
            self.assertEqual(e.exception.failures,
                             self._make_expected_failures(dep))
            self.assertEqual(dep.verify_count, 1)
            self.assertEqual(trigger.verify_count, 0)
            self.assertEqual(repair.repair_count, 0)
            self.assertEqual(repair.status, 'blocked')
            self._check_log_records(silent, ('dep', 'FAIL'))


class _RepairStrategyTestCase(_DependencyNodeTestCase):
    """Shared base class for testing `RepairStrategy` methods."""

    def _make_verify_data(self, *input_data):
        """
        Create `verify_data` for the `RepairStrategy` constructor.

        `RepairStrategy` expects `verify_data` as a list of tuples
        of the form `(constructor, tag, deps)`.  Each item in
        `input_data` is a tuple of the form `(tag, count, deps)` that
        creates one entry in the returned list of `verify_data` tuples
        as follows:
          * `count` is used to create a constructor function that calls
            `self._make_verifier()` with that value plus plus the
            arguments provided by the `RepairStrategy` constructor.
          * `tag` and `deps` will be passed as-is to the `RepairStrategy`
            constructor.

        @param input_data   A list of tuples, each representing one
                            tuple in the `verify_data` list.
        @return   A list suitable to be the `verify_data` parameter for
                  the `RepairStrategy` constructor.
        """
        strategy_data = []
        for tag, count, deps in input_data:
            construct = functools.partial(self._make_verifier, count)
            strategy_data.append((construct, tag, deps))
        return strategy_data


    def _make_repair_data(self, *input_data):
        """
        Create `repair_data` for the `RepairStrategy` constructor.

        `RepairStrategy` expects `repair_data` as a list of tuples
        of the form `(constructor, tag, deps, triggers)`.  Each item in
        `input_data` is a tuple of the form `(tag, success, deps, triggers)`
        that creates one entry in the returned list of `repair_data`
        tuples as follows:
          * `success` is used to create a constructor function that calls
            `self._make_verifier()` with that value plus plus the
            arguments provided by the `RepairStrategy` constructor.
          * `tag`, `deps`, and `triggers` will be passed as-is to the
            `RepairStrategy` constructor.

        @param input_data   A list of tuples, each representing one
                            tuple in the `repair_data` list.
        @return   A list suitable to be the `repair_data` parameter for
                  the `RepairStrategy` constructor.
        """
        strategy_data = []
        for tag, success, deps, triggers in input_data:
            construct = functools.partial(self._make_repair_action, success)
            strategy_data.append((construct, tag, deps, triggers))
        return strategy_data


    def _make_strategy(self, verify_input, repair_input):
        """
        Create a `RepairStrategy` from the given arguments.

        @param verify_input   As for `input_data` in
                              `_make_verify_data()`.
        @param repair_input   As for `input_data` in
                              `_make_repair_data()`.
        """
        verify_data = self._make_verify_data(*verify_input)
        repair_data = self._make_repair_data(*repair_input)
        return hosts.RepairStrategy(verify_data, repair_data, 'unittest')

    def _check_silent_records(self, silent):
        """
        Check that logging honored the `silent` parameter.

        Asserts that logging with `Host.record()` occurred (or did not
        occur) in accordance with the value of `silent`.

        This method only asserts the presence or absence of log records.
        Coverage for the contents of the log records is handled in other
        test cases.

        @param silent   When true, there should be no log records;
                        otherwise there should be records present.
        """
        log_records = self._fake_host.get_log_records()
        if silent:
            self.assertEqual(log_records, [])
        else:
            self.assertNotEqual(log_records, [])


class RepairStrategyVerifyTests(_RepairStrategyTestCase):
    """
    Unit tests for `RepairStrategy.verify()`.

    These unit tests focus on verifying that the `RepairStrategy`
    constructor creates the expected DAG structure from given
    `verify_data`.  Functional testing here is mainly confined to
    asserting that `RepairStrategy.verify()` properly distinguishes
    success from failure.  Testing the behavior of specific DAG
    structures is left to tests in `VerifyTests`.
    """

    def test_single_node(self):
        """
        Test construction of a single-node verification DAG.

        Assert that the structure looks like this:

            Root Node -> Main Node
        """
        verify_data = self._make_verify_data(('main', 0, ()))
        strategy = hosts.RepairStrategy(verify_data, [], 'unittest')
        verifier = self.nodes['main']
        self.assertEqual(
                strategy._verify_root._dependency_list,
                [verifier])
        self.assertEqual(verifier._dependency_list, [])


    def test_single_dependency(self):
        """
        Test construction of a two-node dependency chain.

        Assert that the structure looks like this:

            Root Node -> Parent Node -> Child Node
        """
        verify_data = self._make_verify_data(
                ('child', 0, ()),
                ('parent', 0, ('child',)))
        strategy = hosts.RepairStrategy(verify_data, [], 'unittest')
        parent = self.nodes['parent']
        child = self.nodes['child']
        self.assertEqual(
                strategy._verify_root._dependency_list, [parent])
        self.assertEqual(
                parent._dependency_list, [child])
        self.assertEqual(
                child._dependency_list, [])


    def test_two_nodes_and_dependency(self):
        """
        Test construction of two nodes with a shared dependency.

        Assert that the structure looks like this:

            Root Node -> Left Node ---\
                      \                -> Bottom Node
                        -> Right Node /
        """
        verify_data = self._make_verify_data(
                ('bottom', 0, ()),
                ('left', 0, ('bottom',)),
                ('right', 0, ('bottom',)))
        strategy = hosts.RepairStrategy(verify_data, [], 'unittest')
        bottom = self.nodes['bottom']
        left = self.nodes['left']
        right = self.nodes['right']
        self.assertEqual(
                strategy._verify_root._dependency_list,
                [left, right])
        self.assertEqual(left._dependency_list, [bottom])
        self.assertEqual(right._dependency_list, [bottom])
        self.assertEqual(bottom._dependency_list, [])


    def test_three_nodes(self):
        """
        Test construction of three nodes with no dependencies.

        Assert that the structure looks like this:

                       -> Node One
                      /
            Root Node -> Node Two
                      \
                       -> Node Three

        N.B.  This test exists to enforce ordering expectations of
        root-level DAG nodes.  Three nodes are used to make it unlikely
        that randomly ordered roots will match expectations.
        """
        verify_data = self._make_verify_data(
                ('one', 0, ()),
                ('two', 0, ()),
                ('three', 0, ()))
        strategy = hosts.RepairStrategy(verify_data, [], 'unittest')
        one = self.nodes['one']
        two = self.nodes['two']
        three = self.nodes['three']
        self.assertEqual(
                strategy._verify_root._dependency_list,
                [one, two, three])
        self.assertEqual(one._dependency_list, [])
        self.assertEqual(two._dependency_list, [])
        self.assertEqual(three._dependency_list, [])


    def test_verify(self):
        """
        Test behavior of the `verify()` method.

        Build a `RepairStrategy` with a single verifier.  Assert the
        following:
          * If the verifier passes, `verify()` passes.
          * If the verifier fails, `verify()` fails.
          * The verifier is reinvoked with every call to `verify()`;
            cached results are not re-used.
        """
        verify_data = self._make_verify_data(('tester', 0, ()))
        strategy = hosts.RepairStrategy(verify_data, [], 'unittest')
        verifier = self.nodes['tester']
        count = 0
        for silent in self._generate_silent():
            for i in range(0, 2):
                for j in range(0, 2):
                    strategy.verify(self._fake_host, silent)
                    self._check_silent_records(silent)
                    count += 1
                    self.assertEqual(verifier.verify_count, count)
                verifier.unrepair()
                for j in range(0, 2):
                    with self.assertRaises(Exception) as e:
                        strategy.verify(self._fake_host, silent)
                    self._check_silent_records(silent)
                    count += 1
                    self.assertEqual(verifier.verify_count, count)
                verifier.try_repair()


class RepairStrategyRepairTests(_RepairStrategyTestCase):
    """
    Unit tests for `RepairStrategy.repair()`.

    These unit tests focus on verifying that the `RepairStrategy`
    constructor creates the expected repair list from given
    `repair_data`.  Functional testing here is confined to asserting
    that `RepairStrategy.repair()` properly distinguishes success from
    failure.  Testing the behavior of specific repair structures is left
    to tests in `RepairActionTests`.
    """

    def _check_common_trigger(self, strategy, repair_tags, triggers):
        self.assertEqual(strategy._repair_actions,
                         [self.nodes[tag] for tag in repair_tags])
        for tag in repair_tags:
            self.assertEqual(self.nodes[tag]._trigger_list,
                             triggers)
            self.assertEqual(self.nodes[tag]._dependency_list, [])


    def test_single_repair_with_trigger(self):
        """
        Test constructing a strategy with a single repair trigger.

        Build a `RepairStrategy` with a single repair action and a
        single trigger.  Assert that the trigger graph looks like this:

            Repair -> Trigger

        Assert that there are no repair dependencies.
        """
        verify_input = (('base', 0, ()),)
        repair_input = (('fixit', True, (), ('base',)),)
        strategy = self._make_strategy(verify_input, repair_input)
        self._check_common_trigger(strategy,
                                   ['fixit'],
                                   [self.nodes['base']])


    def test_repair_with_root_trigger(self):
        """
        Test construction of a repair triggering on the root verifier.

        Build a `RepairStrategy` with a single repair action that
        triggers on the root verifier.  Assert that the trigger graph
        looks like this:

            Repair -> Root Verifier

        Assert that there are no repair dependencies.
        """
        root_tag = hosts.RepairStrategy.ROOT_TAG
        repair_input = (('fixit', True, (), (root_tag,)),)
        strategy = self._make_strategy([], repair_input)
        self._check_common_trigger(strategy,
                                   ['fixit'],
                                   [strategy._verify_root])


    def test_three_repairs(self):
        """
        Test constructing a strategy with three repair actions.

        Build a `RepairStrategy` with a three repair actions sharing a
        single trigger.  Assert that the trigger graph looks like this:

            Repair A -> Trigger
            Repair B -> Trigger
            Repair C -> Trigger

        Assert that there are no repair dependencies.

        N.B.  This test exists to enforce ordering expectations of
        repair nodes.  Three nodes are used to make it unlikely that
        randomly ordered actions will match expectations.
        """
        verify_input = (('base', 0, ()),)
        repair_tags = ['a', 'b', 'c']
        repair_input = (
            (tag, True, (), ('base',)) for tag in repair_tags)
        strategy = self._make_strategy(verify_input, repair_input)
        self._check_common_trigger(strategy,
                                   repair_tags,
                                   [self.nodes['base']])


    def test_repair_dependency(self):
        """
        Test construction of a repair with a dependency.

        Build a `RepairStrategy` with a single repair action that
        depends on a single verifier.  Assert that the dependency graph
        looks like this:

            Repair -> Verifier

        Assert that there are no repair triggers.
        """
        verify_input = (('base', 0, ()),)
        repair_input = (('fixit', True, ('base',), ()),)
        strategy = self._make_strategy(verify_input, repair_input)
        self.assertEqual(strategy._repair_actions,
                         [self.nodes['fixit']])
        self.assertEqual(self.nodes['fixit']._trigger_list, [])
        self.assertEqual(self.nodes['fixit']._dependency_list,
                         [self.nodes['base']])


    def _check_repair_failure(self, strategy, silent):
        """
        Check the effects of a call to `repair()` that fails.

        For the given strategy object, call the `repair()` method; the
        call is expected to fail and all repair actions are expected to
        trigger.

        Assert the following:
          * The call raises an exception.
          * For each repair action in the strategy, its `repair()`
            method is called exactly once.

        @param strategy   The strategy to be tested.
        """
        action_counts = [(a, a.repair_count)
                                 for a in strategy._repair_actions]
        with self.assertRaises(Exception) as e:
            strategy.repair(self._fake_host, silent)
        self._check_silent_records(silent)
        for action, count in action_counts:
            self.assertEqual(action.repair_count, count + 1)


    def _check_repair_success(self, strategy, silent):
        """
        Check the effects of a call to `repair()` that succeeds.

        For the given strategy object, call the `repair()` method; the
        call is expected to succeed without raising an exception and all
        repair actions are expected to trigger.

        Assert that for each repair action in the strategy, its
        `repair()` method is called exactly once.

        @param strategy   The strategy to be tested.
        """
        action_counts = [(a, a.repair_count)
                                 for a in strategy._repair_actions]
        strategy.repair(self._fake_host, silent)
        self._check_silent_records(silent)
        for action, count in action_counts:
            self.assertEqual(action.repair_count, count + 1)


    def test_repair(self):
        """
        Test behavior of the `repair()` method.

        Build a `RepairStrategy` with two repair actions each depending
        on its own verifier.  Set up calls to `repair()` for each of
        the following conditions:
          * Both repair actions trigger and fail.
          * Both repair actions trigger and succeed.
          * Both repair actions trigger; the first one fails, but the
            second one succeeds.
          * Both repair actions trigger; the first one succeeds, but the
            second one fails.

        Assert the following:
          * When both repair actions succeed, `repair()` succeeds.
          * When either repair action fails, `repair()` fails.
          * After each call to the strategy's `repair()` method, each
            repair action triggered exactly once.
        """
        verify_input = (('a', 2, ()), ('b', 2, ()))
        repair_input = (('afix', True, (), ('a',)),
                        ('bfix', True, (), ('b',)))
        strategy = self._make_strategy(verify_input, repair_input)

        for silent in self._generate_silent():
            # call where both 'afix' and 'bfix' fail
            self._check_repair_failure(strategy, silent)
            # repair counts are now 1 for both verifiers

            # call where both 'afix' and 'bfix' succeed
            self._check_repair_success(strategy, silent)
            # repair counts are now 0 for both verifiers

            # call where 'afix' fails and 'bfix' succeeds
            for tag in ['a', 'a', 'b']:
                self.nodes[tag].unrepair()
            self._check_repair_failure(strategy, silent)
            # 'a' repair count is 1; 'b' count is 0

            # call where 'afix' succeeds and 'bfix' fails
            for tag in ['b', 'b']:
                self.nodes[tag].unrepair()
            self._check_repair_failure(strategy, silent)
            # 'a' repair count is 0; 'b' count is 1

            for tag in ['a', 'a', 'b']:
                self.nodes[tag].unrepair()
            # repair counts are now 2 for both verifiers


class VerifierResultTestCases(_DependencyNodeTestCase):
    """
    Test to check that we can find correct verifier and
    get the result of it
    """
    def test_find_verifier_by_tag(self):
        """Test to find correct verifier by tag"""
        verify_data = [
            (_GoodVerifier, 'v1', []),
            (_GoodVerifier, 'v2', ['v1']),
            (_BadVerifier, 'v3', []),
            (_BadVerifier, 'v4', []),
            (_SkipVerifier, 'v5', ['v4']),
            (_SkipVerifier, 'v6', ['v2', 'v3'])
        ]
        strategy = hosts.RepairStrategy(verify_data, (), 'unittest')

        for v in range(1,6):
            tag = 'v%s' % v
            verifier = strategy._verify_root._get_node_by_tag(tag)
            self.assertIsNotNone(verifier)
            self.assertEqual(tag, verifier.tag)

        verifier = strategy._verify_root._get_node_by_tag('v0')
        self.assertEqual(repair.VERIFY_NOT_RUN, verifier)

    def test_run_verifier_and_get_results(self):
        """Check the result of verifiers"""
        verify_data = [
            (_GoodVerifier, 'v1', []),
            (_BadVerifier, 'v2', []),
            (_SkipVerifier, 'v3', []),
        ]
        strategy = hosts.RepairStrategy(verify_data, (), 'unittest')
        try:
            strategy.verify(self._fake_host, silent=True)
        except Exception as e:
            pass
        self.assertEqual(repair.VERIFY_NOT_RUN,
                         strategy.verifier_is_good('v0'))
        self.assertEqual(repair.VERIFY_SUCCESS,
                         strategy.verifier_is_good('v1'))
        self.assertEqual(repair.VERIFY_FAILED, strategy.verifier_is_good('v2'))
        self.assertEqual(repair.VERIFY_NOT_RUN,
                         strategy.verifier_is_good('v3'))
        self.assertEqual(repair.VERIFY_NOT_RUN,
                         strategy.verifier_is_good('v4'))

    def test_run_verifier_with_dependencies(self):
        """Check the result if dependency fail or not applicable."""
        verify_data = [
            (_GoodVerifier, 'v1', []),
            (_BadVerifier, 'v2', []),
            (_SkipVerifier, 'v3', []),
            (_GoodVerifier, 'v4', ['v2']),
            (_GoodVerifier, 'v5', ['v3']),
        ]
        strategy = hosts.RepairStrategy(verify_data, (), 'unittest')
        try:
            strategy.verify(self._fake_host, silent=True)
        except Exception as e:
            pass
        self.assertEqual(repair.VERIFY_NOT_RUN,
                         strategy.verifier_is_good('v0'))
        self.assertEqual(repair.VERIFY_SUCCESS,
                         strategy.verifier_is_good('v1'))
        self.assertEqual(repair.VERIFY_FAILED, strategy.verifier_is_good('v2'))
        self.assertEqual(repair.VERIFY_NOT_RUN,
                         strategy.verifier_is_good('v3'))
        # if dependencies fail then the verifier mark as not run
        self.assertEqual(repair.VERIFY_NOT_RUN,
                         strategy.verifier_is_good('v4'))
        # if dependencies not applicable then run only verifier
        self.assertEqual(repair.VERIFY_SUCCESS,
                         strategy.verifier_is_good('v5'))
        self.assertEqual(repair.VERIFY_NOT_RUN,
                         strategy.verifier_is_good('v6'))


if __name__ == '__main__':
    unittest.main()
