All Downloads are FREE. Search and download functionalities are using the official Maven repository.

patterntesting.check.runtime.PublicForTestingAspect.aj Maven / Gradle / Ivy

Go to download

PatternTesting Check.RT (patterntesting-check-rt) provides different runtime checks of known anti patterns (like using null values as arguments or return values) but provides also a test framework for better testing.

There is a newer version: 2.4.0
Show newest version
/**
 * $Id: PublicForTestingAspect.aj,v 1.1 2011/12/22 17:15:11 oboehm Exp $
 *
 * Copyright (c) 2009 by Oliver Boehm
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express orimplied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * (c)reated 18.03.2009 by oliver ([email protected])
 */
package patterntesting.check.runtime;

import junit.framework.TestCase;

import org.aspectj.lang.*;
import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.junit.*;

import patterntesting.annotation.check.ct.*;
import patterntesting.annotation.check.runtime.*;
import patterntesting.runtime.util.*;

/**
 * Methods and constructors marked as "@PublicForTesting" should be only called
 * by test methods or by the class itself. Test methods are recognized by
 * the @Test annotation (from JUnit) or @OnlyForTesting annotation.
 *
 * @author oliver
 * @since 18.03.2009
 * @version $Revision: 1.1 $
 */
public aspect PublicForTestingAspect {
    
    /**
     * JUnit3 test or setup/teardown methods.b
     */
    private pointcut belowJUnit3Methods() :
        cflowbelow(execution(public void TestCase+.test*()))
        || cflowbelow(execution(* TestCase+.setUp()))
        || cflowbelow(execution(* TestCase+.tearDown()))
        ;

    /**
     * JUnit4 test or setup/teardown methods.
     */
    private pointcut belowJUnit4Methods() :
        cflowbelow(execution(@Test * *..*()))
        || cflowbelow(execution(@Before * *..*()))
        || cflowbelow(execution(@BeforeClass * *..*()))
        || cflowbelow(execution(@After * *..*()))
        || cflowbelow(execution(@AfterClass * *..*()))
        ;

    /**
     * JUnit test or setup/teardown methods and methods marked with 
     * @OnlyForTesting.
     */
    private pointcut belowTestMethods() :
        belowJUnit3Methods() || belowJUnit4Methods()
        || cflowbelow(execution(@OnlyForTesting * *..*()))
        || cflowbelow(execution(@OnlyForTesting *..new()))
        || cflowbelow(@within(OnlyForTesting))
        ;

    /**
     * All methods and constructors annotated with "@PublicForTesting" should
     * be called only from test methods or from the class itself.
     */
    public pointcut applicationCode() :
        (call(@PublicForTesting * *..*(..))
            || call(@PublicForTesting *..new(..)))
        && !belowTestMethods()
        ;

    /**
     * We check the caller hierarchy after the pointcut "applicationCode()"
     * because otherwise the stacktrace from the failed assert points to
     * the line before the call (and not the call itself).
     * As a result the protected method is executed but you see the
     * AssertionError afterwards.
     */
    @SuppressAjWarnings({"adviceDidNotMatch"})
    after() : applicationCode()  {
        if (Assertions.enabled) {
            String caller = getCallerClassName();
            Signature sig = thisJoinPointStaticPart.getSignature();
            String self = sig.getDeclaringTypeName();
            assert self.equals(caller) :
                "only test methods or object itself may call "
                + JoinPointHelper.getAsShortString(thisJoinPoint);
        }
    }

    /**
     * The 4th stack element was experimentally guessed and my be wrong
     * in other circumstances. The 3rd stack element is this aspect
     * (PublicForTestingAspect) itself.
     *
     * @return the caller of the protected method (actually the caller of
     *         this aspect here)
     */
    private static String getCallerClassName() {
        Thread t = Thread.currentThread();
        StackTraceElement[] stacktrace = t.getStackTrace();
        return stacktrace[4].getClassName();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy