Skip to content

Commit 84cc587

Browse files
authored
Fix TextFieldBlockLoaderTests test assumption. (elastic#129361) (elastic#130682)
Test assumes that values from keyword doc values fields are in sorted order, but that is no longer the case and values are sometimes in order as was provided during indexing. Actual fix was to check for `synthetic_source_keep` instead of `ignore_above`. Also improved blockLoaderResult assertion by making it readable when it fails. Closes elastic#128012 Closes elastic#128011
1 parent 1f1b8e7 commit 84cc587

File tree

2 files changed

+96
-3
lines changed

2 files changed

+96
-3
lines changed

server/src/test/java/org/elasticsearch/index/mapper/blockloader/TextFieldBlockLoaderTests.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ public TextFieldBlockLoaderTests(Params params) {
2727

2828
@Override
2929
protected Object expected(Map<String, Object> fieldMapping, Object value, TestContext testContext) {
30+
logger.info("field mapping={}", fieldMapping);
31+
logger.info("value={}", value);
32+
logger.info("params={}", params.toString());
3033
return expectedValue(fieldMapping, value, params, testContext);
3134
}
3235

@@ -82,7 +85,8 @@ public static Object expectedValue(Map<String, Object> fieldMapping, Object valu
8285
.map(BytesRef::new)
8386
.collect(Collectors.toList());
8487

85-
if (store == false) {
88+
String ssk = (String) keywordMultiFieldMapping.get("synthetic_source_keep");
89+
if (store == false && "arrays".equals(ssk) == false) {
8690
// using doc_values for synthetic source
8791
indexed = new ArrayList<>(new HashSet<>(indexed));
8892
indexed.sort(BytesRef::compareTo);

test/framework/src/main/java/org/elasticsearch/index/mapper/BlockLoaderTestRunner.java

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.apache.lucene.index.LeafReaderContext;
1414
import org.apache.lucene.store.Directory;
1515
import org.apache.lucene.tests.index.RandomIndexWriter;
16+
import org.apache.lucene.util.BytesRef;
1617
import org.elasticsearch.common.bytes.BytesReference;
1718
import org.elasticsearch.index.IndexSettings;
1819
import org.elasticsearch.index.fieldvisitor.StoredFieldLoader;
@@ -21,14 +22,20 @@
2122
import org.elasticsearch.search.lookup.SearchLookup;
2223
import org.elasticsearch.xcontent.XContentBuilder;
2324
import org.elasticsearch.xcontent.XContentType;
24-
import org.junit.Assert;
25+
import org.hamcrest.BaseMatcher;
26+
import org.hamcrest.Description;
27+
import org.hamcrest.Matcher;
2528

2629
import java.io.IOException;
30+
import java.lang.reflect.Array;
31+
import java.util.ArrayList;
32+
import java.util.List;
2733
import java.util.Map;
2834
import java.util.Set;
2935

3036
import static org.apache.lucene.tests.util.LuceneTestCase.newDirectory;
3137
import static org.apache.lucene.tests.util.LuceneTestCase.random;
38+
import static org.elasticsearch.index.mapper.BlockLoaderTestRunner.PrettyEqual.prettyEqualTo;
3239
import static org.hamcrest.MatcherAssert.assertThat;
3340
import static org.hamcrest.Matchers.equalTo;
3441

@@ -44,7 +51,7 @@ public void runTest(MapperService mapperService, Map<String, Object> document, O
4451
var documentXContent = XContentBuilder.builder(XContentType.JSON.xContent()).map(document);
4552

4653
Object blockLoaderResult = setupAndInvokeBlockLoader(mapperService, documentXContent, blockLoaderFieldName);
47-
Assert.assertEquals(expected, blockLoaderResult);
54+
assertThat(blockLoaderResult, prettyEqualTo(expected));
4855
}
4956

5057
private Object setupAndInvokeBlockLoader(MapperService mapperService, XContentBuilder document, String fieldName) throws IOException {
@@ -145,4 +152,86 @@ public FieldNamesFieldMapper.FieldNamesFieldType fieldNames() {
145152
}
146153
});
147154
}
155+
156+
// Copied from org.hamcrest.core.IsEqual and modified to pretty print failure when bytesref
157+
static class PrettyEqual<T> extends BaseMatcher<T> {
158+
159+
private final Object expectedValue;
160+
161+
PrettyEqual(T equalArg) {
162+
expectedValue = equalArg;
163+
}
164+
165+
@Override
166+
public boolean matches(Object actualValue) {
167+
return areEqual(actualValue, expectedValue);
168+
}
169+
170+
@Override
171+
public void describeTo(Description description) {
172+
description.appendValue(attemptMakeReadable(expectedValue));
173+
}
174+
175+
@Override
176+
public void describeMismatch(Object item, Description description) {
177+
super.describeMismatch(attemptMakeReadable(item), description);
178+
}
179+
180+
private static boolean areEqual(Object actual, Object expected) {
181+
if (actual == null) {
182+
return expected == null;
183+
}
184+
185+
if (expected != null && isArray(actual)) {
186+
return isArray(expected) && areArraysEqual(actual, expected);
187+
}
188+
189+
return actual.equals(expected);
190+
}
191+
192+
private static boolean areArraysEqual(Object actualArray, Object expectedArray) {
193+
return areArrayLengthsEqual(actualArray, expectedArray) && areArrayElementsEqual(actualArray, expectedArray);
194+
}
195+
196+
private static boolean areArrayLengthsEqual(Object actualArray, Object expectedArray) {
197+
return Array.getLength(actualArray) == Array.getLength(expectedArray);
198+
}
199+
200+
private static boolean areArrayElementsEqual(Object actualArray, Object expectedArray) {
201+
for (int i = 0; i < Array.getLength(actualArray); i++) {
202+
if (areEqual(Array.get(actualArray, i), Array.get(expectedArray, i)) == false) {
203+
return false;
204+
}
205+
}
206+
return true;
207+
}
208+
209+
private static boolean isArray(Object o) {
210+
return o.getClass().isArray();
211+
}
212+
213+
// Attempt to make assertions readable:
214+
static Object attemptMakeReadable(Object expected) {
215+
try {
216+
if (expected instanceof BytesRef bytesRef) {
217+
expected = bytesRef.utf8ToString();
218+
} else if (expected instanceof List<?> list && list.getFirst() instanceof BytesRef) {
219+
List<String> expectedList = new ArrayList<>(list.size());
220+
for (Object e : list) {
221+
expectedList.add(((BytesRef) e).utf8ToString());
222+
}
223+
expected = expectedList;
224+
}
225+
return expected;
226+
} catch (Exception | AssertionError e) {
227+
// ip/geo fields can't be converted to strings:
228+
return expected;
229+
}
230+
}
231+
232+
public static <T> Matcher<T> prettyEqualTo(T operand) {
233+
return new PrettyEqual<>(operand);
234+
}
235+
236+
}
148237
}

0 commit comments

Comments
 (0)