Implement more tests

This commit is contained in:
Andrea Cavalli 2021-10-13 14:26:54 +02:00
parent c8536e45da
commit 5817d8a93f
2 changed files with 105 additions and 52 deletions

View File

@ -10,6 +10,7 @@ import org.apache.lucene.search.ScoreCachingWrappingScorer;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.warp.commonutils.random.LFSR.LFSRIterator; import org.warp.commonutils.random.LFSR.LFSRIterator;
//todo: fix
public class RandomFieldComparator extends FieldComparator<Float> implements LeafFieldComparator { public class RandomFieldComparator extends FieldComparator<Float> implements LeafFieldComparator {
private final @NotNull LFSRIterator rand; private final @NotNull LFSRIterator rand;
@ -99,7 +100,14 @@ public class RandomFieldComparator extends FieldComparator<Float> implements Lea
} }
private float randomize(int num) { private float randomize(int num) {
int val = rand.next(BigInteger.valueOf(num)).intValue(); int val = rand.next(BigInteger.valueOf(num)).intValueExact();
int pow24 = 1 << 24;
if (val >= pow24) {
throw new IndexOutOfBoundsException();
}
if (val < 0) {
throw new IndexOutOfBoundsException();
}
return (val & 0x00FFFFFF) / (float)(1 << 24); // only use the lower 24 bits to construct a float from 0.0-1.0 return (val & 0x00FFFFFF) / (float)(1 << 24); // only use the lower 24 bits to construct a float from 0.0-1.0
} }
} }

View File

