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

"""
Tests for ``flocker.control._clusterstate``.
"""

from uuid import uuid4

from twisted.trial.unittest import SynchronousTestCase
from twisted.python.filepath import FilePath
from twisted.internet.task import Clock

from .._clusterstate import ClusterStateService
from .._model import (
    Application, DockerImage, NodeState, DeploymentState, Manifestation,
    Dataset,
)

APP1 = Application(
    name=u"webserver", image=DockerImage.from_string(u"apache"))
APP2 = Application(
    name=u"database", image=DockerImage.from_string(u"postgresql"))
MANIFESTATION = Manifestation(dataset=Dataset(dataset_id=unicode(uuid4())),
                              primary=True)


class ClusterStateServiceTests(SynchronousTestCase):
    """
    Tests for ``ClusterStateService``.
    """
    WITH_APPS = NodeState(hostname=u"host1", applications=[APP1, APP2])
    WITH_MANIFESTATION = NodeState(
        hostname=u"host2",
        manifestations={MANIFESTATION.dataset_id: MANIFESTATION}
    )

    def setUp(self):
        self.clock = Clock()

    def service(self):
        service = ClusterStateService(self.clock)
        service.startService()
        self.addCleanup(service.stopService)
        return service

    def test_applications(self):
        """
        ``ClusterStateService.as_deployment`` copies applications from the
        given node state.
        """
        service = self.service()
        service.apply_changes([self.WITH_APPS])
        self.assertEqual(
            service.as_deployment(),
            DeploymentState(nodes=[self.WITH_APPS])
        )

    def test_other_manifestations(self):
        """
        ``ClusterStateService.as_deployment`` copies over other manifestations
        to the ``Node`` instances it creates.
        """
        service = self.service()
        service.apply_changes([self.WITH_MANIFESTATION])
        self.assertEqual(
            service.as_deployment(),
            DeploymentState(nodes={self.WITH_MANIFESTATION})
        )

    def test_partial_update(self):
        """
        An update that is ignorant about certain parts of a node's state only
        updates the information it knows about.
        """
        service = self.service()
        service.apply_changes([
            NodeState(hostname=u"host1", applications=[APP1]),
            NodeState(hostname=u"host1", applications=None,
                      manifestations={
                          MANIFESTATION.dataset_id:
                          MANIFESTATION})
        ])
        self.assertEqual(service.as_deployment(),
                         DeploymentState(nodes=[NodeState(
                             hostname=u"host1",
                             manifestations={
                                 MANIFESTATION.dataset_id: MANIFESTATION},
                             applications=[APP1])]))

    def test_update(self):
        """
        An update for previously given hostname overrides the previous state
        of that hostname.
        """
        service = self.service()
        service.apply_changes([
            NodeState(hostname=u"host1", applications=[APP1]),
            NodeState(hostname=u"host1", applications=[APP2]),
        ])
        self.assertEqual(service.as_deployment(),
                         DeploymentState(nodes=[NodeState(
                             hostname=u"host1",
                             applications=frozenset([APP2]))]))

    def test_multiple_hosts(self):
        """
        The information from multiple hosts is combined by
        ``ClusterStateService.as_deployment``.
        """
        service = self.service()
        service.apply_changes([
            NodeState(hostname=u"host1", applications=[APP1]),
            NodeState(hostname=u"host2", applications=[APP2]),
        ])
        self.assertEqual(service.as_deployment(),
                         DeploymentState(nodes=[
                             NodeState(
                                 hostname=u"host1",
                                 applications=frozenset([APP1])),
                             NodeState(
                                 hostname=u"host2",
                                 applications=frozenset([APP2])),
                         ]))

    def test_manifestation_path(self):
        """
        ``manifestation_path`` returns the path on the filesystem where the
        given dataset exists.
        """
        identifier = uuid4()
        service = self.service()
        service.apply_changes([
            NodeState(hostname=u"host1", uuid=identifier,
                      manifestations={
                          MANIFESTATION.dataset_id:
                          MANIFESTATION},
                      paths={MANIFESTATION.dataset_id:
                             FilePath(b"/xxx/yyy")})
        ])
        self.assertEqual(
            service.manifestation_path(identifier, MANIFESTATION.dataset_id),
            FilePath(b"/xxx/yyy"))

    def test_expiration(self):
        """
        Information updates that are more than 10 seconds old are wiped.
        """
        service = self.service()
        app_node = NodeState(hostname=u"10.0.0.1", uuid=uuid4(),
                             manifestations=None, devices=None, paths=None,
                             applications=[APP1])
        service.apply_changes([app_node])
        self.clock.advance(9)
        nine_second_state = service.as_deployment()
        self.clock.advance(1)
        ten_second_state = service.as_deployment()
        self.assertEqual(
            [nine_second_state, ten_second_state],
            [DeploymentState(nodes=[app_node]), DeploymentState()])

    def test_updates_different_key(self):
        """
        A wipe created by a ``IClusterStateChange`` with a given wipe key is
        not overwritten by a later ``IClusterStateChange`` with a
        different key.
        """
        service = self.service()
        app_node = NodeState(hostname=u"10.0.0.1", uuid=uuid4(),
                             manifestations=None, devices=None, paths=None,
                             applications=[APP1], used_ports=None)
        app_node_2 = app_node.set("applications", None).set(
            "manifestations", {MANIFESTATION.dataset_id: MANIFESTATION})
        service.apply_changes([app_node])
        self.clock.advance(1)
        service.apply_changes([app_node_2])
        self.clock.advance(9)
        ten_second_state = service.as_deployment()
        self.clock.advance(1)
        eleven_second_state = service.as_deployment()
        self.assertEqual(
            [ten_second_state, eleven_second_state],
            [DeploymentState(nodes=[app_node_2]), DeploymentState()])<commit_msg>Address review comment: Test for expiration delay.<commit_after># Copyright Hybrid Logic Ltd.  See LICENSE file for details.

