diff --git a/README.md b/README.md index 8e4b4bd413..7642301a08 100644 --- a/README.md +++ b/README.md @@ -97,19 +97,18 @@ To use the driver in a project, please use the released driver via Maven Central #### Running Tests and Creating a Package -Our test setup requires a bit of infrastructure to run. -We rely mostly on [`testkit`](https://github.com/neo4j-drivers/testkit). -Testkit is a tooling that is used to run integration tests for all of the drivers we provide. - -Some older tests still rely on [`boltkit`](https://github.com/neo4j-drivers/boltkit), the predecessor to Testkit. -If `boltkit` is not installed, then all tests that requires `boltkit` will be ignored and will not be executed. - -In case you want or can verify contributions with unit tests alone, use the following command to skip all integration and Testkit tests: - +The following command may be used to unit test and install artifacts without running integration tests: ``` mvn clean install -DskipITs -P skip-testkit ``` +Integration tests have the following prerequisites: +- Docker +- [`Testkit`](https://github.com/neo4j-drivers/testkit) + +Testkit that is a tooling that is used to run integration tests for all official Neo4j drivers. +It can be executed using Docker during Maven build and in such case does not require additional setup. See the instructions below for more details. + There are 2 ways of running Testkit tests: 1. Using the `testkit-tests` module of this project. 2. Manually cloning Testkit and running it directly. diff --git a/driver/pom.xml b/driver/pom.xml index c16eccd294..0b71dff909 100644 --- a/driver/pom.xml +++ b/driver/pom.xml @@ -100,6 +100,10 @@ org.reactivestreams reactive-streams-tck + + ch.qos.logback + logback-classic + diff --git a/driver/src/test/java/org/neo4j/driver/integration/ConnectionPoolIT.java b/driver/src/test/java/org/neo4j/driver/integration/ConnectionPoolIT.java index 02b849ae19..c9c7cf0d1f 100644 --- a/driver/src/test/java/org/neo4j/driver/integration/ConnectionPoolIT.java +++ b/driver/src/test/java/org/neo4j/driver/integration/ConnectionPoolIT.java @@ -80,7 +80,8 @@ void shouldRecoverFromDownedServer() throws Throwable { sessionGrabber.start(); // When - neo4j.forceRestartDb(); + neo4j.stopProxy(); + neo4j.startProxy(); // Then we accept a hump with failing sessions, but demand that failures stop as soon as the server is back up. sessionGrabber.assertSessionsAvailableWithin(120); diff --git a/driver/src/test/java/org/neo4j/driver/integration/CredentialsIT.java b/driver/src/test/java/org/neo4j/driver/integration/CredentialsIT.java index c5d2777878..720f40c75f 100644 --- a/driver/src/test/java/org/neo4j/driver/integration/CredentialsIT.java +++ b/driver/src/test/java/org/neo4j/driver/integration/CredentialsIT.java @@ -25,13 +25,8 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.neo4j.driver.AuthTokens.basic; import static org.neo4j.driver.AuthTokens.custom; -import static org.neo4j.driver.Values.ofValue; -import static org.neo4j.driver.Values.parameters; import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING; -import static org.neo4j.driver.util.Neo4jRunner.PASSWORD; -import java.nio.file.Files; -import java.nio.file.Paths; import java.util.Map; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -44,11 +39,7 @@ import org.neo4j.driver.Value; import org.neo4j.driver.exceptions.AuthenticationException; import org.neo4j.driver.exceptions.SecurityException; -import org.neo4j.driver.internal.security.InternalAuthToken; -import org.neo4j.driver.internal.util.DisabledOnNeo4jWith; -import org.neo4j.driver.internal.util.Neo4jFeature; import org.neo4j.driver.util.DatabaseExtension; -import org.neo4j.driver.util.Neo4jSettings; import org.neo4j.driver.util.ParallelizableIT; @ParallelizableIT @@ -56,46 +47,10 @@ class CredentialsIT { @RegisterExtension static final DatabaseExtension neo4j = new DatabaseExtension(); - @Test - @DisabledOnNeo4jWith(Neo4jFeature.BOLT_V4) - // This feature is removed in 4.0 - void shouldBePossibleToChangePassword() throws Exception { - String newPassword = "secret"; - String tmpDataDir = Files.createTempDirectory(Paths.get("target"), "tmp") - .toAbsolutePath() - .toString() - .replace("\\", "/"); - - neo4j.restartDb(Neo4jSettings.TEST_SETTINGS.updateWith(Neo4jSettings.DATA_DIR, tmpDataDir)); - - AuthToken authToken = new InternalAuthToken(parameters( - "scheme", "basic", - "principal", "neo4j", - "credentials", "neo4j", - "new_credentials", newPassword) - .asMap(ofValue())); - - // change the password - try (Driver driver = GraphDatabase.driver(neo4j.uri(), authToken); - Session session = driver.session()) { - session.run("RETURN 1").consume(); - } - - // verify old password does not work - final Driver badDriver = GraphDatabase.driver(CredentialsIT.neo4j.uri(), basic("neo4j", PASSWORD)); - assertThrows(AuthenticationException.class, badDriver::verifyConnectivity); - - // verify new password works - try (Driver driver = GraphDatabase.driver(CredentialsIT.neo4j.uri(), AuthTokens.basic("neo4j", newPassword)); - Session session = driver.session()) { - session.run("RETURN 2").consume(); - } - } - @Test void basicCredentialsShouldWork() { // When & Then - try (Driver driver = GraphDatabase.driver(neo4j.uri(), basic("neo4j", PASSWORD)); + try (Driver driver = GraphDatabase.driver(neo4j.uri(), basic("neo4j", neo4j.adminPassword())); Session session = driver.session()) { Value single = session.run("RETURN 1").single().get(0); assertThat(single.asLong(), equalTo(1L)); @@ -105,7 +60,8 @@ void basicCredentialsShouldWork() { @Test void shouldGetHelpfulErrorOnInvalidCredentials() { SecurityException e = assertThrows(SecurityException.class, () -> { - try (Driver driver = GraphDatabase.driver(neo4j.uri(), basic("thisisnotthepassword", PASSWORD)); + try (Driver driver = + GraphDatabase.driver(neo4j.uri(), basic("thisisnotthepassword", neo4j.adminPassword())); Session session = driver.session()) { session.run("RETURN 1"); } @@ -116,7 +72,7 @@ void shouldGetHelpfulErrorOnInvalidCredentials() { @Test void shouldBeAbleToProvideRealmWithBasicAuth() { // When & Then - try (Driver driver = GraphDatabase.driver(neo4j.uri(), basic("neo4j", PASSWORD, "native")); + try (Driver driver = GraphDatabase.driver(neo4j.uri(), basic("neo4j", neo4j.adminPassword(), "native")); Session session = driver.session()) { Value single = session.run("CREATE () RETURN 1").single().get(0); assertThat(single.asLong(), equalTo(1L)); @@ -126,7 +82,8 @@ void shouldBeAbleToProvideRealmWithBasicAuth() { @Test void shouldBeAbleToConnectWithCustomToken() { // When & Then - try (Driver driver = GraphDatabase.driver(neo4j.uri(), custom("neo4j", PASSWORD, "native", "basic")); + try (Driver driver = + GraphDatabase.driver(neo4j.uri(), custom("neo4j", neo4j.adminPassword(), "native", "basic")); Session session = driver.session()) { Value single = session.run("CREATE () RETURN 1").single().get(0); assertThat(single.asLong(), equalTo(1L)); @@ -138,7 +95,8 @@ void shouldBeAbleToConnectWithCustomTokenWithAdditionalParameters() { Map params = singletonMap("secret", 16); // When & Then - try (Driver driver = GraphDatabase.driver(neo4j.uri(), custom("neo4j", PASSWORD, "native", "basic", params)); + try (Driver driver = GraphDatabase.driver( + neo4j.uri(), custom("neo4j", neo4j.adminPassword(), "native", "basic", params)); Session session = driver.session()) { Value single = session.run("CREATE () RETURN 1").single().get(0); assertThat(single.asLong(), equalTo(1L)); @@ -147,12 +105,12 @@ void shouldBeAbleToConnectWithCustomTokenWithAdditionalParameters() { @Test void directDriverShouldFailEarlyOnWrongCredentials() { - testDriverFailureOnWrongCredentials("bolt://localhost:" + neo4j.boltPort()); + testDriverFailureOnWrongCredentials(neo4j.uri().toString()); } @Test void routingDriverShouldFailEarlyOnWrongCredentials() { - testDriverFailureOnWrongCredentials("neo4j://localhost:" + neo4j.boltPort()); + testDriverFailureOnWrongCredentials(neo4j.uri().toString()); } private void testDriverFailureOnWrongCredentials(String uri) { diff --git a/driver/src/test/java/org/neo4j/driver/integration/DirectDriverIT.java b/driver/src/test/java/org/neo4j/driver/integration/DirectDriverIT.java index 442ab39b56..ecd2d3c2d0 100644 --- a/driver/src/test/java/org/neo4j/driver/integration/DirectDriverIT.java +++ b/driver/src/test/java/org/neo4j/driver/integration/DirectDriverIT.java @@ -25,14 +25,11 @@ import static org.neo4j.driver.internal.util.Matchers.directDriverWithAddress; import java.net.URI; -import org.hamcrest.CoreMatchers; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.neo4j.driver.Driver; import org.neo4j.driver.GraphDatabase; -import org.neo4j.driver.Result; -import org.neo4j.driver.Session; import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.util.DatabaseExtension; import org.neo4j.driver.util.ParallelizableIT; @@ -87,17 +84,4 @@ void shouldRegisterSingleServer() { // Then assertThat(driver, is(directDriverWithAddress(address))); } - - @Test - void shouldConnectIPv6Uri() { - // Given - try (Driver driver = GraphDatabase.driver("bolt://[::1]:" + neo4j.boltPort(), neo4j.authToken()); - Session session = driver.session()) { - // When - Result result = session.run("RETURN 1"); - - // Then - assertThat(result.single().get(0).asInt(), CoreMatchers.equalTo(1)); - } - } } diff --git a/driver/src/test/java/org/neo4j/driver/integration/EncryptionIT.java b/driver/src/test/java/org/neo4j/driver/integration/EncryptionIT.java index 692fd1245c..2337b01aa9 100644 --- a/driver/src/test/java/org/neo4j/driver/integration/EncryptionIT.java +++ b/driver/src/test/java/org/neo4j/driver/integration/EncryptionIT.java @@ -25,6 +25,8 @@ import static org.neo4j.driver.Config.TrustStrategy.trustAllCertificates; import java.net.URI; +import java.util.HashMap; +import java.util.Map; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.neo4j.driver.Config; @@ -81,7 +83,9 @@ void shouldOperateWithoutEncryptionWhenItIsAlsoDisabledInTheDatabase() { } private void testMatchingEncryption(BoltTlsLevel tlsLevel, boolean driverEncrypted, String scheme) { - neo4j.restartDb(Neo4jSettings.TEST_SETTINGS.updateWith(Neo4jSettings.BOLT_TLS_LEVEL, tlsLevel.toString())); + Map tlsConfig = new HashMap<>(); + tlsConfig.put(Neo4jSettings.BOLT_TLS_LEVEL, tlsLevel.toString()); + neo4j.deleteAndStartNeo4j(tlsConfig); Config config; if (scheme.equals(Scheme.BOLT_LOW_TRUST_URI_SCHEME)) { @@ -107,7 +111,9 @@ private void testMatchingEncryption(BoltTlsLevel tlsLevel, boolean driverEncrypt } private void testMismatchingEncryption(BoltTlsLevel tlsLevel, boolean driverEncrypted) { - neo4j.restartDb(Neo4jSettings.TEST_SETTINGS.updateWith(Neo4jSettings.BOLT_TLS_LEVEL, tlsLevel.toString())); + Map tlsConfig = new HashMap<>(); + tlsConfig.put(Neo4jSettings.BOLT_TLS_LEVEL, tlsLevel.toString()); + neo4j.deleteAndStartNeo4j(tlsConfig); Config config = newConfig(driverEncrypted); ServiceUnavailableException e = assertThrows( diff --git a/driver/src/test/java/org/neo4j/driver/integration/ErrorIT.java b/driver/src/test/java/org/neo4j/driver/integration/ErrorIT.java index 43c3909879..6c3104cf09 100644 --- a/driver/src/test/java/org/neo4j/driver/integration/ErrorIT.java +++ b/driver/src/test/java/org/neo4j/driver/integration/ErrorIT.java @@ -177,13 +177,12 @@ void shouldHandleFailureAtRunTime() { } @Test - void shouldGetHelpfulErrorWhenTryingToConnectToHttpPort() throws Throwable { - // the http server needs some time to start up - Thread.sleep(2000); - + void shouldGetHelpfulErrorWhenTryingToConnectToHttpPort() { Config config = Config.builder().withoutEncryption().build(); - final Driver driver = GraphDatabase.driver("bolt://localhost:" + session.httpPort(), config); + URI boltUri = session.uri(); + URI uri = URI.create(String.format("%s://%s:%d", boltUri.getScheme(), boltUri.getHost(), session.httpPort())); + final Driver driver = GraphDatabase.driver(uri, config); ClientException e = assertThrows(ClientException.class, driver::verifyConnectivity); assertEquals( "Server responded HTTP. Make sure you are not trying to connect to the http endpoint " diff --git a/driver/src/test/java/org/neo4j/driver/integration/LoadCSVIT.java b/driver/src/test/java/org/neo4j/driver/integration/LoadCSVIT.java index 15a5f95471..44abb08f48 100644 --- a/driver/src/test/java/org/neo4j/driver/integration/LoadCSVIT.java +++ b/driver/src/test/java/org/neo4j/driver/integration/LoadCSVIT.java @@ -31,14 +31,12 @@ import org.neo4j.driver.Result; import org.neo4j.driver.Session; import org.neo4j.driver.util.DatabaseExtension; -import org.neo4j.driver.util.Neo4jSettings; import org.neo4j.driver.util.ParallelizableIT; @ParallelizableIT class LoadCSVIT { @RegisterExtension - static final DatabaseExtension neo4j = new DatabaseExtension( - Neo4jSettings.TEST_SETTINGS.without(Neo4jSettings.IMPORT_DIR).without(Neo4jSettings.SERVER_IMPORT_DIR)); + static final DatabaseExtension neo4j = new DatabaseExtension(); @Test void shouldLoadCSV() throws Throwable { @@ -74,7 +72,7 @@ private String createLocalIrisData(Session session) throws IOException { session.run("CREATE (c:Class {name: $className}) RETURN c", parameters("className", className)); } - return neo4j.putTmpFile("iris", ".csv", IRIS_DATA).toExternalForm(); + return neo4j.addImportFile("iris", ".csv", IRIS_DATA); } private static String[] IRIS_CLASS_NAMES = new String[] {"Iris-setosa", "Iris-versicolor", "Iris-virginica"}; diff --git a/driver/src/test/java/org/neo4j/driver/integration/ServerKilledIT.java b/driver/src/test/java/org/neo4j/driver/integration/ServerKilledIT.java index b57b91a690..cc15f8df61 100644 --- a/driver/src/test/java/org/neo4j/driver/integration/ServerKilledIT.java +++ b/driver/src/test/java/org/neo4j/driver/integration/ServerKilledIT.java @@ -21,7 +21,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static org.neo4j.driver.Config.TrustStrategy.trustCustomCertificateSignedBy; -import static org.neo4j.driver.util.Neo4jRunner.DEFAULT_AUTH_TOKEN; import java.util.List; import java.util.concurrent.TimeUnit; @@ -69,11 +68,12 @@ private static Stream data() { @MethodSource("data") void shouldRecoverFromServerRestart(String name, Config.ConfigBuilder configBuilder) { // Given config with sessionLivenessCheckTimeout not set, i.e. turned off - try (Driver driver = GraphDatabase.driver(neo4j.uri(), DEFAULT_AUTH_TOKEN, configBuilder.build())) { + try (Driver driver = GraphDatabase.driver(neo4j.uri(), neo4j.authToken(), configBuilder.build())) { acquireAndReleaseConnections(4, driver); // When - neo4j.forceRestartDb(); + neo4j.stopProxy(); + neo4j.startProxy(); // Then we should be able to start using sessions again, at most O(numSessions) session calls later int toleratedFailures = 4; @@ -102,8 +102,9 @@ void shouldDropBrokenOldSessions(String name, Config.ConfigBuilder configBuilder try (Driver driver = createDriver(clock, configBuilder.build())) { acquireAndReleaseConnections(5, driver); - // restart database to invalidate all idle connections in the pool - neo4j.forceRestartDb(); + // restart database access to invalidate all idle connections in the pool + neo4j.stopProxy(); + neo4j.startProxy(); // move clock forward more than configured liveness check timeout clock.progress(TimeUnit.MINUTES.toMillis(livenessCheckTimeoutMinutes + 1)); @@ -131,6 +132,6 @@ private Driver createDriver(Clock clock, Config config) { RoutingSettings routingSettings = RoutingSettings.DEFAULT; RetrySettings retrySettings = RetrySettings.DEFAULT; return factory.newInstance( - neo4j.uri(), DEFAULT_AUTH_TOKEN, routingSettings, retrySettings, config, SecurityPlanImpl.insecure()); + neo4j.uri(), neo4j.authToken(), routingSettings, retrySettings, config, SecurityPlanImpl.insecure()); } } diff --git a/driver/src/test/java/org/neo4j/driver/integration/SessionIT.java b/driver/src/test/java/org/neo4j/driver/integration/SessionIT.java index 3ede881fe5..cc235c64a1 100644 --- a/driver/src/test/java/org/neo4j/driver/integration/SessionIT.java +++ b/driver/src/test/java/org/neo4j/driver/integration/SessionIT.java @@ -50,7 +50,6 @@ import static org.neo4j.driver.internal.util.Matchers.connectionAcquisitionTimeoutError; import static org.neo4j.driver.internal.util.Neo4jFeature.BOLT_V4; import static org.neo4j.driver.util.DaemonThreadFactory.daemon; -import static org.neo4j.driver.util.Neo4jRunner.DEFAULT_AUTH_TOKEN; import java.util.HashSet; import java.util.List; @@ -1247,10 +1246,9 @@ private Driver newDriverWithoutRetries() { private Driver newDriverWithFixedRetries(int maxRetriesCount) { DriverFactory driverFactory = new DriverFactoryWithFixedRetryLogic(maxRetriesCount); - AuthToken auth = DEFAULT_AUTH_TOKEN; return driverFactory.newInstance( neo4j.uri(), - auth, + neo4j.authToken(), RoutingSettings.DEFAULT, RetrySettings.DEFAULT, noLoggingConfig(), diff --git a/driver/src/test/java/org/neo4j/driver/integration/TrustCustomCertificateIT.java b/driver/src/test/java/org/neo4j/driver/integration/TrustCustomCertificateIT.java index ca592292ab..b327ac1250 100644 --- a/driver/src/test/java/org/neo4j/driver/integration/TrustCustomCertificateIT.java +++ b/driver/src/test/java/org/neo4j/driver/integration/TrustCustomCertificateIT.java @@ -24,6 +24,7 @@ import static org.neo4j.driver.Config.TrustStrategy.trustCustomCertificateSignedBy; import static org.neo4j.driver.util.CertificateUtil.createNewCertificateAndKey; import static org.neo4j.driver.util.CertificateUtil.createNewCertificateAndKeySignedBy; +import static org.neo4j.driver.util.DatabaseExtension.getDockerHostGeneralName; import java.io.File; import java.util.function.Supplier; @@ -35,7 +36,6 @@ import org.neo4j.driver.Result; import org.neo4j.driver.Session; import org.neo4j.driver.exceptions.SecurityException; -import org.neo4j.driver.util.CertificateExtension; import org.neo4j.driver.util.CertificateUtil.CertificateKeyPair; import org.neo4j.driver.util.DatabaseExtension; import org.neo4j.driver.util.ParallelizableIT; @@ -43,7 +43,7 @@ @ParallelizableIT class TrustCustomCertificateIT { @RegisterExtension - static final DatabaseExtension neo4j = new CertificateExtension(); + static final DatabaseExtension neo4j = new DatabaseExtension(); @Test void shouldAcceptServerWithCertificateSignedByDriverCertificate() throws Throwable { @@ -51,7 +51,7 @@ void shouldAcceptServerWithCertificateSignedByDriverCertificate() throws Throwab CertificateKeyPair root = createNewCertificateAndKey(); // When - CertificateKeyPair server = createNewCertificateAndKeySignedBy(root); + CertificateKeyPair server = createNewCertificateAndKeySignedBy(root, getDockerHostGeneralName()); neo4j.updateEncryptionKeyAndCert(server.key(), server.cert()); // Then @@ -59,7 +59,7 @@ void shouldAcceptServerWithCertificateSignedByDriverCertificate() throws Throwab } @Test - void shouldAcceptServerWithSameCertificate() throws Throwable { + void shouldAcceptServerWithSameCertificate() { shouldBeAbleToRunCypher(() -> createDriverWithCustomCertificate(neo4j.tlsCertFile())); } @@ -70,7 +70,7 @@ void shouldRejectServerWithUntrustedCertificate() throws Throwable { // When & Then final Driver driver = createDriverWithCustomCertificate(certificateAndKey.cert()); - SecurityException error = assertThrows(SecurityException.class, driver::verifyConnectivity); + assertThrows(SecurityException.class, driver::verifyConnectivity); } private void shouldBeAbleToRunCypher(Supplier driverSupplier) { diff --git a/driver/src/test/java/org/neo4j/driver/integration/async/AsyncSessionServerRestartIT.java b/driver/src/test/java/org/neo4j/driver/integration/async/AsyncSessionServerRestartIT.java index 7370eb0d0d..0db23e4ec6 100644 --- a/driver/src/test/java/org/neo4j/driver/integration/async/AsyncSessionServerRestartIT.java +++ b/driver/src/test/java/org/neo4j/driver/integration/async/AsyncSessionServerRestartIT.java @@ -67,26 +67,26 @@ void shouldFailWhenServerIsRestarted() { ResultCursor cursor = await(session.runAsync(query)); if (i == 0) { - neo4j.stopDb(); + neo4j.stopProxy(); } List records = await(cursor.listAsync()); assertEquals(100, records.size()); } }); - neo4j.startDb(); + neo4j.startProxy(); } @Test void shouldRunAfterRunFailureToAcquireConnection() { - neo4j.stopDb(); + neo4j.stopProxy(); assertThrows(ServiceUnavailableException.class, () -> { ResultCursor cursor = await(session.runAsync("RETURN 42")); await(cursor.nextAsync()); }); - neo4j.startDb(); + neo4j.startProxy(); ResultCursor cursor2 = await(session.runAsync("RETURN 42")); Record record = await(cursor2.singleAsync()); @@ -95,14 +95,14 @@ void shouldRunAfterRunFailureToAcquireConnection() { @Test void shouldBeginTxAfterRunFailureToAcquireConnection() { - neo4j.stopDb(); + neo4j.stopProxy(); assertThrows(ServiceUnavailableException.class, () -> { ResultCursor cursor = await(session.runAsync("RETURN 42")); await(cursor.consumeAsync()); }); - neo4j.startDb(); + neo4j.startProxy(); AsyncTransaction tx = await(session.beginTransactionAsync()); ResultCursor cursor2 = await(tx.runAsync("RETURN 42")); diff --git a/driver/src/test/java/org/neo4j/driver/integration/async/AsyncTransactionIT.java b/driver/src/test/java/org/neo4j/driver/integration/async/AsyncTransactionIT.java index a9722344d2..753e04a819 100644 --- a/driver/src/test/java/org/neo4j/driver/integration/async/AsyncTransactionIT.java +++ b/driver/src/test/java/org/neo4j/driver/integration/async/AsyncTransactionIT.java @@ -508,7 +508,7 @@ void shouldFailToCommitWhenServerIsRestarted() { await(tx.runAsync("CREATE ()")); - neo4j.stopDb(); + neo4j.stopProxy(); assertThrows(ServiceUnavailableException.class, () -> await(tx.commitAsync())); } diff --git a/driver/src/test/java/org/neo4j/driver/integration/reactive/RxTransactionIT.java b/driver/src/test/java/org/neo4j/driver/integration/reactive/RxTransactionIT.java index 5c5336a682..b77d9f7ddb 100644 --- a/driver/src/test/java/org/neo4j/driver/integration/reactive/RxTransactionIT.java +++ b/driver/src/test/java/org/neo4j/driver/integration/reactive/RxTransactionIT.java @@ -549,7 +549,7 @@ void shouldFailToCommitWhenServerIsRestarted() { assertThrows(ServiceUnavailableException.class, () -> { await(Flux.from(result.records()).doOnSubscribe(subscription -> { - neo4j.stopDb(); + neo4j.stopProxy(); })); await(tx.commit()); }); diff --git a/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelPoolIT.java b/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelPoolIT.java index ea974d06fd..c15022ffec 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelPoolIT.java +++ b/driver/src/test/java/org/neo4j/driver/internal/async/pool/NettyChannelPoolIT.java @@ -55,7 +55,6 @@ import org.neo4j.driver.internal.util.FakeClock; import org.neo4j.driver.internal.util.ImmediateSchedulingEventExecutor; import org.neo4j.driver.util.DatabaseExtension; -import org.neo4j.driver.util.Neo4jRunner; import org.neo4j.driver.util.ParallelizableIT; @ParallelizableIT @@ -122,7 +121,7 @@ void shouldAllowAcquireAfterFailures() throws Exception { AuthenticationException e = assertThrows(AuthenticationException.class, () -> acquire(pool)); } - authTokenMap.put("credentials", value(Neo4jRunner.PASSWORD)); + authTokenMap.put("credentials", value(neo4j.adminPassword())); assertNotNull(acquire(pool)); } diff --git a/driver/src/test/java/org/neo4j/driver/internal/util/Neo4jWithFeatureCondition.java b/driver/src/test/java/org/neo4j/driver/internal/util/Neo4jWithFeatureCondition.java index 165e8b3c20..656c8fb16c 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/util/Neo4jWithFeatureCondition.java +++ b/driver/src/test/java/org/neo4j/driver/internal/util/Neo4jWithFeatureCondition.java @@ -30,8 +30,7 @@ import org.junit.jupiter.api.extension.ExtensionContext; import org.neo4j.driver.Driver; import org.neo4j.driver.Session; -import org.neo4j.driver.util.Neo4jRunner; -import org.neo4j.driver.util.Neo4jSettings; +import org.neo4j.driver.util.DatabaseExtension; public class Neo4jWithFeatureCondition implements ExecutionCondition { private static final ConditionEvaluationResult ENABLED_NOT_ANNOTATED = @@ -63,7 +62,7 @@ public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext con } private static ConditionEvaluationResult checkFeatureAvailability(Neo4jFeature feature, boolean negated) { - Driver driver = getSharedNeo4jDriver(); + Driver driver = DatabaseExtension.getInstance().driver(); if (driver != null) { try (Session session = driver.session()) { String agent = session.readTransaction( @@ -88,7 +87,7 @@ private static ConditionEvaluationResult checkEditionAvailability( if (previousResult.isDisabled()) { return previousResult; } - Driver driver = getSharedNeo4jDriver(); + Driver driver = DatabaseExtension.getInstance().driver(); if (driver != null) { try (Session session = driver.session()) { String value = session.run("CALL dbms.components() YIELD edition") @@ -122,17 +121,4 @@ private static ConditionEvaluationResult createResult( : disabled("Disabled on neo4j " + version + " because it does not support " + feature); } } - - private static Driver getSharedNeo4jDriver() { - try { - Neo4jRunner runner = Neo4jRunner.getOrCreateGlobalRunner(); - // ensure database is running with default credentials - runner.ensureRunning(Neo4jSettings.TEST_SETTINGS); - return runner.driver(); - } catch (Throwable t) { - System.err.println("Failed to check database version in the test execution condition"); - t.printStackTrace(); - return null; - } - } } diff --git a/driver/src/test/java/org/neo4j/driver/util/CertificateExtension.java b/driver/src/test/java/org/neo4j/driver/util/CertificateExtension.java deleted file mode 100644 index c654729d37..0000000000 --- a/driver/src/test/java/org/neo4j/driver/util/CertificateExtension.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [http://neo4j.com] - * - * This file is part of Neo4j. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.util; - -import static org.neo4j.driver.util.Neo4jRunner.debug; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; -import java.util.Arrays; -import org.junit.jupiter.api.extension.AfterEachCallback; -import org.junit.jupiter.api.extension.ExtensionContext; - -public class CertificateExtension extends DatabaseExtension implements AfterEachCallback { - private Path originalKeyFile; - private Path originalCertFile; - - @Override - public void beforeEach(ExtensionContext context) throws Exception { - super.beforeEach(context); - - originalKeyFile = Files.createTempFile("key-file-", ""); - originalCertFile = Files.createTempFile("cert-file-", ""); - - Files.copy(tlsKeyFile().toPath(), originalKeyFile, StandardCopyOption.REPLACE_EXISTING); - Files.copy(tlsCertFile().toPath(), originalCertFile, StandardCopyOption.REPLACE_EXISTING); - } - - @Override - public void afterEach(ExtensionContext context) throws Exception { - // if the key and cert file changed, then we restore the file and restart the server. - if (!smallFileContentEquals(tlsKeyFile().toPath(), originalKeyFile) - || !smallFileContentEquals(tlsCertFile().toPath(), originalCertFile)) { - debug("Restoring original key and certificate file after certificate test."); - updateEncryptionKeyAndCert(originalKeyFile.toFile(), originalCertFile.toFile()); - } - Files.deleteIfExists(originalKeyFile); - Files.deleteIfExists(originalCertFile); - } - - private boolean smallFileContentEquals(Path path, Path pathAnother) throws IOException { - byte[] fileContent = Files.readAllBytes(path); - byte[] fileContentAnother = Files.readAllBytes(pathAnother); - return Arrays.equals(fileContent, fileContentAnother); - } -} diff --git a/driver/src/test/java/org/neo4j/driver/util/CertificateUtil.java b/driver/src/test/java/org/neo4j/driver/util/CertificateUtil.java index f987b5bd5f..b84181c1c2 100644 --- a/driver/src/test/java/org/neo4j/driver/util/CertificateUtil.java +++ b/driver/src/test/java/org/neo4j/driver/util/CertificateUtil.java @@ -37,8 +37,11 @@ import java.security.Security; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; +import java.util.Arrays; import java.util.Date; +import java.util.HashSet; import java.util.Objects; +import java.util.Set; import javax.security.auth.x500.X500Principal; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.BasicConstraints; @@ -79,7 +82,7 @@ private static KeyPair generateKeyPair() throws NoSuchProviderException, NoSuchA } private static X509Certificate generateCert( - X500Name issuer, X500Name subject, KeyPair issuerKeys, PublicKey publicKey) + X500Name issuer, X500Name subject, KeyPair issuerKeys, PublicKey publicKey, GeneralName... generalNames) throws GeneralSecurityException, OperatorCreationException, CertIOException { // Create x509 certificate Date startDate = new Date(System.currentTimeMillis()); @@ -89,7 +92,10 @@ private static X509Certificate generateCert( new JcaX509v3CertificateBuilder(issuer, serialNum, startDate, endDate, subject, publicKey); // Subject alternative name (part of SNI extension, used for hostname verification) - GeneralNames subjectAlternativeName = new GeneralNames(new GeneralName(GeneralName.dNSName, DEFAULT_HOST_NAME)); + Set names = new HashSet<>(); + names.add(new GeneralName(GeneralName.dNSName, DEFAULT_HOST_NAME)); + names.addAll(Arrays.asList(generalNames)); + GeneralNames subjectAlternativeName = new GeneralNames(names.toArray(new GeneralName[0])); certBuilder.addExtension(Extension.subjectAlternativeName, false, subjectAlternativeName); certBuilder.addExtension(Extension.basicConstraints, false, new BasicConstraints(true)); @@ -107,7 +113,7 @@ public static class SelfSignedCertificateGenerator { private final KeyPair keyPair; private final X509Certificate certificate; - public SelfSignedCertificateGenerator() + public SelfSignedCertificateGenerator(GeneralName... generalNames) throws GeneralSecurityException, OperatorCreationException, CertIOException { // Create the public/private rsa key pair keyPair = generateKeyPair(); @@ -117,7 +123,8 @@ public SelfSignedCertificateGenerator() new X500Name("CN=" + DEFAULT_HOST_NAME), new X500Name("CN=" + DEFAULT_HOST_NAME), keyPair, - keyPair.getPublic()); + keyPair.getPublic(), + generalNames); } public void savePrivateKey(File saveTo) throws IOException { @@ -128,14 +135,15 @@ public void saveSelfSignedCertificate(File saveTo) throws CertificateEncodingExc writePem("CERTIFICATE", certificate.getEncoded(), saveTo); } - public X509Certificate sign(PKCS10CertificationRequest csr, PublicKey csrPublicKey) + public X509Certificate sign(PKCS10CertificationRequest csr, PublicKey csrPublicKey, GeneralName... generalNames) throws GeneralSecurityException, OperatorCreationException, CertIOException { return generateCert( X500Name.getInstance( this.certificate.getSubjectX500Principal().getEncoded()), csr.getSubject(), keyPair, - csrPublicKey); + csrPublicKey, + generalNames); } } @@ -195,26 +203,27 @@ private static void writePem(String type, byte[] encodedContent, File path) thro } } - public static CertificateKeyPair createNewCertificateAndKeySignedBy(CertificateKeyPair root) - throws Throwable { + public static CertificateKeyPair createNewCertificateAndKeySignedBy( + CertificateKeyPair root, GeneralName... generalNames) throws Throwable { Objects.requireNonNull(root.certGenerator); File cert = tempFile("driver", ".cert"); File key = tempFile("driver", ".key"); CertificateUtil.CertificateSigningRequestGenerator csrGenerator = new CertificateUtil.CertificateSigningRequestGenerator(); - X509Certificate signedCert = - root.certGenerator.sign(csrGenerator.certificateSigningRequest(), csrGenerator.publicKey()); + X509Certificate signedCert = root.certGenerator.sign( + csrGenerator.certificateSigningRequest(), csrGenerator.publicKey(), generalNames); csrGenerator.savePrivateKey(key); saveX509Cert(signedCert, cert); return new CertificateKeyPair<>(cert, key); } - public static CertificateKeyPair createNewCertificateAndKey() throws Throwable { + public static CertificateKeyPair createNewCertificateAndKey(GeneralName... ipAddresses) + throws Throwable { File cert = tempFile("driver", ".cert"); File key = tempFile("driver", ".key"); CertificateUtil.SelfSignedCertificateGenerator certGenerator = - new CertificateUtil.SelfSignedCertificateGenerator(); + new CertificateUtil.SelfSignedCertificateGenerator(ipAddresses); certGenerator.saveSelfSignedCertificate(cert); certGenerator.savePrivateKey(key); diff --git a/driver/src/test/java/org/neo4j/driver/util/DatabaseExtension.java b/driver/src/test/java/org/neo4j/driver/util/DatabaseExtension.java index 349a8c1faa..c0eea975f1 100644 --- a/driver/src/test/java/org/neo4j/driver/util/DatabaseExtension.java +++ b/driver/src/test/java/org/neo4j/driver/util/DatabaseExtension.java @@ -19,121 +19,227 @@ package org.neo4j.driver.util; import static java.lang.Integer.parseInt; -import static org.neo4j.driver.util.Neo4jRunner.DEFAULT_AUTH_TOKEN; -import static org.neo4j.driver.util.Neo4jRunner.HOME_DIR; -import static org.neo4j.driver.util.Neo4jRunner.debug; -import static org.neo4j.driver.util.Neo4jRunner.getOrCreateGlobalRunner; -import static org.neo4j.driver.util.Neo4jSettings.DEFAULT_TLS_CERT_PATH; -import static org.neo4j.driver.util.Neo4jSettings.DEFAULT_TLS_KEY_PATH; +import static org.neo4j.driver.util.Neo4jSettings.BOLT_TLS_LEVEL; +import static org.neo4j.driver.util.Neo4jSettings.BoltTlsLevel.OPTIONAL; +import static org.neo4j.driver.util.Neo4jSettings.BoltTlsLevel.REQUIRED; +import static org.neo4j.driver.util.Neo4jSettings.SSL_POLICY_BOLT_CLIENT_AUTH; +import static org.neo4j.driver.util.Neo4jSettings.SSL_POLICY_BOLT_ENABLED; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.net.URI; -import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import org.bouncycastle.asn1.x509.GeneralName; import org.junit.jupiter.api.extension.AfterAllCallback; +import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ConditionEvaluationResult; +import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtensionContext; import org.neo4j.driver.AuthToken; +import org.neo4j.driver.AuthTokens; +import org.neo4j.driver.Config; import org.neo4j.driver.Driver; +import org.neo4j.driver.GraphDatabase; import org.neo4j.driver.Session; import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.types.TypeSystem; +import org.neo4j.driver.util.CertificateUtil.CertificateKeyPair; +import org.testcontainers.DockerClientFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.Neo4jContainer; +import org.testcontainers.containers.Network; +import org.testcontainers.images.builder.ImageFromDockerfile; +import org.testcontainers.utility.DockerImageName; +import org.testcontainers.utility.MountableFile; -public class DatabaseExtension implements BeforeEachCallback, AfterAllCallback { - static final String TEST_RESOURCE_FOLDER_PATH = "src/test/resources"; +public class DatabaseExtension implements ExecutionCondition, BeforeEachCallback, AfterEachCallback, AfterAllCallback { + private static final int BOLT_PORT = 7687; + private static final int HTTP_PORT = 7474; - private final Neo4jSettings settings; - private Neo4jRunner runner; + private static final boolean dockerAvailable; + private static final DatabaseExtension instance; + private static final URI boltUri; + private static final URI httpUri; + private static final AuthToken authToken; + private static final File cert; + private static final File key; + private static final Network network; + private static final GenericContainer nginx; + private static final Map defaultConfig; - public DatabaseExtension() { - this(Neo4jSettings.TEST_SETTINGS); + private static Neo4jContainer neo4jContainer; + private static Driver driver; + private static boolean nginxRunning; + + static { + dockerAvailable = isDockerAvailable(); + instance = new DatabaseExtension(); + defaultConfig = new HashMap<>(); + defaultConfig.put(SSL_POLICY_BOLT_ENABLED, "true"); + defaultConfig.put(SSL_POLICY_BOLT_CLIENT_AUTH, "NONE"); + defaultConfig.put(BOLT_TLS_LEVEL, OPTIONAL.toString()); + + if (dockerAvailable) { + CertificateKeyPair pair = generateCertificateAndKey(); + cert = pair.cert(); + key = pair.key(); + + network = Network.newNetwork(); + neo4jContainer = setupNeo4jContainer(cert, key, defaultConfig); + neo4jContainer.start(); + nginx = setupNginxContainer(); + nginx.start(); + nginxRunning = true; + + URI neo4jBoltUri = URI.create(neo4jContainer.getBoltUrl()); + URI neo4jHttpUri = URI.create(neo4jContainer.getHttpUrl()); + + boltUri = URI.create(String.format( + "%s://%s:%d", neo4jBoltUri.getScheme(), neo4jBoltUri.getHost(), nginx.getMappedPort(BOLT_PORT))); + httpUri = URI.create(String.format( + "%s://%s:%d", neo4jHttpUri.getScheme(), neo4jHttpUri.getHost(), nginx.getMappedPort(HTTP_PORT))); + + authToken = AuthTokens.basic("neo4j", neo4jContainer.getAdminPassword()); + driver = GraphDatabase.driver(boltUri, authToken); + waitForBoltAvailability(); + } else { + // stub init, this is not usable when Docker is unavailable + boltUri = URI.create(""); + httpUri = URI.create(""); + authToken = AuthTokens.none(); + cert = new File(""); + key = new File(""); + network = null; + nginx = new GenericContainer<>(DockerImageName.parse("alpine:latest")); + } } - public DatabaseExtension(Neo4jSettings settings) { - this.settings = settings; + @Override + public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { + return dockerAvailable + ? ConditionEvaluationResult.enabled("Docker is available") + : ConditionEvaluationResult.disabled("Docker is unavailable"); } @Override public void beforeEach(ExtensionContext context) throws Exception { - runner = getOrCreateGlobalRunner(); - runner.ensureRunning(settings); - TestUtil.cleanDb(driver()); + TestUtil.cleanDb(driver); } @Override - public void afterAll(ExtensionContext context) { - if (runner != null) { - runner.stopNeo4j(); + public void afterEach(ExtensionContext context) throws Exception { + if (!nginxRunning) { + startProxy(); } } + @Override + public void afterAll(ExtensionContext context) { + deleteAndStartNeo4j(Collections.emptyMap()); + } + public Driver driver() { - return runner.driver(); + return driver; } public TypeSystem typeSystem() { - return driver().defaultTypeSystem(); + return driver.defaultTypeSystem(); } - public void forceRestartDb() { - runner.forceToRestart(); - } + public void deleteAndStartNeo4j(Map config) { + Map updatedConfig = new HashMap<>(defaultConfig); + updatedConfig.putAll(config); - public void restartDb(Neo4jSettings neo4jSettings) { - runner.restartNeo4j(neo4jSettings); + neo4jContainer.stop(); + neo4jContainer = setupNeo4jContainer(cert, key, updatedConfig); + neo4jContainer.start(); + if (REQUIRED.toString().equals(config.get(BOLT_TLS_LEVEL))) { + driver = GraphDatabase.driver( + boltUri, + authToken, + Config.builder() + .withTrustStrategy(Config.TrustStrategy.trustCustomCertificateSignedBy(cert)) + .withEncryption() + .build()); + } else { + driver = GraphDatabase.driver(boltUri, authToken); + } + waitForBoltAvailability(); } - public URL putTmpFile(String prefix, String suffix, String contents) throws IOException { + public String addImportFile(String prefix, String suffix, String contents) throws IOException { File tmpFile = File.createTempFile(prefix, suffix, null); tmpFile.deleteOnExit(); try (PrintWriter out = new PrintWriter(tmpFile)) { out.println(contents); } - return tmpFile.toURI().toURL(); + Path tmpFilePath = tmpFile.toPath(); + Path targetPath = + Paths.get("/var/lib/neo4j/import", tmpFilePath.getFileName().toString()); + neo4jContainer.copyFileToContainer(MountableFile.forHostPath(tmpFilePath), targetPath.toString()); + return String.format("file:///%s", tmpFile.getName()); } public URI uri() { - return runner.boltUri(); + return boltUri; } public int httpPort() { - return runner.httpPort(); + return httpUri.getPort(); } public int boltPort() { - return runner.boltPort(); + return boltUri.getPort(); } public AuthToken authToken() { - return DEFAULT_AUTH_TOKEN; + return authToken; } - public BoltServerAddress address() { - return runner.boltAddress(); + public String adminPassword() { + return neo4jContainer.getAdminPassword(); } - public void updateEncryptionKeyAndCert(File key, File cert) throws Exception { - FileTools.copyFile(key, tlsKeyFile()); - FileTools.copyFile(cert, tlsCertFile()); - debug("Updated neo4j key and certificate file."); - runner.forceToRestart(); // needs to force to restart as no configuration changed + public BoltServerAddress address() { + return new BoltServerAddress(boltUri); } - public File tlsCertFile() { - return new File(HOME_DIR, DEFAULT_TLS_CERT_PATH); + public void updateEncryptionKeyAndCert(File key, File cert) { + System.out.println("Updated neo4j key and certificate file."); + neo4jContainer.stop(); + neo4jContainer = setupNeo4jContainer(cert, key, defaultConfig); + neo4jContainer.start(); + driver = GraphDatabase.driver(boltUri, authToken); + waitForBoltAvailability(); } - public File tlsKeyFile() { - return new File(HOME_DIR, DEFAULT_TLS_KEY_PATH); + public File tlsCertFile() { + return cert; } - public void startDb() { - runner.startNeo4j(); + public void startProxy() { + try { + nginx.execInContainer("nginx"); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } + nginxRunning = true; } - public void stopDb() { - runner.stopNeo4j(); + public void stopProxy() { + try { + nginx.execInContainer("nginx", "-s", "stop"); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } + nginxRunning = false; } public boolean isNeo4j44OrEarlier() { @@ -144,12 +250,8 @@ public boolean isNeo4j43OrEarlier() { return isNeo4jVersionOrEarlier(4, 3); } - public void dumpLogs() { - runner.dumpDebugLog(); - } - private boolean isNeo4jVersionOrEarlier(int major, int minor) { - try (Session session = driver().session()) { + try (Session session = driver.session()) { String neo4jVersion = session.readTransaction( tx -> tx.run("CALL dbms.components() YIELD versions " + "RETURN versions[0] AS version") .single() @@ -159,4 +261,99 @@ private boolean isNeo4jVersionOrEarlier(int major, int minor) { return parseInt(versions[0]) <= major && parseInt(versions[1]) <= minor; } } + + public static DatabaseExtension getInstance() { + return instance; + } + + public static GeneralName getDockerHostGeneralName() { + String host = DockerClientFactory.instance().dockerHostIpAddress(); + GeneralName generalName; + try { + generalName = new GeneralName(GeneralName.iPAddress, host); + } catch (IllegalArgumentException e) { + generalName = new GeneralName(GeneralName.dNSName, host); + } + return generalName; + } + + private static CertificateKeyPair generateCertificateAndKey() { + try { + return CertificateUtil.createNewCertificateAndKey(getDockerHostGeneralName()); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + private static Neo4jContainer setupNeo4jContainer(File cert, File key, Map config) { + String neo4JVersion = + Optional.ofNullable(System.getenv("NEO4J_VERSION")).orElse("4.4"); + + ImageFromDockerfile extendedNeo4jImage = new ImageFromDockerfile() + .withDockerfileFromBuilder(builder -> builder.from(String.format("neo4j:%s-enterprise", neo4JVersion)) + .run("mkdir /var/lib/neo4j/certificates/bolt") + .copy("public.crt", "/var/lib/neo4j/certificates/bolt/") + .copy("private.key", "/var/lib/neo4j/certificates/bolt/") + .build()) + .withFileFromPath("public.crt", cert.toPath()) + .withFileFromPath("private.key", key.toPath()); + + DockerImageName extendedNeo4jImageAsSubstitute = + DockerImageName.parse(extendedNeo4jImage.get()).asCompatibleSubstituteFor("neo4j"); + + neo4jContainer = new Neo4jContainer<>(extendedNeo4jImageAsSubstitute) + .withEnv("NEO4J_ACCEPT_LICENSE_AGREEMENT", "yes") + .withNetwork(network) + .withNetworkAliases("neo4j"); + for (Map.Entry entry : config.entrySet()) { + neo4jContainer.withNeo4jConfig(entry.getKey(), entry.getValue()); + } + + return neo4jContainer; + } + + private static GenericContainer setupNginxContainer() { + ImageFromDockerfile extendedNginxImage = new ImageFromDockerfile() + .withDockerfileFromBuilder(builder -> builder.from("nginx:1.23.0-alpine") + .copy("nginx.conf", "/etc/nginx/") + .build()) + .withFileFromClasspath("nginx.conf", "nginx.conf"); + + //noinspection rawtypes + return new GenericContainer(extendedNginxImage.get()) + .withNetwork(network) + .withExposedPorts(BOLT_PORT, HTTP_PORT) + .withCommand("sh", "-c", "nginx && while sleep 3600; do :; done"); + } + + private static void waitForBoltAvailability() { + int maxAttempts = 600; + for (int attempt = 0; attempt < maxAttempts; attempt++) { + try { + driver.verifyConnectivity(); + return; + } catch (RuntimeException verificationException) { + if (attempt == maxAttempts - 1) { + throw new RuntimeException( + "Timed out waiting for Neo4j to become available over Bolt", verificationException); + } + try { + Thread.sleep(500); + } catch (InterruptedException interruptedException) { + interruptedException.addSuppressed(verificationException); + throw new RuntimeException( + "Interrupted while waiting for Neo4j to become available over Bolt", interruptedException); + } + } + } + } + + private static boolean isDockerAvailable() { + try { + DockerClientFactory.instance().client(); + return true; + } catch (Throwable ex) { + return false; + } + } } diff --git a/driver/src/test/java/org/neo4j/driver/util/Neo4jRunner.java b/driver/src/test/java/org/neo4j/driver/util/Neo4jRunner.java deleted file mode 100644 index 152038f71a..0000000000 --- a/driver/src/test/java/org/neo4j/driver/util/Neo4jRunner.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [http://neo4j.com] - * - * This file is part of Neo4j. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.util; - -import static java.util.Arrays.asList; -import static java.util.logging.Level.INFO; -import static org.junit.jupiter.api.Assumptions.assumeTrue; -import static org.neo4j.driver.AuthTokens.basic; -import static org.neo4j.driver.Logging.console; -import static org.neo4j.driver.util.FileTools.moveFile; -import static org.neo4j.driver.util.FileTools.updateProperties; -import static org.neo4j.driver.util.Neo4jSettings.CURRENT_BOLT_PORT; -import static org.neo4j.driver.util.Neo4jSettings.CURRENT_HTTP_PORT; -import static org.neo4j.driver.util.Neo4jSettings.TEST_JVM_ID; -import static org.neo4j.driver.util.cc.CommandLineUtil.boltKitAvailable; -import static org.neo4j.driver.util.cc.CommandLineUtil.executeCommand; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.StandardSocketOptions; -import java.net.URI; -import java.nio.channels.SocketChannel; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Scanner; -import org.neo4j.driver.AuthToken; -import org.neo4j.driver.Config; -import org.neo4j.driver.Driver; -import org.neo4j.driver.GraphDatabase; -import org.neo4j.driver.internal.BoltServerAddress; -import org.neo4j.driver.internal.util.ErrorUtil; - -/** - * This class wraps the neo4j stand-alone jar in some code to help pulling it in from a remote URL and then launching - * it in a separate process. - */ -public class Neo4jRunner { - private static Neo4jRunner globalInstance; - - private static final String DEFAULT_NEOCTRL_ARGS = "-e 3.5.11"; - private static final String ENV_NEOCTRL_ARGS = System.getenv("JAVA_DRIVER_NEOCTRL_ARGS"); - public static final String NEOCTRL_ARGS = - System.getProperty("neoctrl.args", ENV_NEOCTRL_ARGS == null ? DEFAULT_NEOCTRL_ARGS : ENV_NEOCTRL_ARGS); - public static final Config DEFAULT_CONFIG = - Config.builder().withLogging(console(INFO)).withoutEncryption().build(); - - public static final String USER = "neo4j"; - public static final String PASSWORD = "password"; - public static final AuthToken DEFAULT_AUTH_TOKEN = basic(USER, PASSWORD); - - private Neo4jSettings currentSettings = Neo4jSettings.TEST_SETTINGS; - - public static final String TARGET_DIR = new File("../target").getAbsolutePath(); - private static final String NEO4J_DIR = new File(TARGET_DIR, "test-server-" + TEST_JVM_ID).getAbsolutePath(); - public static final String HOME_DIR = new File(NEO4J_DIR, "neo4jHome").getAbsolutePath(); - - private Driver driver; - private boolean restartDriver; - - public int httpPort() { - return CURRENT_HTTP_PORT; - } - - public int boltPort() { - return CURRENT_BOLT_PORT; - } - - public BoltServerAddress boltAddress() { - return new BoltServerAddress(boltUri()); - } - - public URI boltUri() { - return URI.create("bolt://localhost:" + boltPort()); - } - - /** Global runner controlling a single server, used to avoid having to restart the server between tests */ - public static synchronized Neo4jRunner getOrCreateGlobalRunner() throws IOException { - assumeTrue(boltKitAvailable(), "BoltKit support unavailable"); - if (globalInstance == null) { - globalInstance = new Neo4jRunner(); - } - return globalInstance; - } - - public static synchronized boolean globalRunnerExists() { - return globalInstance != null; - } - - private Neo4jRunner() throws IOException { - try { - installNeo4j(); - updateServerSettingsFile(); - try { - startNeo4j(); - } catch (Exception e) { - debug("Failed to start server first time due to error: " - + ErrorUtil.getRootCause(e).getMessage()); - debug("Retry to start server again."); - startNeo4j(); - } - } finally { - // Make sure we stop on JVM exit even if start failed - installShutdownHook(); - } - } - - public void ensureRunning(Neo4jSettings neo4jSettings) { - ServerStatus status = serverStatus(); - switch (status) { - case OFFLINE: - updateServerSettings(neo4jSettings); - startNeo4j(); - break; - case ONLINE: - restartNeo4j(neo4jSettings); - break; - } - } - - public Driver driver() { - if (restartDriver) { - restartDriver = false; - if (driver != null) { - driver.close(); - driver = null; - } - } - - if (driver == null) { - driver = GraphDatabase.driver(boltUri(), DEFAULT_AUTH_TOKEN, DEFAULT_CONFIG); - } - return driver; - } - - private void installNeo4j() throws IOException { - File targetHomeFile = new File(HOME_DIR); - if (targetHomeFile.exists()) { - debug("Found and using server installed at `%s`. ", HOME_DIR); - } else { - List commands = new ArrayList<>(); - commands.add("neoctrl-install"); - String[] split = NEOCTRL_ARGS.trim().split("\\s+"); - commands.addAll(asList(split)); - commands.add(NEO4J_DIR); - - String tempHomeDir = executeCommand(commands).trim(); - debug("Downloaded server at `%s`, now renaming to `%s`.", tempHomeDir, HOME_DIR); - - moveFile(new File(tempHomeDir), targetHomeFile); - debug("Installed server at `%s`.", HOME_DIR); - executeCommand("neoctrl-set-initial-password", PASSWORD, HOME_DIR); - } - } - - public void startNeo4j() { - debug("Starting server..."); - executeCommand("neoctrl-start", HOME_DIR, "-v"); - debug("Server started."); - } - - public synchronized void stopNeo4j() { - if (serverStatus() == ServerStatus.OFFLINE) { - return; - } - restartDriver = true; - - debug("Stopping server..."); - executeCommand("neoctrl-stop", HOME_DIR); - debug("Server stopped."); - } - - public void killNeo4j() { - if (serverStatus() == ServerStatus.OFFLINE) { - return; - } - restartDriver = true; - - debug("Killing server..."); - executeCommand("neoctrl-stop", "-k", HOME_DIR); - debug("Server killed."); - } - - public void forceToRestart() { - stopNeo4j(); - startNeo4j(); - } - - /** - * Restart the server with default testing server configuration - */ - public void restartNeo4j() { - restartNeo4j(Neo4jSettings.TEST_SETTINGS); - } - - /** - * Will only restart the server if any configuration changes happens - * @param neo4jSettings - */ - public void restartNeo4j(Neo4jSettings neo4jSettings) { - if (updateServerSettings(neo4jSettings)) // needs to update server setting files - { - forceToRestart(); - } - } - - /** - * prints the debug log contents to stdOut - */ - public void dumpDebugLog() { - try { - System.out.println("Debug log for: " + HOME_DIR); - Scanner input = new Scanner(new File(HOME_DIR + "/logs/debug.log")); - - while (input.hasNextLine()) { - System.out.println(input.nextLine()); - } - } catch (FileNotFoundException e) { - System.out.println("Unable to find debug log file for: " + HOME_DIR); - e.printStackTrace(); - } - } - - private enum ServerStatus { - ONLINE, - OFFLINE - } - - private ServerStatus serverStatus() { - try { - SocketChannel soChannel = SocketChannel.open(); - soChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true); - BoltServerAddress address = boltAddress(); - soChannel.connect(new InetSocketAddress(address.connectionHost(), address.port())); - soChannel.close(); - return ServerStatus.ONLINE; - } catch (IOException e) { - return ServerStatus.OFFLINE; - } - } - - private boolean updateServerSettings(Neo4jSettings newSetting) { - if (currentSettings.equals(newSetting)) { - return false; - } else { - currentSettings = newSetting; - } - updateServerSettingsFile(); - return true; - } - - /** - * Write updated neo4j settings into neo4j-server.properties for use by the next start - */ - private void updateServerSettingsFile() { - Map propertiesMap = currentSettings.propertiesMap(); - - if (propertiesMap.isEmpty()) { - return; - } - - File oldFile = new File(HOME_DIR, "conf/neo4j.conf"); - try { - debug("Changing server properties file (for next start): %s", oldFile.getCanonicalPath()); - for (Map.Entry property : propertiesMap.entrySet()) { - String name = property.getKey(); - Object value = property.getValue(); - debug("%s=%s", name, value); - } - - updateProperties(oldFile, propertiesMap, currentSettings.excludes()); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private void installShutdownHook() { - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - try { - debug("Starting shutdown hook"); - if (driver != null) { - driver.close(); - } - stopNeo4j(); - debug("Finished shutdown hook"); - } catch (Exception e) { - e.printStackTrace(); - } - })); - } - - public static void debug(String text, Object... args) { - System.out.println(String.format(text, args)); - } - - public static void debug(String text) { - System.out.println(text); - } -} diff --git a/driver/src/test/java/org/neo4j/driver/util/Neo4jSettings.java b/driver/src/test/java/org/neo4j/driver/util/Neo4jSettings.java index de3541bc8a..7c5ad16580 100644 --- a/driver/src/test/java/org/neo4j/driver/util/Neo4jSettings.java +++ b/driver/src/test/java/org/neo4j/driver/util/Neo4jSettings.java @@ -29,16 +29,14 @@ public class Neo4jSettings { public static final String DATA_DIR = "dbms.directories.data"; public static final String IMPORT_DIR = "dbms.directories.import"; + public static final String SSL_POLICY_BOLT_ENABLED = "dbms.ssl.policy.bolt.enabled"; + public static final String SSL_POLICY_BOLT_CLIENT_AUTH = "dbms.ssl.policy.bolt.client_auth"; // 5.0 - public static final String SERVER_IMPORT_DIR = "server.directories.import"; public static final String LISTEN_ADDR = "dbms.default_listen_address"; public static final String IPV6_ENABLED_ADDR = "::"; public static final String BOLT_TLS_LEVEL = "dbms.connector.bolt.tls_level"; private static final String DEFAULT_IMPORT_DIR = "import"; - private static final String DEFAULT_CERT_DIR = "certificates"; - public static final String DEFAULT_TLS_CERT_PATH = DEFAULT_CERT_DIR + "/neo4j.cert"; - public static final String DEFAULT_TLS_KEY_PATH = DEFAULT_CERT_DIR + "/neo4j.key"; public static final String DEFAULT_BOLT_TLS_LEVEL = BoltTlsLevel.OPTIONAL.toString(); public static final String DEFAULT_DATA_DIR = "data"; @@ -93,21 +91,6 @@ public Map propertiesMap() { return settings; } - public Neo4jSettings updateWith(String key, String value) { - return updateWith(map(key, value), excludes); - } - - private Neo4jSettings updateWith(Map updates, Set excludes) { - HashMap newSettings = new HashMap<>(settings); - for (Map.Entry entry : updates.entrySet()) { - newSettings.put(entry.getKey(), entry.getValue()); - } - for (String exclude : excludes) { - newSettings.remove(exclude); - } - return new Neo4jSettings(newSettings, excludes); - } - public Neo4jSettings without(String key) { Set newExcludes = new HashSet<>(excludes); newExcludes.add(key); diff --git a/driver/src/test/java/org/neo4j/driver/util/ProcessEnvConfigurator.java b/driver/src/test/java/org/neo4j/driver/util/ProcessEnvConfigurator.java deleted file mode 100644 index 7c60e7e02c..0000000000 --- a/driver/src/test/java/org/neo4j/driver/util/ProcessEnvConfigurator.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [http://neo4j.com] - * - * This file is part of Neo4j. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.util; - -public final class ProcessEnvConfigurator { - /** - * Name of environment variable used by the Neo4j database. - */ - private static final String JAVA_HOME = "JAVA_HOME"; - /** - * Name of environment variable to be used for the Neo4j database, defined by the build system. - */ - private static final String NEO4J_JAVA = "NEO4J_JAVA"; - /** - * Name of an optional environment variable containing file path to a local Neo4j package. - * This package is used by boltkit instead of downloading a package with the specified Neo4j version. - */ - private static final String BOLTKIT_LOCAL_PACKAGE = "NEOCTRL_LOCAL_PACKAGE"; - - private ProcessEnvConfigurator() {} - - public static void configure(ProcessBuilder processBuilder) { - processBuilder.environment().put(JAVA_HOME, determineJavaHome()); - - String localPackage = determineLocalPackage(); - if (localPackage != null) { - processBuilder.environment().put(BOLTKIT_LOCAL_PACKAGE, localPackage); - } - } - - /** - * This driver is built to work with multiple java versions. Neo4j, however, works with a specific version of - * Java. This allows specifying which Java version to use for Neo4j separately from which version to use for - * the driver tests. - *

