package org.jooby.internal;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.isA;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.Field;
import java.nio.channels.ClosedChannelException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Queue;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import org.jooby.Err;
import org.jooby.MediaType;
import org.jooby.Mutant;
import org.jooby.Renderer;
import org.jooby.Request;
import org.jooby.WebSocket;
import org.jooby.WebSocket.CloseStatus;
import org.jooby.WebSocket.OnClose;
import org.jooby.WebSocket.OnMessage;
import org.jooby.internal.parser.ParserExecutor;
import org.jooby.spi.NativeWebSocket;
import org.jooby.test.MockUnit;
import org.jooby.test.MockUnit.Block;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
@RunWith(PowerMockRunner.class)
@PrepareForTest({WebSocketImpl.class, WebSocketRendererContext.class })
public class WebSocketImplTest {
private Block connect = unit -> {
WebSocket.OnOpen1 handler = unit.get(WebSocket.OnOpen1.class);
handler.onOpen(eq(unit.get(Request.class)), isA(WebSocketImpl.class));
Injector injector = unit.get(Injector.class);
expect(injector.getInstance(Key.get(new TypeLiteral<Set<Renderer>>() {
}))).andReturn(Collections.emptySet());
};
@SuppressWarnings("unchecked")
private Block callbacks = unit -> {
NativeWebSocket nws = unit.get(NativeWebSocket.class);
nws.onBinaryMessage(isA(Consumer.class));
nws.onTextMessage(isA(Consumer.class));
nws.onErrorMessage(isA(Consumer.class));
nws.onCloseMessage(isA(BiConsumer.class));
};
private Block locale = unit -> {
Request req = unit.get(Request.class);
expect(req.locale()).andReturn(Locale.CANADA);
};
@SuppressWarnings({"resource" })
@Test
public void sendString() throws Exception {
Object data = "String";
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
new MockUnit(WebSocket.OnOpen1.class, WebSocket.SuccessCallback.class,
WebSocket.OnError.class, Injector.class, Request.class, NativeWebSocket.class)
.expect(connect)
.expect(callbacks)
.expect(locale)
.expect(unit -> {
List<Renderer> renderers = Collections.emptyList();
NativeWebSocket ws = unit.get(NativeWebSocket.class);
expect(ws.isOpen()).andReturn(true);
WebSocketRendererContext ctx = unit.mockConstructor(WebSocketRendererContext.class,
new Class[]{List.class, NativeWebSocket.class, MediaType.class, Charset.class,
Locale.class,
WebSocket.SuccessCallback.class,
WebSocket.OnError.class },
renderers, ws,
produces, StandardCharsets.UTF_8,
Locale.CANADA,
unit.get(WebSocket.SuccessCallback.class),
unit.get(WebSocket.OnError.class));
ctx.render(data);
})
.run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
ws.connect(unit.get(Injector.class), unit.get(Request.class),
unit.get(NativeWebSocket.class));
ws.send(data, unit.get(WebSocket.SuccessCallback.class),
unit.get(WebSocket.OnError.class));
});
}
@SuppressWarnings("unchecked")
@Before
@After
public void resetSessions() throws Exception {
Field field = WebSocketImpl.class.getDeclaredField("sessions");
field.setAccessible(true);
Queue<WebSocket> sessions = (Queue<WebSocket>) field.get(null);
sessions.clear();
}
@SuppressWarnings({"resource" })
@Test
public void sendBroadcast() throws Exception {
Object data = "String";
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
new MockUnit(WebSocket.OnOpen1.class, WebSocket.SuccessCallback.class,
WebSocket.OnError.class, Injector.class, Request.class, NativeWebSocket.class)
.expect(connect)
.expect(callbacks)
.expect(locale)
.expect(unit -> {
List<Renderer> renderers = Collections.emptyList();
NativeWebSocket ws = unit.get(NativeWebSocket.class);
expect(ws.isOpen()).andReturn(true);
WebSocketRendererContext ctx = unit.mockConstructor(WebSocketRendererContext.class,
new Class[]{List.class, NativeWebSocket.class, MediaType.class, Charset.class,
Locale.class,
WebSocket.SuccessCallback.class,
WebSocket.OnError.class },
renderers, ws,
produces, StandardCharsets.UTF_8,
Locale.CANADA,
unit.get(WebSocket.SuccessCallback.class),
unit.get(WebSocket.OnError.class));
ctx.render(data);
})
.run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
ws.connect(unit.get(Injector.class), unit.get(Request.class),
unit.get(NativeWebSocket.class));
ws.broadcast(data, unit.get(WebSocket.SuccessCallback.class),
unit.get(WebSocket.OnError.class));
});
}
@SuppressWarnings({"resource" })
@Test
public void sendBroadcastErr() throws Exception {
Object data = "String";
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
new MockUnit(WebSocket.OnOpen1.class, WebSocket.SuccessCallback.class,
WebSocket.OnError.class, Injector.class, Request.class, NativeWebSocket.class)
.expect(connect)
.expect(callbacks)
.expect(locale)
.expect(unit -> {
List<Renderer> renderers = Collections.emptyList();
NativeWebSocket ws = unit.get(NativeWebSocket.class);
expect(ws.isOpen()).andReturn(true);
WebSocketRendererContext ctx = unit.mockConstructor(WebSocketRendererContext.class,
new Class[]{List.class, NativeWebSocket.class, MediaType.class, Charset.class,
Locale.class,
WebSocket.SuccessCallback.class,
WebSocket.OnError.class },
renderers, ws,
produces, StandardCharsets.UTF_8,
Locale.CANADA,
unit.get(WebSocket.SuccessCallback.class),
unit.get(WebSocket.OnError.class));
ctx.render(data);
IllegalStateException x = new IllegalStateException("intentional err");
expectLastCall().andThrow(x);
unit.get(WebSocket.OnError.class).onError(x);
})
.run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
ws.connect(unit.get(Injector.class), unit.get(Request.class),
unit.get(NativeWebSocket.class));
ws.broadcast(data, unit.get(WebSocket.SuccessCallback.class),
unit.get(WebSocket.OnError.class));
});
}
@SuppressWarnings({"resource" })
@Test(expected = Err.class)
public void sendClose() throws Exception {
Object data = "String";
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
new MockUnit(WebSocket.OnOpen1.class, WebSocket.SuccessCallback.class,
WebSocket.OnError.class, Injector.class, Request.class, NativeWebSocket.class)
.expect(connect)
.expect(callbacks)
.expect(locale)
.expect(unit -> {
NativeWebSocket ws = unit.get(NativeWebSocket.class);
expect(ws.isOpen()).andReturn(false);
})
.run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
ws.connect(unit.get(Injector.class), unit.get(Request.class),
unit.get(NativeWebSocket.class));
ws.send(data, unit.get(WebSocket.SuccessCallback.class),
unit.get(WebSocket.OnError.class));
});
}
@SuppressWarnings("resource")
@Test
public void toStr() throws Exception {
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
new MockUnit(WebSocket.OnOpen1.class)
.run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
assertEquals("WS /\n" +
" pattern: /pattern\n" +
" vars: {}\n" +
" consumes: */*\n" +
" produces: */*\n" +
"", ws.toString());
});
}
@SuppressWarnings({"resource" })
@Test
public void isOpen() throws Exception {
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
new MockUnit(WebSocket.OnOpen1.class, WebSocket.SuccessCallback.class,
WebSocket.OnError.class, Injector.class, Request.class, NativeWebSocket.class)
.expect(connect)
.expect(callbacks)
.expect(locale)
.expect(unit -> {
NativeWebSocket ws = unit.get(NativeWebSocket.class);
expect(ws.isOpen()).andReturn(true);
})
.run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
ws.connect(unit.get(Injector.class), unit.get(Request.class),
unit.get(NativeWebSocket.class));
assertTrue(ws.isOpen());
});
}
@SuppressWarnings("resource")
@Test
public void pauseAndResume() throws Exception {
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
new MockUnit(WebSocket.OnOpen1.class, Injector.class, Request.class, NativeWebSocket.class)
.expect(connect)
.expect(callbacks)
.expect(locale)
.expect(unit -> {
NativeWebSocket channel = unit.get(NativeWebSocket.class);
channel.pause();
channel.resume();
})
.run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
ws.connect(unit.get(Injector.class), unit.get(Request.class),
unit.get(NativeWebSocket.class));
ws.pause();
ws.pause();
ws.resume();
ws.resume();
});
}
@Test
public void close() throws Exception {
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
new MockUnit(WebSocket.OnOpen1.class, Injector.class, Request.class, NativeWebSocket.class)
.expect(connect)
.expect(callbacks)
.expect(locale)
.expect(unit -> {
NativeWebSocket ws = unit.get(NativeWebSocket.class);
ws.close(WebSocket.NORMAL.code(), WebSocket.NORMAL.reason());
}).run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
ws.connect(unit.get(Injector.class), unit.get(Request.class),
unit.get(NativeWebSocket.class));
ws.close(WebSocket.NORMAL);
});
}
@SuppressWarnings("resource")
@Test
public void terminate() throws Exception {
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
new MockUnit(WebSocket.OnOpen1.class, Injector.class, Request.class, NativeWebSocket.class)
.expect(connect)
.expect(callbacks)
.expect(locale)
.expect(unit -> {
NativeWebSocket ws = unit.get(NativeWebSocket.class);
ws.terminate();
})
.run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
ws.connect(unit.get(Injector.class), unit.get(Request.class),
unit.get(NativeWebSocket.class));
ws.terminate();
});
}
@SuppressWarnings("resource")
@Test
public void props() throws Exception {
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
new MockUnit(WebSocket.OnOpen1.class)
.run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
assertEquals(pattern, ws.pattern());
assertEquals(path, ws.path());
assertEquals(consumes, ws.consumes());
assertEquals(produces, ws.produces());
});
}
@SuppressWarnings({"resource", "unchecked" })
@Test
public void require() throws Exception {
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
Object instance = new Object();
new MockUnit(WebSocket.OnOpen1.class, Injector.class, Request.class, NativeWebSocket.class)
.expect(connect)
.expect(locale)
.expect(unit -> {
NativeWebSocket nws = unit.get(NativeWebSocket.class);
nws.onBinaryMessage(isA(Consumer.class));
nws.onTextMessage(isA(Consumer.class));
nws.onErrorMessage(isA(Consumer.class));
nws.onCloseMessage(isA(BiConsumer.class));
})
.expect(unit -> {
Injector injector = unit.get(Injector.class);
expect(injector.getInstance(Key.get(Object.class))).andReturn(instance);
})
.run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
ws.connect(unit.get(Injector.class), unit.get(Request.class),
unit.get(NativeWebSocket.class));
assertEquals(instance, ws.require(Object.class));
});
}
@SuppressWarnings({"resource", "unchecked" })
@Test
public void onMessage() throws Exception {
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
new MockUnit(WebSocket.OnOpen1.class, Injector.class, OnMessage.class, Request.class,
NativeWebSocket.class,
Mutant.class)
.expect(connect)
.expect(locale)
.expect(unit -> {
NativeWebSocket nws = unit.get(NativeWebSocket.class);
nws.onBinaryMessage(isA(Consumer.class));
nws.onTextMessage(unit.capture(Consumer.class));
nws.onErrorMessage(isA(Consumer.class));
nws.onCloseMessage(isA(BiConsumer.class));
})
.expect(unit -> {
OnMessage<Mutant> callback = unit.get(OnMessage.class);
callback.onMessage(isA(Mutant.class));
})
.expect(unit -> {
Injector injector = unit.get(Injector.class);
expect(injector.getInstance(ParserExecutor.class)).andReturn(
unit.mock(ParserExecutor.class));
})
.run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
ws.connect(unit.get(Injector.class), unit.get(Request.class),
unit.get(NativeWebSocket.class));
ws.onMessage(unit.get(OnMessage.class));
}, unit -> {
unit.captured(Consumer.class).iterator().next().accept("something");
});
}
@SuppressWarnings({"resource", "unchecked" })
@Test
public void onErr() throws Exception {
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
Exception ex = new Exception();
new MockUnit(WebSocket.OnOpen1.class, Injector.class, Request.class, NativeWebSocket.class,
WebSocket.OnError.class)
.expect(connect)
.expect(locale)
.expect(unit -> {
NativeWebSocket nws = unit.get(NativeWebSocket.class);
nws.onBinaryMessage(isA(Consumer.class));
nws.onTextMessage(isA(Consumer.class));
nws.onErrorMessage(unit.capture(Consumer.class));
nws.onCloseMessage(isA(BiConsumer.class));
expect(nws.isOpen()).andReturn(false);
})
.expect(unit -> {
WebSocket.OnError callback = unit.get(WebSocket.OnError.class);
callback.onError(ex);
})
.run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
ws.connect(unit.get(Injector.class), unit.get(Request.class),
unit.get(NativeWebSocket.class));
ws.onError(unit.get(WebSocket.OnError.class));
}, unit -> {
unit.captured(Consumer.class).iterator().next().accept(ex);
});
}
@SuppressWarnings({"resource", "unchecked" })
@Test
public void onSilentErr() throws Exception {
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
Exception ex = new ClosedChannelException();
new MockUnit(WebSocket.OnOpen1.class, Injector.class, Request.class, NativeWebSocket.class,
WebSocket.OnError.class)
.expect(connect)
.expect(locale)
.expect(unit -> {
NativeWebSocket nws = unit.get(NativeWebSocket.class);
nws.onBinaryMessage(isA(Consumer.class));
nws.onTextMessage(isA(Consumer.class));
nws.onErrorMessage(unit.capture(Consumer.class));
nws.onCloseMessage(isA(BiConsumer.class));
expect(nws.isOpen()).andReturn(false);
})
.run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
ws.connect(unit.get(Injector.class), unit.get(Request.class),
unit.get(NativeWebSocket.class));
ws.onError(unit.get(WebSocket.OnError.class));
}, unit -> {
unit.captured(Consumer.class).iterator().next().accept(ex);
});
}
@SuppressWarnings({"resource", "unchecked" })
@Test
public void onErrAndWsOpen() throws Exception {
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
Exception ex = new Exception();
new MockUnit(WebSocket.OnOpen1.class, Injector.class, Request.class, NativeWebSocket.class,
WebSocket.OnError.class)
.expect(connect)
.expect(locale)
.expect(unit -> {
NativeWebSocket nws = unit.get(NativeWebSocket.class);
nws.onBinaryMessage(isA(Consumer.class));
nws.onTextMessage(isA(Consumer.class));
nws.onErrorMessage(unit.capture(Consumer.class));
nws.onCloseMessage(isA(BiConsumer.class));
expect(nws.isOpen()).andReturn(true);
nws.close(1011, "Server error");
})
.expect(unit -> {
WebSocket.OnError callback = unit.get(WebSocket.OnError.class);
callback.onError(ex);
})
.run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
ws.connect(unit.get(Injector.class), unit.get(Request.class),
unit.get(NativeWebSocket.class));
ws.onError(unit.get(WebSocket.OnError.class));
}, unit -> {
unit.captured(Consumer.class).iterator().next().accept(ex);
});
}
@SuppressWarnings({"resource", "unchecked" })
@Test
public void onClose() throws Exception {
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
WebSocket.CloseStatus status = WebSocket.NORMAL;
new MockUnit(WebSocket.OnOpen1.class, OnMessage.class, OnClose.class, Request.class,
NativeWebSocket.class, Injector.class)
.expect(connect)
.expect(locale)
.expect(unit -> {
NativeWebSocket nws = unit.get(NativeWebSocket.class);
nws.onBinaryMessage(isA(Consumer.class));
nws.onTextMessage(isA(Consumer.class));
nws.onErrorMessage(isA(Consumer.class));
nws.onCloseMessage(unit.capture(BiConsumer.class));
})
.expect(unit -> {
OnClose callback = unit.get(OnClose.class);
callback.onClose(unit.capture(WebSocket.CloseStatus.class));
})
.run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
ws.connect(unit.get(Injector.class), unit.get(Request.class),
unit.get(NativeWebSocket.class));
ws.onClose(unit.get(WebSocket.OnClose.class));
}, unit -> {
unit.captured(BiConsumer.class).iterator().next()
.accept(status.code(), Optional.of(status.reason()));
}, unit -> {
CloseStatus captured = unit.captured(WebSocket.CloseStatus.class).iterator().next();
assertEquals(status.code(), captured.code());
assertEquals(status.reason(), captured.reason());
});
}
@SuppressWarnings({"resource", "unchecked" })
@Test
public void onCloseNullReason() throws Exception {
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
WebSocket.CloseStatus status = WebSocket.CloseStatus.of(1000);
new MockUnit(WebSocket.OnOpen1.class, OnMessage.class, OnClose.class, NativeWebSocket.class,
Request.class, Injector.class)
.expect(connect)
.expect(locale)
.expect(unit -> {
NativeWebSocket nws = unit.get(NativeWebSocket.class);
nws.onBinaryMessage(isA(Consumer.class));
nws.onTextMessage(isA(Consumer.class));
nws.onErrorMessage(isA(Consumer.class));
nws.onCloseMessage(unit.capture(BiConsumer.class));
})
.expect(unit -> {
OnClose callback = unit.get(OnClose.class);
callback.onClose(unit.capture(WebSocket.CloseStatus.class));
})
.run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
ws.connect(unit.get(Injector.class), unit.get(Request.class),
unit.get(NativeWebSocket.class));
ws.onClose(unit.get(OnClose.class));
}, unit -> {
unit.captured(BiConsumer.class).iterator().next()
.accept(status.code(), Optional.empty());
}, unit -> {
CloseStatus captured = unit.captured(WebSocket.CloseStatus.class).iterator().next();
assertEquals(status.code(), captured.code());
assertEquals(null, captured.reason());
});
}
@SuppressWarnings({"resource", "unchecked" })
@Test
public void onCloseEmptyReason() throws Exception {
String path = "/";
String pattern = "/pattern";
Map<Object, String> vars = new HashMap<>();
MediaType consumes = MediaType.all;
MediaType produces = MediaType.all;
WebSocket.CloseStatus status = WebSocket.CloseStatus.of(1000, "");
new MockUnit(WebSocket.OnOpen1.class, OnMessage.class, NativeWebSocket.class, Request.class,
Injector.class, OnClose.class)
.expect(connect)
.expect(locale)
.expect(unit -> {
NativeWebSocket nws = unit.get(NativeWebSocket.class);
nws.onBinaryMessage(isA(Consumer.class));
nws.onTextMessage(isA(Consumer.class));
nws.onErrorMessage(isA(Consumer.class));
nws.onCloseMessage(unit.capture(BiConsumer.class));
})
.expect(unit -> {
OnClose callback = unit.get(OnClose.class);
callback.onClose(unit.capture(WebSocket.CloseStatus.class));
})
.run(unit -> {
WebSocketImpl ws = new WebSocketImpl(
unit.get(WebSocket.OnOpen1.class), path, pattern, vars, consumes, produces);
ws.connect(unit.get(Injector.class), unit.get(Request.class),
unit.get(NativeWebSocket.class));
ws.onClose(unit.get(OnClose.class));
}, unit -> {
unit.captured(BiConsumer.class).iterator().next()
.accept(status.code(), Optional.of(""));
}, unit -> {
CloseStatus captured = unit.captured(WebSocket.CloseStatus.class).iterator().next();
assertEquals(status.code(), captured.code());
assertEquals(null, captured.reason());
});
}
}