|
@@ -18,6 +18,7 @@
|
|
|
*/
|
|
|
package org.elasticsearch.common.unit;
|
|
|
|
|
|
+import org.elasticsearch.ElasticsearchParseException;
|
|
|
import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
|
|
import org.elasticsearch.common.io.stream.StreamInput;
|
|
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
@@ -32,37 +33,131 @@ import static org.hamcrest.CoreMatchers.equalTo;
|
|
|
import static org.hamcrest.CoreMatchers.sameInstance;
|
|
|
|
|
|
public class FuzzinessTests extends ESTestCase {
|
|
|
- public void testNumerics() {
|
|
|
- String[] options = new String[]{"1.0", "1", "1.000000"};
|
|
|
- assertThat(Fuzziness.build(randomFrom(options)).asFloat(), equalTo(1f));
|
|
|
+
|
|
|
+ public void testFromString() {
|
|
|
+ assertSame(Fuzziness.AUTO, Fuzziness.fromString("AUTO"));
|
|
|
+ assertSame(Fuzziness.AUTO, Fuzziness.fromString("auto"));
|
|
|
+ assertSame(Fuzziness.ZERO, Fuzziness.fromString("0"));
|
|
|
+ assertSame(Fuzziness.ZERO, Fuzziness.fromString("0.0"));
|
|
|
+ assertSame(Fuzziness.ONE, Fuzziness.fromString("1"));
|
|
|
+ assertSame(Fuzziness.ONE, Fuzziness.fromString("1.0"));
|
|
|
+ assertSame(Fuzziness.TWO, Fuzziness.fromString("2"));
|
|
|
+ assertSame(Fuzziness.TWO, Fuzziness.fromString("2.0"));
|
|
|
+
|
|
|
+ // cases that should throw exceptions
|
|
|
+ IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> Fuzziness.fromString(null));
|
|
|
+ assertEquals("fuzziness cannot be null or empty.", ex.getMessage());
|
|
|
+ ex = expectThrows(IllegalArgumentException.class, () -> Fuzziness.fromString(""));
|
|
|
+ assertEquals("fuzziness cannot be null or empty.", ex.getMessage());
|
|
|
+ ex = expectThrows(IllegalArgumentException.class, () -> Fuzziness.fromString("foo"));
|
|
|
+ assertEquals("fuzziness cannot be [foo].", ex.getMessage());
|
|
|
+ ex = expectThrows(IllegalArgumentException.class, () -> Fuzziness.fromString("1.2"));
|
|
|
+ assertEquals("fuzziness needs to be one of 0.0, 1.0 or 2.0 but was 1.2", ex.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ public void testNumericConstants() {
|
|
|
+ assertSame(Fuzziness.ZERO, Fuzziness.fromEdits(0));
|
|
|
+ assertSame(Fuzziness.ZERO, Fuzziness.fromString("0"));
|
|
|
+ assertSame(Fuzziness.ZERO, Fuzziness.fromString("0.0"));
|
|
|
+ assertThat(Fuzziness.ZERO.asString(), equalTo("0"));
|
|
|
+ assertThat(Fuzziness.ZERO.asDistance(), equalTo(0));
|
|
|
+ assertThat(Fuzziness.ZERO.asDistance(randomAlphaOfLengthBetween(0, randomIntBetween(1, 500))), equalTo(0));
|
|
|
+ assertThat(Fuzziness.ZERO.asFloat(), equalTo(0.0f));
|
|
|
+
|
|
|
+ assertSame(Fuzziness.ONE, Fuzziness.fromEdits(1));
|
|
|
+ assertSame(Fuzziness.ONE, Fuzziness.fromString("1"));
|
|
|
+ assertSame(Fuzziness.ONE, Fuzziness.fromString("1.0"));
|
|
|
+ assertThat(Fuzziness.ONE.asString(), equalTo("1"));
|
|
|
+ assertThat(Fuzziness.ONE.asDistance(), equalTo(1));
|
|
|
+ assertThat(Fuzziness.ONE.asDistance(randomAlphaOfLengthBetween(0, randomIntBetween(1, 500))), equalTo(1));
|
|
|
+ assertThat(Fuzziness.ONE.asFloat(), equalTo(1.0f));
|
|
|
+
|
|
|
+ assertSame(Fuzziness.TWO, Fuzziness.fromEdits(2));
|
|
|
+ assertSame(Fuzziness.TWO, Fuzziness.fromString("2"));
|
|
|
+ assertSame(Fuzziness.TWO, Fuzziness.fromString("2.0"));
|
|
|
+ assertThat(Fuzziness.TWO.asString(), equalTo("2"));
|
|
|
+ assertThat(Fuzziness.TWO.asDistance(), equalTo(2));
|
|
|
+ assertThat(Fuzziness.TWO.asDistance(randomAlphaOfLengthBetween(0, randomIntBetween(1, 500))), equalTo(2));
|
|
|
+ assertThat(Fuzziness.TWO.asFloat(), equalTo(2.0f));
|
|
|
+ }
|
|
|
+
|
|
|
+ public void testAutoFuzziness() {
|
|
|
+ assertSame(Fuzziness.AUTO, Fuzziness.fromString("auto"));
|
|
|
+ assertSame(Fuzziness.AUTO, Fuzziness.fromString("AUTO"));
|
|
|
+ assertThat(Fuzziness.AUTO.asString(), equalTo("AUTO"));
|
|
|
+ assertThat(Fuzziness.AUTO.asDistance(), equalTo(1));
|
|
|
+ assertThat(Fuzziness.AUTO.asDistance(randomAlphaOfLengthBetween(0, 2)), equalTo(0));
|
|
|
+ assertThat(Fuzziness.AUTO.asDistance(randomAlphaOfLengthBetween(3, 5)), equalTo(1));
|
|
|
+ assertThat(Fuzziness.AUTO.asDistance(randomAlphaOfLengthBetween(6, 100)), equalTo(2));
|
|
|
+ assertThat(Fuzziness.AUTO.asFloat(), equalTo(1.0f));
|
|
|
+ }
|
|
|
+
|
|
|
+ public void testCustomAutoFuzziness() {
|
|
|
+ int lowDistance = randomIntBetween(1, 10);
|
|
|
+ int highDistance = randomIntBetween(lowDistance, 20);
|
|
|
+ String auto = randomFrom("auto", "AUTO");
|
|
|
+ Fuzziness fuzziness = Fuzziness.fromString(auto + ":" + lowDistance + "," + highDistance);
|
|
|
+ assertNotSame(Fuzziness.AUTO, fuzziness);
|
|
|
+ if (lowDistance != Fuzziness.DEFAULT_LOW_DISTANCE || highDistance != Fuzziness.DEFAULT_HIGH_DISTANCE) {
|
|
|
+ assertThat(fuzziness.asString(), equalTo("AUTO:" + lowDistance + "," + highDistance));
|
|
|
+ }
|
|
|
+ if (lowDistance > 5) {
|
|
|
+ assertThat(fuzziness.asDistance(), equalTo(0));
|
|
|
+ } else if (highDistance > 5) {
|
|
|
+ assertThat(fuzziness.asDistance(), equalTo(1));
|
|
|
+ } else {
|
|
|
+ assertThat(fuzziness.asDistance(), equalTo(2));
|
|
|
+ }
|
|
|
+ assertThat(fuzziness.asDistance(randomAlphaOfLengthBetween(0, lowDistance - 1)), equalTo(0));
|
|
|
+ if (lowDistance != highDistance) {
|
|
|
+ assertThat(fuzziness.asDistance(randomAlphaOfLengthBetween(lowDistance, highDistance - 1)), equalTo(1));
|
|
|
+ }
|
|
|
+ assertThat(fuzziness.asDistance(randomAlphaOfLengthBetween(highDistance, 100)), equalTo(2));
|
|
|
+ assertThat(fuzziness.asFloat(), equalTo(1.0f));
|
|
|
+ }
|
|
|
+
|
|
|
+ public void testFromEditsIllegalArgs() {
|
|
|
+ int illegalValue = randomValueOtherThanMany(i -> i >= 0 && i <= 2, () -> randomInt());
|
|
|
+ IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> Fuzziness.fromEdits(illegalValue));
|
|
|
+ assertThat(e.getMessage(), equalTo("Valid edit distances are [0, 1, 2] but was [" + illegalValue + "]"));
|
|
|
+ }
|
|
|
+
|
|
|
+ public void testFromStringIllegalArgs() {
|
|
|
+ Exception e = expectThrows(IllegalArgumentException.class, () -> Fuzziness.fromString(null));
|
|
|
+ assertThat(e.getMessage(), equalTo("fuzziness cannot be null or empty."));
|
|
|
+
|
|
|
+ e = expectThrows(IllegalArgumentException.class, () -> Fuzziness.fromString(""));
|
|
|
+ assertThat(e.getMessage(), equalTo("fuzziness cannot be null or empty."));
|
|
|
+
|
|
|
+ e = expectThrows(IllegalArgumentException.class, () -> Fuzziness.fromString("illegal"));
|
|
|
+ assertThat(e.getMessage(), equalTo("fuzziness cannot be [illegal]."));
|
|
|
+
|
|
|
+ e = expectThrows(ElasticsearchParseException.class, () -> Fuzziness.fromString("AUTO:badFormat"));
|
|
|
+ assertThat(e.getMessage(), equalTo("failed to find low and high distance values"));
|
|
|
}
|
|
|
|
|
|
public void testParseFromXContent() throws IOException {
|
|
|
final int iters = randomIntBetween(10, 50);
|
|
|
for (int i = 0; i < iters; i++) {
|
|
|
{
|
|
|
- float floatValue = randomFloat();
|
|
|
+ float floatValue = randomFrom(0.0f, 1.0f, 2.0f);
|
|
|
XContentBuilder json = jsonBuilder().startObject()
|
|
|
- .field(Fuzziness.X_FIELD_NAME, floatValue)
|
|
|
+ .field(Fuzziness.X_FIELD_NAME, randomBoolean() ? String.valueOf(floatValue) : floatValue)
|
|
|
.endObject();
|
|
|
try (XContentParser parser = createParser(json)) {
|
|
|
assertThat(parser.nextToken(), equalTo(XContentParser.Token.START_OBJECT));
|
|
|
assertThat(parser.nextToken(), equalTo(XContentParser.Token.FIELD_NAME));
|
|
|
- assertThat(parser.nextToken(), equalTo(XContentParser.Token.VALUE_NUMBER));
|
|
|
+ assertThat(parser.nextToken(),
|
|
|
+ anyOf(equalTo(XContentParser.Token.VALUE_NUMBER), equalTo(XContentParser.Token.VALUE_STRING)));
|
|
|
Fuzziness fuzziness = Fuzziness.parse(parser);
|
|
|
assertThat(fuzziness.asFloat(), equalTo(floatValue));
|
|
|
assertThat(parser.nextToken(), equalTo(XContentParser.Token.END_OBJECT));
|
|
|
}
|
|
|
}
|
|
|
{
|
|
|
- Integer intValue = frequently() ? randomIntBetween(0, 2) : randomIntBetween(0, 100);
|
|
|
- Float floatRep = randomFloat();
|
|
|
- Number value = intValue;
|
|
|
- if (randomBoolean()) {
|
|
|
- value = Float.valueOf(floatRep += intValue);
|
|
|
- }
|
|
|
+ int intValue = randomIntBetween(0, 2);
|
|
|
XContentBuilder json = jsonBuilder().startObject()
|
|
|
- .field(Fuzziness.X_FIELD_NAME, randomBoolean() ? value.toString() : value)
|
|
|
+ .field(Fuzziness.X_FIELD_NAME, randomBoolean() ? String.valueOf(intValue) : intValue)
|
|
|
.endObject();
|
|
|
try (XContentParser parser = createParser(json)) {
|
|
|
assertThat(parser.nextToken(), equalTo(XContentParser.Token.START_OBJECT));
|
|
@@ -70,24 +165,19 @@ public class FuzzinessTests extends ESTestCase {
|
|
|
assertThat(parser.nextToken(), anyOf(equalTo(XContentParser.Token.VALUE_NUMBER),
|
|
|
equalTo(XContentParser.Token.VALUE_STRING)));
|
|
|
Fuzziness fuzziness = Fuzziness.parse(parser);
|
|
|
- if (value.intValue() >= 1) {
|
|
|
- assertThat(fuzziness.asDistance(), equalTo(Math.min(2, value.intValue())));
|
|
|
- }
|
|
|
assertThat(parser.nextToken(), equalTo(XContentParser.Token.END_OBJECT));
|
|
|
- if (intValue.equals(value)) {
|
|
|
- switch (intValue) {
|
|
|
- case 1:
|
|
|
- assertThat(fuzziness, sameInstance(Fuzziness.ONE));
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- assertThat(fuzziness, sameInstance(Fuzziness.TWO));
|
|
|
- break;
|
|
|
- case 0:
|
|
|
- assertThat(fuzziness, sameInstance(Fuzziness.ZERO));
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
+ switch (intValue) {
|
|
|
+ case 1:
|
|
|
+ assertThat(fuzziness, sameInstance(Fuzziness.ONE));
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ assertThat(fuzziness, sameInstance(Fuzziness.TWO));
|
|
|
+ break;
|
|
|
+ case 0:
|
|
|
+ assertThat(fuzziness, sameInstance(Fuzziness.ZERO));
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -104,7 +194,7 @@ public class FuzzinessTests extends ESTestCase {
|
|
|
int lowDistance = randomIntBetween(1, 3);
|
|
|
int highDistance = randomIntBetween(4, 10);
|
|
|
auto.append(":").append(lowDistance).append(",").append(highDistance);
|
|
|
- expectedFuzziness = Fuzziness.build(auto.toString());
|
|
|
+ expectedFuzziness = Fuzziness.fromString(auto.toString());
|
|
|
}
|
|
|
json = expectedFuzziness.toXContent(jsonBuilder().startObject(), null).endObject();
|
|
|
}
|
|
@@ -122,20 +212,6 @@ public class FuzzinessTests extends ESTestCase {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- public void testAuto() {
|
|
|
- assertThat(Fuzziness.AUTO.asFloat(), equalTo(1f));
|
|
|
- }
|
|
|
-
|
|
|
- public void testAsDistance() {
|
|
|
- final int iters = randomIntBetween(10, 50);
|
|
|
- for (int i = 0; i < iters; i++) {
|
|
|
- Integer integer = Integer.valueOf(randomIntBetween(0, 10));
|
|
|
- String value = "" + (randomBoolean() ? integer.intValue() : integer.floatValue());
|
|
|
- assertThat(Fuzziness.build(value).asDistance(), equalTo(Math.min(2, integer.intValue())));
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
public void testSerialization() throws IOException {
|
|
@@ -146,21 +222,16 @@ public class FuzzinessTests extends ESTestCase {
|
|
|
fuzziness = Fuzziness.fromEdits(randomIntBetween(0, 2));
|
|
|
deserializedFuzziness = doSerializeRoundtrip(fuzziness);
|
|
|
assertEquals(fuzziness, deserializedFuzziness);
|
|
|
- }
|
|
|
|
|
|
- public void testSerializationDefaultAuto() throws IOException {
|
|
|
- Fuzziness fuzziness = Fuzziness.AUTO;
|
|
|
- Fuzziness deserializedFuzziness = doSerializeRoundtrip(fuzziness);
|
|
|
- assertEquals(fuzziness, deserializedFuzziness);
|
|
|
- assertEquals(fuzziness.asFloat(), deserializedFuzziness.asFloat(), 0f);
|
|
|
- }
|
|
|
+ // custom AUTO
|
|
|
+ int lowDistance = randomIntBetween(1, 10);
|
|
|
+ int highDistance = randomIntBetween(lowDistance, 20);
|
|
|
+ fuzziness = Fuzziness.fromString("AUTO:" + lowDistance + "," + highDistance);
|
|
|
|
|
|
- public void testSerializationCustomAuto() throws IOException {
|
|
|
- Fuzziness original = Fuzziness.build("AUTO:4,7");
|
|
|
- Fuzziness deserializedFuzziness = doSerializeRoundtrip(original);
|
|
|
- assertNotSame(original, deserializedFuzziness);
|
|
|
- assertEquals(original, deserializedFuzziness);
|
|
|
- assertEquals(original.asString(), deserializedFuzziness.asString());
|
|
|
+ deserializedFuzziness = doSerializeRoundtrip(fuzziness);
|
|
|
+ assertNotSame(fuzziness, deserializedFuzziness);
|
|
|
+ assertEquals(fuzziness, deserializedFuzziness);
|
|
|
+ assertEquals(fuzziness.asString(), deserializedFuzziness.asString());
|
|
|
}
|
|
|
|
|
|
private static Fuzziness doSerializeRoundtrip(Fuzziness in) throws IOException {
|
|
@@ -171,21 +242,21 @@ public class FuzzinessTests extends ESTestCase {
|
|
|
}
|
|
|
|
|
|
public void testAsDistanceString() {
|
|
|
- Fuzziness fuzziness = Fuzziness.build("0");
|
|
|
+ Fuzziness fuzziness = Fuzziness.fromEdits(0);
|
|
|
assertEquals(0, fuzziness.asDistance(randomAlphaOfLengthBetween(0, 10)));
|
|
|
- fuzziness = Fuzziness.build("1");
|
|
|
+ fuzziness = Fuzziness.fromEdits(1);
|
|
|
assertEquals(1, fuzziness.asDistance(randomAlphaOfLengthBetween(0, 10)));
|
|
|
- fuzziness = Fuzziness.build("2");
|
|
|
+ fuzziness = Fuzziness.fromEdits(2);
|
|
|
assertEquals(2, fuzziness.asDistance(randomAlphaOfLengthBetween(0, 10)));
|
|
|
|
|
|
- fuzziness = Fuzziness.build("AUTO");
|
|
|
+ fuzziness = Fuzziness.fromString("AUTO");
|
|
|
assertEquals(0, fuzziness.asDistance(""));
|
|
|
assertEquals(0, fuzziness.asDistance("ab"));
|
|
|
assertEquals(1, fuzziness.asDistance("abc"));
|
|
|
assertEquals(1, fuzziness.asDistance("abcde"));
|
|
|
assertEquals(2, fuzziness.asDistance("abcdef"));
|
|
|
|
|
|
- fuzziness = Fuzziness.build("AUTO:5,7");
|
|
|
+ fuzziness = Fuzziness.fromString("AUTO:5,7");
|
|
|
assertEquals(0, fuzziness.asDistance(""));
|
|
|
assertEquals(0, fuzziness.asDistance("abcd"));
|
|
|
assertEquals(1, fuzziness.asDistance("abcde"));
|