def test_detector_set_chip_enable_length_mistmatch(self): detector = ExcaliburDetector(self.detector_fems) chip_enable_mask = [0xff, 0x3f] with assert_raises_regexp(ExcaliburDetectorError, 'Mismatch in length of asic enable mask'): detector.set_chip_enable_mask(chip_enable_mask)
def __init__(self, **kwargs): """Initialise the ExcaliburAdapter object. :param kwargs: keyword arguments passed to ApiAdapter as options. """ # Initialise the ApiAdapter base class to store adapter options super(ExcaliburAdapter, self).__init__(**kwargs) # Compile the regular expression used to resolve paths into actions and resources self.path_regexp = re.compile('(.*?)/(.*)') # Parse the FEM connection information out of the adapter options and initialise the # detector object self.detector = None if 'detector_fems' in self.options: fems = [ tuple(fem.strip().split(':')) for fem in self.options['detector_fems'].split(',') ] try: self.detector = ExcaliburDetector(fems) logging.debug('ExcaliburAdapter loaded') if 'powercard_fem_idx' in self.options: try: powercard_fem_idx = int( self.options['powercard_fem_idx']) except Exception as e: logging.error( 'Failed to parse powercard FEM index from options: {}' .format(e)) else: logging.debug('Setting power card FEM index to %d', int(self.options['powercard_fem_idx'])) self.detector.set_powercard_fem_idx(powercard_fem_idx) if 'chip_enable_mask' in self.options: try: chip_enable_mask = [ int(mask, 0) for mask in self.options['chip_enable_mask'].split(',') ] except ValueError as e: logging.error( "Failed to parse chip enable mask from options: {}" .format(e)) else: logging.debug( "Setting chip enable mask for FEMS: {}".format( ', '.join( [hex(mask) for mask in chip_enable_mask]))) self.detector.set_chip_enable_mask(chip_enable_mask) except ExcaliburDetectorError as e: logging.error( 'ExcaliburAdapter failed to initialise detector: %s', e) else: logging.warning( 'No detector FEM option specified in configuration')
def test_detector_bad_fem_spec(self): with assert_raises_regexp(ExcaliburDetectorError, "Failed to initialise detector FEM list"): detector = ExcaliburDetector([1, 2, 3]) with assert_raises_regexp(ExcaliburDetectorError, "Failed to initialise detector FEM list"): detector = ExcaliburDetector('nonsense')
def test_detector_bad_powercard_idx(self): detector = ExcaliburDetector(self.detector_fems) powercard_idx = 4 with assert_raises_regexp( ExcaliburDetectorError, "Illegal FEM index {} specified for power card".format( powercard_idx)): detector.set_powercard_fem_idx(powercard_idx)
def test_detector_bad_fem_port(self): bad_detector_fems = self.detector_fems[:] bad_detector_fems[0] = ('192.168.0.1', 'bad_port', '10.0.2.1') with assert_raises_regexp(ExcaliburDetectorError, "Failed to initialise detector FEM list"): detector = ExcaliburDetector(bad_detector_fems)
def setup_class(cls): ExcaliburFem.use_stub_api = True cls.detector_fems = [('192.168.0.1', 6969, '10.0.2.1'), ('192.168.0.2', 6969, '10.0.2.1'), ('192.168.0.3', 6969, '10.0.2.1')] cls.detector = ExcaliburDetector(cls.detector_fems) root_logger = logging.getLogger() root_logger.setLevel(logging.DEBUG)
class ExcaliburAdapter(ApiAdapter): """ExcaliburAdapter class. This class provides the adapter interface between the ODIN server and the EXCALIBUR detector system, transforming the REST-like API HTTP verbs into the appropriate EXCALIBUR detector control actions """ def __init__(self, **kwargs): """Initialise the ExcaliburAdapter object. :param kwargs: keyword arguments passed to ApiAdapter as options. """ # Initialise the ApiAdapter base class to store adapter options super(ExcaliburAdapter, self).__init__(**kwargs) # Compile the regular expression used to resolve paths into actions and resources self.path_regexp = re.compile('(.*?)/(.*)') # Parse the FEM connection information out of the adapter options and initialise the # detector object self.detector = None if 'detector_fems' in self.options: fems = [ tuple(fem.strip().split(':')) for fem in self.options['detector_fems'].split(',') ] try: self.detector = ExcaliburDetector(fems) logging.debug('ExcaliburAdapter loaded') if 'powercard_fem_idx' in self.options: try: powercard_fem_idx = int( self.options['powercard_fem_idx']) except Exception as e: logging.error( 'Failed to parse powercard FEM index from options: {}' .format(e)) else: logging.debug('Setting power card FEM index to %d', int(self.options['powercard_fem_idx'])) self.detector.set_powercard_fem_idx(powercard_fem_idx) if 'chip_enable_mask' in self.options: try: chip_enable_mask = [ int(mask, 0) for mask in self.options['chip_enable_mask'].split(',') ] except ValueError as e: logging.error( "Failed to parse chip enable mask from options: {}" .format(e)) else: logging.debug( "Setting chip enable mask for FEMS: {}".format( ', '.join( [hex(mask) for mask in chip_enable_mask]))) self.detector.set_chip_enable_mask(chip_enable_mask) except ExcaliburDetectorError as e: logging.error( 'ExcaliburAdapter failed to initialise detector: %s', e) else: logging.warning( 'No detector FEM option specified in configuration') @request_types('application/json') @response_types('application/json', default='application/json') @require_valid_detector def get(self, path, request): """Handle an HTTP GET request. This method is the implementation of the HTTP GET handler for ExcaliburAdapter. :param path: URI path of the GET request :param request: Tornado HTTP request object :return: ApiAdapterResponse object to be returned to the client """ try: response = self.detector.get(path) status_code = 200 except ExcaliburDetectorError as e: response = {'error': str(e)} logging.error(e) status_code = 400 return ApiAdapterResponse(response, status_code=status_code) @request_types('application/json') @response_types('application/json', default='application/json') @require_valid_detector def put(self, path, request): """Handle an HTTP PUT request. This method is the implementation of the HTTP PUT handler for ExcaliburAdapter/ :param path: URI path of the PUT request :param request: Tornado HTTP request object :return: ApiAdapterResponse object to be returned to the client """ try: data = json_decode(request.body) self.detector.set(path, data) response = self.detector.get(path) status_code = 200 except ExcaliburDetectorError as e: response = {'error': str(e)} status_code = 400 logging.error(e) except (TypeError, ValueError) as e: response = { 'error': 'Failed to decode PUT request body: {}'.format(str(e)) } logging.error(e) status_code = 400 return ApiAdapterResponse(response, status_code=status_code) @request_types('application/json') @response_types('application/json', default='application/json') @require_valid_detector def delete(self, path, request): """Handle an HTTP DELETE request. This method is the implementation of the HTTP DELETE verb for ExcaliburAdapter. :param path: URI path of the DELETE request :param request: Tornado HTTP request object :return: ApiAdapterResponse object to be returned to the client """ response = { 'response': '{}: DELETE on path {}'.format(self.name, path) } status_code = 200 logging.debug(response) return ApiAdapterResponse(response, status_code=status_code)
def test_detector_set_chip_enable_mask_single(self): detector = ExcaliburDetector(('192.168.0.1', 6969, '10.0.2.1')) chip_enable_mask = 0xff detector.set_chip_enable_mask(chip_enable_mask) assert_equal([chip_enable_mask], detector.chip_enable_mask)
def test_detector_set_chip_enable_mask(self): detector = ExcaliburDetector(self.detector_fems) chip_enable_mask = [0xff, 0x3f, 0x7f] detector.set_chip_enable_mask(chip_enable_mask) assert_equal(chip_enable_mask, detector.chip_enable_mask)
def test_detector_powercard_idx(self): detector = ExcaliburDetector(self.detector_fems) powercard_idx = 1 detector.set_powercard_fem_idx(powercard_idx) assert_equal(detector.powercard_fem_idx, powercard_idx)
def test_detector_single_fem(self): detector = ExcaliburDetector(self.detector_fems[0]) assert_equal(len(detector.fems), 1)
def test_detector_connect_fems(self): detector = ExcaliburDetector(self.detector_fems) detector.connect()