001: /*******************************************************************************
002: * Copyright (c) 2007 Brad Reynolds and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * Brad Reynolds - initial API and implementation
010: ******************************************************************************/package org.eclipse.jface.conformance.databinding;
011:
012: import java.lang.reflect.Constructor;
013: import java.lang.reflect.Method;
014: import java.util.Iterator;
015: import java.util.LinkedHashSet;
016:
017: import junit.framework.Test;
018: import junit.framework.TestSuite;
019:
020: /**
021: * Builds a test suite.
022: *
023: * @since 1.1
024: */
025: public class SuiteBuilder {
026: private LinkedHashSet content;
027:
028: public SuiteBuilder() {
029: content = new LinkedHashSet();
030: }
031:
032: /**
033: * Adds all test methods from the provided <code>testCase</code> to the
034: * suite.
035: *
036: * @param testCase
037: * @return builder
038: */
039: public SuiteBuilder addTests(Class testCase) {
040: content.add(testCase);
041: return this ;
042: }
043:
044: /**
045: * Adds all test methods from the provided <code>testCase</code> with the
046: * provided <code>parameters</code>. A constructor must exist in the
047: * testCase that accepts a String as the first parameter followed by
048: * parameters matching the provided parameters. If an appropriate
049: * constructor is not found an exception will be thrown.
050: *
051: * @param testCase
052: * @param parameters
053: * @return builder
054: */
055: public SuiteBuilder addParameterizedTests(Class testCase,
056: Object[] parameters) {
057:
058: Constructor constructor = findConstructor(testCase, parameters);
059: if (constructor == null) {
060: throw new IllegalArgumentException(
061: "The parameters provided don't match a constructor found in ["
062: + testCase.getName() + "]");
063: }
064:
065: content.add(new ParameterizedTest(testCase, constructor,
066: parameters));
067:
068: return this ;
069: }
070:
071: /**
072: * Convenience method for invoking
073: * {@link #addParameterizedTests(Class, Object[])} with a delegate.
074: *
075: * @param testCase
076: * @param delegate
077: * @return
078: */
079: public SuiteBuilder addObservableContractTest(Class testCase,
080: IObservableContractDelegate delegate) {
081:
082: addParameterizedTests(testCase, new Object[] { delegate });
083: return this ;
084: }
085:
086: /**
087: * Builds a new TestSuite out of the tests.
088: *
089: * @return suite
090: */
091: public TestSuite build() {
092: TestSuite suite = new TestSuite();
093:
094: for (Iterator it = content.iterator(); it.hasNext();) {
095: Object o = it.next();
096: if (o instanceof Class) {
097: suite.addTestSuite((Class) o);
098: } else if (o instanceof ParameterizedTest) {
099: ParameterizedTest test = (ParameterizedTest) o;
100:
101: Method[] methods = test.testClass.getMethods();
102: for (int i = 0; i < methods.length; i++) {
103: String name = methods[i].getName();
104: if (name.startsWith("test")) {
105: try {
106: suite.addTest((Test) test.constructor
107: .newInstance(toParamArray(name,
108: test.parameters)));
109: } catch (Exception e) {
110: throw new RuntimeException(e);
111: }
112: }
113: }
114: }
115: }
116:
117: return suite;
118: }
119:
120: private Object[] toParamArray(String testName, Object[] parameters) {
121: Object[] result = new Object[parameters.length + 1];
122: result[0] = testName;
123: System.arraycopy(parameters, 0, result, 1, parameters.length);
124: return result;
125: }
126:
127: /**
128: * Returns the constructor that has a String as the first parameters and
129: * then matches the type of the parameters.
130: *
131: * @param parameters
132: * @return
133: */
134: private static Constructor findConstructor(Class clazz,
135: Object[] parameters) {
136: Constructor[] constructors = clazz.getConstructors();
137: int expectedParametersLength = parameters.length + 1;
138:
139: for (int i = 0; i < constructors.length; i++) {
140: Constructor constructor = constructors[i];
141: Class[] types = constructor.getParameterTypes();
142:
143: if (types.length != expectedParametersLength
144: || !String.class.equals(types[0])) {
145: continue;
146: }
147:
148: boolean skip = false;
149: for (int j = 1; j < types.length; j++) {
150: Class type = types[j];
151: if (!type.isInstance(parameters[j - 1])) {
152: skip = true;
153: break;
154: }
155: }
156:
157: if (!skip) {
158: return constructor;
159: }
160: }
161:
162: return null;
163: }
164:
165: /* package */static class ParameterizedTest {
166: final Constructor constructor;
167:
168: final Object[] parameters;
169:
170: private Class testClass;
171:
172: ParameterizedTest(Class testClass, Constructor constructor,
173: Object[] parameterss) {
174: this.testClass = testClass;
175: this.constructor = constructor;
176: this.parameters = parameterss;
177: }
178: }
179: }
|