You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-issues@jackrabbit.apache.org by "Manfred Baedke (Jira)" <ji...@apache.org> on 2026/08/26 13:03:00 UTC
[jira] [Updated] (OAK-12373) Flacky test TokenCleanupTest#testExpiredReachingThreshold()
[ https://issues.apache.org/jira/browse/OAK-12373?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Manfred Baedke updated OAK-12373:
---------------------------------
Summary: Flacky test TokenCleanupTest#testExpiredReachingThreshold() (was: Flacky test TokenCleanupTest#testExpiredReachingThreshold)
> Flacky test TokenCleanupTest#testExpiredReachingThreshold()
> -----------------------------------------------------------
>
> Key: OAK-12373
> URL: https://issues.apache.org/jira/browse/OAK-12373
> Project: Jackrabbit Oak
> Issue Type: Bug
> Components: security
> Reporter: Manfred Baedke
> Priority: Major
>
> AI analysis:
>
> ## ## Failing Test: `TokenCleanupTest.testExpiredReachingThreshold`
> ### What's Failing
> The test at [line 84–89](https://github.com/apache/jackrabbit-oak/blob/9cc98aacf1285609d81ef9653d6bd891e3d1e38f/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/token/TokenCleanupTest.java#L84-L89) fails with:
> ```
> expected: <50> but was: <54>
> ```
> ### Root Cause
> The test asserts that after cleanup is triggered, only `extras` (the non-expired tokens created until cleanup ran) remain. However, the assertion in `assertTokenNodes` (line 53) uses `expectedNumber * 2` as the max-count hint to `getChildrenCount`, which means if **more** tokens exist than expected, the count returned can exceed `expectedNumber`. The actual issue is in the test logic itself:
> - `createExpiredTokens(4)` creates 4 expired tokens.
> - `createTokensUntilCleanup()` loops until cleanup is triggered and returns `extras` (the count of non-expired tokens created).
> - The test then asserts only `extras` tokens remain, expecting all 4 expired ones to have been removed.
> The problem is that `createTokensUntilCleanup()` can loop up to 50 iterations, and if cleanup is triggered on iteration 50 (the cap), **not all expired tokens may be cleaned up** — or the threshold/randomness of `shouldRunCleanup` causes cleanup to fire before all expired tokens have been created in sequence, leaving behind some. The real flakiness is that `createTokensUntilCleanup` doesn't account for the 4 pre-created expired tokens that were present *before* it started, so the final count includes leftover tokens the assertion didn't anticipate.
> ### Fix
> The `assertTokenNodes` call should account for any expired tokens that were **not** cleaned up. Since the cleanup threshold is `5` and cleanup removes all expired tokens upon triggering, the assertion should be:
> ```java
> @Test
> public void testExpiredReachingThreshold() throws Exception {
> // one under the cleanup limit so cleanup doesn't get triggered
> createExpiredTokens(4);
> int extras = createTokensUntilCleanup();
> // After cleanup, only the non-expired tokens created in createTokensUntilCleanup should remain.
> // The 4 expired tokens should have been deleted; if cleanup did not fire within the loop cap,
> // account for remaining expired tokens explicitly.
> Tree tokenParent = root.getTree(getTestUser().getPath() + '/' + TokenConstants.TOKENS_NODE_NAME);
> long remaining = tokenParent.getChildrenCount(Long.MAX_VALUE);
> assertTrue("Expected at most " + extras + " tokens after cleanup, but found " + remaining,
> remaining <= extras);
> }
> ```
> Or, more minimally, fix the `createTokensUntilCleanup()` guard — the loop cap of `50` is too low and can be hit before cleanup is probabilistically triggered, causing the method to return `50` while some expired tokens still remain:
> ```java
> private int createTokensUntilCleanup() {
> int tkn = 0;
> boolean clean = false;
> while (!clean && tkn < 200) { // increase cap to reduce flakiness
> TokenInfo tokenInfo = createTokenInfo(tokenProvider, userId);
> clean = TokenProviderImpl.shouldRunCleanup(tokenInfo.getToken());
> tkn++;
> }
> return tkn;
> }
> ```
> The most robust fix is **both**: increase the loop cap so cleanup reliably fires before the limit is hit, and update the assertion to be tolerant of edge cases where cleanup fires but leaves residual tokens. The cap of `50` combined with randomized `shouldRunCleanup` evaluation makes this test inherently flaky.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)