// SPDX-License-Identifier: GPL-3.0-or-later #ifndef TESTLOADMODEL_H #define TESTLOADMODEL_H #include /*! * \brief Logique pure du modèle de charge : table de paliers et identité matérielle. * * Aucun serveur nymea ici. Ce qui est éprouvé ne dépend ni d'un ThingManager ni d'un * cycle d'arbitrage : la dérivation des paliers est une combinatoire, et * \c EnergyArbitrator::sameHardware() une comparaison. */ class TestLoadModel : public QObject { Q_OBJECT private slots: //! La table dérive de TOUTES les sommes de sous-ensembles, triées, 0 compris. void testStageTableIsDerivedFromSubsetSums(); //! Puissances distinctes : l'ordre de déclaration n'a aucun effet observable. void testRelayOrderIsInertWhenPowersAreDistinct(); //! Puissances égales : l'ordre décide QUEL contact sert le palier — et ça se voit. void testRelayOrderDecidesWhichContactServesATiedStage(); //! Un réordonnancement sans effet ne doit PAS coûter une reconstruction. void testReorderingDistinctRelaysKeepsTheAdapter(); //! Mais un échange de contacts à puissance égale, si. void testSwappingTiedRelaysRebuilds(); //! Libellé, rang et besoins se mettent à jour en place : jamais de reconstruction. void testSoftFieldsNeverRebuild(); // ── §11 — compteur et sonde par charge ───────────────────────────────── //! Les deux champs traversent l'aller-retour, et sont OMIS quand ils sont vides. void testMeasurementThingsRoundTrip(); //! Ils ne sont pas des canaux de commande : ils n'entrent pas dans claimedThingIds(). void testMeasurementThingsAreNotClaimed(); //! Donc deux charges peuvent partager le même compteur et la même sonde. void testTwoLoadsMayShareAMeter(); //! Et les changer ne reconstruit rien : ils n'ont aucun effet sur le matériel. void testMeasurementThingsAreSoftFields(); // ── §12 — le plancher de modulation ──────────────────────────────────── //! Déclaré en dynamic, et il traverse l'aller-retour. void testFloorIsDeclaredForContinuousLoads(); //! Interdit là où il se DÉRIVE : deux sources d'une même vérité divergent. void testFloorIsRefusedWhereItWouldBeDerived(); //! Un plancher au-dessus du plafond rendrait la charge inatteignable. void testFloorAboveCeilingIsRefused(); // ── 3g-2 — le rang de la borne vit dans LoadConfig (LM-1206/LM-1207) ─── //! Une entrée evcharger est valide SANS charge utile, et traverse l'aller-retour. void testEvChargerConfigIsRankOnly(); //! Toute charge utile d'un autre mécanisme y est refusée (LM-300, union discriminée). void testEvChargerConfigRefusesPayloads(); //! Elle revendique son Thing : une borne ne peut pas être aussi une charge pilotée. void testEvChargerClaimsItsThing(); }; #endif // TESTLOADMODEL_H