Skip to content

CLARIN-DSpace v9/Port #1413 (de-flake scheduled ITs) to the v9 base - #1435

Merged
milanmajchrak merged 1 commit into
dtq-dev-9-basefrom
ufal/port-1413-9-base
Sep 10, 2026
Merged

CLARIN-DSpace v9/Port #1413 (de-flake scheduled ITs) to the v9 base#1435
milanmajchrak merged 1 commit into
dtq-dev-9-basefrom
ufal/port-1413-9-base

Conversation

@milanmajchrak

Copy link
Copy Markdown
Collaborator

What

Ports dataquest-dev/DSpace PR #1413 ("de-flake scheduled ITs", commit 23f37863a4) to
dtq-dev-9-base. Test-only — no production code, no config, no migration.

Sync card: BE-03 (_sync3/cards/BE-03.md, tranche T4, disposition TESTS-ONLY, size S, risk low).

Why

All six flake sources the source PR removed are live on this branch. Verified at blob level
before porting — four of the six files are byte-identical with the source commit's pre-image:

file 9-base blob 23f37863a4^ blob
dspace-api/.../curate/ItemHandleCheckerIT.java d006c9ebcc d006c9ebcc
dspace-api/.../curate/RequiredMetadataIT.java ca9be23295 ca9be23295
dspace-api/.../xmlworkflow/XmlWorkflowFactoryTest.java 03a6a0e949 03a6a0e949
dspace-server-webapp/.../PreviewContentServiceImplIT.java 47f7564b8e 47f7564b8e
dspace-server-webapp/.../BitstreamFormatRestRepositoryIT.java f9b2bb3023 af963696f0 (unrelated @Autowired ObjectMapper refactor)
dspace-server-webapp/.../StatisticsRestRepositoryIT.java 3baeeb9b7a 716ccf8b8d (v9 drift)

The failure modes, unchanged from the source PR:

  • RequiredMetadataIT / ItemHandleCheckerIT planted a random numeric handle
    (123456789/ + 1000..1999) that handle_seq reaches late in the module run. The sequence
    mint path does no existence check, so the flush of whichever test was minting at that moment
    died on the handle unique index. XmlWorkflowFactoryTest had the same problem with the fixed
    numeric handle 123456789/999. All three now use non-numeric suffixes the sequence can never
    mint.
  • PreviewContentServiceImplIT deleted its custom bitstream format through the shared test
    context after earlier builder deletes had already detached it from the thread-bound session,
    so the delete was silently lost — one leaked bitstreamformatregistry row per test.
  • BitstreamFormatRestRepositoryIT asserted against a hardcoded DEFAULT_AMOUNT_FORMATS = 95,
    so any leaked row (see above) turned it red whenever class order put Preview first.
  • StatisticsRestRepositoryIT#totalVisitsReport_Item_Visited queried the usage report before
    its posted view event was visible to a new Solr searcher — the one place in the class that
    did not commit (grep -c 'getSolrLoggerService().commit()' → 1 here, 2 on dtq-dev).

Changes

git cherry-pick -x 23f37863a4. Four files applied clean; StatisticsRestRepositoryIT
auto-merged (the single hunk is far from the v9 drift); BitstreamFormatRestRepositoryIT
had six conflicts, all the same one.

The single adaptation: this branch already carries an unrelated refactor that replaced the
six per-test ObjectMapper mapper = new ObjectMapper(); locals with one
@Autowired private ObjectMapper mapper field. That refactor is kept; the source hunks were
applied on top of it. Nothing else differs — every added and removed line of the source patch
is byte-identical here:

$ git diff origin/dtq-dev-9-base --stat        # this branch
 6 files changed, 65 insertions(+), 48 deletions(-)
$ git show --stat --format='' 23f37863a4       # source commit
 6 files changed, 65 insertions(+), 48 deletions(-)

Per-file comparison of the two patches' +/- payload lines:

ItemHandleCheckerIT.java:             added=SAME(3)   removed=SAME(8)
RequiredMetadataIT.java:              added=SAME(3)   removed=SAME(8)
XmlWorkflowFactoryTest.java:          added=SAME(3)   removed=SAME(1)
PreviewContentServiceImplIT.java:     added=SAME(8)   removed=SAME(6)
StatisticsRestRepositoryIT.java:      added=SAME(4)   removed=SAME(0)
BitstreamFormatRestRepositoryIT.java: added=SAME(44)  removed=SAME(25)

Testing

