Archive for the ‘How to’ Category

Conexión a Base de Datos Safari-JavaScript

Monday, October 19th, 2009

Para realizar la conexión a una base de datos  mediante Javascript, podemos utilizar el siguiente código:

try {
   if (!window.openDatabase) {
      alert('not supported');
   } else {
      var shortName = 'mydatabase';
      var version = '1.0';
      var displayName = 'My Important Database';
      var maxSize = 65536; // in bytes
      var mydb = openDatabase(shortName, version, displayName, maxSize);

      // You should have a database instance in mydb.
   }
} catch(e) {
   // Error handling code goes here.
   if (e == 2) {
      // Version number mismatch.
      alert("Invalid database version.");
   } else {
      alert("Unknown error "+e+".");
   }
   return;
}

alert("Database is: "+mydb);

Con esto, sin más que implementar las transacciones necesarias, podemos hacer persistente la información cargada durante la sesión para su uso posterior.

Estas bases de datos se pueden utilizar para la implementación de aplicaciones Offline mediante Safari.

Para eliminar estas bases de datos creadas por aplicaciones web, basta con ir a la sección “Safari” de los ajustes del iPhone.

Vía: Safari Client-Side Storage and Offline Applications Programming Guide


iPhone SDK: Registrar una clase como observador de un evento

Monday, July 6th, 2009
[[NSNotificationCenter defaultCenter]
      addObserver:self
      selector:@selector(onDataChangeEvent:)
      name:@"dataChangeEvent"
      object:nil];

La clase que contiene este código:

  1. Recibirá notificaciones de disparo del evento “dataChangeEvent”.
  2. Debe implementar el método “onDataChagneEvent”.

Cuando algún otro objeto dispare el evento, las instancias de esta clase recibirán la notificación y ejecutarán el método especificado.


Llamadas a funciones estáticas externas en C

Wednesday, February 27th, 2008

Sí, sí, ya lo sé. ¿Por qué querría alguien hacer una llamada a una función declarada como estática desde otro módulo?

Si una función se ha declarado estática para restringir el acceso a la misma, para no incluirla en el API del módulo, ¿por qué “bypassear” la funcionalidad y acceder a ella?

En mi caso, la respuesta es sencilla: pruebas unitarias. ¿Cómo hacer pruebas unitarias de estas rutinas?

La respuesta es, creando punteros a estas rutinas, accesibles desde otros módulos. Y puesto que cualquier solución implica cambios en los módulos a probar, en el ejemplo a continuación trataré de ser lo menos “intrusivo” posible.

Supongamos el módulo stfunc.c:

#include <stdio.h>
static int funcprintf(const char* str) {
   return printf(str);
}

Para probar esta rutina, tenemos esta otra, en otro fichero diferente (main.c):

int main() {
   int a = funcprintf("Loquesea");
   return a;
}

