From 6bcabce13341436da76107da3f4e4ce41cadf57b Mon Sep 17 00:00:00 2001 From: donalevans Date: Thu, 16 Oct 2025 09:32:57 -0700 Subject: [PATCH 1/2] Introduce ESTestCase.randomValueOtherThanArray() methods The existing randomValueOtherThan() method uses Objects.equals() to determine if a randomly generated object is equal to the provided argument. This approach does not work as expected for arrays, however, since two arrays with identical contents will not be considered equal by Objects.equals(). See #136652 This commit introduces randomValueOtherThanArray() methods for Object arrays and primitive arrays and converts all places in the code that were previously passing arrays into randomValueOtherThan() to use the new array-specific methods --- .../DeleteSampleConfigurationActionTests.java | 2 +- .../PutSampleConfigurationActionTests.java | 2 +- ...SynonymsActionRequestSerializingTests.java | 8 +-- .../search/vectors/KnnSearchBuilderTests.java | 2 +- .../org/elasticsearch/test/ESTestCase.java | 65 +++++++++++++++++++ .../esql/plugin/ClusterRequestTests.java | 2 +- .../DataNodeRequestSerializationTests.java | 2 +- 7 files changed, 73 insertions(+), 10 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/sampling/DeleteSampleConfigurationActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/sampling/DeleteSampleConfigurationActionTests.java index 9727c82eb7178..b6730ae174433 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/sampling/DeleteSampleConfigurationActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/sampling/DeleteSampleConfigurationActionTests.java @@ -47,7 +47,7 @@ protected DeleteSampleConfigurationAction.Request mutateInstance(DeleteSampleCon instance.masterNodeTimeout(), instance.ackTimeout() ); - String[] newIndices = randomValueOtherThan(instance.indices(), () -> new String[] { randomAlphaOfLength(10) }); + String[] newIndices = randomValueOtherThanArray(instance.indices(), () -> new String[] { randomAlphaOfLength(10) }); mutated.indices(newIndices); yield mutated; } diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/sampling/PutSampleConfigurationActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/sampling/PutSampleConfigurationActionTests.java index ffe446a9cc2b0..8992b289fb7c1 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/sampling/PutSampleConfigurationActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/sampling/PutSampleConfigurationActionTests.java @@ -55,7 +55,7 @@ protected PutSampleConfigurationAction.Request mutateInstance(PutSampleConfigura instance.masterNodeTimeout(), instance.ackTimeout() ); - mutated.indices(randomValueOtherThan(instance.indices(), () -> new String[] { randomAlphaOfLengthBetween(1, 10) })); + mutated.indices(randomValueOtherThanArray(instance.indices(), () -> new String[] { randomAlphaOfLengthBetween(1, 10) })); yield mutated; } default -> throw new IllegalStateException("Invalid mutation case"); diff --git a/server/src/test/java/org/elasticsearch/action/synonyms/PutSynonymsActionRequestSerializingTests.java b/server/src/test/java/org/elasticsearch/action/synonyms/PutSynonymsActionRequestSerializingTests.java index ff9953fef595a..cae017a5f1ee4 100644 --- a/server/src/test/java/org/elasticsearch/action/synonyms/PutSynonymsActionRequestSerializingTests.java +++ b/server/src/test/java/org/elasticsearch/action/synonyms/PutSynonymsActionRequestSerializingTests.java @@ -14,8 +14,6 @@ import org.elasticsearch.test.AbstractWireSerializingTestCase; import java.io.IOException; -import java.util.Arrays; -import java.util.List; import static org.elasticsearch.action.synonyms.SynonymsTestUtils.randomSynonymsSet; @@ -34,14 +32,14 @@ protected PutSynonymsAction.Request createTestInstance() { @Override protected PutSynonymsAction.Request mutateInstance(PutSynonymsAction.Request instance) throws IOException { String synonymsSetId = instance.synonymsSetId(); - List synonymRules = Arrays.asList(instance.synonymRules()); + SynonymRule[] synonymRules = instance.synonymRules(); boolean refresh = instance.refresh(); switch (between(0, 2)) { case 0 -> synonymsSetId = randomValueOtherThan(synonymsSetId, () -> randomIdentifier()); - case 1 -> synonymRules = randomValueOtherThan(synonymRules, () -> Arrays.asList(randomSynonymsSet())); + case 1 -> synonymRules = randomValueOtherThanArray(synonymRules, () -> randomSynonymsSet()); case 2 -> refresh = refresh == false; default -> throw new AssertionError("Illegal randomisation branch"); } - return new PutSynonymsAction.Request(synonymsSetId, synonymRules.toArray(new SynonymRule[0]), refresh); + return new PutSynonymsAction.Request(synonymsSetId, synonymRules, refresh); } } diff --git a/server/src/test/java/org/elasticsearch/search/vectors/KnnSearchBuilderTests.java b/server/src/test/java/org/elasticsearch/search/vectors/KnnSearchBuilderTests.java index 7c0c4ba25300b..5fc9c3e5a417f 100644 --- a/server/src/test/java/org/elasticsearch/search/vectors/KnnSearchBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/search/vectors/KnnSearchBuilderTests.java @@ -126,7 +126,7 @@ yield new KnnSearchBuilder( ).boost(instance.boost); } case 1 -> { - float[] newVector = randomValueOtherThan(instance.queryVector.asFloatVector(), () -> randomVector(5)); + float[] newVector = randomValueOtherThanArray(instance.queryVector.asFloatVector(), () -> randomVector(5)); yield new KnnSearchBuilder( instance.field, newVector, diff --git a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java index 8150456194b76..d190e61b4704b 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java @@ -1501,9 +1501,74 @@ public static void maybeSet(Consumer consumer, T value) { * helper to get a random value in a certain range that's different from the input */ public static T randomValueOtherThan(T input, Supplier randomSupplier) { + assert input == null || input.getClass().isArray() == false + : "randomValueOtherThan() does not work as expected with arrays, use randomValueOtherThanArray() instead"; return randomValueOtherThanMany(v -> Objects.equals(input, v), randomSupplier); } + /** + * helper to get a random value in a certain range that's different from the input, for object arrays + */ + public static T[] randomValueOtherThanArray(T[] input, Supplier randomSupplier) { + return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); + } + + /** + * helper to get a random value in a certain range that's different from the input, for boolean arrays + */ + public static boolean[] randomValueOtherThanArray(boolean[] input, Supplier randomSupplier) { + return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); + } + + /** + * helper to get a random value in a certain range that's different from the input, for byte arrays + */ + public static byte[] randomValueOtherThanArray(byte[] input, Supplier randomSupplier) { + return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); + } + + /** + * helper to get a random value in a certain range that's different from the input, for char arrays + */ + public static char[] randomValueOtherThanArray(char[] input, Supplier randomSupplier) { + return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); + } + + /** + * helper to get a random value in a certain range that's different from the input, for short arrays + */ + public static short[] randomValueOtherThanArray(short[] input, Supplier randomSupplier) { + return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); + } + + /** + * helper to get a random value in a certain range that's different from the input, for int arrays + */ + public static int[] randomValueOtherThanArray(int[] input, Supplier randomSupplier) { + return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); + } + + /** + * helper to get a random value in a certain range that's different from the input, for long arrays + */ + public static long[] randomValueOtherThanArray(long[] input, Supplier randomSupplier) { + return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); + } + + /** + * helper to get a random value in a certain range that's different from the input, for float arrays + */ + public static float[] randomValueOtherThanArray(float[] input, Supplier randomSupplier) { + return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); + } + + /** + * helper to get a random value in a certain range that's different from the input, for double arrays + */ + public static double[] randomValueOtherThanArray(double[] input, Supplier randomSupplier) { + return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); + } + /** * helper to get a random value in a certain range that's different from the input */ diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ClusterRequestTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ClusterRequestTests.java index b25fba6f1dc48..44f20ff492c3f 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ClusterRequestTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ClusterRequestTests.java @@ -121,7 +121,7 @@ protected ClusterComputeRequest mutateInstance(ClusterComputeRequest in) throws in.configuration(), new RemoteClusterPlan( plan.plan(), - randomValueOtherThan(plan.targetIndices(), () -> generateRandomStringArray(10, 10, false, false)), + randomValueOtherThanArray(plan.targetIndices(), () -> generateRandomStringArray(10, 10, false, false)), plan.originalIndices() ) ); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSerializationTests.java index a9faac859f0da..0b89c07ec971a 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSerializationTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSerializationTests.java @@ -243,7 +243,7 @@ protected DataNodeRequest mutateInstance(DataNodeRequest in) throws IOException yield request; } case 7 -> { - var indices = randomValueOtherThan(in.indices(), () -> generateRandomStringArray(10, 10, false, false)); + var indices = randomValueOtherThanArray(in.indices(), () -> generateRandomStringArray(10, 10, false, false)); var request = new DataNodeRequest( in.sessionId(), in.configuration(), From 34c84b55c7acf418dabb581cd52653a3797ba264 Mon Sep 17 00:00:00 2001 From: donalevans Date: Thu, 16 Oct 2025 10:38:24 -0700 Subject: [PATCH 2/2] Change method name --- .../DeleteSampleConfigurationActionTests.java | 2 +- .../PutSampleConfigurationActionTests.java | 2 +- ...SynonymsActionRequestSerializingTests.java | 2 +- .../search/vectors/KnnSearchBuilderTests.java | 2 +- .../org/elasticsearch/test/ESTestCase.java | 20 +++++++++---------- .../esql/plugin/ClusterRequestTests.java | 2 +- .../DataNodeRequestSerializationTests.java | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/sampling/DeleteSampleConfigurationActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/sampling/DeleteSampleConfigurationActionTests.java index b6730ae174433..ba9d4d656bcc4 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/sampling/DeleteSampleConfigurationActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/sampling/DeleteSampleConfigurationActionTests.java @@ -47,7 +47,7 @@ protected DeleteSampleConfigurationAction.Request mutateInstance(DeleteSampleCon instance.masterNodeTimeout(), instance.ackTimeout() ); - String[] newIndices = randomValueOtherThanArray(instance.indices(), () -> new String[] { randomAlphaOfLength(10) }); + String[] newIndices = randomArrayOtherThan(instance.indices(), () -> new String[] { randomAlphaOfLength(10) }); mutated.indices(newIndices); yield mutated; } diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/sampling/PutSampleConfigurationActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/sampling/PutSampleConfigurationActionTests.java index 8992b289fb7c1..a4fc1b91e491c 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/sampling/PutSampleConfigurationActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/sampling/PutSampleConfigurationActionTests.java @@ -55,7 +55,7 @@ protected PutSampleConfigurationAction.Request mutateInstance(PutSampleConfigura instance.masterNodeTimeout(), instance.ackTimeout() ); - mutated.indices(randomValueOtherThanArray(instance.indices(), () -> new String[] { randomAlphaOfLengthBetween(1, 10) })); + mutated.indices(randomArrayOtherThan(instance.indices(), () -> new String[] { randomAlphaOfLengthBetween(1, 10) })); yield mutated; } default -> throw new IllegalStateException("Invalid mutation case"); diff --git a/server/src/test/java/org/elasticsearch/action/synonyms/PutSynonymsActionRequestSerializingTests.java b/server/src/test/java/org/elasticsearch/action/synonyms/PutSynonymsActionRequestSerializingTests.java index cae017a5f1ee4..8af9bc9c6202b 100644 --- a/server/src/test/java/org/elasticsearch/action/synonyms/PutSynonymsActionRequestSerializingTests.java +++ b/server/src/test/java/org/elasticsearch/action/synonyms/PutSynonymsActionRequestSerializingTests.java @@ -36,7 +36,7 @@ protected PutSynonymsAction.Request mutateInstance(PutSynonymsAction.Request ins boolean refresh = instance.refresh(); switch (between(0, 2)) { case 0 -> synonymsSetId = randomValueOtherThan(synonymsSetId, () -> randomIdentifier()); - case 1 -> synonymRules = randomValueOtherThanArray(synonymRules, () -> randomSynonymsSet()); + case 1 -> synonymRules = randomArrayOtherThan(synonymRules, () -> randomSynonymsSet()); case 2 -> refresh = refresh == false; default -> throw new AssertionError("Illegal randomisation branch"); } diff --git a/server/src/test/java/org/elasticsearch/search/vectors/KnnSearchBuilderTests.java b/server/src/test/java/org/elasticsearch/search/vectors/KnnSearchBuilderTests.java index 5fc9c3e5a417f..9f97fe7c861c7 100644 --- a/server/src/test/java/org/elasticsearch/search/vectors/KnnSearchBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/search/vectors/KnnSearchBuilderTests.java @@ -126,7 +126,7 @@ yield new KnnSearchBuilder( ).boost(instance.boost); } case 1 -> { - float[] newVector = randomValueOtherThanArray(instance.queryVector.asFloatVector(), () -> randomVector(5)); + float[] newVector = randomArrayOtherThan(instance.queryVector.asFloatVector(), () -> randomVector(5)); yield new KnnSearchBuilder( instance.field, newVector, diff --git a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java index d190e61b4704b..b8639c3c02064 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java @@ -1502,70 +1502,70 @@ public static void maybeSet(Consumer consumer, T value) { */ public static T randomValueOtherThan(T input, Supplier randomSupplier) { assert input == null || input.getClass().isArray() == false - : "randomValueOtherThan() does not work as expected with arrays, use randomValueOtherThanArray() instead"; + : "randomValueOtherThan() does not work as expected with arrays, use randomArrayOtherThan() instead"; return randomValueOtherThanMany(v -> Objects.equals(input, v), randomSupplier); } /** * helper to get a random value in a certain range that's different from the input, for object arrays */ - public static T[] randomValueOtherThanArray(T[] input, Supplier randomSupplier) { + public static T[] randomArrayOtherThan(T[] input, Supplier randomSupplier) { return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); } /** * helper to get a random value in a certain range that's different from the input, for boolean arrays */ - public static boolean[] randomValueOtherThanArray(boolean[] input, Supplier randomSupplier) { + public static boolean[] randomArrayOtherThan(boolean[] input, Supplier randomSupplier) { return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); } /** * helper to get a random value in a certain range that's different from the input, for byte arrays */ - public static byte[] randomValueOtherThanArray(byte[] input, Supplier randomSupplier) { + public static byte[] randomArrayOtherThan(byte[] input, Supplier randomSupplier) { return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); } /** * helper to get a random value in a certain range that's different from the input, for char arrays */ - public static char[] randomValueOtherThanArray(char[] input, Supplier randomSupplier) { + public static char[] randomArrayOtherThan(char[] input, Supplier randomSupplier) { return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); } /** * helper to get a random value in a certain range that's different from the input, for short arrays */ - public static short[] randomValueOtherThanArray(short[] input, Supplier randomSupplier) { + public static short[] randomArrayOtherThan(short[] input, Supplier randomSupplier) { return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); } /** * helper to get a random value in a certain range that's different from the input, for int arrays */ - public static int[] randomValueOtherThanArray(int[] input, Supplier randomSupplier) { + public static int[] randomArrayOtherThan(int[] input, Supplier randomSupplier) { return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); } /** * helper to get a random value in a certain range that's different from the input, for long arrays */ - public static long[] randomValueOtherThanArray(long[] input, Supplier randomSupplier) { + public static long[] randomArrayOtherThan(long[] input, Supplier randomSupplier) { return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); } /** * helper to get a random value in a certain range that's different from the input, for float arrays */ - public static float[] randomValueOtherThanArray(float[] input, Supplier randomSupplier) { + public static float[] randomArrayOtherThan(float[] input, Supplier randomSupplier) { return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); } /** * helper to get a random value in a certain range that's different from the input, for double arrays */ - public static double[] randomValueOtherThanArray(double[] input, Supplier randomSupplier) { + public static double[] randomArrayOtherThan(double[] input, Supplier randomSupplier) { return randomValueOtherThanMany(v -> Arrays.equals(input, v), randomSupplier); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ClusterRequestTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ClusterRequestTests.java index 44f20ff492c3f..da54b327050bf 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ClusterRequestTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/ClusterRequestTests.java @@ -121,7 +121,7 @@ protected ClusterComputeRequest mutateInstance(ClusterComputeRequest in) throws in.configuration(), new RemoteClusterPlan( plan.plan(), - randomValueOtherThanArray(plan.targetIndices(), () -> generateRandomStringArray(10, 10, false, false)), + randomArrayOtherThan(plan.targetIndices(), () -> generateRandomStringArray(10, 10, false, false)), plan.originalIndices() ) ); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSerializationTests.java index 0b89c07ec971a..267515b52c94f 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSerializationTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/plugin/DataNodeRequestSerializationTests.java @@ -243,7 +243,7 @@ protected DataNodeRequest mutateInstance(DataNodeRequest in) throws IOException yield request; } case 7 -> { - var indices = randomValueOtherThanArray(in.indices(), () -> generateRandomStringArray(10, 10, false, false)); + var indices = randomArrayOtherThan(in.indices(), () -> generateRandomStringArray(10, 10, false, false)); var request = new DataNodeRequest( in.sessionId(), in.configuration(),