[EGC / Commodity Price] PeriodEnd == PeriodStart accepted, forecast ordering and bounds unenforced, and two TC_SEPRTestBase defects that hide it
Verified on master (99a81bd3298). Six items: four about the time bounds on forecast/period data in Electrical Grid Conditions and Commodity Price, two test-base defects that hide them, and one reference-app arithmetic defect.
| # | What | Why it matters |
|---|---|---|
| 1 | PeriodEnd == PeriodStart is accepted in both servers |
A controller gets a zero-length period where the spec mandates strict > |
| 2 | Cross-entry forecast time-ordering is enforced by nobody | A controller cannot rely on forecast entries arriving in time order |
| 3 | EGC's kMaxForecastEntries is declared and never used |
ForecastConditions can exceed its max 56, so a client with a 56-entry buffer overruns |
| 4 | §9.9.6.4 is enforced nowhere | A controller sees a non-empty PriceForecast alongside a null CurrentPrice.PeriodEnd |
| 5 | Two test-base defects | The cert harness mis-evaluates a conformant device |
| 6 | The reference app's price components do not sum to the price | Anyone copying the sample data ships a device that breaks §9.9.5.3.6 |
1 — PeriodEnd == PeriodStart is accepted in both servers
09-13-electrical-grid-conditions-cluster.md:75 gives PeriodEnd the constraint min (PeriodStart + 1) and :89 states "This SHALL be greater than PeriodStart." 09-09-commodity-price-cluster.md:105 is identical. Strict > is mandated.
- EGC:
electrical-grid-conditions-server.cpp:132rejects onlyperiodStart > periodEnd, so equality passes. - Commodity Price: the same defect survived the SCI rewrite, inverted —
CommodityPriceCluster.cpp:93:VerifyOrReturnError(price.periodEnd.IsNull() || (price.periodStart <= price.periodEnd.Value()), ConstraintError).
2 — Cross-entry forecast time-ordering is enforced by nobody
The ForecastConditions / PriceForecast ordering SHALLs are implemented in no server and asserted by no test base (TC_SEPRTestBase.py:41-60, TC_EGCTestBase.py:36-52 check only list-ness, type and max-56). They survive only as a -1 fudge in the reference apps' trigger data: ElectricalGridConditionsEventTriggers.cpp:105-106 and CommodityPriceEventTriggers.cpp:115-116, both currentStart + k30MinsInSeconds - 1.
Note Commodity Price is now covered for the per-entry bound since the rewrite — PriceStorage::Set (CommodityPriceCluster.cpp:116-135) calls ValidatePrice per entry. EGC's SetForecastConditions (:165-174) still validates nothing per entry.
3 — EGC's kMaxForecastEntries is declared and never used
electrical-grid-conditions-server.h:32-33 declares it; nothing reads it, so ForecastConditions' max 56 is unenforced. Commodity Price's own copy is used, at CommodityPriceCluster.cpp:442.
4 — §9.9.6.4 ("if CurrentPrice.PeriodEnd is null then PriceForecast SHALL be empty") is enforced nowhere
SetCurrentPrice and SetForecast stay fully independent. Neither inspects the other's stored state.
5 — Two test-base defects that mis-evaluate a conformant device
These are bugs in the harness, not the servers, and they produce false results:
TC_SEPRTestBase.py:98/:102-103testif struct.price is not NullValue:for optional fields, so an absent optional field reads as present. The assertion at:106(assert_true(bPriceIncluded or bPriceLevelIncluded, ...)) can then never fail. A conformant DUT supplying only one ofPrice/PriceLevelis mis-evaluated. The correct idiom (is not None) is used nearby at:110and:122, so the file disagrees with itself.TC_SEPRTestBase.py:86-87assertsassert_less_equal(struct.periodStart, now_time_epoch_s, ...)with the failure message "PeriodStart must not be in the past", while the comment at:84says "verify that the PeriodStart is in the past". The message states the opposite of the assertion, so whoever debugs a failure here is sent the wrong way.
6 — The reference app's own price components do not sum to the price
§9.9.5.3.6 requires the components to sum to the Price. CommodityPriceEventTriggers.cpp:50 sets amount = 15916; :62 and :66 derive amount * 95 / 100 = 15120 and amount * 5 / 100 = 795, summing to 15915. Integer truncation leaves it one minor unit short, and nothing checks the rule. The same arithmetic repeats at :126/:130.
Related: #38581 (EGC deep-check and memory lifetime), #40272 (Commodity Tariff validation).
Found during a Matter 1.6.0 specification-versus-implementation review.
Source: project-chip/connectedhomeip