Description
ContentletIndexAPIImpl is the vendor-neutral router of the ES→OpenSearch migration, but its integration test ContentletIndexAPIImplTest (dotcms-integration/src/test/java/com/dotcms/content/elasticsearch/business/ContentletIndexAPIImplTest.java, 1261 lines, 14 @Test) is still coupled to ElasticSearch internals.
Running the suite under a non-zero migration phase (verified at phase 3 via the new opensearch-phase-suite profile) makes 6 of 14 tests fail — most of them purely because of ES-specific assertions/helpers, not product defects.
./mvnw verify -pl :dotcms-integration -Dcoreit.test.skip=false \
-Dopensearch.phase.test=true -Dopensearch.phase=3 \
-Dit.test=ContentletIndexAPIImplTest
In scope (test decoupling — fix here):
- Replace the ES-direct search helper
indexSearch() (~L1088-1110: RestHighLevelClientProvider + SearchRequest/QueryBuilders/SearchSourceBuilder/SearchResponse/SearchHits) with the vendor-neutral read path (SearchAPI / ContentletAPI.search / ContentSearchResponse) so the read-back hits whichever store the active phase routes to.
- Replace
@Test(expected = ElasticsearchStatusException.class) (~L1257, testGetIndexDocumentCountWithInvalidIndexNameFails) with the neutral exception the router throws (DotRuntimeException wrapping the OS index-not-found). Observed under phase 3: expected ElasticsearchStatusException but was DotRuntimeException.
- Make the
.os naming assertion in activateDeactivateIndex phase-aware (observed ComparisonFailure: expected:<live_…[.os]> but was:<live_…[]>).
- Re-evaluate
testGetIndexDocumentCountSuccess and createContentIndexAndDelete (AssertionError) against the store the active phase uses.
- Remove the 8
org.elasticsearch.* imports (L80-87) once neutralized.
Out of scope (genuine product gaps — file as separate bug issues):
optimize → index_not_found_exception looking up the index without the .os suffix (optimize-path routing/naming gap under phase 3).
testSearch → MissingRequiredPropertyException: 'Builder.<variant kind>' parsing sitesearch index settings (OpenSearch client deserialization).
Test_TrackHits_SearchCount (in ESContentFactoryImplTest) → expected:<60> but was:<30>: the OS search path doesn't honor ES_TRACK_TOTAL_HITS like ES.
Acceptance Criteria
Additional Context
Blast-radius experiment (local, phase 3 / OS-only, opensearch-phase-suite): ContentletIndexAPIImplTest 8/14; rest of the high-level flow ~93% pass (ContentletCheckInTest 11/11, ESContentletAPIImplTest 87/89, ESContentFactoryImplTest 39/42) — confirming ES coupling is concentrated in this one class, not spread across the suite.
Related: PR #36268 / issue #36266 (added the opensearch-phase-suite profile and the phase-aware test bootstrap).
Description
ContentletIndexAPIImplis the vendor-neutral router of the ES→OpenSearch migration, but its integration testContentletIndexAPIImplTest(dotcms-integration/src/test/java/com/dotcms/content/elasticsearch/business/ContentletIndexAPIImplTest.java, 1261 lines, 14@Test) is still coupled to ElasticSearch internals.Running the suite under a non-zero migration phase (verified at phase 3 via the new
opensearch-phase-suiteprofile) makes 6 of 14 tests fail — most of them purely because of ES-specific assertions/helpers, not product defects.In scope (test decoupling — fix here):
indexSearch()(~L1088-1110:RestHighLevelClientProvider+SearchRequest/QueryBuilders/SearchSourceBuilder/SearchResponse/SearchHits) with the vendor-neutral read path (SearchAPI/ContentletAPI.search/ContentSearchResponse) so the read-back hits whichever store the active phase routes to.@Test(expected = ElasticsearchStatusException.class)(~L1257,testGetIndexDocumentCountWithInvalidIndexNameFails) with the neutral exception the router throws (DotRuntimeExceptionwrapping the OS index-not-found). Observed under phase 3: expectedElasticsearchStatusExceptionbut wasDotRuntimeException..osnaming assertion inactivateDeactivateIndexphase-aware (observedComparisonFailure: expected:<live_…[.os]> but was:<live_…[]>).testGetIndexDocumentCountSuccessandcreateContentIndexAndDelete(AssertionError) against the store the active phase uses.org.elasticsearch.*imports (L80-87) once neutralized.Out of scope (genuine product gaps — file as separate bug issues):
optimize→index_not_found_exceptionlooking up the index without the.ossuffix (optimize-path routing/naming gap under phase 3).testSearch→MissingRequiredPropertyException: 'Builder.<variant kind>'parsing sitesearch index settings (OpenSearch client deserialization).Test_TrackHits_SearchCount(inESContentFactoryImplTest) →expected:<60> but was:<30>: the OS search path doesn't honorES_TRACK_TOTAL_HITSlike ES.Acceptance Criteria
ContentletIndexAPIImplTestpasses under phase 0 (normal profile, ES) and phase 3 (-Dopensearch.phase.test=true -Dopensearch.phase=3).org.elasticsearch.*imports remain in the file.Additional Context
Blast-radius experiment (local, phase 3 / OS-only,
opensearch-phase-suite):ContentletIndexAPIImplTest8/14; rest of the high-level flow ~93% pass (ContentletCheckInTest11/11,ESContentletAPIImplTest87/89,ESContentFactoryImplTest39/42) — confirming ES coupling is concentrated in this one class, not spread across the suite.Related: PR #36268 / issue #36266 (added the
opensearch-phase-suiteprofile and the phase-aware test bootstrap).