// // ======================================================================== // Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // // You may elect to redistribute this code under either of these licenses. // ======================================================================== // package org.eclipse.jetty.websocket.jsr356.server; import java.net.URI; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import javax.websocket.ClientEndpointConfig; import javax.websocket.ContainerProvider; import javax.websocket.Endpoint; import javax.websocket.EndpointConfig; import javax.websocket.MessageHandler; import javax.websocket.RemoteEndpoint; import javax.websocket.Session; import javax.websocket.WebSocketContainer; import javax.websocket.server.ServerEndpointConfig; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer; import org.eclipse.jetty.websocket.jsr356.server.samples.echo.BasicEchoEndpoint; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; public class JsrBatchModeTest { private Server server; private ServerConnector connector; private WebSocketContainer client; @Before public void prepare() throws Exception { server = new Server(); connector = new ServerConnector(server); server.addConnector(connector); ServletContextHandler context = new ServletContextHandler(server, "/", true, false); ServerContainer container = WebSocketServerContainerInitializer.configureContext(context); ServerEndpointConfig config = ServerEndpointConfig.Builder.create(BasicEchoEndpoint.class, "/").build(); container.addEndpoint(config); server.start(); client = ContainerProvider.getWebSocketContainer(); } @After public void dispose() throws Exception { server.stop(); } @Test public void testBatchModeOn() throws Exception { ClientEndpointConfig config = ClientEndpointConfig.Builder.create().build(); URI uri = URI.create("ws://localhost:" + connector.getLocalPort()); final CountDownLatch latch = new CountDownLatch(1); EndpointAdapter endpoint = new EndpointAdapter() { @Override public void onMessage(String message) { latch.countDown(); } }; try (Session session = client.connectToServer(endpoint, config, uri)) { RemoteEndpoint.Async remote = session.getAsyncRemote(); remote.setBatchingAllowed(true); Future<Void> future = remote.sendText("batch_mode_on"); // The write is aggregated and therefore completes immediately. future.get(1, TimeUnit.MICROSECONDS); // Did not flush explicitly, so the message should not be back yet. Assert.assertFalse(latch.await(1, TimeUnit.SECONDS)); // Explicitly flush. remote.flushBatch(); // Wait for the echo. Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); } } @Test public void testBatchModeOff() throws Exception { ClientEndpointConfig config = ClientEndpointConfig.Builder.create().build(); URI uri = URI.create("ws://localhost:" + connector.getLocalPort()); final CountDownLatch latch = new CountDownLatch(1); EndpointAdapter endpoint = new EndpointAdapter() { @Override public void onMessage(String message) { latch.countDown(); } }; try (Session session = client.connectToServer(endpoint, config, uri)) { RemoteEndpoint.Async remote = session.getAsyncRemote(); remote.setBatchingAllowed(false); Future<Void> future = remote.sendText("batch_mode_off"); // The write is immediate. future.get(1, TimeUnit.SECONDS); // Wait for the echo. Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); } } @Test public void testBatchModeAuto() throws Exception { ClientEndpointConfig config = ClientEndpointConfig.Builder.create().build(); URI uri = URI.create("ws://localhost:" + connector.getLocalPort()); final CountDownLatch latch = new CountDownLatch(1); EndpointAdapter endpoint = new EndpointAdapter() { @Override public void onMessage(String message) { latch.countDown(); } }; try (Session session = client.connectToServer(endpoint, config, uri)) { RemoteEndpoint.Async remote = session.getAsyncRemote(); Future<Void> future = remote.sendText("batch_mode_auto"); // The write is immediate, as per the specification. future.get(1, TimeUnit.SECONDS); // Wait for the echo. Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); } } private static abstract class EndpointAdapter extends Endpoint implements MessageHandler.Whole<String> { @Override public void onOpen(Session session, EndpointConfig config) { session.addMessageHandler(this); } } }