[hibernate-commits] Hibernate SVN: r19398 - in core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate: test and 1 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Fri May 7 03:10:14 EDT 2010


Author: stliu
Date: 2010-05-07 03:10:13 -0400 (Fri, 07 May 2010)
New Revision: 19398

Added:
   core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate/junit/FailureExpected.java
   core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate/junit/RequiresDialect.java
   core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate/junit/SkipForDialect.java
   core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate/test/annotations/
   core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate/test/annotations/HibernateTestCase.java
Log:
JBPAPP-4235 HHH-4822 Add @FailureExpected annotation to annotations and entitymananger modules to allow the skipping of tests

Added: core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate/junit/FailureExpected.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate/junit/FailureExpected.java	                        (rev 0)
+++ core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate/junit/FailureExpected.java	2010-05-07 07:10:13 UTC (rev 19398)
@@ -0,0 +1,51 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.junit;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotations used to mark a test as an expected failure.
+ *
+ * @author Hardy Ferentschik
+ * @author Steve Ebersole
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ ElementType.METHOD, ElementType.TYPE })
+public @interface FailureExpected {
+	/**
+	 * The key of a JIRA issue which covers this expected failure.
+	 * @return The jira issue key
+	 */
+	String jiraKey();
+
+	/**
+	 * A message explaining the reason for the expected failure.  Optional.
+	 * @return The reason
+	 */
+	String message() default "";
+}
\ No newline at end of file

Added: core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate/junit/RequiresDialect.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate/junit/RequiresDialect.java	                        (rev 0)
+++ core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate/junit/RequiresDialect.java	2010-05-07 07:10:13 UTC (rev 19398)
@@ -0,0 +1,54 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.junit;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.hibernate.dialect.Dialect;
+
+/**
+ * Annotation used to indicate that a test should be run only when run against the
+ * indicated dialects.
+ * 
+ * @author Hardy Ferentschik
+ */
+ at Target({ElementType.METHOD, ElementType.TYPE})
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface RequiresDialect {
+	/**
+	 * The dialects against which to run the test
+	 * @return The dialects
+	 */
+	Class<? extends Dialect>[] value();
+
+	/**
+	 * Used to indicate if the dialects should be matched strictly (classes equal) or
+	 * non-strictly (instanceof).
+	 * @return Should strict matching be used?
+	 */
+	boolean strictMatching() default false;
+}

Added: core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate/junit/SkipForDialect.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate/junit/SkipForDialect.java	                        (rev 0)
+++ core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate/junit/SkipForDialect.java	2010-05-07 07:10:13 UTC (rev 19398)
@@ -0,0 +1,68 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.junit;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.hibernate.dialect.Dialect;
+
+/**
+ * Annotation used to indicate that a test should be skipped when run against the
+ * indicated dialects.
+ *
+ * @author Hardy Ferentschik
+ * @author Steve Ebersole
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target({ ElementType.METHOD, ElementType.TYPE })
+public @interface SkipForDialect {
+	/**
+	 * The dialects against which to skip the test
+	 * @return The dialects
+	 */
+	Class<? extends Dialect>[] value();
+
+	/**
+	 * Used to indicate if the dialects should be matched strictly (classes equal) or
+	 * non-strictly (instanceof).
+	 * @return Should strict matching be used?
+	 */
+	boolean strictMatching() default false;
+
+	/**
+	 * Comment describing the reason for the skip.
+	 * @return The comment
+	 */
+	String comment() default "";
+
+	/**
+	 * The key of a JIRA issue which covers the reason for this skip.  Eventually we should make this
+	 * a requirement.
+	 * @return The jira issue key
+	 */
+	String jiraKey() default "";
+}
\ No newline at end of file

