def test_read_one_bank_two_addresses(self): """ Test read from one bank with two addresses. """ def read(_data): """ Read dummy """ if _data['bank'] == 1: return { 'data': bytearray(b'abc') + bytearray([255] * 200) + bytearray(b'def') + bytearray([255] * 48) } else: raise Exception('Wrong page') SetUpTestInjections(master_communicator=MasterCommunicator(read)) eeprom_file = EepromFile() address1 = EepromAddress(1, 2, 10) address2 = EepromAddress(1, 203, 4) data = eeprom_file.read([address1, address2]) self.assertEqual(2, len(data)) self.assertEqual(address1, data[address1].address) self.assertEqual( bytearray(b'c') + bytearray([255] * 9), data[address1].bytes) self.assertEqual(address2, data[address2].address) self.assertEqual(bytearray(b'def\xff'), data[address2].bytes)
def test_cache_invalidate(self): """ Test the cache invalidation. """ state = {'count': 0} def read(_): """ Read dummy. """ if state['count'] == 0: state['count'] = 1 return {'data': bytearray([255] * 256)} elif state['count'] == 1: state['count'] = 2 return {'data': bytearray([255] * 256)} else: raise Exception('Too many reads !') SetUpTestInjections(master_communicator=MasterCommunicator(read)) eeprom_file = EepromFile() address = EepromAddress(1, 0, 256) read = eeprom_file.read([address]) self.assertEqual(bytearray([255] * 256), read[address].bytes) # Second read should come from cache. address = EepromAddress(1, 0, 256) read = eeprom_file.read([address]) self.assertEqual(bytearray([255] * 256), read[address].bytes) eeprom_file.invalidate_cache() # Should be read from communicator, since cache is invalid address = EepromAddress(1, 0, 256) read = eeprom_file.read([address]) self.assertEqual(bytearray([255] * 256), read[address].bytes) self.assertEqual(2, state['count'])
def test_read_multiple_banks(self): """ Test read from multiple banks. """ def read(_data): """ Read dummy. """ if _data['bank'] == 1: return {'data': bytearray(b'abc') + bytearray([255] * 200) + bytearray(b'def') + bytearray([255] * 48)} if _data['bank'] == 100: return {'data': bytearray(b'hello') + bytearray([0] * 100) + bytearray(b'world') + bytearray([0] * 146)} else: raise Exception('Wrong page') SetUpTestInjections(master_communicator=MasterCommunicator(read)) eeprom_file = EepromFile() address1 = EepromAddress(1, 2, 10) address2 = EepromAddress(100, 4, 10) address3 = EepromAddress(100, 105, 5) data = eeprom_file.read([address1, address2, address3]) self.assertEqual(3, len(data)) self.assertEqual(address1, data[address1].address) self.assertEqual(bytearray(b'c') + bytearray([255] * 9), data[address1].bytes) self.assertEqual(address2, data[address2].address) self.assertEqual(bytearray(b'o') + bytearray([0] * 9), data[address2].bytes) self.assertEqual(address3, data[address3].address) self.assertEqual(bytearray(b'world'), data[address3].bytes)
def get_module_addresses(module_type): # type: (str) -> List[str] """ Get the addresses for the modules of the given type. :param module_type: the type of the module (O, R, D, I, T, C) :returns: A list containing the addresses of the modules (strings of length 4). """ eeprom_file = EepromFile() base_address = EepromAddress(0, 1, 2) no_modules = eeprom_file.read([base_address]) modules = [] no_input_modules = no_modules[base_address].bytes[0] for i in range(no_input_modules): address = EepromAddress(2 + i, 252, 1) is_can = chr(eeprom_file.read([address])[address].bytes[0]) == 'C' address = EepromAddress(2 + i, 0, 4) module = eeprom_file.read([address])[address].bytes if not is_can or chr(module[0]) == 'C': modules.append(module) no_output_modules = no_modules[base_address].bytes[1] for i in range(no_output_modules): address = EepromAddress(33 + i, 0, 4) modules.append(eeprom_file.read([address])[address].bytes) return [module for module in modules if chr(module[0]) == module_type]
def test_write_multiple_fields(self): """ Test writing multiple fields to the eeprom file. """ done = {} def read(data): """ Read dummy. """ if data['bank'] == 1: done['read1'] = True return {'data': bytearray([255] * 256)} elif data['bank'] == 2: done['read2'] = True return {'data': bytearray([0] * 256)} else: raise Exception('Wrong page') def write(data): """ Write dummy. """ if 'write1' not in done: done['write1'] = True self.assertEqual(1, data['bank']) self.assertEqual(2, data['address']) self.assertEqual(bytearray(b'abc'), data['data']) elif 'write2' not in done: done['write2'] = True self.assertEqual(2, data['bank']) self.assertEqual(123, data['address']) self.assertEqual(bytearray(b'More bytes'), data['data']) elif 'write3' not in done: done['write3'] = True self.assertEqual(2, data['bank']) self.assertEqual(133, data['address']) self.assertEqual(bytearray(b' than 10'), data['data']) else: raise Exception('Too many writes') SetUpTestInjections( master_communicator=MasterCommunicator(read, write)) eeprom_file = EepromFile() eeprom_file.write([ EepromData(EepromAddress(1, 2, 3), bytearray(b'abc')), EepromData(EepromAddress(2, 123, 18), bytearray(b'More bytes than 10')) ]) self.assertTrue('read1' in done) self.assertTrue('read2' in done) self.assertTrue('write1' in done) self.assertTrue('write2' in done) self.assertTrue('write3' in done)
def test_write_single_field(self): """ Write a single field to the eeprom file. """ done = {} def read(data): """ Read dummy. """ if data['bank'] == 1: done['read1'] = True return {'data': bytearray([255] * 256)} else: raise Exception('Wrong page') def write(data): """ Write dummy. """ self.assertEqual(1, data['bank']) self.assertEqual(2, data['address']) self.assertEqual(bytearray(b'abc'), data['data']) done['write'] = True SetUpTestInjections(master_communicator=MasterCommunicator(read, write)) eeprom_file = EepromFile() eeprom_file.write([EepromData(EepromAddress(1, 2, 3), bytearray(b'abc'))]) self.assertTrue('read1' in done) self.assertTrue('write' in done)
def test_write_end_of_page(self): """ Test writing an address that is close (< BATCH_SIZE) to the end of the page. """ done = {} def read(_): """ Read dummy. """ return {'data': bytearray([0] * 256)} def write(data): """ Write dummy. """ self.assertEqual(117, data['bank']) self.assertEqual(248, data['address']) self.assertEqual( bytearray(b'test') + bytearray([255] * 4), data['data']) done['done'] = True SetUpTestInjections( master_communicator=MasterCommunicator(read, write)) eeprom_file = EepromFile() eeprom_file.write([ EepromData(EepromAddress(117, 248, 8), bytearray(b'test') + bytearray([255] * 4)) ]) self.assertTrue(done['done'])
class OutputConfiguration(EepromModel): """ Models an output. The maximum number of inputs is 240 (30 modules), the actual number of outputs is 8 times the number of output modules (eeprom address 0, 2). """ id = EepromId(240, address=EepromAddress(0, 2, 1), multiplier=8) module_type = EepromString(1, lambda mid: (33 + mid / 8, 0), read_only=True, shared=True) name = EepromString(16, page_per_module(8, 33, 20, 16)) timer = EepromWord(page_per_module(8, 33, 4, 2)) floor = EepromByte(page_per_module(8, 33, 157, 1)) type = EepromByte(page_per_module(8, 33, 149, 1)) lock_bit_id = EepromByte(lambda mid: (231, mid)) can_led_1_id = EepromByte(gen_address(221, 32, 0)) can_led_1_function = EepromEnum(gen_address(221, 32, 1), get_led_functions()) can_led_2_id = EepromByte(gen_address(221, 32, 2)) can_led_2_function = EepromEnum(gen_address(221, 32, 3), get_led_functions()) can_led_3_id = EepromByte(gen_address(221, 32, 4)) can_led_3_function = EepromEnum(gen_address(221, 32, 5), get_led_functions()) can_led_4_id = EepromByte(gen_address(221, 32, 6)) can_led_4_function = EepromEnum(gen_address(221, 32, 7), get_led_functions())
def test_cache_write(self): """ Test the eeprom cache on writing. """ state = {'read': 0, 'write': 0} def read(_): """ Read dummy. """ if state['read'] == 0: state['read'] = 1 return {'data': bytearray([255] * 256)} else: raise Exception('Too many reads !') def write(data): """ Write dummy. """ if state['write'] == 0: self.assertEqual(1, data['bank']) self.assertEqual(100, data['address']) self.assertEqual(bytearray([0] * 10), data['data']) state['write'] = 1 elif state['write'] == 1: self.assertEqual(1, data['bank']) self.assertEqual(110, data['address']) self.assertEqual(bytearray([0] * 10), data['data']) state['write'] = 2 else: raise Exception('Too many writes !') SetUpTestInjections( master_communicator=MasterCommunicator(read, write)) eeprom_file = EepromFile() address = EepromAddress(1, 0, 256) read = eeprom_file.read([address]) self.assertEqual(bytearray([255] * 256), read[address].bytes) eeprom_file.write( [EepromData(EepromAddress(1, 100, 20), bytearray([0] * 20))]) address = EepromAddress(1, 0, 256) read = eeprom_file.read([address]) self.assertEqual(bytearray([255] * 100 + [0] * 20 + [255] * 136), read[address].bytes) self.assertEqual(1, state['read']) self.assertEqual(2, state['write'])
def test_cache_write_exception(self): """ The cache should be invalidated if a write fails. """ state = {'read': 0, 'write': 0} def read(_): """ Read dummy. """ if state['read'] == 0: state['read'] = 1 return {'data': bytearray([255] * 256)} elif state['read'] == 1: state['read'] = 2 return {'data': bytearray([255] * 256)} else: raise Exception('Too many reads !') def write(_): """ Write dummy. """ state['write'] += 1 raise Exception('write fails...') SetUpTestInjections( master_communicator=MasterCommunicator(read, write)) eeprom_file = EepromFile() address = EepromAddress(1, 0, 256) read = eeprom_file.read([address]) self.assertEqual(bytearray([255] * 256), read[address].bytes) try: eeprom_file.write( [EepromData(EepromAddress(1, 100, 20), bytearray([0] * 20))]) self.fail('Should not get here !') except Exception: pass address = EepromAddress(1, 0, 256) read = eeprom_file.read([address]) self.assertEqual(bytearray([255] * 256), read[address].bytes) self.assertEqual(2, state['read']) self.assertEqual(1, state['write'])
class ShutterConfiguration(EepromModel): """ Models a shutter. The maximum number of shutters is 120 (30 modules), the actual number of shutters is 4 times the number of shutter modules (eeprom address 0, 3). """ id = EepromId(120, address=EepromAddress(0, 3, 1), multiplier=4) timer_up = EepromByte(page_per_module(4, 33, 177, 2)) timer_down = EepromByte(page_per_module(4, 33, 178, 2)) up_down_config = EepromByte(page_per_module(4, 33, 185, 1)) name = EepromString(16, page_per_module(4, 33, 189, 16)) group_1 = EepromByte(lambda mid: (63, (mid * 2) + 0)) group_2 = EepromByte(lambda mid: (63, (mid * 2) + 1)) steps = EextWord()
def test_cache(self): """ Test the caching of banks. """ state = {'count': 0} def read(_): """ Read dummy. """ if state['count'] == 0: state['count'] = 1 return {'data': bytearray([255] * 256)} else: raise Exception('Too many reads !') SetUpTestInjections(master_communicator=MasterCommunicator(read)) eeprom_file = EepromFile() address = EepromAddress(1, 0, 256) read = eeprom_file.read([address]) self.assertEqual(bytearray([255] * 256), read[address].bytes) # Second read should come from cache, if read is called # an exception will be thrown. address = EepromAddress(1, 0, 256) read = eeprom_file.read([address]) self.assertEqual(bytearray([255] * 256), read[address].bytes)
def test_read_one_bank_one_address(self): """ Test read from one bank with one address """ def read(_data): """ Read dummy. """ if _data['bank'] == 1: return {'data': bytearray(b'abc') + bytearray([255] * 200) + bytearray(b'def') + bytearray([255] * 48)} else: raise Exception('Wrong page') SetUpTestInjections(master_communicator=MasterCommunicator(read)) eeprom_file = EepromFile() address = EepromAddress(1, 0, 3) data = eeprom_file.read([address]) self.assertEqual(1, len(data)) self.assertEqual(address, data[address].address) self.assertEqual(bytearray(b'abc'), data[address].bytes)
class InputConfiguration(EepromModel): """ Models an input. The maximum number of inputs is 240 (30 modules), the actual number of inputs is 8 times the number of input modules (eeprom address 0, 1). """ id = EepromId(240, address=EepromAddress(0, 1, 1), multiplier=8) module_type = EepromString(1, lambda mid: (2 + mid / 8, 0), read_only=True, shared=True) name = EepromString( 8, per_module( 8, lambda mid, iid: (115 + (mid / 4), 64 * (mid % 4) + 8 * iid))) action = EepromByte(page_per_module(8, 2, 4, 1)) basic_actions = EepromActions(15, page_per_module(8, 2, 12, 30)) invert = EepromByte(lambda mid: (32, mid)) can = EepromString(1, lambda mid: (2 + mid / 8, 252), read_only=True, shared=True)
class Model4(EepromModel): """ Dummy model with a dynamic maximum id. """ id = EepromId(10, address=EepromAddress(0, 0, 1), multiplier=2) name = EepromString(10, lambda id: (1, 2 + id * 10))