diff --git a/pom.xml b/pom.xml index cabbfb2..a9ac289 100644 --- a/pom.xml +++ b/pom.xml @@ -1,59 +1,60 @@ - - 4.0.0 - - - org.sonatype.oss - oss-parent - 7 - - - com.falkordb - jfalkordb - 0.5.1-SNAPSHOT - jar - - JFalkorDB - Official client for FalkorDB - https://www.falkordb.com - - - FalkorDB - https://www.falkordb.com - - - - CircleCI - https://circleci.com/gh/FalkorDB/JFalkorDB - - - - GitHub - https://github.com/FalkorDB/JFalkorDB/issues - - - - https://github.com/FalkorDB/JFalkorDB - scm:git:git://github.com/FalkorDB/JFalkorDB.git - scm:git:git@github.com:FalkorDB/JFalkorDB.git - - - - - BSD 3-Clause - https://opensource.org/licenses/BSD-3-Clause - repo - - - - - - gkorland - Guy Korland - gkorland@gmail.com - - + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + 4.0.0 + + + org.sonatype.oss + oss-parent + 7 + + + com.falkordb + jfalkordb + 0.5.1-SNAPSHOT + jar + + JFalkorDB + Official client for FalkorDB + https://www.falkordb.com + + + FalkorDB + https://www.falkordb.com + + + + CircleCI + https://circleci.com/gh/FalkorDB/JFalkorDB + + + + GitHub + https://github.com/FalkorDB/JFalkorDB/issues + + + + https://github.com/FalkorDB/JFalkorDB + scm:git:git://github.com/FalkorDB/JFalkorDB.git + scm:git:git@github.com:FalkorDB/JFalkorDB.git + + + + + BSD 3-Clause + https://opensource.org/licenses/BSD-3-Clause + repo + + + + + + gkorland + Guy Korland + gkorland@gmail.com + + central @@ -62,125 +63,172 @@ central https://central.sonatype.com/repository/maven-snapshots/ - + - - 8 - 8 - - - - - redis.clients - jedis - 6.1.0 - - - org.apache.commons - commons-text - 1.14.0 - - - org.slf4j - slf4j-simple - 2.0.17 - test - - - org.junit.jupiter - junit-jupiter - 5.13.4 - test - - - nl.jqno.equalsverifier - equalsverifier - 3.19.4 - test - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.5.3 - - - - org.jacoco - jacoco-maven-plugin - 0.8.13 - - - - prepare-agent - - - - report - test - - report - - - - - - - org.apache.maven.plugins - maven-source-plugin - 3.3.1 - - - attach-sources - - jar-no-fork - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.11.2 - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 3.2.7 - - - sign-artifacts - verify - - sign - - - - - - org.sonatype.central - central-publishing-maven-plugin - 0.8.0 - true - - central - true - published - - - - + + 8 + 8 + + + + + redis.clients + jedis + 6.1.0 + + + org.apache.commons + commons-text + 1.14.0 + + + org.slf4j + slf4j-simple + 2.0.17 + test + + + org.junit.jupiter + junit-jupiter + 5.13.4 + test + + + nl.jqno.equalsverifier + equalsverifier + 3.19.4 + test + + + org.testcontainers + testcontainers + 1.21.3 + test + + + org.testcontainers + junit-jupiter + 1.21.3 + test + + + com.redis + testcontainers-redis + 2.2.4 + test + + + + + + + + maven-surefire-plugin + + + **/*IT.java + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.5.3 + + + integration-tests + + integration-test + verify + + + + **/*IT.java + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.3 + + + + org.jacoco + jacoco-maven-plugin + 0.8.13 + + + + prepare-agent + + + + report + test + + report + + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.3.1 + + + attach-sources + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.11.2 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.2.7 + + + sign-artifacts + verify + + sign + + + + + + org.sonatype.central + central-publishing-maven-plugin + 0.8.0 + true + + central + true + published + + + + diff --git a/src/test/java/com/falkordb/GraphAPITest.java b/src/test/java/com/falkordb/GraphAPITest.java index a49c31a..46f2ffb 100644 --- a/src/test/java/com/falkordb/GraphAPITest.java +++ b/src/test/java/com/falkordb/GraphAPITest.java @@ -1,33 +1,28 @@ package com.falkordb; -import static org.junit.jupiter.api.Assertions.fail; - -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import org.junit.jupiter.api.Assertions; +import com.falkordb.Statistics.Label; +import com.falkordb.exceptions.GraphException; +import com.falkordb.graph_entities.*; +import com.falkordb.test.BaseTestContainerTestIT; +import com.falkordb.test.utils.PathBuilder; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import com.falkordb.Statistics.Label; -import com.falkordb.exceptions.GraphException; -import com.falkordb.graph_entities.Edge; -import com.falkordb.graph_entities.Node; -import com.falkordb.graph_entities.Path; -import com.falkordb.graph_entities.Point; -import com.falkordb.graph_entities.Property; -import com.falkordb.test.utils.PathBuilder; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.junit.jupiter.api.Assertions.fail; -public class GraphAPITest { +public class GraphAPITest extends BaseTestContainerTestIT { private GraphContextGenerator client; @BeforeEach public void createApi() { - client = FalkorDB.driver().graph("social"); + client = FalkorDB.driver(getFalkordbHost(), getFalkordbPort()).graph("social"); } @AfterEach @@ -293,8 +288,8 @@ public void testRecord() { "r.place", "r.since", "r.doubleValue", "r.boolValue"), record.keys()); Assertions.assertEquals(Arrays.asList(expectedNode, expectedEdge, - name, (long) age, doubleValue, true, - place, (long) since, doubleValue, false), + name, (long) age, doubleValue, true, + place, (long) since, doubleValue, false), record.values()); Node a = record.getValue("a"); @@ -580,8 +575,8 @@ public void testContextedAPI() { "r.place", "r.since", "r.doubleValue", "r.boolValue"), record.keys()); Assertions.assertEquals(Arrays.asList(expectedNode, expectedEdge, - name, (long) age, doubleValue, true, - place, (long) since, doubleValue, false), + name, (long) age, doubleValue, true, + place, (long) since, doubleValue, false), record.values()); Node a = record.getValue("a"); @@ -599,13 +594,13 @@ public void testContextedAPI() { // Test profile functionality in contexted API ResultSet profileResult = c.profile("MATCH (a:person) WHERE (a.name = 'roi') RETURN a.age"); Assertions.assertNotNull(profileResult); - + // Verify profile result structure in contexted API Assertions.assertTrue(profileResult.size() > 0, "Profile result should contain execution plan operations"); Header profileHeader = profileResult.getHeader(); Assertions.assertNotNull(profileHeader, "Profile result should have a header"); Assertions.assertTrue(profileHeader.getSchemaNames().size() > 0, "Profile result header should have columns"); - + // Verify profile result contains meaningful data Iterator profileIterator = profileResult.iterator(); Assertions.assertTrue(profileIterator.hasNext(), "Profile result should have execution plan operations"); @@ -826,7 +821,7 @@ public void testVecf32() { Object res = vector.get(0); // The result can be either Double or Float depending on the server version - if ( res instanceof Double) { + if (res instanceof Double) { List v = r.getValue(0); Assertions.assertEquals(2.1, v.get(0), 0.01); Assertions.assertEquals(-0.82, v.get(1), 0.01); @@ -986,44 +981,44 @@ public void testProfile() { // Create sample data for profiling client.query("CREATE (:person{name:'alice',age:30})"); client.query("CREATE (:person{name:'bob',age:25})"); - + // Test basic profile ResultSet profileResult = client.profile("MATCH (a:person) WHERE (a.name = 'alice') RETURN a.age"); Assertions.assertNotNull(profileResult); - + // Verify profile result has expected structure Assertions.assertTrue(profileResult.size() > 0, "Profile result should contain execution plan operations"); - + // Verify profile result has a header Header header = profileResult.getHeader(); Assertions.assertNotNull(header, "Profile result should have a header"); Assertions.assertTrue(header.getSchemaNames().size() > 0, "Profile result header should have columns"); - + // Verify the profile result contains timing information (execution plan data) // Profile results typically contain execution plan operations with timing data Iterator iterator = profileResult.iterator(); Assertions.assertTrue(iterator.hasNext(), "Profile result should have at least one operation"); - + Record firstRecord = iterator.next(); Assertions.assertNotNull(firstRecord, "Profile result record should not be null"); Assertions.assertTrue(firstRecord.size() > 0, "Profile result record should have values"); - + // Test profile with parameters Map params = new HashMap<>(); params.put("name", "alice"); ResultSet profileResultWithParams = client.profile("MATCH (a:person) WHERE (a.name = $name) RETURN a.age", params); Assertions.assertNotNull(profileResultWithParams); - + // Verify parameterized profile result has expected structure Assertions.assertTrue(profileResultWithParams.size() > 0, "Parameterized profile result should contain execution plan operations"); Header paramHeader = profileResultWithParams.getHeader(); Assertions.assertNotNull(paramHeader, "Parameterized profile result should have a header"); - + // Test profile with more complex query ResultSet complexProfileResult = client.profile("MATCH (p:person) WHERE p.age > 20 RETURN p.name, p.age ORDER BY p.age"); Assertions.assertNotNull(complexProfileResult); Assertions.assertTrue(complexProfileResult.size() > 0, "Complex profile result should contain execution plan operations"); - + // Verify all profile results have statistics (execution plans should have execution time) Assertions.assertNotNull(profileResult.getStatistics(), "Profile result should have statistics"); Assertions.assertNotNull(profileResultWithParams.getStatistics(), "Parameterized profile result should have statistics"); @@ -1040,7 +1035,7 @@ public void testGraphCopy() { // Copy the graph client.copyGraph("social-copied"); - GraphContextGenerator client2 = FalkorDB.driver().graph("social-copied"); + GraphContextGenerator client2 = FalkorDB.driver(getFalkordbHost(), getFalkordbPort()).graph("social-copied"); try { // Compare graph contents ResultSet copiedResultSet = client2.query("MATCH (p:person)-[rel:knows]->(p2:person) RETURN p,rel,p2"); @@ -1069,7 +1064,7 @@ public void testGraphCopyContextedAPI() { c.copyGraph("social-copied"); } - GraphContextGenerator client2 = FalkorDB.driver().graph("social-copied"); + GraphContextGenerator client2 = FalkorDB.driver(getFalkordbHost(), getFalkordbPort()).graph("social-copied"); try { // Compare graph contents ResultSet copiedResultSet = client2.query("MATCH (p:person)-[rel:knows]->(p2:person) RETURN p,rel,p2"); @@ -1098,9 +1093,9 @@ public void testExplain() { Assertions.assertFalse(explainResult.isEmpty()); // Should contain typical execution plan keywords in one of the lines boolean containsExpectedKeywords = explainResult.stream() - .anyMatch(line -> line.toLowerCase().contains("scan") || - line.toLowerCase().contains("project") || - line.toLowerCase().contains("results")); + .anyMatch(line -> line.toLowerCase().contains("scan") || + line.toLowerCase().contains("project") || + line.toLowerCase().contains("results")); Assertions.assertTrue(containsExpectedKeywords); // Test explain with parameters diff --git a/src/test/java/com/falkordb/InstantiationTest.java b/src/test/java/com/falkordb/InstantiationTest.java index c474c20..7ca7e1b 100644 --- a/src/test/java/com/falkordb/InstantiationTest.java +++ b/src/test/java/com/falkordb/InstantiationTest.java @@ -1,38 +1,41 @@ package com.falkordb; -import java.net.URI; - +import com.falkordb.test.BaseTestContainerTestIT; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -public class InstantiationTest { +import java.net.URI; + +public class InstantiationTest extends BaseTestContainerTestIT { private GraphContextGenerator client; @Test public void createDefaultClient() { - client = FalkorDB.driver().graph("g"); + + client = FalkorDB.driver(getFalkordbHost(), getFalkordbPort()).graph("g"); ResultSet resultSet = client.query("CREATE ({name:'bsb'})"); Assertions.assertEquals(1, resultSet.getStatistics().nodesCreated()); } @Test public void createClientWithHostAndPort() { - client = FalkorDB.driver("localhost", 6379).graph("g"); + client = FalkorDB.driver(getFalkordbHost(), getFalkordbPort()).graph("g"); ResultSet resultSet = client.query("CREATE ({name:'bsb'})"); Assertions.assertEquals(1, resultSet.getStatistics().nodesCreated()); } @Test public void createClientWithHostAndPortNoUser() { - client = FalkorDB.driver("localhost", 6379, null, null).graph("g"); + client = FalkorDB.driver(getFalkordbHost(), getFalkordbPort(), null, null).graph("g"); ResultSet resultSet = client.query("CREATE ({name:'bsb'})"); Assertions.assertEquals(1, resultSet.getStatistics().nodesCreated()); } @Test public void createClientWithURL() { - client = FalkorDB.driver(URI.create("redis://localhost:6379")).graph("g"); + client = FalkorDB.driver(URI.create(String.format("redis://%s:%d", + getFalkordbHost(), getFalkordbPort()))).graph("g"); ResultSet resultSet = client.query("CREATE ({name:'bsb'})"); Assertions.assertEquals(1, resultSet.getStatistics().nodesCreated()); } diff --git a/src/test/java/com/falkordb/IterableTest.java b/src/test/java/com/falkordb/IterableTest.java index 7ff89b1..2af210c 100644 --- a/src/test/java/com/falkordb/IterableTest.java +++ b/src/test/java/com/falkordb/IterableTest.java @@ -1,19 +1,20 @@ package com.falkordb; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertEquals; - +import com.falkordb.test.BaseTestContainerTestIT; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class IterableTest { +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class IterableTest extends BaseTestContainerTestIT { private GraphContextGenerator api; @BeforeEach public void createApi() { - api = FalkorDB.driver().graph("social"); + api = FalkorDB.driver(getFalkordbHost(), getFalkordbPort()).graph("social"); } @AfterEach diff --git a/src/test/java/com/falkordb/ListGraphsTest.java b/src/test/java/com/falkordb/ListGraphsTest.java index eaa8d18..c9c8531 100644 --- a/src/test/java/com/falkordb/ListGraphsTest.java +++ b/src/test/java/com/falkordb/ListGraphsTest.java @@ -1,18 +1,19 @@ package com.falkordb; -import java.util.List; - +import com.falkordb.test.BaseTestContainerTestIT; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class ListGraphsTest { +import java.util.List; + +public class ListGraphsTest extends BaseTestContainerTestIT { private Driver driver; @BeforeEach public void setUp() { - driver = FalkorDB.driver(); + driver = FalkorDB.driver(getFalkordbHost(), getFalkordbPort()); } @Test @@ -29,13 +30,13 @@ public void testListGraphsWithCreatedGraph() { // Create a test graph GraphContextGenerator testGraph = driver.graph("test-list-graph"); testGraph.query("CREATE (:TestNode {name:'test'})"); - + try { // List graphs and verify our graph is included List graphs = driver.listGraphs(); Assertions.assertNotNull(graphs); - Assertions.assertTrue(graphs.contains("test-list-graph"), - "Graph list should contain the created graph: " + graphs); + Assertions.assertTrue(graphs.contains("test-list-graph"), + "Graph list should contain the created graph: " + graphs); } finally { // Clean up the test graph testGraph.deleteGraph(); @@ -48,38 +49,38 @@ public void testListGraphsAfterDeletion() { // Create a test graph GraphContextGenerator testGraph = driver.graph("test-delete-graph"); testGraph.query("CREATE (:TestNode {name:'test'})"); - + // Verify graph exists List graphsBefore = driver.listGraphs(); Assertions.assertTrue(graphsBefore.contains("test-delete-graph")); - + // Delete the graph testGraph.deleteGraph(); testGraph.close(); - + // Verify graph is no longer in the list List graphsAfter = driver.listGraphs(); - Assertions.assertFalse(graphsAfter.contains("test-delete-graph"), - "Graph list should not contain the deleted graph: " + graphsAfter); + Assertions.assertFalse(graphsAfter.contains("test-delete-graph"), + "Graph list should not contain the deleted graph: " + graphsAfter); } @Test public void testListGraphsMultiple() { GraphContextGenerator graph1 = driver.graph("test-multi-1"); GraphContextGenerator graph2 = driver.graph("test-multi-2"); - + try { // Create nodes in both graphs graph1.query("CREATE (:TestNode {name:'test1'})"); graph2.query("CREATE (:TestNode {name:'test2'})"); - + // List graphs and verify both are included List graphs = driver.listGraphs(); Assertions.assertNotNull(graphs); - Assertions.assertTrue(graphs.contains("test-multi-1"), - "Graph list should contain test-multi-1: " + graphs); - Assertions.assertTrue(graphs.contains("test-multi-2"), - "Graph list should contain test-multi-2: " + graphs); + Assertions.assertTrue(graphs.contains("test-multi-1"), + "Graph list should contain test-multi-1: " + graphs); + Assertions.assertTrue(graphs.contains("test-multi-2"), + "Graph list should contain test-multi-2: " + graphs); } finally { // Clean up both test graphs graph1.deleteGraph(); diff --git a/src/test/java/com/falkordb/PipelineTest.java b/src/test/java/com/falkordb/PipelineTest.java index e9ad384..9adb436 100644 --- a/src/test/java/com/falkordb/PipelineTest.java +++ b/src/test/java/com/falkordb/PipelineTest.java @@ -1,23 +1,23 @@ package com.falkordb; -import java.util.*; - +import com.falkordb.graph_entities.Node; +import com.falkordb.graph_entities.Property; +import com.falkordb.impl.resultset.ResultSetImpl; +import com.falkordb.test.BaseTestContainerTestIT; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import com.falkordb.graph_entities.Node; -import com.falkordb.graph_entities.Property; -import com.falkordb.impl.resultset.ResultSetImpl; +import java.util.*; -public class PipelineTest { +public class PipelineTest extends BaseTestContainerTestIT { private GraphContextGenerator api; @BeforeEach public void createApi() { - api = FalkorDB.driver().graph("social"); + api = FalkorDB.driver(getFalkordbHost(), getFalkordbPort()).graph("social"); } @@ -220,26 +220,26 @@ public void testProfile() { pipeline.query("CREATE (:person{name:'bob',age:25})"); pipeline.profile("MATCH (a:person) WHERE (a.name = 'alice') RETURN a.age"); List results = pipeline.syncAndReturnAll(); - + // Check that profile result is not null and has expected structure ResultSet profileResult = (ResultSet) results.get(2); Assertions.assertNotNull(profileResult); - + // Verify profile result contains execution plan operations Assertions.assertTrue(profileResult.size() > 0, "Profile result should contain execution plan operations"); - + // Verify profile result has a header with columns Header header = profileResult.getHeader(); Assertions.assertNotNull(header, "Profile result should have a header"); Assertions.assertTrue(header.getSchemaNames().size() > 0, "Profile result header should have columns"); - + // Verify profile result contains execution plan data Iterator iterator = profileResult.iterator(); Assertions.assertTrue(iterator.hasNext(), "Profile result should have execution plan operations"); Record record = iterator.next(); Assertions.assertNotNull(record, "Profile result record should not be null"); Assertions.assertTrue(record.size() > 0, "Profile result record should have values"); - + // Verify profile result has statistics (execution metrics) Assertions.assertNotNull(profileResult.getStatistics(), "Profile result should have statistics"); } @@ -260,7 +260,7 @@ public void testGraphCopy() { originalResultSetIterator = originalResultSet.iterator(); } - GraphContextGenerator api2 = FalkorDB.driver().graph("social-copied"); + GraphContextGenerator api2 = FalkorDB.driver(getFalkordbHost(), getFalkordbPort()).graph("social-copied"); try { // Compare graph contents ResultSet copiedResultSet = api2.query("MATCH (p:person)-[rel:knows]->(p2:person) RETURN p,rel,p2"); @@ -277,27 +277,27 @@ public void testGraphCopy() { } @Test - public void testExplainInPipeline(){ + public void testExplainInPipeline() { try (GraphContext c = api.getContext()) { // Create some test data first c.query("CREATE (:Person {name:'Bob'})"); - + GraphPipeline pipeline = c.pipelined(); pipeline.explain("MATCH (p:Person) RETURN p"); - + Map params = new HashMap<>(); params.put("name", "Bob"); pipeline.explain("MATCH (p:Person) WHERE p.name = $name RETURN p", params); - + List results = pipeline.syncAndReturnAll(); - + // Check explain results Assertions.assertTrue(results.get(0) instanceof List); @SuppressWarnings("unchecked") List explainResult1 = (List) results.get(0); Assertions.assertNotNull(explainResult1); Assertions.assertFalse(explainResult1.isEmpty()); - + Assertions.assertTrue(results.get(1) instanceof List); @SuppressWarnings("unchecked") List explainResult2 = (List) results.get(1); diff --git a/src/test/java/com/falkordb/TransactionTest.java b/src/test/java/com/falkordb/TransactionTest.java index 8dd1254..a735fb9 100644 --- a/src/test/java/com/falkordb/TransactionTest.java +++ b/src/test/java/com/falkordb/TransactionTest.java @@ -1,21 +1,17 @@ package com.falkordb; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - +import com.falkordb.graph_entities.Node; +import com.falkordb.graph_entities.Property; +import com.falkordb.impl.resultset.ResultSetImpl; +import com.falkordb.test.BaseTestContainerTestIT; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import com.falkordb.graph_entities.Node; -import com.falkordb.graph_entities.Property; -import com.falkordb.impl.resultset.ResultSetImpl; +import java.util.*; -public class TransactionTest { +public class TransactionTest extends BaseTestContainerTestIT { private GraphContextGenerator api; @@ -23,8 +19,8 @@ public TransactionTest() { } @BeforeEach - public void createApi(){ - api = FalkorDB.driver().graph("social"); + public void createApi() { + api = FalkorDB.driver(getFalkordbHost(), getFalkordbPort()).graph("social"); } @AfterEach @@ -34,7 +30,7 @@ public void deleteGraph() { } @Test - public void testMultiExec(){ + public void testMultiExec() { try (GraphContext c = api.getContext()) { GraphTransaction transaction = c.multi(); @@ -124,7 +120,7 @@ record = iterator.next(); } @Test - public void testWriteTransactionWatch(){ + public void testWriteTransactionWatch() { GraphContext c1 = api.getContext(); GraphContext c2 = api.getContext(); @@ -142,7 +138,7 @@ public void testWriteTransactionWatch(){ } @Test - public void testReadTransactionWatch(){ + public void testReadTransactionWatch() { GraphContext c1 = api.getContext(); GraphContext c2 = api.getContext(); @@ -163,7 +159,7 @@ public void testReadTransactionWatch(){ } @Test - public void testMultiExecWithReadOnlyQueries(){ + public void testMultiExecWithReadOnlyQueries() { try (GraphContext c = api.getContext()) { GraphTransaction transaction = c.multi(); @@ -242,7 +238,7 @@ record = iterator.next(); } @Test - public void testProfile(){ + public void testProfile() { try (GraphContext c = api.getContext()) { GraphTransaction transaction = c.multi(); @@ -255,49 +251,49 @@ public void testProfile(){ Assertions.assertEquals(ResultSetImpl.class, results.get(2).getClass()); ResultSet profileResult = (ResultSet) results.get(2); Assertions.assertNotNull(profileResult); - + // Verify profile result contains execution plan operations Assertions.assertTrue(profileResult.size() > 0, "Profile result should contain execution plan operations"); - + // Verify profile result has a header with columns Header header = profileResult.getHeader(); Assertions.assertNotNull(header, "Profile result should have a header"); Assertions.assertTrue(header.getSchemaNames().size() > 0, "Profile result header should have columns"); - + // Verify profile result contains execution plan data Iterator iterator = profileResult.iterator(); Assertions.assertTrue(iterator.hasNext(), "Profile result should have execution plan operations"); Record record = iterator.next(); Assertions.assertNotNull(record, "Profile result record should not be null"); Assertions.assertTrue(record.size() > 0, "Profile result record should have values"); - + // Verify profile result has statistics (execution metrics) Assertions.assertNotNull(profileResult.getStatistics(), "Profile result should have statistics"); } } - + @Test - public void testExplainInTransaction(){ + public void testExplainInTransaction() { try (GraphContext c = api.getContext()) { // Create some test data first c.query("CREATE (:Person {name:'Alice'})"); - + GraphTransaction transaction = c.multi(); transaction.explain("MATCH (p:Person) RETURN p"); - + Map params = new HashMap<>(); params.put("name", "Alice"); transaction.explain("MATCH (p:Person) WHERE p.name = $name RETURN p", params); - + List results = transaction.exec(); - + // Check explain results Assertions.assertTrue(results.get(0) instanceof List); @SuppressWarnings("unchecked") List explainResult1 = (List) results.get(0); Assertions.assertNotNull(explainResult1); Assertions.assertFalse(explainResult1.isEmpty()); - + Assertions.assertTrue(results.get(1) instanceof List); @SuppressWarnings("unchecked") List explainResult2 = (List) results.get(1); diff --git a/src/test/java/com/falkordb/exceptions/GraphErrorTest.java b/src/test/java/com/falkordb/exceptions/GraphErrorTest.java index b983f9f..ac750d0 100644 --- a/src/test/java/com/falkordb/exceptions/GraphErrorTest.java +++ b/src/test/java/com/falkordb/exceptions/GraphErrorTest.java @@ -1,31 +1,31 @@ package com.falkordb.exceptions; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.HashMap; - +import com.falkordb.FalkorDB; +import com.falkordb.GraphContext; +import com.falkordb.GraphContextGenerator; +import com.falkordb.test.BaseTestContainerTestIT; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import com.falkordb.FalkorDB; -import com.falkordb.GraphContext; -import com.falkordb.GraphContextGenerator; +import java.util.HashMap; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; -public class GraphErrorTest { +public class GraphErrorTest extends BaseTestContainerTestIT { private GraphContextGenerator api; @BeforeEach public void createApi() { - api = FalkorDB.driver().graph("social"); + api = FalkorDB.driver(getFalkordbHost(), getFalkordbPort()).graph("social"); Assertions.assertNotNull(api.query("CREATE (:person{mixed_prop: 'strval'}), (:person{mixed_prop: 50})")); } @AfterEach - public void deleteGraph() throws Exception{ + public void deleteGraph() throws Exception { api.deleteGraph(); api.close(); diff --git a/src/test/java/com/falkordb/graph_entities/PathTest.java b/src/test/java/com/falkordb/graph_entities/PathTest.java index acd8c71..64c0f82 100644 --- a/src/test/java/com/falkordb/graph_entities/PathTest.java +++ b/src/test/java/com/falkordb/graph_entities/PathTest.java @@ -12,13 +12,13 @@ public class PathTest { - private Node buildNode(int id){ + private Node buildNode(int id) { Node n = new Node(); n.setId(id); return n; } - private Edge buildEdge(int id, int src, int dst){ + private Edge buildEdge(int id, int src, int dst) { Edge e = new Edge(); e.setId(id); e.setSource(src); @@ -30,25 +30,25 @@ private List buildNodeArray(int size) { return IntStream.range(0, size).mapToObj(i -> buildNode(i)).collect(Collectors.toList()); } - private List buildEdgeArray(int size){ - return IntStream.range(0, size).mapToObj(i -> buildEdge(i, i, i+1)).collect(Collectors.toList()); + private List buildEdgeArray(int size) { + return IntStream.range(0, size).mapToObj(i -> buildEdge(i, i, i + 1)).collect(Collectors.toList()); } - private Path buildPath(int nodeCount){ - return new Path(buildNodeArray(nodeCount), buildEdgeArray(nodeCount-1)); + private Path buildPath(int nodeCount) { + return new Path(buildNodeArray(nodeCount), buildEdgeArray(nodeCount - 1)); } @Test - public void testEmptyPath(){ + public void testEmptyPath() { Path path = buildPath(0); assertEquals(0, path.length()); assertEquals(0, path.nodeCount()); - assertThrows(IndexOutOfBoundsException.class, ()->path.getNode(0)); - assertThrows(IndexOutOfBoundsException.class, ()->path.getEdge(0)); + assertThrows(IndexOutOfBoundsException.class, () -> path.getNode(0)); + assertThrows(IndexOutOfBoundsException.class, () -> path.getEdge(0)); } @Test - public void testSingleNodePath(){ + public void testSingleNodePath() { Path path = buildPath(1); assertEquals(0, path.length()); assertEquals(1, path.nodeCount()); @@ -60,16 +60,16 @@ public void testSingleNodePath(){ } @Test - public void testRandomLengthPath(){ + public void testRandomLengthPath() { int nodeCount = ThreadLocalRandom.current().nextInt(2, 100 + 1); Path path = buildPath(nodeCount); assertEquals(buildNodeArray(nodeCount), path.getNodes()); - assertEquals(buildEdgeArray(nodeCount-1), path.getEdges()); - assertDoesNotThrow(()->path.getEdge(0)); + assertEquals(buildEdgeArray(nodeCount - 1), path.getEdges()); + assertDoesNotThrow(() -> path.getEdge(0)); } @Test - public void hashCodeEqualTest(){ + public void hashCodeEqualTest() { EqualsVerifier.forClass(Path.class).verify(); } } \ No newline at end of file diff --git a/src/test/java/com/falkordb/impl/UtilsTest.java b/src/test/java/com/falkordb/impl/UtilsTest.java index 8cf2cc2..e4f296f 100644 --- a/src/test/java/com/falkordb/impl/UtilsTest.java +++ b/src/test/java/com/falkordb/impl/UtilsTest.java @@ -1,16 +1,13 @@ package com.falkordb.impl; -import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.HashMap; -import java.util.IllegalFormatConversionException; import java.util.List; import java.util.Map; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - public class UtilsTest { @Test diff --git a/src/test/java/com/falkordb/impl/api/DriverImplParseResponseTest.java b/src/test/java/com/falkordb/impl/api/DriverImplParseResponseTest.java index 2909a9d..8e843a0 100644 --- a/src/test/java/com/falkordb/impl/api/DriverImplParseResponseTest.java +++ b/src/test/java/com/falkordb/impl/api/DriverImplParseResponseTest.java @@ -1,14 +1,13 @@ package com.falkordb.impl.api; -import java.util.Arrays; -import java.util.List; - import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - import redis.clients.jedis.util.SafeEncoder; +import java.util.Arrays; +import java.util.List; + /** * Unit tests for DriverImpl parseListResponse method to ensure comprehensive coverage */ @@ -26,7 +25,7 @@ public void setUp() { public void testParseListResponseWithEmptyList() { List emptyList = Arrays.asList(); List result = driverImpl.parseListResponse(emptyList); - + Assertions.assertNotNull(result); Assertions.assertTrue(result.isEmpty()); } @@ -35,7 +34,7 @@ public void testParseListResponseWithEmptyList() { public void testParseListResponseWithStringList() { List stringList = Arrays.asList("graph1", "graph2", "graph3"); List result = driverImpl.parseListResponse(stringList); - + Assertions.assertNotNull(result); Assertions.assertEquals(3, result.size()); Assertions.assertEquals("graph1", result.get(0)); @@ -48,9 +47,9 @@ public void testParseListResponseWithByteArrayList() { byte[] bytes1 = SafeEncoder.encode("graph1"); byte[] bytes2 = SafeEncoder.encode("graph2"); List byteArrayList = Arrays.asList(bytes1, bytes2); - + List result = driverImpl.parseListResponse(byteArrayList); - + Assertions.assertNotNull(result); Assertions.assertEquals(2, result.size()); Assertions.assertEquals("graph1", result.get(0)); @@ -62,9 +61,9 @@ public void testParseListResponseWithMixedTypes() { byte[] bytes1 = SafeEncoder.encode("graph1"); String string1 = "graph2"; List mixedList = Arrays.asList(bytes1, string1); - + List result = driverImpl.parseListResponse(mixedList); - + Assertions.assertNotNull(result); Assertions.assertEquals(2, result.size()); Assertions.assertEquals("graph1", result.get(0)); @@ -75,9 +74,9 @@ public void testParseListResponseWithMixedTypes() { public void testParseListResponseWithUnsupportedTypes() { // Test with unsupported types (Integer, null, etc.) that should be ignored List mixedList = Arrays.asList("graph1", 123, null, "graph2", new Object()); - + List result = driverImpl.parseListResponse(mixedList); - + Assertions.assertNotNull(result); Assertions.assertEquals(2, result.size()); Assertions.assertEquals("graph1", result.get(0)); @@ -89,7 +88,7 @@ public void testParseListResponseWithNonListResponse() { // Test when response is not a List (should return empty list) String nonListResponse = "not a list"; List result = driverImpl.parseListResponse(nonListResponse); - + Assertions.assertNotNull(result); Assertions.assertTrue(result.isEmpty()); } @@ -98,7 +97,7 @@ public void testParseListResponseWithNonListResponse() { public void testParseListResponseWithNullResponse() { // Test when response is null (should return empty list) List result = driverImpl.parseListResponse(null); - + Assertions.assertNotNull(result); Assertions.assertTrue(result.isEmpty()); } diff --git a/src/test/java/com/falkordb/impl/api/GraphExplainBuilderUnitTest.java b/src/test/java/com/falkordb/impl/api/GraphExplainBuilderUnitTest.java index a0fe941..96b4a77 100644 --- a/src/test/java/com/falkordb/impl/api/GraphExplainBuilderUnitTest.java +++ b/src/test/java/com/falkordb/impl/api/GraphExplainBuilderUnitTest.java @@ -1,14 +1,13 @@ package com.falkordb.impl.api; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; - import redis.clients.jedis.util.SafeEncoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** * Unit tests for the response parsing Builder logic used in GraphPipelineImpl and GraphTransactionImpl * explain methods. This tests the specific Builder.build() methods to ensure comprehensive coverage. @@ -19,14 +18,14 @@ public class GraphExplainBuilderUnitTest { public void testExplainBuilderWithListResponse() { // Test the Builder logic from GraphPipelineImpl/GraphTransactionImpl explain methods List mockResponse = Arrays.asList( - SafeEncoder.encode("Results"), - SafeEncoder.encode(" Project"), - SafeEncoder.encode(" Filter"), - SafeEncoder.encode(" NodeByLabelScan") + SafeEncoder.encode("Results"), + SafeEncoder.encode(" Project"), + SafeEncoder.encode(" Filter"), + SafeEncoder.encode(" NodeByLabelScan") ); - + List result = buildExplainResponse(mockResponse); - + Assertions.assertNotNull(result); Assertions.assertEquals(4, result.size()); Assertions.assertEquals("Results", result.get(0)); @@ -39,14 +38,14 @@ public void testExplainBuilderWithListResponse() { public void testExplainBuilderWithMixedTypeResponse() { // Test Builder logic with mixed byte arrays and strings List mockResponse = Arrays.asList( - SafeEncoder.encode("Results"), - " Project", // String instead of byte array - SafeEncoder.encode(" Filter"), - " NodeByLabelScan" // Another string + SafeEncoder.encode("Results"), + " Project", // String instead of byte array + SafeEncoder.encode(" Filter"), + " NodeByLabelScan" // Another string ); - + List result = buildExplainResponse(mockResponse); - + Assertions.assertNotNull(result); Assertions.assertEquals(4, result.size()); Assertions.assertEquals("Results", result.get(0)); @@ -59,9 +58,9 @@ public void testExplainBuilderWithMixedTypeResponse() { public void testExplainBuilderWithEmptyListResponse() { // Test Builder logic with empty response List emptyResponse = new ArrayList<>(); - + List result = buildExplainResponse(emptyResponse); - + Assertions.assertNotNull(result); Assertions.assertTrue(result.isEmpty()); } @@ -70,11 +69,11 @@ public void testExplainBuilderWithEmptyListResponse() { public void testExplainBuilderWithSingleItemResponse() { // Test Builder logic with single item response List singleItemResponse = Arrays.asList( - SafeEncoder.encode("Single result") + SafeEncoder.encode("Single result") ); - + List result = buildExplainResponse(singleItemResponse); - + Assertions.assertNotNull(result); Assertions.assertEquals(1, result.size()); Assertions.assertEquals("Single result", result.get(0)); @@ -84,14 +83,14 @@ public void testExplainBuilderWithSingleItemResponse() { public void testExplainBuilderWithNullItemsInResponse() { // Test Builder logic with null items in response (edge case) List responseWithNulls = Arrays.asList( - SafeEncoder.encode("Valid line"), - null, // null item - SafeEncoder.encode("Another valid line"), - null // another null item + SafeEncoder.encode("Valid line"), + null, // null item + SafeEncoder.encode("Another valid line"), + null // another null item ); - + List result = buildExplainResponseSafely(responseWithNulls); - + Assertions.assertNotNull(result); Assertions.assertEquals(4, result.size()); Assertions.assertEquals("Valid line", result.get(0)); @@ -104,9 +103,9 @@ public void testExplainBuilderWithNullItemsInResponse() { public void testExplainBuilderFallbackWithByteArrayResponse() { // Test Builder fallback logic when response is not a List (byte array) byte[] singleByteResponse = SafeEncoder.encode("Fallback response"); - + List result = buildExplainResponseFallback(singleByteResponse); - + Assertions.assertNotNull(result); Assertions.assertEquals(1, result.size()); Assertions.assertEquals("Fallback response", result.get(0)); @@ -116,9 +115,9 @@ public void testExplainBuilderFallbackWithByteArrayResponse() { public void testExplainBuilderFallbackWithStringResponse() { // Test Builder fallback logic when response is not a List (string) String singleStringResponse = "String fallback response"; - + List result = buildExplainResponseFallback(singleStringResponse); - + Assertions.assertNotNull(result); Assertions.assertEquals(1, result.size()); Assertions.assertEquals("String fallback response", result.get(0)); @@ -128,14 +127,14 @@ public void testExplainBuilderFallbackWithStringResponse() { public void testExplainBuilderWithComplexStrings() { // Test Builder logic with complex strings containing special characters List complexResponse = Arrays.asList( - SafeEncoder.encode("Results with unicode: 🔍"), - SafeEncoder.encode(" Project with quotes: \"value\""), - SafeEncoder.encode(" Filter with newlines:\n nested content"), - SafeEncoder.encode(" Scan with tabs:\ttabbed content") + SafeEncoder.encode("Results with unicode: 🔍"), + SafeEncoder.encode(" Project with quotes: \"value\""), + SafeEncoder.encode(" Filter with newlines:\n nested content"), + SafeEncoder.encode(" Scan with tabs:\ttabbed content") ); - + List result = buildExplainResponse(complexResponse); - + Assertions.assertNotNull(result); Assertions.assertEquals(4, result.size()); Assertions.assertEquals("Results with unicode: 🔍", result.get(0)); @@ -148,13 +147,13 @@ public void testExplainBuilderWithComplexStrings() { public void testExplainBuilderWithNumericStrings() { // Test Builder logic when response contains numeric values as strings List numericResponse = Arrays.asList( - SafeEncoder.encode("Cost: 1.23"), - SafeEncoder.encode("Rows: 1000"), - "Numeric object: 456" // Direct numeric string + SafeEncoder.encode("Cost: 1.23"), + SafeEncoder.encode("Rows: 1000"), + "Numeric object: 456" // Direct numeric string ); - + List result = buildExplainResponse(numericResponse); - + Assertions.assertNotNull(result); Assertions.assertEquals(3, result.size()); Assertions.assertEquals("Cost: 1.23", result.get(0)); @@ -169,9 +168,9 @@ public void testExplainBuilderWithLongResponse() { for (int i = 0; i < 100; i++) { longResponse.add(SafeEncoder.encode("Line " + i)); } - + List result = buildExplainResponse(longResponse); - + Assertions.assertNotNull(result); Assertions.assertEquals(100, result.size()); Assertions.assertEquals("Line 0", result.get(0)); diff --git a/src/test/java/com/falkordb/impl/api/GraphExplainUnitTest.java b/src/test/java/com/falkordb/impl/api/GraphExplainUnitTest.java index 0af66c6..de11d67 100644 --- a/src/test/java/com/falkordb/impl/api/GraphExplainUnitTest.java +++ b/src/test/java/com/falkordb/impl/api/GraphExplainUnitTest.java @@ -1,20 +1,14 @@ package com.falkordb.impl.api; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - +import com.falkordb.ResultSet; +import com.falkordb.impl.Utils; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - -import com.falkordb.ResultSet; -import com.falkordb.impl.Utils; - import redis.clients.jedis.util.SafeEncoder; +import java.util.*; + /** * Unit tests for Graph explain functionality to ensure comprehensive coverage * without requiring a live database connection. @@ -31,13 +25,13 @@ public void setUp() { @Test public void testExplainWithoutParameters() { String query = "MATCH (n:Person) RETURN n"; - + // Set up mock response List mockResponse = Arrays.asList( - SafeEncoder.encode("Results"), - SafeEncoder.encode(" Project"), - SafeEncoder.encode(" Filter"), - SafeEncoder.encode(" NodeByLabelScan") + SafeEncoder.encode("Results"), + SafeEncoder.encode(" Project"), + SafeEncoder.encode(" Filter"), + SafeEncoder.encode(" NodeByLabelScan") ); testGraph.setMockExplainResponse(mockResponse); @@ -59,13 +53,13 @@ public void testExplainWithParameters() { String query = "MATCH (p:Person) WHERE p.name = $name RETURN p"; Map params = new HashMap<>(); params.put("name", "Alice"); - + // Set up mock response List mockResponse = Arrays.asList( - SafeEncoder.encode("Results"), - SafeEncoder.encode(" Project"), - SafeEncoder.encode(" Filter"), - SafeEncoder.encode(" NodeByLabelScan") + SafeEncoder.encode("Results"), + SafeEncoder.encode(" Project"), + SafeEncoder.encode(" Filter"), + SafeEncoder.encode(" NodeByLabelScan") ); testGraph.setMockExplainResponse(mockResponse); @@ -85,12 +79,12 @@ public void testExplainWithParameters() { public void testExplainResponseParsingWithByteArrays() { // Test response parsing logic similar to GraphImpl.sendExplain List mockResponse = Arrays.asList( - SafeEncoder.encode("Results"), - SafeEncoder.encode(" Project") + SafeEncoder.encode("Results"), + SafeEncoder.encode(" Project") ); - + List result = parseExplainResponse(mockResponse); - + Assertions.assertNotNull(result); Assertions.assertEquals(2, result.size()); Assertions.assertEquals("Results", result.get(0)); @@ -101,13 +95,13 @@ public void testExplainResponseParsingWithByteArrays() { public void testExplainResponseParsingWithMixedTypes() { // Test mixed byte arrays and strings List mockResponse = Arrays.asList( - SafeEncoder.encode("Results"), - " Project", // String instead of byte array - SafeEncoder.encode(" Filter") + SafeEncoder.encode("Results"), + " Project", // String instead of byte array + SafeEncoder.encode(" Filter") ); - + List result = parseExplainResponse(mockResponse); - + Assertions.assertNotNull(result); Assertions.assertEquals(3, result.size()); Assertions.assertEquals("Results", result.get(0)); @@ -118,9 +112,9 @@ public void testExplainResponseParsingWithMixedTypes() { @Test public void testExplainResponseParsingWithEmptyList() { List mockResponse = new ArrayList<>(); - + List result = parseExplainResponse(mockResponse); - + Assertions.assertNotNull(result); Assertions.assertTrue(result.isEmpty()); } @@ -129,9 +123,9 @@ public void testExplainResponseParsingWithEmptyList() { public void testExplainResponseParsingWithNonListResponse() { // Test fallback behavior when response is not a List byte[] singleResponse = SafeEncoder.encode("Single response"); - + List result = parseExplainResponseFallback(singleResponse); - + Assertions.assertNotNull(result); Assertions.assertEquals(1, result.size()); Assertions.assertEquals("Single response", result.get(0)); @@ -143,12 +137,12 @@ public void testExplainWithComplexParameters() { Map params = new HashMap<>(); params.put("minAge", 25); params.put("city", "New York"); - + List mockResponse = Arrays.asList( - SafeEncoder.encode("Results"), - SafeEncoder.encode(" Project"), - SafeEncoder.encode(" Filter"), - SafeEncoder.encode(" NodeByLabelScan") + SafeEncoder.encode("Results"), + SafeEncoder.encode(" Project"), + SafeEncoder.encode(" Filter"), + SafeEncoder.encode(" NodeByLabelScan") ); testGraph.setMockExplainResponse(mockResponse); @@ -156,7 +150,7 @@ public void testExplainWithComplexParameters() { Assertions.assertNotNull(result); Assertions.assertEquals(4, result.size()); - + String preparedQuery = testGraph.getLastPreparedQuery(); Assertions.assertTrue(preparedQuery.contains("minAge=25")); Assertions.assertTrue(preparedQuery.contains("city=\"New York\"")); @@ -167,9 +161,9 @@ public void testExplainWithSpecialCharacters() { String query = "MATCH (p:Person) WHERE p.name = $name RETURN p"; Map params = new HashMap<>(); params.put("name", "John \"The Rock\" Doe"); - + List mockResponse = Arrays.asList( - SafeEncoder.encode("Results") + SafeEncoder.encode("Results") ); testGraph.setMockExplainResponse(mockResponse); @@ -177,7 +171,7 @@ public void testExplainWithSpecialCharacters() { Assertions.assertNotNull(result); Assertions.assertEquals(1, result.size()); - + // Verify that special characters are properly escaped String preparedQuery = testGraph.getLastPreparedQuery(); Assertions.assertTrue(preparedQuery.contains("name=\"John \\\"The Rock\\\" Doe\"")); @@ -243,7 +237,7 @@ protected ResultSet sendReadOnlyQuery(String preparedQuery, long timeout) { @Override protected List sendExplain(String preparedQuery) { this.lastPreparedQuery = preparedQuery; - + // Simulate the parsing logic from GraphImpl.sendExplain if (mockExplainResponse instanceof List) { List result = new ArrayList<>(mockExplainResponse.size()); diff --git a/src/test/java/com/falkordb/impl/api/GraphPipelineTransactionExplainUnitTest.java b/src/test/java/com/falkordb/impl/api/GraphPipelineTransactionExplainUnitTest.java index 07eb789..6d1512c 100644 --- a/src/test/java/com/falkordb/impl/api/GraphPipelineTransactionExplainUnitTest.java +++ b/src/test/java/com/falkordb/impl/api/GraphPipelineTransactionExplainUnitTest.java @@ -1,22 +1,12 @@ package com.falkordb.impl.api; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - +import com.falkordb.impl.Utils; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - -import com.falkordb.GraphPipeline; -import com.falkordb.GraphTransaction; -import com.falkordb.impl.Utils; - -import redis.clients.jedis.Response; import redis.clients.jedis.util.SafeEncoder; +import java.util.*; + /** * Unit tests for GraphPipeline and GraphTransaction explain functionality * to ensure comprehensive coverage without requiring a live database connection. @@ -29,9 +19,9 @@ public void testPipelineExplainParameterHandling() { String query = "MATCH (p:Person) WHERE p.name = $name RETURN p"; Map params = new HashMap<>(); params.put("name", "Alice"); - + String expectedPreparedQuery = Utils.prepareQuery(query, params); - + // Verify the query preparation logic works correctly Assertions.assertTrue(expectedPreparedQuery.contains("name=\"Alice\"")); Assertions.assertTrue(expectedPreparedQuery.startsWith("CYPHER")); @@ -43,9 +33,9 @@ public void testTransactionExplainParameterHandling() { String query = "MATCH (p:Person) WHERE p.age > $minAge RETURN p"; Map params = new HashMap<>(); params.put("minAge", 30); - + String expectedPreparedQuery = Utils.prepareQuery(query, params); - + // Verify the query preparation logic works correctly Assertions.assertTrue(expectedPreparedQuery.contains("minAge=30")); Assertions.assertTrue(expectedPreparedQuery.startsWith("CYPHER")); @@ -55,9 +45,9 @@ public void testTransactionExplainParameterHandling() { public void testExplainQueryPreparationWithEmptyParameters() { String query = "MATCH (n) RETURN n"; Map emptyParams = new HashMap<>(); - + String preparedQuery = Utils.prepareQuery(query, emptyParams); - + // Even with empty parameters, Utils.prepareQuery adds CYPHER prefix Assertions.assertEquals("CYPHER " + query, preparedQuery); } @@ -65,12 +55,12 @@ public void testExplainQueryPreparationWithEmptyParameters() { @Test public void testExplainQueryPreparationWithNullParameters() { String query = "MATCH (n) RETURN n"; - + // Utils.prepareQuery doesn't handle null parameters, so we need to test with empty map // This tests the behavior when explain methods handle null parameters Map emptyParams = new HashMap<>(); String preparedQuery = Utils.prepareQuery(query, emptyParams); - + // Should add CYPHER prefix even with empty params Assertions.assertEquals("CYPHER " + query, preparedQuery); } @@ -82,9 +72,9 @@ public void testExplainQueryPreparationWithComplexParameters() { params.put("name", "John Doe"); params.put("age", 25); params.put("active", true); - + String preparedQuery = Utils.prepareQuery(query, params); - + Assertions.assertTrue(preparedQuery.contains("name=\"John Doe\"")); Assertions.assertTrue(preparedQuery.contains("age=25")); Assertions.assertTrue(preparedQuery.contains("active=true")); @@ -94,16 +84,16 @@ public void testExplainQueryPreparationWithComplexParameters() { public void testExplainResponseStructureValidation() { // Test that explain responses follow expected structure List mockExplainResponse = Arrays.asList( - SafeEncoder.encode("Results"), - SafeEncoder.encode(" Project"), - SafeEncoder.encode(" Filter"), - SafeEncoder.encode(" NodeByLabelScan") + SafeEncoder.encode("Results"), + SafeEncoder.encode(" Project"), + SafeEncoder.encode(" Filter"), + SafeEncoder.encode(" NodeByLabelScan") ); - + // Validate structure - should be a list of strings Assertions.assertTrue(mockExplainResponse instanceof List); Assertions.assertEquals(4, mockExplainResponse.size()); - + // Convert to expected format List converted = convertResponse(mockExplainResponse); Assertions.assertEquals("Results", converted.get(0)); @@ -116,13 +106,13 @@ public void testExplainResponseStructureValidation() { public void testExplainResponseWithUnicodeCharacters() { // Test handling of Unicode characters in explain responses List mockResponse = Arrays.asList( - SafeEncoder.encode("Results with Unicode: café"), - SafeEncoder.encode(" Project with émojis: 🚀"), - SafeEncoder.encode(" Filter with 中文") + SafeEncoder.encode("Results with Unicode: café"), + SafeEncoder.encode(" Project with émojis: 🚀"), + SafeEncoder.encode(" Filter with 中文") ); - + List converted = convertResponse(mockResponse); - + Assertions.assertEquals("Results with Unicode: café", converted.get(0)); Assertions.assertEquals(" Project with émojis: 🚀", converted.get(1)); Assertions.assertEquals(" Filter with 中文", converted.get(2)); @@ -135,14 +125,14 @@ public void testExplainResponseWithLongStrings() { for (int i = 0; i < 100; i++) { longString.append("repeated_content_").append(i).append(" "); } - + List mockResponse = Arrays.asList( - SafeEncoder.encode(longString.toString()), - SafeEncoder.encode("Normal line") + SafeEncoder.encode(longString.toString()), + SafeEncoder.encode("Normal line") ); - + List converted = convertResponse(mockResponse); - + Assertions.assertEquals(2, converted.size()); Assertions.assertTrue(converted.get(0).length() > 1000); Assertions.assertEquals("Normal line", converted.get(1)); @@ -154,9 +144,9 @@ public void testExplainParameterEscaping() { String query = "MATCH (p:Person) WHERE p.description = $desc RETURN p"; Map params = new HashMap<>(); params.put("desc", "Person with \"quotes\" and 'apostrophes' and \\ backslashes"); - + String preparedQuery = Utils.prepareQuery(query, params); - + // Verify that quotes are properly escaped Assertions.assertTrue(preparedQuery.contains("\\\"")); Assertions.assertTrue(preparedQuery.contains("desc=")); @@ -168,9 +158,9 @@ public void testExplainWithArrayParameters() { String query = "MATCH (p:Person) WHERE p.name IN $names RETURN p"; Map params = new HashMap<>(); params.put("names", Arrays.asList("Alice", "Bob", "Charlie")); - + String preparedQuery = Utils.prepareQuery(query, params); - + Assertions.assertTrue(preparedQuery.contains("names=[")); Assertions.assertTrue(preparedQuery.contains("\"Alice\"")); Assertions.assertTrue(preparedQuery.contains("\"Bob\"")); @@ -183,9 +173,9 @@ public void testExplainWithNumericArrayParameters() { String query = "MATCH (p:Person) WHERE p.age IN $ages RETURN p"; Map params = new HashMap<>(); params.put("ages", Arrays.asList(25, 30, 35)); - + String preparedQuery = Utils.prepareQuery(query, params); - + Assertions.assertTrue(preparedQuery.contains("ages=[25, 30, 35]")); } @@ -195,14 +185,14 @@ public void testExplainResponseErrorHandling() { List emptyResponse = new ArrayList<>(); List converted = convertResponse(emptyResponse); Assertions.assertTrue(converted.isEmpty()); - + // Test with null items in response List responseWithNull = Arrays.asList( - SafeEncoder.encode("Valid line"), - null, - SafeEncoder.encode("Another valid line") + SafeEncoder.encode("Valid line"), + null, + SafeEncoder.encode("Another valid line") ); - + List convertedWithNulls = convertResponseSafely(responseWithNull); Assertions.assertEquals(2, convertedWithNulls.size()); Assertions.assertEquals("Valid line", convertedWithNulls.get(0)); diff --git a/src/test/java/com/falkordb/test/BaseTestContainerTestIT.java b/src/test/java/com/falkordb/test/BaseTestContainerTestIT.java new file mode 100644 index 0000000..699374b --- /dev/null +++ b/src/test/java/com/falkordb/test/BaseTestContainerTestIT.java @@ -0,0 +1,50 @@ +package com.falkordb.test; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.output.Slf4jLogConsumer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; + +import java.time.Duration; + +public class BaseTestContainerTestIT { + private static final Logger log = LoggerFactory.getLogger(BaseTestContainerTestIT.class); + public static final DockerImageName FALKORDB_IMAGE = DockerImageName.parse("falkordb/falkordb:latest"); + public static final int FALKORDB_PORT = 6379; + + private static GenericContainer containerFalkorDB; + private static final int falkordbPort = 6379; // Default port for Falkordb, adjust if necessary + + @BeforeAll + public static void setUpContainer() { + // allow overriding image via -Dfalkordb.image=repo/image:tag + DockerImageName image = DockerImageName.parse( + System.getProperty("falkordb.image", FALKORDB_IMAGE.asCanonicalNameString()) + ); + containerFalkorDB = new GenericContainer<>(image) + .withExposedPorts(FALKORDB_PORT) + .withLogConsumer(new Slf4jLogConsumer(log)) + .waitingFor(Wait.forListeningPort()) + .withStartupTimeout(Duration.ofSeconds(90)); + containerFalkorDB.start(); + } + + @AfterAll + public static void tearDownContainer() { + if (containerFalkorDB != null) { + containerFalkorDB.stop(); + } + } + + protected int getFalkordbPort() { + return containerFalkorDB.getFirstMappedPort(); + } + + protected String getFalkordbHost() { + return containerFalkorDB.getHost(); + } +} diff --git a/src/test/java/com/falkordb/test/utils/PathBuilder.java b/src/test/java/com/falkordb/test/utils/PathBuilder.java index 1f1c7f0..7389d4b 100644 --- a/src/test/java/com/falkordb/test/utils/PathBuilder.java +++ b/src/test/java/com/falkordb/test/utils/PathBuilder.java @@ -7,7 +7,7 @@ import java.util.ArrayList; import java.util.List; -public final class PathBuilder{ +public final class PathBuilder { private final List nodes; private final List edges; private Class currentAppendClass = Node.class; @@ -16,20 +16,20 @@ public PathBuilder() { this(0); } - public PathBuilder(int nodesCount){ + public PathBuilder(int nodesCount) { this.nodes = new ArrayList<>(nodesCount); this.edges = new ArrayList<>(nodesCount > 0 ? nodesCount - 1 : 0); } - public PathBuilder append(Object object){ + public PathBuilder append(Object object) { Class c = object.getClass(); - if(!currentAppendClass.equals(c)){ - throw new IllegalArgumentException("Path Builder expected " + currentAppendClass.getSimpleName() + " but was " + c.getSimpleName()); + if (!currentAppendClass.equals(c)) { + throw new IllegalArgumentException("Path Builder expected " + currentAppendClass.getSimpleName() + " but was " + c.getSimpleName()); } - if(c.equals(Node.class)) { - return appendNode((Node)object); + if (c.equals(Node.class)) { + return appendNode((Node) object); } - return appendEdge((Edge)object); + return appendEdge((Edge) object); } private PathBuilder appendEdge(Edge edge) { @@ -38,15 +38,15 @@ private PathBuilder appendEdge(Edge edge) { return this; } - private PathBuilder appendNode(Node node){ + private PathBuilder appendNode(Node node) { nodes.add(node); currentAppendClass = Edge.class; return this; } - public Path build(){ - if(nodes.size() != edges.size() + 1){ - throw new IllegalArgumentException("Path builder nodes count should be edge count + 1"); + public Path build() { + if (nodes.size() != edges.size() + 1) { + throw new IllegalArgumentException("Path builder nodes count should be edge count + 1"); } return new Path(nodes, edges); } diff --git a/src/test/java/com/falkordb/test/utils/PathBuilderTest.java b/src/test/java/com/falkordb/test/utils/PathBuilderTest.java index 98ff3a1..43e6889 100644 --- a/src/test/java/com/falkordb/test/utils/PathBuilderTest.java +++ b/src/test/java/com/falkordb/test/utils/PathBuilderTest.java @@ -1,11 +1,10 @@ package com.falkordb.test.utils; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - +import com.falkordb.graph_entities.Edge; import org.junit.jupiter.api.Test; -import com.falkordb.graph_entities.Edge; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; public class PathBuilderTest {