Static checks (card AC-BE-03-1 / -3):

$ grep -c 'randomString()'            ItemHandleCheckerIT.java RequiredMetadataIT.java   -> 0, 0
$ grep -c '123456789/999'             XmlWorkflowFactoryTest.java                        -> 0
$ grep -c 'deleteBitstreamFormat(customMimeTypeFormatId)'  PreviewContentServiceImplIT.java -> 1
$ grep -c 'DEFAULT_AMOUNT_FORMATS'    BitstreamFormatRestRepositoryIT.java               -> 0
$ grep -c 'getSolrLoggerService().commit()'  StatisticsRestRepositoryIT.java             -> 2
$ grep -c 'new ObjectMapper()'        BitstreamFormatRestRepositoryIT.java               -> 0

Build: mvn clean install -P-assembly -DskipTests -> BUILD SUCCESS, 0 checkstyle violations.

Local IT gate — PreviewContentServiceImplIT + BitstreamFormatRestRepositoryIT with
-Dfailsafe.runOrder=reversealphabetical (Preview first, i.e. the order that used to leak),
three separate runs, all green, each number read from the per-class report file with its
mtime:

run PreviewContentServiceImplIT mtime BitstreamFormatRestRepositoryIT mtime total
1 13/0/0/0 (126.2 s) 10:56:05 22/0/0/2 (6.079 s) 10:56:12 Tests run: 35, Failures: 0, Errors: 0, Skipped: 2
2 13/0/0/0 (113.7 s) 10:58:33 22/0/0/2 (6.310 s) 10:58:39 Tests run: 35, Failures: 0, Errors: 0, Skipped: 2
3 13/0/0/0 (119.3 s) 11:08:35 22/0/0/2 (5.364 s) 11:08:40 Tests run: 35, Failures: 0, Errors: 0, Skipped: 2

(Skipped: 2 = the two pre-existing @Ignored tests, untouched.)

Negative control — the port is not vacuous. The same command on the un-ported base
origin/dtq-dev-9-base (1cda0dcd6c):

[INFO]  Tests run: 13, Failures: 0, Errors: 0, Skipped: 0 -- in PreviewContentServiceImplIT
[ERROR] Tests run: 22, Failures: 4, Errors: 0, Skipped: 2 <<< FAILURE! -- in BitstreamFormatRestRepositoryIT
[ERROR]   createNonAdminAccess, createAlreadyExisting, createNonValidSupportLevel, createNoAccess
JSON path "$.page.totalElements"   Expected: is <95>   but: was <108>
JSON path "$.page.totalElements"   Expected: is <96>   but: was <109>   (createAlreadyExisting)
[INFO] BUILD FAILURE

Exactly the four tests that assert against DEFAULT_AMOUNT_FORMATS fail, and the drift is
108 - 95 = 13 — one leaked bitstreamformatregistry row per PreviewContentServiceImplIT
test, which is precisely the mechanism the source PR describes. Note that Preview itself is
green on the base: the leak is invisible from inside the class that causes it, which is why
the gate has to fix class order.

🤖 Generated with Claude Code

