Lance l'optimiseur de $ETM_POWERSYNC_OPTIMIZER_CMD (défaut : la référence, mode normal) et y branche le vrai moteur : handshake direct accepté, GetPlan répondus sous 10 s, session entière conforme au contrat embarqué (règles sémantiques comprises), chaque plan appliqué sans fallbackCode, consigne hors bornes écrêtée et surcharge délestée par L4. Relais transparent pour capturer la session. README : la lancer contre un autre optimiseur. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
59 lines
4.3 KiB
Markdown
59 lines
4.3 KiB
Markdown
# `etm-powersync-optimizer-conformance` — conformité d'un optimiseur quelconque
|
||
|
||
Suite de test du moteur (Qt Test, harnais nymea du dépôt). Elle lance **votre** optimiseur, branche
|
||
dessus le **vrai** moteur — serveur nymea, arbitre, `SocketScheduler`, `OptimizerClient`,
|
||
adaptateurs, sur les mocks de la suite `simulation` — et vérifie, une fonction par point :
|
||
|
||
| Fonction | Ce qui est vérifié |
|
||
|---|---|
|
||
| `testHandshakeIsAccepted` | le client du moteur, **directement** sur l'optimiseur, passe le handshake (§3) : majeure 1, aucun code d'erreur |
|
||
| `testGetPlanIsAnsweredInTime` | 8 cycles : chaque `GetPlan` répondu sous le délai du moteur (10 s), aucun échec de requête ; latence max affichée |
|
||
| `testTheSessionMatchesTheContract` | la session entière (les deux sens) est conforme au contrat OpenRPC **embarqué** dans le moteur, règles sémantiques comprises (`tools/etm-powersync-schema-check --semantic`) |
|
||
| `testEveryPlanIsAccepted` | à chaque cycle, le plan est **appliqué** : l'optimiseur commande, `GetPlan` sans `fallbackCode` |
|
||
| `testTheSafetyLoopStaysOnTop` | la boucle de sécurité reste au-dessus : une consigne hors bornes (réécrite en 100 kW par le relais de test) est **écrêtée** par l'adaptateur (`clamped`), une surcharge de phase est **délestée** par L4 |
|
||
|
||
Les fonctions 2 à 5 passent par un relais transparent (une ligne reçue = une ligne renvoyée) qui
|
||
capture la session et mesure les délais ; la 5 est la seule où il réécrit une réponse. Banc : deux
|
||
charges `etmvariableload` (0–2 000 W ; plancher 800, 3 000 W) et une PAC SG-Ready (P3 1 500 W,
|
||
P4 3 000 W) ; surplus de −1 000 à 9 000 W.
|
||
|
||
## Lancer contre un autre optimiseur
|
||
|
||
Construire le moteur avec ses tests (`qmake6 …/etm-powersync-energy-plugin-etm.pro CONFIG+=build_tests
|
||
&& make -j4`), puis, **un processus par fonction** (le harnais nymea ne rend pas sa mémoire entre deux
|
||
tests, `AGENTS.md`) :
|
||
|
||
```sh
|
||
cd <build>/tests/auto/conformance
|
||
export NYMEA_PLUGINS_PATH=<build>/tests/mocks/plugins/energymocks:/usr/lib/x86_64-linux-gnu/nymea/plugins
|
||
export ETM_POWERSYNC_OPTIMIZER_CMD='exec /chemin/de/mon-optimiseur --listen {endpoint}'
|
||
for fn in testHandshakeIsAccepted testGetPlanIsAnsweredInTime testTheSessionMatchesTheContract \
|
||
testEveryPlanIsAccepted testTheSafetyLoopStaysOnTop; do
|
||
systemd-run --user --scope -q -p MemoryMax=2G \
|
||
bwrap --dev-bind / / --unshare-net --tmpfs /tmp --bind "$PWD/../../.." "$PWD/../../.." \
|
||
--bind <sources> <sources> --chdir "$PWD" ./target_wrapper.sh ./etm-powersync-optimizer-conformance "$fn"
|
||
done
|
||
```
|
||
|
||
`bwrap --unshare-net` est recommandé : le harnais ouvre des ports fixes, et l'optimiseur que lance la
|
||
commande vit dans le même réseau privé (la boucle locale y fonctionne, `tcp://127.0.0.1:…` compris).
|
||
|
||
| Variable | Défaut | Sens |
|
||
|---|---|---|
|
||
| `ETM_POWERSYNC_OPTIMIZER_CMD` | l'optimiseur de référence du dépôt, mode `normal` | Commande qui démarre le **serveur** (`/bin/sh -c`, dans son propre groupe de processus, arrêtée par SIGTERM puis SIGKILL). `{endpoint}` y est remplacé par l'endpoint où écouter, aussi passé dans `ETM_POWERSYNC_OPTIMIZER_ENDPOINT`. `-` : ne rien lancer, l'optimiseur écoute déjà |
|
||
| `ETM_POWERSYNC_OPTIMIZER_ENDPOINT` | `unix://<répertoire temporaire du test>/optimiseur.sock` | Où l'optimiseur écoute (`unix:///…` ou `tcp://hôte:port`) |
|
||
| `ETM_POWERSYNC_OPTIMIZER_TOKEN_FILE` | aucun | Fichier du token que l'optimiseur attend ; le moteur l'envoie au handshake (16 caractères au moins) |
|
||
| `ETM_POWERSYNC_OPTIMIZER_START_S` | `15` | Délai pour que l'endpoint accepte une connexion |
|
||
| `ETM_POWERSYNC_SOURCE_DIR` | sources du build | Racine où trouver le validateur et l'optimiseur de référence |
|
||
|
||
L'attente de démarrage ouvre une connexion de sonde, refermée sans handshake : un serveur conforme
|
||
la tolère. Un échec dit ce qui manque — code d'erreur du client, écart au contrat (chemin, mot-clé),
|
||
cycles non appliqués avec leur `fallbackCode`, latences.
|
||
|
||
## Ce qu'elle ne vérifie pas
|
||
|
||
La **qualité** des plans (aucune comparaison au rule-based : c'est `refoptimizer`, pour la référence
|
||
seulement), les bornes VE (aucune borne au banc), `UpdateLearned` (ignoré par le moteur 1.1), le
|
||
comportement sous défaut de transport. Le contrat : `docs/etm-powersync-optimizer-protocol.openrpc.json`
|
||
(prose : `docs/OPTIMIZER_PROTOCOL.md`, annexe G).
|