"""
Tests for ``flocker.control._clusterstate``.
"""

from uuid import uuid4

from twisted.trial.unittest import SynchronousTestCase
from twisted.python.filepath import FilePath
from twisted.internet.task import Clock

from .._clusterstate import ClusterStateService
from .._model import (
    Application, DockerImage, NodeState, DeploymentState, Manifestation,
    Dataset,
)

APP1 = Application(
    name=u"webserver", image=DockerImage.from_string(u"apache"))
APP2 = Application(
    name=u"database", image=DockerImage.from_string(u"postgresql"))
MANIFESTATION = Manifestation(dataset=Dataset(dataset_id=unicode(uuid4())),
                              primary=True)


class ClusterStateServiceTests(SynchronousTestCase):
    """
    Tests for ``ClusterStateService``.
    """
    WITH_APPS = NodeState(hostname=u"host1", applications=[APP1, APP2])
    WITH_MANIFESTATION = NodeState(
        hostname=u"host2",
        manifestations={MANIFESTATION.dataset_id: MANIFESTATION}
    )

    def setUp(self):
        self.clock = Clock()

    def service(self):
        service = ClusterStateService(self.clock)
        service.startService()
        self.addCleanup(service.stopService)
        return service

    def test_applications(self):
        """
        ``ClusterStateService.as_deployment`` copies applications from the
        given node state.
        """
        service = self.service()
        service.apply_changes([self.WITH_APPS])
        self.assertEqual(
            service.as_deployment(),
            DeploymentState(nodes=[self.WITH_APPS])
        )

    def test_other_manifestations(self):
        """
        ``ClusterStateService.as_deployment`` copies over other manifestations
        to the ``Node`` instances it creates.
        """
        service = self.service()
        service.apply_changes([self.WITH_MANIFESTATION])
        self.assertEqual(
            service.as_deployment(),
            DeploymentState(nodes={self.WITH_MANIFESTATION})
        )

    def test_partial_update(self):
        """
        An update that is ignorant about certain parts of a node's state only
        updates the information it knows about.
        """
        service = self.service()
        service.apply_changes([
            NodeState(hostname=u"host1", applications=[APP1]),
            NodeState(hostname=u"host1", applications=None,
                      manifestations={
                          MANIFESTATION.dataset_id:
                          MANIFESTATION})
        ])
        self.assertEqual(service.as_deployment(),
                         DeploymentState(nodes=[NodeState(
                             hostname=u"host1",
                             manifestations={
                                 MANIFESTATION.dataset_id: MANIFESTATION},
                             applications=[APP1])]))

    def test_update(self):
        """
        An update for previously given hostname overrides the previous state
        of that hostname.
        """
        service = self.service()
        service.apply_changes([
            NodeState(hostname=u"host1", applications=[APP1]),
            NodeState(hostname=u"host1", applications=[APP2]),
        ])
        self.assertEqual(service.as_deployment(),
                         DeploymentState(nodes=[NodeState(
                             hostname=u"host1",
                             applications=frozenset([APP2]))]))

    def test_multiple_hosts(self):
        """
        The information from multiple hosts is combined by
        ``ClusterStateService.as_deployment``.
        """
        service = self.service()
        service.apply_changes([
            NodeState(hostname=u"host1", applications=[APP1]),
            NodeState(hostname=u"host2", applications=[APP2]),
        ])
        self.assertEqual(service.as_deployment(),
                         DeploymentState(nodes=[
                             NodeState(
                                 hostname=u"host1",
                                 applications=frozenset([APP1])),
                             NodeState(
                                 hostname=u"host2",
                                 applications=frozenset([APP2])),
                         ]))

    def test_manifestation_path(self):
        """
        ``manifestation_path`` returns the path on the filesystem where the
        given dataset exists.
        """
        identifier = uuid4()
        service = self.service()
        service.apply_changes([
            NodeState(hostname=u"host1", uuid=identifier,
                      manifestations={
                          MANIFESTATION.dataset_id:
                          MANIFESTATION},
                      paths={MANIFESTATION.dataset_id:
                             FilePath(b"/xxx/yyy")})
        ])
        self.assertEqual(
            service.manifestation_path(identifier, MANIFESTATION.dataset_id),
            FilePath(b"/xxx/yyy"))

    def test_expiration(self):
        """
        Information updates that are more than 10 seconds old are wiped.
        """
        service = self.service()
        app_node = NodeState(hostname=u"10.0.0.1", uuid=uuid4(),
                             manifestations=None, devices=None, paths=None,
                             applications=[APP1])
        service.apply_changes([app_node])
        self.clock.advance(9)
        nine_second_state = service.as_deployment()
        self.clock.advance(1)
        ten_second_state = service.as_deployment()
        self.assertEqual(
            [nine_second_state, ten_second_state],
            [DeploymentState(nodes=[app_node]), DeploymentState()])

    def test_updates_different_key(self):
        """
        A wipe created by a ``IClusterStateChange`` with a given wipe key is
        not overwritten by a later ``IClusterStateChange`` with a
        different key.
        """
        service = self.service()
        app_node = NodeState(hostname=u"10.0.0.1", uuid=uuid4(),
                             manifestations=None, devices=None, paths=None,
                             applications=[APP1], used_ports=None)
        app_node_2 = app_node.set("applications", None).set(
            "manifestations", {MANIFESTATION.dataset_id: MANIFESTATION})
        service.apply_changes([app_node])
        self.clock.advance(1)
        service.apply_changes([app_node_2])
        self.clock.advance(9)
        ten_second_state = service.as_deployment()
        self.clock.advance(1)
        eleven_second_state = service.as_deployment()
        self.assertEqual(
            [ten_second_state, eleven_second_state],
            [DeploymentState(nodes=[app_node_2]), DeploymentState()])

    def test_update_with_same_key(self):
        """
        An update with the same key as a previous one delays wiping.
        """
        service = self.service()
        app_node = NodeState(hostname=u"10.0.0.1", uuid=uuid4(),
                             manifestations=None, devices=None, paths=None,
                             applications=[APP1], used_ports=None)
        service.apply_changes([app_node])
        self.clock.advance(1)
        service.apply_changes([app_node])
        self.clock.advance(9)
        self.assertEqual(service.as_deployment(),
                         DeploymentState(nodes=[app_node]))
{'fraction_non_alphanumeric': 0.10040104130021811, 'fraction_numerical': 0.008091184127207485, 'mean_word_length': 1.9880176581879336, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 5, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4657061', 'n_tokens_mistral': 3767, 'n_tokens_neox': 3693, 'n_words': 679}