def test_remove_accents_from_name(self): # Arrange # list of names in unicode code points, which is the same as ISO-8859-1 encoding names_uni = [ u'Somebody', u'S\xf8rina', u'\xe9\xe5\xf5\xf6\xc6' ] # best ascii equivalents of names names_ascii = [ 'Somebody', 'Sorina', 'eaooAE' ] # Act conv_names = ExpData.make_name_list_ascii(names_uni).split(',') # Assert self.assertTrue(conv_names == names_ascii)
def __init__(self, ca_server, dbid, options_folder, test_mode=False): """Constructor. Args: ca_server (CAServer): The CA server used for generating PVs on the fly dbid (string): The id of the database that holds IOC information. options_folder (string): The location of the folder containing the config.xml file that holds IOC options """ if test_mode: ps = MockProcServWrapper() else: super(DatabaseServer, self).__init__() ps = ProcServWrapper() self._ca_server = ca_server self._options_holder = OptionsHolder(options_folder, OptionsLoader()) # Initialise database connection try: self._db = IOCData(dbid, ps, MACROS["$(MYPVPREFIX)"]) print_and_log("Connected to database", "INFO", "DBSVR") except Exception as err: self._db = None print_and_log("Problem initialising DB connection: %s" % err, "MAJOR", "DBSVR") # Initialise experimental database connection try: self._ed = ExpData(MACROS["$(MYPVPREFIX)"]) print_and_log("Connected to experimental details database", "INFO", "DBSVR") except Exception as err: self._ed = None print_and_log("Problem connecting to experimental details database: %s" % err, "MAJOR", "DBSVR") if self._db is not None and not test_mode: # Start a background thread for keeping track of running IOCs self.monitor_lock = RLock() monitor_thread = Thread(target=self.update_ioc_monitors, args=()) monitor_thread.daemon = True # Daemonise thread monitor_thread.start()
def setUp(self): self.ca = MockChannelAccess() self.exp_data = ExpData("TEST_PREFIX", self.ca)
class TestExpData(unittest.TestCase): def setUp(self): self.ca = MockChannelAccess() self.exp_data = ExpData("TEST_PREFIX", self.ca) def decodepv(self, pv): return json.loads(dehex_and_decompress(self.ca.caget(pv))) def test_single_surname_returns_surname(self): # Arrange fullname = "Tom Jones" # Act surname = self.exp_data._get_surname_from_fullname(fullname) # Assert self.assertEquals(surname, "Jones") def test_double_barrelled_surname_returns_last_name(self): # Arrange fullname = "Tom de Jones" # Act surname = self.exp_data._get_surname_from_fullname(fullname) # Assert self.assertEquals(surname, "Jones") def test_single_name_returns_fullname(self): # Arrange fullname = "TomJones" # Act surname = self.exp_data._get_surname_from_fullname(fullname) # Assert self.assertEquals(surname, "TomJones") def test_update_username_for_single_user(self): # Arrange users = '[{"name":"Tom Jones","institute":"STFC","role":"user"}]' # Act self.exp_data.updateUsername(users) # Assert simnames = self.decodepv(self.exp_data._simnames) surnames = self.decodepv(self.exp_data._surnamepv) orgs = self.decodepv(self.exp_data._orgspv) self.assertEqual(simnames[0]["name"], "Tom Jones") self.assertTrue("Jones" in surnames) self.assertTrue("STFC" in orgs) def test_update_username_for_multiple_users_same_institute(self): # Arrange users = '[' users += '{"name":"Tom Jones","institute":"STFC","role":"user"},' users += '{"name":"David James","institute":"STFC","role":"user"}' users += ']' # Act self.exp_data.updateUsername(users) # Assert simnames = self.decodepv(self.exp_data._simnames) surnames = self.decodepv(self.exp_data._surnamepv) orgs = self.decodepv(self.exp_data._orgspv) self.assertEqual(len(simnames), 2) self.assertEqual(len(surnames), 2) self.assertEqual(len(orgs), 1) def test_update_username_for_blank_users(self): # Arrange users = '[{"name":"Tom Jones","institute":"STFC","role":"user"}]' self.exp_data.updateUsername(users) # Act self.exp_data.updateUsername("") # Assert simnames = self.decodepv(self.exp_data._simnames) surnames = self.decodepv(self.exp_data._surnamepv) orgs = self.decodepv(self.exp_data._orgspv) self.assertEqual(len(simnames), 0) self.assertEqual(len(surnames), 0) self.assertEqual(len(orgs), 0) def test_remove_accents_from_name(self): # Arrange # list of names in unicode code points, which is the same as ISO-8859-1 encoding names_uni = [ u'Somebody', u'S\xf8rina', u'\xe9\xe5\xf5\xf6\xc6' ] # best ascii equivalents of names names_ascii = [ 'Somebody', 'Sorina', 'eaooAE' ] # Act conv_names = ExpData.make_name_list_ascii(names_uni).split(',') # Assert self.assertTrue(conv_names == names_ascii)
class DatabaseServer(Driver): """The class for handling all the static PV access and monitors etc. """ def __init__(self, ca_server, dbid, options_folder, test_mode=False): """Constructor. Args: ca_server (CAServer): The CA server used for generating PVs on the fly dbid (string): The id of the database that holds IOC information. options_folder (string): The location of the folder containing the config.xml file that holds IOC options """ if test_mode: ps = MockProcServWrapper() else: super(DatabaseServer, self).__init__() ps = ProcServWrapper() self._ca_server = ca_server self._options_holder = OptionsHolder(options_folder, OptionsLoader()) # Initialise database connection try: self._db = IOCData(dbid, ps, MACROS["$(MYPVPREFIX)"]) print_and_log("Connected to database", "INFO", "DBSVR") except Exception as err: self._db = None print_and_log("Problem initialising DB connection: %s" % err, "MAJOR", "DBSVR") # Initialise experimental database connection try: self._ed = ExpData(MACROS["$(MYPVPREFIX)"]) print_and_log("Connected to experimental details database", "INFO", "DBSVR") except Exception as err: self._ed = None print_and_log("Problem connecting to experimental details database: %s" % err, "MAJOR", "DBSVR") if self._db is not None and not test_mode: # Start a background thread for keeping track of running IOCs self.monitor_lock = RLock() monitor_thread = Thread(target=self.update_ioc_monitors, args=()) monitor_thread.daemon = True # Daemonise thread monitor_thread.start() def read(self, reason): """A method called by SimpleServer when a PV is read from the DatabaseServer over Channel Access. Args: reason (string): The PV that is being requested (without the PV prefix) Returns: string : A compressed and hexed JSON formatted string that gives the desired information based on reason. """ if reason == 'SAMPLE_PARS': value = self.encode4return(self.get_sample_par_names()) elif reason == 'BEAMLINE_PARS': value = self.encode4return(self.get_beamline_par_names()) elif reason == 'USER_PARS': value = self.encode4return(self.get_user_par_names()) elif reason == "IOCS_NOT_TO_STOP": value = self.encode4return(IOCS_NOT_TO_STOP) else: value = self.getParam(reason) return value def write(self, reason, value): """A method called by SimpleServer when a PV is written to the DatabaseServer over Channel Access. Args: reason (string): The PV that is being requested (without the PV prefix) value (string): The data being written to the 'reason' PV Returns: bool : True """ status = True try: if reason == 'ED:RBNUMBER:SP': #print_and_log("Updating to use experiment ID: " + value, "INFO", "DBSVR") self._ed.updateExperimentID(value) elif reason == 'ED:USERNAME:SP': self._ed.updateUsername(dehex_and_decompress(value)) except Exception as err: value = compress_and_hex(convert_to_json("Error: " + str(err))) print_and_log(str(err), "MAJOR") # store the values if status: self.setParam(reason, value) return status def update_ioc_monitors(self): """Updates all the PVs that hold information on the IOCS and their associated PVs """ while True: if self._db is not None: self._db.update_iocs_status() self.setParam("IOCS", self.encode4return(self._get_iocs_info())) self.setParam("PVS:ALL", self.encode4return(self._get_interesting_pvs(""))) self.setParam("PVS:ACTIVE", self.encode4return(self._get_active_pvs())) self.setParam("PVS:INTEREST:HIGH", self.encode4return(self._get_interesting_pvs("HIGH"))) self.setParam("PVS:INTEREST:MEDIUM", self.encode4return(self._get_interesting_pvs("MEDIUM"))) self.setParam("PVS:INTEREST:FACILITY", self.encode4return(self._get_interesting_pvs("FACILITY"))) # Update them with self.monitor_lock: self.updatePVs() sleep(1) def encode4return(self, data): """Converts data to JSON, compresses it and converts it to hex. Args: data (string): The data to encode Returns: string : The encoded data """ return compress_and_hex(json.dumps(data).encode('ascii', 'replace')) def _get_iocs_info(self): iocs = self._db.get_iocs() options = self._options_holder.get_config_options() for iocname in iocs.keys(): if iocname in options: iocs[iocname].update(options[iocname]) return iocs def _get_interesting_pvs(self, level, ioc=None): if self._db is not None: return self._db.get_interesting_pvs(level, ioc) else: return list() def _get_active_pvs(self): if self._db is not None: return self._db.get_active_pvs() else: return list() def get_sample_par_names(self): """Returns the sample parameters from the database, replacing the MYPVPREFIX macro Returns: list : A list of sample parameter names, an empty list if the database does not exist """ if self._db is not None: return [p.replace(MACROS["$(MYPVPREFIX)"], "") for p in self._db.get_sample_pars()] else: return list() def get_beamline_par_names(self): """Returns the beamline parameters from the database, replacing the MYPVPREFIX macro Returns: list : A list of beamline parameter names, an empty list if the database does not exist """ if self._db is not None: return [p.replace(MACROS["$(MYPVPREFIX)"], "") for p in self._db.get_beamline_pars()] else: return list() def get_user_par_names(self): """Returns the user parameters from the database, replacing the MYPVPREFIX macro Returns: list : A list of user parameter names, an empty list if the database does not exist """ if self._db is not None: return [p.replace(MACROS["$(MYPVPREFIX)"], "") for p in self._db.get_user_pars()] else: return list()