|
|
|
@ -32,103 +32,74 @@ import org.springframework.web.socket.WebSocketSession; |
|
|
|
import static org.junit.Assert.*; |
|
|
|
import static org.junit.Assert.*; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Unit tests for |
|
|
|
* Unit tests for {@link ConcurrentWebSocketSessionDecorator}. |
|
|
|
* {@link org.springframework.web.socket.handler.ConcurrentWebSocketSessionDecorator}. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @author Rossen Stoyanchev |
|
|
|
* @author Rossen Stoyanchev |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@SuppressWarnings("resource") |
|
|
|
@SuppressWarnings("resource") |
|
|
|
public class ConcurrentWebSocketSessionDecoratorTests { |
|
|
|
public class ConcurrentWebSocketSessionDecoratorTests { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void send() throws IOException { |
|
|
|
public void send() throws IOException { |
|
|
|
|
|
|
|
|
|
|
|
TestWebSocketSession session = new TestWebSocketSession(); |
|
|
|
TestWebSocketSession session = new TestWebSocketSession(); |
|
|
|
session.setOpen(true); |
|
|
|
session.setOpen(true); |
|
|
|
|
|
|
|
|
|
|
|
ConcurrentWebSocketSessionDecorator concurrentSession = |
|
|
|
ConcurrentWebSocketSessionDecorator decorator = |
|
|
|
new ConcurrentWebSocketSessionDecorator(session, 1000, 1024); |
|
|
|
new ConcurrentWebSocketSessionDecorator(session, 1000, 1024); |
|
|
|
|
|
|
|
|
|
|
|
TextMessage textMessage = new TextMessage("payload"); |
|
|
|
TextMessage textMessage = new TextMessage("payload"); |
|
|
|
concurrentSession.sendMessage(textMessage); |
|
|
|
decorator.sendMessage(textMessage); |
|
|
|
|
|
|
|
|
|
|
|
assertEquals(1, session.getSentMessages().size()); |
|
|
|
assertEquals(1, session.getSentMessages().size()); |
|
|
|
assertEquals(textMessage, session.getSentMessages().get(0)); |
|
|
|
assertEquals(textMessage, session.getSentMessages().get(0)); |
|
|
|
|
|
|
|
|
|
|
|
assertEquals(0, concurrentSession.getBufferSize()); |
|
|
|
assertEquals(0, decorator.getBufferSize()); |
|
|
|
assertEquals(0, concurrentSession.getTimeSinceSendStarted()); |
|
|
|
assertEquals(0, decorator.getTimeSinceSendStarted()); |
|
|
|
assertTrue(session.isOpen()); |
|
|
|
assertTrue(session.isOpen()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void sendAfterBlockedSend() throws IOException, InterruptedException { |
|
|
|
public void sendAfterBlockedSend() throws IOException, InterruptedException { |
|
|
|
|
|
|
|
|
|
|
|
BlockingSession blockingSession = new BlockingSession(); |
|
|
|
BlockingSession session = new BlockingSession(); |
|
|
|
blockingSession.setOpen(true); |
|
|
|
session.setOpen(true); |
|
|
|
CountDownLatch sentMessageLatch = blockingSession.getSentMessageLatch(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final ConcurrentWebSocketSessionDecorator concurrentSession = |
|
|
|
final ConcurrentWebSocketSessionDecorator decorator = |
|
|
|
new ConcurrentWebSocketSessionDecorator(blockingSession, 10 * 1000, 1024); |
|
|
|
new ConcurrentWebSocketSessionDecorator(session, 10 * 1000, 1024); |
|
|
|
|
|
|
|
|
|
|
|
Executors.newSingleThreadExecutor().submit((Runnable) () -> { |
|
|
|
sendBlockingMessage(decorator); |
|
|
|
TextMessage message = new TextMessage("slow message"); |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
concurrentSession.sendMessage(message); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (IOException e) { |
|
|
|
|
|
|
|
e.printStackTrace(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assertTrue(sentMessageLatch.await(5, TimeUnit.SECONDS)); |
|
|
|
Thread.sleep(50); |
|
|
|
|
|
|
|
assertTrue(decorator.getTimeSinceSendStarted() > 0); |
|
|
|
// ensure some send time elapses
|
|
|
|
|
|
|
|
Thread.sleep(100); |
|
|
|
|
|
|
|
assertTrue(concurrentSession.getTimeSinceSendStarted() > 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TextMessage payload = new TextMessage("payload"); |
|
|
|
TextMessage payload = new TextMessage("payload"); |
|
|
|
for (int i = 0; i < 5; i++) { |
|
|
|
for (int i = 0; i < 5; i++) { |
|
|
|
concurrentSession.sendMessage(payload); |
|
|
|
decorator.sendMessage(payload); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
assertTrue(concurrentSession.getTimeSinceSendStarted() > 0); |
|
|
|
assertTrue(decorator.getTimeSinceSendStarted() > 0); |
|
|
|
assertEquals(5 * payload.getPayloadLength(), concurrentSession.getBufferSize()); |
|
|
|
assertEquals(5 * payload.getPayloadLength(), decorator.getBufferSize()); |
|
|
|
assertTrue(blockingSession.isOpen()); |
|
|
|
assertTrue(session.isOpen()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void sendTimeLimitExceeded() throws IOException, InterruptedException { |
|
|
|
public void sendTimeLimitExceeded() throws IOException, InterruptedException { |
|
|
|
|
|
|
|
|
|
|
|
BlockingSession blockingSession = new BlockingSession(); |
|
|
|
BlockingSession session = new BlockingSession(); |
|
|
|
blockingSession.setId("123"); |
|
|
|
session.setId("123"); |
|
|
|
blockingSession.setOpen(true); |
|
|
|
session.setOpen(true); |
|
|
|
CountDownLatch sentMessageLatch = blockingSession.getSentMessageLatch(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sendTimeLimit = 100; |
|
|
|
|
|
|
|
int bufferSizeLimit = 1024; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final ConcurrentWebSocketSessionDecorator concurrentSession = |
|
|
|
final ConcurrentWebSocketSessionDecorator decorator = |
|
|
|
new ConcurrentWebSocketSessionDecorator(blockingSession, sendTimeLimit, bufferSizeLimit); |
|
|
|
new ConcurrentWebSocketSessionDecorator(session, 100, 1024); |
|
|
|
|
|
|
|
|
|
|
|
Executors.newSingleThreadExecutor().submit((Runnable) () -> { |
|
|
|
sendBlockingMessage(decorator); |
|
|
|
TextMessage message = new TextMessage("slow message"); |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
concurrentSession.sendMessage(message); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (IOException e) { |
|
|
|
|
|
|
|
e.printStackTrace(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assertTrue(sentMessageLatch.await(5, TimeUnit.SECONDS)); |
|
|
|
// Exceed send time..
|
|
|
|
|
|
|
|
Thread.sleep(200); |
|
|
|
// ensure some send time elapses
|
|
|
|
|
|
|
|
Thread.sleep(sendTimeLimit + 100); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
|
TextMessage payload = new TextMessage("payload"); |
|
|
|
TextMessage payload = new TextMessage("payload"); |
|
|
|
concurrentSession.sendMessage(payload); |
|
|
|
decorator.sendMessage(payload); |
|
|
|
fail("Expected exception"); |
|
|
|
fail("Expected exception"); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (SessionLimitExceededException ex) { |
|
|
|
catch (SessionLimitExceededException ex) { |
|
|
|
@ -142,28 +113,14 @@ public class ConcurrentWebSocketSessionDecoratorTests { |
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void sendBufferSizeExceeded() throws IOException, InterruptedException { |
|
|
|
public void sendBufferSizeExceeded() throws IOException, InterruptedException { |
|
|
|
|
|
|
|
|
|
|
|
BlockingSession blockingSession = new BlockingSession(); |
|
|
|
BlockingSession session = new BlockingSession(); |
|
|
|
blockingSession.setId("123"); |
|
|
|
session.setId("123"); |
|
|
|
blockingSession.setOpen(true); |
|
|
|
session.setOpen(true); |
|
|
|
CountDownLatch sentMessageLatch = blockingSession.getSentMessageLatch(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sendTimeLimit = 10 * 1000; |
|
|
|
|
|
|
|
int bufferSizeLimit = 1024; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final ConcurrentWebSocketSessionDecorator concurrentSession = |
|
|
|
|
|
|
|
new ConcurrentWebSocketSessionDecorator(blockingSession, sendTimeLimit, bufferSizeLimit); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Executors.newSingleThreadExecutor().submit((Runnable) () -> { |
|
|
|
final ConcurrentWebSocketSessionDecorator decorator = |
|
|
|
TextMessage message = new TextMessage("slow message"); |
|
|
|
new ConcurrentWebSocketSessionDecorator(session, 10*1000, 1024); |
|
|
|
try { |
|
|
|
|
|
|
|
concurrentSession.sendMessage(message); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (IOException e) { |
|
|
|
|
|
|
|
e.printStackTrace(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assertTrue(sentMessageLatch.await(5, TimeUnit.SECONDS)); |
|
|
|
sendBlockingMessage(decorator); |
|
|
|
|
|
|
|
|
|
|
|
StringBuilder sb = new StringBuilder(); |
|
|
|
StringBuilder sb = new StringBuilder(); |
|
|
|
for (int i = 0 ; i < 1023; i++) { |
|
|
|
for (int i = 0 ; i < 1023; i++) { |
|
|
|
@ -171,13 +128,13 @@ public class ConcurrentWebSocketSessionDecoratorTests { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
TextMessage message = new TextMessage(sb.toString()); |
|
|
|
TextMessage message = new TextMessage(sb.toString()); |
|
|
|
concurrentSession.sendMessage(message); |
|
|
|
decorator.sendMessage(message); |
|
|
|
|
|
|
|
|
|
|
|
assertEquals(1023, concurrentSession.getBufferSize()); |
|
|
|
assertEquals(1023, decorator.getBufferSize()); |
|
|
|
assertTrue(blockingSession.isOpen()); |
|
|
|
assertTrue(session.isOpen()); |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
|
concurrentSession.sendMessage(message); |
|
|
|
decorator.sendMessage(message); |
|
|
|
fail("Expected exception"); |
|
|
|
fail("Expected exception"); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (SessionLimitExceededException ex) { |
|
|
|
catch (SessionLimitExceededException ex) { |
|
|
|
@ -191,35 +148,35 @@ public class ConcurrentWebSocketSessionDecoratorTests { |
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void closeStatusNormal() throws Exception { |
|
|
|
public void closeStatusNormal() throws Exception { |
|
|
|
|
|
|
|
|
|
|
|
BlockingSession delegate = new BlockingSession(); |
|
|
|
BlockingSession session = new BlockingSession(); |
|
|
|
delegate.setOpen(true); |
|
|
|
session.setOpen(true); |
|
|
|
WebSocketSession decorator = new ConcurrentWebSocketSessionDecorator(delegate, 10 * 1000, 1024); |
|
|
|
WebSocketSession decorator = new ConcurrentWebSocketSessionDecorator(session, 10 * 1000, 1024); |
|
|
|
|
|
|
|
|
|
|
|
decorator.close(CloseStatus.PROTOCOL_ERROR); |
|
|
|
decorator.close(CloseStatus.PROTOCOL_ERROR); |
|
|
|
assertEquals(CloseStatus.PROTOCOL_ERROR, delegate.getCloseStatus()); |
|
|
|
assertEquals(CloseStatus.PROTOCOL_ERROR, session.getCloseStatus()); |
|
|
|
|
|
|
|
|
|
|
|
decorator.close(CloseStatus.SERVER_ERROR); |
|
|
|
decorator.close(CloseStatus.SERVER_ERROR); |
|
|
|
assertEquals("Should have been ignored", CloseStatus.PROTOCOL_ERROR, delegate.getCloseStatus()); |
|
|
|
assertEquals("Should have been ignored", CloseStatus.PROTOCOL_ERROR, session.getCloseStatus()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void closeStatusChangesToSessionNotReliable() throws Exception { |
|
|
|
public void closeStatusChangesToSessionNotReliable() throws Exception { |
|
|
|
|
|
|
|
|
|
|
|
BlockingSession blockingSession = new BlockingSession(); |
|
|
|
BlockingSession session = new BlockingSession(); |
|
|
|
blockingSession.setId("123"); |
|
|
|
session.setId("123"); |
|
|
|
blockingSession.setOpen(true); |
|
|
|
session.setOpen(true); |
|
|
|
CountDownLatch sentMessageLatch = blockingSession.getSentMessageLatch(); |
|
|
|
CountDownLatch sentMessageLatch = session.getSentMessageLatch(); |
|
|
|
|
|
|
|
|
|
|
|
int sendTimeLimit = 100; |
|
|
|
int sendTimeLimit = 100; |
|
|
|
int bufferSizeLimit = 1024; |
|
|
|
int bufferSizeLimit = 1024; |
|
|
|
|
|
|
|
|
|
|
|
final ConcurrentWebSocketSessionDecorator concurrentSession = |
|
|
|
final ConcurrentWebSocketSessionDecorator decorator = |
|
|
|
new ConcurrentWebSocketSessionDecorator(blockingSession, sendTimeLimit, bufferSizeLimit); |
|
|
|
new ConcurrentWebSocketSessionDecorator(session, sendTimeLimit, bufferSizeLimit); |
|
|
|
|
|
|
|
|
|
|
|
Executors.newSingleThreadExecutor().submit((Runnable) () -> { |
|
|
|
Executors.newSingleThreadExecutor().submit((Runnable) () -> { |
|
|
|
TextMessage message = new TextMessage("slow message"); |
|
|
|
TextMessage message = new TextMessage("slow message"); |
|
|
|
try { |
|
|
|
try { |
|
|
|
concurrentSession.sendMessage(message); |
|
|
|
decorator.sendMessage(message); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (IOException e) { |
|
|
|
catch (IOException e) { |
|
|
|
e.printStackTrace(); |
|
|
|
e.printStackTrace(); |
|
|
|
@ -231,10 +188,24 @@ public class ConcurrentWebSocketSessionDecoratorTests { |
|
|
|
// ensure some send time elapses
|
|
|
|
// ensure some send time elapses
|
|
|
|
Thread.sleep(sendTimeLimit + 100); |
|
|
|
Thread.sleep(sendTimeLimit + 100); |
|
|
|
|
|
|
|
|
|
|
|
concurrentSession.close(CloseStatus.PROTOCOL_ERROR); |
|
|
|
decorator.close(CloseStatus.PROTOCOL_ERROR); |
|
|
|
|
|
|
|
|
|
|
|
assertEquals("CloseStatus should have changed to SESSION_NOT_RELIABLE", |
|
|
|
assertEquals("CloseStatus should have changed to SESSION_NOT_RELIABLE", |
|
|
|
CloseStatus.SESSION_NOT_RELIABLE, blockingSession.getCloseStatus()); |
|
|
|
CloseStatus.SESSION_NOT_RELIABLE, session.getCloseStatus()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void sendBlockingMessage(ConcurrentWebSocketSessionDecorator session) throws InterruptedException { |
|
|
|
|
|
|
|
Executors.newSingleThreadExecutor().submit(() -> { |
|
|
|
|
|
|
|
TextMessage message = new TextMessage("slow message"); |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
session.sendMessage(message); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (IOException e) { |
|
|
|
|
|
|
|
e.printStackTrace(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
BlockingSession delegate = (BlockingSession) session.getDelegate(); |
|
|
|
|
|
|
|
assertTrue(delegate.getSentMessageLatch().await(5, TimeUnit.SECONDS)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|