@Test public void shouldLaunchAServerInSpecifiedDirectory() { // Given File workDir = testDir.directory( "specific" ); // When try ( ServerControls server = getTestServerBuilder( workDir ).newServer() ) { // Then assertThat( HTTP.GET( server.httpURI().toString() ).status(), equalTo( 200 ) ); assertThat( workDir.list().length, equalTo( 1 ) ); } // And after it's been closed, it should've cleaned up after itself. assertThat( Arrays.toString( workDir.list() ), workDir.list().length, equalTo( 0 ) ); }
@Test public void shouldFindFreePort() { // Given one server is running try ( ServerControls firstServer = getTestServerBuilder( testDir.directory() ).newServer() ) { // When I start a second server try ( ServerControls secondServer = getTestServerBuilder( testDir.directory() ).newServer() ) { // Then assertThat( secondServer.httpURI().getPort(), not( firstServer.httpURI().getPort() ) ); } } }
@Test public void shouldHandleFixturesWithSyntaxErrorsGracefully() throws Exception { // Given two files in the root folder File targetFolder = testDir.directory(); FileUtils.writeToFile( new File( targetFolder, "fixture1.cyp" ), "this is not a valid cypher statement", false ); // When try ( ServerControls ignore = getServerBuilder( targetFolder ) .withFixture( targetFolder ).newServer() ) { fail("Should have thrown exception"); } catch ( RuntimeException e ) { assertThat( e.getMessage(), equalTo( "Invalid input 't': expected <init> (line 1, column 1 (offset: 0))" + lineSeparator() + "\"this is not a valid cypher statement\"" + lineSeparator() + " ^" ) ); } }
@Test public void shouldMountUnmanagedExtensionsByClass() { // When try ( ServerControls server = getTestServerBuilder( testDir.directory() ) .withExtension( "/path/to/my/extension", MyUnmanagedExtension.class ) .newServer() ) { // Then assertThat( HTTP.GET( server.httpURI().toString() + "path/to/my/extension/myExtension" ).status(), equalTo( 234 ) ); } }
@Test public void shouldMountUnmanagedExtensionsByPackage() { // When try ( ServerControls server = getTestServerBuilder( testDir.directory() ) .withExtension( "/path/to/my/extension", "org.neo4j.harness.extensionpackage" ) .newServer() ) { // Then assertThat( HTTP.GET( server.httpURI().toString() + "path/to/my/extension/myExtension" ).status(), equalTo( 234 ) ); } }
@Test public void shouldLaunchWithDeclaredProcedures() throws Exception { // When try ( ServerControls server = createServer( MyProcedures.class ).newServer() ) { // Then HTTP.Response response = HTTP.POST( server.httpURI().resolve( "db/data/transaction/commit" ).toString(), quotedJson( "{ 'statements': [ { 'statement': 'CALL org.neo4j.harness.myProc' } ] }" ) ); JsonNode result = response.get( "results" ).get( 0 ); assertEquals( "someNumber", result.get( "columns" ).get( 0 ).asText() ); assertEquals( 1337, result.get( "data" ).get( 0 ).get( "row" ).get( 0 ).asInt() ); assertEquals( "[]", response.get( "errors" ).toString() ); } }
@Test public void shouldWorkWithInjectableFromKernelExtension() throws Throwable { // When try ( ServerControls server = createServer( MyFunctionsUsingMyService.class ).newServer() ) { // Then HTTP.Response response = HTTP.POST( server.httpURI().resolve( "db/data/transaction/commit" ).toString(), quotedJson( "{ 'statements': [ { 'statement': 'RETURN my.hello() AS result' } ] }" ) ); assertEquals( "[]", response.get( "errors" ).toString() ); JsonNode result = response.get( "results" ).get( 0 ); assertEquals( "result", result.get( "columns" ).get( 0 ).asText() ); assertEquals( "world", result.get( "data" ).get( 0 ).get( "row" ).get( 0 ).asText() ); } }
@Test public void shouldWorkWithInjectableFromKernelExtension() throws Throwable { // When try ( ServerControls server = createServer( MyProceduresUsingMyService.class ).newServer() ) { // Then HTTP.Response response = HTTP.POST( server.httpURI().resolve( "db/data/transaction/commit" ).toString(), quotedJson( "{ 'statements': [ { 'statement': 'CALL hello' } ] }" ) ); assertEquals( "[]", response.get( "errors" ).toString() ); JsonNode result = response.get( "results" ).get( 0 ); assertEquals( "result", result.get( "columns" ).get( 0 ).asText() ); assertEquals( "world", result.get( "data" ).get( 0 ).get( "row" ).get( 0 ).asText() ); } }
@Test public void shouldFailWhenProvidingANonDirectoryAsSource() throws IOException { File notADirectory = File.createTempFile( "prefix", "suffix" ); assertFalse( notADirectory.isDirectory() ); try ( ServerControls ignored = getTestServerBuilder( testDir.directory() ) .copyFrom( notADirectory ).newServer() ) { fail( "server should not start" ); } catch ( RuntimeException rte ) { Throwable cause = rte.getCause(); assertTrue( cause instanceof IOException ); assertTrue( cause.getMessage().contains( "exists but is not a directory" ) ); } }
@Test public void shouldGetHelpfulErrorOnProcedureThrowsException() throws Exception { // When try ( ServerControls server = createServer( MyProcedures.class ).newServer() ) { // Then HTTP.Response response = HTTP.POST( server.httpURI().resolve( "db/data/transaction/commit" ).toString(), quotedJson( "{ 'statements': [ { 'statement': 'CALL org.neo4j.harness.procThatThrows' } ] }" ) ); String error = response.get( "errors" ).get( 0 ).get( "message" ).asText(); assertEquals( "Failed to invoke procedure `org.neo4j.harness.procThatThrows`: " + "Caused by: java.lang.RuntimeException: This is an exception", error ); } }
@Test public void shouldHandleStringFixtures() throws Exception { // Given two files in the root folder File targetFolder = testDir.directory(); // When try ( ServerControls server = getServerBuilder( targetFolder ) .withFixture( "CREATE (a:User)" ) .newServer() ) { // Then HTTP.Response response = HTTP.POST( server.httpURI().toString() + "db/data/transaction/commit", quotedJson( "{'statements':[{'statement':'MATCH (n:User) RETURN n'}]}" ) ); assertThat( response.get( "results" ).get(0).get("data").size(), equalTo(1)); } }
@Test public void shouldLaunchWithDeclaredFunctions() throws Exception { // When Class<MyFunctions> functionClass = MyFunctions.class; try ( ServerControls server = createServer( functionClass ).newServer() ) { // Then HTTP.Response response = HTTP.POST( server.httpURI().resolve( "db/data/transaction/commit" ).toString(), quotedJson( "{ 'statements': [ { 'statement': 'RETURN org.neo4j.harness.myFunc() AS someNumber' } ] " + "}" ) ); JsonNode result = response.get( "results" ).get( 0 ); assertEquals( "someNumber", result.get( "columns" ).get( 0 ).asText() ); assertEquals( 1337, result.get( "data" ).get( 0 ).get( "row" ).get( 0 ).asInt() ); assertEquals( "[]", response.get( "errors" ).toString() ); } }
@Test public void shouldLaunchWithDeclaredFunctions() throws Exception { // When try ( ServerControls server = createServer( MyFunctions.class ).newServer() ) { // Then HTTP.Response response = HTTP.POST( server.httpURI().resolve( "db/data/transaction/commit" ).toString(), quotedJson( "{ 'statements': [ { 'statement': 'RETURN org.neo4j.harness.myFunc() AS someNumber' } ] " + "}" ) ); JsonNode result = response.get( "results" ).get( 0 ); assertEquals( "someNumber", result.get( "columns" ).get( 0 ).asText() ); assertEquals( 1337, result.get( "data" ).get( 0 ).get( "row" ).get( 0 ).asInt() ); assertEquals( "[]", response.get( "errors" ).toString() ); } }
@Test public void shouldIgnoreEmptyFixtureFiles() throws Exception { // Given two files in the root folder File targetFolder = testDir.directory(); FileUtils.writeToFile( new File( targetFolder, "fixture1.cyp" ), "CREATE (u:User)\n" + "CREATE (a:OtherUser)", false ); FileUtils.writeToFile( new File( targetFolder, "fixture2.cyp" ), "", false ); // When try ( ServerControls server = getServerBuilder( targetFolder ) .withFixture( targetFolder ).newServer() ) { // Then HTTP.Response response = HTTP.POST( server.httpURI().toString() + "db/data/transaction/commit", quotedJson( "{'statements':[{'statement':'MATCH (n:User) RETURN n'}]}" ) ); assertThat( response.get( "results" ).get(0).get("data").size(), equalTo(1)); } }
@Test public void shouldOpenBoltPort() throws Throwable { // given try ( ServerControls controls = getTestServerBuilder( testDir.directory() ).newServer() ) { URI uri = controls.boltURI(); // when new SocketConnection().connect( new HostnamePort( uri.getHost(), uri.getPort() ) ); // then no exception } }
@Test public void shouldGetHelpfulErrorOnProcedureThrowsException() throws Exception { // When try ( ServerControls server = createServer( MyFunctions.class ).newServer() ) { // Then HTTP.Response response = HTTP.POST( server.httpURI().resolve( "db/data/transaction/commit" ).toString(), quotedJson( "{ 'statements': [ { 'statement': 'RETURN org.neo4j.harness.funcThatThrows()' } ] }" ) ); String error = response.get( "errors" ).get( 0 ).get( "message" ).asText(); assertEquals( "Failed to invoke function `org.neo4j.harness.funcThatThrows`: Caused by: java.lang" + ".RuntimeException: This is an exception", error ); } } }
@Test public void shouldGetHelpfulErrorOnProcedureThrowsException() throws Exception { // When try ( ServerControls server = createServer( MyFunctions.class ).newServer() ) { // Then HTTP.Response response = HTTP.POST( server.httpURI().resolve( "db/data/transaction/commit" ).toString(), quotedJson( "{ 'statements': [ { 'statement': 'RETURN org.neo4j.harness.funcThatThrows()' } ] }" ) ); String error = response.get( "errors" ).get( 0 ).get( "message" ).asText(); assertEquals( "Failed to invoke function `org.neo4j.harness.funcThatThrows`: Caused by: java.lang" + ".RuntimeException: This is an exception", error ); } }
@Test public void shouldWorkWithInjectableFromKernelExtensionWithMorePower() throws Throwable { // When try ( ServerControls server = createServer( MyFunctionsUsingMyCoreAPI.class ).newServer() ) { HTTP.POST( server.httpURI().resolve( "db/data/transaction/commit" ).toString(), quotedJson( "{ 'statements': [ { 'statement': 'CREATE (), (), ()' } ] }" ) ); // Then assertQueryGetsValue( server, "RETURN my.countNodes() AS value", 3L ); assertQueryGetsError( server, "RETURN my.willFail() AS value", "Write operations are not allowed" ); } }
private void testStartupWithConnectors( boolean httpEnabled, boolean httpsEnabled, boolean boltEnabled ) { TestServerBuilder serverBuilder = newInProcessBuilder( testDir.directory() ) .withConfig( "dbms.connector.http.enabled", Boolean.toString( httpEnabled ) ) .withConfig( "dbms.connector.http.listen_address", ":0" ) .withConfig( "dbms.connector.https.enabled", Boolean.toString( httpsEnabled ) ) .withConfig( "dbms.connector.https.listen_address", ":0" ) .withConfig( "dbms.connector.bolt.enabled", Boolean.toString( boltEnabled ) ) .withConfig( "dbms.connector.bolt.listen_address", ":0" ); try ( ServerControls server = serverBuilder.newServer() ) { GraphDatabaseService db = server.graph(); assertDbAccessible( db ); verifyConnector( db, "http", httpEnabled ); verifyConnector( db, "https", httpsEnabled ); verifyConnector( db, "bolt", boltEnabled ); } }
@Test public void shouldWorkWithInjectableFromKernelExtensionWithMorePower() throws Throwable { // When try ( ServerControls server = createServer( MyProceduresUsingMyCoreAPI.class ) .withConfig( GraphDatabaseSettings.record_id_batch_size, "1" ) .newServer() ) { // Then assertQueryGetsValue( server, "CALL makeNode(\\'Test\\')", 0L ); assertQueryGetsValue( server, "CALL makeNode(\\'Test\\')", 1L ); assertQueryGetsValue( server, "CALL makeNode(\\'Test\\')", 2L ); assertQueryGetsValue( server, "CALL countNodes", 3L ); assertQueryGetsError( server, "CALL willFail", "Write operations are not allowed" ); } }