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