Author: kmalhi
Date: Fri Jul 2 00:58:50 2010
New Revision: 959824
URL: http://svn.apache.org/viewvc?rev=959824&view=rev
Log:
A custom JUnit Runner to run tests involving OpenEjb validation.
Added:
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/rules/InvokeMethod.java
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/rules/Keys.java
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/rules/ValidationRunner.java
Added:
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/rules/InvokeMethod.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/rules/InvokeMethod.java?rev=959824&view=auto
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/rules/InvokeMethod.java
(added)
+++
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/rules/InvokeMethod.java
Fri Jul 2 00:58:50 2010
@@ -0,0 +1,106 @@
+package org.apache.openejb.config.rules;
+
+import static
org.apache.openejb.config.rules.ValidationAssertions.assertFailures;
+import static org.junit.Assert.fail;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.ResourceBundle;
+import java.util.Set;
+
+import org.apache.openejb.assembler.classic.Assembler;
+import org.apache.openejb.assembler.classic.SecurityServiceInfo;
+import org.apache.openejb.assembler.classic.TransactionServiceInfo;
+import org.apache.openejb.config.ConfigurationFactory;
+import org.apache.openejb.config.ValidationFailedException;
+import org.apache.openejb.jee.EjbJar;
+import org.apache.openejb.util.Join;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+/**
+ * This Statement is the one which runs the test.
+ *
+ */
+public class InvokeMethod extends Statement {
+ private ConfigurationFactory config;
+ private Assembler assembler;
+ // The test method
+ private final FrameworkMethod testMethod;
+ // The TestCase instance
+ private Object target;
+ // These are all the keys defined in
org.apache.openejb.config.rules.Messages.properties
+ private static Set<String> allKeys;
+ static {
+ ResourceBundle bundle =
ResourceBundle.getBundle("org.apache.openejb.config.rules.Messages");
+ allKeys = bundle.keySet();
+ }
+
+ public InvokeMethod(FrameworkMethod testMethod, Object target) {
+ this.testMethod = testMethod;
+ this.target = target;
+ }
+
+ @Override
+ public void evaluate() throws Throwable {
+ List<String> expectedKeys = validateKeys();
+ setUp();
+ Object obj = testMethod.invokeExplosively(target);
+ if (obj instanceof EjbJar) {
+ EjbJar ejbJar = (EjbJar) obj;
+ try {
+ assembler.createApplication(config.configureApplication(ejbJar));
+ fail("A ValidationFailedException should have been thrown");
+ } catch (ValidationFailedException vfe) {
+ assertFailures(expectedKeys, vfe);
+ }
+ }
+ tearDown();
+ }
+
+ private void setUp() throws Exception {
+ config = new ConfigurationFactory();
+ assembler = new Assembler();
+
assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class));
+
assembler.createSecurityService(config.configureService(SecurityServiceInfo.class));
+ }
+
+ private void tearDown() {
+ }
+
+ /**
+ * Tests to see if the keys specified in the @Keys annotation are also
available in the org.apache.openejb.config.rules.Messages.properties file. If
there are any invalid keys,
+ * then it throws an exception and causes the test to error out. If all the
keys are valid, then it writes those keys to a file. This list of keys can then
be compared with all
+ * the Keys in org.apache.openejb.config.rules.Messages.properties and one
can then find out the "test coverage" of the keys i.e. this tool can be used to
find keys for which
+ * tests have not yet been written
+ *
+ * @return
+ * @throws Exception
+ */
+ private List<String> validateKeys() throws Exception {
+ Keys annotation = testMethod.getAnnotation(Keys.class);
+ String[] keys = annotation.value();
+ ArrayList<String> wrongKeys = new ArrayList<String>();
+ for (String key : keys) {
+ if (allKeys.contains("1." + key)) {
+ continue;
+ } else {
+ wrongKeys.add(key);
+ }
+ }
+ if (wrongKeys.isEmpty()) {
+ return Arrays.asList(keys);
+ } else {
+ String commaDelimitedKeys = Join.join(",", wrongKeys);
+ throw new Exception("The following keys listed in the @Keys annotation
on the method " + testMethod.getName() + "() of " +
testMethod.getMethod().getDeclaringClass()
+ + " are invalid : " + commaDelimitedKeys + " . Only keys listed in
org.apache.openejb.config.rules.Messages.properties are allowed to be used in
this annotation. ");
+ }
+ }
+}
Added:
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/rules/Keys.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/rules/Keys.java?rev=959824&view=auto
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/rules/Keys.java
(added)
+++
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/rules/Keys.java
Fri Jul 2 00:58:50 2010
@@ -0,0 +1,14 @@
+package org.apache.openejb.config.rules;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+/**
+ * Used to specify the keys being tested.
+ */
+...@target(ElementType.METHOD)
+...@retention(RetentionPolicy.RUNTIME)
+public @interface Keys {
+ String[] value();
+}
Added:
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/rules/ValidationRunner.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/rules/ValidationRunner.java?rev=959824&view=auto
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/rules/ValidationRunner.java
(added)
+++
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/rules/ValidationRunner.java
Fri Jul 2 00:58:50 2010
@@ -0,0 +1,71 @@
+package org.apache.openejb.config.rules;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.internal.runners.model.ReflectiveCallable;
+import org.junit.internal.runners.statements.Fail;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.Statement;
+
+/**
+ * This class is created specifically to write tests which test OpenEjb
validation code. Specifically, it is used to check the usage of keys defined in
+ * org.apache.openejb.config.rules.Messages.properties. To use this runner,
simply annotate your test case with @RunWith(ValidationRunner.class). Here are
some things to keep in
+ * mind when writing tests: 1. A test method needs to be annotated with
org.apache.openejb.config.rules.Keys instead of the org.junit.Test 2. Any usage
of the @Test annotation will
+ * be ignored 3. If the @Keys and @Test annotation are used together on a test
method, then the TestCase will error out 4. Every test method should create a
EjbJar and return it
+ * from the method. It should list the keys being tested in the @Keys
annotation 5. The runner will invoke the test method and use the Assembler and
ConfigurationFactory to create
+ * the application 6. This will kick off validation and this Runner will catch
ValidationFailureException and make sure that all the keys specified in the
@Keys annotation show up
+ * in the ValidationFailureException 7. If the keys listed in the @Keys
annotation match the keys found in the ValidationFailureException, the test
passes, else the test fails. 8.
+ * This Runner also validates that the keys specified in the @Keys annotation
are also available in the org.apache.openejb.config.rules.Messages.properties
file. If the key is not
+ * found, then the Runner throws and exception resulting in your test case not
being allowed to run.
+ */
+public class ValidationRunner extends BlockJUnit4ClassRunner {
+ public ValidationRunner(Class<?> klass) throws InitializationError {
+ super(klass);
+ }
+
+ /**
+ * Flags an error if you have annotated a test with both @Test and @Keys.
Any method annotated with @Test will be ignored anyways.
+ */
+ @Override
+ protected void collectInitializationErrors(List<Throwable> errors) {
+ super.collectInitializationErrors(errors);
+ List<FrameworkMethod> methodsAnnotatedWithKeys =
getTestClass().getAnnotatedMethods(Keys.class);
+ for (FrameworkMethod frameworkMethod : methodsAnnotatedWithKeys) {
+ if (frameworkMethod.getAnnotation(Test.class) != null) {
+ String gripe = "The method " + frameworkMethod.getName() + "() can
only be annotated with @Keys";
+ errors.add(new Exception(gripe));
+ }
+ }
+ }
+
+ @Override
+ protected Statement methodBlock(FrameworkMethod method) {
+ Object test;
+ try {
+ test = new ReflectiveCallable() {
+ @Override
+ protected Object runReflectiveCall() throws Throwable {
+ return createTest();
+ }
+ }.run();
+ } catch (Throwable e) {
+ return new Fail(e);
+ }
+ Statement statement = new InvokeMethod(method, test);
+ statement = withBefores(method, test, statement);
+ statement = withAfters(method, test, statement);
+ return statement;
+ }
+
+ /**
+ * By default JUnit includes all methods annotated with @Test. This method
only allows methods annotated with @Keys to be included in the list of methods
to be run in a TestCase.
+ * Any @Test methods will be ignored
+ */
+ @Override
+ protected List<FrameworkMethod> computeTestMethods() {
+ return getTestClass().getAnnotatedMethods(Keys.class);
+ }
+}