Émulateurs
Un émulateur, c’est Signal Lab qui joue l’API, l’appareil ou le service auquel votre système s’adresse. Il écoute sur une adresse et répond selon des règles : une API HTTP par routes, un appareil OSC, UDP ou TCP par « sur ceci, répondre cela », un broker MQTT comme le fait tout broker, plus des règles qui lui sont propres. Il peut être lent, échouer ou tomber en panne de temps en temps, pour que vous puissiez tester ce que fait votre système quand sa dépendance se comporte mal. Chaque échange est compté, listé et envoyé à l’Inspecteur.
Un émulateur est un seul document. L’écran Émulateurs en conserve une bibliothèque ; le même document s’exécute dans une expérience comme nœud Émulateur, depuis la ligne de commande avec signallab emulate, et via l’API et MCP, et répond de la même façon partout.
L’écran
À gauche se trouve la bibliothèque (Bibliothèque) : chaque émulateur avec son protocole et son adresse, un point qui pulse et un compteur de requêtes sur ceux qui tournent. À droite se trouvent les réglages et les règles de l’émulateur sélectionné, et en dessous ce qu’il a reçu (En direct).
Créer un émulateur
Appuyez sur l’un des boutons en haut de la bibliothèque :
Bouton Crée Écoute sur Avec une règle qui fonctionne telle quelle + API HTTP Une API HTTP 127.0.0.1:18080GET /health→ 200{"status":"ok"}+ Appareil OSC Un appareil OSC 127.0.0.1:9100/ping→/pongavec le compteur en int+ Appareil UDP Un appareil UDP 127.0.0.1:7100un datagramme contenant PING→PONG 1,PONG 2, …+ Appareil TCP Un appareil TCP 127.0.0.1:7200une ligne contenant PING→PONG+ Broker MQTT Un broker MQTT 127.0.0.1:1883une publication sur lab/<name>/set→ la même charge utile, retenue, surlab/<name>/stateQuand un autre émulateur de la bibliothèque utilise déjà ce port, le port libre suivant est pris.
Donnez-lui un nom dans le champ Nom (120 caractères au plus).
Réglez le champ Écouter sur :
IP:port.127.0.0.1ne répond qu’à cet ordinateur ;0.0.0.0répond aussi au réseau.Modifiez les règles (voir plus bas), et indiquez dans le champ Note ce qu’il remplace.
Les modifications s’enregistrent d’elles-mêmes. Le bouton Dupliquer crée une copie sur le port libre suivant. Le bouton Supprimer demande une confirmation (Supprimer ?), arrête l’émulateur s’il tourne et le retire de la bibliothèque.
Les règles sont essayées dans l’ordre, de la première à la dernière ; la première qui correspond répond. L’en-tête de chaque règle affiche un résumé d’une ligne ; cliquez dessus pour déplier ou replier la règle. Les boutons ↑ et ↓ déplacent une règle, × la supprime.
L’exécuter
- Sélectionnez l’émulateur et appuyez sur Démarrer. Son port s’ouvre avant que le bouton ne revienne : un port déjà pris, ou un émulateur qui a un problème, est refusé à ce moment-là avec la raison.
- Dirigez votre système vers lui. Pour une API HTTP, le bouton Copier l’URL copie son adresse (
http://127.0.0.1:18080), et chaque route a son propre bouton Copier l’URL (sauf quand son chemin contient un modèle{{…}}). - Regardez la liste Reçus se remplir.
- Appuyez sur Arrêter, ou arrêtez sa tâche depuis le bandeau de la console.
L’état affiché à côté des boutons indique Arrêté, l’adresse où il répond, ou qu’il est en panne.
Un émulateur continue de répondre avec les règles avec lesquelles il a démarré. Quand vous le modifiez pendant qu’il tourne, le bouton Redémarrer apparaît : appuyez dessus pour redémarrer avec les règles telles qu’elles sont maintenant. D’ici là, les compteurs de correspondances des règles sont masqués, car ils appartiennent aux anciennes règles.
Le bouton Mettre en panne rend un émulateur en cours indisponible jusqu’à ce que vous appuyiez sur Réactiver : une requête HTTP reçoit 503, un appareil TCP et un broker MQTT coupent leurs connexions et refusent les nouvelles, un appareil OSC ou UDP ne répond plus. Voir Tomber en panne.
Deux émulateurs d’un même transport ne peuvent pas partager un port : les émulateurs HTTP, TCP et MQTT écoutent sur des ports TCP, les émulateurs OSC et UDP sur des ports UDP. Une API HTTP et un appareil OSC peuvent tous deux utiliser le port 8080 ; deux API HTTP ne le peuvent pas. Un second émulateur sur un port pris est refusé au démarrage.
TIP
Dans un navigateur connecté à un serveur, l’émulateur tourne sur le serveur. Celui qui écoute sur 0.0.0.0 est joint par le nom du serveur, et Copier l’URL copie cette adresse ; celui qui écoute sur 127.0.0.1 ne répond qu’aux programmes du serveur lui-même.
Ce qui est arrivé
Pendant qu’il tourne, le panneau En direct compte :
| Compteur | Quoi |
|---|---|
| Requêtes | Tout ce qui est arrivé : requêtes, messages, lignes. |
| Sans règle | Ce qu’aucune règle n’a pris. Une requête HTTP sans route reçoit tout de même sa réponse (voir Requêtes qu’aucune route ne prend) ; les autres n’en reçoivent aucune. |
| En échec | Les échanges pour lesquels une réponse n’a pas pu être construite ou envoyée. |
| Pendant la panne | Ce qui est arrivé pendant que l’émulateur était en panne. Affiché quand une panne est programmée ou que quelque chose l’a trouvé en panne. Jamais compté comme Sans règle. |
| Non remis | MQTT uniquement, quand cela se produit : les messages qu’un client avait trop de retard pour recevoir. |
L’en-tête de chaque règle indique combien de fois elle a correspondu depuis le démarrage.
La liste Reçus affiche les 300 échanges les plus récents, le plus récent en premier :
| Colonne | Quoi |
|---|---|
| Heure | Quand il est arrivé. |
| Source | L’adresse du client. |
| Requête | Ce qui est arrivé, en notation du protocole : GET /users/7, /ping 1, POWER?. |
| Règle | La règle qui l’a pris (#2), ou —. |
| Réponse | Ce qui est reparti : 200 OK · 37 B, /pong 3, une charge utile ; retenu ou fermé pour une défaillance ; l’erreur quand la réponse a échoué ; en panne quand il est arrivé pendant une panne. |
| ms | De l’arrivée jusqu’au départ de la réponse, délai compris. |
Le bouton ⌕ d’une ligne (Ouvrir dans l’Inspecteur) ouvre cet échange dans l’Inspecteur, si la capture était active. Quand plus de 200 échanges arrivent en un cinquième de seconde, la liste en saute certains et indique combien. Le moteur conserve les 500 échanges les plus récents de chaque émulateur en cours, avec ce qui est arrivé, pour la ligne de commande, l’API et MCP.
API HTTP
Un serveur HTTP/1.1. Chaque requête reçoit la réponse de la première route qui la prend.
Routes
Une route prend une requête quand sa méthode, son chemin et toutes ses conditions correspondent.
| Champ | Quoi |
|---|---|
| Méthode | GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS, ou Toutes. Une route GET répond aussi à HEAD. |
| Chemin | Commence par /. Un segment :name prend n’importe quel segment unique, lu comme {{request.params.name}} ; un dernier segment * prend tout ce qui se trouve en dessous. Un / final ne change rien ; la chaîne de requête ne fait pas partie du chemin. |
| Conditions | Chacune doit être remplie. Ajoutez-en une avec + Condition. |
Exemples de chemins :
| Chemin | Prend | Ne prend pas |
|---|---|---|
/health | /health, /health/ | /health/db, /Health |
/users/:id | /users/7 (params.id vaut 7), /users/a%20b (a b) | /users, /users/7/orders |
/files/* | /files, /files/a, /files/a/b/c | /file, /other/files/a |
Une condition lit une partie de la requête (Où) et la compare :
| Où | Nom | Lit |
|---|---|---|
| En-tête | Un nom d’en-tête, casse indifférente | La valeur de l’en-tête ; pour un en-tête envoyé plusieurs fois, ses valeurs jointes par , . |
| Paramètres d’URL | Un paramètre de la chaîne de requête | Sa valeur, décodée ; la première, s’il est répété. |
| Corps | — | Tout le corps, en texte. |
| JSON | Un chemin JSON, comme $.user.id | Ce champ d’un corps JSON. |
Les comparaisons sont égal à, différent de, inférieur à, au plus, supérieur à, au moins, contient, correspond à la regex, est vide et n’est pas vide. Les nombres se comparent comme des nombres, le texte à l’identique. Un en-tête, un paramètre ou un champ absent est vide. Une comparaison impossible — du texte face à un nombre — n’est pas remplie.
Réponses
Une route a de une à 16 réponses (Réponses).
| Champ | Quoi | Par défaut |
|---|---|---|
| Statut | 100–599. | 200 |
| Défaillance | Autre chose qu’une réponse ; voir Défaillances. | Aucune — répondre |
| Délai, ms | Combien de temps attendre avant de répondre, 0–60 000 ms. | 0 |
| Gigue, ms | Jusqu’à autant de plus, au hasard, 0–60 000 ms. | 0 |
| Poids | Sa part quand la route répond au hasard. Affiché seulement dans ce cas. | 1 |
| En-têtes | Jusqu’à 32. Les noms peuvent utiliser des paramètres ; les valeurs sont des modèles. | aucun |
| Corps | Un modèle, jusqu’à 256 Kio tel qu’écrit. | vide |
Sans en-tête Content-Type, un corps qui est du JSON valide part en application/json et tout autre corps en text/plain; charset=utf-8.
Avec deux réponses ou plus, le champ Quelle réponse décide laquelle une requête reçoit :
| Quelle réponse | Les requêtes reçoivent | Pour |
|---|---|---|
| Dans l’ordre, puis la dernière | La première, la deuxième, …, puis la dernière à partir de là : 500, 500, 200, 200, 200… | Les réessais : échouer deux fois, puis fonctionner. |
| À tour de rôle | De nouveau la première après la dernière : 200, 500, 200, 500… | Une dépendance qui échoue de temps en temps, régulièrement. |
| Au hasard, selon le poids | Chacune tirée selon son poids. Des poids de 8 et 2 donnent la première environ 80 % du temps. Au moins un poids doit être supérieur à 0. | Une part réaliste d’échecs. |
Le menu Ajouter une réponse ajoute à la route une réponse toute prête :
| Préréglage | Ajoute |
|---|---|
| 200 JSON | 200, {"ok":true} |
| 201 Created | 201, {"id":"{{uuid}}"}, en-tête Location: {{request.path}}/{{counter}} |
| 404 Not found | 404, {"error":"not found"} |
| 500 Server error | 500, {"error":"internal"} |
| 503 Unavailable | 503, {"error":"unavailable"}, en-tête Retry-After: 1 |
| Lente — 2 s | 200, {"ok":true} au bout de 2000 ms |
| Pas de réponse | La défaillance Pas de réponse |
| Connexion fermée | La défaillance Fermer la connexion |
| JSON mal formé | 200, {"items":[{"id":1},{"id":2}]} avec la défaillance Corps mal formé |
Défaillances
| Défaillance | Ce que rencontre le client |
|---|---|
| Aucune — répondre | La réponse. |
| Pas de réponse | Rien. La requête est retenue jusqu’à 2 minutes, puis la connexion est fermée — c’est donc le délai d’attente du client lui-même qui est testé. Le délai ne s’applique pas. |
| Fermer la connexion | La connexion se ferme sans réponse, après le délai. |
| Corps mal formé | Une réponse HTTP complète, avec le statut et les en-têtes définis, dont le corps s’arrête à mi-chemin : du JSON qui ne s’analyse pas. Quand tout le corps était du JSON, le type de contenu indique toujours application/json. |
Requêtes qu’aucune route ne prend
Le champ Requêtes qu’aucune route ne prend décide de ce que reçoit une requête qui ne correspond à aucune route :
- 404 Not found — 404 avec le corps
{"error":"no_route"}; - Cette réponse — une réponse que vous définissez, avec tout ce qu’a la réponse d’une route. Son
{{counter}}compte les requêtes qu’aucune route n’a prises.
Dans les deux cas, la requête compte comme Sans règle.
Ce qu’une réponse HTTP peut lire
| Modèle | Valeur |
|---|---|
{{request.method}} | GET, POST, … |
{{request.path}} | Le chemin, sans la chaîne de requête. |
{{request.params.id}} | Le segment de chemin nommé :id. |
{{request.query.page}} | Un paramètre de la chaîne de requête, décodé. |
{{request.headers.x-key}} | Un en-tête ; noms en minuscules. |
{{request.body}} | Le corps en texte : ses 64 premiers Kio. |
{{request.json.name}} | Un champ d’un corps JSON, quand le corps est du JSON et tient dans 64 Kio. |
{{request.from}} | L’IP:port du client. |
Un corps de requête de plus de 1 Mio reçoit 413 et est compté comme En échec. Une réponse qui ne peut pas être construite — un modèle qui nomme quelque chose que la requête n’a pas — reçoit 500 avec l’erreur dans son corps, et est comptée comme En échec.
Appareil OSC
Chaque message qui arrive — chaque message d’un bundle séparément — reçoit la réponse de la première règle à laquelle il correspond. Un datagramme qui n’est pas de l’OSC est compté comme Sans règle.
| Champ | Quoi |
|---|---|
| Motif d’adresse | Un motif d’adresse OSC 1.0 : * n’importe quels caractères, ? un seul, [a-z] un ensemble, {a,b} l’un ou l’autre, chacun à l’intérieur d’un segment (voir OSC). |
| Règles d’arguments | Jusqu’à 16 conditions sur les arguments, comme dans Attente OSC (voir Nœuds). |
| Répondre | Désactivé : prendre le message sans rien répondre. |
| Adresse de réponse | L’adresse de la réponse, un modèle. |
| Arguments de réponse | Jusqu’à 16 arguments, chacun avec un Type (int, float, str, long, double, bool, blob, nil) et une Valeur sous forme de modèle. |
| Répondre à | Vide : retour à l’adresse et au port de l’expéditeur. Sinon IP:port. |
| Délai, ms, Gigue, ms | 0–60 000 ms chacun. |
La valeur d’un argument est lue selon son type une fois le modèle rempli : {{request.args[0]}} renvoie le premier argument comme nombre quand le type est numérique. Un bool accepte true, 1, yes, on ou false, 0, no, off ; un blob accepte des octets en hex ; une valeur vide est le zéro du type.
Les réponses partent du port propre à l’émulateur : un client qui écoute sur le port depuis lequel il a envoyé les entend.
Une réponse OSC peut lire {{request.address}}, {{request.args[0]}} et {{request.from}}.
Appareil UDP
Chaque datagramme reçoit la réponse de la première règle à laquelle il correspond.
| Champ | Quoi |
|---|---|
| Correspondance | N’importe quel datagramme, Contient le texte, Correspond à la regex ou Contient les octets (hex). |
| Motif | Le texte, l’expression régulière ou les octets à rechercher. |
| Réponse | Recevoir sans répondre, Texte ou Hex, puis la réponse elle-même sous forme de modèle. |
| Répondre à | Vide : retour à l’expéditeur. Sinon IP:port. |
| Délai, ms, Gigue, ms | 0–60 000 ms chacun. |
Une réponse UDP ou TCP peut lire :
| Modèle | Valeur |
|---|---|
{{request.text}} | La charge utile en texte. |
{{request.match}} | Ce qui a correspondu : le texte, le premier groupe d’une expression régulière (ou toute la correspondance), les octets. |
{{request.hex}} | La charge utile en octets hex, ses 1024 premiers. |
{{request.bytes}} | La taille de la charge utile. |
{{request.from}} | L’IP:port de l’expéditeur. |
Une réponse texte fait au plus 65 507 octets.
Appareil TCP
Un appareil qui parle par lignes sur une connexion TCP, comme un projecteur ou une matrice de commutation. Chaque message qu’envoie un client reçoit la réponse de la première règle à laquelle il correspond ; la réponse revient sur la même connexion.
| Champ | Quoi |
|---|---|
| Fin de message | Ce qui termine un message, et qui est ajouté après chaque réponse et après l’accueil : LF (\n) (un \r qui le précède est supprimé), CR LF (\r\n), CR (\r), ou Aucune — chaque segment. Les lignes vides sont ignorées. |
| Accueil | Envoyé quand un client se connecte ; vide pour aucun. Il peut lire {{request.from}}. |
| Correspondance, Motif, Réponse | Comme pour un appareil UDP. |
| Puis fermer la connexion | Fermer la connexion après la réponse de cette règle — à QUIT, par exemple. |
| Délai, ms, Gigue, ms | 0–60 000 ms chacun. |
Un message de plus de 64 Kio sans son délimiteur est pris tel quel.
Broker MQTT
Un petit broker MQTT 3.1.1 sur TCP simple. Il fait ce que fait un broker : les clients se connectent, s’abonnent avec + et #, publient en QoS 0, 1 et 2, les messages retenus et les messages de dernière volonté fonctionnent, et une seconde connexion avec l’identifiant d’un client prend le relais de la première. Les sessions sont toujours propres : un client qui demande à garder sa session en reçoit une neuve, et rien n’est mis en file pour un client absent.
En plus, chaque message qui lui est publié est confronté aux règles : la première qui correspond publie aussi une réponse — un appareil qui rend compte de ce qu’il a fait.
| Champ | Quoi |
|---|---|
| Nom d’utilisateur, Mot de passe | Quand un nom d’utilisateur est défini, un client doit se connecter avec celui-ci et le mot de passe ; vide : tout le monde peut se connecter. Un mot de passe sans nom d’utilisateur est refusé, car MQTT 3.1.1 ne peut pas le transporter. |
| Retenus | Jusqu’à 64 messages (Topic, Charge utile, QoS) présents dès le démarrage, comme s’ils avaient été publiés avec retain : un client qui s’abonne les reçoit en premier. |
| Filtre de topic | Les topics que prend une règle : + un niveau, # le reste — lab/+/set. |
| Correspondance, Motif | Une condition sur la charge utile, comme pour un appareil UDP. |
| Répondre | Désactivé : prendre le message sans rien publier de plus. |
| Topic de réponse, Charge utile de réponse | Des modèles. Le topic ne peut pas contenir + ni #. |
| QoS, Retain | Ceux de la réponse. |
| Délai, ms, Gigue, ms | 0–60 000 ms chacun. |
Une réponse MQTT peut lire {{request.topic}}, {{request.levels[1]}} (les niveaux du topic, à partir de 0), {{request.payload}}, {{request.json.state}}, {{request.match}}, {{request.qos}}, {{request.retain}}, {{request.client}} (l’identifiant du client) et {{request.from}}.
Modèles dans les réponses
Les réponses s’écrivent dans le même langage de modèles que les expériences : un champ signifie donc la même chose ici et là. Une réponse peut lire :
request— ce qui est arrivé, comme listé plus haut pour chaque protocole ;{{counter}}— combien de messages cette règle a pris depuis le démarrage de l’émulateur, celui-ci compris ;- les générateurs —
{{uuid}},{{now.iso}}, les valeurs aléatoires et les autres ; les aléatoires sont tirés de la graine de l’émulateur ; - les paramètres, quand l’émulateur tourne dans une expérience ou est démarré avec
signallab emulate --param.
Une réponse ne lit jamais de secrets, et un nom inconnu est une erreur, pas un texte vide.
Certains champs sont fixés au démarrage de l’émulateur, avant que quoi que ce soit n’arrive : un chemin, une condition, un motif d’adresse, un motif de charge utile, un filtre de topic, Répondre à, le nom d’un en-tête, les messages retenus et les identifiants de connexion du broker. Ils n’acceptent que du texte et des paramètres, ni request ni générateurs.
La graine pilote l’ordre aléatoire des réponses, la gigue et les générateurs aléatoires. Sur l’écran Émulateurs, chaque démarrage prend une nouvelle graine ; une expérience utilise la graine de l’exécution, et signallab emulate --seed prend celle que vous donnez.
Tomber en panne
Pour tester ce que fait votre système quand une dépendance flanche par intermittence, cochez Tombe en panne de temps en temps :
| Champ | Quoi | Par défaut |
|---|---|---|
| En service, ms | Combien de temps il répond, 10–3 600 000 ms. | 10 000 |
| En panne, ms | Combien de temps il est en panne, 10–3 600 000 ms. | 3000 |
| Pendant la panne | HTTP uniquement : ce que rencontre une requête pendant la panne. | 503 Unavailable |
Le calendrier démarre avec l’émulateur et se répète : en service, en panne, en service, en panne… Pendant la panne :
| Émulateur | Ce qui se passe |
|---|---|
| HTTP | 503 Unavailable : 503 avec Retry-After réglé sur le nombre de secondes avant son retour (au moins 1). Fermer la connexion : la connexion se ferme sans réponse. Pas de réponse : retenue jusqu’à 2 minutes, puis fermée. |
| Appareil TCP | Les connexions ouvertes sont coupées en moins de 0,1 s ; les nouvelles sont fermées dès leur arrivée. |
| Broker MQTT | Toutes les connexions sont coupées ; les nouvelles sont refusées (code de retour CONNACK 3, serveur indisponible). |
| Appareil OSC, UDP | Rien ne reçoit de réponse. |
Ce qui arrive pendant la panne compte comme Pendant la panne, pas comme Sans règle, et ses règles ne sont pas consultées.
Le bouton Mettre en panne fait la même chose à la demande, quoi que dise le calendrier, jusqu’à ce que vous appuyiez sur Réactiver ; HTTP reçoit alors 503 sans Retry-After. Dans une expérience, le nœud Émulateur en panne/en service le fait à une étape de l’exécution (voir Nœuds et Défaillances).
Problèmes
Pendant que vous le modifiez, l’émulateur est vérifié un instant après chaque changement, et un problème s’affiche sous ses boutons avant que vous n’appuyiez sur Démarrer. Un problème indique où il se trouve — la règle, la réponse ou le message retenu, et le champ — et ce qui ne va pas : un chemin sans son /, une expression régulière qui ne compile pas, un modèle de réponse qui nomme autre chose que request, les paramètres et les générateurs, une valeur hors limites. Le bouton Démarrer refuse un émulateur qui a un problème.
Limites
| Quoi | Limite | À la limite |
|---|---|---|
| Routes ou règles par émulateur | 64 | Refusé à la vérification. |
| Réponses par route | 16 | Refusé. |
| Conditions par route | 16 | Refusé. |
| En-têtes par réponse | 32 | Refusé. |
| Conditions sur les arguments, arguments de réponse (OSC) | 16 chacun | Refusé. |
| Messages retenus (MQTT) | 64 | Refusé. |
| Un corps, une réponse ou un accueil tel qu’écrit | 256 Kio | Refusé. |
| Un délai ou une gigue | 60 000 ms | Refusé. |
| Corps de requête HTTP | 1 Mio | 413. |
| Connexions HTTP simultanées | 512 | Les suivantes sont fermées dès leur arrivée. |
| En-tête de requête HTTP | 30 s | Un client doit l’envoyer dans ce délai. |
| Connexions TCP simultanées | 256 | Les suivantes sont fermées dès leur arrivée. |
| Réponses OSC et UDP en attente de leur délai | 1024 | Les suivantes sont abandonnées et comptées comme En échec. |
| Clients MQTT simultanés | 256 | Les suivants sont fermés dès leur arrivée. |
| Paquet MQTT | 256 Kio | La connexion du client prend fin. |
| Abonnements MQTT par client | 100 | Les suivants sont refusés. |
| Topics MQTT retenus | 1000 topics, 16 Mio | Un nouveau message retenu est acheminé, mais pas retenu. |
| Messages MQTT en attente pour un client lent | 1024 messages, 8 Mio | Il les manque ; comptés comme Non remis. |
Émuler ceci
Pour créer un émulateur à partir d’une réponse qui a fonctionné :
- Sur l’écran HTTP, envoyez une requête et obtenez une réponse — ou utilisez le bouton Envoyer maintenant sur un nœud HTTP d’une expérience.
- Appuyez sur ⧉ Émuler ceci à côté de la réponse. La boîte de dialogue Émuler cette réponse montre la route qu’elle va créer.
- Dans le champ Ajouter à, choisissez l’un de vos émulateurs HTTP, ou Un nouvel émulateur.
- Appuyez sur Ajouter la route. L’écran Émulateurs s’ouvre sur cet émulateur.
La route répond à la méthode et au chemin de la requête (sans la chaîne de requête) avec le statut, les en-têtes et le corps de la réponse. Les en-têtes propres à cet échange-là (Content-Length, Date, Server, ETag et autres) sont omis, et le corps est envoyé tel quel, même s’il contient {{. Un nouvel émulateur ne contient que cette route. Ajoutée à un émulateur existant, la route passe en premier, pour répondre avant une route plus large ; un émulateur en cours la prend en compte quand vous appuyez sur Redémarrer.
Depuis une expérience, une URL écrite avec des modèles devient un motif : sa base ({{api}}) est supprimée, un segment qui est un seul modèle (/orders/{{order_id}}) devient :order_id, et un segment modélisé seulement en partie termine le chemin par *.
Le jeu de départ
La première fois que Signal Lab ne trouve pas de bibliothèque d’émulateurs, il en écrit cinq, tous sur cet ordinateur. Leurs noms et leurs notes sont écrits dans la langue de l’interface à ce moment-là.
| Émulateur | Écoute sur | Fait |
|---|---|---|
| API de démonstration | 127.0.0.1:8080 | GET /health → {"status":"ok","time":…} ; GET /users/:id → un utilisateur avec cet identifiant ; POST /users → 201 avec un Location ; GET /slow → au bout de 1500 ms ; /flaky → 503, 503, puis 200 à partir de là. |
| Appareil OSC de démonstration | 127.0.0.1:9100 | /ping → /pong avec le compteur ; /fader/* → /ack avec l’adresse reçue ; /cue/* pris sans réponse. |
| Appareil UDP de démonstration | 127.0.0.1:7100 | PING → PONG et le compteur ; tout le reste → ACK et sa taille en octets. |
| Appareil TCP de démonstration | 127.0.0.1:7200 | Lignes terminées par CR LF. Accueille avec READY ; POWER? → POWER=ON ; POWER ON ou POWER OFF → OK ON / OK OFF ; QUIT → BYE, puis raccroche. |
| Broker MQTT de démonstration | 127.0.0.1:1883 | Retient online sur lab/status ; ON ou OFF publié sur lab/<name>/set → la même chose, retenue, sur lab/<name>/state. |
Le signal de départ Le service répond-il ? de la bibliothèque de signaux interroge http://127.0.0.1:8080/, l’adresse de l’émulateur API de démonstration : celui-ci n’a pas de route pour /, il reçoit donc 404.
Le fichier de la bibliothèque
La bibliothèque est emulators.json dans le dossier de données (voir Fichiers) ; survolez le compteur sous la liste pour voir son chemin. Il est écrit en entier 0,7 s après la dernière modification, via un fichier temporaire : une écriture ratée laisse donc le précédent intact. Si le fichier ne peut pas être lu, la liste affiche l’erreur avec le chemin, la ligne et la colonne, et le fichier est laissé tel quel : corrigez-le et appuyez sur Recharger le fichier. Appuyez aussi sur Recharger le fichier après l’avoir modifié à la main. Sans fichier, le jeu de départ est réécrit.
{
"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" }
}
}
]
}L’objet emulator seul est un document que signallab emulate lit aussi.
Dans les expériences et les scripts
- Dans une expérience, un nœud Émulateur ouvre son émulateur avant la première étape et répond jusqu’à la fin de l’exécution ; ce qu’il a reçu est compté dans le rapport. Un émulateur HTTP y est aussi ce qu’écoute Attente de requête HTTP (Nœuds), et un émulateur OSC ou UDP partage son port avec les attentes de l’exécution. Deux émulateurs d’un même transport dans une même expérience ne peuvent pas partager un port. Voir Nœuds et Défaillances.
signallab emulateexécute des émulateurs depuis des fichiers ou depuis cette bibliothèque jusqu’à Ctrl+C ou--for, en affichant ce qu’ils répondent ; voir La ligne de commande.
Voir aussi
- Inspecteur — chaque échange, décodé.
- Dégradation — un mauvais réseau entre votre système et un émulateur.
- Données et modèles