/**
* 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.hadoop.fs.ftp;
import java.net.URI;
import junit.framework.TestCase;
import org.apache.ftpserver.DefaultFtpServerContext;
import org.apache.ftpserver.FtpServer;
import org.apache.ftpserver.ftplet.Authority;
import org.apache.ftpserver.ftplet.UserManager;
import org.apache.ftpserver.listener.mina.MinaListener;
import org.apache.ftpserver.usermanager.BaseUser;
import org.apache.ftpserver.usermanager.WritePermission;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.dfs.DFSTestUtil;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.mapred.JobConf;
/**
* Generates a bunch of random files and directories using class 'DFSTestUtil',
* stores them on the FTP file system, copies them and check if all the files
* were retrieved successfully without any data corruption
*/
public class TestFTPFileSystem extends TestCase {
private Configuration defaultConf = new JobConf();
private FtpServer server = null;
private FileSystem localFs = null;
private FileSystem ftpFs = null;
private Path workDir = new Path(new Path(System.getProperty(
"test.build.data", "."), "data"), "TestFTPFileSystem");
Path ftpServerRoot = new Path(workDir, "FTPServer");
Path ftpServerConfig = null;
private void startServer() {
try {
DefaultFtpServerContext context = new DefaultFtpServerContext(false);
MinaListener listener = new MinaListener();
// Set port to 0 for OS to give a free port
listener.setPort(0);
context.setListener("default", listener);
// Create a test user.
UserManager userManager = context.getUserManager();
BaseUser adminUser = new BaseUser();
adminUser.setName("admin");
adminUser.setPassword("admin");
adminUser.setEnabled(true);
adminUser.setAuthorities(new Authority[] { new WritePermission() });
Path adminUserHome = new Path(ftpServerRoot, "user/admin");
adminUser.setHomeDirectory(adminUserHome.toUri().getPath());
adminUser.setMaxIdleTime(0);
userManager.save(adminUser);
// Initialize the server and start.
server = new FtpServer(context);
server.start();
} catch (Exception e) {
throw new RuntimeException("FTP server start-up failed", e);
}
}
private void stopServer() {
if (server != null) {
server.stop();
}
}
@Override
public void setUp() throws Exception {
startServer();
defaultConf = new Configuration();
localFs = FileSystem.getLocal(defaultConf);
ftpServerConfig = new Path(localFs.getWorkingDirectory(), "res");
MinaListener listener = (MinaListener) server.getServerContext()
.getListener("default");
int serverPort = listener.getPort();
ftpFs = FileSystem.get(URI.create("ftp://admin:admin@localhost:"
+ serverPort), defaultConf);
}
@Override
public void tearDown() throws Exception {
localFs.delete(ftpServerRoot, true);
localFs.delete(ftpServerConfig, true);
localFs.close();
ftpFs.close();
stopServer();
}
/**
* Tests FTPFileSystem, create(), open(), delete(), mkdirs(), rename(),
* listStatus(), getStatus() APIs. *
*
* @throws Exception
*/
public void testReadWrite() throws Exception {
DFSTestUtil util = new DFSTestUtil("TestFTPFileSystem", 20, 3, 1024 * 1024);
localFs.setWorkingDirectory(workDir);
Path localData = new Path(workDir, "srcData");
Path remoteData = new Path("srcData");
util.createFiles(localFs, localData.toUri().getPath());
boolean dataConsistency = util.checkFiles(localFs, localData.getName());
assertTrue("Test data corrupted", dataConsistency);
// Copy files and directories recursively to FTP file system.
boolean filesCopied = FileUtil.copy(localFs, localData, ftpFs, remoteData,
false, defaultConf);
assertTrue("Copying to FTPFileSystem failed", filesCopied);
// Rename the remote copy
Path renamedData = new Path("Renamed");
boolean renamed = ftpFs.rename(remoteData, renamedData);
assertTrue("Rename failed", renamed);
// Copy files and directories from FTP file system and delete remote copy.
filesCopied = FileUtil.copy(ftpFs, renamedData, localFs, workDir, true,
defaultConf);
assertTrue("Copying from FTPFileSystem fails", filesCopied);
// Check if the data was received completely without any corruption.
dataConsistency = util.checkFiles(localFs, renamedData.getName());
assertTrue("Invalid or corrupted data recieved from FTP Server!",
dataConsistency);
// Delete local copies
boolean deleteSuccess = localFs.delete(renamedData, true)
& localFs.delete(localData, true);
assertTrue("Local test data deletion failed", deleteSuccess);
}
}