Skip to content

Commit 8d0c9b4

Browse files
tcarmelveilleuxrestyled-commits
authored andcommitted
Fix post-review comments on Q quality utils from project-chip#34266 (project-chip#34416)
* Fix post-review comments on Q quality utils from project-chip#34266 - PR project-chip#34266 had post review comments See: project-chip#34266 (review) - Fix 0->0 case - Introduce `Timestamp` more places where it makes sense - Simplify some code lines Fixes project-chip#34334 Testing done: - Added unit test for 0->0 - Tests still pass * Restyled by clang-format * Address review comments * Restyled by clang-format --------- Co-authored-by: Restyled.io <commits@restyled.io>
1 parent eace30a commit 8d0c9b4

File tree

2 files changed

+33
-28
lines changed

2 files changed

+33
-28
lines changed

src/app/cluster-building-blocks/QuieterReporting.h

+21-25
Original file line numberDiff line numberDiff line change
@@ -142,15 +142,6 @@ class QuieterReportingAttribute
142142
};
143143
}
144144

145-
/**
146-
* @brief Factory to generate a functor that forces reportable now.
147-
* @return a functor usable for the `changedPredicate` arg of `SetValue()`
148-
*/
149-
static SufficientChangePredicate GetForceReportablePredicate()
150-
{
151-
return [](const SufficientChangePredicateCandidate & candidate) -> bool { return true; };
152-
}
153-
154145
Nullable<T> value() const { return mValue; }
155146
QuieterReportingPolicyFlags & policy() { return mPolicyFlags; }
156147
const QuieterReportingPolicyFlags & policy() const { return mPolicyFlags; }
@@ -163,6 +154,7 @@ class QuieterReportingAttribute
163154
* - The policies from `QuieterReportingPolicyEnum` and set via `SetPolicy()` are self-explanatory by name.
164155
* - The changedPredicate will be called with last dirty <timestamp, value> and new <timestamp value> and may override
165156
* the dirty state altogether when it returns true. Use sparingly and default to a functor returning false.
157+
* The changedPredicate is only called on change.
166158
*
167159
* Internal recording will be done about last dirty value and last dirty timestamp based on the policies having applied.
168160
*
@@ -172,13 +164,13 @@ class QuieterReportingAttribute
172164
* @return AttributeDirtyState::kMustReport if attribute must be marked dirty right away, or
173165
* AttributeDirtyState::kNoReportNeeded otherwise.
174166
*/
175-
AttributeDirtyState SetValue(const chip::app::DataModel::Nullable<T> & newValue, Timestamp now,
176-
SufficientChangePredicate changedPredicate)
167+
AttributeDirtyState SetValue(const DataModel::Nullable<T> & newValue, Timestamp now, SufficientChangePredicate changedPredicate)
177168
{
178-
bool isChangeOfNull = newValue.IsNull() ^ mValue.IsNull();
179-
bool areBothValuesNonNull = !newValue.IsNull() && !mValue.IsNull();
169+
bool isChangeOfNull = newValue.IsNull() != mValue.IsNull();
170+
bool areBothValuesNonNull = !newValue.IsNull() && !mValue.IsNull();
171+
bool areBothValuesDifferent = areBothValuesNonNull && (newValue.Value() != mValue.Value());
180172

181-
bool changeToFromZero = areBothValuesNonNull && (newValue.Value() == 0 || mValue.Value() == 0);
173+
bool changeToFromZero = areBothValuesNonNull && areBothValuesDifferent && (newValue.Value() == 0 || mValue.Value() == 0);
182174
bool isIncrement = areBothValuesNonNull && (newValue.Value() > mValue.Value());
183175
bool isDecrement = areBothValuesNonNull && (newValue.Value() < mValue.Value());
184176

@@ -188,13 +180,17 @@ class QuieterReportingAttribute
188180
isNewlyDirty = isNewlyDirty || (mPolicyFlags.Has(QuieterReportingPolicyEnum::kMarkDirtyOnDecrement) && isDecrement);
189181
isNewlyDirty = isNewlyDirty || (mPolicyFlags.Has(QuieterReportingPolicyEnum::kMarkDirtyOnIncrement) && isIncrement);
190182

191-
SufficientChangePredicateCandidate candidate{
192-
mLastDirtyTimestampMillis, // lastDirtyTimestamp
193-
now, // nowTimestamp
194-
mLastDirtyValue, // lastDirtyValue
195-
newValue // newValue
196-
};
197-
isNewlyDirty = isNewlyDirty || changedPredicate(candidate);
183+
// Only execute predicate on value change from last marked dirty.
184+
if (newValue != mLastDirtyValue)
185+
{
186+
SufficientChangePredicateCandidate candidate{
187+
mLastDirtyTimestampMillis, // lastDirtyTimestamp
188+
now, // nowTimestamp
189+
mLastDirtyValue, // lastDirtyValue
190+
newValue // newValue
191+
};
192+
isNewlyDirty = isNewlyDirty || changedPredicate(candidate);
193+
}
198194

199195
mValue = newValue;
200196

@@ -217,20 +213,20 @@ class QuieterReportingAttribute
217213
* @return AttributeDirtyState::kMustReport if attribute must be marked dirty right away, or
218214
* AttributeDirtyState::kNoReportNeeded otherwise.
219215
*/
220-
AttributeDirtyState SetValue(const chip::app::DataModel::Nullable<T> & newValue, Timestamp now)
216+
AttributeDirtyState SetValue(const DataModel::Nullable<T> & newValue, Timestamp now)
221217
{
222218
return SetValue(newValue, now, [](const SufficientChangePredicateCandidate &) -> bool { return false; });
223219
}
224220

225221
protected:
226222
// Current value of the attribute.
227-
chip::app::DataModel::Nullable<T> mValue;
223+
DataModel::Nullable<T> mValue;
228224
// Last value that was marked as dirty (to use in comparisons for change, e.g. by SufficientChangePredicate).
229-
chip::app::DataModel::Nullable<T> mLastDirtyValue;
225+
DataModel::Nullable<T> mLastDirtyValue;
230226
// Enabled internal change detection policies.
231227
QuieterReportingPolicyFlags mPolicyFlags{ 0 };
232228
// Timestamp associated with the last time the attribute was marked dirty (to use in comparisons for change).
233-
chip::System::Clock::Milliseconds64 mLastDirtyTimestampMillis{};
229+
chip::System::Clock::Timestamp mLastDirtyTimestampMillis{};
234230
};
235231

