diff options
Diffstat (limited to 'codan/org.eclipse.cdt.codan.core.tests/src/org')
36 files changed, 6779 insertions, 0 deletions
diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/cfg/ControlFlowGraphTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/cfg/ControlFlowGraphTest.java new file mode 100644 index 00000000000..b9cfd4d9426 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/cfg/ControlFlowGraphTest.java @@ -0,0 +1,677 @@ +/******************************************************************************* + * Copyright (c) 2009, 2015 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cfg; + +import java.util.Collection; +import java.util.Iterator; + +import org.eclipse.cdt.codan.core.cxx.internal.model.cfg.ControlFlowGraphBuilder; +import org.eclipse.cdt.codan.core.model.IChecker; +import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock; +import org.eclipse.cdt.codan.core.model.cfg.IBranchNode; +import org.eclipse.cdt.codan.core.model.cfg.IConnectorNode; +import org.eclipse.cdt.codan.core.model.cfg.IDecisionNode; +import org.eclipse.cdt.codan.core.model.cfg.IExitNode; +import org.eclipse.cdt.codan.core.model.cfg.IJumpNode; +import org.eclipse.cdt.codan.core.model.cfg.IPlainNode; +import org.eclipse.cdt.codan.core.model.cfg.ISingleOutgoing; +import org.eclipse.cdt.codan.core.model.cfg.IStartNode; +import org.eclipse.cdt.codan.core.tests.CodanFastCxxAstTestCase; +import org.eclipse.cdt.codan.internal.core.cfg.AbstractBasicBlock; +import org.eclipse.cdt.codan.internal.core.cfg.ControlFlowGraph; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.c.CASTVisitor; +import org.eclipse.cdt.core.parser.ParserLanguage; + +/** + * Tests for ControlFlowGraph + */ +public class ControlFlowGraphTest extends CodanFastCxxAstTestCase { + ControlFlowGraph graph; + + /** + * @param ast + */ + private void processAst(IASTTranslationUnit ast) { + CASTVisitor visitor = new CASTVisitor() { + { + shouldVisitDeclarations = true; + } + + @Override + public int visit(IASTDeclaration decl) { + if (decl instanceof IASTFunctionDefinition) { + graph = new ControlFlowGraphBuilder().build((IASTFunctionDefinition) decl); + return PROCESS_ABORT; + } + return PROCESS_CONTINUE; + } + }; + ast.accept(visitor); + } + + private void checkCfg() { + checkCfg(true); + } + + /** + * + */ + private void checkCfg(boolean decision) { + assertNotNull(graph); + assertNotNull(graph.getStartNode()); + Collection<IBasicBlock> nodes = graph.getNodes(); + for (Iterator<IBasicBlock> iterator = nodes.iterator(); iterator.hasNext();) { + IBasicBlock node = iterator.next(); + checkNode(node, decision); + } + } + + /** + * @param node + */ + private void checkNode(IBasicBlock node, boolean decision) { + IBasicBlock[] incomingNodes = node.getIncomingNodes(); + nodes: for (int i = 0; i < incomingNodes.length; i++) { + IBasicBlock b = incomingNodes[i]; + if (b == null) { + if (node instanceof IBranchNode) + continue nodes; + // check if dead node + Iterator<IBasicBlock> iterator = graph.getUnconnectedNodeIterator(); + boolean dead = false; + for (; iterator.hasNext();) { + IBasicBlock d = iterator.next(); + if (node == d) { + dead = true; + break; + } + } + if (!dead) + fail("Block " + node + " prev is null"); + } else if (!contains(node, b.getOutgoingNodes())) + fail("Block " + node + " inconsitent prev/next " + b); + } + IBasicBlock[] outgoingNodes = node.getOutgoingNodes(); + for (int i = 0; i < outgoingNodes.length; i++) { + IBasicBlock b = outgoingNodes[i]; + if (b == null) + fail("Block " + node + " next is null"); + if (!contains(node, b.getIncomingNodes())) + fail("Block " + node + " inconsitent next/prev " + b); + } + if (node instanceof IDecisionNode && decision) { + assertTrue("decision node outgoing size " + node.getOutgoingSize(), node.getOutgoingSize() >= 1); + assertNotNull(((IDecisionNode) node).getMergeNode()); + } + } + + /** + * @param node + * @param outgoingIterator + * @return + */ + private boolean contains(IBasicBlock node, IBasicBlock[] blocks) { + for (int i = 0; i < blocks.length; i++) { + IBasicBlock b = blocks[i]; + if (b.equals(node)) + return true; + } + return false; + } + + protected void buildAndCheck(String code) { + buildAndCheck(code, false); + } + + protected void buildAndCheck_cpp(String code) { + buildAndCheck(code, true); + } + + /** + * @param file + */ + protected void buildAndCheck(String code, boolean cpp) { + buildCfg(code, cpp); + checkCfg(); + } + + /** + * @param code + * @param cpp + */ + private void buildCfg(String code, boolean cpp) { + parse(code, cpp ? ParserLanguage.CPP : ParserLanguage.C, true); + processAst(tu); + } + + private void buildCfg_C(String code) { + parse(code, ParserLanguage.C, true); + processAst(tu); + } + + private void buildCfg_CPP(String code) { + parse(code, ParserLanguage.CPP, true); + processAst(tu); + } + + /** + * @param des + * @return + */ + private String data(IBasicBlock des) { + return ((AbstractBasicBlock) des).toStringData(); + } + + /** + * Return first node after the branch + * + * @param des + * @return + */ + private IBasicBlock branchEnd(IDecisionNode des, String label) { + IBasicBlock[] outgoingNodes = des.getOutgoingNodes(); + for (int i = 0; i < outgoingNodes.length; i++) { + IBasicBlock iBasicBlock = outgoingNodes[i]; + IBranchNode bn = (IBranchNode) iBasicBlock; + if (label.equals(bn.getLabel())) + return bn.getOutgoing(); + } + return null; + } + + /** + * Return node where control jumps, following the chain until jump is hit + * + * @param a + * @return + */ + private IBasicBlock jumpEnd(IBasicBlock a) { + if (a instanceof IJumpNode) + return ((IJumpNode) a).getOutgoing(); + if (a instanceof ISingleOutgoing) + return jumpEnd(((ISingleOutgoing) a).getOutgoing()); + return null; + } + + @Override + public boolean isCpp() { + return true; + } + + // main() { + // int a; + // a=1; + // } + public void test_basic() { + buildAndCheck(getAboveComment()); + } + + // main() { + // int a=10; + // while (a--) { + // a=a-2; + // } + // } + public void test_while() { + buildAndCheck(getAboveComment()); + IStartNode startNode = graph.getStartNode(); + IPlainNode decl = (IPlainNode) startNode.getOutgoing(); + IConnectorNode conn = (IConnectorNode) decl.getOutgoing(); + IDecisionNode des = (IDecisionNode) conn.getOutgoing(); + assertEquals("a--", data(des)); + IPlainNode bThen = (IPlainNode) branchEnd(des, IBranchNode.THEN); + assertEquals("a=a-2;", data(bThen)); + IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE); + IBasicBlock m2 = jumpEnd(bThen); + IBasicBlock m1 = jumpEnd(bElse); + assertSame(conn, m2); + IExitNode ret = (IExitNode) ((IConnectorNode) m1).getOutgoing(); + } + + // main() { + // int a=10; + // if (a--) { + // a=a-2; + // } + // } + public void test_if() { + buildAndCheck(getAboveComment()); + IStartNode startNode = graph.getStartNode(); + IPlainNode decl = (IPlainNode) startNode.getOutgoing(); + IDecisionNode des = (IDecisionNode) decl.getOutgoing(); + assertEquals("a--", data(des)); + IPlainNode bThen = (IPlainNode) branchEnd(des, IBranchNode.THEN); + assertEquals("a=a-2;", data(bThen)); + IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE); + IBasicBlock m2 = jumpEnd(bThen); + IBasicBlock m1 = jumpEnd(bElse); + assertSame(m1, m2); + } + + // main() { + // int a=10; + // if (a--) { + // return; + // } + // } + public void test_if_ret() { + buildAndCheck(getAboveComment()); + IStartNode startNode = graph.getStartNode(); + IPlainNode decl = (IPlainNode) startNode.getOutgoing(); + IDecisionNode des = (IDecisionNode) decl.getOutgoing(); + assertEquals("a--", data(des)); + IExitNode bThen = (IExitNode) branchEnd(des, IBranchNode.THEN); + IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE); + IBasicBlock m1 = jumpEnd(bElse); + } + + // main() { + // return; + // a++; + // } + public void test_dead() { + buildCfg(getAboveComment(), false); + IStartNode startNode = graph.getStartNode(); + IExitNode ret = (IExitNode) startNode.getOutgoing(); + assertEquals(1, graph.getUnconnectedNodeSize()); + } + + // main() { + // int a=10; + // if (a--) { + // return; + // a++; + // } + // } + public void test_if_dead() { + buildCfg(getAboveComment(), false); + IStartNode startNode = graph.getStartNode(); + IPlainNode decl = (IPlainNode) startNode.getOutgoing(); + IDecisionNode des = (IDecisionNode) decl.getOutgoing(); + assertEquals("a--", data(des)); + IExitNode bThen = (IExitNode) branchEnd(des, IBranchNode.THEN); + IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE); + IBasicBlock m1 = jumpEnd(bElse); + assertEquals(1, graph.getUnconnectedNodeSize()); + } + + // foo(int x) { + // int a=10; + // if (a--) { + // if (x<0) + // a++; + // } + // } + public void test_ifif() { + buildAndCheck(getAboveComment()); + IStartNode startNode = graph.getStartNode(); + IPlainNode decl = (IPlainNode) startNode.getOutgoing(); + IDecisionNode des = (IDecisionNode) decl.getOutgoing(); + assertEquals("a--", data(des)); + IDecisionNode bThen = (IDecisionNode) branchEnd(des, IBranchNode.THEN); + assertEquals("x<0", data(bThen)); + IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE); + IBasicBlock m2 = jumpEnd(branchEnd(bThen, IBranchNode.THEN)); + IBasicBlock m1 = jumpEnd(bElse); + IBasicBlock m3 = jumpEnd(m2); + assertSame(m1, m3); + } + + // int foo() { + // throw 5; + // } + public void test_throw() { + buildAndCheck_cpp(getAboveComment()); + IStartNode startNode = graph.getStartNode(); + assertEquals(1, graph.getExitNodeSize()); + Iterator<IExitNode> exitNodeIterator = graph.getExitNodeIterator(); + IExitNode exit = exitNodeIterator.next(); + assertEquals("throw 5;", data(exit)); + } + + // int foo() { + // exit(0); + // } + public void test_exit() { + buildAndCheck(getAboveComment()); + IStartNode startNode = graph.getStartNode(); + assertEquals(1, graph.getExitNodeSize()); + Iterator<IExitNode> exitNodeIterator = graph.getExitNodeIterator(); + IExitNode exit = exitNodeIterator.next(); + assertEquals("exit(0);", data(exit)); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.codan.core.test.CodanFastCxxAstTestCase#getChecker() + */ + @Override + public IChecker getChecker() { + return null; + } + + // int foo() { + // void * p; + // try { + // *p = 1; + // } catch (int e) { + // }; + // } + public void test_try() { + buildAndCheck_cpp(getAboveComment()); + IStartNode startNode = graph.getStartNode(); + IPlainNode decl = (IPlainNode) startNode.getOutgoing(); + IDecisionNode des = (IDecisionNode) decl.getOutgoing(); + //assertEquals("", data(des)); + IPlainNode bThen = (IPlainNode) branchEnd(des, IBranchNode.TRY_BODY); + assertEquals("*p = 1;", data(bThen)); + IBasicBlock bElse = null; + IBasicBlock[] outgoingNodes = des.getOutgoingNodes(); + for (int i = 1; i < outgoingNodes.length; i++) { + IBasicBlock iBasicBlock = outgoingNodes[i]; + IBranchNode bn = (IBranchNode) iBasicBlock; + bElse = bn; + } + IBasicBlock m2 = jumpEnd(bThen); + IBasicBlock m1 = jumpEnd(bElse); + assertSame(m1, m2); + } + + // foo() { + // switch (0) { + // case 1: ; + // } + // } + public void test_switch1() { + buildCfg(getAboveComment(), false); + checkCfg(false); + } + + // foo() { + // switch (0) { + // case 1: break; + // } + // } + public void test_switchbreak() { + buildCfg(getAboveComment(), false); + checkCfg(false); + } + + // foo() { + // switch (0) { + // a++; + // } + // } + public void test_switchdead() { + buildCfg(getAboveComment(), false); + checkCfg(false); + IStartNode startNode = graph.getStartNode(); + assertEquals(1, graph.getUnconnectedNodeSize()); + } + + // foo() { + // int a=10,x=5; + // if (x<0) + // a++; + // } + public void test_deadbranch() { + buildCfg(getAboveComment(), false); + checkCfg(false); + IStartNode startNode = graph.getStartNode(); + IPlainNode decl = (IPlainNode) startNode.getOutgoing(); + IDecisionNode des = (IDecisionNode) decl.getOutgoing(); + assertEquals("x<0", data(des)); + IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE); + IBasicBlock m2 = jumpEnd(branchEnd(des, IBranchNode.THEN)); + IBasicBlock m1 = jumpEnd(bElse); + assertNull(m2); + assertNotNull(m1); + } + + // int test1_f() + // { + // while (1) + // { + // } + // } + public void test_infiniloop() { + buildCfg_C(getAboveComment()); + checkCfg(false); + IStartNode startNode = graph.getStartNode(); + IConnectorNode conn = (IConnectorNode) startNode.getOutgoing(); + IDecisionNode des = (IDecisionNode) conn.getOutgoing(); + assertEquals("1", data(des)); + IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE); + IBasicBlock bThen = branchEnd(des, IBranchNode.THEN); + IBasicBlock m2 = jumpEnd(bThen); + IBasicBlock m1 = jumpEnd(bElse); + assertNotNull(m2); + assertNull(m1); + } + + // void foo() { + // for (int i=0;i<N;i++) { + // bar(); + // } + //} + public void test_for() { + buildCfg_CPP(getAboveComment()); + checkCfg(false); + IStartNode startNode = graph.getStartNode(); + IPlainNode decl = (IPlainNode) startNode.getOutgoing(); + IConnectorNode conn = (IConnectorNode) decl.getOutgoing(); + IDecisionNode des = (IDecisionNode) conn.getOutgoing(); + assertEquals("i<N", data(des)); + IPlainNode bThen = (IPlainNode) branchEnd(des, IBranchNode.THEN); + assertEquals("bar();", data(bThen)); + IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE); + IBasicBlock m1 = jumpEnd(bElse); + IBasicBlock m2 = bThen.getOutgoing(); + assertNotNull(m1); + assertSame(conn, jumpEnd(bThen)); + assertEquals("i++", data(((IConnectorNode) m2).getOutgoing())); + } + + // void foo() { + // for (int i : arr) { + // bar(); + // } + // } + public void test_range_loop() { + buildCfg_CPP(getAboveComment()); + checkCfg(false); + IStartNode startNode = graph.getStartNode(); + IPlainNode decl = (IPlainNode) startNode.getOutgoing(); + IConnectorNode conn = (IConnectorNode) decl.getOutgoing(); + IDecisionNode des = (IDecisionNode) conn.getOutgoing(); + assertEquals("arr", data(des)); // condition + IPlainNode bThen = (IPlainNode) branchEnd(des, IBranchNode.THEN); + assertEquals("bar();", data(bThen)); + IBasicBlock bElse = branchEnd(des, IBranchNode.ELSE); + assertNotNull(bElse); + IBasicBlock m2 = bThen.getOutgoing(); + IBasicBlock m1 = jumpEnd(bElse); + assertNotNull(m1); + assertSame(conn, jumpEnd(bThen)); + assertEquals("", data(((IConnectorNode) m2).getOutgoing())); // increment + } + + // int main() { + // goto b; + // a: + // return 2; + // b: + // goto a; + // } + public void test_bad_labels() { + buildAndCheck(getAboveComment()); + assertEquals(0, graph.getUnconnectedNodeSize()); + IStartNode startNode = graph.getStartNode(); + IJumpNode gotoB = (IJumpNode) startNode.getOutgoing(); + IConnectorNode bConn = gotoB.getJumpNode(); + IJumpNode gotoA = (IJumpNode) bConn.getOutgoing(); + IConnectorNode aConn = gotoA.getJumpNode(); + IExitNode ret = (IExitNode) aConn.getOutgoing(); + assertEquals("return 2;", data(ret)); + } + + // int main(int a) { + // goto b; + // if (a) return 2; + // b: + // return 1; + // } + public void test_labels_if() { + buildAndCheck(getAboveComment()); + assertEquals(1, graph.getUnconnectedNodeSize()); // if is dead code + } + + // int main(int a) { + // goto b; + // b:; + // } + public void test_goto() { + buildAndCheck(getAboveComment()); + assertEquals(0, graph.getUnconnectedNodeSize()); + } + + // int main() { + // return 1; + // a: + // return 2; + // b: + // goto a; + // } + public void test_dead_labels() { + buildAndCheck(getAboveComment()); + assertEquals(1, graph.getUnconnectedNodeSize()); + IStartNode startNode = graph.getStartNode(); + IExitNode ret = (IExitNode) startNode.getOutgoing(); + assertEquals("return 1;", data(ret)); + IBranchNode labelB = (IBranchNode) graph.getUnconnectedNodeIterator().next(); // BranchNode: b: + Collection<IBasicBlock> res = graph.getDeadNodes(); + assertEquals(6, res.size()); + + IJumpNode gotoA = (IJumpNode) ((IConnectorNode) labelB.getOutgoing()).getOutgoing(); + IConnectorNode aConn = gotoA.getJumpNode(); + IExitNode ret2 = (IExitNode) aConn.getOutgoing(); + assertEquals("return 2;", data(ret2)); + assertTrue(res.contains(gotoA));// goto a; + assertTrue(res.contains(aConn)); + assertTrue(res.contains(ret2)); // return 2; + assertTrue(res.contains(ret2.getIncoming())); // Branch Node: a: + } + + // int main(int a) { + // if (a) { + // return 1; + // } else { + // return 2; + // } + // a++; + // } + public void test_dead_connector() { + buildAndCheck(getAboveComment()); + assertEquals(1, graph.getUnconnectedNodeSize()); + IConnectorNode connIf = (IConnectorNode) graph.getUnconnectedNodeIterator().next(); + assertEquals("a++;", data(connIf.getOutgoing())); + } + + // int main(int a) { + // for (;1;a++) { + // return 1; + // } + // a--; + // } + public void test_dead_connector_for() { + buildAndCheck(getAboveComment()); + assertEquals(2, graph.getUnconnectedNodeSize()); + IConnectorNode conn = (IConnectorNode) graph.getUnconnectedNodeIterator().next(); + assertEquals("a++", data(conn.getOutgoing())); + } + + // int main(int a) { + // while (0) { + // return 1; + // } + // + // a++; + // } + public void test_dead_connector_while() { + buildAndCheck(getAboveComment()); + assertEquals(1, graph.getUnconnectedNodeSize()); + IBranchNode trueBranch = (IBranchNode) graph.getUnconnectedNodeIterator().next(); + assertEquals("return 1;", data(trueBranch.getOutgoing())); + } + + // int foo(int x) { + // switch (x) { + // case 0: + // return 42;; + // default: + // } + // } + public void test_dead_statement_in_switch() throws Exception { + buildAndCheck(getAboveComment()); + IDecisionNode swittch = (IDecisionNode) graph.getStartNode().getOutgoing(); + Collection<IBasicBlock> deadNodes = graph.getDeadNodes(); + // Make sure the switch statement's merge node has not been marked as dead. + assertFalse(deadNodes.contains(swittch.getMergeNode())); + } + + // int main(int a) { + // switch (a) { + // case 1: { + // break; + // } + // case 2: { + // break; + // } + // } + // } + public void test_switch_break_in_compound_statement() { + // Test that the target node of the jump for the 'break' in a case + // is the connector node at the end of the switch, not the connector + // node for the next case. + buildAndCheck(getAboveComment()); + IDecisionNode swittch = (IDecisionNode) graph.getStartNode().getOutgoing(); + IPlainNode case1Branch = (IPlainNode) swittch.getOutgoingNodes()[0]; + IJumpNode case1Jump = (IJumpNode) case1Branch.getOutgoing(); + assertEquals(swittch.getMergeNode(), case1Jump.getJumpNode()); + } + + // int main(int a) { + // switch (a) { + // } + // } + public void test_empty_switch() { + buildAndCheck(getAboveComment()); + // Decision node should be optimized away entirely + assertFalse(graph.getStartNode() instanceof IDecisionNode); + } + + // int main(int a) { + // switch (a) { + // case 1: { + // break; + // } + // } + // } + public void test_switch_no_explicit_default() { + buildAndCheck(getAboveComment()); + IDecisionNode swittch = (IDecisionNode) graph.getStartNode().getOutgoing(); + assertTrue(swittch.getOutgoingSize() == 2); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/cxx/CxxAstUtilsTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/cxx/CxxAstUtilsTest.java new file mode 100644 index 00000000000..2133f771f5e --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/cxx/CxxAstUtilsTest.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2009, 2012 QNX Software Systems + * 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: + * QNX Software Systems (Alena Laskavaia) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cxx; + +import java.io.IOException; + +import org.eclipse.cdt.codan.core.model.IChecker; +import org.eclipse.cdt.codan.core.tests.CodanFastCxxAstTestCase; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTStatement; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.c.ICBasicType; + +/** + * Test CxxAstUtils + */ +public class CxxAstUtilsTest extends CodanFastCxxAstTestCase { + @Override + public IChecker getChecker() { + return null; // not testing checker + } + + // typedef int A; + // typedef A B; + // void main() { + // B x; + // } + public void testUnwindTypedef() throws IOException { + String code = getAboveComment(); + IASTTranslationUnit tu = parse(code); + final Object result[] = new Object[1]; + ASTVisitor astVisitor = new ASTVisitor() { + { + shouldVisitDeclarations = true; + } + + @Override + public int visit(IASTDeclaration decl) { + if (decl instanceof IASTSimpleDeclaration) { + IASTSimpleDeclaration sdecl = (IASTSimpleDeclaration) decl; + IASTDeclSpecifier spec = sdecl.getDeclSpecifier(); + if (spec instanceof IASTNamedTypeSpecifier) { + IASTName tname = ((IASTNamedTypeSpecifier) spec).getName(); + IType typeName = (IType) tname.resolveBinding(); + result[0] = CxxAstUtils.unwindTypedef(typeName); + } + } + return PROCESS_CONTINUE; + } + }; + tu.accept(astVisitor); + assertNotNull(result[0]); + ICBasicType type = (ICBasicType) result[0]; + assertEquals(Kind.eInt, type.getKind()); + } + + // #define AAA a + // void main (){ + // AAA; + // b; + //} + public void testIsInMacro() throws IOException { + String code = getAboveComment(); + IASTTranslationUnit tu = parse(code); + final Object result[] = new Object[2]; + ASTVisitor astVisitor = new ASTVisitor() { + int i; + { + shouldVisitStatements = true; + } + + @Override + public int visit(IASTStatement stmt) { + if (stmt instanceof IASTExpressionStatement) { + boolean check = CxxAstUtils.isInMacro(((IASTExpressionStatement) stmt).getExpression()); + result[i] = check; + i++; + } + return PROCESS_CONTINUE; + } + }; + tu.accept(astVisitor); + assertNotNull("Stmt not found", result[0]); //$NON-NLS-1$ + assertTrue((Boolean) result[0]); + assertFalse((Boolean) result[1]); + } + + //void f() __attribute__((noreturn)); + // + //int test() { + // a(); + // f(); + // exit(0); + //} + public void testExitStatement() throws IOException { + String code = getAboveComment(); + IASTTranslationUnit tu = parse(code); + final Object result[] = new Object[4]; + ASTVisitor astVisitor = new ASTVisitor() { + int i; + { + shouldVisitStatements = true; + } + + @Override + public int visit(IASTStatement stmt) { + boolean check = CxxAstUtils.isExitStatement(stmt); + result[i] = check; + i++; + return PROCESS_CONTINUE; + } + }; + tu.accept(astVisitor); + assertNotNull("Stmt not found", result[0]); //$NON-NLS-1$ + assertFalse((Boolean) result[0]); // compound body + assertFalse((Boolean) result[1]); + assertTrue((Boolean) result[2]); + assertTrue((Boolean) result[3]); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/cxx/externaltool/ArgsSeparatorTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/cxx/externaltool/ArgsSeparatorTest.java new file mode 100644 index 00000000000..0623c6477a3 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/cxx/externaltool/ArgsSeparatorTest.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * 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: + * Alex Ruiz (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.cxx.externaltool; + +import static org.junit.Assert.assertArrayEquals; +import junit.framework.TestCase; + +/** + * Tests for <code>{@link ArgsSeparator}</code>. + */ +@SuppressWarnings("nls") +public class ArgsSeparatorTest extends TestCase { + private ArgsSeparator separator; + + @Override + protected void setUp() { + separator = new ArgsSeparator(); + } + + public void testWithSpaceAsDelimiter() { + String[] args = separator.splitArguments("abc def ghi"); + assertArrayEquals(new String[] { "abc", "def", "ghi" }, args); + } + + public void testWithSingleQuote() { + String[] args = separator.splitArguments("abc 'def ghi' jkl"); + assertArrayEquals(new String[] { "abc", "def ghi", "jkl" }, args); + } + + public void testWithDoubleQuote() { + String[] args = separator.splitArguments("abc \"def ghi\" jkl"); + assertArrayEquals(new String[] { "abc", "def ghi", "jkl" }, args); + } + + public void testWithEscapedSingleQuote() { + String[] args = separator.splitArguments("abc 'def \\' ghi' jkl"); + assertArrayEquals(new String[] { "abc", "def \\' ghi", "jkl" }, args); + } + + public void testWithEscapedDoubleQuote() { + String[] args = separator.splitArguments("abc 'def \\\" ghi' jkl"); + assertArrayEquals(new String[] { "abc", "def \\\" ghi", "jkl" }, args); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/AbstractClassInstantiationCheckerTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/AbstractClassInstantiationCheckerTest.java new file mode 100644 index 00000000000..2bb86d7377f --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/AbstractClassInstantiationCheckerTest.java @@ -0,0 +1,376 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 Anton Gorenkov + * 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: + * Anton Gorenkov - initial implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; +import org.eclipse.cdt.codan.internal.checkers.AbstractClassInstantiationChecker; + +/** + * Test for {@see AbstractClassInstantiationChecker} class + */ +public class AbstractClassInstantiationCheckerTest extends CheckerTestCase { + @Override + public boolean isCpp() { + return true; + } + + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems(AbstractClassInstantiationChecker.ER_ID); + } + + // class C { + // virtual void f() {} + // }; + // void scope () { + // C c; // No errors. + // } + public void testNotAbstractClassCreationOnStack() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class C { + // virtual void f() {} + // }; + // void scope () { + // C* c = new C(); // No errors. + // } + public void testNotAbstractClassCreationWithNew() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class C { + // virtual void f() {} + // }; + // void scope () { + // C::C(); // No errors. + // } + public void testNotAbstractClassCreationWithDirectConstructorCall() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class C { + // virtual void f() = 0; + // }; + // void scope () { + // C* c1; // No errors. + // C& c2; // No errors. + // } + public void testAbstractClassPointerOrReverenceDeclaration() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class C { + // virtual void f() = 0; + // }; + // typedef C typedefC; + // void scope () { + // C c; // 1 error for: C::f(). + // typedefC tc; // 1 error for: C::f(). + // } + public void testAbstractClassCreationOnStack() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(6, 7); + } + + // class C { + // virtual void f() = 0; + // }; + // typedef C typedefC; + // void scope () { + // C *c1, c2, &c3; // 1 error for: C::f(). + // typedefC *tc1, tc2, &tc3; // 1 error for: C::f(). + // } + public void testAbstractClassCreationOnStackWithRefAndPtr() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(6, 7); + } + + // class C { + // virtual void f() = 0; + // }; + // typedef C typedefC; + // void test ( C _c ) {} // 1 error for: C::f(). + // void test2 ( typedefC _c ) {} // 1 error for: C::f(). + // void test3 ( C _c, typedefC _c ) {} // 2 errors for: C::f(), C::f(). + // void test4 ( C ) {} // 1 error for: C::f(). + // void test5 ( C* _c ) {} // No errors. + // void test6 ( typedefC& _c ) {} // No errors. + public void testAbstractClassCreationAsFunctionParameter() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(5, 6, 7, 7, 8); + } + + // class C { + // virtual void f() = 0; + // }; + // template <typename C> // No errors. + // void test () {} + public void testAbstractClassCreationAsFunctionTemplateParameter() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class C { + // virtual void f() = 0; + // }; + // typedef C typedefC; + // void scope () { + // C* c1 = new C(); // 1 error for: C::f(). + // C* c2 = new C[10]; // 1 error for: C::f(). + // C* c3 = new typedefC(); // 1 error for: C::f(). + // C* c4 = new typedefC; // 1 error for: C::f(). + // C* c5 (new C()); // 1 error for: C::f(). + // C* c6 (new typedefC()); // 1 error for: C::f(). + // C* c7 = new typedefC[10]; // 1 error for: C::f(). + // C** x1 = new C*(); // No errors. + // typedefC** x2 = new typedefC*(); // No errors. + // } + public void testAbstractClassCreationWithNew() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(6, 7, 8, 9, 10, 11, 12); + } + + // class C { + // virtual void f() = 0; + // }; + // typedef C typedefC; + // void scope () { + // C::C(); // 1 error for: C::f(). + // typedefC::C(); // 1 error for: C::f(). + // } + public void testAbstractClassCreationWithDirectConstructorCall() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(6, 7); + } + + // namespace N { + // class C { + // virtual void f() = 0; + // }; + // } + // void scope () { + // N::C* c = new N::C(); // 1 error for: N::C::f(). + // } + public void testAbstractClassFromNamespace() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(7); + } + + // class C { + // virtual void f() = 0; + // virtual int g() const = 0; + // }; + // void scope () { + // C* c = new C(); // 2 errors for: C::f(), C::g(). + // } + public void testAbstractClassWithAFewVirtualMethods() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(6, 6); + } + + // class Base { + // virtual void f() = 0; + // }; + // class Derived : public Base { + // }; + // void scope () { + // Derived* d = new Derived(); // 1 error for: Base::f(). + // } + public void testAbstractClassBecauseOfBaseClass() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(7); + } + + // class Base { + // virtual void f() = 0; + // virtual int g() const = 0; + // }; + // class Derived : public Base { + // virtual int g() const = 0; + // }; + // void scope () { + // Derived* c = new Derived(); // 2 errors for: Base::f(), Derived::g(). + // } + public void testAbstractClassWithVirtualRedefinition() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(9, 9); + } + + // class C { + // virtual void f() = 0; + // }; + // typedef C typedefC; // No errors. + public void testAbstractClassTypedef() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class C { + // virtual void f() = 0; + // }; + // extern C typedefC; // 1 error for: C::f(). + public void testExternAbstractClassDeclaration() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(4); + } + + // class A { + // public: + // virtual ~A() = 0; + // }; + // + // class B : public A { + // public: + // virtual ~B() {} + // }; + // + // B b; + public void testPureVirtualDestructorOverride_1() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class A { + // public: + // virtual ~A() = 0; + // }; + // + // class B : public A { + // }; + // + // B b; + public void testPureVirtualDestructorOverride_2() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // struct MyInterface { + // virtual void doIt() = 0; + // }; + // + // struct Empty: virtual public MyInterface {}; + // + // struct Implementer: virtual public MyInterface { + // virtual void doIt(); + // }; + // + // struct Multiple: public Empty, public Implementer {}; + // + // static Multiple sharedMultiple; + public void testDiamondInheritanceWithOneImplementor_bug351612a() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // struct MyInterface { + // virtual void doIt() = 0; + // }; + // + // struct Empty: virtual public MyInterface {}; + // + // struct Implementer: public MyInterface { + // virtual void doIt(); + // }; + // + // struct Multiple: public Empty, public Implementer {}; + // + // static Multiple sharedMultiple; + public void testDiamondInheritanceWithOneImplementor_bug351612b() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(13); + } + + // struct MyInterface { + // virtual void doIt() = 0; + // }; + // + // struct Empty: public MyInterface {}; + // + // struct Implementer: virtual public MyInterface { + // virtual void doIt(); + // }; + // + // struct Multiple: public Empty, public Implementer {}; + // + // static Multiple sharedMultiple; + public void testDiamondInheritanceWithOneImplementor_bug351612c() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(13); + } + + // struct MyInterface { + // virtual void doIt() = 0; + // }; + // + // struct Empty: virtual public MyInterface {}; + // + // struct Implementer: virtual public MyInterface { + // virtual void doIt(); + // }; + // + // struct Multiple: virtual public Implementer, virtual public Empty {}; + // + // static Multiple sharedMultiple; + public void testDiamondInheritanceWithOneImplementor_bug419938() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // struct A { + // virtual void test(int) = 0; + // virtual ~A(); + // }; + // + // struct B : public A { + // using A::test; + // void test(const char*); + // void test(int); + // }; + // + // int main() { + // B c; + // } + public void testUsingDeclarationInDerivedClass_bug414279() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // struct N { + // int node; + // }; + // + // template <typename T> + // struct List { + // template <int T::*> + // struct Base {}; + // }; + // + // List<N>::Base<&N::node> base; + public void testUnsafeMethodCallException_bug416284() throws Exception { + // Just check that codan runs without any exceptions being thrown. + loadCodeAndRun(getAboveComment()); + } + + // template <int I> + // struct S : S<I - 1> {}; + // + // S<1> waldo; + public void testMaxInstantiationDepth_430282() throws Exception { + // Just check that codan runs without any exceptions being thrown. + loadCodeAndRun(getAboveComment()); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/AssignmentInConditionCheckerTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/AssignmentInConditionCheckerTest.java new file mode 100644 index 00000000000..aa1d42f4404 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/AssignmentInConditionCheckerTest.java @@ -0,0 +1,143 @@ +/******************************************************************************* + * Copyright (c) 2009, 2016 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; +import org.eclipse.cdt.codan.internal.core.model.CodanProblemMarker; +import org.eclipse.core.resources.IMarker; + +/** + * Test for {@see AssignmentInConditionChecker} class + */ +public class AssignmentInConditionCheckerTest extends CheckerTestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems("org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem"); + } + + // main() { + // int a=1,b=3; + // if (a=b) b=4; // error here on line 3 + // } + public void test_basic() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + } + + // main() { + // int a=1,b=3; + // + // if ((a=b)) b--; // no error + // } + public void test_fixed() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // main() { + // int a=1,b=3; + // if ((a=b)!=0) b=4; // no error here on line 3 + // } + public void test3() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // main() { + // int i,a[10]; + // if (a[i]=0) b=4; // no error here on line 3 + // } + public void test_array() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + } + + // main() { + // int i,b=3; + // for (i = 0; i=b; i++) { // here + // } + // } + public void test_for() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + } + + // main() { + // int i,b=3; + // while (i=b) { // here + // } + // } + public void test_while() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + } + + // main() { + // int i,b=3; + // (i=b)?i++:b++; // here + // } + public void test_tri() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + } + + // main() { + // int a=1,b=3; + // if (a=b) b=4; // error here on line 3 + // } + public void test_basic_params() throws Exception { + loadCodeAndRun(getAboveComment()); + IMarker marker = checkErrorLine(3); + String arg = CodanProblemMarker.getProblemArgument(marker, 0); + assertEquals("a=b", arg); //$NON-NLS-1$ + } + + // main() { + // int i; + // while (i=b()) { // @suppress("Assignment in condition") + // } + // } + public void test_while2supp() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // main() { + // int i; + // while (i=b()) { /* @suppress("Assignment in condition") */ + // } + // } + public void test_while3supp() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // #define LOOP() while (i=b() /* @suppress("Assignment in condition") */ ) { } + // main() { + // int i; + // LOOP(); + // } + public void test_whileMacroSupp() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(4); // TODO: suppression does not work in macro body now + } + + // #define LOOP() while (i=b()) { } + // main() { + // int i; + // LOOP(); // err + // } + public void test_whileMacro() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(4); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/AssignmentToItselfCheckerTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/AssignmentToItselfCheckerTest.java new file mode 100644 index 00000000000..869969c319c --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/AssignmentToItselfCheckerTest.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2010 Severin Gehwolf + * 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: + * Severin Gehwolf - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; +import org.eclipse.core.resources.IMarker; + +/** + * Test for {@see AssignmentToItselfChecker} class + */ +public class AssignmentToItselfCheckerTest extends CheckerTestCase { + // void main() { + // int x = 0; + // x = 10; + // } + public void testNoErrorConstants() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // void main() { + // int x = 10; + // int s = 10; + // x = s; + // } + public void testNoErrorVariables() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // void main() { + // int x = 0; + // x = x; + // } + public void testSimpleVariableSelfAssignmentError() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + } + + // void main() { + // char str[] = "hello testing world"; + // int x = 10; + // str[i] = str[i]; + // } + public void testArraySelfAssignmentError() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(4); + } + + // #define X a = 1 + // void main() { + // int a; + // X; + // } + public void testNoError_Bug321933() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // void foo() { + // int x = 0; x + // = x; + // } + public void testMarkerOffset_Bug486610() throws Exception { + String code = getAboveComment(); + loadCodeAndRun(code); + IMarker marker = checkErrorLine(2); + int start = marker.getAttribute(IMarker.CHAR_START, -1); + int end = marker.getAttribute(IMarker.CHAR_END, -1); + // The offset should start at the beginning of the expression "x = x" + assertEquals("x\n = x", code.substring(start, end)); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/CaseBreakCheckerTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/CaseBreakCheckerTest.java new file mode 100644 index 00000000000..3f5f808b8fa --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/CaseBreakCheckerTest.java @@ -0,0 +1,580 @@ +/******************************************************************************* + * Copyright (c) 2010, 2015 Gil Barash + * 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: + * Gil Barash - Initial implementation + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import org.eclipse.cdt.codan.core.param.IProblemPreference; +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; +import org.eclipse.cdt.codan.internal.checkers.CaseBreakChecker; + +/** + * Test for {@link CaseBreakChecker} class + */ +public class CaseBreakCheckerTest extends CheckerTestCase { + public static final String ER_ID = CaseBreakChecker.ER_ID; + + @Override + public void setUp() throws Exception { + super.setUp(); + // Set default preferences. + setEmpty(false); + setLast(true); + } + + // void foo(void) { + // int a; + // switch (a) { + // case 1: + // } + // } + public void testEmptyLastCaseBad() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(4); + } + + // void foo(void) { + // int a; + // switch (a) { + // default: + // } + // } + public void testEmptyLastCaseDefaultBad() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(4); + } + + // void foo(void) { + // int a, b; + // switch (a) { + // case 1: + // b = 2; + // } + // } + public void testLastCaseBad() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(5); + } + + // void foo(void) { + // int a, b; + // switch (a) { + // case 1: + // case 2: + // b = 2; + // break; + // } + // } + public void testEmptyCaseBad() throws Exception { + setEmpty(true); + loadCodeAndRun(getAboveComment()); + checkErrorLines(4); + } + + // void foo(void) { + // int a; + // switch (a) { + // case 1: + // break; + // } + // } + public void testEmptyLastCaseOKbreak() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrorsOfKind(ER_ID); + } + + // void foo(void) { + // int a; + // switch (a) { + // case 1: + // return; + // } + // } + public void testEmptyLastCaseWithReturn() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrorsOfKind(ER_ID); + } + + // void foo(int a) { + // while (a--) + // switch (a) { + // case 1: + // continue; + // } + // } + public void testEmptyLastCaseWithContinue() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrorsOfKind(ER_ID); + } + + // void foo(int a) { + // + // switch (a) { + // case 1: + // throw 1; + // } + // } + public void testEmptyLastCaseWithThrow() throws Exception { + loadCodeAndRunCpp(getAboveComment()); + checkNoErrorsOfKind(ER_ID); + } + + // void foo(void) { + // int a, b; + // switch (a) { + // case 1: + // b = 2; + // break; + // } + // } + public void testLastCaseOKbreak() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrorsOfKind(ER_ID); + } + + // void foo(void) { + // int a, b; + // switch (a) { + // case 1: + // break; + // case 2: + // b = 2; + // break; + // } + // } + public void testEmptyCaseOKbreak() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrorsOfKind(ER_ID); + } + + // void foo(void) { + // int a; + // switch (a) { + // case 1: + // /* no break */ + // } + // } + public void testEmptyLastCaseOKcomment() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrorsOfKind(ER_ID); + } + + // void foo(int a, int b) { + // switch (a) { + // case 1: + // switch (b) { + // case 2: + // break; + // } + // case 2: + // break; + // } + // } + public void testEmptyLastCaseTwoSwitches() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(7); + } + + // void foo(void) { + // int a, b; + // switch (a) { + // case 1: + // b = 2; + // /* no break */ + // } + // } + public void testLastCaseOKcomment() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrorsOfKind(ER_ID); + } + + // void foo(void) { + // int a, b; + // switch (a) { + // case 1: + // /* no break */ + // case 2: + // b = 2; + // break; + // } + public void testEmptyCaseOKcomment() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrorsOfKind(ER_ID); + } + + // void foo(void) { + // int a, b; + // switch (a) { + // case 1: + // b = 2; + // /* no break */ + // bye(); + // } + // } + public void testLastCaseBadCommentNotLast() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(7); + } + + // void foo(void) { + // int a, b; + // switch (a) { + // case 1: + // b = 2; + // /* no break */ + // case 2: + // b = 2; + // /*no break*/ + // case 3: + // b = 2; + // //no break + // case 4: + // b = 2; + // // no break + // case 5: + // b = 2; + // /* no brea */ + // case 6: + // b = 2; + // /* no break1 */ + // case 7: + // b = 2; + // /* fallthrough */ + // } + // } + public void testDifferentComments() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(17,23); + } + + // void foo(void) { + // int a, b; + // switch (a) { + // case 1: //err + // // lolo + // case 2: //err + // case 3://err + // } + // + // switch (a) { + // case 1: + // b = 2; // err + // // lolo + // case 2: + // b = 2; // err + // case 3: // err + // case 4: + // break; + // case 5: // err + // case 6: // err + // } + // + // switch (a) { + // case 1: + // b = 2; // err + // // lolo + // case 2: + // b = 2; //err + // case 3: + // b = 2; + // /* no break */ + // case 4: + // b = 2; // err + // case 5: + // b = 2; + // break; + // case 6: + // b = 2; + // /* no break */ + // b = 2; //err + // case 7: + // b = 2;//err + // } + // + // switch (a) { + // case 1: + // b = 2; // err + // // lolo + // case 2: + // b = 2; // err + // default: //err + // } + // } + public void testGeneral1() throws Exception { + setEmpty(true); + setLast(true); + loadCodeAndRun(getAboveComment()); + checkErrorComments(); + } + + // void foo(void) { + // int a, b; + // switch (a) { + // case 1: + // b = 2; + // // lolo + // /* no break */ + // case 2: + // b = 2; + // /* no break */ + // // lolo + // case 3: + // /* no break */ + // b = 2; + // // loo + // case 4: + // b = 2; + // // lolo + // /* no break */ + // case 5: + // // lolo + // b = 2; + // /* no break */ + // } + // } + public void testGeneralComments1() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(9, 14); + } + + // void foo(void) { + // int a, b; + // switch (a) { + // case 0: + // switch( b ) { + // case 2: // err + // } // err + // + // case 1: + // switch( b ) { + // case 2: + // break; + // } // err + // case 3: + // switch( b ) { + // case 2: + // break; + // } + // break; + // case 4: + // switch( b ) { + // case 2: + // /* no break */ + // } // err + // case 5: + // switch( b ) { + // case 2: // err + // } + // /* no break */ + // } + // } + public void testNestedSwitches() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorComments(); + } + + // void foo(void) { + // int a, b; + // switch (a) { + // case 1: + // b = 2; + // } + // } + public void testLastCaseIgnore() throws Exception { + setLast(false); + loadCodeAndRun(getAboveComment()); + checkNoErrorsOfKind(ER_ID); + setLast(true); + } + + // void foo(void) { + // int a, b; + // switch (a) { + // case 1: + // case 2: + // b = 2; + // break; + // case 3: case 4: + // b = 2; + // break; + // } + // } + public void testEmptyCaseIgnore() throws Exception { + setEmpty(false); + loadCodeAndRun(getAboveComment()); + checkNoErrorsOfKind(ER_ID); + } + + // void foo(void) { + // int a; + // switch (a) { + // case 1: + // } + // } + public void testEmptyLastCaseIgnore() throws Exception { + String code = getAboveComment(); + setLast(false); + loadCodeAndRun(code); + checkNoErrorsOfKind(ER_ID); + setLast(true); + setEmpty(false); + loadCodeAndRun(code); + checkErrorLine(4, ER_ID); + } + + private void setLast(boolean val) { + IProblemPreference pref = getPreference(CaseBreakChecker.ER_ID, CaseBreakChecker.PARAM_LAST_CASE); + pref.setValue(val); + } + + private void setEmpty(boolean val) { + IProblemPreference pref = getPreference(CaseBreakChecker.ER_ID, CaseBreakChecker.PARAM_EMPTY_CASE); + pref.setValue(val); + } + + // void foo(int a) { + // switch (a) { + // case 1: + // while (a--) + // break; // err + // case 2: + // while (a--) { + // break; + // } // err + // } + // } + public void testEmptyCaseWithLoopBreak() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorComments(); + } + + // void foo(int a) { + // switch (a) { + // case 1: { + // break; + // } + // case 2: { + // a--; + // break; + // } + // } + // } + public void testCaseWithCurlyBrackets() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrorsOfKind(ER_ID); + } + + // void foo(void) { + // int a; + // switch (a) { + // case 2: + // break; + // case 1: + // } + // } + public void testEmptyLastCaseError() throws Exception { + String code = getAboveComment(); + setLast(true); + setEmpty(false); + loadCodeAndRun(code); + checkErrorLine(6, ER_ID); + setLast(false); + loadCodeAndRun(code); + checkNoErrorsOfKind(ER_ID); + } + + // void foo(int a) { + // switch (a) { + // case 2: + // if (a*2<10) + // return; + // else + // break; + // case 1: + // break; + // } + // } + public void testIf() throws Exception { + String code = getAboveComment(); + loadCodeAndRun(code); + checkNoErrorsOfKind(ER_ID); + } + + // void foo(int a) { + // switch(a) { + // case 2: + // if (a*2<10) + // return; + // else + // a++; + // case 1: + // break; + // } + // } + public void testIfErr() throws Exception { + String code = getAboveComment(); + loadCodeAndRun(code); + checkErrorLine(7, ER_ID); + } + + // #define DEFINE_BREAK {break;} + // void foo(int a) { + // switch (a) { + // case 1: + // DEFINE_BREAK // No warning here + // } + // } + public void testBreakInBraces() throws Exception { + String code = getAboveComment(); + loadCodeAndRun(code); + checkNoErrorsOfKind(ER_ID); + } + + // #define MY_MACRO(i) \ + // case i: { \ + // } + // + // void f() { + // int x; + // switch (x) { + // MY_MACRO(1) // No warning here + // } + // } + public void testInMacro() throws Exception { + String code = getAboveComment(); + loadCodeAndRun(code); + checkNoErrorsOfKind(ER_ID); + } + + // void foo() { + // switch (0) + // default: { + // } + // } + public void testEmptyCompoundStatement() throws Exception { + String code = getAboveComment(); + loadCodeAndRun(code); + checkErrorLine(4, ER_ID); + } + + // void foo() { + // switch (0) { + // case 0: + // return 42;; + // case 1: + // break; + // } + // } + public void testDoubleSemicolon_bug441714() throws Exception { + String code = getAboveComment(); + loadCodeAndRun(code); + checkNoErrorsOfKind(ER_ID); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/CatchByReferenceTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/CatchByReferenceTest.java new file mode 100644 index 00000000000..30fe974c204 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/CatchByReferenceTest.java @@ -0,0 +1,139 @@ +/******************************************************************************* + * Copyright (c) 2009, 2011 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; +import org.eclipse.cdt.codan.internal.checkers.CatchByReference; + +/** + * Test for {@see CatchByReference} class + */ +public class CatchByReferenceTest extends CheckerTestCase { + @Override + public boolean isCpp() { + return true; + } + + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems(CatchByReference.ER_ID); + } + + // void main() { + // try { + // foo(); + // } catch (int e) { + // } + // } + public void test_int() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class C {}; + // void main() { + // try { + // foo(); + // } catch (C e) { + // } + // } + public void test_class() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(5); + } + + // class C {}; + // void main() { + // try { + // foo(); + // } catch (C & e) { + // } + // } + public void test_class_ref() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class C {}; + // void main() { + // try { + // foo(); + // } catch (C * e) { + // } + // } + public void test_class_point() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // typedef int A; + // void main() { + // try { + // foo(); + // } catch (A e) { + // } + // } + public void test_int_typedef() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // typedef int A; + // typedef A B; + // void main() { + // try { + // foo(); + // } catch (B e) { + // } + // } + public void test_int_typedef2() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // void main() { + // try { + // foo(); + // } catch (C e) { + // } + // } + public void test_class_unknown() throws Exception { + setPreferenceValue(CatchByReference.ER_ID, CatchByReference.PARAM_UNKNOWN_TYPE, false); + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // void main() { + // try { + // foo(); + // } catch (C e) { + // } + // } + public void test_class_unknown_on() throws Exception { + setPreferenceValue(CatchByReference.ER_ID, CatchByReference.PARAM_UNKNOWN_TYPE, true); + loadCodeAndRun(getAboveComment()); + checkErrorLine(4); + } + + // class C {}; + // typedef C B; + // void main() { + // try { + // foo(); + // } catch (B e) { + // } + // } + public void test_class_typedef() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(6); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/ClassMembersInitializationCheckerTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/ClassMembersInitializationCheckerTest.java new file mode 100644 index 00000000000..5cd0fa13aa1 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/ClassMembersInitializationCheckerTest.java @@ -0,0 +1,650 @@ +/******************************************************************************* + * Copyright (c) 2011, 2013 Anton Gorenkov and others + * 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: + * Anton Gorenkov - initial implementation + * Marc-Andre Laperle + * Nathan Ridge + * Danny Ferreira + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; +import org.eclipse.cdt.codan.internal.checkers.ClassMembersInitializationChecker; + +/** + * Test for {@see ClassMembersInitializationChecker} class + */ +public class ClassMembersInitializationCheckerTest extends CheckerTestCase { + @Override + public boolean isCpp() { + return true; + } + + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems(ClassMembersInitializationChecker.ER_ID); + } + + private void disableSkipConstructorsWithFCalls() { + setPreferenceValue(ClassMembersInitializationChecker.ER_ID, ClassMembersInitializationChecker.PARAM_SKIP, false); + } + + public void checkMultiErrorsOnLine(int line, int count) { + for (int i = 0; i < count; ++i) { + checkErrorLine(line); + } + assertEquals(count, markers.length); + } + + // class C { + // int m; + // C() : m(0) {} // No warnings. + // }; + public void testInitializationListShouldBeChecked() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class C { + // int m; + // C() { m = 0; } // No warnings. + // }; + public void testAssignmentsInConstructorShouldBeChecked() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class C { + // int m; + // unsigned int ui; + // float f; + // double d; + // bool b; + // char c; + // long l; + // C() {} // 7 warnings for: m, ui, f, d, b, c, l. + // }; + public void testBasicTypesShouldBeInitialized() throws Exception { + loadCodeAndRun(getAboveComment()); + checkMultiErrorsOnLine(9, 7); + } + + // class Value {}; + // class C { + // int* i; + // Value* v; + // C() {} // 2 warnings for: i, v. + // } + public void testPointersShouldBeInitialized() throws Exception { + loadCodeAndRun(getAboveComment()); + checkMultiErrorsOnLine(5, 2); + } + + // class Value {}; + // class C { + // int& i; + // Value& v; + // C() {} // 2 warnings for: i, v. + // } + public void testReferencesShouldBeInitialized() throws Exception { + loadCodeAndRun(getAboveComment()); + checkMultiErrorsOnLine(5, 2); + } + + // enum Enum { v1, v2 }; + // class C { + // Enum e; + // C() {} // 1 warning for: e. + // } + public void testEnumsShouldBeInitialized() throws Exception { + loadCodeAndRun(getAboveComment()); + checkMultiErrorsOnLine(4, 1); + } + + // enum Enum { v1, v2 }; + // class Value {}; + // typedef int IntTypedef; + // typedef int* IntPtrTypedef; + // typedef int& IntRefTypedef; + // typedef Enum EnumTypedef; + // typedef Value ValueTypedef; + // class C { + // IntTypedef i; + // IntPtrTypedef ip; + // IntRefTypedef ir; + // EnumTypedef e; + // ValueTypedef v; + // C() {} // 5 warnings for: i, ip, ir, e. + // } + public void testTypedefsShouldBeInitialized() throws Exception { + loadCodeAndRun(getAboveComment()); + checkMultiErrorsOnLine(14, 4); + } + + // class C { + // C() : i1(0) {} // 1 warning for: i2. + // C(int) : i2(0) {} // 1 warning for: i1. + // int i1, i2; + // }; + public void testAFewConstructorsHandling() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(2, 3); + } + + // template <typename T1, typename T2> + // class C { + // C() : i1(0), t1(T1()) {} // 1 warning for: i2. + // int i1, i2; + // T1 t1; + // T2 t2; + // }; + public void testTemplateClassHandling() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(3); + } + + // class C { + // template <typename T> + // C() : i1(0) {} // 1 warning for: i2. + // int i1, i2; + // }; + public void testTemplateConstructorHandling() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(3); + } + + // class C { + // C(); // No warnings. + // int i; + // }; + public void testTemplateConstructorDeclarationOnlyHandling() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class C { + // C(); + // int i1, i2; + // }; + // C::C() : i1(0) {} // 1 warning for: i2. + public void testExternalConstructorHandling() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(5); + } + + // template <typename T1, typename T2> + // class C { + // C(); + // int i1, i2; + // T1 t1; + // T2 t2; + // }; + // template <typename T1, typename T2> + // C<T1,T2>::C() : i1(0), t1(T1()) {} // 1 warning for: i2. + public void testExternalConstructorOfTemplateClassHandling() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(9); + } + + // class C { + // template <typename T> + // C(); + // int i1, i2; + // }; + // template <typename T> + // C::C() : i1(0) {} // 1 warning for: i2. + public void testExternalTemplateConstructorHandling() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(7); + } + + // template <typename T1, typename T2> + // class C { + // template <typename T> + // C(); + // int i1, i2; + // T1 t1; + // T2 t2; + // }; + // template <typename T1, typename T2> + // template <typename T> + // C<T1,T2>::C() : i1(0), t1(T1()) {} // 1 warning for: i2. + public void testExternalTemplateConstructorOfTemplateClassHandling() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(11); + } + + // class C { + // class NestedC { + // NestedC() : i(0) {} // No warnings. + // int i; + // }; + // C() {} // 1 warning for: i. + // int i; + // }; + public void testNestedClassesHandling() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(6); + } + + // class C { + // C() // 1 warning for: i. + // { + // class NestedC { + // NestedC() { i = 0; } // No warnings. + // int i; + // }; + // } + // int i; + // }; + public void testNestedClassInConstructorHandling() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(2); + } + + // class C { + // C(); + // int i; + // }; + // + // C::C() // 1 warning for: i. + // { + // class NestedC { // No warnings. + // NestedC() { i = 0; } + // int i; + // }; + // } + public void testNestedClassInExternalConstructorHandling() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(6); + } + + // class C { + // C() // 1 warning for: i. + // { + // class NestedC { + // NestedC() { i = 0; } // No warnings. + // void C() { i = 0; } // No warnings. + // int i; + // }; + // } + // int i; + // }; + public void testNestedClassWithMethodNamedAsAnotherClassHandling() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(2); + } + + // class C { + // C() {} // 1 warning for: i. + // int someFunction() { i = 0; } // No warnings. + // int i; + // }; + public void testAssignmentIsNotInConstructor() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(2); + } + + // class CBase { + // CBase() : i1(0) {} // No warnings. + // int i1; + // }; + // class CDerived : public CBase { + // CDerived() : i2(0) {} // No warnings. + // int i2; + // }; + public void testBaseClassMemberShouldNotBeTakenIntoAccount() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class C { + // C() {} // No warnings. + // static int i1, i2; + // }; + // int C::i1 = 0; + // // NOTE: Static members are always initialized with 0, so there should not be warning on C::i2 + // int C::i2; + public void testNoErrorsOnStaticMembers() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class C { + // public: + // C(const C& c) = delete; + // int i1, i2; + // }; + public void testNoErrorsOnDeletedConstructor() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // void func(int & a) { a = 0; } + // class C { + // C() { func(i); } // No warnings. + // int i; + // }; + public void testNoErrorsOnFunctionCallInitialization() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // void func(const int & a) {} + // class C { + // C() { func(i); } // 1 warning for: i. + // int i; + // }; + public void testNoErrorsOnReadingFunctionCall() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(3); + } + + // class C { + // C() { (i1) = 0; *&i2 = 0; } // No warnings. + // int i1, i2; + // }; + public void testNoErrorsOnComplexAssignment() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class C { + // C() : i1(0) { // No warnings. + // i2 = i1; + // int someVar = 0; + // i3 = someVar; + // } + // int i1, i2, i3; + // }; + public void testNoErrorsOnChainInitialization() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class A { protected: A(){} public: int a; }; // 1 warning for: a. + // class C: public A { + // C() { + // a = 1; + // } + // }; + public void testErrorOnProtectedConstructor() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(1); + } + + // struct S { + // int i; + // S() {} // 1 warning for: i. + // }; + public void testCheckStructs() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(3); + } + + // union U { + // int a; + // char b; + // U() { // No warnings. + // a=0; + // } + // }; + public void testSkipUnions() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class C { + // int c; + // }; + public void testNoErrorsIfThereIsNoConstructorsDefined() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class C { + // int i; + // C(bool b) { // No warnings. + // if (b) + // i = 0; + // // else - 'i' will be not initialized + // } + // }; + public void testNoErrorsIfMemberWasInitializedInOneOfTheIfBranch() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class A { + // int a; + // A(int a) { setA(a); } // No warnings. + // A() { getA(); } // 1 warning for: a. + // void setA(int a) { + // this->a = a; + // } + // int getA() const { + // return a; + // } + // }; + public void testUsingMethodsInConstructorWithPreference() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(4); + } + + // class A; + // void initializeA1(A*); + // void initializeA2(A**); + // void initializeA3(A&); + // + // class A { + // int a; + // A() { initializeA1(this); } // No warnings. + // A(int a) { initializeA2(&this); } // No warnings. + // A(float a) { initializeA3(*this); } // No warnings. + // A(double a) { initializeA3(*(this)); } // No warnings. + // }; + public void testUsingConstMethodsInConstructorWithPreference() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + + // class A { + // int a; + // A(int a) { setA(a); } // 1 warning for: a. + // A() { getA(); } // 1 warning for: a. + // void setA(int a) { + // this->a = a; + // } + // int getA() const { + // return a; + // } + // }; + public void testUsingMethodsInConstructorWithoutPreference() throws Exception { + disableSkipConstructorsWithFCalls(); + loadCodeAndRun(getAboveComment()); + checkErrorLines(3,4); + } + + // class A; + // void initializeA1(A*); + // void initializeA2(A**); + // void initializeA3(A&); + // + // class A { + // int a; + // A() { initializeA1(this); } // 1 warning for: a. + // A(int a) { initializeA2(&this); } // 1 warning for: a. + // A(float a) { initializeA3(*this); } // 1 warning for: a. + // A(double a) { initializeA3(*(this)); } // 1 warning for: a. + // }; + public void testUsingConstMethodsInConstructorWithoutPreference() throws Exception { + disableSkipConstructorsWithFCalls(); + loadCodeAndRun(getAboveComment()); + checkErrorLines(8,9,10,11); + } + + // @file:test.h + // class C { + // int field; + // C(); + // void initObject(); + //}; + + // @file:test.cpp + // #include "test.h" + // C::C() { + // initObject(); + // } + public void testMethodDeclarationInOtherFile_368419() throws Exception { + CharSequence[] code = getContents(2); + loadcode(code[0].toString()); + loadcode(code[1].toString()); + runOnProject(); + checkNoErrors(); + } + + //class D { + // int field; + // D(const D& toBeCopied) { + // *this = toBeCopied; + // }; + //}; + public void testAssignThis_368420() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + //class D { + // int field; + // D(const D& toBeCopied) { + // *(&(*this)) = toBeCopied; + // }; + //}; + public void testAssignThisUnaryExpressions_368420() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + //class D { + // int field; + // D(const D& toBeCopied) { + // this = toBeCopied; + // }; + //}; + public void testAssignThisNonLValue_368420() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(3); + } + + //class D { + // int field; + // D(); + // D(const D& toBeCopied) { + // D temp; + // temp = *(&(*this)) = toBeCopied; + // }; + //}; + public void testAssignThisMultiBinaryExpressions_368420() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + //@file:test.h + //template <typename> + //struct B; + + //@file:test.cpp + //#include "test.h" + // + //template <typename> + //struct A { + //}; + // + //template <typename valueT> + //struct B<A<valueT> > { + // const A<valueT>& obj; + // B(const A<valueT>& o) : obj(o) {} + //}; + public void testTemplatePartialSpecialization_368611() throws Exception { + CharSequence[] code = getContents(2); + loadcode(code[0].toString()); + loadcode(code[1].toString()); + runOnProject(); + checkNoErrors(); + } + + // struct S { + // int i; + // S() = default; + // }; + public void testDefaultConstructor_365498() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + } + + // struct S { + // int i; + // + // S(S&) = default; + // S(const S&) = default; + // S(volatile S&) = default; + // S(const volatile S&) = default; + // S(S&&) = default; + // S(const S&&) = default; + // S(volatile S&&) = default; + // S(const volatile S&&) = default; + // }; + public void testDefaultCopyOrMoveConstructor_395018() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // template <typename T> + // struct S { + // int i; + // + // S(const S&) = default; + // S(S&&) = default; + // }; + public void testDefaultCopyOrMoveConstructorInTemplate_408303() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // struct A { + // A(int n) : waldo(n) {} + // A() : A(42) {} + // int waldo; + // }; + public void testDelegatingConstructor_402607() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // struct A { + // typedef A B; + // A(int n) : waldo(n) {} + // A() : B(42) {} + // int waldo; + // }; + public void testDelegatingConstructorTypedef_402607() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // struct A { + // A() {}; + // int x = 0; + // }; + public void testNonstaticDataMemberInitializer_400673() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/CommentCheckerLineTests.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/CommentCheckerLineTests.java new file mode 100644 index 00000000000..59e438128b9 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/CommentCheckerLineTests.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2015 QNX Software System and others. + * 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: + * Elena Laskavaia (QNX Software System) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import java.io.File; + +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; +import org.eclipse.cdt.codan.internal.checkers.CommentChecker; +import org.junit.Test; + +/** + * Tests for CommentChecker + */ +public class CommentCheckerLineTests extends CheckerTestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems(CommentChecker.COMMENT_NO_LINE); + } + + // void foo() { + // return; // error + // } + @Test + public void testLineComment() throws Exception { + checkSampleAbove(); + } + + // void foo() { + // return; + // } + @Test + public void testNoLineComment() throws Exception { + checkSampleAbove(); + } + + // char * foo() { + // return "// this is a string"; + // } + @Test + public void testNoLineCommentInString() throws Exception { + checkSampleAbove(); + } + + // void foo() { + // return; // not an error in c++ + // } + @Test + public void testLineCommentCpp() throws Exception { + checkSampleAboveCpp(); + } + + // #define AAA // error even in prepro + @Test + public void testLineCommentInPrepro() throws Exception { + checkSampleAbove(); + } + + // @file:test.h + // int foo();// error too + + + // @file:test.c + // #include "test.h" + // int bar() { + // foo(); + // } + public void testHeader() throws Exception { + loadcode(getContents(2)); + runOnProject(); + checkErrorLine(new File("test.h"), 1); //$NON-NLS-1$ + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/CommentCheckerNestedTests.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/CommentCheckerNestedTests.java new file mode 100644 index 00000000000..ea95da3d0f0 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/CommentCheckerNestedTests.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2015 QNX Software System and others. + * 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: + * Elena Laskavaia (QNX Software System) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; +import org.eclipse.cdt.codan.internal.checkers.CommentChecker; +import org.junit.Test; + +/** + * Tests for CommentChecker + */ +public class CommentCheckerNestedTests extends CheckerTestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems(CommentChecker.COMMENT_NO_START); + } + + // void foo() { + // return; /* /* */ // error + // } + @Test + public void testLineComment() throws Exception { + checkSampleAbove(); + } + // void foo() { + // return; /* + // /* // error + // */ + // } + @Test + public void testLineComment2() throws Exception { + checkSampleAbove(); + } + + // void foo() { + // return; /* */ + // } + @Test + public void testNoLineComment() throws Exception { + checkSampleAbove(); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/FormatStringCheckerTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/FormatStringCheckerTest.java new file mode 100644 index 00000000000..e4e13476dc2 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/FormatStringCheckerTest.java @@ -0,0 +1,266 @@ +/******************************************************************************* + * Copyright (c) 2010, 2011 Meisam Fathi and others + * 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: + * Meisam Fathi - base API + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; + +/** + * Test for {@see FormatStringChecker} class + */ +public class FormatStringCheckerTest extends CheckerTestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems("org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem"); //$NON-NLS-1$ + } + + // int f(){ + // return 0; + // } + public void testBase() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // int f(){ + // char inputstr[5]; + // scanf("%s", inputstr); // here + // return 0; + // } + public void testSimple() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + } + + // int main(void) { + // char inputstr1[5]; + // int inputval; + // int i = 5; + // scanf("%i %4s", inputval, inputstr1); // no error here + // printf("%d" ,i); + // return 0; + // } + public void testIntRight() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // int main(void) { + // char inputstr[5]; + // int inputval; + // int i = 5; + // scanf("%d %9s", inputval, inputstr); + // printf("%d" ,i); + // return 0; + // } + public void testIntWrong() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(5); + } + + // int main(void) { + // char inputstr1[5]; + // int inputval; + // int i = 5; + // scanf("%4s %i", inputstr1, inputval); + // printf("%d" ,i); + // return 0; + // } + public void testRightInt() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // int main(void) { + // char inputstr1[5]; + // char inputstr2[5]; + // int i = 5; + // scanf("%4s %9s", inputstr1, inputstr2); + // printf("%d" ,i); + // return 0; + // } + public void testRightWrong() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(5); + } + + // int main(void) { + // char inputstr1[5]; + // int inputval; + // int i = 5; + // scanf("%9s %i", inputstr1, inputval); + // printf("%d" ,i); + // return 0; + // } + public void testWrongInt() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(5); + } + + // int main(void) { + // char inputstr1[5]; + // char inputstr2[5]; + // int i = 5; + // scanf("%9s %4s", inputstr1, inputstr2); + // printf("%d" ,i); + // return 0; + // } + public void testWrongRight() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(5); + } + + // int main(void) { + // char inputstr[5]; + // int i = 5; + // scanf("%s", inputstr); + // printf("%d" ,i); + // return 0; + // } + public void testInfiniteSize() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(4); + } + + // int main(void) { + // puts("Enter a string whose length is bellow 5:"); + // char inputstr[5]; + // int i = 5; + // scanf("%3s", inputstr); + // printf("%d" ,i); + // return 0; + // } + public void testRight() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // int main(void) { + // char inputstr1[5]; + // char inputstr2[5]; + // int i = 5; + // scanf("%3s %4s", inputstr1, inputstr2); + // printf("%d" ,i); + // return 0; + // } + public void testRightRight() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // int main(void) { + // char inputstr1[5]; + // char inputstr2[5]; + // int i = 5; + // scanf("%8s %9s", inputstr1, inputstr2); + // printf("%d" ,i); + // return 0; + // } + public void testWrongWrong() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(5); + } + + // char inputstr[5]; + // int foo(void){ + // char inputstr[15]; + // return 0; + // } + // int main(void) { + // puts("Enter a string whose length is bellow 5:"); + // int i = 5; + // scanf("%10s", inputstr); + // printf("%d" ,i); + // return 0; + // } + public void testGlobalBeforeWrong() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(9); + } + + // int main(void) { + // puts("Enter a string whose length is bellow 5:"); + // char inputstr[15]; + // int i = 5; + // scanf("%10s", inputstr); + // printf("%d" ,i); + // return 0; + // } + // int foo(void){ + // char inputstr[5]; + // return 0; + // } + public void testNonglobalAfterRight() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // int main(void) { + // char inputstr[5]; + // int i = 5; + // scanf("%10s", inputstr); + // printf("%d" ,i); + // return EXIT_SUCCESS; + // } + // int foo(void){ + // char inputstr[15]; + // return 0; + // } + public void testNonglobalAfterWrong() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(4); + } + + // int foo(void){ + // char inputstr[5]; + // return 0; + // } + // int main(void) { + // char inputstr[15]; + // int i = 5; + // scanf("%10s", inputstr); + // printf("%d" ,i); + // return 0; + // } + public void testNonglobalBeforeRight() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // int foo(void){ + // char inputstr[15]; + // return 0; + // } + // int main(void) { + // char inputstr[5]; + // int i = 5; + // scanf("%10s", inputstr); + // printf("%d" ,i); + // return 0; + // } + public void testNonglobalBeforeWrong() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(8); + } + + // int main(void) { + // char inputstr1[5]; + // int inputval; + // int i = 5; + // scanf("%i %as", inputval, inputstr1); // no error here + // printf("%d" ,i); + // return 0; + // } + public void testGaurdedRight() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } +}
\ No newline at end of file diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/NonVirtualDestructorCheckerTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/NonVirtualDestructorCheckerTest.java new file mode 100644 index 00000000000..6949d3f09a4 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/NonVirtualDestructorCheckerTest.java @@ -0,0 +1,221 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 Patrick Hofer and others. + * 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: + * Patrick Hofer - Initial API and implementation + * Tomasz Wesolowski + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; +import org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructor; +import org.eclipse.core.resources.IMarker; + +/** + * Test for {@link NonVirtualDestructor} class. + */ +public class NonVirtualDestructorCheckerTest extends CheckerTestCase { + @Override + public boolean isCpp() { + return true; + } + + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems(NonVirtualDestructor.PROBLEM_ID); + } + + // struct A { + // virtual void f() = 0; + // virtual ~A(); // ok. + // }; + public void testVirtualDtorInClass() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // struct A { + // virtual void f() = 0; + // protected: + // ~A(); // ok. + // }; + public void testNonPublicVirtualDtorInClass() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // struct A { + // virtual void f() { }; + // ~A(); // warn! public non-virtual dtor. + // }; + public void testPublicVirtualDtorInClass() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(3); + } + + // struct A { + // virtual void f() { }; + // // warn! implicit public non-virtual dtor. + // }; + public void testImplicitPublicNonVirtualDtorInClass() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(1); + } + + // struct F { }; + // + // struct A { + // virtual void f() { }; + // private: + // friend class F; + // ~A(); // warn! can be called from class F. + // }; + public void testPublicNonVirtualDtorCanBeCalledFromFriendClass() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(7); + } + + // struct A { + // virtual void f() { }; + // virtual ~A(); + // }; + // + // struct B { + // ~B(); // ok. + // }; + public void testVirtualDtorInBaseClass1() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // struct A { + // virtual void f() { }; + // virtual ~A(); // ok. + // }; + // + // struct B : public A { }; + // + // struct C { }; + // + // struct D : public B, C { }; + // + // struct E : public D { }; + public void testVirtualDtorInBaseClass2() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class A { + // public: + // virtual ~A(); + // }; + // + // class B : public A { + // public: + // ~B(); + // virtual void m(); + // friend class C; + // }; + public void testVirtualDtorInBaseClass3() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // struct A { + // virtual void f() { }; + // ~A(); // warn! public non-virtual dtor. + // // this affects B, D and E further down in the hierarchy as well + // }; + // + // struct B : public A { }; + // + // struct C { }; + // + // struct D : public B, C { }; + // + // struct E : public D { + // }; + public void testNonVirtualDtorInBaseClass() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(3, 7, 11, 13); + } + + // class A { + // virtual void f1() { }; + // virtual void f2() = 0; + // }; + // + // class B : public A { + // virtual void f1() { }; + // virtual void f2() { }; + // virtual ~B(); + // }; + public void testAbstractBaseClass() throws Exception { + loadCodeAndRun(getAboveComment()); + // It doesn't matter if the class is abstract or not - dtor can be called polymorphically. + checkErrorLines(1); + } + + // struct Base { + // }; + // struct Derived : Base { + // virtual void bar(); + // }; + public void testImplicitDtorInBaseClass() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(3); + } + + // struct Base { + // ~Base(); + // }; + // struct Derived : Base { + // virtual void bar(); + // }; + public void testExplicitDtorInBaseClass() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(4); + } + + // class C : public C {}; + public void testBug368446_stackOverflow() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class B; + // class A : public B {}; + // class B : public A {}; + public void testBug368446_stackOverflow_indirect() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // class Foo { + // virtual void bar(); + // }; + public void testBug372009_wrongClassNameInMessage() throws Exception { + loadCodeAndRun(getAboveComment()); + assertMessageContains("Foo", markers[0]); + } + + // class Foo { + // virtual void bar(); + // }; + public void testBug496628_MarkerBounds() throws Exception { + String code = getAboveComment(); + loadCodeAndRun(code); + IMarker marker = checkErrorLine(1); + int start = marker.getAttribute(IMarker.CHAR_START, -1); + int end = marker.getAttribute(IMarker.CHAR_END, -1); + // The error should not cover the entire class + assertTrue((start == -1 && end == -1) || // ok, not multi-line + !code.substring(start, end).contains("\n")); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/ProblemBindingCheckerTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/ProblemBindingCheckerTest.java new file mode 100644 index 00000000000..149785324d9 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/ProblemBindingCheckerTest.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2011, 2015 Marc-Andre Laperle and others. + * 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: + * Marc-Andre Laperle - Initial API and implementation + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; +import org.eclipse.cdt.codan.internal.checkers.ProblemBindingChecker; +import org.eclipse.core.resources.IMarker; + +public class ProblemBindingCheckerTest extends CheckerTestCase { + @Override + public boolean isCpp() { + return true; + } + + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems( + ProblemBindingChecker.ERR_ID_AmbiguousProblem, ProblemBindingChecker.ERR_ID_Candidates, + ProblemBindingChecker.ERR_ID_CircularReferenceProblem, ProblemBindingChecker.ERR_ID_FieldResolutionProblem, + ProblemBindingChecker.ERR_ID_FunctionResolutionProblem, ProblemBindingChecker.ERR_ID_InvalidArguments, + ProblemBindingChecker.ERR_ID_InvalidTemplateArgumentsProblem, ProblemBindingChecker.ERR_ID_LabelStatementNotFoundProblem, + ProblemBindingChecker.ERR_ID_MemberDeclarationNotFoundProblem, ProblemBindingChecker.ERR_ID_MethodResolutionProblem, + ProblemBindingChecker.ERR_ID_OverloadProblem, ProblemBindingChecker.ERR_ID_RedeclarationProblem, + ProblemBindingChecker.ERR_ID_RedefinitionProblem, ProblemBindingChecker.ERR_ID_TypeResolutionProblem, + ProblemBindingChecker.ERR_ID_VariableResolutionProblem); + } + + // int main () { + // struct X {} x; + // fun(x.y); + // } + public void testFieldInFunctionCall_338683() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3, ProblemBindingChecker.ERR_ID_FieldResolutionProblem); + } + + // struct A { + // A(int x, int y); + // }; + // + // void test() { + // A a("hi", 1, 2); + // } + public void testImplicitConstructorCall_404774() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(6, ProblemBindingChecker.ERR_ID_InvalidArguments); + } + + // int main () { + // struct X {} x; + // x.b( + // x.y(), + // x.y( + // x.y), + // x.y( + // x.y( + // a, + // fun( + // x.b(), + // x.y, + // a.b())))); + // } + public void testVariousFieldMethodCombinations_338683() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3, ProblemBindingChecker.ERR_ID_MethodResolutionProblem); + checkErrorLine(4, ProblemBindingChecker.ERR_ID_MethodResolutionProblem); + checkErrorLine(5, ProblemBindingChecker.ERR_ID_MethodResolutionProblem); + checkErrorLine(6, ProblemBindingChecker.ERR_ID_FieldResolutionProblem); + checkErrorLine(7, ProblemBindingChecker.ERR_ID_MethodResolutionProblem); + checkErrorLine(8, ProblemBindingChecker.ERR_ID_MethodResolutionProblem); + checkErrorLine(9, ProblemBindingChecker.ERR_ID_VariableResolutionProblem); + checkErrorLine(10, ProblemBindingChecker.ERR_ID_FunctionResolutionProblem); + checkErrorLine(11, ProblemBindingChecker.ERR_ID_MethodResolutionProblem); + checkErrorLine(12, ProblemBindingChecker.ERR_ID_FieldResolutionProblem); + checkErrorLine(13, ProblemBindingChecker.ERR_ID_MethodResolutionProblem); + } + + // #define MACRO(code) code + // int main() { + // MACRO(foo()); + // return 0; + // } + public void testDontUnderlineWholeMacro_341089() throws Exception { + loadCodeAndRun(getAboveComment()); + IMarker marker = checkErrorLine(3, ProblemBindingChecker.ERR_ID_FunctionResolutionProblem); + assertFalse(marker.getAttribute(IMarker.MESSAGE, "").contains("MACRO")); + } + + // auto d = 42_waldo; + public void testNonexistentUDLOperator_484619() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(1, ProblemBindingChecker.ERR_ID_FunctionResolutionProblem); + } + + // struct R {}; + // R operator "" _waldo(const char*, unsigned long); // expects a string literal + // auto d = 42_waldo; // passing an integer + public void testUDLOperatorWithWrongType_484619() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3, ProblemBindingChecker.ERR_ID_InvalidArguments); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/ReturnCheckerTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/ReturnCheckerTest.java new file mode 100644 index 00000000000..69715f65a74 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/ReturnCheckerTest.java @@ -0,0 +1,451 @@ +/******************************************************************************* + * Copyright (c) 2009, 2015 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + * Felipe Martinez - ReturnCheckerTest implementation + * Tomasz Wesolowski - Bug 348387 + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import org.eclipse.cdt.codan.core.param.IProblemPreference; +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; +import org.eclipse.cdt.codan.internal.checkers.ReturnChecker; + +/** + * Test for {@see ReturnCheckerTest} class + */ +public class ReturnCheckerTest extends CheckerTestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems(ReturnChecker.RET_NORET_ID,ReturnChecker.RET_ERR_VALUE_ID,ReturnChecker.RET_NO_VALUE_ID); + } + + // dummy() { + // return; // no error here on line 2 + // } + public void testDummyFunction() throws Exception { + checkSampleAbove(); + // because return type if not defined, usually people don't care + } + + // void void_function(void) { + // return; // no error here + // } + public void testVoidFunction() throws Exception { + checkSampleAbove(); + } + + // int integer_return_function(void) { // error + // if (global) { + // if (global == 100) { + // return; // error here on line 4 + // } + // } + // } + public void testBasicTypeFunction() throws Exception { + checkSampleAbove(); + } + + // + // struct My_Struct { + // int a; + // }; + // + // struct My_Struct struct_return_function(void) { + // return; // error here on line 6 + // } + public void testUserDefinedFunction() throws Exception { + checkSampleAbove(); + } + + // typedef unsigned int uint8_t; + // + // uint8_t return_typedef(void) { + // return; // error here on line 4 + // } + public void testTypedefReturnFunction() throws Exception { + checkSampleAbove(); + } + + + // typedef unsigned int uint8_t; + // + // uint8_t (*return_fp_no_typedef(void))(void) + // { + // return; // error here on line 5 + // } + public void testFunctionPointerReturnFunction() throws Exception { + checkSampleAbove(); + } + + // void test() { + // class A { + // public: + // void m() { + // return; // should not be an error here + // } + // }; + // } + public void testInnerFunction_Bug315525() throws Exception { + checkSampleAbove(); + } + + // void test() { + // class A { + // public: + // int m() { + // return; // error here + // } + // }; + // } + public void testInnerFunction_Bug316154() throws Exception { + checkSampleAbove(); + } + + // class c { + // c() { + // return 0; + // } + // + // ~c() { + // return; + // } + // }; + public void testConstructorRetValue() throws Exception { + loadCodeAndRunCpp(getAboveComment()); + checkErrorLine(3, ReturnChecker.RET_ERR_VALUE_ID); + } + + // class c { + // c() { + // return; + // } + // + // ~c() { + // return; + // } + // }; + public void testConstructor_Bug323602() throws Exception { + IProblemPreference macro = getPreference(ReturnChecker.RET_NO_VALUE_ID, ReturnChecker.PARAM_IMPLICIT); + macro.setValue(Boolean.TRUE); + loadCodeAndRunCpp(getAboveComment()); + checkNoErrors(); + } + + // void f() + // { + // [](int r){return r;}(5); + // } + public void testLambda_Bug332285() throws Exception { + checkSampleAbove(); + } +// void f() +// { +// if ([](int r){return r == 0;}(0)) +// ; +// } + public void testLambda2_Bug332285() throws Exception { + checkSampleAbove(); + } + + // void g() + // { + // int r; + // ({return r;}); // error + // } + public void testGccExtensions() throws Exception { + checkSampleAbove(); + } + + // auto f() -> void + // { + // } + public void testVoidLateSpecifiedReturnType_Bug337677() throws Exception { + checkSampleAboveCpp(); + } + + // auto f() -> void* // error + // { + // } + public void testVoidPointerLateSpecifiedReturnType_Bug337677() throws Exception { + checkSampleAboveCpp(); + } + +// int f() // error +// { +// if (g()) +// h(); +// else +// return 0; +// } + public void testBranches_Bug342906() throws Exception { + checkSampleAbove(); + } + +// int f() // error +// { +// switch (g()) { +// case 1: h(); break; +// case 2: +// return 0; +// } + public void testSwitch() throws Exception { + checkSampleAbove(); + } + + //int bar(int foo) + //{ + // if(foo) + // return 0; + // else + // return 0; + //} + public void testBranches_Bug343767() throws Exception { + checkSampleAbove(); + } + + //int bar(int foo) + //{ + // if(foo) + // return 0; + // else + // return 0; + // foo++; + //} + public void testBranchesDeadCode_Bug343767() throws Exception { + checkSampleAbove(); + } + +// int f() // error +// { +// switch (g()) { +// case 1: return 1; +// case 2: return 0; +// } +// } + public void testBranchesSwitch_Bug343767a() throws Exception { + checkSampleAbove(); + } +// int f() +// { +// switch (g()) { +// case 1: return 1; +// case 2: return 0; +// default: return -1; +// } +// } + public void testBranchesSwitch_Bug343767b() throws Exception { + checkSampleAbove(); + } + //int bar(int foo) + //{ + // if(foo) + // return 0; + // else + // if (g()) return 0; + // else return 1; + //} + public void testBranches2_Bug343767() throws Exception { + checkSampleAbove(); + } + //int bar(int foo) // error + //{ + // while(foo) { + // return 0; + // } + //} + public void testWhile() throws Exception { + checkSampleAbove(); + } + + // int f345687() { + // { + // return 0; + // } + // } + public void testNextedBlock_Bug345687() throws Exception { + checkSampleAbove(); + } + + // int + // fp_goto(int a) + // { + // if (a) { + // goto end; + // } + // end: + // return (a); + // } + public void testGoto_Bug346559() throws Exception { + checkSampleAbove(); + } + + // int main() + // { + // char c; // added so function body is non-empty + // // no error since return value in main is optional + // } + public void testMainFunction() throws Exception { + checkSampleAbove(); + } + + // #include <vector> + // std::vector<int> f() { + // return {1,2,3}; + // } + public void testReturnInitializerList() throws Exception { + checkSampleAbove(); + } + + // void f() __attribute__((noreturn)); + // + // int test() { + // f(); + // } + public void testNoReturn() throws Exception { + checkSampleAbove(); + } + + // struct A { + // A(); + // ~A() __attribute__((noreturn)); + // }; + // + // int test() { + // A(); + // } + public void testNoReturnInDestructor_461538() throws Exception { + checkSampleAboveCpp(); + } + + // int try1() { + // try { + // return 5; + // } catch (...) { + // return 5; + // } + // } + public void testTryBlock1() throws Exception { + // bug 348387 + checkSampleAboveCpp(); + } + + // int try2() { // error + // try { + // return 5; + // } catch (int) { + // } + // } + public void testTryBlock2() throws Exception { + checkSampleAboveCpp(); + } + + // int try3() { // error + // try { + // } catch (int a) { + // return 5; + // } + // } + public void testTryBlock3() throws Exception { + checkSampleAboveCpp(); + } + + // int retindead() { + // return 5; + // ; + // } + public void testRetInDeadCode1() throws Exception { + // bug 348386 + checkSampleAbove(); + } + + // int retindead() { + // throw 42; + // ; + // } + public void testRetInDeadCodeThrow() throws Exception { + // bug 356908 + checkSampleAboveCpp(); + } + +// bool func( int i ) +// { +// switch( i ) +// { +// case 0: +// return true; +// default: +// return false; +// break; +// } +// } + public void testRetInDeadCodeCase() throws Exception { + // Bug 350168 + checkSampleAboveCpp(); + } + +// int test1() { +// do { +// return 1; +// } while (0); +// } + public void testNoRetInfinitLoop() throws Exception { + // Bug 394521 + checkSampleAbove(); + } + +// int test1_f() // WARNING HERE: "No return, in function returning non-void" +// { +// while (1) +// { +// } +// } + public void testNoRetInfinitLoop2() throws Exception { + // Bug 394521 + checkSampleAboveCpp(); + } + + // int foo() { // error + // int waldo = waldo(); + // if (waldo); + // } + public void testSelfReferencingVariable_452325() throws Exception { + // Just check that codan runs without any exceptions being thrown. + checkSampleAboveCpp(); + } + + // int bar(int x) { return x; } + // int foo() { // error + // int waldo = bar(waldo); + // if (bar(waldo)); + // } + public void testSelfReferencingVariable_479638() throws Exception { + // Just check that codan runs without any exceptions being thrown. + checkSampleAboveCpp(); + } + + // int foo(int x) { // error + // switch (x) { + // } + // } + public void testEmptySwitch_455828() throws Exception { + checkSampleAbove(); + } + + // int foo(int x) { // error + // switch (x) { + // case 0: + // return 42;; + // default: + // } + // } + public void testDoubleSemicolonInSwitchCase_455828() throws Exception { + checkSampleAboveCpp(); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/ReturnStyleCheckerTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/ReturnStyleCheckerTest.java new file mode 100644 index 00000000000..b28128afe53 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/ReturnStyleCheckerTest.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2010, 2011 Marc-Andre Laperle and others. + * 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: + * Marc-Andre Laperle - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; + +public class ReturnStyleCheckerTest extends CheckerTestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems("org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem"); //$NON-NLS-1$ + } + + // void foo() { + // return; // no error + // } + public void testSimpleReturn() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // void foo() { + // return + // ; // no error + // } + public void testSimpleReturnMultiLine() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // int foo() { + // return(0); // no error + // } + public void testSimpleReturnValue() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // int foo() { + // return 0; // error line 2 + // } + public void testSimpleReturnValueError() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(2); + } + + // int foo() { + // return // no error + // ( + // 0 + // ); + // } + public void testReturnValueMultiline() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // int foo() { + // return // error line 2 + // 0 + // ; + // } + public void testReturnValueMultilineError() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(2); + } + + // int foo() { + // return ((0));// no error + // } + public void testReturnValueMultipleBrackets() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // int foo() { + // return // no error + // ( + // (0) + // ); + // } + public void testReturnValueMultilineMultipleBrackets() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // #define MY_RETURN return(0); + // + // int foo() { + // MY_RETURN // no error + // } + public void testReturnDefine() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // #define MY_RETURN return 0; + // + // int foo() { + // MY_RETURN // error line 4 + // } + public void testReturnDefineError() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(4); + } +}
\ No newline at end of file diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/StatementHasNoEffectCheckerTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/StatementHasNoEffectCheckerTest.java new file mode 100644 index 00000000000..4859975b9b3 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/StatementHasNoEffectCheckerTest.java @@ -0,0 +1,197 @@ +/******************************************************************************* + * Copyright (c) 2009, 2015 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import java.io.File; + +import org.eclipse.cdt.codan.core.param.IProblemPreference; +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; +import org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectChecker; +import org.eclipse.core.resources.IMarker; + +/** + * Test for {@see StatementHasNoEffectChecker} class + */ +public class StatementHasNoEffectCheckerTest extends CheckerTestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems(StatementHasNoEffectChecker.ER_ID); + } + + // main() { + // int a; + // +a; // error here on line 3 + // } + public void testUnaryExpression() throws Exception { + checkSampleAbove(); + } + + // main() { + // int a,b; + // + // b+a; // error here on line 4 + // } + public void testBinaryExpression() throws Exception { + checkSampleAbove(); + } + + // main() { + // int a,b; + // + // a=b+a; // no error here + // } + public void testNormalAssignment() throws Exception { + checkSampleAbove(); + } + + // main() { + // int a,b; + // + // (a=b); // no errors here + // a+=b; + // a<<=b; + // a-=b; + // a++; + // b--; + // --a; + // ++b; + // a%=2; + // a>>=2; + // } + public void testFalsePositives() throws Exception { + checkSampleAbove(); + } + + // main() { + // int a; + // a; // error here on line 3 + // } + public void testIdExpression() throws Exception { + checkSampleAbove(); + } + + // main() { + // int a=({foo();a;}); // no error here on line 2 + // char *p=({char s[]="Some string";&s[0];}); // no error here on line 3 + // } + public void testGNUExpressionCompoundStmtFalsePositives() throws Exception { + checkSampleAbove(); + } + + // main() { + // int z=({int a=0; +a; a;}) // error here on line 2 + // } + public void testGNUExpressionCompoundStmtInside() throws Exception { + checkSampleAbove(); + } + + // main() { + // int a; + // +a; // error here on line 3 + // } + + // foo() { + // int a; + // + // +a; // error here on line 4 + // } + public void test2FilesUnaryExpression() throws Exception { + /* This test is using two files */ + CharSequence[] code = getContents(2); + File f1 = loadcode(code[0].toString()); + File f2 = loadcode(code[1].toString()); + runOnProject(); + checkErrorLine(f1, 3); + checkErrorLine(f2, 4); + } + + // main() { + // for (a=b;a;a=a->next); + // } + public void testForTestExpression() throws Exception { + checkSampleAbove(); + } + + // void main() { + // bool a; + // class c {}; + // c z; + // (a = z.foo(1)) || (a = z.foo(2)); + // } + public void testLazyEvalHack() throws Exception { + checkSampleAboveCpp(); + } + + // main() { + // A a,b; + // + // b+=a; // no error here on line 4 + // } + public void testOverloadedBinaryExpression() throws Exception { + checkSampleAboveCpp(); + } + + //#define FUNC(a) a + // main() { + // int a; + // FUNC(a); // error by default + // } + public void testInMacro() throws Exception { + IProblemPreference macro = getPreference(StatementHasNoEffectChecker.ER_ID, StatementHasNoEffectChecker.PARAM_MACRO_ID); + macro.setValue(Boolean.TRUE); + checkSampleAbove(); + } + + //#define FUNC(a) a + // main() { + // int x; + // FUNC(x); // error + // } + public void testMessageInMacro() throws Exception { + loadCodeAndRun(getAboveComment()); + IMarker m = checkErrorLine(4); + assertMessageMatch("'FUNC(x)'", m); //$NON-NLS-1$ + } + + //#define FUNC(a) a + // main() { + // int a; + // FUNC(a); // no error if macro exp turned off + // } + public void testInMacroParamOff() throws Exception { + IProblemPreference macro = getPreference(StatementHasNoEffectChecker.ER_ID, StatementHasNoEffectChecker.PARAM_MACRO_ID); + macro.setValue(Boolean.FALSE); + checkSampleAbove(); + } + + // main() { + // int a; + // +a; // error here on line 3 + // } + public void testMessage() throws Exception { + loadCodeAndRun(getAboveComment()); + IMarker m = checkErrorLine(3); + assertMessageMatch("'\\+a'", m); //$NON-NLS-1$ + } + + // class S { + // int operator*(); // may have side effect + // }; + // + // int main() { + // S s; + // *s; + // } + public void testOverloadedOperator_bug399146() throws Exception { + checkSampleAboveCpp(); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/SuggestedParenthesisCheckerTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/SuggestedParenthesisCheckerTest.java new file mode 100644 index 00000000000..78b8acfd6ea --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/SuggestedParenthesisCheckerTest.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2009, 2011 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import org.eclipse.cdt.codan.core.param.IProblemPreference; +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; +import org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisChecker; + +/** + * Test for {@see SuggestedParenthesisChecker} class + */ +public class SuggestedParenthesisCheckerTest extends CheckerTestCase { + // main() { + // int a=1,b=3; + // if (!a<10) b=4; // error here on line 3 + // } + public void test1() throws Exception { + IProblemPreference macro = getPreference(SuggestedParenthesisChecker.ER_ID, SuggestedParenthesisChecker.PARAM_NOT); + macro.setValue(Boolean.TRUE); + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + } + + // main() { + // int a=1,b=3; + // + // if (b+a && a>b || b-a) b--; // error here on line 4 + // } + public void test2() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(4); + } + + // main() { + // int a=1,b=3; + // if (!(a<10)) b=4; // no error here on line 3 + // } + public void test3() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // main() { + // int a=1,b=3; + // if (a && !b) b=4; // no error here on line 3 + // } + public void test_lastnot() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // main() { + // int a=1,b=3; + // if ((!a) && 10) b=4; // no error here on line 3 + // } + public void test_fixed() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // main() { + // int a=1,b=3; + // if (a && b & a) b=4; // error here on line 3 + // } + public void test_mixedbin() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/SuspiciousSemicolonCheckerTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/SuspiciousSemicolonCheckerTest.java new file mode 100644 index 00000000000..cb1b822a228 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/SuspiciousSemicolonCheckerTest.java @@ -0,0 +1,175 @@ +/******************************************************************************* + * Copyright (c) 2010, 2011 Marc-Andre Laperle and others. + * 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: + * Marc-Andre Laperle - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; +import org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonChecker; + +public class SuspiciousSemicolonCheckerTest extends CheckerTestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems("org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem"); + } + + // void foo() { + // if(0); + // } + public void testIf1() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(2); + } + + // void foo() { + // if(0); + // { + // } + // } + public void testIf2() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(2); + } + + // void foo() { + // if(0) + // foo(); + // } + public void testIf3() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // void foo() { + // if(0) + // ; + // } + public void testIf4() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + } + + // void foo() { + // if(0);{ + // } + // } + public void testIf5() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(2); + } + + // void foo() { + // if(0) {}; + // } + public void testIf6() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // void foo() { + // if(0 + // ); + // } + // } + public void testIf7() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + } + + // void foo() { + // if(0) + // ; + // else if(0); + // } + public void testElseIf1() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + checkErrorLine(4); + } + + // void foo() { + // if(0) + // ; + // else if(0); + // { + // + // } + // } + public void testElseIf2() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + checkErrorLine(4); + } + + // void foo() { + // if(0) + // ; + // else if(0);{ + // } + // } + public void testElseIf3() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + checkErrorLine(4); + } + + // void foo() { + // if(0) + // ; + // else if(0){}; + // } + public void testElseIf4() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + } + + // void foo() { + // if(0) + // ; + // else if(0 + // ); + // } + public void testElseIf5() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(3); + checkErrorLine(5); + } + + // #define OP + // void foo() { + // if(0) + // OP; + // } + public void testMacro() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // #define MACRO(cond) if (cond) ; + // void foo() { + // MACRO(true); + // } + public void testMacroExpansion() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // main() { + // if (false) + // ; // only this one is reported + // else + // ; + // } + public void testIfElse() throws Exception { + setPreferenceValue(SuspiciousSemicolonChecker.ER_ID, SuspiciousSemicolonChecker.PARAM_ALFTER_ELSE, Boolean.TRUE); + loadCodeAndRun(getAboveComment()); + checkErrorLines(3, 5); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/UnusedSymbolInFileScopeCheckerTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/UnusedSymbolInFileScopeCheckerTest.java new file mode 100644 index 00000000000..87eb9e0998e --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/internal/checkers/UnusedSymbolInFileScopeCheckerTest.java @@ -0,0 +1,344 @@ +/******************************************************************************* + * Copyright (c) 2011, 2013 Andrew Gvozdev and others. + * 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: + * Andrew Gvozdev - initial API and implementation + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.codan.core.internal.checkers; + +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; +import org.eclipse.cdt.codan.internal.checkers.UnusedSymbolInFileScopeChecker; + +/** + * Test for {@see UnusedSymbolInFileScopeChecker} class + */ +public class UnusedSymbolInFileScopeCheckerTest extends CheckerTestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems( + UnusedSymbolInFileScopeChecker.ER_UNUSED_VARIABLE_DECLARATION_ID, + UnusedSymbolInFileScopeChecker.ER_UNUSED_FUNCTION_DECLARATION_ID, + UnusedSymbolInFileScopeChecker.ER_UNUSED_STATIC_FUNCTION_ID); + } + + //////////////////////////////////////////////////////////////////////////// + // extern function declarations + //////////////////////////////////////////////////////////////////////////// + + // int test_fun(); + // extern int test_efun(); + public void testExternFunction_Declaration_Unused() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(1); + checkErrorLine(2); + } + + // int test_fun(); + // void fun() { + // test_fun(); + // } + public void testExternFunction_Declaration_Used() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // void test_fun(); + // void test_fun() {} + public void testExternFunction_Declaration_FollowedByDefinition() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + //////////////////////////////////////////////////////////////////////////// + // extern function definitions + //////////////////////////////////////////////////////////////////////////// + + // void test_fun(void) {} + public void testExternFunction_Definition() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + //////////////////////////////////////////////////////////////////////////// + // Static function declarations + //////////////////////////////////////////////////////////////////////////// + + // static void test_fun(void); + public void testStaticFunction_Declaration_Unused() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(1); + } + + // static void test_fun(void); + // static void test_fun(void) {} + public void testStaticFunction_Declaration_FollowedByDefinition() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(2); + } + + // static void test_fun(void); + // void fun() { + // test_fun(); + // } + public void testStaticFunction_Declaration_Used() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(1); + } + + //////////////////////////////////////////////////////////////////////////// + // Static function definitions + //////////////////////////////////////////////////////////////////////////// + + // static void test_fun(void) {} + public void testStaticFunction_Definition_Unused() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(1); + } + + // static void test_fun(void); + // static void test_fun(void) {} + public void testStaticFunction_Definition_Unused_WithDeclaration() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(2); + } + + // static void test_fun(void) {} + // void fun() { + // test_fun(); + // } + public void testStaticFunction_Definition_Used() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // void fun() { + // test_fun(); + // } + // static int test_fun(void) {} + public void testStaticFunction_Definition_UsedBeforeDefinition() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // static int test_fun(void) {} + // static int test_fun(int) {} + // void fun() { + // test_fun(0); + // } + public void testStaticFunction_Definition_Signature() throws Exception { + loadCodeAndRunCpp(getAboveComment()); + checkErrorLine(1); + } + + // static int test_fun(void) {} + // void fun() { + // int test_fun=0; + // } + public void testStaticFunction_Definition_SynonymLocalScope() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(1); + } + + // static int test_fun(void) {} + // void fun(int test_fun) { + // } + public void testStaticFunction_Definition_SynonymArgs() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(1); + } + + // static int (test_fun) (); + public void testStaticFunction_Definition_InParentheses() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(1); + } + + // static int test_fun(int i) {} + // int i = test_fun(X); + public void testStaticFunction_Definition_UnknownParameterType() throws Exception { + loadCodeAndRunCpp(getAboveComment()); + checkNoErrors(); + } + + // static void test_fun(void) {} + // void Class::fun() { + // test_fun(); + // } + public void testStaticFunction_Definition_InQualifiedFunction() throws Exception { + loadCodeAndRunCpp(getAboveComment()); + checkNoErrors(); + } + + // static int test_fun(X) {} + // int i = test_fun(X); + public void testStaticFunction_Definition_UnknownArgumentType() throws Exception { + loadCodeAndRunCpp(getAboveComment()); + checkNoErrors(); + } + + //////////////////////////////////////////////////////////////////////////// + // Extern variables declaration + //////////////////////////////////////////////////////////////////////////// + + // extern int test_var; + public void testExternVariable_Declaration_Unused() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(1); + } + + // extern int test_var; + // void fun() { + // test_var=0; + // } + public void testExternVariable_Declaration_Used() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // extern int i, + // test_var; + public void testExternVariable_Declaration_Combined() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(1); + checkErrorLine(2); + } + + //////////////////////////////////////////////////////////////////////////// + // Extern variables definition + //////////////////////////////////////////////////////////////////////////// + + // int test_var; + // int test_var2=0; + public void testGlobalVariable_Definition() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // extern const int test_var=0; // not quite legal but some compilers allow that + public void testExternVariable_Definition1() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // extern const int test_var; + // const int test_var = 0; + public void testExternVariable_Definition2() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + //////////////////////////////////////////////////////////////////////////// + // Static variables + //////////////////////////////////////////////////////////////////////////// + + // static int test_var; + public void testStaticVariable_Unused() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(1); + } + + // static int (*test_var)(float, char, char); + public void testStaticVariable_Unused_FunctionPointer() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLine(1); + } + + // static int test_var; + // int i=test_var; + public void testStaticVariable_Used_GlobalScope() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // static int test_var; + // void fun() { + // int i=test_var; + // } + public void testStaticVariable_Used_LocalScope() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // static int test_var; + // void Class::fun() { + // test_var = 0; + // } + public void testStaticVariable_Used_InQualifiedFunction() throws Exception { + loadCodeAndRunCpp(getAboveComment()); + checkNoErrors(); + } + + // class Class; + // static Class test_var; // constructor is called here + public void testStaticVariable_Used_Constructor() throws Exception { + loadCodeAndRunCpp(getAboveComment()); + checkNoErrors(); + } + + // static X test_var; // avoid possible false positive, binding checker would complain anyway + public void testExternVariable_Declaration_IgnoreUnresolved() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // static char* test_var="$Id: UnusedSymbolInFileScopeCheckerTest.java,v 1.2 2011/04/29 11:17:42 agvozdev Exp $"; + public void testExternVariable_Declaration_CvsIdent() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // static char* test_var="@(#) $Header: /cvsroot/tools/org.eclipse.cdt/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/UnusedSymbolInFileScopeCheckerTest.java,v 1.2 2011/04/29 11:17:42 agvozdev Exp $"; + public void testExternVariable_Declaration_SccsIdent() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // static char test_var[]("@(#) $Id: UnusedSymbolInFileScopeCheckerTest.java,v 1.2 2011/04/29 11:17:42 agvozdev Exp $"); + public void testExternVariable_Declaration_CvsIdentInitializer() throws Exception { + loadCodeAndRunCpp(getAboveComment()); + checkNoErrors(); + } + + // static int v1 __attribute__((unused)); + // int f1() __attribute__((__unused__)); + // extern int f2() __attribute__((unused)); + // static void f3() __attribute__((unused)); + // static void f4() __attribute__((unused)); + // static void f4() __attribute__((unused)) {} + public void testAttributeUnused() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // extern int* pxCurrentTCB; + // + // int main() { + // asm ("lds r26, pxCurrentTCB\n\t"); + // } + public void testUseInAsm_bug393129() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + // static void foo(int) {} + // static void foo(float) {} + // + // template <typename T> + // void bar(T t) { + // foo(t); + // } + // + // int main() { + // bar(0); + // } + public void testOverloadedStaticFunctionUsedInTemplate_bug358694() throws Exception { + loadCodeAndRunCpp(getAboveComment()); + checkNoErrors(); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/param/BasicProblemPreferenceTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/param/BasicProblemPreferenceTest.java new file mode 100644 index 00000000000..bd94d48c041 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/param/BasicProblemPreferenceTest.java @@ -0,0 +1,131 @@ +/******************************************************************************* + * Copyright (c) 2009,2010 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.param; + +import java.io.File; + +import org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor.PreferenceType; + +import junit.framework.TestCase; + +/** + * Test for BasicProblemPreference + */ +public class BasicProblemPreferenceTest extends TestCase { + private static final String TEST_STR = "aaa"; + BasicProblemPreference pref; + String key = "xxx"; + + @Override + protected void setUp() throws Exception { + pref = new BasicProblemPreference(key, "My Value"); + } + + public void testIntegerExportValue() { + pref.setType(PreferenceType.TYPE_INTEGER); + pref.setValue(22); + String value = pref.exportValue(); + assertEquals(String.valueOf(22), value); + } + + public void testIntegerImportValue() { + pref.setType(PreferenceType.TYPE_INTEGER); + pref.importValue("22"); + assertEquals(22, pref.getValue()); + } + + public void testStringExportValue() { + pref.setType(PreferenceType.TYPE_STRING); + pref.setValue(TEST_STR); + String value = pref.exportValue(); + assertEquals(TEST_STR, value); + } + + public void testStringImportValue() { + pref.setType(PreferenceType.TYPE_STRING); + pref.importValue(TEST_STR); + assertEquals(TEST_STR, pref.getValue()); + } + + public void testBooleanImportValue() { + pref.setType(PreferenceType.TYPE_BOOLEAN); + pref.setValue(Boolean.TRUE); + String value = pref.exportValue(); + assertEquals("true", value); + pref.importValue(TEST_STR); + assertEquals(Boolean.FALSE, pref.getValue()); + } + + public void testFileImportValue() { + pref.setType(PreferenceType.TYPE_FILE); + File file = new File("file.c"); + pref.setValue(file); + String value = pref.exportValue(); + assertEquals(file.getName(), value); + pref.importValue(file.getName()); + assertEquals(file, pref.getValue()); + } + + public void testBadKey() { + try { + pref.setKey(null); + fail("Should be exception"); + } catch (Exception e) { + assertTrue(true); + } + } + + public void testBadType() { + try { + pref.setType(null); + fail("Should be exception"); + } catch (Exception e) { + assertTrue(true); + } + } + + public void testStringImportValueNum() { + pref.setType(PreferenceType.TYPE_STRING); + pref.importValue("42.5"); + assertEquals("42.5", pref.getValue()); + } + + /** + * @param str + */ + protected void checkImportExport(String str) { + pref.setType(PreferenceType.TYPE_STRING); + pref.setValue(str); + pref.importValue(pref.exportValue()); + assertEquals(str, pref.getValue()); + } + + public void testStringExportSpecial() { + checkImportExport("a=b"); + checkImportExport("\""); + checkImportExport("33"); + checkImportExport("22.4"); + checkImportExport("a,b"); + checkImportExport("{a+b}"); + checkImportExport("\b"); + } + // public void testEscape() { + // String str = "\"a\""; + // String res = pref.escape(str); + // assertEquals("\"\\\"a\\\"\"", res); + // } + // + // public void testUnEscape() { + // String res = "\"a\""; + // String str = "\"\\\"a\\\"\""; + // assertEquals(res, pref.unescape(str)); + // } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/param/ListProblemPreferenceTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/param/ListProblemPreferenceTest.java new file mode 100644 index 00000000000..095a643e3a0 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/param/ListProblemPreferenceTest.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * Copyright (c) 2009,2010 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.param; + +import java.util.Arrays; + +import org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor.PreferenceType; + +import junit.framework.TestCase; + +/** + * Test for BasicProblemPreference + */ +public class ListProblemPreferenceTest extends TestCase { + private static final String PAR1 = "0"; + private static final String PAR2 = "1"; + private ListProblemPreference list; + private String key = "list"; + private ListProblemPreference list2; + + @Override + protected void setUp() throws Exception { + list = new ListProblemPreference(key, "My Value"); + list2 = new ListProblemPreference(key, "My Value2"); + } + + /** + * @param parval + * @return + */ + protected BasicProblemPreference addPar(String key, Object parval) { + BasicProblemPreference str = makePar(key, parval); + list.addChildDescriptor(str); + return (BasicProblemPreference) list.getChildDescriptor(key); + } + + /** + * @param parval + * @param parval + * @return + */ + protected BasicProblemPreference makePar(String key, Object parval) { + BasicProblemPreference str = new BasicProblemPreference(key, key); + if (parval != null) { + str.setValue(parval); + str.setType(PreferenceType.typeOf(parval)); + } + return str; + } + + public void testExportValueStr() { + BasicProblemPreference str = addPar(PAR1, "42.5"); + String value = list.exportValue(); + assertEquals("(42.5)", value); + } + + public void testImportValue() { + addPar(PAR1, "xxx"); + String value = list.exportValue(); + BasicProblemPreference str2 = new BasicProblemPreference(PAR1, PAR1); + list2.addChildDescriptor(str2); + list2.importValue(value); + assertEquals("xxx", list2.getChildValue(PAR1)); + } + + public void testImportValueSpec() { + BasicProblemPreference str = addPar(PAR1, "a=b"); + String value = list.exportValue(); + BasicProblemPreference str2 = new BasicProblemPreference(PAR1, PAR1); + list2.addChildDescriptor(str2); + list2.importValue(value); + assertEquals(str.getValue(), list2.getChildValue(PAR1)); + } + + public void testImportValue2() { + addPar(PAR1, "a=b"); + BasicProblemPreference p2 = addPar(PAR2, "2,\"2"); + String value = list.exportValue(); + list = new ListProblemPreference(key, "My Value"); + addPar(PAR1, null); + addPar(PAR2, null); + list.importValue(value); + assertEquals("a=b", list.getChildValue(PAR1)); + assertEquals(p2.getValue(), list.getChildValue(PAR2)); + } + + public void testImportValue2_nosec() { + addPar(PAR1, "a=b"); + BasicProblemPreference p2 = addPar(PAR2, "2' 2\""); + String value = list.exportValue(); + list = new ListProblemPreference(key, "My Value"); + addPar(PAR1, null); + list.importValue(value); + assertEquals("a=b", list.getChildValue(PAR1)); + assertEquals(p2.getValue(), list.getChildValue(PAR2)); + } + + public void testGetValue() { + list.setChildDescriptor(new BasicProblemPreference("#", "Value")); + String x[] = { "a", "b" }; + list.addChildValue(x[0]); + list.addChildValue(x[1]); + Object[] values = list.getValues(); + assertTrue(Arrays.deepEquals(x, values)); + } + + public void testSetValue() { + list.setChildDescriptor(new BasicProblemPreference("#", "Value")); + String x[] = { "a", "b" }; + list.setValue(x); + Object[] values = list.getValues(); + assertTrue(Arrays.deepEquals(x, values)); + } + + public void testSetValueImport() { + list.setChildDescriptor(new BasicProblemPreference("#", "Value")); + String x[] = { "a", "b" }; + list.setValue(x); + list.importValue("(x)"); + Object[] values = list.getValues(); + assertEquals(1, values.length); + assertEquals("x", values[0]); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/param/MapProblemPreferenceTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/param/MapProblemPreferenceTest.java new file mode 100644 index 00000000000..e0abcb169c3 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/param/MapProblemPreferenceTest.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2009,2010 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.param; + +import org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor.PreferenceType; + +import junit.framework.TestCase; + +/** + * Test for BasicProblemPreference + */ +public class MapProblemPreferenceTest extends TestCase { + private static final String PAR1 = "aaa"; + private static final String PAR2 = "bbb"; + private MapProblemPreference map; + private String key = "map"; + private MapProblemPreference map2; + + @Override + protected void setUp() throws Exception { + map = new MapProblemPreference(key, "My Value"); + map2 = new MapProblemPreference(key, "My Value2"); + } + + /** + * @param parval + * @return + */ + protected BasicProblemPreference addPar(String key, Object parval) { + BasicProblemPreference str = makePar(key, parval); + map.addChildDescriptor(str); + return str; + } + + /** + * @param parval + * @param parval + * @return + */ + protected BasicProblemPreference makePar(String key, Object parval) { + BasicProblemPreference str = new BasicProblemPreference(key, key); + if (parval != null) { + str.setValue(parval); + str.setType(PreferenceType.typeOf(parval)); + } + return str; + } + + public void testExportValueStr() { + BasicProblemPreference str = addPar(PAR1, "42.5"); + String value = map.exportValue(); + assertEquals("{" + str.getKey() + "=>42.5}", value); + } + + public void testImportValue() { + addPar(PAR1, "xxx"); + String value = map.exportValue(); + BasicProblemPreference str2 = new BasicProblemPreference(PAR1, PAR1); + map2.addChildDescriptor(str2); + map2.importValue(value); + assertEquals("xxx", map2.getChildValue(PAR1)); + } + + public void testImportValueSpec() { + BasicProblemPreference str = addPar(PAR1, "a=b"); + String value = map.exportValue(); + BasicProblemPreference str2 = new BasicProblemPreference(PAR1, PAR1); + map2.addChildDescriptor(str2); + map2.importValue(value); + assertEquals(str.getValue(), map2.getChildValue(PAR1)); + } + + public void testImportValue2() { + addPar(PAR1, "a=b"); + BasicProblemPreference p2 = addPar(PAR2, "2,\"2"); + String value = map.exportValue(); + map = new MapProblemPreference(key, "My Value"); + addPar(PAR1, null); + addPar(PAR2, null); + map.importValue(value); + assertEquals("a=b", map.getChildValue(PAR1)); + assertEquals(p2.getValue(), map.getChildValue(PAR2)); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/AutomatedIntegrationSuite.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/AutomatedIntegrationSuite.java new file mode 100644 index 00000000000..79093b226e8 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/AutomatedIntegrationSuite.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2004, 2015 QNX Software Systems and others. + * 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: + * QNX Software Systems - initial API and implementation + * Markus Schorn (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.codan.core.tests; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.eclipse.cdt.codan.core.internal.checkers.AbstractClassInstantiationCheckerTest; +import org.eclipse.cdt.codan.core.internal.checkers.AssignmentInConditionCheckerTest; +import org.eclipse.cdt.codan.core.internal.checkers.AssignmentToItselfCheckerTest; +import org.eclipse.cdt.codan.core.internal.checkers.CaseBreakCheckerTest; +import org.eclipse.cdt.codan.core.internal.checkers.CatchByReferenceTest; +import org.eclipse.cdt.codan.core.internal.checkers.ClassMembersInitializationCheckerTest; +import org.eclipse.cdt.codan.core.internal.checkers.CommentCheckerLineTests; +import org.eclipse.cdt.codan.core.internal.checkers.CommentCheckerNestedTests; +import org.eclipse.cdt.codan.core.internal.checkers.FormatStringCheckerTest; +import org.eclipse.cdt.codan.core.internal.checkers.NonVirtualDestructorCheckerTest; +import org.eclipse.cdt.codan.core.internal.checkers.ProblemBindingCheckerTest; +import org.eclipse.cdt.codan.core.internal.checkers.ReturnCheckerTest; +import org.eclipse.cdt.codan.core.internal.checkers.ReturnStyleCheckerTest; +import org.eclipse.cdt.codan.core.internal.checkers.StatementHasNoEffectCheckerTest; +import org.eclipse.cdt.codan.core.internal.checkers.SuggestedParenthesisCheckerTest; +import org.eclipse.cdt.codan.core.internal.checkers.SuspiciousSemicolonCheckerTest; +import org.eclipse.cdt.codan.core.internal.checkers.UnusedSymbolInFileScopeCheckerTest; +import org.eclipse.cdt.codan.internal.checkers.ui.quickfix.AssignmentInConditionQuickFixTest; +import org.eclipse.cdt.codan.internal.checkers.ui.quickfix.CaseBreakQuickFixTest; +import org.eclipse.cdt.codan.internal.checkers.ui.quickfix.CatchByReferenceQuickFixTest; +import org.eclipse.cdt.codan.internal.checkers.ui.quickfix.CreateLocalVariableQuickFixTest; +import org.eclipse.cdt.codan.internal.checkers.ui.quickfix.SuggestedParenthesisQuickFixTest; + +public class AutomatedIntegrationSuite extends TestSuite { + public AutomatedIntegrationSuite() { + } + + public AutomatedIntegrationSuite(Class<? extends TestCase> theClass, String name) { + super(theClass, name); + } + + public AutomatedIntegrationSuite(Class<? extends TestCase> theClass) { + super(theClass); + } + + public AutomatedIntegrationSuite(String name) { + super(name); + } + + public static Test suite() { + final AutomatedIntegrationSuite suite = new AutomatedIntegrationSuite(); + // checkers + suite.addTestSuite(AbstractClassInstantiationCheckerTest.class); + suite.addTestSuite(AssignmentInConditionCheckerTest.class); + suite.addTestSuite(AssignmentToItselfCheckerTest.class); + suite.addTestSuite(CaseBreakCheckerTest.class); + suite.addTestSuite(CatchByReferenceTest.class); + suite.addTestSuite(ClassMembersInitializationCheckerTest.class); + suite.addTestSuite(FormatStringCheckerTest.class); + suite.addTestSuite(NonVirtualDestructorCheckerTest.class); + suite.addTestSuite(ProblemBindingCheckerTest.class); + suite.addTestSuite(ReturnCheckerTest.class); + suite.addTestSuite(ReturnStyleCheckerTest.class); + suite.addTestSuite(StatementHasNoEffectCheckerTest.class); + suite.addTestSuite(SuggestedParenthesisCheckerTest.class); + suite.addTestSuite(SuspiciousSemicolonCheckerTest.class); + suite.addTestSuite(UnusedSymbolInFileScopeCheckerTest.class); + suite.addTestSuite(CommentCheckerLineTests.class); + suite.addTestSuite(CommentCheckerNestedTests.class); + // framework + suite.addTest(CodanFastTestSuite.suite()); + // quick fixes + suite.addTestSuite(CreateLocalVariableQuickFixTest.class); + suite.addTestSuite(SuggestedParenthesisQuickFixTest.class); + suite.addTestSuite(CatchByReferenceQuickFixTest.class); + suite.addTestSuite(CaseBreakQuickFixTest.class); + suite.addTestSuite(AssignmentInConditionQuickFixTest.class); + return suite; + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CheckerTestCase.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CheckerTestCase.java new file mode 100644 index 00000000000..2c5d488f3a7 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CheckerTestCase.java @@ -0,0 +1,261 @@ +/******************************************************************************* + * Copyright (c) 2009, 2016 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + * Marc-Andre Laperle + *******************************************************************************/ +package org.eclipse.cdt.codan.core.tests; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.codan.core.CodanRuntime; +import org.eclipse.cdt.codan.core.model.CheckerLaunchMode; +import org.eclipse.cdt.codan.core.model.IProblem; +import org.eclipse.cdt.codan.core.model.IProblemProfile; +import org.eclipse.cdt.codan.core.model.IProblemReporter; +import org.eclipse.cdt.codan.core.param.IProblemPreference; +import org.eclipse.cdt.codan.core.param.MapProblemPreference; +import org.eclipse.cdt.codan.core.param.RootProblemPreference; +import org.eclipse.cdt.codan.internal.core.model.CodanProblem; +import org.eclipse.cdt.codan.internal.core.model.CodanProblemMarker; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.NullProgressMonitor; + +/** + * Base class for tests. If you want to use outside of this plugin, you need + * to override {@link #getPlugin()} method and maybe {@link #getSourcePrefix()} + * method to get source directory for the tests, + * default is "src". To make it read comment from java class, you need to + * include this source directory (with test java files) into the build bundle. + * + */ +@SuppressWarnings("nls") +public class CheckerTestCase extends CodanTestCase { + protected IMarker[] markers; + + public IMarker checkErrorLine(int i) { + return checkErrorLine(currentFile, i); + } + + public void checkErrorLines(Object... args) { + for (Object i : args) { + checkErrorLine((Integer) i); + } + assertEquals(args.length, markers.length); + } + + public void checkErrorComments() { + for (Object i : errLines) { + checkErrorLine((Integer) i); + } + assertEquals("Expected number of errors " + errLines.size(),errLines.size(), markers.length); + } + + public IMarker checkErrorLine(int i, String problemId) { + return checkErrorLine(currentFile, i, problemId); + } + + public IMarker checkErrorLine(File file, int expectedLine) { + return checkErrorLine(file, expectedLine, null); + } + + /** + * @param expectedLine + * - line + * @return + */ + public IMarker checkErrorLine(File file, int expectedLine, String problemId) { + assertTrue(markers != null); + assertTrue("No problems found but should", markers.length > 0); //$NON-NLS-1$ + boolean found = false; + Integer line = null; + String mfile = null; + IMarker m = null; + for (int j = 0; j < markers.length; j++) { + m = markers[j]; + line = getLine(m); + mfile = m.getResource().getName(); + if (line.equals(expectedLine) && (problemId == null || problemId.equals(CodanProblemMarker.getProblemId(m)))) { + found = true; + if (file != null && !file.getName().equals(mfile)) + found = false; + else + break; + } + } + assertEquals("Error on line " + expectedLine + " is not found", Integer.valueOf(expectedLine), line); + if (file != null) + assertEquals(file.getName(), mfile); + assertTrue(found); + assertNotNull(m); + return m; + } + + /** + * @param line + * @param m + * @return + */ + public Integer getLine(IMarker m) { + Integer line = null; + try { + line = (Integer) m.getAttribute(IMarker.LINE_NUMBER); + if (line == null || line.equals(-1)) { + Object pos = m.getAttribute(IMarker.CHAR_START); + line = pos2line(((Integer) pos).intValue()); + } + } catch (CoreException e) { + fail(e.getMessage()); + } catch (IOException e) { + fail(e.getMessage()); + } + return line; + } + + public void checkNoErrors() { + if (markers != null && markers.length > 0) { + IMarker m = markers[0]; + fail("Found " + markers.length + " errors but should not. First " + + CodanProblemMarker.getProblemId(m) + " at line " + getLine(m)); + } + } + + public void checkNoErrorsOfKind(String problemId) { + if (markers != null && markers.length > 0) { + List<IMarker> filtered = new ArrayList<IMarker>(markers.length); + for (IMarker m : markers) { + if (CodanProblemMarker.getProblemId(m).equals(problemId)) { + filtered.add(m); + } + } + if (!filtered.isEmpty()) { + IMarker m = filtered.get(0); + fail("Found " + filtered.size() + " errors but should not. First " + + CodanProblemMarker.getProblemId(m) + " at line " + getLine(m)); + } + } + } + + public void runOnProject() { + try { + indexFiles(); + } catch (Exception e) { + fail(e.getMessage()); + } + runCodan(); + } + + public void loadCodeAndRun(String code) throws CoreException { + loadcode(code); + runCodan(); + } + + public void loadCodeAndRunCpp(String code) throws CoreException { + loadcode(code, true); + runCodan(); + } + + protected void runCodan() { + CodanRuntime.getInstance().getBuilder().processResource(cproject.getProject(), new NullProgressMonitor()); + try { + markers = cproject.getProject().findMarkers(IProblemReporter.GENERIC_CODE_ANALYSIS_MARKER_TYPE, true, 1); + } catch (CoreException e) { + fail(e.getMessage()); + } + } + + /** + * @param problemId + * @param paramId + * @return + */ + protected IProblemPreference getPreference(String problemId, String paramId) { + IProblemProfile resourceProfile = + CodanRuntime.getInstance().getCheckersRegistry().getResourceProfile(cproject.getResource()); + IProblem problem = resourceProfile.findProblem(problemId); + IProblemPreference pref = ((MapProblemPreference) problem.getPreference()).getChildDescriptor(paramId); + return pref; + } + + protected IProblemPreference setPreferenceValue(String problemId, String paramId, Object value) { + IProblemPreference param = getPreference(problemId, paramId); + param.setValue(value); + return param; + } + + /** + * @param string + * @param m + */ + public void assertMessageMatch(String pattern, IMarker m) { + try { + String message = (String) m.getAttribute(IMarker.MESSAGE); + if (message.matches(pattern)) { + fail("Expected " + message + " to match with /" + pattern //$NON-NLS-1$ //$NON-NLS-2$ + + "/"); //$NON-NLS-1$ + } + } catch (CoreException e) { + fail(e.getMessage()); + } + } + + public void assertMessageContains(CharSequence charSequence, IMarker m) { + try { + String message = (String) m.getAttribute(IMarker.MESSAGE); + if (!message.contains(charSequence)) { + fail("Expected " + message + " to contain /" + charSequence //$NON-NLS-1$ //$NON-NLS-2$ + + "/"); //$NON-NLS-1$ + } + } catch (CoreException e) { + fail(e.getMessage()); + } + } + + /** + * Enable given problems and disable the rest + * @param ids + */ + protected void enableProblems(String... ids) { + IProblemProfile profile = CodanRuntime.getInstance().getCheckersRegistry().getWorkspaceProfile(); + IProblem[] problems = profile.getProblems(); + for (int i = 0; i < problems.length; i++) { + IProblem p = problems[i]; + boolean enabled = false; + for (int j = 0; j < ids.length; j++) { + String pid = ids[j]; + if (p.getId().equals(pid)) { + enabled = true; + // Force the launch mode to FULL_BUILD to make sure we can test the problem even + // if by default it is not set to run on FULL_BUILD. + IProblemPreference preference = p.getPreference(); + if (preference instanceof RootProblemPreference) { + RootProblemPreference rootProblemPreference = (RootProblemPreference) preference; + rootProblemPreference.getLaunchModePreference().enableInLaunchModes(CheckerLaunchMode.RUN_ON_FULL_BUILD); + } + break; + } + } + ((CodanProblem) p).setEnabled(enabled); + } + CodanRuntime.getInstance().getCheckersRegistry().updateProfile(cproject.getProject(), profile); + } + + protected void checkSampleAbove() throws CoreException { + loadCodeAndRun(getAboveComment()); + checkErrorComments(); + } + + protected void checkSampleAboveCpp() throws CoreException { + loadCodeAndRunCpp(getAboveComment()); + checkErrorComments(); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CodanCoreTestActivator.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CodanCoreTestActivator.java new file mode 100644 index 00000000000..e11f5e2764f --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CodanCoreTestActivator.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2010, 2011 Alena Laskavaia and others. + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.tests; + +import org.eclipse.core.runtime.Plugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class CodanCoreTestActivator extends Plugin { + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.cdt.codan.core.test"; //$NON-NLS-1$ + // The shared instance + private static CodanCoreTestActivator plugin; + + /** + * The constructor + */ + public CodanCoreTestActivator() { + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static CodanCoreTestActivator getDefault() { + return plugin; + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CodanFastCxxAstTestCase.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CodanFastCxxAstTestCase.java new file mode 100644 index 00000000000..5ca94aaef4c --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CodanFastCxxAstTestCase.java @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (c) 2009,2013 QNX Software Systems + * 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: + * QNX Software Systems (Alena Laskavaia) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.tests; + +import junit.framework.TestCase; + +import org.eclipse.cdt.codan.core.CodanRuntime; +import org.eclipse.cdt.codan.core.model.IChecker; +import org.eclipse.cdt.codan.core.model.ICheckerInvocationContext; +import org.eclipse.cdt.codan.core.model.IProblemLocation; +import org.eclipse.cdt.codan.core.model.IProblemReporter; +import org.eclipse.cdt.codan.core.model.IRunnableInEditorChecker; +import org.eclipse.cdt.codan.internal.core.CheckerInvocationContext; +import org.eclipse.cdt.core.dom.ast.IASTProblem; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.parser.ISourceCodeParser; +import org.eclipse.cdt.core.dom.parser.c.ANSICParserExtensionConfiguration; +import org.eclipse.cdt.core.dom.parser.c.GCCParserExtensionConfiguration; +import org.eclipse.cdt.core.dom.parser.c.ICParserExtensionConfiguration; +import org.eclipse.cdt.core.dom.parser.cpp.ANSICPPParserExtensionConfiguration; +import org.eclipse.cdt.core.dom.parser.cpp.GPPParserExtensionConfiguration; +import org.eclipse.cdt.core.dom.parser.cpp.ICPPParserExtensionConfiguration; +import org.eclipse.cdt.core.parser.FileContent; +import org.eclipse.cdt.core.parser.IScanner; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.parser.NullLogService; +import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.core.parser.ParserMode; +import org.eclipse.cdt.core.parser.ScannerInfo; +import org.eclipse.cdt.core.parser.tests.ast2.AST2TestBase; +import org.eclipse.cdt.core.testplugin.util.TestSourceReader; +import org.eclipse.cdt.internal.core.dom.parser.c.CVisitor; +import org.eclipse.cdt.internal.core.dom.parser.c.GNUCSourceParser; +import org.eclipse.cdt.internal.core.dom.parser.cpp.GNUCPPSourceParser; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; + +import java.io.IOException; +import java.util.ArrayList; + +/** + * TODO: add description + */ +@SuppressWarnings({ "nls", "restriction" }) +public abstract class CodanFastCxxAstTestCase extends TestCase { + protected IASTTranslationUnit tu; + + protected String getAboveComment() { + return getContents(1)[0].toString(); + } + + protected StringBuilder[] getContents(int sections) { + try { + CodanCoreTestActivator plugin = CodanCoreTestActivator.getDefault(); + return TestSourceReader.getContentsForTest(plugin == null ? null : plugin.getBundle(), "src", getClass(), getName(), sections); + } catch (IOException e) { + fail(e.getMessage()); + return null; + } + } + + public boolean isCpp() { + return false; + } + + private static final NullLogService NULL_LOG = new NullLogService(); + + /** + * @return + * + */ + public IASTTranslationUnit parse(String code) { + return parse(code, isCpp() ? ParserLanguage.CPP : ParserLanguage.C, true); + } + + protected IASTTranslationUnit parse(String code, ParserLanguage lang, boolean gcc) { + FileContent codeReader = FileContent.create("code.c", code.toCharArray()); + IScannerInfo scannerInfo = new ScannerInfo(); + IScanner scanner = AST2TestBase.createScanner(codeReader, lang, ParserMode.COMPLETE_PARSE, scannerInfo); + ISourceCodeParser parser2 = null; + if (lang == ParserLanguage.CPP) { + ICPPParserExtensionConfiguration config = null; + if (gcc) + config = new GPPParserExtensionConfiguration(); + else + config = new ANSICPPParserExtensionConfiguration(); + parser2 = new GNUCPPSourceParser(scanner, ParserMode.COMPLETE_PARSE, NULL_LOG, config); + } else { + ICParserExtensionConfiguration config = null; + if (gcc) + config = new GCCParserExtensionConfiguration(); + else + config = new ANSICParserExtensionConfiguration(); + parser2 = new GNUCSourceParser(scanner, ParserMode.COMPLETE_PARSE, NULL_LOG, config); + } + IASTTranslationUnit tu = parser2.parse(); + if (parser2.encounteredError() && !hasCodeErrors()) + fail("PARSE FAILURE"); + if (!hasCodeErrors()) { + if (lang == ParserLanguage.C) { + IASTProblem[] problems = CVisitor.getProblems(tu); + assertEquals(problems.length, 0); + } else if (lang == ParserLanguage.CPP) { + IASTProblem[] problems = CPPVisitor.getProblems(tu); + assertEquals(problems.length, 0); + } + } + this.tu = tu; + return tu; + } + + /** + * Override if any of code that test tried to parse has errors, otherwise + * parse method would assert + * + * @return + */ + protected boolean hasCodeErrors() { + return false; + } + + public class ProblemInstance { + String id; + IProblemLocation loc; + Object[] args; + + /** + * @param id + * @param loc + * @param args + */ + public ProblemInstance(String id, IProblemLocation loc, Object[] args) { + this.id = id; + this.loc = loc; + this.args = args; + } + } + private ArrayList<ProblemInstance> codanproblems = new ArrayList<CodanFastCxxAstTestCase.ProblemInstance>(); + + void runCodan(String code) { + tu = parse(code); + runCodan(tu); + } + + void runCodan(IASTTranslationUnit tu) { + IProblemReporter problemReporter = CodanRuntime.getInstance().getProblemReporter(); + CodanRuntime.getInstance().setProblemReporter(new IProblemReporter() { + public void reportProblem(String problemId, IProblemLocation loc, Object... args) { + codanproblems.add(new ProblemInstance(problemId, loc, args)); + } + }); + ICheckerInvocationContext context = new CheckerInvocationContext(null); + try { + IChecker checker = getChecker(); + ((IRunnableInEditorChecker) checker).processModel(tu, context); + } finally { + CodanRuntime.getInstance().setProblemReporter(problemReporter); + context.dispose(); + } + } + + /** + * @return + */ + public abstract IChecker getChecker(); + + protected int line2offset(int linePar, String code) throws IOException { + byte[] bytes = code.getBytes(); + int line = 1; + for (int j = 0; j < bytes.length; j++) { + byte c = bytes[j]; + if (line >= linePar) + return j; + if (c == '\n') + line++; + } + return 0; + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CodanFastTestSuite.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CodanFastTestSuite.java new file mode 100644 index 00000000000..e1147e315ea --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CodanFastTestSuite.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2004, 2011 QNX Software Systems and others. + * 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: + * QNX Software Systems - initial API and implementation + * Markus Schorn (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.codan.core.tests; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.eclipse.cdt.codan.core.cfg.ControlFlowGraphTest; +import org.eclipse.cdt.codan.core.cxx.CxxAstUtilsTest; +import org.eclipse.cdt.codan.core.param.BasicProblemPreferenceTest; +import org.eclipse.cdt.codan.core.param.ListProblemPreferenceTest; +import org.eclipse.cdt.codan.core.param.MapProblemPreferenceTest; + +public class CodanFastTestSuite extends TestSuite { + public CodanFastTestSuite() { + } + + public CodanFastTestSuite(Class<? extends TestCase> theClass, String name) { + super(theClass, name); + } + + public CodanFastTestSuite(Class<? extends TestCase> theClass) { + super(theClass); + } + + public CodanFastTestSuite(String name) { + super(name); + } + + public static Test suite() { + final CodanFastTestSuite suite = new CodanFastTestSuite(); + suite.addTestSuite(BasicProblemPreferenceTest.class); + suite.addTestSuite(ListProblemPreferenceTest.class); + suite.addTestSuite(MapProblemPreferenceTest.class); + suite.addTestSuite(CxxAstUtilsTest.class); + suite.addTestSuite(ControlFlowGraphTest.class); + return suite; + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CodanTestCase.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CodanTestCase.java new file mode 100644 index 00000000000..718a998799a --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/CodanTestCase.java @@ -0,0 +1,274 @@ +/******************************************************************************* + * Copyright (c) 2009, 2015 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.tests; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.regex.Pattern; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.IPDOMManager; +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.testplugin.CProjectHelper; +import org.eclipse.cdt.core.testplugin.util.BaseTestCase; +import org.eclipse.cdt.core.testplugin.util.TestSourceReader; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRunnable; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Plugin; + +/** + * TODO: add description + */ +@SuppressWarnings("nls") +public class CodanTestCase extends BaseTestCase { + ArrayList<File> tempFiles = new ArrayList<File>(); + protected File tmpDir; + protected ICProject cproject; + protected File currentFile; + protected ICElement currentCElem; + protected IFile currentIFile; + protected ArrayList<Integer> errLines = new ArrayList<Integer>(); + + /** + * + */ + public CodanTestCase() { + super(); + } + + /** + * @param name + */ + public CodanTestCase(String name) { + super(name); + } + + /** + * Override for c++ (i.e. at least one c++ test) + * + * @return is c++ tests + */ + public boolean isCpp() { + return false; + } + + @Override + public void setUp() throws Exception { + super.setUp(); + removeLeftOverProjects(); + cproject = createProject(isCpp()); + tmpDir = cproject.getProject().getLocation().makeAbsolute().toFile(); + // this make CodanRunner to propagate all exceptions it normally just logs + System.setProperty("codan.rethrow", "true"); // test can override setUp and unset this + } + + @Override + public void tearDown() throws Exception { + if (cproject != null) { + try { + cproject.getProject().delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT, new NullProgressMonitor()); + } catch (CoreException e) { + throw e; + } + } + super.tearDown(); + } + + /** + * @throws CoreException + */ + private void removeLeftOverProjects() throws CoreException { + try { + final IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IProject[] projects = workspace.getRoot().getProjects(); + for (int i = 0; i < projects.length; i++) { + IProject p = projects[i]; + if (p.getName().startsWith("Codan")) { + p.delete(IResource.FORCE | IResource.ALWAYS_DELETE_PROJECT_CONTENT, new NullProgressMonitor()); + } + } + } catch (Throwable e) { + // moving on... + } + } + + protected ICProject createProject(final boolean cpp) throws CoreException { + final ICProject cprojects[] = new ICProject[1]; + ModelJoiner mj = new ModelJoiner(); + try { + // Create the cproject + final String projectName = "CodanProjTest_" + System.currentTimeMillis(); + final IWorkspace workspace = ResourcesPlugin.getWorkspace(); + workspace.run(new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) throws CoreException { + // Create the cproject + ICProject cproject = cpp ? CProjectHelper.createCCProject(projectName, null, IPDOMManager.ID_NO_INDEXER) + : CProjectHelper.createCProject(projectName, null, IPDOMManager.ID_NO_INDEXER); + cprojects[0] = cproject; + } + }, null); + mj.join(); + } finally { + mj.dispose(); + } + return cprojects[0]; + } + + protected void indexFiles() throws CoreException, InterruptedException { + final IWorkspace workspace = ResourcesPlugin.getWorkspace(); + workspace.run(new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) throws CoreException { + cproject.getProject().refreshLocal(1, monitor); + } + }, null); + // Index the cproject + CCorePlugin.getIndexManager().setIndexerId(cproject, IPDOMManager.ID_FAST_INDEXER); + CCorePlugin.getIndexManager().reindex(cproject); + // wait until the indexer is done + waitForIndexer(cproject); + } + + /** + * @param pos + * @return + * @throws IOException + */ + protected int pos2line(int pos) throws IOException { + FileInputStream st = new FileInputStream(currentFile); + try { + int c; + int line = 1; + int cur = 0; + while ((c = st.read()) != -1) { + if (c == '\n') + line++; + if (cur >= pos) + return line; + cur++; + } + } finally { + st.close(); + } + return 0; + } + + protected String getAboveComment() { + return getContents(1)[0].toString(); + } + + protected StringBuilder[] getContents(int sections) { + try { + return TestSourceReader.getContentsForTest(getPlugin().getBundle(), getSourcePrefix(), getClass(), getName(), sections); + } catch (IOException e) { + fail(e.getMessage()); + return null; + } + } + + protected String getSourcePrefix() { + return "src"; + } + + protected Plugin getPlugin() { + CodanCoreTestActivator plugin = CodanCoreTestActivator.getDefault(); + return plugin; + } + + public File loadcode(String code, boolean cpp) throws CoreException { + String fileKey = "@file:"; + int indf = code.indexOf(fileKey); + if (indf >= 0) { + int sep = code.indexOf('\n'); + if (sep != -1) { + String line = code.substring(0, sep); + code = code.substring(sep + 1); + String fileName = line.substring(indf + fileKey.length()).trim(); + return loadcode(code, new File(tmpDir, fileName)); + } + } + String ext = cpp ? ".cpp" : ".c"; + File testFile = null; + try { + testFile = File.createTempFile("test", ext, tmpDir); //$NON-NLS-1$ + } catch (IOException e1) { + fail(e1.getMessage()); + return null; + } + return loadcode(code, testFile); + } + + private File loadcode(String code, File testFile) throws CoreException { + try { + tempFiles.add(testFile); + loadErrorComments(code); + TestUtils.saveFile(new ByteArrayInputStream(code.getBytes()), testFile); + currentFile = testFile; + try { + cproject.getProject().refreshLocal(1, null); + waitForIndexer(cproject); + } catch (InterruptedException e) { + } + currentCElem = cproject.findElement(new Path(currentFile.toString())); + currentIFile = (IFile) currentCElem.getResource(); + return testFile; + } catch (IOException e) { + fail("Cannot save test: " + testFile + ": " + e.getMessage()); + return null; + } catch (CModelException e) { + fail("Cannot find file: " + testFile + ": " + e.getMessage()); + return null; + } + } + private static Pattern COMMENT_TAG_PATTERN = Pattern.compile("//\\s*(err|ERR|ERROR|error)\\b"); + + private void loadErrorComments(String trim) { + String[] lines = trim.split("\n"); + for (int i = 0; i < lines.length; i++) { + String string = lines[i]; + if (COMMENT_TAG_PATTERN.matcher(string).find()) { + errLines.add(i + 1); + } + } + } + + public File loadcode_c(String code) throws CoreException { + return loadcode(code, true); + } + + public File loadcode_cpp(String code) throws CoreException { + return loadcode(code, false); + } + + public File loadcode(String code) throws CoreException { + return loadcode(code, isCpp()); + } + + public File loadcode(CharSequence... more) throws CoreException { + File file = null; + for (CharSequence cseq : more) { + file = loadcode(cseq.toString(), isCpp()); + } + return file; + } +}
\ No newline at end of file diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/TestUtils.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/TestUtils.java new file mode 100644 index 00000000000..471fcbae883 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/TestUtils.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2009, 2015 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.core.tests; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.net.URL; + +/** + * TODO: add description + */ +@SuppressWarnings("nls") +public class TestUtils { + public static File saveFile(InputStream st, File testFile) throws FileNotFoundException, IOException { + BufferedReader r = new BufferedReader(new InputStreamReader(st)); + String line; + PrintStream wr = new PrintStream(testFile); + try { + while ((line = r.readLine()) != null) { + wr.println(line); + } + } finally { + wr.close(); + } + return testFile; + } + + public static String loadFile(InputStream st) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(st)); + String buffer; + StringBuilder result = new StringBuilder(); + while ((buffer = br.readLine()) != null) { + result.append(buffer); + } + st.close(); + return result.toString(); + } + + /** + * @param clazz + * @return + * @throws IOException + */ + public static InputStream getJavaFileText(String srcRoot, Class<?> clazz) throws IOException { + CodanCoreTestActivator plugin = CodanCoreTestActivator.getDefault(); + String classFile = clazz.getName().replaceAll("\\.", "/"); + classFile += ".java"; + InputStream st = null; + if (plugin != null) { + URL resource = plugin.getBundle().getResource(srcRoot + "/" + classFile); + if (resource == null) + throw new IOException("Cannot find file " + srcRoot + "/" + classFile + " in bundle " + plugin.getBundle().getBundleId()); + st = resource.openStream(); + } else { + st = clazz.getResourceAsStream("/" + classFile); + } + return st; + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/AssignmentInConditionQuickFixTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/AssignmentInConditionQuickFixTest.java new file mode 100644 index 00000000000..092764fdf8f --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/AssignmentInConditionQuickFixTest.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2013 Nathan Ridge + * 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: + * Nathan Ridge - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.checkers.ui.quickfix; + +import org.eclipse.cdt.codan.ui.AbstractCodanCMarkerResolution; + +public class AssignmentInConditionQuickFixTest extends QuickFixTestCase { + @SuppressWarnings("restriction") + @Override + protected AbstractCodanCMarkerResolution createQuickFix() { + return new QuickFixAssignmentInCondition(); + } + + // void func() { + // int a, b; + // if (a == 1 && b = 2) { + // } + // } + public void testComparisonAndAssignment_bug352267() throws Exception { + loadcode(getAboveComment()); + String result = runQuickFixOneFile(); + assertContainedIn("b == 2", result); + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/CaseBreakQuickFixTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/CaseBreakQuickFixTest.java new file mode 100644 index 00000000000..bafe92bc2ae --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/CaseBreakQuickFixTest.java @@ -0,0 +1,69 @@ +/*******************************************************************************
+ * Copyright (c) 2010, 2013 Tomasz Wesolowski and others
+ * 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:
+ * Tomasz Wesolowski - initial API and implementation
+ *******************************************************************************/ +package org.eclipse.cdt.codan.internal.checkers.ui.quickfix;
+
+import org.eclipse.cdt.codan.ui.AbstractCodanCMarkerResolution;
+
+public class CaseBreakQuickFixTest extends QuickFixTestCase {
+ @SuppressWarnings("restriction")
+ @Override
+ protected AbstractCodanCMarkerResolution createQuickFix() {
+ return new CaseBreakQuickFixBreak();
+ }
+
+ //void func() {
+ // int a;
+ // switch(a) {
+ // case 1:
+ // hello();
+ // case 2:
+ // break;
+ // }
+ //}
+ public void testSimpleCase() throws Exception {
+ loadcode(getAboveComment());
+ String result = runQuickFixOneFile();
+ assertContainedIn("break;\tcase 2:", result);
+ }
+
+ //void func() {
+ // int a;
+ // switch(a) {
+ // case 1: {
+ // hello();
+ // }
+ // default:
+ // }
+ //}
+ public void testCompositeStatementCase() throws Exception {
+ loadcode(getAboveComment());
+ String result = runQuickFixOneFile();
+ assertContainedIn("hello();\t\tbreak;", result);
+ }
+
+ // int main() {
+ // int a;
+ // switch(a)
+ // {
+ // case 0:
+ // {
+ // }
+ // default:
+ // break;
+ // }
+ // return 0;
+ // }
+ public void testNPE_bug363884() throws Exception {
+ loadcode(getAboveComment());
+ String result = runQuickFixOneFile();
+ assertContainedIn("break;\t}\t\t\tdefault:", result);
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/CatchByReferenceQuickFixTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/CatchByReferenceQuickFixTest.java new file mode 100644 index 00000000000..d3dd2f85391 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/CatchByReferenceQuickFixTest.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 Tomasz Wesolowski and others + * 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: + * Tomasz Wesolowski - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.checkers.ui.quickfix; + +import org.eclipse.cdt.codan.internal.checkers.CatchByReference; +import org.eclipse.cdt.codan.ui.AbstractCodanCMarkerResolution; + +/** + * @author Tomasz Wesolowski + */ +@SuppressWarnings("restriction") +public class CatchByReferenceQuickFixTest extends QuickFixTestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems(CatchByReference.ER_ID); + } + + @Override + public boolean isCpp() { + return true; + } + + @Override + protected AbstractCodanCMarkerResolution createQuickFix() { + return null; // quick fix to be chosen per test + } + + // struct C { + // }; + // void foo() { + // try { + // } catch (C exception) { + // } + // } + public void testCatchByReference() throws Exception { + setQuickFix(new CatchByReferenceQuickFix()); + loadcode(getAboveComment()); + String result = runQuickFixOneFile(); + assertContainedIn("catch (C & exception)", result); //$NON-NLS-1$ + } + + // struct C { + // }; + // void foo() { + // try { + // } catch (C) { + // } + // } + public void testCatchByReferenceNoDeclName() throws Exception { + setQuickFix(new CatchByReferenceQuickFix()); + loadcode(getAboveComment()); + String result = runQuickFixOneFile(); + assertContainedIn("catch (C &)", result); //$NON-NLS-1$ + } + + // struct C { + // }; + // void foo() { + // try { + // } catch (C exception) { + // } + // } + public void testCatchByConstReference() throws Exception { + setQuickFix(new CatchByConstReferenceQuickFix()); + loadcode(getAboveComment()); + String result = runQuickFixOneFile(); + assertContainedIn("catch (const C & exception)", result); //$NON-NLS-1$ + } + + // struct C { + // }; + // void foo() { + // try { + // } catch (C) { + // } + // } + public void testCatchByConstReferenceNoDeclName() throws Exception { + setQuickFix(new CatchByConstReferenceQuickFix()); + loadcode(getAboveComment()); + String result = runQuickFixOneFile(); + assertContainedIn("catch (const C &)", result); //$NON-NLS-1$ + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/CreateLocalVariableQuickFixTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/CreateLocalVariableQuickFixTest.java new file mode 100644 index 00000000000..f721c7ade19 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/CreateLocalVariableQuickFixTest.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2010, 2011 Tomasz Wesolowski and others + * 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: + * Tomasz Wesolowski - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.checkers.ui.quickfix; + +import org.eclipse.cdt.codan.internal.checkers.ProblemBindingChecker; +import org.eclipse.cdt.codan.ui.AbstractCodanCMarkerResolution; + +/** + * @author Tomasz Wesolowski + */ +public class CreateLocalVariableQuickFixTest extends QuickFixTestCase { + @SuppressWarnings("restriction") + @Override + protected AbstractCodanCMarkerResolution createQuickFix() { + return new QuickFixCreateLocalVariable(); + } + + @Override + public boolean isCpp() { + return true; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.codan.core.test.CodanTestCase#setUp() + */ + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems(ProblemBindingChecker.ERR_ID_FieldResolutionProblem, ProblemBindingChecker.ERR_ID_MethodResolutionProblem, + ProblemBindingChecker.ERR_ID_VariableResolutionProblem); + } + + // void func() { + // aChar = 'a'; + // } + public void testChar() throws Exception { + loadcode(getAboveComment()); + String result = runQuickFixOneFile(); + assertContainedIn("char aChar;", result); //$NON-NLS-1$ + } + + // void func() { + // aDouble = 40.; + // } + public void testDouble() throws Exception { + loadcode(getAboveComment()); + String result = runQuickFixOneFile(); + assertContainedIn("double aDouble;", result); //$NON-NLS-1$ + } + + // void func() { + // aString = "foo"; + // } + public void testString() throws Exception { + loadcode(getAboveComment()); + String result = runQuickFixOneFile(); + assertContainedIn("const char* aString;", result); //$NON-NLS-1$ + } + + // void func() { + // aWString = L"foo"; + // } + public void testWString() throws Exception { + loadcode(getAboveComment()); + String result = runQuickFixOneFile(); + assertContainedIn("const wchar_t* aWString;", result); //$NON-NLS-1$ + } + + // void func() { + // aFuncPtr = func; + // } + public void testFuncPtr() throws Exception { + loadcode(getAboveComment()); + String result = runQuickFixOneFile(); + assertContainedIn("void (*aFuncPtr)();", result); //$NON-NLS-1$ + } + + //class Foo { + // void bar(char); + //}; + //void func() { + //Foo foo; + //foo.bar(aChar); + //} + public void testInMethodCall() throws Exception { + loadcode(getAboveComment()); + indexFiles(); + String result = runQuickFixOneFile(); + assertContainedIn("char aChar", result); //$NON-NLS-1$ + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixTestCase.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixTestCase.java new file mode 100644 index 00000000000..2fd7fa29df2 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixTestCase.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * Copyright (c) 2009, 2015 QNX Software Systems + * 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: + * QNX Software Systems (Alena Laskavaia) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.checkers.ui.quickfix; + +import java.io.IOException; + +import org.eclipse.cdt.codan.core.PreferenceConstants; +import org.eclipse.cdt.codan.core.tests.CheckerTestCase; +import org.eclipse.cdt.codan.core.tests.TestUtils; +import org.eclipse.cdt.codan.internal.ui.CodanUIActivator; +import org.eclipse.cdt.codan.ui.AbstractCodanCMarkerResolution; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; + +/** + * Abstract base class for Quck Fix tests. + */ +@SuppressWarnings("restriction") +public abstract class QuickFixTestCase extends CheckerTestCase { + AbstractCodanCMarkerResolution quickFix; + Display display; + + /** + * Dispatch ui events for at least msec - milliseconds + * + * @param msec - + * milliseconds delay + * @param display - + * display that dispatches events + */ + public void dispatch(int msec) { + long cur = System.currentTimeMillis(); + long pass = 0; + while (pass < msec) { + if (!display.readAndDispatch()) + display.sleep(); + pass = System.currentTimeMillis() - cur; + } + } + + public static void closeWelcome() { + try { + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + IWorkbenchPage activePage = window.getActivePage(); + IWorkbenchPart activePart = activePage.getActivePart(); + if (activePart.getTitle().equals("Welcome")) { //$NON-NLS-1$ + //activePage.close(); + activePart.dispose(); + } + } catch (Exception e) { + // ignore + } + } + + @Override + public void setUp() throws Exception { + super.setUp(); + quickFix = createQuickFix(); + display = PlatformUI.getWorkbench().getDisplay(); + closeWelcome(); + IPreferenceStore store = CodanUIActivator.getDefault().getPreferenceStore(cproject.getProject()); + // turn off editor reconciler + store.setValue(PreferenceConstants.P_RUN_IN_EDITOR, false); + } + + @Override + public void tearDown() throws Exception { + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + IWorkbenchPage[] pages = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPages(); + for (IWorkbenchPage page : pages) { + page.closeAllEditors(false); + dispatch(0); + } + } + }); + + super.tearDown(); + } + + /** + * @return + */ + protected abstract AbstractCodanCMarkerResolution createQuickFix(); + + /** + * @param code + * @param string + * @return + */ + protected ISelection textSelection(String code, String string) { + return new TextSelection(code.indexOf(string), string.length()); + } + + public String runQuickFixOneFile() throws IOException, CoreException { + // need to load before running codan because otherwise marker is lost when doing quick fix 8[] + runCodan(); + doRunQuickFix(); + String result = TestUtils.loadFile(currentIFile.getContents()); + return result; + } + + public void doRunQuickFix() { + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + for (int i = 0; i < markers.length; i++) { + IMarker marker = markers[i]; + quickFix.run(marker); + dispatch(0); + } + PlatformUI.getWorkbench().saveAllEditors(false); + } + }); + + } + + /** + * @param result + * @param expected + */ + public void assertContainedIn(String expected, String result) { + assertTrue("Text <" + expected + "> not found in <" + result + ">", result.contains(expected)); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ + } + + /** + * Changes the quick fix to be used + * @param quickFix + */ + public void setQuickFix(AbstractCodanCMarkerResolution quickFix) { + this.quickFix = quickFix; + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/SuggestedParenthesisQuickFixTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/SuggestedParenthesisQuickFixTest.java new file mode 100644 index 00000000000..09b0c15b1ce --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/SuggestedParenthesisQuickFixTest.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2009,2012 QNX Software Systems + * 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: + * QNX Software Systems (Alena Laskavaia) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.checkers.ui.quickfix; + +import java.io.File; +import java.io.FileInputStream; + +import org.eclipse.cdt.codan.core.tests.TestUtils; +import org.eclipse.cdt.codan.ui.AbstractCodanCMarkerResolution; +import org.eclipse.cdt.internal.ui.util.EditorUtility; + +/** + * Test for quick fix for suggested parenthesis + */ +@SuppressWarnings("restriction") +public class SuggestedParenthesisQuickFixTest extends QuickFixTestCase { + @Override + public AbstractCodanCMarkerResolution createQuickFix() { + return new SuggestedParenthesisQuickFix(); + } + + // main() { + // int a=1,b=3; + // if (b+a && a>b || b-a) b--; // error here + // } + public void testSimple() throws Exception { + loadcode(getAboveComment()); + String result = runQuickFixOneFile(); + assertContainedIn("(b+a && a>b)", result); //$NON-NLS-1$ + } + + // @file:header.h + // int foo(); + + // @file:main.c + // #include "header.h" + // main() { + // foo(); + // } + public void test2FilesExample() throws Exception { + /* + * There are no problems in either of the two files, so quick fix is not called. + */ + CharSequence[] code = getContents(2); + File f1 = loadcode(code[0].toString()); + File f2 = loadcode(code[1].toString()); + // lets pretend marker is found in main.c but fixes go in both files, + // to check do something like this + EditorUtility.openInEditor(f2); + runCodan(); + doRunQuickFix(); + String result_main = TestUtils.loadFile(new FileInputStream(f2)); + String result_header = TestUtils.loadFile(new FileInputStream(f1)); + assertContainedIn("foo", result_main); //$NON-NLS-1$ + assertContainedIn("foo", result_header); //$NON-NLS-1$ + } +} |