Browse Source

Fix flaky multi-valued test for Cartesian centroid (#90507)

See https://github.com/elastic/elasticsearch/issues/90505
Craig Taverner 3 years ago
parent
commit
332b76566b

+ 13 - 8
x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/search/aggregations/metrics/CartesianCentroidAggregatorTests.java

@@ -149,6 +149,7 @@ public class CartesianCentroidAggregatorTests extends AggregatorTestCase {
         }
     }
 
+    // TODO Consider merging this code with the almost identical code in the CartesianShapeCentroidAggregatorTests
     private void assertCentroid(RandomIndexWriter w, CartesianPoint expectedCentroid) throws IOException {
         MappedFieldType fieldType = new PointFieldMapper.PointFieldType("field");
         CartesianCentroidAggregationBuilder aggBuilder = new CartesianCentroidAggregationBuilder("my_agg").field("field");
@@ -159,25 +160,29 @@ public class CartesianCentroidAggregatorTests extends AggregatorTestCase {
             assertEquals("my_agg", result.getName());
             SpatialPoint centroid = result.centroid();
             assertNotNull(centroid);
-            double xTolerance = tolerance(expectedCentroid.getX(), centroid.getX());
-            double yTolerance = tolerance(expectedCentroid.getY(), centroid.getY());
-            assertEquals(expectedCentroid.getX(), centroid.getX(), xTolerance);
-            assertEquals(expectedCentroid.getY(), centroid.getY(), yTolerance);
+            assertCentroid("x-value", result.count(), centroid.getX(), expectedCentroid.getX());
+            assertCentroid("y-value", result.count(), centroid.getY(), expectedCentroid.getY());
             assertTrue(AggregationInspectionHelper.hasValue(result));
         }
     }
 
+    private void assertCentroid(String name, long count, double value, double expected) {
+        assertEquals("Centroid over " + count + " had incorrect " + name, expected, value, tolerance(value, expected, count));
+    }
+
     /**
      * Due to cartesian ranging from very large numbers to very small, we need different ways of calculating accuracy for the extremes
      */
-    private double tolerance(double a, double b) {
+    private double tolerance(double a, double b, long count) {
         double coordinate = (Math.abs(a) + Math.abs(b)) / 2;
         if (coordinate < 1.0) {
-            // When dealing with small numbers, we use the same tolerance as in the geo case
-            return 1e-6D;
+            // When dealing with small numbers, we use an absolute tolerance, similar to the geo case
+            return 1e-7D;
         } else {
             // For large numbers we use a tolerance based on a faction of the expected value
-            return coordinate / 1e6D;
+            double tolerance = coordinate / 1e7D;
+            // For very large numbers the floating point error is worse for large counts
+            return tolerance > 1e25 ? tolerance * count : tolerance;
         }
     }