diff --git a/driver/pom.xml b/driver/pom.xml
index c0ac6cbec1..881fad3aeb 100644
--- a/driver/pom.xml
+++ b/driver/pom.xml
@@ -82,6 +82,16 @@
reactor-test
test
+
+ org.testcontainers
+ junit-jupiter
+ test
+
+
+ org.testcontainers
+ neo4j
+ test
+
diff --git a/driver/src/test/java/org/neo4j/driver/stress/AbstractStressTestBase.java b/driver/src/test/java/org/neo4j/driver/stress/AbstractStressTestBase.java
index f807aa372a..5b66037340 100644
--- a/driver/src/test/java/org/neo4j/driver/stress/AbstractStressTestBase.java
+++ b/driver/src/test/java/org/neo4j/driver/stress/AbstractStressTestBase.java
@@ -21,7 +21,6 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
@@ -88,7 +87,6 @@
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import static org.neo4j.driver.SessionConfig.builder;
-@ExtendWith( DumpLogsOnFailureWatcher.class )
abstract class AbstractStressTestBase
{
private static final int THREAD_COUNT = Integer.getInteger( "threadCount", 8 );
@@ -202,8 +200,6 @@ private void runStressTest( Function>> threadLauncher ) throws
verifyResults( context, resourcesInfo );
}
- abstract void dumpLogs();
-
abstract URI databaseUri();
abstract AuthToken authToken();
diff --git a/driver/src/test/java/org/neo4j/driver/stress/CausalClusteringStressIT.java b/driver/src/test/java/org/neo4j/driver/stress/CausalClusteringStressIT.java
index 133fb67271..ff4fd85000 100644
--- a/driver/src/test/java/org/neo4j/driver/stress/CausalClusteringStressIT.java
+++ b/driver/src/test/java/org/neo4j/driver/stress/CausalClusteringStressIT.java
@@ -19,6 +19,7 @@
package org.neo4j.driver.stress;
import org.junit.jupiter.api.extension.RegisterExtension;
+import org.testcontainers.junit.jupiter.Testcontainers;
import java.net.URI;
import java.util.Arrays;
@@ -30,6 +31,7 @@
import org.neo4j.driver.exceptions.SessionExpiredException;
import org.neo4j.driver.util.cc.LocalOrRemoteClusterExtension;
+@Testcontainers( disabledWithoutDocker = true )
class CausalClusteringStressIT extends AbstractStressTestBase
{
@RegisterExtension
@@ -84,12 +86,6 @@ void printStats( Context context )
System.out.println( "Bookmark failures: " + context.getBookmarkFailures() );
}
- @Override
- void dumpLogs()
- {
- clusterRule.dumpClusterLogs();
- }
-
@Override
List> createTestSpecificBlockingCommands()
{
@@ -112,5 +108,4 @@ int getLeaderSwitchCount()
return leaderSwitches.get();
}
}
-
}
diff --git a/driver/src/test/java/org/neo4j/driver/stress/DumpLogsOnFailureWatcher.java b/driver/src/test/java/org/neo4j/driver/stress/DumpLogsOnFailureWatcher.java
deleted file mode 100644
index 949c018927..0000000000
--- a/driver/src/test/java/org/neo4j/driver/stress/DumpLogsOnFailureWatcher.java
+++ /dev/null
@@ -1,55 +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.stress;
-
-import org.junit.jupiter.api.extension.ExtensionContext;
-import org.junit.jupiter.api.extension.TestWatcher;
-
-import java.util.Optional;
-
-public class DumpLogsOnFailureWatcher implements TestWatcher
-{
- @Override
- public void testDisabled( ExtensionContext context, Optional reason )
- {
- // do nothing
- }
-
- @Override
- public void testSuccessful( ExtensionContext context )
- {
- // do nothing
- }
-
- @Override
- public void testAborted( ExtensionContext context, Throwable cause )
- {
- // do nothing
- }
-
- @Override
- public void testFailed( ExtensionContext context, Throwable cause )
- {
- if ( context.getTestInstance().isPresent() && context.getTestInstance().get() instanceof AbstractStressTestBase>)
- {
- AbstractStressTestBase> clusterTest = (AbstractStressTestBase>) context.getTestInstance().get();
- clusterTest.dumpLogs();
- }
- }
-}
diff --git a/driver/src/test/java/org/neo4j/driver/stress/SingleInstanceStressIT.java b/driver/src/test/java/org/neo4j/driver/stress/SingleInstanceStressIT.java
index 9c128467ab..63038d1cc0 100644
--- a/driver/src/test/java/org/neo4j/driver/stress/SingleInstanceStressIT.java
+++ b/driver/src/test/java/org/neo4j/driver/stress/SingleInstanceStressIT.java
@@ -145,10 +145,4 @@ List> createTestSpecificRxCommands()
static class Context extends AbstractContext
{
}
-
- @Override
- void dumpLogs()
- {
- neo4j.dumpLogs();
- }
}
diff --git a/driver/src/test/java/org/neo4j/driver/util/cc/Cluster.java b/driver/src/test/java/org/neo4j/driver/util/cc/Cluster.java
deleted file mode 100644
index 81079cce95..0000000000
--- a/driver/src/test/java/org/neo4j/driver/util/cc/Cluster.java
+++ /dev/null
@@ -1,385 +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 java.io.FileNotFoundException;
-import java.net.URI;
-import java.nio.file.Path;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.concurrent.TimeUnit;
-
-import org.neo4j.driver.Bookmark;
-import org.neo4j.driver.Driver;
-import org.neo4j.driver.internal.BoltServerAddress;
-import org.neo4j.driver.util.TestUtil;
-import org.neo4j.driver.util.cc.ClusterMemberRoleDiscoveryFactory.ClusterMemberRoleDiscovery;
-
-import static java.util.Collections.emptySet;
-import static java.util.Collections.unmodifiableSet;
-import static org.neo4j.driver.util.TestUtil.sleep;
-
-public class Cluster implements AutoCloseable
-{
- private static final String ADMIN_USER = "neo4j";
- private static final int STARTUP_TIMEOUT_SECONDS = 120;
- private static final int ONLINE_MEMBERS_CHECK_SLEEP_MS = 500;
-
- private final Path path;
- private final Set members;
- private final Set offlineMembers;
- private final ClusterDrivers clusterDrivers;
-
- public Cluster( Path path, String password )
- {
- this( path, emptySet(), new ClusterDrivers( ADMIN_USER, password ) );
- }
-
- private Cluster( Path path, Set members, ClusterDrivers clusterDrivers )
- {
- this.path = path;
- this.members = members;
- this.offlineMembers = new HashSet<>();
- this.clusterDrivers = clusterDrivers;
- }
-
- Cluster withMembers( Set newMembers ) throws ClusterUnavailableException
- {
- waitForMembersToBeOnline( newMembers, clusterDrivers );
- return new Cluster( path, newMembers, clusterDrivers );
- }
-
- public URI getRoutingUri()
- {
- return randomOf( cores() ).getRoutingUri();
- }
-
- public Path getPath()
- {
- return path;
- }
-
- public void deleteData()
- {
- // execute write query to remove all nodes and retrieve bookmark
- Driver driverToLeader = clusterDrivers.getDriver( leader() );
- Bookmark bookmark = TestUtil.cleanDb( driverToLeader );
- if ( bookmark == null )
- {
- throw new IllegalStateException( "Cleanup of the database did not produce a bookmark" );
- }
-
- // ensure that every cluster member is up-to-date and contains no nodes
- for ( ClusterMember member : members )
- {
- Driver driver = clusterDrivers.getDriver( member );
- long nodeCount = TestUtil.countNodes( driver, bookmark );
- if ( nodeCount != 0 )
- {
- throw new IllegalStateException( "Not all nodes have been deleted. " + nodeCount + " still there somehow" );
- }
- }
- }
-
- public Set members()
- {
- return unmodifiableSet( members );
- }
-
- public ClusterMember leader()
- {
- Set leaders = membersWithRole( ClusterMemberRole.LEADER );
- if ( leaders.size() != 1 )
- {
- throw new IllegalStateException( "Single leader expected. " + leaders );
- }
- return leaders.iterator().next();
- }
-
- public ClusterMember anyFollower()
- {
- return randomOf( followers() );
- }
-
- public Set followers()
- {
- return membersWithRole( ClusterMemberRole.FOLLOWER );
- }
-
- public ClusterMember anyReadReplica()
- {
- return randomOf( readReplicas() );
- }
-
- public Set cores()
- {
- Set readReplicas = membersWithRole( ClusterMemberRole.READ_REPLICA );
- Set cores = new HashSet<>( members );
- cores.removeAll( readReplicas );
- return cores;
- }
-
- public Set readReplicas()
- {
- return membersWithRole( ClusterMemberRole.READ_REPLICA );
- }
-
- public void start( ClusterMember member )
- {
- startNoWait( member );
- waitForMembersToBeOnline();
- }
-
- public Driver getDirectDriver( ClusterMember member )
- {
- return clusterDrivers.getDriver( member );
- }
-
- public void dumpClusterDebugLog()
- {
- for ( ClusterMember member : members )
- {
-
- System.out.println( "Debug log for: " + member.getPath().toString() );
- try
- {
- member.dumpDebugLog();
- }
- catch ( FileNotFoundException e )
- {
- System.out.println("Unable to find debug log file for: " + member.getPath().toString());
- e.printStackTrace();
- }
- }
- }
-
- @Override
- public void close()
- {
- clusterDrivers.close();
- }
-
- @Override
- public String toString()
- {
- return "Cluster{" +
- "path=" + path +
- ", members=" + members +
- "}";
- }
-
- private void addOfflineMember( ClusterMember member )
- {
- if ( !offlineMembers.remove( member ) )
- {
- throw new IllegalArgumentException( "Cluster member is not offline: " + member );
- }
- members.add( member );
- }
-
- private void startNoWait( ClusterMember member )
- {
- addOfflineMember( member );
- SharedCluster.start( member );
- }
-
- private Set membersWithRole( ClusterMemberRole role )
- {
- Set membersWithRole = new HashSet<>();
- int retryCount = 0;
-
- while ( membersWithRole.isEmpty() && retryCount < 10 )
- {
- Driver driver = driverToAnyCore( members, clusterDrivers );
- final ClusterMemberRoleDiscovery discovery = clusterDrivers.getDiscovery();
- final Map clusterOverview = discovery.findClusterOverview( driver );
- for ( BoltServerAddress boltAddress : clusterOverview.keySet() )
- {
- if ( role == clusterOverview.get( boltAddress ) )
- {
- ClusterMember member = findByBoltAddress( boltAddress, members );
- if ( member == null )
- {
- throw new IllegalStateException( "Unknown cluster member: '" + boltAddress + "'\n" + this );
- }
- membersWithRole.add( member );
- }
- }
- retryCount++;
-
- if ( !membersWithRole.isEmpty() )
- {
- break;
- }
- else
- {
- try
- {
- // give some time for cluster to stabilise
- Thread.sleep( 2000 );
- }
- catch ( InterruptedException ignored )
- {
- }
- }
- }
-
- if ( membersWithRole.isEmpty() )
- {
- throw new IllegalStateException( "No cluster members with role '" + role + " " + this );
- }
-
- return membersWithRole;
- }
-
- private void waitForMembersToBeOnline()
- {
- try
- {
- waitForMembersToBeOnline( members, clusterDrivers );
- }
- catch ( ClusterUnavailableException e )
- {
- throw new RuntimeException( e );
- }
- }
-
- private static void waitForMembersToBeOnline( Set members, ClusterDrivers clusterDrivers )
- throws ClusterUnavailableException
- {
- if ( members.isEmpty() )
- {
- throw new IllegalArgumentException( "No members to wait for" );
- }
-
- Set expectedOnlineAddresses = extractBoltAddresses( members );
- Set actualOnlineAddresses = emptySet();
-
- long deadline = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis( STARTUP_TIMEOUT_SECONDS );
- Throwable error = null;
-
- while ( !expectedOnlineAddresses.equals( actualOnlineAddresses ) )
- {
- sleep( ONLINE_MEMBERS_CHECK_SLEEP_MS );
- assertDeadlineNotReached( deadline, expectedOnlineAddresses, actualOnlineAddresses, error );
-
- Driver driver = driverToAnyCore( members, clusterDrivers );
- final ClusterMemberRoleDiscovery discovery = clusterDrivers.getDiscovery();
- try
- {
- final Map clusterOverview = discovery.findClusterOverview( driver );
- actualOnlineAddresses = clusterOverview.keySet();
- }
- catch ( Throwable t )
- {
- t.printStackTrace();
-
- if ( error == null )
- {
- error = t;
- }
- else
- {
- error.addSuppressed( t );
- }
- }
- }
- }
-
- private static Driver driverToAnyCore( Set members, ClusterDrivers clusterDrivers )
- {
- if ( members.isEmpty() )
- {
- throw new IllegalArgumentException( "No members, can't create driver" );
- }
-
- for ( ClusterMember member : members )
- {
- Driver driver = clusterDrivers.getDriver( member );
- final ClusterMemberRoleDiscovery discovery = clusterDrivers.getDiscovery();
- if ( discovery.isCoreMember( driver ) )
- {
- return driver;
- }
- }
-
- throw new IllegalStateException( "No core members found among: " + members );
- }
-
- private static void assertDeadlineNotReached( long deadline, Set> expectedAddresses, Set> actualAddresses,
- Throwable error ) throws ClusterUnavailableException
- {
- if ( System.currentTimeMillis() > deadline )
- {
- String baseMessage = "Cluster did not become available in " + STARTUP_TIMEOUT_SECONDS + " seconds.\n";
- String errorMessage = error == null ? "" : "There were errors checking cluster members.\n";
- String expectedAddressesMessage = "Expected online addresses: " + expectedAddresses + "\n";
- String actualAddressesMessage = "Actual last seen online addresses: " + actualAddresses + "\n";
- String message = baseMessage + errorMessage + expectedAddressesMessage + actualAddressesMessage;
-
- ClusterUnavailableException clusterUnavailable = new ClusterUnavailableException( message );
-
- if ( error != null )
- {
- clusterUnavailable.addSuppressed( error );
- }
-
- throw clusterUnavailable;
- }
- }
-
- private static Set extractBoltAddresses( Set members )
- {
- Set addresses = new HashSet<>();
- for ( ClusterMember member : members )
- {
- addresses.add( member.getBoltAddress() );
- }
- return addresses;
- }
-
- private static ClusterMember findByBoltAddress( BoltServerAddress boltAddress, Set members )
- {
- for ( ClusterMember member : members )
- {
- if ( member.getBoltAddress().equals( boltAddress ) )
- {
- return member;
- }
- }
- return null;
- }
-
- private static ClusterMember randomOf( Set members )
- {
- int randomIndex = ThreadLocalRandom.current().nextInt( members.size() );
- int currentIndex = 0;
- for ( ClusterMember member : members )
- {
- if ( currentIndex == randomIndex )
- {
- return member;
- }
- currentIndex++;
- }
- throw new AssertionError();
- }
-}
diff --git a/driver/src/test/java/org/neo4j/driver/util/cc/ClusterControl.java b/driver/src/test/java/org/neo4j/driver/util/cc/ClusterControl.java
deleted file mode 100644
index ae6d1329c0..0000000000
--- a/driver/src/test/java/org/neo4j/driver/util/cc/ClusterControl.java
+++ /dev/null
@@ -1,60 +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 java.nio.file.Path;
-
-import static org.neo4j.driver.util.cc.CommandLineUtil.executeCommand;
-
-final class ClusterControl
-{
- private ClusterControl()
- {
- }
-
- static void installCluster( String neo4jVersion, int cores, int readReplicas, String password, int port,
- Path path )
- {
- executeCommand( "neoctrl-cluster", "install",
- "--cores", String.valueOf( cores ), "--read-replicas", String.valueOf( readReplicas ),
- "--password", password, "--initial-port", String.valueOf( port ),
- neo4jVersion, path.toString() );
- }
-
- static String startCluster( Path path )
- {
- return executeCommand( "neoctrl-cluster", "start", path.toString() );
- }
-
- static String startClusterMember( Path path )
- {
- return executeCommand( "neoctrl-start", path.toString() );
- }
-
- static void stopCluster( Path path )
- {
- executeCommand( "neoctrl-cluster", "stop", path.toString() );
- }
-
- static void killCluster( Path path )
- {
- executeCommand( "neoctrl-cluster", "stop", "--kill", path.toString() );
- }
-
-}
diff --git a/driver/src/test/java/org/neo4j/driver/util/cc/ClusterDrivers.java b/driver/src/test/java/org/neo4j/driver/util/cc/ClusterDrivers.java
deleted file mode 100644
index 1d68da6c5c..0000000000
--- a/driver/src/test/java/org/neo4j/driver/util/cc/ClusterDrivers.java
+++ /dev/null
@@ -1,97 +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 java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-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.messaging.BoltProtocolVersion;
-import org.neo4j.driver.util.cc.ClusterMemberRoleDiscoveryFactory.ClusterMemberRoleDiscovery;
-
-import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING;
-
-public class ClusterDrivers implements AutoCloseable
-{
- private final String user;
- private final String password;
- private final Map membersWithDrivers;
- private ClusterMemberRoleDiscovery discovery;
-
- public ClusterDrivers( String user, String password )
- {
- this.user = user;
- this.password = password;
- this.membersWithDrivers = new ConcurrentHashMap<>();
- }
-
- public Driver getDriver( ClusterMember member )
- {
- final Driver driver = membersWithDrivers.computeIfAbsent( member, this::createDriver );
- if ( discovery == null )
- {
- try ( Session session = driver.session() )
- {
- String version = session.readTransaction( tx -> tx.run( "RETURN 1" ).consume().server().protocolVersion() );
- List versionParts = Arrays.stream( version.split( "\\." ) ).map( Integer::parseInt ).collect( Collectors.toList() );
- BoltProtocolVersion protocolVersion = new BoltProtocolVersion( versionParts.get( 0 ), versionParts.get( 1 ) );
- discovery = ClusterMemberRoleDiscoveryFactory.newInstance( protocolVersion );
- }
- }
- return driver;
- }
-
- public ClusterMemberRoleDiscovery getDiscovery()
- {
- return discovery;
- }
-
- @Override
- public void close()
- {
- for ( Driver driver : membersWithDrivers.values() )
- {
- driver.close();
- }
- }
-
- private Driver createDriver( ClusterMember member )
- {
- return GraphDatabase.driver( member.getBoltUri(), AuthTokens.basic( user, password ), driverConfig() );
- }
-
- private static Config driverConfig()
- {
- return Config.builder()
- .withLogging( DEV_NULL_LOGGING )
- .withoutEncryption()
- .withMaxConnectionPoolSize( 1 )
- .withConnectionLivenessCheckTimeout( 0, TimeUnit.MILLISECONDS )
- .withEventLoopThreads( 1 )
- .build();
- }
-}
diff --git a/driver/src/test/java/org/neo4j/driver/util/cc/ClusterExtension.java b/driver/src/test/java/org/neo4j/driver/util/cc/ClusterExtension.java
deleted file mode 100644
index add7438fc0..0000000000
--- a/driver/src/test/java/org/neo4j/driver/util/cc/ClusterExtension.java
+++ /dev/null
@@ -1,154 +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 org.junit.jupiter.api.extension.AfterAllCallback;
-import org.junit.jupiter.api.extension.AfterEachCallback;
-import org.junit.jupiter.api.extension.BeforeAllCallback;
-import org.junit.jupiter.api.extension.ExtensionContext;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import org.neo4j.driver.AuthToken;
-import org.neo4j.driver.AuthTokens;
-import org.neo4j.driver.util.Neo4jRunner;
-
-import static org.junit.jupiter.api.Assumptions.assumeTrue;
-import static org.neo4j.driver.util.Neo4jRunner.PASSWORD;
-import static org.neo4j.driver.util.Neo4jRunner.TARGET_DIR;
-import static org.neo4j.driver.util.Neo4jRunner.USER;
-import static org.neo4j.driver.util.cc.CommandLineUtil.boltKitAvailable;
-
-public class ClusterExtension implements BeforeAllCallback, AfterEachCallback, AfterAllCallback
-{
- private static final Path CLUSTER_DIR = Paths.get( TARGET_DIR, "test-cluster" ).toAbsolutePath();
- private static final int INITIAL_PORT = 20_000;
-
- public static final int CORE_COUNT = 3;
- public static final int READ_REPLICA_COUNT = 2;
-
- public Cluster getCluster()
- {
- return SharedCluster.get();
- }
-
- public AuthToken getDefaultAuthToken()
- {
- return AuthTokens.basic( USER, PASSWORD );
- }
-
- @Override
- public void beforeAll( ExtensionContext context ) throws Exception
- {
- assumeTrue( boltKitAvailable(), "BoltKit cluster support unavailable" );
-
- stopSingleInstanceDatabase();
-
- if ( !SharedCluster.exists() )
- {
- SharedCluster.install( parseNeo4jVersion(),
- CORE_COUNT, READ_REPLICA_COUNT, PASSWORD, INITIAL_PORT, CLUSTER_DIR );
-
- try
- {
- SharedCluster.start();
- }
- catch ( Throwable startError )
- {
- try
- {
- SharedCluster.kill();
- }
- catch ( Throwable killError )
- {
- startError.addSuppressed( killError );
- }
- finally
- {
- SharedCluster.remove();
- }
- throw startError;
- }
- finally
- {
- addShutdownHookToStopCluster();
- }
- }
-
- getCluster().deleteData();
- }
-
- @Override
- public void afterEach( ExtensionContext context )
- {
- Cluster cluster = getCluster();
- cluster.deleteData();
- }
-
- @Override
- public void afterAll( ExtensionContext context )
- {
- if ( SharedCluster.exists() )
- {
- try
- {
- SharedCluster.stop();
- }
- finally
- {
- SharedCluster.remove();
- }
- }
- }
-
- private static String parseNeo4jVersion()
- {
- String[] split = Neo4jRunner.NEOCTRL_ARGS.split( "\\s+" );
- return split[split.length - 1];
- }
-
- private static void stopSingleInstanceDatabase() throws IOException
- {
- if ( Neo4jRunner.globalRunnerExists() )
- {
- Neo4jRunner.getOrCreateGlobalRunner().stopNeo4j();
- }
- }
-
- private static void addShutdownHookToStopCluster()
- {
- Runtime.getRuntime().addShutdownHook( new Thread( () ->
- {
- try
- {
- if ( SharedCluster.exists() )
- {
- SharedCluster.kill();
- }
- }
- catch ( Throwable t )
- {
- System.err.println( "Cluster stopping shutdown hook failed" );
- t.printStackTrace();
- }
- } ) );
- }
-}
diff --git a/driver/src/test/java/org/neo4j/driver/util/cc/ClusterMember.java b/driver/src/test/java/org/neo4j/driver/util/cc/ClusterMember.java
deleted file mode 100644
index 68ec80aa1f..0000000000
--- a/driver/src/test/java/org/neo4j/driver/util/cc/ClusterMember.java
+++ /dev/null
@@ -1,122 +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 java.io.File;
-import java.io.FileNotFoundException;
-import java.net.InetAddress;
-import java.net.URI;
-import java.net.UnknownHostException;
-import java.nio.file.Path;
-import java.util.Objects;
-import java.util.Scanner;
-
-import org.neo4j.driver.internal.BoltServerAddress;
-
-import static java.util.Objects.requireNonNull;
-
-public class ClusterMember
-{
- public static final String SIMPLE_SCHEME = "bolt://";
- public static final String ROUTING_SCHEME = "neo4j://";
-
- private final URI boltUri;
- private final BoltServerAddress boltAddress;
- private final Path path;
-
- public ClusterMember( URI boltUri, Path path )
- {
- this.boltUri = requireNonNull( boltUri );
- this.boltAddress = newBoltServerAddress( boltUri );
- this.path = requireNonNull( path );
- }
-
- public URI getBoltUri()
- {
- return boltUri;
- }
-
- public URI getRoutingUri()
- {
- return URI.create( boltUri.toString().replace( SIMPLE_SCHEME, ROUTING_SCHEME ) );
- }
-
- public BoltServerAddress getBoltAddress()
- {
- return boltAddress;
- }
-
- public Path getPath()
- {
- return path;
- }
-
- public void dumpDebugLog() throws FileNotFoundException
- {
- Scanner input = new Scanner( new File( path.toAbsolutePath().toString() + "/logs/debug.log" ));
-
- while (input.hasNextLine())
- {
- System.out.println(input.nextLine());
- }
- }
-
- @Override
- public boolean equals( Object o )
- {
- if ( this == o )
- {
- return true;
- }
- if ( o == null || getClass() != o.getClass() )
- {
- return false;
- }
- ClusterMember that = (ClusterMember) o;
- return Objects.equals( boltAddress, that.boltAddress );
- }
-
- @Override
- public int hashCode()
- {
- return Objects.hash( boltAddress );
- }
-
- @Override
- public String toString()
- {
- return "ClusterMember{" +
- "boltUri=" + boltUri +
- ", boltAddress=" + boltAddress +
- ", path=" + path +
- '}';
- }
-
- private static BoltServerAddress newBoltServerAddress( URI uri )
- {
- try
- {
- return new BoltServerAddress( InetAddress.getByName( uri.getHost() ).getHostAddress(), uri.getPort() );
- }
- catch ( UnknownHostException e )
- {
- throw new RuntimeException( e );
- }
- }
-}
diff --git a/driver/src/test/java/org/neo4j/driver/util/cc/ClusterMemberRole.java b/driver/src/test/java/org/neo4j/driver/util/cc/ClusterMemberRole.java
deleted file mode 100644
index bd81c9fd79..0000000000
--- a/driver/src/test/java/org/neo4j/driver/util/cc/ClusterMemberRole.java
+++ /dev/null
@@ -1,27 +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;
-
-public enum ClusterMemberRole
-{
- LEADER,
- FOLLOWER,
- READ_REPLICA,
- UNKNOWN
-}
diff --git a/driver/src/test/java/org/neo4j/driver/util/cc/ClusterMemberRoleDiscoveryFactory.java b/driver/src/test/java/org/neo4j/driver/util/cc/ClusterMemberRoleDiscoveryFactory.java
deleted file mode 100644
index ece7025c8c..0000000000
--- a/driver/src/test/java/org/neo4j/driver/util/cc/ClusterMemberRoleDiscoveryFactory.java
+++ /dev/null
@@ -1,162 +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 java.net.InetAddress;
-import java.net.URI;
-import java.net.UnknownHostException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.neo4j.driver.AccessMode;
-import org.neo4j.driver.Driver;
-import org.neo4j.driver.Record;
-import org.neo4j.driver.Result;
-import org.neo4j.driver.Session;
-import org.neo4j.driver.Values;
-import org.neo4j.driver.internal.BoltServerAddress;
-import org.neo4j.driver.internal.messaging.BoltProtocolVersion;
-
-import static org.neo4j.driver.SessionConfig.builder;
-import static org.neo4j.driver.Values.parameters;
-import static org.neo4j.driver.internal.util.Iterables.single;
-
-public class ClusterMemberRoleDiscoveryFactory
-{
- public static ClusterMemberRoleDiscovery newInstance( BoltProtocolVersion version )
- {
- if ( version.getMajorVersion() >= 4 )
- {
- return new SimpleClusterMemberRoleDiscovery();
- }
- else
- {
- return new LegacyClusterMemberRoleDiscovery();
- }
- }
-
- public interface ClusterMemberRoleDiscovery
- {
- boolean isCoreMember( Driver driver );
-
- Map findClusterOverview( Driver driver );
- }
-
- public static class LegacyClusterMemberRoleDiscovery implements ClusterMemberRoleDiscovery
- {
- @Override
- public boolean isCoreMember( Driver driver )
- {
- try ( Session session = driver.session( builder().withDefaultAccessMode( AccessMode.READ ).build() ) )
- {
- Record record = single( session.run( "CALL dbms.cluster.role()" ).list() );
- ClusterMemberRole role = extractRole( record );
- return role == ClusterMemberRole.LEADER || role == ClusterMemberRole.FOLLOWER;
- }
- }
-
- @Override
- public Map findClusterOverview( Driver driver )
- {
- try ( Session session = driver.session( builder().withDefaultAccessMode( AccessMode.WRITE ).build() ) )
- {
- Result result = session.run( "CALL dbms.cluster.overview()" );
- Map overview = new HashMap<>();
- for ( Record record : result.list() )
- {
- final BoltServerAddress address = extractBoltAddress( record );
- final ClusterMemberRole role = extractRole( record );
- overview.put( address, role );
- }
- return overview;
- }
- }
- }
-
- public static class SimpleClusterMemberRoleDiscovery implements ClusterMemberRoleDiscovery
- {
- private static final String DEFAULT_DATABASE = "neo4j";
-
- @Override
- public boolean isCoreMember( Driver driver )
- {
- try ( Session session = driver.session( builder().withDefaultAccessMode( AccessMode.READ ).build() ) )
- {
- Record record = single( session.run( "CALL dbms.cluster.role($database)",
- parameters( "database", DEFAULT_DATABASE ) ).list() );
- ClusterMemberRole role = extractRole( record );
- return role == ClusterMemberRole.LEADER || role == ClusterMemberRole.FOLLOWER;
- }
- }
-
- @Override
- public Map findClusterOverview( Driver driver )
- {
- try ( Session session = driver.session( builder().withDefaultAccessMode( AccessMode.READ ).build() ) )
- {
- Result result = session.run( "CALL dbms.cluster.overview()" );
- Map overview = new HashMap<>();
- for ( Record record : result.list() )
- {
- final BoltServerAddress address = extractBoltAddress( record );
- final ClusterMemberRole role = extractRoleForDatabase( record, DEFAULT_DATABASE );
- if ( role != ClusterMemberRole.UNKNOWN ) // the unknown ones has not fully come online
- {
- overview.put( address, role );
- }
- }
- return overview;
- }
- }
- }
-
- private static ClusterMemberRole extractRoleForDatabase( Record record, String database )
- {
- final Map databases = record.get( "databases" ).asMap( Values.ofString() );
- final String roleString = databases.get( database );
- return ClusterMemberRole.valueOf( roleString.toUpperCase() );
- }
-
- private static BoltServerAddress extractBoltAddress( Record record )
- {
- List