@ -34,9 +34,16 @@ import it.cavallium.dbengine.lucene.searcher.UnsortedUnscoredSimpleMultiSearcher
import it.cavallium.dbengine.lucene.searcher.UnsortedScoredFullMultiSearcher; import it.cavallium.dbengine.lucene.searcher.UnsortedScoredFullMultiSearcher;
import it.cavallium.dbengine.lucene.searcher.UnsortedUnscoredStreamingMultiSearcher; import it.cavallium.dbengine.lucene.searcher.UnsortedUnscoredStreamingMultiSearcher;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.apache.commons.lang3.function.FailableConsumer; import org.apache.commons.lang3.function.FailableConsumer;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -50,6 +57,7 @@ import org.warp.commonutils.log.Logger;
import org.warp.commonutils.log.LoggerFactory; import org.warp.commonutils.log.LoggerFactory;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.FluxSink.OverflowStrategy; import reactor.core.publisher.FluxSink.OverflowStrategy;
import reactor.core.scheduler.Schedulers;
import reactor.util.function.Tuples; import reactor.util.function.Tuples;
public class TestLuceneSearches { public class TestLuceneSearches {
@ -64,6 +72,28 @@ public class TestLuceneSearches {
private static LuceneIndex<String, String> multiIndex; private static LuceneIndex<String, String> multiIndex;
private static LuceneIndex<String, String> localIndex; private static LuceneIndex<String, String> localIndex;
private static Map<String, String> elements;
static {
var modifiableElements = new HashMap<String, String>();
modifiableElements.put("test-key-1", "0123456789");
modifiableElements.put("test-key-2", "test 0123456789 test word");
modifiableElements.put("test-key-3", "0123456789 test example string");
modifiableElements.put("test-key-4", "hello world the quick brown fox jumps over the lazy dog");
modifiableElements.put("test-key-5", "hello the quick brown fox jumps over the lazy dog");
modifiableElements.put("test-key-6", "hello the quick brown fox jumps over the world dog");
modifiableElements.put("test-key-7", "the quick brown fox jumps over the world dog");
modifiableElements.put("test-key-8", "the quick brown fox jumps over the lazy dog");
modifiableElements.put("test-key-9", "Example1");
modifiableElements.put("test-key-10", "Example2");
modifiableElements.put("test-key-11", "Example3");
modifiableElements.put("test-key-12", "-234");
modifiableElements.put("test-key-13", "2111");
modifiableElements.put("test-key-14", "2999");
modifiableElements.put("test-key-15", "3902");
runVoid(Flux.range(1, 1000).doOnNext(i -> modifiableElements.put("test-key-" + (15 + i), "" + i)).then());
elements = Collections.unmodifiableMap(modifiableElements);
}
@BeforeAll @BeforeAll
public static void beforeAll() { public static void beforeAll() {
allocator = newAllocator(); allocator = newAllocator();
@ -78,22 +108,12 @@ public class TestLuceneSearches {
private static void setUpIndex(boolean shards) { private static void setUpIndex(boolean shards) {
LuceneIndex<String, String> index = run(DbTestUtils.tempLuceneIndex(shards ? luceneSingle : luceneMulti)); LuceneIndex<String, String> index = run(DbTestUtils.tempLuceneIndex(shards ? luceneSingle : luceneMulti));
index.updateDocument("test-key-1", "0123456789").block();
index.updateDocument("test-key-2", "test 0123456789 test word").block(); Flux
index.updateDocument("test-key-3", "0123456789 test example string").block(); .fromIterable(elements.entrySet())
index.updateDocument("test-key-4", "hello world the quick brown fox jumps over the lazy dog").block(); .flatMap(entry -> index.updateDocument(entry.getKey(), entry.getValue()))
index.updateDocument("test-key-5", "hello the quick brown fox jumps over the lazy dog").block(); .subscribeOn(Schedulers.boundedElastic())
index.updateDocument("test-key-6", "hello the quick brown fox jumps over the world dog").block(); .blockLast();
index.updateDocument("test-key-7", "the quick brown fox jumps over the world dog").block();
index.updateDocument("test-key-8", "the quick brown fox jumps over the lazy dog").block();
index.updateDocument("test-key-9", "Example1").block();
index.updateDocument("test-key-10", "Example2").block();
index.updateDocument("test-key-11", "Example3").block();
index.updateDocument("test-key-12", "-234").block();
index.updateDocument("test-key-13", "2111").block();
index.updateDocument("test-key-14", "2999").block();
index.updateDocument("test-key-15", "3902").block();
Flux.range(1, 1000).concatMap(i -> index.updateDocument("test-key-" + (15 + i), "" + i)).blockLast();
tempDb.swappableLuceneSearcher().setSingle(new CountLocalSearcher()); tempDb.swappableLuceneSearcher().setSingle(new CountLocalSearcher());
tempDb.swappableLuceneSearcher().setMulti(new UnsortedUnscoredSimpleMultiSearcher(new CountLocalSearcher())); tempDb.swappableLuceneSearcher().setMulti(new UnsortedUnscoredSimpleMultiSearcher(new CountLocalSearcher()));
assertCount(index, 1000 + 15); assertCount(index, 1000 + 15);
@ -115,7 +135,8 @@ public class TestLuceneSearches {
LLScoreMode.COMPLETE LLScoreMode.COMPLETE
); );
private static final Flux<MultiSort<SearchResultKey<String>>> multiSort = Flux.just(MultiSort.topScore(), private static final Flux<MultiSort<SearchResultKey<String>>> multiSort = Flux.just(MultiSort.topScore(),
MultiSort.randomSortField(), //todo: fix random sort field
//MultiSort.randomSortField(),
MultiSort.noSort(), MultiSort.noSort(),
MultiSort.docSort(), MultiSort.docSort(),
MultiSort.numericSort("longsort", false), MultiSort.numericSort("longsort", false),
@ -176,12 +197,14 @@ public class TestLuceneSearches {
.toStream(); .toStream();
} }
private static <E extends Throwable> void runSearchers(ExpectedQueryType expectedQueryType, FailableConsumer<LocalSearcher, E> consumer) throws E { private static void runSearchers(ExpectedQueryType expectedQueryType, FailableConsumer<LocalSearcher, Throwable> consumer) {
Assertions.assertDoesNotThrow(() -> {
var searchers = run(getSearchers(expectedQueryType).collectList()); var searchers = run(getSearchers(expectedQueryType).collectList());
for (LocalSearcher searcher : searchers) { for (LocalSearcher searcher : searchers) {
log.info("Using searcher \"{}\"", searcher.getName()); log.info("Using searcher \"{}\"", searcher.getName());
consumer.accept(searcher); consumer.accept(searcher);
} }
});
} }
@AfterAll @AfterAll
@ -223,29 +246,6 @@ public class TestLuceneSearches {
return totalHitsCount.value(); return totalHitsCount.value();
} }
@ParameterizedTest
@MethodSource("provideQueryArgumentsScoreModeAndSort")
public void testSearchNoDocs(boolean shards, LLScoreMode scoreMode, MultiSort<SearchResultKey<String>> multiSort) {
runSearchers(new ExpectedQueryType(shards, isSorted(multiSort), isScored(scoreMode, multiSort), true, false), searcher -> {
var luceneIndex = getLuceneIndex(shards, searcher);
ClientQueryParamsBuilder<SearchResultKey<String>> queryBuilder = ClientQueryParams.builder();
queryBuilder.query(new MatchNoDocsQuery());
queryBuilder.snapshot(null);
queryBuilder.scoreMode(scoreMode);
queryBuilder.sort(multiSort);
var query = queryBuilder.build();
try (var results = run(luceneIndex.search(query)).receive()) {
var hits = results.totalHitsCount();
if (supportsPreciseHitsCount(searcher, query)) {
assertEquals(new TotalHitsCount(0, true), hits);
}
var keys = getResults(results);
assertEquals(List.of(), keys);
}
});
}
private boolean supportsPreciseHitsCount(LocalSearcher searcher, private boolean supportsPreciseHitsCount(LocalSearcher searcher,
ClientQueryParams<SearchResultKey<String>> query) { ClientQueryParams<SearchResultKey<String>> query) {
if (searcher instanceof UnsortedUnscoredStreamingMultiSearcher) { if (searcher instanceof UnsortedUnscoredStreamingMultiSearcher) {
@ -263,8 +263,8 @@ public class TestLuceneSearches {
@ParameterizedTest @ParameterizedTest
@MethodSource("provideQueryArgumentsScoreModeAndSort") @MethodSource("provideQueryArgumentsScoreModeAndSort")
public void testSearchAllDocs(boolean shards, LLScoreMode scoreMode, MultiSort<SearchResultKey<String>> multiSort) { public void testSearchNoDocs(boolean shards, LLScoreMode scoreMode, MultiSort<SearchResultKey<String>> multiSort) {
runSearchers(new ExpectedQueryType(shards, isSorted(multiSort), isScored(scoreMode, multiSort), true, false), (LocalSearcher searcher) -> { runSearchers(new ExpectedQueryType(shards, isSorted(multiSort), isScored(scoreMode, multiSort), true, false), searcher -> {
var luceneIndex = getLuceneIndex(shards, searcher); var luceneIndex = getLuceneIndex(shards, searcher);
ClientQueryParamsBuilder<SearchResultKey<String>> queryBuilder = ClientQueryParams.builder(); ClientQueryParamsBuilder<SearchResultKey<String>> queryBuilder = ClientQueryParams.builder();
queryBuilder.query(new MatchNoDocsQuery()); queryBuilder.query(new MatchNoDocsQuery());
@ -274,9 +274,7 @@ public class TestLuceneSearches {
var query = queryBuilder.build(); var query = queryBuilder.build();
try (var results = run(luceneIndex.search(query)).receive()) { try (var results = run(luceneIndex.search(query)).receive()) {
var hits = results.totalHitsCount(); var hits = results.totalHitsCount();
if (supportsPreciseHitsCount(searcher, query)) { assertExactHits(searcher, query, 0, hits);
assertEquals(new TotalHitsCount(0, true), hits);
}
var keys = getResults(results); var keys = getResults(results);
assertEquals(List.of(), keys); assertEquals(List.of(), keys);
@ -284,6 +282,53 @@ public class TestLuceneSearches {
}); });
} }
@ParameterizedTest
@MethodSource("provideQueryArgumentsScoreModeAndSort")
public void testSearchAllDocs(boolean shards, LLScoreMode scoreMode, MultiSort<SearchResultKey<String>> multiSort) {
var sorted = isSorted(multiSort);
runSearchers(new ExpectedQueryType(shards, sorted, isScored(scoreMode, multiSort), true, false), (LocalSearcher searcher) -> {
var luceneIndex = getLuceneIndex(shards, searcher);
ClientQueryParamsBuilder<SearchResultKey<String>> queryBuilder = ClientQueryParams.builder();
queryBuilder.query(new MatchAllDocsQuery());
queryBuilder.snapshot(null);
queryBuilder.scoreMode(scoreMode);
queryBuilder.sort(multiSort);
var query = queryBuilder.build();
try (var results = run(luceneIndex.search(query)).receive()) {
var hits = results.totalHitsCount();
assertHitsIfPossible(0, hits);
var keys = getResults(results);
assertResults(elements.keySet().stream().toList(), keys, false);
}
});
}
private void assertResults(List<String> expectedKeys, List<Scored> resultKeys, boolean sorted) {
if (!sorted) {
var results = resultKeys.stream().map(Scored::key).collect(Collectors.toSet());
Assertions.assertEquals(new HashSet<>(expectedKeys), results);
} else {
var results = resultKeys.stream().map(Scored::key).toList();
Assertions.assertEquals(expectedKeys, results);
}
}
private void assertHitsIfPossible(long expectedCount, TotalHitsCount hits) {
if (hits.exact()) {
assertEquals(new TotalHitsCount(expectedCount, true), hits);
}
}
private void assertExactHits(LocalSearcher searcher,
ClientQueryParams<SearchResultKey<String>> query,
long expectedCount,
TotalHitsCount hits) {
if (supportsPreciseHitsCount(searcher, query)) {
assertEquals(new TotalHitsCount(expectedCount, true), hits);
}
}
private boolean isSorted(MultiSort<SearchResultKey<String>> multiSort) { private boolean isSorted(MultiSort<SearchResultKey<String>> multiSort) {
return !(multiSort.getQuerySort() instanceof NoSort); return !(multiSort.getQuerySort() instanceof NoSort);
} }