package org.jooby.internal.undertow; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; import static org.junit.Assert.assertEquals; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Optional; import java.util.concurrent.CountDownLatch; import org.jooby.test.MockUnit; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import io.undertow.io.IoCallback; import io.undertow.io.Sender; import io.undertow.server.HttpServerExchange; import io.undertow.util.HeaderMap; import io.undertow.util.Headers; @RunWith(PowerMockRunner.class) @PrepareForTest({UndertowSse.class, HttpServerExchange.class, HeaderMap.class }) public class UndertowSseTest { @Test public void defaults() throws Exception { new MockUnit(HttpServerExchange.class) .run(unit -> { new UndertowSse(unit.get(HttpServerExchange.class)); }); } @Test public void close() throws Exception { new MockUnit(HttpServerExchange.class) .expect(unit -> { HttpServerExchange exchange = unit.get(HttpServerExchange.class); expect(exchange.endExchange()).andReturn(exchange); }) .run(unit -> { new UndertowSse(unit.get(HttpServerExchange.class)).close(); }); } @Test public void handshake() throws Exception { new MockUnit(HttpServerExchange.class, Runnable.class, HeaderMap.class) .expect(unit -> { HeaderMap headers = unit.get(HeaderMap.class); expect(headers.put(Headers.CONNECTION, "Close")).andReturn(headers); expect(headers.put(Headers.CONTENT_TYPE, "text/event-stream; charset=utf-8")) .andReturn(headers); HttpServerExchange exchange = unit.get(HttpServerExchange.class); expect(exchange.getResponseHeaders()).andReturn(headers); expect(exchange.setStatusCode(200)).andReturn(exchange); expect(exchange.setPersistent(false)).andReturn(exchange); expect(exchange.dispatch(unit.get(Runnable.class))).andReturn(exchange); }) .run(unit -> { new UndertowSse(unit.get(HttpServerExchange.class)) .handshake(unit.get(Runnable.class)); }); } @Test public void send() throws Exception { byte[] bytes = {0 }; CountDownLatch latch = new CountDownLatch(1); new MockUnit(HttpServerExchange.class, Sender.class) .expect(unit -> { Sender sender = unit.get(Sender.class); sender.send(eq(ByteBuffer.wrap(bytes)), unit.capture(IoCallback.class)); HttpServerExchange exchange = unit.get(HttpServerExchange.class); expect(exchange.getResponseSender()).andReturn(sender); }) .run(unit -> { new UndertowSse(unit.get(HttpServerExchange.class)) .send(Optional.of("id"), bytes).future().onSuccess(id -> { assertEquals("id", id.get()); latch.countDown(); }); }, unit -> { IoCallback callback = unit.captured(IoCallback.class).iterator().next(); callback.onComplete(unit.get(HttpServerExchange.class), unit.get(Sender.class)); latch.await(); }); } @Test(expected = IllegalStateException.class) public void sendError() throws Exception { byte[] bytes = {0 }; new MockUnit(HttpServerExchange.class) .expect(unit -> { HttpServerExchange exchange = unit.get(HttpServerExchange.class); expect(exchange.getResponseSender()) .andThrow(new IllegalStateException("intentional err")); }) .run(unit -> { new UndertowSse(unit.get(HttpServerExchange.class)) .send(Optional.of("id"), bytes); }); } @Test public void sendFailure() throws Exception { byte[] bytes = {0 }; IOException ex = new IOException("intentional err"); CountDownLatch latch = new CountDownLatch(1); new MockUnit(HttpServerExchange.class, Sender.class) .expect(unit -> { Sender sender = unit.get(Sender.class); sender.send(eq(ByteBuffer.wrap(bytes)), unit.capture(IoCallback.class)); HttpServerExchange exchange = unit.get(HttpServerExchange.class); expect(exchange.getResponseSender()).andReturn(sender); }) .run(unit -> { new UndertowSse(unit.get(HttpServerExchange.class)) .send(Optional.of("id"), bytes).future().onFailure(cause -> { assertEquals(ex, cause); latch.countDown(); }); }, unit -> { IoCallback callback = unit.captured(IoCallback.class).iterator().next(); callback.onException(unit.get(HttpServerExchange.class), unit.get(Sender.class), ex); latch.await(); }); } }