Enable tests to run in parallel by default#3895
Enable tests to run in parallel by default#3895ExtReMLapin wants to merge 52 commits intoArcadeData:mainfrom
Conversation
This reverts commit be84308.
…penCypherAggregatingFunctionsComprehensiveTest.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…penCypherAggregatingFunctionsComprehensiveTest.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…tion.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Code Review
This pull request significantly expands OpenCypher function support, adding geospatial, temporal, vector, and string functions along with GQL-conformant aliases. It also improves test parallelization by updating the TestHelper and implementing resource locks across the test suite. Feedback focuses on fixing a potential NumberFormatException for empty vector strings, ensuring split() preserves trailing empty strings per Cypher specifications, restoring robustness in point() coordinate parsing, and handling potential nulls or incorrect types in map-based distance calculations.
| final String inner = trimmed.startsWith("[") && trimmed.endsWith("]") ? trimmed.substring(1, trimmed.length() - 1) : trimmed; | ||
| final String[] parts = inner.split(","); | ||
| final float[] result = new float[parts.length]; |
There was a problem hiding this comment.
The current parsing logic will throw a NumberFormatException if the input string represents an empty array []. When inner is an empty string, split(",") returns an array containing one empty string, which Float.parseFloat() cannot handle. Additionally, it doesn't handle cases with extra commas or whitespace between values gracefully.
| final String inner = trimmed.startsWith("[") && trimmed.endsWith("]") ? trimmed.substring(1, trimmed.length() - 1) : trimmed; | |
| final String[] parts = inner.split(","); | |
| final float[] result = new float[parts.length]; | |
| final String inner = trimmed.startsWith("[") && trimmed.endsWith("]") ? trimmed.substring(1, trimmed.length() - 1).trim() : trimmed; | |
| if (inner.isEmpty()) | |
| return new float[0]; | |
| final String[] parts = inner.split(","); | |
| final float[] result = new float[parts.length]; |
| return null; | ||
| final String str = args[0].toString(); | ||
| final String delimiter = args[1].toString(); | ||
| return List.of(str.split(Pattern.quote(delimiter))); |
There was a problem hiding this comment.
Java's String.split(regex) discards trailing empty strings by default. To comply with the Cypher specification, which expects trailing empty strings to be preserved (e.g., split('a,b,', ',') should return ['a', 'b', '']), you should use the two-argument version of split with a negative limit.
| return List.of(str.split(Pattern.quote(delimiter))); | |
| return List.of(str.split(Pattern.quote(delimiter), -1)); |
| final double lat = ((Number) args[0]).doubleValue(); | ||
| final double lon = ((Number) args[1]).doubleValue(); |
There was a problem hiding this comment.
This change reduces robustness compared to the previous implementation. The previous code used GeoUtils.getDoubleValue(), which safely handles both Number and String inputs. The direct cast to Number will throw a ClassCastException if the input is a string representation of a coordinate.
| final double lat = ((Number) args[0]).doubleValue(); | |
| final double lon = ((Number) args[1]).doubleValue(); | |
| final double lat = com.arcadedb.function.sql.geo.GeoUtils.getDoubleValue(args[0]); | |
| final double lon = com.arcadedb.function.sql.geo.GeoUtils.getDoubleValue(args[1]); |
| ((Number) p1.get("latitude")).doubleValue(), ((Number) p1.get("longitude")).doubleValue(), | ||
| ((Number) p2.get("latitude")).doubleValue(), ((Number) p2.get("longitude")).doubleValue()); |
There was a problem hiding this comment.
This code is unsafe as it assumes the map values are non-null and of type Number. If a coordinate is null in the map (which is possible in Cypher), this will throw a NullPointerException. If it's a String, it will throw a ClassCastException. It is safer to use GeoUtils.getDoubleValue() after verifying the values are not null.
Up to standards ✅🟢 Issues
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #3895 +/- ##
============================================
- Coverage 64.71% 56.53% -8.19%
- Complexity 0 1572 +1572
============================================
Files 1581 1585 +4
Lines 117023 117508 +485
Branches 24858 24957 +99
============================================
- Hits 75730 66431 -9299
- Misses 30933 41743 +10810
+ Partials 10360 9334 -1026 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
/gemini review |
|
This was 100% vibecoded and tested by qwen 27b |
There was a problem hiding this comment.
Code Review
This pull request introduces parallel test execution by enabling JUnit 5 class-level concurrency and increasing Maven fork counts. Key changes include updates to TestHelper for capturing and restoring GlobalConfiguration snapshots, adding @ResourceLock annotations to various test classes, and refining configuration dumping logic. Review feedback identifies significant risks with concurrent class execution due to shared global state, recommending that classes run sequentially within forks to avoid flakiness. Additionally, suggestions were made to optimize the configuration restoration logic and cache configuration values to reduce overhead.
| # Parallel test execution: classes run concurrently, methods within a class run sequentially | ||
| junit.jupiter.execution.parallel.enabled=true | ||
| junit.jupiter.execution.parallel.mode.default=same_thread | ||
| junit.jupiter.execution.parallel.mode.classes.default=concurrent |
There was a problem hiding this comment.
Enabling concurrent execution of test classes within the same JVM is highly risky for this codebase. Many tests (via TestHelper) mutate the static GlobalConfiguration and other global states. While some tests have been annotated with @ResourceLock, any test that lacks this annotation will still run in parallel and potentially interfere with others, leading to race conditions and flaky results. Since parallelism is already provided by Maven forks (forkCount in pom.xml), it is much safer to run classes sequentially within each fork.
junit.jupiter.execution.parallel.mode.classes.default=same_thread
| synchronized (ACTIVE_DB_LOCK) { | ||
| final Collection<Database> activeDatabases = DatabaseFactory.getActiveDatabaseInstances(); | ||
|
|
||
| if (!activeDatabases.isEmpty()) | ||
| LogManager.instance() | ||
| .log(TestHelper.class, Level.SEVERE, "Found active databases: " + activeDatabases + ". Forced closing..."); | ||
| if (!activeDatabases.isEmpty()) | ||
| LogManager.instance() | ||
| .log(TestHelper.class, Level.SEVERE, "Found active databases: " + activeDatabases + ". Forced closing..."); | ||
|
|
||
| for (final Database db : activeDatabases) | ||
| db.close(); | ||
| for (final Database db : activeDatabases) | ||
| db.close(); | ||
|
|
||
| assertThat(activeDatabases.isEmpty()).as("Found active databases: " + activeDatabases).isTrue(); | ||
| assertThat(activeDatabases.isEmpty()).as("Found active databases: " + activeDatabases).isTrue(); | ||
| } |
There was a problem hiding this comment.
This synchronization only prevents multiple threads from executing the checkActiveDatabases logic simultaneously. It does not protect against other concurrent tests (running in different threads within the same JVM) opening or closing databases while this check is in progress. In a parallel execution environment, this will likely lead to intermittent test failures when one test's cleanup phase overlaps with another test's setup phase. Disabling class-level parallelism in junit-platform.properties is the recommended fix.
| if (snapshot == null) | ||
| return; | ||
| for (final Map.Entry<GlobalConfiguration, Object> e : snapshot.entrySet()) | ||
| e.getKey().setValue(e.getValue()); |
There was a problem hiding this comment.
Restoring every configuration value after every test method is expensive, especially since setValue can trigger side effects like logging or configuration dumping. It is more efficient to only restore values that were actually modified during the test execution.
final GlobalConfiguration config = e.getKey();
final Object value = e.getValue();
if (value != null && !value.equals(config.getValue()))
config.setValue(value);| private static final Object ACTIVE_DB_LOCK = new Object(); | ||
| private Map<GlobalConfiguration, Object> configSnapshot; |
There was a problem hiding this comment.
Since captureConfigSnapshot is called before every test method, caching the GlobalConfiguration.values() array in a constant can avoid repeated array allocations.
| private static final Object ACTIVE_DB_LOCK = new Object(); | |
| private Map<GlobalConfiguration, Object> configSnapshot; | |
| private static final Object ACTIVE_DB_LOCK = new Object(); | |
| private static final GlobalConfiguration[] CONFIG_VALUES = GlobalConfiguration.values(); | |
| private Map<GlobalConfiguration, Object> configSnapshot; |
|
I'm not a java guy so I have no idea what i'm doing |
…skip ci] Bumps [org.postgresql:postgresql](https://github.com/pgjdbc/pgjdbc) from 42.7.10 to 42.7.11. Release notes *Sourced from [org.postgresql:postgresql's releases](https://github.com/pgjdbc/pgjdbc/releases).* > v42.7.11 > -------- > > Security > -------- > > * fix: Limit SCRAM PBKDF2 iterations accepted from the server. > pgjdbc was vulnerable to a client-side denial of service in SCRAM-SHA-256 authentication, where a malicious or compromised PostgreSQL server could specify an extremely large PBKDF2 iteration count, causing the client to consume unbounded CPU and potentially exhaust connection pools. The fix introduces a new scramMaxIterations connection property (defaulting to 100,000) to cap iteration counts before computation begins. > See the [Security Advisory](GHSA-98qh-xjc8-98pq) for more detail. > The following [CVE-2026-42198](https://nvd.nist.gov/vuln/detail/CVE-2026-42198) has been issued. > > Changes > ------- > > * fix: Add sources and javadocs to shaded published lib generation [`@sehrope`](https://github.com/sehrope) ([#4043](https://redirect.github.com/pgjdbc/pgjdbc/issues/4043)) > * update Changelog and website for release of 42.7.11 [`@davecramer`](https://github.com/davecramer) ([#4042](https://redirect.github.com/pgjdbc/pgjdbc/issues/4042)) > * Fix scram fix location in changelog and update published artifact developer list [`@sehrope`](https://github.com/sehrope) ([#4041](https://redirect.github.com/pgjdbc/pgjdbc/issues/4041)) > * Restrict test with scram\_iterations to v16+ and release notes [`@sehrope`](https://github.com/sehrope) ([#4040](https://redirect.github.com/pgjdbc/pgjdbc/issues/4040)) > * chore(deps): update ubuntu:24.04 docker digest to 84e77de [`@renovate-bot`](https://github.com/renovate-bot) ([#4017](https://redirect.github.com/pgjdbc/pgjdbc/issues/4017)) > * test: add tests for QueryExecutor#getTransactionState [`@vlsi`](https://github.com/vlsi) ([#4006](https://redirect.github.com/pgjdbc/pgjdbc/issues/4006)) > * chore(deps): update actions/create-github-app-token action to v2.2.2 [`@renovate-bot`](https://github.com/renovate-bot) ([#3983](https://redirect.github.com/pgjdbc/pgjdbc/issues/3983)) > * fix: fix flaky CopyBothResponseTest by using WAL flush LSN [`@vlsi`](https://github.com/vlsi) ([#3979](https://redirect.github.com/pgjdbc/pgjdbc/issues/3979)) > * fix: fix flaky replication restart tests by waiting for confirmed\_flush\_lsn [`@vlsi`](https://github.com/vlsi) ([#3975](https://redirect.github.com/pgjdbc/pgjdbc/issues/3975)) > * test: fix flaky LogicalReplicationStatusTest by polling pg\_stat\_replication [`@vlsi`](https://github.com/vlsi) ([#3974](https://redirect.github.com/pgjdbc/pgjdbc/issues/3974)) > * chore: replace Appveyor with ikalnytskyi/action-setup-postgres [`@vlsi`](https://github.com/vlsi) ([#3966](https://redirect.github.com/pgjdbc/pgjdbc/issues/3966)) > * test: move test table creation from [`@BeforeEach`](https://github.com/BeforeEach) to [`@BeforeAll`](https://github.com/BeforeAll) [`@vlsi`](https://github.com/vlsi) ([#3967](https://redirect.github.com/pgjdbc/pgjdbc/issues/3967)) > * Return jsonb as PGObject fixes Issue [#3926](https://redirect.github.com/pgjdbc/pgjdbc/issues/3926) [`@davecramer`](https://github.com/davecramer) ([#3956](https://redirect.github.com/pgjdbc/pgjdbc/issues/3956)) > * Update docker scripts [`@davecramer`](https://github.com/davecramer) ([#3958](https://redirect.github.com/pgjdbc/pgjdbc/issues/3958)) > * implement require\_auth, this is pretty much how libpq does this. [`@davecramer`](https://github.com/davecramer) ([#3895](https://redirect.github.com/pgjdbc/pgjdbc/issues/3895)) > * docs: add SCRAM authentication test setup section to TESTING.md [`@emmaeng700`](https://github.com/emmaeng700) ([#3945](https://redirect.github.com/pgjdbc/pgjdbc/issues/3945)) > * Add RequireServerVersion annotation for tests [`@sehrope`](https://github.com/sehrope) ([#3939](https://redirect.github.com/pgjdbc/pgjdbc/issues/3939)) > > 🐛 Bug Fixes > ----------- > > * fix: ensure extended protocol messages end with Sync message [`@vlsi`](https://github.com/vlsi) ([#3728](https://redirect.github.com/pgjdbc/pgjdbc/issues/3728)) > * fix: enable cursor-based fetching in extended protocol when transaction started via SQL command [`@vlsi`](https://github.com/vlsi) ([#3996](https://redirect.github.com/pgjdbc/pgjdbc/issues/3996)) > * fix: retry with SSL on IOException when sslMode=ALLOW [`@vlsi`](https://github.com/vlsi) ([#3973](https://redirect.github.com/pgjdbc/pgjdbc/issues/3973)) > * fix: allow fallback to non-SSL connection when sslMode=prefer and sslResponseTimeout kicks in [`@vlsi`](https://github.com/vlsi) ([#3968](https://redirect.github.com/pgjdbc/pgjdbc/issues/3968)) > * fix: catch SecurityException from setContextClassLoader on ForkJoinPool workers [`@vlsi`](https://github.com/vlsi) ([#3962](https://redirect.github.com/pgjdbc/pgjdbc/issues/3962)) > * fix: use compareTo for LogSequenceNumber comparison [`@vlsi`](https://github.com/vlsi) ([#3961](https://redirect.github.com/pgjdbc/pgjdbc/issues/3961)) > * fix: release COPY lock on IOException to prevent connection hang ([#3957](https://redirect.github.com/pgjdbc/pgjdbc/issues/3957)) [`@vlsi`](https://github.com/vlsi) ([#3960](https://redirect.github.com/pgjdbc/pgjdbc/issues/3960)) > > 🧰 Maintenance > ------------- > > * style: replace [`@exception`](https://github.com/exception) with [`@throws`](https://github.com/throws) in getBoolean javadoc [`@vlsi`](https://github.com/vlsi) ([#4035](https://redirect.github.com/pgjdbc/pgjdbc/issues/4035)) > * chore: use `@vlsi/github-actions-random-matrix` npm package [`@vlsi`](https://github.com/vlsi) ([#4008](https://redirect.github.com/pgjdbc/pgjdbc/issues/4008)) > * chore: use tag names for pinning github actions, pin ikalnytskyi/action-setup-postgres [`@vlsi`](https://github.com/vlsi) ([#4007](https://redirect.github.com/pgjdbc/pgjdbc/issues/4007)) > * chore: bump errorprone to 2.48.0 [`@vlsi`](https://github.com/vlsi) ([#4005](https://redirect.github.com/pgjdbc/pgjdbc/issues/4005)) > * test: add [`@DisableLogger`](https://github.com/DisableLogger) annotation to suppress expected log warnings in tests [`@vlsi`](https://github.com/vlsi) ([#3971](https://redirect.github.com/pgjdbc/pgjdbc/issues/3971)) > * chore: suppress deprecations in test code to reduce build verbosity [`@vlsi`](https://github.com/vlsi) ([#3972](https://redirect.github.com/pgjdbc/pgjdbc/issues/3972)) > * chore: replace log warning in ConnectionFactory.closeStream with Throwable.addSuppressed [`@vlsi`](https://github.com/vlsi) ([#3970](https://redirect.github.com/pgjdbc/pgjdbc/issues/3970)) > * chore: use greedy pairwise coverage for CI matrix generation [`@vlsi`](https://github.com/vlsi) ([#3965](https://redirect.github.com/pgjdbc/pgjdbc/issues/3965)) > * chore: use full version tags in GitHub Actions comments [`@vlsi`](https://github.com/vlsi) ([#3963](https://redirect.github.com/pgjdbc/pgjdbc/issues/3963)) > > ⬆️ Dependencies > --------------- ... (truncated) Changelog *Sourced from [org.postgresql:postgresql's changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md).* > [42.7.11] (2026-04-28) > ---------------------- > > ### Security > > * fix: Limit SCRAM PBKDF2 iterations accepted from the server. > pgjdbc was vulnerable to a client-side denial of service in SCRAM-SHA-256 authentication, where a malicious or compromised PostgreSQL server could specify an extremely large PBKDF2 iteration count, causing the client to consume unbounded CPU and potentially exhaust connection pools. The fix introduces a new scramMaxIterations connection property (defaulting to 100,000) to cap iteration counts before computation begins. > See the [Security Advisory](GHSA-98qh-xjc8-98pq) for more detail. > The following [CVE-2026-42198](https://nvd.nist.gov/vuln/detail/CVE-2026-42198) has been issued. > > ### Added > > * feat: implement require\_auth connection property, aligning with libpq behavior [PR [#3895](https://redirect.github.com/pgjdbc/pgjdbc/issues/3895)]([pgjdbc/pgjdbc#3895](https://redirect.github.com/pgjdbc/pgjdbc/pull/3895)) > > ### Changed > > * chore: replace Appveyor CI with ikalnytskyi/action-setup-postgres [PR [#3966](https://redirect.github.com/pgjdbc/pgjdbc/issues/3966)]([pgjdbc/pgjdbc#3966](https://redirect.github.com/pgjdbc/pgjdbc/pull/3966)) > * chore: upgrade Gradle to v9 [PR [#3978](https://redirect.github.com/pgjdbc/pgjdbc/issues/3978)]([pgjdbc/pgjdbc#3978](https://redirect.github.com/pgjdbc/pgjdbc/pull/3978)) > > ### Fixed > > * fix: ensure extended protocol messages end with Sync message [PR [#3728](https://redirect.github.com/pgjdbc/pgjdbc/issues/3728)]([pgjdbc/pgjdbc#3728](https://redirect.github.com/pgjdbc/pgjdbc/pull/3728)) > * fix: enable cursor-based fetching in extended protocol when transaction started via SQL command [PR [#3996](https://redirect.github.com/pgjdbc/pgjdbc/issues/3996)]([pgjdbc/pgjdbc#3996](https://redirect.github.com/pgjdbc/pgjdbc/pull/3996)) > * fix: retry with SSL on IOException when sslMode=ALLOW [PR [#3973](https://redirect.github.com/pgjdbc/pgjdbc/issues/3973)]([pgjdbc/pgjdbc#3973](https://redirect.github.com/pgjdbc/pgjdbc/pull/3973)) > * fix: make sure the driver honours connectTimeout when retrying the connection [PR [#3968](https://redirect.github.com/pgjdbc/pgjdbc/issues/3968)]([pgjdbc/pgjdbc#3968](https://redirect.github.com/pgjdbc/pgjdbc/pull/3968)) > * fix: allow fallback to non-SSL connection when sslMode=prefer and sslResponseTimeout kicks in [PR [#3968](https://redirect.github.com/pgjdbc/pgjdbc/issues/3968)]([pgjdbc/pgjdbc#3968](https://redirect.github.com/pgjdbc/pgjdbc/pull/3968)) > * fix: catch SecurityException from setContextClassLoader on ForkJoinPool workers [PR [#3962](https://redirect.github.com/pgjdbc/pgjdbc/issues/3962)]([pgjdbc/pgjdbc#3962](https://redirect.github.com/pgjdbc/pgjdbc/pull/3962)) > * fix: use compareTo for LogSequenceNumber comparison to handle unsigned values correctly [PR [#3961](https://redirect.github.com/pgjdbc/pgjdbc/issues/3961)]([pgjdbc/pgjdbc#3961](https://redirect.github.com/pgjdbc/pgjdbc/pull/3961)) > * fix: release COPY lock on IOException to prevent connection hang [PR [#3957](https://redirect.github.com/pgjdbc/pgjdbc/issues/3957)]([pgjdbc/pgjdbc#3957](https://redirect.github.com/pgjdbc/pgjdbc/pull/3957)) > * fix: return jsonb as PGObject instead of String [PR [#3956](https://redirect.github.com/pgjdbc/pgjdbc/issues/3956)]([pgjdbc/pgjdbc#3956](https://redirect.github.com/pgjdbc/pgjdbc/pull/3956)) > * fix: align SSL key file permission check with libpq [PR [#3952](https://redirect.github.com/pgjdbc/pgjdbc/issues/3952)]([pgjdbc/pgjdbc#3952](https://redirect.github.com/pgjdbc/pgjdbc/pull/3952)) > * fix: guard connection closed flag with a reentrant lock to protect against concurrent close [PR [#3905](https://redirect.github.com/pgjdbc/pgjdbc/issues/3905)]([pgjdbc/pgjdbc#3905](https://redirect.github.com/pgjdbc/pgjdbc/pull/3905)) Commits * [`78e261f`](pgjdbc/pgjdbc@78e261f) fix: Add sources and javadocs to shaded published lib generation * [`1e09fa0`](pgjdbc/pgjdbc@1e09fa0) update Changelog and website for release of 42.7.11 ([#4042](https://redirect.github.com/pgjdbc/pgjdbc/issues/4042)) * [`d479fa5`](pgjdbc/pgjdbc@d479fa5) Fix scram fix location in changelog and update published artifact developer l... * [`b04fc46`](pgjdbc/pgjdbc@b04fc46) docs: Add scram max iters fix to changelog * [`cf54822`](pgjdbc/pgjdbc@cf54822) test: Disable scram test on older version without scram\_iterations GUC * [`7dbcc79`](pgjdbc/pgjdbc@7dbcc79) test: Add SCRAM max iteration tests * [`c9d41d1`](pgjdbc/pgjdbc@c9d41d1) fix: Limit SCRAM PBKDF2 iterations accepted from the server * [`a340cb2`](pgjdbc/pgjdbc@a340cb2) style: replace [`@exception`](https://github.com/exception) with [`@throws`](https://github.com/throws) in getBoolean javadoc * [`77837f8`](pgjdbc/pgjdbc@77837f8) fix(deps): update dependency org.openrewrite.rewrite:org.openrewrite.rewrite.... * [`23af03b`](pgjdbc/pgjdbc@23af03b) chore(deps): update actions/checkout action to v6 * Additional commits viewable in [compare view](pgjdbc/pgjdbc@REL42.7.10...REL42.7.11) [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- Dependabot commands and options You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
To be merged after #3428