Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
f363428
added neo4j functions tests
Feb 15, 2026
2376022
fixed factory
Feb 15, 2026
cdec6bb
Merge branch 'ArcadeData:main' into more_tests
ExtReMLapin Feb 15, 2026
44d0c39
Merge branch 'ArcadeData:main' into more_tests
ExtReMLapin Feb 15, 2026
be84308
added elementid() (uses ID())
Feb 15, 2026
1ba12c7
Revert "added elementid() (uses ID())"
Feb 15, 2026
1d0342e
Merge branch 'ArcadeData:main' into more_tests
ExtReMLapin Feb 15, 2026
6488c38
fixed some tests (expect 64bit, not 32)
Feb 15, 2026
e8375db
more 64bit fixes
Feb 15, 2026
a41ff64
fixed some errors
Feb 15, 2026
ca38e62
more errors fixes
Feb 15, 2026
703eba0
Merge branch 'ArcadeData:main' into more_tests
ExtReMLapin Feb 16, 2026
a8f9dcd
Update engine/src/test/java/com/arcadedb/query/opencypher/functions/O…
ExtReMLapin Feb 16, 2026
ddc6dbf
Update engine/src/test/java/com/arcadedb/query/opencypher/functions/O…
ExtReMLapin Feb 16, 2026
99aa587
Merge branch 'ArcadeData:main' into more_tests
ExtReMLapin Feb 16, 2026
c454c1c
fixed compilation error
Feb 18, 2026
c826fe5
Merge branch 'ArcadeData:main' into more_tests
ExtReMLapin Mar 19, 2026
16af5f2
fixed exception not being detected
Mar 19, 2026
00afff9
fixed missing exceptions
Mar 19, 2026
64e2abd
updated tests
Mar 19, 2026
8280281
updated tests
Mar 20, 2026
3b6fd79
Coll insert/remove force second arg
Mar 20, 2026
6a23fdf
point.distance cypher
Mar 20, 2026
9dff309
cypher point use map like cypher, not like sql
Mar 20, 2026
0762c40
geo utils support map xy or longitude latitude
Mar 20, 2026
91407e5
left support two args error and neg len error
Mar 20, 2026
2c5f0f0
two args and neg len
Mar 20, 2026
6275cb2
force 3 args for Replace function
Mar 20, 2026
69e265d
lTrim support two args
Mar 20, 2026
50ec604
rtrim two args
Mar 20, 2026
28f6a6e
substring better errors handling
Mar 20, 2026
87e67e6
sync
Mar 20, 2026
2f591d6
Round added precision and mode
Mar 20, 2026
3266b9b
added timezones
Mar 20, 2026
7e9e0c6
updated vectors
Mar 20, 2026
ce445f6
sync
Mar 20, 2026
f7b0fb0
SQLFunctionStandardDeviation now returns 0.0 instead of null
Mar 20, 2026
34c5150
Update engine/src/main/java/com/arcadedb/function/geo/CypherPointFunc…
ExtReMLapin Mar 20, 2026
ef55e43
updated old test
Mar 20, 2026
14fa415
Merge branch 'ArcadeData:main' into more_tests
ExtReMLapin Apr 18, 2026
8e79172
sync
Apr 18, 2026
f8f942c
sync
Apr 18, 2026
867ccca
support for parallel tests running + isolation
Apr 18, 2026
f58e1ad
fixed config print
Apr 18, 2026
b09a93f
fixed codacy being a crybaby
Apr 18, 2026
136f775
Merge branch 'main' into more_test_fast_tests
ExtReMLapin Apr 22, 2026
05758f2
removed whitespace
ExtReMLapin Apr 22, 2026
24af8f3
removed whitespace
ExtReMLapin Apr 22, 2026
2ea2ee0
removed whitespace
ExtReMLapin Apr 22, 2026
3b6117c
removed whitespace
ExtReMLapin Apr 22, 2026
7705b9e
removed whitespace
ExtReMLapin Apr 22, 2026
15b72ba
removed whitespace
ExtReMLapin Apr 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,10 @@ cd package
### Testing Commands
- **Run specific test class**: `mvn test -Dtest=ClassName`
- **Run tests with specific pattern**: `mvn test -Dtest="*Pattern*"`
- **Run without slow/benchmark tests**: `mvn test -pl engine -DskipITs -Dgroups='!slow,!benchmark'`
- **Override fork count** (e.g. all cores): `mvn test -Dforkcount=1C`
- **Performance tests**: Located in `src/test/java/performance/` packages
- **Parallel execution**: enabled by default - classes run concurrently across JVM forks; methods within a class run sequentially. Tests that mutate `GlobalConfiguration` are annotated `@ResourceLock("GlobalConfiguration")` to serialize with each other.

