diff --git a/enterprise-update-test/pom.xml b/enterprise-update-test/pom.xml index c423f66a7c..c2d254b468 100644 --- a/enterprise-update-test/pom.xml +++ b/enterprise-update-test/pom.xml @@ -53,6 +53,37 @@ test + + de.schlichtherle.truezip + truezip-driver-zip + 7.7.9 + + + de.schlichtherle.truezip + truezip-file + 7.7.9 + + + commons-io + commons-io + 2.4 + + + org.apache.logging.log4j + log4j-api + 2.3 + + + org.apache.logging.log4j + log4j-core + 2.3 + + + + org.springframework + spring-core + 4.2.4.RELEASE + diff --git a/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/CaseSensitivePathComparator.java b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/CaseSensitivePathComparator.java new file mode 100644 index 0000000000..56c03633ba --- /dev/null +++ b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/CaseSensitivePathComparator.java @@ -0,0 +1,28 @@ +/* + * Copyright 2016 Alfresco Software, Ltd. All rights reserved. + * + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +package org.alfresco.update.tool.dircomp; + +import java.nio.file.Path; +import java.util.Comparator; + +/** + * Provides a platform agnostic and consistent sorting mechanism + * for {@link java.nio.file.Path} objects. + * + * @author Matt Ward + */ +public class CaseSensitivePathComparator implements Comparator +{ + @Override + public int compare(Path p1, Path p2) + { + String pathStr1 = p1.toString(); + String pathStr2 = p2.toString(); + return pathStr1.compareTo(pathStr2); + } +} diff --git a/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/FileTreeCompare.java b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/FileTreeCompare.java new file mode 100644 index 0000000000..4c164402df --- /dev/null +++ b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/FileTreeCompare.java @@ -0,0 +1,22 @@ +/* + * Copyright 2016 Alfresco Software, Ltd. All rights reserved. + * + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +package org.alfresco.update.tool.dircomp; + +import java.nio.file.Path; +import java.util.List; + + +/** + * File tree comparison tool interface. + * + * @author Matt Ward + */ +public interface FileTreeCompare +{ + ResultSet compare(Path p1, Path p2); +} diff --git a/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/FileTreeCompareImpl.java b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/FileTreeCompareImpl.java new file mode 100644 index 0000000000..86dda25b16 --- /dev/null +++ b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/FileTreeCompareImpl.java @@ -0,0 +1,241 @@ +/* + * Copyright 2016 Alfresco Software, Ltd. All rights reserved. + * + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +package org.alfresco.update.tool.dircomp; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.alfresco.update.tool.dircomp.exception.FileTreeCompareException; +import org.apache.commons.io.FileUtils; + +import de.schlichtherle.truezip.file.TArchiveDetector; +import de.schlichtherle.truezip.file.TConfig; +import de.schlichtherle.truezip.file.TFile; +import de.schlichtherle.truezip.file.TVFS; +import de.schlichtherle.truezip.fs.archive.zip.ZipDriver; +import de.schlichtherle.truezip.socket.sl.IOPoolLocator; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.util.AntPathMatcher; + +/** + * Class capable of comparing two trees of files to determine which directories or + * files appear in one tree and not the other, or whether a file that appears in + * both has differences in its content. + * + * @author Matt Ward + */ +public class FileTreeCompareImpl implements FileTreeCompare +{ + private static final Logger log = LogManager.getLogger(FileTreeCompareImpl.class); + private final Set ignorePaths = new HashSet<>(); + private final AntPathMatcher pathMatcher = new AntPathMatcher(File.separator); + + public FileTreeCompareImpl() + { + this(new HashSet()); + } + + public FileTreeCompareImpl(Set ignorePaths) + { + // This config MUST be present before any TFile objects etc. are created. + TConfig config = TConfig.get(); + config.setArchiveDetector(new TArchiveDetector("war|jar", new ZipDriver(IOPoolLocator.SINGLETON))); + this.ignorePaths.addAll(ignorePaths); + } + + @Override + public ResultSet compare(Path p1, Path p2) + { + ResultSet resultSet = new ResultSet(); + try + { + compare(resultSet.stats, resultSet.results, p1, p2); + } + catch (Exception e) + { + throw new FileTreeCompareException("Unable to compare file trees.", e); + } + return resultSet; + } + + private void compare(ResultSet.Stats stats, List results, Path tree1, Path tree2) throws IOException + { + SortedPathSet set1 = sortedPaths(tree1); + SortedPathSet set2 = sortedPaths(tree2); + + SortedPathSet all = new SortedPathSet(); + all.addAll(set1); + all.addAll(set2); + + for (Path pathToFind : all) + { + if (pathMatchesIgnorePattern(pathToFind)) + { + // Skip paths that we don't want to examine, e.g. tomcat/temp + log.debug("Skipping path: "+pathToFind); + stats.ignoredFileCount++; + continue; + } + + Result result = new Result(); + results.add(result); + stats.resultCount++; + + if (set1.contains(pathToFind) && set2.contains(pathToFind)) + { + log.debug("In both: "+pathToFind); + // Set the results, translating paths back to absolute as required. + result.p1 = tree1.resolve(pathToFind); + result.p2 = tree2.resolve(pathToFind); + boolean contentMatches = false; + if (Files.isRegularFile(result.p1) && Files.isRegularFile(result.p2)) + { + contentMatches = FileUtils.contentEquals(result.p1.toFile(), result.p2.toFile()); + if (!contentMatches && isSpecialArchive(pathToFind)) + { + Path archive1 = extract(result.p1); + Path archive2 = extract(result.p2); + result.subTree1 = archive1; + result.subTree2 = archive2; + final int diffBefore = stats.differenceCount; + compare(stats, result.subResults, archive1, archive2); + final int diffAfter = stats.differenceCount; + if (diffAfter == diffBefore) + { + // No significant differences were found in the (recursive) subtree comparison. + // We can therefore mark the special archive files matching in both trees. + contentMatches = true; + } + } + } + else if (Files.isDirectory(result.p1) && Files.isDirectory(result.p2)) + { + // Two directories are counted as the same. + contentMatches = true; + } + result.equal = contentMatches; + } + else if (set1.contains(pathToFind)) + { + log.debug("In tree1 only: "+pathToFind); + result.p1 = tree1.resolve(pathToFind); + result.p2 = null; + } + else if (set2.contains(pathToFind)) + { + log.debug("In tree2 only: "+pathToFind); + result.p1 = null; + result.p2 = tree2.resolve(pathToFind); + } + else + { + throw new IllegalStateException( + "Something went wrong. The path is not found in either tree: "+pathToFind); + } + + if (!result.equal) + { + stats.differenceCount++; + } + } + } + + private boolean isSpecialArchive(Path pathToFind) + { + return pathToFind.getFileName().toString().toLowerCase().endsWith(".war") || + pathToFind.getFileName().toString().toLowerCase().endsWith(".jar"); + } + + /** + * If the set of paths to ignore ({@link #ignorePaths}) contains + * a pattern matching the specified path, then true is returned. + *

+ * Patterns are ant-style patterns. + * + * @param path The path to check + * @return True if there is a path in the ignorePaths set that is a prefix of the path. + */ + private boolean pathMatchesIgnorePattern(String path) + { + for (String pattern : ignorePaths) + { + if (pathMatcher.match(pattern, path)) + { + return true; + } + } + return false; + } + + /** + * @see #pathMatchesIgnorePattern(String) + */ + private boolean pathMatchesIgnorePattern(Path path) + { + return pathMatchesIgnorePattern(path.toString()); + } + + private Path extract(Path archivePath) throws IOException + { + String destDirName = archivePath.getFileName().toString(); + Path dest = Files.createTempDirectory(destDirName); + extract(archivePath, dest); + return dest; + } + + private void extract(Path archivePath, Path destPath) throws IOException + { + TFile archive = new TFile(archivePath.toFile()); + TFile dest = new TFile(destPath.toFile(), TArchiveDetector.NULL); + try + { + // Unzip the archive. + archive.cp_rp(dest); + } + finally + { + TVFS.umount(archive); + TVFS.umount(dest); + } + } + + /** + * Traverse path and create a {@link SortedPathSet} containing the set + * of paths encountered. The {@link Path} instances are relative to + * the base path provided as a parameter to this method. + * + * @param path The path to traverse. + * @return SortedPathSet + * @throws IOException + */ + protected SortedPathSet sortedPaths(Path path) throws IOException + { + SortedPathSet sortedPaths = new SortedPathSet(); + collectPaths(sortedPaths, path, path.toFile()); + return sortedPaths; + } + + private void collectPaths(SortedPathSet sortedSet, Path root, File path) throws IOException + { + for (File f : path.listFiles()) + { + Path relativePath = root.relativize(f.toPath()); + sortedSet.add(relativePath); + if (f.isDirectory()) + { + collectPaths(sortedSet, root, f); + } + } + } +} diff --git a/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/HtmlResultFormatter.java b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/HtmlResultFormatter.java new file mode 100644 index 0000000000..b934897628 --- /dev/null +++ b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/HtmlResultFormatter.java @@ -0,0 +1,155 @@ +/* + * Copyright 2016 Alfresco Software, Ltd. All rights reserved. + * + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +package org.alfresco.update.tool.dircomp; + +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.List; + +/** + * Format results as HTML. + * + * @author Matt Ward + */ +public class HtmlResultFormatter implements ResultFormatter +{ + private int maxPathDisplayLength = 80; + private boolean differencesOnly; + + + @Override + public void format(ResultSet resultSet, OutputStream out) + { + try(PrintWriter pw = new PrintWriter(out)) + { + pw.println(""); + pw.println(""); + pw.println(""); + pw.println("File tree comparison results"); + pw.println(""); + pw.println(""); + pw.println(""); + pw.println("

Files examined: "+resultSet.stats.resultCount+"

"); + pw.println("

Files with differences: "+resultSet.stats.differenceCount+"

"); + pw.println("

Ignored files: "+resultSet.stats.ignoredFileCount+"

"); + String passOrFail; + if (resultSet.stats.differenceCount > 0) + { + passOrFail = "FAILED"; + } + else + { + passOrFail = "PASSED"; + } + pw.println("

Status: "+passOrFail+"

"); + + outputResultsTable(resultSet.results, pw, 0); + + pw.println(""); + pw.println(""); + } + } + + private void outputResultsTable(List results, PrintWriter pw, int row) + { + pw.println(""); + pw.println(""); + pw.println(""); + pw.println(""); + pw.println(""); + pw.println(""); + pw.println(""); + pw.println(""); + pw.println(""); + + for (Result r : results) + { + ++row; + + outputResult(pw, row, r); + + if (!r.subResults.isEmpty()) + { + // Only show the subresults if there are + if (!differencesOnly || !r.equal) + { + pw.println(""); + } + } + } + + pw.println(""); + pw.println("
#Updated installFresh install
 "); + outputResultsTable(r.subResults, pw, row); + pw.println("
"); + } + + private void outputResult(PrintWriter pw, int row, Result r) + { + if (differencesOnly && r.equal) + { + return; + } + pw.println(""); + + pw.println(""+row+""); + + String p1 = (r.p1 == null) ? "" : r.p1.toString(); + String p1Abbr = abbreviate(p1, maxPathDisplayLength); + String p2 = (r.p2 == null) ? "" : r.p2.toString(); + String p2Abbr = abbreviate(p2, maxPathDisplayLength); + + // TODO: URL/HTML-encode as appropriate + String diffClass; + if (r.equal) + { + if (r.subResults.isEmpty()) + { + // Result refers to a normal file or directory. + diffClass = "info"; + } + else + { + // File is a special archive, but no differences in the sub-results are considered important. + diffClass = "warning"; + } + } + else + { + // The file/directory appears different in each tree. If it is a special archive, then there + // are differences that we care about. + diffClass = "danger"; + } + + pw.println( + String.format("%s%s", + diffClass, + p1, + p1Abbr, + diffClass, + p2, + p2Abbr)); + + pw.println(""); + } + + private String abbreviate(String str, int maxLength) + { + return (str.length() > maxLength) ? "..."+str.substring(str.length()-maxLength) : str; + } + + public void setMaxPathDisplayLength(int maxPathDisplayLength) + { + this.maxPathDisplayLength = maxPathDisplayLength; + } + + public void setDifferencesOnly(boolean differencesOnly) + { + this.differencesOnly = differencesOnly; + } +} diff --git a/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/Result.java b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/Result.java new file mode 100644 index 0000000000..355cebb239 --- /dev/null +++ b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/Result.java @@ -0,0 +1,95 @@ +/* + * Copyright 2016 Alfresco Software, Ltd. All rights reserved. + * + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +package org.alfresco.update.tool.dircomp; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +/** + * Simple struct-style result data class. + * + * @author Matt Ward + */ +public final class Result +{ + /** + * The path within tree1 being compared (intended to be the updated Alfresco installation). + *

+ * This field will be null if the file in question appears only in the tree2. + */ + Path p1; + /** + * The path within tree2 being compared (intended to be the freshly installed equivalent of {@link #p1}). + *

+ * This field will be null if the file in question appears only in the tree1. + */ + Path p2; + /** + * Are the paths in {@link #p1} and {@link #p2} of identical content? If they refer to a directory, then + * equal in this sense is to have the same directory name. If they refer to a plain file, then equal means + * that they contain the exact same contents. + */ + boolean equal; + /** + * The root path of sub-tree1 to which {@link #subResults} refers. + * @see #subResults + */ + Path subTree1; + /** + * The root path of sub-tree2 to which {@link #subResults} refers. + * @see #subResults + */ + Path subTree2; + /** + * If p1 and p2 refer to a special archive with differences, e.g. they refer to alfresco.war, + * then a deep comparison of the archives will be performed and the results stored here. + *

+ * The paths to the expanded archives will be stored in {@link #subTree1} and {@link #subTree2} + * and all the paths in {@link #subResults} will be within those new roots. + */ + List subResults = new ArrayList<>(); + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + (this.equal ? 1231 : 1237); + result = prime * result + ((this.p1 == null) ? 0 : this.p1.hashCode()); + result = prime * result + ((this.p2 == null) ? 0 : this.p2.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + Result other = (Result) obj; + if (this.equal != other.equal) return false; + if (this.p1 == null) + { + if (other.p1 != null) return false; + } + else if (!this.p1.equals(other.p1)) return false; + if (this.p2 == null) + { + if (other.p2 != null) return false; + } + else if (!this.p2.equals(other.p2)) return false; + return true; + } + + @Override + public String toString() + { + return String.format("Result[p1=%s, p2=%s, equal=%b]", p1, p2, equal); + } +} diff --git a/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/ResultFormatter.java b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/ResultFormatter.java new file mode 100644 index 0000000000..6eddc194a1 --- /dev/null +++ b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/ResultFormatter.java @@ -0,0 +1,28 @@ +/* + * Copyright 2016 Alfresco Software, Ltd. All rights reserved. + * + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +package org.alfresco.update.tool.dircomp; + +import java.io.OutputStream; +import java.util.Collection; + +/** + * Format a set of {@link Result} objects. + * + * @author Matt Ward + */ +public interface ResultFormatter +{ + /** + * Format the result set to the supplied {@link OutputStream}. The caller + * must take care of creating and destroying the OutputStream correctly. + * + * @param results The results to format. + * @param out The stream to format the results to. + */ + void format(ResultSet results, OutputStream out); +} diff --git a/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/ResultSet.java b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/ResultSet.java new file mode 100644 index 0000000000..fecd88a1ff --- /dev/null +++ b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/ResultSet.java @@ -0,0 +1,40 @@ +package org.alfresco.update.tool.dircomp; + +import java.util.ArrayList; +import java.util.List; + +/* + * Copyright 2015-2016 Alfresco Software, Ltd. All rights reserved. + * + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +public class ResultSet +{ + final List results = new ArrayList<>(); + final Stats stats = new Stats(); + + /** + * Class for aggregating basic statistics relating to the directory tree comparisons. + *

+ * For all counts, unless specified otherwise, if a file appears in both trees, it is + * counted only once, as it is relative files we are tracking regardless of which + * tree(s) they exist in. + */ + public static class Stats + { + /** + * The number of files (including directories) examined. + */ + int resultCount; + /** + * The number of files discovered to have differences. + */ + int differenceCount; + /** + * The number of files that were completely ignored due to being in the ignore list. + */ + int ignoredFileCount; + } +} diff --git a/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/SortedPathSet.java b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/SortedPathSet.java new file mode 100644 index 0000000000..52c7087cb6 --- /dev/null +++ b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/SortedPathSet.java @@ -0,0 +1,28 @@ +/* + * Copyright 2016 Alfresco Software, Ltd. All rights reserved. + * + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +package org.alfresco.update.tool.dircomp; + +import java.nio.file.Path; +import java.util.TreeSet; + +/** + * Sorted set of {@link Path} objects that provides consistent + * cross-platform sort order. + * + * @see java.util.TreeSet + * @author Matt Ward + */ +public class SortedPathSet extends TreeSet +{ + private static final long serialVersionUID = 1L; + + public SortedPathSet() + { + super(new CaseSensitivePathComparator()); + } +} diff --git a/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/exception/FileTreeCompareException.java b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/exception/FileTreeCompareException.java new file mode 100644 index 0000000000..ebf1e4545f --- /dev/null +++ b/enterprise-update-test/src/main/java/org/alfresco/update/tool/dircomp/exception/FileTreeCompareException.java @@ -0,0 +1,31 @@ +/* + * Copyright 2016 Alfresco Software, Ltd. All rights reserved. + * + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +package org.alfresco.update.tool.dircomp.exception; + +import org.alfresco.update.tool.dircomp.FileTreeCompare; + +/** + * Exception class representing failures during file tree comparison. + * + * @see FileTreeCompare + * @author Matt Ward + */ +public class FileTreeCompareException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + public FileTreeCompareException(String message) + { + super(message); + } + + public FileTreeCompareException(String message, Throwable cause) + { + super(message, cause); + } +} diff --git a/enterprise-update-test/src/test/java/org/alfresco/update/tool/dircomp/FileTreeCompareImplTest.java b/enterprise-update-test/src/test/java/org/alfresco/update/tool/dircomp/FileTreeCompareImplTest.java new file mode 100644 index 0000000000..5abde16cf1 --- /dev/null +++ b/enterprise-update-test/src/test/java/org/alfresco/update/tool/dircomp/FileTreeCompareImplTest.java @@ -0,0 +1,298 @@ +/* + * Copyright 2016 Alfresco Software, Ltd. All rights reserved. + * + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +package org.alfresco.update.tool.dircomp; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.util.AntPathMatcher; + +/** + * Tests for the {@link FileTreeCompareImpl} class. + * + * @author Matt Ward + */ +public class FileTreeCompareImplTest +{ + FileTreeCompareImpl comparator; + + @Before + public void setUp() throws Exception + { + comparator = new FileTreeCompareImpl(); + } + + @Test + public void canGetSortedPathSet() throws IOException + { + Path tree = pathFromClasspath("dir_compare/simple_file_folders/tree1"); + SortedPathSet paths = comparator.sortedPaths(tree); + Iterator it = paths.iterator(); + + System.out.println("Paths:"); + for (Path p : paths) + { + System.out.println("\t"+p); + } + + assertEquals(11, paths.size()); + + assertEquals("a", unixPathStr(tree, it.next())); + assertEquals("b", unixPathStr(tree, it.next())); + assertEquals("b/blah.txt", unixPathStr(tree, it.next())); + assertEquals("c", unixPathStr(tree, it.next())); + assertEquals("c/c1", unixPathStr(tree, it.next())); + assertEquals("c/c1/commands.bat", unixPathStr(tree, it.next())); + assertEquals("c/c1/commands.sh", unixPathStr(tree, it.next())); + assertEquals("c/c2", unixPathStr(tree, it.next())); + assertEquals("c/c2/Aardvark.java", unixPathStr(tree, it.next())); + assertEquals("c/c2/Banana.java", unixPathStr(tree, it.next())); + assertEquals("d", unixPathStr(tree, it.next())); + } + + private String unixPathStr(Path root, Path path) + { + // Allow test to run on Windows also + String pathStr = path.toString(); + pathStr = pathStr.replace(File.separatorChar, '/'); + return pathStr; + } + + @Test + public void canDiffSimpleTreesOfFilesAndFolders() + { + Path tree1 = pathFromClasspath("dir_compare/simple_file_folders/tree1"); + Path tree2 = pathFromClasspath("dir_compare/simple_file_folders/tree2"); + + ResultSet resultSet = comparator.compare(tree1, tree2); + + System.out.println("Comparison results:"); + for (Result r : resultSet.results) + { + System.out.println("\t"+r); + } + + // One result for each relative file/folder + assertEquals(13, resultSet.results.size()); + assertEquals(13, resultSet.stats.resultCount); + + Iterator rit = resultSet.results.iterator(); + // TODO: currently all of the files are in one, other or both but where they + // are in both, the file *contents* are identical. + // TODO: evolve test data and functionality to cope with different file contents. + assertResultEquals(tree1.resolve("a"), tree2.resolve("a"), true, rit.next()); + assertResultEquals(null, tree2.resolve("a/story.txt"), false, rit.next()); + assertResultEquals(tree1.resolve("b"), tree2.resolve("b"), true, rit.next()); + assertResultEquals(tree1.resolve("b/blah.txt"), tree2.resolve("b/blah.txt"), true, rit.next()); + assertResultEquals(tree1.resolve("c"), tree2.resolve("c"), true, rit.next()); + assertResultEquals(tree1.resolve("c/c1"), tree2.resolve("c/c1"), true, rit.next()); + assertResultEquals(tree1.resolve("c/c1/commands.bat"), tree2.resolve("c/c1/commands.bat"), true, rit.next()); + assertResultEquals(tree1.resolve("c/c1/commands.sh"), tree2.resolve("c/c1/commands.sh"), true, rit.next()); + assertResultEquals(tree1.resolve("c/c2"), tree2.resolve("c/c2"), true, rit.next()); + // Aardvark.java appears in both trees but is not the same! + assertResultEquals(tree1.resolve("c/c2/Aardvark.java"), tree2.resolve("c/c2/Aardvark.java"), false, rit.next()); + assertResultEquals(tree1.resolve("c/c2/Banana.java"), null, false, rit.next()); + assertResultEquals(tree1.resolve("d"), null, false, rit.next()); + assertResultEquals(null, tree2.resolve("e"), false, rit.next()); + } + + /** + * A "learning test" allowing me to check my assumptions and document the expected behaviour. + */ + @Test + public void testAntPathMatcher() + { + AntPathMatcher matcher = new AntPathMatcher(); + assertTrue(matcher.match("**/common/lib/**/*.pc", "prefix/common/lib/pkgconfig/ImageMagick++-6.Q16.pc")); + assertFalse(matcher.match("**/common/lib/**/*.pc", "/absolute/prefix/common/lib/pkgconfig/ImageMagick++-6.Q16.pc")); + assertTrue(matcher.match("/**/common/lib/**/*.pc", "/absolute/prefix/common/lib/pkgconfig/ImageMagick++-6.Q16.pc")); + assertTrue(matcher.match("common/lib/**/*.pc", "common/lib/pkgconfig/Wand.pc")); + assertTrue(matcher.match("**/*.pc", "common/lib/pkgconfig/Wand.pc")); + assertFalse(matcher.match("*.pc", "common/lib/pkgconfig/Wand.pc")); + + assertTrue(matcher.match("libreoffice.app/Contents/Resources/bootstraprc", "libreoffice.app/Contents/Resources/bootstraprc")); + assertTrue(matcher.match("*.sh", "alfresco.sh")); + assertFalse(matcher.match("*.sh", "a/different/alfresco.sh")); + + // What about path separators? + assertTrue(matcher.match("**\\common\\lib\\**\\*.pc", "prefix\\common\\lib\\pkgconfig\\ImageMagick++-6.Q16.pc")); + assertTrue(matcher.match("\\**\\common\\lib\\**\\*.pc", "\\absolute\\prefix\\common\\lib\\pkgconfig\\ImageMagick++-6.Q16.pc")); + + // Path separator must be set before this will work + assertFalse(matcher.match("**/common/lib/**/*.pc", "prefix\\common\\lib\\pkgconfig\\ImageMagick++-6.Q16.pc")); + matcher.setPathSeparator("\\"); + assertTrue(matcher.match("**/common/lib/**/*.pc", "prefix\\common\\lib\\pkgconfig\\ImageMagick++-6.Q16.pc")); + } + + @Test + public void canIgnoreSpecifiedPaths() + { + Path tree1 = pathFromClasspath("dir_compare/simple_file_folders/tree1"); + Path tree2 = pathFromClasspath("dir_compare/simple_file_folders/tree2"); + + Set ignorePaths = new HashSet<>(); + ignorePaths.add("b/blah.txt"); + ignorePaths.add("c/c2/**"); + ignorePaths.add("d/**"); + ignorePaths.add("e/**"); + comparator = new FileTreeCompareImpl(ignorePaths); + + // Perform the comparison + ResultSet resultSet = comparator.compare(tree1, tree2); + + System.out.println("Comparison results:"); + for (Result r : resultSet.results) + { + System.out.println("\t"+r); + } + + Iterator rit = resultSet.results.iterator(); + assertResultEquals(tree1.resolve("a"), tree2.resolve("a"), true, rit.next()); + assertResultEquals(null, tree2.resolve("a/story.txt"), false, rit.next()); + assertResultEquals(tree1.resolve("b"), tree2.resolve("b"), true, rit.next()); + // No b/blah.txt here. + assertResultEquals(tree1.resolve("c"), tree2.resolve("c"), true, rit.next()); + assertResultEquals(tree1.resolve("c/c1"), tree2.resolve("c/c1"), true, rit.next()); + assertResultEquals(tree1.resolve("c/c1/commands.bat"), tree2.resolve("c/c1/commands.bat"), true, rit.next()); + assertResultEquals(tree1.resolve("c/c1/commands.sh"), tree2.resolve("c/c1/commands.sh"), true, rit.next()); + // No c/c2, c/c2/Aardvark.java, c/c2/Banana.java, d or e here. + + List results = resultSet.results; + assertResultNotPresent(tree1.resolve("b/blah.txt"), tree2.resolve("b/blah.txt"), true, results); + assertResultNotPresent(tree1.resolve("c/c2"), tree2.resolve("c/c2"), true, results); + assertResultNotPresent(tree1.resolve("c/c2/Aardvark.java"), tree2.resolve("c/c2/Aardvark.java"), false, results); + assertResultNotPresent(tree1.resolve("c/c2/Banana.java"), null, false, results); + assertResultNotPresent(tree1.resolve("d"), null, false, results); + assertResultNotPresent(null, tree2.resolve("e"), false, results); + assertEquals(7, results.size()); + + // TODO: What about paths within war/jar/zip files? + } + + @Test + public void canDiffTreesContainingWarFiles() + { + Path tree1 = pathFromClasspath("dir_compare/file_folders_plus_war/tree1"); + Path tree2 = pathFromClasspath("dir_compare/file_folders_plus_war/tree2"); + + ResultSet resultSet = comparator.compare(tree1, tree2); + + System.out.println("Comparison results:"); + for (Result r : resultSet.results) + { + System.out.println("\t"+r); + } + + // The 14 top-level results + 17 sub-results. + assertEquals(31, resultSet.stats.resultCount); + + // One result for each relative file/folder + assertEquals(14, resultSet.results.size()); + + + Iterator rit = resultSet.results.iterator(); + // TODO: currently all of the files are in one, other or both but where they + // are in both, the file *contents* are identical. + // TODO: evolve test data and functionality to cope with different file contents. + assertResultEquals(tree1.resolve("a"), tree2.resolve("a"), true, rit.next()); + assertResultEquals(null, tree2.resolve("a/story.txt"), false, rit.next()); + assertResultEquals(tree1.resolve("b"), tree2.resolve("b"), true, rit.next()); + + // Examine the results of the war file comparison + Result result = rit.next(); + // The WAR files are different. + assertResultEquals( + tree1.resolve("b/alfresco-testdata-webapp.war"), + tree2.resolve("b/alfresco-testdata-webapp.war"), + false, + result); + List subResults = result.subResults; + System.out.println("subResults:"); + for (Result r : subResults) + { + System.out.println("\t"+r); + } + Iterator subIt = subResults.iterator(); + Path subTree1 = result.subTree1; + Path subTree2 = result.subTree2; + assertEquals(17, subResults.size()); + assertResultEquals(subTree1.resolve("META-INF"), subTree2.resolve("META-INF"), true, subIt.next()); + assertResultEquals(subTree1.resolve("META-INF/MANIFEST.MF"), subTree2.resolve("META-INF/MANIFEST.MF"), false, subIt.next()); + assertResultEquals(subTree1.resolve("META-INF/maven"), subTree2.resolve("META-INF/maven"), true, subIt.next()); + assertResultEquals(subTree1.resolve("META-INF/maven/org.alfresco.dummy"), subTree2.resolve("META-INF/maven/org.alfresco.dummy"), true, subIt.next()); + assertResultEquals(subTree1.resolve("META-INF/maven/org.alfresco.dummy/alfresco-testdata-webapp"), subTree2.resolve("META-INF/maven/org.alfresco.dummy/alfresco-testdata-webapp"), true, subIt.next()); + assertResultEquals(subTree1.resolve("META-INF/maven/org.alfresco.dummy/alfresco-testdata-webapp/pom.properties"), subTree2.resolve("META-INF/maven/org.alfresco.dummy/alfresco-testdata-webapp/pom.properties"), false, subIt.next()); + assertResultEquals(subTree1.resolve("META-INF/maven/org.alfresco.dummy/alfresco-testdata-webapp/pom.xml"), subTree2.resolve("META-INF/maven/org.alfresco.dummy/alfresco-testdata-webapp/pom.xml"), true, subIt.next()); + assertResultEquals(subTree1.resolve("WEB-INF"), subTree2.resolve("WEB-INF"), true, subIt.next()); + assertResultEquals(subTree1.resolve("WEB-INF/classes"), subTree2.resolve("WEB-INF/classes"), true, subIt.next()); + assertResultEquals(subTree1.resolve("WEB-INF/classes/org"), subTree2.resolve("WEB-INF/classes/org"), true, subIt.next()); + assertResultEquals(subTree1.resolve("WEB-INF/classes/org/alfresco"), subTree2.resolve("WEB-INF/classes/org/alfresco"), true, subIt.next()); + assertResultEquals(subTree1.resolve("WEB-INF/classes/org/alfresco/testdata"), subTree2.resolve("WEB-INF/classes/org/alfresco/testdata"), true, subIt.next()); + assertResultEquals(subTree1.resolve("WEB-INF/classes/org/alfresco/testdata/webapp"), subTree2.resolve("WEB-INF/classes/org/alfresco/testdata/webapp"), true, subIt.next()); + assertResultEquals(null, subTree2.resolve("WEB-INF/classes/org/alfresco/testdata/webapp/Another.class"), false, subIt.next()); + assertResultEquals(subTree1.resolve("WEB-INF/classes/org/alfresco/testdata/webapp/ExampleJavaClass.class"), subTree2.resolve("WEB-INF/classes/org/alfresco/testdata/webapp/ExampleJavaClass.class"), true, subIt.next()); + assertResultEquals(subTree1.resolve("WEB-INF/web.xml"), subTree2.resolve("WEB-INF/web.xml"), true, subIt.next()); + assertResultEquals(subTree1.resolve("index.jsp"), subTree2.resolve("index.jsp"), false, subIt.next()); + + // Back up to the top-level comparisons + assertResultEquals(tree1.resolve("b/blah.txt"), tree2.resolve("b/blah.txt"), true, rit.next()); + assertResultEquals(tree1.resolve("c"), tree2.resolve("c"), true, rit.next()); + assertResultEquals(tree1.resolve("c/c1"), tree2.resolve("c/c1"), true, rit.next()); + assertResultEquals(tree1.resolve("c/c1/commands.bat"), tree2.resolve("c/c1/commands.bat"), true, rit.next()); + assertResultEquals(tree1.resolve("c/c1/commands.sh"), tree2.resolve("c/c1/commands.sh"), true, rit.next()); + assertResultEquals(tree1.resolve("c/c2"), tree2.resolve("c/c2"), true, rit.next()); + // Aardvark.java appears in both trees but is not the same! + assertResultEquals(tree1.resolve("c/c2/Aardvark.java"), tree2.resolve("c/c2/Aardvark.java"), false, rit.next()); + assertResultEquals(tree1.resolve("c/c2/Banana.java"), null, false, rit.next()); + assertResultEquals(tree1.resolve("d"), null, false, rit.next()); + assertResultEquals(null, tree2.resolve("e"), false, rit.next()); + } + + private void assertResultNotPresent(Path p1, Path p2, boolean contentEqual, List results) + { + Result r = new Result(); + r.p1 = p1; + r.p2 = p2; + r.equal = contentEqual; + assertFalse("Result should not be present: "+r, results.contains(r)); + } + + private void assertResultEquals(Path p1, Path p2, boolean contentEqual, Result result) + { + Result expected = new Result(); + expected.p1 = p1; + expected.p2 = p2; + expected.equal = contentEqual; + assertEquals(expected, result); + } + + private Path pathFromClasspath(String path) + { + try + { + return Paths.get(getClass().getClassLoader().getResource(path).toURI()); + } + catch (URISyntaxException error) + { + throw new RuntimeException(""); + } + } +} diff --git a/enterprise-update-test/src/test/java/org/alfresco/update/tool/dircomp/HtmlResultFormatterTest.java b/enterprise-update-test/src/test/java/org/alfresco/update/tool/dircomp/HtmlResultFormatterTest.java new file mode 100644 index 0000000000..09d7919ba4 --- /dev/null +++ b/enterprise-update-test/src/test/java/org/alfresco/update/tool/dircomp/HtmlResultFormatterTest.java @@ -0,0 +1,118 @@ +/* + * Copyright 2016 Alfresco Software, Ltd. All rights reserved. + * + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +package org.alfresco.update.tool.dircomp; + +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.commons.io.FileUtils; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.springframework.util.AntPathMatcher; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Tests for the {@link HtmlResultFormatter} class. + *

+ * TODO: currently these aren't tests so much as useful utilities to help with manual testing. + * + * @author Matt Ward + */ +public class HtmlResultFormatterTest +{ + @Before + public void setUp() throws Exception + { + } + + @Test + public void canFormatToHTML() throws IOException + { + ResultSet resultSet = new ResultSet(); + List results = resultSet.results; + addResult(results, "/t1/a", "/t2/a", true); + addResult(results, "/t1/a/b", "/t2/a/b", true); + addResult(results, "/t1/a/c", "/t2/a/c", true); + addResult(results, "/t1/a/b/c/something.txt", "/t2/a/b/c/something.txt", true); + addResult(results, "/t1/a/b/c/another.txt", "/t2/a/b/c/another.txt", false); + addResult(results, null, "/t2/a/b/c/blah.txt", false); + addResult(results, "/t1/dir-only-in-p1", null, false); + addResult(results, null, "/t2/dir-only-in-p2", false); + + try(ByteArrayOutputStream os = new ByteArrayOutputStream()) + { + HtmlResultFormatter formatter = new HtmlResultFormatter(); + formatter.format(resultSet, os); + System.out.println(os.toString()); + + // Uncomment to write to file +// Path file = Files.createTempFile(getClass().getSimpleName(), ".html"); +// FileUtils.write(file.toFile(), os.toString()); +// System.out.println("File: "+file); + } + } + + @Ignore + @Test + public void bigDiff() throws IOException + { + Path path1 = Paths.get("/Users/MWard/dev2/alf-installs/alf-5.1-b667"); + Path path2 = Paths.get("/Users/MWard/dev2/alf-installs/alf-5.1-b669"); + + Set ignores = new HashSet<>(); + ignores.add("alf_data/postgresql/**"); + ignores.add("META-INF/MANIFEST.MF"); + ignores.add("META-INF/maven/**"); + ignores.add("README.txt"); + + // Temporary ignores, until we sort out custom diffing or pre-processing before diffs. + ignores.add("**/*.sh"); + ignores.add("**/*.bat"); + ignores.add("uninstall.app/**"); + ignores.add("common/bin/**"); + ignores.add("common/include/**"); + ignores.add("common/lib/**/*.pc"); + ignores.add("common/lib/**/*.la"); + ignores.add("libreoffice.app/Contents/Resources/bootstraprc"); + ignores.add("postgresql/bin/**"); + + FileTreeCompare comparator = new FileTreeCompareImpl(ignores); + ResultSet resultSet = comparator.compare(path1, path2); + + Path file = Files.createTempFile(getClass().getSimpleName(), ".html"); + HtmlResultFormatter formatter = new HtmlResultFormatter(); + formatter.setDifferencesOnly(true); + try(FileOutputStream fos = new FileOutputStream(file.toFile()); + BufferedOutputStream bos = new BufferedOutputStream(fos)) + { + formatter.format(resultSet, bos); + } + System.out.println("File: "+file); + } + + private void addResult(List results, String p1, String p2, boolean contentMatch) + { + Result r = new Result(); + r.p1 = p1 != null ? Paths.get(p1) : null; + r.p2 = p2 != null ? Paths.get(p2) : null; + r.equal = contentMatch; + results.add(r); + } +} diff --git a/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/b/alfresco-testdata-webapp.war b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/b/alfresco-testdata-webapp.war new file mode 100644 index 0000000000..8f1c6ac5f2 Binary files /dev/null and b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/b/alfresco-testdata-webapp.war differ diff --git a/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/b/blah.txt b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/b/blah.txt new file mode 100644 index 0000000000..e508b95435 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/b/blah.txt @@ -0,0 +1,2 @@ +Sample content +More sample content diff --git a/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/c/c1/commands.bat b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/c/c1/commands.bat new file mode 100644 index 0000000000..fb7b3bb193 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/c/c1/commands.bat @@ -0,0 +1,2 @@ +echo Hello +echo World diff --git a/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/c/c1/commands.sh b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/c/c1/commands.sh new file mode 100644 index 0000000000..35d5edb327 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/c/c1/commands.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +echo hello +echo world diff --git a/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/c/c2/Aardvark.java b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/c/c2/Aardvark.java new file mode 100644 index 0000000000..5733268500 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/c/c2/Aardvark.java @@ -0,0 +1,7 @@ +public class Aardvark +{ + public static void main(String[] args) + { + System.out.println("Aardvark!"); + } +} diff --git a/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/c/c2/Banana.java b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/c/c2/Banana.java new file mode 100644 index 0000000000..a9d5570d63 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree1/c/c2/Banana.java @@ -0,0 +1,7 @@ +public class Aardvark +{ + public static void main(String[] args) + { + System.out.println("Banana!"); + } +} diff --git a/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/a/story.txt b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/a/story.txt new file mode 100644 index 0000000000..69c3b8a81a --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/a/story.txt @@ -0,0 +1,5 @@ +Once upon +A time +Lived +A +Troll diff --git a/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/b/alfresco-testdata-webapp.war b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/b/alfresco-testdata-webapp.war new file mode 100644 index 0000000000..af3bdb7237 Binary files /dev/null and b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/b/alfresco-testdata-webapp.war differ diff --git a/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/b/blah.txt b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/b/blah.txt new file mode 100644 index 0000000000..e508b95435 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/b/blah.txt @@ -0,0 +1,2 @@ +Sample content +More sample content diff --git a/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/c/c1/commands.bat b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/c/c1/commands.bat new file mode 100644 index 0000000000..fb7b3bb193 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/c/c1/commands.bat @@ -0,0 +1,2 @@ +echo Hello +echo World diff --git a/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/c/c1/commands.sh b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/c/c1/commands.sh new file mode 100644 index 0000000000..35d5edb327 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/c/c1/commands.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +echo hello +echo world diff --git a/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/c/c2/Aardvark.java b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/c/c2/Aardvark.java new file mode 100644 index 0000000000..bf3d78b9f5 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/file_folders_plus_war/tree2/c/c2/Aardvark.java @@ -0,0 +1,7 @@ +public class Aardvark +{ + public static void main(String[] args) + { + System.out.println("Hello Aardvark!"); + } +} diff --git a/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree1/b/blah.txt b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree1/b/blah.txt new file mode 100644 index 0000000000..e508b95435 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree1/b/blah.txt @@ -0,0 +1,2 @@ +Sample content +More sample content diff --git a/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree1/c/c1/commands.bat b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree1/c/c1/commands.bat new file mode 100644 index 0000000000..fb7b3bb193 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree1/c/c1/commands.bat @@ -0,0 +1,2 @@ +echo Hello +echo World diff --git a/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree1/c/c1/commands.sh b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree1/c/c1/commands.sh new file mode 100644 index 0000000000..35d5edb327 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree1/c/c1/commands.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +echo hello +echo world diff --git a/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree1/c/c2/Aardvark.java b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree1/c/c2/Aardvark.java new file mode 100644 index 0000000000..5733268500 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree1/c/c2/Aardvark.java @@ -0,0 +1,7 @@ +public class Aardvark +{ + public static void main(String[] args) + { + System.out.println("Aardvark!"); + } +} diff --git a/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree1/c/c2/Banana.java b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree1/c/c2/Banana.java new file mode 100644 index 0000000000..a9d5570d63 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree1/c/c2/Banana.java @@ -0,0 +1,7 @@ +public class Aardvark +{ + public static void main(String[] args) + { + System.out.println("Banana!"); + } +} diff --git a/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree2/a/story.txt b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree2/a/story.txt new file mode 100644 index 0000000000..69c3b8a81a --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree2/a/story.txt @@ -0,0 +1,5 @@ +Once upon +A time +Lived +A +Troll diff --git a/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree2/b/blah.txt b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree2/b/blah.txt new file mode 100644 index 0000000000..e508b95435 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree2/b/blah.txt @@ -0,0 +1,2 @@ +Sample content +More sample content diff --git a/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree2/c/c1/commands.bat b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree2/c/c1/commands.bat new file mode 100644 index 0000000000..fb7b3bb193 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree2/c/c1/commands.bat @@ -0,0 +1,2 @@ +echo Hello +echo World diff --git a/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree2/c/c1/commands.sh b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree2/c/c1/commands.sh new file mode 100644 index 0000000000..35d5edb327 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree2/c/c1/commands.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +echo hello +echo world diff --git a/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree2/c/c2/Aardvark.java b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree2/c/c2/Aardvark.java new file mode 100644 index 0000000000..bf3d78b9f5 --- /dev/null +++ b/enterprise-update-test/src/test/resources/dir_compare/simple_file_folders/tree2/c/c2/Aardvark.java @@ -0,0 +1,7 @@ +public class Aardvark +{ + public static void main(String[] args) + { + System.out.println("Hello Aardvark!"); + } +}