def instrumentar(self): """@brief Instrumenta el proyecto mediante dos subprocesos.""" # No queremos dos thread para hacer lo mismo if self.inst_thread is None or not self.inst_thread.isAlive(): self.inst = False # Comenzar la instrumentación self.inst_thread = Instrumentador(self) self.inst_thread.start()
class Proyecto(object): """@brief Clase Proyecto con todas las operaciones sobre un proyecto idiginBPEL. Realiza la creación de un nuevo proyecto, la comprobación, el guardado y la eliminación así como todas las otras operaciones que tengan relación con un proyecto. """ ## @name Nombres de ficheros por defecto ## @{ ## Nombre del bpel importado bpel_nom = "bpel_original.bpel" ## Nombre del fichero de configuración de proyecto proy_nom = "proyecto.xml" ## Nombre del ant a ejecutar para realizar las acciones build_nom = "build.xml" ## Nombre del fichero que reune los casos de prueba test_nom = "test.bpts" ## Nombre del fichero bpr generado por la instrumentación bpr_nom = "bpr_file.bpr" ## @} ## @name Directorios de Proyecto ## @{ ## Directorio con los casos de prueba casos_nom = "casos" ## Directorio 'almacén' con las trazas generadas por la ejecución trazas_nom = "trazas" ## Directorio con las trazas que se van a usar en el análisis trazas_anl_nom = "anl_trazas" ## Directorio con las trazas que se usarán en el análisis anltrazas_nom = "anltrazas" ## Directorio con los invariantes generados invr_nom = "invariantes" ## Directorio con las dependencias del bpel dep_nom = "dependencias" ## @} ## @name Url de Namespaces ## @{ bpel_url = "http://docs.oasis-open.org/wsbpel/2.0/process/executable" wsdl_url = "http://schemas.xmlsoap.org/wsdl/" xsd_url = "http://www.w3.org/2001/XMLSchema" test_url = "http://www.bpelunit.org/schema/testSuite" ## @} ## @name Configuración de conexión por defecto ## @{ ## Url del servidor Active Bpel svr = "localhost" ## Puerto del servidor Active Bpel port = "7777" ## @} ## @name Flags de estado y propiedades ## @{ ## Flag de instrumentado inst = False ## Flag de modificado el proyecto mod = False ## Flag de si hay casos de prueba incluidos hay_casos = False # @} ## @name Inicialización ## @{ def __init__(self, nombre, idg, bpel=""): """@brief Constructor de la clase proyecto. Establece los valores por defecto para las rutas del proyecto. Crea el proyecto si se le indica la ruta a un bpel Lee la configuración del proyecto ya creado si no Comprueba que el proyecto esté bien @param nombre Nombre del proyecto a cargar/crear. @param idg Instancia de la clase de control . @param bpel Ruta al bpel original. """ # Valores por defecto de proyecto ## Nombre del proyecto (se emplea en la ruta) self.nombre = nombre ## Instancia del control del proyecto self.idg = idg ## Instancia del control de opciones self.opts = idg.opt ## Ruta del bpel original (si está especificado) self.bpel_o = path.abspath(bpel) if bpel else "" # Variables internas, rutas, etc... self._set_vars() # Si se indica la ruta del bpel, debemos crear el proyecto # Si ya está creado, leemos su configuración if not bpel: self.cargar_proy() else: self.crear() self.guardar() self.idg.obtener_lista_proyectos() # Proyecto instrumentado o no self.inst = path.exists(self.bpr) # Comprueba que la estructura del proyecto está bien try: self.check() except (ProyectoRecuperable) as e: log.error(_("El proyecto se ha creado con errores: " + str(e))) ## @name Listas ## @{ ## Lista con los ficheros en el proyecto self.fichs = os.listdir(self.dir) ## Lista con los ficheros de casos de prueba (.bpts) self.fcasos = os.listdir(self.casos_dir) ## Lista con los ficheros de las trazas self.ftrazas = os.listdir(self.trazas_dir) ## Lista con los ficheros de invariantes self.finvr = os.listdir(self.invr_dir) ## @} # Número de casos self.hay_casos = len(self.casos) > 0 def _set_vars(self): """@brief Establece las variables internas del objeto""" idg = self.idg opt = self.opts # Urls generales de proyecto self.home = opt.get("home") self.share = opt.get("share") self.takuan = opt.get("takuan") self.bpelunit = opt.get("bpelunit") self.svr = opt.get("svr") self.port = opt.get("port") ## Directorio del proyecto self.dir = path.join(self.home, "proy", self.nombre) self.dir = path.abspath(self.dir) ## @name Rutas de Ficheros ## @{ ## Ruta al bpel importado, se emplea para ejecutar etc... self.bpel = path.join(self.dir, self.bpel_nom) # bpel ## Ruta al fichero de configuración del proyecto. self.proy = path.join(self.dir, self.proy_nom) # config proy ## Ruta al fichero ant para realizar las ejecuciones. self.build = path.join(self.dir, self.build_nom) # ant proy ## Ruta al fichero bpts que contiene los casos de prueba. self.test = path.join(self.dir, self.test_nom) # test.bpts ## Ruta al fichero bpr que se genera en la instrumentación. self.bpr = path.join(self.dir, self.bpr_nom) # instrument ## @} ## @name Rutas Directorios ## @{ ## Ruta al directorio que contiene los casos de prueba self.casos_dir = path.join(self.dir, self.casos_nom) # Casos ## Ruta al directorio que contiene todas las trazas self.trazas_dir = path.join(self.dir, self.trazas_nom) # Trazas ## Ruta al directorio que contiene las trazas a usar en el análisis self.trazas_anl_dir = path.join(self.dir, self.trazas_anl_nom) ## Ruta al directorio que contiene las trazas self.anltrazas_dir = path.join(self.dir, self.anltrazas_nom) # Trazas ## Ruta al directorio que contiene los invariantes self.invr_dir = path.join(self.dir, self.invr_nom) # Invariantes ## Ruta al directorio que contiene las dependencias self.dep_dir = path.join(self.dir, self.dep_nom) # Dependencias ## @} ## @name Listas ## @{ ## Lista con las rutas de las dependencias del bpel self.deps = [] ## Lista con las rutas de las dependencias no encontradas del bpel self.dep_miss = [] ## Lista con los casos de prueba disponibles "fichero:nom_caso" self.casos = {} ## @} ## @name Ejecución ## @{ ## Subproceso de la ejecución self.ejec_subproc = None ## Thread instrumentador self.inst_thread = None ## @} ## @name Analisis ## @{ ## Tipo de aplanado self.aplanado = "index-flattering" ## Simplify self.simplify = True ## Subproceso self.anl_subproc = None ## @} ## @} ## @name Tratar Bpel ## @{ def buscar_dependencias(self, bpel): """@brief Busca las dependencias de un bpel recursivamente. Copia el bpel y las dependencias al proyecto. Modifica el bpel y las dependencias para adaptarlos al proyecto \returns True si todo va bien, None si algo falla. Eleva excepciones ProyectoError. """ # Comprobar el bpel que nos pasan if not path.exists(bpel): log.error(_("El bpel no existe: ") + bpel) raise ProyectoError(_("Bpel no existe: ") + bpel) # Buscar las dependencias del bpel recursivamente ## Lista de rutas con las dependencias del bpel self.deps, self.dep_miss = self.__buscar_dependencias([bpel]) log.info( "%i dependencias encontradas, %i dependencias rotas, %i dependencias totales" % (len(self.deps), len(self.dep_miss), len(self.dep_miss) + len(self.deps)) ) return True def __buscar_dependencias(self, files, deps=set(), miss=set(), first=True): """@brief Busca las dependencias xsd y wsdl recursivamente en los ficheros y devuelve sus rutas completas. Copia las dependencias al proyecto y las modifica para adaptar los import a rutas relativas al proyecto. Añade las dependencias que no han podido ser obtenidas a dep_miss. @param files Lista con rutas a los ficheros en los que buscar @param first Flag para saber si estamos mirando el bpel original. @retval (deps,deps_miss) Listas con las rutas de las dependencias, encontradas y rotas. """ if first: deps = set() miss = set() # Caso de parada de la función if len(files) == 0: return [] local_deps = set() # Buscamos en todas las rutas de ficheros que recibamos for f in files: nom = path.basename(f) # Nombre del fichero dir = path.dirname(f) # Directorio del fichero proy = path.join(self.dep_dir, nom) # Ruta dentro del proyecto if path.exists(proy): # Si ya existe en el proyecto miss.discard(dir) # Quitamos de las dependencias rotas log.debug(_("Dependencia: ") + nom) # Abrimos el fichero, obtenemos uss imports, modificamos las rutas # y lo serializamos de nuevo pero dentro del proyecto. # Cargar fichero en memoria try: xml = md.parse(f) except: # Mostramos un error y añadimos # a las dependencias rotas log.error(_("Error al parsear ") + f) miss.add(f) continue # Buscar los imports en el fichero # empleando los distintos namespaces imps_l = xml.getElementsByTagName("import") imps_l += xml.getElementsByTagNameNS(self.bpel_url, "import") imps_l += xml.getElementsByTagNameNS(self.wsdl_url, "import") imps_l += xml.getElementsByTagNameNS(self.xsd_url, "import") imps = set(imps_l) # Modificar los import a rutas al mismo directorio # Obtener las rutas absolutas meterlas en deps for i in imps: attr = "location" if i.hasAttribute("location") else "schemaLocation" # Si no está el atributo por alguna razón, pasar de el. ruta = i.getAttribute(attr) if not ruta: continue # Ruta real de la dependencia encontrada dep = path.abspath(path.join(dir, ruta)) # Añadir la dependencia al conjunto local y total local_deps.add(dep) deps.add(dep) log.debug(nom + " --> " + path.basename(ruta)) # Los bpel (first) apuntan a dentro del directorio dependencias # El resto de dependencias, al mismo directorio en el que están. if first: ruta = path.join(self.dep_nom, path.basename(ruta)) else: ruta = path.basename(ruta) log.debug(ruta) # Modificar el atributo con la ruta correcta i.setAttribute(attr, ruta) # Copiar el fichero en el proyecto try: # Serializar el xml a un fichero en el directorio self.dep_dir # Con la ruta adecuada si es el bpel original. if first: file = open(self.bpel, "w") else: file = open(path.join(self.dep_dir, nom), "w") file.write(xml.toxml("utf-8")) except: # Si no se ha podido escribir la versión modificada del # fichero, añadirlo a las dependencias rotas log.error(_("Error al escribir en el proyecto: ") + nom) miss.add(ruta) finally: file.close() # fin del for # fin del for # Llamada recursiva, false porque ya no es la primera llamada. self.__buscar_dependencias(list(local_deps), deps, miss, False) # Si es la primera llamada, devolvemos todas las dependencias. if first: return list(deps), list(miss) # Si es una llamada normal, devolvemos los ficheros a mirar en # la siguiente iteración. else: return files ## @} ## @name Ejecuciones ## @{ def instrumentar(self): """@brief Instrumenta el proyecto mediante dos subprocesos.""" # No queremos dos thread para hacer lo mismo if self.inst_thread is None or not self.inst_thread.isAlive(): self.inst = False # Comenzar la instrumentación self.inst_thread = Instrumentador(self) self.inst_thread.start() def ejecutar(self): """@brief Ejecuta los casos de prueba del proyecto en el servidor ABpel. """ # No crear otro subproceso si ya se está ejecutando uno. if self.ejec_subproc is not None and self.ejec_subproc.poll() is None: log.warning(_("El proyecto ya se esta ejecutando")) return # Ruta logs bpelunit log.debug(self.bpelunit) BUpath = path.join(self.bpelunit, "process-logs") # Borrar los logs antiguos bpelunit try: self.borrar_trazas(BUpath) except: log.error( _( "No se han podido eliminar los logs antiguos de \ bpelunit: " + BUpath ) ) # Ejecutar el ant en un subproceso aparte cmd = ("ant", "-f", self.build, "test") log.info(_("Ejecutando tests: ") + str(cmd)) # Escribimos en una tubería desde la cual podremos leer el log # Sin expansión de argumentos por shell # El resultado va todo a stdout, el de stderr también. self.ejec_subproc = subproc.Popen(cmd, shell=False, stdout=subproc.PIPE, stderr=subproc.STDOUT) def comprobar_abpel(self): """@brief Comprueba el estado del servidor ActiveBpel. @returns True si está corriendo, False si no lo está, None si no se pudo conectar. """ # Abrir la url del servidor en el puerto predeterminado de tomcat url = "http://%s:%s/BpelAdmin/home.jsp" % (self.svr, "8080") # Realizar la conexión try: f = urllib.urlopen(url) log.info(_("Comprobando servidor ActiveBPEL en: ") + url) except IOError: log.error(_("No se pudo realizar la conexión con ActiveBPEL en: ") + url) else: # Comprobar el código http code = f.getcode() log.debug(_("Código de la conexión al servidor ActiveBPEL: ") + str(code)) # Expresión regular para saber si está activo patron = re.compile(".*Running.*") activo = False # leer el resultado for line in f: if patron.match(line): activo = True break log.info(_("Estado del servidor ActiveBPEL : ") + "Running" if activo else "Stopped") return activo return None def cancelar_ejecucion(self): """@brief Termina la ejecución matando el proceso relacionado.""" try: self.ejec_subproc.kill() except: return False else: log.info("Subproceso de ejecución matado") return True def seleccionar_trazas_analisis(self, trz): """@brief El análisis utiliza las trazas que están en el directorio anl_trazas de manera que hay que enlazar las trazas seleccionadas para el análisis desde trazas a anl_trazas. @param trz Trazas seleccionadas en una estructura tipo trz[fichero][caso] = t_file """ # Acortar nombres anl_tdir = self.trazas_anl_dir tdir = self.trazas_dir # Limpiar ficheros antiguos seleccionados # El directorio anl_tdir puede que no exista self.borrar_trazas(anl_tdir) log.debug("Linking trace files from %s to %s for analysis" % (tdir, anl_tdir)) # Añadir la selección actual enlazando los ficheros desde su lugar en # self.trazas_dir for file, cases in trz.items(): for case, tfile in cases.items(): os.link(path.join(tdir, tfile), path.join(anl_tdir, tfile)) def analizar(self, trz): """@brief Ejecuta los scripts de aplanado y el motor Daikon sobre las trazas seleccionadas.""" self.seleccionar_trazas_analisis(trz) # No crear otro subproceso si ya se está ejecutando if self.anl_subproc is not None and self.anl_subproc.poll() is None: log.warning(_("Ya hay un análisis en curso")) return cmd = ["ant", "-f", self.build, "analyze"] log.info(_("Analizando: ") + str(cmd)) # Abrimos un proceso y leeremos de su salida estandar. # Redireccionamos la salida de errores a la estandar. self.anl_subproc = subproc.Popen(cmd, shell=False, stdout=subproc.PIPE, stderr=subproc.STDOUT) return self.anl_subproc ## @} ## @name Casos de prueba ## @{ def list_bpts(self, path): """@brief Lista los casos de prueba que hay en un bpts. @param path Ruta del fichero @returns Una lista con los nombres de los casos.""" # Lo parseamos con ElementTree # Abrirlo try: bpts = et.ElementTree() bproot = bpts.parse(path) except: raise ProyectoRecuperable(_("No se ha podido cargar el fichero de casos de prueba ") + path) # Construir los nombres con la uri es un peñazo ns = "{%s}" % self.test_url # Encontramos elementos básicos testSuite = bproot tCases = bproot.find(ns + "testCases") # Buscamos todos los casos de prueba y los devolvemos. return [c.get("name") for c in tCases.findall(ns + "testCase")] def add_bpts(self, ruta): """@brief Añade un fichero con casos de prueba al proyecto. @param ruta Ruta al fichero .bpts. El primer bpts que se añade es el que nos proporcionará la información referida al <put>. Eleva ProyectoRecuperable en caso de error.""" # Comprobamos que exista y se pueda leer if not path.exists(ruta) or not os.access(ruta, os.F_OK or os.R_OK): raise ProyectoRecuperable(_("No existe el fichero de casos de prueba o no es accesible")) # Nombre del fichero y directorio de la ruta nom = path.basename(ruta) dir = path.dirname(ruta) # Escapamos los caracteres separadores ':' por '.' pnom = nom.replace(":", ".") # Lo copiamos al proyecto en casos_dir # Aseguramos el nombre para no sobreescribir i = 1 pruta = path.join(self.casos_dir, pnom) while path.exists(pruta): pnom = "%s-%d" % (nom, i) pruta = path.join(self.casos_dir, pnom) i = i + 1 log.debug(pruta) try: # Copiar de ruta a pruta (en el proyecto) shutil.copy(ruta, pruta) except: raise ProyectoRecuperable(_("No se pudo copiar al proyecto el fichero de casos de prueba: ") + ruta) # Añadimos el fichero a fcasos self.fcasos.append(pnom) # Añadimos los casos del nuevo bpts (escapando : por . ) self.casos[pnom] = [n.replace(":", ".") for n in self.list_bpts(pruta)] # Actualizamos la información de test.bpts con la del proyecto self.add_bpts_info(pruta) def bpts_find_delays(self, bpts): """@brief Toma un bpts y renombra cada caso añadiéndole entre paréntesis el número de rounds que realiza en base a sus delaySequences @bpts Ruta al bpts o el DOM minidom abierto. """ pass def add_bpts_info(self, bpts_path): """@brief Añade al bpts general del proyecto la información necesaria para la ejecución. La primera vez que se añade un bpts incluye información extra. También declara inline los elementos de los casos de test. @param path Ruta al bpts.""" # Abrirlo try: bpts = md.parse(bpts_path) except: raise ProyectoRecuperable(_("No se ha podido cargar el fichero de casos de prueba ") + bpts_path) # Elementos del fichero nuevo que añadimos testSuite = bpts.getElementsByTagNameNS(self.test_url, "testSuite")[0] deploy = bpts.getElementsByTagNameNS(self.test_url, "deployment")[0] partners = deploy.getElementsByTagNameNS(self.test_url, "partner") put = deploy.getElementsByTagNameNS(self.test_url, "put")[0] wsdl = deploy.getElementsByTagNameNS(self.test_url, "wsdl")[0] # Declarar los namespaces huerfanos # Esto es una acción bastante pesada y puede llevar un rato. log.info("Processing bpts namespaces. This may take a while") cases_dom = bpts.getElementsByTagNameNS(self.test_url, "testCases")[0] util.xml.minidom_namespaces(cases_dom) # Guardamos el bpts tras la modificación try: file = open(bpts_path, "w") file.write(bpts.toxml("utf-8")) except: raise ProyectoRecuperable( "No se ha podido escribir el bpts nuevo \ %s " % bpts_path ) # Abrimos el fichero general .bpts de casos de prueba # Lo abrimos con minidom para conservar namespaces. try: test = md.parse(self.test) except: raise ProyectoRecuperable(_("No se ha podido cargar el fichero de tests") + self.test) # Buscamos los elementos en el test.bpts ttestSuite = test.getElementsByTagNameNS(self.test_url, "testSuite")[0] tdeploy = test.getElementsByTagNameNS(self.test_url, "deployment")[0] tput = tdeploy.getElementsByTagNameNS(self.test_url, "put")[0] twsdl = tput.getElementsByTagNameNS(self.test_url, "wsdl")[0] # Añadimos al testSuite de test.bpts las declaraciones # de espacios de nombres del .bpts nuevo for prefix, uri in testSuite.attributes.items(): if not ttestSuite.hasAttribute(prefix): ttestSuite.setAttribute(prefix, uri) # Le ponemos al wsdl el valor del que hemos abierto wsdl try: if wsdl.hasChildNodes: # log.debug(wsdl.firstChild.data) #DEBUG if twsdl.firstChild: twsdl.removeChild(twsdl.firstChild) # Eliminar el nodo texto # Añadir nuevo twsdl.appendChild(test.createTextNode(path.join(self.dep_nom, wsdl.firstChild.data))) except: raise ProyectoRecuperable(_("El fichero test.bpts está roto")) log.debug(_("Add informacion al bpts a partir del bpts nuevo")) # Copiar el wsdl y los partner # Hay que añadirles el dependencias/ para la ruta. # Solo lo hacemos la primera vez if not self.hay_casos: for p in partners: sub = test.createElementNS(self.test_url, "tes:partner") # Se le añade el prefijo manualmente ------^^^ sub.setAttributeNS(self.test_url, "name", p.getAttribute("name")) sub.setAttributeNS(self.test_url, "wsdl", path.join(self.dep_nom, p.getAttribute("wsdl"))) tdeploy.appendChild(sub) # log.debug(sub) #DEBUG try: file = open(self.test, "w") file.write(test.toxml("utf-8")) except: raise ProyectoRecuperable(_("No se ha podido escribir el fichero de tests") + self.test) # log.debug(tdeploy.toxml('utf-8')) #DEBUG self.hay_casos = True def vaciar_bpts(self, ruta): """@brief Elimina todos los casos de un bpts @param ruta La ruta al bpts a vaciar.""" log.debug(_("Vaciando de casos de prueba el fichero: ") + ruta) try: test_dom = md.parse(ruta) except: e = _("No se ha podido cargar el fichero bpts ") + ruta log.error(e) raise ProyectoRecuperable(e) for caso in test_dom.getElementsByTagNameNS(self.test_url, "testCase"): caso.parentNode.removeChild(caso) try: file = open(self.test, "w") file.write(test_dom.toxml("utf-8")) except: e = _("No se ha podido escribir el fichero bpts ") + ruta log.error(e) raise ProyectoRecuperable(e) def rm_caso(self, btps, caso): """@brief Elimina un caso de prueba del test.bpts. @param bpts Nombre del fichero bpts del caso. @param caso Nombre del caso dentro del bpts a borrar.""" nombre = "%s:%s" % (bpts, caso) try: test_dom = md.parse(self.test) except: e = _("No se ha podido cargar el fichero de tests ") + self.test log.error(e) raise ProyectoRecuperable(e) caso_dom = [ f for f in test_dom.getElementsByTagNameNS(self.test_url, "testCase") if f.getAttribute("name") == nombre ] if len(caso_dom) == 0: log.warning(_("Al eliminar un caso del test.bpts no se ha encontrado el caso en test.bpts ") + nombre) return caso_dom = caso_dom[0] test_dom.removeChild(caso_dom) def add_casos(self, casos): """@brief Añade un caso de prueba en un bpts al test.bpts. @param casos Diccionario de tipo casos[fichero] = [caso1, caso2 ..] El parsear y añadir un nuevo caso al test.bpts es un proceso que consume bastante tiempo y memoria. Cuando hay 200+ casos, la aplicación puede llegar a quedarse congelada. El procedimiento mejorado para añadir casos emplea: * Un dicc de casos casos[fichero] = [casos..] para pasar todos los ficheros y casos a la vez y abrir solo una vez el test.bpts * Un dicc de los dom de los casos que ya estaban en el test.bpts El procedimiento consiste en: 1. Cachear en un diccionario el dom de todos los casos que habia en el test.bpts 2. Dejar el test.bpts vacío teóricamente desligando todos los casos que había. 3. Recorrer el diccionario de casos que recibe la función añadiendo casos. 3.1 Si el caso ya estaba antes, se vuelve a ligar el dom cacheado. 3.2 Si el caso es nuevo y no estaba antes en el test.bpts, se arreglan sus namespaces, y se añade al test.bpts """ # Abrir el fichero de test general # Con minidom para no perder los namespaces. try: test_dom = md.parse(self.test) except: e = _("No se ha podido cargar el fichero de tests ") + self.test log.error(e) raise ProyectoRecuperable(e) # Encontrar el testCases de test.bpts test_cases = test_dom.getElementsByTagNameNS(self.test_url, "testCases")[0] # Buscar todos los nodos hijos tests_doms = test_dom.getElementsByTagNameNS(self.test_url, "testCase") # Obtenemos sus nombres en un diccionario casos_test[nombre] = dom_elto # Los desligamos del padre testCases Con esto dejamos el test.bpts # vacío pero mantenemos el dom de los hijos que ya estaban cacheado en # el diccionario, para no tener que introducirlo de nuevo si el caso se # repite. casos_test = {} for tc in tests_doms: casos_test[tc.getAttribute("name")] = tc test_cases.removeChild(tc) # Añadir los ficheros pasados for fnom in casos: # Abrir el fichero de casos try: bpts_dom = md.parse(path.join(self.casos_dir, fnom)) except: e = _("No se ha podido cargar el fichero bpts ") + fnom log.error(e) raise ProyectoRecuperable(e) # Añadir los casos de ese fichero for caso in casos[fnom]: # Formamos el nombre completo del caso fichero:caso nombre = "%s:%s" % (fnom, caso) # Comprobamos que el caso no esté en el test # si ya estaba en el casos_test, lo tenemos cacheado en el # diccionario y lo añadimos. if nombre in casos_test: log.warning(_("Intentando add un caso que ya estaba en el test.bpts ") + nombre) test_cases.appendChild(casos_test[nombre]) continue # Acortar el nombre de la función bytag = bpts_dom.getElementsByTagNameNS # Encontrar el caso en el bpts caso_dom = [f for f in bytag(self.test_url, "testCase") if f.getAttribute("name") == caso] if len(caso_dom) == 0: log.warning( _("Al add un caso al test.bpts, no se ha encontrado el caso en su fichero original ") + caso ) continue caso_dom = caso_dom[0] # Ponerle el nuevo nombre fichero:caso caso_dom.setAttribute("name", nombre) # Clonar el caso y sus hijos, y añadirlo al test test_cases.appendChild(caso_dom.cloneNode(True)) # Escribir el fichero test try: file = open(self.test, "w") file.write(test_dom.toxml("utf-8")) except: e = _("No se ha podido escribir el fichero bpts ") + bpts log.error(e) raise ProyectoRecuperable(e) ## @} ## @name Trazas ## @{ def borrar_trazas(self, dir): """@brief Borra todas las trazas.log en un directorio. @param dir El directorio . """ log.info("Cleaning old trace files from %s" % self.trazas_anl_dir) [os.remove(path.join(dir, f)) for f in os.listdir(dir) if f.endswith(".log")] def trazas_disponibles(self): """@brief Devuelve las trazas disponibles en un diccionario trazas[fichero][caso] = [trace_file, trace_file ..] @retval Una lista con los nombres de los ficheros de trazas. """ return self.dict_trazas(os.listdir(self.trazas_dir)) def ordenar_trazas(self, trazas): """@brief Toma una lista con nombres de ficheros de trazas y la devuelve ordenada por tiempo de generación de mayor a menor timestamp es decir, de más nueva a la más antigua. @retval La lista trazas ordenada por tiempos de la más nueva a la más antigua. """ # Función que obtiene un float con el tiempo de la traza n2f = lambda n: float(self.parse_traza(n)[2]) def traza_time_cmp(x, y): # Nombre a float # (sacar el timestamp del nombre de la traza y convertirlo a float.) # Devolver la diferencia try: return int(n2f(y) - n2f(x)) except: return -1 # Ordenar las trazas por tiempo de ejecución trazas.sort(traza_time_cmp) return trazas def parse_traza(self, traza): """@brief Toma el nombre de un fichero de traza y devuelve 3 valores, fichero, caso, time @param traza El nombre del fichero de traza. @retval Los 3 valores fich, caso, time """ # Estructura de los nombres # 0(fichero):1(caso):2(timestamp) # Ejemplo: LoanApprovalProcess.bpts:LargeAmount-1267033799.94.log # El timestamp se encuentra en segundos y es obtenido con time.time() try: fich, caso, time = traza.split(":") time = time.rsplit(".", 1)[0] except: # log.warning(_("Hay una traza que no sigue el formato: " + traza)) return "", "", "" return fich, caso, time def dict_trazas(self, trazas): """@brief Toma una lista con nombres de ficheros de trazas y devuelve un objeto del tipo trazas[fichero][caso] = [fich_traza, ..] @param trazas Lista con los nombres de los ficheros de trazas. @retval Un diccionario donde los nombres de los ficheros de trazas están ordenados de más reciente a más antiguo. { fichero : { caso_prueba: [fich_traza 1, fich_traza 2, ..], caso_prueba2: [fich_traza 1, fich_traza 2, ..], ... } } """ # Diccionario a devolver trz = {} # Ordenar las trazas que se pasan tord = self.ordenar_trazas(trazas) # Añadir las trazas al diccionario # como están ordenadas, se añaden a las listas por orden. for f in tord: fich, caso, time = self.parse_traza(f) # log.debug("fichero %s , caso %s, time %s" % (fich,caso,time)) if not fich or not caso or not time: log.warning("Wrong format for trace file %s " % f) continue if fich not in trz: trz[fich] = {} if caso not in trz[fich]: trz[fich][caso] = [] trz[fich][caso].append(f) return trz def ultimas_trazas(self, trazas): """@brief Devuelve las últimas trazas disponibles en una lista. @param trazas Lista con los nombres de los ficheros de trazas. @retval Lista con el más reciente de cada caso de los ficheros de traza. """ tr = {} tord = self.ordenar_trazas(trazas) tend = [] for f in tord: nom = f.rsplit(":", 1)[0] if nom not in tr: tr[nom] = True tend.append(f) return tend ## @} ## @name Analisis ## @{ def set_aplanado(self, modo): """@brief Establece el modo de aplanado""" self.aplanado = modo def set_simplify(self, flag): """@brief Establece el modo de simplify""" self.simplify = flag def anl_copiar_inv(self): """Copia el último invariante generado en la última ejecución a la carpeta de invariantes. Renombrándolos convenientemente""" log.info("Importando invariante generado") # Importar el fichero de invariantes dirs = glob.glob(path.join(self.dir, "daikon-out*")) log.debug(path.join(self.dir, "daikon-out*")) dirs.sort() log.debug(dirs) if dir: src = os.path.join(dirs[-1], "procesoInspeccionado.out") dst = os.path.join(self.invr_dir, "invr-" + str(time.time()) + ".out") shutil.move(src, dst) ## @} ## @name Invariantes ## @{ def inv_ultimo(self): """@brief Devuelve el último invariante @retval La ruta completa al último invariante o None. """ invs = glob.glob(path.join(self.invr_dir, "invr-*")) if invs: invs.sort() invs = invs[-1] else: return None return invs ## @} ## @name Cargar y Crear ## @{ def crear(self): """@brief Crea el proyecto desde 0 la primera vez.""" try: # Comprobar el nombre if len(str(self.nombre).strip()) == 0: raise ProyectoError(_("Nombre de proyecto vacio")) # Comprobar el bpel original if not path.exists(self.bpel_o): raise ProyectoError(_("Fichero bpel no existe ") + self.bpel_o) # Crear el directorio nuevo en data # Copiar los ficheros básicos de skel log.info(_("Inicializando proyecto")) try: shutil.copytree(path.join(self.share, "skel"), self.dir) except: raise ProyectoError(_("Error al iniciar proyecto con: ") + path.join(self.share, "skel")) # Buscar dependencias (y el bpel original modificándolo) # Si falla borramos el intento de proyecto # y elevamos de nuevo la excepción try: log.info(_("Buscando dependencias")) self.buscar_dependencias(self.bpel_o) except ProyectoError, error: log.error(_("Crear Proyecto: Error al crear ficheros de proyecto")) raise error # Imprimir directorios del proyecto log.info(_("Proyecto creado correctamente")) log.info(str(os.listdir(self.dir))) return True except: