Saltar al contenido

Emuladores ​

Un emulador es Signal Lab haciendo el papel de la API, el dispositivo o el servicio con el que habla tu sistema. Escucha en una dirección y responde según reglas: una API HTTP, por rutas; un dispositivo OSC, UDP o TCP, con “ante esto, responde aquello”; un bróker MQTT, como cualquier bróker y además con reglas propias. Puede ser lento, fallar o caer de vez en cuando, para que pruebes qué hace tu sistema cuando su dependencia se porta mal. Cada intercambio se cuenta, se muestra en una lista y se envía al Inspector.

Un emulador es un solo documento. La pantalla Emuladores guarda una biblioteca de ellos; el mismo documento funciona dentro de un experimento como nodo Emulador, desde la línea de comandos con signallab emulate, y a través de la API y de MCP, y responde igual en todas partes.

La pantalla ​

A la izquierda está la biblioteca (Biblioteca): cada emulador con su protocolo y su dirección, y un punto que late y un recuento de solicitudes en los que están en marcha. A la derecha están los ajustes y las reglas del emulador seleccionado y, debajo, lo que ha recibido (En vivo).

Crear un emulador ​

  1. Pulsa uno de los botones de la parte superior de la biblioteca:

    BotónCreaEscucha enCon una regla que funciona tal cual
    + API HTTPUna API HTTP127.0.0.1:18080GET /health → 200 {"status":"ok"}
    + Dispositivo OSCUn dispositivo OSC127.0.0.1:9100/ping → /pong con el recuento como int
    + Dispositivo UDPUn dispositivo UDP127.0.0.1:7100un datagrama que contiene PING → PONG 1, PONG 2, …
    + Dispositivo TCPUn dispositivo TCP127.0.0.1:7200una línea que contiene PING → PONG
    + Bróker MQTTUn bróker MQTT127.0.0.1:1883una publicación en lab/<name>/set → la misma carga útil, retenida, en lab/<name>/state

    Si otro emulador de la biblioteca ya usa ese puerto, se toma el siguiente libre.

  2. Dale un Nombre (como máximo 120 caracteres).

  3. Rellena el campo Escuchar en con IP:port. 127.0.0.1 solo responde a este equipo; 0.0.0.0 responde también a la red.

  4. Cambia las reglas (más abajo) e indica en el campo Nota a qué sustituye.

Los cambios se guardan solos. Duplicar crea una copia en el siguiente puerto libre. Eliminar vuelve a preguntar (¿Eliminar?), detiene el emulador si está en marcha y lo quita de la biblioteca.

Las reglas se prueban en orden, de la primera a la última; responde la primera que coincide. La cabecera de cada regla muestra un resumen de una línea; haz clic en ella para abrir o plegar la regla. Los botones ↑ y ↓ mueven una regla, y × la quita.

