Skip to content

Commit

Permalink
test(ISD-847): Add workaround to unit tests simulating charm initiali…
Browse files Browse the repository at this point in the history
…zation after config-change event
  • Loading branch information
amandahla committed Jun 28, 2023
1 parent dc91043 commit d7e3bb5
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 38 deletions.
3 changes: 0 additions & 3 deletions src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,6 @@ def _on_config_changed(self, event: ops.HookEvent) -> None:
self.unit.status = ops.WaitingStatus("Waiting for pebble")
return
try:
self._charm_state = CharmState.from_charm(charm=self)
self._synapse = Synapse(charm_state=self._charm_state)
self._synapse.check_server_name(container)
self.model.unit.status = ops.MaintenanceStatus("Configuring Synapse")
self._synapse.execute_migrate_config(container)
except (
Expand Down
22 changes: 21 additions & 1 deletion tests/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

"""pytest fixtures for the unit test."""

# pylint: disable=too-few-public-methods
# pylint: disable=too-few-public-methods, protected-access

import typing
import unittest.mock
Expand Down Expand Up @@ -165,6 +165,26 @@ def harness_server_name_configured_fixture(harness: Harness) -> Harness:
return harness


@pytest.fixture(name="harness_server_name_changed")
def harness_server_name_changed_fixture(harness_server_name_configured: Harness) -> Harness:
"""Ops testing framework harness fixture with server_name changed.
This is a workaround for the fact that Harness doesn't reinitialize the charm as expected.
Reference: https://github.com/canonical/operator/issues/736
"""
harness = harness_server_name_configured
harness.disable_hooks()
harness._framework = ops.framework.Framework(
harness._storage, harness._charm_dir, harness._meta, harness._model
)
harness._charm = None
server_name_changed = "pebble-layer-1.synapse.com"
harness.update_config({"server_name": server_name_changed})
harness.enable_hooks()
harness.begin_with_initial_hooks()
return harness


@pytest.fixture(name="container_mocked")
def container_mocked_fixture(monkeypatch: pytest.MonkeyPatch) -> unittest.mock.MagicMock:
"""Mock container base to others fixtures."""
Expand Down
46 changes: 12 additions & 34 deletions tests/unit/test_charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,32 +114,26 @@ def test_traefik_integration(harness_server_name_configured: Harness) -> None:


@pytest.mark.parametrize("harness", [0], indirect=True)
def test_server_name_change(harness_server_name_configured: Harness) -> None:
def test_server_name_change(harness_server_name_changed: Harness) -> None:
"""
arrange: start the Synapse charm, set Synapse container to be ready and set server_name.
act: change to a different server_name.
assert: Synapse charm should prevent the change with a BlockStatus.
"""
harness = harness_server_name_configured
server_name_changed = "pebble-layer-1.synapse.com"
harness.update_config({"server_name": server_name_changed})
harness = harness_server_name_changed
assert isinstance(harness.model.unit.status, ops.BlockedStatus)
assert "server_name modification is not allowed" in str(harness.model.unit.status)


@pytest.mark.parametrize("harness", [0], indirect=True)
def test_reset_instance_action(harness_server_name_configured: Harness) -> None:
def test_reset_instance_action(harness_server_name_changed: Harness) -> None:
"""
arrange: start the Synapse charm, set Synapse container to be ready and set server_name.
act: run reset-instance action.
assert: Synapse charm should reset the instance.
"""
harness = harness_server_name_configured
harness = harness_server_name_changed
harness.set_leader(True)
server_name_changed = "pebble-layer-1.synapse.com"
harness.update_config({"server_name": server_name_changed})
assert isinstance(harness.model.unit.status, ops.BlockedStatus)
assert "server_name modification is not allowed" in str(harness.model.unit.status)
event = unittest.mock.Mock()
# Calling to test the action since is not possible calling via harness
harness.charm._on_reset_instance_action(event)
Expand All @@ -149,18 +143,14 @@ def test_reset_instance_action(harness_server_name_configured: Harness) -> None:


@pytest.mark.parametrize("harness", [1], indirect=True)
def test_reset_instance_action_failed(harness_server_name_configured: Harness) -> None:
def test_reset_instance_action_failed(harness_server_name_changed: Harness) -> None:
"""
arrange: start the Synapse charm, set Synapse container to be ready and set server_name.
act: change server_name and run reset-instance action.
assert: Synapse charm should be blocked by error on migrate_config command.
"""
harness = harness_server_name_configured
harness = harness_server_name_changed
harness.set_leader(True)
server_name_changed = "pebble-layer-1.synapse.com"
harness.update_config({"server_name": server_name_changed})
assert isinstance(harness.model.unit.status, ops.BlockedStatus)
assert "server_name modification is not allowed" in str(harness.model.unit.status)
event = unittest.mock.Mock()
# Calling to test the action since is not possible calling via harness
harness.charm._on_reset_instance_action(event)
Expand All @@ -172,19 +162,15 @@ def test_reset_instance_action_failed(harness_server_name_configured: Harness) -
@pytest.mark.parametrize("harness", [0], indirect=True)
def test_reset_instance_action_path_error_blocked(
container_with_path_error_blocked: unittest.mock.MagicMock,
harness_server_name_configured: Harness,
harness_server_name_changed: Harness,
) -> None:
"""
arrange: start the Synapse charm, set Synapse container to be ready and set server_name.
act: change server_name and run reset-instance action.
assert: Synapse charm should be blocked by error on remove_path.
"""
harness = harness_server_name_configured
harness = harness_server_name_changed
harness.set_leader(True)
server_name_changed = "pebble-layer-1.synapse.com"
harness.update_config({"server_name": server_name_changed})
assert isinstance(harness.model.unit.status, ops.BlockedStatus)
assert "server_name modification is not allowed" in str(harness.model.unit.status)
harness.charm.unit.get_container = unittest.mock.MagicMock(
return_value=container_with_path_error_blocked
)
Expand All @@ -199,20 +185,17 @@ def test_reset_instance_action_path_error_blocked(
@pytest.mark.parametrize("harness", [0], indirect=True)
def test_reset_instance_action_path_error_pass(
container_with_path_error_pass: unittest.mock.MagicMock,
harness_server_name_configured: Harness,
harness_server_name_changed: Harness,
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""
arrange: start the Synapse charm, set Synapse container to be ready and set server_name.
act: change server_name and run reset-instance action.
assert: Synapse charm should reset the instance.
"""
harness = harness_server_name_configured
harness = harness_server_name_changed
harness.set_leader(True)
server_name_changed = "pebble-layer-1.synapse.com"
harness.update_config({"server_name": server_name_changed})
assert isinstance(harness.model.unit.status, ops.BlockedStatus)
assert "server_name modification is not allowed" in str(harness.model.unit.status)
content = io.StringIO(f'server_name: "{server_name_changed}"')
pull_mock = unittest.mock.MagicMock(return_value=content)
monkeypatch.setattr(container_with_path_error_pass, "pull", pull_mock)
Expand All @@ -228,19 +211,14 @@ def test_reset_instance_action_path_error_pass(

@pytest.mark.parametrize("harness", [0], indirect=True)
def test_reset_instance_action_no_leader(
harness_server_name_configured: Harness,
harness_server_name_changed: Harness,
) -> None:
"""
arrange: start the Synapse charm, set Synapse container to be ready and set server_name.
act: change server_name and run reset-instance action.
assert: Synapse charm should take no action if no leader.
"""
harness = harness_server_name_configured
harness.set_leader(True)
server_name_changed = "pebble-layer-1.synapse.com"
harness.update_config({"server_name": server_name_changed})
assert isinstance(harness.model.unit.status, ops.BlockedStatus)
assert "server_name modification is not allowed" in str(harness.model.unit.status)
harness = harness_server_name_changed
harness.set_leader(False)
event = unittest.mock.MagicMock()
# Calling to test the action since is not possible calling via harness
Expand Down

0 comments on commit d7e3bb5

Please sign in to comment.