Si intentamos compilar, obtenemos el error “undefined reference to `funcprintf’”.

Así pues, vamos a crear un puntero a esta rutina para permitir el acceso a la misma desde el módulo de prueba. Creamos un fichero llamado ptrdefs.h:

#ifndef _PTRDEFS_H
#define _PTRDEFS_H
int (*fpointer)(const char*) = &funcprintf;
#endif

Y modificamos los ficheros anteriores de esta manera:
Fichero stfunc.c:

#include <stdio.h>

static int funcprintf(const char* str) {
   return printf(str);
}

#ifdef UNIT_TESTING
#include
<ptrdefs.h>
#endif

Fichero main.c:

int main() {
   int a = fpointer("Loquesea");

   return a;
}

Con esto, basta añadir la opción -DUNIT_TESTING para tener acceso a la rutina.

Por tro lado, el fichero ptrdefs.h sólo estará disponible para los tests unitarios. Esto evita el acceso indeseado.

[Código completo del ejemplo: static.tgz]


Utilización de gprof/gcov: cobertura de ramas (y II)

Tuesday, February 5th, 2008

Continuando con la temática del post anterior, vamos a ver en este caso, como chequear la cobertura lógica en bloques de código con condiciones de acceso más o menos complejas.

Supongamos el siguiente fichero de código main.c:

main.c

En este caso, el script de compilación y ejecución será compexec.sh:

compexec.sh

Nótese como la herramienta gcov ha sido ejecutada con las opciones -b y -c. Según “man gcov”:

  1. -b
    –branch-probabilities
    Write branch frequencies to the output file, and write branch summary info to the standard output. This option allows you to see how often each branch in your program was taken. Unconditional branches will not be shown, unless the -u option is given.
  2. -c
    –branch-counts
    Write branch frequencies as the number of branches taken, rather than the percentage of branches taken.

Es decir, pedimos a la herramienta que devuelva información sobre ejecución de las “ramas lógicas”, dando como resultado el fichero main.c.gcov:

main.c.gcov

Aquí podemos ver información, aunque un tanto críptica, sobre la ejecución de dos bloques if-else. Como puede verse, cada uno de ellos presenta cuatro ramas, numeradas de “branch 0″ a “branch 3″. Veamos a continuación la explicación de estos datos:

Supongamos la condición:

if (a || b) {
   x;
} else {
   y;
}

Esta condición (o combinación de condiciones) da lugar a 4 ramas, que se corresponden con las posibles combinaciones de valores booleanos de las dos variables:

a b
—-
0 0
0 1
1 0
1 1

Podemos reescribir esta condición como:

if (a == false) {
   // Branch 0
   if (b == false) {
      // Branch 2
      y;
   } else {
      // Branch 3;
      x;
   }
} else {
   // Branch 1
   x;
}

Supongamos ahora la condición:

if (a && b) {
   x;
} else {
   y;
}

Como antes, esta condición (o combinación de condiciones) da lugar a 4 ramas, que se corresponden con las posibles combinaciones de valores booleanos de las dos variables:

a b
—-
1 1
1 0
0 1
0 0

Podemos reescribir esta condición como:

if (a == true) {
   // Branch 0
   if (b == true) {
      // Branch 2
      x;
   } else {
      // Branch 3;
      y;
   }
} else {
   // Branch 1
   y;
}

En cualquiera de los casos anteriores, la herramienta gcov (con las opciones -bc) nos devuelve el número de veces que cada una de las ramas nombradas más arriba ha sido ejecutada.

Si se omite la opción -c, los resultados son porcentajes, de manera que la suma de las ejecuciones de todas las ramas deberá ser el 100 %.

Además, se puede deducir que, en cualquiera de los casos:

1.- (nº de ejecuciones de rama 0) + (nº ejecuciones rama 1) = (nº ejecuciones
del if

2.- (nº ejec rama 2) + (nº ejec rama 3) = (nº ejec rama 1)

En conclusión, podemos deducir qué líneas de código y ramas lógicas han sido ejecutadas y añadir/modificar los test cases necesarios para alcanzar la cobertura deseada.

[Código completo y resultados.]


Utilización de gprof/gcov para obtención de datos de cobertura (I)

Monday, February 4th, 2008

Vamos a ver, en unos pasos muy simples, cómo utilizar las herramientas gprof/gcov (integradas con el compilador gcc) para obtener información de cobertura de ejecución de una aplicación. Los resultados son aplicables a cualquier entorno en que dispongamos de estas herramientas (Linux, windows+cygwin, MacOSX+Xcode, etc).

Para empezar el código fuente, main.c:

main.c

A continuación, las instrucciones de compilación y ejecución, compexec.sh:

compexec.sh

Como se puede apreciar, son tres las opciones añadidas al compilador/linkador para obtener los resultados esperados:

  1. -pgEsto es lo que dice “man gcc” acerca de esta opción:

    Generate extra code to write profile information suitable for the analysis program gprof. You must use this option when compiling the source files you want data about, and you must also use it when linking.

    Es decir, prepara el ejecutable para generar información suscpetible de ser utilizada por gprof para obtener información de “profiling”. Tras la ejecución de la aplicación generada con esta opción, se crea el fichero gmon.out.

  2. -ftest-coverage
  3. -fprofile-arcsEstas dos opciones son las que indican al compilador que, durante la ejecución de la aplicación, debe generarse información de cobertura.

    [La salida "man gcc" para estas opciones es demasiado larga para incluirla aquí, pero puede verse en este enlace.]

    El ejecutable compilado/linkado con estas opciones genera los ficheros main.gcno y main.gcda, que contienen los datos utilizados por gcov para generar información “legible” de cobertura.

Así pues, una vez ejecutada la aplicación y obtenidos estos ficheros, basta con ejecutar el comando gcov:

$ gcov main.c

(tal como se ha incluido en el fichero compexec.sh) y como resultado se obtiene el fichero main.c.gcov:

main.c.gcov

El fichero de resultados muestra el número de veces que un statement ha sido ejecutado.

Las instrucciones marcadas con “#####” son aquellas no cubiertas por la ejecución de la aplicación.

[Código completo y resultados.]