from unittest import mock import pytest from devices.models.sensor import ArmaSensor from devices.services.sensor.enums import SystemMessage from devices.services.sensor.rabbitmq import SensorManagement, SensorResponseException SENSOR_DATA = { "name": "SENSOR_TEST", "ip": "192.168.56.103", "port": 5000, "type": 'firewall' } # each case contains the source message and the expected response test_send_message_with_decode_success = [ ('{"status": "ok"}', {'status': 'ok'}), ('["1","2"]', ["1", "2"]), ('{}', {}) ] test_send_message_with_decode_error = [ ('', {'status': 'error', 'detail': 'sensor doesnt return response'}), (b'', {'status': 'error', 'detail': 'sensor doesnt return response'}), ([], {'status': 'error', 'detail': 'sensor doesnt return response'}), ('body_from_sensor', {'status': 'error', 'detail': 'failed to decode sensor response to json'}), (b'body_from_sensor', {'status': 'error', 'detail': 'failed to decode sensor response to json'}), ] test_send_message_without_decode = [ ('', '{"status": "error", "detail": "sensor doesnt return response"}'), (b'', '{"status": "error", "detail": "sensor doesnt return response"}'), ([], '{"status": "error", "detail": "sensor doesnt return response"}'), ('body_from_sensor', 'body_from_sensor'), (b'bytes_from_sensor', b'bytes_from_sensor'), ] def mock_pika(*args, **kwargs): class MockBlockingChannel: def basic_consume(self, *args, **kwargs): pass def basic_publish(self, *args, **kwargs): pass def exchange_declare(self, *args, **kwargs): pass def queue_declare(self, *args, **kwargs): class Queue: queue = 'callback_queue' class Method: method = Queue() return Method() class MockBlockingConnection: def __init__(self, *args, **kwargs): pass def close(self): pass def process_data_events(self, *args, **kwargs): pass def call_later(self, *args, **kwargs): pass def channel(self): return MockBlockingChannel() return MockBlockingConnection @pytest.mark.unit @pytest.mark.django_db class TestSensorManagement: @pytest.fixture(autouse=True) def setup_tests(self): self.sensor = ArmaSensor.objects.create(**SENSOR_DATA) @mock.patch('pika.BlockingConnection', mock_pika()) def test_send_message_to_all_without_response(self): service = SensorManagement() response = service.send_message() assert response is None @mock.patch('pika.BlockingConnection', mock_pika()) def test_send_message_to_all_but_no_one_answer(self): service = SensorManagement(proceed=False) response = service.send_message(message_type=SystemMessage.ping, wait_response=True) assert response == () @pytest.mark.parametrize('test_data', test_send_message_with_decode_error) @mock.patch('pika.BlockingConnection', mock_pika()) def test_send_message_to_all_with_decode_error(self, test_data): service = SensorManagement(proceed=False) body = test_data[0] service._response_callback(None, None, None, body, True) response = service.send_message(message_type=SystemMessage.ping, wait_response=True) print(response) assert response[0] == test_data[1] assert len(response) == 1 @pytest.mark.parametrize('test_data', test_send_message_with_decode_error) @mock.patch('pika.BlockingConnection', mock_pika()) def test_send_message_to_sensor_with_decode_error(self, test_data: tuple): service = SensorManagement(proceed=False) body = test_data[0] service._response_callback(None, None, None, body, True) with pytest.raises(SensorResponseException) as exc: service.send_message(sensor=self.sensor, message_type=SystemMessage.ping, wait_response=True) assert exc.value.detail['status'] == test_data[1]['status'] assert exc.value.detail['detail'] == test_data[1]['detail'] @pytest.mark.parametrize('test_data', test_send_message_without_decode) @mock.patch('pika.BlockingConnection', mock_pika()) def test_send_message_to_all_without_decode(self, test_data): service = SensorManagement(proceed=False) body = test_data[0] service._response_callback(None, None, None, body, False) response = service.send_message(message_type=SystemMessage.ping, wait_response=True) assert response[0] == test_data[1] assert len(response) == 1 @pytest.mark.parametrize('test_data', test_send_message_without_decode) @mock.patch('pika.BlockingConnection', mock_pika()) def test_send_message_to_sensor_without_decode(self, test_data: tuple): service = SensorManagement(proceed=False) body = test_data[0] service._response_callback(None, None, None, body, False) response = service.send_message(sensor=self.sensor, message_type=SystemMessage.ping, wait_response=True) assert response == test_data[1] @pytest.mark.parametrize('test_data', test_send_message_with_decode_success) @mock.patch('pika.BlockingConnection', mock_pika()) def test_send_message_to_all_with_decode_success(self, test_data): service = SensorManagement(proceed=False) body = test_data[0] service._response_callback(None, None, None, body, True) response = service.send_message(message_type=SystemMessage.ping, wait_response=True) assert response[0] == test_data[1] assert len(response) == 1 @pytest.mark.parametrize('test_data', test_send_message_with_decode_success) @mock.patch('pika.BlockingConnection', mock_pika()) def test_send_message_to_sensor_with_decode_success(self, test_data): service = SensorManagement(proceed=False) body = test_data[0] service._response_callback(None, None, None, body, True) response = service.send_message(sensor=self.sensor, message_type=SystemMessage.ping, wait_response=True) assert response == test_data[1]