/*******************************************************************************
* Copyright (c) 2008, 2015 Nokia Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Ed Swartz (Nokia) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.autotools.ui.tests.autoconf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.eclipse.cdt.autotools.ui.editors.AutoconfEditorMessages;
import org.eclipse.cdt.autotools.ui.editors.parser.AutoconfElement;
import org.eclipse.cdt.autotools.ui.editors.parser.AutoconfIfElement;
import org.eclipse.cdt.autotools.ui.editors.parser.AutoconfMacroArgumentElement;
import org.eclipse.cdt.autotools.ui.editors.parser.AutoconfMacroElement;
import org.eclipse.cdt.autotools.ui.editors.parser.AutoconfParser;
import org.junit.Test;
/**
* Test parsing with macros
* @author eswartz
*
*/
public class TestMacroParser extends BaseParserTest {
@Test
public void testEmpty() {
parse("");
}
@Test
public void testComments() {
//
String text =
"dnl first line\n" +
"dnl second line\n";
AutoconfElement root = parse(text);
Object[] kids = root.getChildren();
// these are stripped
assertEquals(0, kids.length);
assertTreeStructure(root, new String[] {});
}
@Test
public void testMacroParsing1() {
//
String text =
"AC_REQUIRE([AM_SANITY_CHECK])\n" +
"";
AutoconfElement root = parse(text);
assertTreeStructure(root, new String[] { "AC_REQUIRE", "AM_SANITY_CHECK", null });
AutoconfElement[] kids = root.getChildren();
assertEquals(1, kids.length);
assertTrue(kids[0] instanceof AutoconfMacroElement);
AutoconfMacroElement macro = (AutoconfMacroElement) kids[0];
assertEquals("AC_REQUIRE", macro.getName());
assertEquals(1, macro.getParameterCount());
AutoconfElement[] args = macro.getChildren();
assertEquals(1, args.length);
assertTrue(args[0] instanceof AutoconfMacroArgumentElement);
assertEquals("AM_SANITY_CHECK", ((AutoconfMacroArgumentElement)args[0]).getName());
assertEquals("AM_SANITY_CHECK", macro.getParameter(0));
// keep quotes in source
assertEqualSource("[AM_SANITY_CHECK]", args[0]);
assertEqualSource("AC_REQUIRE([AM_SANITY_CHECK])", macro);
}
@Test
public void testMacroParsing2() {
//
String text =
"AC_TWO_ARGS(first,second)\n" +
"";
AutoconfElement root = parse(text);
assertTreeStructure(root, new String[] { "AC_TWO_ARGS", "first", "second", null });
AutoconfElement[] kids = root.getChildren();
assertEquals(1, kids.length);
assertTrue(kids[0] instanceof AutoconfMacroElement);
AutoconfMacroElement macro = (AutoconfMacroElement) kids[0];
assertEquals("AC_TWO_ARGS", macro.getName());
assertEquals(2, macro.getParameterCount());
AutoconfElement[] args = macro.getChildren();
assertEquals(2, args.length);
assertTrue(args[0] instanceof AutoconfMacroArgumentElement);
assertEquals("first", ((AutoconfMacroArgumentElement)args[0]).getName());
assertTrue(args[1] instanceof AutoconfMacroArgumentElement);
assertEquals("second", ((AutoconfMacroArgumentElement)args[1]).getName());
assertEquals("first", macro.getParameter(0));
assertEquals("second", macro.getParameter(1));
assertEqualSource("first", args[0]);
assertEqualSource("second", args[1]);
assertEqualSource("AC_TWO_ARGS(first,second)", macro);
}
@Test
public void testMacroParsing3() {
//
String text =
"AC_ONE_ARG( [quoted( arg ), second] )\n" +
"";
AutoconfElement root = parse(text);
assertTreeStructure(root, new String[] { "AC_ONE_ARG", "quoted( arg ), second", null });
AutoconfElement[] kids = root.getChildren();
assertEquals(1, kids.length);
assertTrue(kids[0] instanceof AutoconfMacroElement);
AutoconfMacroElement macro = (AutoconfMacroElement) kids[0];
assertEquals("AC_ONE_ARG", macro.getName());
AutoconfElement[] args = macro.getChildren();
assertEquals(1, macro.getParameterCount());
assertEquals(1, args.length);
assertTrue(args[0] instanceof AutoconfMacroArgumentElement);
// spaces removed from outermost arguments, but not inner
assertEquals("quoted( arg ), second", ((AutoconfMacroArgumentElement)args[0]).getName());
assertEquals("quoted( arg ), second", macro.getParameter(0));
assertEqualSource("[quoted( arg ), second]", args[0]);
assertEqualSource("AC_ONE_ARG( [quoted( arg ), second] )", macro);
}
@Test
public void testMacroParsing4() {
//
String text =
"AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],\r\n" +
" [AM_AUTOMAKE_VERSION([1.4-p6])])\r\n" +
"\r\n" +
"";
AutoconfElement root = parse(text);
AutoconfElement[] kids = root.getChildren();
assertEquals(1, kids.length);
assertTrue(kids[0] instanceof AutoconfMacroElement);
AutoconfMacroElement macro = (AutoconfMacroElement) kids[0];
assertEquals("AC_DEFUN", macro.getName());
// spaces and quotes dropped
assertEquals(2, macro.getParameterCount());
assertEquals("AM_SET_CURRENT_AUTOMAKE_VERSION", macro.getParameter(0));
assertEquals("AM_AUTOMAKE_VERSION([1.4-p6])", macro.getParameter(1));
// no spaces in source either, but quotes kept
assertEqualSource("[AM_SET_CURRENT_AUTOMAKE_VERSION]", macro.getChildren()[0]);
assertEqualSource("[AM_AUTOMAKE_VERSION([1.4-p6])]", macro.getChildren()[1]);
}
@Test
public void testMacroParsing5() {
// check that complex shell constructs don't throw off the
// parser, and also that we don't mistake shell tokens in a macro argument
String arg2 =
"AC_MSG_CHECKING(for working $2)\n" +
"# Run test in a subshell; some versions of sh will print an error if\n" +
"# an executable is not found, even if stderr is redirected.\n" +
"# Redirect stdin to placate older versions of autoconf. Sigh.\n" +
"if ($2 --version) < /dev/null > /dev/null 2>&1; then\n" +
" $1=$2\n" +
" AC_MSG_RESULT(found)\n" +
"else\n" +
" $1=\"$3/missing $2\"\n" +
" AC_MSG_RESULT(missing)\n" +
"fi\n" +
"AC_SUBST($1)";
String text =
"AC_DEFUN([AM_MISSING_PROG],\n" +
"[" + arg2 + "])\n" +
"";
AutoconfElement root = parse(text);
assertTreeStructure(root, new String[] {
"AC_DEFUN",
"AM_MISSING_PROG",
arg2,
null,
});
AutoconfElement[] kids = root.getChildren();
assertEquals(1, kids.length);
assertTrue(kids[0] instanceof AutoconfMacroElement);
AutoconfMacroElement macro = (AutoconfMacroElement) kids[0];
assertEquals("AC_DEFUN", macro.getName());
assertEquals("AM_MISSING_PROG", macro.getVar());
// spaces dropped
assertEquals(2, macro.getParameterCount());
assertEquals("AM_MISSING_PROG", macro.getParameter(0));
// be sure complex arguments aren't mangled
assertEquals(arg2, macro.getParameter(1));
assertEqualSource("[" + arg2 + "]", macro.getChildren()[1]);
}
@Test
public void testMacroParsing6() {
// empty arguments
String text =
"AC_DEFUN( ,\n" +
")\n";
AutoconfElement root = parse(text);
AutoconfElement[] kids = root.getChildren();
assertEquals(1, kids.length);
assertTrue(kids[0] instanceof AutoconfMacroElement);
AutoconfMacroElement macro = (AutoconfMacroElement) kids[0];
assertEquals("AC_DEFUN", macro.getName());
assertEquals("", macro.getVar());
// spaces dropped
assertEquals(2, macro.getParameterCount());
assertEquals("", macro.getParameter(0));
assertEquals("", macro.getParameter(1));
assertEqualSource("", macro.getChildren()[0]);
assertEqualSource("", macro.getChildren()[1]);
}
@Test
public void testWithErrorUnmatchedLeftParen() {
String text =
"AC_BAD_MACRO(\n";
AutoconfElement root = parse(text, true);
assertEquals(1, root.getChildren().length);
assertTrue(root.getChildren()[0] instanceof AutoconfMacroElement);
checkError(AutoconfEditorMessages.getString(AutoconfParser.UNMATCHED_LEFT_PARENTHESIS));
}
@Test
public void testWithErrorUnmatchedRightParen() {
String text =
"AC_BAD_MACRO())\n";
AutoconfElement root = parse(text, true);
assertEquals(1, root.getChildren().length);
assertTrue(root.getChildren()[0] instanceof AutoconfMacroElement);
checkError(AutoconfEditorMessages.getString(AutoconfParser.UNMATCHED_RIGHT_PARENTHESIS));
}
@Test
public void testNoFalseUnmatchedRightParen() {
String text =
"AC_BAD_MACRO()\n" +
"(\n"+
"cd foo;\n"+
"if test -f myfile; then exit 1; fi\n"+
")\n";
// nothing but the macro and 'if' is detected as meaningful
AutoconfElement root = parse(text);
assertEquals(2, root.getChildren().length);
assertTrue(root.getChildren()[0] instanceof AutoconfMacroElement);
assertTrue(root.getChildren()[1] instanceof AutoconfIfElement);
}
@Test
public void testNestedMacro() {
String text =
"AC_1(AC_2())\n";
AutoconfElement root = parse(text);
assertEquals(1, root.getChildren().length);
assertTrue(root.getChildren()[0] instanceof AutoconfMacroElement);
AutoconfMacroElement ac1 = (AutoconfMacroElement) root.getChildren()[0];
assertEquals(1, ac1.getChildren().length);
assertTrue(ac1.getChildren()[0] instanceof AutoconfMacroArgumentElement);
AutoconfMacroArgumentElement ac2 = (AutoconfMacroArgumentElement) ac1.getChildren()[0];
// one empty argument
assertEquals(1, ac2.getChildren().length);
}
}