Browse Source

ES|QL: reduce memory footprint for MvAppendTests with shapes (#109517)

Fixing MvAppendTests CB exceptions by generating smaller geometries: the
test generates a lot of documents and the CB is too small for multiple
big shapes.

Fixes https://github.com/elastic/elasticsearch/issues/109409
Luigi Dell'Aquila 1 year ago
parent
commit
47edae4fbd

+ 2 - 0
docs/reference/esql/functions/mv-functions.asciidoc

@@ -8,6 +8,7 @@
 {esql} supports these multivalue functions:
 
 // tag::mv_list[]
+* <<esql-mv_append>>
 * <<esql-mv_avg>>
 * <<esql-mv_concat>>
 * <<esql-mv_count>>
@@ -23,6 +24,7 @@
 * <<esql-mv_zip>>
 // end::mv_list[]
 
+include::layout/mv_append.asciidoc[]
 include::layout/mv_avg.asciidoc[]
 include::layout/mv_concat.asciidoc[]
 include::layout/mv_count.asciidoc[]

+ 0 - 3
muted-tests.yml

@@ -56,9 +56,6 @@ tests:
 - class: "org.elasticsearch.xpack.inference.InferenceCrudIT"
   issue: "https://github.com/elastic/elasticsearch/issues/109391"
   method: "testDeleteEndpointWhileReferencedByPipeline"
-- class: org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvAppendTests
-  method: testEvaluateBlockWithoutNulls {TestCase=<cartesian_shape>, <cartesian_shape>}
-  issue: https://github.com/elastic/elasticsearch/issues/109409
 - class: "org.elasticsearch.xpack.rollup.job.RollupIndexerStateTests"
   issue: "https://github.com/elastic/elasticsearch/issues/109627"
   method: "testMultipleJobTriggering"

+ 111 - 4
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppendTests.java

@@ -13,6 +13,18 @@ import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
 import org.apache.lucene.util.BytesRef;
 import org.elasticsearch.geo.GeometryTestUtils;
 import org.elasticsearch.geo.ShapeTestUtils;
+import org.elasticsearch.geometry.Circle;
+import org.elasticsearch.geometry.Geometry;
+import org.elasticsearch.geometry.GeometryCollection;
+import org.elasticsearch.geometry.GeometryVisitor;
+import org.elasticsearch.geometry.Line;
+import org.elasticsearch.geometry.LinearRing;
+import org.elasticsearch.geometry.MultiLine;
+import org.elasticsearch.geometry.MultiPoint;
+import org.elasticsearch.geometry.MultiPolygon;
+import org.elasticsearch.geometry.Point;
+import org.elasticsearch.geometry.Polygon;
+import org.elasticsearch.geometry.Rectangle;
 import org.elasticsearch.xpack.esql.core.expression.Expression;
 import org.elasticsearch.xpack.esql.core.tree.Source;
 import org.elasticsearch.xpack.esql.core.type.DataType;
@@ -235,8 +247,25 @@ public class MvAppendTests extends AbstractFunctionTestCase {
         }));
 
         suppliers.add(new TestCaseSupplier(List.of(DataType.GEO_SHAPE, DataType.GEO_SHAPE), () -> {
-            List<Object> field1 = randomList(1, 5, () -> new BytesRef(GEO.asWkt(GeometryTestUtils.randomGeometry(randomBoolean()))));
-            List<Object> field2 = randomList(1, 5, () -> new BytesRef(GEO.asWkt(GeometryTestUtils.randomGeometry(randomBoolean()))));
+            GeometryPointCountVisitor pointCounter = new GeometryPointCountVisitor();
+            List<Object> field1 = randomList(
+                1,
+                3,
+                () -> new BytesRef(
+                    GEO.asWkt(
+                        randomValueOtherThanMany(g -> g.visit(pointCounter) > 500, () -> GeometryTestUtils.randomGeometry(randomBoolean()))
+                    )
+                )
+            );
+            List<Object> field2 = randomList(
+                1,
+                3,
+                () -> new BytesRef(
+                    GEO.asWkt(
+                        randomValueOtherThanMany(g -> g.visit(pointCounter) > 500, () -> GeometryTestUtils.randomGeometry(randomBoolean()))
+                    )
+                )
+            );
             var result = new ArrayList<>(field1);
             result.addAll(field2);
             return new TestCaseSupplier.TestCase(
@@ -251,8 +280,25 @@ public class MvAppendTests extends AbstractFunctionTestCase {
         }));
 
         suppliers.add(new TestCaseSupplier(List.of(DataType.CARTESIAN_SHAPE, DataType.CARTESIAN_SHAPE), () -> {
-            List<Object> field1 = randomList(1, 5, () -> new BytesRef(CARTESIAN.asWkt(ShapeTestUtils.randomGeometry(randomBoolean()))));
-            List<Object> field2 = randomList(1, 5, () -> new BytesRef(CARTESIAN.asWkt(ShapeTestUtils.randomGeometry(randomBoolean()))));
+            GeometryPointCountVisitor pointCounter = new GeometryPointCountVisitor();
+            List<Object> field1 = randomList(
+                1,
+                3,
+                () -> new BytesRef(
+                    GEO.asWkt(
+                        randomValueOtherThanMany(g -> g.visit(pointCounter) > 500, () -> ShapeTestUtils.randomGeometry(randomBoolean()))
+                    )
+                )
+            );
+            List<Object> field2 = randomList(
+                1,
+                3,
+                () -> new BytesRef(
+                    GEO.asWkt(
+                        randomValueOtherThanMany(g -> g.visit(pointCounter) > 500, () -> ShapeTestUtils.randomGeometry(randomBoolean()))
+                    )
+                )
+            );
             var result = new ArrayList<>(field1);
             result.addAll(field2);
             return new TestCaseSupplier.TestCase(
@@ -293,4 +339,65 @@ public class MvAppendTests extends AbstractFunctionTestCase {
             );
         }));
     }
+
+    public static class GeometryPointCountVisitor implements GeometryVisitor<Integer, RuntimeException> {
+
+        @Override
+        public Integer visit(Circle circle) throws RuntimeException {
+            return 2;
+        }
+
+        @Override
+        public Integer visit(GeometryCollection<?> collection) throws RuntimeException {
+            int size = 0;
+            for (Geometry geometry : collection) {
+                size += geometry.visit(this);
+            }
+            return size;
+        }
+
+        @Override
+        public Integer visit(Line line) throws RuntimeException {
+            return line.length();
+        }
+
+        @Override
+        public Integer visit(LinearRing ring) throws RuntimeException {
+            return ring.length();
+        }
+
+        @Override
+        public Integer visit(MultiLine multiLine) throws RuntimeException {
+            return visit((GeometryCollection<Line>) multiLine);
+        }
+
+        @Override
+        public Integer visit(MultiPoint multiPoint) throws RuntimeException {
+            return multiPoint.size();
+        }
+
+        @Override
+        public Integer visit(MultiPolygon multiPolygon) throws RuntimeException {
+            return visit((GeometryCollection<Polygon>) multiPolygon);
+        }
+
+        @Override
+        public Integer visit(Point point) throws RuntimeException {
+            return 1;
+        }
+
+        @Override
+        public Integer visit(Polygon polygon) throws RuntimeException {
+            int size = polygon.getPolygon().length();
+            for (int i = 0; i < polygon.getNumberOfHoles(); i++) {
+                size += polygon.getHole(i).length();
+            }
+            return size;
+        }
+
+        @Override
+        public Integer visit(Rectangle rectangle) throws RuntimeException {
+            return 4;
+        }
+    }
 }