# -*- coding: utf-8 -*- ########################################################################## # OpenLP - Open Source Lyrics Projection # # ---------------------------------------------------------------------- # # Copyright (c) 2008-2020 OpenLP Developers # # ---------------------------------------------------------------------- # # This program is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation, either version 3 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program. If not, see . # ########################################################################## """ Package to test the openlp.core.projectors.pjlink commands package. """ from unittest import TestCase from unittest.mock import call, patch import openlp.core.projectors.pjlink from openlp.core.projectors.pjlinkcommands import process_command from openlp.core.projectors.constants import E_ERROR, E_WARN, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, S_OK from openlp.core.projectors.db import Projector from openlp.core.projectors.pjlink import PJLink from tests.resources.projector.data import TEST1_DATA class TestPJLinkCommands(TestCase): """ Tests PJLink commands part 1 """ def setUp(self): """ Initial test setup """ self.pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) def tearDown(self): """ Test reset """ del(self.pjlink) @patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_avmt_audio_muted(self, mock_log, mock_UpdateIcons): """ Test avmt status shutter unchanged and mute on """ # GIVEN: Test setup log_warning_text = [] log_debug_text = [call('({ip}) Processing command "AVMT" with data "21"'.format(ip=self.pjlink.name)), call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name)), call('({ip}) Setting speaker to muted'.format(ip=self.pjlink.name))] self.pjlink.shutter = True self.pjlink.mute = False # WHEN: Called with setting shutter closed and mute on process_command(projector=self.pjlink, cmd='AVMT', data='21') # THEN: Shutter should be closed and mute should be True assert self.pjlink.shutter, 'Shutter should not have changed' assert self.pjlink.mute, 'Audio should be off' assert mock_UpdateIcons.emit.called, 'Update icons should have been called' mock_log.warning.assert_has_calls(log_warning_text) mock_log.debug.assert_has_calls(log_debug_text) @patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_avmt_bad_data(self, mock_log, mock_UpdateIcons): """ Test avmt bad data fail """ # GIVEN: Test object log_warning_text = [call('({ip}) Invalid av mute response: 36'.format(ip=self.pjlink.name))] log_debug_text = [call('({ip}) Processing command "AVMT" with data "36"'.format(ip=self.pjlink.name)), call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name))] self.pjlink.shutter = True self.pjlink.mute = True # WHEN: Called with an invalid setting process_command(projector=self.pjlink, cmd='AVMT', data='36') # THEN: Shutter should be closed and mute should be True assert self.pjlink.shutter, 'Shutter should changed' assert self.pjlink.mute, 'Audio should not have changed' assert not mock_UpdateIcons.emit.called, 'Update icons should NOT have been called' mock_log.warning.assert_has_calls(log_warning_text) mock_log.debug.assert_has_calls(log_debug_text) @patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_avmt_closed_muted(self, mock_log, mock_UpdateIcons): """ Test avmt status shutter closed and mute off """ # GIVEN: Test object log_warning_text = [] log_debug_text = [call('({ip}) Processing command "AVMT" with data "31"'.format(ip=self.pjlink.name)), call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name)), call('({ip}) Setting shutter to closed'.format(ip=self.pjlink.name)), call('({ip}) Setting speaker to muted'.format(ip=self.pjlink.name))] self.pjlink.shutter = False self.pjlink.mute = False # WHEN: Called with setting shutter to closed and mute on process_command(projector=self.pjlink, cmd='AVMT', data='31') # THEN: Shutter should be closed and mute should be True assert self.pjlink.shutter, 'Shutter should have been set to closed' assert self.pjlink.mute, 'Audio should be muted' assert mock_UpdateIcons.emit.called, 'Update icons should have been called' mock_log.warning.assert_has_calls(log_warning_text) mock_log.debug.assert_has_calls(log_debug_text) @patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_avmt_open_unmuted(self, mock_log, mock_UpdateIcons): """ Test avmt status shutter open and mute off """ # GIVEN: Test object log_warning_text = [] log_debug_text = [call('({ip}) Processing command "AVMT" with data "30"'.format(ip=self.pjlink.name)), call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name)), call('({ip}) Setting shutter to open'.format(ip=self.pjlink.name)), call('({ip}) Setting speaker to normal'.format(ip=self.pjlink.name))] self.pjlink.shutter = True self.pjlink.mute = True # WHEN: Called with setting shutter to closed and mute on process_command(projector=self.pjlink, cmd='AVMT', data='30') # THEN: Shutter should be closed and mute should be True assert not self.pjlink.shutter, 'Shutter should have been set to off' assert not self.pjlink.mute, 'Audio should be on' assert mock_UpdateIcons.emit.called, 'Update icons should have been called' mock_log.warning.assert_has_calls(log_warning_text) mock_log.debug.assert_has_calls(log_debug_text) @patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_avmt_shutter_closed(self, mock_log, mock_UpdateIcons): """ Test avmt status shutter closed and audio unchanged """ # GIVEN: Test object log_warning_text = [] log_debug_text = [call('({ip}) Processing command "AVMT" with data "11"'.format(ip=self.pjlink.name)), call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name)), call('({ip}) Setting shutter to closed'.format(ip=self.pjlink.name))] self.pjlink.shutter = False self.pjlink.mute = True # WHEN: Called with setting shutter closed and mute off process_command(projector=self.pjlink, cmd='AVMT', data='11') # THEN: Shutter should be True and mute should be False assert self.pjlink.shutter, 'Shutter should have been set to closed' assert self.pjlink.mute, 'Audio should not have changed' assert mock_UpdateIcons.emit.called, 'Update icons should have been called' mock_log.warning.assert_has_calls(log_warning_text) mock_log.debug.assert_has_calls(log_debug_text) @patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_avmt_status_timer_check_delete(self, mock_log, mock_UpdateIcons): """ Test avmt deletes callback in projector.status_timer_check """ # GIVEN: Test object log_warning_text = [] log_debug_text = [call('({ip}) Processing command "AVMT" with data "11"'.format(ip=self.pjlink.name)), call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name)), call('({ip}) Setting shutter to closed'.format(ip=self.pjlink.name))] self.pjlink.shutter = False self.pjlink.mute = True self.pjlink.status_timer_checks = {'AVMT': self.pjlink.get_av_mute_status} # WHEN: Called with setting shutter closed and mute off with patch.object(self.pjlink, 'status_timer') as mock_status_timer: process_command(projector=self.pjlink, cmd='AVMT', data='11') # THEN: Shutter should be True and mute should be False assert self.pjlink.shutter, 'Shutter should have been set to closed' assert self.pjlink.mute, 'Audio should not have changed' assert mock_UpdateIcons.emit.called, 'Update icons should have been called' assert 'AVMT' not in self.pjlink.status_timer_checks, 'Status timer list should not have AVMT callback' assert mock_status_timer.stop.called, 'Projector status_timer.stop() should have been called' mock_log.warning.assert_has_calls(log_warning_text) mock_log.debug.assert_has_calls(log_debug_text) @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_clss_1(self, mock_log): """ Test CLSS request returns non-standard reply 1 """ # GIVEN: Test object log_error_calls = [] log_warning_calls = [] log_debug_calls = [call('({ip}) Processing command "CLSS" with data "1"'.format(ip=self.pjlink.name)), call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)), call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=self.pjlink.name))] # WHEN: Process non-standard reply process_command(projector=self.pjlink, cmd='CLSS', data='1') # THEN: Projector class should be set with proper value assert '1' == self.pjlink.pjlink_class, 'Should have set class=1' mock_log.error.assert_has_calls(log_error_calls) mock_log.warning.assert_has_calls(log_warning_calls) mock_log.debug.assert_has_calls(log_debug_calls) @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_clss_2(self, mock_log): """ Test CLSS request returns non-standard reply 1 """ # GIVEN: Test object log_error_calls = [] log_warning_calls = [] log_debug_calls = [call('({ip}) Processing command "CLSS" with data "2"'.format(ip=self.pjlink.name)), call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)), call('({ip}) Setting pjlink_class for this projector to "2"'.format(ip=self.pjlink.name))] # WHEN: Process non-standard reply process_command(projector=self.pjlink, cmd='CLSS', data='2') # THEN: Projector class should be set with proper value assert '2' == self.pjlink.pjlink_class, 'Should have set class=2' mock_log.error.assert_has_calls(log_error_calls) mock_log.warning.assert_has_calls(log_warning_calls) mock_log.debug.assert_has_calls(log_debug_calls) @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_clss_invalid_nan(self, mock_log): """ Test CLSS reply has no class number """ # GIVEN: Test setup log_warning_calls = [call('({ip}) NAN CLSS version reply "Z" - ' 'defaulting to class "1"'.format(ip=self.pjlink.name))] log_debug_calls = [call('({ip}) Processing command "CLSS" with data "Z"'.format(ip=self.pjlink.name)), call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)), call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=self.pjlink.name))] # WHEN: Process invalid reply process_command(projector=self.pjlink, cmd='CLSS', data='Z') # THEN: Projector class should be set with default value assert self.pjlink.pjlink_class == '1', 'Invalid NaN class reply should have set class=1' mock_log.warning.assert_has_calls(log_warning_calls) mock_log.debug.assert_has_calls(log_debug_calls) @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_clss_invalid_no_version(self, mock_log): """ Test CLSS reply has no class number """ # GIVEN: Test object log_warning_calls = [call('({ip}) No numbers found in class version reply "Invalid" ' '- defaulting to class "1"'.format(ip=self.pjlink.name))] log_debug_calls = [call('({ip}) Processing command "CLSS" with data "Invalid"'.format(ip=self.pjlink.name)), call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)), call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=self.pjlink.name))] # WHEN: Process invalid reply process_command(projector=self.pjlink, cmd='CLSS', data='Invalid') # THEN: Projector class should be set with default value assert self.pjlink.pjlink_class == '1', 'Invalid class reply should have set class=1' mock_log.warning.assert_has_calls(log_warning_calls) mock_log.debug.assert_has_calls(log_debug_calls) @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_clss_nonstandard_reply_1(self, mock_log): """ Test CLSS request returns non-standard reply 1 """ # GIVEN: Test object log_error_calls = [] log_warning_calls = [call('({ip}) Non-standard CLSS reply: "Class 1"'.format(ip=self.pjlink.name))] log_debug_calls = [call('({ip}) Processing command "CLSS" with data "Class 1"'.format(ip=self.pjlink.name)), call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)), call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=self.pjlink.name))] # WHEN: Process non-standard reply process_command(projector=self.pjlink, cmd='CLSS', data='Class 1') # THEN: Projector class should be set with proper value assert '1' == self.pjlink.pjlink_class, 'Non-standard class reply should have set class=1' mock_log.error.assert_has_calls(log_error_calls) mock_log.warning.assert_has_calls(log_warning_calls) mock_log.debug.assert_has_calls(log_debug_calls) @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_clss_nonstandard_reply_2(self, mock_log): """ Test CLSS request returns non-standard reply 1 """ # GIVEN: Test object log_warning_calls = [call('({ip}) Non-standard CLSS reply: "Version2"'.format(ip=self.pjlink.name))] log_debug_calls = [call('({ip}) Processing command "CLSS" with data "Version2"'.format(ip=self.pjlink.name)), call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)), call('({ip}) Setting pjlink_class for this projector to "2"'.format(ip=self.pjlink.name))] # WHEN: Process non-standard reply process_command(projector=self.pjlink, cmd='CLSS', data='Version2') # THEN: Projector class should be set with proper value assert '2' == self.pjlink.pjlink_class, 'Non-standard class reply should have set class=1' mock_log.warning.assert_has_calls(log_warning_calls) mock_log.debug.assert_has_calls(log_debug_calls) @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_erst_all_error(self, mock_log): """ Test test_projector_process_erst_all_error """ # GIVEN: Test object chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_ERROR], lamp=PJLINK_ERST_STATUS[E_ERROR], temp=PJLINK_ERST_STATUS[E_ERROR], cover=PJLINK_ERST_STATUS[E_ERROR], filt=PJLINK_ERST_STATUS[E_ERROR], other=PJLINK_ERST_STATUS[E_ERROR]) chk_test = {'Fan': E_ERROR, 'Lamp': E_ERROR, 'Temperature': E_ERROR, 'Cover': E_ERROR, 'Filter': E_ERROR, 'Other': E_ERROR} log_warning_calls = [] log_debug_calls = [call('({ip}) Processing command "ERST" with data "{chk}"'.format(ip=self.pjlink.name, chk=chk_data)), call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))] self.pjlink.projector_errors = None # WHEN: process_erst with status set to WARN process_command(projector=self.pjlink, cmd='ERST', data=chk_data) # THEN: PJLink instance errors should match chk_value assert self.pjlink.projector_errors == chk_test, 'Projector errors should be all E_ERROR' mock_log.warning.assert_has_calls(log_warning_calls) mock_log.debug.assert_has_calls(log_debug_calls) @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_erst_all_ok(self, mock_log): """ Test to verify pjlink.projector_errors is set to None when no errors """ # GIVEN: Test object chk_data = '0' * PJLINK_ERST_DATA['DATA_LENGTH'] log_warning_calls = [] log_debug_calls = [call('({ip}) Processing command "ERST" with data "{chk}"'.format(ip=self.pjlink.name, chk=chk_data)), call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))] # WHEN: process_erst with no errors process_command(projector=self.pjlink, cmd='ERST', data=chk_data) # THEN: PJLink instance errors should be None assert self.pjlink.projector_errors is None, 'projector_errors should have been set to None' mock_log.warning.assert_has_calls(log_warning_calls) mock_log.debug.assert_has_calls(log_debug_calls) @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_erst_all_warn(self, mock_log): """ Test test_projector_process_erst_all_error """ # GIVEN: Test object chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_WARN], lamp=PJLINK_ERST_STATUS[E_WARN], temp=PJLINK_ERST_STATUS[E_WARN], cover=PJLINK_ERST_STATUS[E_WARN], filt=PJLINK_ERST_STATUS[E_WARN], other=PJLINK_ERST_STATUS[E_WARN]) chk_test = {'Fan': E_WARN, 'Lamp': E_WARN, 'Temperature': E_WARN, 'Cover': E_WARN, 'Filter': E_WARN, 'Other': E_WARN} log_warning_calls = [] log_debug_calls = [call('({ip}) Processing command "ERST" with data "{chk}"'.format(ip=self.pjlink.name, chk=chk_data)), call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))] self.pjlink.projector_errors = None # WHEN: process_erst with status set to WARN process_command(projector=self.pjlink, cmd='ERST', data=chk_data) # THEN: PJLink instance errors should match chk_value assert self.pjlink.projector_errors == chk_test, 'Projector errors should be all E_WARN' mock_log.warning.assert_has_calls(log_warning_calls) mock_log.debug.assert_has_calls(log_debug_calls) @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_erst_data_invalid_length(self, mock_log): """ Test test_projector_process_erst_data_invalid_length """ # GIVEN: Test object chk_data = '0' * (PJLINK_ERST_DATA['DATA_LENGTH'] + 1) log_warn_calls = [call('({ip}) Invalid error status response "{data}": ' 'length != {chk}'.format(ip=self.pjlink.name, data=chk_data, chk=PJLINK_ERST_DATA['DATA_LENGTH']))] log_debug_calls = [call('({ip}) Processing command "ERST" with data "{data}"'.format(ip=self.pjlink.name, data=chk_data)), call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))] self.pjlink.projector_errors = None # WHEN: process_erst called with invalid data (too many values process_command(self.pjlink, cmd='ERST', data=chk_data) # THEN: pjlink.projector_errors should be empty and warning logged assert not self.pjlink.projector_errors, 'There should be no errors' mock_log.warning.assert_has_calls(log_warn_calls) mock_log.debug.assert_has_calls(log_debug_calls) @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_erst_data_invalid_nan(self, mock_log): """ Test ERST called with invalid data """ # GIVEN: Test object chk_data = 'Z' + ('0' * (PJLINK_ERST_DATA['DATA_LENGTH'] - 1)) log_warn_calls = [call('({ip}) Invalid error status response "{data}"'.format(ip=self.pjlink.name, data=chk_data))] log_debug_calls = [call('({ip}) Processing command "ERST" with data "{data}"'.format(ip=self.pjlink.name, data=chk_data)), call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))] self.pjlink.projector_errors = None # WHEN: process_erst called with invalid data (too many values process_command(self.pjlink, cmd='ERST', data=chk_data) # THEN: pjlink.projector_errors should be empty and warning logged assert not self.pjlink.projector_errors, 'There should be no errors' mock_log.warning.assert_has_calls(log_warn_calls) mock_log.debug.assert_has_calls(log_debug_calls) @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_erst_warn_cover_only(self, mock_log): """ Test test_projector_process_erst_warn_cover_only """ # GIVEN: Test object chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[S_OK], lamp=PJLINK_ERST_STATUS[S_OK], temp=PJLINK_ERST_STATUS[S_OK], cover=PJLINK_ERST_STATUS[E_WARN], filt=PJLINK_ERST_STATUS[S_OK], other=PJLINK_ERST_STATUS[S_OK]) chk_test = {'Cover': E_WARN} log_warn_calls = [] log_debug_calls = [call('({ip}) Processing command "ERST" with data "{data}"'.format(ip=self.pjlink.name, data=chk_data)), call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))] self.pjlink.projector_errors = None # WHEN: process_erst with status set to WARN process_command(projector=self.pjlink, cmd='ERST', data=chk_data) # THEN: PJLink instance errors should match only cover warning assert 1 == len(self.pjlink.projector_errors), 'There should only be 1 error listed in projector_errors' assert 'Cover' in self.pjlink.projector_errors, '"Cover" should be the only error listed' assert self.pjlink.projector_errors['Cover'] == E_WARN, '"Cover" should have E_WARN listed as error' assert chk_test == self.pjlink.projector_errors, 'projector_errors should match test errors' mock_log.warning.assert_has_calls(log_warn_calls) mock_log.debug.assert_has_calls(log_debug_calls) @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_inf1(self, mock_log): """ Test saving INF1 data (manufacturer) """ # GIVEN: Test object chk_data = 'TEst INformation MultiCase' log_warn_calls = [] log_debug_calls = [call('({ip}) Processing command "INF1" with data "{data}"'.format(ip=self.pjlink.name, data=chk_data)), call('({ip}) Calling function for INF1'.format(ip=self.pjlink.name)), call('({ip}) Setting projector manufacturer data to ' '"{data}"'.format(ip=self.pjlink.name, data=chk_data))] self.pjlink.manufacturer = None # WHEN: process_inf called with test data process_command(projector=self.pjlink, cmd='INF1', data=chk_data) # THEN: Data should be saved assert self.pjlink.manufacturer == chk_data, 'Test data should have been saved' mock_log.warning.assert_has_calls(log_warn_calls) mock_log.debug.assert_has_calls(log_debug_calls) @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_inf2(self, mock_log): """ Test saving INF2 data (model) """ # GIVEN: Test object chk_data = 'TEst moDEl MultiCase' log_warn_calls = [] log_debug_calls = [call('({ip}) Processing command "INF2" with data "{data}"'.format(ip=self.pjlink.name, data=chk_data)), call('({ip}) Calling function for INF2'.format(ip=self.pjlink.name)), call('({ip}) Setting projector model to "{data}"'.format(ip=self.pjlink.name, data=chk_data))] self.pjlink.model = None # WHEN: process_inf called with test data process_command(projector=self.pjlink, cmd='INF2', data=chk_data) # THEN: Data should be saved assert self.pjlink.model == chk_data, 'Test data should have been saved' mock_log.warning.assert_has_calls(log_warn_calls) mock_log.debug.assert_has_calls(log_debug_calls) @patch.object(openlp.core.projectors.pjlinkcommands, 'log') def test_projector_info(self, mock_log): """ Test saving INF2 data (model) """ # GIVEN: Test object chk_data = 'TEst ExtrANEous MultiCase INformatoin that MFGR might Set' log_warn_calls = [] log_debug_calls = [call('({ip}) Processing command "INFO" with data "{data}"'.format(ip=self.pjlink.name, data=chk_data)), call('({ip}) Calling function for INFO'.format(ip=self.pjlink.name)), call('({ip}) Setting projector other_info to "{data}"'.format(ip=self.pjlink.name, data=chk_data))] self.pjlink.other_info = None # WHEN: process_inf called with test data process_command(projector=self.pjlink, cmd='INFO', data=chk_data) # THEN: Data should be saved assert self.pjlink.other_info == chk_data, 'Test data should have been saved' mock_log.warning.assert_has_calls(log_warn_calls) mock_log.debug.assert_has_calls(log_debug_calls)