Created util for input-output comparison tests.

This commit is contained in:
JesseBrault0709 2024-05-20 19:22:54 +02:00
parent c88656bd87
commit d099f9514d
5 changed files with 118 additions and 60 deletions

View File

@ -0,0 +1,22 @@
package groowt.view.component.web.util;
import java.io.File;
import java.nio.file.Path;
public final class ExtensionUtil {
public static String getNameWithoutExtension(String fileName) {
return fileName.substring(0, fileName.lastIndexOf("."));
}
public static String getNameWithoutExtension(File file) {
return getNameWithoutExtension(file.getName());
}
public static String getNameWithoutExtension(Path path) {
return getNameWithoutExtension(path.getFileName().toString());
}
private ExtensionUtil() {}
}

View File

@ -0,0 +1,19 @@
package groowt.view.component.web.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public final class FileUtil {
public static String readFile(File file) {
try (final var fis = new FileInputStream(file)) {
return new String(fis.readAllBytes());
} catch (IOException ioException) {
throw new RuntimeException(ioException);
}
}
private FileUtil() {}
}

View File

@ -3,16 +3,15 @@ package groowt.view.component.web.ast;
import groowt.view.component.web.antlr.ParserUtil; import groowt.view.component.web.antlr.ParserUtil;
import groowt.view.component.web.antlr.TokenList; import groowt.view.component.web.antlr.TokenList;
import java.io.File;
import java.nio.file.Path; import java.nio.file.Path;
public class DefaultAstBuilderTests extends AstBuilderTests { public class DefaultAstBuilderTests extends AstBuilderTests {
public DefaultAstBuilderTests() { public DefaultAstBuilderTests() {
super( super(
Path.of(String.join(File.separator, "src", "test", "ast")), Path.of("src", "test", "ast"),
"*.wvc", "*.wvc",
new File(String.join(File.separator, "src", "test", "ast", "trees")), Path.of("src", "test", "ast", "trees"),
"_ast.txt" "_ast.txt"
); );
} }

View File

@ -2,51 +2,25 @@ package groowt.view.component.web.ast;
import groowt.view.component.web.antlr.TokenList; import groowt.view.component.web.antlr.TokenList;
import groowt.view.component.web.ast.node.Node; import groowt.view.component.web.ast.node.Node;
import groowt.view.component.web.testutil.FileComparisonTestUtil;
import groowt.view.component.web.util.ExtensionUtil;
import groowt.view.component.web.util.FileUtil;
import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.Collection; import java.util.Collection;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.*;
public abstract class AstBuilderTests { public abstract class AstBuilderTests {
protected record BuildResult(Node node, TokenList tokenList) {} protected record BuildResult(Node node, TokenList tokenList) {}
private static final Pattern withoutExtension = Pattern.compile("(?<name>.*)\\..+");
protected static String getNameWithoutExtension(File file) {
final var m = withoutExtension.matcher(file.getName());
if (m.matches()) {
return m.group("name");
} else {
throw new IllegalArgumentException("Cannot get name without extension for " + file);
}
}
protected static String readFile(File file) {
try (final var fis = new FileInputStream(file)) {
return new String(fis.readAllBytes());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private final Path sourceFileDir; private final Path sourceFileDir;
private final String sourceFileGlob; private final String sourceFileGlob;
private final File astTreeDir; private final Path astTreeDir;
private final String astFileSuffixAndExt; private final String astFileSuffixAndExt;
public AstBuilderTests(Path sourceFileDir, String sourceFileGlob, File astTreeDir, String astFileSuffixAndExt) { public AstBuilderTests(Path sourceFileDir, String sourceFileGlob, Path astTreeDir, String astFileSuffixAndExt) {
this.sourceFileDir = sourceFileDir; this.sourceFileDir = sourceFileDir;
this.sourceFileGlob = sourceFileGlob; this.sourceFileGlob = sourceFileGlob;
this.astTreeDir = astTreeDir; this.astTreeDir = astTreeDir;
@ -57,35 +31,21 @@ public abstract class AstBuilderTests {
protected abstract String format(BuildResult buildResult); protected abstract String format(BuildResult buildResult);
protected void doSourceFileTest(String source, String expected) {
final BuildResult buildResult = this.buildFromSource(source);
final var actual = this.format(buildResult);
assertEquals(expected, actual);
}
@TestFactory @TestFactory
public Collection<DynamicTest> getSourceFileTests() { public Collection<DynamicTest> getSourceFileTests() {
final var fs = FileSystems.getDefault(); return FileComparisonTestUtil.getTestsFor(
final PathMatcher matcher = fs.getPathMatcher( this.sourceFileDir,
"glob:" + this.sourceFileDir.toString() + File.separator + this.sourceFileGlob this.sourceFileGlob,
this.astTreeDir,
sourcePath -> {
final String nameWithoutExtension = ExtensionUtil.getNameWithoutExtension(sourcePath);
return Path.of(nameWithoutExtension + this.astFileSuffixAndExt);
},
sourceFile -> {
final BuildResult buildResult = this.buildFromSource(FileUtil.readFile(sourceFile));
return this.format(buildResult);
}
); );
try (final Stream<Path> paths = Files.walk(this.sourceFileDir)) {
return paths.filter(matcher::matches)
.map(Path::toFile)
.filter(File::isFile)
.map(file -> {
final var name = getNameWithoutExtension(file);
final var expectedAstFile = new File(this.astTreeDir, name + this.astFileSuffixAndExt);
final var source = readFile(file);
final var expected = readFile(expectedAstFile);
return DynamicTest.dynamicTest(
name,
() -> this.doSourceFileTest(source, expected)
);
}).toList();
} catch (IOException e) {
throw new RuntimeException(e);
}
} }
} }

View File

@ -0,0 +1,58 @@
package groowt.view.component.web.testutil;
import groowt.view.component.web.util.ExtensionUtil;
import groowt.view.component.web.util.FileUtil;
import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.DynamicTest;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Function;
import static org.junit.jupiter.api.Assertions.*;
public final class FileComparisonTestUtil {
public static void doComparisonTest(File expected, String actualText) {
if (!expected.isFile()) {
throw new IllegalArgumentException("expected is not a file or does not exist: " + expected);
}
final String expectedText = FileUtil.readFile(expected);
assertEquals(expectedText, actualText);
}
public static Collection<DynamicTest> getTestsFor(
Path inputDirectory,
String inputFilesGlob,
Path outputDirectory,
Function<Path, @Nullable Path> inputFileToExpected,
Function<File, String> inputToActual
) {
final Collection<DynamicTest> result = new ArrayList<>();
final FileSystem fileSystem = FileSystems.getDefault();
final PathMatcher matcher = fileSystem.getPathMatcher("glob:" + inputDirectory.resolve(inputFilesGlob));
try (final var files = Files.walk(inputDirectory)) {
files.filter(Files::isRegularFile)
.filter(matcher::matches)
.forEach(inputPath -> {
final @Nullable Path expected = inputFileToExpected.apply(inputPath);
if (expected != null) {
final File expectedResolvedFile = outputDirectory.resolve(expected).toFile();
result.add(DynamicTest.dynamicTest(ExtensionUtil.getNameWithoutExtension(inputPath), () -> {
final String actual = inputToActual.apply(inputPath.toFile());
doComparisonTest(expectedResolvedFile, actual);
}));
}
});
} catch (IOException ioException) {
throw new RuntimeException(ioException);
}
return result;
}
private FileComparisonTestUtil() {}
}