You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2011/11/09 23:47:15 UTC
svn commit: r1200017 - in /commons/proper/vfs/trunk: core/pom.xml
core/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java
core/src/test/java/org/apache/commons/vfs2/util/FreeSocketPortUtil.java
pom.xml
Author: ggregory
Date: Wed Nov 9 22:47:15 2011
New Revision: 1200017
URL: http://svn.apache.org/viewvc?rev=1200017&view=rev
Log:
Tests with an embedded Apache SSHd (MINA) server unless the user provides a system property to a SSH server URL.
Added:
commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/util/FreeSocketPortUtil.java
Modified:
commons/proper/vfs/trunk/core/pom.xml
commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java
commons/proper/vfs/trunk/pom.xml
Modified: commons/proper/vfs/trunk/core/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/pom.xml?rev=1200017&r1=1200016&r2=1200017&view=diff
==============================================================================
--- commons/proper/vfs/trunk/core/pom.xml (original)
+++ commons/proper/vfs/trunk/core/pom.xml Wed Nov 9 22:47:15 2011
@@ -97,6 +97,22 @@
<artifactId>slf4j-log4j12</artifactId>
<scope>test</scope>
</dependency>
+ <!-- SSHd -->
+ <dependency>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcprov-jdk15</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<properties>
Modified: commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java?rev=1200017&r1=1200016&r2=1200017&view=diff
==============================================================================
--- commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java (original)
+++ commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java Wed Nov 9 22:47:15 2011
@@ -16,6 +16,13 @@
*/
package org.apache.commons.vfs2.provider.sftp.test;
+import java.io.File;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.List;
+
import junit.framework.Test;
import org.apache.commons.vfs2.FileObject;
@@ -27,36 +34,250 @@ import org.apache.commons.vfs2.provider.
import org.apache.commons.vfs2.provider.sftp.TrustEveryoneUserInfo;
import org.apache.commons.vfs2.test.AbstractProviderTestConfig;
import org.apache.commons.vfs2.test.ProviderTestSuite;
+import org.apache.commons.vfs2.util.FreeSocketPortUtil;
+import org.apache.ftpserver.ftplet.FtpException;
+import org.apache.sshd.SshServer;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Session;
+import org.apache.sshd.common.util.SecurityUtils;
+import org.apache.sshd.server.Command;
+import org.apache.sshd.server.FileSystemFactory;
+import org.apache.sshd.server.FileSystemView;
+import org.apache.sshd.server.ForwardingFilter;
+import org.apache.sshd.server.PasswordAuthenticator;
+import org.apache.sshd.server.PublickeyAuthenticator;
+import org.apache.sshd.server.SshFile;
+import org.apache.sshd.server.auth.UserAuthNone;
+import org.apache.sshd.server.filesystem.NativeSshFile;
+import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider;
+import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
+import org.apache.sshd.server.session.ServerSession;
+import org.apache.sshd.server.sftp.SftpSubsystem;
/**
- * Test cases for the SFTP provider.
- *
+ * Tests cases for the SFTP provider.
+ * <p>
+ * Starts and stops an embedded Apache SSHd (MINA) server.
+ * </p>
+ *
* @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
*/
-public class SftpProviderTestCase
- extends AbstractProviderTestConfig
+public class SftpProviderTestCase extends AbstractProviderTestConfig
{
+ /**
+ * Implements FileSystemFactory because SSHd does not know about users and home directories.
+ */
+ static final class TestFileSystemFactory implements FileSystemFactory
+ {
+ /**
+ * Accepts only the known test user.
+ */
+ public FileSystemView createFileSystemView(Session session) throws IOException
+ {
+ final String userName = session.getUsername();
+ if (!DEFAULT_USER.equals(userName))
+ {
+ return null;
+ }
+ return new TestFileSystemView(getTestDirectory(), userName);
+ }
+ }
+
+ /**
+ * Implements FileSystemView because SSHd does not know about users and home directories.
+ */
+ static final class TestFileSystemView implements FileSystemView
+ {
+ private final String homeDirStr;
+
+ private final String userName;
+
+ // private boolean caseInsensitive;
+
+ public TestFileSystemView(String homeDirStr, String userName)
+ {
+ this.homeDirStr = new File(homeDirStr).getAbsolutePath();
+ this.userName = userName;
+ }
+
+ public SshFile getFile(SshFile baseDir, String file)
+ {
+ return this.getFile(baseDir.getAbsolutePath(), file);
+ }
+
+ public SshFile getFile(final String file)
+ {
+ return this.getFile(homeDirStr, file);
+ }
+
+ protected SshFile getFile(final String dir, final String file)
+ {
+ final String home = removePrefix(NativeSshFile.normalizeSeparateChar(homeDirStr));
+ String userFileName = removePrefix(NativeSshFile.normalizeSeparateChar(file));
+ final File sshFile = userFileName.startsWith(home) ? new File(userFileName) : new File(home, userFileName);
+ userFileName = removePrefix(NativeSshFile.normalizeSeparateChar(sshFile.getAbsolutePath()));
+ return new TestNativeSshFile(userFileName, sshFile, userName);
+ }
+
+ private String removePrefix(final String s)
+ {
+ final int index = s.indexOf('/');
+ if (index < 1)
+ {
+ return s;
+ }
+ return s.substring(index);
+ }
+ }
+
+ /**
+ * Extends NativeSshFile because its constructor is protected and I do not want to create a whole NativeSshFile implementation for
+ * testing.
+ */
+ static class TestNativeSshFile extends NativeSshFile
+ {
+ TestNativeSshFile(String fileName, File file, String userName)
+ {
+ super(fileName, file, userName);
+ }
+ }
+
+ private static int SocketPort;
+
+ private static final String DEFAULT_USER = "testtest";
+
+ // private static final String DEFAULT_PWD = "testtest";
+
+ private static String ConnectionUri;
+
+ private static SshServer Server;
+
private static final String TEST_URI = "test.sftp.uri";
- public static Test suite() throws Exception
+
+ private static String getSystemTestUriOverride()
{
- if (System.getProperty(TEST_URI) != null)
+ return System.getProperty(TEST_URI);
+ }
+
+ /**
+ * Creates and starts an embedded Apache SSHd Server (MINA).
+ *
+ * @throws FtpException
+ * @throws IOException
+ */
+ private static void setUpClass() throws FtpException, IOException
+ {
+ if (Server != null)
{
- return new ProviderTestSuite(new SftpProviderTestCase());
+ return;
}
- else
+ // System.setProperty("vfs.sftp.sshdir", getTestDirectory() + "/../vfs.sftp.sshdir");
+ String tmpDir = System.getProperty("java.io.tmpdir");
+ Server = SshServer.setUpDefaultServer();
+ Server.setPort(SocketPort);
+ if (SecurityUtils.isBouncyCastleRegistered())
+ {
+ Server.setKeyPairProvider(new PEMGeneratorHostKeyProvider(tmpDir + "/key.pem"));
+ } else
{
- return notConfigured(SftpProviderTestCase.class);
+ Server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(tmpDir + "/key.ser"));
}
+ List<NamedFactory<Command>> list = new ArrayList<NamedFactory<Command>>(1);
+ list.add(new SftpSubsystem.Factory());
+ Server.setSubsystemFactories(list);
+ Server.setPasswordAuthenticator(new PasswordAuthenticator()
+ {
+ public boolean authenticate(String username, String password, ServerSession session)
+ {
+ return username != null && username.equals(password);
+ }
+ });
+ Server.setPublickeyAuthenticator(new PublickeyAuthenticator()
+ {
+ public boolean authenticate(String username, PublicKey key, ServerSession session)
+ {
+ // File f = new File("/Users/" + username + "/.ssh/authorized_keys");
+ return true;
+ }
+ });
+ Server.setForwardingFilter(new ForwardingFilter()
+ {
+ public boolean canConnect(InetSocketAddress address, ServerSession session)
+ {
+ return true;
+ }
+
+ public boolean canForwardAgent(ServerSession session)
+ {
+ return true;
+ }
+
+ public boolean canForwardX11(ServerSession session)
+ {
+ return true;
+ }
+
+ public boolean canListen(InetSocketAddress address, ServerSession session)
+ {
+ return true;
+ }
+ });
+ // HACK Start
+ // How do we really do simple user to directory matching?
+ Server.setFileSystemFactory(new TestFileSystemFactory());
+ // HACK End
+ Server.start();
+ // HACK Start
+ // How do we really do simple security?
+ // Do this after we start the server to simplify this set up code.
+ Server.getUserAuthFactories().add(new UserAuthNone.Factory());
+ // HACK End
}
/**
- * Prepares the file system manager.
+ * Creates the test suite for the ftp file system.
*/
- @Override
- public void prepare(final DefaultFileSystemManager manager)
- throws Exception
+ public static Test suite() throws Exception
{
- manager.addProvider("sftp", new SftpFileProvider());
+ return new ProviderTestSuite(new SftpProviderTestCase())
+ {
+ @Override
+ protected void setUp() throws Exception
+ {
+ if (getSystemTestUriOverride() == null)
+ {
+ setUpClass();
+ }
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ tearDownClass();
+ super.tearDown();
+ }
+ };
+ }
+
+ /**
+ * Stops the embedded Apache SSHd Server (MINA).
+ *
+ * @throws InterruptedException
+ */
+ private static void tearDownClass() throws InterruptedException
+ {
+ if (Server != null)
+ {
+ Server.stop();
+ }
+ }
+
+ public SftpProviderTestCase() throws IOException
+ {
+ SocketPort = FreeSocketPortUtil.findFreeLocalPort();
+ // Use %40 for @ in the FTP URL password if you need a @
+ ConnectionUri = String.format("sftp://%s@localhost:%d", DEFAULT_USER, SocketPort);
}
/**
@@ -65,7 +286,11 @@ public class SftpProviderTestCase
@Override
public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
{
- final String uri = System.getProperty(TEST_URI);
+ String uri = getSystemTestUriOverride();
+ if (uri == null)
+ {
+ uri = ConnectionUri;
+ }
FileSystemOptions fileSystemOptions = new FileSystemOptions();
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(fileSystemOptions, "no");
@@ -73,4 +298,13 @@ public class SftpProviderTestCase
return manager.resolveFile(uri, fileSystemOptions);
}
+
+ /**
+ * Prepares the file system manager.
+ */
+ @Override
+ public void prepare(final DefaultFileSystemManager manager) throws Exception
+ {
+ manager.addProvider("sftp", new SftpFileProvider());
+ }
}
Added: commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/util/FreeSocketPortUtil.java
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/util/FreeSocketPortUtil.java?rev=1200017&view=auto
==============================================================================
--- commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/util/FreeSocketPortUtil.java (added)
+++ commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/util/FreeSocketPortUtil.java Wed Nov 9 22:47:15 2011
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.commons.vfs2.util;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+
+public class FreeSocketPortUtil
+{
+
+ public static void main(String[] args) throws IOException
+ {
+ System.out.println(FreeSocketPortUtil.findFreeLocalPort());
+ }
+
+ /**
+ * Finds a free local socket port.
+ *
+ * @return a free local socket port.
+ * @throws IOException
+ */
+ public static int findFreeLocalPort() throws IOException
+ {
+ ServerSocket server = new ServerSocket(0);
+ try
+ {
+ return server.getLocalPort();
+ } finally
+ {
+ server.close();
+ }
+ }
+}
Modified: commons/proper/vfs/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/pom.xml?rev=1200017&r1=1200016&r2=1200017&view=diff
==============================================================================
--- commons/proper/vfs/trunk/pom.xml (original)
+++ commons/proper/vfs/trunk/pom.xml Wed Nov 9 22:47:15 2011
@@ -380,6 +380,25 @@
<version>1.6.3</version>
<scope>test</scope>
</dependency>
+ <!-- SSHd -->
+ <dependency>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-core</artifactId>
+ <version>0.6.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcprov-jdk15</artifactId>
+ <version>1.46</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.1</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</dependencyManagement>
@@ -433,10 +452,8 @@
</site>
</distributionManagement>
- <!-- Releasing VFS as a multi-module build with binary artifacts is somewhat
- painful. This profile hooks into the commons-parent and the apache-pom to
- get the build done and then uses the assembly to package it up.
- -->
+ <!-- Releasing VFS as a multi-module build with binary artifacts is somewhat painful. This profile hooks into the commons-parent and the apache-pom
+ to get the build done and then uses the assembly to package it up. -->
<profiles>
<profile>
<id>include-sandbox</id>