/* * DependenciesTests.java * Copyright (c) 1998-2008, The University of Sheffield. * * This code is from the GATE project (http://gate.ac.uk/) and is free * software licenced under the GNU General Public License version 3. It is * distributed without any warranty. For more details see COPYING.txt in the * top level directory (or at http://gatewiki.sf.net/COPYING.txt). */ package gate.yam.depend; import gate.persist.PersistenceException; import gate.util.GateException; import gate.yam.YamFile; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.Logger; import org.springframework.core.io.FileSystemResource; import java.io.*; import java.nio.channels.FileChannel; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Tests for Dependencies * @author Angus Roberts */ public class DependenciesTests extends TestCase { /** Logger */ static Logger log = Logger.getLogger("gate.yam.depend.DependenciesTests"); /** * Matches the names of YamFiles as used in testing, capturing the numeric * part for use as a shorthand. (see @link #shorthandToPaths(String). * YamFiles used in testing are named using a conventionally, as defined in * this pattern. */ private static Pattern testFilePattern = Pattern.compile("yam-depends-(\\d+).yam"); /** * Some test files come in to versions - their original, and their modified * version. This pattern matches the original, capturing the parts that make * up the name of the actual file as used in tests. */ private static Pattern originalTestFilePattern = Pattern.compile("(yam-depends-)ORIGINAL-(\\d+.yam)"); /** * A FilenameFilter that accepts yam files used by DependenciesTests. * By convention, filenames are "yam-depends-\d+.yam" */ class DependenciesTestsFileFilter implements FilenameFilter { /** Accept a file if it is a yam file used in DependenciesTests*/ public boolean accept(File dir, String name) { return testFilePattern.matcher(name).matches(); } } /** * A FilenameFilter that accepts original versions of yam files used by * DependenciesTests. By convention, filenames are * "yam-depends-ORIGINAL-\d+.yam" */ class DependenciesTestsOriginalFileFilter implements FilenameFilter { /** Accept a file if it is the original version of * a yam file used in DependenciesTests */ public boolean accept(File dir, String name) { return originalTestFilePattern.matcher(name).matches(); } } /** * The directory that test yam files are found in. */ private static File yamDir; /** * By convention, each yam file used in testing is named * "yam-depends-\d+.yam". This Map maps the digit part to the full name. * It is used so that we can refer to sets and graphs of files by just their * digit part. */ Map<String, String> yamFileNameMap = new HashMap<String, String>(); /** * As for @link #yamFileNameMap, but maps the digit part of the name to the * actual YamFile, post-generate(). */ Map<String, YamFile> yamFileMap = new HashMap<String, YamFile>(); /** * A List of parsed YamFiles that make up a wiki */ private List<YamFile> wiki1 = new ArrayList<YamFile>(); /** * A Dependencies instance for wiki1 */ private Dependencies dep1; /** Create a Dependencies test case * * @param testName The name of the test */ public DependenciesTests(String testName) { super(testName); } // TODO remove setting of directories to strings - get from where? /** * Set up the tests for Dependencies */ protected void setUp() { // set up the directory to which dependencies will be serialized String testDirName = System.getProperty("gate.yam.depend.test.dir"); if (testDirName == null) { testDirName = "test/scratch/dependencies"; } File testDirFile = new File(testDirName); testDirFile.mkdirs(); Dependencies.setSerializationDirectory(testDirFile); // get a directory of yam files for testing String yamDirName = System.getProperty("java.yam.resources.dir"); if (yamDirName == null) { yamDirName = this.getClass().getResource("/gate/yam/resources").getFile(); } log.info("Getting test yam files from: " + yamDirName); yamDir = new File(yamDirName); // Some of our test files have original and modified versions, named // yam-depends-ORIGINAL-\d+.yam and yam-depends-MODIFIED-\d+.yam // Copy the original versions to their "proper" names for loading File[] originalVersions = yamDir.listFiles(new DependenciesTestsOriginalFileFilter()); for(File origFile : originalVersions) { //Work out the name as used in tests Matcher matcher = originalTestFilePattern.matcher(origFile.getName()); if (!matcher.matches()) { fail("Failed to setup - filename not conventional: " + origFile.getName()); } String newName = matcher.group(1) + matcher.group(2); File newFile = new File(yamDir, newName); copy(origFile, newFile); } // Get all the yam files used by DependenciesTests File[] testFiles = yamDir.listFiles(new DependenciesTestsFileFilter()); for(File file : testFiles ) { YamFile yamFile = YamFile.get(new FileSystemResource(file)); try{ String canPath = yamFile.getCanonicalPath(); log.info("Getting test file: " + canPath); // Group 1 of testFilePattern is the numeric part Matcher matcher = testFilePattern.matcher(file.getName()); if(!matcher.matches()) { fail("Failed to setup - filename not conventional: " + file.getName()); } String number = matcher.group(1); yamFile.generate(); yamFileNameMap.put(number, canPath); yamFileMap.put(number, yamFile); } catch(GateException ge) { fail("Failed to setup: " + ge.getMessage()); } } // Add some files to a list, to use as a wiki wiki1.add(yamFileMap.get("1")); wiki1.add(yamFileMap.get("2")); wiki1.add(yamFileMap.get("3")); wiki1.add(yamFileMap.get("4")); wiki1.add(yamFileMap.get("5")); // Get dependencies for the wiki try{ // Clear it before getting a new one - could have persisted on disk Dependencies.remove("1"); dep1 = Dependencies.get("1"); } catch(PersistenceException pe) { fail("Failed to set up: " + pe.getMessage()); } assertTrue("New Dependencies not empty", dep1.isEmpty()); // Add all the files in the wiki to the dependencies for(YamFile yam : wiki1) { dep1.created(yam); } assertFalse( "Dependencies is empty after adding links", dep1.isEmpty() ); } /** * Test a few Dependencies basics: equality, hashCode, YamFile creation * and removal. * @throws Exception if the test fails */ public void testCreateAndBasics() throws Exception { log.info("========== DependenciesTests.tesCreateAndBasics() =============="); log.info("testing dependencies.created(YamFile) and equality methods"); // Create a Dependencies that is the same as our global dep1 Dependencies dep2 = Dependencies.get("2"); for(YamFile yam : wiki1) { dep2.created(yam); } // What does this dependencies look like? assertEquals("Dependencies linksTo not correct after create", shorthandToPaths("1:[2,3];2:[4,5];3:[5]"), dep2.linksToAsString()); assertEquals("Dependencies linkedBy not correct after create", shorthandToPaths("2:[1];3:[1];4:[2];5:[2,3]"), dep2.linkedByAsString()); assertEquals("Dependencies includes not correct after create", shorthandToPaths("1:[2,3,4];2:[4]"), dep2.includesAsString()); assertEquals("Dependencies includedBy not correct after create", shorthandToPaths("2:[1];3:[1];4:[1,2]"), dep2.includedByAsString()); // Test equality assertEquals("Same Dependencies not equal", dep1, dep1); assertEquals( "Dependencies not equal after get", dep1, Dependencies.get("1")); assertEquals("Identical Dependencies not equal", dep1, dep2); assertEquals( "Identical Dependencies with different hash codes", dep1.hashCode(), dep2.hashCode()); // Can we remove a Dependencies? Dependencies.remove("2"); assertFalse("Dependencies still exists after removal", Dependencies.exists("2")); } /** * Test Dependencies YamFile deletion * @throws Exception if the test fails */ public void testDelete() throws Exception { log.info("============== DependenciesTests.testDelete() =================="); log.info("testing dependencies.deleted(YamFile)"); // Holds results from Dependencies event operations Set<String> toRegenerate; // What happens if we delete a YamFile? // First, delete one that has links and includes in it toRegenerate = dep1.deleted(yamFileMap.get("1")); assertEquals("Regenerate set not correct after delete", new HashSet<String>(), toRegenerate); assertEquals("Dependencies linksTo not correct after delete", shorthandToPaths("2:[4,5];3:[5]"), dep1.linksToAsString()); assertEquals("Dependencies linkedBy not correct after delete", shorthandToPaths("4:[2];5:[2,3]"), dep1.linkedByAsString()); assertEquals("Dependencies includes not correct after delete", shorthandToPaths("2:[4]"), dep1.includesAsString()); assertEquals("Dependencies includedBy not correct after delete", shorthandToPaths("4:[2]"), dep1.includedByAsString()); // Now recreate it - put it back toRegenerate = dep1.created(yamFileMap.get("1")); assertEquals("Regenerate set not correct after create", new HashSet<String>(), toRegenerate); assertEquals("Dependencies linksTo not correct after create", shorthandToPaths("1:[2,3];2:[4,5];3:[5]"), dep1.linksToAsString()); assertEquals("Dependencies linkedBy not correct after create", shorthandToPaths("2:[1];3:[1];4:[2];5:[2,3]"), dep1.linkedByAsString()); assertEquals("Dependencies includes not correct after create", shorthandToPaths("1:[2,3,4];2:[4]"), dep1.includesAsString()); assertEquals("Dependencies includedBy not correct after create", shorthandToPaths("2:[1];3:[1];4:[1,2]"), dep1.includedByAsString()); } /** * Test Dependencies YamFile renaming * @throws Exception if the test fails */ public void testRename() throws Exception { log.info("============== DependenciesTests.testRename() =================="); log.info("testing dependencies.renamed(YamFile)"); // Holds results from Dependencies event operations Set<String> toRegenerate; List<String> toRegenerateSorted; // Rename a YamFile. We don't really, just pretend that one file is a rename // of another toRegenerate = dep1.renamed(yamFileMap.get("2"), yamFileMap.get("6")); toRegenerateSorted = new ArrayList<String>(toRegenerate); Collections.sort(toRegenerateSorted); assertEquals("Regenerate set not correct after rename", numbersToList("1"), toRegenerateSorted); assertEquals("Dependencies linksTo not correct after rename", shorthandToPaths("1:[3,6];3:[5];6:[4,5]"), dep1.linksToAsString()); assertEquals("Dependencies linkedBy not correct after rename", shorthandToPaths("3:[1];4:[6];5:[3,6];6:[1]"), dep1.linkedByAsString()); assertEquals("Dependencies includes not correct after rename", shorthandToPaths("1:[3,4,6];6:[4]"), dep1.includesAsString()); assertEquals("Dependencies includedBy not correct after rename", shorthandToPaths("3:[1];4:[1,6];6:[1]"), dep1.includedByAsString()); // Put everything back in its original form for further tests dep1.renamed(yamFileMap.get("6"), yamFileMap.get("2")); } /** * Test Dependencies - further YamFile deletion tests * @throws Exception if the test fails */ public void testDelete2() throws Exception { log.info("============== DependenciesTests.testDelete2() ================="); log.info("testing dependencies.deleted(YamFile)"); // Holds results from Dependencies event operations Set<String> toRegenerate; List<String> toRegenerateSorted; // Delete a YamFile that will need a bit nore regeneration toRegenerate = dep1.deleted(yamFileMap.get("4")); toRegenerateSorted = new ArrayList<String>(toRegenerate); Collections.sort(toRegenerateSorted); assertEquals("Regenerate set not correct after delete", numbersToList("1,2"), toRegenerateSorted); // And delete another toRegenerate = dep1.deleted(yamFileMap.get("5")); toRegenerateSorted = new ArrayList<String>(toRegenerate); Collections.sort(toRegenerateSorted); assertEquals("Regenerate set not correct after delete", numbersToList("2,3"), toRegenerateSorted); // Put everything back in its original form for further tests dep1.created(yamFileMap.get("4")); dep1.created(yamFileMap.get("5")); // Check all is how it should be assertEquals("Dependencies linksTo not correct after delete and create", shorthandToPaths("1:[2,3];2:[4,5];3:[5]"), dep1.linksToAsString()); assertEquals("Dependencies linkedBy not correct after delete and create", shorthandToPaths("2:[1];3:[1];4:[2];5:[2,3]"), dep1.linkedByAsString()); assertEquals("Dependencies includes not correct after delete and create", shorthandToPaths("1:[2,3,4];2:[4]"), dep1.includesAsString()); assertEquals("Dependencies includedBy not correct after delete and create", shorthandToPaths("2:[1];3:[1];4:[1,2]"), dep1.includedByAsString()); } /** * Test Dependencies YamFile modification * @throws Exception if the test fails */ public void testModify() throws Exception { log.info("============== DependenciesTests.testModify() =================="); log.info("testing dependencies.modified(YamFile)"); // Holds results from Dependencies event operations Set<String> toRegenerate; List<String> toRegenerateSorted; // File modification. We fake this by copying a modified version over // an existing file, and re-generating the yam. File currentFile = new File(yamDir, "yam-depends-2.yam"); File modFile = new File(yamDir, "yam-depends-MODIFIED-2.yam"); copy(modFile, currentFile); // Regenerate the yam yamFileMap.get("2").generate(); // Notify the modification toRegenerate = dep1.modified(yamFileMap.get("2")); toRegenerateSorted = new ArrayList<String>(toRegenerate); Collections.sort(toRegenerateSorted); assertEquals("Regenerate set not correct after modify", numbersToList("1"), toRegenerateSorted); // Check all is how it should be assertEquals("Dependencies linksTo not correct after modify", shorthandToPaths("1:[2,3];2:[4,7];3:[5]"), dep1.linksToAsString()); assertEquals("Dependencies linkedBy not correct after modify", shorthandToPaths("2:[1];3:[1];4:[2];5:[3];7:[2]"), dep1.linkedByAsString()); assertEquals("Dependencies includes not correct after modify", shorthandToPaths("1:[2,3,4];2:[4]"), dep1.includesAsString()); assertEquals("Dependencies includedBy not correct after modify", shorthandToPaths("2:[1];3:[1];4:[1,2]"), dep1.includedByAsString()); // Another File modification. currentFile = new File(yamDir, "yam-depends-1.yam"); modFile = new File(yamDir, "yam-depends-MODIFIED-1.yam"); copy(modFile, currentFile); // Regenerate the yam yamFileMap.get("1").generate(); // Notify the modification toRegenerate = dep1.modified(yamFileMap.get("1")); assertEquals("Regenerate set not correct after modify", new HashSet<String>(), toRegenerate); // Check all is how it should be assertEquals("Dependencies linksTo not correct after modify", shorthandToPaths("1:[2,3];2:[4,7];3:[5]"), dep1.linksToAsString()); assertEquals("Dependencies linkedBy not correct after modify", shorthandToPaths("2:[1];3:[1];4:[2];5:[3];7:[2]"), dep1.linkedByAsString()); assertEquals("Dependencies includes not correct after modify", shorthandToPaths("1:[3,4];2:[4]"), dep1.includesAsString()); assertEquals("Dependencies includedBy not correct after modify", shorthandToPaths("3:[1];4:[1,2]"), dep1.includedByAsString()); // Modify all files back copy(new File(yamDir, "yam-depends-ORIGINAL-1.yam"), new File(yamDir, "yam-depends-1.yam")); copy(new File(yamDir, "yam-depends-ORIGINAL-2.yam"), new File(yamDir, "yam-depends-2.yam")); // Regenerate the yams yamFileMap.get("1").generate(); yamFileMap.get("2").generate(); } /** * Test links to non-yam files and urls * @throws Exception if the test fails */ public void testNonYamLinks() throws Exception { log.info("============ DependenciesTests.testNonYamLinks() ==============="); log.info("testing links to non yam files and urls"); // Add a new file to the wiki, create it. YamFile yf = yamFileMap.get("8"); wiki1.add(yf); dep1.created(yf); // Check all is how it should be assertEquals("Dependencies linksTo not correct after create", shorthandToPaths("1:[2,3];2:[4,5];3:[5];" + "8:[../../non-existent.html,non-existent.html]"), dep1.linksToAsString()); assertEquals("Dependencies linkedBy not correct after create", shorthandToPaths("../../non-existent.html:[8];" + "" + "non-existent.html:[8];2:[1];3:[1];4:[2];5:[2,3]"), dep1.linkedByAsString()); assertEquals("Dependencies includes not correct after create", shorthandToPaths("1:[2,3,4];2:[4]"), dep1.includesAsString()); assertEquals("Dependencies includedBy not correct after create", shorthandToPaths("2:[1];3:[1];4:[1,2]"), dep1.includedByAsString()); // Get rid of the new file dep1.deleted(yf); // Check all is how it should be assertEquals("Dependencies linksTo not correct after delete", shorthandToPaths("1:[2,3];2:[4,5];3:[5]"), dep1.linksToAsString()); assertEquals("Dependencies linkedBy not correct after delete", shorthandToPaths("2:[1];3:[1];4:[2];5:[2,3]"), dep1.linkedByAsString()); assertEquals("Dependencies includes not correct after delete", shorthandToPaths("1:[2,3,4];2:[4]"), dep1.includesAsString()); assertEquals("Dependencies includedBy not correct after delete", shorthandToPaths("2:[1];3:[1];4:[1,2]"), dep1.includedByAsString()); } /** * Test Dependencies File creation, deletion, and renaming * @throws Exception if the test fails */ public void testNonYamChanges() throws Exception { log.info("========= DependenciesTests.testNonYamChanges() ============="); // Holds results from Dependencies event operations Set<String> toRegenerate; List<String> toRegenerateSorted; // Create, ie upload, a file log.info("testing dependencies.created(File)"); File nonYam = new File(yamDir, "nonYamFile.abc"); toRegenerate = dep1.created(nonYam); // Should be nothing to regenerate, nothing links to it assertEquals("Regenerate set not correct after created(File)", new HashSet<String>(), toRegenerate); // Check all is how it should be - no changes assertEquals("Dependencies linksTo not correct after create", shorthandToPaths("1:[2,3];2:[4,5];3:[5]"), dep1.linksToAsString()); assertEquals("Dependencies linkedBy not correct after create", shorthandToPaths("2:[1];3:[1];4:[2];5:[2,3]"), dep1.linkedByAsString()); assertEquals("Dependencies includes not correct after create", shorthandToPaths("1:[2,3,4];2:[4]"), dep1.includesAsString()); assertEquals("Dependencies includedBy not correct after create", shorthandToPaths("2:[1];3:[1];4:[1,2]"), dep1.includedByAsString()); // Now delete the non yam toRegenerate = dep1.deleted(nonYam); // Should be nothing to regenerate, nothing links to it assertEquals("Regenerate set not correct after deleted(File)", new HashSet<String>(), toRegenerate); // Now add in a page that links to a non-existent non-yam YamFile linkingFile = yamFileMap.get("9"); wiki1.add(linkingFile); toRegenerate = dep1.created(linkingFile); // Should be nothing to regenerate, nothing dependent on 9 has changed assertEquals("Regenerate set not correct after created(YamFile)", new HashSet<String>(), toRegenerate); // Check all is how it should be - a new link to a non yam file assertEquals("Dependencies linksTo not correct after create", shorthandToPaths("1:[2,3];2:[4,5];3:[5];9:[nonYamFile.abc]"), dep1.linksToAsString()); assertEquals("Dependencies linkedBy not correct after create", shorthandToPaths("nonYamFile.abc:[9];2:[1];3:[1];4:[2];5:[2,3]"), dep1.linkedByAsString()); assertEquals("Dependencies includes not correct after create", shorthandToPaths("1:[2,3,4];2:[4]"), dep1.includesAsString()); assertEquals("Dependencies includedBy not correct after create", shorthandToPaths("2:[1];3:[1];4:[1,2]"), dep1.includedByAsString()); // Now create the non yam file again toRegenerate = dep1.created(nonYam); toRegenerateSorted = new ArrayList<String>(toRegenerate); Collections.sort(toRegenerateSorted); // We should need to regenerate the web page that links to the non yam assertEquals("Regenerate set not correct after created(File)", numbersToList("9"), toRegenerateSorted); // Rename: we should have to regenerate the linker // We don't really rename a file on the fiesystem, just pretend log.info("testing dependencies.renamed(File, File)"); File nonYamRenamed = new File(yamDir, "nonYamFileRenamed.abc"); toRegenerate = dep1.renamed(nonYam, nonYamRenamed); toRegenerateSorted = new ArrayList<String>(toRegenerate); Collections.sort(toRegenerateSorted); assertEquals("Regenerate set not correct after renamed(File)", numbersToList("9"), toRegenerateSorted); // Check all is how it should be - link to the renamed file assertEquals("Dependencies linksTo not correct after rename", shorthandToPaths("1:[2,3];2:[4,5];3:[5];9:[nonYamFileRenamed.abc]"), dep1.linksToAsString()); assertEquals("Dependencies linkedBy not correct after rename", shorthandToPaths("nonYamFileRenamed.abc:[9];2:[1];3:[1];4:[2]" + ";5:[2,3]"), dep1.linkedByAsString()); assertEquals("Dependencies includes not correct after rename", shorthandToPaths("1:[2,3,4];2:[4]"), dep1.includesAsString()); assertEquals("Dependencies includedBy not correct after rename", shorthandToPaths("2:[1];3:[1];4:[1,2]"), dep1.includedByAsString()); // Delete: we should get some files to regenerate log.info("testing dependencies.deleted(File)"); toRegenerate = dep1.deleted(nonYamRenamed); toRegenerateSorted = new ArrayList<String>(toRegenerate); Collections.sort(toRegenerateSorted); assertEquals("Regenerate set not correct after deleted(File)", numbersToList("9"), toRegenerateSorted); // Check all is how it should be - , with a link to a now non-existent file assertEquals("Dependencies linksTo not correct after delete", shorthandToPaths("1:[2,3];2:[4,5];3:[5];9:[nonYamFileRenamed.abc]"), dep1.linksToAsString()); assertEquals("Dependencies linkedBy not correct after delete", shorthandToPaths("nonYamFileRenamed.abc:[9];2:[1];3:[1];4:[2]" + ";5:[2,3]"), dep1.linkedByAsString()); assertEquals("Dependencies includes not correct after delete", shorthandToPaths("1:[2,3,4];2:[4]"), dep1.includesAsString()); assertEquals("Dependencies includedBy not correct after delete", shorthandToPaths("2:[1];3:[1];4:[1,2]"), dep1.includedByAsString()); // Remove the linking yam file - should be nothing to regenerate toRegenerate = dep1.deleted(linkingFile); assertEquals("Regenerate set not correct after deleted(YamFile)", new HashSet<String>(), toRegenerate); // ... and we should be back to the beggining assertEquals("Dependencies linksTo not correct after delete", shorthandToPaths("1:[2,3];2:[4,5];3:[5]"), dep1.linksToAsString()); assertEquals("Dependencies linkedBy not correct after delete", shorthandToPaths("2:[1];3:[1];4:[2]" + ";5:[2,3]"), dep1.linkedByAsString()); assertEquals("Dependencies includes not correct after delete", shorthandToPaths("1:[2,3,4];2:[4]"), dep1.includesAsString()); assertEquals("Dependencies includedBy not correct after delete", shorthandToPaths("2:[1];3:[1];4:[1,2]"), dep1.includedByAsString()); } /** * Test Dependencies serialization * @throws Exception if the test fails */ public void testSerialization() throws Exception { log.info("============= DependenciesTests.testSerialization() ============"); log.info("testing serialization and deserialization of Dependencies"); Dependencies.remove("1"); Dependencies dep1 = Dependencies.get("1"); // Add all the files in a wiki to the depencies for(YamFile yam : wiki1) { dep1.created(yam); } Dependencies.serialize(); Dependencies.clear(); assertTrue("Dependencies removed", Dependencies.exists("1")); Dependencies dep1Reloaded = Dependencies.get("1"); assertEquals( "Dependencies not consistently serialized / deserialized", dep1, dep1Reloaded ); Dependencies.remove("1"); } /** * Suite of tests for Dependencies * @return The suite of tests */ public static Test suite() { TestSuite suite= new TestSuite(); suite.addTest(new DependenciesTests("testCreateAndBasics")); suite.addTest(new DependenciesTests("testDelete")); suite.addTest(new DependenciesTests("testRename")); suite.addTest(new DependenciesTests("testDelete2")); suite.addTest(new DependenciesTests("testModify")); suite.addTest(new DependenciesTests("testNonYamLinks")); suite.addTest(new DependenciesTests("testNonYamChanges")); suite.addTest(new DependenciesTests("testSerialization")); return suite; } /** * <p>Replace all file numbers in str with the equivalent canonical paths in * yamFileNameMap. All files used in Dependencies testing are named by * convention as "yam-depends-\d+.yam". Dependencies will report its * internal state graphs in the form "pathA:[pathB,pathC];pathB[pathD]", * where pathX is the canonical path of a file.</p> * <p>For test files, we can refer to a Dependencies graph in a shorthand form * using just the digit part of the test name, e.g. "1:[2,3];2[4]" and then * translate this to full canonical paths using this method.</p> * <p>Non-yam files are referred to by their path relative to their linking * node. They are replaced by their full canonical path. For example, * "1:[some-file.html]", where some-file is not from yam, will become * "/parent/path/yam-depends-1.yam:[/parent/path/some-file.html]" * </p> * @param str A string in which we want to replace numbers with test file * canonical paths * @return The equivalent string with numbers replaced by test file * canonical paths */ public String shorthandToPaths(String str) { StringBuilder bldr = new StringBuilder(); for(String nodeAndArcs : str.split("(\\]\\;)|(\\])")) { String[] nodeAndArcsSplit = nodeAndArcs.split("\\:\\["); String node = nodeAndArcsSplit[0]; String arcs = nodeAndArcsSplit[1]; String nodePath = null; if(node.matches("\\d+")) { // We've got a number representing a yam file: map it to a filename nodePath = yamFileNameMap.get(node); } else { // We've got a string representing a non-yam file // A non-yam node is relative to its sole arc // e.g. abc.html:[2] File yamParent = new File(yamFileNameMap.get(arcs)).getParentFile(); try{ nodePath = new File(yamParent, node).getCanonicalPath(); } catch(IOException ioe) { fail("Couldn't resolve link canonical path: " + ioe.getMessage()); } } bldr.append(nodePath); bldr.append(":["); for(String arc: arcs.split("\\,")) { if(arc.matches("\\d+")) { // We've got a number representing a yam file: map it to a filename bldr.append(yamFileNameMap.get(arc)); } else { // We've got a string representing a non-yam file // An arc to a non-yam is relative to its node File yamParent = new File(nodePath).getParentFile(); File link = new File(yamParent, arc); try{ bldr.append(link.getCanonicalPath()); } catch(IOException ioe) { fail("Couldn't resolve link canonical path: " + ioe.getMessage()); } } bldr.append(","); } bldr.deleteCharAt(bldr.length() - 1); bldr.append("];"); } bldr.deleteCharAt(bldr.length() - 1); return bldr.toString(); } /** * Replace all file numbers in str with the equivalent canonical paths in * yamFileNameMap, as described in * @link DependenciesTests#shorthandToPaths(String). * By convention, the file numbers in str are comma separated * @param str A comma separated list of numbers * @return A List of canonical paths equivalent to the numbers in str */ private List<String> numbersToList(String str) { List<String> pathList = new ArrayList<String>(); for(String number : str.split(",")) { pathList.add(yamFileNameMap.get(number)); } return pathList; } /** * Copy one File to another. Testing fails if the copy fails. * @param in The File that will be copied * @param out The File to which in will be copied */ private void copy(File in, File out) { log.info("Copying yam file from: " + in.getName() + " to: " + out.getName()); try { FileChannel ic = new FileInputStream(in).getChannel(); FileChannel oc = new FileOutputStream(out).getChannel(); ic.transferTo(0, ic.size(), oc); ic.close(); oc.close(); } catch (IOException ioe) { fail("Failed testing while copying modified file: " + ioe.getMessage()); } } }