fix(tests): la suite de simulation ne compilait plus depuis bb674e5
Le lot E §12 a ajouté le paramètre minPowerW au constructeur
d'EtmVariableLoadAdapter sans le répercuter sur les cinq sites d'appel de
tests/auto/simulation. La suite ne compile donc plus depuis ce commit —
autrement dit, personne ne l'a exécutée depuis. Les cinq sites passent
désormais minPowerW = 0 explicitement.
Deux attentes avaient rouillé pendant ce temps, et les deux portent sur du
TEXTE publié — ce qui est précisément ce que ces tests doivent surveiller :
- testEcsColdStartLockExpires attendait « insuffisant » là où 9a69f46 a
délibérément fait sortir BELOW_MIN_POWER. Le cas est « il y a un budget,
il n'est pas au bon FORMAT » : le motif doit nommer le palier. Ce que le
test éprouve reste le même — ce n'est pas le verrou.
- testDecisionReasonRendering attendait « Surplus insuffisant » pour
SG_NORMAL, reformulé en « Aucun surplus à allouer » par le même commit,
parce que ce motif ne sort plus que pour un budget nul ou négatif.
Le catalogue de motifs avait dérivé au passage : BATTERY_RESERVE et
BELOW_MIN_POWER étaient entrés en 3g-1 sans ligne de rendu attendue ni entrée
dans la liste de clôture. Leur texte — celui sur lequel le banc s'appuie pour
distinguer « il n'y a rien » de « il y en a, mais pas au bon format » ou
« une règle le retient » — n'était donc éprouvé par rien. Refermé, avec les
deux formes de BELOW_MIN_POWER (avec et sans état).
Suite verte : simulation 24/24 fonctions, dont les 16 scénarios de `run`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017TVywtayEeoRJ2yWUW4iZj
This commit is contained in:
parent
4c103737ff
commit
a8a51d6b32
@ -201,7 +201,7 @@ void Simulation::testEcsSurplusPV()
|
|||||||
|
|
||||||
EtmVariableLoadAdapter *ecs = new EtmVariableLoadAdapter(
|
EtmVariableLoadAdapter *ecs = new EtmVariableLoadAdapter(
|
||||||
thingManager, ecsId.toString(), "ECS variable",
|
thingManager, ecsId.toString(), "ECS variable",
|
||||||
QList<int>({0, 1200, 2400}), 2400, 1, LoadNeeds(), arbitrator);
|
QList<int>({0, 1200, 2400}), 2400, /* minPowerW */ 0, 1, LoadNeeds(), arbitrator);
|
||||||
arbitrator->registerEtmVariableLoadAdapter(ecs);
|
arbitrator->registerEtmVariableLoadAdapter(ecs);
|
||||||
|
|
||||||
auto setMeterW = [&](double signedW){ meterThing->setStateValue("currentPower", signedW); }; // <0 = export
|
auto setMeterW = [&](double signedW){ meterThing->setStateValue("currentPower", signedW); }; // <0 = export
|
||||||
@ -249,7 +249,7 @@ void Simulation::testEcsSurplusPV()
|
|||||||
rThing->setStateValue("currentPowerW", 0);
|
rThing->setStateValue("currentPowerW", 0);
|
||||||
|
|
||||||
EtmVariableLoadAdapter *router = new EtmVariableLoadAdapter(
|
EtmVariableLoadAdapter *router = new EtmVariableLoadAdapter(
|
||||||
tm2, rId.toString(), "Routeur PV", QList<int>(), 3000, 1, LoadNeeds(), arb2); // powerLevels vide → dynamic
|
tm2, rId.toString(), "Routeur PV", QList<int>(), 3000, /* minPowerW */ 0, 1, LoadNeeds(), arb2); // powerLevels vide → dynamic
|
||||||
arb2->registerEtmVariableLoadAdapter(router);
|
arb2->registerEtmVariableLoadAdapter(router);
|
||||||
|
|
||||||
m2->setStateValue("currentPower", -2000); arb2->simulationCallUpdate(t0); QCoreApplication::processEvents();
|
m2->setStateValue("currentPower", -2000); arb2->simulationCallUpdate(t0); QCoreApplication::processEvents();
|
||||||
@ -290,7 +290,7 @@ void Simulation::testMeterSilentFallback()
|
|||||||
|
|
||||||
EtmVariableLoadAdapter *ecs = new EtmVariableLoadAdapter(
|
EtmVariableLoadAdapter *ecs = new EtmVariableLoadAdapter(
|
||||||
thingManager, ecsId.toString(), "ECS repli",
|
thingManager, ecsId.toString(), "ECS repli",
|
||||||
QList<int>({0, 2400}), 2400, 1, LoadNeeds(), arbitrator);
|
QList<int>({0, 2400}), 2400, /* minPowerW */ 0, 1, LoadNeeds(), arbitrator);
|
||||||
arbitrator->registerEtmVariableLoadAdapter(ecs);
|
arbitrator->registerEtmVariableLoadAdapter(ecs);
|
||||||
|
|
||||||
const QDateTime t0 = utcDateTime(QDate(2026, 6, 8), QTime(13, 0, 0));
|
const QDateTime t0 = utcDateTime(QDate(2026, 6, 8), QTime(13, 0, 0));
|
||||||
@ -1415,7 +1415,11 @@ void Simulation::testEcsColdStartLockExpires()
|
|||||||
RelayRouter *r3 = new RelayRouter(tm, "froid3", "Charge à froid 3",
|
RelayRouter *r3 = new RelayRouter(tm, "froid3", "Charge à froid 3",
|
||||||
QList<LoadConfigRelay>({ {rA.toString(), 1000} }), 0, 0, 1, LoadNeeds(), arb);
|
QList<LoadConfigRelay>({ {rA.toString(), 1000} }), 0, 0, 1, LoadNeeds(), arb);
|
||||||
const QString mBudget = motifPour(r3, 200, t0); // 200 W < palier 1000 W
|
const QString mBudget = motifPour(r3, 200, t0); // 200 W < palier 1000 W
|
||||||
QVERIFY2(mBudget.contains("insuffisant", Qt::CaseInsensitive), qUtf8Printable("motif: " + mBudget));
|
// §12 / f134048 — ce cas n'est plus « surplus insuffisant » mais BELOW_MIN_POWER : il y a
|
||||||
|
// un budget, il n'est simplement pas au bon FORMAT. Le motif doit donc nommer le palier —
|
||||||
|
// la distinction envoie l'installateur attendre le soleil ou relire son câblage, pas la
|
||||||
|
// même chose. Ce qui reste inchangé, et qui est l'objet du test : ce n'est pas le verrou.
|
||||||
|
QVERIFY2(mBudget.contains("palier", Qt::CaseInsensitive), qUtf8Printable("motif: " + mBudget));
|
||||||
QVERIFY2(!mBudget.contains("Verrou"), qUtf8Printable("motif: " + mBudget));
|
QVERIFY2(!mBudget.contains("Verrou"), qUtf8Printable("motif: " + mBudget));
|
||||||
|
|
||||||
// 3. Verrou minOn : palier maintenu AU-DESSUS du budget. Troisième cas, troisième texte.
|
// 3. Verrou minOn : palier maintenu AU-DESSUS du budget. Troisième cas, troisième texte.
|
||||||
@ -4022,8 +4026,31 @@ void Simulation::testDecisionReasonRendering()
|
|||||||
{ { DecisionCode::SgRecommended, {{"budgetW", 2000}, {"estimatedW", 1500}} },
|
{ { DecisionCode::SgRecommended, {{"budgetW", 2000}, {"estimatedW", 1500}} },
|
||||||
QStringLiteral("PAC test"),
|
QStringLiteral("PAC test"),
|
||||||
QStringLiteral("Surplus PV 2000 W — PAC test recommandée (état 3, ~1500 W)") },
|
QStringLiteral("Surplus PV 2000 W — PAC test recommandée (état 3, ~1500 W)") },
|
||||||
|
// §12 / f134048 — SG_NORMAL ne sort plus QUE pour un budget nul ou négatif : le cas
|
||||||
|
// « budget présent mais sous l'état 3 » est passé à BELOW_MIN_POWER. La phrase dit
|
||||||
|
// donc « aucun surplus », là où « insuffisant » couvrait aussi, et à tort, un budget
|
||||||
|
// de 933 W devant un état à 1 500 W.
|
||||||
{ { DecisionCode::SgNormal, {{"budgetW", 1000}} }, QStringLiteral("PAC test"),
|
{ { DecisionCode::SgNormal, {{"budgetW", 1000}} }, QStringLiteral("PAC test"),
|
||||||
QStringLiteral("Surplus insuffisant (1000 W) — PAC test en normal (état 2, non pilotée)") },
|
QStringLiteral("Aucun surplus à allouer (1000 W) — PAC test en normal (état 2, non pilotée)") },
|
||||||
|
|
||||||
|
// 3g-1 — les deux motifs sur lesquels le banc s'appuie pour distinguer « il n'y a
|
||||||
|
// rien » de « il y en a, mais pas au bon format » ou « une règle le retient ». Leur
|
||||||
|
// TEXTE n'était pas éprouvé : ils ont rejoint le catalogue sans ligne ici.
|
||||||
|
{ { DecisionCode::BatteryReserve,
|
||||||
|
{{"withheldW", 3200}, {"socPercent", 35}, {"reservePercent", 80}} },
|
||||||
|
QStringLiteral("Chauffe-eau"),
|
||||||
|
QStringLiteral("3200 W de surplus retenus — batterie à 35 %, sous la réserve de 80 % ; "
|
||||||
|
"aucune charge n'est servie") },
|
||||||
|
{ { DecisionCode::BelowMinPower, {{"budgetW", 1096}, {"minPowerW", 2070}} },
|
||||||
|
QStringLiteral("Borne du garage"),
|
||||||
|
QStringLiteral("Budget 1096 W sous le premier palier de Borne du garage (2070 W) — 0 W, "
|
||||||
|
"le budget passe à la charge suivante") },
|
||||||
|
// La variante à ÉTATS nomme l'état hors d'atteinte : sans lui, une phrase vague en
|
||||||
|
// remplacerait une autre (note de DecisionCode::BelowMinPower).
|
||||||
|
{ { DecisionCode::BelowMinPower, {{"budgetW", 933}, {"minPowerW", 1500}, {"state", 3}} },
|
||||||
|
QStringLiteral("PAC test"),
|
||||||
|
QStringLiteral("Budget 933 W sous l'état 3 de PAC test (1500 W estimés) — état 2, "
|
||||||
|
"le budget passe à la charge suivante") },
|
||||||
|
|
||||||
// --- Sécurité et cycle de vie ---
|
// --- Sécurité et cycle de vie ---
|
||||||
{ { DecisionCode::DegradedL2 }, QString(),
|
{ { DecisionCode::DegradedL2 }, QString(),
|
||||||
@ -4054,7 +4081,10 @@ void Simulation::testDecisionReasonRendering()
|
|||||||
DecisionCode::SurplusSetpoint, DecisionCode::SurplusInsufficient,
|
DecisionCode::SurplusSetpoint, DecisionCode::SurplusInsufficient,
|
||||||
DecisionCode::LockMinStateHold, DecisionCode::SgForced, DecisionCode::SgRecommended,
|
DecisionCode::LockMinStateHold, DecisionCode::SgForced, DecisionCode::SgRecommended,
|
||||||
DecisionCode::SgNormal, DecisionCode::DegradedL2, DecisionCode::SafeStateRelay,
|
DecisionCode::SgNormal, DecisionCode::DegradedL2, DecisionCode::SafeStateRelay,
|
||||||
DecisionCode::SafeStateSetpoint, DecisionCode::SafeStateSgReady };
|
DecisionCode::SafeStateSetpoint, DecisionCode::SafeStateSgReady,
|
||||||
|
// 3g-1 : ajoutés au catalogue sans être ajoutés ICI — la clôture avait dérivé, donc
|
||||||
|
// la garantie « tout code a une ligne de rendu éprouvée » ne tenait plus.
|
||||||
|
DecisionCode::BatteryReserve, DecisionCode::BelowMinPower };
|
||||||
for (const QString &code : catalogue)
|
for (const QString &code : catalogue)
|
||||||
QVERIFY2(codesCouverts.contains(code),
|
QVERIFY2(codesCouverts.contains(code),
|
||||||
qUtf8Printable(QStringLiteral("code %1 sans ligne de rendu attendue").arg(code)));
|
qUtf8Printable(QStringLiteral("code %1 sans ligne de rendu attendue").arg(code)));
|
||||||
@ -4603,7 +4633,7 @@ void Simulation::testRuntimeViewIsSubstantial()
|
|||||||
QVERIFY(varThing);
|
QVERIFY(varThing);
|
||||||
varThing->setStateValue("currentPowerW", 0);
|
varThing->setStateValue("currentPowerW", 0);
|
||||||
EtmVariableLoadAdapter *continu = new EtmVariableLoadAdapter(
|
EtmVariableLoadAdapter *continu = new EtmVariableLoadAdapter(
|
||||||
tm, varId.toString(), "Routeur PV", QList<int>(), 4000, 2, LoadNeeds(), arb);
|
tm, varId.toString(), "Routeur PV", QList<int>(), 4000, /* minPowerW */ 0, 2, LoadNeeds(), arb);
|
||||||
|
|
||||||
LoadAction consigne;
|
LoadAction consigne;
|
||||||
consigne.kind = LoadAction::Setpoint; consigne.funding = LoadAction::Surplus;
|
consigne.kind = LoadAction::Setpoint; consigne.funding = LoadAction::Surplus;
|
||||||
@ -4626,7 +4656,7 @@ void Simulation::testRuntimeViewIsSubstantial()
|
|||||||
// Le code de défaut n'est pas du code mort : un thing absent de la configuration le lève.
|
// Le code de défaut n'est pas du code mort : un thing absent de la configuration le lève.
|
||||||
EtmVariableLoadAdapter *fantome = new EtmVariableLoadAdapter(
|
EtmVariableLoadAdapter *fantome = new EtmVariableLoadAdapter(
|
||||||
tm, "{deadbeef-0000-0000-0000-000000000042}", "Charge fantôme",
|
tm, "{deadbeef-0000-0000-0000-000000000042}", "Charge fantôme",
|
||||||
QList<int>(), 1000, 3, LoadNeeds(), arb);
|
QList<int>(), 1000, /* minPowerW */ 0, 3, LoadNeeds(), arb);
|
||||||
QCOMPARE(fantome->runtimeView(t0).faultCode, QString("THING_MISSING"));
|
QCOMPARE(fantome->runtimeView(t0).faultCode, QString("THING_MISSING"));
|
||||||
|
|
||||||
// ---- 3. SgReadyAdapter : état normé, estimation, verrou minStateHold ------------------
|
// ---- 3. SgReadyAdapter : état normé, estimation, verrou minStateHold ------------------
|
||||||
@ -4933,3 +4963,4 @@ QStringList Simulation::plotSpotMarketData(int powerBalanceCount)
|
|||||||
|
|
||||||
|
|
||||||
QTEST_MAIN(Simulation)
|
QTEST_MAIN(Simulation)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user