- * This method determines which java home to use based on present environment variables. - * - * @return path to the java home. - */ - private static String determineJavaHome() { - return System.getenv().getOrDefault(NEO4J_JAVA, System.getProperties().getProperty("java.home")); - } - - private static String determineLocalPackage() { - String value = System.getenv().getOrDefault(BOLTKIT_LOCAL_PACKAGE, "").trim(); - return value.isEmpty() ? null : value; - } -} diff --git a/driver/src/test/java/org/neo4j/driver/util/cc/CommandLineException.java b/driver/src/test/java/org/neo4j/driver/util/cc/CommandLineException.java deleted file mode 100644 index d245aaaee0..0000000000 --- a/driver/src/test/java/org/neo4j/driver/util/cc/CommandLineException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [http://neo4j.com] - * - * This file is part of Neo4j. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.util.cc; - -class CommandLineException extends RuntimeException { - CommandLineException(String message) { - super(message); - } - - CommandLineException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/driver/src/test/java/org/neo4j/driver/util/cc/CommandLineUtil.java b/driver/src/test/java/org/neo4j/driver/util/cc/CommandLineUtil.java deleted file mode 100644 index b6027238ad..0000000000 --- a/driver/src/test/java/org/neo4j/driver/util/cc/CommandLineUtil.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) "Neo4j" - * Neo4j Sweden AB [http://neo4j.com] - * - * This file is part of Neo4j. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.neo4j.driver.util.cc; - -import static java.lang.System.lineSeparator; -import static java.util.Arrays.asList; -import static java.util.concurrent.TimeUnit.MINUTES; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import org.neo4j.driver.util.DaemonThreadFactory; -import org.neo4j.driver.util.ProcessEnvConfigurator; - -public class CommandLineUtil { - private static final ExecutorService executor = - Executors.newCachedThreadPool(new DaemonThreadFactory("command-line-thread-")); - - public static boolean boltKitAvailable() { - try { - executeCommand("neoctrl-cluster", "--help"); - return true; - } catch (CommandLineException e) { - return false; - } - } - - public static String executeCommand(List commands) { - try { - ProcessBuilder processBuilder = new ProcessBuilder().command(commands); - ProcessEnvConfigurator.configure(processBuilder); - return executeAndGetStdOut(processBuilder); - } catch (IOException | CommandLineException e) { - throw new CommandLineException("Error running command " + commands, e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new CommandLineException("Interrupted while waiting for command " + commands, e); - } - } - - public static String executeCommand(String... command) { - return executeCommand(asList(command)); - } - - private static String executeAndGetStdOut(ProcessBuilder processBuilder) throws IOException, InterruptedException { - Process process = processBuilder.start(); - Future stdOutFuture = read(process.getInputStream()); - Future stdErrFuture = read(process.getErrorStream()); - int exitCode = process.waitFor(); - String stdOut = get(stdOutFuture); - String stdErr = get(stdErrFuture); - if (exitCode != 0) { - throw new CommandLineException("Non-zero exit code\nSTDOUT:\n" + stdOut + "\nSTDERR:\n" + stdErr); - } - return stdOut; - } - - private static Future read(final InputStream input) { - return executor.submit(new Callable() { - @Override - public String call() throws Exception { - return readToString(input); - } - }); - } - - private static String readToString(InputStream input) { - StringBuilder result = new StringBuilder(); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(input))) { - String line; - while ((line = reader.readLine()) != null) { - result.append(line).append(lineSeparator()); - } - } catch (IOException e) { - throw new CommandLineException("Unable to read from stream", e); - } - return result.toString(); - } - - private static T get(Future future) { - try { - return future.get(10, MINUTES); - } catch (Exception e) { - throw new RuntimeException(e); - } - } -} diff --git a/driver/src/test/resources/logback-test.xml b/driver/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..ea9a2a3fac --- /dev/null +++ b/driver/src/test/resources/logback-test.xml @@ -0,0 +1,14 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n + + + + + + + + + + \ No newline at end of file diff --git a/driver/src/test/resources/nginx.conf b/driver/src/test/resources/nginx.conf new file mode 100644 index 0000000000..4b8694ed11 --- /dev/null +++ b/driver/src/test/resources/nginx.conf @@ -0,0 +1,30 @@ +user nginx; +worker_processes auto; + +error_log /var/log/nginx/error.log notice; +pid /var/run/nginx.pid; + + +events { + worker_connections 1024; +} + +stream { + server { + resolver 127.0.0.11 ipv6=off; + + set $upstream neo4j:7687; + + listen 7687; + proxy_pass $upstream; + } + + server { + resolver 127.0.0.11 ipv6=off; + + set $upstream neo4j:7474; + + listen 7474; + proxy_pass $upstream; + } +} \ No newline at end of file diff --git a/examples/pom.xml b/examples/pom.xml index a18bd4456a..eddc9f5683 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -74,6 +74,10 @@ neo4j test + + org.bouncycastle + bcpkix-jdk15on + diff --git a/examples/src/test/java/org/neo4j/docs/driver/ExamplesIT.java b/examples/src/test/java/org/neo4j/docs/driver/ExamplesIT.java index b92fce2084..e62d97a2da 100644 --- a/examples/src/test/java/org/neo4j/docs/driver/ExamplesIT.java +++ b/examples/src/test/java/org/neo4j/docs/driver/ExamplesIT.java @@ -36,8 +36,6 @@ import static org.neo4j.driver.Values.parameters; import static org.neo4j.driver.internal.util.Neo4jEdition.ENTERPRISE; import static org.neo4j.driver.internal.util.Neo4jFeature.BOLT_V4; -import static org.neo4j.driver.util.Neo4jRunner.PASSWORD; -import static org.neo4j.driver.util.Neo4jRunner.USER; import static org.neo4j.driver.util.TestUtil.await; import static org.neo4j.driver.util.TestUtil.createDatabase; import static org.neo4j.driver.util.TestUtil.dropDatabase; @@ -52,8 +50,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import org.junit.jupiter.api.parallel.Execution; -import org.junit.jupiter.api.parallel.ExecutionMode; import org.neo4j.driver.Config; import org.neo4j.driver.Driver; import org.neo4j.driver.Session; @@ -70,8 +66,9 @@ import org.neo4j.driver.util.TestUtil; @ParallelizableIT -@Execution(ExecutionMode.CONCURRENT) class ExamplesIT { + static final String USER = "neo4j"; + @RegisterExtension static final DatabaseExtension neo4j = new DatabaseExtension(); @@ -128,7 +125,8 @@ void setUp() { @Test void testShouldRunAutocommitTransactionExample() throws Exception { // Given - try (AutocommitTransactionExample example = new AutocommitTransactionExample(uri, USER, PASSWORD)) { + try (AutocommitTransactionExample example = + new AutocommitTransactionExample(uri, USER, neo4j.adminPassword())) { // When example.addPerson("Alice"); @@ -139,7 +137,8 @@ void testShouldRunAutocommitTransactionExample() throws Exception { @Test void testShouldRunAsyncAutocommitTransactionExample() throws Exception { - try (AsyncAutocommitTransactionExample example = new AsyncAutocommitTransactionExample(uri, USER, PASSWORD)) { + try (AsyncAutocommitTransactionExample example = + new AsyncAutocommitTransactionExample(uri, USER, neo4j.adminPassword())) { // create some 'Product' nodes try (Session session = neo4j.driver().session()) { session.run("UNWIND ['Tesseract', 'Orb', 'Eye of Agamotto'] AS item " @@ -157,7 +156,7 @@ void testShouldAsyncRunResultConsumeExample() throws Exception { // Given write("CREATE (a:Person {name: 'Alice'})"); write("CREATE (a:Person {name: 'Bob'})"); - try (AsyncResultConsumeExample example = new AsyncResultConsumeExample(uri, USER, PASSWORD)) { + try (AsyncResultConsumeExample example = new AsyncResultConsumeExample(uri, USER, neo4j.adminPassword())) { // When List names = await(example.getPeople()); @@ -171,7 +170,8 @@ void testShouldAsyncRunMultipleTransactionExample() throws Exception { // Given write("CREATE (a:Person {name: 'Alice'})"); write("CREATE (a:Person {name: 'Bob'})"); - try (AsyncRunMultipleTransactionExample example = new AsyncRunMultipleTransactionExample(uri, USER, PASSWORD)) { + try (AsyncRunMultipleTransactionExample example = + new AsyncRunMultipleTransactionExample(uri, USER, neo4j.adminPassword())) { // When Integer nodesCreated = await(example.addEmployees("Acme")); @@ -186,7 +186,7 @@ void testShouldAsyncRunMultipleTransactionExample() throws Exception { @Test void testShouldRunConfigConnectionPoolExample() throws Exception { // Given - try (ConfigConnectionPoolExample example = new ConfigConnectionPoolExample(uri, USER, PASSWORD)) { + try (ConfigConnectionPoolExample example = new ConfigConnectionPoolExample(uri, USER, neo4j.adminPassword())) { // Then assertTrue(example.canConnect()); } @@ -195,7 +195,7 @@ void testShouldRunConfigConnectionPoolExample() throws Exception { @Test void testShouldRunBasicAuthExample() throws Exception { // Given - try (BasicAuthExample example = new BasicAuthExample(uri, USER, PASSWORD)) { + try (BasicAuthExample example = new BasicAuthExample(uri, USER, neo4j.adminPassword())) { // Then assertTrue(example.canConnect()); } @@ -204,7 +204,8 @@ void testShouldRunBasicAuthExample() throws Exception { @Test void testShouldRunConfigConnectionTimeoutExample() throws Exception { // Given - try (ConfigConnectionTimeoutExample example = new ConfigConnectionTimeoutExample(uri, USER, PASSWORD)) { + try (ConfigConnectionTimeoutExample example = + new ConfigConnectionTimeoutExample(uri, USER, neo4j.adminPassword())) { // Then assertThat(example, instanceOf(ConfigConnectionTimeoutExample.class)); } @@ -213,7 +214,7 @@ void testShouldRunConfigConnectionTimeoutExample() throws Exception { @Test void testShouldRunConfigMaxRetryTimeExample() throws Exception { // Given - try (ConfigMaxRetryTimeExample example = new ConfigMaxRetryTimeExample(uri, USER, PASSWORD)) { + try (ConfigMaxRetryTimeExample example = new ConfigMaxRetryTimeExample(uri, USER, neo4j.adminPassword())) { // Then assertThat(example, instanceOf(ConfigMaxRetryTimeExample.class)); } @@ -222,7 +223,7 @@ void testShouldRunConfigMaxRetryTimeExample() throws Exception { @Test void testShouldRunConfigTrustExample() throws Exception { // Given - try (ConfigTrustExample example = new ConfigTrustExample(uri, USER, PASSWORD)) { + try (ConfigTrustExample example = new ConfigTrustExample(uri, USER, neo4j.adminPassword())) { // Then assertThat(example, instanceOf(ConfigTrustExample.class)); } @@ -231,7 +232,7 @@ void testShouldRunConfigTrustExample() throws Exception { @Test void testShouldRunConfigUnencryptedExample() throws Exception { // Given - try (ConfigUnencryptedExample example = new ConfigUnencryptedExample(uri, USER, PASSWORD)) { + try (ConfigUnencryptedExample example = new ConfigUnencryptedExample(uri, USER, neo4j.adminPassword())) { // Then assertThat(example, instanceOf(ConfigUnencryptedExample.class)); } @@ -240,7 +241,7 @@ void testShouldRunConfigUnencryptedExample() throws Exception { @Test void testShouldRunCypherErrorExample() throws Exception { // Given - try (CypherErrorExample example = new CypherErrorExample(uri, USER, PASSWORD)) { + try (CypherErrorExample example = new CypherErrorExample(uri, USER, neo4j.adminPassword())) { // When & Then StdIOCapture stdIO = new StdIOCapture(); try (AutoCloseable ignored = stdIO.capture()) { @@ -255,7 +256,7 @@ void testShouldRunCypherErrorExample() throws Exception { @Test void testShouldRunDriverLifecycleExample() throws Exception { // Given - try (DriverLifecycleExample example = new DriverLifecycleExample(uri, USER, PASSWORD)) { + try (DriverLifecycleExample example = new DriverLifecycleExample(uri, USER, neo4j.adminPassword())) { // Then assertThat(example, instanceOf(DriverLifecycleExample.class)); } @@ -264,7 +265,7 @@ void testShouldRunDriverLifecycleExample() throws Exception { @Test void testShouldRunHelloWorld() throws Exception { // Given - try (HelloWorldExample greeter = new HelloWorldExample(uri, USER, PASSWORD)) { + try (HelloWorldExample greeter = new HelloWorldExample(uri, USER, neo4j.adminPassword())) { // When StdIOCapture stdIO = new StdIOCapture(); @@ -285,7 +286,8 @@ void testShouldRunDriverIntroduction() throws Exception { .withEncryption() .withTrustStrategy(trustAllCertificates()) .build(); - try (DriverIntroductionExample intro = new DriverIntroductionExample(uri, USER, PASSWORD, config)) { + try (DriverIntroductionExample intro = + new DriverIntroductionExample(uri, USER, neo4j.adminPassword(), config)) { // When StdIOCapture stdIO = new StdIOCapture(); @@ -304,7 +306,7 @@ void testShouldRunDriverIntroduction() throws Exception { @Test void testShouldRunReadWriteTransactionExample() throws Exception { // Given - try (ReadWriteTransactionExample example = new ReadWriteTransactionExample(uri, USER, PASSWORD)) { + try (ReadWriteTransactionExample example = new ReadWriteTransactionExample(uri, USER, neo4j.adminPassword())) { // When long nodeID = example.addPerson("Alice"); @@ -318,7 +320,7 @@ void testShouldRunResultConsumeExample() throws Exception { // Given write("CREATE (a:Person {name: 'Alice'})"); write("CREATE (a:Person {name: 'Bob'})"); - try (ResultConsumeExample example = new ResultConsumeExample(uri, USER, PASSWORD)) { + try (ResultConsumeExample example = new ResultConsumeExample(uri, USER, neo4j.adminPassword())) { // When List names = example.getPeople(); @@ -332,7 +334,7 @@ void testShouldRunResultRetainExample() throws Exception { // Given write("CREATE (a:Person {name: 'Alice'})"); write("CREATE (a:Person {name: 'Bob'})"); - try (ResultRetainExample example = new ResultRetainExample(uri, USER, PASSWORD)) { + try (ResultRetainExample example = new ResultRetainExample(uri, USER, neo4j.adminPassword())) { // When example.addEmployees("Acme"); @@ -346,15 +348,15 @@ void testShouldRunResultRetainExample() throws Exception { @Test void testShouldRunServiceUnavailableExample() throws Exception { // Given - try (ServiceUnavailableExample example = new ServiceUnavailableExample(uri, USER, PASSWORD)) { + try (ServiceUnavailableExample example = new ServiceUnavailableExample(uri, USER, neo4j.adminPassword())) { try { // When - neo4j.stopDb(); + neo4j.stopProxy(); // Then assertThat(example.addItem(), equalTo(false)); } finally { - neo4j.startDb(); + neo4j.startProxy(); } } } @@ -362,7 +364,7 @@ void testShouldRunServiceUnavailableExample() throws Exception { @Test void testShouldRunSessionExample() throws Exception { // Given - try (SessionExample example = new SessionExample(uri, USER, PASSWORD)) { + try (SessionExample example = new SessionExample(uri, USER, neo4j.adminPassword())) { // When example.addPerson("Alice"); @@ -375,7 +377,7 @@ void testShouldRunSessionExample() throws Exception { @Test void testShouldRunTransactionFunctionExample() throws Exception { // Given - try (TransactionFunctionExample example = new TransactionFunctionExample(uri, USER, PASSWORD)) { + try (TransactionFunctionExample example = new TransactionFunctionExample(uri, USER, neo4j.adminPassword())) { // When example.addPerson("Alice"); @@ -387,7 +389,8 @@ void testShouldRunTransactionFunctionExample() throws Exception { @Test void testShouldConfigureTransactionTimeoutExample() throws Exception { // Given - try (TransactionTimeoutConfigExample example = new TransactionTimeoutConfigExample(uri, USER, PASSWORD)) { + try (TransactionTimeoutConfigExample example = + new TransactionTimeoutConfigExample(uri, USER, neo4j.adminPassword())) { // When example.addPerson("Alice"); @@ -399,7 +402,8 @@ void testShouldConfigureTransactionTimeoutExample() throws Exception { @Test void testShouldConfigureTransactionMetadataExample() throws Exception { // Given - try (TransactionMetadataConfigExample example = new TransactionMetadataConfigExample(uri, USER, PASSWORD)) { + try (TransactionMetadataConfigExample example = + new TransactionMetadataConfigExample(uri, USER, neo4j.adminPassword())) { // When example.addPerson("Alice"); @@ -410,7 +414,8 @@ void testShouldConfigureTransactionMetadataExample() throws Exception { @Test void testShouldRunAsyncTransactionFunctionExample() throws Exception { - try (AsyncTransactionFunctionExample example = new AsyncTransactionFunctionExample(uri, USER, PASSWORD)) { + try (AsyncTransactionFunctionExample example = + new AsyncTransactionFunctionExample(uri, USER, neo4j.adminPassword())) { // create some 'Product' nodes try (Session session = neo4j.driver().session()) { session.run( @@ -432,7 +437,7 @@ void testShouldRunAsyncTransactionFunctionExample() throws Exception { @Test void testPassBookmarksExample() throws Exception { - try (PassBookmarkExample example = new PassBookmarkExample(uri, USER, PASSWORD)) { + try (PassBookmarkExample example = new PassBookmarkExample(uri, USER, neo4j.adminPassword())) { // When example.addEmployAndMakeFriends(); @@ -458,7 +463,8 @@ void testPassBookmarksExample() throws Exception { @Test void testAsyncUnmanagedTransactionExample() throws Exception { - try (AsyncUnmanagedTransactionExample example = new AsyncUnmanagedTransactionExample(uri, USER, PASSWORD)) { + try (AsyncUnmanagedTransactionExample example = + new AsyncUnmanagedTransactionExample(uri, USER, neo4j.adminPassword())) { // create a 'Product' node try (Session session = neo4j.driver().session()) { session.run("CREATE (:Product {id: 0, title: 'Mind Gem'})"); @@ -491,7 +497,7 @@ void testSlf4jLogging() throws Exception { assertThat(logFileContent, is(emptyString())); String randomString = UUID.randomUUID().toString(); - try (Slf4jLoggingExample example = new Slf4jLoggingExample(uri, USER, PASSWORD)) { + try (Slf4jLoggingExample example = new Slf4jLoggingExample(uri, USER, neo4j.adminPassword())) { Object result = example.runReturnQuery(randomString); assertEquals(randomString, result); } @@ -505,7 +511,7 @@ void testSlf4jLogging() throws Exception { @Test void testHostnameVerificationExample() { try (HostnameVerificationExample example = - new HostnameVerificationExample(uri, USER, PASSWORD, neo4j.tlsCertFile())) { + new HostnameVerificationExample(uri, USER, neo4j.adminPassword(), neo4j.tlsCertFile())) { assertTrue(example.canConnect()); } } @@ -513,7 +519,8 @@ void testHostnameVerificationExample() { @Test @EnabledOnNeo4jWith(BOLT_V4) void testShouldRunRxAutocommitTransactionExample() throws Exception { - try (RxAutocommitTransactionExample example = new RxAutocommitTransactionExample(uri, USER, PASSWORD)) { + try (RxAutocommitTransactionExample example = + new RxAutocommitTransactionExample(uri, USER, neo4j.adminPassword())) { // create some 'Product' nodes try (Session session = neo4j.driver().session()) { session.run("UNWIND ['Tesseract', 'Orb', 'Eye of Agamotto'] AS item " @@ -532,7 +539,8 @@ void testShouldRunRxAutocommitTransactionExample() throws Exception { @Test @EnabledOnNeo4jWith(BOLT_V4) void testRxUnmanagedTransactionExample() throws Exception { - try (RxUnmanagedTransactionExample example = new RxUnmanagedTransactionExample(uri, USER, PASSWORD)) { + try (RxUnmanagedTransactionExample example = + new RxUnmanagedTransactionExample(uri, USER, neo4j.adminPassword())) { // create a 'Product' node try (Session session = neo4j.driver().session()) { session.run("CREATE (:Product {id: 0, title: 'Mind Gem'})"); @@ -551,7 +559,8 @@ void testRxUnmanagedTransactionExample() throws Exception { @Test @EnabledOnNeo4jWith(BOLT_V4) void testShouldRunRxTransactionFunctionExampleReactor() throws Exception { - try (RxTransactionFunctionExample example = new RxTransactionFunctionExample(uri, USER, PASSWORD)) { + try (RxTransactionFunctionExample example = + new RxTransactionFunctionExample(uri, USER, neo4j.adminPassword())) { // create some 'Product' nodes try (Session session = neo4j.driver().session()) { session.run( @@ -576,7 +585,8 @@ void testShouldRunRxTransactionFunctionExampleReactor() throws Exception { @Test @EnabledOnNeo4jWith(BOLT_V4) void testShouldRunRxTransactionFunctionExampleRxJava() throws Exception { - try (RxTransactionFunctionExample example = new RxTransactionFunctionExample(uri, USER, PASSWORD)) { + try (RxTransactionFunctionExample example = + new RxTransactionFunctionExample(uri, USER, neo4j.adminPassword())) { // create some 'Product' nodes try (Session session = neo4j.driver().session()) { session.run( @@ -604,7 +614,7 @@ void testShouldRunRxResultConsumeExampleReactor() throws Exception { // Given write("CREATE (a:Person {name: 'Alice'})"); write("CREATE (a:Person {name: 'Bob'})"); - try (RxResultConsumeExample example = new RxResultConsumeExample(uri, USER, PASSWORD)) { + try (RxResultConsumeExample example = new RxResultConsumeExample(uri, USER, neo4j.adminPassword())) { // When List names = await(example.getPeople()); @@ -619,7 +629,7 @@ void testShouldRunRxResultConsumeExampleRxJava() throws Exception { // Given write("CREATE (a:Person {name: 'Alice'})"); write("CREATE (a:Person {name: 'Bob'})"); - try (RxResultConsumeExample example = new RxResultConsumeExample(uri, USER, PASSWORD)) { + try (RxResultConsumeExample example = new RxResultConsumeExample(uri, USER, neo4j.adminPassword())) { // When List names = await(example.getPeopleRxJava()); @@ -635,7 +645,7 @@ void testUseAnotherDatabaseExample() throws Exception { dropDatabase(driver, "examples"); createDatabase(driver, "examples"); - try (DatabaseSelectionExample example = new DatabaseSelectionExample(uri, USER, PASSWORD)) { + try (DatabaseSelectionExample example = new DatabaseSelectionExample(uri, USER, neo4j.adminPassword())) { // When example.useAnotherDatabaseExample(); @@ -647,7 +657,7 @@ void testUseAnotherDatabaseExample() throws Exception { @Test void testReadingValuesExample() throws Exception { - try (ReadingValuesExample example = new ReadingValuesExample(uri, USER, PASSWORD)) { + try (ReadingValuesExample example = new ReadingValuesExample(uri, USER, neo4j.adminPassword())) { assertThat(example.integerFieldIsNull(), is(false)); assertThat(example.integerAsInteger(), is(4)); assertThat(example.integerAsLong(), is(4L)); diff --git a/pom.xml b/pom.xml index 2d8518ec9a..3b27e6d983 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ ${project.groupId}.${project.artifactId} ${project.basedir} - 1C + 2 parallelizableIT 3.0.0-M6 diff --git a/testkit-tests/pom.xml b/testkit-tests/pom.xml index 797f846888..7437177ad6 100644 --- a/testkit-tests/pom.xml +++ b/testkit-tests/pom.xml @@ -19,7 +19,7 @@ ${project.basedir}/.. https://github.com/neo4j-drivers/testkit.git - 4.4 + 5.0 --tests TESTKIT_TESTS INTEGRATION_TESTS STUB_TESTS STRESS_TESTS TLS_TESTS 7200000