236232
} // namespace detail

src/app/cluster-building-blocks/tests/TestQuieterReporting.cpp

+12-3
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ TEST(TestQuieterReporting, ChangeToFromZeroPolicyWorks)
7474
EXPECT_EQ(attribute.SetValue(0, now), AttributeDirtyState::kMustReport);
7575
EXPECT_EQ(attribute.value().ValueOr(INT_MAX), 0);
7676

77+
// 0 --> 0, expect NOT marked dirty.
78+
EXPECT_EQ(attribute.SetValue(0, now), AttributeDirtyState::kNoReportNeeded);
79+
EXPECT_EQ(attribute.value().ValueOr(INT_MAX), 0);
80+
7781
// 0 --> 11, expect marked dirty.
7882
EXPECT_EQ(attribute.SetValue(11, now), AttributeDirtyState::kMustReport);
7983
EXPECT_EQ(attribute.value().ValueOr(INT_MAX), 11);
@@ -209,9 +213,6 @@ TEST(TestQuieterReporting, SufficientChangePredicateWorks)
209213
EXPECT_EQ(attribute.SetValue(10, now), AttributeDirtyState::kNoReportNeeded);
210214
EXPECT_EQ(attribute.value().ValueOr(INT_MAX), 10);
211215

212-
// Forcing dirty can be done with a force-true predicate
213-
EXPECT_EQ(attribute.SetValue(10, now, attribute.GetForceReportablePredicate()), AttributeDirtyState::kMustReport);
214-
215216
auto predicate = attribute.GetPredicateForSufficientTimeSinceLastDirty(1000_ms);
216217

217218
now = fakeClock.Advance(100_ms);
@@ -250,6 +251,14 @@ TEST(TestQuieterReporting, SufficientChangePredicateWorks)
250251
EXPECT_EQ(attribute.SetValue(14, now, predicate), AttributeDirtyState::kNoReportNeeded);
251252
EXPECT_EQ(attribute.value().ValueOr(INT_MAX), 14);
252253

254+
// Forcing dirty can NOT done with a force-true predicate.
255+
decltype(attribute)::SufficientChangePredicate forceTruePredicate{
256+
[](const decltype(attribute)::SufficientChangePredicateCandidate &) -> bool { return true; }
257+
};
258+
now = fakeClock.Advance(1_ms);
259+
EXPECT_EQ(attribute.SetValue(12, now, forceTruePredicate), AttributeDirtyState::kNoReportNeeded);
260+
EXPECT_EQ(attribute.value().ValueOr(INT_MAX), 12);
261+
253262
// Change to a value that marks dirty no matter what (e.g. null). Should be dirty even
254263
// before delay.
255264
now = fakeClock.Advance(1_ms);

0 commit comments

Comments
 (0)