/*
* 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.support;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.util.MimeTypeUtils;
import org.springframework.util.SerializationTestUtils;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
/**
* Test fixture for {@link MessageHeaderAccessor}.
*
* @author Rossen Stoyanchev
* @author Sebastien Deleuze
* @author Juergen Hoeller
*/
public class MessageHeaderAccessorTests {
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Test
public void newEmptyHeaders() {
MessageHeaderAccessor accessor = new MessageHeaderAccessor();
assertEquals(0, accessor.toMap().size());
}
@Test
public void existingHeaders() throws InterruptedException {
Map<String, Object> map = new HashMap<>();
map.put("foo", "bar");
map.put("bar", "baz");
GenericMessage<String> message = new GenericMessage<>("payload", map);
MessageHeaderAccessor accessor = new MessageHeaderAccessor(message);
MessageHeaders actual = accessor.getMessageHeaders();
assertEquals(3, actual.size());
assertEquals("bar", actual.get("foo"));
assertEquals("baz", actual.get("bar"));
}
@Test
public void existingHeadersModification() throws InterruptedException {
Map<String, Object> map = new HashMap<>();
map.put("foo", "bar");
map.put("bar", "baz");
GenericMessage<String> message = new GenericMessage<>("payload", map);
Thread.sleep(50);
MessageHeaderAccessor accessor = new MessageHeaderAccessor(message);
accessor.setHeader("foo", "BAR");
MessageHeaders actual = accessor.getMessageHeaders();
assertEquals(3, actual.size());
assertNotEquals(message.getHeaders().getId(), actual.getId());
assertEquals("BAR", actual.get("foo"));
assertEquals("baz", actual.get("bar"));
}
@Test
public void testRemoveHeader() {
Message<?> message = new GenericMessage<>("payload", Collections.singletonMap("foo", "bar"));
MessageHeaderAccessor accessor = new MessageHeaderAccessor(message);
accessor.removeHeader("foo");
Map<String, Object> headers = accessor.toMap();
assertFalse(headers.containsKey("foo"));
}
@Test
public void testRemoveHeaderEvenIfNull() {
Message<?> message = new GenericMessage<>("payload", Collections.singletonMap("foo", null));
MessageHeaderAccessor accessor = new MessageHeaderAccessor(message);
accessor.removeHeader("foo");
Map<String, Object> headers = accessor.toMap();
assertFalse(headers.containsKey("foo"));
}
@Test
public void removeHeaders() {
Map<String, Object> map = new HashMap<>();
map.put("foo", "bar");
map.put("bar", "baz");
GenericMessage<String> message = new GenericMessage<>("payload", map);
MessageHeaderAccessor accessor = new MessageHeaderAccessor(message);
accessor.removeHeaders("fo*");
MessageHeaders actual = accessor.getMessageHeaders();
assertEquals(2, actual.size());
assertNull(actual.get("foo"));
assertEquals("baz", actual.get("bar"));
}
@Test
public void copyHeaders() {
Map<String, Object> map1 = new HashMap<>();
map1.put("foo", "bar");
GenericMessage<String> message = new GenericMessage<>("payload", map1);
MessageHeaderAccessor accessor = new MessageHeaderAccessor(message);
Map<String, Object> map2 = new HashMap<>();
map2.put("foo", "BAR");
map2.put("bar", "baz");
accessor.copyHeaders(map2);
MessageHeaders actual = accessor.getMessageHeaders();
assertEquals(3, actual.size());
assertEquals("BAR", actual.get("foo"));
assertEquals("baz", actual.get("bar"));
}
@Test
public void copyHeadersIfAbsent() {
Map<String, Object> map1 = new HashMap<>();
map1.put("foo", "bar");
GenericMessage<String> message = new GenericMessage<>("payload", map1);
MessageHeaderAccessor accessor = new MessageHeaderAccessor(message);
Map<String, Object> map2 = new HashMap<>();
map2.put("foo", "BAR");
map2.put("bar", "baz");
accessor.copyHeadersIfAbsent(map2);
MessageHeaders actual = accessor.getMessageHeaders();
assertEquals(3, actual.size());
assertEquals("bar", actual.get("foo"));
assertEquals("baz", actual.get("bar"));
}
@Test
public void copyHeadersFromNullMap() {
MessageHeaderAccessor headers = new MessageHeaderAccessor();
headers.copyHeaders(null);
headers.copyHeadersIfAbsent(null);
assertEquals(1, headers.getMessageHeaders().size());
assertEquals(Collections.singleton("id"), headers.getMessageHeaders().keySet());
}
@Test
public void toMap() {
MessageHeaderAccessor accessor = new MessageHeaderAccessor();
accessor.setHeader("foo", "bar1");
Map<String, Object> map1 = accessor.toMap();
accessor.setHeader("foo", "bar2");
Map<String, Object> map2 = accessor.toMap();
accessor.setHeader("foo", "bar3");
Map<String, Object> map3 = accessor.toMap();
assertEquals(1, map1.size());
assertEquals(1, map2.size());
assertEquals(1, map3.size());
assertEquals("bar1", map1.get("foo"));
assertEquals("bar2", map2.get("foo"));
assertEquals("bar3", map3.get("foo"));
}
@Test
public void leaveMutable() {
MessageHeaderAccessor accessor = new MessageHeaderAccessor();
accessor.setHeader("foo", "bar");
accessor.setLeaveMutable(true);
MessageHeaders headers = accessor.getMessageHeaders();
Message<?> message = MessageBuilder.createMessage("payload", headers);
accessor.setHeader("foo", "baz");
assertEquals("baz", headers.get("foo"));
assertSame(accessor, MessageHeaderAccessor.getAccessor(message, MessageHeaderAccessor.class));
}
@Test
public void leaveMutableDefaultBehavior() {
MessageHeaderAccessor accessor = new MessageHeaderAccessor();
accessor.setHeader("foo", "bar");
MessageHeaders headers = accessor.getMessageHeaders();
Message<?> message = MessageBuilder.createMessage("payload", headers);
this.thrown.expect(IllegalStateException.class);
this.thrown.expectMessage("Already immutable");
accessor.setLeaveMutable(true);
this.thrown.expect(IllegalStateException.class);
this.thrown.expectMessage("Already immutable");
accessor.setHeader("foo", "baz");
assertEquals("bar", headers.get("foo"));
assertSame(accessor, MessageHeaderAccessor.getAccessor(message, MessageHeaderAccessor.class));
}
@Test
public void getAccessor() {
MessageHeaderAccessor expected = new MessageHeaderAccessor();
Message<?> message = MessageBuilder.createMessage("payload", expected.getMessageHeaders());
assertSame(expected, MessageHeaderAccessor.getAccessor(message, MessageHeaderAccessor.class));
}
@Test
public void getMutableAccessorSameInstance() {
TestMessageHeaderAccessor expected = new TestMessageHeaderAccessor();
expected.setLeaveMutable(true);
Message<?> message = MessageBuilder.createMessage("payload", expected.getMessageHeaders());
MessageHeaderAccessor actual = MessageHeaderAccessor.getMutableAccessor(message);
assertNotNull(actual);
assertTrue(actual.isMutable());
assertSame(expected, actual);
}
@Test
public void getMutableAccessorNewInstance() {
Message<?> message = MessageBuilder.withPayload("payload").build();
MessageHeaderAccessor actual = MessageHeaderAccessor.getMutableAccessor(message);
assertNotNull(actual);
assertTrue(actual.isMutable());
}
@Test
public void getMutableAccessorNewInstanceMatchingType() {
TestMessageHeaderAccessor expected = new TestMessageHeaderAccessor();
Message<?> message = MessageBuilder.createMessage("payload", expected.getMessageHeaders());
MessageHeaderAccessor actual = MessageHeaderAccessor.getMutableAccessor(message);
assertNotNull(actual);
assertTrue(actual.isMutable());
assertEquals(TestMessageHeaderAccessor.class, actual.getClass());
}
@Test
public void timestampEnabled() {
MessageHeaderAccessor accessor = new MessageHeaderAccessor();
accessor.setEnableTimestamp(true);
assertNotNull(accessor.getMessageHeaders().getTimestamp());
}
@Test
public void timestampDefaultBehavior() {
MessageHeaderAccessor accessor = new MessageHeaderAccessor();
assertNull(accessor.getMessageHeaders().getTimestamp());
}
@Test
public void idGeneratorCustom() {
final UUID id = new UUID(0L, 23L);
MessageHeaderAccessor accessor = new MessageHeaderAccessor();
accessor.setIdGenerator(() -> id);
assertSame(id, accessor.getMessageHeaders().getId());
}
@Test
public void idGeneratorDefaultBehavior() {
MessageHeaderAccessor accessor = new MessageHeaderAccessor();
assertNotNull(accessor.getMessageHeaders().getId());
}
@Test
public void idTimestampWithMutableHeaders() {
MessageHeaderAccessor accessor = new MessageHeaderAccessor();
accessor.setIdGenerator(() -> MessageHeaders.ID_VALUE_NONE);
accessor.setEnableTimestamp(false);
accessor.setLeaveMutable(true);
MessageHeaders headers = accessor.getMessageHeaders();
assertNull(headers.getId());
assertNull(headers.getTimestamp());
final UUID id = new UUID(0L, 23L);
accessor.setIdGenerator(() -> id);
accessor.setEnableTimestamp(true);
accessor.setImmutable();
assertSame(id, accessor.getMessageHeaders().getId());
assertNotNull(headers.getTimestamp());
}
@Test
public void getShortLogMessagePayload() {
MessageHeaderAccessor accessor = new MessageHeaderAccessor();
accessor.setContentType(MimeTypeUtils.TEXT_PLAIN);
assertEquals("headers={contentType=text/plain} payload=p", accessor.getShortLogMessage("p"));
assertEquals("headers={contentType=text/plain} payload=p", accessor.getShortLogMessage("p".getBytes(StandardCharsets.UTF_8)));
assertEquals("headers={contentType=text/plain} payload=p", accessor.getShortLogMessage(new Object() {
@Override
public String toString() {
return "p";
}
}));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 80; i++) {
sb.append("a");
}
final String payload = sb.toString() + " > 80";
String actual = accessor.getShortLogMessage(payload);
assertEquals("headers={contentType=text/plain} payload=" + sb + "...(truncated)", actual);
actual = accessor.getShortLogMessage(payload.getBytes(StandardCharsets.UTF_8));
assertEquals("headers={contentType=text/plain} payload=" + sb + "...(truncated)", actual);
actual = accessor.getShortLogMessage(new Object() {
@Override
public String toString() {
return payload;
}
});
assertThat(actual, startsWith("headers={contentType=text/plain} payload=" + getClass().getName() + "$"));
}
@Test
public void getDetailedLogMessagePayload() {
MessageHeaderAccessor accessor = new MessageHeaderAccessor();
accessor.setContentType(MimeTypeUtils.TEXT_PLAIN);
assertEquals("headers={contentType=text/plain} payload=p", accessor.getDetailedLogMessage("p"));
assertEquals("headers={contentType=text/plain} payload=p", accessor.getDetailedLogMessage("p".getBytes(StandardCharsets.UTF_8)));
assertEquals("headers={contentType=text/plain} payload=p", accessor.getDetailedLogMessage(new Object() {
@Override
public String toString() {
return "p";
}
}));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 80; i++) {
sb.append("a");
}
final String payload = sb.toString() + " > 80";
String actual = accessor.getDetailedLogMessage(payload);
assertEquals("headers={contentType=text/plain} payload=" + sb + " > 80", actual);
actual = accessor.getDetailedLogMessage(payload.getBytes(StandardCharsets.UTF_8));
assertEquals("headers={contentType=text/plain} payload=" + sb + " > 80", actual);
actual = accessor.getDetailedLogMessage(new Object() {
@Override
public String toString() {
return payload;
}
});
assertEquals("headers={contentType=text/plain} payload=" + sb + " > 80", actual);
}
@Test
public void serializeMutableHeaders() throws Exception {
Map<String, Object> headers = new HashMap<>();
headers.put("foo", "bar");
Message<String> message = new GenericMessage<>("test", headers);
MessageHeaderAccessor mutableAccessor = MessageHeaderAccessor.getMutableAccessor(message);
mutableAccessor.setContentType(MimeTypeUtils.TEXT_PLAIN);
message = new GenericMessage<>(message.getPayload(), mutableAccessor.getMessageHeaders());
Message<?> output = (Message<?>) SerializationTestUtils.serializeAndDeserialize(message);
assertEquals("test", output.getPayload());
assertEquals("bar", output.getHeaders().get("foo"));
assertNotNull(output.getHeaders().get(MessageHeaders.CONTENT_TYPE));
}
public static class TestMessageHeaderAccessor extends MessageHeaderAccessor {
public TestMessageHeaderAccessor() {
}
private TestMessageHeaderAccessor(Message<?> message) {
super(message);
}
public static TestMessageHeaderAccessor wrap(Message<?> message) {
return new TestMessageHeaderAccessor(message);
}
@Override
protected TestMessageHeaderAccessor createAccessor(Message<?> message) {
return wrap(message);
}
}
}