<commit_before># Copyright Hybrid Logic Ltd.  See LICENSE file for details.

"""
Tests for :module:`flocker.node.script`.
"""

from StringIO import StringIO

from pyrsistent import pmap

from twisted.trial.unittest import SynchronousTestCase
from twisted.python.usage import UsageError
from twisted.python.filepath import FilePath
from twisted.application.service import Service

from yaml import safe_dump, safe_load
from ...testtools import StandardOptionsTestsMixin, MemoryCoreReactor
from ...volume.testtools import make_volume_options_tests
from ...route import make_memory_network

from ..script import (
    ZFSAgentOptions, ZFSAgentScript,
    ChangeStateOptions, ChangeStateScript,
    ReportStateOptions, ReportStateScript)
from .. import script as script_module
from .._docker import FakeDockerClient, Unit
from ...control._model import (
    Application, Deployment, DockerImage, Node, AttachedVolume, Dataset,
    Manifestation)
from .._loop import AgentLoopService
from .._deploy import P2PNodeDeployer

from ...volume.testtools import create_volume_service


class ChangeStateScriptTests(SynchronousTestCase):
    """
    Tests for ``ChangeStateScript``.
    """
    def test_deployer_docker_client(self):
        """
        ``ChangeState._docker_client`` is configured with the default docker
        client.
        """
        self.assertIs(None, ChangeStateScript()._docker_client)


class ChangeStateScriptMainTests(SynchronousTestCase):
    """
    Tests for ``ChangeStateScript.main``.
    """
    def test_main_calls_deployer_change_node_state(self):
        """
        ``ChangeStateScript.main`` calls ``change_node_state`` with
        the ``Deployment`` and `hostname` supplied on the command line.
        """
        script = ChangeStateScript()

        change_node_state_calls = []

        def spy_change_node_state(
                deployer, desired_state, current_cluster_state):
            """
            A stand in for ``Deployer.change_node_state`` which records calls
            made to it.
            """
            change_node_state_calls.append((desired_state,
                                            current_cluster_state,
                                            deployer.hostname))

        self.patch(
            script_module, 'change_node_state', spy_change_node_state)

        expected_deployment = object()
        expected_current = object()
        expected_hostname = b'node1.example.com'
        options = dict(deployment=expected_deployment,
                       current=expected_current,
                       hostname=expected_hostname)
        script.main(
            reactor=object(), options=options, volume_service=Service())

        self.assertEqual(
            [(expected_deployment, expected_current, expected_hostname)],
            change_node_state_calls
        )


class StandardChangeStateOptionsTests(
        make_volume_options_tests(
            ChangeStateOptions, extra_arguments=[
                safe_dump(dict(version=1, nodes={})),
                safe_dump(dict(version=1, applications={})),
                safe_dump({}),
                b"node001",
            ])):
    """
    Tests for the volume configuration arguments of ``ChangeStateOptions``.
    """


class ChangeStateOptionsTests(StandardOptionsTestsMixin, SynchronousTestCase):
    """
    Tests for :class:`ChangeStateOptions`.
    """
    options = ChangeStateOptions

    def test_custom_configs(self):
        """
        The supplied application and deployment configuration strings are
        parsed as a :class:`Deployment` on the options instance.
        """
        application = Application(
            name=u'mysql-hybridcluster',
            image=DockerImage(repository=u'hybridlogic/mysql5.9',
                              tag=u'latest'),
            ports=frozenset(),
            links=frozenset(),
            )

        node = Node(hostname='node1.example.com',
                    applications=frozenset([application]))
        options = self.options()
        deployment_config = {"nodes": {node.hostname: [application.name]},
                             "version": 1}

        application_config = dict(
            version=1,
            applications={
                application.name: {'image': 'hybridlogic/mysql5.9:latest'}
            }
        )

        current_config = {'node2.example.com': {
            'applications': {
                'mysql-something': {
                    'image': 'unknown',
                    'volume': {'mountpoint': b'/var/lib/data'},
                }
            },
            'version': 1
        }}

        options.parseOptions(
            [safe_dump(deployment_config),
             safe_dump(application_config),
             safe_dump(current_config),
             b'node1.example.com'])

        self.assertEqual(
            Deployment(nodes=frozenset([node])), options['deployment'])

    def test_current_configuration(self):
        """
        The supplied current cluster configuration strings is parsed as a
        :class:`Deployment` on the options instance.
        """
        options = self.options()
        deployment_config = {"nodes": {},
                             "version": 1}

        application_config = dict(
            version=1,
            applications={},
        )

        current_config = {'node2.example.com': {
            'applications': {
                'mysql-something': {
                    'image': 'unknown',
                    'volume': {'mountpoint': b'/var/lib/data'},
                }
            },
            'version': 1
        }}

        expected_current_config = Deployment(nodes=frozenset([
            Node(hostname='node2.example.com', applications=frozenset([
                Application(
                    name='mysql-something',
                    image=DockerImage.from_string('unknown'),
                    ports=frozenset(),
                    links=frozenset(),
                    volume=AttachedVolume(
                        manifestation=Manifestation(
                            dataset=Dataset(
                                dataset_id=None,
                                metadata=pmap({'name': 'mysql-something'})),
                            primary=True),
                        mountpoint=FilePath(b'/var/lib/data'),
                    )
                ),
            ]))]))<commit_msg>One more test that needs to use dataset_id_from_name().<commit_after># Copyright Hybrid Logic Ltd.  See LICENSE file for details.

"""
Tests for :module:`flocker.node.script`.
"""

from StringIO import StringIO

