Skip to content

Commit 6eb02f7

Browse files
authored
[rrd4j] Improve unstable RRD4jPersistenceServiceTest (#21362)
* Poll using the same query criteria as the test * Return the successful query result directly * Avoid races between readiness checks and assertions Signed-off-by: Wouter Born <github@maindrain.net>
1 parent 30b3f56 commit 6eb02f7

1 file changed

Lines changed: 21 additions & 42 deletions

File tree

bundles/org.openhab.persistence.rrd4j/src/test/java/org/openhab/persistence/rrd4j/internal/RRD4jPersistenceServiceTest.java

Lines changed: 21 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -51,24 +51,19 @@
5151
*/
5252
@ExtendWith(MockitoExtension.class)
5353
class RRD4jPersistenceServiceTest {
54-
private static final long STORAGE_TIMEOUT_MS = 20000; // 20 seconds for CI
54+
private static final long STORAGE_TIMEOUT_MS = 20_000; // 20 seconds for CI
5555
private static final long POLL_INTERVAL_MS = 250; // Check every 250ms
5656

5757
private final Logger logger = LoggerFactory.getLogger(RRD4jPersistenceServiceTest.class);
5858

59-
@Mock
60-
private ItemRegistry itemRegistry;
61-
62-
@Mock
63-
private NumberItem numberItem;
64-
65-
@Mock
66-
private SwitchItem switchItem;
59+
private @Mock ItemRegistry itemRegistry;
60+
private @Mock NumberItem numberItem;
61+
private @Mock SwitchItem switchItem;
6762

6863
private RRD4jPersistenceService service;
6964

7065
@BeforeEach
71-
void setUp() throws Exception {
66+
void setUp() {
7267
// Create service with empty config
7368
service = new RRD4jPersistenceService(itemRegistry, Map.of());
7469
}
@@ -77,27 +72,23 @@ void setUp() throws Exception {
7772
* Waits for data to be persisted by polling the database.
7873
* This is more robust than Thread.sleep() in CI environments with resource contention.
7974
*
80-
* @param itemName the name of the item to check
81-
* @param timeoutMs maximum time to wait in milliseconds
75+
* @param criteria the query criteria to use to check for persisted data
8276
* @throws InterruptedException if interrupted while waiting
8377
*/
84-
private void waitForStorage(String itemName, long timeoutMs) throws InterruptedException {
78+
private Iterable<HistoricItem> waitForStorage(FilterCriteria criteria) throws InterruptedException {
8579
long startTime = System.currentTimeMillis();
8680
int attempts = 0;
8781

88-
while (System.currentTimeMillis() - startTime < timeoutMs) {
82+
while (System.currentTimeMillis() - startTime < STORAGE_TIMEOUT_MS) {
8983
attempts++;
9084

91-
FilterCriteria criteria = new FilterCriteria();
92-
criteria.setItemName(itemName);
93-
criteria.setPageSize(1);
94-
9585
try {
9686
Iterable<HistoricItem> results = service.query(criteria);
9787
if (results.iterator().hasNext()) {
9888
long elapsed = System.currentTimeMillis() - startTime;
99-
logger.info("Storage completed for '{}' after {}ms ({} attempts)", itemName, elapsed, attempts);
100-
return; // Success!
89+
logger.info("Storage completed for '{}' after {}ms ({} attempts)", criteria.getItemName(), elapsed,
90+
attempts);
91+
return results;
10192
}
10293
} catch (Exception e) {
10394
// Query might fail if data not ready yet, continue polling
@@ -108,8 +99,8 @@ private void waitForStorage(String itemName, long timeoutMs) throws InterruptedE
10899
}
109100

110101
long elapsed = System.currentTimeMillis() - startTime;
111-
fail(String.format("Data for item '%s' was not persisted within %dms (%d polling attempts).", itemName, elapsed,
112-
attempts));
102+
return fail(String.format("Data for item '%s' was not persisted within %dms (%d polling attempts).",
103+
criteria.getItemName(), elapsed, attempts));
113104
}
114105

115106
private void configureNumberItem(String suffix) throws Exception {
@@ -155,17 +146,14 @@ void storeAndRetrieveNumberValue(boolean reloadAfterStore) throws Exception {
155146
service = new RRD4jPersistenceService(itemRegistry, Map.of());
156147
}
157148

158-
// Wait for background storage to complete
159-
waitForStorage(numberItem.getName(), STORAGE_TIMEOUT_MS);
160-
161-
// Query the value back
162149
FilterCriteria criteria = new FilterCriteria();
163150
criteria.setItemName(numberItem.getName());
164151
criteria.setOrdering(FilterCriteria.Ordering.DESCENDING);
165152
criteria.setPageSize(1);
166153
criteria.setPageNumber(0);
167154

168-
Iterable<HistoricItem> results = service.query(criteria);
155+
// Wait for background storage to complete
156+
Iterable<HistoricItem> results = waitForStorage(criteria);
169157
assertNotNull(results);
170158

171159
// Verify the retrieved value
@@ -189,17 +177,14 @@ void storeAndRetrieveSwitchValue(boolean reloadAfterStore) throws Exception {
189177
service = new RRD4jPersistenceService(itemRegistry, Map.of());
190178
}
191179

192-
// Wait for background storage to complete
193-
waitForStorage(switchItem.getName(), STORAGE_TIMEOUT_MS);
194-
195-
// Query the value back
196180
FilterCriteria criteria = new FilterCriteria();
197181
criteria.setItemName(switchItem.getName());
198182
criteria.setOrdering(FilterCriteria.Ordering.DESCENDING);
199183
criteria.setPageSize(1);
200184
criteria.setPageNumber(0);
201185

202-
Iterable<HistoricItem> results = service.query(criteria);
186+
// Wait for background storage to complete
187+
Iterable<HistoricItem> results = waitForStorage(criteria);
203188
assertNotNull(results);
204189

205190
// Verify the retrieved value (converted back to OnOffType by toStateMapper)
@@ -228,17 +213,14 @@ void queryWithTimeRange(boolean reloadAfterStore) throws Exception {
228213
service = new RRD4jPersistenceService(itemRegistry, Map.of());
229214
}
230215

231-
// Wait for background storage to complete
232-
waitForStorage(numberItem.getName(), STORAGE_TIMEOUT_MS);
233-
234-
// Query with time range
235216
FilterCriteria criteria = new FilterCriteria();
236217
criteria.setItemName(numberItem.getName());
237218
criteria.setBeginDate(ZonedDateTime.now(ZoneId.systemDefault()).minusHours(1));
238219
criteria.setEndDate(ZonedDateTime.now(ZoneId.systemDefault()).plusHours(1));
239220
criteria.setOrdering(FilterCriteria.Ordering.ASCENDING);
240221

241-
Iterable<HistoricItem> results = service.query(criteria);
222+
// Wait for background storage to complete
223+
Iterable<HistoricItem> results = waitForStorage(criteria);
242224
assertNotNull(results);
243225

244226
// Verify we got at least one result
@@ -282,18 +264,15 @@ void storeAndRetrieveWithInvalidDBConfig(boolean reloadAfterStore) throws Except
282264
service = new RRD4jPersistenceService(itemRegistry, Map.of("something.invalid", "invalid/path/to/db"));
283265
}
284266

285-
// Wait for background storage to complete
286-
waitForStorage(numberItem.getName(), STORAGE_TIMEOUT_MS);
287-
288-
// Query the value back
289267
FilterCriteria criteria = new FilterCriteria();
290268
criteria.setItemName(numberItem.getName());
291269
criteria.setOrdering(FilterCriteria.Ordering.ASCENDING);
292270
criteria.setPageSize(1);
293271
criteria.setPageNumber(0);
294272
criteria.setBeginDate(ZonedDateTime.now(ZoneId.systemDefault()).minusHours(1));
295273

296-
Iterable<HistoricItem> results = service.query(criteria);
274+
// Wait for background storage to complete
275+
Iterable<HistoricItem> results = waitForStorage(criteria);
297276
assertNotNull(results);
298277

299278
// Verify the retrieved value

0 commit comments

Comments
 (0)