/* * Copyright 2015 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.cloud.stream.module.splitter; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertThat; import static org.springframework.cloud.stream.test.matcher.MessageQueueMatcher.receivesPayloadThat; import static org.springframework.integration.test.matcher.HeaderMatcher.hasSequenceNumber; import static org.springframework.integration.test.matcher.HeaderMatcher.hasSequenceSize; import static org.springframework.integration.test.matcher.PayloadMatcher.hasPayload; import java.io.File; import java.io.FileOutputStream; import java.util.Arrays; import java.util.concurrent.TimeUnit; import org.hamcrest.Description; import org.hamcrest.DiagnosingMatcher; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.IntegrationTest; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.boot.test.WebIntegrationTest; import org.springframework.cloud.stream.annotation.Bindings; import org.springframework.cloud.stream.messaging.Processor; import org.springframework.cloud.stream.test.binder.MessageCollector; import org.springframework.integration.IntegrationMessageHeaderAccessor; import org.springframework.integration.endpoint.EventDrivenConsumer; import org.springframework.integration.file.splitter.FileSplitter; import org.springframework.integration.file.splitter.FileSplitter.FileMarker; import org.springframework.integration.file.splitter.FileSplitter.FileMarker.Mark; import org.springframework.integration.splitter.AbstractMessageSplitter; import org.springframework.integration.splitter.DefaultMessageSplitter; import org.springframework.integration.splitter.ExpressionEvaluatingSplitter; import org.springframework.integration.test.util.TestUtils; import org.springframework.messaging.Message; import org.springframework.messaging.support.GenericMessage; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * Integration Tests for the Splitter Processor. * */ @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = SplitterProcessorApplication.class) @WebIntegrationTest(randomPort = true) @DirtiesContext public abstract class SplitterProcessorIntegrationTests { @Autowired @Bindings(SplitterProcessor.class) protected Processor channels; @Autowired protected MessageCollector collector; @Autowired protected AbstractMessageSplitter splitter; @Autowired @Qualifier("splitterProcessor.splitterHandler.splitter") protected EventDrivenConsumer consumer; /** * Validates that the module loads with default properties. */ public static class UsingNothingIntegrationTests extends SplitterProcessorIntegrationTests { @Test public void test() { assertThat(this.splitter, instanceOf(DefaultMessageSplitter.class)); assertSame(this.splitter, TestUtils.getPropertyValue(this.consumer, "handler")); this.channels.input().send(new GenericMessage<>(Arrays.asList("hello", "world"))); assertThat(this.collector.forChannel(this.channels.output()), receivesPayloadThat(is("hello"))); assertThat(this.collector.forChannel(this.channels.output()), receivesPayloadThat(is("world"))); } } @IntegrationTest("delimiters = ,") public static class withDelimitersTests extends SplitterProcessorIntegrationTests { @Test public void test() { assertThat(this.splitter, instanceOf(DefaultMessageSplitter.class)); assertSame(this.splitter, TestUtils.getPropertyValue(this.consumer, "handler")); this.channels.input().send(new GenericMessage<>("hello,world")); assertThat(this.collector.forChannel(this.channels.output()), receivesPayloadThat(is("hello"))); assertThat(this.collector.forChannel(this.channels.output()), receivesPayloadThat(is("world"))); } } @IntegrationTest({ "fileMarkers = false", "charset = UTF-8", "applySequence = false" }) public static class fromFileTests extends SplitterProcessorIntegrationTests { @Test public void test() throws Exception { assertThat(this.splitter, instanceOf(FileSplitter.class)); assertSame(this.splitter, TestUtils.getPropertyValue(this.consumer, "handler")); File file = new File(System.getProperty("java.io.tmpdir") + File.separator + "splitter.proc.test"); FileOutputStream fos = new FileOutputStream(file); fos.write("hello\nworld\n".getBytes()); fos.close(); this.channels.input().send(new GenericMessage<>(file)); Message<?> m = this.collector.forChannel(this.channels.output()).poll(10, TimeUnit.SECONDS); assertNotNull(m); assertNull((m.getHeaders().get(IntegrationMessageHeaderAccessor.SEQUENCE_NUMBER))); assertThat(m, hasPayload("hello")); assertThat(this.collector.forChannel(this.channels.output()), receivesPayloadThat(is("world"))); file.delete(); } } @IntegrationTest({ "fileMarkers = true", "charset = UTF-8" }) public static class fromFileWithMarkersTests extends SplitterProcessorIntegrationTests { @Test public void test() throws Exception { assertThat(this.splitter, instanceOf(FileSplitter.class)); assertSame(this.splitter, TestUtils.getPropertyValue(this.consumer, "handler")); File file = new File(System.getProperty("java.io.tmpdir") + File.separator + "splitter.proc.test"); FileOutputStream fos = new FileOutputStream(file); fos.write("hello\nworld\n".getBytes()); fos.close(); this.channels.input().send(new GenericMessage<>(file)); Message<?> m = this.collector.forChannel(this.channels.output()).poll(10, TimeUnit.SECONDS); assertNotNull(m); assertThat(m.getPayload(), instanceOf(FileMarker.class)); assertThat((FileMarker) m.getPayload(), hasMark(Mark.START)); assertThat(m, allOf(hasSequenceNumber(1), hasSequenceSize(0))); assertThat(this.collector.forChannel(this.channels.output()), receivesPayloadThat(is("hello"))); assertThat(this.collector.forChannel(this.channels.output()), receivesPayloadThat(is("world"))); assertThat(this.collector.forChannel(this.channels.output()), receivesPayloadThat(allOf( instanceOf(FileMarker.class), hasMark(Mark.END)))); file.delete(); } } @IntegrationTest("expression=payload.split(',')") public static class UsingExpressionIntegrationTests extends SplitterProcessorIntegrationTests { @Test public void test() { assertThat(this.splitter, instanceOf(ExpressionEvaluatingSplitter.class)); this.channels.input().send(new GenericMessage<>("hello,world")); assertThat(this.collector.forChannel(this.channels.output()), receivesPayloadThat(is("hello"))); assertThat(this.collector.forChannel(this.channels.output()), receivesPayloadThat(is("world"))); } } private static MarkerMatcher hasMark(Mark expected) { return new MarkerMatcher(expected); } private static final class MarkerMatcher extends DiagnosingMatcher<FileMarker> { private final Mark expected; private MarkerMatcher(Mark expected) { this.expected = expected; } @Override public void describeTo(Description description) { description.appendText("the mark to be ").appendText(this.expected.name()); } @Override protected boolean matches(Object item, Description mismatchDescription) { Mark mark = ((FileMarker) item).getMark(); boolean match = this.expected.compareTo(mark) == 0; if (!match) { mismatchDescription.appendText("is ").appendText(mark.name()); } return match; } } }