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

patterntesting.runtime.junit.CloneableTester Maven / Gradle / Ivy

Go to download

PatternTesting Runtime (patterntesting-rt) is the runtime component for the PatternTesting framework. It provides the annotations and base classes for the PatternTesting testing framework (e.g. patterntesting-check, patterntesting-concurrent or patterntesting-exception) but can be also used standalone for classpath monitoring or profiling. It uses AOP and AspectJ to perform this feat.

There is a newer version: 2.4.0
Show newest version
/*
 * $Id: CloneableTester.java,v 1.13 2014/01/04 19:28:54 oboehm Exp $
 *
 * Copyright (c) 2010 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 06.08.2010 by oliver ([email protected])
 */

package patterntesting.runtime.junit;

import java.lang.reflect.*;
import java.util.*;

import org.slf4j.*;

import patterntesting.runtime.exception.DetailedAssertionError;
import patterntesting.runtime.monitor.ClasspathMonitor;

/**
 * This tester checks class which implements Clonable and has therefore
 * the clone method implemented. According {@link Object#clone()} the
 * following conditions should be true:
 * 
*
 * x.clone() != x
* will be true, and that the expression: *
*
 * x.clone().getClass() == x.getClass()
* will be true, but these are not absolute requirements. * While it is typically the case that: *
*
 * x.clone().equals(x)
* will be true, this is not an absolute requirement. *

* So the equals method will be only checked if it is overwritten. *
* NOTE: In the future this class will be perhaps part of the ObjectTester * class. *
* Before v1.1 the methods are named "checkCloning". Since 1.1 these * methods will have now an "assert" prefix ("assertCloning"). * * @author oliver * @since 1.0.2 (06.08.2010) */ public final class CloneableTester { private static final Logger log = LoggerFactory.getLogger(CloneableTester.class); private static final ClasspathMonitor classpathMonitor = ClasspathMonitor.getInstance(); /** Utility class - no need to instantiate it. */ private CloneableTester() {} /** * Check cloning. * * @param clazz the clazz * @since 1.1 */ public static void assertCloning(final Class clazz) { try { assertCloning(clazz.newInstance()); } catch (InstantiationException e) { throw new AssertionError("can't instantiate " + clazz + ":" + e); } catch (IllegalAccessException e) { throw new AssertionError("can't access " + clazz + ":" + e); } } /** * We call the clone method of the given orig paramter.Because the * clone method is normally "protected" we use reflection to call it. * Then we compare the orig and cloned object which should be equals. * * @param orig the original object * @since 1.1 */ public static void assertCloning(final Cloneable orig) { Cloneable clone = getCloneOf(orig); if (ObjectTester.hasEqualsDeclared(orig.getClass())) { ObjectTester.assertEquals(orig, clone); } } /** * Gets the clone of the given Cloneable object. * * @param orig the orig * @return the clone of * @throws AssertionError the assertion error */ public static Cloneable getCloneOf(final Cloneable orig) throws AssertionError { try { Method cloneMethod = getPublicCloneMethod(orig.getClass()); Cloneable clone = (Cloneable) cloneMethod.invoke(orig); if (clone == orig) { throw new AssertionError(clone + " must have another reference as original object"); } return clone; } catch (SecurityException e) { throw new DetailedAssertionError("can't access clone method of " + orig.getClass(), e); } catch (IllegalAccessException e) { throw new DetailedAssertionError("can't access clone method of " + orig.getClass(), e); } catch (InvocationTargetException e) { throw new DetailedAssertionError("clone of " + orig.getClass() + " failed", e); } } private static Method getPublicCloneMethod(final Class cloneClass) throws AssertionError { try { return cloneClass.getMethod("clone"); } catch (NoSuchMethodException nsme) { if (hasCloneMethod(cloneClass)) { throw new AssertionError("clone() is not public in " + cloneClass); } AssertionError error = new AssertionError("no clone method found in " + cloneClass); error.initCause(nsme); throw error; } } private static boolean hasCloneMethod(final Class cloneClass) { try { Method m = cloneClass.getDeclaredMethod("clone"); if (log.isTraceEnabled()) { log.trace(m + " found in " + cloneClass); } return true; } catch (NoSuchMethodException e) { return false; } } /** * Check for each class in the given collection if it can be cloned * correct. * * @param classes a collection of classes to be checked * @since 1.1 */ public static void assertCloning(final Collection> classes) { for (Class clazz : classes) { assertCloning(clazz); } } /** * Check for each class in the given package if it can be cloned * correct. *
* To get a name of a package call {@link Package#getPackage(String)}. * But be sure that you can't get null as result. In this case * use {@link #assertCloningOfPackage(String)}. * * @param pkg the package e.g. "patterntesting.runtime" * @see #assertCloningOfPackage(String) * @since 1.1 */ public static void assertCloning(final Package pkg) { assert pkg!= null; assertCloningOfPackage(pkg.getName()); } /** * Check for each class in the given package if it can be cloned * correct. * * @param packageName the package name e.g. "patterntesting.runtime" * @since 1.1 */ public static void assertCloningOfPackage(final String packageName) { assert packageName != null; Collection> cloneables = getCloneableClasses(packageName); assertCloning(cloneables); } /** * Check for each class in the given package if the clone method is * implemented correct. * * @param packageName the package name e.g. "patterntesting.runtime" * @param excluded classes which should be excluded from the check * @see #assertCloningOfPackage(String) * @since 1.1 */ @SuppressWarnings("unchecked") public static void assertCloningOfPackage(final String packageName, final Class... excluded) { List> excludedList = Arrays.asList((Class[]) excluded); assertCloningOfPackage(packageName, excludedList); } /** * Check for each class in the given package if the clone method is * implemented correct. * * @param packageName the package name e.g. "patterntesting.runtime" * @param excluded classes which should be excluded from the check * @see #assertCloningOfPackage(String) * @since 1.1 */ public static void assertCloningOfPackage(final String packageName, final List> excluded) { Collection> classes = getCloneableClasses(packageName); log.debug(excluded + " will be excluded from check"); ObjectTester.removeClasses(classes, excluded); assertCloning(classes); } private static Collection> getCloneableClasses(final String packageName) { Collection> cloneables = classpathMonitor.getClassList(packageName, Cloneable.class); return cloneables; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy