This is an automated email from the ASF dual-hosted git repository.
xiangfu0 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git
The following commit(s) were added to refs/heads/master by this push:
new 12da4085328 [CI] Parallelize unit-test phase with fork-safe
port/temp-dir isolation (#19199)
12da4085328 is described below
commit 12da4085328ddba69fa309a39ab7fb1edf350235
Author: Xiang Fu <[email protected]>
AuthorDate: Tue Aug 11 15:33:40 2026 -0700
[CI] Parallelize unit-test phase with fork-safe port/temp-dir isolation
(#19199)
---
.../scripts/pr-tests/.pinot_tests_unit.sh | 59 +++++++++++++---
...elixExternalViewBasedQueryQuotaManagerTest.java | 15 +++-
pinot-common/pom.xml | 3 +-
.../org/apache/pinot/common/utils/ZkStarter.java | 37 +++++++++-
pinot-controller/pom.xml | 29 ++++++++
.../ControllerStarterDynamicEnvTest.java | 21 ++++--
.../controller/ControllerStarterStatelessTest.java | 16 +++--
.../pinot/controller/helix/ControllerTest.java | 32 +++++++--
.../controller/utils/SegmentMetadataMockUtils.java | 13 +++-
.../RealtimeProvisioningInput_dateTimeColumn.json | 2 +-
.../RealtimeProvisioningInput_timeColumn.json | 2 +-
.../core/accounting/QueryMonitorConfigTest.java | 15 ++--
.../data/manager/BaseTableDataManagerTest.java | 4 +-
.../core/geospatial/transform/GeoFunctionTest.java | 4 +-
.../function/BaseTransformFunctionTest.java | 3 +-
.../DistinctFromTransformFunctionTest.java | 26 +++++--
.../DictionaryBasedGroupKeyGeneratorTest.java | 4 +-
.../executor/QueryExecutorExceptionsTest.java | 4 +-
.../core/query/executor/QueryExecutorTest.java | 4 +-
.../pinot/core/startree/v2/BaseStarTreeV2Test.java | 4 +-
.../queries/BaseFSTBasedRegexpLikeQueriesTest.java | 4 +-
.../pinot/queries/BaseFunnelCountQueriesTest.java | 3 +-
.../pinot/queries/BaseMultiValueQueriesTest.java | 4 +-
.../queries/BaseMultiValueRawQueriesTest.java | 4 +-
.../pinot/queries/BaseSingleValueQueriesTest.java | 4 +-
.../queries/GapfillQueriesScalabilityTest.java | 4 +-
.../apache/pinot/queries/GapfillQueriesTest.java | 4 +-
.../apache/pinot/queries/HistogramQueriesTest.java | 4 +-
.../queries/JsonIngestionFromAvroQueriesTest.java | 4 +-
.../apache/pinot/queries/JsonMatchQueriesTest.java | 4 +-
.../JsonUnnestIngestionFromAvroQueriesTest.java | 4 +-
.../pinot/queries/MultiValueRawQueriesTest.java | 4 +-
.../pinot/queries/PercentileKLLQueriesTest.java | 4 +-
.../queries/PercentileTDigestQueriesTest.java | 4 +-
.../pinot/queries/StatisticalQueriesTest.java | 4 +-
.../pinot/queries/TextSearchQueriesTest.java | 79 ++++++++++++----------
.../kafka30/server/KafkaServerStartableTest.java | 11 +--
.../plugin/stream/pulsar/PulsarConsumerTest.java | 12 +++-
.../io/reader/impl/FixedBitIntReaderTest.java | 4 +-
.../invertedindex/LuceneMutableTextIndexTest.java | 73 ++++++++++++++++----
.../local/segment/creator/DictionariesTest.java | 6 +-
.../segment/creator/DictionaryOptimiserTest.java | 6 +-
.../index/forward/FixedBitMVForwardIndexTest.java | 4 +-
.../forward/FixedBitSVForwardIndexReaderTest.java | 4 +-
.../index/loader/SegmentPreProcessorTest.java | 10 ++-
.../FixedBitSVForwardIndexReaderV2Test.java | 4 +-
.../segment/store/SegmentLocalFSDirectoryTest.java | 6 +-
.../spi/memory/PinotDataBufferTestBase.java | 4 +-
.../apache/pinot/server/api/BaseResourceTest.java | 24 +++----
.../pinot/server/api/TablesResourceTest.java | 4 +-
pinot-spi/pom.xml | 3 +-
pom.xml | 75 ++++++++++++++++++--
52 files changed, 529 insertions(+), 156 deletions(-)
diff --git a/.github/workflows/scripts/pr-tests/.pinot_tests_unit.sh
b/.github/workflows/scripts/pr-tests/.pinot_tests_unit.sh
index ccac6353b30..4ba09637f94 100755
--- a/.github/workflows/scripts/pr-tests/.pinot_tests_unit.sh
+++ b/.github/workflows/scripts/pr-tests/.pinot_tests_unit.sh
@@ -26,11 +26,48 @@ ifconfig
netstat -i
# Unit Tests
-# - TEST_SET#1 runs install and test together so the module list must ensure
no additional modules were tested
-# due to the -am flag (include dependency modules)
-# - tests for pinot-plugins should not be ran multi-threaded
+# - Both test sets run plain `mvn test` (no install, no -am): the modules
were already built
+# and installed by .pinot_tests_build.sh, so only the modules listed here
are tested.
+#
+# Parallelism / memory:
+# - UNIT_TEST_FORK_COUNT (default 3) sets surefire forkCount so test
*classes* run in
+# separate parallel JVMs (reuseForks=false keeps one class per JVM). This
is
+# process-level isolation, not TestNG intra-JVM threading, so tests that
were unsafe
+# to run multi-threaded within a single JVM (e.g. pinot-plugins) are
unaffected.
+# Cross-fork resource collisions (ZK/controller ports, temp dirs) are
avoided by
+# offsetting per surefire.forkNumber; embedded Kafka clusters use
ephemeral ports.
+# This is the main lever for shortening the unit-test phase. 3 forks on
the 4-vCPU
+# runner keeps a core free for the Maven reactor / GC while test JVMs
spend much of
+# their time blocked on ZK/Helix/socket startup, so the extra fork still
pays off.
+# - UNIT_TEST_FORK_HEAP (default 2500m) caps per-fork heap so N forks fit in
the
+# runner's memory (N * heap + the mvn JVM must stay under the runner's
RAM).
+# - UNIT_TEST_RERUN_COUNT (default 0) retries a failing test before failing
the build. Left at 0
+# because the load-sensitive flaky tests parallel forks exposed are fixed
at the root cause
+# (SegmentPreProcessorTest mtime granularity, LuceneMutableTextIndexTest
NRT-refresh wait). It
+# remains overridable as an escape hatch if a new flake appears, but is
intentionally not a
+# standing default so real failures are never masked.
+UNIT_TEST_FORK_COUNT="${UNIT_TEST_FORK_COUNT:-3}"
+# 2500m/fork: 3 forks * 2500m + the 2g Maven JVM (~9.5g) stays well under the
runner's 16g.
+UNIT_TEST_FORK_HEAP="${UNIT_TEST_FORK_HEAP:-2500m}"
+UNIT_TEST_RERUN_COUNT="${UNIT_TEST_RERUN_COUNT:-0}"
+# Coverage adds ~30% to the test phase (JaCoCo agent per fork + aggregate
report). Keep it on by
+# default to preserve Codecov behavior; set RUN_CODECOVERAGE=false (e.g. on
PRs) to trade coverage
+# for a faster run.
+RUN_CODECOVERAGE="${RUN_CODECOVERAGE:-true}"
+# Fork-scope the JaCoCo exec file (jacoco-<forkNumber>.exec) so parallel forks
don't append to
+# one shared jacoco.exec and corrupt coverage. Only the unit lane sets this;
other lanes keep
+# the default empty suffix (target/jacoco.exec).
+FORK_OPTS="-Dunit.test.fork.count=${UNIT_TEST_FORK_COUNT}
-Dunit.test.fork.heap=${UNIT_TEST_FORK_HEAP}
-Dunit.test.rerun.count=${UNIT_TEST_RERUN_COUNT}
-Djacoco.exec.suffix=-\${surefire.forkNumber}"
+if [ "$RUN_CODECOVERAGE" == "true" ]; then
+ COVERAGE_PROFILE=",codecoverage"
+else
+ COVERAGE_PROFILE=""
+fi
if [ "$RUN_TEST_SET" == "1" ]; then
- mvn test \
+ # pinot-segment-local's tests run in set #2 to balance pinot-core's longer
test time in this
+ # shard against set #2's longer build. It remains built in set #1 as a
pinot-core dependency.
+ # No -am on this command, so only the listed modules test.
+ mvn test ${FORK_OPTS} \
-pl 'pinot-spi' \
-pl 'pinot-segment-spi' \
-pl 'pinot-common' \
@@ -38,10 +75,10 @@ if [ "$RUN_TEST_SET" == "1" ]; then
-pl 'pinot-core' \
-pl 'pinot-query-planner' \
-pl 'pinot-query-runtime' \
- -P github-actions,codecoverage,no-integration-tests || exit 1
+ -P github-actions,no-integration-tests${COVERAGE_PROFILE} || exit 1
fi
if [ "$RUN_TEST_SET" == "2" ]; then
- mvn test \
+ mvn test ${FORK_OPTS} \
-pl '!pinot-spi' \
-pl '!pinot-segment-spi' \
-pl '!pinot-common' \
@@ -49,7 +86,13 @@ if [ "$RUN_TEST_SET" == "2" ]; then
-pl '!pinot-query-planner' \
-pl '!pinot-query-runtime' \
-pl '!:pinot-yammer' \
- -P github-actions,codecoverage,no-integration-tests || exit 1
+ -P github-actions,no-integration-tests${COVERAGE_PROFILE} || exit 1
fi
-mvn jacoco:report-aggregate@report -P codecoverage || exit 1
+# Aggregate coverage across all per-fork exec files (jacoco-*.exec) written
under forkCount>1,
+# while still matching the single-fork jacoco.exec produced by non-parallel
runs. Skipped when
+# coverage is disabled.
+if [ "$RUN_CODECOVERAGE" == "true" ]; then
+ mvn jacoco:report-aggregate@report -P codecoverage \
+ -Djacoco.dataFileIncludes='**/target/jacoco-*.exec,**/target/jacoco.exec'
|| exit 1
+fi
diff --git
a/pinot-broker/src/test/java/org/apache/pinot/broker/queryquota/HelixExternalViewBasedQueryQuotaManagerTest.java
b/pinot-broker/src/test/java/org/apache/pinot/broker/queryquota/HelixExternalViewBasedQueryQuotaManagerTest.java
index e2efb05f45e..5ba6072161f 100644
---
a/pinot-broker/src/test/java/org/apache/pinot/broker/queryquota/HelixExternalViewBasedQueryQuotaManagerTest.java
+++
b/pinot-broker/src/test/java/org/apache/pinot/broker/queryquota/HelixExternalViewBasedQueryQuotaManagerTest.java
@@ -327,10 +327,10 @@ public class HelixExternalViewBasedQueryQuotaManagerTest {
Assert.assertEquals(_queryQuotaManager.getDatabaseRateLimiterMap().size(),
1);
Assert.assertEquals(_queryQuotaManager.getApplicationRateLimiterMap().size(),
1);
- runQueries(100, true, APP_NAME);
- runQueries(100, true, "otherApp");
+ assertApplicationRateLimitedInBurst(APP_NAME, 100);
+ assertApplicationRateLimitedInBurst("otherApp", 100);
runQueries(100, false, "someApp");
- runQueries(201, true, "someApp");
+ assertApplicationRateLimitedInBurst("someApp", 201);
Assert.assertEquals(_queryQuotaManager.getApplicationRateLimiterMap().size(),
3);
_queryQuotaManager.dropTableQueryQuota(OFFLINE_TABLE_NAME);
@@ -697,4 +697,13 @@ public class HelixExternalViewBasedQueryQuotaManagerTest {
Assert.assertTrue(failCount == 0, "Expected no failure with qps: " + qps
+ " and app :" + appName);
}
}
+
+ private void assertApplicationRateLimitedInBurst(String appName, int
numQueries) {
+ for (int i = 0; i < numQueries; i++) {
+ if (!_queryQuotaManager.acquireApplication(appName)) {
+ return;
+ }
+ }
+ Assert.fail("Expected application rate limiting for " + numQueries + "
queries and app: " + appName);
+ }
}
diff --git a/pinot-common/pom.xml b/pinot-common/pom.xml
index a6630836cba..a36aea1d936 100644
--- a/pinot-common/pom.xml
+++ b/pinot-common/pom.xml
@@ -59,7 +59,8 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
- <forkCount>1</forkCount>
+ <!-- Keep this module's historical fork reuse, but honor the root
parallel-fork knob. -->
+ <forkCount>${unit.test.fork.count}</forkCount>
<reuseForks>true</reuseForks>
<properties>
<property>
diff --git
a/pinot-common/src/main/java/org/apache/pinot/common/utils/ZkStarter.java
b/pinot-common/src/main/java/org/apache/pinot/common/utils/ZkStarter.java
index 84bc8fcd666..2672f862411 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/utils/ZkStarter.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/utils/ZkStarter.java
@@ -21,6 +21,7 @@ package org.apache.pinot.common.utils;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
+import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -42,6 +43,33 @@ public class ZkStarter {
public static final int DEFAULT_ZK_TEST_PORT = 2191;
private static final int DEFAULT_ZK_CLIENT_RETRIES = 10;
+ /// Per-fork offset applied to the default test port so that concurrent
surefire forks
+ /// (forkCount > 1, reuseForks=false) do not scan from the same base port
and collide.
+ ///
+ /// This is purely a test-harness hook: the offset is derived from the
`surefire.forkNumber`
+ /// system property, which surefire injects only inside a forked test JVM
(1-based, so it is 1
+ /// even at forkCount=1, and 1..N under parallel forks). In any production
process that property
+ /// is absent, so `forkNumber()` returns 0 and the no-arg {@link
#startLocalZkServer()} scans
+ /// from the historical {@link #DEFAULT_ZK_TEST_PORT}. Under tests each fork
scans from a distinct
+ /// base ({@code DEFAULT_ZK_TEST_PORT + forkNumber*1000}); the exact port is
still chosen by
+ /// findOpenPort and read back via {@code getZkUrl()}, so no caller depends
on the literal base.
+ /// The stride (1000) is large enough that a fork exhausting ports below the
next boundary
+ /// (findOpenPort scans upward) does not spill into the neighboring fork's
band.
+ ///
+ /// The offset is deliberately centralized on the no-arg entry point rather
than pushed into each
+ /// test: several tests across different modules call {@link
#startLocalZkServer()} directly, and
+ /// duplicating the fork math into each caller (or introducing a parallel
test-only start helper)
+ /// is more surface and more error-prone than one guarded, production-inert
read here.
+ private static final int FORK_PORT_OFFSET = forkNumber() * 1000;
+
+ private static int forkNumber() {
+ try {
+ return Integer.parseInt(System.getProperty("surefire.forkNumber", "0"));
+ } catch (NumberFormatException e) {
+ return 0;
+ }
+ }
+
public static class ZookeeperInstance {
private PublicZooKeeperServerMain _serverMain;
private String _dataDirPath;
@@ -135,9 +163,10 @@ public class ZkStarter {
}
}
- /// Starts an empty local Zk instance on the default port
+ /// Starts an empty local Zk instance on the default port (offset per
surefire fork so that
+ /// concurrent forks bind disjoint port ranges).
public static ZookeeperInstance startLocalZkServer() {
- return startLocalZkServer(NetUtils.findOpenPort(DEFAULT_ZK_TEST_PORT));
+ return startLocalZkServer(NetUtils.findOpenPort(DEFAULT_ZK_TEST_PORT +
FORK_PORT_OFFSET));
}
public static String getDefaultZkStr() {
@@ -147,8 +176,10 @@ public class ZkStarter {
/// Starts a local Zk instance with a generated empty data directory
/// @param port The port to listen on
public static ZookeeperInstance startLocalZkServer(final int port) {
+ // Use a random UUID rather than a timestamp so that concurrent
forks/threads never share a
+ // ZK data directory (System.currentTimeMillis() collides when two
instances start in the same ms).
return startLocalZkServer(port,
- org.apache.commons.io.FileUtils.getTempDirectoryPath() +
File.separator + "test-" + System.currentTimeMillis());
+ org.apache.commons.io.FileUtils.getTempDirectoryPath() +
File.separator + "test-" + UUID.randomUUID());
}
/// Starts a local Zk instance
diff --git a/pinot-controller/pom.xml b/pinot-controller/pom.xml
index 3fa8183c99b..d89cf983459 100644
--- a/pinot-controller/pom.xml
+++ b/pinot-controller/pom.xml
@@ -172,12 +172,41 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
+ <!-- The stateful and stateless TestNG suites run in separate forks
but Surefire names
+ both reports TEST-TestSuite.xml. Keep their reports in
fork-specific subdirectories
+ so one suite cannot overwrite the other. -->
+
<reportsDirectory>${project.build.directory}/surefire-reports/$${surefire.forkNumber}</reportsDirectory>
+ <!-- Surefire collapses repeated TestNG invocations onto one
class/method key when it
+ computes the XML suite count. Use TestNG's per-class JUnit
reporter for this module;
+ it reports every invocation and does not write the shared HTML
assets. -->
+ <disableXmlReport>true</disableXmlReport>
+ <properties combine.children="append">
+ <property>
+ <name>reporter</name>
+ <value>org.testng.reporters.JUnitReportReporter</value>
+ </property>
+ </properties>
<suiteXmlFiles>
<suiteXmlFile>testng-statefull.xml</suiteXmlFile>
<suiteXmlFile>testng-stateless.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-report-plugin</artifactId>
+ <version>${surefire.version}</version>
+ <configuration>
+ <!-- CI uses three possible fork indices, while Controller has only
two TestNG suite test
+ sets, so at most two directories are populated. List all three;
the report plugin
+ ignores missing directories. -->
+ <reportsDirectories>
+
<reportsDirectory>${project.build.directory}/surefire-reports/1/junitreports</reportsDirectory>
+
<reportsDirectory>${project.build.directory}/surefire-reports/2/junitreports</reportsDirectory>
+
<reportsDirectory>${project.build.directory}/surefire-reports/3/junitreports</reportsDirectory>
+ </reportsDirectories>
+ </configuration>
+ </plugin>
</plugins>
</build>
diff --git
a/pinot-controller/src/test/java/org/apache/pinot/controller/ControllerStarterDynamicEnvTest.java
b/pinot-controller/src/test/java/org/apache/pinot/controller/ControllerStarterDynamicEnvTest.java
index d81b380a7f7..7c876623485 100644
---
a/pinot-controller/src/test/java/org/apache/pinot/controller/ControllerStarterDynamicEnvTest.java
+++
b/pinot-controller/src/test/java/org/apache/pinot/controller/ControllerStarterDynamicEnvTest.java
@@ -43,6 +43,7 @@ import static org.testng.Assert.*;
/// This class tests env variables when starting controller from configs
public class ControllerStarterDynamicEnvTest extends ControllerTest {
private final Map<String, Object> _configOverride = new HashMap<>();
+ private int _controllerPortOverride;
@Override
protected void overrideControllerConf(Map<String, Object> properties) {
@@ -53,10 +54,11 @@ public class ControllerStarterDynamicEnvTest extends
ControllerTest {
@Test
public void testNoVariable()
throws Exception {
+ int controllerPort = findControllerPortInForkRange();
_configOverride.clear();
_configOverride.put(CONTROLLER_HOST, "myHost");
_configOverride.put(CONFIG_OF_INSTANCE_ID, "Controller_myInstance");
- _configOverride.put(CONTROLLER_PORT, 1234);
+ _configOverride.put(CONTROLLER_PORT, controllerPort);
startZk();
this.startController();
@@ -66,7 +68,7 @@ public class ControllerStarterDynamicEnvTest extends
ControllerTest {
InstanceConfig instanceConfig =
HelixHelper.getInstanceConfig(_helixManager, instanceId);
assertEquals(instanceConfig.getInstanceName(), instanceId);
assertEquals(instanceConfig.getHostName(), "myHost");
- assertEquals(instanceConfig.getPort(), "1234");
+ assertEquals(instanceConfig.getPort(), Integer.toString(controllerPort));
assertEquals(instanceConfig.getTags(), Set.of(CONTROLLER_INSTANCE));
stopController();
@@ -76,11 +78,12 @@ public class ControllerStarterDynamicEnvTest extends
ControllerTest {
@Test
public void testOneVariable()
throws Exception {
+ int controllerPort = findControllerPortInForkRange();
_configOverride.clear();
_configOverride.put("dynamic.env.config", "controller.host");
_configOverride.put(CONTROLLER_HOST, "HOST");
_configOverride.put(CONFIG_OF_INSTANCE_ID, "Controller_myInstance");
- _configOverride.put(CONTROLLER_PORT, 1234);
+ _configOverride.put(CONTROLLER_PORT, controllerPort);
startZk();
this.startController();
@@ -90,7 +93,7 @@ public class ControllerStarterDynamicEnvTest extends
ControllerTest {
InstanceConfig instanceConfig =
HelixHelper.getInstanceConfig(_helixManager, instanceId);
assertEquals(instanceConfig.getInstanceName(), instanceId);
assertEquals(instanceConfig.getHostName(), "myHost");
- assertEquals(instanceConfig.getPort(), "1234");
+ assertEquals(instanceConfig.getPort(), Integer.toString(controllerPort));
assertEquals(instanceConfig.getTags(), Set.of(CONTROLLER_INSTANCE));
stopController();
@@ -100,6 +103,7 @@ public class ControllerStarterDynamicEnvTest extends
ControllerTest {
@Test
public void testMultipleVariables()
throws Exception {
+ int controllerPort = findControllerPortInForkRange();
_configOverride.clear();
_configOverride.put("dynamic.env.config",
"controller.host,controller.port");
_configOverride.put(CONTROLLER_HOST, "HOST");
@@ -114,7 +118,7 @@ public class ControllerStarterDynamicEnvTest extends
ControllerTest {
InstanceConfig instanceConfig =
HelixHelper.getInstanceConfig(_helixManager, instanceId);
assertEquals(instanceConfig.getInstanceName(), instanceId);
assertEquals(instanceConfig.getHostName(), "myHost");
- assertEquals(instanceConfig.getPort(), "1234");
+ assertEquals(instanceConfig.getPort(), Integer.toString(controllerPort));
assertEquals(instanceConfig.getTags(), Set.of(CONTROLLER_INSTANCE));
stopController();
@@ -150,7 +154,7 @@ public class ControllerStarterDynamicEnvTest extends
ControllerTest {
throws Exception {
Map<String, String> envVariables = new HashMap<>();
envVariables.put("HOST", "myHost");
- envVariables.put("PORT", "1234");
+ envVariables.put("PORT", Integer.toString(_controllerPortOverride));
_controllerStarter = createControllerStarter();
_controllerStarter.init(new PinotConfiguration(properties, envVariables));
_controllerStarter.start();
@@ -184,4 +188,9 @@ public class ControllerStarterDynamicEnvTest extends
ControllerTest {
}
assertEquals(System.getProperty("user.timezone"), "UTC");
}
+
+ private int findControllerPortInForkRange() {
+ _controllerPortOverride = NetUtils.findOpenPort(_nextControllerPort);
+ return _controllerPortOverride;
+ }
}
diff --git
a/pinot-controller/src/test/java/org/apache/pinot/controller/ControllerStarterStatelessTest.java
b/pinot-controller/src/test/java/org/apache/pinot/controller/ControllerStarterStatelessTest.java
index 8ce575e0389..9b5c837aa74 100644
---
a/pinot-controller/src/test/java/org/apache/pinot/controller/ControllerStarterStatelessTest.java
+++
b/pinot-controller/src/test/java/org/apache/pinot/controller/ControllerStarterStatelessTest.java
@@ -24,6 +24,7 @@ import java.util.Set;
import org.apache.helix.model.InstanceConfig;
import org.apache.pinot.common.utils.helix.HelixHelper;
import org.apache.pinot.controller.helix.ControllerTest;
+import org.apache.pinot.spi.utils.NetUtils;
import org.testng.annotations.Test;
import static org.apache.pinot.controller.ControllerConf.CONTROLLER_HOST;
@@ -46,10 +47,11 @@ public class ControllerStarterStatelessTest extends
ControllerTest {
@Test
public void testHostnamePortOverride()
throws Exception {
+ int controllerPort = NetUtils.findOpenPort(_nextControllerPort);
_configOverride.clear();
_configOverride.put(CONFIG_OF_INSTANCE_ID, "Controller_myInstance");
_configOverride.put(CONTROLLER_HOST, "myHost");
- _configOverride.put(CONTROLLER_PORT, 1234);
+ _configOverride.put(CONTROLLER_PORT, controllerPort);
startZk();
startController();
@@ -59,7 +61,7 @@ public class ControllerStarterStatelessTest extends
ControllerTest {
InstanceConfig instanceConfig =
HelixHelper.getInstanceConfig(_helixManager, instanceId);
assertEquals(instanceConfig.getInstanceName(), instanceId);
assertEquals(instanceConfig.getHostName(), "myHost");
- assertEquals(instanceConfig.getPort(), "1234");
+ assertEquals(instanceConfig.getPort(), Integer.toString(controllerPort));
assertEquals(instanceConfig.getTags(), Set.of(CONTROLLER_INSTANCE));
stopController();
@@ -69,10 +71,11 @@ public class ControllerStarterStatelessTest extends
ControllerTest {
@Test
public void testInvalidInstanceId()
throws Exception {
+ int controllerPort = NetUtils.findOpenPort(_nextControllerPort);
_configOverride.clear();
_configOverride.put(CONFIG_OF_INSTANCE_ID, "myInstance");
_configOverride.put(CONTROLLER_HOST, "myHost");
- _configOverride.put(CONTROLLER_PORT, 1234);
+ _configOverride.put(CONTROLLER_PORT, controllerPort);
startZk();
try {
@@ -88,19 +91,20 @@ public class ControllerStarterStatelessTest extends
ControllerTest {
@Test
public void testDefaultInstanceId()
throws Exception {
+ int controllerPort = NetUtils.findOpenPort(_nextControllerPort);
_configOverride.clear();
_configOverride.put(CONTROLLER_HOST, "myHost");
- _configOverride.put(CONTROLLER_PORT, 1234);
+ _configOverride.put(CONTROLLER_PORT, controllerPort);
startZk();
startController();
String instanceId = _controllerStarter.getInstanceId();
- assertEquals(instanceId, "Controller_myHost_1234");
+ assertEquals(instanceId, "Controller_myHost_" + controllerPort);
InstanceConfig instanceConfig =
HelixHelper.getInstanceConfig(_helixManager, instanceId);
assertEquals(instanceConfig.getInstanceName(), instanceId);
assertEquals(instanceConfig.getHostName(), "myHost");
- assertEquals(instanceConfig.getPort(), "1234");
+ assertEquals(instanceConfig.getPort(), Integer.toString(controllerPort));
assertEquals(instanceConfig.getTags(), Set.of(CONTROLLER_INSTANCE));
stopController();
diff --git
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/ControllerTest.java
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/ControllerTest.java
index 9c4317d32b2..6a45cf081bd 100644
---
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/ControllerTest.java
+++
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/ControllerTest.java
@@ -29,6 +29,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
@@ -121,18 +122,39 @@ public class ControllerTest {
private static final Logger LOGGER =
LoggerFactory.getLogger(ControllerTest.class);
public static final String LOCAL_HOST = "localhost";
+ // Use a random UUID rather than a timestamp so concurrent forks never share
a data/temp dir
+ // (System.currentTimeMillis() collides when two forks initialize in the
same millisecond).
public static final String DEFAULT_DATA_DIR = new
File(FileUtils.getTempDirectoryPath(),
- "test-controller-data-dir" +
System.currentTimeMillis()).getAbsolutePath();
+ "test-controller-data-dir" + UUID.randomUUID()).getAbsolutePath();
public static final String DEFAULT_LOCAL_TEMP_DIR = new
File(FileUtils.getTempDirectoryPath(),
- "test-controller-local-temp-dir" +
System.currentTimeMillis()).getAbsolutePath();
+ "test-controller-local-temp-dir" + UUID.randomUUID()).getAbsolutePath();
public static final String BROKER_INSTANCE_ID_PREFIX = "Broker_localhost_";
public static final String SERVER_INSTANCE_ID_PREFIX = "Server_localhost_";
public static final String MINION_INSTANCE_ID_PREFIX = "Minion_localhost_";
public static final String TEST_PORT_BASE_PROPERTY = "pinot.test.port.base";
public static final String TEST_ZK_PORT_BASE_PROPERTY =
"pinot.test.zk.port.base";
- private static final AtomicInteger NEXT_CONFIGURED_ZK_PORT =
- new AtomicInteger(Integer.getInteger(TEST_ZK_PORT_BASE_PROPERTY, 0));
+ /// Per-fork port offset so that concurrent surefire forks (forkCount > 1,
reuseForks=false)
+ /// allocate disjoint port ranges. surefire injects a 1-based
`surefire.forkNumber` into each
+ /// fork (so it is 1 even at forkCount=1, 1..N under parallel forks); it is
0 only outside a
+ /// surefire fork. The stride (5000) comfortably exceeds the ~3000-port span
one ControllerTest
+ /// instance uses. Ports are still probed with findOpenPort, so the offset
only separates the
+ /// per-fork starting points; no test depends on a literal base port.
+ private static final int FORK_PORT_OFFSET = forkNumber() * 5000;
+
+ private static int forkNumber() {
+ try {
+ return Integer.parseInt(System.getProperty("surefire.forkNumber", "0"));
+ } catch (NumberFormatException e) {
+ return 0;
+ }
+ }
+
+ // Offset only when an explicit ZK port base is configured; a base of 0
means "let ZkStarter
+ // pick the port" (which is already fork-aware), so it must stay 0 for
forked runs too.
+ private static final int CONFIGURED_ZK_PORT_BASE =
Integer.getInteger(TEST_ZK_PORT_BASE_PROPERTY, 0);
+ private static final AtomicInteger NEXT_CONFIGURED_ZK_PORT = new
AtomicInteger(
+ CONFIGURED_ZK_PORT_BASE > 0 ? CONFIGURED_ZK_PORT_BASE + FORK_PORT_OFFSET
: 0);
// Default ControllerTest instance settings
public static final int DEFAULT_MIN_NUM_REPLICAS = 2;
@@ -150,7 +172,7 @@ public class ControllerTest {
protected final String _clusterName = getClass().getSimpleName();
protected final List<HelixManager> _fakeInstanceHelixManagers = new
ArrayList<>();
- protected int _nextControllerPort =
Integer.getInteger(TEST_PORT_BASE_PROPERTY, 20000);
+ protected int _nextControllerPort =
Integer.getInteger(TEST_PORT_BASE_PROPERTY, 20000) + FORK_PORT_OFFSET;
protected int _nextBrokerPort = _nextControllerPort + 1000;
protected int _nextBrokerGrpcPort = _nextBrokerPort + 500;
protected int _nextBrokerQueryRunnerPort = _nextBrokerGrpcPort + 250;
diff --git
a/pinot-controller/src/test/java/org/apache/pinot/controller/utils/SegmentMetadataMockUtils.java
b/pinot-controller/src/test/java/org/apache/pinot/controller/utils/SegmentMetadataMockUtils.java
index 041fbbf3c49..532b5dc2b0f 100644
---
a/pinot-controller/src/test/java/org/apache/pinot/controller/utils/SegmentMetadataMockUtils.java
+++
b/pinot-controller/src/test/java/org/apache/pinot/controller/utils/SegmentMetadataMockUtils.java
@@ -21,6 +21,7 @@ package org.apache.pinot.controller.utils;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
import org.apache.pinot.common.metadata.segment.SegmentZKMetadata;
import org.apache.pinot.common.partition.function.MurmurPartitionFunction;
import org.apache.pinot.segment.spi.ColumnMetadata;
@@ -34,6 +35,8 @@ import static org.mockito.Mockito.when;
public class SegmentMetadataMockUtils {
+ private static final AtomicLong UNIQUE_ID_GENERATOR = new AtomicLong();
+
private SegmentMetadataMockUtils() {
}
@@ -60,22 +63,26 @@ public class SegmentMetadataMockUtils {
}
public static SegmentMetadata mockSegmentMetadata(String tableName) {
- String uniqueNumericString = Long.toString(System.nanoTime());
+ String uniqueNumericString = nextUniqueNumericString();
return mockSegmentMetadata(tableName, tableName + uniqueNumericString,
100, uniqueNumericString);
}
public static SegmentMetadata mockSegmentMetadata(String tableName, long
startTime,
long endTime, TimeUnit timeUnit) {
- String uniqueNumericString = Long.toString(System.nanoTime());
+ String uniqueNumericString = nextUniqueNumericString();
return mockSegmentMetadata(tableName, tableName + uniqueNumericString, 100,
uniqueNumericString, startTime, endTime, timeUnit);
}
public static SegmentMetadata mockSegmentMetadata(String tableName, String
segmentName) {
- String uniqueNumericString = Long.toString(System.nanoTime());
+ String uniqueNumericString = nextUniqueNumericString();
return mockSegmentMetadata(tableName, segmentName, 100,
uniqueNumericString);
}
+ private static String nextUniqueNumericString() {
+ return Long.toString(UNIQUE_ID_GENERATOR.incrementAndGet());
+ }
+
public static SegmentZKMetadata mockSegmentZKMetadata(String segmentName,
long numTotalDocs) {
SegmentZKMetadata segmentZKMetadata =
Mockito.mock(SegmentZKMetadata.class);
Mockito.when(segmentZKMetadata.getSegmentName()).thenReturn(segmentName);
diff --git
a/pinot-controller/src/test/resources/recommenderInput/RealtimeProvisioningInput_dateTimeColumn.json
b/pinot-controller/src/test/resources/recommenderInput/RealtimeProvisioningInput_dateTimeColumn.json
index a068eb371ee..836d79b1e26 100644
---
a/pinot-controller/src/test/resources/recommenderInput/RealtimeProvisioningInput_dateTimeColumn.json
+++
b/pinot-controller/src/test/resources/recommenderInput/RealtimeProvisioningInput_dateTimeColumn.json
@@ -134,7 +134,7 @@
"select f from tableName where t between 1 and 1000": 2
},
"qps": 150,
- "numMessagesPerSecInKafkaTopic":1000,
+ "numMessagesPerSecInKafkaTopic":100,
"numRecordsPerPush":10000000,
"tableType": "HYBRID",
"latencySLA": 500,
diff --git
a/pinot-controller/src/test/resources/recommenderInput/RealtimeProvisioningInput_timeColumn.json
b/pinot-controller/src/test/resources/recommenderInput/RealtimeProvisioningInput_timeColumn.json
index e05a2f50ac6..3d82e248900 100644
---
a/pinot-controller/src/test/resources/recommenderInput/RealtimeProvisioningInput_timeColumn.json
+++
b/pinot-controller/src/test/resources/recommenderInput/RealtimeProvisioningInput_timeColumn.json
@@ -134,7 +134,7 @@
"select f from tableName where t between 1 and 1000": 2
},
"qps": 150,
- "numMessagesPerSecInKafkaTopic":1000,
+ "numMessagesPerSecInKafkaTopic":100,
"tableType": "HYBRID",
"latencySLA": 500,
"rulesToExecute": {
diff --git
a/pinot-core/src/test/java/org/apache/pinot/core/accounting/QueryMonitorConfigTest.java
b/pinot-core/src/test/java/org/apache/pinot/core/accounting/QueryMonitorConfigTest.java
index 85f9f02f165..fcb7fb1021c 100644
---
a/pinot-core/src/test/java/org/apache/pinot/core/accounting/QueryMonitorConfigTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/core/accounting/QueryMonitorConfigTest.java
@@ -135,12 +135,13 @@ public class QueryMonitorConfigTest {
new PerQueryCPUMemResourceUsageAccountant(new PinotConfiguration(),
"test", InstanceType.SERVER);
assertEquals(accountant.getQueryMonitorConfig().getPanicLevel(),
- Accounting.DEFAULT_PANIC_LEVEL_HEAP_USAGE_RATIO *
accountant.getQueryMonitorConfig().getMaxHeapSize());
+ (long) ((double) Accounting.DEFAULT_PANIC_LEVEL_HEAP_USAGE_RATIO
+ * accountant.getQueryMonitorConfig().getMaxHeapSize()));
accountant.getWatcherTask()
.onChange(Set.of(Accounting.COMMON_PREFIX + "." +
Accounting.Keys.PANIC_LEVEL_HEAP_USAGE_RATIO),
CLUSTER_CONFIGS);
assertEquals(accountant.getQueryMonitorConfig().getPanicLevel(),
- EXPECTED_PANIC_LEVEL *
accountant.getQueryMonitorConfig().getMaxHeapSize());
+ (long) (EXPECTED_PANIC_LEVEL *
accountant.getQueryMonitorConfig().getMaxHeapSize()));
}
@Test
@@ -149,12 +150,13 @@ public class QueryMonitorConfigTest {
new PerQueryCPUMemResourceUsageAccountant(new PinotConfiguration(),
"test", InstanceType.SERVER);
assertEquals(accountant.getQueryMonitorConfig().getCriticalLevel(),
- Accounting.DEFAULT_CRITICAL_LEVEL_HEAP_USAGE_RATIO *
accountant.getQueryMonitorConfig().getMaxHeapSize());
+ (long) ((double) Accounting.DEFAULT_CRITICAL_LEVEL_HEAP_USAGE_RATIO
+ * accountant.getQueryMonitorConfig().getMaxHeapSize()));
accountant.getWatcherTask()
.onChange(Set.of(Accounting.COMMON_PREFIX + "." +
Accounting.Keys.CRITICAL_LEVEL_HEAP_USAGE_RATIO),
CLUSTER_CONFIGS);
assertEquals(accountant.getQueryMonitorConfig().getCriticalLevel(),
- EXPECTED_CRITICAL_LEVEL *
accountant.getQueryMonitorConfig().getMaxHeapSize());
+ (long) (EXPECTED_CRITICAL_LEVEL *
accountant.getQueryMonitorConfig().getMaxHeapSize()));
}
@Test
@@ -163,12 +165,13 @@ public class QueryMonitorConfigTest {
new PerQueryCPUMemResourceUsageAccountant(new PinotConfiguration(),
"test", InstanceType.SERVER);
assertEquals(accountant.getQueryMonitorConfig().getAlarmingLevel(),
- Accounting.DEFAULT_ALARMING_LEVEL_HEAP_USAGE_RATIO *
accountant.getQueryMonitorConfig().getMaxHeapSize());
+ (long) ((double) Accounting.DEFAULT_ALARMING_LEVEL_HEAP_USAGE_RATIO
+ * accountant.getQueryMonitorConfig().getMaxHeapSize()));
accountant.getWatcherTask()
.onChange(Set.of(Accounting.COMMON_PREFIX + "." +
Accounting.Keys.ALARMING_LEVEL_HEAP_USAGE_RATIO),
CLUSTER_CONFIGS);
assertEquals(accountant.getQueryMonitorConfig().getAlarmingLevel(),
- EXPECTED_ALARMING_LEVEL *
accountant.getQueryMonitorConfig().getMaxHeapSize());
+ (long) (EXPECTED_ALARMING_LEVEL *
accountant.getQueryMonitorConfig().getMaxHeapSize()));
}
@Test
diff --git
a/pinot-core/src/test/java/org/apache/pinot/core/data/manager/BaseTableDataManagerTest.java
b/pinot-core/src/test/java/org/apache/pinot/core/data/manager/BaseTableDataManagerTest.java
index d2b6aad8d30..5a5b7de8bdc 100644
---
a/pinot-core/src/test/java/org/apache/pinot/core/data/manager/BaseTableDataManagerTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/core/data/manager/BaseTableDataManagerTest.java
@@ -28,6 +28,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -92,7 +93,8 @@ import static org.testng.Assert.*;
public class BaseTableDataManagerTest {
- private static final File TEMP_DIR = new File(FileUtils.getTempDirectory(),
"BaseTableDataManagerTest");
+ private static final File TEMP_DIR =
+ new File(FileUtils.getTempDirectory(), "BaseTableDataManagerTest-" +
UUID.randomUUID());
private static final String RAW_TABLE_NAME = "testTable";
private static final String OFFLINE_TABLE_NAME =
TableNameBuilder.OFFLINE.tableNameWithType(RAW_TABLE_NAME);
private static final File TABLE_DATA_DIR = new File(TEMP_DIR,
OFFLINE_TABLE_NAME);
diff --git
a/pinot-core/src/test/java/org/apache/pinot/core/geospatial/transform/GeoFunctionTest.java
b/pinot-core/src/test/java/org/apache/pinot/core/geospatial/transform/GeoFunctionTest.java
index b00d3d94f2b..b4f703bf6c5 100644
---
a/pinot-core/src/test/java/org/apache/pinot/core/geospatial/transform/GeoFunctionTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/core/geospatial/transform/GeoFunctionTest.java
@@ -25,6 +25,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.UUID;
import java.util.function.BiConsumer;
import org.apache.commons.io.FileUtils;
import org.apache.pinot.common.request.context.ExpressionContext;
@@ -61,7 +62,8 @@ public abstract class GeoFunctionTest {
private static final String RAW_TABLE_NAME = "testTable";
private static final String SEGMENT_NAME = "testSegment";
- private static final String INDEX_DIR_PATH =
FileUtils.getTempDirectoryPath() + File.separator + SEGMENT_NAME;
+ private static final String INDEX_DIR_PATH =
+ FileUtils.getTempDirectoryPath() + File.separator + SEGMENT_NAME + "-" +
UUID.randomUUID();
private static final double DELTA = 0.00001;
diff --git
a/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/BaseTransformFunctionTest.java
b/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/BaseTransformFunctionTest.java
index ccc4804e0ac..fda7bc4c8bb 100644
---
a/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/BaseTransformFunctionTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/BaseTransformFunctionTest.java
@@ -123,7 +123,8 @@ public abstract class BaseTransformFunctionTest {
/// index sitting on the column doesn't perturb the predicate evaluator's
path selection.
protected static final String INT_MV_DICT_RAW_INV_COLUMN = "intMVDictRawInv";
private static final String SEGMENT_NAME = "testSegment";
- private static final String INDEX_DIR_PATH =
FileUtils.getTempDirectoryPath() + File.separator + SEGMENT_NAME;
+ private static final String INDEX_DIR_PATH =
+ FileUtils.getTempDirectoryPath() + File.separator + SEGMENT_NAME + "-" +
UUID.randomUUID();
private static final Random RANDOM = new Random();
protected final int[] _intSVValues = new int[NUM_ROWS];
protected final long[] _longSVValues = new long[NUM_ROWS];
diff --git
a/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/DistinctFromTransformFunctionTest.java
b/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/DistinctFromTransformFunctionTest.java
index 26cd4f21587..6536fd5f8b5 100644
---
a/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/DistinctFromTransformFunctionTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/DistinctFromTransformFunctionTest.java
@@ -25,6 +25,7 @@ import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.pinot.common.request.context.ExpressionContext;
import org.apache.pinot.common.request.context.RequestContextUtils;
@@ -48,12 +49,14 @@ import org.apache.pinot.spi.data.readers.GenericRow;
import org.apache.pinot.spi.utils.ReadMode;
import org.apache.pinot.spi.utils.builder.TableConfigBuilder;
import org.testng.Assert;
+import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public abstract class DistinctFromTransformFunctionTest {
private static final String SEGMENT_NAME = "testSegment";
+ private static final String INDEX_DIR_SUFFIX = "-" + UUID.randomUUID();
private static final String INT_SV_COLUMN = "intSV";
private static final String INT_SV_NULL_COLUMN = "intSV2";
private static final Random RANDOM = new Random();
@@ -65,6 +68,7 @@ public abstract class DistinctFromTransformFunctionTest {
private final int[] _intSVValues = new int[NUM_ROWS];
private Map<String, DataSource> _dataSourceMap;
+ private IndexSegment _indexSegment;
private ProjectionBlock _projectionBlock;
DistinctFromTransformFunctionTest(boolean isDistinctFrom) {
@@ -73,10 +77,10 @@ public abstract class DistinctFromTransformFunctionTest {
}
private static String getIndexDirPath(String segmentName) {
- return FileUtils.getTempDirectoryPath() + File.separator + segmentName;
+ return FileUtils.getTempDirectoryPath() + File.separator + segmentName +
INDEX_DIR_SUFFIX;
}
- private static Map<String, DataSource> getDataSourceMap(Schema schema,
List<GenericRow> rows, String segmentName)
+ private Map<String, DataSource> getDataSourceMap(Schema schema,
List<GenericRow> rows, String segmentName)
throws Exception {
TableConfig tableConfig =
new
TableConfigBuilder(TableType.OFFLINE).setTableName(segmentName).setNullHandlingEnabled(true).build();
@@ -86,12 +90,11 @@ public abstract class DistinctFromTransformFunctionTest {
SegmentIndexCreationDriverImpl driver = new
SegmentIndexCreationDriverImpl();
driver.init(config, new GenericRowRecordReader(rows));
driver.build();
- IndexSegment indexSegment =
- ImmutableSegmentLoader.load(new File(getIndexDirPath(segmentName),
segmentName), ReadMode.heap);
- Set<String> columnNames = indexSegment.getPhysicalColumnNames();
+ _indexSegment = ImmutableSegmentLoader.load(new
File(getIndexDirPath(segmentName), segmentName), ReadMode.heap);
+ Set<String> columnNames = _indexSegment.getPhysicalColumnNames();
Map<String, DataSource> enableNullDataSourceMap = new
HashMap<>(columnNames.size());
for (String columnName : columnNames) {
- enableNullDataSourceMap.put(columnName,
indexSegment.getDataSource(columnName));
+ enableNullDataSourceMap.put(columnName,
_indexSegment.getDataSource(columnName));
}
return enableNullDataSourceMap;
}
@@ -143,6 +146,17 @@ public abstract class DistinctFromTransformFunctionTest {
_projectionBlock = getProjectionBlock(_dataSourceMap);
}
+ @AfterClass
+ public void tearDown() {
+ try {
+ if (_indexSegment != null) {
+ _indexSegment.destroy();
+ }
+ } finally {
+ FileUtils.deleteQuietly(new File(getIndexDirPath(SEGMENT_NAME)));
+ }
+ }
+
protected void testTransformFunction(ExpressionContext expression, boolean[]
expectedValues,
ProjectionBlock projectionBlock, Map<String, DataSource> dataSourceMap)
throws Exception {
diff --git
a/pinot-core/src/test/java/org/apache/pinot/core/query/aggregation/groupby/DictionaryBasedGroupKeyGeneratorTest.java
b/pinot-core/src/test/java/org/apache/pinot/core/query/aggregation/groupby/DictionaryBasedGroupKeyGeneratorTest.java
index d681044951e..9a41ec0100f 100644
---
a/pinot-core/src/test/java/org/apache/pinot/core/query/aggregation/groupby/DictionaryBasedGroupKeyGeneratorTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/core/query/aggregation/groupby/DictionaryBasedGroupKeyGeneratorTest.java
@@ -26,6 +26,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.pinot.common.request.context.ExpressionContext;
@@ -62,7 +63,8 @@ import static org.testng.Assert.assertTrue;
public class DictionaryBasedGroupKeyGeneratorTest {
private static final String SEGMENT_NAME = "testSegment";
- private static final String INDEX_DIR_PATH =
FileUtils.getTempDirectoryPath() + File.separator + SEGMENT_NAME;
+ private static final String INDEX_DIR_PATH =
+ FileUtils.getTempDirectoryPath() + File.separator + SEGMENT_NAME + "-" +
UUID.randomUUID();
private static final int NUM_ROWS = 1000;
private static final int UNIQUE_ROWS = 100;
private static final int MAX_STEP_LENGTH = 1000;
diff --git
a/pinot-core/src/test/java/org/apache/pinot/core/query/executor/QueryExecutorExceptionsTest.java
b/pinot-core/src/test/java/org/apache/pinot/core/query/executor/QueryExecutorExceptionsTest.java
index e5f6ad58983..054f430c074 100644
---
a/pinot-core/src/test/java/org/apache/pinot/core/query/executor/QueryExecutorExceptionsTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/core/query/executor/QueryExecutorExceptionsTest.java
@@ -24,6 +24,7 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.commons.configuration2.PropertiesConfiguration;
@@ -78,7 +79,8 @@ public class QueryExecutorExceptionsTest {
private static final String AVRO_DATA_PATH = "data/simpleData200001.avro";
private static final String EMPTY_JSON_DATA_PATH =
"data/test_empty_data.json";
private static final String QUERY_EXECUTOR_CONFIG_PATH =
"conf/query-executor.properties";
- private static final File INDEX_DIR = new File(FileUtils.getTempDirectory(),
"QueryExecutorTest");
+ private static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(), "QueryExecutorTest-" +
UUID.randomUUID());
private static final String RAW_TABLE_NAME = "testTable";
private static final String OFFLINE_TABLE_NAME =
TableNameBuilder.OFFLINE.tableNameWithType(RAW_TABLE_NAME);
private static final int NUM_SEGMENTS_TO_GENERATE = 2;
diff --git
a/pinot-core/src/test/java/org/apache/pinot/core/query/executor/QueryExecutorTest.java
b/pinot-core/src/test/java/org/apache/pinot/core/query/executor/QueryExecutorTest.java
index 318fd8e3fbf..ecd4a223d88 100644
---
a/pinot-core/src/test/java/org/apache/pinot/core/query/executor/QueryExecutorTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/core/query/executor/QueryExecutorTest.java
@@ -29,6 +29,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
+import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -96,7 +97,8 @@ public class QueryExecutorTest {
private static final String AVRO_DATA_PATH = "data/sampleEatsData30k.avro";
private static final String EMPTY_JSON_DATA_PATH =
"data/test_empty_data.json";
private static final String QUERY_EXECUTOR_CONFIG_PATH =
"conf/query-executor.properties";
- private static final File TEMP_DIR = new File(FileUtils.getTempDirectory(),
"QueryExecutorTest");
+ private static final File TEMP_DIR =
+ new File(FileUtils.getTempDirectory(), "QueryExecutorTest-" +
UUID.randomUUID());
private static final String RAW_TABLE_NAME = "sampleEatsData";
private static final String OFFLINE_TABLE_NAME =
TableNameBuilder.OFFLINE.tableNameWithType(RAW_TABLE_NAME);
private static final int NUM_SEGMENTS_TO_GENERATE = 2;
diff --git
a/pinot-core/src/test/java/org/apache/pinot/core/startree/v2/BaseStarTreeV2Test.java
b/pinot-core/src/test/java/org/apache/pinot/core/startree/v2/BaseStarTreeV2Test.java
index cd4bb07bbd9..6bba131d59d 100644
---
a/pinot-core/src/test/java/org/apache/pinot/core/startree/v2/BaseStarTreeV2Test.java
+++
b/pinot-core/src/test/java/org/apache/pinot/core/startree/v2/BaseStarTreeV2Test.java
@@ -28,6 +28,7 @@ import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
+import java.util.UUID;
import javax.annotation.Nullable;
import org.apache.commons.io.FileUtils;
import org.apache.pinot.common.request.context.ExpressionContext;
@@ -85,7 +86,8 @@ import static org.testng.Assert.assertNull;
abstract class BaseStarTreeV2Test<R, A> {
private static final Random RANDOM = new Random();
- private static final File TEMP_DIR = new File(FileUtils.getTempDirectory(),
"BaseStarTreeV2Test");
+ private static final File TEMP_DIR =
+ new File(FileUtils.getTempDirectory(), "BaseStarTreeV2Test-" +
UUID.randomUUID());
protected static final String TABLE_NAME = "testTable";
private static final String SEGMENT_NAME = "testSegment";
diff --git
a/pinot-core/src/test/java/org/apache/pinot/queries/BaseFSTBasedRegexpLikeQueriesTest.java
b/pinot-core/src/test/java/org/apache/pinot/queries/BaseFSTBasedRegexpLikeQueriesTest.java
index 59eb2b4edae..6b33fa8bb2d 100644
---
a/pinot-core/src/test/java/org/apache/pinot/queries/BaseFSTBasedRegexpLikeQueriesTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/queries/BaseFSTBasedRegexpLikeQueriesTest.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
+import java.util.UUID;
import javax.annotation.Nullable;
import org.apache.commons.io.FileUtils;
import org.apache.pinot.common.response.broker.BrokerResponseNative;
@@ -62,7 +63,8 @@ import static org.testng.Assert.assertNotNull;
public abstract class BaseFSTBasedRegexpLikeQueriesTest extends
BaseQueriesTest {
private static final File INDEX_DIR =
- new File(FileUtils.getTempDirectory(),
BaseFSTBasedRegexpLikeQueriesTest.class.getSimpleName());
+ new File(FileUtils.getTempDirectory(),
BaseFSTBasedRegexpLikeQueriesTest.class.getSimpleName() + "-"
+ + UUID.randomUUID());
private static final String TABLE_NAME = "testTable";
private static final String SEGMENT_NAME = "testSegment";
private static final String DOMAIN_NAMES_COL = "DOMAIN_NAMES";
diff --git
a/pinot-core/src/test/java/org/apache/pinot/queries/BaseFunnelCountQueriesTest.java
b/pinot-core/src/test/java/org/apache/pinot/queries/BaseFunnelCountQueriesTest.java
index 9bed905c079..603c1892007 100644
---
a/pinot-core/src/test/java/org/apache/pinot/queries/BaseFunnelCountQueriesTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/queries/BaseFunnelCountQueriesTest.java
@@ -27,6 +27,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;
+import java.util.UUID;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
@@ -58,7 +59,7 @@ import static org.testng.Assert.assertTrue;
@SuppressWarnings("rawtypes")
abstract public class BaseFunnelCountQueriesTest extends BaseQueriesTest {
protected static final File INDEX_DIR =
- new File(FileUtils.getTempDirectory(), "FunnelCountQueriesTest");
+ new File(FileUtils.getTempDirectory(), "FunnelCountQueriesTest-" +
UUID.randomUUID());
protected static final String RAW_TABLE_NAME = "testTable";
protected static final String SEGMENT_NAME = "testSegment";
protected static final Random RANDOM = new Random();
diff --git
a/pinot-core/src/test/java/org/apache/pinot/queries/BaseMultiValueQueriesTest.java
b/pinot-core/src/test/java/org/apache/pinot/queries/BaseMultiValueQueriesTest.java
index 268463cefce..46910884d3e 100644
---
a/pinot-core/src/test/java/org/apache/pinot/queries/BaseMultiValueQueriesTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/queries/BaseMultiValueQueriesTest.java
@@ -22,6 +22,7 @@ import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import
org.apache.pinot.segment.local.indexsegment.immutable.ImmutableSegmentLoader;
import
org.apache.pinot.segment.local.segment.creator.impl.SegmentIndexCreationDriverImpl;
@@ -61,7 +62,8 @@ import static org.testng.Assert.assertNotNull;
/// - column10, METRIC, INT, 3960, F, F, F
/// - daysSinceEpoch, TIME, INT, 1, T, F, F
public abstract class BaseMultiValueQueriesTest extends BaseQueriesTest {
- protected static final File INDEX_DIR = new
File(FileUtils.getTempDirectory(), "MultiValueQueriesTest");
+ protected static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(), "MultiValueQueriesTest-" +
UUID.randomUUID());
protected static final String AVRO_DATA = "data" + File.separator +
"test_data-mv.avro";
protected static final String RAW_TABLE_NAME = "testTable";
protected static final String SEGMENT_NAME =
"testTable_1756015683_1756015683";
diff --git
a/pinot-core/src/test/java/org/apache/pinot/queries/BaseMultiValueRawQueriesTest.java
b/pinot-core/src/test/java/org/apache/pinot/queries/BaseMultiValueRawQueriesTest.java
index b9ca42971aa..7a6185ff9c5 100644
---
a/pinot-core/src/test/java/org/apache/pinot/queries/BaseMultiValueRawQueriesTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/queries/BaseMultiValueRawQueriesTest.java
@@ -22,6 +22,7 @@ import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import
org.apache.pinot.segment.local.indexsegment.immutable.ImmutableSegmentLoader;
import
org.apache.pinot.segment.local.segment.creator.impl.SegmentIndexCreationDriverImpl;
@@ -61,7 +62,8 @@ import static org.testng.Assert.assertNotNull;
/// - column10, METRIC, INT, 3960, F, F, F
/// - daysSinceEpoch, TIME, INT, 1, T, F, F
public class BaseMultiValueRawQueriesTest extends BaseQueriesTest {
- private static final File INDEX_DIR = new File(FileUtils.getTempDirectory(),
"MultiValueRawQueriesTest");
+ private static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(), "MultiValueRawQueriesTest-" +
UUID.randomUUID());
private static final String AVRO_DATA = "data" + File.separator +
"test_data-mv.avro";
protected static final String RAW_TABLE_NAME = "testTable";
private static final String SEGMENT_NAME = "testTable_1756015683_1756015683";
diff --git
a/pinot-core/src/test/java/org/apache/pinot/queries/BaseSingleValueQueriesTest.java
b/pinot-core/src/test/java/org/apache/pinot/queries/BaseSingleValueQueriesTest.java
index 65c007b5c5d..343d0d7c651 100644
---
a/pinot-core/src/test/java/org/apache/pinot/queries/BaseSingleValueQueriesTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/queries/BaseSingleValueQueriesTest.java
@@ -22,6 +22,7 @@ import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import
org.apache.pinot.segment.local.indexsegment.immutable.ImmutableSegmentLoader;
import
org.apache.pinot.segment.local.segment.creator.impl.SegmentIndexCreationDriverImpl;
@@ -62,7 +63,8 @@ import static org.testng.Assert.assertNotNull;
/// - column18, METRIC, INT, 1440, F, T
/// - daysSinceEpoch, TIME, INT, 2, T, F
public abstract class BaseSingleValueQueriesTest extends BaseQueriesTest {
- private static final File INDEX_DIR = new File(FileUtils.getTempDirectory(),
"SingleValueQueriesTest");
+ private static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(), "SingleValueQueriesTest-" +
UUID.randomUUID());
private static final String AVRO_DATA = "data" + File.separator +
"test_data-sv.avro";
protected static final String RAW_TABLE_NAME = "testTable";
private static final String SEGMENT_NAME = "testTable_126164076_167572854";
diff --git
a/pinot-core/src/test/java/org/apache/pinot/queries/GapfillQueriesScalabilityTest.java
b/pinot-core/src/test/java/org/apache/pinot/queries/GapfillQueriesScalabilityTest.java
index 5e6a8aeab30..391e490d4a5 100644
---
a/pinot-core/src/test/java/org/apache/pinot/queries/GapfillQueriesScalabilityTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/queries/GapfillQueriesScalabilityTest.java
@@ -23,6 +23,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.pinot.common.response.broker.BrokerResponseNative;
import org.apache.pinot.common.response.broker.ResultTable;
@@ -49,7 +50,8 @@ import org.testng.annotations.Test;
/// Scalability Queries test for Gapfill queries.
public class GapfillQueriesScalabilityTest extends BaseQueriesTest {
- private static final File INDEX_DIR = new File(FileUtils.getTempDirectory(),
"PostAggregationGapfillQueriesTest");
+ private static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(),
"PostAggregationGapfillQueriesTest-" + UUID.randomUUID());
private static final String RAW_TABLE_NAME = "parkingData";
private static final String SEGMENT_NAME = "testSegment";
diff --git
a/pinot-core/src/test/java/org/apache/pinot/queries/GapfillQueriesTest.java
b/pinot-core/src/test/java/org/apache/pinot/queries/GapfillQueriesTest.java
index 3d7d1c839f5..3a42409b16a 100644
--- a/pinot-core/src/test/java/org/apache/pinot/queries/GapfillQueriesTest.java
+++ b/pinot-core/src/test/java/org/apache/pinot/queries/GapfillQueriesTest.java
@@ -23,6 +23,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.pinot.common.response.broker.BrokerResponseNative;
import org.apache.pinot.common.response.broker.ResultTable;
@@ -51,7 +52,8 @@ import org.testng.annotations.Test;
/// Queries test for Gapfill queries.
// TODO: Item 1. table alias for subquery in next PR
public class GapfillQueriesTest extends BaseQueriesTest {
- private static final File INDEX_DIR = new File(FileUtils.getTempDirectory(),
"PostAggregationGapfillQueriesTest");
+ private static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(),
"PostAggregationGapfillQueriesTest-" + UUID.randomUUID());
private static final String RAW_TABLE_NAME = "parkingData";
private static final String SEGMENT_NAME = "testSegment";
diff --git
a/pinot-core/src/test/java/org/apache/pinot/queries/HistogramQueriesTest.java
b/pinot-core/src/test/java/org/apache/pinot/queries/HistogramQueriesTest.java
index b53eac4e97f..aeb93a96c79 100644
---
a/pinot-core/src/test/java/org/apache/pinot/queries/HistogramQueriesTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/queries/HistogramQueriesTest.java
@@ -24,6 +24,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.pinot.common.response.broker.BrokerResponseNative;
import org.apache.pinot.common.response.broker.ResultTable;
@@ -59,7 +60,8 @@ import static org.testng.Assert.assertTrue;
/// Queries test for histogram queries.
@SuppressWarnings({"rawtypes", "unchecked"})
public class HistogramQueriesTest extends BaseQueriesTest {
- private static final File INDEX_DIR = new File(FileUtils.getTempDirectory(),
"HistogramQueriesTest");
+ private static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(), "HistogramQueriesTest-" +
UUID.randomUUID());
private static final String RAW_TABLE_NAME = "testTable";
private static final String SEGMENT_NAME = "testSegment";
diff --git
a/pinot-core/src/test/java/org/apache/pinot/queries/JsonIngestionFromAvroQueriesTest.java
b/pinot-core/src/test/java/org/apache/pinot/queries/JsonIngestionFromAvroQueriesTest.java
index 0e78b88e4f4..0555cd63964 100644
---
a/pinot-core/src/test/java/org/apache/pinot/queries/JsonIngestionFromAvroQueriesTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/queries/JsonIngestionFromAvroQueriesTest.java
@@ -29,6 +29,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.apache.avro.Schema;
@@ -64,7 +65,8 @@ import static org.testng.Assert.assertEquals;
/// Test if ComplexType (RECORD, ARRAY, MAP, UNION, ENUM, and FIXED) field
from an AVRO file can be ingested into a JSON
/// column in a Pinot segment.
public class JsonIngestionFromAvroQueriesTest extends BaseQueriesTest {
- private static final File INDEX_DIR = new File(FileUtils.getTempDirectory(),
"JsonIngestionFromAvroTest");
+ private static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(), "JsonIngestionFromAvroTest-" +
UUID.randomUUID());
private static final File AVRO_DATA_FILE = new File(INDEX_DIR,
"JsonIngestionFromAvroTest.avro");
private static final String RAW_TABLE_NAME = "testTable";
private static final String SEGMENT_NAME = "testSegment";
diff --git
a/pinot-core/src/test/java/org/apache/pinot/queries/JsonMatchQueriesTest.java
b/pinot-core/src/test/java/org/apache/pinot/queries/JsonMatchQueriesTest.java
index f28ab8fa4b5..5b6dba43401 100644
---
a/pinot-core/src/test/java/org/apache/pinot/queries/JsonMatchQueriesTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/queries/JsonMatchQueriesTest.java
@@ -26,6 +26,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.pinot.common.response.broker.BrokerResponseNative;
import
org.apache.pinot.segment.local.indexsegment.immutable.ImmutableSegmentLoader;
@@ -54,7 +55,8 @@ import static org.testng.Assert.assertTrue;
/// Queries test for JSON_MATCH predicate.
public class JsonMatchQueriesTest extends BaseQueriesTest {
- private static final File INDEX_DIR = new File(FileUtils.getTempDirectory(),
"JsonMatchQueriesTest");
+ private static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(), "JsonMatchQueriesTest-" +
UUID.randomUUID());
private static final String RAW_TABLE_NAME = "testTable";
private static final String SEGMENT_NAME = "testSegment";
diff --git
a/pinot-core/src/test/java/org/apache/pinot/queries/JsonUnnestIngestionFromAvroQueriesTest.java
b/pinot-core/src/test/java/org/apache/pinot/queries/JsonUnnestIngestionFromAvroQueriesTest.java
index 525840ddc5f..9e400221f59 100644
---
a/pinot-core/src/test/java/org/apache/pinot/queries/JsonUnnestIngestionFromAvroQueriesTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/queries/JsonUnnestIngestionFromAvroQueriesTest.java
@@ -28,6 +28,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.UUID;
import org.apache.avro.Schema;
import org.apache.avro.file.DataFileWriter;
import org.apache.avro.generic.GenericData;
@@ -64,7 +65,8 @@ import static org.apache.avro.Schema.*;
/// Test if ComplexType (RECORD, ARRAY, MAP, UNION, ENUM, and FIXED) field
from an AVRO file can be ingested into a JSON
/// column in a Pinot segment.
public class JsonUnnestIngestionFromAvroQueriesTest extends BaseQueriesTest {
- private static final File INDEX_DIR = new File(FileUtils.getTempDirectory(),
"JsonIngestionFromAvroTest");
+ private static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(), "JsonIngestionFromAvroTest-" +
UUID.randomUUID());
private static final File AVRO_DATA_FILE = new File(INDEX_DIR,
"JsonIngestionFromAvroTest.avro");
private static final String RAW_TABLE_NAME = "testTable";
private static final String SEGMENT_NAME = "testSegment";
diff --git
a/pinot-core/src/test/java/org/apache/pinot/queries/MultiValueRawQueriesTest.java
b/pinot-core/src/test/java/org/apache/pinot/queries/MultiValueRawQueriesTest.java
index 8fbee387466..4b940672505 100644
---
a/pinot-core/src/test/java/org/apache/pinot/queries/MultiValueRawQueriesTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/queries/MultiValueRawQueriesTest.java
@@ -26,6 +26,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.pinot.common.response.broker.BrokerResponseNative;
@@ -53,7 +54,8 @@ import static org.testng.Assert.*;
public class MultiValueRawQueriesTest extends BaseQueriesTest {
- private static final File INDEX_DIR = new File(FileUtils.getTempDirectory(),
"MultiValueRawQueriesTest");
+ private static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(), "MultiValueRawQueriesTest-" +
UUID.randomUUID());
private static final String RAW_TABLE_NAME = "testTable";
private static final String SEGMENT_NAME_1 = "testSegment1";
diff --git
a/pinot-core/src/test/java/org/apache/pinot/queries/PercentileKLLQueriesTest.java
b/pinot-core/src/test/java/org/apache/pinot/queries/PercentileKLLQueriesTest.java
index 0aa7b2e697f..7cc104ef5ed 100644
---
a/pinot-core/src/test/java/org/apache/pinot/queries/PercentileKLLQueriesTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/queries/PercentileKLLQueriesTest.java
@@ -26,6 +26,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.datasketches.kll.KllDoublesSketch;
import org.apache.pinot.common.response.broker.BrokerResponseNative;
@@ -66,7 +67,8 @@ import static org.testng.Assert.assertNotNull;
/// - Compares the results for PERCENTILE_KLL on double column and KLL column
with results for PERCENTILE on
/// double column
public class PercentileKLLQueriesTest extends BaseQueriesTest {
- protected static final File INDEX_DIR = new
File(FileUtils.getTempDirectory(), "PercentileKllQueriesTest");
+ protected static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(), "PercentileKllQueriesTest-" +
UUID.randomUUID());
protected static final String TABLE_NAME = "testTable";
protected static final String SEGMENT_NAME = "testSegment";
diff --git
a/pinot-core/src/test/java/org/apache/pinot/queries/PercentileTDigestQueriesTest.java
b/pinot-core/src/test/java/org/apache/pinot/queries/PercentileTDigestQueriesTest.java
index 97c76cdb04c..497fc1b0961 100644
---
a/pinot-core/src/test/java/org/apache/pinot/queries/PercentileTDigestQueriesTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/queries/PercentileTDigestQueriesTest.java
@@ -30,6 +30,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.pinot.common.request.PinotQuery;
import org.apache.pinot.common.response.broker.BrokerResponseNative;
@@ -78,7 +79,8 @@ import static org.testng.Assert.assertTrue;
/// - Compares the results for PERCENTILE_TDIGEST on double column and TDigest
column with results for PERCENTILE on
/// double column
public class PercentileTDigestQueriesTest extends BaseQueriesTest {
- protected static final File INDEX_DIR = new
File(FileUtils.getTempDirectory(), "PercentileTDigestQueriesTest");
+ protected static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(), "PercentileTDigestQueriesTest-" +
UUID.randomUUID());
protected static final String TABLE_NAME = "testTable";
protected static final String SEGMENT_NAME = "testSegment";
diff --git
a/pinot-core/src/test/java/org/apache/pinot/queries/StatisticalQueriesTest.java
b/pinot-core/src/test/java/org/apache/pinot/queries/StatisticalQueriesTest.java
index 5ded2ed8f8d..75489ceabba 100644
---
a/pinot-core/src/test/java/org/apache/pinot/queries/StatisticalQueriesTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/queries/StatisticalQueriesTest.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.commons.math3.stat.correlation.Covariance;
import org.apache.commons.math3.stat.descriptive.moment.Kurtosis;
@@ -66,7 +67,8 @@ import static org.testng.Assert.assertTrue;
/// Queries test for statistical queries (i.e Variance, Covariance, Standard
Deviation etc)
public class StatisticalQueriesTest extends BaseQueriesTest {
- private static final File INDEX_DIR = new File(FileUtils.getTempDirectory(),
"CovarianceQueriesTest");
+ private static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(), "CovarianceQueriesTest-" +
UUID.randomUUID());
private static final String RAW_TABLE_NAME = "testTable";
private static final String SEGMENT_NAME = "testSegment";
diff --git
a/pinot-core/src/test/java/org/apache/pinot/queries/TextSearchQueriesTest.java
b/pinot-core/src/test/java/org/apache/pinot/queries/TextSearchQueriesTest.java
index c1fb75b2237..76ae6671441 100644
---
a/pinot-core/src/test/java/org/apache/pinot/queries/TextSearchQueriesTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/queries/TextSearchQueriesTest.java
@@ -30,6 +30,10 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
+import java.util.UUID;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.analysis.Analyzer;
@@ -85,7 +89,8 @@ import static org.testng.Assert.*;
/// The test table has a SKILLS column and QUERY_LOG column. Text index is
created
/// on each of these columns.
public class TextSearchQueriesTest extends BaseQueriesTest {
- private static final File INDEX_DIR = new File(FileUtils.getTempDirectory(),
"TextSearchQueriesTest");
+ private static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(), "TextSearchQueriesTest-" +
UUID.randomUUID());
protected static final String TABLE_NAME = "MyTable";
private static final String SEGMENT_NAME = "testSegment";
@@ -1591,31 +1596,29 @@ public class TextSearchQueriesTest extends
BaseQueriesTest {
public void testMultiThreadedLuceneRealtime()
throws Exception {
File indexFile = new File(INDEX_DIR.getPath() + "/realtime-test3.index");
- Directory indexDirectory = FSDirectory.open(indexFile.toPath());
- Analyzer analyzer = new CaseAwareStandardAnalyzer();
- // create and open a writer
- IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
- indexWriterConfig.setRAMBufferSizeMB(500);
- IndexWriter indexWriter = new IndexWriter(indexDirectory,
indexWriterConfig);
-
- // create an NRT index reader
- SearcherManager searcherManager = new SearcherManager(indexWriter, false,
false, null);
-
- // background thread to refresh NRT reader
- ControlledRealTimeReopenThread controlledRealTimeReopenThread =
- new ControlledRealTimeReopenThread(indexWriter, searcherManager, 0.01,
0.01);
- controlledRealTimeReopenThread.start();
-
- // start writer and reader
- Thread writer = new Thread(new RealtimeWriter(indexWriter));
- Thread realtimeReader = new Thread(new RealtimeReader(searcherManager,
analyzer));
-
- writer.start();
- realtimeReader.start();
-
- writer.join();
- realtimeReader.join();
- controlledRealTimeReopenThread.join();
+ try (Directory indexDirectory = FSDirectory.open(indexFile.toPath());
+ Analyzer analyzer = new CaseAwareStandardAnalyzer()) {
+ // create and open a writer
+ IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
+ indexWriterConfig.setRAMBufferSizeMB(500);
+ try (IndexWriter indexWriter = new IndexWriter(indexDirectory,
indexWriterConfig);
+ SearcherManager searcherManager = new SearcherManager(indexWriter,
false, false, null);
+ ControlledRealTimeReopenThread<IndexSearcher>
controlledRealTimeReopenThread =
+ new ControlledRealTimeReopenThread<>(indexWriter,
searcherManager, 0.01, 0.01)) {
+ controlledRealTimeReopenThread.start();
+
+ // Start the writer and reader, and propagate worker failures back to
the test thread.
+ ExecutorService executorService = Executors.newFixedThreadPool(2);
+ try {
+ Future<?> writer = executorService.submit(new
RealtimeWriter(indexWriter));
+ Future<?> realtimeReader = executorService.submit(new
RealtimeReader(searcherManager, analyzer));
+ writer.get();
+ realtimeReader.get();
+ } finally {
+ executorService.shutdownNow();
+ }
+ }
+ }
}
private static class RealtimeWriter implements Runnable {
@@ -1662,9 +1665,8 @@ public class TextSearchQueriesTest extends
BaseQueriesTest {
} finally {
try {
_indexWriter.commit();
- _indexWriter.close();
} catch (Exception e) {
- throw new RuntimeException("Failed to commit/close the index
writer");
+ throw new RuntimeException("Failed to commit the index writer");
}
}
}
@@ -1689,16 +1691,19 @@ public class TextSearchQueriesTest extends
BaseQueriesTest {
// in the index
while (count < 1000) {
IndexSearcher indexSearcher = _searcherManager.acquire();
- int hits = indexSearcher.search(query,
Integer.MAX_VALUE).scoreDocs.length;
- // TODO: see how we can make this more deterministic
- if (count > 200) {
- // we should see an increasing number of hits
- assertTrue(hits > 0);
- assertTrue(hits >= prevHits);
+ try {
+ int hits = indexSearcher.search(query,
Integer.MAX_VALUE).scoreDocs.length;
+ // TODO: see how we can make this more deterministic
+ if (count > 200) {
+ // we should see an increasing number of hits
+ assertTrue(hits > 0);
+ assertTrue(hits >= prevHits);
+ }
+ count++;
+ prevHits = hits;
+ } finally {
+ _searcherManager.release(indexSearcher);
}
- count++;
- prevHits = hits;
- _searcherManager.release(indexSearcher);
Thread.sleep(1);
}
} catch (Exception e) {
diff --git
a/pinot-plugins/pinot-stream-ingestion/pinot-kafka-3.0/src/test/java/org/apache/pinot/plugin/stream/kafka30/server/KafkaServerStartableTest.java
b/pinot-plugins/pinot-stream-ingestion/pinot-kafka-3.0/src/test/java/org/apache/pinot/plugin/stream/kafka30/server/KafkaServerStartableTest.java
index 5ac31b00377..42b5d48c691 100644
---
a/pinot-plugins/pinot-stream-ingestion/pinot-kafka-3.0/src/test/java/org/apache/pinot/plugin/stream/kafka30/server/KafkaServerStartableTest.java
+++
b/pinot-plugins/pinot-stream-ingestion/pinot-kafka-3.0/src/test/java/org/apache/pinot/plugin/stream/kafka30/server/KafkaServerStartableTest.java
@@ -65,11 +65,12 @@ public class KafkaServerStartableTest {
}
@Test
- public void testStopReleasesBrokerPort()
+ public void testStopMakesBrokerUnavailable()
throws Exception {
int kafkaServerPort = NetUtils.findOpenPort();
+ String brokerList = "localhost:" + kafkaServerPort;
Properties serverProperties = new Properties();
- serverProperties.put("kafka.server.bootstrap.servers", "localhost:" +
kafkaServerPort);
+ serverProperties.put("kafka.server.bootstrap.servers", brokerList);
serverProperties.put("kafka.server.port",
Integer.toString(kafkaServerPort));
serverProperties.put("kafka.server.broker.id", "0");
serverProperties.put("kafka.server.owner.name",
getClass().getSimpleName());
@@ -79,11 +80,13 @@ public class KafkaServerStartableTest {
kafkaServerStartable.init(serverProperties);
kafkaServerStartable.start();
try {
- Assert.assertFalse(NetUtils.available(kafkaServerPort), "Kafka port
should be in use while broker is running");
+ Assert.assertTrue(kafkaServerStartable.isKafkaAvailable(brokerList),
+ "Kafka broker should be reachable while running");
} finally {
kafkaServerStartable.stop();
}
- Assert.assertTrue(NetUtils.available(kafkaServerPort), "Kafka port should
be released after broker stop");
+ Assert.assertFalse(kafkaServerStartable.isKafkaAvailable(brokerList),
+ "Kafka broker should be unavailable after stop");
}
private static final class TestableKafkaServerStartable extends
KafkaServerStartable {
diff --git
a/pinot-plugins/pinot-stream-ingestion/pinot-pulsar/src/test/java/org/apache/pinot/plugin/stream/pulsar/PulsarConsumerTest.java
b/pinot-plugins/pinot-stream-ingestion/pinot-pulsar/src/test/java/org/apache/pinot/plugin/stream/pulsar/PulsarConsumerTest.java
index f65cf67d3a0..42c91edcd07 100644
---
a/pinot-plugins/pinot-stream-ingestion/pinot-pulsar/src/test/java/org/apache/pinot/plugin/stream/pulsar/PulsarConsumerTest.java
+++
b/pinot-plugins/pinot-stream-ingestion/pinot-pulsar/src/test/java/org/apache/pinot/plugin/stream/pulsar/PulsarConsumerTest.java
@@ -56,6 +56,9 @@ import static org.testng.Assert.assertTrue;
public class PulsarConsumerTest {
private static final DockerImageName PULSAR_IMAGE =
DockerImageName.parse("apachepulsar/pulsar:3.2.2");
+ // The image defaults to 6 GiB, which can exhaust the Docker VM when unit
tests use multiple forks.
+ private static final String PULSAR_MEMORY = "-Xms512m -Xmx1g
-XX:MaxDirectMemorySize=1g";
+ private static final Duration PULSAR_STARTUP_TIMEOUT =
Duration.ofMinutes(10);
public static final String TABLE_NAME_WITH_TYPE = "tableName_REALTIME";
public static final String TEST_TOPIC = "test-topic";
public static final String TEST_TOPIC_BATCH = "test-topic-batch";
@@ -75,7 +78,8 @@ public class PulsarConsumerTest {
@BeforeClass
public void setUp()
throws Exception {
- _pulsar = new
PulsarContainer(PULSAR_IMAGE).withStartupTimeout(Duration.ofMinutes(5));
+ _pulsar = new PulsarContainer(PULSAR_IMAGE).withEnv("PULSAR_MEM",
PULSAR_MEMORY)
+ .withStartupTimeout(PULSAR_STARTUP_TIMEOUT);
_pulsar.start();
try (PulsarAdmin admin =
PulsarAdmin.builder().serviceHttpUrl(_pulsar.getHttpServiceUrl()).build()) {
Topics topics = admin.topics();
@@ -88,10 +92,12 @@ public class PulsarConsumerTest {
}
}
- @AfterClass
+ @AfterClass(alwaysRun = true)
public void tearDown()
throws Exception {
- _pulsar.stop();
+ if (_pulsar != null) {
+ _pulsar.stop();
+ }
}
public void publishRecords(PulsarClient client)
diff --git
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/io/reader/impl/FixedBitIntReaderTest.java
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/io/reader/impl/FixedBitIntReaderTest.java
index f957d450996..5614e773642 100644
---
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/io/reader/impl/FixedBitIntReaderTest.java
+++
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/io/reader/impl/FixedBitIntReaderTest.java
@@ -21,6 +21,7 @@ package org.apache.pinot.segment.local.io.reader.impl;
import java.io.File;
import java.io.IOException;
import java.util.Random;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.pinot.segment.local.PinotBuffersAfterMethodCheckRule;
import
org.apache.pinot.segment.local.io.writer.impl.FixedBitSVForwardIndexWriter;
@@ -33,7 +34,8 @@ import static org.testng.Assert.assertEquals;
public class FixedBitIntReaderTest implements PinotBuffersAfterMethodCheckRule
{
- private static final File INDEX_DIR = new File(FileUtils.getTempDirectory(),
"FixedBitIntReaderTest");
+ private static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(), "FixedBitIntReaderTest-" +
UUID.randomUUID());
private static final int NUM_VALUES = 95;
private static final Random RANDOM = new Random();
diff --git
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/realtime/impl/invertedindex/LuceneMutableTextIndexTest.java
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/realtime/impl/invertedindex/LuceneMutableTextIndexTest.java
index 4bfc2a3f67d..f6afbf9a37c 100644
---
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/realtime/impl/invertedindex/LuceneMutableTextIndexTest.java
+++
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/realtime/impl/invertedindex/LuceneMutableTextIndexTest.java
@@ -20,10 +20,12 @@ package
org.apache.pinot.segment.local.realtime.impl.invertedindex;
import java.io.File;
import java.io.IOException;
+import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.io.FileUtils;
import org.apache.lucene.analysis.Analyzer;
@@ -48,7 +50,8 @@ import static org.testng.Assert.assertEquals;
public class LuceneMutableTextIndexTest {
private static final AtomicInteger SEGMENT_NAME_SUFFIX_COUNTER = new
AtomicInteger(0);
- private static final File INDEX_DIR = new File(FileUtils.getTempDirectory(),
"LuceneMutableIndexTest");
+ private static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(), "LuceneMutableIndexTest-" +
UUID.randomUUID());
private static final String TEXT_COLUMN_NAME = "testColumnName";
private static final String CUSTOM_ANALYZER_FQCN =
CustomAnalyzer.class.getName();
private static final String CUSTOM_QUERY_PARSER_FQCN =
CustomQueryParser.class.getName();
@@ -64,14 +67,21 @@ public class LuceneMutableTextIndexTest {
@BeforeMethod
public void setUpMethod() {
+ // Give each test a fresh refresh queue and worker. Closing and
immediately replacing indexes in the
+ // same queue can race the worker's empty-list exit and leave the
replacement without a refresher.
+ RealtimeLuceneIndexRefreshManager.getInstance().reset();
_queryThreadContext = QueryThreadContext.openForSseTest();
}
- @AfterMethod
+ @AfterMethod(alwaysRun = true)
public void tearDownMethod() {
- if (_queryThreadContext != null) {
- _queryThreadContext.close();
- _queryThreadContext = null;
+ try {
+ closeCurrentIndex();
+ } finally {
+ if (_queryThreadContext != null) {
+ _queryThreadContext.close();
+ _queryThreadContext = null;
+ }
}
}
@@ -179,6 +189,7 @@ public class LuceneMutableTextIndexTest {
private void configureIndex(String analyzerClass, String analyzerClassArgs,
String analyzerClassArgTypes,
String queryParserClass) {
+ closeCurrentIndex();
TextIndexConfigBuilder builder = new TextIndexConfigBuilder();
if (null != analyzerClass) {
builder.withLuceneAnalyzerClass(analyzerClass);
@@ -214,11 +225,34 @@ public class LuceneMutableTextIndexTest {
// ensure searches work after .commit() is called
_realtimeLuceneTextIndex.commit();
- // sleep for index refresh
- try {
- Thread.sleep(100);
- } catch (Exception e) {
- // no-op
+ // Wait for the async NRT index refresh to make the committed documents
searchable. A fixed
+ // sleep is flaky under CPU load (the refresh thread may not run in time),
so poll until a
+ // sentinel query is visible, up to a generous timeout.
+ //
+ // The sentinel is the regex /.*house.*/ -> doc 1 ("...data warehouses"),
which every test in
+ // this class also asserts and which matches under both the default
StandardAnalyzer and the
+ // custom KeywordTokenizer (regex matches the single keyword-tokenized
term). A term sentinel
+ // like "stream" would never match the keyword-tokenized custom-analyzer
cases, making the
+ // barrier spin the full timeout for those tests.
+ awaitIndexRefreshed("/.*house.*/", ImmutableRoaringBitmap.bitmapOf(1));
+ }
+
+ private void awaitIndexRefreshed(String sentinelQuery,
ImmutableRoaringBitmap expected) {
+ long deadlineNanos = System.nanoTime() + TimeUnit.SECONDS.toNanos(30);
+ while (true) {
+ if (expected.equals(_realtimeLuceneTextIndex.getDocIds(sentinelQuery))) {
+ return;
+ }
+ if (System.nanoTime() >= deadlineNanos) {
+ // Fall through and let the caller's assertions report the actual
mismatch.
+ return;
+ }
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ return;
+ }
}
}
@@ -230,7 +264,18 @@ public class LuceneMutableTextIndexTest {
@AfterClass
public void tearDown() {
- _realtimeLuceneTextIndex.close();
+ try {
+ closeCurrentIndex();
+ } finally {
+ FileUtils.deleteQuietly(INDEX_DIR);
+ }
+ }
+
+ private void closeCurrentIndex() {
+ if (_realtimeLuceneTextIndex != null) {
+ _realtimeLuceneTextIndex.close();
+ _realtimeLuceneTextIndex = null;
+ }
}
@Test
@@ -247,8 +292,8 @@ public class LuceneMutableTextIndexTest {
index.add(new String[]{"foo bar"});
index.add(new String[]{"baz qux"});
- // Force a searcher refresh — triggers the refresh listener which
records the current doc count
- index.getSearcherManager().maybeRefresh();
+ // Block until the refresh attempt completes so the listener has
recorded the current doc count
+ index.getSearcherManager().maybeRefreshBlocking();
assertEquals(index.getSearchableDocCount(), 3);
} finally {
@@ -258,6 +303,7 @@ public class LuceneMutableTextIndexTest {
@Test
public void testQueries() {
+ configureIndex(null, null, null, null);
TestUtils.waitForCondition(aVoid -> {
try {
return
_realtimeLuceneTextIndex.getSearcherManager().isSearcherCurrent();
@@ -275,6 +321,7 @@ public class LuceneMutableTextIndexTest {
expectedExceptionsMessageRegExp = ".*TEXT_MATCH query interrupted while
querying the consuming segment.*")
public void testQueryCancellationIsSuccessful()
throws InterruptedException, ExecutionException {
+ configureIndex(null, null, null, null);
// Avoid early finalization by not using Executors.newSingleThreadExecutor
(java <= 20, JDK-8145304)
ExecutorService baseExecutor = Executors.newFixedThreadPool(1);
// Wrap with contextAwareExecutorService to propagate QueryThreadContext
to child threads
diff --git
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/creator/DictionariesTest.java
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/creator/DictionariesTest.java
index eaec194da84..28a63602f7a 100644
---
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/creator/DictionariesTest.java
+++
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/creator/DictionariesTest.java
@@ -28,6 +28,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.UUID;
import java.util.concurrent.TimeUnit;
import org.apache.avro.Schema.Field;
import org.apache.avro.file.DataFileStream;
@@ -76,7 +77,10 @@ import org.testng.annotations.Test;
public class DictionariesTest implements PinotBuffersAfterMethodCheckRule {
private static final String AVRO_DATA = "data/test_sample_data.avro";
- private static final File INDEX_DIR = new
File(DictionariesTest.class.toString());
+ // Per-run unique dir so this test never shares an index directory with
DictionaryOptimiserTest
+ // (which derived its path from the same class) when the two run
concurrently in parallel forks.
+ private static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectoryPath(),
DictionariesTest.class.getSimpleName() + "-" + UUID.randomUUID());
private static final Map<String, Set<Object>> UNIQUE_ENTRIES = new
HashMap<>();
private static File _segmentDirectory;
diff --git
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/creator/DictionaryOptimiserTest.java
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/creator/DictionaryOptimiserTest.java
index 7447f57ba1b..e9df72b00ba 100644
---
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/creator/DictionaryOptimiserTest.java
+++
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/creator/DictionaryOptimiserTest.java
@@ -23,6 +23,7 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
+import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.apache.avro.file.DataFileStream;
@@ -60,7 +61,10 @@ public class DictionaryOptimiserTest implements
PinotBuffersAfterMethodCheckRule
private static final Logger LOGGER =
LoggerFactory.getLogger(DictionaryOptimiserTest.class);
private static final String AVRO_DATA = "data/mixed_cardinality_data.avro";
- private static final File INDEX_DIR = new
File(DictionariesTest.class.toString());
+ // Per-class unique dir so this test never shares an index directory with
DictionariesTest (which
+ // used the same DictionariesTest.class-derived path) when the two run
concurrently in parallel forks.
+ private static final File INDEX_DIR = new
File(FileUtils.getTempDirectoryPath(),
+ DictionaryOptimiserTest.class.getSimpleName() + "-" + UUID.randomUUID());
private static File _segmentDirectory;
diff --git
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/forward/FixedBitMVForwardIndexTest.java
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/forward/FixedBitMVForwardIndexTest.java
index eb18a2349c6..2b35db720de 100644
---
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/forward/FixedBitMVForwardIndexTest.java
+++
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/forward/FixedBitMVForwardIndexTest.java
@@ -23,6 +23,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.pinot.segment.local.PinotBuffersAfterMethodCheckRule;
import
org.apache.pinot.segment.local.io.writer.impl.FixedBitMVForwardIndexWriter;
@@ -39,7 +40,8 @@ import static org.testng.Assert.assertEquals;
public class FixedBitMVForwardIndexTest implements
PinotBuffersAfterMethodCheckRule {
- private static final File TEMP_DIR = new File(FileUtils.getTempDirectory(),
"FixedBitMVForwardIndexTest");
+ private static final File TEMP_DIR =
+ new File(FileUtils.getTempDirectory(), "FixedBitMVForwardIndexTest-" +
UUID.randomUUID());
private static final File INDEX_FILE =
new File(TEMP_DIR, "testColumn" +
V1Constants.Indexes.UNSORTED_MV_FORWARD_INDEX_FILE_EXTENSION);
private static final int NUM_DOCS = 100;
diff --git
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/forward/FixedBitSVForwardIndexReaderTest.java
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/forward/FixedBitSVForwardIndexReaderTest.java
index 26d76661d0c..b114d2dc6cc 100644
---
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/forward/FixedBitSVForwardIndexReaderTest.java
+++
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/forward/FixedBitSVForwardIndexReaderTest.java
@@ -22,6 +22,7 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.pinot.segment.local.PinotBuffersAfterMethodCheckRule;
import
org.apache.pinot.segment.local.io.writer.impl.FixedBitSVForwardIndexWriter;
@@ -37,7 +38,8 @@ import static org.testng.Assert.assertEquals;
public class FixedBitSVForwardIndexReaderTest implements
PinotBuffersAfterMethodCheckRule {
- private static final File TEMP_DIR = new File(FileUtils.getTempDirectory(),
"FixedBitMVForwardIndexTest");
+ private static final File TEMP_DIR =
+ new File(FileUtils.getTempDirectory(),
"FixedBitSVForwardIndexReaderTest-" + UUID.randomUUID());
private static final File INDEX_FILE =
new File(TEMP_DIR, "testColumn" +
V1Constants.Indexes.UNSORTED_SV_FORWARD_INDEX_FILE_EXTENSION);
private static final int NUM_DOCS = 100;
diff --git
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/loader/SegmentPreProcessorTest.java
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/loader/SegmentPreProcessorTest.java
index 05234c1f2a8..c7272504a37 100644
---
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/loader/SegmentPreProcessorTest.java
+++
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/loader/SegmentPreProcessorTest.java
@@ -1093,7 +1093,15 @@ public class SegmentPreProcessorTest implements
PinotBuffersAfterClassCheckRule
// Create inverted index the second time.
checkInvertedIndexCreation(true);
- assertEquals(Files.getLastModifiedTime(singleFileIndex.toPath()),
newLastModifiedTime);
+ // The second (no-op) creation must not rewrite the file. Assert the mtime
did not advance
+ // meaningfully rather than requiring exact equality: the 2s sleeps above
guarantee a real
+ // rewrite would move the mtime by ~2000ms, whereas an untouched file can
still report a
+ // sub-millisecond-to-millisecond delta between two getLastModifiedTime
reads (filesystem
+ // timestamp granularity / metadata flush), which made exact equality
flaky under CPU load.
+ long mtimeDeltaMs =
+ Files.getLastModifiedTime(singleFileIndex.toPath()).toMillis() -
newLastModifiedTime.toMillis();
+ assertTrue(Math.abs(mtimeDeltaMs) < 1000,
+ "columns.psf was rewritten by the no-op index recreation (mtime moved
" + mtimeDeltaMs + " ms)");
assertEquals(singleFileIndex.length(), newFileSize);
}
diff --git
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/readers/forward/FixedBitSVForwardIndexReaderV2Test.java
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/readers/forward/FixedBitSVForwardIndexReaderV2Test.java
index 37b71514af8..e421678cfe5 100644
---
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/readers/forward/FixedBitSVForwardIndexReaderV2Test.java
+++
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/readers/forward/FixedBitSVForwardIndexReaderV2Test.java
@@ -22,6 +22,7 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.pinot.segment.local.PinotBuffersAfterMethodCheckRule;
import org.apache.pinot.segment.local.io.util.PinotDataBitSetV2;
@@ -36,7 +37,8 @@ import static org.testng.Assert.assertEquals;
public class FixedBitSVForwardIndexReaderV2Test implements
PinotBuffersAfterMethodCheckRule {
- private static final File INDEX_DIR = new File(FileUtils.getTempDirectory(),
"FixedBitIntReaderTest");
+ private static final File INDEX_DIR =
+ new File(FileUtils.getTempDirectory(),
"FixedBitSVForwardIndexReaderV2Test-" + UUID.randomUUID());
private static final int NUM_VALUES = 99_999;
private static final int NUM_DOC_IDS = PinotDataBitSetV2.MAX_DOC_PER_CALL;
private static final Random RANDOM = new Random();
diff --git
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/store/SegmentLocalFSDirectoryTest.java
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/store/SegmentLocalFSDirectoryTest.java
index 87e9920b502..6ae0d375718 100644
---
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/store/SegmentLocalFSDirectoryTest.java
+++
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/store/SegmentLocalFSDirectoryTest.java
@@ -19,6 +19,7 @@
package org.apache.pinot.segment.local.segment.store;
import java.io.File;
+import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.pinot.segment.local.PinotBuffersAfterClassCheckRule;
import org.apache.pinot.segment.spi.creator.SegmentVersion;
@@ -35,7 +36,10 @@ import org.testng.annotations.Test;
public class SegmentLocalFSDirectoryTest implements
PinotBuffersAfterClassCheckRule {
- private static final File TEST_DIRECTORY = new
File(SingleFileIndexDirectoryTest.class.toString());
+ // Self-scoped unique dir (was derived from
SingleFileIndexDirectoryTest.class) so parallel forks
+ // never share a directory.
+ private static final File TEST_DIRECTORY = new
File(FileUtils.getTempDirectoryPath(),
+ SegmentLocalFSDirectoryTest.class.getSimpleName() + "-" +
UUID.randomUUID());
private SegmentDirectory _segmentDirectory;
private SegmentMetadataImpl _metadata;
diff --git
a/pinot-segment-spi/src/test/java/org/apache/pinot/segment/spi/memory/PinotDataBufferTestBase.java
b/pinot-segment-spi/src/test/java/org/apache/pinot/segment/spi/memory/PinotDataBufferTestBase.java
index 4e87fa86fe1..66d907dc9d3 100644
---
a/pinot-segment-spi/src/test/java/org/apache/pinot/segment/spi/memory/PinotDataBufferTestBase.java
+++
b/pinot-segment-spi/src/test/java/org/apache/pinot/segment/spi/memory/PinotDataBufferTestBase.java
@@ -21,6 +21,7 @@ package org.apache.pinot.segment.spi.memory;
import java.io.File;
import java.io.IOException;
import java.util.Random;
+import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.commons.io.FileUtils;
@@ -35,7 +36,8 @@ public class PinotDataBufferTestBase {
protected static final Random RANDOM = new Random();
protected ExecutorService _executorService;
- protected static final File TEMP_FILE = new
File(FileUtils.getTempDirectory(), "PinotDataBufferTest");
+ protected static final File TEMP_FILE =
+ new File(FileUtils.getTempDirectory(), "PinotDataBufferTest-" +
UUID.randomUUID());
protected static final int FILE_OFFSET = 10; // Not page-aligned
protected static final int BUFFER_SIZE = 10_000; // Not page-aligned
protected static final int CHAR_ARRAY_LENGTH = BUFFER_SIZE / Character.BYTES;
diff --git
a/pinot-server/src/test/java/org/apache/pinot/server/api/BaseResourceTest.java
b/pinot-server/src/test/java/org/apache/pinot/server/api/BaseResourceTest.java
index 0e4297f86d3..200fcce5cb0 100644
---
a/pinot-server/src/test/java/org/apache/pinot/server/api/BaseResourceTest.java
+++
b/pinot-server/src/test/java/org/apache/pinot/server/api/BaseResourceTest.java
@@ -21,6 +21,7 @@ package org.apache.pinot.server.api;
import java.io.File;
import java.io.InputStream;
import java.net.URI;
+import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -71,11 +72,9 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
public abstract class BaseResourceTest {
- protected static final File TEMP_DIR = new
File(FileUtils.getTempDirectory(), "BaseResourceTest");
protected static final String RAW_TABLE_NAME = "testTable";
protected static final String REALTIME_TABLE_NAME =
TableNameBuilder.REALTIME.tableNameWithType(RAW_TABLE_NAME);
protected static final String OFFLINE_TABLE_NAME =
TableNameBuilder.OFFLINE.tableNameWithType(RAW_TABLE_NAME);
@@ -89,6 +88,7 @@ public abstract class BaseResourceTest {
protected final Map<String, TableDataManager> _tableDataManagerMap = new
HashMap<>();
protected final List<ImmutableSegment> _realtimeIndexSegments = new
ArrayList<>();
protected final List<ImmutableSegment> _offlineIndexSegments = new
ArrayList<>();
+ protected File _tempDir;
protected File _avroFile;
protected AdminApiApplication _adminApiApplication;
protected WebTarget _webTarget;
@@ -105,13 +105,12 @@ public abstract class BaseResourceTest {
throws Exception {
ServerMetrics.register(mock(ServerMetrics.class));
- FileUtils.deleteQuietly(TEMP_DIR);
- assertTrue(TEMP_DIR.mkdirs());
- // Copy the Avro fixture out of the classpath into TEMP_DIR so it is
always backed by a real file.
+ _tempDir = Files.createTempDirectory(getClass().getSimpleName() +
"-").toFile();
+ // Copy the Avro fixture out of the classpath into the temp directory so
it is always backed by a real file.
// The fixture may be served from a packaged test-jar when this base class
is reused from another
// module, in which case it cannot be opened as a plain File via the
resource URL.
String avroFileName = getAvroFileName();
- _avroFile = new File(TEMP_DIR, new File(avroFileName).getName());
+ _avroFile = new File(_tempDir, new File(avroFileName).getName());
try (InputStream avroStream =
getClass().getClassLoader().getResourceAsStream(avroFileName)) {
assertNotNull(avroStream);
FileUtils.copyInputStreamToFile(avroStream, _avroFile);
@@ -128,7 +127,7 @@ public abstract class BaseResourceTest {
when(_serverInstance.getServerMetrics()).thenReturn(mock(ServerMetrics.class));
when(_serverInstance.getInstanceDataManager()).thenReturn(instanceDataManager);
when(_serverInstance.getInstanceDataManager().getSegmentFileDirectory()).thenReturn(
- FileUtils.getTempDirectoryPath());
+ _tempDir.getAbsolutePath());
// Create a single HelixManager mock with proper segment data
HelixManager helixManager = mock(HelixManager.class);
@@ -165,11 +164,12 @@ public abstract class BaseResourceTest {
mock(ServerReloadJobStatusCache.class),
serverConf);
_adminApiApplication.start(List.of(
- new ListenerConfig(CommonConstants.HTTP_PROTOCOL, "0.0.0.0",
CommonConstants.Server.DEFAULT_ADMIN_API_PORT,
+ new ListenerConfig(CommonConstants.HTTP_PROTOCOL, "0.0.0.0", 0,
CommonConstants.HTTP_PROTOCOL, new TlsConfig(),
HttpServerThreadPoolConfig.defaultInstance())));
+ int adminApiPort =
_adminApiApplication.getHttpServer().getListeners().iterator().next().getPort();
_webTarget = ClientBuilder.newClient().target(
- String.format("http://%s:%d", NetUtils.getHostAddress(),
CommonConstants.Server.DEFAULT_ADMIN_API_PORT));
+ String.format("http://%s:%d", NetUtils.getHostAddress(),
adminApiPort));
}
protected void configureServerConf(PinotConfiguration serverConf) {
@@ -186,7 +186,7 @@ public abstract class BaseResourceTest {
immutableSegment.offload();
immutableSegment.destroy();
}
- FileUtils.deleteQuietly(TEMP_DIR);
+ FileUtils.deleteQuietly(_tempDir);
}
protected List<ImmutableSegment> setUpSegments(String tableNameWithType, int
numSegments,
@@ -208,7 +208,7 @@ public abstract class BaseResourceTest {
protected ImmutableSegment setUpSegment(String tableNameWithType, String
segmentName, String segmentNamePostfix,
List<ImmutableSegment> segments, boolean compressionStatsEnabled)
throws Exception {
- File tableDataDir = new File(TEMP_DIR, tableNameWithType);
+ File tableDataDir = new File(_tempDir, tableNameWithType);
SegmentGeneratorConfig config =
SegmentTestUtils.getSegmentGeneratorConfigWithoutTimeColumn(_avroFile,
tableDataDir, tableNameWithType);
config.setSegmentName(segmentName);
@@ -226,7 +226,7 @@ public abstract class BaseResourceTest {
protected void addTable(String tableNameWithType) {
InstanceDataManagerConfig instanceDataManagerConfig =
mock(InstanceDataManagerConfig.class);
-
when(instanceDataManagerConfig.getInstanceDataDir()).thenReturn(TEMP_DIR.getAbsolutePath());
+
when(instanceDataManagerConfig.getInstanceDataDir()).thenReturn(_tempDir.getAbsolutePath());
when(instanceDataManagerConfig.getInstanceId()).thenReturn("Server_1_100.89.121.12");
TableType tableType =
TableNameBuilder.getTableTypeFromTableName(tableNameWithType);
assertNotNull(tableType);
diff --git
a/pinot-server/src/test/java/org/apache/pinot/server/api/TablesResourceTest.java
b/pinot-server/src/test/java/org/apache/pinot/server/api/TablesResourceTest.java
index fe912f3055c..742614358f9 100644
---
a/pinot-server/src/test/java/org/apache/pinot/server/api/TablesResourceTest.java
+++
b/pinot-server/src/test/java/org/apache/pinot/server/api/TablesResourceTest.java
@@ -471,7 +471,7 @@ public class TablesResourceTest extends BaseResourceTest {
Assert.assertEquals(response.getStatus(),
Response.Status.OK.getStatusCode());
File segmentFile = response.readEntity(File.class);
- File tempMetadataDir = new File(FileUtils.getTempDirectory(),
"segment_metadata");
+ File tempMetadataDir = new File(_tempDir, "segment_metadata");
FileUtils.forceMkdir(tempMetadataDir);
// Extract metadata.properties
@@ -750,7 +750,7 @@ public class TablesResourceTest extends BaseResourceTest {
.build();
// Segment 1: dictionary-encoded with tracked uncompressed value bytes.
- File tableDataDir = new File(TEMP_DIR, mixedTableName);
+ File tableDataDir = new File(_tempDir, mixedTableName);
TableConfig dictTableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(mixedTableName).build();
dictTableConfig.getIndexingConfig().setCompressionStatsEnabled(true);
SegmentGeneratorConfig dictConfig = new
SegmentGeneratorConfig(dictTableConfig, schema);
diff --git a/pinot-spi/pom.xml b/pinot-spi/pom.xml
index 34fda62848f..11ac645dedd 100644
--- a/pinot-spi/pom.xml
+++ b/pinot-spi/pom.xml
@@ -193,7 +193,8 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
- <forkCount>1</forkCount>
+ <!-- Keep this module's historical fork reuse, but honor the root
parallel-fork knob. -->
+ <forkCount>${unit.test.fork.count}</forkCount>
<reuseForks>true</reuseForks>
</configuration>
</plugin>
diff --git a/pom.xml b/pom.xml
index f319c23e50a..c362a4463c2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -139,9 +139,36 @@
<!-- Only unit tests are run by default. -->
<skip.integration.tests>true</skip.integration.tests>
<skip.unit.tests>false</skip.unit.tests>
+ <!--
+ Per-fork heap for unit tests. Defaults to 4g to preserve historical
behavior. When
+ running multiple parallel forks (unit.test.fork.count > 1) CI lowers
this so that
+ N forks * heap + the Maven JVM stay within the runner's memory.
+ -->
+ <unit.test.fork.heap>4g</unit.test.fork.heap>
<!-- Sets the VM argument line used when unit tests are run. -->
- <argLine>-Xms4g -Xmx4g</argLine>
+ <argLine>-Xms${unit.test.fork.heap} -Xmx${unit.test.fork.heap}</argLine>
<SKIP_INTEGRATION_TESTS>true</SKIP_INTEGRATION_TESTS>
+ <!--
+ Number of parallel JVM forks used by surefire for unit tests. Defaults
to 1 to
+ preserve the historical single-fork behavior for local/dev builds. CI
overrides
+ this (e.g. -Dunit.test.fork.count=3) to run test classes in parallel
forks and
+ shorten the unit-test phase. Must be a positive integer.
+ -->
+ <unit.test.fork.count>1</unit.test.fork.count>
+ <!--
+ Number of times surefire retries a failing unit test before failing the
build. Defaults to
+ 0 (no retry) so local/dev behavior is unchanged; CI raises it to absorb
a few pre-existing
+ load-sensitive flaky tests exposed by parallel forks. A test passing
only on retry is
+ reported as flaky, not silently passed.
+ -->
+ <unit.test.rerun.count>0</unit.test.rerun.count>
+ <!--
+ Suffix for the JaCoCo exec file name. Empty by default so coverage
writes the
+ historical target/jacoco.exec (used by report / report-aggregate
everywhere). The
+ unit-test script sets this to -${surefire.forkNumber} so parallel forks
each write a
+ distinct jacoco-<n>.exec instead of appending to one shared file.
+ -->
+ <jacoco.exec.suffix></jacoco.exec.suffix>
<!-- Checkstyle violation prop.-->
<checkstyle.violation.severity>warning</checkstyle.violation.severity>
@@ -557,7 +584,9 @@
<activeByDefault>false</activeByDefault>
</activation>
<properties>
- <argLine>-Xms4g -Xmx4g -Dlog4j2.configurationFile=log4j2.xml</argLine>
+ <!-- Inherits unit.test.fork.heap from the global properties
(overridable via
+ -Dunit.test.fork.heap); adds the log4j2 config used under
github-actions. -->
+ <argLine>-Xms${unit.test.fork.heap} -Xmx${unit.test.fork.heap}
-Dlog4j2.configurationFile=log4j2.xml</argLine>
</properties>
</profile>
<profile>
@@ -578,6 +607,13 @@
<includes>
<include>org/apache/pinot/**/*</include>
</includes>
+ <!-- Exec file suffix defaults to empty, keeping the
historical
+ target/jacoco.exec used by report / report-aggregate
everywhere (incl.
+ the integration lanes). The unit-test script sets
jacoco.exec.suffix to
+ -${surefire.forkNumber} so parallel forks (forkCount >
1) each write a
+ distinct jacoco-<n>.exec instead of appending to one
shared file; it
+ then aggregates with a matching jacoco-*.exec glob. -->
+
<destFile>${project.build.directory}/jacoco${jacoco.exec.suffix}.exec</destFile>
</configuration>
</execution>
</executions>
@@ -2167,13 +2203,20 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
- <forkCount>1</forkCount>
+ <!-- Overridable via -Dunit.test.fork.count (defaults to 1); see
the property
+ definition for details. -->
+ <forkCount>${unit.test.fork.count}</forkCount>
<reuseForks>false</reuseForks>
+ <!-- Retries a failing test up to N times (default 0); see
property definition. -->
+
<rerunFailingTestsCount>${unit.test.rerun.count}</rerunFailingTestsCount>
<!-- 60 minutes -->
<forkedProcessTimeoutInSeconds>3600</forkedProcessTimeoutInSeconds>
<!-- Disable zookeeper force sync -->
<systemPropertyVariables>
<zookeeper.forceSync>no</zookeeper.forceSync>
+ <!-- Expose the 1-based fork index so tests can offset port
bases / temp dirs per
+ fork (1 even at forkCount=1, 1..N under parallel forks). -->
+
<surefire.forkNumber>$${surefire.forkNumber}</surefire.forkNumber>
</systemPropertyVariables>
<trimStackTrace>false</trimStackTrace>
<reportFormat>plain</reportFormat>
@@ -2513,8 +2556,32 @@
<excludes>
<exclude>**/*IT.java</exclude>
</excludes>
- <forkCount>1</forkCount>
+ <!-- forkCount is overridable via -Dunit.test.fork.count (defaults
to 1). Each
+ fork runs a distinct test class (reuseForks=false), so raising
the count
+ parallelizes classes across JVMs while preserving class-level
isolation. -->
+ <forkCount>${unit.test.fork.count}</forkCount>
<reuseForks>false</reuseForks>
+ <!-- Retries a failing test up to N times before marking it failed
(default 0 = no
+ retry). CI sets this to tolerate a handful of pre-existing
load-sensitive flaky
+ tests (Lucene NRT refresh, filesystem mtime) that surface only
when many parallel
+ forks saturate the runner; a test that passes on retry is
reported as flaky, not
+ green-washed. -->
+
<rerunFailingTestsCount>${unit.test.rerun.count}</rerunFailingTestsCount>
+ <properties>
+ <!-- Surefire is the default report writer; modules can explicitly
opt into an isolated
+ reporter. TestNG's native HTML/XML reporters write shared
files and assets, which
+ race when multiple forks use one module. -->
+ <property>
+ <name>usedefaultlisteners</name>
+ <value>false</value>
+ </property>
+ </properties>
+ <systemPropertyVariables>
+ <!-- Expose the 1-based fork index (1 even at forkCount=1, 1..N
under parallel forks)
+ so tests can offset port bases / temp dirs per fork (see
ZkStarter.FORK_PORT_OFFSET,
+ ControllerTest port bases). -->
+ <surefire.forkNumber>$${surefire.forkNumber}</surefire.forkNumber>
+ </systemPropertyVariables>
</configuration>
<executions>
<execution>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]