blob: 4c2cc38d8f0fe41c94f153a4329f3569f3cf2ba7 [file] [log] [blame]
/**
* 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.
*/
import org.apache.hadoop.hdfs.*;
import junit.framework.TestCase;
import java.io.*;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.fs.permission.*;
import java.net.*;
/**
* This class tests that the Fuse module for DFS can mount properly
* and does a few simple commands:
* mkdir
* rmdir
* ls
* cat
*
* cp and touch are purposely not tested because they won't work with the current module
*
*/
public class TestFuseDFS extends TestCase {
/**
* mount the fuse file system using assumed fuse module library installed in /usr/local/lib or somewhere else on your
* pre-existing LD_LIBRARY_PATH
*
*/
static Process fuse_process;
static String fuse_cmd;
static private void mount(String mountpoint, URI dfs) throws IOException, InterruptedException {
String cp = System.getProperty("java.class.path");
Runtime r = Runtime.getRuntime();
fuse_cmd = System.getProperty("build.test") + "/../fuse_dfs";
String libhdfs = System.getProperty("build.test") + "/../../../libhdfs/";
String arch = System.getProperty("os.arch");
String jvm = System.getProperty("java.home") + "/lib/" + arch + "/server";
String lp = System.getProperty("LD_LIBRARY_PATH") + ":" + "/usr/local/lib:" + libhdfs + ":" + jvm;
System.err.println("LD_LIBRARY_PATH=" + lp);
String cmd[] = { fuse_cmd, "dfs://" + dfs.getHost() + ":" + String.valueOf(dfs.getPort()),
mountpoint, "-obig_writes", "-odebug", "-oentry_timeout=0.1", "-oattribute_timeout=0.1", "-ousetrash", "rw", "-oinitchecks",
"-ordbuffer=32768"};
final String [] envp = {
"CLASSPATH="+ cp,
"LD_LIBRARY_PATH=" + lp,
"PATH=" + "/usr/bin:/bin"
};
// ensure the mount point is not currently mounted
Process p = r.exec("fusermount -u " + mountpoint);
p.waitFor();
// clean up the mount point
p = r.exec("rm -rf " + mountpoint);
assertTrue(p.waitFor() == 0);
// make the mount point if needed
p = r.exec("mkdir -p " + mountpoint);
assertTrue(p.waitFor() == 0);
// mount fuse to the mount point
fuse_process = r.exec(cmd, envp);
// give DFS a chance to come up
try { Thread.sleep(3000); } catch(Exception e) { }
}
/**
* unmounts fuse for before shutting down.
*/
static private void umount(String mpoint) throws IOException, InterruptedException {
Runtime r= Runtime.getRuntime();
Process p = r.exec("fusermount -u " + mpoint);
p.waitFor();
}
/**
* Set things up - create mini dfs cluster and mount the fuse filesystem.
*/
public TestFuseDFS() throws IOException,InterruptedException {
}
static private MiniDFSCluster cluster;
static private DistributedFileSystem fileSys;
final static private String mpoint;
static {
mpoint = System.getProperty("build.test") + "/mnt";
System.runFinalizersOnExit(true);
startStuff();
}
static public void startStuff() {
try {
Configuration conf = new HdfsConfiguration();
conf.setBoolean(DFSConfigKeys.DFS_PERMISSIONS_ENABLED_KEY,false);
cluster = new MiniDFSCluster(conf, 1, true, null);
fileSys = (DistributedFileSystem)cluster.getFileSystem();
assertTrue(fileSys.getFileStatus(new Path("/")).isDir());
mount(mpoint, fileSys.getUri());
} catch(Exception e) {
e.printStackTrace();
}
}
public void setUp() {
}
/**
* use shell to create a dir and then use filesys to see it exists.
*/
public void testMkdir() throws IOException,InterruptedException, Exception {
try {
// First create a new directory with mkdirs
Path path = new Path("/foo");
Runtime r = Runtime.getRuntime();
String cmd = "mkdir -p " + mpoint + path.toString();
Process p = r.exec(cmd);
assertTrue(p.waitFor() == 0);
// check it is there
assertTrue(fileSys.getFileStatus(path).isDir());
// check again through the shell
String lsCmd = "ls " + mpoint + path.toString();
p = r.exec(lsCmd);
assertTrue(p.waitFor() == 0);
} catch(Exception e) {
e.printStackTrace();
throw e;
}
}
/**
* use shell to create a dir and then use filesys to see it exists.
*/
public void testWrites() throws IOException,InterruptedException {
try {
// write a hello file
File file = new File(mpoint, "hello.txt");
FileOutputStream f = new FileOutputStream(file);
String s = "hello ";
f.write(s.getBytes());
s = "world";
f.write(s.getBytes());
f.flush();
f.close();
try {
Thread.sleep(1000);
} catch(Exception e) {
}
// check the file exists.
Path myPath = new Path("/hello.txt");
assertTrue(fileSys.exists(myPath));
// check the data is ok
FileInputStream fi = new FileInputStream(new File(mpoint, "hello.txt"));
byte b[] = new byte[12];
int length = fi.read(b,0,12);
assertTrue(length > 0);
String s2 = new String( b, 0, length);
assertEquals("hello world", s2);
} catch(Exception e) {
e.printStackTrace();
} finally {
}
}
/**
* Test ls for dir already created in testMkdDir also tests bad ls
*/
public void testLs() throws IOException,InterruptedException {
try {
// First create a new directory with mkdirs
Runtime r = Runtime.getRuntime();
// mkdir
Process p = r.exec("mkdir -p " + mpoint + "/test/mkdirs");
assertTrue(p.waitFor() == 0);
// ls
p = r.exec("ls " + mpoint + "/test/mkdirs");
assertTrue(p.waitFor() == 0);
// ls non-existant directory
p = r.exec("ls " + mpoint + "/test/mkdirsNotThere");
int res = p.waitFor();
assertFalse(res == 0);
} catch(Exception e) {
e.printStackTrace();
}
}
/**
* Remove a dir using the shell and use filesys to see it no longer exists.
*/
public void testRmdir() throws IOException,InterruptedException {
try {
// First create a new directory with mkdirs
Runtime r = Runtime.getRuntime();
Process p = r.exec("mkdir -p " + mpoint + "/test/rmdir");
assertTrue(p.waitFor() == 0);
Path myPath = new Path("/test/rmdir");
assertTrue(fileSys.exists(myPath));
// remove it
p = r.exec("rmdir " + mpoint + "/test/rmdir");
assertTrue(p.waitFor() == 0);
// check it is not there
assertFalse(fileSys.exists(myPath));
Path trashPath = new Path("/user/root/.Trash/Current/test/rmdir");
assertTrue(fileSys.exists(trashPath));
// make it again to test trashing same thing twice
p = r.exec("mkdir -p " + mpoint + "/test/rmdir");
assertTrue(p.waitFor() == 0);
assertTrue(fileSys.exists(myPath));
// remove it
p = r.exec("rmdir " + mpoint + "/test/rmdir");
assertTrue(p.waitFor() == 0);
// check it is not there
assertFalse(fileSys.exists(myPath));
trashPath = new Path("/user/root/.Trash/Current/test/rmdir.1");
assertTrue(fileSys.exists(trashPath));
} catch(Exception e) {
e.printStackTrace();
}
}
/**
* use shell to create a dir and then use filesys to see it exists.
*/
public void testDF() throws IOException,InterruptedException, Exception {
try {
// First create a new directory with mkdirs
Path path = new Path("/foo");
Runtime r = Runtime.getRuntime();
String cmd = "mkdir -p " + mpoint + path.toString();
Process p = r.exec(cmd);
assertTrue(p.waitFor() == 0);
File f = new File(mpoint + "/foo");
DistributedFileSystem.DiskStatus d = fileSys.getDiskStatus();
long fileUsedBlocks = (f.getTotalSpace() - f.getFreeSpace())/(64 * 1024 * 1024);
long dfsUsedBlocks = (long)Math.ceil((double)d.getDfsUsed()/(64 * 1024 * 1024));
assertTrue(fileUsedBlocks == dfsUsedBlocks);
assertTrue(d.getCapacity() == f.getTotalSpace());
} catch(Exception e) {
e.printStackTrace();
throw e;
}
}
/**
* use shell to create a dir and then use filesys to see it exists.
*/
public void testChown() throws IOException,InterruptedException, Exception {
try {
// First create a new directory with mkdirs
Path path = new Path("/foo");
Runtime r = Runtime.getRuntime();
String cmd = "mkdir -p " + mpoint + path.toString();
Process p = r.exec(cmd);
assertTrue(p.waitFor() == 0);
// check it is there
assertTrue(fileSys.getFileStatus(path).isDir());
FileStatus foo = fileSys.getFileStatus(path);
System.err.println("DEBUG:owner=" + foo.getOwner());
cmd = "chown nobody " + mpoint + path.toString();
p = r.exec(cmd);
assertTrue(p.waitFor() == 0);
// cmd = "chgrp nobody " + mpoint + path.toString();
// p = r.exec(cmd);
// assertTrue(p.waitFor() == 0);
foo = fileSys.getFileStatus(path);
System.err.println("DEBUG:owner=" + foo.getOwner());
assertTrue(foo.getOwner().equals("nobody"));
assertTrue(foo.getGroup().equals("nobody"));
} catch(Exception e) {
e.printStackTrace();
throw e;
}
}
/**
* use shell to create a dir and then use filesys to see it exists.
*/
public void testChmod() throws IOException,InterruptedException, Exception {
try {
// First create a new directory with mkdirs
Path path = new Path("/foo");
Runtime r = Runtime.getRuntime();
String cmd = "mkdir -p " + mpoint + path.toString();
Process p = r.exec(cmd);
assertTrue(p.waitFor() == 0);
// check it is there
assertTrue(fileSys.getFileStatus(path).isDir());
cmd = "chmod 777 " + mpoint + path.toString();
p = r.exec(cmd);
assertTrue(p.waitFor() == 0);
FileStatus foo = fileSys.getFileStatus(path);
FsPermission perm = foo.getPermission();
assertTrue(perm.toShort() == 0777);
} catch(Exception e) {
e.printStackTrace();
throw e;
}
}
/**
* use shell to create a dir and then use filesys to see it exists.
*/
public void testUtimes() throws IOException,InterruptedException, Exception {
try {
// First create a new directory with mkdirs
Path path = new Path("/utimetest");
Runtime r = Runtime.getRuntime();
String cmd = "touch " + mpoint + path.toString();
Process p = r.exec(cmd);
assertTrue(p.waitFor() == 0);
// check it is there
assertTrue(fileSys.exists(path));
FileStatus foo = fileSys.getFileStatus(path);
long oldTime = foo.getModificationTime();
try { Thread.sleep(1000); } catch(Exception e) {}
cmd = "touch " + mpoint + path.toString();
p = r.exec(cmd);
assertTrue(p.waitFor() == 0);
try { Thread.sleep(1000); } catch(Exception e) {}
foo = fileSys.getFileStatus(path);
long newTime = foo.getModificationTime();
assertTrue(newTime > oldTime);
} catch(Exception e) {
e.printStackTrace();
throw e;
} finally {
}
}
/**
*
* Test dfs_read on a file size that will trigger multiple internal reads.
* First, just check raw size reading is ok and then check with smaller reads
* including checking the validity of the data read.
*
*/
public void testReads() throws IOException,InterruptedException {
try {
// First create a new directory with mkdirs
Runtime r = Runtime.getRuntime();
Process p;
// create the file
Path myPath = new Path("/test/hello.reads");
FSDataOutputStream s = fileSys.create(myPath);
String hello = "hello world!";
int written = 0;
int mycount = 0;
while(written < 1024 * 9) {
s.writeUTF(hello);
s.writeInt(mycount++);
written += hello.length() + 4;
}
s.close();
// check it exists
assertTrue(fileSys.exists(myPath));
FileStatus foo = fileSys.getFileStatus(myPath);
assertTrue(foo.getLen() >= 9 * 1024);
{
// cat the file
DataInputStream is = new DataInputStream(new FileInputStream(mpoint + "/test/hello.reads"));
byte buf [] = new byte[4096];
// test reading 0 length
assertTrue(is.read(buf, 0, 0) == 0);
// test real reads
assertTrue(is.read(buf, 0, 1024) == 1024);
assertTrue(is.read(buf, 0, 4096) == 4096);
assertTrue(is.read(buf, 0, 4096) == 4096);
is.close();
}
{
DataInputStream is = new DataInputStream(new FileInputStream(mpoint + "/test/hello.reads"));
int read = 0;
int counter = 0;
try {
while(true) {
String s2 = DataInputStream.readUTF(is);
int s3 = is.readInt();
assertTrue(s2.equals(hello));
assertTrue(s3 == counter++);
read += hello.length() + 4;
}
} catch(EOFException e) {
assertTrue(read >= 9 * 1024);
}
}
// check reading an empty file for EOF
{
// create the file
myPath = new Path("/test/hello.reads2");
s = fileSys.create(myPath);
s.close();
FSDataInputStream fs = fileSys.open(myPath);
assertEquals(-1, fs.read());
FileInputStream f = new FileInputStream(mpoint + "/test/hello.reads2");
assertEquals(-1, f.read());
}
} catch(Exception e) {
e.printStackTrace();
} finally {
}
}
/**
* Use filesys to create the hello world! file and then cat it and see its contents are correct.
*/
public void testCat() throws IOException,InterruptedException {
try {
// First create a new directory with mkdirs
Runtime r = Runtime.getRuntime();
Process p = r.exec("rm -rf " + mpoint + "/test/hello");
assertTrue(p.waitFor() == 0);
// create the file
Path myPath = new Path("/test/hello");
FSDataOutputStream s = fileSys.create(myPath);
String hello = "hello world!";
s.writeUTF(hello);
s.writeInt(1033);
s.close();
// check it exists
assertTrue(fileSys.exists(myPath));
// cat the file
DataInputStream is = new DataInputStream(new FileInputStream(mpoint + "/test/hello"));
String s2 = DataInputStream.readUTF(is);
int s3 = is.readInt();
assertTrue(s2.equals(hello));
assertTrue(s3 == 1033);
} catch(Exception e) {
e.printStackTrace();
} finally {
}
}
/**
* Use filesys to create the hello world! file and then cat it and see its contents are correct.
*/
public void testAppends() throws IOException,InterruptedException {
try {
// First create a new directory with mkdirs
Runtime r = Runtime.getRuntime();
{
FileOutputStream os = new FileOutputStream(mpoint + "/appends");
String hello = "hello";
os.write(hello.getBytes());
os.flush();
os.close();
}
// check it exists
Path myPath = new Path("/appends");
assertTrue(fileSys.exists(myPath));
try {
Thread.sleep(1000);
} catch(Exception e) {
}
FileStatus foo = fileSys.getFileStatus(myPath);
File f = new File(mpoint + "/appends");
assertTrue(f.length() > 0);
{
FileOutputStream os = new FileOutputStream(mpoint + "/appends", true);
String hello = " world!";
os.write(hello.getBytes());
os.flush();
os.close();
}
// cat the file
FileInputStream is = new FileInputStream(mpoint + "/appends");
byte b[] = new byte[1024];
int len = is.read(b);
assertTrue(len > 0);
String s2 = new String(b,0,len);
assertTrue(s2.equals("hello world!"));
} catch(Exception e) {
e.printStackTrace();
} finally {
}
}
public void testDone() throws IOException {
close();
}
/**
* Unmount and close
*/
protected void tearDown() throws Exception {
}
/**
* Unmount and close
*/
protected void finalize() throws Throwable {
close();
}
public void close() {
try {
int length;
// print out the fuse debug output
{
do {
InputStream i = fuse_process.getInputStream();
byte b[] = new byte[i.available()];
length = i.read(b);
System.err.println("read x bytes: " + length);
System.err.write(b,0,b.length);
} while(length > 0) ;
}
do {
InputStream i = fuse_process.getErrorStream();
byte b[] = new byte[i.available()];
length = i.read(b);
System.err.println("read x bytes: " + length);
System.err.write(b,0,b.length);
} while(length > 0) ;
umount(mpoint);
fuse_process.destroy();
fuse_process = null;
if(fileSys != null) {
fileSys.close();
fileSys = null;
}
if(cluster != null) {
cluster.shutdown();
cluster = null;
}
} catch(Exception e) { }
}
};