JFlexXrefTest.java revision 1167
0N/A/*
1472N/A * CDDL HEADER START
0N/A *
0N/A * The contents of this file are subject to the terms of the
0N/A * Common Development and Distribution License (the "License").
0N/A * You may not use this file except in compliance with the License.
0N/A *
0N/A * See LICENSE.txt included in this distribution for the specific
0N/A * language governing permissions and limitations under the License.
0N/A *
0N/A * When distributing Covered Code, include this CDDL HEADER in each
0N/A * file and include the License file at LICENSE.txt.
0N/A * If applicable, add the following below this CDDL HEADER, with the
0N/A * fields enclosed by brackets "[]" replaced with your own identifying
0N/A * information: Portions Copyright [yyyy] [name of copyright owner]
0N/A *
0N/A * CDDL HEADER END
0N/A */
1472N/A
1472N/A/*
1472N/A * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
0N/A */
0N/A
0N/Apackage org.opensolaris.opengrok.analysis;
0N/A
0N/Aimport java.io.File;
0N/Aimport java.io.FileInputStream;
0N/Aimport java.io.IOException;
0N/Aimport java.io.InputStreamReader;
0N/Aimport java.io.Reader;
0N/Aimport java.io.StringReader;
0N/Aimport java.io.StringWriter;
0N/Aimport org.junit.AfterClass;
0N/Aimport org.junit.BeforeClass;
0N/Aimport org.junit.Test;
0N/Aimport org.opensolaris.opengrok.analysis.c.CXref;
0N/Aimport org.opensolaris.opengrok.analysis.c.CxxXref;
0N/Aimport org.opensolaris.opengrok.analysis.document.TroffXref;
0N/Aimport org.opensolaris.opengrok.analysis.fortran.FortranXref;
0N/Aimport org.opensolaris.opengrok.analysis.java.JavaXref;
0N/Aimport org.opensolaris.opengrok.analysis.lisp.LispXref;
0N/Aimport org.opensolaris.opengrok.analysis.perl.PerlXref;
0N/Aimport org.opensolaris.opengrok.analysis.plain.PlainXref;
0N/Aimport org.opensolaris.opengrok.analysis.plain.XMLXref;
0N/Aimport org.opensolaris.opengrok.analysis.sh.ShXref;
0N/Aimport org.opensolaris.opengrok.analysis.sql.SQLXref;
0N/Aimport org.opensolaris.opengrok.analysis.tcl.TclXref;
0N/Aimport org.opensolaris.opengrok.configuration.RuntimeEnvironment;
0N/Aimport org.opensolaris.opengrok.util.TestRepository;
0N/A
0N/Aimport static org.junit.Assert.*;
1703N/A
0N/A/**
0N/A * Unit tests for JFlexXref.
0N/A */
0N/Apublic class JFlexXrefTest {
0N/A
0N/A private static Ctags ctags;
0N/A private static TestRepository repository;
0N/A
0N/A /**
0N/A * This is what we expect to find at the beginning of the first line
0N/A * returned by an xref.
0N/A */
0N/A private static final String FIRST_LINE_PREAMBLE =
0N/A "<a class=\"l\" name=\"1\" href=\"#1\">" +
0N/A "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;</a>";
0N/A
0N/A @BeforeClass
0N/A public static void setUpClass() throws Exception {
0N/A ctags = new Ctags();
0N/A ctags.setBinary(RuntimeEnvironment.getInstance().getCtags());
0N/A repository = new TestRepository();
0N/A repository.create(JFlexXrefTest.class.getResourceAsStream(
0N/A "/org/opensolaris/opengrok/index/source.zip"));
0N/A }
0N/A
0N/A @AfterClass
0N/A public static void tearDownClass() throws Exception {
0N/A ctags.close();
0N/A ctags = null;
0N/A repository.destroy();
0N/A }
0N/A
0N/A /**
0N/A * Regression test case for bug #15890. Check that we get the expected the
0N/A * expected line count from input with some special characters that used
0N/A * to cause trouble.
0N/A */
0N/A @Test
0N/A public void testBug15890LineCount() throws Exception {
0N/A String fileContents =
0N/A "line 1\n" +
0N/A "line 2\n" +
0N/A "line 3\n" +
0N/A "line 4 with \u000B char\n" +
0N/A "line 5 with \u000C char\n" +
0N/A "line 6 with \u0085 char\n" +
0N/A "line 7 with \u2028 char\n" +
0N/A "line 8 with \u2029 char\n" +
0N/A "line 9\n";
0N/A
0N/A bug15890LineCount(new CXref(new StringReader(fileContents)));
0N/A bug15890LineCount(new CxxXref(new StringReader(fileContents)));
0N/A bug15890LineCount(new LispXref(new StringReader(fileContents)));
0N/A bug15890LineCount(new JavaXref(new StringReader(fileContents)));
0N/A bug15890LineCount(new FortranXref(new StringReader(fileContents)));
0N/A bug15890LineCount(new XMLXref(new StringReader(fileContents)));
0N/A bug15890LineCount(new ShXref(new StringReader(fileContents)));
0N/A bug15890LineCount(new TclXref(new StringReader(fileContents)));
0N/A bug15890LineCount(new SQLXref(new StringReader(fileContents)));
0N/A bug15890LineCount(new TroffXref(new StringReader(fileContents)));
0N/A bug15890LineCount(new PlainXref(new StringReader(fileContents)));
0N/A bug15890LineCount(new PerlXref(new StringReader(fileContents)));
0N/A }
0N/A
0N/A /**
0N/A * Helper method that checks the line count for
0N/A * {@link #testBug15890LineCount()}.
0N/A *
0N/A * @param xref an instance of the xref class to test
0N/A */
0N/A private void bug15890LineCount(JFlexXref xref) throws Exception {
0N/A xref.write(new StringWriter());
0N/A assertEquals(10, xref.getLineNumber());
0N/A }
0N/A
0N/A /**
0N/A * Regression test case for bug #15890. Check that an anchor is correctly
0N/A * inserted for definitions that appear after some special characters that
0N/A * used to cause trouble.
0N/A */
0N/A @Test
0N/A public void testBug15890Anchor() throws Exception {
0N/A bug15890Anchor(CXref.class, "c/bug15890.c");
0N/A bug15890Anchor(CxxXref.class, "c/bug15890.c");
0N/A bug15890Anchor(LispXref.class, "lisp/bug15890.lisp");
0N/A bug15890Anchor(JavaXref.class, "java/bug15890.java");
0N/A }
0N/A
0N/A /**
0N/A * Helper method for {@link #testBug15890Anchor()}.
0N/A *
0N/A * @param klass the Xref sub-class to test
0N/A * @param path path to input file with a definition
0N/A */
0N/A private void bug15890Anchor(Class<? extends JFlexXref> klass, String path)
0N/A throws Exception {
0N/A File file = new File(repository.getSourceRoot() + File.separator + path);
0N/A Definitions defs = ctags.doCtags(file.getAbsolutePath() + "\n");
0N/A
0N/A // Input files contain non-ascii characters and are encoded in UTF-8
0N/A Reader in = new InputStreamReader(new FileInputStream(file), "UTF-8");
0N/A
0N/A JFlexXref xref = klass.getConstructor(Reader.class).newInstance(in);
0N/A xref.setDefs(defs);
0N/A
0N/A StringWriter out = new StringWriter();
0N/A xref.write(out);
0N/A //TODO improve below to reflect all possible classes of a definition
0N/A assertTrue(
0N/A "No anchor found",
0N/A out.toString().contains("\" name=\"bug15890\"/><a href="));
0N/A }
0N/A
0N/A /**
0N/A * Regression test case for bug #14663, which used to break syntax
0N/A * highlighting in ShXref.
0N/A */
0N/A @Test
0N/A public void testBug14663() throws Exception {
0N/A // \" should not start a new string literal
0N/A assertXrefLine(ShXref.class, "echo \\\"", "<b>echo</b> \\\"");
0N/A // \" should not terminate a string literal
0N/A assertXrefLine(ShXref.class, "echo \"\\\"\"",
0N/A "<b>echo</b> <span class=\"s\">\"\\\"\"</span>");
0N/A // \` should not start a command substitution
0N/A assertXrefLine(ShXref.class, "echo \\`", "<b>echo</b> \\`");
0N/A // \` should not start command substitution inside a string
0N/A assertXrefLine(ShXref.class, "echo \"\\`\"",
0N/A "<b>echo</b> <span class=\"s\">\"\\`\"</span>");
0N/A // \` should not terminate command substitution
0N/A assertXrefLine(ShXref.class, "echo `\\``",
0N/A "<b>echo</b> <span>`\\``</span>");
0N/A // $# should not start a comment
0N/A assertXrefLine(ShXref.class, "$#", "$#");
0N/A }
0N/A
0N/A /**
0N/A * Helper method that checks that the expected output is produced for a
0N/A * line with the specified xref class. Fails if the output is not as
0N/A * expected.
0N/A *
0N/A * @param xrefClass xref class to test
0N/A * @param inputLine the source code line to parse
0N/A * @param expectedOutput the expected output from the xreffer
0N/A */
0N/A private void assertXrefLine(Class<? extends JFlexXref> xrefClass,
0N/A String inputLine, String expectedOutput) throws Exception {
0N/A JFlexXref xref = xrefClass.getConstructor(Reader.class).newInstance(
0N/A new StringReader(inputLine));
0N/A
0N/A StringWriter output = new StringWriter();
0N/A xref.write(output);
0N/A
0N/A assertEquals(FIRST_LINE_PREAMBLE + expectedOutput, output.toString());
0N/A }
0N/A
0N/A /**
0N/A * Regression test case for bug #16883. Some of the state used to survive
0N/A * across invocations in ShXref, so that a syntax error in one file might
0N/A * cause broken highlighting in subsequent files. Test that the instance
0N/A * is properly reset now.
0N/A */
0N/A @Test
0N/A public void bug16883() throws Exception {
0N/A // Analyze a script with broken syntax (unterminated string literal)
0N/A ShXref xref = new ShXref(new StringReader("echo \"xyz"));
0N/A StringWriter out = new StringWriter();
0N/A xref.write(out);
0N/A assertEquals(
0N/A FIRST_LINE_PREAMBLE +
0N/A "<b>echo</b> <span class=\"s\">\"xyz</span>",
0N/A out.toString());
0N/A
0N/A // Reuse the xref and verify that the broken syntax in the previous
0N/A // file doesn't cause broken highlighting in the next file
0N/A out = new StringWriter();
0N/A String contents = "echo \"hello\"";
0N/A xref.reInit(contents.toCharArray(), contents.length());
0N/A xref.write(out);
0N/A assertEquals(
0N/A FIRST_LINE_PREAMBLE +
0N/A "<b>echo</b> <span class=\"s\">\"hello\"</span>",
0N/A out.toString());
0N/A }
0N/A
0N/A /**
0N/A * <p>
0N/A * Test the handling of #include in C and C++. In particular, these issues
0N/A * are tested:
0N/A * </p>
0N/A *
0N/A * <ul>
0N/A *
0N/A * <li>
0N/A * Verify that we use breadcrumb path for both #include &lt;x/y.h&gt; and
0N/A * #include "x/y.h" in C and C++ (bug #17817)
0N/A * </li>
0N/A *
0N/A * <li>
0N/A * Verify that the link generated for #include &lt;vector&gt; performs a
0N/A * path search (bug #17816)
0N/A * </li>
0N/A *
0N/A * </ul>
0N/A */
0N/A @Test
0N/A public void testCXrefInclude() throws Exception {
0N/A testCXrefInclude(CXref.class);
0N/A testCXrefInclude(CxxXref.class);
0N/A }
0N/A
0N/A private void testCXrefInclude(Class<? extends JFlexXref> klass) throws Exception {
0N/A String[][] testData = {
0N/A { "#include <abc.h>", "#<b>include</b> &lt;<a href=\"/source/s?path=abc.h\">abc.h</a>&gt;" },
0N/A { "#include <abc/def.h>", "#<b>include</b> &lt;<a href=\"/source/s?path=abc\">abc</a>/<a href=\"/source/s?path=abc/def.h\">def.h</a>&gt;" },
0N/A { "#include \"abc.h\"", "#<b>include</b> <span class=\"s\">\"<a href=\"/source/s?path=abc.h\">abc.h</a>\"</span>" },
0N/A { "#include \"abc/def.h\"", "#<b>include</b> <span class=\"s\">\"<a href=\"/source/s?path=abc\">abc</a>/<a href=\"/source/s?path=abc/def.h\">def.h</a>\"</span>" },
0N/A { "#include <vector>", "#<b>include</b> &lt;<a href=\"/source/s?path=vector\">vector</a>&gt;" },
0N/A };
0N/A
0N/A for (String[] s : testData) {
0N/A StringReader in = new StringReader(s[0]);
0N/A StringWriter out = new StringWriter();
0N/A JFlexXref xref = klass.getConstructor(Reader.class).newInstance(in);
0N/A xref.write(out);
0N/A assertEquals(FIRST_LINE_PREAMBLE + s[1], out.toString());
1703N/A }
0N/A }
0N/A
1703N/A /**
0N/A * Verify that ShXref handles here-documents. Bug #18198.
0N/A */
1703N/A @Test
0N/A public void testShXrefHeredoc() throws IOException {
0N/A StringReader in = new StringReader(
1703N/A "cat<<EOF\n" +
0N/A "This shouldn't cause any problem.\n" +
0N/A "EOF\n" +
1703N/A "var='some string'\n");
0N/A
0N/A ShXref xref = new ShXref(in);
1703N/A StringWriter out = new StringWriter();
1703N/A xref.write(out);
0N/A
1703N/A String[] result = out.toString().split("\n");
1703N/A
0N/A // The single-quote on line 2 shouldn't start a string literal.
0N/A assertTrue(result[1].endsWith("This shouldn't cause any problem."));
0N/A
0N/A // The string literal on line 4 should be recognized as one.
0N/A assertTrue(
0N/A result[3].endsWith("=<span class=\"s\">'some string'</span>"));
0N/A }
0N/A
0N/A /**
0N/A * Test that JavaXref handles empty Java comments. Bug #17885.
*/
@Test
public void testEmptyJavaComment() throws IOException {
StringReader in = new StringReader("/**/\nclass xyz { }\n");
JavaXref xref = new JavaXref(in);
StringWriter out = new StringWriter();
xref.write(out);
// Verify that the comment's <span> block is terminated.
assertTrue(out.toString().contains("<span class=\"c\">/**/</span>"));
}
}