HADOOP-18155. Refactor tests in TestFileUtil (#4063)

(cherry picked from commit d0fa9b5775)

 Conflicts:
	hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java
	hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFileUtil.java

Co-authored-by: Gautham B A <gautham.bangalore@gmail.com>
(cherry picked from commit 743db6e7b4)
(cherry picked from commit 826d13a59a)

Conflicts:
	hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java
	hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFileUtil.java
This commit is contained in:
Wei-Chiu Chuang 2022-03-14 08:40:17 +08:00 committed by Masatake Iwasaki
parent 12c3b8f8df
commit 10f3f0cf42
2 changed files with 232 additions and 134 deletions

View File

@ -30,6 +30,7 @@ import java.io.OutputStream;
import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
@ -757,6 +758,14 @@ public class FileUtil {
+ " would create entry outside of " + outputDir);
}
if (entry.isSymbolicLink() || entry.isLink()) {
String canonicalTargetPath = getCanonicalPath(entry.getLinkName(), outputDir);
if (!canonicalTargetPath.startsWith(targetDirPath)) {
throw new IOException(
"expanding " + entry.getName() + " would create entry outside of " + outputDir);
}
}
if (entry.isDirectory()) {
File subDir = new File(outputDir, entry.getName());
if (!subDir.mkdirs() && !subDir.isDirectory()) {
@ -779,7 +788,8 @@ public class FileUtil {
}
if (entry.isLink()) {
File src = new File(outputDir, entry.getLinkName());
String canonicalTargetPath = getCanonicalPath(entry.getLinkName(), outputDir);
File src = new File(canonicalTargetPath);
HardLink.createHardLink(src, outputFile);
return;
}
@ -797,6 +807,20 @@ public class FileUtil {
}
}
/**
* Gets the canonical path for the given path.
*
* @param path The path for which the canonical path needs to be computed.
* @param parentDir The parent directory to use if the path is a relative path.
* @return The canonical path of the given path.
*/
private static String getCanonicalPath(String path, File parentDir) throws IOException {
java.nio.file.Path targetPath = Paths.get(path);
return (targetPath.isAbsolute() ?
new File(path) :
new File(parentDir, path)).getCanonicalPath();
}
/**
* Class for creating hardlinks.
* Supports Unix, WindXP.

View File

@ -45,6 +45,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.Objects;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
@ -55,9 +56,11 @@ import org.apache.commons.io.FileUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.test.GenericTestUtils;
import org.apache.hadoop.util.Shell;
import org.apache.hadoop.test.LambdaTestUtils;
import org.apache.hadoop.util.StringUtils;
import org.apache.tools.tar.TarEntry;
import org.apache.tools.tar.TarOutputStream;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@ -153,13 +156,12 @@ public class TestFileUtil {
FileUtils.forceMkdir(dir1);
FileUtils.forceMkdir(dir2);
new File(del, FILE).createNewFile();
File tmpFile = new File(tmp, FILE);
tmpFile.createNewFile();
Verify.createNewFile(new File(del, FILE));
File tmpFile = Verify.createNewFile(new File(tmp, FILE));
// create files
new File(dir1, FILE).createNewFile();
new File(dir2, FILE).createNewFile();
Verify.createNewFile(new File(dir1, FILE));
Verify.createNewFile(new File(dir2, FILE));
// create a symlink to file
File link = new File(del, LINK);
@ -168,7 +170,7 @@ public class TestFileUtil {
// create a symlink to dir
File linkDir = new File(del, "tmpDir");
FileUtil.symLink(tmp.toString(), linkDir.toString());
Assert.assertEquals(5, del.listFiles().length);
Assert.assertEquals(5, Objects.requireNonNull(del.listFiles()).length);
// create files in partitioned directories
createFile(partitioned, "part-r-00000", "foo");
@ -195,13 +197,9 @@ public class TestFileUtil {
private File createFile(File directory, String name, String contents)
throws IOException {
File newFile = new File(directory, name);
PrintWriter pw = new PrintWriter(newFile);
try {
try (PrintWriter pw = new PrintWriter(newFile)) {
pw.println(contents);
}
finally {
pw.close();
}
return newFile;
}
@ -213,11 +211,11 @@ public class TestFileUtil {
//Test existing directory with no files case
File newDir = new File(tmp.getPath(),"test");
newDir.mkdir();
Verify.mkdir(newDir);
Assert.assertTrue("Failed to create test dir", newDir.exists());
files = FileUtil.listFiles(newDir);
Assert.assertEquals(0, files.length);
newDir.delete();
assertTrue(newDir.delete());
Assert.assertFalse("Failed to delete test dir", newDir.exists());
//Test non-existing directory case, this throws
@ -239,11 +237,11 @@ public class TestFileUtil {
//Test existing directory with no files case
File newDir = new File(tmp.getPath(),"test");
newDir.mkdir();
Verify.mkdir(newDir);
Assert.assertTrue("Failed to create test dir", newDir.exists());
files = FileUtil.list(newDir);
Assert.assertEquals("New directory unexpectedly contains files", 0, files.length);
newDir.delete();
assertTrue(newDir.delete());
Assert.assertFalse("Failed to delete test dir", newDir.exists());
//Test non-existing directory case, this throws
@ -261,7 +259,7 @@ public class TestFileUtil {
public void testFullyDelete() throws IOException {
boolean ret = FileUtil.fullyDelete(del);
Assert.assertTrue(ret);
Assert.assertFalse(del.exists());
Verify.notExists(del);
validateTmpDir();
}
@ -274,13 +272,13 @@ public class TestFileUtil {
@Test (timeout = 30000)
public void testFullyDeleteSymlinks() throws IOException {
File link = new File(del, LINK);
Assert.assertEquals(5, del.list().length);
assertDelListLength(5);
// Since tmpDir is symlink to tmp, fullyDelete(tmpDir) should not
// delete contents of tmp. See setupDirs for details.
boolean ret = FileUtil.fullyDelete(link);
Assert.assertTrue(ret);
Assert.assertFalse(link.exists());
Assert.assertEquals(4, del.list().length);
Verify.notExists(link);
assertDelListLength(4);
validateTmpDir();
File linkDir = new File(del, "tmpDir");
@ -288,8 +286,8 @@ public class TestFileUtil {
// delete contents of tmp. See setupDirs for details.
ret = FileUtil.fullyDelete(linkDir);
Assert.assertTrue(ret);
Assert.assertFalse(linkDir.exists());
Assert.assertEquals(3, del.list().length);
Verify.notExists(linkDir);
assertDelListLength(3);
validateTmpDir();
}
@ -305,16 +303,16 @@ public class TestFileUtil {
// to make y as a dangling link to file tmp/x
boolean ret = FileUtil.fullyDelete(tmp);
Assert.assertTrue(ret);
Assert.assertFalse(tmp.exists());
Verify.notExists(tmp);
// dangling symlink to file
File link = new File(del, LINK);
Assert.assertEquals(5, del.list().length);
assertDelListLength(5);
// Even though 'y' is dangling symlink to file tmp/x, fullyDelete(y)
// should delete 'y' properly.
ret = FileUtil.fullyDelete(link);
Assert.assertTrue(ret);
Assert.assertEquals(4, del.list().length);
assertDelListLength(4);
// dangling symlink to directory
File linkDir = new File(del, "tmpDir");
@ -322,22 +320,22 @@ public class TestFileUtil {
// delete tmpDir properly.
ret = FileUtil.fullyDelete(linkDir);
Assert.assertTrue(ret);
Assert.assertEquals(3, del.list().length);
assertDelListLength(3);
}
@Test (timeout = 30000)
public void testFullyDeleteContents() throws IOException {
boolean ret = FileUtil.fullyDeleteContents(del);
Assert.assertTrue(ret);
Assert.assertTrue(del.exists());
Assert.assertEquals(0, del.listFiles().length);
Verify.exists(del);
Assert.assertEquals(0, Objects.requireNonNull(del.listFiles()).length);
validateTmpDir();
}
private void validateTmpDir() {
Assert.assertTrue(tmp.exists());
Assert.assertEquals(1, tmp.listFiles().length);
Assert.assertTrue(new File(tmp, FILE).exists());
Verify.exists(tmp);
Assert.assertEquals(1, Objects.requireNonNull(tmp.listFiles()).length);
Verify.exists(new File(tmp, FILE));
}
/**
@ -361,15 +359,15 @@ public class TestFileUtil {
* @throws IOException
*/
private void setupDirsAndNonWritablePermissions() throws IOException {
new MyFile(del, FILE_1_NAME).createNewFile();
Verify.createNewFile(new MyFile(del, FILE_1_NAME));
// "file1" is non-deletable by default, see MyFile.delete().
xSubDir.mkdirs();
file2.createNewFile();
Verify.mkdirs(xSubDir);
Verify.createNewFile(file2);
xSubSubDir.mkdirs();
file22.createNewFile();
Verify.mkdirs(xSubSubDir);
Verify.createNewFile(file22);
revokePermissions(file22);
revokePermissions(xSubSubDir);
@ -377,8 +375,8 @@ public class TestFileUtil {
revokePermissions(file2);
revokePermissions(xSubDir);
ySubDir.mkdirs();
file3.createNewFile();
Verify.mkdirs(ySubDir);
Verify.createNewFile(file3);
File tmpFile = new File(tmp, FILE);
tmpFile.createNewFile();
@ -445,6 +443,88 @@ public class TestFileUtil {
validateAndSetWritablePermissions(false, ret);
}
/**
* Asserts if the {@link TestFileUtil#del} meets the given expected length.
*
* @param expectedLength The expected length of the {@link TestFileUtil#del}.
*/
private void assertDelListLength(int expectedLength) {
assertEquals(expectedLength, del.list().length);
}
/**
* Helper class to perform {@link File} operation and also verify them.
*/
public static class Verify {
/**
* Invokes {@link File#createNewFile()} on the given {@link File} instance.
*
* @param file The file to call {@link File#createNewFile()} on.
* @return The result of {@link File#createNewFile()}.
* @throws IOException As per {@link File#createNewFile()}.
*/
public static File createNewFile(File file) throws IOException {
assertTrue("Unable to create new file " + file, file.createNewFile());
return file;
}
/**
* Invokes {@link File#mkdir()} on the given {@link File} instance.
*
* @param file The file to call {@link File#mkdir()} on.
* @return The result of {@link File#mkdir()}.
*/
public static File mkdir(File file) {
assertTrue("Unable to mkdir for " + file, file.mkdir());
return file;
}
/**
* Invokes {@link File#mkdirs()} on the given {@link File} instance.
*
* @param file The file to call {@link File#mkdirs()} on.
* @return The result of {@link File#mkdirs()}.
*/
public static File mkdirs(File file) {
assertTrue("Unable to mkdirs for " + file, file.mkdirs());
return file;
}
/**
* Invokes {@link File#delete()} on the given {@link File} instance.
*
* @param file The file to call {@link File#delete()} on.
* @return The result of {@link File#delete()}.
*/
public static File delete(File file) {
assertTrue("Unable to delete " + file, file.delete());
return file;
}
/**
* Invokes {@link File#exists()} on the given {@link File} instance.
*
* @param file The file to call {@link File#exists()} on.
* @return The result of {@link File#exists()}.
*/
public static File exists(File file) {
assertTrue("Expected file " + file + " doesn't exist", file.exists());
return file;
}
/**
* Invokes {@link File#exists()} on the given {@link File} instance to check if the
* {@link File} doesn't exists.
*
* @param file The file to call {@link File#exists()} on.
* @return The negation of the result of {@link File#exists()}.
*/
public static File notExists(File file) {
assertFalse("Expected file " + file + " must not exist", file.exists());
return file;
}
}
/**
* Extend {@link File}. Same as {@link File} except for two things: (1) This
* treats file1Name as a very special file which is not delete-able
@ -635,12 +715,11 @@ public class TestFileUtil {
}
@Test (timeout = 30000)
public void testUnTar() throws IOException {
public void testUnTar() throws Exception {
// make a simple tar:
final File simpleTar = new File(del, FILE);
OutputStream os = new FileOutputStream(simpleTar);
TarOutputStream tos = new TarOutputStream(os);
try {
try (TarOutputStream tos = new TarOutputStream(os)) {
TarEntry te = new TarEntry("/bar/foo");
byte[] data = "some-content".getBytes("UTF-8");
te.setSize(data.length);
@ -649,55 +728,49 @@ public class TestFileUtil {
tos.closeEntry();
tos.flush();
tos.finish();
} finally {
tos.close();
}
// successfully untar it into an existing dir:
FileUtil.unTar(simpleTar, tmp);
// check result:
assertTrue(new File(tmp, "/bar/foo").exists());
Verify.exists(new File(tmp, "/bar/foo"));
assertEquals(12, new File(tmp, "/bar/foo").length());
final File regularFile = new File(tmp, "QuickBrownFoxJumpsOverTheLazyDog");
regularFile.createNewFile();
assertTrue(regularFile.exists());
try {
final File regularFile =
Verify.createNewFile(new File(tmp, "QuickBrownFoxJumpsOverTheLazyDog"));
LambdaTestUtils.intercept(IOException.class,
new Callable<Void>() {
@Override
public Void call() throws Exception {
FileUtil.unTar(simpleTar, regularFile);
assertTrue("An IOException expected.", false);
} catch (IOException ioe) {
// okay
return null;
}
});
}
@Test (timeout = 30000)
public void testReplaceFile() throws IOException {
final File srcFile = new File(tmp, "src");
// src exists, and target does not exist:
srcFile.createNewFile();
assertTrue(srcFile.exists());
final File srcFile = Verify.createNewFile(new File(tmp, "src"));
final File targetFile = new File(tmp, "target");
assertTrue(!targetFile.exists());
Verify.notExists(targetFile);
FileUtil.replaceFile(srcFile, targetFile);
assertTrue(!srcFile.exists());
assertTrue(targetFile.exists());
Verify.notExists(srcFile);
Verify.exists(targetFile);
// src exists and target is a regular file:
srcFile.createNewFile();
assertTrue(srcFile.exists());
Verify.createNewFile(srcFile);
Verify.exists(srcFile);
FileUtil.replaceFile(srcFile, targetFile);
assertTrue(!srcFile.exists());
assertTrue(targetFile.exists());
Verify.notExists(srcFile);
Verify.exists(targetFile);
// src exists, and target is a non-empty directory:
srcFile.createNewFile();
assertTrue(srcFile.exists());
targetFile.delete();
targetFile.mkdirs();
File obstacle = new File(targetFile, "obstacle");
obstacle.createNewFile();
assertTrue(obstacle.exists());
Verify.createNewFile(srcFile);
Verify.exists(srcFile);
Verify.delete(targetFile);
Verify.mkdirs(targetFile);
File obstacle = Verify.createNewFile(new File(targetFile, "obstacle"));
assertTrue(targetFile.exists() && targetFile.isDirectory());
try {
FileUtil.replaceFile(srcFile, targetFile);
@ -706,9 +779,9 @@ public class TestFileUtil {
// okay
}
// check up the post-condition: nothing is deleted:
assertTrue(srcFile.exists());
Verify.exists(srcFile);
assertTrue(targetFile.exists() && targetFile.isDirectory());
assertTrue(obstacle.exists());
Verify.exists(obstacle);
}
@Test (timeout = 30000)
@ -721,13 +794,13 @@ public class TestFileUtil {
assertTrue(tmp1.exists() && tmp2.exists());
assertTrue(tmp1.canWrite() && tmp2.canWrite());
assertTrue(tmp1.canRead() && tmp2.canRead());
tmp1.delete();
tmp2.delete();
Verify.delete(tmp1);
Verify.delete(tmp2);
assertTrue(!tmp1.exists() && !tmp2.exists());
}
@Test (timeout = 30000)
public void testUnZip() throws IOException {
public void testUnZip() throws Exception {
// make sa simple zip
final File simpleZip = new File(del, FILE);
OutputStream os = new FileOutputStream(simpleZip);
@ -748,18 +821,19 @@ public class TestFileUtil {
// successfully unzip it into an existing dir:
FileUtil.unZip(simpleZip, tmp);
// check result:
assertTrue(new File(tmp, "foo").exists());
Verify.exists(new File(tmp, "foo"));
assertEquals(12, new File(tmp, "foo").length());
final File regularFile = new File(tmp, "QuickBrownFoxJumpsOverTheLazyDog");
regularFile.createNewFile();
assertTrue(regularFile.exists());
try {
final File regularFile =
Verify.createNewFile(new File(tmp, "QuickBrownFoxJumpsOverTheLazyDog"));
LambdaTestUtils.intercept(IOException.class,
new Callable<Void>() {
@Override
public Void call() throws Exception {
FileUtil.unZip(simpleZip, regularFile);
assertTrue("An IOException expected.", false);
} catch (IOException ioe) {
// okay
return null;
}
});
}
@Test (timeout = 30000)
@ -805,24 +879,24 @@ public class TestFileUtil {
final File dest = new File(del, "dest");
boolean result = FileUtil.copy(fs, srcPath, dest, false, conf);
assertTrue(result);
assertTrue(dest.exists());
Verify.exists(dest);
assertEquals(content.getBytes().length
+ System.getProperty("line.separator").getBytes().length, dest.length());
assertTrue(srcFile.exists()); // should not be deleted
Verify.exists(srcFile); // should not be deleted
// copy regular file, delete src:
dest.delete();
assertTrue(!dest.exists());
Verify.delete(dest);
Verify.notExists(dest);
result = FileUtil.copy(fs, srcPath, dest, true, conf);
assertTrue(result);
assertTrue(dest.exists());
Verify.exists(dest);
assertEquals(content.getBytes().length
+ System.getProperty("line.separator").getBytes().length, dest.length());
assertTrue(!srcFile.exists()); // should be deleted
Verify.notExists(srcFile); // should be deleted
// copy a dir:
dest.delete();
assertTrue(!dest.exists());
Verify.delete(dest);
Verify.notExists(dest);
srcPath = new Path(partitioned.toURI());
result = FileUtil.copy(fs, srcPath, dest, true, conf);
assertTrue(result);
@ -834,7 +908,7 @@ public class TestFileUtil {
assertEquals(3
+ System.getProperty("line.separator").getBytes().length, f.length());
}
assertTrue(!partitioned.exists()); // should be deleted
Verify.notExists(partitioned); // should be deleted
}
@Test (timeout = 30000)
@ -922,8 +996,8 @@ public class TestFileUtil {
// create the symlink
FileUtil.symLink(file.getAbsolutePath(), link.getAbsolutePath());
Assert.assertTrue(file.exists());
Assert.assertTrue(link.exists());
Verify.exists(file);
Verify.exists(link);
File link2 = new File(del, "_link2");
@ -933,10 +1007,10 @@ public class TestFileUtil {
// Make sure the file still exists
// (NOTE: this would fail on Java6 on Windows if we didn't
// copy the file in FileUtil#symlink)
Assert.assertTrue(file.exists());
Verify.exists(file);
Assert.assertTrue(link2.exists());
Assert.assertFalse(link.exists());
Verify.exists(link2);
Verify.notExists(link);
}
/**
@ -951,13 +1025,13 @@ public class TestFileUtil {
// create the symlink
FileUtil.symLink(file.getAbsolutePath(), link.getAbsolutePath());
Assert.assertTrue(file.exists());
Assert.assertTrue(link.exists());
Verify.exists(file);
Verify.exists(link);
// make sure that deleting a symlink works properly
Assert.assertTrue(link.delete());
Assert.assertFalse(link.exists());
Assert.assertTrue(file.exists());
Verify.delete(link);
Verify.notExists(link);
Verify.exists(file);
}
/**
@ -984,13 +1058,13 @@ public class TestFileUtil {
Assert.assertEquals(data.length, file.length());
Assert.assertEquals(data.length, link.length());
file.delete();
Assert.assertFalse(file.exists());
Verify.delete(file);
Verify.notExists(file);
Assert.assertEquals(0, link.length());
link.delete();
Assert.assertFalse(link.exists());
Verify.delete(link);
Verify.notExists(link);
}
/**
@ -1056,7 +1130,7 @@ public class TestFileUtil {
public void testSymlinkSameFile() throws IOException {
File file = new File(del, FILE);
file.delete();
Verify.delete(file);
// Create a symbolic link
// The operation should succeed
@ -1129,21 +1203,21 @@ public class TestFileUtil {
String parentDir = untarDir.getCanonicalPath() + Path.SEPARATOR + "name";
File testFile = new File(parentDir + Path.SEPARATOR + "version");
Assert.assertTrue(testFile.exists());
Verify.exists(testFile);
Assert.assertTrue(testFile.length() == 0);
String imageDir = parentDir + Path.SEPARATOR + "image";
testFile = new File(imageDir + Path.SEPARATOR + "fsimage");
Assert.assertTrue(testFile.exists());
Verify.exists(testFile);
Assert.assertTrue(testFile.length() == 157);
String currentDir = parentDir + Path.SEPARATOR + "current";
testFile = new File(currentDir + Path.SEPARATOR + "fsimage");
Assert.assertTrue(testFile.exists());
Verify.exists(testFile);
Assert.assertTrue(testFile.length() == 4331);
testFile = new File(currentDir + Path.SEPARATOR + "edits");
Assert.assertTrue(testFile.exists());
Verify.exists(testFile);
Assert.assertTrue(testFile.length() == 1033);
testFile = new File(currentDir + Path.SEPARATOR + "fstime");
Assert.assertTrue(testFile.exists());
Verify.exists(testFile);
Assert.assertTrue(testFile.length() == 8);
}
@ -1216,9 +1290,9 @@ public class TestFileUtil {
}
// create non-jar files, which we expect to not be included in the classpath
Assert.assertTrue(new File(tmp, "text.txt").createNewFile());
Assert.assertTrue(new File(tmp, "executable.exe").createNewFile());
Assert.assertTrue(new File(tmp, "README").createNewFile());
Verify.createNewFile(new File(tmp, "text.txt"));
Verify.createNewFile(new File(tmp, "executable.exe"));
Verify.createNewFile(new File(tmp, "README"));
// create classpath jar
String wildcardPath = tmp.getCanonicalPath() + File.separator + "*";
@ -1304,9 +1378,9 @@ public class TestFileUtil {
}
// create non-jar files, which we expect to not be included in the result
assertTrue(new File(tmp, "text.txt").createNewFile());
assertTrue(new File(tmp, "executable.exe").createNewFile());
assertTrue(new File(tmp, "README").createNewFile());
Verify.createNewFile(new File(tmp, "text.txt"));
Verify.createNewFile(new File(tmp, "executable.exe"));
Verify.createNewFile(new File(tmp, "README"));
// pass in the directory
String directory = tmp.getCanonicalPath();
@ -1340,7 +1414,7 @@ public class TestFileUtil {
uri4 = new URI(uris4);
uri5 = new URI(uris5);
uri6 = new URI(uris6);
} catch (URISyntaxException use) {
} catch (URISyntaxException ignored) {
}
// Set up InetAddress
inet1 = mock(InetAddress.class);
@ -1363,7 +1437,7 @@ public class TestFileUtil {
when(InetAddress.getByName(uris3)).thenReturn(inet3);
when(InetAddress.getByName(uris4)).thenReturn(inet4);
when(InetAddress.getByName(uris5)).thenReturn(inet5);
} catch (UnknownHostException ue) {
} catch (UnknownHostException ignored) {
}
fs1 = mock(FileSystem.class);
@ -1383,18 +1457,18 @@ public class TestFileUtil {
@Test
public void testCompareFsNull() throws Exception {
setupCompareFs();
assertEquals(FileUtil.compareFs(null,fs1),false);
assertEquals(FileUtil.compareFs(fs1,null),false);
assertFalse(FileUtil.compareFs(null, fs1));
assertFalse(FileUtil.compareFs(fs1, null));
}
@Test
public void testCompareFsDirectories() throws Exception {
setupCompareFs();
assertEquals(FileUtil.compareFs(fs1,fs1),true);
assertEquals(FileUtil.compareFs(fs1,fs2),false);
assertEquals(FileUtil.compareFs(fs1,fs5),false);
assertEquals(FileUtil.compareFs(fs3,fs4),true);
assertEquals(FileUtil.compareFs(fs1,fs6),false);
assertTrue(FileUtil.compareFs(fs1, fs1));
assertFalse(FileUtil.compareFs(fs1, fs2));
assertFalse(FileUtil.compareFs(fs1, fs5));
assertTrue(FileUtil.compareFs(fs3, fs4));
assertFalse(FileUtil.compareFs(fs1, fs6));
}
/*