/**
* 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;
import java.io.File;
import java.io.IOException;
import java.io.DataOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.HashSet;
import java.util.Set;
import junit.framework.TestCase;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FsShell;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.Trash;
import org.apache.hadoop.fs.LocalFileSystem;
import org.apache.hadoop.hdfs.DFSUtil;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* This class tests commands from Trash.
*/
public class TestTrash {
public final static Path TEST_DIR =
new Path(new File(System.getProperty("test.build.data","/tmp")
).toString().replace(' ', '+'), "testTrash");
@Before
public void setUp() throws Exception {
File testDir = new File(TEST_DIR.toUri().getPath());
if (testDir.exists()) {
FileUtil.fullyDelete(testDir);
testDir.mkdirs();
}
}
protected static Path writeFile(FileSystem fs, Path f) throws IOException {
DataOutputStream out = fs.create(f);
out.writeBytes("dhruba: " + f);
out.close();
assertTrue(fs.exists(f));
return f;
}
protected static Path mkdir(FileSystem fs, Path p) throws IOException {
assertTrue(fs.mkdirs(p));
assertTrue(fs.exists(p));
assertTrue(fs.getFileStatus(p).isDir());
return p;
}
// check that the specified file is in Trash
public static void checkTrash(FileSystem fs, Path trashRoot,
Path path) throws IOException {
Path p = new Path(trashRoot+"/"+ path.toUri().getPath());
assertTrue(fs.exists(p));
}
// check that the specified file is not in Trash
public static void checkNotInTrash(FileSystem fs, Path trashRoot, String pathname)
throws IOException {
Path p = new Path(trashRoot+"/"+ new Path(pathname).getName());
assertTrue(!fs.exists(p));
}
protected static void trashShell(final FileSystem fs, final Path base)
throws IOException {
Configuration conf = new Configuration();
conf.set("fs.trash.interval", "10"); // 10 minute
conf.set("fs.default.name", fs.getUri().toString());
FsShell shell = new FsShell();
shell.setConf(conf);
Path trashRoot = null;
// First create a new directory with mkdirs
Path myPath = new Path(base, "test/mkdirs");
mkdir(fs, myPath);
// Second, create a file in that directory.
Path myFile = new Path(base, "test/mkdirs/myFile");
writeFile(fs, myFile);
// Verify that expunge without Trash directory
// won't throw Exception
{
String[] args = new String[1];
args[0] = "-expunge";
int val = -1;
try {
val = shell.run(args);
} catch (Exception e) {
System.err.println("Exception raised from Trash.run " +
e.getLocalizedMessage());
}
assertTrue(val == 0);
}
// Verify that we succeed in removing the file we created.
// This should go into Trash.
{
String[] args = new String[2];
args[0] = "-rm";
args[1] = myFile.toString();
int val = -1;
try {
val = shell.run(args);
} catch (Exception e) {
System.err.println("Exception raised from Trash.run " +
e.getLocalizedMessage());
}
assertTrue(val == 0);
trashRoot = shell.getCurrentTrashDir();
checkTrash(fs, trashRoot, myFile);
}
// Verify that we can recreate the file
writeFile(fs, myFile);
// Verify that we succeed in removing the file we re-created
{
String[] args = new String[2];
args[0] = "-rm";
args[1] = new Path(base, "test/mkdirs/myFile").toString();
int val = -1;
try {
val = shell.run(args);
} catch (Exception e) {
System.err.println("Exception raised from Trash.run " +
e.getLocalizedMessage());
}
assertTrue(val == 0);
}
// Verify that we can recreate the file
writeFile(fs, myFile);
// Verify that we succeed in removing the whole directory
// along with the file inside it.
{
String[] args = new String[2];
args[0] = "-rmr";
args[1] = new Path(base, "test/mkdirs").toString();
int val = -1;
try {
val = shell.run(args);
} catch (Exception e) {
System.err.println("Exception raised from Trash.run " +
e.getLocalizedMessage());
}
assertTrue(val == 0);
}
// recreate directory
mkdir(fs, myPath);
// Verify that we succeed in removing the whole directory
{
String[] args = new String[2];
args[0] = "-rmr";
args[1] = new Path(base, "test/mkdirs").toString();
int val = -1;
try {
val = shell.run(args);
} catch (Exception e) {
System.err.println("Exception raised from Trash.run " +
e.getLocalizedMessage());
}
assertTrue(val == 0);
}
// Check that we can delete a file from the trash
{
Path toErase = new Path(trashRoot, "toErase");
int retVal = -1;
writeFile(fs, toErase);
try {
retVal = shell.run(new String[] {"-rm", toErase.toString()});
} catch (Exception e) {
System.err.println("Exception raised from Trash.run " +
e.getLocalizedMessage());
}
assertTrue(retVal == 0);
checkNotInTrash (fs, trashRoot, toErase.toString());
checkNotInTrash (fs, trashRoot, toErase.toString()+".1");
}
// simulate Trash removal
{
String[] args = new String[1];
args[0] = "-expunge";
int val = -1;
try {
val = shell.run(args);
} catch (Exception e) {
System.err.println("Exception raised from Trash.run " +
e.getLocalizedMessage());
}
assertTrue(val == 0);
}
// verify that after expunging the Trash, it really goes away
checkNotInTrash(fs, trashRoot, new Path(base, "test/mkdirs/myFile").toString());
// recreate directory and file
mkdir(fs, myPath);
writeFile(fs, myFile);
// remove file first, then remove directory
{
String[] args = new String[2];
args[0] = "-rm";
args[1] = myFile.toString();
int val = -1;
try {
val = shell.run(args);
} catch (Exception e) {
System.err.println("Exception raised from Trash.run " +
e.getLocalizedMessage());
}
assertTrue(val == 0);
checkTrash(fs, trashRoot, myFile);
args = new String[2];
args[0] = "-rmr";
args[1] = myPath.toString();
val = -1;
try {
val = shell.run(args);
} catch (Exception e) {
System.err.println("Exception raised from Trash.run " +
e.getLocalizedMessage());
}
assertTrue(val == 0);
checkTrash(fs, trashRoot, myPath);
}
// attempt to remove parent of trash
{
String[] args = new String[2];
args[0] = "-rmr";
args[1] = trashRoot.getParent().getParent().toString();
int val = -1;
try {
val = shell.run(args);
} catch (Exception e) {
System.err.println("Exception raised from Trash.run " +
e.getLocalizedMessage());
}
assertTrue(val == -1);
assertTrue(fs.exists(trashRoot));
}
// Verify skip trash option really works
// recreate directory and file
mkdir(fs, myPath);
writeFile(fs, myFile);
// Verify that skip trash option really skips the trash for files (rm)
{
String[] args = new String[3];
args[0] = "-rm";
args[1] = "-skipTrash";
args[2] = myFile.toString();
int val = -1;
try {
// Clear out trash
assertEquals(0, shell.run(new String [] { "-expunge" } ));
val = shell.run(args);
}catch (Exception e) {
System.err.println("Exception raised from Trash.run " +
e.getLocalizedMessage());
}
assertFalse(fs.exists(trashRoot)); // No new Current should be created
assertFalse(fs.exists(myFile));
assertTrue(val == 0);
}
// recreate directory and file
mkdir(fs, myPath);
writeFile(fs, myFile);
// Verify that skip trash option really skips the trash for rmr
{
String[] args = new String[3];
args[0] = "-rmr";
args[1] = "-skipTrash";
args[2] = myPath.toString();
int val = -1;
try {
// Clear out trash
assertEquals(0, shell.run(new String [] { "-expunge" } ));
val = shell.run(args);
}catch (Exception e) {
System.err.println("Exception raised from Trash.run " +
e.getLocalizedMessage());
}
assertFalse(fs.exists(trashRoot)); // No new Current should be created
assertFalse(fs.exists(myPath));
assertFalse(fs.exists(myFile));
assertTrue(val == 0);
}
}
public static void trashNonDefaultFS(Configuration conf) throws IOException {
conf.set("fs.trash.interval", "10"); // 10 minute
// attempt non-default FileSystem trash
{
final FileSystem lfs = FileSystem.getLocal(conf);
Path p = TEST_DIR;
Path f = new Path(p, "foo/bar");
if (lfs.exists(p)) {
lfs.delete(p, true);
}
try {
f = writeFile(lfs, f);
FileSystem.closeAll();
FileSystem localFs = FileSystem.get(URI.create("file:///"), conf);
Trash lTrash = new Trash(localFs, conf);
lTrash.moveToTrash(f.getParent());
checkTrash(localFs, lTrash.getCurrentTrashDir(), f);
} finally {
if (lfs.exists(p)) {
lfs.delete(p, true);
}
}
}
}
@Test
public void testIsTempPath() throws IOException {
TestCase.assertTrue(DeleteUtils.isTempPath("/tmp", "/tmp/a/b"));
TestCase.assertFalse(DeleteUtils.isTempPath("/tmp", "/no_tmp/a/b"));
TestCase
.assertFalse(DeleteUtils.isTempPath("/test/*/tmp", "/tmp/a/b"));
TestCase.assertTrue(DeleteUtils.isTempPath("/test/*/tmp",
"/test/di/tmp/user/f"));
TestCase.assertTrue(DeleteUtils.isTempPath("{/tmp,/test/*/tmp}",
"/tmp/a/b"));
TestCase.assertFalse(DeleteUtils.isTempPath("{/tmp,/test/*/tmp}",
"/test/a/b/tmp/c/d"));
TestCase.assertFalse(DeleteUtils.isTempPath("{/tmp,/test/*/tmp}",
"/no_tmp/a/b"));
TestCase.assertFalse(DeleteUtils.isTempPath("{/tmp,/test/*/tmp}",
"/test/di/b/c"));
TestCase.assertTrue(DeleteUtils.isTempPath("{/tmp,/test/*/tmp}",
"/test/di/tmp/f"));
TestCase.assertTrue(DeleteUtils.isTempPathUseDefaultOnFailure("relative_path",
"/tmp/a/b"));
TestCase.assertFalse(DeleteUtils.isTempPathUseDefaultOnFailure("relative_path",
"/no_tmp/a/b"));
TestCase.assertFalse(DeleteUtils.isTempPathUseDefaultOnFailure("relative_path",
"/namespace/di/b/c"));
TestCase.assertTrue(DeleteUtils.isTempPathUseDefaultOnFailure("relative_path",
"/namespace/di/tmp/f"));
}
@Test
public void testTrash() throws IOException {
Configuration conf = new Configuration();
conf.setClass("fs.file.impl", TestLFS.class, FileSystem.class);
trashShell(FileSystem.getLocal(conf), TEST_DIR);
}
@Test
public void testPluggableTrash() throws IOException {
Configuration conf = new Configuration();
// Test plugged TrashPolicy
conf.setClass("fs.trash.classname", TestTrashPolicy.class, TrashPolicy.class);
Trash trash = new Trash(conf);
assertTrue(trash.getTrashPolicy().getClass().equals(TestTrashPolicy.class));
}
@Test
public void testNonDefaultFS() throws IOException {
Configuration conf = new Configuration();
conf.setClass("fs.file.impl", TestLFS.class, FileSystem.class);
conf.set("fs.default.name", "invalid://host/bar/foo");
trashNonDefaultFS(conf);
}
@Test
public void testTrashEmptier() throws Exception {
Configuration conf = new Configuration();
conf.setClass("fs.file.impl", TestLFS.class, FileSystem.class);
trashEmptier(FileSystem.getLocal(conf), conf);
}
@Test
public void testTrashPatternEmptier() throws Exception {
Configuration conf = new Configuration();
conf.setClass("fs.file.impl", TestLFS.class, FileSystem.class);
trashPatternEmptier(FileSystem.getLocal(conf), conf);
trashPatternEmptierTwoPatterns(FileSystem.getLocal(conf), conf);
}
protected int cmdUsingShell(String cmd, FsShell shell, Path myFile) {
// Delete the file to trash
String[] args = new String[2];
args[0] = cmd;
args[1] = myFile.toString();
try {
return shell.run(args);
} catch (Exception e) {
System.err.println("Exception raised from Trash.run " +
e.getLocalizedMessage());
}
return -1;
}
protected int rmUsingShell(FsShell shell, Path myFile) {
return cmdUsingShell("-rm", shell, myFile);
}
protected void trashEmptier(FileSystem fs, Configuration conf) throws Exception {
// Trash with 12 second deletes and 6 seconds checkpoints
conf.set("fs.trash.interval", "0.2"); // 12 seconds
conf.set("fs.trash.checkpoint.interval", "0.1"); // 6 seconds
Trash trash = new Trash(conf);
// clean up trash can
fs.delete(trash.getCurrentTrashDir().getParent(), true);
// Start Emptier in background
Runnable emptier = trash.getEmptier();
Thread emptierThread = new Thread(emptier);
emptierThread.start();
FsShell shell = new FsShell();
shell.setConf(conf);
shell.init();
// First create a new directory with mkdirs
Path myPath = new Path(TEST_DIR, "test/mkdirs");
mkdir(fs, myPath);
int fileIndex = 0;
Set<String> checkpoints = new HashSet<String>();
while (true) {
// Create a file with a new name
Path myFile = new Path(TEST_DIR, "test/mkdirs/myFile" + fileIndex++);
writeFile(fs, myFile);
// Delete the file to trash
assertTrue(rmUsingShell(shell, myFile) == 0);
Path trashDir = shell.getCurrentTrashDir();
FileStatus files[] = fs.listStatus(trashDir.getParent());
// Scan files in .Trash and add them to set of checkpoints
for (FileStatus file : files) {
String fileName = file.getPath().getName();
checkpoints.add(fileName);
}
// If checkpoints has 5 objects it is Current + 4 checkpoint directories
if (checkpoints.size() == 5) {
// The actual contents should be smaller since the last checkpoint
// should've been deleted and Current might not have been recreated yet
assertTrue(5 > files.length);
break;
}
Thread.sleep(5000);
}
emptierThread.interrupt();
emptierThread.join();
}
private void deleteAndCheckTrash(FileSystem fs, FsShell shell,
String srcPath, String trashPath) throws IOException {
Path myPath = new Path(TEST_DIR, srcPath);
mkdir(fs, myPath.getParent());
writeFile(fs, myPath);
assertTrue(rmUsingShell(shell, myPath) == 0);
Path trashmyPath = new Path(TEST_DIR, trashPath);
assertTrue(fs.exists(trashmyPath));
}
/**
* @param fs
* @param conf
* @throws Exception
*/
protected void trashPatternEmptier(FileSystem fs, Configuration conf) throws Exception {
// Trash with 12 second deletes and 6 seconds checkpoints
conf.set("fs.trash.interval", "0.2"); // 12 seconds
conf.set("fs.trash.checkpoint.interval", "0.1"); // 6 seconds
conf.setClass("fs.trash.classname", TrashPolicyPattern.class, TrashPolicy.class);
conf.set("fs.trash.base.paths", TEST_DIR + "/my_root/*/");
conf.set("fs.trash.unmatched.paths", TEST_DIR + "/unmatched/");
Trash trash = new Trash(conf);
// clean up trash can
fs.delete(new Path(TEST_DIR + "/my_root/*/"), true);
fs.delete(new Path(TEST_DIR + "/my_root_not/*/"), true);
FsShell shell = new FsShell();
shell.setConf(conf);
shell.init();
// First create a new directory with mkdirs
deleteAndCheckTrash(fs, shell, "my_root/sub_dir1/sub_dir1_1/myFile",
"my_root/sub_dir1/.Trash/Current/" + TEST_DIR
+ "/my_root/sub_dir1/sub_dir1_1");
deleteAndCheckTrash(fs, shell, "my_root/sub_dir2/sub_dir2_1/myFile",
"my_root/sub_dir2/.Trash/Current/" + TEST_DIR
+ "/my_root/sub_dir2/sub_dir2_1");
deleteAndCheckTrash(fs, shell, "my_root_not/", "unmatched/.Trash/Current"
+ TEST_DIR + "/my_root_not");
deleteAndCheckTrash(fs, shell, "my_root/file", "unmatched/.Trash/Current"
+ TEST_DIR + "/my_root/file");
Path currentTrash = new Path(TEST_DIR, "my_root/sub_dir1/.Trash/Current/");
fs.mkdirs(currentTrash);
cmdUsingShell("-rmr", shell, currentTrash);
assertTrue(!fs.exists(currentTrash));
cmdUsingShell("-rmr", shell, new Path(TEST_DIR, "my_root"));
assertTrue(fs.exists(new Path(TEST_DIR,
"unmatched/.Trash/Current/" + TEST_DIR + "/my_root")));
// Test Emplier
// Start Emptier in background
Runnable emptier = trash.getEmptier();
Thread emptierThread = new Thread(emptier);
emptierThread.start();
int fileIndex = 0;
Set<String> checkpoints = new HashSet<String>();
while (true) {
// Create a file with a new name
Path myFile = new Path(TEST_DIR, "my_root/sub_dir1/sub_dir2/myFile" + fileIndex++);
writeFile(fs, myFile);
// Delete the file to trash
String[] args = new String[2];
args[0] = "-rm";
args[1] = myFile.toString();
int val = -1;
try {
val = shell.run(args);
} catch (Exception e) {
System.err.println("Exception raised from Trash.run " +
e.getLocalizedMessage());
}
assertTrue(val == 0);
Path trashDir = new Path(TEST_DIR, "my_root/sub_dir1/.Trash/Current/");
FileStatus files[] = fs.listStatus(trashDir.getParent());
// Scan files in .Trash and add them to set of checkpoints
for (FileStatus file : files) {
String fileName = file.getPath().getName();
checkpoints.add(fileName);
}
// If checkpoints has 5 objects it is Current + 4 checkpoint directories
if (checkpoints.size() == 5) {
// The actual contents should be smaller since the last checkpoint
// should've been deleted and Current might not have been recreated yet
assertTrue(5 > files.length);
break;
}
Thread.sleep(5000);
}
emptierThread.interrupt();
emptierThread.join();
}
/**
* @param fs
* @param conf
* @throws Exception
*/
protected void trashPatternEmptierTwoPatterns(FileSystem fs, Configuration conf) throws Exception {
// Trash with 12 second deletes and 6 seconds checkpoints
conf.set("fs.trash.interval", "0.2"); // 12 seconds
conf.set("fs.trash.checkpoint.interval", "0.1"); // 6 seconds
conf.setClass("fs.trash.classname", TrashPolicyPattern.class, TrashPolicy.class);
conf.set("fs.trash.base.paths", "{" + TEST_DIR + "/my_root1/*/," + TEST_DIR
+ "/2my_root/*/}");
conf.set("fs.trash.unmatched.paths", TEST_DIR + "/unmatched/");
Trash trash = new Trash(conf);
// clean up trash can
fs.delete(new Path(TEST_DIR + "/my_root1/*/"), true);
fs.delete(new Path(TEST_DIR + "/2my_root/*/"), true);
fs.delete(new Path(TEST_DIR + "/my_root_not/*/"), true);
FsShell shell = new FsShell();
shell.setConf(conf);
shell.init();
// First create a new directory with mkdirs
deleteAndCheckTrash(fs, shell, "my_root1/sub_dir1/sub_dir1_1/myFile",
"my_root1/sub_dir1/.Trash/Current/" + TEST_DIR
+ "/my_root1/sub_dir1/sub_dir1_1");
deleteAndCheckTrash(fs, shell, "2my_root/sub_dir2/sub_dir2_1/myFile",
"2my_root/sub_dir2/.Trash/Current/" + TEST_DIR
+ "/2my_root/sub_dir2/sub_dir2_1");
deleteAndCheckTrash(fs, shell, "my_root_not/", "unmatched/.Trash/Current"
+ TEST_DIR + "/my_root_not");
deleteAndCheckTrash(fs, shell, "my_root1/file", "unmatched/.Trash/Current"
+ TEST_DIR + "/my_root1/file");
deleteAndCheckTrash(fs, shell, "2my_root/file", "unmatched/.Trash/Current"
+ TEST_DIR + "/2my_root/file");
// Test rmr
Path currentTrash = new Path(TEST_DIR, "2my_root/sub_dir1/.Trash/Current/");
fs.mkdirs(currentTrash);
cmdUsingShell("-rmr", shell, currentTrash);
assertTrue(!fs.exists(currentTrash));
cmdUsingShell("-rmr", shell, new Path(TEST_DIR, "2my_root"));
assertTrue(fs.exists(new Path(TEST_DIR,
"unmatched/.Trash/Current/" + TEST_DIR + "/2my_root")));
// Test rmr from another directory pattern
currentTrash = new Path(TEST_DIR, "my_root1/sub_dir1/.Trash/Current/");
fs.mkdirs(currentTrash);
cmdUsingShell("-rmr", shell, currentTrash);
assertTrue(!fs.exists(currentTrash));
cmdUsingShell("-rmr", shell, new Path(TEST_DIR, "my_root1"));
assertTrue(fs.exists(new Path(TEST_DIR,
"unmatched/.Trash/Current/" + TEST_DIR + "/my_root1")));
// Test Emplier
// Start Emptier in background
Runnable emptier = trash.getEmptier();
Thread emptierThread = new Thread(emptier);
emptierThread.start();
int fileIndex = 0;
Set<String> checkpoints = new HashSet<String>();
while (true) {
// Create a file with a new name
Path myFile = new Path(TEST_DIR, "2my_root/sub_dir1/sub_dir2/myFile" + fileIndex++);
writeFile(fs, myFile);
if (checkpoints.size() > 2) {
fs.mkdirs(new Path(TEST_DIR + "/my_root1"));
}
// Delete the file to trash
String[] args = new String[2];
args[0] = "-rm";
args[1] = myFile.toString();
int val = -1;
try {
val = shell.run(args);
} catch (Exception e) {
System.err.println("Exception raised from Trash.run " +
e.getLocalizedMessage());
}
assertTrue(val == 0);
Path trashDir = new Path(TEST_DIR, "2my_root/sub_dir1/.Trash/Current/");
FileStatus files[] = fs.listStatus(trashDir.getParent());
// Scan files in .Trash and add them to set of checkpoints
for (FileStatus file : files) {
String fileName = file.getPath().getName();
checkpoints.add(fileName);
}
// If checkpoints has 5 objects it is Current + 4 checkpoint directories
if (checkpoints.size() == 5) {
// The actual contents should be smaller since the last checkpoint
// should've been deleted and Current might not have been recreated yet
assertTrue(5 > files.length);
break;
}
Thread.sleep(5000);
}
// Another base path pattern
checkpoints.clear();
while (true) {
// Create a file with a new name
Path myFile = new Path(TEST_DIR, "my_root1/sub_dir1/sub_dir2/myFile" + fileIndex++);
writeFile(fs, myFile);
// Delete the file to trash
String[] args = new String[2];
args[0] = "-rm";
args[1] = myFile.toString();
int val = -1;
try {
val = shell.run(args);
} catch (Exception e) {
System.err.println("Exception raised from Trash.run " +
e.getLocalizedMessage());
}
assertTrue(val == 0);
Path trashDir = new Path(TEST_DIR, "my_root1/sub_dir1/.Trash/Current/");
FileStatus files[] = fs.listStatus(trashDir.getParent());
// Scan files in .Trash and add them to set of checkpoints
for (FileStatus file : files) {
String fileName = file.getPath().getName();
checkpoints.add(fileName);
}
// If checkpoints has 5 objects it is Current + 4 checkpoint directories
if (checkpoints.size() == 5) {
// The actual contents should be smaller since the last checkpoint
// should've been deleted and Current might not have been recreated yet
assertTrue(5 > files.length);
break;
}
Thread.sleep(5000);
}
// default trash path
checkpoints.clear();
while (true) {
// Create a file with a new name
Path myFile = new Path(TEST_DIR, "sub_dir1/sub_dir2/myFile" + fileIndex++);
writeFile(fs, myFile);
// Delete the file to trash
String[] args = new String[2];
args[0] = "-rm";
args[1] = myFile.toString();
int val = -1;
try {
val = shell.run(args);
} catch (Exception e) {
System.err.println("Exception raised from Trash.run " +
e.getLocalizedMessage());
}
assertTrue(val == 0);
Path trashDir = new Path(TEST_DIR, "unmatched/.Trash/Current/");
FileStatus files[] = fs.listStatus(trashDir.getParent());
// Scan files in .Trash and add them to set of checkpoints
for (FileStatus file : files) {
String fileName = file.getPath().getName();
checkpoints.add(fileName);
}
// If checkpoints has 5 objects it is Current + 4 checkpoint directories
if (checkpoints.size() == 5) {
// The actual contents should be smaller since the last checkpoint
// should've been deleted and Current might not have been recreated yet
assertTrue(5 > files.length);
break;
}
Thread.sleep(5000);
}
emptierThread.interrupt();
emptierThread.join();
}
static class TestLFS extends LocalFileSystem {
Path home;
TestLFS() throws IOException {
this(new Path(TEST_DIR, "user/test"));
}
TestLFS(Path home) throws IOException {
super();
this.home = home;
}
public Path getHomeDirectory() {
return home;
}
public Path getHomeDirectory(String userName) {
return home;
}
}
// Test TrashPolicy. Don't care about implementation.
public static class TestTrashPolicy extends TrashPolicy {
public TestTrashPolicy() { }
@Override
public void initialize(Configuration conf, FileSystem fs, Path home) {
}
@Override
public boolean isEnabled() {
return false;
}
@Override
public boolean moveToTrash(Path path) throws IOException {
return false;
}
@Override
public boolean moveFromTrash(Path path) throws IOException {
return false;
}
@Override
public void createCheckpoint() throws IOException {
}
@Override
public void deleteCheckpoint() throws IOException {
}
@Override
public Path getCurrentTrashDir() {
return null;
}
@Override
public Runnable getEmptier() throws IOException {
return null;
}
}
}