Skip to content

Commit fe44a4d

Browse files
authored
test: fix SparseVectorFieldMapperTests edge case (#132937)
1 parent 3854e38 commit fe44a4d

File tree

2 files changed

+52
-24
lines changed

2 files changed

+52
-24
lines changed

muted-tests.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -489,9 +489,6 @@ tests:
489489
- class: org.elasticsearch.reservedstate.service.FileSettingsServiceIT
490490
method: testSettingsAppliedOnStart
491491
issue: https://github.com/elastic/elasticsearch/issues/131210
492-
- class: org.elasticsearch.index.mapper.vectors.SparseVectorFieldMapperTests
493-
method: testPruningScenarios
494-
issue: https://github.com/elastic/elasticsearch/issues/132810
495492
- class: org.elasticsearch.test.rest.yaml.CcsCommonYamlTestSuiteIT
496493
method: test {p0=search/160_exists_query/Test exists query on mapped date field with no doc values}
497494
issue: https://github.com/elastic/elasticsearch/issues/132828

server/src/test/java/org/elasticsearch/index/mapper/vectors/SparseVectorFieldMapperTests.java

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.elasticsearch.inference.WeightedToken;
4141
import org.elasticsearch.search.lookup.Source;
4242
import org.elasticsearch.search.vectors.SparseVectorQueryWrapper;
43+
import org.elasticsearch.test.ESTestCase;
4344
import org.elasticsearch.test.index.IndexVersionUtils;
4445
import org.elasticsearch.xcontent.ToXContent;
4546
import org.elasticsearch.xcontent.XContentBuilder;
@@ -55,16 +56,16 @@
5556
import java.util.LinkedHashMap;
5657
import java.util.List;
5758
import java.util.Map;
59+
import java.util.NavigableSet;
5860
import java.util.Set;
5961
import java.util.TreeMap;
6062
import java.util.stream.Collectors;
6163
import java.util.stream.Stream;
6264

65+
import static org.elasticsearch.index.IndexVersions.NEW_SPARSE_VECTOR;
6366
import static org.elasticsearch.index.IndexVersions.SPARSE_VECTOR_PRUNING_INDEX_OPTIONS_SUPPORT;
67+
import static org.elasticsearch.index.IndexVersions.SPARSE_VECTOR_PRUNING_INDEX_OPTIONS_SUPPORT_BACKPORT_8_X;
6468
import static org.elasticsearch.index.IndexVersions.UPGRADE_TO_LUCENE_10_0_0;
65-
import static org.elasticsearch.index.mapper.vectors.SparseVectorFieldMapper.NEW_SPARSE_VECTOR_INDEX_VERSION;
66-
import static org.elasticsearch.index.mapper.vectors.SparseVectorFieldMapper.PREVIOUS_SPARSE_VECTOR_INDEX_VERSION;
67-
import static org.elasticsearch.index.mapper.vectors.SparseVectorFieldMapper.SPARSE_VECTOR_PRUNING_INDEX_OPTIONS_VERSION;
6869
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertToXContentEquivalent;
6970
import static org.elasticsearch.xcontent.XContentFactory.jsonBuilder;
7071
import static org.hamcrest.Matchers.containsString;
@@ -286,7 +287,7 @@ public void testDefaultsWithAndWithoutIncludeDefaultsOlderIndexVersion() throws
286287
IndexVersion indexVersion = IndexVersionUtils.randomVersionBetween(
287288
random(),
288289
UPGRADE_TO_LUCENE_10_0_0,
289-
IndexVersionUtils.getPreviousVersion(SPARSE_VECTOR_PRUNING_INDEX_OPTIONS_VERSION)
290+
IndexVersionUtils.getPreviousVersion(SPARSE_VECTOR_PRUNING_INDEX_OPTIONS_SUPPORT)
290291
);
291292

292293
XContentBuilder orig = JsonXContent.contentBuilder().startObject();
@@ -501,21 +502,21 @@ protected IngestScriptSupport ingestScriptSupport() {
501502
@Override
502503
protected String[] getParseMinimalWarnings(IndexVersion indexVersion) {
503504
String[] additionalWarnings = null;
504-
if (indexVersion.before(PREVIOUS_SPARSE_VECTOR_INDEX_VERSION)) {
505+
if (indexVersion.before(IndexVersions.V_8_0_0)) {
505506
additionalWarnings = new String[] { SparseVectorFieldMapper.ERROR_MESSAGE_7X };
506507
}
507508
return Strings.concatStringArrays(super.getParseMinimalWarnings(indexVersion), additionalWarnings);
508509
}
509510

510511
@Override
511512
protected IndexVersion boostNotAllowedIndexVersion() {
512-
return NEW_SPARSE_VECTOR_INDEX_VERSION;
513+
return NEW_SPARSE_VECTOR;
513514
}
514515

515516
public void testSparseVectorUnsupportedIndex() {
516517
IndexVersion version = IndexVersionUtils.randomVersionBetween(
517518
random(),
518-
PREVIOUS_SPARSE_VECTOR_INDEX_VERSION,
519+
IndexVersions.V_8_0_0,
519520
IndexVersions.FIRST_DETACHED_INDEX_VERSION
520521
);
521522
Exception e = expectThrows(MapperParsingException.class, () -> createMapperService(version, fieldMapping(b -> {
@@ -742,9 +743,11 @@ private void withSearchExecutionContext(MapperService mapperService, CheckedCons
742743

743744
iw.addDocument(mapper.parse(source(b -> b.field("field", RARE_TOKENS))).rootDoc());
744745

745-
// This will lower the averageTokenFreqRatio so that common tokens get pruned with default settings
746+
// This will lower the averageTokenFreqRatio so that common tokens get pruned with default settings.
747+
// Depending on how the index is created, we will have 30-37 numUniqueTokens
748+
// this will result in an averageTokenFreqRatio of 0.1021 - 0.1259
746749
Map<String, Float> uniqueDoc = new TreeMap<>();
747-
for (int i = 0; i < 20; i++) {
750+
for (int i = 0; i < 30; i++) {
748751
uniqueDoc.put("unique" + i, 0.5f);
749752
}
750753
iw.addDocument(mapper.parse(source(b -> b.field("field", uniqueDoc))).rootDoc());
@@ -758,10 +761,10 @@ private void withSearchExecutionContext(MapperService mapperService, CheckedCons
758761
}
759762

760763
public void testPruningScenarios() throws Exception {
761-
for (int i = 0; i < 120; i++) {
764+
for (int i = 0; i < 200; i++) {
762765
assertPruningScenario(
763766
randomFrom(validIndexPruningScenarios),
764-
new PruningOptions(randomBoolean() ? randomBoolean() : null, randomFrom(PruningConfig.values()))
767+
new PruningOptions(randomFrom(true, false, null), randomFrom(PruningConfig.values()))
765768
);
766769
}
767770
}
@@ -791,7 +794,8 @@ private PruningScenario getEffectivePruningScenario(
791794
}
792795

793796
if (shouldPrune == null) {
794-
shouldPrune = indexVersion.onOrAfter(SPARSE_VECTOR_PRUNING_INDEX_OPTIONS_SUPPORT);
797+
shouldPrune = indexVersion.between(SPARSE_VECTOR_PRUNING_INDEX_OPTIONS_SUPPORT_BACKPORT_8_X, UPGRADE_TO_LUCENE_10_0_0)
798+
|| indexVersion.onOrAfter(SPARSE_VECTOR_PRUNING_INDEX_OPTIONS_SUPPORT);
795799
}
796800

797801
PruningScenario pruningScenario = PruningScenario.NO_PRUNING;
@@ -829,7 +833,7 @@ private List<Query> getExpectedQueryClauses(
829833
}
830834

831835
private void assertPruningScenario(PruningOptions indexPruningOptions, PruningOptions queryPruningOptions) throws IOException {
832-
IndexVersion indexVersion = getIndexVersionForTest(randomBoolean());
836+
IndexVersion indexVersion = getIndexVersion();
833837
MapperService mapperService = createMapperService(indexVersion, getIndexMapping(indexPruningOptions));
834838
PruningScenario effectivePruningScenario = getEffectivePruningScenario(indexPruningOptions, queryPruningOptions, indexVersion);
835839
withSearchExecutionContext(mapperService, (context) -> {
@@ -848,14 +852,41 @@ private void assertPruningScenario(PruningOptions indexPruningOptions, PruningOp
848852
});
849853
}
850854

851-
private IndexVersion getIndexVersionForTest(boolean usePreviousIndex) {
852-
return usePreviousIndex
853-
? IndexVersionUtils.randomVersionBetween(
854-
random(),
855-
UPGRADE_TO_LUCENE_10_0_0,
856-
IndexVersionUtils.getPreviousVersion(SPARSE_VECTOR_PRUNING_INDEX_OPTIONS_SUPPORT)
857-
)
858-
: IndexVersionUtils.randomVersionBetween(random(), SPARSE_VECTOR_PRUNING_INDEX_OPTIONS_SUPPORT, IndexVersion.current());
855+
private static IndexVersion getIndexVersion() {
856+
VersionRange versionRange = randomFrom(VersionRange.values());
857+
return versionRange.getRandomVersion();
858+
}
859+
860+
private enum VersionRange {
861+
ES_V8X_WITHOUT_INDEX_OPTIONS_SUPPORT(
862+
NEW_SPARSE_VECTOR,
863+
IndexVersionUtils.getPreviousVersion(SPARSE_VECTOR_PRUNING_INDEX_OPTIONS_SUPPORT_BACKPORT_8_X)
864+
),
865+
ES_V8X_WITH_INDEX_OPTIONS_SUPPORT(
866+
SPARSE_VECTOR_PRUNING_INDEX_OPTIONS_SUPPORT_BACKPORT_8_X,
867+
IndexVersionUtils.getPreviousVersion(UPGRADE_TO_LUCENE_10_0_0)
868+
),
869+
ES_V9X_WITHOUT_INDEX_OPTIONS_SUPPORT(
870+
UPGRADE_TO_LUCENE_10_0_0,
871+
IndexVersionUtils.getPreviousVersion(SPARSE_VECTOR_PRUNING_INDEX_OPTIONS_SUPPORT)
872+
),
873+
ES_V9X_WITH_INDEX_OPTIONS_SUPPORT(SPARSE_VECTOR_PRUNING_INDEX_OPTIONS_SUPPORT, IndexVersion.current());
874+
875+
private final IndexVersion fromVersion;
876+
private final IndexVersion toVersion;
877+
878+
VersionRange(IndexVersion fromVersion, IndexVersion toVersion) {
879+
this.fromVersion = fromVersion;
880+
this.toVersion = toVersion;
881+
}
882+
883+
IndexVersion getRandomVersion() {
884+
// TODO: replace implementation with `IndexVersionUtils::randomVersionBetween` once support is added
885+
// for handling unbalanced version distributions.
886+
NavigableSet<IndexVersion> allReleaseVersions = IndexVersionUtils.allReleasedVersions();
887+
Set<IndexVersion> candidateVersions = allReleaseVersions.subSet(fromVersion, toVersion);
888+
return ESTestCase.randomFrom(candidateVersions);
889+
}
859890
}
860891

861892
private static final List<WeightedToken> QUERY_VECTORS = Stream.of(RARE_TOKENS, MEDIUM_TOKENS, COMMON_TOKENS)

0 commit comments

Comments
 (0)