package com.github.tornaia.lsr;

import org.junit.Assert;

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;

/**
 * Assertion for recursively testing directories.
 */
public class AssertFile {

    private AssertFile() {
    }

    /**
     * Asserts that two directories are recursively equal. If they are not, an {@link AssertionError} is thrown with the
     * given message.<br/>
     * There will be a binary comparison of all files under expected with all files under actual. File attributes will
     * not be considered.<br/>
     * Missing or additional files are considered an error.<br/>
     *
     * @param expected Path expected directory
     * @param actual   Path actual directory
     */
    public static final void assertPathEqualsRecursively(final Path expected, final Path actual) {
        Assert.assertNotNull(expected);
        Assert.assertNotNull(actual);
        final Path absoluteExpected = expected.toAbsolutePath();
        final Path absoluteActual = actual.toAbsolutePath();
        try {
            Files.walkFileTree(expected, new FileVisitor<Path>() {

                @Override
                public FileVisitResult preVisitDirectory(Path expectedDir, BasicFileAttributes attrs)
                        throws IOException {
                    Path relativeExpectedDir = absoluteExpected.relativize(expectedDir.toAbsolutePath());
                    Path actualDir = absoluteActual.resolve(relativeExpectedDir);

                    if (!Files.exists(actualDir)) {
                        Assert.fail(String.format("Directory \'%s\' missing in target.", expectedDir.getFileName()));
                    }

                    Assert.assertEquals(String.format("Directory size of \'%s\' differ. ", relativeExpectedDir),
                            expectedDir.toFile().list().length, actualDir.toFile().list().length);

                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult visitFile(Path expectedFile, BasicFileAttributes attrs) throws IOException {
                    Path relativeExpectedFile = absoluteExpected.relativize(expectedFile.toAbsolutePath());
                    Path actualFile = absoluteActual.resolve(relativeExpectedFile);

                    if (!Files.exists(actualFile)) {
                        Assert.fail(String.format("File \'%s\' missing in target.", expectedFile.getFileName()));
                    }
                    Assert.assertEquals(String.format("File size of \'%s\' differ. ", relativeExpectedFile),
                            Files.size(expectedFile), Files.size(actualFile));
                    Assert.assertArrayEquals(String.format("File content of \'%s\' differ. ", relativeExpectedFile),
                            Files.readAllBytes(expectedFile), Files.readAllBytes(actualFile));

                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                    Assert.fail(exc.getMessage());
                    return FileVisitResult.TERMINATE;
                }

                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    return FileVisitResult.CONTINUE;
                }

            });
        } catch (IOException e) {
            Assert.fail(e.getMessage());
        }
    }
}
@@ -30,34 +30,8 @@
 r;%0A%0A
-import org.junit.Assert;%0A%0A
 impo
@@ -234,16 +234,51 @@
 butes;%0A%0A
+import static org.junit.Assert.*;%0A%0A
 /**%0A * A
@@ -884,22 +884,16 @@
  static 
-final 
 void ass
@@ -959,39 +959,32 @@
 tual) %7B%0A        
-Assert.
 assertNotNull(ex
@@ -996,31 +996,24 @@
 d);%0A        
-Assert.
 assertNotNul
@@ -1661,39 +1661,32 @@
                 
-Assert.
 fail(String.form
@@ -1710,33 +1710,42 @@
 s%5C' missing 
-in
+from
  target
+ %5C'%25s%5C'
 .%22, expected
@@ -1753,32 +1753,57 @@
 ir.getFileName()
+, actualDir.getFileName()
 ));%0A            
@@ -1825,39 +1825,32 @@
                 
-Assert.
 assertEquals(Str
@@ -1877,32 +1877,43 @@
 y size of %5C'%25s%5C'
+ and %5C'%25s%5C'
  differ. %22, rela
@@ -1931,38 +1931,21 @@
 dDir
-),%0A                           
+, actualDir),
  exp
@@ -2493,31 +2493,24 @@
             
-Assert.
 fail(String.
@@ -2618,31 +2618,24 @@
             
-Assert.
 assertEquals
@@ -2674,69 +2674,138 @@
 s%5C' 
-differ. %22, relativeExpectedFile),%0A                           
+and %5C'%25s%5C' differ. %22, expectedFile.getFileName().toFile().getAbsolutePath(), actualFile.getFileName().toFile().getAbsolutePath()),
  Fil
@@ -2872,23 +2872,16 @@
         
-Assert.
 assertAr
@@ -2932,69 +2932,138 @@
 s%5C' 
-differ. %22, relativeExpectedFile),%0A                           
+and %5C'%25s%5C' differ. %22, expectedFile.getFileName().toFile().getAbsolutePath(), actualFile.getFileName().toFile().getAbsolutePath()),
  Fil
@@ -3345,31 +3345,24 @@
             
-Assert.
 fail(exc.get
@@ -3712,23 +3712,16 @@
         
-Assert.
 fail(e.g

Improve output on error