Skip to content

Commit 39ff1e2

Browse files
committed
Add StompProtocolHandler tests
1 parent 364bc35 commit 39ff1e2

File tree

7 files changed

+268
-38
lines changed

7 files changed

+268
-38
lines changed

spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompProtocolHandler.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.springframework.messaging.handler.websocket.SubProtocolHandler;
3131
import org.springframework.messaging.simp.SimpMessageType;
3232
import org.springframework.messaging.simp.handler.MutableUserQueueSuffixResolver;
33+
import org.springframework.messaging.simp.handler.SimpleUserQueueSuffixResolver;
3334
import org.springframework.messaging.support.MessageBuilder;
3435
import org.springframework.util.Assert;
3536
import org.springframework.web.socket.CloseStatus;
@@ -64,7 +65,7 @@ public class StompProtocolHandler implements SubProtocolHandler {
6465

6566
private final StompMessageConverter stompMessageConverter = new StompMessageConverter();
6667

67-
private MutableUserQueueSuffixResolver queueSuffixResolver;
68+
private MutableUserQueueSuffixResolver queueSuffixResolver = new SimpleUserQueueSuffixResolver();
6869

6970

7071
/**

spring-messaging/src/test/java/org/springframework/messaging/simp/config/WebSocketMessageBrokerConfigurationTests.java

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,12 @@
2727
import org.springframework.beans.factory.annotation.Autowired;
2828
import org.springframework.context.annotation.Bean;
2929
import org.springframework.context.annotation.Configuration;
30-
import org.springframework.messaging.Message;
3130
import org.springframework.messaging.SubscribableChannel;
3231
import org.springframework.messaging.handler.annotation.MessageMapping;
3332
import org.springframework.messaging.simp.AbstractWebSocketIntegrationTests;
3433
import org.springframework.messaging.simp.JettyTestServer;
3534
import org.springframework.messaging.simp.stomp.StompCommand;
36-
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
37-
import org.springframework.messaging.simp.stomp.StompMessageConverter;
38-
import org.springframework.messaging.support.MessageBuilder;
35+
import org.springframework.messaging.simp.stomp.StompTextMessageBuilder;
3936
import org.springframework.messaging.support.channel.ExecutorSubscribableChannel;
4037
import org.springframework.stereotype.Controller;
4138
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
@@ -76,16 +73,13 @@ public void sendMessage() throws Exception {
7673
this.server.init(cxt);
7774
this.server.start();
7875

79-
StompHeaderAccessor headers = StompHeaderAccessor.create(StompCommand.SEND);
80-
headers.setDestination("/app/foo");
81-
Message<byte[]> message = MessageBuilder.withPayloadAndHeaders(new byte[0], headers).build();
82-
byte[] bytes = new StompMessageConverter().fromMessage(message);
83-
final TextMessage webSocketMessage = new TextMessage(new String(bytes));
76+
final TextMessage textMessage = StompTextMessageBuilder.create(StompCommand.SEND)
77+
.headers("destination:/app/foo").build();
8478

8579
WebSocketHandler clientHandler = new TextWebSocketHandlerAdapter() {
8680
@Override
8781
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
88-
session.sendMessage(webSocketMessage);
82+
session.sendMessage(textMessage);
8983
}
9084
};
9185

spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompMessageConverterTests.java

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.springframework.messaging.MessageHeaders;
2525
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
2626
import org.springframework.messaging.simp.SimpMessageType;
27+
import org.springframework.web.socket.TextMessage;
2728

2829
import static org.junit.Assert.*;
2930

@@ -41,14 +42,17 @@ public void setup() {
4142
this.converter = new StompMessageConverter();
4243
}
4344

44-
@SuppressWarnings("unchecked")
4545
@Test
4646
public void connectFrame() throws Exception {
4747

48-
String accept = "accept-version:1.1\n";
49-
String host = "host:github.org\n";
50-
String frame = "\n\n\nCONNECT\n" + accept + host + "\n";
51-
Message<byte[]> message = (Message<byte[]>) this.converter.toMessage(frame.getBytes("UTF-8"));
48+
String accept = "accept-version:1.1";
49+
String host = "host:github.org";
50+
51+
TextMessage textMessage = StompTextMessageBuilder.create(StompCommand.CONNECT)
52+
.headers(accept, host).build();
53+
54+
@SuppressWarnings("unchecked")
55+
Message<byte[]> message = (Message<byte[]>) this.converter.toMessage(textMessage.getPayload());
5256

5357
assertEquals(0, message.getPayload().length);
5458

@@ -80,11 +84,14 @@ public void connectFrame() throws Exception {
8084
@Test
8185
public void connectWithEscapes() throws Exception {
8286

83-
String accept = "accept-version:1.1\n";
84-
String host = "ho\\c\\ns\\rt:st\\nomp.gi\\cthu\\b.org\n";
85-
String frame = "CONNECT\n" + accept + host + "\n";
87+
String accept = "accept-version:1.1";
88+
String host = "ho\\c\\ns\\rt:st\\nomp.gi\\cthu\\b.org";
89+
90+
TextMessage textMessage = StompTextMessageBuilder.create(StompCommand.CONNECT)
91+
.headers(accept, host).build();
92+
8693
@SuppressWarnings("unchecked")
87-
Message<byte[]> message = (Message<byte[]>) this.converter.toMessage(frame.getBytes("UTF-8"));
94+
Message<byte[]> message = (Message<byte[]>) this.converter.toMessage(textMessage.getPayload());
8895

8996
assertEquals(0, message.getPayload().length);
9097

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright 2002-2013 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.messaging.simp.stomp;
18+
19+
import java.util.Arrays;
20+
import java.util.HashSet;
21+
22+
import org.junit.Before;
23+
import org.junit.Test;
24+
import org.mockito.ArgumentCaptor;
25+
import org.mockito.Mockito;
26+
import org.springframework.messaging.Message;
27+
import org.springframework.messaging.MessageChannel;
28+
import org.springframework.web.socket.TextMessage;
29+
import org.springframework.web.socket.support.TestPrincipal;
30+
import org.springframework.web.socket.support.TestWebSocketSession;
31+
32+
import static org.junit.Assert.*;
33+
import static org.mockito.Mockito.*;
34+
35+
/**
36+
* Test fixture for {@link StompProtocolHandler} tests.
37+
*
38+
* @author Rossen Stoyanchev
39+
*/
40+
public class StompProtocolHandlerTests {
41+
42+
private StompProtocolHandler stompHandler;
43+
44+
private TestWebSocketSession session;
45+
46+
private MessageChannel channel;
47+
48+
private ArgumentCaptor<Message> messageCaptor;
49+
50+
51+
@Before
52+
public void setup() {
53+
this.stompHandler = new StompProtocolHandler();
54+
this.channel = Mockito.mock(MessageChannel.class);
55+
this.messageCaptor = ArgumentCaptor.forClass(Message.class);
56+
57+
this.session = new TestWebSocketSession();
58+
this.session.setId("s1");
59+
this.session.setPrincipal(new TestPrincipal("joe"));
60+
}
61+
62+
@Test
63+
public void handleConnect() {
64+
65+
TextMessage textMessage = StompTextMessageBuilder.create(StompCommand.CONNECT).headers(
66+
"login:guest", "passcode:guest", "accept-version:1.1,1.0", "heart-beat:10000,10000").build();
67+
68+
this.stompHandler.handleMessageFromClient(this.session, textMessage, this.channel);
69+
70+
verify(this.channel).send(this.messageCaptor.capture());
71+
Message<?> actual = this.messageCaptor.getValue();
72+
assertNotNull(actual);
73+
74+
StompHeaderAccessor headers = StompHeaderAccessor.wrap(actual);
75+
assertEquals(StompCommand.CONNECT, headers.getCommand());
76+
assertEquals("s1", headers.getSessionId());
77+
assertEquals("joe", headers.getUser().getName());
78+
assertEquals("guest", headers.getLogin());
79+
assertEquals("PROTECTED", headers.getPasscode());
80+
assertArrayEquals(new long[] {10000, 10000}, headers.getHeartbeat());
81+
assertEquals(new HashSet<>(Arrays.asList("1.1","1.0")), headers.getAcceptVersion());
82+
83+
// Check CONNECTED reply
84+
85+
assertEquals(1, this.session.getSentMessages().size());
86+
textMessage = (TextMessage) this.session.getSentMessages().get(0);
87+
Message<?> message = new StompMessageConverter().toMessage(textMessage.getPayload());
88+
StompHeaderAccessor replyHeaders = StompHeaderAccessor.wrap(message);
89+
90+
assertEquals(StompCommand.CONNECTED, replyHeaders.getCommand());
91+
assertEquals("1.1", replyHeaders.getVersion());
92+
assertArrayEquals(new long[] {0, 0}, replyHeaders.getHeartbeat());
93+
assertEquals("joe", replyHeaders.getNativeHeader("user-name").get(0));
94+
assertEquals("s1", replyHeaders.getNativeHeader("queue-suffix").get(0));
95+
}
96+
97+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright 2002-2013 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.messaging.simp.stomp;
18+
19+
import java.util.ArrayList;
20+
import java.util.Arrays;
21+
import java.util.List;
22+
23+
import org.springframework.web.socket.TextMessage;
24+
25+
26+
/**
27+
* A builder for creating WebSocket messages with STOMP frame content.
28+
*
29+
* @author Rossen Stoyanchev
30+
*/
31+
public class StompTextMessageBuilder {
32+
33+
private StompCommand command;
34+
35+
private final List<String> headerLines = new ArrayList<String>();
36+
37+
private String body;
38+
39+
40+
private StompTextMessageBuilder(StompCommand command) {
41+
this.command = command;
42+
}
43+
44+
public static StompTextMessageBuilder create(StompCommand command) {
45+
return new StompTextMessageBuilder(command);
46+
}
47+
48+
public StompTextMessageBuilder headers(String... headerLines) {
49+
this.headerLines.addAll(Arrays.asList(headerLines));
50+
return this;
51+
}
52+
53+
public StompTextMessageBuilder body(String body) {
54+
this.body = body;
55+
return this;
56+
}
57+
58+
public TextMessage build() {
59+
StringBuilder sb = new StringBuilder(this.command.name()).append("\n");
60+
for (String line : this.headerLines) {
61+
sb.append(line).append("\n");
62+
}
63+
sb.append("\n");
64+
if (this.body != null) {
65+
sb.append(this.body);
66+
}
67+
sb.append("\u0000");
68+
return new TextMessage(sb.toString());
69+
}
70+
71+
}

spring-websocket/src/test/java/org/springframework/web/socket/server/config/WebSocketConfigurationTests.java

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,26 @@
1717
package org.springframework.web.socket.server.config;
1818

1919
import java.util.Arrays;
20+
import java.util.concurrent.CountDownLatch;
21+
import java.util.concurrent.TimeUnit;
2022

2123
import org.junit.Test;
2224
import org.junit.runner.RunWith;
2325
import org.junit.runners.Parameterized;
2426
import org.junit.runners.Parameterized.Parameters;
25-
import org.mockito.Mockito;
2627
import org.springframework.beans.factory.annotation.Autowired;
2728
import org.springframework.context.annotation.Bean;
2829
import org.springframework.context.annotation.Configuration;
2930
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
3031
import org.springframework.web.socket.AbstractWebSocketIntegrationTests;
3132
import org.springframework.web.socket.JettyTestServer;
32-
import org.springframework.web.socket.WebSocketHandler;
3333
import org.springframework.web.socket.WebSocketSession;
34+
import org.springframework.web.socket.adapter.WebSocketHandlerAdapter;
3435
import org.springframework.web.socket.client.jetty.JettyWebSocketClient;
3536
import org.springframework.web.socket.server.HandshakeHandler;
3637
import org.springframework.web.socket.sockjs.transport.handler.WebSocketTransportHandler;
3738

38-
import static org.mockito.Matchers.*;
39-
import static org.mockito.Mockito.*;
39+
import static org.junit.Assert.*;
4040

4141

4242
/**
@@ -63,13 +63,10 @@ public void registerWebSocketHandler() throws Exception {
6363
this.server.init(cxt);
6464
this.server.start();
6565

66-
WebSocketHandler clientHandler = Mockito.mock(WebSocketHandler.class);
67-
WebSocketHandler serverHandler = cxt.getBean(WebSocketHandler.class);
66+
this.webSocketClient.doHandshake(new WebSocketHandlerAdapter(), getWsBaseUrl() + "/ws");
6867

69-
this.webSocketClient.doHandshake(clientHandler, getWsBaseUrl() + "/ws");
70-
71-
verify(serverHandler).afterConnectionEstablished(any(WebSocketSession.class));
72-
verify(clientHandler).afterConnectionEstablished(any(WebSocketSession.class));
68+
TestWebSocketHandler serverHandler = cxt.getBean(TestWebSocketHandler.class);
69+
assertTrue(serverHandler.latch.await(2, TimeUnit.SECONDS));
7370
}
7471

7572
@Test
@@ -81,13 +78,10 @@ public void registerWebSocketHandlerWithSockJS() throws Exception {
8178
this.server.init(cxt);
8279
this.server.start();
8380

84-
WebSocketHandler clientHandler = Mockito.mock(WebSocketHandler.class);
85-
WebSocketHandler serverHandler = cxt.getBean(WebSocketHandler.class);
86-
87-
this.webSocketClient.doHandshake(clientHandler, getWsBaseUrl() + "/sockjs/websocket");
81+
this.webSocketClient.doHandshake(new WebSocketHandlerAdapter(), getWsBaseUrl() + "/sockjs/websocket");
8882

89-
verify(serverHandler).afterConnectionEstablished(any(WebSocketSession.class));
90-
verify(clientHandler).afterConnectionEstablished(any(WebSocketSession.class));
83+
TestWebSocketHandler serverHandler = cxt.getBean(TestWebSocketHandler.class);
84+
assertTrue(serverHandler.latch.await(2, TimeUnit.SECONDS));
9185
}
9286

9387

@@ -110,8 +104,18 @@ public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
110104
}
111105

112106
@Bean
113-
public WebSocketHandler serverHandler() {
114-
return Mockito.mock(WebSocketHandler.class);
107+
public TestWebSocketHandler serverHandler() {
108+
return new TestWebSocketHandler();
109+
}
110+
}
111+
112+
private static class TestWebSocketHandler extends WebSocketHandlerAdapter {
113+
114+
private CountDownLatch latch = new CountDownLatch(1);
115+
116+
@Override
117+
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
118+
this.latch.countDown();
115119
}
116120
}
117121

0 commit comments

Comments
 (0)