## Codebase Navigation Map

Expand Down
20 changes: 20 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,26 @@ Build and run default tests:
$ mvn clean install
```

Tests run in parallel by default: classes execute concurrently across multiple JVM forks (`forkCount=0.5C`, i.e. half the available CPU cores). No extra flags needed.

Run only unit tests for the engine module, skipping slow/benchmark tests:

```shell
$ mvn test -pl engine -DskipITs -Dgroups='!slow,!benchmark'
```

Override the number of parallel JVM forks (e.g. use all cores):

```shell
$ mvn test -pl engine -DskipITs -Dforkcount=1C
```

Run a single test class:

```shell
$ mvn test -pl engine -Dtest=MyTestClass -DskipITs
```

To run additional integration test locally use:

```shell
Expand Down
25 changes: 12 additions & 13 deletions engine/src/main/java/com/arcadedb/GlobalConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,19 @@ public enum GlobalConfiguration {
// ENVIRONMENT
DUMP_CONFIG_AT_STARTUP("arcadedb.dumpConfigAtStartup", SCOPE.JVM, "Dumps the configuration at startup", Boolean.class, false,
value -> {
//dumpConfiguration(System.out);

try {
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
dumpConfiguration(new PrintStream(buffer));
if (LogManager.instance() != null)
LogManager.instance().log(buffer, Level.WARNING, new String(buffer.toByteArray()));
else
System.out.println(new String(buffer.toByteArray()));
if (Boolean.TRUE.equals(value))
try {
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
dumpConfiguration(new PrintStream(buffer));
if (LogManager.instance() != null)
LogManager.instance().log(buffer, Level.WARNING, new String(buffer.toByteArray()));
else
System.out.println(new String(buffer.toByteArray()));

buffer.close();
} catch (IOException e) {
System.out.println("Error on printing initial configuration to log (error=" + e + ")");
}
buffer.close();
} catch (IOException e) {
System.out.println("Error on printing initial configuration to log (error=" + e + ")");
}

return value;
}),
Expand Down
4 changes: 4 additions & 0 deletions engine/src/test/java/com/arcadedb/ACIDTransactionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,12 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import org.junit.jupiter.api.parallel.Isolated;
import org.junit.jupiter.api.parallel.ResourceLock;

@Tag("slow")
@Isolated
@ResourceLock("GlobalConfiguration")
class ACIDTransactionTest extends TestHelper {
@Test
void asyncTX() {
Expand Down
2 changes: 2 additions & 0 deletions engine/src/test/java/com/arcadedb/CompareParserAST.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@

import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.parallel.ResourceLock;

/**
* Compares the AST generated by ANTLR and JavaCC parsers for the same MATCH query.
*/
@ResourceLock("GlobalConfiguration")
public class CompareParserAST {
public static void main(String[] args) {
DatabaseFactory factory = new DatabaseFactory("./target/databases/compare-parser");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import org.junit.jupiter.api.parallel.ResourceLock;

@ResourceLock("GlobalConfiguration")
class GlobalConfigurationTest extends TestHelper {
@Test
void maxPageRAMAutoTune() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@
import java.util.logging.*;

import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.parallel.ResourceLock;

@ResourceLock("GlobalConfiguration")
class RandomTestMultiThreadsTest extends TestHelper {
private static final int CYCLES = 10000;
private static final int STARTING_ACCOUNT = 10000;
Expand Down
42 changes: 32 additions & 10 deletions engine/src/test/java/com/arcadedb/TestHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@

import java.io.File;
import java.util.Collection;
import java.util.EnumMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
Expand All @@ -43,10 +45,13 @@
import static org.assertj.core.api.Assertions.fail;

public abstract class TestHelper {
protected static final int PARALLEL_LEVEL = 4;
protected static final int PARALLEL_LEVEL = 4;
protected final DatabaseFactory factory;
protected Database database;
protected boolean autoStartTx = false;
protected boolean autoStartTx = false;

private static final Object ACTIVE_DB_LOCK = new Object();
private Map<GlobalConfiguration, Object> configSnapshot;
Comment on lines +53 to +54
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Since captureConfigSnapshot is called before every test method, caching the GlobalConfiguration.values() array in a constant can avoid repeated array allocations.

Suggested change
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;


public interface DatabaseTest<PAR> {
void call(PAR iArgument) throws Exception;
Expand Down Expand Up @@ -158,6 +163,7 @@ protected void endTest() {

@BeforeEach
public void beforeTest() {
configSnapshot = captureConfigSnapshot();
GlobalConfiguration.SERVER_ROOT_PATH.setValue("./target");
if (autoStartTx && !database.isTransactionActive())
database.begin();
Expand All @@ -184,14 +190,28 @@ public void afterTest() {

checkActiveDatabases();
FileUtils.deleteRecursively(new File(getDatabasePath()));
GlobalConfiguration.resetAll();
restoreConfigSnapshot(configSnapshot);
}

@AfterAll
public static void endAllTests() {
GlobalConfiguration.resetAll();
}

private static Map<GlobalConfiguration, Object> captureConfigSnapshot() {
final Map<GlobalConfiguration, Object> snapshot = new EnumMap<>(GlobalConfiguration.class);
for (final GlobalConfiguration v : GlobalConfiguration.values())
snapshot.put(v, v.getValue());
return snapshot;
}

private static void restoreConfigSnapshot(final Map<GlobalConfiguration, Object> snapshot) {
if (snapshot == null)
return;
for (final Map.Entry<GlobalConfiguration, Object> e : snapshot.entrySet())
e.getKey().setValue(e.getValue());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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);

}

protected String getPerformanceProfile() {
return "default";
}
Expand Down Expand Up @@ -227,15 +247,17 @@ protected void checkDatabaseIntegrity() {
}

public static void checkActiveDatabases() {
final Collection<Database> activeDatabases = DatabaseFactory.getActiveDatabaseInstances();
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();
}
Comment on lines +250 to +261
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

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.

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@

import static com.arcadedb.schema.LocalSchema.STATISTICS_FILE_NAME;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.parallel.ResourceLock;

@Tag("slow")
@ResourceLock("GlobalConfiguration")
class RecordRecyclingTest {
private final static int TOT_RECORDS = 100_000;
private final static String VERTEX_TYPE = "Product";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
import java.time.format.DateTimeFormatter;

import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.parallel.ResourceLock;

@ResourceLock("GlobalConfiguration")
class TestInsertAndSelectWithThreadBucketSelectionStrategy {

@BeforeEach
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class GeomFromText {

@Test
void sqlHappyPath() throws Exception {
TestHelper.executeInNewDatabase("GeoDatabase", (db) -> {
TestHelper.executeInNewDatabase((db) -> {
final ResultSet result = db.query("sql", "select geo.geomFromText('POINT (10 20)') as geom");
assertThat(result.hasNext()).isTrue();
final Object geom = result.next().getProperty("geom");
Expand All @@ -58,7 +58,7 @@ void javaExecuteHappyPath() {

@Test
void nullInput_sql_returnsNull() throws Exception {
TestHelper.executeInNewDatabase("GeoDatabase", (db) -> {
TestHelper.executeInNewDatabase((db) -> {
final ResultSet result = db.query("sql", "select geo.geomFromText(null) as geom");
assertThat(result.hasNext()).isTrue();
final Object geom = result.next().getProperty("geom");
Expand Down Expand Up @@ -100,7 +100,7 @@ class Point {

@Test
void sqlHappyPath() throws Exception {
TestHelper.executeInNewDatabase("GeoDatabase", (db) -> {
TestHelper.executeInNewDatabase((db) -> {
final ResultSet result = db.query("sql", "select geo.point(10, 20) as wkt");
assertThat(result.hasNext()).isTrue();
final String wkt = result.next().getProperty("wkt");
Expand All @@ -124,7 +124,7 @@ void javaExecuteHappyPath() {

@Test
void nullFirstArg_sql_returnsNull() throws Exception {
TestHelper.executeInNewDatabase("GeoDatabase", (db) -> {
TestHelper.executeInNewDatabase((db) -> {
final ResultSet result = db.query("sql", "select geo.point(null, 20) as wkt");
assertThat(result.hasNext()).isTrue();
final Object wkt = result.next().getProperty("wkt");
Expand Down Expand Up @@ -164,7 +164,7 @@ class LineString {

@Test
void sqlHappyPath() throws Exception {
TestHelper.executeInNewDatabase("GeoDatabase", (db) -> {
TestHelper.executeInNewDatabase((db) -> {
final ResultSet result = db.query("sql", "select geo.lineString([[0,0],[10,10],[20,0]]) as wkt");
assertThat(result.hasNext()).isTrue();
final String wkt = result.next().getProperty("wkt");
Expand Down Expand Up @@ -193,7 +193,7 @@ void javaExecuteHappyPath() {

@Test
void nullInput_sql_returnsNull() throws Exception {
TestHelper.executeInNewDatabase("GeoDatabase", (db) -> {
TestHelper.executeInNewDatabase((db) -> {
final ResultSet result = db.query("sql", "select geo.lineString(null) as wkt");
assertThat(result.hasNext()).isTrue();
final Object wkt = result.next().getProperty("wkt");
Expand Down Expand Up @@ -239,7 +239,7 @@ class Polygon {

@Test
void sqlHappyPath() throws Exception {
TestHelper.executeInNewDatabase("GeoDatabase", (db) -> {
TestHelper.executeInNewDatabase((db) -> {
final ResultSet result = db.query("sql", "select geo.polygon([[0,0],[10,0],[10,10],[0,10],[0,0]]) as wkt");
assertThat(result.hasNext()).isTrue();
final String wkt = result.next().getProperty("wkt");
Expand All @@ -265,7 +265,7 @@ void javaExecuteHappyPath() {

@Test
void nullInput_sql_returnsNull() throws Exception {
TestHelper.executeInNewDatabase("GeoDatabase", (db) -> {
TestHelper.executeInNewDatabase((db) -> {
final ResultSet result = db.query("sql", "select geo.polygon(null) as wkt");
assertThat(result.hasNext()).isTrue();
final Object wkt = result.next().getProperty("wkt");
Expand All @@ -281,7 +281,7 @@ void nullInput_execute_returnsNull() {

@Test
void openRing_sql_autoClose() throws Exception {
TestHelper.executeInNewDatabase("GeoDatabase", (db) -> {
TestHelper.executeInNewDatabase((db) -> {
final ResultSet result = db.query("sql", "select geo.polygon([[0,0],[10,0],[10,10],[0,10]]) as wkt");
assertThat(result.hasNext()).isTrue();
final String wkt = result.next().getProperty("wkt");
Expand Down
Loading
Loading