"""Test for heartbeat module.""" import json import os import pytest from freezegun import freeze_time from notifications_delivery import config from notifications_delivery.utils import heartbeat class FakeWorker: """Fake worker for tests.""" def __init__(self, name, is_alive): """Create a fake worker.""" self.name = name self.is_alive = lambda: is_alive @pytest.fixture(autouse=True) def delete_heartbeat(): """Automatically delete heartbeat file before each test.""" try: os.remove(config.HEARTBEAT_FILE) except: # noqa pass @freeze_time('2025-01-03 12:00:01') @pytest.mark.parametrize('workers, expected_result', ( ( ( FakeWorker('worker1', True), ), { 'timestamp': 1735905601.0, 'workers': [ {'name': 'worker1', 'is_alive': True} ], } ), ( ( FakeWorker('worker1', True), FakeWorker('worker2', False), ), { 'timestamp': 1735905601.0, 'workers': [ {'name': 'worker1', 'is_alive': True}, {'name': 'worker2', 'is_alive': False}, ], } ), )) def test_heartbeat_send(workers, expected_result): """Test that heartbeat is sent.""" heartbeat.send(workers) with open(config.HEARTBEAT_FILE) as f: data = json.load(f) assert data == expected_result @freeze_time('2025-01-03 12:00:01') @pytest.mark.parametrize('heartbeat_data, expected_result, expected_message', ( ( None, False, "Can't read heartbeat data\n" ), ( '', False, 'Invalid heartbeat data\n' ), ( json.dumps({ 'timestamp': 1735905300.0, 'workers': [{'name': 'worker1', 'is_alive': True}] }), False, 'Heartbeat data is stale\n' ), ( json.dumps({ 'timestamp': 1735905600.0, 'workers': [{'name': 'worker1', 'is_alive': False}] }), False, 'Dead workers: worker1\n' ), ( json.dumps({ 'timestamp': 1735905600.0, 'workers': [ {'name': 'worker1', 'is_alive': False}, {'name': 'worker2', 'is_alive': True}, {'name': 'worker3', 'is_alive': False}, ]}), False, 'Dead workers: worker1, worker3\n' ), ( json.dumps({ 'timestamp': 1735905600.0, 'workers': [{'name': 'worker1', 'is_alive': True}] }), True, '' ), )) def test_heartbeat_validate(heartbeat_data, expected_result, expected_message, capsys): """Test that heartbeat is validated.""" if heartbeat_data is not None: with open(config.HEARTBEAT_FILE, 'w') as f: f.write(heartbeat_data) result = heartbeat.validate() captured = capsys.readouterr() assert result == expected_result assert captured.out == expected_message