/* * Copyright 2014-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.integration.file.remote.synchronizer; import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; import org.springframework.beans.factory.BeanFactory; import org.springframework.integration.file.filters.AcceptOnceFileListFilter; import org.springframework.integration.file.remote.session.Session; import org.springframework.integration.file.remote.session.SessionFactory; import org.springframework.messaging.MessagingException; /** * @author Gary Russell * @author Artem Bilan * * @since 4.0.4 * */ public class AbstractRemoteFileSynchronizerTests { @Test public void testRollback() throws Exception { final AtomicBoolean failWhenCopyingBar = new AtomicBoolean(true); final AtomicInteger count = new AtomicInteger(); SessionFactory<String> sf = new StringSessionFactory(); AbstractInboundFileSynchronizer<String> sync = new AbstractInboundFileSynchronizer<String>(sf) { @Override protected boolean isFile(String file) { return true; } @Override protected String getFilename(String file) { return file; } @Override protected long getModified(String file) { return 0; } @Override protected void copyFileToLocalDirectory(String remoteDirectoryPath, String remoteFile, File localDirectory, Session<String> session) throws IOException { if ("bar".equals(remoteFile) && failWhenCopyingBar.getAndSet(false)) { throw new IOException("fail"); } count.incrementAndGet(); } }; sync.setFilter(new AcceptOnceFileListFilter<String>()); sync.setRemoteDirectory("foo"); try { sync.synchronizeToLocalDirectory(mock(File.class)); assertEquals(1, count.get()); fail("Expected exception"); } catch (MessagingException e) { assertThat(e.getCause(), instanceOf(MessagingException.class)); assertThat(e.getCause().getCause(), instanceOf(IOException.class)); assertEquals("fail", e.getCause().getCause().getMessage()); } sync.synchronizeToLocalDirectory(mock(File.class)); assertEquals(3, count.get()); sync.close(); } @Test public void testMaxFetchSizeSynchronizer() throws Exception { final AtomicInteger count = new AtomicInteger(); AbstractInboundFileSynchronizer<String> sync = createLimitingSynchronizer(count); sync.synchronizeToLocalDirectory(mock(File.class), 1); assertEquals(1, count.get()); sync.synchronizeToLocalDirectory(mock(File.class), 1); assertEquals(2, count.get()); sync.synchronizeToLocalDirectory(mock(File.class), 1); assertEquals(3, count.get()); sync.close(); } @Test public void testMaxFetchSizeSource() throws Exception { final AtomicInteger count = new AtomicInteger(); AbstractInboundFileSynchronizer<String> sync = createLimitingSynchronizer(count); AbstractInboundFileSynchronizingMessageSource<String> source = new AbstractInboundFileSynchronizingMessageSource<String>(sync) { @Override public String getComponentType() { return "foo"; } }; source.setLocalDirectory(new File(System.getProperty("java.io.tmpdir") + File.separator + UUID.randomUUID())); source.setAutoCreateLocalDirectory(true); source.setBeanFactory(mock(BeanFactory.class)); source.setMaxFetchSize(1); source.setBeanName("maxFetchSizeSource"); source.afterPropertiesSet(); source.start(); source.receive(); assertEquals(1, count.get()); sync.synchronizeToLocalDirectory(mock(File.class), 1); source.receive(); sync.synchronizeToLocalDirectory(mock(File.class), 1); source.receive(); source.stop(); } private AbstractInboundFileSynchronizer<String> createLimitingSynchronizer(final AtomicInteger count) { SessionFactory<String> sf = new StringSessionFactory(); AbstractInboundFileSynchronizer<String> sync = new AbstractInboundFileSynchronizer<String>(sf) { @Override protected boolean isFile(String file) { return true; } @Override protected String getFilename(String file) { return file; } @Override protected long getModified(String file) { return 0; } @Override protected void copyFileToLocalDirectory(String remoteDirectoryPath, String remoteFile, File localDirectory, Session<String> session) throws IOException { count.incrementAndGet(); } }; sync.setFilter(new AcceptOnceFileListFilter<String>()); sync.setRemoteDirectory("foo"); sync.setBeanFactory(mock(BeanFactory.class)); return sync; } private class StringSessionFactory implements SessionFactory<String> { @Override public Session<String> getSession() { return new StringSession(); } } private class StringSession implements Session<String> { @Override public boolean remove(String path) throws IOException { return true; } @Override public String[] list(String path) throws IOException { return new String[] {"foo", "bar", "baz"}; } @Override public void read(String source, OutputStream outputStream) throws IOException { } @Override public void write(InputStream inputStream, String destination) throws IOException { } @Override public void append(InputStream inputStream, String destination) throws IOException { } @Override public boolean mkdir(String directory) throws IOException { return true; } @Override public boolean rmdir(String directory) throws IOException { return true; } @Override public void rename(String pathFrom, String pathTo) throws IOException { } @Override public void close() { } @Override public boolean isOpen() { return true; } @Override public boolean exists(String path) throws IOException { return true; } @Override public String[] listNames(String path) throws IOException { return new String[0]; } @Override public InputStream readRaw(String source) throws IOException { return null; } @Override public boolean finalizeRaw() throws IOException { return true; } @Override public Object getClientInstance() { return null; } } }