1package org.junit.internal.runners;
2
3import junit.extensions.TestDecorator;
4import junit.framework.AssertionFailedError;
5import junit.framework.Test;
6import junit.framework.TestCase;
7import junit.framework.TestListener;
8import junit.framework.TestResult;
9import junit.framework.TestSuite;
10import org.junit.runner.Describable;
11import org.junit.runner.Description;
12import org.junit.runner.Runner;
13import org.junit.runner.manipulation.Filter;
14import org.junit.runner.manipulation.Filterable;
15import org.junit.runner.manipulation.NoTestsRemainException;
16import org.junit.runner.manipulation.Sortable;
17import org.junit.runner.manipulation.Sorter;
18import org.junit.runner.notification.Failure;
19import org.junit.runner.notification.RunNotifier;
20
21public class JUnit38ClassRunner extends Runner implements Filterable, Sortable {
22	private final class OldTestClassAdaptingListener implements
23			TestListener {
24		private final RunNotifier fNotifier;
25
26		private OldTestClassAdaptingListener(RunNotifier notifier) {
27			fNotifier= notifier;
28		}
29
30		public void endTest(Test test) {
31			fNotifier.fireTestFinished(asDescription(test));
32		}
33
34		public void startTest(Test test) {
35			fNotifier.fireTestStarted(asDescription(test));
36		}
37
38		// Implement junit.framework.TestListener
39		public void addError(Test test, Throwable t) {
40			Failure failure= new Failure(asDescription(test), t);
41			fNotifier.fireTestFailure(failure);
42		}
43
44		private Description asDescription(Test test) {
45			if (test instanceof Describable) {
46				Describable facade= (Describable) test;
47				return facade.getDescription();
48			}
49			return Description.createTestDescription(getEffectiveClass(test), getName(test));
50		}
51
52		private Class<? extends Test> getEffectiveClass(Test test) {
53			return test.getClass();
54		}
55
56		private String getName(Test test) {
57			if (test instanceof TestCase)
58				return ((TestCase) test).getName();
59			else
60				return test.toString();
61		}
62
63		public void addFailure(Test test, AssertionFailedError t) {
64			addError(test, t);
65		}
66	}
67
68	private Test fTest;
69
70	public JUnit38ClassRunner(Class<?> klass) {
71		this(new TestSuite(klass.asSubclass(TestCase.class)));
72	}
73
74	public JUnit38ClassRunner(Test test) {
75		super();
76		setTest(test);
77	}
78
79	@Override
80	public void run(RunNotifier notifier) {
81		TestResult result= new TestResult();
82		result.addListener(createAdaptingListener(notifier));
83		getTest().run(result);
84	}
85
86	public TestListener createAdaptingListener(final RunNotifier notifier) {
87		return new OldTestClassAdaptingListener(notifier);
88	}
89
90	@Override
91	public Description getDescription() {
92		return makeDescription(getTest());
93	}
94
95	private static Description makeDescription(Test test) {
96		if (test instanceof TestCase) {
97			TestCase tc= (TestCase) test;
98			return Description.createTestDescription(tc.getClass(), tc.getName());
99		} else if (test instanceof TestSuite) {
100			TestSuite ts= (TestSuite) test;
101			String name= ts.getName() == null ? createSuiteDescription(ts) : ts.getName();
102			Description description= Description.createSuiteDescription(name);
103			int n= ts.testCount();
104			for (int i= 0; i < n; i++) {
105				Description made= makeDescription(ts.testAt(i));
106				description.addChild(made);
107			}
108			return description;
109		} else if (test instanceof Describable) {
110			Describable adapter= (Describable) test;
111			return adapter.getDescription();
112		} else if (test instanceof TestDecorator) {
113			TestDecorator decorator= (TestDecorator) test;
114			return makeDescription(decorator.getTest());
115		} else {
116			// This is the best we can do in this case
117			return Description.createSuiteDescription(test.getClass());
118		}
119	}
120
121	private static String createSuiteDescription(TestSuite ts) {
122		int count= ts.countTestCases();
123		String example = count == 0 ? "" : String.format(" [example: %s]", ts.testAt(0));
124		return String.format("TestSuite with %s tests%s", count, example);
125	}
126
127	public void filter(Filter filter) throws NoTestsRemainException {
128		if (getTest() instanceof Filterable) {
129			Filterable adapter= (Filterable) getTest();
130			adapter.filter(filter);
131		} else if (getTest() instanceof TestSuite) {
132			TestSuite suite= (TestSuite) getTest();
133			TestSuite filtered= new TestSuite(suite.getName());
134			int n= suite.testCount();
135			for (int i= 0; i < n; i++) {
136				Test test= suite.testAt(i);
137				if (filter.shouldRun(makeDescription(test)))
138					filtered.addTest(test);
139			}
140			setTest(filtered);
141		}
142	}
143
144	public void sort(Sorter sorter) {
145		if (getTest() instanceof Sortable) {
146			Sortable adapter= (Sortable) getTest();
147			adapter.sort(sorter);
148		}
149	}
150
151	private void setTest(Test test) {
152		fTest = test;
153	}
154
155	private Test getTest() {
156		return fTest;
157	}
158}
159