New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix for ArithmeticException[/ by zero] when parsing a polygon #8475
Changes from 2 commits
c39ca47
345c06e
4993565
0067a0c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -155,6 +155,39 @@ public void testParse_polygonNoHoles() throws IOException { | |
assertGeometryEquals(jtsGeom(expected), polygonGeoJson); | ||
} | ||
|
||
@Test | ||
public void testParse_invalidPolygon() throws IOException { | ||
/** | ||
* TODO parser should fail if poly is not composed of an array of LinearRings | ||
* This test only checks number of coordinates, not the validity of the LinearRing | ||
*/ | ||
// test case 1: create an invalid polygon with only 2 points | ||
String invalidPoly1 = XContentFactory.jsonBuilder().startObject().field("type", "polygon") | ||
.startArray("coordinates") | ||
.startArray() | ||
.startArray().value(-74.011).value(40.753).endArray() | ||
.startArray().value(-75.022).value(41.783).endArray() | ||
.endArray() | ||
.endArray() | ||
.endObject().string(); | ||
XContentParser parser = JsonXContent.jsonXContent.createParser(invalidPoly1); | ||
parser.nextToken(); | ||
ElasticsearchGeoAssertions.assertValidParseException(parser); | ||
|
||
// test case 2: create an invalid polygon with only 1 point | ||
String invalidPolyGeoJson1 = XContentFactory.jsonBuilder().startObject().field("type", "polygon") | ||
.startArray("coordinates") | ||
.startArray() | ||
.startArray().value(-74.011).value(40.753).endArray() | ||
.endArray() | ||
.endArray() | ||
.endObject().string(); | ||
|
||
parser = JsonXContent.jsonXContent.createParser(invalidPolyGeoJson1); | ||
parser.nextToken(); | ||
ElasticsearchGeoAssertions.assertValidParseException(parser); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we now add a test for an invalid polygon with 0 points? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The following coordinate arrays are considered valid GeoJSON: {
"shape": {
"type": "polygon",
"coordinates": [[[]]]
}
}
{
"shape": {
"type": "polygon",
"coordinates": [[[null, null]]]
}
} The code, however, threw jackson parse exception and number format exceptions, respectively. The code has been updated to throw a more meaningful ParseException and IllegalArgumentException for these cases to help the end user diagnose the actual issue. |
||
|
||
@Test | ||
public void testParse_polygonWithHole() throws IOException { | ||
String polygonGeoJson = XContentFactory.jsonBuilder().startObject().field("type", "Polygon") | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,9 +26,12 @@ | |
import com.spatial4j.core.shape.jts.JtsGeometry; | ||
import com.spatial4j.core.shape.jts.JtsPoint; | ||
import com.vividsolutions.jts.geom.*; | ||
import org.elasticsearch.ElasticsearchParseException; | ||
import org.elasticsearch.common.geo.GeoDistance; | ||
import org.elasticsearch.common.geo.GeoPoint; | ||
import org.elasticsearch.common.geo.builders.ShapeBuilder; | ||
import org.elasticsearch.common.unit.DistanceUnit; | ||
import org.elasticsearch.common.xcontent.XContentParser; | ||
import org.hamcrest.Matcher; | ||
import org.junit.Assert; | ||
|
||
|
@@ -246,4 +249,12 @@ private static double distance(double lat1, double lon1, double lat2, double lon | |
return GeoDistance.ARC.calculate(lat1, lon1, lat2, lon2, DistanceUnit.DEFAULT); | ||
} | ||
|
||
public static void assertValidParseException(XContentParser parser) { | ||
try { | ||
ShapeBuilder.parse(parser); | ||
Assert.fail("process completed successfully when parse exception expected"); | ||
} catch (Exception e) { | ||
assert(e instanceof ElasticsearchParseException): "expected ElasticsearchParse exception but found " + e.getClass().getName(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could possibly use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Main thing here is that the test fails rather than errors on this line |
||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This statement and the message below don't seem to correlate. Should we not also check if
coordinates.children.size() == 0
here? Also from the linked spec it looks like 0 points would not be valid anyway?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. There's a discrepancy between JTS and GeoJSON. JTS treats 0 points as a valid linear ring/linestring where GeoJSON does not. If we're going to conform to GeoJSON (which I think is the right approach - but open for thoughts) then I should insert the check for 0 points.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, should not insert the check for 0 points. The current check would be valid per the GeoJSON spec - I'll change the exception message.