/* * Copyright (c) 2002-2016 iterate GmbH. All rights reserved. * https://cyberduck.io/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ package ch.cyberduck.core.threading; import ch.cyberduck.core.AbstractController; import ch.cyberduck.core.Credentials; import ch.cyberduck.core.DisabledPasswordCallback; import ch.cyberduck.core.DisabledTranscriptListener; import ch.cyberduck.core.Host; import ch.cyberduck.core.ListProgressListener; import ch.cyberduck.core.NullLocal; import ch.cyberduck.core.NullSession; import ch.cyberduck.core.NullTransferSession; import ch.cyberduck.core.Path; import ch.cyberduck.core.PathCache; import ch.cyberduck.core.Session; import ch.cyberduck.core.TestLoginConnectionService; import ch.cyberduck.core.TestProtocol; import ch.cyberduck.core.exception.BackgroundException; import ch.cyberduck.core.exception.ConnectionRefusedException; import ch.cyberduck.core.pool.DefaultSessionPool; import ch.cyberduck.core.pool.SessionPool; import ch.cyberduck.core.pool.StatelessSessionPool; import ch.cyberduck.core.ssl.DefaultX509KeyManager; import ch.cyberduck.core.ssl.DisabledX509TrustManager; import ch.cyberduck.core.transfer.CopyTransfer; import ch.cyberduck.core.transfer.DownloadTransfer; import ch.cyberduck.core.transfer.Transfer; import ch.cyberduck.core.transfer.TransferAction; import ch.cyberduck.core.transfer.TransferAdapter; import ch.cyberduck.core.transfer.TransferItem; import ch.cyberduck.core.transfer.TransferListener; import ch.cyberduck.core.transfer.TransferOptions; import ch.cyberduck.core.transfer.TransferProgress; import ch.cyberduck.core.transfer.TransferPrompt; import ch.cyberduck.core.transfer.UploadTransfer; import ch.cyberduck.core.vault.DefaultVaultRegistry; import ch.cyberduck.core.worker.ConcurrentTransferWorker; import org.junit.Test; import java.net.SocketException; import java.util.Collections; import java.util.EnumSet; import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; import static org.junit.Assert.*; public class TransferBackgroundActionTest { @Test public void testWorkerImplementationDefaultConcurrent() { final AbstractController controller = new AbstractController() { @Override public void invoke(final MainAction runnable, final boolean wait) { runnable.run(); } }; final Host host = new Host(new TestProtocol(), "l"); host.setTransfer(Host.TransferType.concurrent); assertEquals(ConcurrentTransferWorker.class, new TransferBackgroundAction(controller, new StatelessSessionPool( new TestLoginConnectionService(), new NullSession(host), PathCache.empty(), new DisabledTranscriptListener(), new DefaultVaultRegistry(new DisabledPasswordCallback())), SessionPool.DISCONNECTED, new TransferAdapter(), new UploadTransfer(host, Collections.emptyList()), new TransferOptions()).worker.getClass()); assertEquals(ConcurrentTransferWorker.class, new TransferBackgroundAction(controller, new StatelessSessionPool( new TestLoginConnectionService(), new NullSession(host), PathCache.empty(), new DisabledTranscriptListener(), new DefaultVaultRegistry(new DisabledPasswordCallback())), SessionPool.DISCONNECTED, new TransferAdapter(), new DownloadTransfer(host, Collections.emptyList()), new TransferOptions()).worker.getClass()); } @Test public void testDuplicate() throws Exception { final Host host = new Host(new TestProtocol(), "test.cyberduck.ch") { @Override public Credentials getCredentials() { return new Credentials( System.getProperties().getProperty("sftp.user"), System.getProperties().getProperty("sftp.password") ); } }; final Path directory = new Path("/home/jenkins/transfer", EnumSet.of(Path.Type.directory)); final Path test = new Path(directory, "test", EnumSet.of(Path.Type.file)); test.attributes().setSize(0L); final Path copy = new Path(directory, UUID.randomUUID().toString(), EnumSet.of(Path.Type.file)); final CopyTransfer t = new CopyTransfer(host, host, Collections.singletonMap(test, copy)) { @Override public TransferAction action(final Session<?> source, final Session<?> destination, final boolean resumeRequested, final boolean reloadRequested, final TransferPrompt prompt, final ListProgressListener listener) { return TransferAction.overwrite; } }; final AbstractController controller = new AbstractController() { @Override public void invoke(final MainAction runnable, final boolean wait) { runnable.run(); } }; final AtomicBoolean start = new AtomicBoolean(); final AtomicBoolean stop = new AtomicBoolean(); final Session session = new NullTransferSession(host); final Session destination = new NullTransferSession(host); final TransferBackgroundAction action = new TransferBackgroundAction(controller, new StatelessSessionPool( new TestLoginConnectionService(), session, PathCache.empty(), new DisabledTranscriptListener(), new DefaultVaultRegistry(new DisabledPasswordCallback())), new StatelessSessionPool( new TestLoginConnectionService(), destination, PathCache.empty(), new DisabledTranscriptListener(), new DefaultVaultRegistry(new DisabledPasswordCallback())), new TransferListener() { @Override public void transferDidStart(final Transfer transfer) { assertEquals(t, transfer); start.set(true); } @Override public void transferDidStop(final Transfer transfer) { assertEquals(t, transfer); stop.set(true); } @Override public void transferDidProgress(final Transfer transfer, final TransferProgress status) { // } }, t, new TransferOptions()); action.prepare(); action.call(); assertTrue(destination.isConnected()); action.finish(); assertFalse(action.hasFailed()); assertTrue(start.get()); assertTrue(stop.get()); assertTrue(t.isComplete()); assertNotNull(t.getTimestamp()); } @Test public void testCopyBetweenHosts() throws Exception { final Session session = new NullTransferSession(new Host(new TestProtocol(), "test.cyberduck.ch")); final Session destination = new NullTransferSession(new Host(new TestProtocol(), "test.cyberduck.ch")); final Path directory = new Path("/home/jenkins/transfer", EnumSet.of(Path.Type.directory)); final Path test = new Path(directory, "test", EnumSet.of(Path.Type.file)); test.attributes().setSize(0L); final Path copy = new Path(new Path("/transfer", EnumSet.of(Path.Type.directory)), UUID.randomUUID().toString(), EnumSet.of(Path.Type.file)); final Transfer t = new CopyTransfer(session.getHost(), destination.getHost(), Collections.singletonMap(test, copy)) { @Override public TransferAction action(final Session<?> source, final Session<?> destination, final boolean resumeRequested, final boolean reloadRequested, final TransferPrompt prompt, final ListProgressListener listener) { return TransferAction.overwrite; } }; final AbstractController controller = new AbstractController() { @Override public void invoke(final MainAction runnable, final boolean wait) { runnable.run(); } }; final AtomicBoolean start = new AtomicBoolean(); final AtomicBoolean stop = new AtomicBoolean(); final TransferBackgroundAction action = new TransferBackgroundAction(controller, new StatelessSessionPool( new TestLoginConnectionService(), session, PathCache.empty(), new DisabledTranscriptListener(), new DefaultVaultRegistry(new DisabledPasswordCallback())), new StatelessSessionPool( new TestLoginConnectionService(), destination, PathCache.empty(), new DisabledTranscriptListener(), new DefaultVaultRegistry(new DisabledPasswordCallback())), new TransferListener() { @Override public void transferDidStart(final Transfer transfer) { assertEquals(t, transfer); start.set(true); } @Override public void transferDidStop(final Transfer transfer) { assertEquals(t, transfer); stop.set(true); } @Override public void transferDidProgress(final Transfer transfer, final TransferProgress status) { // } }, t, new TransferOptions()); action.prepare(); action.call(); action.finish(); assertFalse(action.hasFailed()); assertTrue(start.get()); assertTrue(stop.get()); assertTrue(t.isComplete()); assertNotNull(t.getTimestamp()); } @Test public void testResumeOnRetryWithException() { final AtomicBoolean alert = new AtomicBoolean(); final AbstractController controller = new AbstractController() { @Override public void invoke(final MainAction runnable, final boolean wait) { runnable.run(); } }; final Host host = new Host(new TestProtocol(), "test.cyberduck.ch"); final TransferOptions options = new TransferOptions(); final TransferBackgroundAction action = new TransferBackgroundAction(controller, new DefaultSessionPool( new TestLoginConnectionService(), new DisabledX509TrustManager(), new DefaultX509KeyManager(), new DefaultVaultRegistry(new DisabledPasswordCallback()), PathCache.empty(), new DisabledTranscriptListener(), host) { @Override public Session<?> borrow(final BackgroundActionState callback) throws BackgroundException { throw new ConnectionRefusedException("d", new SocketException()); } }, SessionPool.DISCONNECTED, new TransferAdapter(), new DownloadTransfer(host, Collections.singletonList(new TransferItem(new Path("/home/test", EnumSet.of(Path.Type.file)), new NullLocal("/t")))), options) { @Override public boolean alert(final BackgroundException failure) { final boolean alerted = alert.get(); alert.set(true); return !alerted; } }; assertFalse(alert.get()); // Connect, prepare and run new BackgroundCallable<Boolean>(action, controller).call(); assertTrue(alert.get()); assertTrue(action.hasFailed()); // assertTrue(options.resumeRequested); } }