/* * Copyright (C) 2015-2017 Lightbend Inc. */ package play.soap.sbtplugin.tester; import java.lang.RuntimeException; import java.io.IOException; import java.net.ServerSocket; import java.util.function.*; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import javax.xml.namespace.QName; import javax.xml.ws.Endpoint; import javax.xml.ws.handler.MessageContext; import javax.xml.ws.handler.soap.*; import org.apache.cxf.jaxws.EndpointImpl; import org.junit.*; import play.soap.testservice.client.*; import play.Application; import play.inject.guice.GuiceApplicationBuilder; import java.util.concurrent.TimeUnit; import java.util.concurrent.CompletionStage; import static org.junit.Assert.*; import static play.test.Helpers.*; public class HelloWorldTest { @Test public void sayHello() { withClient(client -> assertEquals("Hello world", await(client.sayHello("world"))) ); } @Test public void sayHelloToManyPeople() { withClient(client -> { List names = Arrays.asList("foo", "bar"); List hellos = Arrays.asList("Hello foo", "Hello bar"); assertEquals(hellos, await(client.sayHelloToMany(names))); }); } @Test public void sayHelloToOneUser() { withClient(client -> { User user = new User(); user.setName("world"); assertEquals("world", await(client.sayHelloToUser(user)).getUser().getName()); }); } @Test public void sayHelloException() { withClient(client -> { try { await(client.sayHelloException("world")); fail(); } catch (HelloException_Exception e) { assertEquals("Hello world", e.getMessage()); } }); } @Test public void dontSayHello() { withClient(client -> { assertNull(await(client.dontSayHello())); }); } @Test public void workWithCustomHandlers() { withApp(app -> { final AtomicBoolean invoked = new AtomicBoolean(); HelloWorld client = app.injector().instanceOf(HelloWorldService.class).getHelloWorld(new SOAPHandler() { public Set getHeaders() { return null; } public boolean handleMessage(SOAPMessageContext context) { invoked.set(true); return true; } public boolean handleFault(SOAPMessageContext context) { return true; } public void close(MessageContext context) { } }); assertEquals("Hello world", await(client.sayHello("world"))); assertTrue(invoked.get()); }); } private static T await(CompletionStage promise) { try { return promise.toCompletableFuture().get(10, TimeUnit.SECONDS); } catch (Exception ex) { throw new RuntimeException(ex); } } private static void withClient(Consumer block) { withApp(app -> { HelloWorld client = app.injector().instanceOf(HelloWorldService.class).getHelloWorld(); block.accept(client); }); } private static void withApp(Consumer block) { withService(port -> { GuiceApplicationBuilder builder = new GuiceApplicationBuilder() .configure("play.soap.address", "http://localhost:"+port+"/helloWorld") .configure("play.soap.debugLog", true); Application app = builder.build(); running(app, () -> block.accept(app)); }); } private static void withService(Consumer block) { final int port = findAvailablePort(); final Endpoint endpoint = Endpoint.publish( "http://localhost:"+port+"/helloWorld", new play.soap.testservice.HelloWorldImpl()); try { block.accept(port); } finally { endpoint.stop(); // Need to shutdown whole engine. Note, Jetty's shutdown doesn't seem to happen synchronously, have to wait // a few seconds for the port to be released. This is why we use a different port each time. ((EndpointImpl) endpoint).getBus().shutdown(true); } } private static int findAvailablePort() { try { final ServerSocket socket = new ServerSocket(0); try { return socket.getLocalPort(); } finally { socket.close(); } } catch (IOException ioe) { throw new RuntimeException(ioe); } } }