View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.vfs2.provider.sftp;
18  
19  import java.io.File;
20  import java.util.ArrayList;
21  import java.util.List;
22  import java.util.concurrent.Callable;
23  import java.util.concurrent.ExecutorService;
24  import java.util.concurrent.Executors;
25  import java.util.concurrent.Future;
26  import java.util.concurrent.TimeUnit;
27  
28  import org.apache.commons.vfs2.AbstractProviderTestCase;
29  import org.apache.commons.vfs2.Capability;
30  import org.apache.commons.vfs2.FileObject;
31  import org.apache.commons.vfs2.Selectors;
32  import org.apache.commons.vfs2.VFS;
33  import org.junit.Test;
34  
35  /**
36   * MultiThread tests for writing with SFTP provider.
37   */
38  public class SftpMultiThreadWriteTests extends AbstractProviderTestCase {
39  
40      /**
41       * Sets up a scratch folder for the test to use.
42       */
43      protected FileObject createScratchFolder() throws Exception {
44          final FileObject scratchFolder = getWriteFolder();
45  
46          // Make sure the test folder is empty
47          scratchFolder.delete(Selectors.EXCLUDE_SELF);
48          scratchFolder.createFolder();
49  
50          return scratchFolder;
51      }
52  
53      /**
54       * Returns the capabilities required by the tests of this test case.
55       */
56      @Override
57      protected Capability[] getRequiredCapabilities() {
58          return new Capability[] {Capability.CREATE, Capability.DELETE, Capability.GET_TYPE, Capability.LIST_CHILDREN,
59              Capability.READ_CONTENT, Capability.WRITE_CONTENT};
60      }
61  
62      /**
63       * Tests file copy from local file system in parallel mode. This was a problem with SFTP channels.
64       */
65      @Test
66      public void testParallelCopyFromLocalFileSystem() throws Exception {
67          final File localFile = new File("src/test/resources/test-data/test.zip");
68  
69          final FileObject localFileObject = VFS.getManager().toFileObject(localFile);
70  
71          final FileObject scratchFolder = createScratchFolder();
72  
73          final List<Callable<Boolean>> tasks = new ArrayList<>();
74          for (int i = 0; i < 100; i++) {
75              final String fileName = "file" + i + "copy.txt";
76              tasks.add(() -> {
77                  try {
78                      final FileObject fileObjectCopy = scratchFolder.resolveFile(fileName);
79  
80                      assertFalse(fileObjectCopy.exists());
81                      fileObjectCopy.copyFrom(localFileObject, Selectors.SELECT_SELF);
82                  } catch (final Throwable e) {
83                      return false;
84                  }
85                  return true;
86              });
87          }
88  
89          final ExecutorService service = Executors.newFixedThreadPool(10);
90          try {
91              final List<Future<Boolean>> futures = service.invokeAll(tasks);
92              assertTrue(futures.stream().allMatch(future -> {
93                  try {
94                      return future.get(5, TimeUnit.SECONDS);
95                  } catch (final Exception e) {
96                      return false;
97                  }
98              }));
99          } finally {
100             service.shutdown();
101         }
102     }
103 }