Package de.fosd.typechef.lexer

Source Code of de.fosd.typechef.lexer.PreprocessorTestCase$I

package de.fosd.typechef.lexer;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

import static de.fosd.typechef.lexer.Token.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

public class PreprocessorTestCase {
    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));
        p.addFeature(Feature.GNUCEXTENSIONS);
    }

    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,
                INTEGER
                /* , 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 _CONCAT_X(y) X ## y\n", NL);
        testInput("_CONCAT_X(A)\n", NL, I("XA"));
        testInput("#define _CONCAT_INT_X(y) int X ## y\n", NL);
        testInput("_CONCAT_INT_X(A)\n", NL, I("int"), WHITESPACE, I("XA"));

        testInput("#define _CONCAT_X2(y) y ## X\n", NL);
        testInput("_CONCAT_X2(A)\n", NL, I("AX"));
        testInput("#define _CONCAT_INT_X2(y) int y ## X\n", NL);
        testInput("_CONCAT_INT_X2(A)\n", NL, I("int"), WHITESPACE, I("AX"));

        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);

        testInput("#define FNAME(name) paging##64_##name\n", NL);
        testInput("#define gpte_to_gfn_lvl FNAME(gpte_to_gfn_lvl)\n", NL);
        //The kernel sources expect this result:
        //testInput("gpte_to_gfn_lvl\n", NL, I("paging64_gpte_to_gfn_lvl"));
        testInput("gpte_to_gfn_lvl\n", NL, I("paging64"), I("_gpte_to_gfn_lvl"));

        testInput("#undef FNAME\n", NL);
        testInput("#undef gpte_to_gfn_lvl\n", NL);

        //Variants expanding to the expected name:
        testInput("#define FNAME(name) paging64_##name\n", NL);
        testInput("#define gpte_to_gfn_lvl FNAME(gpte_to_gfn_lvl)\n", NL);
        testInput("gpte_to_gfn_lvl\n", NL, I("paging64_gpte_to_gfn_lvl"));

        testInput("#define FNAME(name) paging##64##_##name\n", NL);
        testInput("#define gpte_to_gfn_lvl FNAME(gpte_to_gfn_lvl)\n", NL);
        testInput("gpte_to_gfn_lvl\n", NL, I("paging64_gpte_to_gfn_lvl"));

        testInput("#undef FNAME\n", NL);
        testInput("#undef gpte_to_gfn_lvl\n", NL);

        testInput("#define FNAME(name) pagin##g64_##name\n", NL);
        testInput("#define gpte_to_gfn_lvl FNAME(gpte_to_gfn_lvl)\n", NL);
        testInput("gpte_to_gfn_lvl\n", NL, I("paging64_gpte_to_gfn_lvl"));


        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");
        /*}

      public void testVariadicMacrosGnuC() throws Exception {*/
        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("var()\n", NL, I("a"), WHITESPACE, WHITESPACE, I("b"));
        testInput("#define var2(p1, args...) p1 a args b\n", NL);
        testInput("var2(firstParam, e, f, g)\n", NL, I("firstParam"), WHITESPACE, I("a"), WHITESPACE, I("e"), ',',
                WHITESPACE, I("f"), ',', WHITESPACE, I("g"), WHITESPACE, I("b"));
        testInput("var2(p1)\n", NL, I("p1"), WHITESPACE, I("a"), WHITESPACE, WHITESPACE, I("b"));
        /*}

      public void testVariadicMacrosC99() throws Exception {*/
        testInput("#define varC99(x, ...) a __VA_ARGS__ b\n", NL);
        testInput("varC99(e, f, g)\n", NL, I("a"),
                WHITESPACE, I("f"), ',', WHITESPACE, I("g"), WHITESPACE, I("b"));
        testInput("varC99()\n", NL, I("a"), WHITESPACE, WHITESPACE, I("b"));

        testInput("#define varC99_2(firstParam, ...) a firstParam, __VA_ARGS__ b\n", NL);
        testInput("varC99_2(e, f, g)\n", NL, I("a"), WHITESPACE, I("e"), ',',
                WHITESPACE, I("f"), ',', WHITESPACE, I("g"), WHITESPACE, I("b"));
        testInput("#define eprintf(format, ...) fprintf stderr, format, ##__VA_ARGS__\n", NL);
        testInput("eprintf (a)\n", NL, I("fprintf"), WHITESPACE, I("stderr"), ',', WHITESPACE, I("a"));

        //XXX: should not crash, but should cause an error! How to test an expected error?
        try {
            testInput("#define BUGGY_CONCAT(y) ## y\n", NL);
            //Flush the remaining NL
            testInput("", NL);
            fail("expected exception");
        } catch (de.fosd.typechef.lexer.LexerException e) {
            //expected
        }
    }

    @After
    public void tearDown() throws Exception {
        writer.close();

        Token t;
        do {
            t = p.getNextToken();
            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.getNextToken();
            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());
        }
    }
}
TOP

Related Classes of de.fosd.typechef.lexer.PreprocessorTestCase$I

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.