From dc0927bceaa122ca9a73373a430cec9fc8001470 Mon Sep 17 00:00:00 2001 From: Antia Anderson Date: Tue, 25 Aug 2026 19:32:14 -0400 Subject: Start work diagnostics Signed-off-by: Antia Anderson --- test/moe/anita/mai/diag/ConsolePrinterTest.java | 110 ++++++++++++++++++++++++ test/moe/anita/mai/diag/JsonPrinterTest.java | 92 ++++++++++++++++++++ test/moe/anita/mai/test/TestRunner.java | 11 ++- 3 files changed, 207 insertions(+), 6 deletions(-) create mode 100644 test/moe/anita/mai/diag/ConsolePrinterTest.java create mode 100644 test/moe/anita/mai/diag/JsonPrinterTest.java (limited to 'test') diff --git a/test/moe/anita/mai/diag/ConsolePrinterTest.java b/test/moe/anita/mai/diag/ConsolePrinterTest.java new file mode 100644 index 0000000..30b4a19 --- /dev/null +++ b/test/moe/anita/mai/diag/ConsolePrinterTest.java @@ -0,0 +1,110 @@ +package moe.anita.mai.diag; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; + +import moe.anita.mai.buffer.MemBuf; +import moe.anita.mai.span.Pos; +import moe.anita.mai.span.Span; +import moe.anita.mai.test.Case; +import moe.anita.mai.test.Runner; + +@Runner(name = "Console Diagnostics") +public final class ConsolePrinterTest { + + @Case(name = "prints error diagnostic") + static void error() { + var source = new MemBuf("foo.mai", "mut x :=\n"); + var span = Span.of(Pos.of(7, 1, 8), Pos.of(9, 1, 10)); + + String output = print( + source, + new Diagnostic( + Diagnostic.Level.ERROR, + "expected expression", + span, + "expected expression here" + ) + ); + + String expected = """ + error: expected expression + --> foo.mai:1:8 + | + 1 | mut x := + | ^^ expected expression here + | + """; + + assert output.equals(expected) : "\nexpected:\n" + expected + "\nactual:\n" + output; + } + + @Case(name = "prints warning diagnostic") + static void warning() { + var source = new MemBuf("foo.mai", "mut value := 10\n"); + var span = Span.of(Pos.of(4, 1, 5), Pos.of(9, 1, 10)); + + String output = print( + source, + new Diagnostic( + Diagnostic.Level.WARNING, + "unused variable", + span, + "value is never used" + ) + ); + + String expected = """ + warning: unused variable + --> foo.mai:1:5 + | + 1 | mut value := 10 + | ^^^^^ value is never used + | + """; + + assert output.equals(expected) : "\nexpected:\n" + expected + "\nactual:\n" + output; + } + + @Case(name = "prints diagnostic without label") + static void noLabel() { + var source = new MemBuf("foo.mai", "foo\n"); + var span = Span.of(Pos.of(0, 1, 1), Pos.of(3, 1, 4)); + + String output = print( + source, + new Diagnostic( + Diagnostic.Level.ERROR, + "unknown name", + span, + null + ) + ); + + String expected = """ + error: unknown name + --> foo.mai:1:1 + | + 1 | foo + | ^^^ + | + """; + + assert output.equals(expected) : "\nexpected:\n" + expected + "\nactual:\n" + output; + } + + private static String print(MemBuf source, Diagnostic diagnostic) { + var bytes = new ByteArrayOutputStream(); + + try (var out = new PrintStream(bytes, true, StandardCharsets.UTF_8)) { + var printer = new ConsolePrinter(out, ColorMode.NEVER); + printer.print(source, diagnostic); + } + + return bytes.toString(StandardCharsets.UTF_8); + } + + private ConsolePrinterTest() { + } +} diff --git a/test/moe/anita/mai/diag/JsonPrinterTest.java b/test/moe/anita/mai/diag/JsonPrinterTest.java new file mode 100644 index 0000000..f097c47 --- /dev/null +++ b/test/moe/anita/mai/diag/JsonPrinterTest.java @@ -0,0 +1,92 @@ +package moe.anita.mai.diag; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; + +import moe.anita.mai.buffer.MemBuf; +import moe.anita.mai.span.Pos; +import moe.anita.mai.span.Span; + +import moe.anita.mai.test.Case; +import moe.anita.mai.test.Runner; + +@Runner(name = "JSON Diagnostics") +public final class JsonPrinterTest { + + @Case(name = "prints error diagnostic") + static void error() { + var source = new MemBuf("foo.mai", "mut x :=\n"); + var span = Span.of(Pos.of(7, 1, 8), Pos.of(9, 1, 10)); + + String output = print( + source, + new Diagnostic( + Diagnostic.Level.ERROR, + "expected expression", + span, + "expected expression here" + ) + ); + + String expected = """ + {"source":"foo.mai","level":"error","message":"expected expression","label":"expected expression here","span":{"start":{"offset":7,"line":1,"column":8},"end":{"offset":9,"line":1,"column":10}}} + """; + + assert output.equals(expected) : "\nexpected:\n" + expected + "\nactual:\n" + output; + } + + @Case(name = "omits empty label") + static void noLabel() { + var source = new MemBuf("foo.mai", "foo\n"); + var span = Span.of(Pos.of(0, 1, 1), Pos.of(3, 1, 4)); + + String output = print( + source, + new Diagnostic( + Diagnostic.Level.ERROR, + "unknown name", + span, + null + ) + ); + + String expected = """ + {"source":"foo.mai","level":"error","message":"unknown name","span":{"start":{"offset":0,"line":1,"column":1},"end":{"offset":3,"line":1,"column":4}}} + """; + + assert output.equals(expected) : "\nexpected:\n" + expected + "\nactual:\n" + output; + } + + @Case(name = "escapes JSON strings") + static void escaping() { + var source = new MemBuf("foo.mai", "foo\n"); + var span = Span.of(Pos.of(0, 1, 1), Pos.of(3, 1, 4)); + + String output = print( + source, + new Diagnostic( + Diagnostic.Level.ERROR, + "expected \"foo\"\nfound \\bar", + span, + null + ) + ); + + assert output.contains("expected \\\"foo\\\"\\nfound \\\\bar"); + } + + private static String print(MemBuf source, Diagnostic diagnostic) { + var bytes = new ByteArrayOutputStream(); + + try (var out = new PrintStream(bytes, true, StandardCharsets.UTF_8)) { + var printer = new JsonPrinter(out); + printer.print(source, diagnostic); + } + + return bytes.toString(StandardCharsets.UTF_8); + } + + private JsonPrinterTest() { + } +} diff --git a/test/moe/anita/mai/test/TestRunner.java b/test/moe/anita/mai/test/TestRunner.java index 8103cad..894c266 100644 --- a/test/moe/anita/mai/test/TestRunner.java +++ b/test/moe/anita/mai/test/TestRunner.java @@ -10,7 +10,10 @@ import java.nio.file.Path; public final class TestRunner { - public static void main(String[] args) throws IOException { + private TestRunner() { + } + + static void main(String[] args) throws IOException { Path root = Path.of( System.getProperty( "mai.test.classes", @@ -90,7 +93,7 @@ public final class TestRunner { continue; } - runCase(testClass, method, testCase, result ); + runCase(testClass, method, testCase, result); } } @@ -141,7 +144,6 @@ public final class TestRunner { } } - private static boolean validCase(Method method) { return method.getParameterCount() == 0 && method.getReturnType() == void.class; } @@ -165,7 +167,4 @@ public final class TestRunner { int failed; int skipped; } - - private TestRunner() { - } } -- cgit v1.2.3