From 5e49328129cb072df5a167404c16b6a3bf698fd5 Mon Sep 17 00:00:00 2001 From: cramakri <cramakri> Date: Wed, 11 Jul 2012 09:16:51 +0000 Subject: [PATCH] BIS-21 SP-177 : Add a wrapper that catches assertions in hardlink makers SVN: 26071 --- ...sertionCatchingImmutableCopierWrapper.java | 74 ++++++ .../filesystem/AbstractHardlinkMakerTest.java | 210 ++++++++++++++++++ .../FastRecursiveHardLinkMakerTest.java | 54 +++++ .../RecursiveHardLinkMakerTest.java | 166 +------------- .../filesystem/TestBigStructureCreator.java | 163 ++++++++++++++ 5 files changed, 504 insertions(+), 163 deletions(-) create mode 100644 common/source/java/ch/systemsx/cisd/common/filesystem/AssertionCatchingImmutableCopierWrapper.java create mode 100644 common/sourceTest/java/ch/systemsx/cisd/common/filesystem/AbstractHardlinkMakerTest.java create mode 100644 common/sourceTest/java/ch/systemsx/cisd/common/filesystem/FastRecursiveHardLinkMakerTest.java create mode 100644 common/sourceTest/java/ch/systemsx/cisd/common/filesystem/TestBigStructureCreator.java diff --git a/common/source/java/ch/systemsx/cisd/common/filesystem/AssertionCatchingImmutableCopierWrapper.java b/common/source/java/ch/systemsx/cisd/common/filesystem/AssertionCatchingImmutableCopierWrapper.java new file mode 100644 index 00000000000..2b04e08a57b --- /dev/null +++ b/common/source/java/ch/systemsx/cisd/common/filesystem/AssertionCatchingImmutableCopierWrapper.java @@ -0,0 +1,74 @@ +/* + * Copyright 2012 ETH Zuerich, CISD + * + * Licensed 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 ch.systemsx.cisd.common.filesystem; + +import java.io.File; + +import ch.systemsx.cisd.common.exceptions.Status; + +/** + * A wrapper on an {@link IImmutableCopier} that catches assertions and returns a failure status if + * any are encountered. + * + * @author Chandrasekhar Ramakrishnan + */ +public class AssertionCatchingImmutableCopierWrapper implements IImmutableCopier +{ + private final IImmutableCopier wrapped; + + /** + * Create a wrapper on copier + * + * @param copier The copier to wrap. + */ + public AssertionCatchingImmutableCopierWrapper(IImmutableCopier copier) + { + this.wrapped = copier; + } + + @Override + public Status copyImmutably(File source, File destinationDirectory, String nameOrNull) + { + Status result; + try + { + result = wrapped.copyImmutably(source, destinationDirectory, nameOrNull); + } catch (AssertionError e) + { + result = Status.createError(e.getMessage()); + } + + return result; + } + + @Override + public Status copyImmutably(File source, File destinationDirectory, String nameOrNull, + CopyModeExisting mode) + { + Status result; + try + { + result = wrapped.copyImmutably(source, destinationDirectory, nameOrNull, mode); + } catch (AssertionError e) + { + result = Status.createError(e.getMessage()); + } + + return result; + } + +} diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/AbstractHardlinkMakerTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/AbstractHardlinkMakerTest.java new file mode 100644 index 00000000000..26f8dc1e2f5 --- /dev/null +++ b/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/AbstractHardlinkMakerTest.java @@ -0,0 +1,210 @@ +/* + * Copyright 2012 ETH Zuerich, CISD + * + * Licensed 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 ch.systemsx.cisd.common.filesystem; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertFalse; +import static org.testng.AssertJUnit.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import ch.systemsx.cisd.common.collections.CollectionIO; +import ch.systemsx.cisd.common.logging.LogInitializer; + +/** + * The abstract superclass of tests for the various hardlink maker implementations. + * + * @author Chandrasekhar Ramakrishnan + */ +public abstract class AbstractHardlinkMakerTest +{ + protected static final File unitTestRootDirectory = new File("targets" + File.separator + + "unit-test-wd"); + + protected static final File workingDirectory = new File(unitTestRootDirectory, + FastRecursiveHardLinkMakerTest.class.getSimpleName()); + + protected static final File outputDir = new File(workingDirectory, "output"); + + protected static File createFile(File directory, String name) throws IOException + { + final File file = new File(directory, name); + file.createNewFile(); + assert file.isFile(); + CollectionIO + .writeIterable(file, Arrays.asList("test line 1", "test line 2", "test line 3")); + file.deleteOnExit(); + return file; + } + + @BeforeClass + public void init() + { + LogInitializer.init(); + unitTestRootDirectory.mkdirs(); + assert unitTestRootDirectory.isDirectory(); + } + + @BeforeMethod + public void setUp() + { + FileUtilities.deleteRecursively(workingDirectory); + outputDir.mkdirs(); + } + + @AfterClass + public void clean() + { + FileUtilities.deleteRecursively(outputDir); + } + + private static File createDirectory(File directory, String name) throws IOException + { + final File file = new File(directory, name); + file.mkdir(); + assert file.isDirectory(); + file.deleteOnExit(); + return file; + } + + private static File mkPath(File parent, String... subdirs) + { + File file = parent; + for (String subdir : subdirs) + { + file = new File(file, subdir); + } + return file; + } + + private static void assertFileExists(File file) + { + assert file.isFile(); + } + + private static void assertStructureExists(File destinationDir) + { + assertFileExists(mkPath(destinationDir, "dir1", "dir1a", "file1a")); + assertFileExists(mkPath(destinationDir, "dir1", "dir1b", "file1b")); + assertFileExists(mkPath(destinationDir, "dir2", "file4")); + assertFileExists(mkPath(destinationDir, "file2")); + assertFileExists(mkPath(destinationDir, "file3")); + } + + private void createStructure(File inputDir) throws IOException + { + final File dir1 = createDirectory(inputDir, "dir1"); + final File dir1a = createDirectory(dir1, "dir1a"); + final File dir1b = createDirectory(dir1, "dir1b"); + final File dir2 = createDirectory(inputDir, "dir2"); + createFile(dir1a, "file1a"); + createFile(dir1b, "file1b"); + createFile(inputDir, "file2"); + createFile(inputDir, "file3"); + createFile(dir2, "file4"); + } + + @Test(groups = + { "requires_unix" }) + public void testCopyWithHardLinks() throws IOException + { + File inputDir = createDirectory(workingDirectory, "resource-to-copy"); + createStructure(inputDir); + assertTrue(createHardLinkCopier().copyImmutably(inputDir, outputDir, null).isOK()); + File newInput = new File(outputDir, inputDir.getName()); + + assertStructureExists(newInput); + boolean deleted = FileUtilities.deleteRecursively(inputDir); + assert deleted; + assertStructureExists(newInput); + } + + private static void assertFilesIdentical(File file1, File file2) + { + List<String> list1 = CollectionIO.readList(file1); + List<String> list2 = CollectionIO.readList(file2); + assertEquals(list1, list2); + } + + @Test(groups = + { "requires_unix" }) + public void testCopyFile() throws IOException + { + File src = createFile(workingDirectory, "fileXXX"); + assertFileExists(src); + + assertTrue(createHardLinkCopier().copyImmutably(src, outputDir, null).isOK()); + File dest = new File(outputDir, src.getName()); + assertFileExists(dest); + + modifyDest(dest); + assertFilesIdentical(src, dest); + } + + private static void modifyDest(File file) + { + List<String> list = Arrays.asList("new line 1", "new line 2"); + CollectionIO.writeIterable(file, list); + } + + /** + * + * + */ + public AbstractHardlinkMakerTest() + { + super(); + } + + @Test(groups = + { "requires_unix" }) + public void testDeleteWhileCopying() throws IOException + { + TestBigStructureCreator creator = + createBigStructureCreator(new File(workingDirectory, "big-structure")); + final File src = creator.createBigStructure(); + assertTrue(creator.verifyStructure()); + creator.deleteBigStructureAsync(); + IImmutableCopier copier = + new AssertionCatchingImmutableCopierWrapper(createHardLinkCopier()); + assertFalse(copier.copyImmutably(src, outputDir, null).isOK()); + File dest = new File(outputDir, src.getName()); + + TestBigStructureCreator structureCopy = new TestBigStructureCreator(dest); + assertFalse("Big structure was partially copied", structureCopy.verifyStructure()); + assertFalse("Original was not partially deleted", creator.verifyStructure()); + + } + + /** + * Construct a TestBigStructureCreator. Subclasses may override. + */ + protected TestBigStructureCreator createBigStructureCreator(File root) + { + return new TestBigStructureCreator(root); + } + + protected abstract IImmutableCopier createHardLinkCopier(); +} \ No newline at end of file diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/FastRecursiveHardLinkMakerTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/FastRecursiveHardLinkMakerTest.java new file mode 100644 index 00000000000..fde9aa107b0 --- /dev/null +++ b/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/FastRecursiveHardLinkMakerTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2007 ETH Zuerich, CISD + * + * Licensed 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 ch.systemsx.cisd.common.filesystem; + +import static org.testng.AssertJUnit.assertFalse; +import static org.testng.AssertJUnit.assertTrue; + +import java.io.File; +import java.io.IOException; + +import org.testng.annotations.Test; + +/** + * Test cases for the {@link FastRecursiveHardLinkMaker}. + * <p> + * More or less a duplicate of {@link RecursiveHardLinkMakerTest}. + * + * @author Chandrasekhar Ramakrishnan + */ +public class FastRecursiveHardLinkMakerTest extends AbstractHardlinkMakerTest +{ + + @Override + protected TestBigStructureCreator createBigStructureCreator(File root) + { + int[] numberOfFolders = + { 100, 10 }; + int[] numberOfFiles = + { 1, 10, 10 }; + return new TestBigStructureCreator(root, numberOfFolders, numberOfFiles); + } + + @Override + protected IImmutableCopier createHardLinkCopier() + { + IImmutableCopier copier = FastRecursiveHardLinkMaker.tryCreate(); + assert copier != null; + return copier; + } +} diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/RecursiveHardLinkMakerTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/RecursiveHardLinkMakerTest.java index dc1e21fa2d0..6212f7682c7 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/RecursiveHardLinkMakerTest.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/RecursiveHardLinkMakerTest.java @@ -16,179 +16,19 @@ package ch.systemsx.cisd.common.filesystem; -import static org.testng.AssertJUnit.*; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; - -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import ch.systemsx.cisd.common.collections.CollectionIO; -import ch.systemsx.cisd.common.filesystem.FileUtilities; -import ch.systemsx.cisd.common.filesystem.HardLinkMaker; -import ch.systemsx.cisd.common.filesystem.IImmutableCopier; -import ch.systemsx.cisd.common.filesystem.RecursiveHardLinkMaker; -import ch.systemsx.cisd.common.logging.LogInitializer; - /** * Test cases for the {@link RecursiveHardLinkMaker}. * * @author Tomasz Pylak */ -public class RecursiveHardLinkMakerTest +public class RecursiveHardLinkMakerTest extends AbstractHardlinkMakerTest { - private static final File unitTestRootDirectory = - new File("targets" + File.separator + "unit-test-wd"); - - private static final File workingDirectory = - new File(unitTestRootDirectory, RecursiveHardLinkMakerTest.class.getSimpleName()); - - private static final File outputDir = new File(workingDirectory, "output"); - - @BeforeClass - public void init() - { - LogInitializer.init(); - unitTestRootDirectory.mkdirs(); - assert unitTestRootDirectory.isDirectory(); - } - - @BeforeMethod - public void setUp() - { - FileUtilities.deleteRecursively(workingDirectory); - outputDir.mkdirs(); - } - - @AfterClass - public void clean() - { - FileUtilities.deleteRecursively(outputDir); - } - - private static File createFile(File directory, String name) throws IOException - { - final File file = new File(directory, name); - file.createNewFile(); - assert file.isFile(); - CollectionIO - .writeIterable(file, Arrays.asList("test line 1", "test line 2", "test line 3")); - file.deleteOnExit(); - return file; - } - - private static File createDirectory(File directory, String name) throws IOException - { - final File file = new File(directory, name); - file.mkdir(); - assert file.isDirectory(); - file.deleteOnExit(); - return file; - } - - private static File mkPath(File parent, String... subdirs) - { - File file = parent; - for (String subdir : subdirs) - { - file = new File(file, subdir); - } - return file; - } - - private static void assertFileExists(File file) - { - assert file.isFile(); - } - - private static IImmutableCopier createHardLinkCopier() + @Override + protected IImmutableCopier createHardLinkCopier() { IImmutableCopier copier = RecursiveHardLinkMaker.tryCreate(HardLinkMaker.tryCreate()); assert copier != null; return copier; } - // ------------------------------------- test 1 - - // creates following structure - // dir1 - // ---dir1a - // ------file1a - // ---dir1b - // ------file1b - // dir2 - // ---file4 - // file2 - // file3 - private void createStructure(File inputDir) throws IOException - { - final File dir1 = createDirectory(inputDir, "dir1"); - final File dir1a = createDirectory(dir1, "dir1a"); - final File dir1b = createDirectory(dir1, "dir1b"); - final File dir2 = createDirectory(inputDir, "dir2"); - createFile(dir1a, "file1a"); - createFile(dir1b, "file1b"); - createFile(inputDir, "file2"); - createFile(inputDir, "file3"); - createFile(dir2, "file4"); - } - - @Test(groups = - { "requires_unix" }) - public void testCopyWithHardLinks() throws IOException - { - File inputDir = createDirectory(workingDirectory, "resource-to-copy"); - createStructure(inputDir); - assertTrue(createHardLinkCopier().copyImmutably(inputDir, outputDir, null).isOK()); - File newInput = new File(outputDir, inputDir.getName()); - - assertStructureExists(newInput); - boolean deleted = FileUtilities.deleteRecursively(inputDir); - assert deleted; - assertStructureExists(newInput); - } - - private static void assertStructureExists(File destinationDir) - { - assertFileExists(mkPath(destinationDir, "dir1", "dir1a", "file1a")); - assertFileExists(mkPath(destinationDir, "dir1", "dir1b", "file1b")); - assertFileExists(mkPath(destinationDir, "dir2", "file4")); - assertFileExists(mkPath(destinationDir, "file2")); - assertFileExists(mkPath(destinationDir, "file3")); - } - - // ------------------------------------- test 2 - - @Test(groups = - { "requires_unix" }) - public void testCopyFile() throws IOException - { - File src = createFile(workingDirectory, "fileXXX"); - assertFileExists(src); - - assertTrue(createHardLinkCopier().copyImmutably(src, outputDir, null).isOK()); - File dest = new File(outputDir, src.getName()); - assertFileExists(dest); - - modifyDest(dest); - assertFilesIdentical(src, dest); - } - - private static void assertFilesIdentical(File file1, File file2) - { - List<String> list1 = CollectionIO.readList(file1); - List<String> list2 = CollectionIO.readList(file2); - assertEquals(list1, list2); - } - - private static void modifyDest(File file) - { - List<String> list = Arrays.asList("new line 1", "new line 2"); - CollectionIO.writeIterable(file, list); - } } diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/TestBigStructureCreator.java b/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/TestBigStructureCreator.java new file mode 100644 index 00000000000..0b54b70de66 --- /dev/null +++ b/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/TestBigStructureCreator.java @@ -0,0 +1,163 @@ +/* + * Copyright 2012 ETH Zuerich, CISD + * + * Licensed 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 ch.systemsx.cisd.common.filesystem; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; + +import ch.systemsx.cisd.common.collections.CollectionIO; + +/** + * Create a large file/folder structure that will take some time to copy. + * + * @author Chandrasekhar Ramakrishnan + */ +public class TestBigStructureCreator +{ + private final File root; + + private final int[] numberOfFoldersPerLevel; + + private final int[] numberOfFilesPerFolder; + + /** + * Create a larger structure that will take a few seconds to copy. + */ + public static File createBigStructure(File directory, String name) throws IOException + { + final File root = new File(directory, name); + TestBigStructureCreator creator = new TestBigStructureCreator(root); + return creator.createBigStructure(); + } + + public TestBigStructureCreator(File root) + { + this(root, new int[] + { 100, 2 }, new int[] + { 0, 0, 10 }); + } + + public TestBigStructureCreator(File root, int[] numberOfFoldersPerLevel, + int[] numberOfFilesPerFolder) + { + this.root = root; + this.root.mkdir(); + assert numberOfFilesPerFolder.length == numberOfFoldersPerLevel.length + 1; + this.numberOfFoldersPerLevel = numberOfFoldersPerLevel; + this.numberOfFilesPerFolder = numberOfFilesPerFolder; + } + + /** + * Create a structure. + */ + public File createBigStructure() throws IOException + { + return createStructure(root, 0); + } + + /** + * Delete the structure asynchronously. + */ + public void deleteBigStructureAsync() + { + Runnable deleter = new Runnable() + { + @Override + public void run() + { + try + { + Thread.sleep(100); + } catch (InterruptedException e) + { + } + System.out.println("Deleting source"); + FileUtilities.deleteRecursively(root); + } + + }; + + Thread deleterThread = new Thread(deleter); + deleterThread.start(); + } + + /** + * Verify that the structure is complete. + */ + public boolean verifyStructure() + { + return verifyStructure(root, 0); + } + + private File createStructure(File localRoot, int depth) throws IOException + { + final int maxDepth = numberOfFoldersPerLevel.length; + for (int i = 0; i < numberOfFilesPerFolder[depth]; ++i) + { + File file = new File(localRoot, "File-" + i); + file.createNewFile(); + CollectionIO.writeIterable(file, + Arrays.asList("test line 1", "test line 2", "test line 3")); + } + if (maxDepth == depth) + { + return localRoot; + } + + for (int i = 0; i < numberOfFoldersPerLevel[depth]; ++i) + { + File folder = new File(localRoot, "Folder-" + i); + folder.mkdir(); + createStructure(folder, depth + 1); + } + + return localRoot; + } + + private boolean verifyStructure(File localRoot, int depth) + { + final int maxDepth = numberOfFoldersPerLevel.length; + for (int i = 0; i < numberOfFilesPerFolder[depth]; ++i) + { + File file = new File(localRoot, "File-" + i); + if (false == file.exists()) + { + return false; + } + } + if (maxDepth == depth) + { + return true; + } + + for (int i = 0; i < numberOfFoldersPerLevel[depth]; ++i) + { + File folder = new File(localRoot, "Folder-" + i); + if (false == folder.exists()) + { + return false; + } + if (false == verifyStructure(folder, depth + 1)) + { + return false; + } + } + + return true; + } +} -- GitLab