summaryrefslogtreecommitdiffstats
path: root/junit4/src/main/java/junit
diff options
context:
space:
mode:
Diffstat (limited to 'junit4/src/main/java/junit')
-rw-r--r--junit4/src/main/java/junit/extensions/ActiveTestSuite.java70
-rw-r--r--junit4/src/main/java/junit/extensions/RepeatedTest.java38
-rw-r--r--junit4/src/main/java/junit/extensions/TestDecorator.java43
-rw-r--r--junit4/src/main/java/junit/extensions/TestSetup.java42
-rw-r--r--junit4/src/main/java/junit/extensions/package-info.java4
-rw-r--r--junit4/src/main/java/junit/framework/Assert.java296
-rw-r--r--junit4/src/main/java/junit/framework/AssertionFailedError.java20
-rw-r--r--junit4/src/main/java/junit/framework/ComparisonCompactor.java72
-rw-r--r--junit4/src/main/java/junit/framework/ComparisonFailure.java52
-rw-r--r--junit4/src/main/java/junit/framework/JUnit4TestAdapter.java85
-rw-r--r--junit4/src/main/java/junit/framework/JUnit4TestAdapterCache.java81
-rw-r--r--junit4/src/main/java/junit/framework/JUnit4TestCaseFacade.java33
-rw-r--r--junit4/src/main/java/junit/framework/Protectable.java14
-rw-r--r--junit4/src/main/java/junit/framework/Test.java17
-rw-r--r--junit4/src/main/java/junit/framework/TestCase.java212
-rw-r--r--junit4/src/main/java/junit/framework/TestFailure.java58
-rw-r--r--junit4/src/main/java/junit/framework/TestListener.java23
-rw-r--r--junit4/src/main/java/junit/framework/TestResult.java169
-rw-r--r--junit4/src/main/java/junit/framework/TestSuite.java307
-rw-r--r--junit4/src/main/java/junit/framework/package-info.java4
-rw-r--r--junit4/src/main/java/junit/runner/BaseTestRunner.java318
-rw-r--r--junit4/src/main/java/junit/runner/TestRunListener.java19
-rw-r--r--junit4/src/main/java/junit/runner/Version.java18
-rw-r--r--junit4/src/main/java/junit/runner/Version.java.template18
-rw-r--r--junit4/src/main/java/junit/runner/logo.gifbin0 -> 964 bytes
-rw-r--r--junit4/src/main/java/junit/runner/package-info.java4
-rw-r--r--junit4/src/main/java/junit/runner/smalllogo.gifbin0 -> 883 bytes
-rw-r--r--junit4/src/main/java/junit/textui/ResultPrinter.java139
-rw-r--r--junit4/src/main/java/junit/textui/TestRunner.java203
-rw-r--r--junit4/src/main/java/junit/textui/package-info.java4
30 files changed, 2363 insertions, 0 deletions
diff --git a/junit4/src/main/java/junit/extensions/ActiveTestSuite.java b/junit4/src/main/java/junit/extensions/ActiveTestSuite.java
new file mode 100644
index 0000000..0623565
--- /dev/null
+++ b/junit4/src/main/java/junit/extensions/ActiveTestSuite.java
@@ -0,0 +1,70 @@
+package junit.extensions;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+/**
+ * A TestSuite for active Tests. It runs each
+ * test in a separate thread and waits until all
+ * threads have terminated.
+ * -- Aarhus Radisson Scandinavian Center 11th floor
+ */
+public class ActiveTestSuite extends TestSuite {
+ private volatile int fActiveTestDeathCount;
+
+ public ActiveTestSuite() {
+ }
+
+ public ActiveTestSuite(Class<? extends TestCase> theClass) {
+ super(theClass);
+ }
+
+ public ActiveTestSuite(String name) {
+ super (name);
+ }
+
+ public ActiveTestSuite(Class<? extends TestCase> theClass, String name) {
+ super(theClass, name);
+ }
+
+ @Override
+ public void run(TestResult result) {
+ fActiveTestDeathCount= 0;
+ super.run(result);
+ waitUntilFinished();
+ }
+
+ @Override
+ public void runTest(final Test test, final TestResult result) {
+ Thread t= new Thread() {
+ @Override
+ public void run() {
+ try {
+ // inlined due to limitation in VA/Java
+ //ActiveTestSuite.super.runTest(test, result);
+ test.run(result);
+ } finally {
+ ActiveTestSuite.this.runFinished();
+ }
+ }
+ };
+ t.start();
+ }
+
+ synchronized void waitUntilFinished() {
+ while (fActiveTestDeathCount < testCount()) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ return; // ignore
+ }
+ }
+ }
+
+ synchronized public void runFinished() {
+ fActiveTestDeathCount++;
+ notifyAll();
+ }
+} \ No newline at end of file
diff --git a/junit4/src/main/java/junit/extensions/RepeatedTest.java b/junit4/src/main/java/junit/extensions/RepeatedTest.java
new file mode 100644
index 0000000..3b687a5
--- /dev/null
+++ b/junit4/src/main/java/junit/extensions/RepeatedTest.java
@@ -0,0 +1,38 @@
+package junit.extensions;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+/**
+ * A Decorator that runs a test repeatedly.
+ *
+ */
+public class RepeatedTest extends TestDecorator {
+ private int fTimesRepeat;
+
+ public RepeatedTest(Test test, int repeat) {
+ super(test);
+ if (repeat < 0)
+ throw new IllegalArgumentException("Repetition count must be >= 0");
+ fTimesRepeat= repeat;
+ }
+
+ @Override
+ public int countTestCases() {
+ return super.countTestCases() * fTimesRepeat;
+ }
+
+ @Override
+ public void run(TestResult result) {
+ for (int i= 0; i < fTimesRepeat; i++) {
+ if (result.shouldStop())
+ break;
+ super.run(result);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "(repeated)";
+ }
+} \ No newline at end of file
diff --git a/junit4/src/main/java/junit/extensions/TestDecorator.java b/junit4/src/main/java/junit/extensions/TestDecorator.java
new file mode 100644
index 0000000..d9ae474
--- /dev/null
+++ b/junit4/src/main/java/junit/extensions/TestDecorator.java
@@ -0,0 +1,43 @@
+package junit.extensions;
+
+import junit.framework.Assert;
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+/**
+ * A Decorator for Tests. Use TestDecorator as the base class for defining new
+ * test decorators. Test decorator subclasses can be introduced to add behaviour
+ * before or after a test is run.
+ *
+ */
+public class TestDecorator extends Assert implements Test {
+ protected Test fTest;
+
+ public TestDecorator(Test test) {
+ fTest= test;
+ }
+
+ /**
+ * The basic run behaviour.
+ */
+ public void basicRun(TestResult result) {
+ fTest.run(result);
+ }
+
+ public int countTestCases() {
+ return fTest.countTestCases();
+ }
+
+ public void run(TestResult result) {
+ basicRun(result);
+ }
+
+ @Override
+ public String toString() {
+ return fTest.toString();
+ }
+
+ public Test getTest() {
+ return fTest;
+ }
+} \ No newline at end of file
diff --git a/junit4/src/main/java/junit/extensions/TestSetup.java b/junit4/src/main/java/junit/extensions/TestSetup.java
new file mode 100644
index 0000000..00dcd21
--- /dev/null
+++ b/junit4/src/main/java/junit/extensions/TestSetup.java
@@ -0,0 +1,42 @@
+package junit.extensions;
+
+import junit.framework.Protectable;
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+/**
+ * A Decorator to set up and tear down additional fixture state. Subclass
+ * TestSetup and insert it into your tests when you want to set up additional
+ * state once before the tests are run.
+ */
+public class TestSetup extends TestDecorator {
+
+ public TestSetup(Test test) {
+ super(test);
+ }
+
+ @Override
+ public void run(final TestResult result) {
+ Protectable p= new Protectable() {
+ public void protect() throws Exception {
+ setUp();
+ basicRun(result);
+ tearDown();
+ }
+ };
+ result.runProtected(this, p);
+ }
+
+ /**
+ * Sets up the fixture. Override to set up additional fixture state.
+ */
+ protected void setUp() throws Exception {
+ }
+
+ /**
+ * Tears down the fixture. Override to tear down the additional fixture
+ * state.
+ */
+ protected void tearDown() throws Exception {
+ }
+} \ No newline at end of file
diff --git a/junit4/src/main/java/junit/extensions/package-info.java b/junit4/src/main/java/junit/extensions/package-info.java
new file mode 100644
index 0000000..a1c5bb4
--- /dev/null
+++ b/junit4/src/main/java/junit/extensions/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Provides extended functionality for JUnit v3.x.
+ */
+package junit.extensions; \ No newline at end of file
diff --git a/junit4/src/main/java/junit/framework/Assert.java b/junit4/src/main/java/junit/framework/Assert.java
new file mode 100644
index 0000000..3dcc23d
--- /dev/null
+++ b/junit4/src/main/java/junit/framework/Assert.java
@@ -0,0 +1,296 @@
+package junit.framework;
+
+/**
+ * A set of assert methods. Messages are only displayed when an assert fails.
+ */
+
+public class Assert {
+ /**
+ * Protect constructor since it is a static only class
+ */
+ protected Assert() {
+ }
+
+ /**
+ * Asserts that a condition is true. If it isn't it throws
+ * an AssertionFailedError with the given message.
+ */
+ static public void assertTrue(String message, boolean condition) {
+ if (!condition)
+ fail(message);
+ }
+ /**
+ * Asserts that a condition is true. If it isn't it throws
+ * an AssertionFailedError.
+ */
+ static public void assertTrue(boolean condition) {
+ assertTrue(null, condition);
+ }
+ /**
+ * Asserts that a condition is false. If it isn't it throws
+ * an AssertionFailedError with the given message.
+ */
+ static public void assertFalse(String message, boolean condition) {
+ assertTrue(message, !condition);
+ }
+ /**
+ * Asserts that a condition is false. If it isn't it throws
+ * an AssertionFailedError.
+ */
+ static public void assertFalse(boolean condition) {
+ assertFalse(null, condition);
+ }
+ /**
+ * Fails a test with the given message.
+ */
+ static public void fail(String message) {
+ if (message == null) {
+ throw new AssertionFailedError();
+ }
+ throw new AssertionFailedError(message);
+ }
+ /**
+ * Fails a test with no message.
+ */
+ static public void fail() {
+ fail(null);
+ }
+ /**
+ * Asserts that two objects are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertEquals(String message, Object expected, Object actual) {
+ if (expected == null && actual == null)
+ return;
+ if (expected != null && expected.equals(actual))
+ return;
+ failNotEquals(message, expected, actual);
+ }
+ /**
+ * Asserts that two objects are equal. If they are not
+ * an AssertionFailedError is thrown.
+ */
+ static public void assertEquals(Object expected, Object actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two Strings are equal.
+ */
+ static public void assertEquals(String message, String expected, String actual) {
+ if (expected == null && actual == null)
+ return;
+ if (expected != null && expected.equals(actual))
+ return;
+ String cleanMessage= message == null ? "" : message;
+ throw new ComparisonFailure(cleanMessage, expected, actual);
+ }
+ /**
+ * Asserts that two Strings are equal.
+ */
+ static public void assertEquals(String expected, String actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two doubles are equal concerning a delta. If they are not
+ * an AssertionFailedError is thrown with the given message. If the expected
+ * value is infinity then the delta value is ignored.
+ */
+ static public void assertEquals(String message, double expected, double actual, double delta) {
+ if (Double.compare(expected, actual) == 0)
+ return;
+ if (!(Math.abs(expected-actual) <= delta))
+ failNotEquals(message, new Double(expected), new Double(actual));
+ }
+ /**
+ * Asserts that two doubles are equal concerning a delta. If the expected
+ * value is infinity then the delta value is ignored.
+ */
+ static public void assertEquals(double expected, double actual, double delta) {
+ assertEquals(null, expected, actual, delta);
+ }
+ /**
+ * Asserts that two floats are equal concerning a positive delta. If they
+ * are not an AssertionFailedError is thrown with the given message. If the
+ * expected value is infinity then the delta value is ignored.
+ */
+ static public void assertEquals(String message, float expected, float actual, float delta) {
+ if (Float.compare(expected, actual) == 0)
+ return;
+ if (!(Math.abs(expected - actual) <= delta))
+ failNotEquals(message, new Float(expected), new Float(actual));
+ }
+ /**
+ * Asserts that two floats are equal concerning a delta. If the expected
+ * value is infinity then the delta value is ignored.
+ */
+ static public void assertEquals(float expected, float actual, float delta) {
+ assertEquals(null, expected, actual, delta);
+ }
+ /**
+ * Asserts that two longs are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertEquals(String message, long expected, long actual) {
+ assertEquals(message, new Long(expected), new Long(actual));
+ }
+ /**
+ * Asserts that two longs are equal.
+ */
+ static public void assertEquals(long expected, long actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two booleans are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertEquals(String message, boolean expected, boolean actual) {
+ assertEquals(message, Boolean.valueOf(expected), Boolean.valueOf(actual));
+ }
+ /**
+ * Asserts that two booleans are equal.
+ */
+ static public void assertEquals(boolean expected, boolean actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two bytes are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertEquals(String message, byte expected, byte actual) {
+ assertEquals(message, new Byte(expected), new Byte(actual));
+ }
+ /**
+ * Asserts that two bytes are equal.
+ */
+ static public void assertEquals(byte expected, byte actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two chars are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertEquals(String message, char expected, char actual) {
+ assertEquals(message, new Character(expected), new Character(actual));
+ }
+ /**
+ * Asserts that two chars are equal.
+ */
+ static public void assertEquals(char expected, char actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two shorts are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertEquals(String message, short expected, short actual) {
+ assertEquals(message, new Short(expected), new Short(actual));
+ }
+ /**
+ * Asserts that two shorts are equal.
+ */
+ static public void assertEquals(short expected, short actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that two ints are equal. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertEquals(String message, int expected, int actual) {
+ assertEquals(message, new Integer(expected), new Integer(actual));
+ }
+ /**
+ * Asserts that two ints are equal.
+ */
+ static public void assertEquals(int expected, int actual) {
+ assertEquals(null, expected, actual);
+ }
+ /**
+ * Asserts that an object isn't null.
+ */
+ static public void assertNotNull(Object object) {
+ assertNotNull(null, object);
+ }
+ /**
+ * Asserts that an object isn't null. If it is
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertNotNull(String message, Object object) {
+ assertTrue(message, object != null);
+ }
+ /**
+ * Asserts that an object is null. If it isn't an {@link AssertionError} is
+ * thrown.
+ * Message contains: Expected: <null> but was: object
+ *
+ * @param object
+ * Object to check or <code>null</code>
+ */
+ static public void assertNull(Object object) {
+ String message = "Expected: <null> but was: " + String.valueOf(object);
+ assertNull(message, object);
+ }
+ /**
+ * Asserts that an object is null. If it is not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertNull(String message, Object object) {
+ assertTrue(message, object == null);
+ }
+ /**
+ * Asserts that two objects refer to the same object. If they are not
+ * an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertSame(String message, Object expected, Object actual) {
+ if (expected == actual)
+ return;
+ failNotSame(message, expected, actual);
+ }
+ /**
+ * Asserts that two objects refer to the same object. If they are not
+ * the same an AssertionFailedError is thrown.
+ */
+ static public void assertSame(Object expected, Object actual) {
+ assertSame(null, expected, actual);
+ }
+ /**
+ * Asserts that two objects do not refer to the same object. If they do
+ * refer to the same object an AssertionFailedError is thrown with the
+ * given message.
+ */
+ static public void assertNotSame(String message, Object expected, Object actual) {
+ if (expected == actual)
+ failSame(message);
+ }
+ /**
+ * Asserts that two objects do not refer to the same object. If they do
+ * refer to the same object an AssertionFailedError is thrown.
+ */
+ static public void assertNotSame(Object expected, Object actual) {
+ assertNotSame(null, expected, actual);
+ }
+
+ static public void failSame(String message) {
+ String formatted= "";
+ if (message != null)
+ formatted= message+" ";
+ fail(formatted+"expected not same");
+ }
+
+ static public void failNotSame(String message, Object expected, Object actual) {
+ String formatted= "";
+ if (message != null)
+ formatted= message+" ";
+ fail(formatted+"expected same:<"+expected+"> was not:<"+actual+">");
+ }
+
+ static public void failNotEquals(String message, Object expected, Object actual) {
+ fail(format(message, expected, actual));
+ }
+
+ public static String format(String message, Object expected, Object actual) {
+ String formatted= "";
+ if (message != null && message.length() > 0)
+ formatted= message+" ";
+ return formatted+"expected:<"+expected+"> but was:<"+actual+">";
+ }
+}
diff --git a/junit4/src/main/java/junit/framework/AssertionFailedError.java b/junit4/src/main/java/junit/framework/AssertionFailedError.java
new file mode 100644
index 0000000..0d7802c
--- /dev/null
+++ b/junit4/src/main/java/junit/framework/AssertionFailedError.java
@@ -0,0 +1,20 @@
+package junit.framework;
+
+/**
+ * Thrown when an assertion failed.
+ */
+public class AssertionFailedError extends AssertionError {
+
+ private static final long serialVersionUID= 1L;
+
+ public AssertionFailedError() {
+ }
+
+ public AssertionFailedError(String message) {
+ super(defaultString(message));
+ }
+
+ private static String defaultString(String message) {
+ return message == null ? "" : message;
+ }
+} \ No newline at end of file
diff --git a/junit4/src/main/java/junit/framework/ComparisonCompactor.java b/junit4/src/main/java/junit/framework/ComparisonCompactor.java
new file mode 100644
index 0000000..bbc3ba1
--- /dev/null
+++ b/junit4/src/main/java/junit/framework/ComparisonCompactor.java
@@ -0,0 +1,72 @@
+package junit.framework;
+
+public class ComparisonCompactor {
+
+ private static final String ELLIPSIS= "...";
+ private static final String DELTA_END= "]";
+ private static final String DELTA_START= "[";
+
+ private int fContextLength;
+ private String fExpected;
+ private String fActual;
+ private int fPrefix;
+ private int fSuffix;
+
+ public ComparisonCompactor(int contextLength, String expected, String actual) {
+ fContextLength= contextLength;
+ fExpected= expected;
+ fActual= actual;
+ }
+
+ public String compact(String message) {
+ if (fExpected == null || fActual == null || areStringsEqual())
+ return Assert.format(message, fExpected, fActual);
+
+ findCommonPrefix();
+ findCommonSuffix();
+ String expected= compactString(fExpected);
+ String actual= compactString(fActual);
+ return Assert.format(message, expected, actual);
+ }
+
+ private String compactString(String source) {
+ String result= DELTA_START + source.substring(fPrefix, source.length() - fSuffix + 1) + DELTA_END;
+ if (fPrefix > 0)
+ result= computeCommonPrefix() + result;
+ if (fSuffix > 0)
+ result= result + computeCommonSuffix();
+ return result;
+ }
+
+ private void findCommonPrefix() {
+ fPrefix= 0;
+ int end= Math.min(fExpected.length(), fActual.length());
+ for (; fPrefix < end; fPrefix++) {
+ if (fExpected.charAt(fPrefix) != fActual.charAt(fPrefix))
+ break;
+ }
+ }
+
+ private void findCommonSuffix() {
+ int expectedSuffix= fExpected.length() - 1;
+ int actualSuffix= fActual.length() - 1;
+ for (; actualSuffix >= fPrefix && expectedSuffix >= fPrefix; actualSuffix--, expectedSuffix--) {
+ if (fExpected.charAt(expectedSuffix) != fActual.charAt(actualSuffix))
+ break;
+ }
+ fSuffix= fExpected.length() - expectedSuffix;
+ }
+
+ private String computeCommonPrefix() {
+ return (fPrefix > fContextLength ? ELLIPSIS : "") + fExpected.substring(Math.max(0, fPrefix - fContextLength), fPrefix);
+ }
+
+ private String computeCommonSuffix() {
+ int end= Math.min(fExpected.length() - fSuffix + 1 + fContextLength, fExpected.length());
+ return fExpected.substring(fExpected.length() - fSuffix + 1, end) + (fExpected.length() - fSuffix + 1 < fExpected.length() - fContextLength ? ELLIPSIS : "");
+ }
+
+ private boolean areStringsEqual() {
+ return fExpected.equals(fActual);
+ }
+}
diff --git a/junit4/src/main/java/junit/framework/ComparisonFailure.java b/junit4/src/main/java/junit/framework/ComparisonFailure.java
new file mode 100644
index 0000000..5077993
--- /dev/null
+++ b/junit4/src/main/java/junit/framework/ComparisonFailure.java
@@ -0,0 +1,52 @@
+package junit.framework;
+
+/**
+ * Thrown when an assert equals for Strings failed.
+ *
+ * Inspired by a patch from Alex Chaffee mailto:alex@purpletech.com
+ */
+public class ComparisonFailure extends AssertionFailedError {
+ private static final int MAX_CONTEXT_LENGTH= 20;
+ private static final long serialVersionUID= 1L;
+
+ private String fExpected;
+ private String fActual;
+
+ /**
+ * Constructs a comparison failure.
+ * @param message the identifying message or null
+ * @param expected the expected string value
+ * @param actual the actual string value
+ */
+ public ComparisonFailure (String message, String expected, String actual) {
+ super (message);
+ fExpected= expected;
+ fActual= actual;
+ }
+
+ /**
+ * Returns "..." in place of common prefix and "..." in
+ * place of common suffix between expected and actual.
+ *
+ * @see Throwable#getMessage()
+ */
+ @Override
+ public String getMessage() {
+ return new ComparisonCompactor(MAX_CONTEXT_LENGTH, fExpected, fActual).compact(super.getMessage());
+ }
+
+ /**
+ * Gets the actual string value
+ * @return the actual string value
+ */
+ public String getActual() {
+ return fActual;
+ }
+ /**
+ * Gets the expected string value
+ * @return the expected string value
+ */
+ public String getExpected() {
+ return fExpected;
+ }
+} \ No newline at end of file
diff --git a/junit4/src/main/java/junit/framework/JUnit4TestAdapter.java b/junit4/src/main/java/junit/framework/JUnit4TestAdapter.java
new file mode 100644
index 0000000..a05a313
--- /dev/null
+++ b/junit4/src/main/java/junit/framework/JUnit4TestAdapter.java
@@ -0,0 +1,85 @@
+package junit.framework;
+
+import java.util.List;
+
+import org.junit.Ignore;
+import org.junit.runner.Describable;
+import org.junit.runner.Description;
+import org.junit.runner.Request;
+import org.junit.runner.Runner;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.Filterable;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.manipulation.Sortable;
+import org.junit.runner.manipulation.Sorter;
+
+public class JUnit4TestAdapter implements Test, Filterable, Sortable, Describable {
+ private final Class<?> fNewTestClass;
+
+ private final Runner fRunner;
+
+ private final JUnit4TestAdapterCache fCache;
+
+ public JUnit4TestAdapter(Class<?> newTestClass) {
+ this(newTestClass, JUnit4TestAdapterCache.getDefault());
+ }
+
+ public JUnit4TestAdapter(final Class<?> newTestClass,
+ JUnit4TestAdapterCache cache) {
+ fCache = cache;
+ fNewTestClass = newTestClass;
+ fRunner = Request.classWithoutSuiteMethod(newTestClass).getRunner();
+ }
+
+ public int countTestCases() {
+ return fRunner.testCount();
+ }
+
+ public void run(TestResult result) {
+ fRunner.run(fCache.getNotifier(result, this));
+ }
+
+ // reflective interface for Eclipse
+ public List<Test> getTests() {
+ return fCache.asTestList(getDescription());
+ }
+
+ // reflective interface for Eclipse
+ public Class<?> getTestClass() {
+ return fNewTestClass;
+ }
+
+ public Description getDescription() {
+ Description description= fRunner.getDescription();
+ return removeIgnored(description);
+ }
+
+ private Description removeIgnored(Description description) {
+ if (isIgnored(description))
+ return Description.EMPTY;
+ Description result = description.childlessCopy();
+ for (Description each : description.getChildren()) {
+ Description child= removeIgnored(each);
+ if (! child.isEmpty())
+ result.addChild(child);
+ }
+ return result;
+ }
+
+ private boolean isIgnored(Description description) {
+ return description.getAnnotation(Ignore.class) != null;
+ }
+
+ @Override
+ public String toString() {
+ return fNewTestClass.getName();
+ }
+
+ public void filter(Filter filter) throws NoTestsRemainException {
+ filter.apply(fRunner);
+ }
+
+ public void sort(Sorter sorter) {
+ sorter.apply(fRunner);
+ }
+} \ No newline at end of file
diff --git a/junit4/src/main/java/junit/framework/JUnit4TestAdapterCache.java b/junit4/src/main/java/junit/framework/JUnit4TestAdapterCache.java
new file mode 100644
index 0000000..26175c5
--- /dev/null
+++ b/junit4/src/main/java/junit/framework/JUnit4TestAdapterCache.java
@@ -0,0 +1,81 @@
+/**
+ *
+ */
+package junit.framework;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+import org.junit.runner.Description;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.junit.runner.notification.RunNotifier;
+
+public class JUnit4TestAdapterCache extends HashMap<Description, Test> {
+ private static final long serialVersionUID = 1L;
+ private static final JUnit4TestAdapterCache fInstance = new JUnit4TestAdapterCache();
+
+ public static JUnit4TestAdapterCache getDefault() {
+ return fInstance;
+ }
+
+ public Test asTest(Description description) {
+ if (description.isSuite())
+ return createTest(description);
+ else {
+ if (!containsKey(description))
+ put(description, createTest(description));
+ return get(description);
+ }
+ }
+
+ Test createTest(Description description) {
+ if (description.isTest())
+ return new JUnit4TestCaseFacade(description);
+ else {
+ TestSuite suite = new TestSuite(description.getDisplayName());
+ for (Description child : description.getChildren())
+ suite.addTest(asTest(child));
+ return suite;
+ }
+ }
+
+ public RunNotifier getNotifier(final TestResult result,
+ final JUnit4TestAdapter adapter) {
+ RunNotifier notifier = new RunNotifier();
+ notifier.addListener(new RunListener() {
+ @Override
+ public void testFailure(Failure failure) throws Exception {
+ result.addError(asTest(failure.getDescription()), failure.getException());
+ }
+
+ @Override
+ public void testFinished(Description description)
+ throws Exception {
+ result.endTest(asTest(description));
+ }
+
+ @Override
+ public void testStarted(Description description)
+ throws Exception {
+ result.startTest(asTest(description));
+ }
+ });
+ return notifier;
+ }
+
+ public List<Test> asTestList(Description description) {
+ if (description.isTest())
+ return Arrays.asList(asTest(description));
+ else {
+ List<Test> returnThis = new ArrayList<Test>();
+ for (Description child : description.getChildren()) {
+ returnThis.add(asTest(child));
+ }
+ return returnThis;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/junit4/src/main/java/junit/framework/JUnit4TestCaseFacade.java b/junit4/src/main/java/junit/framework/JUnit4TestCaseFacade.java
new file mode 100644
index 0000000..fd43822
--- /dev/null
+++ b/junit4/src/main/java/junit/framework/JUnit4TestCaseFacade.java
@@ -0,0 +1,33 @@
+/**
+ *
+ */
+package junit.framework;
+
+import org.junit.runner.Describable;
+import org.junit.runner.Description;
+
+public class JUnit4TestCaseFacade implements Test, Describable {
+ private final Description fDescription;
+
+ JUnit4TestCaseFacade(Description description) {
+ fDescription = description;
+ }
+
+ @Override
+ public String toString() {
+ return getDescription().toString();
+ }
+
+ public int countTestCases() {
+ return 1;
+ }
+
+ public void run(TestResult result) {
+ throw new RuntimeException(
+ "This test stub created only for informational purposes.");
+ }
+
+ public Description getDescription() {
+ return fDescription;
+ }
+} \ No newline at end of file
diff --git a/junit4/src/main/java/junit/framework/Protectable.java b/junit4/src/main/java/junit/framework/Protectable.java
new file mode 100644
index 0000000..e143237
--- /dev/null
+++ b/junit4/src/main/java/junit/framework/Protectable.java
@@ -0,0 +1,14 @@
+package junit.framework;
+
+/**
+ * A <em>Protectable</em> can be run and can throw a Throwable.
+ *
+ * @see TestResult
+ */
+public interface Protectable {
+
+ /**
+ * Run the the following method protected.
+ */
+ public abstract void protect() throws Throwable;
+} \ No newline at end of file
diff --git a/junit4/src/main/java/junit/framework/Test.java b/junit4/src/main/java/junit/framework/Test.java
new file mode 100644
index 0000000..a016ee8
--- /dev/null
+++ b/junit4/src/main/java/junit/framework/Test.java
@@ -0,0 +1,17 @@
+package junit.framework;
+
+/**
+ * A <em>Test</em> can be run and collect its results.
+ *
+ * @see TestResult
+ */
+public interface Test {
+ /**
+ * Counts the number of test cases that will be run by this test.
+ */
+ public abstract int countTestCases();
+ /**
+ * Runs a test and collects its result in a TestResult instance.
+ */
+ public abstract void run(TestResult result);
+} \ No newline at end of file
diff --git a/junit4/src/main/java/junit/framework/TestCase.java b/junit4/src/main/java/junit/framework/TestCase.java
new file mode 100644
index 0000000..b047ec9
--- /dev/null
+++ b/junit4/src/main/java/junit/framework/TestCase.java
@@ -0,0 +1,212 @@
+package junit.framework;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * A test case defines the fixture to run multiple tests. To define a test case<br/>
+ * <ol>
+ * <li>implement a subclass of <code>TestCase</code></li>
+ * <li>define instance variables that store the state of the fixture</li>
+ * <li>initialize the fixture state by overriding {@link #setUp()}</li>
+ * <li>clean-up after a test by overriding {@link #tearDown()}.</li>
+ * </ol>
+ * Each test runs in its own fixture so there
+ * can be no side effects among test runs.
+ * Here is an example:
+ * <pre>
+ * public class MathTest extends TestCase {
+ * protected double fValue1;
+ * protected double fValue2;
+ *
+ * protected void setUp() {
+ * fValue1= 2.0;
+ * fValue2= 3.0;
+ * }
+ * }
+ * </pre>
+ *
+ * For each test implement a method which interacts
+ * with the fixture. Verify the expected results with assertions specified
+ * by calling {@link junit.framework.Assert#assertTrue(String, boolean)} with a boolean.
+ * <pre>
+ * public void testAdd() {
+ * double result= fValue1 + fValue2;
+ * assertTrue(result == 5.0);
+ * }
+ * </pre>
+ *
+ * Once the methods are defined you can run them. The framework supports
+ * both a static type safe and more dynamic way to run a test.
+ * In the static way you override the runTest method and define the method to
+ * be invoked. A convenient way to do so is with an anonymous inner class.
+ * <pre>
+ * TestCase test= new MathTest("add") {
+ * public void runTest() {
+ * testAdd();
+ * }
+ * };
+ * test.run();
+ * </pre>
+ *
+ * The dynamic way uses reflection to implement {@link #runTest()}. It dynamically finds
+ * and invokes a method.
+ * In this case the name of the test case has to correspond to the test method
+ * to be run.
+ * <pre>
+ * TestCase test= new MathTest("testAdd");
+ * test.run();
+ * </pre>
+ *
+ * The tests to be run can be collected into a TestSuite. JUnit provides
+ * different <i>test runners</i> which can run a test suite and collect the results.
+ * A test runner either expects a static method <code>suite</code> as the entry
+ * point to get a test to run or it will extract the suite automatically.
+ * <pre>
+ * public static Test suite() {
+ * suite.addTest(new MathTest("testAdd"));
+ * suite.addTest(new MathTest("testDivideByZero"));
+ * return suite;
+ * }
+ * </pre>
+ * @see TestResult
+ * @see TestSuite
+ */
+public abstract class TestCase extends Assert implements Test {
+ /**
+ * the name of the test case
+ */
+ private String fName;
+
+ /**
+ * No-arg constructor to enable serialization. This method
+ * is not intended to be used by mere mortals without calling setName().
+ */
+ public TestCase() {
+ fName= null;
+ }
+ /**
+ * Constructs a test case with the given name.
+ */
+ public TestCase(String name) {
+ fName= name;
+ }
+ /**
+ * Counts the number of test cases executed by run(TestResult result).
+ */
+ public int countTestCases() {
+ return 1;
+ }
+ /**
+ * Creates a default TestResult object
+ *
+ * @see TestResult
+ */
+ protected TestResult createResult() {
+ return new TestResult();
+ }
+ /**
+ * A convenience method to run this test, collecting the results with a
+ * default TestResult object.
+ *
+ * @see TestResult
+ */
+ public TestResult run() {
+ TestResult result= createResult();
+ run(result);
+ return result;
+ }
+ /**
+ * Runs the test case and collects the results in TestResult.
+ */
+ public void run(TestResult result) {
+ result.run(this);
+ }
+ /**
+ * Runs the bare test sequence.
+ * @throws Throwable if any exception is thrown
+ */
+ public void runBare() throws Throwable {
+ Throwable exception= null;
+ setUp();
+ try {
+ runTest();
+ } catch (Throwable running) {
+ exception= running;
+ }
+ finally {
+ try {
+ tearDown();
+ } catch (Throwable tearingDown) {
+ if (exception == null) exception= tearingDown;
+ }
+ }
+ if (exception != null) throw exception;
+ }
+ /**
+ * Override to run the test and assert its state.
+ * @throws Throwable if any exception is thrown
+ */
+ protected void runTest() throws Throwable {
+ assertNotNull("TestCase.fName cannot be null", fName); // Some VMs crash when calling getMethod(null,null);
+ Method runMethod= null;
+ try {
+ // use getMethod to get all public inherited
+ // methods. getDeclaredMethods returns all
+ // methods of this class but excludes the
+ // inherited ones.
+ runMethod= getClass().getMethod(fName, (Class[])null);
+ } catch (NoSuchMethodException e) {
+ fail("Method \""+fName+"\" not found");
+ }
+ if (!Modifier.isPublic(runMethod.getModifiers())) {
+ fail("Method \""+fName+"\" should be public");
+ }
+
+ try {
+ runMethod.invoke(this);
+ }
+ catch (InvocationTargetException e) {
+ e.fillInStackTrace();
+ throw e.getTargetException();
+ }
+ catch (IllegalAccessException e) {
+ e.fillInStackTrace();
+ throw e;
+ }
+ }
+ /**
+ * Sets up the fixture, for example, open a network connection.
+ * This method is called before a test is executed.
+ */
+ protected void setUp() throws Exception {
+ }
+ /**
+ * Tears down the fixture, for example, close a network connection.
+ * This method is called after a test is executed.
+ */
+ protected void tearDown() throws Exception {
+ }
+ /**
+ * Returns a string representation of the test case
+ */
+ @Override
+ public String toString() {
+ return getName() + "(" + getClass().getName() + ")";
+ }
+ /**
+ * Gets the name of a TestCase
+ * @return the name of the TestCase
+ */
+ public String getName() {
+ return fName;
+ }
+ /**
+ * Sets the name of a TestCase
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ fName= name;
+ }
+}
diff --git a/junit4/src/main/java/junit/framework/TestFailure.java b/junit4/src/main/java/junit/framework/TestFailure.java
new file mode 100644
index 0000000..6662b1f
--- /dev/null
+++ b/junit4/src/main/java/junit/framework/TestFailure.java
@@ -0,0 +1,58 @@
+package junit.framework;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+
+/**
+ * A <code>TestFailure</code> collects a failed test together with
+ * the caught exception.
+ * @see TestResult
+ */
+public class TestFailure extends Object {
+ protected Test fFailedTest;
+ protected Throwable fThrownException;
+
+
+ /**
+ * Constructs a TestFailure with the given test and exception.
+ */
+ public TestFailure(Test failedTest, Throwable thrownException) {
+ fFailedTest= failedTest;
+ fThrownException= thrownException;
+ }
+ /**
+ * Gets the failed test.
+ */
+ public Test failedTest() {
+ return fFailedTest;
+ }
+ /**
+ * Gets the thrown exception.
+ */
+ public Throwable thrownException() {
+ return fThrownException;
+ }
+ /**
+ * Returns a short description of the failure.
+ */
+ @Override
+ public String toString() {
+ StringBuffer buffer= new StringBuffer();
+ buffer.append(fFailedTest+": "+fThrownException.getMessage());
+ return buffer.toString();
+ }
+ public String trace() {
+ StringWriter stringWriter= new StringWriter();
+ PrintWriter writer= new PrintWriter(stringWriter);
+ thrownException().printStackTrace(writer);
+ StringBuffer buffer= stringWriter.getBuffer();
+ return buffer.toString();
+ }
+ public String exceptionMessage() {
+ return thrownException().getMessage();
+ }
+ public boolean isFailure() {
+ return thrownException() instanceof AssertionFailedError;
+ }
+} \ No newline at end of file
diff --git a/junit4/src/main/java/junit/framework/TestListener.java b/junit4/src/main/java/junit/framework/TestListener.java
new file mode 100644
index 0000000..9b69443
--- /dev/null
+++ b/junit4/src/main/java/junit/framework/TestListener.java
@@ -0,0 +1,23 @@
+package junit.framework;
+
+/**
+ * A Listener for test progress
+ */
+public interface TestListener {
+ /**
+ * An error occurred.
+ */
+ public void addError(Test test, Throwable t);
+ /**
+ * A failure occurred.
+ */
+ public void addFailure(Test test, AssertionFailedError t);
+ /**
+ * A test ended.
+ */
+ public void endTest(Test test);
+ /**
+ * A test started.
+ */
+ public void startTest(Test test);
+} \ No newline at end of file
diff --git a/junit4/src/main/java/junit/framework/TestResult.java b/junit4/src/main/java/junit/framework/TestResult.java
new file mode 100644
index 0000000..5768e9a
--- /dev/null
+++ b/junit4/src/main/java/junit/framework/TestResult.java
@@ -0,0 +1,169 @@
+package junit.framework;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+
+/**
+ * A <code>TestResult</code> collects the results of executing
+ * a test case. It is an instance of the Collecting Parameter pattern.
+ * The test framework distinguishes between <i>failures</i> and <i>errors</i>.
+ * A failure is anticipated and checked for with assertions. Errors are
+ * unanticipated problems like an {@link ArrayIndexOutOfBoundsException}.
+ *
+ * @see Test
+ */
+public class TestResult extends Object {
+ protected List<TestFailure> fFailures;
+ protected List<TestFailure> fErrors;
+ protected List<TestListener> fListeners;
+ protected int fRunTests;
+ private boolean fStop;
+
+ public TestResult() {
+ fFailures= new ArrayList<TestFailure>();
+ fErrors= new ArrayList<TestFailure>();
+ fListeners= new ArrayList<TestListener>();
+ fRunTests= 0;
+ fStop= false;
+ }
+ /**
+ * Adds an error to the list of errors. The passed in exception
+ * caused the error.
+ */
+ public synchronized void addError(Test test, Throwable t) {
+ fErrors.add(new TestFailure(test, t));
+ for (TestListener each : cloneListeners())
+ each.addError(test, t);
+ }
+ /**
+ * Adds a failure to the list of failures. The passed in exception
+ * caused the failure.
+ */
+ public synchronized void addFailure(Test test, AssertionFailedError t) {
+ fFailures.add(new TestFailure(test, t));
+ for (TestListener each : cloneListeners())
+ each.addFailure(test, t);
+ }
+ /**
+ * Registers a TestListener
+ */
+ public synchronized void addListener(TestListener listener) {
+ fListeners.add(listener);
+ }
+ /**
+ * Unregisters a TestListener
+ */
+ public synchronized void removeListener(TestListener listener) {
+ fListeners.remove(listener);
+ }
+ /**
+ * Returns a copy of the listeners.
+ */
+ private synchronized List<TestListener> cloneListeners() {
+ List<TestListener> result= new ArrayList<TestListener>();
+ result.addAll(fListeners);
+ return result;
+ }
+ /**
+ * Informs the result that a test was completed.
+ */
+ public void endTest(Test test) {
+ for (TestListener each : cloneListeners())
+ each.endTest(test);
+ }
+ /**
+ * Gets the number of detected errors.
+ */
+ public synchronized int errorCount() {
+ return fErrors.size();
+ }
+ /**
+ * Returns an Enumeration for the errors
+ */
+ public synchronized Enumeration<TestFailure> errors() {
+ return Collections.enumeration(fErrors);
+ }
+
+
+ /**
+ * Gets the number of detected failures.
+ */
+ public synchronized int failureCount() {
+ return fFailures.size();
+ }
+ /**
+ * Returns an Enumeration for the failures
+ */
+ public synchronized Enumeration<TestFailure> failures() {
+ return Collections.enumeration(fFailures);
+ }
+
+ /**
+ * Runs a TestCase.
+ */
+ protected void run(final TestCase test) {
+ startTest(test);
+ Protectable p= new Protectable() {
+ public void protect() throws Throwable {
+ test.runBare();
+ }
+ };
+ runProtected(test, p);
+
+ endTest(test);
+ }
+ /**
+ * Gets the number of run tests.
+ */
+ public synchronized int runCount() {
+ return fRunTests;
+ }
+ /**
+ * Runs a TestCase.
+ */
+ public void runProtected(final Test test, Protectable p) {
+ try {
+ p.protect();
+ }
+ catch (AssertionFailedError e) {
+ addFailure(test, e);
+ }
+ catch (ThreadDeath e) { // don't catch ThreadDeath by accident
+ throw e;
+ }
+ catch (Throwable e) {
+ addError(test, e);
+ }
+ }
+ /**
+ * Checks whether the test run should stop
+ */
+ public synchronized boolean shouldStop() {
+ return fStop;
+ }
+ /**
+ * Informs the result that a test will be started.
+ */
+ public void startTest(Test test) {
+ final int count= test.countTestCases();
+ synchronized(this) {
+ fRunTests+= count;
+ }
+ for (TestListener each : cloneListeners())
+ each.startTest(test);
+ }
+ /**
+ * Marks that the test run should stop.
+ */
+ public synchronized void stop() {
+ fStop= true;
+ }
+ /**
+ * Returns whether the entire test was successful or not.
+ */
+ public synchronized boolean wasSuccessful() {
+ return failureCount() == 0 && errorCount() == 0;
+ }
+} \ No newline at end of file
diff --git a/junit4/src/main/java/junit/framework/TestSuite.java b/junit4/src/main/java/junit/framework/TestSuite.java
new file mode 100644
index 0000000..336efd1
--- /dev/null
+++ b/junit4/src/main/java/junit/framework/TestSuite.java
@@ -0,0 +1,307 @@
+package junit.framework;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * <p>A <code>TestSuite</code> is a <code>Composite</code> of Tests.
+ * It runs a collection of test cases. Here is an example using
+ * the dynamic test definition.
+ * <pre>
+ * TestSuite suite= new TestSuite();
+ * suite.addTest(new MathTest("testAdd"));
+ * suite.addTest(new MathTest("testDivideByZero"));
+ * </pre>
+ * </p>
+ *
+ * <p>Alternatively, a TestSuite can extract the tests to be run automatically.
+ * To do so you pass the class of your TestCase class to the
+ * TestSuite constructor.
+ * <pre>
+ * TestSuite suite= new TestSuite(MathTest.class);
+ * </pre>
+ * </p>
+ *
+ * <p>This constructor creates a suite with all the methods
+ * starting with "test" that take no arguments.</p>
+ *
+ * <p>A final option is to do the same for a large array of test classes.
+ * <pre>
+ * Class[] testClasses = { MathTest.class, AnotherTest.class }
+ * TestSuite suite= new TestSuite(testClasses);
+ * </pre>
+ * </p>
+ *
+ * @see Test
+ */
+public class TestSuite implements Test {
+
+ /**
+ * ...as the moon sets over the early morning Merlin, Oregon
+ * mountains, our intrepid adventurers type...
+ */
+ static public Test createTest(Class<?> theClass, String name) {
+ Constructor<?> constructor;
+ try {
+ constructor= getTestConstructor(theClass);
+ } catch (NoSuchMethodException e) {
+ return warning("Class "+theClass.getName()+" has no public constructor TestCase(String name) or TestCase()");
+ }
+ Object test;
+ try {
+ if (constructor.getParameterTypes().length == 0) {
+ test= constructor.newInstance(new Object[0]);
+ if (test instanceof TestCase)
+ ((TestCase) test).setName(name);
+ } else {
+ test= constructor.newInstance(new Object[]{name});
+ }
+ } catch (InstantiationException e) {
+ return(warning("Cannot instantiate test case: "+name+" ("+exceptionToString(e)+")"));
+ } catch (InvocationTargetException e) {
+ return(warning("Exception in constructor: "+name+" ("+exceptionToString(e.getTargetException())+")"));
+ } catch (IllegalAccessException e) {
+ return(warning("Cannot access test case: "+name+" ("+exceptionToString(e)+")"));
+ }
+ return (Test) test;
+ }
+
+ /**
+ * Gets a constructor which takes a single String as
+ * its argument or a no arg constructor.
+ */
+ public static Constructor<?> getTestConstructor(Class<?> theClass) throws NoSuchMethodException {
+ try {
+ return theClass.getConstructor(String.class);
+ } catch (NoSuchMethodException e) {
+ // fall through
+ }
+ return theClass.getConstructor(new Class[0]);
+ }
+
+ /**
+ * Returns a test which will fail and log a warning message.
+ */
+ public static Test warning(final String message) {
+ return new TestCase("warning") {
+ @Override
+ protected void runTest() {
+ fail(message);
+ }
+ };
+ }
+
+ /**
+ * Converts the stack trace into a string
+ */
+ private static String exceptionToString(Throwable t) {
+ StringWriter stringWriter= new StringWriter();
+ PrintWriter writer= new PrintWriter(stringWriter);
+ t.printStackTrace(writer);
+ return stringWriter.toString();
+ }
+
+ private String fName;
+
+ private Vector<Test> fTests= new Vector<Test>(10); // Cannot convert this to List because it is used directly by some test runners
+
+ /**
+ * Constructs an empty TestSuite.
+ */
+ public TestSuite() {
+ }
+
+ /**
+ * Constructs a TestSuite from the given class. Adds all the methods
+ * starting with "test" as test cases to the suite.
+ * Parts of this method were written at 2337 meters in the Hueffihuette,
+ * Kanton Uri
+ */
+ public TestSuite(final Class<?> theClass) {
+ addTestsFromTestCase(theClass);
+ }
+
+ private void addTestsFromTestCase(final Class<?> theClass) {
+ fName= theClass.getName();
+ try {
+ getTestConstructor(theClass); // Avoid generating multiple error messages
+ } catch (NoSuchMethodException e) {
+ addTest(warning("Class "+theClass.getName()+" has no public constructor TestCase(String name) or TestCase()"));
+ return;
+ }
+
+ if (!Modifier.isPublic(theClass.getModifiers())) {
+ addTest(warning("Class "+theClass.getName()+" is not public"));
+ return;
+ }
+
+ Class<?> superClass= theClass;
+ List<String> names= new ArrayList<String>();
+ while (Test.class.isAssignableFrom(superClass)) {
+ for (Method each : superClass.getDeclaredMethods())
+ addTestMethod(each, names, theClass);
+ superClass= superClass.getSuperclass();
+ }
+ if (fTests.size() == 0)
+ addTest(warning("No tests found in "+theClass.getName()));
+ }
+
+ /**
+ * Constructs a TestSuite from the given class with the given name.
+ * @see TestSuite#TestSuite(Class)
+ */
+ public TestSuite(Class<? extends TestCase> theClass, String name) {
+ this(theClass);
+ setName(name);
+ }
+
+ /**
+ * Constructs an empty TestSuite.
+ */
+ public TestSuite(String name) {
+ setName(name);
+ }
+
+ /**
+ * Constructs a TestSuite from the given array of classes.
+ * @param classes {@link TestCase}s
+ */
+ public TestSuite (Class<?>... classes) {
+ for (Class<?> each : classes)
+ addTest(testCaseForClass(each));
+ }
+
+ private Test testCaseForClass(Class<?> each) {
+ if (TestCase.class.isAssignableFrom(each))
+ return new TestSuite(each.asSubclass(TestCase.class));
+ else
+ return warning(each.getCanonicalName() + " does not extend TestCase");
+ }
+
+ /**
+ * Constructs a TestSuite from the given array of classes with the given name.
+ * @see TestSuite#TestSuite(Class[])
+ */
+ public TestSuite(Class<? extends TestCase>[] classes, String name) {
+ this(classes);
+ setName(name);
+ }
+
+ /**
+ * Adds a test to the suite.
+ */
+ public void addTest(Test test) {
+ fTests.add(test);
+ }
+
+ /**
+ * Adds the tests from the given class to the suite
+ */
+ public void addTestSuite(Class<? extends TestCase> testClass) {
+ addTest(new TestSuite(testClass));
+ }
+
+ /**
+ * Counts the number of test cases that will be run by this test.
+ */
+ public int countTestCases() {
+ int count= 0;
+ for (Test each : fTests)
+ count+= each.countTestCases();
+ return count;
+ }
+
+ /**
+ * Returns the name of the suite. Not all
+ * test suites have a name and this method
+ * can return null.
+ */
+ public String getName() {
+ return fName;
+ }
+
+ /**
+ * Runs the tests and collects their result in a TestResult.
+ */
+ public void run(TestResult result) {
+ for (Test each : fTests) {
+ if (result.shouldStop() )
+ break;
+ runTest(each, result);
+ }
+ }
+
+ public void runTest(Test test, TestResult result) {
+ test.run(result);
+ }
+
+ /**
+ * Sets the name of the suite.
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ fName= name;
+ }
+
+ /**
+ * Returns the test at the given index
+ */
+ public Test testAt(int index) {
+ return fTests.get(index);
+ }
+
+ /**
+ * Returns the number of tests in this suite
+ */
+ public int testCount() {
+ return fTests.size();
+ }
+
+ /**
+ * Returns the tests as an enumeration
+ */
+ public Enumeration<Test> tests() {
+ return fTests.elements();
+ }
+
+ /**
+ */
+ @Override
+ public String toString() {
+ if (getName() != null)
+ return getName();
+ return super.toString();
+ }
+
+ private void addTestMethod(Method m, List<String> names, Class<?> theClass) {
+ String name= m.getName();
+ if (names.contains(name))
+ return;
+ if (! isPublicTestMethod(m)) {
+ if (isTestMethod(m))
+ addTest(warning("Test method isn't public: "+ m.getName() + "(" + theClass.getCanonicalName() + ")"));
+ return;
+ }
+ names.add(name);
+ addTest(createTest(theClass, name));
+ }
+
+ private boolean isPublicTestMethod(Method m) {
+ return isTestMethod(m) && Modifier.isPublic(m.getModifiers());
+ }
+
+ private boolean isTestMethod(Method m) {
+ return
+ m.getParameterTypes().length == 0 &&
+ m.getName().startsWith("test") &&
+ m.getReturnType().equals(Void.TYPE);
+ }
+} \ No newline at end of file
diff --git a/junit4/src/main/java/junit/framework/package-info.java b/junit4/src/main/java/junit/framework/package-info.java
new file mode 100644
index 0000000..153a1c8
--- /dev/null
+++ b/junit4/src/main/java/junit/framework/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Provides JUnit v3.x core classes.
+ */
+package junit.framework; \ No newline at end of file
diff --git a/junit4/src/main/java/junit/runner/BaseTestRunner.java b/junit4/src/main/java/junit/runner/BaseTestRunner.java
new file mode 100644
index 0000000..6a4b090
--- /dev/null
+++ b/junit4/src/main/java/junit/runner/BaseTestRunner.java
@@ -0,0 +1,318 @@
+package junit.runner;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.text.NumberFormat;
+import java.util.Properties;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestListener;
+import junit.framework.TestSuite;
+
+/**
+ * Base class for all test runners.
+ * This class was born live on stage in Sardinia during XP2000.
+ */
+public abstract class BaseTestRunner implements TestListener {
+ public static final String SUITE_METHODNAME= "suite";
+
+ private static Properties fPreferences;
+ static int fgMaxMessageLength= 500;
+ static boolean fgFilterStack= true;
+ boolean fLoading= true;
+
+ /*
+ * Implementation of TestListener
+ */
+ public synchronized void startTest(Test test) {
+ testStarted(test.toString());
+ }
+
+ protected static void setPreferences(Properties preferences) {
+ fPreferences= preferences;
+ }
+
+ protected static Properties getPreferences() {
+ if (fPreferences == null) {
+ fPreferences= new Properties();
+ fPreferences.put("loading", "true");
+ fPreferences.put("filterstack", "true");
+ readPreferences();
+ }
+ return fPreferences;
+ }
+
+ public static void savePreferences() throws IOException {
+ FileOutputStream fos= new FileOutputStream(getPreferencesFile());
+ try {
+ getPreferences().store(fos, "");
+ } finally {
+ fos.close();
+ }
+ }
+
+ public static void setPreference(String key, String value) {
+ getPreferences().put(key, value);
+ }
+
+ public synchronized void endTest(Test test) {
+ testEnded(test.toString());
+ }
+
+ public synchronized void addError(final Test test, final Throwable t) {
+ testFailed(TestRunListener.STATUS_ERROR, test, t);
+ }
+
+ public synchronized void addFailure(final Test test, final AssertionFailedError t) {
+ testFailed(TestRunListener.STATUS_FAILURE, test, t);
+ }
+
+ // TestRunListener implementation
+
+ public abstract void testStarted(String testName);
+
+ public abstract void testEnded(String testName);
+
+ public abstract void testFailed(int status, Test test, Throwable t);
+
+ /**
+ * Returns the Test corresponding to the given suite. This is
+ * a template method, subclasses override runFailed(), clearStatus().
+ */
+ public Test getTest(String suiteClassName) {
+ if (suiteClassName.length() <= 0) {
+ clearStatus();
+ return null;
+ }
+ Class<?> testClass= null;
+ try {
+ testClass= loadSuiteClass(suiteClassName);
+ } catch (ClassNotFoundException e) {
+ String clazz= e.getMessage();
+ if (clazz == null)
+ clazz= suiteClassName;
+ runFailed("Class not found \""+clazz+"\"");
+ return null;
+ } catch(Exception e) {
+ runFailed("Error: "+e.toString());
+ return null;
+ }
+ Method suiteMethod= null;
+ try {
+ suiteMethod= testClass.getMethod(SUITE_METHODNAME, new Class[0]);
+ } catch(Exception e) {
+ // try to extract a test suite automatically
+ clearStatus();
+ return new TestSuite(testClass);
+ }
+ if (! Modifier.isStatic(suiteMethod.getModifiers())) {
+ runFailed("Suite() method must be static");
+ return null;
+ }
+ Test test= null;
+ try {
+ test= (Test)suiteMethod.invoke(null, (Object[])new Class[0]); // static method
+ if (test == null)
+ return test;
+ }
+ catch (InvocationTargetException e) {
+ runFailed("Failed to invoke suite():" + e.getTargetException().toString());
+ return null;
+ }
+ catch (IllegalAccessException e) {
+ runFailed("Failed to invoke suite():" + e.toString());
+ return null;
+ }
+
+ clearStatus();
+ return test;
+ }
+
+ /**
+ * Returns the formatted string of the elapsed time.
+ */
+ public String elapsedTimeAsString(long runTime) {
+ return NumberFormat.getInstance().format((double)runTime/1000);
+ }
+
+ /**
+ * Processes the command line arguments and
+ * returns the name of the suite class to run or null
+ */
+ protected String processArguments(String[] args) {
+ String suiteName= null;
+ for (int i= 0; i < args.length; i++) {
+ if (args[i].equals("-noloading")) {
+ setLoading(false);
+ } else if (args[i].equals("-nofilterstack")) {
+ fgFilterStack= false;
+ } else if (args[i].equals("-c")) {
+ if (args.length > i+1)
+ suiteName= extractClassName(args[i+1]);
+ else
+ System.out.println("Missing Test class name");
+ i++;
+ } else {
+ suiteName= args[i];
+ }
+ }
+ return suiteName;
+ }
+
+ /**
+ * Sets the loading behaviour of the test runner
+ */
+ public void setLoading(boolean enable) {
+ fLoading= enable;
+ }
+ /**
+ * Extract the class name from a String in VA/Java style
+ */
+ public String extractClassName(String className) {
+ if(className.startsWith("Default package for"))
+ return className.substring(className.lastIndexOf(".")+1);
+ return className;
+ }
+
+ /**
+ * Truncates a String to the maximum length.
+ */
+ public static String truncate(String s) {
+ if (fgMaxMessageLength != -1 && s.length() > fgMaxMessageLength)
+ s= s.substring(0, fgMaxMessageLength)+"...";
+ return s;
+ }
+
+ /**
+ * Override to define how to handle a failed loading of
+ * a test suite.
+ */
+ protected abstract void runFailed(String message);
+
+ /**
+ * Returns the loaded Class for a suite name.
+ */
+ protected Class<?> loadSuiteClass(String suiteClassName) throws ClassNotFoundException {
+ return Class.forName(suiteClassName);
+ }
+
+ /**
+ * Clears the status message.
+ */
+ protected void clearStatus() { // Belongs in the GUI TestRunner class
+ }
+
+ protected boolean useReloadingTestSuiteLoader() {
+ return getPreference("loading").equals("true") && fLoading;
+ }
+
+ private static File getPreferencesFile() {
+ String home= System.getProperty("user.home");
+ return new File(home, "junit.properties");
+ }
+
+ private static void readPreferences() {
+ InputStream is= null;
+ try {
+ is= new FileInputStream(getPreferencesFile());
+ setPreferences(new Properties(getPreferences()));
+ getPreferences().load(is);
+ } catch (IOException e) {
+ try {
+ if (is != null)
+ is.close();
+ } catch (IOException e1) {
+ }
+ }
+ }
+
+ public static String getPreference(String key) {
+ return getPreferences().getProperty(key);
+ }
+
+ public static int getPreference(String key, int dflt) {
+ String value= getPreference(key);
+ int intValue= dflt;
+ if (value == null)
+ return intValue;
+ try {
+ intValue= Integer.parseInt(value);
+ } catch (NumberFormatException ne) {
+ }
+ return intValue;
+ }
+
+ /**
+ * Returns a filtered stack trace
+ */
+ public static String getFilteredTrace(Throwable t) {
+ StringWriter stringWriter= new StringWriter();
+ PrintWriter writer= new PrintWriter(stringWriter);
+ t.printStackTrace(writer);
+ StringBuffer buffer= stringWriter.getBuffer();
+ String trace= buffer.toString();
+ return BaseTestRunner.getFilteredTrace(trace);
+ }
+
+ /**
+ * Filters stack frames from internal JUnit classes
+ */
+ public static String getFilteredTrace(String stack) {
+ if (showStackRaw())
+ return stack;
+
+ StringWriter sw= new StringWriter();
+ PrintWriter pw= new PrintWriter(sw);
+ StringReader sr= new StringReader(stack);
+ BufferedReader br= new BufferedReader(sr);
+
+ String line;
+ try {
+ while ((line= br.readLine()) != null) {
+ if (!filterLine(line))
+ pw.println(line);
+ }
+ } catch (Exception IOException) {
+ return stack; // return the stack unfiltered
+ }
+ return sw.toString();
+ }
+
+ protected static boolean showStackRaw() {
+ return !getPreference("filterstack").equals("true") || fgFilterStack == false;
+ }
+
+ static boolean filterLine(String line) {
+ String[] patterns= new String[] {
+ "junit.framework.TestCase",
+ "junit.framework.TestResult",
+ "junit.framework.TestSuite",
+ "junit.framework.Assert.", // don't filter AssertionFailure
+ "junit.swingui.TestRunner",
+ "junit.awtui.TestRunner",
+ "junit.textui.TestRunner",
+ "java.lang.reflect.Method.invoke("
+ };
+ for (int i= 0; i < patterns.length; i++) {
+ if (line.indexOf(patterns[i]) > 0)
+ return true;
+ }
+ return false;
+ }
+
+ static {
+ fgMaxMessageLength= getPreference("maxmessage", fgMaxMessageLength);
+ }
+
+}
diff --git a/junit4/src/main/java/junit/runner/TestRunListener.java b/junit4/src/main/java/junit/runner/TestRunListener.java
new file mode 100644
index 0000000..b11ef07
--- /dev/null
+++ b/junit4/src/main/java/junit/runner/TestRunListener.java
@@ -0,0 +1,19 @@
+package junit.runner;
+/**
+ * A listener interface for observing the
+ * execution of a test run. Unlike TestListener,
+ * this interface using only primitive objects,
+ * making it suitable for remote test execution.
+ */
+ public interface TestRunListener {
+ /* test status constants*/
+ public static final int STATUS_ERROR= 1;
+ public static final int STATUS_FAILURE= 2;
+
+ public void testRunStarted(String testSuiteName, int testCount);
+ public void testRunEnded(long elapsedTime);
+ public void testRunStopped(long elapsedTime);
+ public void testStarted(String testName);
+ public void testEnded(String testName);
+ public void testFailed(int status, String testName, String trace);
+}
diff --git a/junit4/src/main/java/junit/runner/Version.java b/junit4/src/main/java/junit/runner/Version.java
new file mode 100644
index 0000000..21aabfa
--- /dev/null
+++ b/junit4/src/main/java/junit/runner/Version.java
@@ -0,0 +1,18 @@
+package junit.runner;
+
+/**
+ * This class defines the current version of JUnit
+ */
+public class Version {
+ private Version() {
+ // don't instantiate
+ }
+
+ public static String id() {
+ return "4.10-SNAPSHOT";
+ }
+
+ public static void main(String[] args) {
+ System.out.println(id());
+ }
+}
diff --git a/junit4/src/main/java/junit/runner/Version.java.template b/junit4/src/main/java/junit/runner/Version.java.template
new file mode 100644
index 0000000..3182cfd
--- /dev/null
+++ b/junit4/src/main/java/junit/runner/Version.java.template
@@ -0,0 +1,18 @@
+package junit.runner;
+
+/**
+ * This class defines the current version of JUnit
+ */
+public class Version {
+ private Version() {
+ // don't instantiate
+ }
+
+ public static String id() {
+ return "@version@";
+ }
+
+ public static void main(String[] args) {
+ System.out.println(id());
+ }
+}
diff --git a/junit4/src/main/java/junit/runner/logo.gif b/junit4/src/main/java/junit/runner/logo.gif
new file mode 100644
index 0000000..d0e1547
--- /dev/null
+++ b/junit4/src/main/java/junit/runner/logo.gif
Binary files differ
diff --git a/junit4/src/main/java/junit/runner/package-info.java b/junit4/src/main/java/junit/runner/package-info.java
new file mode 100644
index 0000000..b746185
--- /dev/null
+++ b/junit4/src/main/java/junit/runner/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Provides JUnit v3.x test runners.
+ */
+package junit.runner; \ No newline at end of file
diff --git a/junit4/src/main/java/junit/runner/smalllogo.gif b/junit4/src/main/java/junit/runner/smalllogo.gif
new file mode 100644
index 0000000..7b25eaf
--- /dev/null
+++ b/junit4/src/main/java/junit/runner/smalllogo.gif
Binary files differ
diff --git a/junit4/src/main/java/junit/textui/ResultPrinter.java b/junit4/src/main/java/junit/textui/ResultPrinter.java
new file mode 100644
index 0000000..f2f01f5
--- /dev/null
+++ b/junit4/src/main/java/junit/textui/ResultPrinter.java
@@ -0,0 +1,139 @@
+
+package junit.textui;
+
+import java.io.PrintStream;
+import java.text.NumberFormat;
+import java.util.Enumeration;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestFailure;
+import junit.framework.TestListener;
+import junit.framework.TestResult;
+import junit.runner.BaseTestRunner;
+
+public class ResultPrinter implements TestListener {
+ PrintStream fWriter;
+ int fColumn= 0;
+
+ public ResultPrinter(PrintStream writer) {
+ fWriter= writer;
+ }
+
+ /* API for use by textui.TestRunner
+ */
+
+ synchronized void print(TestResult result, long runTime) {
+ printHeader(runTime);
+ printErrors(result);
+ printFailures(result);
+ printFooter(result);
+ }
+
+ void printWaitPrompt() {
+ getWriter().println();
+ getWriter().println("<RETURN> to continue");
+ }
+
+ /* Internal methods
+ */
+
+ protected void printHeader(long runTime) {
+ getWriter().println();
+ getWriter().println("Time: "+elapsedTimeAsString(runTime));
+ }
+
+ protected void printErrors(TestResult result) {
+ printDefects(result.errors(), result.errorCount(), "error");
+ }
+
+ protected void printFailures(TestResult result) {
+ printDefects(result.failures(), result.failureCount(), "failure");
+ }
+
+ protected void printDefects(Enumeration<TestFailure> booBoos, int count, String type) {
+ if (count == 0) return;
+ if (count == 1)
+ getWriter().println("There was " + count + " " + type + ":");
+ else
+ getWriter().println("There were " + count + " " + type + "s:");
+ for (int i= 1; booBoos.hasMoreElements(); i++) {
+ printDefect(booBoos.nextElement(), i);
+ }
+ }
+
+ public void printDefect(TestFailure booBoo, int count) { // only public for testing purposes
+ printDefectHeader(booBoo, count);
+ printDefectTrace(booBoo);
+ }
+
+ protected void printDefectHeader(TestFailure booBoo, int count) {
+ // I feel like making this a println, then adding a line giving the throwable a chance to print something
+ // before we get to the stack trace.
+ getWriter().print(count + ") " + booBoo.failedTest());
+ }
+
+ protected void printDefectTrace(TestFailure booBoo) {
+ getWriter().print(BaseTestRunner.getFilteredTrace(booBoo.trace()));
+ }
+
+ protected void printFooter(TestResult result) {
+ if (result.wasSuccessful()) {
+ getWriter().println();
+ getWriter().print("OK");
+ getWriter().println (" (" + result.runCount() + " test" + (result.runCount() == 1 ? "": "s") + ")");
+
+ } else {
+ getWriter().println();
+ getWriter().println("FAILURES!!!");
+ getWriter().println("Tests run: "+result.runCount()+
+ ", Failures: "+result.failureCount()+
+ ", Errors: "+result.errorCount());
+ }
+ getWriter().println();
+ }
+
+
+ /**
+ * Returns the formatted string of the elapsed time.
+ * Duplicated from BaseTestRunner. Fix it.
+ */
+ protected String elapsedTimeAsString(long runTime) {
+ return NumberFormat.getInstance().format((double)runTime/1000);
+ }
+
+ public PrintStream getWriter() {
+ return fWriter;
+ }
+ /**
+ * @see junit.framework.TestListener#addError(Test, Throwable)
+ */
+ public void addError(Test test, Throwable t) {
+ getWriter().print("E");
+ }
+
+ /**
+ * @see junit.framework.TestListener#addFailure(Test, AssertionFailedError)
+ */
+ public void addFailure(Test test, AssertionFailedError t) {
+ getWriter().print("F");
+ }
+
+ /**
+ * @see junit.framework.TestListener#endTest(Test)
+ */
+ public void endTest(Test test) {
+ }
+
+ /**
+ * @see junit.framework.TestListener#startTest(Test)
+ */
+ public void startTest(Test test) {
+ getWriter().print(".");
+ if (fColumn++ >= 40) {
+ getWriter().println();
+ fColumn= 0;
+ }
+ }
+
+}
diff --git a/junit4/src/main/java/junit/textui/TestRunner.java b/junit4/src/main/java/junit/textui/TestRunner.java
new file mode 100644
index 0000000..046448e
--- /dev/null
+++ b/junit4/src/main/java/junit/textui/TestRunner.java
@@ -0,0 +1,203 @@
+package junit.textui;
+
+
+import java.io.PrintStream;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+import junit.runner.BaseTestRunner;
+import junit.runner.Version;
+
+/**
+ * A command line based tool to run tests.
+ * <pre>
+ * java junit.textui.TestRunner [-wait] TestCaseClass
+ * </pre>
+ *
+ * <p>TestRunner expects the name of a TestCase class as argument.
+ * If this class defines a static <code>suite</code> method it
+ * will be invoked and the returned test is run. Otherwise all
+ * the methods starting with "test" having no arguments are run.</p>
+ *
+ * <p> When the wait command line argument is given TestRunner
+ * waits until the users types RETURN.</p>
+ *
+ * <p>TestRunner prints a trace as the tests are executed followed by a
+ * summary at the end.</p>
+ */
+public class TestRunner extends BaseTestRunner {
+ private ResultPrinter fPrinter;
+
+ public static final int SUCCESS_EXIT= 0;
+ public static final int FAILURE_EXIT= 1;
+ public static final int EXCEPTION_EXIT= 2;
+
+ /**
+ * Constructs a TestRunner.
+ */
+ public TestRunner() {
+ this(System.out);
+ }
+
+ /**
+ * Constructs a TestRunner using the given stream for all the output
+ */
+ public TestRunner(PrintStream writer) {
+ this(new ResultPrinter(writer));
+ }
+
+ /**
+ * Constructs a TestRunner using the given ResultPrinter all the output
+ */
+ public TestRunner(ResultPrinter printer) {
+ fPrinter= printer;
+ }
+
+ /**
+ * Runs a suite extracted from a TestCase subclass.
+ */
+ static public void run(Class<? extends TestCase> testClass) {
+ run(new TestSuite(testClass));
+ }
+
+ /**
+ * Runs a single test and collects its results.
+ * This method can be used to start a test run
+ * from your program.
+ * <pre>
+ * public static void main (String[] args) {
+ * test.textui.TestRunner.run(suite());
+ * }
+ * </pre>
+ */
+ static public TestResult run(Test test) {
+ TestRunner runner= new TestRunner();
+ return runner.doRun(test);
+ }
+
+ /**
+ * Runs a single test and waits until the user
+ * types RETURN.
+ */
+ static public void runAndWait(Test suite) {
+ TestRunner aTestRunner= new TestRunner();
+ aTestRunner.doRun(suite, true);
+ }
+
+ @Override
+ public void testFailed(int status, Test test, Throwable t) {
+ }
+
+ @Override
+ public void testStarted(String testName) {
+ }
+
+ @Override
+ public void testEnded(String testName) {
+ }
+
+ /**
+ * Creates the TestResult to be used for the test run.
+ */
+ protected TestResult createTestResult() {
+ return new TestResult();
+ }
+
+ public TestResult doRun(Test test) {
+ return doRun(test, false);
+ }
+
+ public TestResult doRun(Test suite, boolean wait) {
+ TestResult result= createTestResult();
+ result.addListener(fPrinter);
+ long startTime= System.currentTimeMillis();
+ suite.run(result);
+ long endTime= System.currentTimeMillis();
+ long runTime= endTime-startTime;
+ fPrinter.print(result, runTime);
+
+ pause(wait);
+ return result;
+ }
+
+ protected void pause(boolean wait) {
+ if (!wait) return;
+ fPrinter.printWaitPrompt();
+ try {
+ System.in.read();
+ }
+ catch(Exception e) {
+ }
+ }
+
+ public static void main(String args[]) {
+ TestRunner aTestRunner= new TestRunner();
+ try {
+ TestResult r= aTestRunner.start(args);
+ if (!r.wasSuccessful())
+ System.exit(FAILURE_EXIT);
+ System.exit(SUCCESS_EXIT);
+ } catch(Exception e) {
+ System.err.println(e.getMessage());
+ System.exit(EXCEPTION_EXIT);
+ }
+ }
+
+ /**
+ * Starts a test run. Analyzes the command line arguments and runs the given
+ * test suite.
+ */
+ public TestResult start(String args[]) throws Exception {
+ String testCase= "";
+ String method= "";
+ boolean wait= false;
+
+ for (int i= 0; i < args.length; i++) {
+ if (args[i].equals("-wait"))
+ wait= true;
+ else if (args[i].equals("-c"))
+ testCase= extractClassName(args[++i]);
+ else if (args[i].equals("-m")) {
+ String arg= args[++i];
+ int lastIndex= arg.lastIndexOf('.');
+ testCase= arg.substring(0, lastIndex);
+ method= arg.substring(lastIndex + 1);
+ } else if (args[i].equals("-v"))
+ System.err.println("JUnit " + Version.id() + " by Kent Beck and Erich Gamma");
+ else
+ testCase= args[i];
+ }
+
+ if (testCase.equals(""))
+ throw new Exception("Usage: TestRunner [-wait] testCaseName, where name is the name of the TestCase class");
+
+ try {
+ if (!method.equals(""))
+ return runSingleMethod(testCase, method, wait);
+ Test suite= getTest(testCase);
+ return doRun(suite, wait);
+ } catch (Exception e) {
+ throw new Exception("Could not create and run test suite: " + e);
+ }
+ }
+
+ protected TestResult runSingleMethod(String testCase, String method, boolean wait) throws Exception {
+ Class<? extends TestCase> testClass= loadSuiteClass(testCase).asSubclass(TestCase.class);
+ Test test= TestSuite.createTest(testClass, method);
+ return doRun(test, wait);
+ }
+
+ @Override
+ protected void runFailed(String message) {
+ System.err.println(message);
+ System.exit(FAILURE_EXIT);
+ }
+
+ public void setPrinter(ResultPrinter printer) {
+ fPrinter= printer;
+ }
+
+
+} \ No newline at end of file
diff --git a/junit4/src/main/java/junit/textui/package-info.java b/junit4/src/main/java/junit/textui/package-info.java
new file mode 100644
index 0000000..2aa5176
--- /dev/null
+++ b/junit4/src/main/java/junit/textui/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Provides JUnit v3.x command line based tool to run tests.
+ */
+package junit.textui; \ No newline at end of file