/* * Licensed to Elasticsearch under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Elasticsearch licenses this file to you under * the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.elasticsearch.search.suggest.phrase; import org.elasticsearch.script.Script; import org.elasticsearch.search.suggest.AbstractSuggestionBuilderTestCase; import java.io.IOException; import java.util.HashMap; import java.util.Map; public class PhraseSuggestionBuilderTests extends AbstractSuggestionBuilderTestCase<PhraseSuggestionBuilder> { @Override protected PhraseSuggestionBuilder randomSuggestionBuilder() { return randomPhraseSuggestionBuilder(); } public static PhraseSuggestionBuilder randomPhraseSuggestionBuilder() { PhraseSuggestionBuilder testBuilder = new PhraseSuggestionBuilder(randomAlphaOfLengthBetween(2, 20)); setCommonPropertiesOnRandomBuilder(testBuilder); maybeSet(testBuilder::maxErrors, randomFloat()); maybeSet(testBuilder::separator, randomAlphaOfLengthBetween(1, 10)); maybeSet(testBuilder::realWordErrorLikelihood, randomFloat()); maybeSet(testBuilder::confidence, randomFloat()); maybeSet(testBuilder::collateQuery, randomAlphaOfLengthBetween(3, 20)); // collate query prune and parameters will only be used when query is set if (testBuilder.collateQuery() != null) { maybeSet(testBuilder::collatePrune, randomBoolean()); if (randomBoolean()) { Map<String, Object> collateParams = new HashMap<>(); int numParams = randomIntBetween(1, 5); for (int i = 0; i < numParams; i++) { collateParams.put(randomAlphaOfLength(5), randomAlphaOfLength(5)); } testBuilder.collateParams(collateParams ); } } if (randomBoolean()) { // preTag, postTag testBuilder.highlight(randomAlphaOfLengthBetween(3, 20), randomAlphaOfLengthBetween(3, 20)); } maybeSet(testBuilder::gramSize, randomIntBetween(1, 5)); maybeSet(testBuilder::forceUnigrams, randomBoolean()); maybeSet(testBuilder::tokenLimit, randomIntBetween(1, 20)); if (randomBoolean()) { testBuilder.smoothingModel(randomSmoothingModel()); } if (randomBoolean()) { int numGenerators = randomIntBetween(1, 5); for (int i = 0; i < numGenerators; i++) { testBuilder.addCandidateGenerator(DirectCandidateGeneratorTests.randomCandidateGenerator()); } } return testBuilder; } private static SmoothingModel randomSmoothingModel() { SmoothingModel model = null; switch (randomIntBetween(0,2)) { case 0: model = LaplaceModelTests.createRandomModel(); break; case 1: model = StupidBackoffModelTests.createRandomModel(); break; case 2: model = LinearInterpolationModelTests.createRandomModel(); break; } return model; } @Override protected void mutateSpecificParameters(PhraseSuggestionBuilder builder) throws IOException { switch (randomIntBetween(0, 12)) { case 0: builder.maxErrors(randomValueOtherThan(builder.maxErrors(), () -> randomFloat())); break; case 1: builder.realWordErrorLikelihood(randomValueOtherThan(builder.realWordErrorLikelihood(), () -> randomFloat())); break; case 2: builder.confidence(randomValueOtherThan(builder.confidence(), () -> randomFloat())); break; case 3: builder.gramSize(randomValueOtherThan(builder.gramSize(), () -> randomIntBetween(1, 5))); break; case 4: builder.tokenLimit(randomValueOtherThan(builder.tokenLimit(), () -> randomIntBetween(1, 20))); break; case 5: builder.separator(randomValueOtherThan(builder.separator(), () -> randomAlphaOfLengthBetween(1, 10))); break; case 6: Script collateQuery = builder.collateQuery(); if (collateQuery != null) { builder.collateQuery(randomValueOtherThan(collateQuery.getIdOrCode(), () -> randomAlphaOfLengthBetween(3, 20))); } else { builder.collateQuery(randomAlphaOfLengthBetween(3, 20)); } break; case 7: builder.collatePrune(builder.collatePrune() == null ? randomBoolean() : !builder.collatePrune() ); break; case 8: // preTag, postTag String currentPre = builder.preTag(); if (currentPre != null) { // simply double both values builder.highlight(builder.preTag() + builder.preTag(), builder.postTag() + builder.postTag()); } else { builder.highlight(randomAlphaOfLengthBetween(3, 20), randomAlphaOfLengthBetween(3, 20)); } break; case 9: builder.forceUnigrams(builder.forceUnigrams() == null ? randomBoolean() : ! builder.forceUnigrams()); break; case 10: Map<String, Object> collateParams = builder.collateParams() == null ? new HashMap<>(1) : builder.collateParams(); collateParams.put(randomAlphaOfLength(5), randomAlphaOfLength(5)); builder.collateParams(collateParams); break; case 11: builder.smoothingModel(randomValueOtherThan(builder.smoothingModel(), PhraseSuggestionBuilderTests::randomSmoothingModel)); break; case 12: builder.addCandidateGenerator(DirectCandidateGeneratorTests.randomCandidateGenerator()); break; } } public void testInvalidParameters() throws IOException { // test missing field name Exception e = expectThrows(NullPointerException.class, () -> new PhraseSuggestionBuilder((String) null)); assertEquals("suggestion requires a field name", e.getMessage()); // test empty field name e = expectThrows(IllegalArgumentException.class, () -> new PhraseSuggestionBuilder("")); assertEquals("suggestion field name is empty", e.getMessage()); PhraseSuggestionBuilder builder = new PhraseSuggestionBuilder(randomAlphaOfLengthBetween(2, 20)); e = expectThrows(IllegalArgumentException.class, () -> builder.gramSize(0)); assertEquals("gramSize must be >= 1", e.getMessage()); e = expectThrows(IllegalArgumentException.class, () -> builder.gramSize(-1)); assertEquals("gramSize must be >= 1", e.getMessage()); e = expectThrows(IllegalArgumentException.class, () -> builder.maxErrors(-1)); assertEquals("max_error must be > 0.0", e.getMessage()); e = expectThrows(NullPointerException.class, () -> builder.separator(null)); assertEquals("separator cannot be set to null", e.getMessage()); e = expectThrows(IllegalArgumentException.class, () -> builder.realWordErrorLikelihood(-1)); assertEquals("real_word_error_likelihood must be > 0.0", e.getMessage()); e = expectThrows(IllegalArgumentException.class, () -> builder.confidence(-1)); assertEquals("confidence must be >= 0.0", e.getMessage()); e = expectThrows(IllegalArgumentException.class, () -> builder.tokenLimit(0)); assertEquals("token_limit must be >= 1", e.getMessage()); e = expectThrows(IllegalArgumentException.class, () -> builder.highlight(null, "</b>")); assertEquals("Pre and post tag must both be null or both not be null.", e.getMessage()); e = expectThrows(IllegalArgumentException.class, () -> builder.highlight("<b>", null)); assertEquals("Pre and post tag must both be null or both not be null.", e.getMessage()); } }