package org.atmosphere.tests;
import com.ning.http.client.AsyncHttpClient;
import com.ning.http.client.AsyncHttpClientConfig;
import org.atmosphere.cpr.AtmosphereHandler;
import org.atmosphere.cpr.AtmosphereResource;
import org.atmosphere.cpr.AtmosphereResourceEvent;
import org.atmosphere.cpr.AtmosphereResourceEventListenerAdapter;
import org.atmosphere.nettosphere.Config;
import org.atmosphere.nettosphere.Nettosphere;
import org.atmosphere.wasync.Client;
import org.atmosphere.wasync.ClientFactory;
import org.atmosphere.wasync.Decoder;
import org.atmosphere.wasync.Encoder;
import org.atmosphere.wasync.Event;
import org.atmosphere.wasync.Function;
import org.atmosphere.wasync.Options;
import org.atmosphere.wasync.Request;
import org.atmosphere.wasync.RequestBuilder;
import org.atmosphere.wasync.Socket;
import org.atmosphere.wasync.impl.AtmosphereClient;
import org.atmosphere.wasync.serial.DefaultSerializedFireStage;
import org.atmosphere.wasync.serial.SerializedClient;
import org.atmosphere.wasync.serial.SerializedOptionsBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.net.ConnectException;
import java.net.ServerSocket;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
public abstract class BaseTest {
public final static String RESUME = "Resume";
public Nettosphere server;
public String targetUrl;
public static final Logger logger = LoggerFactory.getLogger(BaseTest.class);
public int port;
public int findFreePort() throws IOException {
ServerSocket socket = null;
try {
socket = new ServerSocket(0);
return socket.getLocalPort();
} finally {
if (socket != null) {
socket.close();
}
}
}
@AfterMethod(alwaysRun = true)
public void tearDownGlobal() throws Exception {
if (server != null && server.isStarted()) {
server.stop();
}
}
abstract Request.TRANSPORT transport();
abstract int statusCode();
abstract int notFoundCode();
abstract int getCount();
@BeforeMethod(alwaysRun = true)
public void start() throws IOException {
if (server != null) server.stop();
port = findFreePort();
targetUrl = "http://127.0.0.1:" + port;
}
@Test
public void closeTest() throws Exception {
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (!b.getAndSet(true)) {
r.suspend(-1);
} else {
r.getBroadcaster().broadcast(RESUME);
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
if (!r.isResuming() || !r.isCancelled()) {
r.getResource().getResponse().getWriter().print(r.getMessage());
r.getResource().resume();
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<String> response = new AtomicReference<String>();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(transport());
Socket socket = client.create(client.newOptionsBuilder().reconnect(false).build());
socket.on(Event.MESSAGE, new Function<String>() {
@Override
public void on(String t) {
logger.info("Function invoked {}", t);
response.set(t);
latch.countDown();
}
}).on(new Function<Throwable>() {
@Override
public void on(Throwable t) {
t.printStackTrace();
latch.countDown();
}
}).open(request.build()).fire("PING");
latch.await(5, TimeUnit.SECONDS);
socket.close();
server.stop();
assertEquals(socket.status(), Socket.STATUS.CLOSE);
}
@Test
public void closeWithoutOpenTest() throws Exception {
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (!b.getAndSet(true)) {
r.suspend(-1);
} else {
r.getBroadcaster().broadcast(RESUME);
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
if (!r.isResuming() || !r.isCancelled()) {
r.getResource().getResponse().getWriter().print(r.getMessage());
r.getResource().resume();
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
Client client = ClientFactory.getDefault().newClient();
Socket socket = client.create();
socket.close();
assertEquals(socket.status(), Socket.STATUS.CLOSE);
}
@Test
public void basicWebSocketTest() throws Exception {
final CountDownLatch l = new CountDownLatch(1);
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (!b.getAndSet(true)) {
r.suspend(-1);
} else {
r.getBroadcaster().broadcast(RESUME);
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
if (!r.isResuming() || !r.isCancelled()) {
r.getResource().getResponse().getWriter().print(r.getMessage());
r.getResource().resume();
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<String> response = new AtomicReference<String>();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(transport());
Socket socket = client.create();
;
socket.on("message", new Function<String>() {
@Override
public void on(String t) {
logger.info("Function invoked {}", t);
response.set(t);
latch.countDown();
}
}).on(new Function<Throwable>() {
@Override
public void on(Throwable t) {
t.printStackTrace();
latch.countDown();
}
}).open(request.build()).fire("PING");
latch.await(5, TimeUnit.SECONDS);
server.stop();
socket.close();
assertEquals(response.get(), RESUME);
}
@Test
public void allStringFunctionTest() throws Exception {
final CountDownLatch latch = new CountDownLatch(2);
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (!b.getAndSet(true)) {
r.suspend(-1);
latch.countDown();
} else {
r.getBroadcaster().broadcast(RESUME);
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
if (!r.isResuming() || !r.isCancelled()) {
r.getResource().getResponse().getWriter().print(r.getMessage());
r.getResource().resume();
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final StringBuilder builder = new StringBuilder();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(transport());
Socket socket = client.create();
socket.on(new Function<String>() {
@Override
public void on(String m) {
builder.append(m);
latch.countDown();
}
}).open(request.build()).fire("PING");
latch.await(5, TimeUnit.SECONDS);
assertEquals(builder.toString(), RESUME);
}
@Test
public void statusHeaderFunctionTest() throws Exception {
final CountDownLatch l = new CountDownLatch(1);
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (!b.getAndSet(true)) {
r.suspend(-1);
} else {
r.getBroadcaster().broadcast(RESUME);
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
if (!r.isResuming() || !r.isCancelled()) {
r.getResource().getResponse().getWriter().print(r.getMessage());
r.getResource().resume();
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(2);
final AtomicInteger status = new AtomicInteger();
final AtomicReference<Map> map = new AtomicReference<Map>();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(transport());
Socket socket = client.create();
socket.on(new Function<Integer>() {
@Override
public void on(Integer statusCode) {
status.set(statusCode);
latch.countDown();
}
}).on(new Function<Map>() {
@Override
public void on(Map t) {
map.set(t);
latch.countDown();
}
}).open(request.build()).fire("PING");
latch.await(5, TimeUnit.SECONDS);
socket.close();
assertEquals(status.get(), statusCode());
assertNotNull(map.get());
assertEquals(map.get().getClass().getInterfaces()[0], Map.class);
}
@Test
public void status404FunctionTest() throws Exception {
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (!b.getAndSet(true)) {
r.suspend(-1);
} else {
r.getBroadcaster().broadcast(RESUME);
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
if (!r.isResuming() || !r.isCancelled()) {
r.getResource().getResponse().getWriter().print(r.getMessage());
r.getResource().resume();
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicInteger status = new AtomicInteger();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/ratata")
.transport(transport());
final Socket socket = client.create();
socket.on(new Function<Integer>() {
@Override
public void on(Integer statusCode) {
status.set(statusCode);
socket.close();
latch.countDown();
}
}).open(request.build());
latch.await(5, TimeUnit.SECONDS);
socket.close();
assertEquals(status.get(), notFoundCode());
}
@Test
public void closedFireTest() throws Exception {
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
@Override
public void onRequest(AtmosphereResource r) throws IOException {
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(1);
final CountDownLatch ioLatch = new CountDownLatch(1);
final AtomicInteger status = new AtomicInteger();
final AtomicReference response2 = new AtomicReference();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(transport());
final Socket socket = client.create();
socket.on(new Function<Integer>() {
@Override
public void on(Integer statusCode) {
status.set(statusCode);
socket.close();
latch.countDown();
}
}).on(new Function<IOException>() {
@Override
public void on(IOException t) {
response2.set(t);
ioLatch.countDown();
}
}).open(request.build());
latch.await(5, TimeUnit.SECONDS);
socket.fire("Yo");
ioLatch.await(5, TimeUnit.SECONDS);
assertNotNull(response2.get());
assertEquals(response2.get().getClass(), IOException.class);
}
@Test
public void basicConnectExceptionTest() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<ConnectException> response = new AtomicReference<ConnectException>();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(transport());
Socket socket = client.create();
IOException ioException = null;
try {
socket.on(new Function<ConnectException>() {
@Override
public void on(ConnectException t) {
response.set(t);
latch.countDown();
}
}).open(request.build());
} catch (IOException ex) {
ioException = ex;
}
latch.await(5, TimeUnit.SECONDS);
socket.close();
assertEquals(response.get().getClass(), ConnectException.class);
assertTrue(IOException.class.isAssignableFrom(ioException.getClass()));
}
@Test
public void basicIOExceptionTest() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<IOException> response = new AtomicReference<IOException>();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(transport());
Socket socket = client.create();
IOException ioException = null;
try {
socket.on(new Function<IOException>() {
@Override
public void on(IOException t) {
response.set(t);
latch.countDown();
}
}).open(request.build());
} catch (IOException ex) {
ioException = ex;
}
latch.await(5, TimeUnit.SECONDS);
socket.close();
assertTrue(IOException.class.isAssignableFrom(response.get().getClass()));
assertTrue(IOException.class.isAssignableFrom(ioException.getClass()));
}
@Test
public void basicEchoEncoderTest() throws Exception {
final CountDownLatch l = new CountDownLatch(1);
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (!b.getAndSet(true)) {
r.suspend(-1);
} else {
r.getBroadcaster().broadcast(r.getRequest().getReader().readLine());
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
if (!r.isResuming() || !r.isCancelled()) {
r.getResource().getResponse().getWriter().print(r.getMessage());
r.getResource().resume();
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<String> response = new AtomicReference<String>();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.encoder(new Encoder<String, String>() {
@Override
public String encode(String s) {
return "<-" + s.toString() + "->";
}
})
.transport(transport());
Socket socket = client.create();
;
socket.on("message", new Function<String>() {
@Override
public void on(String t) {
response.set(t);
latch.countDown();
}
}).on(new Function<Throwable>() {
@Override
public void on(Throwable t) {
t.printStackTrace();
latch.countDown();
}
}).open(request.build()).fire("echo");
latch.await(5, TimeUnit.SECONDS);
socket.close();
assertEquals(response.get(), "<-echo->");
}
@Test
public void requestTimeoutTest() throws Exception {
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (!b.getAndSet(true)) {
r.suspend(-1);
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<Class<? extends TimeoutException>> response = new AtomicReference<Class<? extends TimeoutException>>();
Client client = ClientFactory.getDefault().newClient();
Options o = client.newOptionsBuilder().reconnect(false).requestTimeoutInSeconds(5).build();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.encoder(new Encoder<String, String>() {
@Override
public String encode(String s) {
return "<-" + s.toString() + "->";
}
})
.transport(transport());
Socket socket = client.create(o);
socket.on(new Function<TimeoutException>() {
@Override
public void on(TimeoutException t) {
response.set(t.getClass());
latch.countDown();
}
}).open(request.build());
latch.await(5, TimeUnit.SECONDS);
socket.close();
assertEquals(response.get(), TimeoutException.class);
}
@Test
public void basicDecoderTest() throws Exception {
final CountDownLatch l = new CountDownLatch(1);
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (!b.getAndSet(true)) {
r.suspend(-1);
} else {
r.getBroadcaster().broadcast(r.getRequest().getReader().readLine());
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
if (!r.isResuming() || !r.isCancelled()) {
r.getResource().getResponse().getWriter().print(r.getMessage());
r.getResource().resume();
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<POJO> response = new AtomicReference<POJO>();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.decoder(new Decoder<String, POJO>() {
@Override
public POJO decode(Event e, String s) {
return new POJO(s);
}
})
.transport(transport());
Socket socket = client.create();
socket.on(Event.MESSAGE, new Function<POJO>() {
@Override
public void on(POJO t) {
response.set(t);
latch.countDown();
}
}).open(request.build()).fire("echo");
latch.await(5, TimeUnit.SECONDS);
assertNotNull(response.get());
assertEquals(response.get().getClass(), POJO.class);
socket.close();
}
@Test
public void basicTransportTest() throws Exception {
final CountDownLatch l = new CountDownLatch(1);
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (!b.getAndSet(true)) {
r.suspend(-1);
} else {
r.getBroadcaster().broadcast(r.getRequest().getReader().readLine());
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
if (!r.isResuming() || !r.isCancelled()) {
r.getResource().getResponse().getWriter().print(r.getMessage());
r.getResource().resume();
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<Request.TRANSPORT> response = new AtomicReference<Request.TRANSPORT>();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(transport());
Socket socket = client.create();
socket.on(Event.TRANSPORT, new Function<Request.TRANSPORT>() {
@Override
public void on(Request.TRANSPORT t) {
response.set(t);
latch.countDown();
}
}).open(request.build()).fire("yo");
latch.await(5, TimeUnit.SECONDS);
assertNotNull(response.get());
assertEquals(response.get(), transport());
}
@Test
public void encodersChainingTests() throws Exception {
final CountDownLatch l = new CountDownLatch(1);
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (!b.getAndSet(true)) {
r.suspend(-1);
} else {
r.getBroadcaster().broadcast(r.getRequest().getReader().readLine());
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
if (!r.isResuming() || !r.isCancelled()) {
r.getResource().getResponse().getWriter().print(r.getMessage());
r.getResource().resume();
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<String> response = new AtomicReference<String>();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.encoder(new Encoder<String, POJO>() {
@Override
public POJO encode(String s) {
return new POJO("<-" + s + "->");
}
})
.encoder(new Encoder<POJO, Reader>() {
@Override
public Reader encode(POJO s) {
return new StringReader(s.message);
}
})
.transport(transport());
Socket socket = client.create();
socket.on(Event.MESSAGE, new Function<String>() {
@Override
public void on(String t) {
response.set(t);
latch.countDown();
}
}).on(new Function<Throwable>() {
@Override
public void on(Throwable t) {
t.printStackTrace();
latch.countDown();
}
}).open(request.build()).fire("echo");
latch.await(5, TimeUnit.SECONDS);
socket.close();
assertEquals(response.get(), "<-echo->");
}
public final static class POJO {
public final String message;
public POJO(String message) {
this.message = message;
}
}
public final static class POJO2 {
public final POJO message;
public POJO2(POJO message) {
this.message = message;
}
}
@Test
public void multipleFireBlockingTest() throws Exception {
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
private final AtomicInteger count = new AtomicInteger(2);
private final AtomicReference<StringBuffer> response = new AtomicReference<StringBuffer>(new StringBuffer());
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (!b.getAndSet(true)) {
r.suspend(-1);
} else {
r.getBroadcaster().broadcast(r.getRequest().getReader().readLine());
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
response.get().append(r.getMessage());
if (count.decrementAndGet() == 0 && (!r.isResuming() || !r.isCancelled())) {
r.getResource().getResponse().write(response.toString());
r.getResource().resume();
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<StringBuffer> response = new AtomicReference<StringBuffer>(new StringBuffer());
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(transport());
Socket socket = client.create();
socket.on("message", new Function<String>() {
@Override
public void on(String t) {
logger.info("Function invoked {}", t);
response.get().append(t);
latch.countDown();
}
}).on(new Function<Throwable>() {
@Override
public void on(Throwable t) {
t.printStackTrace();
latch.countDown();
}
}).open(request.build())
.fire("PING").get()
.fire("PONG").get();
latch.await(5, TimeUnit.SECONDS);
socket.close();
// We can't predict the order of requests send
try {
assertEquals(response.get().toString(), "PONGPING");
} catch (AssertionError e) {
assertEquals(response.get().toString(), "PINGPONG");
}
}
@Test
public void multipleFireTest() throws Exception {
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
private final AtomicInteger count = new AtomicInteger(2);
private final AtomicReference<StringBuffer> response = new AtomicReference<StringBuffer>(new StringBuffer());
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (!b.getAndSet(true)) {
r.suspend(-1);
} else {
r.getBroadcaster().broadcast(r.getRequest().getReader().readLine());
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
response.get().append(r.getMessage());
if (count.decrementAndGet() == 0 && (!r.isResuming() || !r.isCancelled())) {
r.getResource().getResponse().write(response.toString());
r.getResource().resume();
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<StringBuffer> response = new AtomicReference<StringBuffer>(new StringBuffer());
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(transport());
Socket socket = client.create();
socket.on("message", new Function<String>() {
@Override
public void on(String t) {
logger.info("Function invoked {}", t);
response.get().append(t);
latch.countDown();
}
}).on(new Function<Throwable>() {
@Override
public void on(Throwable t) {
t.printStackTrace();
latch.countDown();
}
}).open(request.build())
.fire("PING")
.fire("PONG");
latch.await(5, TimeUnit.SECONDS);
socket.close();
// We can't predict the order of requests send
try {
assertEquals(response.get().toString(), "PONGPING");
} catch (AssertionError e) {
assertEquals(response.get().toString(), "PINGPONG");
}
}
@Test(enabled = false)
public void basicLoadTest() throws IOException, InterruptedException {
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/", new AtmosphereHandler() {
@Override
public void onRequest(final AtmosphereResource r) throws IOException {
if (r.getRequest().getMethod().equalsIgnoreCase("GET")) {
r.addEventListener(new AtmosphereResourceEventListenerAdapter() {
@Override
public void onSuspend(AtmosphereResourceEvent event) {
r.removeEventListener(this);
try {
r.getResponse().write("yo!".getBytes()).flushBuffer();
} catch (IOException e) {
e.printStackTrace();
}
}
}).suspend();
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final AsyncHttpClient c = new AsyncHttpClient(new AsyncHttpClientConfig.Builder().setMaxRequestRetry(0).build());
final CountDownLatch l = new CountDownLatch(getCount());
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder();
request.method(Request.METHOD.GET).uri(targetUrl);
request.transport(transport());
request.encoder(new Encoder<String, String>() {
@Override
public String encode(String s) {
return s;
}
});
Socket[] sockets = new Socket[getCount()];
request.decoder(new Decoder<String, String>() {
@Override
public String decode(Event evntp, String s) {
return s;
}
});
for (int i = 0; i < getCount(); i++) {
sockets[i] = client.create(client.newOptionsBuilder().runtime(c, true).build());
sockets[i].on(new Function<Integer>() {
@Override
public void on(Integer statusCode) {
}
});
sockets[i].on(new Function<String>() {
@Override
public void on(String s) {
if (s.equalsIgnoreCase("yo!")) {
System.out.println("=========> " + l.getCount());
l.countDown();
}
}
});
sockets[i].on(new Function<Throwable>() {
@Override
public void on(Throwable t) {
t.printStackTrace();
}
});
sockets[i].open(request.build());
sockets[i].fire("OPEN");
}
boolean pass = l.await(60, TimeUnit.SECONDS);
try {
for (int i = 0; i < sockets.length; i++) {
sockets[i].close();
}
c.close();
server.stop();
} finally {
assertTrue(pass);
}
}
@Test(enabled = true)
public void serializeTest() throws Exception {
System.out.println("=============== STARTING SerializedTest");
if (server != null) {
server.stop();
}
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicInteger count = new AtomicInteger(2);
private final AtomicReference<StringBuffer> response = new AtomicReference<StringBuffer>(new StringBuffer());
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (r.getRequest().getMethod().equalsIgnoreCase("GET")) {
r.suspend(-1);
} else {
try {
r.getBroadcaster().broadcast(r.getRequest().getReader().readLine()).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
if (r.getMessage() != null) {
response.get().append(r.getMessage());
if (count.decrementAndGet() == 0) {
r.getResource().getResponse().write(response.toString());
r.getResource().resume();
}
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<StringBuffer> response = new AtomicReference<StringBuffer>(new StringBuffer());
SerializedClient client = ClientFactory.getDefault().newClient(SerializedClient.class);
SerializedOptionsBuilder b = client.newOptionsBuilder();
b.serializedFireStage(new DefaultSerializedFireStage());
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(transport());
Socket socket = client.create(b.build());
socket.on("message", new Function<String>() {
@Override
public void on(String t) {
logger.info("Serialized Function invoked {}", t);
response.get().append(t);
latch.countDown();
}
}).on(new Function<Throwable>() {
@Override
public void on(Throwable t) {
System.out.println("=============== ERROR");
t.printStackTrace();
}
}).open(request.build())
.fire("PING")
.fire("PONG").get();
latch.await(5, TimeUnit.SECONDS);
socket.close();
assertEquals(response.get().toString(), "PINGPONG");
}
@Test
public void postTest() throws Exception {
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (!b.getAndSet(true)) {
r.suspend(-1);
} else {
r.getResponse().write(r.getRequest().getReader().readLine());
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<String> response = new AtomicReference<String>();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(transport());
Socket socket = client.create();
socket.on(Event.MESSAGE, new Function<String>() {
@Override
public void on(String t) {
response.set(t);
latch.countDown();
}
}).open(request.build()).fire("yoga");
latch.await(5, TimeUnit.SECONDS);
assertNotNull(response.get());
assertEquals(response.get(), "yoga");
}
@Test
public void serverDownTest() throws Exception {
final CountDownLatch latch = new CountDownLatch(3);
final AtomicReference response = new AtomicReference();
final AtomicReference response2 = new AtomicReference();
Client client = ClientFactory.getDefault().newClient();
String unreachableUrl = "http://localhost:815";
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(unreachableUrl + "/suspend")
.transport(transport());
final Socket socket = client.create();
IOException ioException = null;
try {
socket.on(new Function<ConnectException>() {
@Override
public void on(ConnectException t) {
socket.close(); // I close it here, remove this close, issue will not happen
response.set(t);
latch.countDown();
}
}).on(new Function<IOException>() {
@Override
public void on(IOException t) {
response2.set(t);
latch.countDown();
}
}).open(request.build());
} catch (IOException ex) {
ioException = ex;
}
socket.fire("echo");
latch.await(5, TimeUnit.SECONDS);
assertEquals(response.get().getClass(), ConnectException.class);
assertTrue(IOException.class.isAssignableFrom(response2.get().getClass()));
assertTrue(IOException.class.isAssignableFrom(ioException.getClass()));
}
@Test
public void shutdownServerTest() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (!b.getAndSet(true)) {
r.suspend(-1);
} else {
r.getBroadcaster().broadcast(RESUME);
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
if (!r.isResuming() || !r.isCancelled()) {
latch.countDown();
r.getResource().getResponse().getWriter().print(r.getMessage());
r.getResource().resume();
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final AtomicReference response = new AtomicReference();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(transport());
Socket socket = client.create(client.newOptionsBuilder().reconnect(false).build());
socket.on(Event.CLOSE, new Function<String>() {
@Override
public void on(String t) {
//Can I receive close message when server is stopped?
logger.info("Function invoked {}", t);
response.set(t);
}
}).on(new Function<Throwable>() {
@Override
public void on(Throwable t) {
t.printStackTrace();
latch.countDown();
}
}).open(request.build()).fire("PING");
latch.await(5, TimeUnit.SECONDS);
server.stop();
socket.close();
assertEquals(socket.status(), Socket.STATUS.CLOSE);//or ERROR?
}
@Test
public void timeoutTest() throws IOException, InterruptedException {
logger.info("\n\ntimeoutTest\n\n");
final AtomicReference<StringBuilder> b = new AtomicReference<StringBuilder>(new StringBuilder());
final CountDownLatch latch = new CountDownLatch(1);
final CountDownLatch elatch = new CountDownLatch(1);
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
r.addEventListener(new AtmosphereResourceEventListenerAdapter() {
public void onSuspend(AtmosphereResourceEvent event) {
latch.countDown();
}
}).suspend(2, TimeUnit.SECONDS);
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder clientRequest = client.newRequestBuilder().method(Request.METHOD.GET).uri(targetUrl)
.decoder(new Decoder<String, Reader>() {
@Override
public Reader decode(Event e, String s) {
// Fool the decoder mapping
return new StringReader(s);
}
}).transport(transport());
Socket socket = client.create();
socket.on(Event.CLOSE, new Function<String>() {
@Override
public void on(String t) {
b.get().append(t);
}
}).on(new Function<IOException>() {
@Override
public void on(IOException ioe) {
ioe.printStackTrace();
b.get().append("ERROR");
elatch.countDown();
}
}).on(Event.OPEN, new Function<String>() {
@Override
public void on(String t) {
b.get().append(t);
}
}).open(clientRequest.build());
latch.await(5, TimeUnit.SECONDS);
server.stop();
elatch.await(5, TimeUnit.SECONDS);
assertEquals(b.get().toString(), "OPENCLOSEERROR");
}
@Test
public void closeWriteTest() throws IOException, InterruptedException {
logger.info("\n\ncloseWriteTest\n\n");
final AtomicReference<StringBuilder> b = new AtomicReference<StringBuilder>(new StringBuilder());
final CountDownLatch latch = new CountDownLatch(3);
final CountDownLatch flatch = new CountDownLatch(1);
final CountDownLatch elatch = new CountDownLatch(1);
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/", new AtmosphereHandler() {
private final AtomicReference<AtmosphereResource> resource = new AtomicReference<AtmosphereResource>();
@Override
public void onRequest(final AtmosphereResource r) throws IOException {
if (r.getRequest().getMethod().equals("GET")) {
r.addEventListener(new AtmosphereResourceEventListenerAdapter() {
public void onSuspend(AtmosphereResourceEvent event) {
resource.set(r);
for (int i = 0; i < 8192; i++) {
try {
resource.get().getResponse().getOutputStream().write(" ".getBytes());
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
}).suspend();
} else {
String line = r.getRequest().getReader().readLine();
resource.get().write(line).close();
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder clientRequest = client.newRequestBuilder().method(Request.METHOD.GET).uri(targetUrl)
.decoder(new Decoder<String, String>() {
@Override
public String decode(Event e, String s) {
// Fool the decoder mapping
return s;
}
}).transport(transport());
Socket socket = client.create();
socket.on("message", new Function<String>() {
@Override
public void on(String t) {
b.get().append(t);
flatch.countDown();
}
}).on(Event.CLOSE, new Function<String>() {
@Override
public void on(String t) {
b.get().append(t);
}
}).on(Event.REOPENED, new Function<String>() {
@Override
public void on(String t) {
b.get().append(t);
latch.countDown();
}
}).on(new Function<IOException>() {
@Override
public void on(IOException ioe) {
ioe.printStackTrace();
b.get().append("ERROR");
elatch.countDown();
}
}).on(Event.OPEN, new Function<String>() {
@Override
public void on(String t) {
b.get().append(t);
}
}).open(clientRequest.build());
socket.fire("PING");
flatch.await(5, TimeUnit.SECONDS);
server.stop();
elatch.await(5, TimeUnit.SECONDS);
// TODO: Hacky, but on slow machime the stop operation won't finish on time.
// The ERRROR will never comes in that case and the client may reconnect.
assertEquals(b.get().toString(), "OPENPINGCLOSEERROR");
}
@Test
public void reconnectFireTest() throws IOException, InterruptedException {
logger.info("\n\nreconnectFireTest\n\n");
final AtomicReference<StringBuilder> b = new AtomicReference<StringBuilder>(new StringBuilder());
final CountDownLatch latch = new CountDownLatch(1);
final CountDownLatch flatch = new CountDownLatch(1);
final CountDownLatch elatch = new CountDownLatch(1);
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
private final AtomicReference<AtmosphereResource> resource = new AtomicReference<AtmosphereResource>();
@Override
public void onRequest(final AtmosphereResource r) throws IOException {
if (r.getRequest().getMethod().equals("GET")) {
r.addEventListener(new AtmosphereResourceEventListenerAdapter() {
public void onSuspend(AtmosphereResourceEvent event) {
latch.countDown();
resource.set(r);
for (int i = 0; i < 8192; i++) {
resource.get().write(" ");
}
}
}).suspend();
} else {
if (!b.getAndSet(true)) {
resource.get().write(r.getRequest().getReader().readLine()).close();
} else {
resource.get().write(r.getRequest().getReader().readLine());
}
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder clientRequest = client.newRequestBuilder().method(Request.METHOD.GET).uri(targetUrl)
.encoder(new Encoder<String, String>() {
@Override
public String encode(String s) {
System.out.println("[Encode]:" + s);
return s;
}
})
.decoder(new Decoder<String, String>() {
@Override
public String decode(Event e, String s) {
// Fool the decoder mapping
return s;
}
}).transport(transport());
final Socket socket = client.create();
socket.on("message", new Function<String>() {
@Override
public void on(String t) {
//System.out.println("=>" + t);
b.get().append(t);
flatch.countDown();
}
}).on(Event.CLOSE, new Function<String>() {
@Override
public void on(String t) {
b.get().append(t);
}
}).on(Event.REOPENED, new Function<String>() {
@Override
public void on(String t) {
b.get().append(t);
try {
socket.fire("PONG");
} catch (IOException e) {
e.printStackTrace();
}
latch.countDown();
}
}).on(new Function<IOException>() {
@Override
public void on(IOException ioe) {
ioe.printStackTrace();
b.get().append("ERROR");
elatch.countDown();
}
}).on(Event.OPEN, new Function<String>() {
@Override
public void on(String t) {
b.get().append(t);
}
}).open(clientRequest.build());
socket.fire("PING");
latch.await(10, TimeUnit.SECONDS);
flatch.await(10, TimeUnit.SECONDS);
server.stop();
elatch.await(5, TimeUnit.SECONDS);
assertEquals(b.get().toString(), "OPENPINGCLOSEERROR");
}
@Test
public void eventDecoderTest() throws Exception {
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (!b.getAndSet(true)) {
r.suspend(-1);
} else {
r.getBroadcaster().broadcast(r.getRequest().getReader().readLine());
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
if (!r.isResuming() || !r.isCancelled()) {
r.getResource().getResponse().getWriter().print(r.getMessage());
r.getResource().resume();
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(2);
final CountDownLatch xlatch = new CountDownLatch(1);
final AtomicReference<POJO> response = new AtomicReference<POJO>();
final AtomicReference<EventPOJO> open = new AtomicReference<EventPOJO>();
final AtomicReference<EventPOJO> close = new AtomicReference<EventPOJO>();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.decoder(new Decoder<String, POJO>() {
@Override
public POJO decode(Event e, String s) {
if (e.equals(Event.MESSAGE)) {
return new POJO(s);
} else {
return null;
}
}
})
.decoder(new Decoder<String, EventPOJO>() {
@Override
public EventPOJO decode(Event e, String s) {
return new EventPOJO(e, s);
}
})
.transport(transport());
Socket socket = client.create();
socket.on(new Function<POJO>() {
@Override
public void on(POJO t) {
response.set(t);
latch.countDown();
}
}).on(Event.OPEN, new Function<EventPOJO>() {
@Override
public void on(EventPOJO t) {
open.set(t);
latch.countDown();
}
}).on(Event.CLOSE, new Function<EventPOJO>() {
@Override
public void on(EventPOJO t) {
close.set(t);
xlatch.countDown();
}
}).open(request.build()).fire("echo");
latch.await(5, TimeUnit.SECONDS);
socket.close();
xlatch.await(5, TimeUnit.SECONDS);
assertNotNull(response.get());
assertNotNull(open.get());
assertNotNull(close.get());
assertEquals(response.get().getClass(), POJO.class);
assertEquals(open.get().getClass(), EventPOJO.class);
assertEquals(close.get().getClass(), EventPOJO.class);
assertEquals(open.get().e, Event.OPEN);
assertEquals(close.get().e, Event.CLOSE);
assertEquals(open.get().message, Event.OPEN.name());
assertEquals(close.get().message, Event.CLOSE.name());
}
@Test
public void testTimeoutAtmosphereClient() throws IOException, InterruptedException {
final CountDownLatch latch = new CountDownLatch(1);
AtmosphereClient client = ClientFactory.getDefault().newClient(AtmosphereClient.class);
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl)
.trackMessageLength(true)
.transport(transport());
Socket socket = client.create();
IOException ioException = null;
try {
socket.on(new Function<ConnectException>() {
@Override
public void on(ConnectException t) {
latch.countDown();
}
}).on(Event.CLOSE.name(), new Function<String>() {
@Override
public void on(String t) {
logger.info("Connection closed");
}
}).open(request.build());
} catch (IOException ex) {
ioException = ex;
}
assertTrue(latch.await(10, TimeUnit.SECONDS));
assertTrue(IOException.class.isAssignableFrom(ioException.getClass()));
}
@Test
public void basicHelloTest() throws Exception {
final CountDownLatch l = new CountDownLatch(1);
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
r.getResponse().getWriter().print("HELLO");
// at this point, I think Socket should have a STATUS other than INIT when it reads the response in the socket.on(...)
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<String> response = new AtomicReference<String>();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(transport());
Socket socket = client.create();
socket.on("message", new Function<String>() {
@Override
public void on(String t) {
// the status should have been updated to something else than INIT
response.set(t);
latch.countDown();
}
}).on(new Function<Throwable>() {
@Override
public void on(Throwable t) {
t.printStackTrace();
latch.countDown();
}
}).open(request.build());
latch.await();
logger.error("SOCKET STATUS [{}]", socket.status());
assertEquals(response.get(), "HELLO");
assertEquals(socket.status(), Socket.STATUS.OPEN);
socket.close();
assertEquals(socket.status(), Socket.STATUS.CLOSE);
}
@Test
public void customHeaderTest() throws Exception {
final CountDownLatch l = new CountDownLatch(1);
final AtomicReference<String> ref = new AtomicReference<String>();
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
@Override
public void onRequest(AtmosphereResource r) throws IOException {
ref.set(r.getRequest().getHeader("X-Test"));
l.countDown();
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(1);
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.header("X-Test", "foo")
.uri(targetUrl + "/suspend")
.transport(transport());
Socket socket = client.create(client.newOptionsBuilder().reconnect(false).build());
socket.on(Event.CLOSE.name(), new Function<String>() {
@Override
public void on(String t) {
latch.countDown();
}
}).open(request.build()).fire("PING");
l.await(5, TimeUnit.SECONDS);
server.stop();
latch.await(5, TimeUnit.SECONDS);
assertEquals(ref.get(), "foo");
}
@Test
public void testHeadersOnClose() throws IOException, InterruptedException {
final CountDownLatch l = new CountDownLatch(1);
final CountDownLatch closedByClient = new CountDownLatch(1);
final AtomicReference<String> ref = new AtomicReference<String>();
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
@Override
public void onRequest(AtmosphereResource r) throws IOException {
r.addEventListener(new AtmosphereResourceEventListenerAdapter() {
@Override
public void onSuspend(AtmosphereResourceEvent event) {
l.countDown();
}
}).suspend();
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
if (r.isClosedByClient()) {
ref.set(r.getResource().getRequest().getHeader("X-Test"));
closedByClient.countDown();
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
AtmosphereClient client = ClientFactory.getDefault().newClient(AtmosphereClient.class);
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.enableProtocol(true)
.header("X-Test", "foo")
.transport(transport());
Socket socket = client.create();
socket.open(request.build()).close();
closedByClient.await(10, TimeUnit.SECONDS);
assertEquals(ref.get(), "foo");
}
@Test
public void basicFutureBlockingTest() throws Exception {
final CountDownLatch l = new CountDownLatch(1);
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (!b.getAndSet(true)) {
r.suspend(-1);
} else {
r.getBroadcaster().broadcast(RESUME);
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
if (!r.isResuming() || !r.isCancelled()) {
r.getResource().getResponse().getWriter().print(r.getMessage());
r.getResource().resume();
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicReference<String> response = new AtomicReference<String>();
Client client = ClientFactory.getDefault().newClient();
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(transport());
Socket socket = client.create();
socket.on("message", new Function<String>() {
@Override
public void on(String t) {
logger.info("Function invoked {}", t);
response.set(t);
latch.countDown();
}
}).on(new Function<Throwable>() {
@Override
public void on(Throwable t) {
t.printStackTrace();
latch.countDown();
}
}).open(request.build()).fire("PING").get();
latch.await(5, TimeUnit.SECONDS);
server.stop();
socket.close();
assertEquals(response.get(), RESUME);
}
@Test(enabled = true)
public void serializeFutureGetTest() throws Exception {
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicInteger count = new AtomicInteger(1);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
if (r.getRequest().getMethod().equalsIgnoreCase("GET")) {
r.suspend(-1);
} else {
try {
r.getBroadcaster().broadcast(r.getRequest().getReader().readLine()).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
if (r.getMessage() != null) {
r.getResource().getResponse().write(r.getMessage().toString());
if (r.getResource().transport().equals(AtmosphereResource.TRANSPORT.LONG_POLLING)) {
r.getResource().resume();
}
}
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final CountDownLatch latch = new CountDownLatch(2);
final AtomicReference<StringBuffer> response = new AtomicReference<StringBuffer>(new StringBuffer());
SerializedClient client = ClientFactory.getDefault().newClient(SerializedClient.class);
SerializedOptionsBuilder b = client.newOptionsBuilder();
b.serializedFireStage(new DefaultSerializedFireStage());
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(transport());
Socket socket = client.create(b.build());
socket.on("message", new Function<String>() {
@Override
public void on(String t) {
logger.info("Serialized Function invoked {}", t);
response.get().append(t);
latch.countDown();
}
}).open(request.build())
.fire("PING")
.fire("PONG").get();
latch.await(10, TimeUnit.SECONDS);
socket.close();
assertEquals(response.get().toString(), "PINGPONG");
}
@Test
public void ahcCloseTest() throws IOException, InterruptedException {
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
r.suspend();
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final AsyncHttpClient ahc = new AsyncHttpClient(new AsyncHttpClientConfig.Builder().setMaxRequestRetry(0).build());
AtmosphereClient client = ClientFactory.getDefault().newClient(AtmosphereClient.class);
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(Request.TRANSPORT.WEBSOCKET);
Socket socket = client.create(client.newOptionsBuilder().runtime(ahc, false).build());
socket.open(request.build());
socket.close();
// AHC is async closed
Thread.sleep(1000);
assertTrue(ahc.isClosed());
}
@Test(enabled = true)
public void testCloseWithAtmosphereClient() throws IOException, InterruptedException {
final CountDownLatch l = new CountDownLatch(1);
final CountDownLatch closedLatch = new CountDownLatch(1);
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
@Override
public void onRequest(AtmosphereResource r) throws IOException {
r.addEventListener(new AtmosphereResourceEventListenerAdapter() {
@Override
public void onSuspend(AtmosphereResourceEvent event) {
l.countDown();
}
}).suspend();
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
AtmosphereClient client = ClientFactory.getDefault().newClient(AtmosphereClient.class);
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.enableProtocol(true)
.transport(transport());
Socket socket = client.create();
socket.on(Event.CLOSE.name(), new Function<Object>() {
@Override
public void on(Object o) {
closedLatch.countDown();
}
});
socket.open(request.build());
// Wait until the connection is suspended
assertTrue(l.await(5, TimeUnit.SECONDS));
// Close the connection
socket.close();
// Check if Event.CLOSE was called
assertTrue(closedLatch.await(5, TimeUnit.SECONDS));
}
@Test
public void testOpenWithAtmosphereClientAndProtocol() throws Exception {
final CountDownLatch l = new CountDownLatch(1);
final CountDownLatch openedLatch = new CountDownLatch(1);
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
@Override
public void onRequest(AtmosphereResource r) throws IOException {
r.addEventListener(new AtmosphereResourceEventListenerAdapter() {
@Override
public void onSuspend(AtmosphereResourceEvent event) {
l.countDown();
}
}).suspend();
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
AtmosphereClient client = ClientFactory.getDefault().newClient(AtmosphereClient.class);
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.enableProtocol(true)
.transport(transport());
Socket socket = client.create();
socket.on(Event.OPEN.name(), new Function<Object>() {
@Override
public void on(Object o) {
openedLatch.countDown();
}
});
socket.open(request.build());
// Wait until the connection is suspended
assertTrue(l.await(5, TimeUnit.SECONDS));
// Check if Event.OPEN was called
assertTrue(openedLatch.await(5, TimeUnit.SECONDS));
// Cleanup and close the connection
socket.close();
}
@Test
public void ahcCloseTest2() throws IOException, InterruptedException {
Config config = new Config.Builder()
.port(port)
.host("127.0.0.1")
.resource("/suspend", new AtmosphereHandler() {
private final AtomicBoolean b = new AtomicBoolean(false);
@Override
public void onRequest(AtmosphereResource r) throws IOException {
r.suspend();
}
@Override
public void onStateChange(AtmosphereResourceEvent r) throws IOException {
}
@Override
public void destroy() {
}
}).build();
server = new Nettosphere.Builder().config(config).build();
assertNotNull(server);
server.start();
final AsyncHttpClient ahc = new AsyncHttpClient(new AsyncHttpClientConfig.Builder().setMaxRequestRetry(0).build());
SerializedClient client = ClientFactory.getDefault().newClient(SerializedClient.class);
RequestBuilder request = client.newRequestBuilder()
.method(Request.METHOD.GET)
.uri(targetUrl + "/suspend")
.transport(Request.TRANSPORT.WEBSOCKET);
Socket socket = client.create(client.newOptionsBuilder().runtime(ahc).runtimeShared(false).serializedFireStage(new DefaultSerializedFireStage()).build());
socket.open(request.build());
socket.close();
// AHC is async closed
Thread.sleep(1000);
assertTrue(ahc.isClosed());
}
public final static class EventPOJO {
public final String message;
public final Event e;
public EventPOJO(String message) {
this(null, message);
}
public EventPOJO(Event e, String message) {
this.message = message;
this.e = e;
}
}
}