/* * Copyright 2002-2016 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.integration.store; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.junit.Test; import org.springframework.integration.store.MessageGroupStore.MessageGroupCallback; import org.springframework.integration.support.MessageBuilder; import org.springframework.messaging.Message; import org.springframework.messaging.MessagingException; import org.springframework.messaging.support.GenericMessage; import org.springframework.test.util.ReflectionTestUtils; /** * @author Iwein Fuld * @author Dave Syer * @author Gary Russell * @author Ryan Barker * @author Artem Bilan */ public class SimpleMessageStoreTests { @Test @SuppressWarnings("unchecked") public void shouldRetainMessage() { SimpleMessageStore store = new SimpleMessageStore(); Message<String> testMessage1 = MessageBuilder.withPayload("foo").build(); store.addMessage(testMessage1); assertThat(store.getMessage(testMessage1.getHeaders().getId()), is(testMessage1)); } @Test(expected = MessagingException.class) public void shouldNotHoldMoreThanCapacity() { SimpleMessageStore store = new SimpleMessageStore(1); Message<String> testMessage1 = MessageBuilder.withPayload("foo").build(); Message<String> testMessage2 = MessageBuilder.withPayload("bar").build(); store.addMessage(testMessage1); store.addMessage(testMessage2); } @Test public void shouldReleaseCapacity() { SimpleMessageStore store = new SimpleMessageStore(1); Message<String> testMessage1 = MessageBuilder.withPayload("foo").build(); Message<String> testMessage2 = MessageBuilder.withPayload("bar").build(); store.addMessage(testMessage1); try { store.addMessage(testMessage2); fail("Should have thrown"); } catch (Exception e) { assertThat(e, instanceOf(MessagingException.class)); assertThat(e.getMessage(), containsString("was out of capacity (1)")); } store.removeMessage(testMessage2.getHeaders().getId()); try { store.addMessage(testMessage2); fail("Should have thrown"); } catch (Exception e) { assertThat(e, instanceOf(MessagingException.class)); assertThat(e.getMessage(), containsString("was out of capacity (1)")); } store.removeMessage(testMessage1.getHeaders().getId()); store.addMessage(testMessage2); } @Test public void shouldWaitIfCapacity() throws InterruptedException { final SimpleMessageStore store2 = new SimpleMessageStore(1, 1, 1000); final Message<String> testMessage1 = MessageBuilder.withPayload("foo").build(); final Message<String> testMessage2 = MessageBuilder.withPayload("bar").build(); store2.addMessage(testMessage1); final CountDownLatch message2Latch = new CountDownLatch(1); Executors.newSingleThreadExecutor().execute(() -> { store2.addMessage(testMessage2); message2Latch.countDown(); }); // Simulate a blocked consumer Thread.sleep(10); Message<?> t1 = store2.removeMessage(testMessage1.getHeaders().getId()); assertEquals(testMessage1, t1); assertTrue(message2Latch.await(10, TimeUnit.SECONDS)); Message<?> t2 = store2.getMessage(testMessage2.getHeaders().getId()); assertEquals(testMessage2, t2); } @Test(expected = MessagingException.class) public void shouldTimeoutAfterWaitIfCapacity() throws InterruptedException { SimpleMessageStore store2 = new SimpleMessageStore(1, 1, 10); store2.addMessage(new GenericMessage<Object>("foo")); // This should throw store2.addMessage(new GenericMessage<Object>("foo")); fail("Should have thrown already"); } @Test(expected = MessagingException.class) public void shouldNotHoldMoreThanGroupCapacity() { SimpleMessageStore store = new SimpleMessageStore(0, 1); Message<String> testMessage1 = MessageBuilder.withPayload("foo").build(); Message<String> testMessage2 = MessageBuilder.withPayload("bar").build(); store.addMessageToGroup("foo", testMessage1); store.addMessageToGroup("foo", testMessage2); } @Test public void shouldWaitIfGroupCapacity() throws InterruptedException { final SimpleMessageStore store2 = new SimpleMessageStore(1, 1, 1000); final Message<String> testMessage1 = MessageBuilder.withPayload("foo").build(); final Message<String> testMessage2 = MessageBuilder.withPayload("bar").build(); store2.addMessageToGroup("foo", testMessage1); final CountDownLatch message2Latch = new CountDownLatch(1); Executors.newSingleThreadExecutor().execute(() -> { store2.addMessageToGroup("foo", testMessage2); message2Latch.countDown(); }); // Simulate a blocked consumer Thread.sleep(10); store2.removeMessagesFromGroup("foo", testMessage1); assertTrue(message2Latch.await(10, TimeUnit.SECONDS)); MessageGroup messageGroup = store2.getMessageGroup("foo"); messageGroup.getMessages().contains(testMessage2); } @Test(expected = MessagingException.class) public void shouldTimeoutAfterWaitIfGroupCapacity() { SimpleMessageStore store2 = new SimpleMessageStore(1, 1, 1); store2.addMessageToGroup("foo", MessageBuilder.withPayload("foo").build()); // This should throw store2.addMessageToGroup("foo", MessageBuilder.withPayload("bar").build()); fail("Should have thrown already"); } @Test public void shouldHoldCapacityExactly() { SimpleMessageStore store = new SimpleMessageStore(2); Message<String> testMessage1 = MessageBuilder.withPayload("foo").build(); Message<String> testMessage2 = MessageBuilder.withPayload("bar").build(); store.addMessage(testMessage1); store.addMessage(testMessage2); } @Test public void shouldReleaseGroupCapacity() { SimpleMessageStore store = new SimpleMessageStore(0, 1); Message<String> testMessage1 = MessageBuilder.withPayload("foo").build(); Message<String> testMessage2 = MessageBuilder.withPayload("bar").build(); store.addMessageToGroup("foo", testMessage1); try { store.addMessageToGroup("foo", testMessage2); fail("Should have thrown"); } catch (Exception e) { assertThat(e, instanceOf(MessagingException.class)); assertThat(e.getMessage(), containsString("was out of capacity (1) for group 'foo'")); } store.removeMessagesFromGroup("foo", testMessage2); try { store.addMessageToGroup("foo", testMessage2); fail("Should have thrown"); } catch (Exception e) { assertThat(e, instanceOf(MessagingException.class)); assertThat(e.getMessage(), containsString("was out of capacity (1) for group 'foo'")); } store.removeMessagesFromGroup("foo", testMessage1); store.addMessageToGroup("foo", testMessage2); } @Test public void shouldListByCorrelation() throws Exception { SimpleMessageStore store = new SimpleMessageStore(); Message<String> testMessage1 = MessageBuilder.withPayload("foo").build(); store.addMessageToGroup("bar", testMessage1); assertEquals(1, store.getMessageGroup("bar").size()); } @Test public void shouldRemoveFromGroup() throws Exception { SimpleMessageStore store = new SimpleMessageStore(); Message<String> testMessage1 = MessageBuilder.withPayload("foo").build(); store.addMessageToGroup("bar", testMessage1); Message<?> testMessage2 = store.getMessageGroup("bar").getOne(); store.removeMessagesFromGroup("bar", testMessage2); MessageGroup group = store.getMessageGroup("bar"); assertEquals(0, group.size()); assertEquals(0, store.getMessageGroup("bar").size()); } @Test public void testRepeatedAddAndRemoveGroup() throws Exception { SimpleMessageStore store = new SimpleMessageStore(10, 10); for (int i = 0; i < 10; i++) { store.addMessageToGroup("bar", MessageBuilder.withPayload("foo").build()); store.addMessageToGroup("bar", MessageBuilder.withPayload("foo").build()); store.removeMessageGroup("bar"); assertEquals(0, store.getMessageGroup("bar").size()); assertEquals(0, store.getMessageGroupCount()); } } @Test public void shouldCopyMessageGroup() throws Exception { SimpleMessageStore store = new SimpleMessageStore(); store.setCopyOnGet(true); Message<String> testMessage1 = MessageBuilder.withPayload("foo").build(); store.addMessageToGroup("bar", testMessage1); assertNotSame(store.getMessageGroup("bar"), store.getMessageGroup("bar")); } @Test public void shouldRegisterCallbacks() throws Exception { SimpleMessageStore store = new SimpleMessageStore(); store.setExpiryCallbacks(Arrays.<MessageGroupCallback>asList((messageGroupStore, group) -> { })); assertEquals(1, ((Collection<?>) ReflectionTestUtils.getField(store, "expiryCallbacks")).size()); } @Test public void shouldExpireMessageGroup() throws Exception { SimpleMessageStore store = new SimpleMessageStore(); final List<String> list = new ArrayList<String>(); store.registerMessageGroupExpiryCallback((messageGroupStore, group) -> { list.add(group.getOne().getPayload().toString()); messageGroupStore.removeMessageGroup(group.getGroupId()); }); Message<String> testMessage1 = MessageBuilder.withPayload("foo").build(); store.addMessageToGroup("bar", testMessage1); assertEquals(1, store.getMessageGroup("bar").size()); store.expireMessageGroups(-10000); assertEquals("[foo]", list.toString()); assertEquals(0, store.getMessageGroup("bar").size()); } @Test public void testAddAndRemoveMessagesFromMessageGroup() throws Exception { SimpleMessageStore messageStore = new SimpleMessageStore(); String groupId = "X"; List<Message<?>> messages = new ArrayList<Message<?>>(); for (int i = 0; i < 25; i++) { Message<String> message = MessageBuilder.withPayload("foo").setCorrelationId(groupId).build(); messageStore.addMessageToGroup(groupId, message); messages.add(message); } MessageGroup group = messageStore.getMessageGroup(groupId); assertEquals(25, group.size()); messageStore.removeMessagesFromGroup(groupId, messages); group = messageStore.getMessageGroup(groupId); assertEquals(0, group.size()); } }