…ted handle collisions, leaked bitstream formats, stale Solr searcher) (#1413)

Source: 23f3786 (dtq-dev PR #1413)

Test-only. All six flake sources the source commit removed exist unchanged on
this branch, so the port is a straight carry-over:

- ItemHandleCheckerIT / RequiredMetadataIT planted a random numeric handle
  (`123456789/` + 1000..1999) that `handle_seq` reaches late in the module run;
  the sequence mint path does no existence check, so whichever test was minting
  at that moment died on the handle unique index. Replaced by deterministic
  non-numeric suffixes (`handle-checker-test`, `required-metadata-test`), and
  the now-unused `randomString()` helper and `java.util.Random` import go away.
- XmlWorkflowFactoryTest used the numeric handle `123456789/999` for the
  non-mapped collection; same collision class, now `123456789/workflow-test-2`.
- PreviewContentServiceImplIT deleted its custom bitstream format through the
  shared test context after earlier builder deletes had detached it from the
  thread-bound session, so the delete was silently lost -- one leaked
  `bitstreamformatregistry` row per test, which broke BitstreamFormatRestRepositoryIT's
  counts whenever class order put Preview first. The id is now captured before
  `super.destroy()` and the row deleted afterwards through
  `BitstreamFormatBuilder.deleteBitstreamFormat`, which uses its own Context.
- BitstreamFormatRestRepositoryIT no longer asserts against the hardcoded
  `DEFAULT_AMOUNT_FORMATS = 95`; each affected test reads the live baseline via
  `currentTotalFormats()`. Short descriptions are unique in the format registry,
  so `createMockBitstreamRest()` derives them from the JUnit `@Rule TestName`
  instead of a random number, and `createAdminAccess` captures the created id in
  the `andDo` attached to the status check so cleanup still runs if a later
  assertion fails.
- StatisticsRestRepositoryIT#totalVisitsReport_Item_Visited queried the usage
  report before the posted view event became visible to a new Solr searcher; it
  now commits, exactly as topCountriesReport_Community_Visited already did.

One adaptation vs the source commit, in BitstreamFormatRestRepositoryIT only:
this branch already carries an unrelated refactor that replaced the six
per-test `ObjectMapper mapper = new ObjectMapper();` locals with a single
`@Autowired private ObjectMapper mapper` field. That field is kept and the
source hunks were applied on top of it, so no `new ObjectMapper()` returns.
Every added and removed line of the source patch for this file is otherwise
byte-identical (44 added / 25 removed, verified by diffing the two patches).

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 23f3786)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@milanmajchrak

Copy link
Copy Markdown
Collaborator Author

Local gate outputs (per sync rule 2.5)

Base: origin/dtq-dev-9-base = 233d87fe6f. Head: ccef3de5ed. (Branch was cut from
1cda0dcd6c and rebased when the base moved mid-session; the six test files are byte-identical
before and after the rebase.)

B1

$ mvn --no-transfer-progress -V clean install -P-assembly -DskipTests
[INFO] BUILD SUCCESS      EXIT=0        (checkstyle/license/enforcer not skipped, no violations)

AC gate — the two ITs in reverse-alphabetical class order (Preview first, i.e. the order that
used to leak a bitstream format), three runs at this head, all green.
target/failsafe-reports
was deleted before each run, and every number is read from the per-class report file with its
mtime, not the console tail.

run PreviewContentServiceImplIT mtime BitstreamFormatRestRepositoryIT mtime total
1 13/0/0/0 (96.76 s) 11:42:29 22/0/0/2 (5.436 s) 11:42:35 Tests run: 35, Failures: 0, Errors: 0, Skipped: 2
2 13/0/0/0 (95.29 s) 11:44:22 22/0/0/2 (5.141 s) 11:44:27 Tests run: 35, Failures: 0, Errors: 0, Skipped: 2
3 13/0/0/0 (90.58 s) 11:46:09 22/0/0/2 (5.325 s) 11:46:15 Tests run: 35, Failures: 0, Errors: 0, Skipped: 2

(Three further green runs were done at the pre-rebase base, so six in total. Skipped: 2 = the
two pre-existing @Ignored tests, untouched.)

Negative control — the port is not vacuous. The identical command on the un-ported base:

[INFO]  Tests run: 13, Failures: 0, Errors: 0, Skipped: 0 -- in PreviewContentServiceImplIT
[ERROR] Tests run: 22, Failures: 4, Errors: 0, Skipped: 2 <<< FAILURE! -- in BitstreamFormatRestRepositoryIT
[ERROR]   createNonAdminAccess · createAlreadyExisting · createNonValidSupportLevel · createNoAccess
JSON path "$.page.totalElements"   Expected: is <95>   but: was <108>
JSON path "$.page.totalElements"   Expected: is <96>   but: was <109>
[INFO] BUILD FAILURE

Exactly the four tests that assert against DEFAULT_AMOUNT_FORMATS fail, and the drift is
108 − 95 = 13 — one leaked bitstreamformatregistry row for each of Preview's 13 tests, which
is the mechanism the source PR describes. Preview itself stays green on the base: the leak is
invisible from inside the class that causes it, which is why the gate has to pin class order.

Hunk-level parity. Every added and removed line of 23f37863a4 is present byte-for-byte
(65 added / 48 removed, per-file +/- sets diffed against the source patch). The one
adaptation is BitstreamFormatRestRepositoryIT: this branch's @Autowired ObjectMapper field is
kept instead of re-introducing the six new ObjectMapper() locals the source keeps as context.

@milanmajchrak
milanmajchrak merged commit ad3c136 into dtq-dev-9-base Sep 10, 2026
12 checks passed
@milanmajchrak
milanmajchrak deleted the ufal/port-1413-9-base branch September 10, 2026 10:42
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.

1 participant