浏览代码

Add unit tests for GeoBoundsAggregator/InternalGeoBounds (#23259)

* Add unit tests for GeoBoundsAggregator/InternalGeoBounds

Relates #22278
Jim Ferenczi 8 年之前
父节点
当前提交
76d6b872dd

+ 1 - 1
core/src/main/java/org/elasticsearch/index/mapper/GeoPointFieldMapper.java

@@ -162,7 +162,7 @@ public class GeoPointFieldMapper extends FieldMapper implements ArrayValueMapper
     }
 
     public static class GeoPointFieldType extends MappedFieldType {
-        GeoPointFieldType() {
+        public GeoPointFieldType() {
         }
 
         GeoPointFieldType(GeoPointFieldType ref) {

+ 30 - 14
core/src/main/java/org/elasticsearch/search/aggregations/metrics/geobounds/InternalGeoBounds.java

@@ -30,19 +30,20 @@ import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
 import java.io.IOException;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 public class InternalGeoBounds extends InternalMetricsAggregation implements GeoBounds {
-    private final double top;
-    private final double bottom;
-    private final double posLeft;
-    private final double posRight;
-    private final double negLeft;
-    private final double negRight;
-    private final boolean wrapLongitude;
+    final double top;
+    final double bottom;
+    final double posLeft;
+    final double posRight;
+    final double negLeft;
+    final double negRight;
+    final boolean wrapLongitude;
 
     InternalGeoBounds(String name, double top, double bottom, double posLeft, double posRight,
-            double negLeft, double negRight, boolean wrapLongitude,
-            List<PipelineAggregator> pipelineAggregators, Map<String, Object> metaData) {
+                      double negLeft, double negRight, boolean wrapLongitude,
+                      List<PipelineAggregator> pipelineAggregators, Map<String, Object> metaData) {
         super(name, pipelineAggregators, metaData);
         this.top = top;
         this.bottom = bottom;
@@ -82,7 +83,7 @@ public class InternalGeoBounds extends InternalMetricsAggregation implements Geo
     public String getWriteableName() {
         return GeoBoundsAggregationBuilder.NAME;
     }
-    
+
     @Override
     public InternalAggregation doReduce(List<InternalAggregation> aggregations, ReduceContext reduceContext) {
         double top = Double.NEGATIVE_INFINITY;
@@ -187,21 +188,21 @@ public class InternalGeoBounds extends InternalMetricsAggregation implements Geo
     private static class BoundingBox {
         private final GeoPoint topLeft;
         private final GeoPoint bottomRight;
-        
+
         BoundingBox(GeoPoint topLeft, GeoPoint bottomRight) {
             this.topLeft = topLeft;
             this.bottomRight = bottomRight;
         }
-        
+
         public GeoPoint topLeft() {
             return topLeft;
         }
-        
+
         public GeoPoint bottomRight() {
             return bottomRight;
         }
     }
-    
+
     private BoundingBox resolveBoundingBox() {
         if (Double.isInfinite(top)) {
             return null;
@@ -242,4 +243,19 @@ public class InternalGeoBounds extends InternalMetricsAggregation implements Geo
         }
     }
 
+    @Override
+    protected boolean doEquals(Object obj) {
+        InternalGeoBounds other = (InternalGeoBounds) obj;
+        return bottom == other.bottom &&
+            posLeft == other.posLeft &&
+            posRight == other.posRight &&
+            negLeft == other.negLeft &&
+            negRight == other.negRight &&
+            wrapLongitude == other.wrapLongitude;
+    }
+
+    @Override
+    protected int doHashCode() {
+        return Objects.hash(bottom, posLeft, posRight, negLeft, negRight, wrapLongitude);
+    }
 }

+ 118 - 0
core/src/test/java/org/elasticsearch/search/aggregations/metrics/geobounds/GeoBoundsAggregatorTests.java

@@ -0,0 +1,118 @@
+/*
+ * 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.aggregations.metrics.geobounds;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.LatLonDocValuesField;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.MatchAllDocsQuery;
+import org.apache.lucene.store.Directory;
+import org.elasticsearch.common.geo.GeoPoint;
+import org.elasticsearch.index.mapper.GeoPointFieldMapper;
+import org.elasticsearch.index.mapper.MappedFieldType;
+import org.elasticsearch.search.aggregations.AggregatorTestCase;
+import org.elasticsearch.test.geo.RandomGeoGenerator;
+
+import static org.elasticsearch.search.aggregations.metrics.geobounds.InternalGeoBoundsTests.GEOHASH_TOLERANCE;
+import static org.hamcrest.Matchers.closeTo;
+
+public class GeoBoundsAggregatorTests extends AggregatorTestCase {
+    public void testEmpty() throws Exception {
+        try (Directory dir = newDirectory();
+             RandomIndexWriter w = new RandomIndexWriter(random(), dir)) {
+            GeoBoundsAggregationBuilder aggBuilder = new GeoBoundsAggregationBuilder("my_agg")
+                .field("field")
+                .wrapLongitude(false);
+
+            MappedFieldType fieldType = new GeoPointFieldMapper.GeoPointFieldType();
+            fieldType.setHasDocValues(true);
+            fieldType.setName("field");
+            try (IndexReader reader = w.getReader()) {
+                IndexSearcher searcher = new IndexSearcher(reader);
+                InternalGeoBounds bounds = search(searcher, new MatchAllDocsQuery(), aggBuilder, fieldType);
+                assertTrue(Double.isInfinite(bounds.top));
+                assertTrue(Double.isInfinite(bounds.bottom));
+                assertTrue(Double.isInfinite(bounds.posLeft));
+                assertTrue(Double.isInfinite(bounds.posRight));
+                assertTrue(Double.isInfinite(bounds.negLeft));
+                assertTrue(Double.isInfinite(bounds.negRight));
+            }
+        }
+    }
+
+    public void testRandom() throws Exception {
+        double top = Double.NEGATIVE_INFINITY;
+        double bottom = Double.POSITIVE_INFINITY;
+        double posLeft = Double.POSITIVE_INFINITY;
+        double posRight = Double.NEGATIVE_INFINITY;
+        double negLeft = Double.POSITIVE_INFINITY;
+        double negRight = Double.NEGATIVE_INFINITY;
+        int numDocs = randomIntBetween(50, 100);
+        try (Directory dir = newDirectory();
+             RandomIndexWriter w = new RandomIndexWriter(random(), dir)) {
+            for (int i = 0; i < numDocs; i++) {
+                Document doc = new Document();
+                int numValues = randomIntBetween(1, 5);
+                for (int j = 0; j < numValues; j++) {
+                    GeoPoint point = RandomGeoGenerator.randomPoint(random());
+                    if (point.getLat() > top) {
+                        top = point.getLat();
+                    }
+                    if (point.getLat() < bottom) {
+                        bottom = point.getLat();
+                    }
+                    if (point.getLon() >= 0 && point.getLon() < posLeft) {
+                        posLeft = point.getLon();
+                    }
+                    if (point.getLon() >= 0 && point.getLon() > posRight) {
+                        posRight = point.getLon();
+                    }
+                    if (point.getLon() < 0 && point.getLon() < negLeft) {
+                        negLeft = point.getLon();
+                    }
+                    if (point.getLon() < 0 && point.getLon() > negRight) {
+                        negRight = point.getLon();
+                    }
+                    doc.add(new LatLonDocValuesField("field", point.getLat(), point.getLon()));
+                }
+                w.addDocument(doc);
+            }
+            GeoBoundsAggregationBuilder aggBuilder = new GeoBoundsAggregationBuilder("my_agg")
+                .field("field")
+                .wrapLongitude(false);
+
+            MappedFieldType fieldType = new GeoPointFieldMapper.GeoPointFieldType();
+            fieldType.setHasDocValues(true);
+            fieldType.setName("field");
+            try (IndexReader reader = w.getReader()) {
+                IndexSearcher searcher = new IndexSearcher(reader);
+                InternalGeoBounds bounds = search(searcher, new MatchAllDocsQuery(), aggBuilder, fieldType);
+                assertThat(bounds.top, closeTo(top, GEOHASH_TOLERANCE));
+                assertThat(bounds.bottom, closeTo(bottom, GEOHASH_TOLERANCE));
+                assertThat(bounds.posLeft, closeTo(posLeft, GEOHASH_TOLERANCE));
+                assertThat(bounds.posRight, closeTo(posRight, GEOHASH_TOLERANCE));
+                assertThat(bounds.negRight, closeTo(negRight, GEOHASH_TOLERANCE));
+                assertThat(bounds.negLeft, closeTo(negLeft, GEOHASH_TOLERANCE));
+            }
+        }
+    }
+}

+ 85 - 0
core/src/test/java/org/elasticsearch/search/aggregations/metrics/geobounds/InternalGeoBoundsTests.java

@@ -0,0 +1,85 @@
+/*
+ * 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.aggregations.metrics.geobounds;
+
+import org.elasticsearch.common.io.stream.Writeable;
+import org.elasticsearch.search.aggregations.InternalAggregationTestCase;
+import org.elasticsearch.search.aggregations.pipeline.PipelineAggregator;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.closeTo;
+
+public class InternalGeoBoundsTests extends InternalAggregationTestCase<InternalGeoBounds> {
+    static final double GEOHASH_TOLERANCE = 1E-5D;
+
+    @Override
+    protected InternalGeoBounds createTestInstance(String name, List<PipelineAggregator> pipelineAggregators,
+                                                   Map<String, Object> metaData) {
+        InternalGeoBounds geo = new InternalGeoBounds(name,
+            randomDouble(), randomDouble(), randomDouble(), randomDouble(),
+            randomDouble(), randomDouble(), randomBoolean(),
+            pipelineAggregators, Collections.emptyMap());
+        return geo;
+    }
+
+    @Override
+    protected void assertReduced(InternalGeoBounds reduced, List<InternalGeoBounds> inputs) {
+        double top = Double.NEGATIVE_INFINITY;
+        double bottom = Double.POSITIVE_INFINITY;
+        double posLeft = Double.POSITIVE_INFINITY;
+        double posRight = Double.NEGATIVE_INFINITY;
+        double negLeft = Double.POSITIVE_INFINITY;
+        double negRight = Double.NEGATIVE_INFINITY;
+        for (InternalGeoBounds bounds : inputs) {
+            if (bounds.top > top) {
+                top = bounds.top;
+            }
+            if (bounds.bottom < bottom) {
+                bottom = bounds.bottom;
+            }
+            if (bounds.posLeft < posLeft) {
+                posLeft = bounds.posLeft;
+            }
+            if (bounds.posRight > posRight) {
+                posRight = bounds.posRight;
+            }
+            if (bounds.negLeft < negLeft) {
+                negLeft = bounds.negLeft;
+            }
+            if (bounds.negRight > negRight) {
+                negRight = bounds.negRight;
+            }
+        }
+        assertThat(reduced.top, closeTo(top, GEOHASH_TOLERANCE));
+        assertThat(reduced.bottom, closeTo(bottom, GEOHASH_TOLERANCE));
+        assertThat(reduced.posLeft, closeTo(posLeft, GEOHASH_TOLERANCE));
+        assertThat(reduced.posRight, closeTo(posRight, GEOHASH_TOLERANCE));
+        assertThat(reduced.negLeft, closeTo(negLeft, GEOHASH_TOLERANCE));
+        assertThat(reduced.negRight, closeTo(negRight, GEOHASH_TOLERANCE));
+    }
+
+    @Override
+    protected Writeable.Reader<InternalGeoBounds> instanceReader() {
+        return InternalGeoBounds::new;
+    }
+}