/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.messaging.simp.stomp;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import org.hamcrest.CoreMatchers;
import org.junit.Test;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.SimpMessageType;
import org.springframework.messaging.support.IdTimestampMessageHeaderInitializer;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.messaging.support.MessageHeaderAccessor;
import org.springframework.util.AlternativeJdkIdGenerator;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
import org.springframework.util.MultiValueMap;
import static org.junit.Assert.*;
/**
* Unit tests for {@link StompHeaderAccessor}.
*
* @author Rossen Stoyanchev
* @since 4.0
*/
public class StompHeaderAccessorTests {
@Test
public void createWithCommand() {
StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.CONNECTED);
assertEquals(StompCommand.CONNECTED, accessor.getCommand());
accessor = StompHeaderAccessor.create(StompCommand.CONNECTED, new LinkedMultiValueMap<>());
assertEquals(StompCommand.CONNECTED, accessor.getCommand());
}
@Test
public void createWithSubscribeNativeHeaders() {
MultiValueMap<String, String> extHeaders = new LinkedMultiValueMap<>();
extHeaders.add(StompHeaderAccessor.STOMP_ID_HEADER, "s1");
extHeaders.add(StompHeaderAccessor.STOMP_DESTINATION_HEADER, "/d");
StompHeaderAccessor headers = StompHeaderAccessor.create(StompCommand.SUBSCRIBE, extHeaders);
assertEquals(StompCommand.SUBSCRIBE, headers.getCommand());
assertEquals(SimpMessageType.SUBSCRIBE, headers.getMessageType());
assertEquals("/d", headers.getDestination());
assertEquals("s1", headers.getSubscriptionId());
}
@Test
public void createWithUnubscribeNativeHeaders() {
MultiValueMap<String, String> extHeaders = new LinkedMultiValueMap<>();
extHeaders.add(StompHeaderAccessor.STOMP_ID_HEADER, "s1");
StompHeaderAccessor headers = StompHeaderAccessor.create(StompCommand.UNSUBSCRIBE, extHeaders);
assertEquals(StompCommand.UNSUBSCRIBE, headers.getCommand());
assertEquals(SimpMessageType.UNSUBSCRIBE, headers.getMessageType());
assertEquals("s1", headers.getSubscriptionId());
}
@Test
public void createWithMessageFrameNativeHeaders() {
MultiValueMap<String, String> extHeaders = new LinkedMultiValueMap<>();
extHeaders.add(StompHeaderAccessor.DESTINATION_HEADER, "/d");
extHeaders.add(StompHeaderAccessor.STOMP_SUBSCRIPTION_HEADER, "s1");
extHeaders.add(StompHeaderAccessor.STOMP_CONTENT_TYPE_HEADER, "application/json");
StompHeaderAccessor headers = StompHeaderAccessor.create(StompCommand.MESSAGE, extHeaders);
assertEquals(StompCommand.MESSAGE, headers.getCommand());
assertEquals(SimpMessageType.MESSAGE, headers.getMessageType());
assertEquals("s1", headers.getSubscriptionId());
}
@Test
public void createWithConnectNativeHeaders() {
MultiValueMap<String, String> extHeaders = new LinkedMultiValueMap<>();
extHeaders.add(StompHeaderAccessor.STOMP_LOGIN_HEADER, "joe");
extHeaders.add(StompHeaderAccessor.STOMP_PASSCODE_HEADER, "joe123");
StompHeaderAccessor headerAccessor = StompHeaderAccessor.create(StompCommand.CONNECT, extHeaders);
assertEquals(StompCommand.CONNECT, headerAccessor.getCommand());
assertEquals(SimpMessageType.CONNECT, headerAccessor.getMessageType());
assertNotNull(headerAccessor.getHeader("stompCredentials"));
assertEquals("joe", headerAccessor.getLogin());
assertEquals("joe123", headerAccessor.getPasscode());
assertThat(headerAccessor.toString(), CoreMatchers.containsString("passcode=[PROTECTED]"));
Map<String, List<String>> output = headerAccessor.toNativeHeaderMap();
assertEquals("joe", output.get(StompHeaderAccessor.STOMP_LOGIN_HEADER).get(0));
assertEquals("PROTECTED", output.get(StompHeaderAccessor.STOMP_PASSCODE_HEADER).get(0));
}
@Test
public void toNativeHeadersSubscribe() {
StompHeaderAccessor headers = StompHeaderAccessor.create(StompCommand.SUBSCRIBE);
headers.setSubscriptionId("s1");
headers.setDestination("/d");
Map<String, List<String>> actual = headers.toNativeHeaderMap();
assertEquals(2, actual.size());
assertEquals("s1", actual.get(StompHeaderAccessor.STOMP_ID_HEADER).get(0));
assertEquals("/d", actual.get(StompHeaderAccessor.STOMP_DESTINATION_HEADER).get(0));
}
@Test
public void toNativeHeadersUnsubscribe() {
StompHeaderAccessor headers = StompHeaderAccessor.create(StompCommand.UNSUBSCRIBE);
headers.setSubscriptionId("s1");
Map<String, List<String>> actual = headers.toNativeHeaderMap();
assertEquals(1, actual.size());
assertEquals("s1", actual.get(StompHeaderAccessor.STOMP_ID_HEADER).get(0));
}
@Test
public void toNativeHeadersMessageFrame() {
StompHeaderAccessor headers = StompHeaderAccessor.create(StompCommand.MESSAGE);
headers.setSubscriptionId("s1");
headers.setDestination("/d");
headers.setContentType(MimeTypeUtils.APPLICATION_JSON);
headers.updateStompCommandAsServerMessage();
Map<String, List<String>> actual = headers.toNativeHeaderMap();
assertEquals(actual.toString(), 4, actual.size());
assertEquals("s1", actual.get(StompHeaderAccessor.STOMP_SUBSCRIPTION_HEADER).get(0));
assertEquals("/d", actual.get(StompHeaderAccessor.STOMP_DESTINATION_HEADER).get(0));
assertEquals("application/json", actual.get(StompHeaderAccessor.STOMP_CONTENT_TYPE_HEADER).get(0));
assertNotNull("message-id was not created", actual.get(StompHeaderAccessor.STOMP_MESSAGE_ID_HEADER).get(0));
}
@Test
public void toNativeHeadersContentType() {
SimpMessageHeaderAccessor simpHeaderAccessor = SimpMessageHeaderAccessor.create();
simpHeaderAccessor.setContentType(MimeType.valueOf("application/atom+xml"));
Message<byte[]> message = MessageBuilder.createMessage(new byte[0], simpHeaderAccessor.getMessageHeaders());
StompHeaderAccessor stompHeaderAccessor = StompHeaderAccessor.wrap(message);
Map<String, List<String>> map = stompHeaderAccessor.toNativeHeaderMap();
assertEquals("application/atom+xml", map.get(StompHeaderAccessor.STOMP_CONTENT_TYPE_HEADER).get(0));
}
@Test
public void encodeConnectWithLoginAndPasscode() throws UnsupportedEncodingException {
MultiValueMap<String, String> extHeaders = new LinkedMultiValueMap<>();
extHeaders.add(StompHeaderAccessor.STOMP_LOGIN_HEADER, "joe");
extHeaders.add(StompHeaderAccessor.STOMP_PASSCODE_HEADER, "joe123");
StompHeaderAccessor headerAccessor = StompHeaderAccessor.create(StompCommand.CONNECT, extHeaders);
Message<byte[]> message = MessageBuilder.createMessage(new byte[0], headerAccessor.getMessageHeaders());
byte[] bytes = new StompEncoder().encode(message);
assertEquals("CONNECT\nlogin:joe\npasscode:joe123\n\n\0", new String(bytes, "UTF-8"));
}
@Test
public void modifyCustomNativeHeader() {
MultiValueMap<String, String> extHeaders = new LinkedMultiValueMap<>();
extHeaders.add(StompHeaderAccessor.STOMP_ID_HEADER, "s1");
extHeaders.add(StompHeaderAccessor.STOMP_DESTINATION_HEADER, "/d");
extHeaders.add("accountId", "ABC123");
StompHeaderAccessor headers = StompHeaderAccessor.create(StompCommand.SUBSCRIBE, extHeaders);
String accountId = headers.getFirstNativeHeader("accountId");
headers.setNativeHeader("accountId", accountId.toLowerCase());
Map<String, List<String>> actual = headers.toNativeHeaderMap();
assertEquals(3, actual.size());
assertEquals("s1", actual.get(StompHeaderAccessor.STOMP_ID_HEADER).get(0));
assertEquals("/d", actual.get(StompHeaderAccessor.STOMP_DESTINATION_HEADER).get(0));
assertNotNull("abc123", actual.get("accountId").get(0));
}
@Test
public void messageIdAndTimestampDefaultBehavior() {
StompHeaderAccessor headerAccessor = StompHeaderAccessor.create(StompCommand.SEND);
MessageHeaders headers = headerAccessor.getMessageHeaders();
assertNull(headers.getId());
assertNull(headers.getTimestamp());
}
@Test
public void messageIdAndTimestampEnabled() {
IdTimestampMessageHeaderInitializer headerInitializer = new IdTimestampMessageHeaderInitializer();
headerInitializer.setIdGenerator(new AlternativeJdkIdGenerator());
headerInitializer.setEnableTimestamp(true);
StompHeaderAccessor headerAccessor = StompHeaderAccessor.create(StompCommand.SEND);
headerInitializer.initHeaders(headerAccessor);
assertNotNull(headerAccessor.getMessageHeaders().getId());
assertNotNull(headerAccessor.getMessageHeaders().getTimestamp());
}
@Test
public void getAccessor() {
StompHeaderAccessor headerAccessor = StompHeaderAccessor.create(StompCommand.CONNECT);
Message<byte[]> message = MessageBuilder.createMessage(new byte[0], headerAccessor.getMessageHeaders());
assertSame(headerAccessor, MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class));
}
@Test
public void getShortLogMessage() {
StompHeaderAccessor accessor = StompHeaderAccessor.create(StompCommand.SEND);
accessor.setDestination("/foo");
accessor.setContentType(MimeTypeUtils.APPLICATION_JSON);
accessor.setSessionId("123");
String actual = accessor.getShortLogMessage("payload".getBytes(StandardCharsets.UTF_8));
assertEquals("SEND /foo session=123 application/json payload=payload", actual);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 80; i++) {
sb.append("a");
}
final String payload = sb.toString() + " > 80";
actual = accessor.getShortLogMessage(payload.getBytes(StandardCharsets.UTF_8));
assertEquals("SEND /foo session=123 application/json payload=" + sb + "...(truncated)", actual);
}
}