package org.smoothbuild.acceptance; import static java.util.stream.Collectors.joining; import static org.smoothbuild.util.Streams.inputStreamToString; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; public class FileArrayMatcher extends TypeSafeMatcher<File> { private final String[] params; public static Matcher<File> isFileArrayWith(String... params) { return new FileArrayMatcher(params); } private FileArrayMatcher(String... params) { if (params.length % 2 != 0) { throw new IllegalArgumentException("Even number of arguments expected, got " + params.length); } this.params = params; } public void describeTo(Description description) { description.appendText("is array dir with = " + Arrays.toString(params)); } protected boolean matchesSafely(File item) { try { return item.isDirectory() && containsExpectedElements(item) && filesCount(item) == params.length / 2; } catch (IOException e) { throw new RuntimeException(e); } } protected void describeMismatchSafely(File dir, Description mismatchDescription) { try { mismatchDescription.appendText("actual: [" + actualFiles(dir, dir.getPath().length() + 1) .stream().collect(joining(", ")) + "]"); } catch (IOException e) { throw new RuntimeException(e); } } private static List<String> actualFiles(File dir, int rootPathLength) throws IOException { ArrayList<String> result = new ArrayList<>(); for (File file : dir.listFiles()) { if (file.isDirectory()) { result.addAll(actualFiles(file, rootPathLength)); } else { result.add(file.getPath().substring(rootPathLength)); result.add(inputStreamToString(new FileInputStream(file))); } } return result; } private static int filesCount(File item) { int count = 0; for (File file : item.listFiles()) { if (file.isDirectory()) { count += filesCount(file); } else { count++; } } return count; } private boolean containsExpectedElements(File dir) throws IOException { int i = 0; while (i < params.length) { String path = params[i]; String content = params[i + 1]; i += 2; File file = new File(dir, path); if (!(file.exists() && file.isFile())) { return false; } if (!content.equals(inputStreamToString(new FileInputStream(file)))) { return false; } } return true; } }