/* * Copyright (c) 2002-2017 "Neo Technology," * Network Engine for Objects in Lund AB [http://neotechnology.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.v1.util; import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.channels.SocketChannel; import java.util.ArrayList; import java.util.List; import org.neo4j.driver.v1.Config; import static java.lang.Thread.sleep; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; public class StubServer { private static final int SOCKET_CONNECT_ATTEMPTS = 20; public static final Config INSECURE_CONFIG = Config.build() .withoutEncryption().toConfig(); // This may be thrown if the driver has not been closed properly public static class ForceKilled extends Exception {} private static final String BOLT_STUB_COMMAND = "boltstub"; private Process process = null; private StubServer( String script, int port ) throws IOException, InterruptedException { List<String> command = new ArrayList<>(); command.addAll( singletonList( BOLT_STUB_COMMAND ) ); command.addAll( asList( Integer.toString( port ), script ) ); ProcessBuilder server = new ProcessBuilder().inheritIO().command( command ); process = server.start(); waitForSocket( port ); } public static StubServer start( String resource, int port ) throws IOException, InterruptedException { assumeTrue( boltKitAvailable() ); return new StubServer( resource(resource), port ); } public int exitStatus() throws InterruptedException, ForceKilled { sleep( 500 ); // wait for a moment to allow disconnection to occur try { return process.exitValue(); } catch ( IllegalThreadStateException ex ) { // not exited yet process.destroy(); process.waitFor(); throw new ForceKilled(); } } private static String resource( String fileName ) { File resource = new File( TestNeo4j.TEST_RESOURCE_FOLDER_PATH, fileName ); if ( !resource.exists() ) { fail( fileName + " does not exists" ); } return resource.getAbsolutePath(); } private static boolean boltKitAvailable() { try { // run 'help' command to see if boltstub is available Process process = new ProcessBuilder( BOLT_STUB_COMMAND, "-h" ).start(); int exitCode = process.waitFor(); return exitCode == 0; } catch ( IOException | InterruptedException e ) { // unable to run boltstub command, thus it is unavailable return false; } } private static void waitForSocket( int port ) throws InterruptedException { SocketAddress address = new InetSocketAddress( "localhost", port ); for ( int i = 0; i < SOCKET_CONNECT_ATTEMPTS; i++ ) { try { SocketChannel.open( address ); return; } catch ( Exception e ) { sleep( 300 ); } } throw new AssertionError( "Can't connect to " + address ); } }