diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/java/org/anarres/cpp/CppReaderTest.java | 34 | ||||
-rw-r--r-- | src/test/java/org/anarres/cpp/ErrorTest.java | 65 | ||||
-rw-r--r-- | src/test/java/org/anarres/cpp/JavaFileSystemTest.java | 38 | ||||
-rw-r--r-- | src/test/java/org/anarres/cpp/JoinReaderTest.java | 41 | ||||
-rw-r--r-- | src/test/java/org/anarres/cpp/LexerSourceTest.java | 86 | ||||
-rw-r--r-- | src/test/java/org/anarres/cpp/MainTest.java | 11 | ||||
-rw-r--r-- | src/test/java/org/anarres/cpp/PreprocessorTest.java | 167 | ||||
-rw-r--r-- | src/test/resources/test0.c | 61 | ||||
-rw-r--r-- | src/test/resources/test0.h | 7 | ||||
-rw-r--r-- | src/test/resources/test1.c | 2 | ||||
-rw-r--r-- | src/test/resources/test1.h | 7 | ||||
-rw-r--r-- | src/test/resources/trigraph.c | 1 |
12 files changed, 520 insertions, 0 deletions
diff --git a/src/test/java/org/anarres/cpp/CppReaderTest.java b/src/test/java/org/anarres/cpp/CppReaderTest.java new file mode 100644 index 0000000..27eba06 --- /dev/null +++ b/src/test/java/org/anarres/cpp/CppReaderTest.java @@ -0,0 +1,34 @@ +package org.anarres.cpp; + +import java.util.Collections; + +import java.io.StringReader; +import java.io.BufferedReader; +import org.junit.Test; + +public class CppReaderTest { + + private void testCppReader(String in, String out) + throws Exception { + System.out.println("Testing " + in + " => " + out); + StringReader r = new StringReader(in); + CppReader p = new CppReader(r); + p.getPreprocessor().setSystemIncludePath( + Collections.singletonList("src/test/resources") + ); + p.getPreprocessor().getFeatures().add(Feature.LINEMARKERS); + BufferedReader b = new BufferedReader(p); + + String line; + while ((line = b.readLine()) != null) { + System.out.println(" >> " + line); + } + } + + @Test + public void testCppReader() + throws Exception { + testCppReader("#include <test0.h>\n", "ab"); + } + +} diff --git a/src/test/java/org/anarres/cpp/ErrorTest.java b/src/test/java/org/anarres/cpp/ErrorTest.java new file mode 100644 index 0000000..8777452 --- /dev/null +++ b/src/test/java/org/anarres/cpp/ErrorTest.java @@ -0,0 +1,65 @@ +package org.anarres.cpp; + +import java.io.IOException; +import org.junit.Test; +import static org.anarres.cpp.Token.*; +import static org.junit.Assert.*; + +public class ErrorTest { + + private boolean testError(Preprocessor p) + throws LexerException, + IOException { + for (;;) { + Token tok = p.token(); + if (tok.getType() == EOF) + break; + if (tok.getType() == INVALID) + return true; + } + return false; + } + + private void testError(String input) throws Exception { + StringLexerSource sl; + PreprocessorListener pl; + Preprocessor p; + + /* Without a PreprocessorListener, throws an exception. */ + sl = new StringLexerSource(input, true); + p = new Preprocessor(); + p.addFeature(Feature.CSYNTAX); + p.addInput(sl); + try { + assertTrue(testError(p)); + fail("Lexing unexpectedly succeeded without listener."); + } catch (LexerException e) { + /* required */ + } + + /* With a PreprocessorListener, records the error. */ + sl = new StringLexerSource(input, true); + p = new Preprocessor(); + p.addFeature(Feature.CSYNTAX); + p.addInput(sl); + pl = new PreprocessorListener(); + p.setListener(pl); + assertNotNull("CPP has listener", p.getListener()); + assertTrue(testError(p)); + assertTrue("Listener has errors", pl.getErrors() > 0); + + /* Without CSYNTAX, works happily. */ + sl = new StringLexerSource(input, true); + p = new Preprocessor(); + p.addInput(sl); + assertTrue(testError(p)); + } + + @Test + public void testErrors() throws Exception { + testError("\""); + testError("'"); + // testError("''"); + } + +} diff --git a/src/test/java/org/anarres/cpp/JavaFileSystemTest.java b/src/test/java/org/anarres/cpp/JavaFileSystemTest.java new file mode 100644 index 0000000..0ca44be --- /dev/null +++ b/src/test/java/org/anarres/cpp/JavaFileSystemTest.java @@ -0,0 +1,38 @@ +package org.anarres.cpp; + +import java.io.FileNotFoundException; +import org.junit.Test; +import static org.junit.Assert.*; + +public class JavaFileSystemTest { + + @Test + public void testJavaFileSystem() throws Exception { + JavaFileSystem fs = new JavaFileSystem(); + VirtualFile f; + + /* Anyone who has this file on their Unix box is messed up. */ + f = fs.getFile("/foo/bar baz"); + try { + f.getSource(); /* drop on floor */ + + assertTrue("Got a source for a non-file", f.isFile()); + } catch (FileNotFoundException e) { + assertFalse("Got no source for a file", f.isFile()); + } + + /* We hope we have this. */ + f = fs.getFile("/usr/include/stdio.h"); + try { + f.getSource(); /* drop on floor */ + + System.out.println("Opened stdio.h"); + assertTrue("Got a source for a non-file", f.isFile()); + } catch (FileNotFoundException e) { + System.out.println("Failed to open stdio.h"); + assertFalse("Got no source for a file", f.isFile()); + } + + } + +} diff --git a/src/test/java/org/anarres/cpp/JoinReaderTest.java b/src/test/java/org/anarres/cpp/JoinReaderTest.java new file mode 100644 index 0000000..527aa81 --- /dev/null +++ b/src/test/java/org/anarres/cpp/JoinReaderTest.java @@ -0,0 +1,41 @@ +package org.anarres.cpp; + +import java.io.StringReader; +import org.junit.Test; +import static org.junit.Assert.*; + +public class JoinReaderTest { + + private void testJoinReader(String in, String out, boolean tg) + throws Exception { + System.out.println("Testing " + in + " => " + out); + StringReader r = new StringReader(in); + JoinReader j = new JoinReader(r, tg); + + for (int i = 0; i < out.length(); i++) { + int c = j.read(); + System.out.println("At offset " + i + ": " + (char) c); + assertEquals((char) out.charAt(i), c); + } + assertEquals(-1, j.read()); + assertEquals(-1, j.read()); + } + + private void testJoinReader(String in, String out) + throws Exception { + testJoinReader(in, out, true); + testJoinReader(in, out, false); + } + + @Test + public void testJoinReader() + throws Exception { + testJoinReader("ab", "ab"); + testJoinReader("a\\b", "a\\b"); + testJoinReader("a\nb", "a\nb"); + testJoinReader("a\\\nb", "ab\n"); + testJoinReader("foo??(bar", "foo[bar", true); + testJoinReader("foo??/\nbar", "foobar\n", true); + } + +} diff --git a/src/test/java/org/anarres/cpp/LexerSourceTest.java b/src/test/java/org/anarres/cpp/LexerSourceTest.java new file mode 100644 index 0000000..76bc673 --- /dev/null +++ b/src/test/java/org/anarres/cpp/LexerSourceTest.java @@ -0,0 +1,86 @@ +package org.anarres.cpp; + +import java.util.Arrays; +import org.junit.Test; +import static org.anarres.cpp.Token.*; +import static org.junit.Assert.*; + +public class LexerSourceTest { + + private void testLexerSource(String in, int... out) + throws Exception { + System.out.println("Testing '" + in + "' => " + + Arrays.toString(out)); + StringLexerSource s = new StringLexerSource(in); + + int col = 0; + for (int i = 0; i < out.length; i++) { + Token tok = s.token(); + System.out.println("Token is " + tok); + assertEquals(out[i], tok.getType()); + // assertEquals(col, tok.getColumn()); + col += tok.getText().length(); + } + + Token tok = s.token(); + System.out.println("Token is " + tok); + assertEquals(EOF, tok.getType()); + } + + @Test + public void testLexerSource() + throws Exception { + + testLexerSource("int a = 5;", + IDENTIFIER, WHITESPACE, IDENTIFIER, WHITESPACE, + '=', WHITESPACE, NUMBER, ';', EOF + ); + + // \n is WHITESPACE because ppvalid = false + testLexerSource("# # \r\n\n\r \rfoo", + HASH, WHITESPACE, '#', WHITESPACE, IDENTIFIER + ); + + testLexerSource("%:%:", PASTE); + testLexerSource("%:?", '#', '?'); + testLexerSource("%:%=", '#', MOD_EQ); + testLexerSource("0x1234ffdUL 0765I", + NUMBER, WHITESPACE, NUMBER); + + testLexerSource("+= -= *= /= %= <= >= >>= <<= &= |= ^= x", + PLUS_EQ, WHITESPACE, + SUB_EQ, WHITESPACE, + MULT_EQ, WHITESPACE, + DIV_EQ, WHITESPACE, + MOD_EQ, WHITESPACE, + LE, WHITESPACE, + GE, WHITESPACE, + RSH_EQ, WHITESPACE, + LSH_EQ, WHITESPACE, + AND_EQ, WHITESPACE, + OR_EQ, WHITESPACE, + XOR_EQ, WHITESPACE, + IDENTIFIER); + + testLexerSource("/**/", CCOMMENT); + testLexerSource("/* /**/ */", CCOMMENT, WHITESPACE, '*', '/'); + testLexerSource("/** ** **/", CCOMMENT); + testLexerSource("//* ** **/", CPPCOMMENT); + testLexerSource("'\\r' '\\xf' '\\xff' 'x' 'aa' ''", + CHARACTER, WHITESPACE, + CHARACTER, WHITESPACE, + CHARACTER, WHITESPACE, + CHARACTER, WHITESPACE, + SQSTRING, WHITESPACE, + SQSTRING); + + testLexerSource("1i1I1l1L1ui1ul", + NUMBER, NUMBER, + NUMBER, NUMBER, + NUMBER, NUMBER); + + testLexerSource("'' 'x' 'xx'", + SQSTRING, WHITESPACE, CHARACTER, WHITESPACE, SQSTRING); + } + +} diff --git a/src/test/java/org/anarres/cpp/MainTest.java b/src/test/java/org/anarres/cpp/MainTest.java new file mode 100644 index 0000000..5ff7350 --- /dev/null +++ b/src/test/java/org/anarres/cpp/MainTest.java @@ -0,0 +1,11 @@ +package org.anarres.cpp; + +import org.junit.Test; + +public class MainTest { + + @Test + public void testMain() throws Exception { + Main.main(new String[]{"--version"}); + } +} diff --git a/src/test/java/org/anarres/cpp/PreprocessorTest.java b/src/test/java/org/anarres/cpp/PreprocessorTest.java new file mode 100644 index 0000000..fb2a8ac --- /dev/null +++ b/src/test/java/org/anarres/cpp/PreprocessorTest.java @@ -0,0 +1,167 @@ +package org.anarres.cpp; + +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import org.junit.Before; +import org.junit.Test; +import static org.anarres.cpp.Token.*; +import static org.junit.Assert.*; + +public class PreprocessorTest { + + private OutputStreamWriter writer; + private Preprocessor p; + + @Before + public void setUp() throws Exception { + final PipedOutputStream po = new PipedOutputStream(); + writer = new OutputStreamWriter(po); + + p = new Preprocessor(); + p.addInput( + new LexerSource( + new InputStreamReader( + new PipedInputStream(po) + ), + true + ) + ); + } + + private static class I { + + private String t; + + public I(String t) { + this.t = t; + } + + public String getText() { + return t; + } + + public String toString() { + return getText(); + } + } + + private static I I(String t) { + return new I(t); + } + + /* + * When writing tests in this file, remember the preprocessor + * stashes NLs, so you won't see an immediate NL at the end of any + * input line. You will see it right before the next nonblank on + * the following input line. + */ + @Test + public void testPreprocessor() throws Exception { + /* Magic macros */ + testInput("line = __LINE__\n", + I("line"), WHITESPACE, '=', WHITESPACE, NUMBER + /*, NL - all nls deferred so as not to block the reader */ + ); + testInput("file = __FILE__\n", NL, /* from before, etc */ + I("file"), WHITESPACE, '=', WHITESPACE, STRING + ); + + /* Simple definitions */ + testInput("#define A a /* a defined */\n", NL); + testInput("#define B b /* b defined */\n", NL); + testInput("#define C c /* c defined */\n", NL); + + /* Expansion of arguments */ + testInput("#define EXPAND(x) x\n", NL); + testInput("EXPAND(a)\n", NL, I("a")); + testInput("EXPAND(A)\n", NL, I("a")); + + /* Stringification */ + testInput("#define _STRINGIFY(x) #x\n", NL); + testInput("_STRINGIFY(A)\n", NL, "A"); + testInput("#define STRINGIFY(x) _STRINGIFY(x)\n", NL); + testInput("STRINGIFY(b)\n", NL, "b"); + testInput("STRINGIFY(A)\n", NL, "a"); + + /* Concatenation */ + testInput("#define _CONCAT(x, y) x ## y\n", NL); + testInput("_CONCAT(A, B)\n", NL, I("AB")); + testInput("#define A_CONCAT done_a_concat\n", NL); + testInput("_CONCAT(A, _CONCAT(B, C))\n", NL, + I("done_a_concat"), '(', I("b"), ',', WHITESPACE, I("c"), ')' + ); + testInput("#define CONCAT(x, y) _CONCAT(x, y)\n", NL); + testInput("CONCAT(A, CONCAT(B, C))\n", NL, I("abc")); + testInput("#define _CONCAT3(x, y, z) x ## y ## z\n", NL); + testInput("_CONCAT3(a, b, c)\n", NL, I("abc")); + testInput("_CONCAT3(A, B, C)\n", NL, I("ABC")); + + /* Redefinitions, undefinitions. */ + testInput("#define two three\n", NL); + testInput("one /* one */\n", NL, I("one"), WHITESPACE, CCOMMENT); + testInput("#define one two\n", NL); + testInput("one /* three */\n", NL, I("three"), WHITESPACE, CCOMMENT); + testInput("#undef two\n", NL); + testInput("#define two five\n", NL); + testInput("one /* five */\n", NL, I("five"), WHITESPACE, CCOMMENT); + testInput("#undef two\n", NL); + testInput("one /* two */\n", NL, I("two"), WHITESPACE, CCOMMENT); + testInput("#undef one\n", NL); + testInput("#define one four\n", NL); + testInput("one /* four */\n", NL, I("four"), WHITESPACE, CCOMMENT); + testInput("#undef one\n", NL); + testInput("#define one one\n", NL); + testInput("one /* one */\n", NL, I("one"), WHITESPACE, CCOMMENT); + + /* Variadic macros. */ + testInput("#define var(x...) a x b\n", NL); + testInput("var(e, f, g)\n", NL, + I("a"), WHITESPACE, + I("e"), ',', WHITESPACE, + I("f"), ',', WHITESPACE, + I("g"), WHITESPACE, + I("b") + ); + + testInput("#define _Widen(x) L ## x\n", NL); + testInput("#define Widen(x) _Widen(x)\n", NL); + testInput("#define LStr(x) _Widen(#x)\n", NL); + testInput("LStr(x);\n", NL, I("L"), "x"); + + writer.close(); + + Token t; + do { + t = p.token(); + System.out.println("Remaining token " + t); + } while (t.getType() != EOF); + } + + private void testInput(String in, Object... out) + throws Exception { + System.out.print("Input: " + in); + writer.write(in); + writer.flush(); + for (int i = 0; i < out.length; i++) { + Token t = p.token(); + System.out.println(t); + Object v = out[i]; + if (v instanceof String) { + if (t.getType() != STRING) + fail("Expected STRING, but got " + t); + assertEquals((String) v, (String) t.getValue()); + } else if (v instanceof I) { + if (t.getType() != IDENTIFIER) + fail("Expected IDENTIFIER " + v + ", but got " + t); + assertEquals(((I) v).getText(), (String) t.getText()); + } else if (v instanceof Character) + assertEquals((int) ((Character) v).charValue(), t.getType()); + else if (v instanceof Integer) + assertEquals(((Integer) v).intValue(), t.getType()); + else + fail("Bad object " + v.getClass()); + } + } +} diff --git a/src/test/resources/test0.c b/src/test/resources/test0.c new file mode 100644 index 0000000..7e91637 --- /dev/null +++ b/src/test/resources/test0.c @@ -0,0 +1,61 @@ +line = __LINE__ +file = __FILE__ + +#define A a /* a defined */ +#define B b /* b defined */ +#define C c /* c defined */ + +#define EXPAND(x) x +EXPAND(a) -> a +EXPAND(A) -> a + +#define _STRINGIFY(x) #x +_STRINGIFY(A) -> "A" + +#define STRINGIFY(x) _STRINGIFY(x) +STRINGIFY(b) -> "b" +STRINGIFY(A) -> "a" + +#define _CONCAT(x, y) x ## y +_CONCAT(A, B) -> AB + +#define A_CONCAT done_a_concat +_CONCAT(A, _CONCAT(B, C)) -> done_a_concat(b, c) + +#define CONCAT(x, y) _CONCAT(x, y) +CONCAT(A, CONCAT(B, C)) -> abc + +#define _CONCAT3(x, y, z) x ## y ## z +_CONCAT3(a, b, c) -> abc +_CONCAT3(A, B, C) -> ABC +_CONCAT3(A, EXPAND(B), C) -> AEXPAND(b)C + +Line is __LINE__ +File is __FILE__ + +#define two three +one /* one */ +#define one two +one /* three */ +#undef two +#define two five +one /* five */ +#undef two +one /* two */ +#undef one +#define one four +one /* four */ +#undef one +#define one one +one /* one */ + +/* warning line 57 column 0 */ +#warning arse + +#define foo(x) foo(x, b) +foo(1) -> _foo(1, b) without the _ +foo(foo(2)) -> _foo(_foo(2, b), b) without the _ +// foo(y, z) + +#define var(x...) a x b +var(e, f, g) -> a e, f, g b diff --git a/src/test/resources/test0.h b/src/test/resources/test0.h new file mode 100644 index 0000000..b6697c6 --- /dev/null +++ b/src/test/resources/test0.h @@ -0,0 +1,7 @@ + +test0start_2 + +#include "test1.h" + +test0end___6 + diff --git a/src/test/resources/test1.c b/src/test/resources/test1.c new file mode 100644 index 0000000..3e6fbda --- /dev/null +++ b/src/test/resources/test1.c @@ -0,0 +1,2 @@ +#include "./test0.h" +#include <test1.h> diff --git a/src/test/resources/test1.h b/src/test/resources/test1.h new file mode 100644 index 0000000..0b690f7 --- /dev/null +++ b/src/test/resources/test1.h @@ -0,0 +1,7 @@ + +test1start_2 + +test1mid___4 + +test1end___6 + diff --git a/src/test/resources/trigraph.c b/src/test/resources/trigraph.c new file mode 100644 index 0000000..89615fe --- /dev/null +++ b/src/test/resources/trigraph.c @@ -0,0 +1 @@ +??/ |