from pyrsistent import pmap

from twisted.trial.unittest import SynchronousTestCase
from twisted.python.usage import UsageError
from twisted.python.filepath import FilePath
from twisted.application.service import Service

from yaml import safe_dump, safe_load
from ...testtools import StandardOptionsTestsMixin, MemoryCoreReactor
from ...volume.testtools import make_volume_options_tests
from ...route import make_memory_network

from ..script import (
    ZFSAgentOptions, ZFSAgentScript,
    ChangeStateOptions, ChangeStateScript,
    ReportStateOptions, ReportStateScript)
from .. import script as script_module
from .._docker import FakeDockerClient, Unit
from ...control._model import (
    Application, Deployment, DockerImage, Node, AttachedVolume, Dataset,
    Manifestation)
from ...control._config import dataset_id_from_name
from .._loop import AgentLoopService
from .._deploy import P2PNodeDeployer

from ...volume.testtools import create_volume_service


class ChangeStateScriptTests(SynchronousTestCase):
    """
    Tests for ``ChangeStateScript``.
    """
    def test_deployer_docker_client(self):
        """
        ``ChangeState._docker_client`` is configured with the default docker
        client.
        """
        self.assertIs(None, ChangeStateScript()._docker_client)


class ChangeStateScriptMainTests(SynchronousTestCase):
    """
    Tests for ``ChangeStateScript.main``.
    """
    def test_main_calls_deployer_change_node_state(self):
        """
        ``ChangeStateScript.main`` calls ``change_node_state`` with
        the ``Deployment`` and `hostname` supplied on the command line.
        """
        script = ChangeStateScript()

        change_node_state_calls = []

        def spy_change_node_state(
                deployer, desired_state, current_cluster_state):
            """
            A stand in for ``Deployer.change_node_state`` which records calls
            made to it.
            """
            change_node_state_calls.append((desired_state,
                                            current_cluster_state,
                                            deployer.hostname))

        self.patch(
            script_module, 'change_node_state', spy_change_node_state)

        expected_deployment = object()
        expected_current = object()
        expected_hostname = b'node1.example.com'
        options = dict(deployment=expected_deployment,
                       current=expected_current,
                       hostname=expected_hostname)
        script.main(
            reactor=object(), options=options, volume_service=Service())

        self.assertEqual(
            [(expected_deployment, expected_current, expected_hostname)],
            change_node_state_calls
        )


class StandardChangeStateOptionsTests(
        make_volume_options_tests(
            ChangeStateOptions, extra_arguments=[
                safe_dump(dict(version=1, nodes={})),
                safe_dump(dict(version=1, applications={})),
                safe_dump({}),
                b"node001",
            ])):
    """
    Tests for the volume configuration arguments of ``ChangeStateOptions``.
    """


class ChangeStateOptionsTests(StandardOptionsTestsMixin, SynchronousTestCase):
    """
    Tests for :class:`ChangeStateOptions`.
    """
    options = ChangeStateOptions

    def test_custom_configs(self):
        """
        The supplied application and deployment configuration strings are
        parsed as a :class:`Deployment` on the options instance.
        """
        application = Application(
            name=u'mysql-hybridcluster',
            image=DockerImage(repository=u'hybridlogic/mysql5.9',
                              tag=u'latest'),
            ports=frozenset(),
            links=frozenset(),
            )

        node = Node(hostname='node1.example.com',
                    applications=frozenset([application]))
        options = self.options()
        deployment_config = {"nodes": {node.hostname: [application.name]},
                             "version": 1}

        application_config = dict(
            version=1,
            applications={
                application.name: {'image': 'hybridlogic/mysql5.9:latest'}
            }
        )

        current_config = {'node2.example.com': {
            'applications': {
                'mysql-something': {
                    'image': 'unknown',
                    'volume': {'mountpoint': b'/var/lib/data'},
                }
            },
            'version': 1
        }}

        options.parseOptions(
            [safe_dump(deployment_config),
             safe_dump(application_config),
             safe_dump(current_config),
             b'node1.example.com'])

        self.assertEqual(
            Deployment(nodes=frozenset([node])), options['deployment'])

    def test_current_configuration(self):
        """
        The supplied current cluster configuration strings is parsed as a
        :class:`Deployment` on the options instance.
        """
        options = self.options()
        deployment_config = {"nodes": {},
                             "version": 1}

        application_config = dict(
            version=1,
            applications={},
        )

        current_config = {'node2.example.com': {
            'applications': {
                'mysql-something': {
                    'image': 'unknown',
                    'volume': {'mountpoint': b'/var/lib/data'},
                }
            },
            'version': 1
        }}

        expected_current_config = Deployment(nodes=frozenset([
            Node(hostname='node2.example.com', applications=frozenset([
                Application(
                    name='mysql-something',
                    image=DockerImage.from_string('unknown'),
                    ports=frozenset(),
                    links=frozenset(),
                    volume=AttachedVolume(
                        manifestation=Manifestation(
                            dataset=Dataset(
                                dataset_id=dataset_id_from_name(
                                    "mysql-something"),
                                metadata=pmap({'name': 'mysql-something'})),
                            primary=True),
                        mountpoint=FilePath(b'/var/lib/data'),
                    )
                ),
            ]))]))
{'fraction_non_alphanumeric': 0.09781605659796985, 'fraction_numerical': 0.003383574284835435, 'mean_word_length': 1.9403120054261813, 'pattern_counts': {'":': 8, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 9, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4418123', 'n_tokens_mistral': 3302, 'n_tokens_neox': 3174, 'n_words': 656}