From 3d9ce1b5c4fa19a69f8365e5a31357e5707d42de Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Fri, 10 Oct 2025 12:01:47 +0200 Subject: [PATCH 01/11] Fix the code so that testing with -Ptests.asserts=false passes. --- .../lucene/internal/hppc/TestCharHashSet.java | 12 ++++--- .../internal/hppc/TestCharObjectHashMap.java | 12 ++++--- .../internal/hppc/TestIntDoubleHashMap.java | 12 ++++--- .../internal/hppc/TestIntFloatHashMap.java | 12 ++++--- .../lucene/internal/hppc/TestIntHashSet.java | 12 ++++--- .../internal/hppc/TestIntIntHashMap.java | 12 ++++--- .../internal/hppc/TestIntLongHashMap.java | 12 ++++--- .../internal/hppc/TestIntObjectHashMap.java | 12 ++++--- .../internal/hppc/TestLongFloatHashMap.java | 12 ++++--- .../lucene/internal/hppc/TestLongHashSet.java | 12 ++++--- .../internal/hppc/TestLongIntHashMap.java | 12 ++++--- .../internal/hppc/TestLongObjectHashMap.java | 12 ++++--- .../hppc/TestMaxSizedFloatArrayList.java | 12 ++++--- .../hppc/TestMaxSizedIntArrayList.java | 12 ++++--- .../org/apache/lucene/util/TestArrayUtil.java | 16 +++++---- .../lucene/util/hnsw/TestNeighborArray.java | 34 ++++++++++++++----- .../lucene/util/hnsw/TestOnHeapHnswGraph.java | 4 ++- .../tests/util/BaseDocIdSetTestCase.java | 8 +++-- 18 files changed, 142 insertions(+), 88 deletions(-) diff --git a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestCharHashSet.java b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestCharHashSet.java index 1ac24ab34f3a..0df4ed1b9467 100644 --- a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestCharHashSet.java +++ b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestCharHashSet.java @@ -90,11 +90,13 @@ public void testIndexMethods() { MatcherAssert.assertThat(set.indexGet(set.indexOf(keyE)), is(equalTo(keyE))); MatcherAssert.assertThat(set.indexGet(set.indexOf(key1)), is(equalTo(key1))); - expectThrows( - AssertionError.class, - () -> { - set.indexGet(set.indexOf(key2)); - }); + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + set.indexGet(set.indexOf(key2)); + }); + } MatcherAssert.assertThat(set.indexReplace(set.indexOf(keyE), keyE), is(equalTo(keyE))); MatcherAssert.assertThat(set.indexReplace(set.indexOf(key1), key1), is(equalTo(key1))); diff --git a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestCharObjectHashMap.java b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestCharObjectHashMap.java index 30ffbe00cf8d..2f95ec1c194a 100644 --- a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestCharObjectHashMap.java +++ b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestCharObjectHashMap.java @@ -177,11 +177,13 @@ public void testIndexMethods() { assertEquals(value1, map.indexGet(map.indexOf(keyE))); assertEquals(value2, map.indexGet(map.indexOf(key1))); - expectThrows( - AssertionError.class, - () -> { - map.indexGet(map.indexOf(key2)); - }); + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + map.indexGet(map.indexOf(key2)); + }); + } assertEquals(value1, map.indexReplace(map.indexOf(keyE), value3)); assertEquals(value2, map.indexReplace(map.indexOf(key1), value4)); diff --git a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntDoubleHashMap.java b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntDoubleHashMap.java index cb7d92a2c639..55f6cba65489 100644 --- a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntDoubleHashMap.java +++ b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntDoubleHashMap.java @@ -173,11 +173,13 @@ public void testIndexMethods() { assertEquals2(value1, map.indexGet(map.indexOf(keyE))); assertEquals2(value2, map.indexGet(map.indexOf(key1))); - expectThrows( - AssertionError.class, - () -> { - map.indexGet(map.indexOf(key2)); - }); + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + map.indexGet(map.indexOf(key2)); + }); + } assertEquals2(value1, map.indexReplace(map.indexOf(keyE), value3)); assertEquals2(value2, map.indexReplace(map.indexOf(key1), value4)); diff --git a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntFloatHashMap.java b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntFloatHashMap.java index 9539bb9766e0..5c81d9e4d909 100644 --- a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntFloatHashMap.java +++ b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntFloatHashMap.java @@ -173,11 +173,13 @@ public void testIndexMethods() { assertEquals2(value1, map.indexGet(map.indexOf(keyE))); assertEquals2(value2, map.indexGet(map.indexOf(key1))); - expectThrows( - AssertionError.class, - () -> { - map.indexGet(map.indexOf(key2)); - }); + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + map.indexGet(map.indexOf(key2)); + }); + } assertEquals2(value1, map.indexReplace(map.indexOf(keyE), value3)); assertEquals2(value2, map.indexReplace(map.indexOf(key1), value4)); diff --git a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntHashSet.java b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntHashSet.java index eb4ce02b577d..0b8721bbe311 100644 --- a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntHashSet.java +++ b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntHashSet.java @@ -90,11 +90,13 @@ public void testIndexMethods() { MatcherAssert.assertThat(set.indexGet(set.indexOf(keyE)), is(equalTo(keyE))); MatcherAssert.assertThat(set.indexGet(set.indexOf(key1)), is(equalTo(key1))); - expectThrows( - AssertionError.class, - () -> { - set.indexGet(set.indexOf(key2)); - }); + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + set.indexGet(set.indexOf(key2)); + }); + } MatcherAssert.assertThat(set.indexReplace(set.indexOf(keyE), keyE), is(equalTo(keyE))); MatcherAssert.assertThat(set.indexReplace(set.indexOf(key1), key1), is(equalTo(key1))); diff --git a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntIntHashMap.java b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntIntHashMap.java index 7bfa88c1be4e..0d9e2e725bfc 100644 --- a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntIntHashMap.java +++ b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntIntHashMap.java @@ -152,11 +152,13 @@ public void testIndexMethods() { assertEquals(value1, map.indexGet(map.indexOf(keyE))); assertEquals(value2, map.indexGet(map.indexOf(key1))); - expectThrows( - AssertionError.class, - () -> { - map.indexGet(map.indexOf(key2)); - }); + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + map.indexGet(map.indexOf(key2)); + }); + } assertEquals(value1, map.indexReplace(map.indexOf(keyE), value3)); assertEquals(value2, map.indexReplace(map.indexOf(key1), value4)); diff --git a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntLongHashMap.java b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntLongHashMap.java index ccb5e60284a0..6bc1cd8b07fd 100644 --- a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntLongHashMap.java +++ b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntLongHashMap.java @@ -184,11 +184,13 @@ public void testIndexMethods() { assertEquals(value1, map.indexGet(map.indexOf(keyE))); assertEquals(value2, map.indexGet(map.indexOf(key1))); - expectThrows( - AssertionError.class, - () -> { - map.indexGet(map.indexOf(key2)); - }); + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + map.indexGet(map.indexOf(key2)); + }); + } assertEquals(value1, map.indexReplace(map.indexOf(keyE), value3)); assertEquals(value2, map.indexReplace(map.indexOf(key1), value4)); diff --git a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntObjectHashMap.java b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntObjectHashMap.java index 6403cbf92732..9e73beb20977 100644 --- a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntObjectHashMap.java +++ b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestIntObjectHashMap.java @@ -162,11 +162,13 @@ public void testIndexMethods() { assertEquals(value1, map.indexGet(map.indexOf(keyE))); assertEquals(value2, map.indexGet(map.indexOf(key1))); - expectThrows( - AssertionError.class, - () -> { - map.indexGet(map.indexOf(key2)); - }); + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + map.indexGet(map.indexOf(key2)); + }); + } assertEquals(value1, map.indexReplace(map.indexOf(keyE), value3)); assertEquals(value2, map.indexReplace(map.indexOf(key1), value4)); diff --git a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestLongFloatHashMap.java b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestLongFloatHashMap.java index a00a6ab21fa4..600c0ff03c76 100644 --- a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestLongFloatHashMap.java +++ b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestLongFloatHashMap.java @@ -173,11 +173,13 @@ public void testIndexMethods() { assertEquals2(value1, map.indexGet(map.indexOf(keyE))); assertEquals2(value2, map.indexGet(map.indexOf(key1))); - expectThrows( - AssertionError.class, - () -> { - map.indexGet(map.indexOf(key2)); - }); + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + map.indexGet(map.indexOf(key2)); + }); + } assertEquals2(value1, map.indexReplace(map.indexOf(keyE), value3)); assertEquals2(value2, map.indexReplace(map.indexOf(key1), value4)); diff --git a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestLongHashSet.java b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestLongHashSet.java index b07a6077105d..0de1971d6090 100644 --- a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestLongHashSet.java +++ b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestLongHashSet.java @@ -90,11 +90,13 @@ public void testIndexMethods() { MatcherAssert.assertThat(set.indexGet(set.indexOf(keyE)), is(equalTo(keyE))); MatcherAssert.assertThat(set.indexGet(set.indexOf(key1)), is(equalTo(key1))); - expectThrows( - AssertionError.class, - () -> { - set.indexGet(set.indexOf(key2)); - }); + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + set.indexGet(set.indexOf(key2)); + }); + } MatcherAssert.assertThat(set.indexReplace(set.indexOf(keyE), keyE), is(equalTo(keyE))); MatcherAssert.assertThat(set.indexReplace(set.indexOf(key1), key1), is(equalTo(key1))); diff --git a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestLongIntHashMap.java b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestLongIntHashMap.java index 87d6d2edc070..ddf11a5dd6fb 100644 --- a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestLongIntHashMap.java +++ b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestLongIntHashMap.java @@ -161,11 +161,13 @@ public void testIndexMethods() { assertEquals(value1, map.indexGet(map.indexOf(keyE))); assertEquals(value2, map.indexGet(map.indexOf(key1))); - expectThrows( - AssertionError.class, - () -> { - map.indexGet(map.indexOf(key2)); - }); + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + map.indexGet(map.indexOf(key2)); + }); + } assertEquals(value1, map.indexReplace(map.indexOf(keyE), value3)); assertEquals(value2, map.indexReplace(map.indexOf(key1), value4)); diff --git a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestLongObjectHashMap.java b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestLongObjectHashMap.java index a2e92993e366..40669a26cd87 100644 --- a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestLongObjectHashMap.java +++ b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestLongObjectHashMap.java @@ -159,11 +159,13 @@ public void testIndexMethods() { assertEquals(value1, map.indexGet(map.indexOf(keyE))); assertEquals(value2, map.indexGet(map.indexOf(key1))); - expectThrows( - AssertionError.class, - () -> { - map.indexGet(map.indexOf(key2)); - }); + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + map.indexGet(map.indexOf(key2)); + }); + } assertEquals(value1, map.indexReplace(map.indexOf(keyE), value3)); assertEquals(value2, map.indexReplace(map.indexOf(key1), value4)); diff --git a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestMaxSizedFloatArrayList.java b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestMaxSizedFloatArrayList.java index 484a602b0bc3..62a7b91a5fd4 100644 --- a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestMaxSizedFloatArrayList.java +++ b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestMaxSizedFloatArrayList.java @@ -31,11 +31,13 @@ public void testMaxSizeConstructor() { assertEquals(MAX_SIZE, list.maxSize); // Test invalid maxSize (expectedElements > maxSize) - expectThrows( - AssertionError.class, - () -> { - new MaxSizedFloatArrayList(2, 3); - }); + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + new MaxSizedFloatArrayList(2, 3); + }); + } } @Test diff --git a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestMaxSizedIntArrayList.java b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestMaxSizedIntArrayList.java index dc567fd25579..408a0f17de5e 100644 --- a/lucene/core/src/test/org/apache/lucene/internal/hppc/TestMaxSizedIntArrayList.java +++ b/lucene/core/src/test/org/apache/lucene/internal/hppc/TestMaxSizedIntArrayList.java @@ -31,11 +31,13 @@ public void testMaxSizeConstructor() { assertEquals(MAX_SIZE, list.maxSize); // Test invalid maxSize (expectedElements > maxSize) - expectThrows( - AssertionError.class, - () -> { - new MaxSizedIntArrayList(2, 3); - }); + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + new MaxSizedIntArrayList(2, 3); + }); + } } @Test diff --git a/lucene/core/src/test/org/apache/lucene/util/TestArrayUtil.java b/lucene/core/src/test/org/apache/lucene/util/TestArrayUtil.java index d09b2b7aa361..bbd383f32eb7 100644 --- a/lucene/core/src/test/org/apache/lucene/util/TestArrayUtil.java +++ b/lucene/core/src/test/org/apache/lucene/util/TestArrayUtil.java @@ -372,9 +372,11 @@ public void testGrowInRange() { int[] array = new int[] {1, 2, 3}; // If minLength is negative, maxLength does not matter - expectThrows(AssertionError.class, () -> growInRange(array, -1, 4)); - expectThrows(AssertionError.class, () -> growInRange(array, -1, 0)); - expectThrows(AssertionError.class, () -> growInRange(array, -1, -1)); + if (TEST_ASSERTS_ENABLED) { + expectThrows(AssertionError.class, () -> growInRange(array, -1, 4)); + expectThrows(AssertionError.class, () -> growInRange(array, -1, 0)); + expectThrows(AssertionError.class, () -> growInRange(array, -1, -1)); + } // If minLength > maxLength, we throw an exception expectThrows(IllegalArgumentException.class, () -> growInRange(array, 1, 0)); @@ -402,9 +404,11 @@ public void testGrowInRangeFloat() { float[] array = new float[] {1f, 2f, 3f}; // If minLength is negative, maxLength does not matter - expectThrows(AssertionError.class, () -> growInRange(array, -1, 4)); - expectThrows(AssertionError.class, () -> growInRange(array, -1, 0)); - expectThrows(AssertionError.class, () -> growInRange(array, -1, -1)); + if (TEST_ASSERTS_ENABLED) { + expectThrows(AssertionError.class, () -> growInRange(array, -1, 4)); + expectThrows(AssertionError.class, () -> growInRange(array, -1, 0)); + expectThrows(AssertionError.class, () -> growInRange(array, -1, -1)); + } // If minLength > maxLength, we throw an exception expectThrows(IllegalArgumentException.class, () -> growInRange(array, 1, 0)); diff --git a/lucene/core/src/test/org/apache/lucene/util/hnsw/TestNeighborArray.java b/lucene/core/src/test/org/apache/lucene/util/hnsw/TestNeighborArray.java index 4d281b9011e8..0bc28ba2ad87 100644 --- a/lucene/core/src/test/org/apache/lucene/util/hnsw/TestNeighborArray.java +++ b/lucene/core/src/test/org/apache/lucene/util/hnsw/TestNeighborArray.java @@ -28,8 +28,11 @@ public void testScoresDescOrder() throws IOException { neighbors.addInOrder(0, 1); neighbors.addInOrder(1, 0.8f); - AssertionError ex = expectThrows(AssertionError.class, () -> neighbors.addInOrder(2, 0.9f)); - assert ex.getMessage().startsWith("Nodes are added in the incorrect order!") : ex.getMessage(); + if (TEST_ASSERTS_ENABLED) { + AssertionError ex = expectThrows(AssertionError.class, () -> neighbors.addInOrder(2, 0.9f)); + assert ex.getMessage().startsWith("Nodes are added in the incorrect order!") + : ex.getMessage(); + } neighbors.insertSorted(3, 0.9f); assertScoresEqual(new float[] {1, 0.9f, 0.8f}, neighbors); @@ -77,8 +80,11 @@ public void testScoresAscOrder() throws IOException { neighbors.addInOrder(0, 0.1f); neighbors.addInOrder(1, 0.3f); - AssertionError ex = expectThrows(AssertionError.class, () -> neighbors.addInOrder(2, 0.15f)); - assert ex.getMessage().startsWith("Nodes are added in the incorrect order!") : ex.getMessage(); + if (TEST_ASSERTS_ENABLED) { + AssertionError ex = expectThrows(AssertionError.class, () -> neighbors.addInOrder(2, 0.15f)); + assert ex.getMessage().startsWith("Nodes are added in the incorrect order!") + : ex.getMessage(); + } neighbors.insertSorted(3, 0.3f); assertScoresEqual(new float[] {0.1f, 0.3f, 0.3f}, neighbors); @@ -125,7 +131,9 @@ public void testSortAsc() throws IOException { NeighborArray neighbors = new NeighborArray(10, false); neighbors.addOutOfOrder(1, 2); // we disallow calling addInOrder after addOutOfOrder even if they're actual in order - expectThrows(AssertionError.class, () -> neighbors.addInOrder(1, 2)); + if (TEST_ASSERTS_ENABLED) { + expectThrows(AssertionError.class, () -> neighbors.addInOrder(1, 2)); + } neighbors.addOutOfOrder(2, 3); neighbors.addOutOfOrder(5, 6); neighbors.addOutOfOrder(3, 4); @@ -155,7 +163,9 @@ public void testSortDesc() throws IOException { NeighborArray neighbors = new NeighborArray(10, true); neighbors.addOutOfOrder(1, 7); // we disallow calling addInOrder after addOutOfOrder even if they're actual in order - expectThrows(AssertionError.class, () -> neighbors.addInOrder(1, 2)); + if (TEST_ASSERTS_ENABLED) { + expectThrows(AssertionError.class, () -> neighbors.addInOrder(1, 2)); + } neighbors.addOutOfOrder(2, 6); neighbors.addOutOfOrder(5, 3); neighbors.addOutOfOrder(3, 5); @@ -184,7 +194,9 @@ public void testSortDesc() throws IOException { public void testAddwithScoringFunction() throws IOException { NeighborArray neighbors = new NeighborArray(10, true); neighbors.addOutOfOrder(1, Float.NaN); - expectThrows(AssertionError.class, () -> neighbors.addInOrder(1, 2)); + if (TEST_ASSERTS_ENABLED) { + expectThrows(AssertionError.class, () -> neighbors.addInOrder(1, 2)); + } neighbors.addOutOfOrder(2, Float.NaN); neighbors.addOutOfOrder(5, Float.NaN); neighbors.addOutOfOrder(3, Float.NaN); @@ -200,7 +212,9 @@ public void testAddwithScoringFunction() throws IOException { public void testAddwithScoringFunctionLargeOrd() throws IOException { NeighborArray neighbors = new NeighborArray(10, true); neighbors.addOutOfOrder(11, Float.NaN); - expectThrows(AssertionError.class, () -> neighbors.addInOrder(1, 2)); + if (TEST_ASSERTS_ENABLED) { + expectThrows(AssertionError.class, () -> neighbors.addInOrder(1, 2)); + } neighbors.addOutOfOrder(12, Float.NaN); neighbors.addOutOfOrder(15, Float.NaN); neighbors.addOutOfOrder(13, Float.NaN); @@ -264,7 +278,9 @@ public void testMaxSizeMixedOperations() throws IOException { neighbors.addOutOfOrder(1, 0.8f); // Try to add third node in order - should fail because we used addOutOfOrder - expectThrows(AssertionError.class, () -> neighbors.addInOrder(2, 0.6f)); + if (TEST_ASSERTS_ENABLED) { + expectThrows(AssertionError.class, () -> neighbors.addInOrder(2, 0.6f)); + } // Add third node out of order neighbors.addOutOfOrder(2, 0.6f); diff --git a/lucene/core/src/test/org/apache/lucene/util/hnsw/TestOnHeapHnswGraph.java b/lucene/core/src/test/org/apache/lucene/util/hnsw/TestOnHeapHnswGraph.java index f5d2a8ad114d..082079deb8f3 100644 --- a/lucene/core/src/test/org/apache/lucene/util/hnsw/TestOnHeapHnswGraph.java +++ b/lucene/core/src/test/org/apache/lucene/util/hnsw/TestOnHeapHnswGraph.java @@ -38,7 +38,9 @@ public void testNoGrowth() { public void testAddLevelOutOfOrder() { OnHeapHnswGraph graph = new OnHeapHnswGraph(10, -1); graph.addNode(0, 0); - expectThrows(AssertionError.class, () -> graph.addNode(1, 0)); + if (TEST_ASSERTS_ENABLED) { + expectThrows(AssertionError.class, () -> graph.addNode(1, 0)); + } } /* assert exception will be thrown when we call getNodeOnLevel for an incomplete graph */ diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/util/BaseDocIdSetTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/tests/util/BaseDocIdSetTestCase.java index 7ac5dbad09f5..589eb03427f6 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/tests/util/BaseDocIdSetTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/tests/util/BaseDocIdSetTestCase.java @@ -238,12 +238,16 @@ public void testIntoBitSetBoundChecks() throws IOException { it2.advance(from); // This call is not legal, since there is one bit that is set beyond the end of the target bit // set - expectThrows(Throwable.class, () -> it2.intoBitSet(to, dest2, offset)); + if (TEST_ASSERTS_ENABLED) { + expectThrows(Throwable.class, () -> it2.intoBitSet(to, dest2, offset)); + } FixedBitSet dest3 = new FixedBitSet(42 - offset + 1); DocIdSetIterator it3 = copy.iterator(); it3.advance(from); // This call is not legal, since offset is greater than the current doc - expectThrows(Throwable.class, () -> it3.intoBitSet(to, dest3, 21)); + if (TEST_ASSERTS_ENABLED) { + expectThrows(Throwable.class, () -> it3.intoBitSet(to, dest3, 21)); + } } } From 886f50cd1de3fa9b15a62a69b05871603a614073 Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Fri, 10 Oct 2025 18:46:48 +0200 Subject: [PATCH 02/11] More tests that don't work with assertions disabled. --- .../lucene/search/TestBooleanScorerSupplier.java | 2 ++ .../lucene/search/TestConjunctionDISI.java | 3 ++- .../apache/lucene/search/TestMultiCollector.java | 16 +++++++++------- .../org/apache/lucene/search/TestTermScorer.java | 12 +++++++----- .../facetset/TestMatchingFacetSetsCounts.java | 2 ++ .../TestKnnVectorSimilarityFunctions.java | 2 ++ .../lucene/sandbox/facet/TestTaxonomyFacet.java | 12 +++++++----- .../sandbox/search/TestPhraseWildcardQuery.java | 4 +++- .../prefix/tree/TestDateRangePrefixTree.java | 9 ++++++++- .../index/BaseTermVectorsFormatTestCase.java | 5 ++++- 10 files changed, 46 insertions(+), 21 deletions(-) diff --git a/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorerSupplier.java b/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorerSupplier.java index a2b029004512..9695b39081c2 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorerSupplier.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorerSupplier.java @@ -281,6 +281,8 @@ public void testDuelCost() throws Exception { // test the tester... public void testFakeScorerSupplier() { + assumeTrue("Test designed to work only with assertions enabled.", TEST_ASSERTS_ENABLED); + FakeScorerSupplier randomAccessSupplier = new FakeScorerSupplier(TestUtil.nextInt(random(), 31, 100), 30); expectThrows(AssertionError.class, () -> randomAccessSupplier.get(70)); diff --git a/lucene/core/src/test/org/apache/lucene/search/TestConjunctionDISI.java b/lucene/core/src/test/org/apache/lucene/search/TestConjunctionDISI.java index 68d4263b9f42..69cfdc353508 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestConjunctionDISI.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestConjunctionDISI.java @@ -401,7 +401,8 @@ public void testCollapseSubConjunctionScorers() throws IOException { } public void testIllegalAdvancementOfSubIteratorsTripsAssertion() throws IOException { - assumeTrue("Assertions must be enabled for this test!", LuceneTestCase.assertsAreEnabled); + assumeTrue("Assertions must be enabled for this test!", TEST_ASSERTS_ENABLED); + int maxDoc = 100; final int numIterators = TestUtil.nextInt(random(), 2, 5); FixedBitSet set = randomSet(maxDoc); diff --git a/lucene/core/src/test/org/apache/lucene/search/TestMultiCollector.java b/lucene/core/src/test/org/apache/lucene/search/TestMultiCollector.java index cfac083716d9..1a5f54443f6a 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestMultiCollector.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestMultiCollector.java @@ -402,13 +402,15 @@ public void testCacheScoresIfNecessary() throws IOException { final LeafReaderContext ctx = reader.leaves().get(0); - expectThrows( - AssertionError.class, - () -> { - collector(ScoreMode.COMPLETE_NO_SCORES, ScoreCachingWrappingScorer.class) - .getLeafCollector(ctx) - .setScorer(new SimpleScorable()); - }); + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + collector(ScoreMode.COMPLETE_NO_SCORES, ScoreCachingWrappingScorer.class) + .getLeafCollector(ctx) + .setScorer(new SimpleScorable()); + }); + } // no collector needs scores => no caching Collector c1 = collector(ScoreMode.COMPLETE_NO_SCORES, SimpleScorable.class); diff --git a/lucene/core/src/test/org/apache/lucene/search/TestTermScorer.java b/lucene/core/src/test/org/apache/lucene/search/TestTermScorer.java index c2dfa2e6e6a9..38401d312053 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestTermScorer.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestTermScorer.java @@ -208,11 +208,13 @@ public CacheHelper getReaderCacheHelper() { IndexSearcher indexSearcher = new IndexSearcher(forbiddenNorms); Weight weight = indexSearcher.createWeight(termQuery, ScoreMode.COMPLETE, 1); - expectThrows( - AssertionError.class, - () -> { - weight.scorer(forbiddenNorms.getContext()).iterator().nextDoc(); - }); + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + weight.scorer(forbiddenNorms.getContext()).iterator().nextDoc(); + }); + } Weight weight2 = indexSearcher.createWeight(termQuery, ScoreMode.COMPLETE_NO_SCORES, 1); // should not fail this time since norms are not necessary diff --git a/lucene/facet/src/test/org/apache/lucene/facet/facetset/TestMatchingFacetSetsCounts.java b/lucene/facet/src/test/org/apache/lucene/facet/facetset/TestMatchingFacetSetsCounts.java index e1bbad55e5c2..781efc5150f0 100644 --- a/lucene/facet/src/test/org/apache/lucene/facet/facetset/TestMatchingFacetSetsCounts.java +++ b/lucene/facet/src/test/org/apache/lucene/facet/facetset/TestMatchingFacetSetsCounts.java @@ -69,6 +69,8 @@ public void testInvalidTopN() throws IOException { } public void testInconsistentNumOfIndexedDimensions() throws IOException { + assumeTrue("Test designed to work only with assertions enabled.", TEST_ASSERTS_ENABLED); + Directory d = newDirectory(); RandomIndexWriter w = new RandomIndexWriter(random(), d); diff --git a/lucene/queries/src/test/org/apache/lucene/queries/function/TestKnnVectorSimilarityFunctions.java b/lucene/queries/src/test/org/apache/lucene/queries/function/TestKnnVectorSimilarityFunctions.java index df13582259cc..54846a88d64c 100644 --- a/lucene/queries/src/test/org/apache/lucene/queries/function/TestKnnVectorSimilarityFunctions.java +++ b/lucene/queries/src/test/org/apache/lucene/queries/function/TestKnnVectorSimilarityFunctions.java @@ -192,6 +192,8 @@ public void vectorSimilarity_missingByteVectorField_shouldReturnZero() throws Ex @Test public void vectorSimilarity_twoVectorsWithDifferentDimensions_shouldRaiseException() { + assumeTrue("Test designed to work only with assertions enabled.", TEST_ASSERTS_ENABLED); + ValueSource v1 = new ConstKnnByteVectorValueSource(new byte[] {1, 2, 3, 4}); ValueSource v2 = new ByteKnnVectorFieldSource("knnByteField1"); ByteVectorSimilarityFunction byteDenseVectorSimilarityFunction = diff --git a/lucene/sandbox/src/test/org/apache/lucene/sandbox/facet/TestTaxonomyFacet.java b/lucene/sandbox/src/test/org/apache/lucene/sandbox/facet/TestTaxonomyFacet.java index fda474974981..ee8906467492 100644 --- a/lucene/sandbox/src/test/org/apache/lucene/sandbox/facet/TestTaxonomyFacet.java +++ b/lucene/sandbox/src/test/org/apache/lucene/sandbox/facet/TestTaxonomyFacet.java @@ -163,11 +163,13 @@ public void testBasic() throws Exception { new FacetLabel("Author", "Bob"), })); - expectThrows( - AssertionError.class, - () -> { - getTopChildrenByCount(countRecorder2, taxoReader, 10, "Non exitent dim"); - }); + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + getTopChildrenByCount(countRecorder2, taxoReader, 10, "Non exitent dim"); + }); + } writer.close(); IOUtils.close(taxoWriter, searcher.getIndexReader(), taxoReader, taxoDir, dir); diff --git a/lucene/sandbox/src/test/org/apache/lucene/sandbox/search/TestPhraseWildcardQuery.java b/lucene/sandbox/src/test/org/apache/lucene/sandbox/search/TestPhraseWildcardQuery.java index 65bbbed9ecf7..2cb99485b4eb 100644 --- a/lucene/sandbox/src/test/org/apache/lucene/sandbox/search/TestPhraseWildcardQuery.java +++ b/lucene/sandbox/src/test/org/apache/lucene/sandbox/search/TestPhraseWildcardQuery.java @@ -628,7 +628,9 @@ AssertCounters assertCounters() { // Only verify test counters if the number of segments is 2 as expected. // If the randomization produced a different number of segments, // then just ignore test counters. - return reader.leaves().size() == 2 ? new AssertCounters() : AssertCounters.NO_OP; + return reader.leaves().size() == 2 && TEST_ASSERTS_ENABLED + ? new AssertCounters() + : AssertCounters.NO_OP; } /** Fluent API to assert {@link TestCounters}. */ diff --git a/lucene/spatial-extras/src/test/org/apache/lucene/spatial/prefix/tree/TestDateRangePrefixTree.java b/lucene/spatial-extras/src/test/org/apache/lucene/spatial/prefix/tree/TestDateRangePrefixTree.java index 60b2200cc885..13ad5973ae12 100644 --- a/lucene/spatial-extras/src/test/org/apache/lucene/spatial/prefix/tree/TestDateRangePrefixTree.java +++ b/lucene/spatial-extras/src/test/org/apache/lucene/spatial/prefix/tree/TestDateRangePrefixTree.java @@ -183,6 +183,11 @@ public void testParseCalendar() throws ParseException { }; private void roundTrip(Calendar calOrig) throws ParseException { + if (!TEST_ASSERTS_ENABLED) { + // If we're running without assertions, this test won't trigger. + return; + } + Calendar cal = (Calendar) calOrig.clone(); while (true) { String calString; @@ -227,7 +232,9 @@ private void roundTrip(Calendar calOrig) throws ParseException { try { tree.clearFieldsAfter(cal, prevPrecField); } catch (AssertionError e) { - if (e.getMessage().equals("Calendar underflow")) return; + if (e.getMessage().equals("Calendar underflow")) { + return; + } throw e; } } diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/index/BaseTermVectorsFormatTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/tests/index/BaseTermVectorsFormatTestCase.java index a38a82e7deac..64733b91555e 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/tests/index/BaseTermVectorsFormatTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/tests/index/BaseTermVectorsFormatTestCase.java @@ -518,7 +518,10 @@ && equals(tk.payloads[index], docsAndPositionsEnum.getPayload())) { assertTrue(foundPayload); } } - expectThrows(getReadPastLastPositionExceptionClass(), docsAndPositionsEnum::nextPosition); + Class exClass = getReadPastLastPositionExceptionClass(); + if (AssertionError.class.isAssignableFrom(exClass) && TEST_ASSERTS_ENABLED) { + expectThrows(exClass, docsAndPositionsEnum::nextPosition); + } assertEquals(PostingsEnum.NO_MORE_DOCS, docsAndPositionsEnum.nextDoc()); } this.docsEnum.set(docsAndPositionsEnum); From 3fac88d36387399a508ab71e94c3b9d63c5b24d4 Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Fri, 10 Oct 2025 18:57:17 +0200 Subject: [PATCH 03/11] Pick tests.asserts randomly based on the main seed. Use assertions 75% of the time. --- .../gradle/plugins/java/TestsAndRandomizationPlugin.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/plugins/java/TestsAndRandomizationPlugin.java b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/plugins/java/TestsAndRandomizationPlugin.java index 684f14545221..aeef87536adc 100644 --- a/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/plugins/java/TestsAndRandomizationPlugin.java +++ b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/plugins/java/TestsAndRandomizationPlugin.java @@ -223,7 +223,13 @@ public void apply(Project project) { Provider assertsOption = buildOptions.addBooleanOption( - "tests.asserts", "Enables or disables assertions mode.", true); + "tests.asserts", + "Enables or disables assertions mode.", + project.provider( + () -> { + // Run with assertions for ~75% of all seeds. + return new Random(buildGlobals.getProjectSeedAsLong().get()).nextInt(100) > 25; + })); optionsInheritedAsProperties.add("tests.asserts"); buildOptions.addBooleanOption( From 2af8d653a77687c34105a4c9f390f9afb24ea4cf Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Fri, 10 Oct 2025 19:00:37 +0200 Subject: [PATCH 04/11] Changes entry. --- lucene/CHANGES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index ab82a193c5c9..7f975080c863 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -106,6 +106,8 @@ Changes in Runtime Behavior Build --------------------- +* GITHUB#15325: Run the tests with assertions disabled ~25% of the time #15325 (Dawid Weiss) + * GITHUB#14804: Detect and ban wildcard imports in Java (Robert Muir, Dawid Weiss) * GITHUB#14808: Add support for validating sources using ast-grep tool rules #14808 From 170366968f927a35caa97c510e7501e175c88664 Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Fri, 10 Oct 2025 19:08:57 +0200 Subject: [PATCH 05/11] Clean up duplicate assertion-verifying code. --- .../test/org/apache/lucene/TestAssertions.java | 14 +++++++------- .../org/apache/lucene/util/fst/TestFSTs.java | 2 +- .../apache/lucene/tests/util/LuceneTestCase.java | 16 ++++++---------- .../util/RunListenerPrintReproduceInfo.java | 2 +- .../tests/util/TestRuleAssertionsRequired.java | 5 +++-- 5 files changed, 18 insertions(+), 21 deletions(-) diff --git a/lucene/core/src/test/org/apache/lucene/TestAssertions.java b/lucene/core/src/test/org/apache/lucene/TestAssertions.java index 818c3d737a17..514c0d08e5d0 100644 --- a/lucene/core/src/test/org/apache/lucene/TestAssertions.java +++ b/lucene/core/src/test/org/apache/lucene/TestAssertions.java @@ -46,13 +46,13 @@ public boolean incrementToken() { public void testTokenStreams() { new TestTokenStream1(); new TestTokenStream2(); - try { - new TestTokenStream3(); - if (assertsAreEnabled) { - fail("TestTokenStream3 should fail assertion"); - } - } catch (AssertionError _) { - // expected + + if (TEST_ASSERTS_ENABLED) { + expectThrows( + AssertionError.class, + () -> { + new TestTokenStream3(); + }); } } } diff --git a/lucene/core/src/test/org/apache/lucene/util/fst/TestFSTs.java b/lucene/core/src/test/org/apache/lucene/util/fst/TestFSTs.java index 5ce788a6e66e..fd81bd4e7e8c 100644 --- a/lucene/core/src/test/org/apache/lucene/util/fst/TestFSTs.java +++ b/lucene/core/src/test/org/apache/lucene/util/fst/TestFSTs.java @@ -1706,7 +1706,7 @@ public void testLargeOutputsOnArrayArcs() throws Exception { } public void testIllegallyModifyRootArc() throws Exception { - assumeTrue("test relies on assertions", assertsAreEnabled); + assumeTrue("test relies on assertions", TEST_ASSERTS_ENABLED); Set terms = new HashSet<>(); for (int i = 0; i < 100; i++) { diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/util/LuceneTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/tests/util/LuceneTestCase.java index 8ced7b7cf827..631a4fcebb6b 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/tests/util/LuceneTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/tests/util/LuceneTestCase.java @@ -414,7 +414,12 @@ public abstract class LuceneTestCase extends Assert { /** Enables or disables dumping of {@link InfoStream} messages. */ public static final boolean INFOSTREAM = systemPropertyAsBoolean("tests.infostream", VERBOSE); - public static final boolean TEST_ASSERTS_ENABLED = systemPropertyAsBoolean("tests.asserts", true); + /** + * True if {@code tests.asserts} is enabled (either explicitly via the build option or, if not + * present, by the default assertion status on this class). + */ + public static final boolean TEST_ASSERTS_ENABLED = + systemPropertyAsBoolean("tests.asserts", LuceneTestCase.class.desiredAssertionStatus()); /** * The default (embedded resource) lines file. @@ -3109,15 +3114,6 @@ public static List getJvmForkArguments() throws IOException { return Files.readAllLines(forkArgsPath, StandardCharsets.UTF_8); } - /** True if assertions (-ea) are enabled (at least for this class). */ - public static final boolean assertsAreEnabled; - - static { - boolean enabled = false; - assert (enabled = true) == true; // Intentional side-effect!!! - assertsAreEnabled = enabled; - } - /** * Compares two strings with a collator, also looking to see if the strings are impacted by jdk * bugs. may not avoid all jdk bugs in tests. see https://bugs.openjdk.java.net/browse/JDK-8071862 diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/util/RunListenerPrintReproduceInfo.java b/lucene/test-framework/src/java/org/apache/lucene/tests/util/RunListenerPrintReproduceInfo.java index 46cacd074a75..7bdc3a710b8f 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/tests/util/RunListenerPrintReproduceInfo.java +++ b/lucene/test-framework/src/java/org/apache/lucene/tests/util/RunListenerPrintReproduceInfo.java @@ -216,7 +216,7 @@ private void reportAdditionalFailureInfo(final String testName) { } } - if (LuceneTestCase.assertsAreEnabled) { + if (LuceneTestCase.TEST_ASSERTS_ENABLED) { addVmOpt(b, "tests.asserts", "true"); } else { addVmOpt(b, "tests.asserts", "false"); diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/util/TestRuleAssertionsRequired.java b/lucene/test-framework/src/java/org/apache/lucene/tests/util/TestRuleAssertionsRequired.java index df2e43c4955e..192f2ee8321c 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/tests/util/TestRuleAssertionsRequired.java +++ b/lucene/test-framework/src/java/org/apache/lucene/tests/util/TestRuleAssertionsRequired.java @@ -29,9 +29,10 @@ public Statement apply(final Statement base, final Description description) { public void evaluate() throws Throwable { try { // Make sure -ea matches -Dtests.asserts, to catch accidental mis-use: - if (LuceneTestCase.assertsAreEnabled != LuceneTestCase.TEST_ASSERTS_ENABLED) { + var assertsEnabled = LuceneTestCase.class.desiredAssertionStatus(); + if (assertsEnabled != LuceneTestCase.TEST_ASSERTS_ENABLED) { String msg = "Assertions mismatch: "; - if (LuceneTestCase.assertsAreEnabled) { + if (assertsEnabled) { msg += "-ea was specified"; } else { msg += "-ea was not specified"; From 21c825eaea6eacbacc775faf3516ffeadedd51eb Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Fri, 10 Oct 2025 20:37:04 +0200 Subject: [PATCH 06/11] Add a new build option tests.random.maxcalls for debugging too many calls to the asserting Random returned from LuceneTestCase.random(). Added LuceneTestCase.nonAssertingRandom(Random) to acquire a fast, non-asserting random instance for intense local computation. Modified a bunch of tests that exceeded 1 million calls to random() result. --- .../java/TestsAndRandomizationPlugin.java | 4 + .../analysis/util/TestRollingCharBuffer.java | 2 +- .../AbstractTestCompressionMode.java | 6 +- .../utils/TestDataSplitter.java | 2 +- .../lucene/geo/TestGeoEncodingUtils.java | 9 +- .../store/TestByteBuffersDataInput.java | 17 ++-- .../lucene/store/TestMMapDirectory.java | 2 +- .../apache/lucene/util/TestPriorityQueue.java | 3 +- .../util/packed/TestDirectMonotonic.java | 2 +- .../lucene/spatial3d/TestGeo3DPoint.java | 4 +- .../search/suggest/TestInputIterator.java | 4 +- .../index/BaseCompoundFormatTestCase.java | 4 +- .../index/BaseStoredFieldsFormatTestCase.java | 2 +- .../lucene/tests/util/BaseBitSetTestCase.java | 2 +- .../tests/util/BaseDocIdSetTestCase.java | 4 +- .../lucene/tests/util/LuceneTestCase.java | 42 ++++++-- .../lucene/tests/util/MaxCallCountRandom.java | 98 +++++++++++++++++++ 17 files changed, 168 insertions(+), 39 deletions(-) create mode 100644 lucene/test-framework/src/java/org/apache/lucene/tests/util/MaxCallCountRandom.java diff --git a/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/plugins/java/TestsAndRandomizationPlugin.java b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/plugins/java/TestsAndRandomizationPlugin.java index aeef87536adc..b02ba360b734 100644 --- a/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/plugins/java/TestsAndRandomizationPlugin.java +++ b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/plugins/java/TestsAndRandomizationPlugin.java @@ -221,6 +221,10 @@ public void apply(Project project) { buildOptions.addIntOption("tests.timeoutSuite", "Timeout (in millis) for an entire suite."); optionsInheritedAsProperties.add("tests.timeoutSuite"); + buildOptions.addIntOption( + "tests.random.maxcalls", "Max calls to Randoms returned by LuceneTestCase.random()"); + optionsInheritedAsProperties.add("tests.random.maxcalls"); + Provider assertsOption = buildOptions.addBooleanOption( "tests.asserts", diff --git a/lucene/analysis/common/src/test/org/apache/lucene/analysis/util/TestRollingCharBuffer.java b/lucene/analysis/common/src/test/org/apache/lucene/analysis/util/TestRollingCharBuffer.java index 9a9e74c8764c..aa41b62a00b1 100644 --- a/lucene/analysis/common/src/test/org/apache/lucene/analysis/util/TestRollingCharBuffer.java +++ b/lucene/analysis/common/src/test/org/apache/lucene/analysis/util/TestRollingCharBuffer.java @@ -28,7 +28,7 @@ public void test() throws Exception { RollingCharBuffer buffer = new RollingCharBuffer(); - Random random = random(); + Random random = nonAssertingRandom(random()); for (int iter = 0; iter < ITERS; iter++) { final int stringLen = random.nextBoolean() ? random.nextInt(50) : random.nextInt(20000); final String s; diff --git a/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/compressing/AbstractTestCompressionMode.java b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/compressing/AbstractTestCompressionMode.java index 2cca151e0592..7bf8c528dde1 100644 --- a/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/compressing/AbstractTestCompressionMode.java +++ b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/compressing/AbstractTestCompressionMode.java @@ -16,6 +16,7 @@ */ package org.apache.lucene.backward_codecs.compressing; +import com.carrotsearch.randomizedtesting.Xoroshiro128PlusRandom; import com.carrotsearch.randomizedtesting.generators.RandomNumbers; import java.io.IOException; import java.util.Arrays; @@ -39,6 +40,7 @@ static byte[] randomArray(Random random) { } static byte[] randomArray(Random random, int length, int max) { + random = new Xoroshiro128PlusRandom(random.nextLong()); final byte[] arr = new byte[length]; for (int i = 0; i < arr.length; ++i) { arr[i] = (byte) RandomNumbers.randomIntBetween(random, 0, max); @@ -83,7 +85,7 @@ byte[] decompress(byte[] compressed, int originalLength, int offset, int length) } public void testDecompress() throws IOException { - Random random = random(); + Random random = nonAssertingRandom(random()); final int iterations = atLeast(random, 3); for (int i = 0; i < iterations; ++i) { final byte[] decompressed = randomArray(random); @@ -99,7 +101,7 @@ public void testDecompress() throws IOException { } public void testPartialDecompress() throws IOException { - Random random = random(); + Random random = nonAssertingRandom(random()); final int iterations = atLeast(random, 3); for (int i = 0; i < iterations; ++i) { final byte[] decompressed = randomArray(random); diff --git a/lucene/classification/src/test/org/apache/lucene/classification/utils/TestDataSplitter.java b/lucene/classification/src/test/org/apache/lucene/classification/utils/TestDataSplitter.java index 5b8e02b84774..1e7f2447a8f0 100644 --- a/lucene/classification/src/test/org/apache/lucene/classification/utils/TestDataSplitter.java +++ b/lucene/classification/src/test/org/apache/lucene/classification/utils/TestDataSplitter.java @@ -63,7 +63,7 @@ public void setUp() throws Exception { ft.setStoreTermVectorPositions(true); Document doc; - Random rnd = random(); + Random rnd = nonAssertingRandom(random()); int numDocs = atLeast(100); for (int i = 0; i < numDocs; i++) { doc = new Document(); diff --git a/lucene/core/src/test/org/apache/lucene/geo/TestGeoEncodingUtils.java b/lucene/core/src/test/org/apache/lucene/geo/TestGeoEncodingUtils.java index d654e4464753..5e32ac435015 100644 --- a/lucene/core/src/test/org/apache/lucene/geo/TestGeoEncodingUtils.java +++ b/lucene/core/src/test/org/apache/lucene/geo/TestGeoEncodingUtils.java @@ -27,6 +27,7 @@ import static org.apache.lucene.geo.GeoUtils.MIN_LAT_INCL; import static org.apache.lucene.geo.GeoUtils.MIN_LON_INCL; +import com.carrotsearch.randomizedtesting.RandomizedTest; import java.util.Random; import org.apache.lucene.tests.util.LuceneTestCase; import org.apache.lucene.tests.util.TestUtil; @@ -42,8 +43,8 @@ public class TestGeoEncodingUtils extends LuceneTestCase { */ public void testLatitudeQuantization() throws Exception { final double LATITUDE_DECODE = 180.0D / (0x1L << 32); - Random random = random(); - for (int i = 0; i < 10000; i++) { + Random random = nonAssertingRandom(random()); + for (int i = 0; i < RandomizedTest.randomIntBetween(1000, 10000); i++) { int encoded = random.nextInt(); double min = MIN_LAT_INCL + (encoded - (long) Integer.MIN_VALUE) * LATITUDE_DECODE; double decoded = decodeLatitude(encoded); @@ -92,8 +93,8 @@ public void testLatitudeQuantization() throws Exception { */ public void testLongitudeQuantization() throws Exception { final double LONGITUDE_DECODE = 360.0D / (0x1L << 32); - Random random = random(); - for (int i = 0; i < 10000; i++) { + Random random = nonAssertingRandom(random()); + for (int i = 0; i < RandomizedTest.randomIntBetween(1000, 10000); i++) { int encoded = random.nextInt(); double min = MIN_LON_INCL + (encoded - (long) Integer.MIN_VALUE) * LONGITUDE_DECODE; double decoded = decodeLongitude(encoded); diff --git a/lucene/core/src/test/org/apache/lucene/store/TestByteBuffersDataInput.java b/lucene/core/src/test/org/apache/lucene/store/TestByteBuffersDataInput.java index 0d4629e1c99f..8ce5b4465f2e 100644 --- a/lucene/core/src/test/org/apache/lucene/store/TestByteBuffersDataInput.java +++ b/lucene/core/src/test/org/apache/lucene/store/TestByteBuffersDataInput.java @@ -16,10 +16,12 @@ */ package org.apache.lucene.store; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static com.carrotsearch.randomizedtesting.RandomizedTest.randomBoolean; +import static com.carrotsearch.randomizedtesting.RandomizedTest.randomBytesOfLength; +import static com.carrotsearch.randomizedtesting.RandomizedTest.randomIntBetween; +import static com.carrotsearch.randomizedtesting.RandomizedTest.randomLong; +import static com.carrotsearch.randomizedtesting.RandomizedTest.randomLongBetween; -import com.carrotsearch.randomizedtesting.RandomizedTest; import com.carrotsearch.randomizedtesting.Xoroshiro128PlusRandom; import com.carrotsearch.randomizedtesting.annotations.Timeout; import java.io.EOFException; @@ -32,7 +34,7 @@ import org.apache.lucene.util.IOConsumer; import org.junit.Test; -public final class TestByteBuffersDataInput extends RandomizedTest { +public final class TestByteBuffersDataInput extends LuceneTestCase { @Test public void testSanity() throws IOException { ByteBuffersDataOutput out = new ByteBuffersDataOutput(); @@ -72,7 +74,7 @@ public void testRandomReads() throws Exception { long seed = randomLong(); int max = LuceneTestCase.TEST_NIGHTLY ? 1_000_000 : 100_000; List> reply = - TestByteBuffersDataOutput.addRandomData(dst, new Xoroshiro128PlusRandom(seed), max); + TestByteBuffersDataOutput.addRandomData(dst, nonAssertingRandom(random()), max); ByteBuffersDataInput src = dst.toDataInput(); for (IOConsumer c : reply) { @@ -94,10 +96,9 @@ public void testRandomReadsOnSlices() throws Exception { byte[] prefix = new byte[randomIntBetween(0, 1024 * 8)]; dst.writeBytes(prefix); - long seed = randomLong(); - int max = 10_000; + int max = atLeast(5000); List> reply = - TestByteBuffersDataOutput.addRandomData(dst, new Xoroshiro128PlusRandom(seed), max); + TestByteBuffersDataOutput.addRandomData(dst, nonAssertingRandom(random()), max); byte[] suffix = new byte[randomIntBetween(0, 1024 * 8)]; dst.writeBytes(suffix); diff --git a/lucene/core/src/test/org/apache/lucene/store/TestMMapDirectory.java b/lucene/core/src/test/org/apache/lucene/store/TestMMapDirectory.java index f59adb31db25..33e127823346 100644 --- a/lucene/core/src/test/org/apache/lucene/store/TestMMapDirectory.java +++ b/lucene/core/src/test/org/apache/lucene/store/TestMMapDirectory.java @@ -55,7 +55,7 @@ public void testAceWithThreads() throws Exception { try (Directory dir = getDirectory(createTempDir("testAceWithThreads"))) { try (IndexOutput out = dir.createOutput("test", IOContext.DEFAULT)) { - final Random random = random(); + final Random random = nonAssertingRandom(random()); for (int i = 0; i < nInts; i++) { out.writeInt(random.nextInt()); } diff --git a/lucene/core/src/test/org/apache/lucene/util/TestPriorityQueue.java b/lucene/core/src/test/org/apache/lucene/util/TestPriorityQueue.java index da2b5019cd8f..091834b0e380 100644 --- a/lucene/core/src/test/org/apache/lucene/util/TestPriorityQueue.java +++ b/lucene/core/src/test/org/apache/lucene/util/TestPriorityQueue.java @@ -19,7 +19,6 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThanOrEqualTo; -import com.carrotsearch.randomizedtesting.Xoroshiro128PlusRandom; import com.carrotsearch.randomizedtesting.generators.RandomNumbers; import java.util.ArrayList; import java.util.Collections; @@ -217,7 +216,7 @@ public void testRemovalsAndInsertions() { var reference = new java.util.PriorityQueue(); var pq = new IntegerQueue(size); - Random localRandom = new Xoroshiro128PlusRandom(random().nextLong()); + Random localRandom = nonAssertingRandom(random()); // Lucene's PriorityQueue.remove uses reference equality, not .equals to determine which // elements diff --git a/lucene/core/src/test/org/apache/lucene/util/packed/TestDirectMonotonic.java b/lucene/core/src/test/org/apache/lucene/util/packed/TestDirectMonotonic.java index a10af31835ab..845b7ac8a445 100644 --- a/lucene/core/src/test/org/apache/lucene/util/packed/TestDirectMonotonic.java +++ b/lucene/core/src/test/org/apache/lucene/util/packed/TestDirectMonotonic.java @@ -204,7 +204,7 @@ public void testRandomMerging() throws IOException { } private void doTestRandom(boolean merging) throws IOException { - Random random = random(); + Random random = nonAssertingRandom(random()); final int iters = atLeast(random, 3); for (int iter = 0; iter < iters; ++iter) { Directory dir = newDirectory(); diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java index eac5d2697def..ee07a08313fa 100644 --- a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java +++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java @@ -1554,9 +1554,9 @@ public void testMaxValueQuantization() { * the double range and random doubles within the range too. */ public void testQuantization() throws Exception { - Random random = random(); + Random random = nonAssertingRandom(random()); PlanetModel planetModel = randomPlanetModel(); - for (int i = 0; i < 10000; i++) { + for (int i = 0; i < atLeast(5000); i++) { int encoded = random.nextInt(); if (encoded <= planetModel.MIN_ENCODED_VALUE) { continue; diff --git a/lucene/suggest/src/test/org/apache/lucene/search/suggest/TestInputIterator.java b/lucene/suggest/src/test/org/apache/lucene/search/suggest/TestInputIterator.java index 94ba3e3fdb8e..5a75e022580f 100644 --- a/lucene/suggest/src/test/org/apache/lucene/search/suggest/TestInputIterator.java +++ b/lucene/suggest/src/test/org/apache/lucene/search/suggest/TestInputIterator.java @@ -41,8 +41,8 @@ public void testEmpty() throws Exception { } public void testTerms() throws Exception { - Random random = random(); - int num = atLeast(10000); + Random random = nonAssertingRandom(random()); + int num = atLeast(5000); TreeMap> sorted = new TreeMap<>(); TreeMap sortedWithoutPayload = new TreeMap<>(); diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/index/BaseCompoundFormatTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/tests/index/BaseCompoundFormatTestCase.java index a592ace7f030..7e1792f5d55f 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/tests/index/BaseCompoundFormatTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/tests/index/BaseCompoundFormatTestCase.java @@ -682,8 +682,8 @@ protected static SegmentInfo newSegmentInfo(Directory dir, String name) { /** Creates a file of the specified size with random data. */ protected static void createRandomFile(Directory dir, String name, int size, byte[] segId) throws IOException { - Random rnd = random(); - try (IndexOutput os = dir.createOutput(name, newIOContext(random()))) { + Random rnd = nonAssertingRandom(random()); + try (IndexOutput os = dir.createOutput(name, newIOContext(rnd))) { CodecUtil.writeIndexHeader(os, "Foo", 0, segId, "suffix"); for (int i = 0; i < size; i++) { byte b = (byte) rnd.nextInt(256); diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/index/BaseStoredFieldsFormatTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/tests/index/BaseStoredFieldsFormatTestCase.java index 3f4d7d4ae695..dd09fd4dae65 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/tests/index/BaseStoredFieldsFormatTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/tests/index/BaseStoredFieldsFormatTestCase.java @@ -97,7 +97,7 @@ protected void addRandomFields(Document d) { public void testRandomStoredFields() throws IOException { Directory dir = newDirectory(); - Random rand = random(); + Random rand = nonAssertingRandom(random()); RandomIndexWriter w = new RandomIndexWriter( rand, diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/util/BaseBitSetTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/tests/util/BaseBitSetTestCase.java index 205d8861322a..3cb22e517493 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/tests/util/BaseBitSetTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/tests/util/BaseBitSetTestCase.java @@ -46,7 +46,7 @@ static java.util.BitSet randomSet(int numBits, int numBitsSet) { if (numBitsSet == numBits) { set.set(0, numBits); } else { - Random random = random(); + Random random = nonAssertingRandom(random()); for (int i = 0; i < numBitsSet; ++i) { while (true) { final int o = random.nextInt(numBits); diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/util/BaseDocIdSetTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/tests/util/BaseDocIdSetTestCase.java index 589eb03427f6..e5c531c222ce 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/tests/util/BaseDocIdSetTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/tests/util/BaseDocIdSetTestCase.java @@ -63,7 +63,7 @@ public void test2Bits() throws IOException { /** Compare the content of the set against a {@link BitSet}. */ public void testAgainstBitSet() throws IOException { - Random random = random(); + Random random = nonAssertingRandom(random()); final int numBits = TestUtil.nextInt(random, 100, 1 << 20); // test various random sets with various load factors for (float percentSet : new float[] {0f, 0.0001f, random.nextFloat(), 0.9f, 1f}) { @@ -181,7 +181,7 @@ private long ramBytesUsed(DocIdSet set, int length) throws IOException { } public void testIntoBitSet() throws IOException { - Random random = random(); + Random random = nonAssertingRandom(random()); final int numBits = TestUtil.nextInt(random, 100, 1 << 20); // test various random sets with various load factors for (float percentSet : new float[] {0f, 0.0001f, random.nextFloat(), 0.9f, 1f}) { diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/util/LuceneTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/tests/util/LuceneTestCase.java index 631a4fcebb6b..d28a91cecf32 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/tests/util/LuceneTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/tests/util/LuceneTestCase.java @@ -30,6 +30,7 @@ import com.carrotsearch.randomizedtesting.RandomizedContext; import com.carrotsearch.randomizedtesting.RandomizedRunner; import com.carrotsearch.randomizedtesting.RandomizedTest; +import com.carrotsearch.randomizedtesting.Xoroshiro128PlusRandom; import com.carrotsearch.randomizedtesting.annotations.Listeners; import com.carrotsearch.randomizedtesting.annotations.SeedDecorators; import com.carrotsearch.randomizedtesting.annotations.TestGroup; @@ -91,6 +92,7 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; import java.util.regex.Pattern; import junit.framework.AssertionFailedError; import org.apache.lucene.analysis.Analyzer; @@ -287,6 +289,11 @@ public abstract class LuceneTestCase extends Assert { */ public static final String SYSPROP_FAILFAST = "tests.failfast"; + /** + * @see #randomSupplier + */ + public static final String SYSPROP_RANDOM_MAXCALLS = "tests.random.maxcalls"; + /** Annotation for tests that should only be run during nightly builds. */ @Documented @Inherited @@ -686,6 +693,18 @@ static void setLiveIWCFlushMode(LiveIWCFlushMode flushMode) { liveIWCFlushMode = flushMode; } + private static final Supplier randomSupplier; + + static { + int maxCalls = Integer.parseInt(System.getProperty(SYSPROP_RANDOM_MAXCALLS, "0")); + Supplier supplier = () -> RandomizedContext.current().getRandom(); + if (maxCalls > 0) { + var finalizedSupplier = supplier; + supplier = () -> new MaxCallCountRandom(finalizedSupplier.get(), maxCalls); + } + randomSupplier = supplier; + } + // ----------------------------------------------------------------- // Suite and test case setup/ cleanup. // ----------------------------------------------------------------- @@ -738,17 +757,22 @@ public void restoreIndexWriterMaxDocs() { * another test case. * *

There is an overhead connected with getting the {@link Random} for a particular context and - * thread. It is better to cache the {@link Random} locally if tight loops with multiple - * invocations are present or create a derivative local {@link Random} for millions of calls like - * this: - * - *

-   * Random random = new Random(random().nextLong());
-   * // tight loop with many invocations.
-   * 
+ * thread. It is better to use a non-asserting {@link Random} instance locally if tight loops with + * multiple invocations are present. See {@link #nonAssertingRandom(Random)}. */ public static Random random() { - return RandomizedContext.current().getRandom(); + return randomSupplier.get(); + } + + /** + * Returns a Random instance based on the current state of another Random. The returned instance + * should be faster for thousands of consecutive calls because it doesn't assert that it isn't + * shared between threads or used within the correct {@link RandomizedContext}. + * + *

Use this method for local tight loops that generate a lot of random data. + */ + public static Random nonAssertingRandom(Random rnd) { + return new Xoroshiro128PlusRandom(rnd.nextLong()); } /** diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/util/MaxCallCountRandom.java b/lucene/test-framework/src/java/org/apache/lucene/tests/util/MaxCallCountRandom.java new file mode 100644 index 000000000000..c37f31a6bcc3 --- /dev/null +++ b/lucene/test-framework/src/java/org/apache/lucene/tests/util/MaxCallCountRandom.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.apache.lucene.tests.util; + +import java.util.Random; + +/** + * A {@link Random} subclass that counts calls to its methods and throws an exception if their + * number exceeds the provided thresholds. + * + *

This can be used to debug too many calls to a random returned by {@link + * LuceneTestCase#random()}. + */ +final class MaxCallCountRandom extends Random { + private final Random delegate; + // it doesn't have to be volatile (or thread-safe). just an approximation. + private long useCount; + private final long maxCalls; + + public MaxCallCountRandom(Random delegate, long maxCalls) { + this.delegate = delegate; + this.maxCalls = maxCalls; + } + + private void incrementUseCount() { + if (useCount++ > maxCalls) { + throw new RuntimeException("Random.* use count exceeded the limit."); + } + } + + @Override + protected int next(int bits) { + throw new RuntimeException("Shouldn't be reachable."); + } + + @Override + public boolean nextBoolean() { + incrementUseCount(); + return delegate.nextBoolean(); + } + + @Override + public void nextBytes(byte[] bytes) { + incrementUseCount(); + delegate.nextBytes(bytes); + } + + @Override + public double nextDouble() { + incrementUseCount(); + return delegate.nextDouble(); + } + + @Override + public float nextFloat() { + incrementUseCount(); + return delegate.nextFloat(); + } + + @Override + public double nextGaussian() { + incrementUseCount(); + return delegate.nextGaussian(); + } + + @Override + public int nextInt() { + incrementUseCount(); + return delegate.nextInt(); + } + + @Override + public int nextInt(int n) { + incrementUseCount(); + return delegate.nextInt(n); + } + + @Override + public long nextLong() { + incrementUseCount(); + return delegate.nextLong(); + } +} From f3977fef9a4f5b2de32bd16eaff6f0c5d1843dc8 Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Fri, 10 Oct 2025 22:17:09 +0200 Subject: [PATCH 07/11] Added another option for low-level debugging of intense random() calls. tests.random.maxacquires will terminate if too many random() calls are called from within a single test. Corrected a few tests where this was the case. --- .../java/TestsAndRandomizationPlugin.java | 7 +++- .../standard/TestStandardAnalyzer.java | 15 ++++---- .../codecs/lucene103/blocktree/TestTrie.java | 5 ++- .../apache/lucene/geo/TestXYRectangle.java | 24 ++++++------ .../lucene/search/TestCollectorManager.java | 4 +- .../lucene/search/TestConjunctionDISI.java | 10 ++--- .../search/TestMultiCollectorManager.java | 3 +- .../lucene/util/TestMSBRadixSorter.java | 27 +++++-------- .../apache/lucene/util/TestRadixSelector.java | 31 ++++++++------- .../lucene/util/TestStableMSBRadixSorter.java | 27 +++++-------- .../util/automaton/TestCompiledAutomaton.java | 1 - .../bkd/TestMutablePointTreeReaderUtils.java | 19 +++------- .../TestLowercaseAsciiCompression.java | 38 ++++++++++--------- .../lucene/util/packed/TestPackedInts.java | 17 +++++---- .../sandbox/document/TestHalfFloatPoint.java | 9 ++--- .../lucene/tests/util/LuceneTestCase.java | 34 ++++++++++++++++- .../apache/lucene/tests/util/TestUtil.java | 2 + 17 files changed, 153 insertions(+), 120 deletions(-) diff --git a/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/plugins/java/TestsAndRandomizationPlugin.java b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/plugins/java/TestsAndRandomizationPlugin.java index b02ba360b734..1906f4ca20ca 100644 --- a/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/plugins/java/TestsAndRandomizationPlugin.java +++ b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/plugins/java/TestsAndRandomizationPlugin.java @@ -222,9 +222,14 @@ public void apply(Project project) { optionsInheritedAsProperties.add("tests.timeoutSuite"); buildOptions.addIntOption( - "tests.random.maxcalls", "Max calls to Randoms returned by LuceneTestCase.random()"); + "tests.random.maxcalls", + "Max number of calls to Randoms returned by LuceneTestCase.random()"); optionsInheritedAsProperties.add("tests.random.maxcalls"); + buildOptions.addIntOption( + "tests.random.maxacquires", "Max number of per-test calls to LuceneTestCase.random()"); + optionsInheritedAsProperties.add("tests.random.maxacquires"); + Provider assertsOption = buildOptions.addBooleanOption( "tests.asserts", diff --git a/lucene/core/src/test/org/apache/lucene/analysis/standard/TestStandardAnalyzer.java b/lucene/core/src/test/org/apache/lucene/analysis/standard/TestStandardAnalyzer.java index b51cdf863066..a9a7bd7145a4 100644 --- a/lucene/core/src/test/org/apache/lucene/analysis/standard/TestStandardAnalyzer.java +++ b/lucene/core/src/test/org/apache/lucene/analysis/standard/TestStandardAnalyzer.java @@ -76,19 +76,20 @@ public void testLargePartiallyMatchingToken() throws Exception { }; StringBuilder builder = new StringBuilder(); - int numChars = TestUtil.nextInt(random(), 100 * 1024, 1024 * 1024); + var rnd = nonAssertingRandom(random()); + int numChars = TestUtil.nextInt(rnd, 100 * 1024, 1024 * 1024); for (int i = 0; i < numChars; ) { builder.append( - WordBreak_ExtendNumLet_chars[random().nextInt(WordBreak_ExtendNumLet_chars.length)]); + WordBreak_ExtendNumLet_chars[rnd.nextInt(WordBreak_ExtendNumLet_chars.length)]); ++i; - if (random().nextBoolean()) { - int numFormatExtendChars = TestUtil.nextInt(random(), 1, 8); + if (rnd.nextBoolean()) { + int numFormatExtendChars = TestUtil.nextInt(rnd, 1, 8); for (int j = 0; j < numFormatExtendChars; ++j) { int codepoint; - if (random().nextBoolean()) { - codepoint = WordBreak_Format_chars[random().nextInt(WordBreak_Format_chars.length)]; + if (rnd.nextBoolean()) { + codepoint = WordBreak_Format_chars[rnd.nextInt(WordBreak_Format_chars.length)]; } else { - codepoint = WordBreak_Extend_chars[random().nextInt(WordBreak_Extend_chars.length)]; + codepoint = WordBreak_Extend_chars[rnd.nextInt(WordBreak_Extend_chars.length)]; } char[] chars = Character.toChars(codepoint); builder.append(chars); diff --git a/lucene/core/src/test/org/apache/lucene/codecs/lucene103/blocktree/TestTrie.java b/lucene/core/src/test/org/apache/lucene/codecs/lucene103/blocktree/TestTrie.java index f559262b160a..f1bc495f656e 100644 --- a/lucene/core/src/test/org/apache/lucene/codecs/lucene103/blocktree/TestTrie.java +++ b/lucene/core/src/test/org/apache/lucene/codecs/lucene103/blocktree/TestTrie.java @@ -194,9 +194,10 @@ private void testTrieLookup(Supplier randomBytesSupplier, int round) thr } private static byte[] randomBytes() { - byte[] bytes = new byte[random().nextInt(256) + 1]; + var random = nonAssertingRandom(random()); + byte[] bytes = new byte[random.nextInt(256) + 1]; for (int i = 1; i < bytes.length; i++) { - bytes[i] = (byte) random().nextInt(1 << (i % 9)); + bytes[i] = (byte) random.nextInt(1 << (i % 9)); } return bytes; } diff --git a/lucene/core/src/test/org/apache/lucene/geo/TestXYRectangle.java b/lucene/core/src/test/org/apache/lucene/geo/TestXYRectangle.java index a70abdc79640..bd3a13201dc5 100644 --- a/lucene/core/src/test/org/apache/lucene/geo/TestXYRectangle.java +++ b/lucene/core/src/test/org/apache/lucene/geo/TestXYRectangle.java @@ -139,17 +139,19 @@ public void testEqualsAndHashCode() { /** make sure that if a point is inside a circle, it is inside of the bbox as well */ public void testRandomCircleToBBox() { + var random = nonAssertingRandom(random()); + int iters = atLeast(100); for (int iter = 0; iter < iters; iter++) { - float centerX = ShapeTestUtil.nextFloat(random()); - float centerY = ShapeTestUtil.nextFloat(random()); + float centerX = ShapeTestUtil.nextFloat(random); + float centerY = ShapeTestUtil.nextFloat(random); final float radius; - if (random().nextBoolean()) { - radius = random().nextFloat() * TestUtil.nextInt(random(), 1, 100000); + if (random.nextBoolean()) { + radius = random.nextFloat() * TestUtil.nextInt(random, 1, 100000); } else { - radius = Math.abs(ShapeTestUtil.nextFloat(random())); + radius = Math.abs(ShapeTestUtil.nextFloat(random)); } XYRectangle bbox = XYRectangle.fromPointDistance(centerX, centerY, radius); @@ -159,16 +161,16 @@ public void testRandomCircleToBBox() { for (int i = 0; i < numPointsToTry; i++) { double x; - if (random().nextBoolean()) { - x = Math.min(Float.MAX_VALUE, centerX + radius + random().nextDouble()); + if (random.nextBoolean()) { + x = Math.min(Float.MAX_VALUE, centerX + radius + random.nextDouble()); } else { - x = Math.max(-Float.MAX_VALUE, centerX + radius - random().nextDouble()); + x = Math.max(-Float.MAX_VALUE, centerX + radius - random.nextDouble()); } double y; - if (random().nextBoolean()) { - y = Math.min(Float.MAX_VALUE, centerY + radius + random().nextDouble()); + if (random.nextBoolean()) { + y = Math.min(Float.MAX_VALUE, centerY + radius + random.nextDouble()); } else { - y = Math.max(-Float.MAX_VALUE, centerY + radius - random().nextDouble()); + y = Math.max(-Float.MAX_VALUE, centerY + radius - random.nextDouble()); } // cartesian says it's within the circle: diff --git a/lucene/core/src/test/org/apache/lucene/search/TestCollectorManager.java b/lucene/core/src/test/org/apache/lucene/search/TestCollectorManager.java index 1e5826160f61..3ad804b876ef 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestCollectorManager.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestCollectorManager.java @@ -93,12 +93,14 @@ private static DirectoryReader reader(Directory dir) throws IOException { private static Object collectAll( LeafReaderContext ctx, Collection values, CollectorManager collectorManager) throws IOException { + var rnd = nonAssertingRandom(random()); + List collectors = new ArrayList<>(); C collector = collectorManager.newCollector(); collectors.add(collector); LeafCollector leafCollector = collector.getLeafCollector(ctx); for (Integer v : values) { - if (random().nextInt(10) == 1) { + if (rnd.nextInt(10) == 1) { collector = collectorManager.newCollector(); collectors.add(collector); leafCollector = collector.getLeafCollector(ctx); diff --git a/lucene/core/src/test/org/apache/lucene/search/TestConjunctionDISI.java b/lucene/core/src/test/org/apache/lucene/search/TestConjunctionDISI.java index 69cfdc353508..3ade91fc60d7 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestConjunctionDISI.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestConjunctionDISI.java @@ -160,21 +160,21 @@ public float getMaxScore(int upTo) throws IOException { } private static FixedBitSet randomSet(int maxDoc) { - final int step = TestUtil.nextInt(random(), 1, 10); + var random = nonAssertingRandom(random()); + final int step = TestUtil.nextInt(random, 1, 10); FixedBitSet set = new FixedBitSet(maxDoc); - for (int doc = random().nextInt(step); - doc < maxDoc; - doc += TestUtil.nextInt(random(), 1, step)) { + for (int doc = random.nextInt(step); doc < maxDoc; doc += TestUtil.nextInt(random, 1, step)) { set.set(doc); } return set; } private static FixedBitSet clearRandomBits(FixedBitSet other) { + var random = nonAssertingRandom(random()); final FixedBitSet set = new FixedBitSet(other.length()); set.or(other); for (int i = 0; i < set.length(); ++i) { - if (random().nextBoolean()) { + if (random.nextBoolean()) { set.clear(i); } } diff --git a/lucene/core/src/test/org/apache/lucene/search/TestMultiCollectorManager.java b/lucene/core/src/test/org/apache/lucene/search/TestMultiCollectorManager.java index d87515d0596b..57fdf547e315 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestMultiCollectorManager.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestMultiCollectorManager.java @@ -197,8 +197,9 @@ private static Object collectAll( C collector = collectorManager.newCollector(); collectors.add(collector); LeafCollector leafCollector = collector.getLeafCollector(ctx); + Random random = nonAssertingRandom(random()); for (Integer v : values) { - if (random().nextInt(10) == 1) { + if (random.nextInt(10) == 1) { collector = collectorManager.newCollector(); collectors.add(collector); leafCollector = collector.getLeafCollector(ctx); diff --git a/lucene/core/src/test/org/apache/lucene/util/TestMSBRadixSorter.java b/lucene/core/src/test/org/apache/lucene/util/TestMSBRadixSorter.java index 304b9f6e510c..98bb26392224 100644 --- a/lucene/core/src/test/org/apache/lucene/util/TestMSBRadixSorter.java +++ b/lucene/core/src/test/org/apache/lucene/util/TestMSBRadixSorter.java @@ -85,13 +85,14 @@ public void testTwoValues() { } private void testRandom(int commonPrefixLen, int maxLen) { + var random = nonAssertingRandom(random()); byte[] commonPrefix = new byte[commonPrefixLen]; - random().nextBytes(commonPrefix); - final int len = random().nextInt(100000); - BytesRef[] bytes = new BytesRef[len + random().nextInt(50)]; + random.nextBytes(commonPrefix); + final int len = random.nextInt(100000); + BytesRef[] bytes = new BytesRef[len + random.nextInt(50)]; for (int i = 0; i < len; ++i) { - byte[] b = new byte[commonPrefixLen + random().nextInt(maxLen)]; - random().nextBytes(b); + byte[] b = new byte[commonPrefixLen + random.nextInt(maxLen)]; + random.nextBytes(b); System.arraycopy(commonPrefix, 0, b, 0, commonPrefixLen); bytes[i] = new BytesRef(b); } @@ -99,27 +100,19 @@ private void testRandom(int commonPrefixLen, int maxLen) { } public void testRandom() { - for (int iter = 0; iter < 10; ++iter) { - testRandom(0, 10); - } + testRandom(0, 10); } public void testRandomWithLotsOfDuplicates() { - for (int iter = 0; iter < 10; ++iter) { - testRandom(0, 2); - } + testRandom(0, 2); } public void testRandomWithSharedPrefix() { - for (int iter = 0; iter < 10; ++iter) { - testRandom(TestUtil.nextInt(random(), 1, 30), 10); - } + testRandom(TestUtil.nextInt(random(), 1, 30), 10); } public void testRandomWithSharedPrefixAndLotsOfDuplicates() { - for (int iter = 0; iter < 10; ++iter) { - testRandom(TestUtil.nextInt(random(), 1, 30), 2); - } + testRandom(TestUtil.nextInt(random(), 1, 30), 2); } public void testRandom2() { diff --git a/lucene/core/src/test/org/apache/lucene/util/TestRadixSelector.java b/lucene/core/src/test/org/apache/lucene/util/TestRadixSelector.java index ec1849dc3b5b..9af08374945c 100644 --- a/lucene/core/src/test/org/apache/lucene/util/TestRadixSelector.java +++ b/lucene/core/src/test/org/apache/lucene/util/TestRadixSelector.java @@ -22,6 +22,7 @@ import static org.hamcrest.Matchers.sameInstance; import java.util.Arrays; +import java.util.Random; import org.apache.lucene.tests.util.LuceneTestCase; import org.apache.lucene.tests.util.TestUtil; @@ -34,13 +35,15 @@ public void testSelect() { } private void doTestSelect() { - final int from = random().nextInt(5); - final int to = from + TestUtil.nextInt(random(), 1, 10000); - final int maxLen = TestUtil.nextInt(random(), 1, 12); - BytesRef[] arr = new BytesRef[from + to + random().nextInt(5)]; + Random random = nonAssertingRandom(random()); + final int from = random.nextInt(5); + final int to = from + TestUtil.nextInt(random, 1, 10000); + final int maxLen = TestUtil.nextInt(random, 1, 12); + + BytesRef[] arr = new BytesRef[from + to + random.nextInt(5)]; for (int i = 0; i < arr.length; ++i) { - byte[] bytes = new byte[TestUtil.nextInt(random(), 0, maxLen)]; - random().nextBytes(bytes); + byte[] bytes = new byte[TestUtil.nextInt(random, 0, maxLen)]; + random.nextBytes(bytes); arr[i] = new BytesRef(bytes); } doTest(arr, from, to, maxLen); @@ -53,16 +56,18 @@ public void testSharedPrefixes() { } private void doTestSharedPrefixes() { - final int from = random().nextInt(5); - final int to = from + TestUtil.nextInt(random(), 1, 10000); - final int maxLen = TestUtil.nextInt(random(), 1, 12); - BytesRef[] arr = new BytesRef[from + to + random().nextInt(5)]; + Random random = nonAssertingRandom(random()); + + final int from = random.nextInt(5); + final int to = from + TestUtil.nextInt(random, 1, 10000); + final int maxLen = TestUtil.nextInt(random, 1, 12); + BytesRef[] arr = new BytesRef[from + to + random.nextInt(5)]; for (int i = 0; i < arr.length; ++i) { - byte[] bytes = new byte[TestUtil.nextInt(random(), 0, maxLen)]; - random().nextBytes(bytes); + byte[] bytes = new byte[TestUtil.nextInt(random, 0, maxLen)]; + random.nextBytes(bytes); arr[i] = new BytesRef(bytes); } - final int sharedPrefixLength = Math.min(arr[0].length, TestUtil.nextInt(random(), 1, maxLen)); + final int sharedPrefixLength = Math.min(arr[0].length, TestUtil.nextInt(random, 1, maxLen)); for (int i = 1; i < arr.length; ++i) { System.arraycopy( arr[0].bytes, diff --git a/lucene/core/src/test/org/apache/lucene/util/TestStableMSBRadixSorter.java b/lucene/core/src/test/org/apache/lucene/util/TestStableMSBRadixSorter.java index 4e7e06217276..66f94a3b969f 100644 --- a/lucene/core/src/test/org/apache/lucene/util/TestStableMSBRadixSorter.java +++ b/lucene/core/src/test/org/apache/lucene/util/TestStableMSBRadixSorter.java @@ -110,13 +110,14 @@ public void testTwoValues() { } private void testRandom(int commonPrefixLen, int maxLen) { + var random = nonAssertingRandom(random()); byte[] commonPrefix = new byte[commonPrefixLen]; - random().nextBytes(commonPrefix); - final int len = random().nextInt(100000); - BytesRef[] bytes = new BytesRef[len + random().nextInt(50)]; + random.nextBytes(commonPrefix); + final int len = random.nextInt(100000); + BytesRef[] bytes = new BytesRef[len + random.nextInt(50)]; for (int i = 0; i < len; ++i) { - byte[] b = new byte[commonPrefixLen + random().nextInt(maxLen)]; - random().nextBytes(b); + byte[] b = new byte[commonPrefixLen + random.nextInt(maxLen)]; + random.nextBytes(b); System.arraycopy(commonPrefix, 0, b, 0, commonPrefixLen); bytes[i] = new BytesRef(b); } @@ -124,27 +125,19 @@ private void testRandom(int commonPrefixLen, int maxLen) { } public void testRandom() { - for (int iter = 0; iter < 10; ++iter) { - testRandom(0, 10); - } + testRandom(0, 10); } public void testRandomWithLotsOfDuplicates() { - for (int iter = 0; iter < 10; ++iter) { - testRandom(0, 2); - } + testRandom(0, 2); } public void testRandomWithSharedPrefix() { - for (int iter = 0; iter < 10; ++iter) { - testRandom(TestUtil.nextInt(random(), 1, 30), 10); - } + testRandom(TestUtil.nextInt(random(), 1, 30), 10); } public void testRandomWithSharedPrefixAndLotsOfDuplicates() { - for (int iter = 0; iter < 10; ++iter) { - testRandom(TestUtil.nextInt(random(), 1, 30), 2); - } + testRandom(TestUtil.nextInt(random(), 1, 30), 2); } public void testRandom2() { diff --git a/lucene/core/src/test/org/apache/lucene/util/automaton/TestCompiledAutomaton.java b/lucene/core/src/test/org/apache/lucene/util/automaton/TestCompiledAutomaton.java index b4e23f6a2b97..5f336f76c612 100644 --- a/lucene/core/src/test/org/apache/lucene/util/automaton/TestCompiledAutomaton.java +++ b/lucene/core/src/test/org/apache/lucene/util/automaton/TestCompiledAutomaton.java @@ -105,7 +105,6 @@ public void testRandom() throws Exception { } private String randomString() { - // return _TestUtil.randomSimpleString(random); return TestUtil.randomRealisticUnicodeString(random()); } diff --git a/lucene/core/src/test/org/apache/lucene/util/bkd/TestMutablePointTreeReaderUtils.java b/lucene/core/src/test/org/apache/lucene/util/bkd/TestMutablePointTreeReaderUtils.java index 9dbe2ee210a8..0e25b582775f 100644 --- a/lucene/core/src/test/org/apache/lucene/util/bkd/TestMutablePointTreeReaderUtils.java +++ b/lucene/core/src/test/org/apache/lucene/util/bkd/TestMutablePointTreeReaderUtils.java @@ -16,6 +16,7 @@ */ package org.apache.lucene.util.bkd; +import com.carrotsearch.randomizedtesting.annotations.Repeat; import java.util.Arrays; import java.util.Comparator; import org.apache.lucene.codecs.MutablePointTree; @@ -26,17 +27,12 @@ import org.apache.lucene.util.BytesRef; public class TestMutablePointTreeReaderUtils extends LuceneTestCase { - public void testSort() { - for (int iter = 0; iter < 10; ++iter) { - doTestSort(false); - } + doTestSort(false); } public void testSortWithIncrementalDocId() { - for (int iter = 0; iter < 10; ++iter) { - doTestSort(true); - } + doTestSort(true); } private void doTestSort(boolean isDocIdIncremental) { @@ -79,9 +75,7 @@ public int compare(Point o1, Point o2) { } public void testSortByDim() { - for (int iter = 0; iter < 5; ++iter) { - doTestSortByDim(); - } + doTestSortByDim(); } private void doTestSortByDim() { @@ -131,10 +125,9 @@ private void doTestSortByDim() { } } + @Repeat(iterations = 5) public void testPartition() { - for (int iter = 0; iter < 5; ++iter) { - doTestPartition(); - } + doTestPartition(); } private void doTestPartition() { diff --git a/lucene/core/src/test/org/apache/lucene/util/compress/TestLowercaseAsciiCompression.java b/lucene/core/src/test/org/apache/lucene/util/compress/TestLowercaseAsciiCompression.java index bfc9d59a5229..be29ade703f6 100644 --- a/lucene/core/src/test/org/apache/lucene/util/compress/TestLowercaseAsciiCompression.java +++ b/lucene/core/src/test/org/apache/lucene/util/compress/TestLowercaseAsciiCompression.java @@ -80,23 +80,25 @@ public void testFarAwayExceptions() throws Exception { } public void testRandomAscii() throws IOException { - for (int iter = 0; iter < 1000; ++iter) { - int len = random().nextInt(1000); - byte[] bytes = new byte[len + random().nextInt(10)]; + var random = nonAssertingRandom(random()); + for (int iter = 0, max = atLeast(100); iter < max; ++iter) { + int len = random.nextInt(1000); + byte[] bytes = new byte[len + random.nextInt(10)]; for (int i = 0; i < bytes.length; ++i) { - bytes[i] = (byte) TestUtil.nextInt(random(), ' ', '~'); + bytes[i] = (byte) TestUtil.nextInt(random, ' ', '~'); } doTestCompress(bytes, len); } } public void testRandomCompressibleAscii() throws IOException { - for (int iter = 0; iter < 1000; ++iter) { - int len = TestUtil.nextInt(random(), 8, 1000); - byte[] bytes = new byte[len + random().nextInt(10)]; + var random = nonAssertingRandom(random()); + for (int iter = 0, max = atLeast(100); iter < max; ++iter) { + int len = TestUtil.nextInt(random, 8, 1000); + byte[] bytes = new byte[len + random.nextInt(10)]; for (int i = 0; i < bytes.length; ++i) { // only use always compressible bytes - int b = random().nextInt(32); + int b = random.nextInt(32); b = b | 0x20 | ((b & 0x20) << 1); b -= 1; bytes[i] = (byte) b; @@ -106,20 +108,21 @@ public void testRandomCompressibleAscii() throws IOException { } public void testRandomCompressibleAsciiWithExceptions() throws IOException { - for (int iter = 0; iter < 1000; ++iter) { - int len = TestUtil.nextInt(random(), 8, 1000); + var random = nonAssertingRandom(random()); + for (int iter = 0, max = atLeast(100); iter < max; ++iter) { + int len = TestUtil.nextInt(random, 8, 1000); int exceptions = 0; int maxExceptions = len >>> 5; - byte[] bytes = new byte[len + random().nextInt(10)]; + byte[] bytes = new byte[len + random.nextInt(10)]; for (int i = 0; i < bytes.length; ++i) { - if (exceptions == maxExceptions || random().nextInt(100) != 0) { - int b = random().nextInt(32); + if (exceptions == maxExceptions || random.nextInt(100) != 0) { + int b = random.nextInt(32); b = b | 0x20 | ((b & 0x20) << 1); b -= 1; bytes[i] = (byte) b; } else { exceptions++; - bytes[i] = (byte) random().nextInt(256); + bytes[i] = (byte) random.nextInt(256); } } assertTrue(doTestCompress(bytes, len)); @@ -127,10 +130,11 @@ public void testRandomCompressibleAsciiWithExceptions() throws IOException { } public void testRandom() throws IOException { + var random = nonAssertingRandom(random()); for (int iter = 0; iter < 1000; ++iter) { - int len = random().nextInt(1000); - byte[] bytes = new byte[len + random().nextInt(10)]; - random().nextBytes(bytes); + int len = random.nextInt(1000); + byte[] bytes = new byte[len + random.nextInt(10)]; + random.nextBytes(bytes); doTestCompress(bytes, len); } } diff --git a/lucene/core/src/test/org/apache/lucene/util/packed/TestPackedInts.java b/lucene/core/src/test/org/apache/lucene/util/packed/TestPackedInts.java index bdb10f2e6efe..ecdb830c2084 100644 --- a/lucene/core/src/test/org/apache/lucene/util/packed/TestPackedInts.java +++ b/lucene/core/src/test/org/apache/lucene/util/packed/TestPackedInts.java @@ -1225,20 +1225,21 @@ public void testBlockPackedReaderWriter() throws IOException { } public void testMonotonicBlockPackedReaderWriter() throws IOException { + var random = nonAssertingRandom(random()); + final int iters = atLeast(2); for (int iter = 0; iter < iters; ++iter) { - final int blockSize = 1 << TestUtil.nextInt(random(), 6, 18); - final int valueCount = random().nextInt(1 << 18); + final int blockSize = 1 << TestUtil.nextInt(random, 6, 18); + final int valueCount = random.nextInt(1 << 18); final long[] values = new long[valueCount]; if (valueCount > 0) { - values[0] = - random().nextBoolean() ? random().nextInt(10) : random().nextInt(Integer.MAX_VALUE); - int maxDelta = random().nextInt(64); + values[0] = random.nextBoolean() ? random.nextInt(10) : random.nextInt(Integer.MAX_VALUE); + int maxDelta = random.nextInt(64); for (int i = 1; i < valueCount; ++i) { - if (random().nextDouble() < 0.1d) { - maxDelta = random().nextInt(64); + if (random.nextDouble() < 0.1d) { + maxDelta = random.nextInt(64); } - values[i] = Math.max(0, values[i - 1] + TestUtil.nextInt(random(), -16, maxDelta)); + values[i] = Math.max(0, values[i - 1] + TestUtil.nextInt(random, -16, maxDelta)); } } diff --git a/lucene/sandbox/src/test/org/apache/lucene/sandbox/document/TestHalfFloatPoint.java b/lucene/sandbox/src/test/org/apache/lucene/sandbox/document/TestHalfFloatPoint.java index 4182af1692f1..95c13f98148d 100644 --- a/lucene/sandbox/src/test/org/apache/lucene/sandbox/document/TestHalfFloatPoint.java +++ b/lucene/sandbox/src/test/org/apache/lucene/sandbox/document/TestHalfFloatPoint.java @@ -92,15 +92,14 @@ public void testRounding() { values = ArrayUtil.copyOfSubArray(values, 0, o); int iters = atLeast(1000000); + var rnd = nonAssertingRandom(random()); for (int iter = 0; iter < iters; ++iter) { float f; - if (random().nextBoolean()) { - int floatBits = random().nextInt(); + if (rnd.nextBoolean()) { + int floatBits = rnd.nextInt(); f = Float.intBitsToFloat(floatBits); } else { - f = - (float) - ((2 * random().nextFloat() - 1) * Math.pow(2, TestUtil.nextInt(random(), -16, 16))); + f = (float) ((2 * rnd.nextFloat() - 1) * Math.pow(2, TestUtil.nextInt(rnd, -16, 16))); } float rounded = HalfFloatPoint.shortBitsToHalfFloat(HalfFloatPoint.halfFloatToShortBits(f)); if (Float.isFinite(f) == false) { diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/util/LuceneTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/tests/util/LuceneTestCase.java index d28a91cecf32..6a617f0a9fb5 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/tests/util/LuceneTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/tests/util/LuceneTestCase.java @@ -89,8 +89,10 @@ import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; import java.util.regex.Pattern; @@ -290,10 +292,20 @@ public abstract class LuceneTestCase extends Assert { public static final String SYSPROP_FAILFAST = "tests.failfast"; /** + * If specified, limits the number of method calls to each individual instance returned by {@link + * #random()}. + * * @see #randomSupplier */ public static final String SYSPROP_RANDOM_MAXCALLS = "tests.random.maxcalls"; + /** + * If specified, limits the number of calls {@link #random()} itself. + * + * @see #randomSupplier + */ + public static final String SYSPROP_RANDOM_MAXACQUIRES = "tests.random.maxacquires"; + /** Annotation for tests that should only be run during nightly builds. */ @Documented @Inherited @@ -695,6 +707,10 @@ static void setLiveIWCFlushMode(LiveIWCFlushMode flushMode) { private static final Supplier randomSupplier; + /** A counter of calls to {@link #random()} if {@link #SYSPROP_RANDOM_MAXACQUIRES} is defined. */ + @SuppressWarnings("NonFinalStaticField") + private static AtomicLong randomCalls = new AtomicLong(); + static { int maxCalls = Integer.parseInt(System.getProperty(SYSPROP_RANDOM_MAXCALLS, "0")); Supplier supplier = () -> RandomizedContext.current().getRandom(); @@ -702,6 +718,21 @@ static void setLiveIWCFlushMode(LiveIWCFlushMode flushMode) { var finalizedSupplier = supplier; supplier = () -> new MaxCallCountRandom(finalizedSupplier.get(), maxCalls); } + + int maxAquires = Integer.parseInt(System.getProperty(SYSPROP_RANDOM_MAXACQUIRES, "0")); + if (maxAquires > 0) { + var finalizedSupplier = supplier; + supplier = + () -> { + if (randomCalls.incrementAndGet() > maxAquires) { + throw new RuntimeException( + "Too many random() calls. Consider using LuceneTestCase.nonAssertingRandom for" + + " large loops or data generation."); + } + return finalizedSupplier.get(); + }; + } + randomSupplier = supplier; } @@ -712,6 +743,7 @@ static void setLiveIWCFlushMode(LiveIWCFlushMode flushMode) { /** For subclasses to override. Overrides must call {@code super.setUp()}. */ @Before public void setUp() throws Exception { + randomCalls.set(0); parentChainCallRule.setupCalled = true; } @@ -761,7 +793,7 @@ public void restoreIndexWriterMaxDocs() { * multiple invocations are present. See {@link #nonAssertingRandom(Random)}. */ public static Random random() { - return randomSupplier.get(); + return ThreadLocalRandom.current(); } /** diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/util/TestUtil.java b/lucene/test-framework/src/java/org/apache/lucene/tests/util/TestUtil.java index 073da0d3a5bc..07f8d096197f 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/tests/util/TestUtil.java +++ b/lucene/test-framework/src/java/org/apache/lucene/tests/util/TestUtil.java @@ -1695,6 +1695,8 @@ public static String randomAnalysisString(Random random, int maxLength, boolean } public static String randomSubString(Random random, int wordLength, boolean simple) { + random = LuceneTestCase.nonAssertingRandom(random); + if (wordLength == 0) { return ""; } From fd3763545a57d75542842f1b27297cadf9a5ad6c Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Fri, 10 Oct 2025 22:44:06 +0200 Subject: [PATCH 08/11] Tidy and correct a debugging check in LuceneTestCase. --- .../org/apache/lucene/store/BaseDataOutputTestCase.java | 1 + .../org/apache/lucene/store/TestByteBuffersDataInput.java | 6 +----- .../java/org/apache/lucene/tests/util/LuceneTestCase.java | 3 +-- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/lucene/core/src/test/org/apache/lucene/store/BaseDataOutputTestCase.java b/lucene/core/src/test/org/apache/lucene/store/BaseDataOutputTestCase.java index d56a817e2090..bb7483f32f18 100644 --- a/lucene/core/src/test/org/apache/lucene/store/BaseDataOutputTestCase.java +++ b/lucene/core/src/test/org/apache/lucene/store/BaseDataOutputTestCase.java @@ -58,6 +58,7 @@ public void testRandomizedWrites() throws IOException { protected static List> addRandomData( DataOutput dst, Random rnd, int maxAddCalls) throws IOException { try { + rnd = LuceneTestCase.nonAssertingRandom(rnd); List> reply = new ArrayList<>(); for (int i = 0; i < maxAddCalls; i++) { reply.add(RandomPicks.randomFrom(rnd, GENERATORS).apply(dst, rnd)); diff --git a/lucene/core/src/test/org/apache/lucene/store/TestByteBuffersDataInput.java b/lucene/core/src/test/org/apache/lucene/store/TestByteBuffersDataInput.java index 8ce5b4465f2e..d29b9a19092e 100644 --- a/lucene/core/src/test/org/apache/lucene/store/TestByteBuffersDataInput.java +++ b/lucene/core/src/test/org/apache/lucene/store/TestByteBuffersDataInput.java @@ -19,10 +19,8 @@ import static com.carrotsearch.randomizedtesting.RandomizedTest.randomBoolean; import static com.carrotsearch.randomizedtesting.RandomizedTest.randomBytesOfLength; import static com.carrotsearch.randomizedtesting.RandomizedTest.randomIntBetween; -import static com.carrotsearch.randomizedtesting.RandomizedTest.randomLong; import static com.carrotsearch.randomizedtesting.RandomizedTest.randomLongBetween; -import com.carrotsearch.randomizedtesting.Xoroshiro128PlusRandom; import com.carrotsearch.randomizedtesting.annotations.Timeout; import java.io.EOFException; import java.io.IOException; @@ -71,7 +69,6 @@ public void testSanity() throws IOException { public void testRandomReads() throws Exception { ByteBuffersDataOutput dst = new ByteBuffersDataOutput(); - long seed = randomLong(); int max = LuceneTestCase.TEST_NIGHTLY ? 1_000_000 : 100_000; List> reply = TestByteBuffersDataOutput.addRandomData(dst, nonAssertingRandom(random()), max); @@ -151,10 +148,9 @@ public void testSeekAndSkip() throws Exception { dst.writeBytes(prefix); } - long seed = randomLong(); int max = 1000; List> reply = - TestByteBuffersDataOutput.addRandomData(dst, new Xoroshiro128PlusRandom(seed), max); + TestByteBuffersDataOutput.addRandomData(dst, random(), max); ByteBuffersDataInput in = dst.toDataInput().slice(prefix.length, dst.size() - prefix.length); diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/util/LuceneTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/tests/util/LuceneTestCase.java index 6a617f0a9fb5..00177cb2300c 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/tests/util/LuceneTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/tests/util/LuceneTestCase.java @@ -89,7 +89,6 @@ import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; @@ -793,7 +792,7 @@ public void restoreIndexWriterMaxDocs() { * multiple invocations are present. See {@link #nonAssertingRandom(Random)}. */ public static Random random() { - return ThreadLocalRandom.current(); + return randomSupplier.get(); } /** From 2758341223795e51fcee7b64e5d9c16e49259bdb Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Sat, 11 Oct 2025 07:25:44 +0200 Subject: [PATCH 09/11] Final minor touches. --- .../compressing/AbstractTestCompressionMode.java | 3 +-- .../lucene/util/bkd/TestMutablePointTreeReaderUtils.java | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/compressing/AbstractTestCompressionMode.java b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/compressing/AbstractTestCompressionMode.java index 7bf8c528dde1..df639b3973f9 100644 --- a/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/compressing/AbstractTestCompressionMode.java +++ b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/compressing/AbstractTestCompressionMode.java @@ -16,7 +16,6 @@ */ package org.apache.lucene.backward_codecs.compressing; -import com.carrotsearch.randomizedtesting.Xoroshiro128PlusRandom; import com.carrotsearch.randomizedtesting.generators.RandomNumbers; import java.io.IOException; import java.util.Arrays; @@ -40,7 +39,7 @@ static byte[] randomArray(Random random) { } static byte[] randomArray(Random random, int length, int max) { - random = new Xoroshiro128PlusRandom(random.nextLong()); + random = nonAssertingRandom(random); final byte[] arr = new byte[length]; for (int i = 0; i < arr.length; ++i) { arr[i] = (byte) RandomNumbers.randomIntBetween(random, 0, max); diff --git a/lucene/core/src/test/org/apache/lucene/util/bkd/TestMutablePointTreeReaderUtils.java b/lucene/core/src/test/org/apache/lucene/util/bkd/TestMutablePointTreeReaderUtils.java index 0e25b582775f..9343b510b9be 100644 --- a/lucene/core/src/test/org/apache/lucene/util/bkd/TestMutablePointTreeReaderUtils.java +++ b/lucene/core/src/test/org/apache/lucene/util/bkd/TestMutablePointTreeReaderUtils.java @@ -16,7 +16,6 @@ */ package org.apache.lucene.util.bkd; -import com.carrotsearch.randomizedtesting.annotations.Repeat; import java.util.Arrays; import java.util.Comparator; import org.apache.lucene.codecs.MutablePointTree; @@ -125,7 +124,6 @@ private void doTestSortByDim() { } } - @Repeat(iterations = 5) public void testPartition() { doTestPartition(); } From 0c5c4052af3cc9067e96d7068db22333d9cd8d11 Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Sat, 11 Oct 2025 07:37:10 +0200 Subject: [PATCH 10/11] Changes entry. --- lucene/CHANGES.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index e2410fb39dff..a873ca5b7829 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -63,8 +63,6 @@ Improvements This avoids clashes with other ASM versions on classpath because it removes the dependency. (Uwe Schindler) - - * GITHUB#15002: Remove synchronized WeakHashMap from IndexReader. This was added to help prevent SIGSEGV with the old unsafe "mmap hack", which has been replaced by MemorySegments. (Uwe Schindler, Robert Muir) @@ -106,6 +104,9 @@ Changes in Runtime Behavior Build --------------------- +* GITHUB#15327: New low-level build options to detect abuse of LuceneTestCase.random(): + tests.random.maxacquires and tests.random.maxcalls (Dawid Weiss) + * GITHUB#15325: Run the tests with assertions disabled ~25% of the time #15325 (Dawid Weiss) * GITHUB#14804: Detect and ban wildcard imports in Java (Robert Muir, Dawid Weiss) From 1282a2bbd4562722704c94367a4a1dfdf5668e47 Mon Sep 17 00:00:00 2001 From: Dawid Weiss Date: Sat, 11 Oct 2025 07:38:09 +0200 Subject: [PATCH 11/11] Changes entry. --- lucene/CHANGES.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index a873ca5b7829..ddacafe9bdc6 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -105,9 +105,10 @@ Changes in Runtime Behavior Build --------------------- * GITHUB#15327: New low-level build options to detect abuse of LuceneTestCase.random(): - tests.random.maxacquires and tests.random.maxcalls (Dawid Weiss) + tests.random.maxacquires and tests.random.maxcalls (Robert Muir, Dawid Weiss) -* GITHUB#15325: Run the tests with assertions disabled ~25% of the time #15325 (Dawid Weiss) +* GITHUB#15325: Run the tests with assertions disabled ~25% of the time #15325 + (Robert Muir, Dawid Weiss) * GITHUB#14804: Detect and ban wildcard imports in Java (Robert Muir, Dawid Weiss)