Skip to content

Contain IT teardown failures so one flaky cleanup doesn't cascade#1392

Open
kuchtiak-ufal wants to merge 3 commits into
clarin-v7from
random_test_failure_ConcurrentModificationException
Open

Contain IT teardown failures so one flaky cleanup doesn't cascade#1392
kuchtiak-ufal wants to merge 3 commits into
clarin-v7from
random_test_failure_ConcurrentModificationException

Conversation

@kuchtiak-ufal

Copy link
Copy Markdown

This change applies the upstream fix of certain ConcurrentModificationException test failures.
See: Upstream Issue:12324 and the pull request: 12325

Wrap each builder's cleanup() in its own try/catch in AbstractBuilderCleanupUtil
so a single failure (e.g. the intermittent Hibernate ConcurrentModificationException
in ResourceRegistryStandardImpl.releaseResources) no longer aborts cleanup of the
remaining builders. The first failure is rethrown with any subsequent failures
attached via addSuppressed.

Restructure AbstractIntegrationTestWithDatabase.destroy() to run the shared-state
resets (Solr cores, authority cache, QA events, config service, builder cache)
in a finally block, so that state is always reset between tests even when builder
cleanup throws. Previously those resets sat after the try/catch, so any teardown
exception would skip them and poison every subsequent test in the class.

Fixes DSpace#12324

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR applies an upstream test-stability fix to prevent flaky teardown/cleanup failures (notably intermittent ConcurrentModificationException during cleanup) from cascading and breaking subsequent integration tests in CLARIN-DSpace’s DSpace v7 backend test suite.

Changes:

  • Update builder cleanup to continue cleaning remaining builders even if one cleanup step fails, while aggregating failures via suppressed exceptions.
  • Refactor integration test teardown to ensure shared static state (Solr cores, caches, config, builder cache) is reset even when earlier teardown steps fail.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
dspace-api/src/test/java/org/dspace/builder/util/AbstractBuilderCleanupUtil.java Makes builder cleanup resilient by isolating failures per builder and rethrowing an aggregated failure at the end.
dspace-api/src/test/java/org/dspace/AbstractIntegrationTestWithDatabase.java Attempts to contain teardown failures and always reset shared static state after each test to avoid cascading flakes.
Comments suppressed due to low confidence (1)

dspace-api/src/test/java/org/dspace/AbstractIntegrationTestWithDatabase.java:235

  • resetSharedState() wraps all failures into a bare RuntimeException, which drops useful context (message) and contradicts its own throws Exception contract. Since destroy() already aggregates/suppresses teardown failures, it’s clearer to let resetSharedState() propagate its original exception (or wrap with a descriptive message).
        try {
            // Reload our ConfigurationService (to reset configs to defaults again)
            DSpaceServicesFactory.getInstance().getConfigurationService().reloadConfig();

            AbstractBuilder.cleanupBuilderCache();

            // NOTE: we explicitly do NOT destroy our default eperson & admin as they
            // are cached and reused for all tests. This speeds up all tests.
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

@kuchtiak-ufal
kuchtiak-ufal requested a review from kosarko July 22, 2026 11:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

Comment on lines +204 to +206
* Reset all shared static state between tests: Solr cores, authority cache, configuration
* service, and the builder cache. Called from {@link #destroy()} inside a finally block so this always
* runs, even if earlier teardown steps failed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants