@Test public void shouldRunAggregationFunction() throws Throwable { // Given CallableUserAggregationFunction func = compile( SingleAggregationFunction.class ).get( 0 ); // When UserAggregator aggregator = func.create( new BasicContext() ); aggregator.update( new Object[]{"Harry"} ); aggregator.update( new Object[]{"Bonnie"} ); aggregator.update( new Object[]{"Sally"} ); aggregator.update( new Object[]{"Clyde"} ); // Then assertThat( aggregator.result(), equalTo( Arrays.asList( "Bonnie", "Clyde" ) ) ); }
@Test public void shouldGiveHelpfulErrorOnNullMessageException() throws Throwable { // Given CallableUserAggregationFunction method = compile( FunctionThatThrowsNullMsgExceptionAtInvocation.class ).get( 0 ); // Expect exception.expect( ProcedureException.class ); exception.expectMessage( "Failed to invoke function `org.neo4j.kernel.impl.proc.test`: " + "Caused by: java.lang.IndexOutOfBoundsException" ); // When method.create( new BasicContext()).update( new Object[] {}); }
@Test public void shouldRunClassWithMultipleFunctionsDeclared() throws Throwable { // Given List<CallableUserAggregationFunction> compiled = compile( MultiFunction.class ); CallableUserAggregationFunction f1 = compiled.get( 0 ); CallableUserAggregationFunction f2 = compiled.get( 1 ); // When UserAggregator f1Aggregator = f1.create( new BasicContext() ); f1Aggregator.update( new Object[]{"Bonnie"} ); f1Aggregator.update( new Object[]{"Clyde"} ); UserAggregator f2Aggregator = f2.create( new BasicContext() ); f2Aggregator.update( new Object[]{"Bonnie", 1337L} ); f2Aggregator.update( new Object[]{"Bonnie", 42L} ); // Then assertThat( f1Aggregator.result(), equalTo( Arrays.asList( "Bonnie", "Clyde" ) ) ); assertThat( ((Map) f2Aggregator.result()).get( "Bonnie" ), equalTo( 1337L ) ); }
@Test public void shouldCompileAndRunUserAggregationFunctions() throws Throwable { // Given CallableUserAggregationFunction proc = compiler.compileAggregationFunction( AggregationFunctionWithInjectedAPI.class).get( 0 ); // When proc.create( new BasicContext() ).update( new Object[]{} ); Object out = proc.create( new BasicContext() ).result(); // Then assertThat( out, equalTo( "[Bonnie, Clyde]" ) ); }
@Test public void shouldInjectLogging() throws KernelException { // Given Log log = spy( Log.class ); components.register( Log.class, ctx -> log ); CallableUserAggregationFunction function = procedureCompiler.compileAggregationFunction( LoggingFunction.class ).get( 0 ); // When UserAggregator aggregator = function.create( new BasicContext() ); aggregator.update( new Object[]{} ); aggregator.result(); // Then verify( log ).debug( "1" ); verify( log ).info( "2" ); verify( log ).warn( "3" ); verify( log ).error( "4" ); }
@Test public void shouldFailNicelyWhenUnsafeAPISafeModeAggregationFunction() throws Throwable { //When List<CallableUserAggregationFunction> procList = compiler.compileAggregationFunction( AggregationFunctionWithUnsafeAPI.class); verify( log ).warn( notAvailableMessage( "org.neo4j.kernel.impl.proc.listCoolPeople" ) ); assertThat( procList.size(), equalTo( 1 ) ); try { procList.get(0).create( new BasicContext() ).update( new Object[]{} ); Object out = procList.get(0).create( new BasicContext() ).result(); fail(); } catch ( ProcedureException e ) { assertThat( e.getMessage(), notAvailableMessageMatcher( "org.neo4j.kernel.impl.proc.listCoolPeople" ) ); } }
@Test public void shouldLoadWhiteListedFunction() throws Throwable { // Given procedureCompiler = new ReflectiveProcedureCompiler( new TypeMappers(), components, new ComponentRegistry(), NullLog.getInstance(), new ProcedureConfig( Config.defaults( GraphDatabaseSettings.procedure_whitelist, "org.neo4j.kernel.impl.proc.collectCool" ) ) ); CallableUserAggregationFunction method = compile( SingleAggregationFunction.class ).get( 0 ); // Expect UserAggregator created = method.create( new BasicContext() ); created.update( new Object[]{"Bonnie"} ); assertThat(created.result(), equalTo( Collections.singletonList( "Bonnie" ) ) ); }