Ponerlo en marcha ​

  1. Selecciona el emulador y pulsa Iniciar. Su puerto se abre antes de que el botón vuelva a estar disponible: un puerto ya ocupado, o un emulador con un problema, se rechaza ahí mismo con el motivo.
  2. Apunta tu sistema hacia él. En una API HTTP, Copiar URL copia su dirección (http://127.0.0.1:18080), y cada ruta tiene un botón Copiar la URL para la suya (salvo cuando su ruta de acceso contiene una plantilla {{…}}).
  3. Observa cómo se llena la lista Recibidos.
  4. Pulsa Detener, o detén su tarea desde la franja de la consola.

El estado junto a los botones indica Detenido, dónde responde o que está caído.

Un emulador sigue respondiendo con las reglas con las que se inició. Si lo cambias mientras funciona, aparece Reiniciar: púlsalo para volver a iniciarlo con las reglas tal como están ahora. Hasta entonces, los recuentos de coincidencias de las reglas se ocultan, porque pertenecen a las reglas antiguas.

El botón Dejar caído hace que un emulador en marcha no esté disponible hasta que pulsas Levantar: una solicitud HTTP recibe 503, un dispositivo TCP y un bróker MQTT cortan sus conexiones y rechazan las nuevas, y un dispositivo OSC o UDP no responde nada. Consulta Caídas.

Dos emuladores del mismo transporte no pueden compartir un puerto: los emuladores HTTP, TCP y MQTT escuchan en puertos TCP, y los OSC y UDP en puertos UDP. Una API HTTP y un dispositivo OSC pueden usar ambos el puerto 8080; dos API HTTP, no. Un segundo emulador en un puerto ocupado se rechaza al iniciarse.

TIP

En un navegador conectado a un servidor, el emulador funciona en el servidor. A uno que escucha en 0.0.0.0 se llega por el nombre del servidor, y Copiar URL copia esa dirección; uno en 127.0.0.1 solo responde a programas del propio servidor.

Lo que llegó ​

Mientras funciona, el panel En vivo cuenta:

RecuentoQué
SolicitudesTodo lo que llegó: solicitudes, mensajes, líneas.
Sin reglaLo que ninguna regla aceptó. Una solicitud HTTP sin ruta recibe igualmente su respuesta (consulta Solicitudes que ninguna ruta acepta); lo demás no recibe ninguna.
FallidasIntercambios en los que no se pudo crear o enviar una respuesta.
Durante la caídaLo que llegó mientras el emulador estaba caído. Se muestra cuando tiene una caída programada o algo lo encontró caído. Nunca se cuenta en Sin regla.
No entregadosSolo MQTT, cuando ocurre: mensajes que un cliente no pudo recibir porque iba demasiado atrasado.

La cabecera de cada regla muestra cuántas veces coincidió desde el inicio.

La lista Recibidos muestra los 300 intercambios más recientes, el más reciente primero:

ColumnaQué
HoraCuándo llegó.
OrigenLa dirección del cliente.
SolicitudLo que llegó, en notación del protocolo: GET /users/7, /ping 1, POWER?.
ReglaLa regla que lo aceptó (#2), o —.
RespuestaLo que se devolvió: 200 OK · 37 B, /pong 3, una carga útil; retenida o cerrada en caso de fallo; el error, cuando la respuesta falló; caída, cuando llegó mientras estaba caído.
msDesde la llegada hasta que salió la respuesta, retardo incluido.

El botón ⌕ de una fila (Abrir en el Inspector) abre ese intercambio en el Inspector, si la captura estaba activada. Cuando llegan más de 200 intercambios en una quinta parte de segundo, la lista omite algunos e indica cuántos. El motor conserva los 500 intercambios más recientes de cada emulador en marcha, con lo que llegó, para la línea de comandos, la API y MCP.

API HTTP ​

Un servidor HTTP/1.1. Cada solicitud la responde la primera ruta que la acepta.

Rutas ​

Una ruta acepta una solicitud cuando coinciden su método, su ruta de acceso y todas sus condiciones.

CampoQué
MétodoGET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS o Cualquiera. Una ruta GET responde también a HEAD.
Ruta de accesoEmpieza por /. Un segmento :name acepta un segmento cualquiera, que se lee como {{request.params.name}}; un último segmento * acepta todo lo que hay debajo. Una / final no cambia nada; la cadena de consulta no forma parte de la ruta de acceso.
CondicionesDeben cumplirse todas. Añade una con + Condición.

Ejemplos de ruta de acceso:

Ruta de accesoAceptaNo acepta
/health/health, /health//health/db, /Health
/users/:id/users/7 (params.id es 7), /users/a%20b (a b)/users, /users/7/orders
/files/*/files, /files/a, /files/a/b/c/file, /other/files/a

Una condición lee una parte de la solicitud (Dónde) y la compara:

DóndeNombreLee
EncabezadoEl nombre de un encabezado, en mayúsculas o minúsculasEl valor del encabezado; si el encabezado se envía varias veces, sus valores unidos con , .
ConsultaUn parámetro de consultaSu valor, decodificado; el primero, si se repite.
Cuerpo—Todo el cuerpo como texto.
JSONUna ruta JSON, como $.user.idEse campo de un cuerpo JSON.

Las comparaciones son es igual a, no es igual a, menor que, como máximo, mayor que, como mínimo, contiene, coincide con la regex, está vacío y no está vacío. Los números se comparan como números; el texto, exactamente. Un encabezado, parámetro o campo que no existe está vacío. Una comparación que no se puede hacer (texto frente a un número) no se cumple.

Respuestas ​

Una ruta tiene de una a 16 respuestas (Respuestas).

CampoQuéPredeterminado
Estado100–599.200
FalloAlgo distinto de una respuesta; consulta Fallos.Ninguno — responder
Retardo, msCuánto esperar antes de responder, 0–60 000 ms.0
Jitter, msHasta este tiempo más, al azar, 0–60 000 ms.0
PesoSu proporción cuando la ruta responde al azar. Solo se muestra entonces.1
EncabezadosHasta 32. Los nombres pueden usar parámetros; los valores son plantillas.ninguno
CuerpoUna plantilla, de hasta 256 KiB tal como se escribe.vacío

Sin un encabezado Content-Type, un cuerpo que es JSON válido se envía como application/json, y cualquier otro como text/plain; charset=utf-8.

Con dos respuestas o más, el campo Qué respuesta indica cuál recibe cada solicitud:

Qué respuestaLas solicitudes recibenPara
En secuencia, luego la últimaLa primera, la segunda, …, y a partir de ahí la última: 500, 500, 200, 200, 200…Reintentos: fallar dos veces y luego funcionar.
Por turnosOtra vez la primera después de la última: 200, 500, 200, 500…Una dependencia que falla de vez en cuando, con regularidad.
Al azar, por pesoCada una, sorteada según su peso. Con pesos 8 y 2, la primera sale aproximadamente el 80 % de las veces. Al menos un peso debe ser mayor que 0.Una proporción realista de fallos.

El menú Agregar una respuesta añade a la ruta una respuesta ya preparada:

PreajusteAñade
200 JSON200, {"ok":true}
201 Creado201, {"id":"{{uuid}}"}, encabezado Location: {{request.path}}/{{counter}}
404 No encontrado404, {"error":"not found"}
500 Error del servidor500, {"error":"internal"}
503 No disponible503, {"error":"unavailable"}, encabezado Retry-After: 1
Lenta — 2 s200, {"ok":true} al cabo de 2000 ms
Sin respuestaEl fallo Sin respuesta
Conexión cerradaEl fallo Cerrar la conexión
JSON mal formado200, {"items":[{"id":1},{"id":2}]} con el fallo Cuerpo mal formado

Fallos ​

FalloLo que encuentra el cliente
Ninguno — responderLa respuesta.
Sin respuestaNada. La solicitud se retiene hasta 2 minutos y luego se cierra la conexión, así que lo que se prueba es el propio tiempo de espera del cliente. El retardo no se aplica.
Cerrar la conexiónLa conexión se cierra sin respuesta, tras el retardo.
Cuerpo mal formadoUna respuesta HTTP completa, con el estado y los encabezados definidos, cuyo cuerpo se corta a la mitad: un JSON que no se puede analizar. Cuando todo el cuerpo era JSON, el tipo de contenido sigue indicando application/json.

Solicitudes que ninguna ruta acepta ​

La opción Solicitudes que ninguna ruta acepta decide qué recibe una solicitud que no coincide con ninguna ruta:

  • 404 No encontrado: 404 con el cuerpo {"error":"no_route"};
  • Esta respuesta: una respuesta que defines tú, con todo lo que tiene la respuesta de una ruta. Su {{counter}} cuenta las solicitudes que ninguna ruta aceptó.

En ambos casos, la solicitud se cuenta en Sin regla.

Lo que puede leer una respuesta HTTP ​

PlantillaEs
{{request.method}}GET, POST, …
{{request.path}}La ruta de acceso, sin la consulta.
{{request.params.id}}El segmento de la ruta de acceso llamado :id.
{{request.query.page}}Un parámetro de consulta, decodificado.
{{request.headers.x-key}}Un encabezado; los nombres, en minúsculas.
{{request.body}}El cuerpo como texto: sus primeros 64 KiB.
{{request.json.name}}Un campo de un cuerpo JSON, cuando el cuerpo es JSON y no pasa de 64 KiB.
{{request.from}}El IP:port del cliente.

Una solicitud con un cuerpo de más de 1 MiB recibe 413 y se cuenta en Fallidas. Una respuesta que no se puede crear (una plantilla que nombra algo que la solicitud no tiene) recibe 500 con el error en el cuerpo, y se cuenta en Fallidas.

Dispositivo OSC ​

Cada mensaje que llega (cada mensaje de un bundle, por separado) lo responde la primera regla con la que coincide. Un datagrama que no es OSC se cuenta en Sin regla.

CampoQué
Patrón de direcciónUn patrón de dirección OSC 1.0: * cualquier carácter, ? uno, [a-z] un conjunto, {a,b} cualquiera de los dos, cada uno dentro de un segmento (consulta OSC).
Reglas de argumentosHasta 16 condiciones sobre los argumentos, como en Esperar OSC (consulta Nodos).
ResponderDesactivado: aceptar el mensaje y no responder nada.
Dirección de respuestaLa dirección de la respuesta, una plantilla.
Argumentos de respuestaHasta 16 argumentos, cada uno con un Tipo (int, float, str, long, double, bool, blob, nil) y una plantilla de Valor.
Responder aVacío: de vuelta a la dirección y el puerto del emisor. Si no, IP:port.
Retardo, ms, Jitter, ms0–60 000 ms cada uno.

El valor de un argumento se lee según su tipo una vez rellenada la plantilla: {{request.args[0]}} repite el primer argumento como número cuando el tipo es numérico. Un bool acepta true, 1, yes, on o false, 0, no, off; un blob, bytes en hex; un valor vacío es el cero del tipo.

Las respuestas salen del propio puerto del emulador, así que un cliente que escucha en el puerto desde el que envió las oye.

Una respuesta OSC puede leer {{request.address}}, {{request.args[0]}} y {{request.from}}.

Dispositivo UDP ​

Cada datagrama lo responde la primera regla con la que coincide.

CampoQué
CoincidenciaCualquier datagrama, Contiene el texto, Coincide con la regex o Contiene los bytes (hex).
PatrónEl texto, la expresión regular o los bytes que buscar.
RespuestaAceptarlo sin responder, Texto o Hex, y luego la respuesta en sí como plantilla.
Responder aVacío: de vuelta al emisor. Si no, IP:port.
Retardo, ms, Jitter, ms0–60 000 ms cada uno.

Una respuesta UDP o TCP puede leer:

PlantillaEs
{{request.text}}La carga útil como texto.
{{request.match}}Lo que coincidió: el texto, el primer grupo de una expresión regular (o toda la coincidencia), los bytes.
{{request.hex}}La carga útil como bytes en hex, los primeros 1024.
{{request.bytes}}El tamaño de la carga útil.
{{request.from}}El IP:port del emisor.

Una respuesta de texto tiene como máximo 65 507 bytes.

Dispositivo TCP ​

Un dispositivo que habla por líneas en una conexión TCP, como un proyector o un conmutador matricial. Cada mensaje que envía un cliente lo responde la primera regla con la que coincide; la respuesta vuelve por la misma conexión.

CampoQué
Fin de mensajeLo que termina un mensaje, y se añade tras cada respuesta y tras el saludo: LF (\n) (se descarta un \r delante), CR LF (\r\n), CR (\r) o Ninguno — cada fragmento. Las líneas vacías se omiten.
SaludoSe envía cuando se conecta un cliente; vacío para ninguno. Puede leer {{request.from}}.
Coincidencia, Patrón, RespuestaComo en un dispositivo UDP.
Luego cerrar la conexiónCerrar la conexión tras la respuesta de esta regla; por ejemplo, ante QUIT.
Retardo, ms, Jitter, ms0–60 000 ms cada uno.

Un mensaje de más de 64 KiB sin su delimitador se toma tal cual.

Bróker MQTT ​

Un pequeño bróker MQTT 3.1.1 sobre TCP sin cifrar. Hace lo que hace un bróker: los clientes se conectan, se suscriben con + y #, publican con QoS 0, 1 y 2, los mensajes retenidos y los de última voluntad funcionan, y una segunda conexión con el id de un cliente sustituye a la primera. Las sesiones son siempre limpias: un cliente que pide conservar su sesión recibe una nueva, y no se guarda nada en cola para un cliente ausente.

Además, cada mensaje que se le publica se comprueba con las reglas: la primera que coincide publica también una respuesta, como un dispositivo que informa de lo que ha hecho.

CampoQué
Nombre de usuario, ContraseñaSi se define un nombre de usuario, un cliente debe conectarse con él y con la contraseña; vacío: cualquiera puede conectarse. Una contraseña sin nombre de usuario se rechaza, porque MQTT 3.1.1 no puede transportarla.
RetenidosHasta 64 mensajes (Tema, Carga útil, QoS) guardados desde el inicio, como si se hubieran publicado con retain: un cliente que se suscribe los recibe primero.
Filtro de temasQué temas acepta una regla: + un nivel, # el resto; por ejemplo, lab/+/set.
Coincidencia, PatrónUna condición sobre la carga útil, como en un dispositivo UDP.
ResponderDesactivado: aceptar el mensaje y no publicar nada más.
Tema de respuesta, Carga útil de respuestaPlantillas. El tema no puede contener + ni #.
QoS, RetenerLos de la respuesta.
Retardo, ms, Jitter, ms0–60 000 ms cada uno.

Una respuesta MQTT puede leer {{request.topic}}, {{request.levels[1]}} (los niveles del tema, desde 0), {{request.payload}}, {{request.json.state}}, {{request.match}}, {{request.qos}}, {{request.retain}}, {{request.client}} (el id del cliente) y {{request.from}}.

Plantillas en las respuestas ​

Las respuestas se escriben en el mismo lenguaje de plantillas que los experimentos, así que un campo significa lo mismo aquí y allí. Una respuesta puede leer:

  • request: lo que llegó, según se indica para cada protocolo más arriba;
  • {{counter}}: cuántos mensajes ha aceptado esta regla desde que se inició el emulador, este incluido;
  • los generadores: {{uuid}}, {{now.iso}}, valores aleatorios y los demás; los aleatorios se sortean a partir de la semilla del emulador;
  • parámetros, cuando el emulador funciona en un experimento o se inicia con signallab emulate --param.

Una respuesta nunca lee secretos, y un nombre desconocido es un error, no un texto vacío.

Algunos campos quedan fijados al iniciarse el emulador, antes de que llegue nada: una ruta de acceso, una condición, un patrón de dirección, un patrón de carga útil, un filtro de temas, Responder a, el nombre de un encabezado, los mensajes retenidos y el inicio de sesión del bróker. Solo aceptan texto y parámetros, ni request ni generadores.

La semilla rige el orden aleatorio de las respuestas, el jitter y los generadores aleatorios. En la pantalla Emuladores, cada inicio toma una semilla nueva; un experimento usa la semilla de la ejecución, y signallab emulate --seed toma la que le des.

Caídas ​

Para probar qué hace tu sistema cuando una dependencia va y viene, marca Cae de vez en cuando:

CampoQuéPredeterminado
Activo durante, msCuánto tiempo responde, 10–3 600 000 ms.10 000
Caído durante, msCuánto tiempo está caído, 10–3 600 000 ms.3000
Durante la caídaSolo HTTP: lo que encuentra una solicitud mientras está caído.503 No disponible

El programa empieza cuando se inicia el emulador y se repite: activo, caído, activo, caído… Mientras está caído:

EmuladorEncuentra
HTTP503 No disponible: 503 con Retry-After igual a los segundos que faltan para que vuelva (al menos 1). Cerrar la conexión: la conexión se cierra sin respuesta. Sin respuesta: se retiene hasta 2 minutos y luego se cierra.
Dispositivo TCPLas conexiones abiertas se cortan en menos de 0,1 s; las nuevas se cierran según llegan.
Bróker MQTTSe cortan todas las conexiones; las nuevas se rechazan (CONNACK con código de retorno 3, servidor no disponible).
Dispositivo OSC, UDPNo se responde nada.

Lo que llega mientras está caído se cuenta en Durante la caída, no en Sin regla, y no se consulta a sus reglas.

El botón Dejar caído hace lo mismo a petición, diga lo que diga el programa, hasta que pulsas Levantar; HTTP recibe entonces 503 sin Retry-After. En un experimento, el nodo Emulador caído/activo lo hace en un paso de la ejecución (consulta Nodos y Fallos).

Problemas ​

Mientras editas, el emulador se comprueba un momento después de cada cambio, y un problema aparece bajo sus botones antes de que pulses Iniciar. Un problema indica dónde está (la regla, la respuesta o el mensaje retenido, y el campo) y qué está mal: una ruta de acceso sin su /, una expresión regular que no compila, una plantilla de respuesta que nombra algo que no es request, parámetros o generadores, un valor fuera de rango. Iniciar rechaza un emulador con un problema.

Límites ​

QuéLímiteAl llegar al límite
Rutas o reglas por emulador64Se rechaza al comprobarlo.
Respuestas por ruta16Se rechaza.
Condiciones por ruta16Se rechaza.
Encabezados por respuesta32Se rechaza.
Condiciones de argumentos, argumentos de respuesta (OSC)16 de cadaSe rechaza.
Mensajes retenidos (MQTT)64Se rechaza.
Un cuerpo, una respuesta o un saludo, tal como se escribe256 KiBSe rechaza.
Un retardo o un jitter60 000 msSe rechaza.
Cuerpo de una solicitud HTTP1 MiB413.
Conexiones HTTP a la vez512Las demás se cierran según llegan.
Cabecera de una solicitud HTTP30 sUn cliente debe enviarla en este tiempo.
Conexiones TCP a la vez256Las demás se cierran según llegan.
Respuestas OSC y UDP a la espera de su retardo1024Las demás se descartan y se cuentan en Fallidas.
Clientes MQTT a la vez256Los demás se cierran según llegan.
Paquete MQTT256 KiBLa conexión del cliente termina.
Suscripciones MQTT por cliente100Las demás se rechazan.
Temas MQTT retenidos1000 temas, 16 MiBUn nuevo mensaje retenido se encamina, pero no se retiene.
Mensajes MQTT a la espera de un cliente lento1024 mensajes, 8 MiBEl cliente se los pierde; se cuentan en No entregados.

Simular esto ​

Para crear un emulador a partir de una respuesta que funcionó:

  1. En la pantalla HTTP, envía una solicitud y obtén una respuesta, o usa Enviar ahora en un nodo HTTP de un experimento.
  2. Pulsa ⧉ Simular esto junto a la respuesta. El diálogo Simular esta respuesta muestra la ruta que creará.
  3. En Agregar a, elige uno de tus emuladores HTTP, o Un emulador nuevo.
  4. Pulsa Agregar la ruta. La pantalla Emuladores se abre en ese emulador.

La ruta responde al método y la ruta de acceso de la solicitud (sin la consulta) con el estado, los encabezados y el cuerpo de la respuesta. Los encabezados propios de ese único intercambio (Content-Length, Date, Server, ETag y similares) se omiten, y el cuerpo se envía tal como era, aunque contenga {{. Un emulador nuevo contiene solo esta ruta. Si se añade a un emulador existente, la ruta va la primera, de modo que responde antes que una ruta más general; uno en marcha la incorpora cuando pulsas Reiniciar.

Desde un experimento, una URL escrita con plantillas se convierte en un patrón: su base ({{api}}) se elimina, un segmento que es una sola plantilla (/orders/{{order_id}}) pasa a ser :order_id, y un segmento que solo en parte es plantilla termina la ruta de acceso con *.

El conjunto inicial ​

La primera vez que Signal Lab no encuentra ninguna biblioteca de emuladores, escribe cinco, todos en este equipo. Sus nombres y notas se escriben en el idioma que tenga la interfaz en ese momento.

EmuladorEscucha enHace
API de demostración127.0.0.1:8080GET /health → {"status":"ok","time":…}; GET /users/:id → un usuario con ese id; POST /users → 201 con un Location; GET /slow → al cabo de 1500 ms; /flaky → 503, 503 y luego 200 desde entonces.
Dispositivo OSC de demostración127.0.0.1:9100/ping → /pong con el recuento; /fader/* → /ack con la dirección que recibió; /cue/* se acepta sin respuesta.
Dispositivo UDP de demostración127.0.0.1:7100PING → PONG y el recuento; cualquier otra cosa → ACK y su tamaño en bytes.
Dispositivo TCP de demostración127.0.0.1:7200Líneas que terminan en CR LF. Saluda con READY; POWER? → POWER=ON; POWER ON o POWER OFF → OK ON / OK OFF; QUIT → BYE, y cuelga.
Bróker MQTT de demostración127.0.0.1:1883Retiene online en lab/status; ON u OFF publicado en lab/<name>/set → lo mismo, retenido, en lab/<name>/state.

La señal inicial ¿Está activo el servicio? de la biblioteca de señales pregunta a http://127.0.0.1:8080/, la dirección de la API de demostración: como esta no tiene ninguna ruta para /, recibe 404.

El archivo de la biblioteca ​

La biblioteca es emulators.json, en la carpeta de datos (consulta Archivos); pasa el puntero por encima del recuento bajo la lista para ver su ruta. Se escribe entero 0,7 s después del último cambio, a través de un archivo temporal, así que una escritura fallida deja el anterior. Si el archivo no se puede leer, la lista muestra el error con la ruta, la línea y la columna, y el archivo se deja como está: corrígelo y pulsa Recargar el archivo. Pulsa también Recargar el archivo después de editarlo a mano. Si no hay archivo, se vuelve a escribir el conjunto inicial.

json
{
  "version": 1,
  "emulators": [
    {
      "id": "orders-api",
      "note": "Stands in for the orders service.",
      "emulator": {
        "name": "Orders API",
        "bind": "127.0.0.1:18080",
        "protocol": "http",
        "routes": [
          { "method": "GET", "path": "/orders/:id",
            "responses": [{ "body": "{\"id\":\"{{request.params.id}}\",\"state\":\"open\"}" }] },
          { "method": "POST", "path": "/orders", "order": "sequence",
            "responses": [{ "status": 503 }, { "status": 201, "body": "{\"id\":\"{{uuid}}\"}" }] }
        ],
        "outage": { "up_ms": 20000, "down_ms": 2000, "fault": "unavailable" }
      }
    }
  ]
}

El objeto emulator por sí solo es un documento que también lee signallab emulate.

En experimentos y scripts ​

  • En un experimento, un nodo Emulador abre su emulador antes del primer paso y responde hasta que termina la ejecución; lo que recibió se cuenta en el informe. Un emulador HTTP es ahí también lo que escucha Esperar solicitud HTTP (Nodos), y un emulador OSC o UDP comparte su puerto con las esperas de la ejecución. Dos emuladores del mismo transporte en un experimento no pueden compartir un puerto. Consulta Nodos y Fallos.
  • signallab emulate ejecuta emuladores desde archivos o desde esta biblioteca hasta Ctrl+C o --for, mostrando lo que responden; consulta La línea de comandos.