Added: core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate/test/annotations/HibernateTestCase.java
===================================================================
--- core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate/test/annotations/HibernateTestCase.java	                        (rev 0)
+++ core/branches/Branch_3_3_2_GA_CP/testing/src/main/java/org/hibernate/test/annotations/HibernateTestCase.java	2010-05-07 07:10:13 UTC (rev 19398)
@@ -0,0 +1,363 @@
+// $Id: HibernateTestCase.java 18858 2010-02-23 12:57:17Z hardy.ferentschik $
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.test.annotations;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.TestCase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.cfg.Configuration;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.jdbc.Work;
+import org.hibernate.junit.FailureExpected;
+import org.hibernate.junit.RequiresDialect;
+import org.hibernate.junit.SkipForDialect;
+import org.hibernate.junit.SkipLog;
+import org.hibernate.tool.hbm2ddl.SchemaExport;
+import org.hibernate.util.StringHelper;
+
+/**
+ * A base class for all tests.
+ *
+ * @author Emmnauel Bernand
+ * @author Hardy Ferentschik
+ */
+public abstract class HibernateTestCase extends TestCase {
+
+	public static final Logger log = LoggerFactory.getLogger( HibernateTestCase.class );
+
+	protected static Configuration cfg;
+	private static Class<?> lastTestClass;
+
+
+	/**
+	 * Flag indicating whether the test should be run or skipped.
+	 */
+	private boolean runTest = true;
+
+	/**
+	 * List of required dialect for the current {@code runMethod}. If the list is empty any dialect is allowed.
+	 * Otherwise the current dialect or a superclass of the current dialect must be in the list.
+	 */
+	private final Set<Class<? extends Dialect>> requiredDialectList = new HashSet<Class<? extends Dialect>>();
+
+	/**
+	 * List of dialects for which the current {@code runMethod} should be skipped.
+	 */
+	private final Set<Class<? extends Dialect>> skipForDialectList = new HashSet<Class<? extends Dialect>>();
+
+	public HibernateTestCase() {
+		super();
+	}
+
+	public HibernateTestCase(String x) {
+		super( x );
+	}
+
+	@Override
+	public void runBare() throws Throwable {
+		Method runMethod = findTestMethod();
+
+		final Skip skip = determineSkipByDialect( Dialect.getDialect(), runMethod );
+		if ( skip != null ) {
+			reportSkip( skip );
+			return;
+		}
+
+		setUp();
+		try {
+			runTest();
+		}
+		finally {
+			tearDown();
+		}
+	}
+
+	@Override
+	protected void runTest() throws Throwable {
+		Method runMethod = findTestMethod();
+		FailureExpected failureExpected = locateAnnotation( FailureExpected.class, runMethod );
+		try {
+			super.runTest();
+			if ( failureExpected != null ) {
+				throw new FailureExpectedTestPassedException();
+			}
+		}
+		catch ( FailureExpectedTestPassedException t ) {
+			closeResources();
+			throw t;
+		}
+		catch ( Throwable t ) {
+			if ( t instanceof InvocationTargetException ) {
+				t = ( ( InvocationTargetException ) t ).getTargetException();
+			}
+			if ( t instanceof IllegalAccessException ) {
+				t.fillInStackTrace();
+			}
+			closeResources();
+			if ( failureExpected != null ) {
+				StringBuilder builder = new StringBuilder();
+				if ( StringHelper.isNotEmpty( failureExpected.message() ) ) {
+					builder.append( failureExpected.message() );
+				}
+				else {
+					builder.append( "ignoring @FailureExpected test" );
+				}
+				builder.append( " (" )
+						.append( failureExpected.jiraKey() )
+						.append( ")" );
+				SkipLog.LOG.warn( builder.toString(), t );
+			}
+			else {
+				throw t;
+			}
+		}
+	}
+
+	@Override
+	protected void setUp() throws Exception {
+		if ( cfg == null || lastTestClass != getClass() ) {
+			buildConfiguration();
+			lastTestClass = getClass();
+		}
+		else {
+			runSchemaGeneration();
+		}
+	}
+
+	@Override
+	protected void tearDown() throws Exception {
+		runSchemaDrop();
+		handleUnclosedResources();
+	}
+
+	protected static class Skip {
+		private final String reason;
+		private final String testDescription;
+
+		public Skip(String reason, String testDescription) {
+			this.reason = reason;
+			this.testDescription = testDescription;
+		}
+	}
+
+	protected final Skip determineSkipByDialect(Dialect dialect, Method runMethod) {
+		// skips have precedence, so check them first
+		SkipForDialect skipForDialectAnn = locateAnnotation( SkipForDialect.class, runMethod );
+		if ( skipForDialectAnn != null ) {
+			for ( Class<? extends Dialect> dialectClass : skipForDialectAnn.value() ) {
+				if ( skipForDialectAnn.strictMatching() ) {
+					if ( dialectClass.equals( dialect.getClass() ) ) {
+						return buildSkip( dialect, skipForDialectAnn.comment(), skipForDialectAnn.jiraKey() );
+					}
+				}
+				else {
+					if ( dialectClass.isInstance( dialect ) ) {
+						return buildSkip( dialect, skipForDialectAnn.comment(), skipForDialectAnn.jiraKey() );
+					}
+				}
+			}
+		}
+
+		// then check against the requires
+		RequiresDialect requiresDialectAnn = locateAnnotation( RequiresDialect.class, runMethod );
+		if ( requiresDialectAnn != null ) {
+			for ( Class<? extends Dialect> dialectClass : requiresDialectAnn.value() ) {
+				if ( requiresDialectAnn.strictMatching() ) {
+					if ( dialectClass.equals( dialect.getClass() ) ) {
+						return buildSkip( dialect, null, null );
+					}
+				}
+				else {
+					if ( dialectClass.isInstance( dialect ) ) {
+						return buildSkip( dialect, null, null );
+					}
+				}
+			}
+		}
+
+		return null;
+	}
+
+	protected <T extends Annotation> T locateAnnotation(Class<T> annotationClass, Method runMethod) {
+		T annotation = runMethod.getAnnotation( annotationClass );
+		if ( annotation == null ) {
+			annotation = getClass().getAnnotation( annotationClass );
+		}
+		if ( annotation == null ) {
+			annotation = runMethod.getDeclaringClass().getAnnotation( annotationClass );
+		}
+		return annotation;
+	}
+
+	protected Skip buildSkip(Dialect dialect, String comment, String jiraKey) {
+		StringBuilder buffer = new StringBuilder();
+		buffer.append( "skipping database-specific test [" );
+		buffer.append( fullTestName() );
+		buffer.append( "] for dialect [" );
+		buffer.append( dialect.getClass().getName() );
+		buffer.append( ']' );
+
+		if ( StringHelper.isNotEmpty( comment ) ) {
+			buffer.append( "; " ).append( comment );
+		}
+
+		if ( StringHelper.isNotEmpty( jiraKey ) ) {
+			buffer.append( " (" ).append( jiraKey ).append( ')' );
+		}
+
+		return new Skip( buffer.toString(), null );
+	}
+
+	public String fullTestName() {
+		return this.getClass().getName() + "#" + this.getName();
+	}
+
+	protected boolean runForCurrentDialect() {
+		boolean runTestForCurrentDialect = true;
+
+		// check whether the current dialect is assignableFrom from any of the specified required dialects.
+		for ( Class<? extends Dialect> dialect : requiredDialectList ) {
+			if ( dialect.isAssignableFrom( Dialect.getDialect().getClass() ) ) {
+				runTestForCurrentDialect = true;
+				break;
+			}
+			runTestForCurrentDialect = false;
+		}
+
+		// check whether the current dialect is assignableFrom from any of the specified skip for dialects.
+		for ( Class<? extends Dialect> dialect : skipForDialectList ) {
+			if ( dialect.isAssignableFrom( Dialect.getDialect().getClass() ) ) {
+				runTestForCurrentDialect = false;
+				break;
+			}
+			runTestForCurrentDialect = true;
+		}
+
+		return runTestForCurrentDialect;
+	}
+
+	private Method findTestMethod() {
+		String fName = getName();
+		assertNotNull( fName );
+		Method runMethod = null;
+		try {
+			runMethod = getClass().getMethod( fName );
+		}
+		catch ( NoSuchMethodException e ) {
+			fail( "Method \"" + fName + "\" not found" );
+		}
+		if ( !Modifier.isPublic( runMethod.getModifiers() ) ) {
+			fail( "Method \"" + fName + "\" should be public" );
+		}
+		return runMethod;
+	}
+
+	protected abstract void buildConfiguration() throws Exception;
+
+	protected abstract Class<?>[] getAnnotatedClasses();
+
+	protected String[] getMappings() {
+		return new String[]{};
+	}
+
+	protected abstract void handleUnclosedResources();
+
+	protected abstract void closeResources();
+
+	protected String[] getAnnotatedPackages() {
+		return new String[] { };
+	}
+
+	protected String[] getXmlFiles() {
+		return new String[] { };
+	}
+
+	protected Dialect getDialect() {
+		return Dialect.getDialect();
+	}
+
+	protected static void setCfg(Configuration cfg) {
+		HibernateTestCase.cfg = cfg;
+	}
+
+	protected static Configuration getCfg() {
+		return cfg;
+	}
+
+	protected void configure(Configuration cfg) {
+	}
+
+	protected boolean recreateSchema() {
+		return true;
+	}
+
+	protected void runSchemaGeneration() {
+		SchemaExport export = new SchemaExport( cfg );
+		export.create( true, true );
+	}
+
+	protected void runSchemaDrop() {
+		SchemaExport export = new SchemaExport( cfg );
+		export.drop( true, true );
+	}
+
+	private void reportSkip(Skip skip) {
+		reportSkip( skip.reason, skip.testDescription );
+	}
+
+	protected void reportSkip(String reason, String testDescription) {
+		StringBuilder builder = new StringBuilder();
+		builder.append( "*** skipping test [" );
+		builder.append( fullTestName() );
+		builder.append( "] - " );
+		builder.append( testDescription );
+		builder.append( " : " );
+		builder.append( reason );
+		SkipLog.LOG.warn( builder.toString() );
+	}
+
+	public class RollbackWork implements Work {
+
+		public void execute(Connection connection) throws SQLException {
+			connection.rollback();
+		}
+	}
+
+	private static class FailureExpectedTestPassedException extends Exception {
+		public FailureExpectedTestPassedException() {
+			super( "Test marked as @FailureExpected, but did not fail!" );
+		}
+	}
+}



More information about the hibernate-commits mailing list