def test_change_not_existing_electric_meter(self): # Init meter_id = 10 self.state_file = FileLikeMock( json.dumps({ 'next_id': 11, 'electric_meters': [] })) self.logic.state = State(self.state_file_callback) self.logic.state.next_id = meter_id + 1 self.logic.state.electric_meters = {} self.logic.state.electric_meters_dict = {} self.db_file = FileLikeMock(value=json.dumps({ 'data_per_hour': self.data_per_hour, 'keep_raw': self.keep_raw, 'keep_day': self.keep_day, 'keep_month': self.keep_month, 'keep_year': self.keep_year, 'keep_years': self.keep_years, 'data_sources': [] })) self.logic.database = Database.load_database( self.database_file_callback) # Test self.assertRaises(KeyError, self.logic.change_electric_meter, meter_id)
def setUp(self) -> None: self.data_per_hour = 1 self.keep_raw = 3 self.keep_day = 48 self.keep_month = 30 self.keep_year = 12 self.keep_years = 3 self.plugin_type = 'plugin1' self.db_file = FileLikeMock() self.state_file = FileLikeMock() self.database: Database = Database.create_database( self.database_file_callback, self.data_per_hour, self.keep_raw, self.keep_day, self.keep_month, self.keep_year, self.keep_years) self.plugin_loader: PluginLoader = PluginLoader( {'ElectricMeterPlugins': { self.plugin_type: 'TestPlugin' }}, 'testplugins') self.state: State = State.get_state(self.state_file_callback, self.deserialize_electric_meter) self.logic = Logic(self.state, self.database, self.plugin_loader, self.data_per_hour)
def __init__(self, state: State, database: Database, plugin_loader: PluginLoader, data_per_hour: int): Logic.logger.info('Electric meter read frequency: %d / h', data_per_hour) self.state = state self.database = database self.plugin_loader = plugin_loader # Set Serialization hook of loaded electric meters for electric_meter in state.get_electric_meters(): electric_meter.set_serialize_hook(self._call_serialize_hook) # Timer to read electric_meters every db_step schedule.every(int(3600 / data_per_hour)).seconds.do(self._read_electric_meters) schedule_thread = threading.Thread(target=_run_scheduler) schedule_thread.daemon = True schedule_thread.start()
def test_load_empty_file(self): empty_file = FileLikeMock() file_like_object_callback = Mock(return_value=empty_file) deserialize_electric_meter_callback = Mock() # Test state = State.get_state(file_like_object_callback, deserialize_electric_meter_callback) # Assertion self.assertIsNotNone(state) deserialize_electric_meter_callback.assert_not_called() empty_file.seek(0) self.assertEqual({ 'next_id': 10, 'electric_meters': [] }, json.load(empty_file))
def test_load_electric_meter(self): # Setup meter_id = 1 value = 321 pin = 1 active_low = False name = 'test' count = 456 serialized_electric_meter = { "name": name, "custom": { "pin": pin, "active_low": active_low, "value": value, "count": count, } } deserialized_electric_meter = Mock() deserialize_electric_meter_callback = Mock(return_value=deserialized_electric_meter) # Test state = State.get_state( Mock(return_value=create_state_file(meter_id+1, meter_id, value, pin, active_low, name, count)), deserialize_electric_meter_callback) # Assert self.assertIsNotNone(state) deserialize_electric_meter_callback.assert_called_once_with(serialized_electric_meter) loaded_meters_dict = state.get_electric_meters_dict() self.assertIn(meter_id, loaded_meters_dict.keys()) loaded_meter_dict = loaded_meters_dict[meter_id] loaded_meters = state.get_electric_meters() self.assertIn(meter_id, loaded_meters.keys()) loaded_meter = loaded_meters[meter_id] self.assertEqual(deserialized_electric_meter, loaded_meter) self.assertEqual(serialized_electric_meter, loaded_meter_dict)
def setUp(self) -> None: self.state_file_mock = FileLikeMock('') self.state_file_callback = Mock(return_value=self.state_file_mock) self.state = State(self.state_file_callback) self.addCleanup(self.cleanup)
class PersistenceTest(unittest.TestCase): def setUp(self) -> None: self.state_file_mock = FileLikeMock('') self.state_file_callback = Mock(return_value=self.state_file_mock) self.state = State(self.state_file_callback) self.addCleanup(self.cleanup) def cleanup(self) -> None: StringIO.close(self.state_file_mock) def test_get_state(self): file_like_object_callback = Mock( return_value=create_state_file(random.randint(10, 100), 10, 20, 1, False, 'Test', 5)) state = State.get_state(file_like_object_callback, Mock()) file_like_object_callback.assert_called_once_with('r') self.assertIsNotNone(state) def test_save_electric_meter(self): # Setup meter_id = random.randint(10, 100) self.state.next_id = meter_id + 1 name = 'Name123' meter_type = 'TEST_PLUGIN' custom = { 'custom1': 'value1', 'custom2': 'value2', 'custom3': 'value3' } self.state.electric_meters_dict = { meter_id: { 'name': name, 'type': meter_type, 'custom': custom } } self.state.electric_meters = { meter_id: Mock() } # Test self.state.save_state() # Assertion self.state_file_callback.assert_called_with('w') self.assertTrue(self.state_file_mock.close_called) with self.state_file_mock: self.state_file_mock.seek(0) obj = json.load(self.state_file_mock) electric_meter_json = obj['electric_meters'][0] self.assertEqual({ meter_id: { 'name': name, 'type': meter_type, 'custom': custom } }, self.state.electric_meters_dict) self.assertEqual(str(meter_id), str(electric_meter_json['id'])) self.assertEqual(str(name), str(electric_meter_json['name'])) self.assertEqual(str(meter_type), str(electric_meter_json['type'])) self.assertEqual(str(custom), str(electric_meter_json['custom'])) def test_load_electric_meter(self): # Setup meter_id = 1 value = 321 pin = 1 active_low = False name = 'test' count = 456 serialized_electric_meter = { "name": name, "custom": { "pin": pin, "active_low": active_low, "value": value, "count": count, } } deserialized_electric_meter = Mock() deserialize_electric_meter_callback = Mock(return_value=deserialized_electric_meter) # Test state = State.get_state( Mock(return_value=create_state_file(meter_id+1, meter_id, value, pin, active_low, name, count)), deserialize_electric_meter_callback) # Assert self.assertIsNotNone(state) deserialize_electric_meter_callback.assert_called_once_with(serialized_electric_meter) loaded_meters_dict = state.get_electric_meters_dict() self.assertIn(meter_id, loaded_meters_dict.keys()) loaded_meter_dict = loaded_meters_dict[meter_id] loaded_meters = state.get_electric_meters() self.assertIn(meter_id, loaded_meters.keys()) loaded_meter = loaded_meters[meter_id] self.assertEqual(deserialized_electric_meter, loaded_meter) self.assertEqual(serialized_electric_meter, loaded_meter_dict) def test_load_empty_file(self): empty_file = FileLikeMock() file_like_object_callback = Mock(return_value=empty_file) deserialize_electric_meter_callback = Mock() # Test state = State.get_state(file_like_object_callback, deserialize_electric_meter_callback) # Assertion self.assertIsNotNone(state) deserialize_electric_meter_callback.assert_not_called() empty_file.seek(0) self.assertEqual({ 'next_id': 10, 'electric_meters': [] }, json.load(empty_file)) def test_load_invalid_syntax_file(self): # Setup # invalid file invalid_file = \ '''{"next_id" next_id, "electric_meters":[ {{"id": {id}, "vaue": {value}, "count": {count}, "nae: "{name}", "pin: {pin}, "actie_low": act_low} }} ] }}''' state_file_callback = Mock(return_value=StringIO(invalid_file)) # Test # Assert self.assertRaises(Persistence.InvalidStateFileException, State.get_state, state_file_callback, Mock()) def test_load_invalid_semantic_file(self): # Setup next_id = 20 meter_id = 1 value = -321 pin = 123 active_low = '\"invalid_semantics\"' name = 'test' count = 456 error_message = 'Something bla bla could not be loaded' invalid_state_dict = { "next_id": next_id, "electric_meters": [{ "id": meter_id, "name": name, "custom": { "pin": pin, "active_low": active_low, "value": value, "count": count } }] } state_file_callback = \ Mock(return_value=StringIO(json.dumps(invalid_state_dict))) deserialize_electric_meter_callback = \ Mock(side_effect=Plugin.ElectricMeterDeserializeException(error_message)) # Test # Assert with self.assertLogs('logic.Persistence', level=logging.ERROR) as log: self.assertRaises(Plugin.ElectricMeterDeserializeException, State.get_state, state_file_callback, deserialize_electric_meter_callback) deserialize_electric_meter_callback.assert_called_once_with({ "name": name, "custom": { "pin": pin, "active_low": active_low, "value": value, "count": count } }) self.assertIn('ERROR:logic.Persistence:' + error_message, log.output) def test_update_electric_meter(self): electric_meter_id = random.randint(10, 100) electric_meter = Mock() electric_meter_dict = MagicMock() changed_electric_meter_dict = MagicMock() self.state.electric_meters = { electric_meter_id: electric_meter } self.state.electric_meters_dict = { electric_meter_id: electric_meter_dict } # Test self.state.update_electric_meter(electric_meter, changed_electric_meter_dict) # Assertion self.assertIn((electric_meter_id, electric_meter), self.state.electric_meters.items()) self.assertIn((electric_meter_id, changed_electric_meter_dict), self.state.electric_meters_dict.items()) def test_update_not_existing_electric_meter(self): not_existing_meter = Mock() # Test # TODO Exception type self.assertRaises(Exception, self.state.update_electric_meter, not_existing_meter, {}) def test_add_electric_meter(self): electric_meter = Mock() self.state.save_state = Mock() expected_electric_meter_id = random.randint(10, 100) self.state.next_id = expected_electric_meter_id # Test electric_meter_id = self.state.add_electric_meter(electric_meter) # Assertions electric_meter.serialize.assert_called_once() self.state.save_state.assert_called_once() self.assertEqual(expected_electric_meter_id, electric_meter_id) self.assertEqual(self.state.next_id, electric_meter_id + 1) def test_add_duplicated_electric_meter(self): electric_meter = Mock() self.state.add_electric_meter(electric_meter) # Assertion # TODO Exception type self.assertRaises(Exception, self.state.add_electric_meter, electric_meter) def test_remove_electric_meter(self): meter_id = random.randint(10, 100) electric_meter = Mock() electric_meter_dict = MagicMock() self.state.electric_meters[meter_id] = electric_meter self.state.electric_meters_dict[meter_id] = electric_meter_dict # Test self.state.remove_electric_meter(meter_id) # Assertion self.state_file_callback.assert_called_with('w') self.assertNotIn((meter_id, electric_meter), self.state.electric_meters.items()) self.assertNotIn((meter_id, electric_meter_dict), self.state.electric_meters_dict.items()) def test_remove_non_existent_electric_meter(self): meter_id = random.randint(10, 100) # Assertion # TODO Exception type self.assertRaises(Exception, self.state.remove_electric_meter, meter_id)
def test_change_invalid_custom_change_electric_meter(self): # Init meter_id = 10 name = 'Electric Meter not to be changed' custom_value = 11111 custom = {'num': custom_value} serialized_electric_meter = { 'id': meter_id, 'name': name, 'type': self.plugin_type, 'custom': { 'custom_data': custom_value } } state_file_dict = { 'next_id': 11, 'electric_meters': [serialized_electric_meter] } self.state_file = FileLikeMock(json.dumps(state_file_dict)) self.logic.state = State(self.state_file_callback) self.logic.state.next_id = meter_id + 1 electric_meter = self.deserialize_electric_meter( serialized_electric_meter) self.logic.state.electric_meters = {meter_id: electric_meter} self.logic.state.electric_meters_dict = { meter_id: serialized_electric_meter } database_dict = { 'data_per_hour': self.data_per_hour, 'keep_raw': self.keep_raw, 'keep_day': self.keep_day, 'keep_month': self.keep_month, 'keep_year': self.keep_year, 'keep_years': self.keep_years, 'data_sources': [{ 'id': meter_id, 'data': { 'day_counter': 0, 'month_counter': 0, 'year_counter': 0, 'years_counter': 0, 'day_sum': 0, 'month_sum': 0, 'year_sum': 0, 'years_sum': 0, 'raw_data': [], 'day_data': [], 'month_data': [], 'year_data': [], 'years_data': [] } }] } self.db_file = FileLikeMock(json.dumps(database_dict)) self.logic.database = Database.load_database( self.database_file_callback) # Test self.assertRaises(InvalidElectricMeterChangeException, self.logic.change_electric_meter, meter_id, name=name, custom={'num': -1}) # Assert # Assert state file self.logic.state.save_state( ) # Trigger save of state to ensure changes are flushed to state_file self.assertEqual(state_file_dict, json.loads(self.state_file.getvalue())) # Assert Electric Meter equality self.assertEqual(electric_meter.meter_type, self.plugin_type) self.assertEqual(electric_meter.name, name) self.assertEqual(electric_meter.custom_data, custom_value) # Assert Database self.logic.database._save_database() self.assertEqual(database_dict, json.loads(self.db_file.getvalue()))
def test_change_electric_meter(self): # Init meter_id = 10 changed_name = 'Changed name' changed_custom_value = 123 serialized_electric_meter = { 'id': meter_id, 'name': 'Electric Meter to be deleted', 'type': self.plugin_type, 'custom': { 'custom_data': 11111 } } self.state_file = FileLikeMock( json.dumps({ 'next_id': 11, 'electric_meters': [serialized_electric_meter] })) self.logic.state = State(self.state_file_callback) self.logic.state.next_id = meter_id + 1 electric_meter = self.deserialize_electric_meter( serialized_electric_meter) electric_meter.set_serialize_hook(self.logic._call_serialize_hook) self.logic.state.electric_meters = {meter_id: electric_meter} self.logic.state.electric_meters_dict = { meter_id: serialized_electric_meter } database_dict = { 'data_per_hour': self.data_per_hour, 'keep_raw': self.keep_raw, 'keep_day': self.keep_day, 'keep_month': self.keep_month, 'keep_year': self.keep_year, 'keep_years': self.keep_years, 'data_sources': [{ 'id': meter_id, 'data': { 'day_counter': 0, 'month_counter': 0, 'year_counter': 0, 'years_counter': 0, 'day_sum': 0, 'month_sum': 0, 'year_sum': 0, 'years_sum': 0, 'raw_data': [], 'day_data': [], 'month_data': [], 'year_data': [], 'years_data': [] } }] } self.db_file = FileLikeMock(value=json.dumps(database_dict)) self.logic.database = Database.load_database( self.database_file_callback) # Test changed = self.logic.change_electric_meter( meter_id, name=changed_name, custom={'num': changed_custom_value}) # Assert self.assertTrue(changed) # Assert state file self.logic.state.save_state( ) # Trigger save of state to ensure changes are flushed to state_file self.assertEqual( { 'next_id': 11, 'electric_meters': [{ 'id': meter_id, 'name': 'Changed name', 'type': self.plugin_type, 'custom': { 'custom_data': 123 } }] }, json.loads(self.state_file.getvalue())) # Assert Electric Meter changed self.assertEqual(electric_meter.meter_type, self.plugin_type) self.assertEqual(electric_meter.name, changed_name) self.assertEqual(electric_meter.custom_data, changed_custom_value) # Assert Database not changed self.logic.database._save_database() self.assertEqual(database_dict, json.loads(self.db_file.getvalue()))
def test_remove_electric_meter(self): # Init meter_id = 10 serialized_electric_meter = { 'id': meter_id, 'name': 'Electric Meter to be deleted', 'type': self.plugin_type, 'custom': { 'custom_data': 11111 } } self.state_file = FileLikeMock( json.dumps({ 'next_id': 11, 'electric_meters': [serialized_electric_meter] })) self.logic.state = State(self.state_file_callback) self.logic.state.next_id = meter_id + 1 electric_meter = self.deserialize_electric_meter( serialized_electric_meter) self.logic.state.electric_meters = {meter_id: electric_meter} self.logic.state.electric_meters_dict = { meter_id: serialized_electric_meter } self.db_file = FileLikeMock(value=json.dumps({ 'data_per_hour': self.data_per_hour, 'keep_raw': self.keep_raw, 'keep_day': self.keep_day, 'keep_month': self.keep_month, 'keep_year': self.keep_year, 'keep_years': self.keep_years, 'data_sources': [{ 'id': meter_id, 'data': { 'day_counter': 0, 'month_counter': 0, 'year_counter': 0, 'years_counter': 0, 'day_sum': 0, 'month_sum': 0, 'year_sum': 0, 'years_sum': 0, 'raw_data': [], 'day_data': [], 'month_data': [], 'year_data': [], 'years_data': [] } }] })) self.logic.database = Database.load_database( self.database_file_callback) # Test removed_meter = self.logic.remove_electric_meter(meter_id) # Assert self.assertEqual(removed_meter, serialized_electric_meter) self.assertNotIn(electric_meter, self.state.electric_meters.values()) self.assertEqual(0, len(self.state.electric_meters_dict.values())) self.assertEqual({ 'next_id': 11, 'electric_meters': [] }, json.loads(self.state_file.getvalue())) self.assertEqual(0, len(self.database.datasources)) self.assertEqual( { 'data_per_hour': self.data_per_hour, 'keep_raw': self.keep_raw, 'keep_day': self.keep_day, 'keep_month': self.keep_month, 'keep_year': self.keep_year, 'keep_years': self.keep_years, 'data_sources': [] }, json.loads(self.db_file.getvalue()))