001: package org.depunit;
002:
003: import java.lang.reflect.*;
004: import java.util.*;
005: import org.depunit.annotations.*;
006: import org.w3c.dom.*;
007: import java.io.*;
008:
009: public class TestMethod extends DepLink {
010: public static final String STATUS_SUCCESS = "success";
011: public static final String STATUS_NOT_RAN = "not_ran";
012: public static final String STATUS_SKIPPED = "skipped";
013: public static final String STATUS_FAILED = "failed";
014:
015: //===========================================================================
016: private Method m_method;
017: private TestClass m_testClass;
018: /* private HardObserver m_hardDependencies;
019: private SoftObserver m_softDependencies; */
020: private String m_status;
021:
022: private List<String> m_hdMethods; //Yet to be resolved dependencies
023: private List<String> m_sdMethods; //Yet to be resolved dependencies
024: private boolean m_processMethod; //This method represents a before or after processing method
025: private String[] m_groups; //Groups this method belongs to.
026: private List<String> m_cleanupMethods; //Methods that must be called if this one succeds
027: private List<String> m_setupMethods;
028:
029: public TestMethod(Method m, TestClass tc, boolean procMethod) {
030: //super<TestMethod>();
031: m_processMethod = procMethod;
032: m_hdMethods = new ArrayList<String>();
033: m_sdMethods = new ArrayList<String>();
034: m_cleanupMethods = new ArrayList<String>();
035: m_setupMethods = new ArrayList<String>();
036: m_status = null;
037: /* m_hardDependencies = new HardObserver();
038: m_softDependencies = new SoftObserver(); */
039:
040: m_method = m;
041: m_testClass = tc;
042:
043: Test annot = (Test) m.getAnnotation(Test.class);
044: if (annot != null) {
045: String[] hard = annot.hardDependencyOn();
046: for (String h : hard)
047: addHardDependency(h);
048:
049: String[] soft = annot.softDependencyOn();
050: for (String s : soft)
051: addSoftDependency(s);
052:
053: m_groups = annot.groups();
054: String cleanupMethod = annot.cleanupMethod();
055: if (!cleanupMethod.equals(""))
056: m_cleanupMethods.add(cleanupMethod);
057: }
058: }
059:
060: //---------------------------------------------------------------------------
061: public synchronized void update(Observable o, Object arg) {
062: StateChange sc = (StateChange) arg;
063:
064: String status = sc.getStatus();
065: if (status != null) //Test was ran
066: {
067: if ((sc.getDepType() == HARD_DEPENDENCY)
068: && (!status.equals(STATUS_SUCCESS)))
069: setStatus(STATUS_SKIPPED);
070:
071: m_depCount--;
072: if (m_depCount == 0)
073: notify();
074: } else //The tests are begin reset
075: {
076: m_depCount++;
077: if (sc.getDepType() == HARD_DEPENDENCY)
078: reset();
079: }
080: }
081:
082: //---------------------------------------------------------------------------
083: private List<String> getDependents(TestMethod tm) {
084: ArrayList<String> dependents = new ArrayList<String>();
085:
086: Set<DepLink> deps = tm.getHardObservers();
087: for (DepLink dl : deps) {
088: TestMethod innerTm = (TestMethod) dl;
089: if (!innerTm.isProcessMethod() && innerTm != this ) {
090: dependents.add(innerTm.getFullName());
091: //System.out.println(" dep: "+innerTm.getFullName());
092: dependents.addAll(getDependents(innerTm));
093: }
094: }
095:
096: deps = tm.getSoftObservers();
097: for (DepLink dl : deps) {
098: TestMethod innerTm = (TestMethod) dl;
099: if (!innerTm.isProcessMethod() && innerTm != this ) {
100: dependents.add(innerTm.getFullName());
101: //System.out.println(" dep: "+innerTm.getFullName());
102: dependents.addAll(getDependents(innerTm));
103: }
104: }
105:
106: return (dependents);
107: }
108:
109: //---------------------------------------------------------------------------
110: /**
111: If this method is a cleaup method then it will find all the methods that
112: depend on the setup method.
113: */
114: public void gatherCleanupDependencies(
115: Map<String, TestMethod> methods) {
116: if (!isProcessMethod()) //Process methods already have thier dependencies setup
117: {
118: ArrayList<String> setupDependents = new ArrayList<String>();
119:
120: for (String setup : m_setupMethods) {
121: //System.out.println("Setup: "+setup);
122: //System.out.println("Cleanup: "+getFullName());
123: setupDependents
124: .addAll(getDependents(methods.get(setup)));
125: }
126:
127: m_sdMethods.addAll(setupDependents);
128: }
129: }
130:
131: //---------------------------------------------------------------------------
132: /**
133: This runs through all the soft dependencies again to make sure the observer
134: is set. Additional dependencies may have been added durring the call to
135: gatherCleanupDependencies
136: */
137: public void addCleanupDependencies(Map<String, TestMethod> methods) {
138: for (String method : m_sdMethods) {
139: TestMethod tm = methods.get(method);
140: if (tm.addSoftObserver(this ))
141: m_depCount++;
142: }
143: }
144:
145: //---------------------------------------------------------------------------
146: public void resolveCleanupMethods(Map<String, TestMethod> methods)
147: throws MissingDependencyException {
148: ListIterator<String> it = m_cleanupMethods.listIterator();
149: while (it.hasNext()) {
150: String method = it.next();
151:
152: if (methods.get(m_testClass.getFullName() + "." + method) != null) {
153: method = m_testClass.getFullName() + "." + method;
154: it.set(method);
155: } else if (methods.get(method) == null)
156: throw new MissingDependencyException(method);
157:
158: TestMethod tm = methods.get(method);
159: //Instead call special method
160: tm.yourMyCleanupMethod(getFullName());
161: }
162: }
163:
164: //---------------------------------------------------------------------------
165: public void resolveDependencies(
166: Map<String, List<TestMethod>> groupBucket,
167: Map<String, TestMethod> methods)
168: throws MissingDependencyException {
169: ListIterator<String> it = m_hdMethods.listIterator();
170: while (it.hasNext()) {
171: String method = it.next();
172:
173: //Check to see if it is a group first
174: List<TestMethod> group = groupBucket.get(method);
175: if (group != null) {
176: it.remove(); //Remove group name
177: for (TestMethod tm : group) {
178: it.add(tm.getFullName()); //Add members of group
179: //m_hardDependencies.add(tm);
180: if (tm.addHardObserver(this ))
181: m_depCount++;
182: }
183: } else { //Check to see if name is only partial
184: TestMethod tm = methods.get(m_testClass.getFullName()
185: + "." + method);
186: if (tm != null) {
187: it.set(m_testClass.getFullName() + "." + method);
188: //m_hardDependencies.add(tm);
189: if (tm.addHardObserver(this ))
190: m_depCount++;
191: } else if ((tm = methods.get(method)) != null)
192: //m_hardDependencies.add(tm);
193: if (tm.addHardObserver(this ))
194: m_depCount++;
195: else
196: throw new MissingDependencyException(method);
197: }
198: }
199:
200: it = m_sdMethods.listIterator();
201: while (it.hasNext()) {
202: String method = it.next();
203:
204: //Check to se if it is a group first
205: List<TestMethod> group = groupBucket.get(method);
206: if (group != null) {
207: it.remove(); //Remove group name
208: for (TestMethod tm : group) {
209: it.add(tm.getFullName()); //Add members of group
210: //m_softDependencies.add(tm);
211: if (tm.addSoftObserver(this ))
212: m_depCount++;
213: }
214: } else {
215: TestMethod tm = methods.get(m_testClass.getFullName()
216: + "." + method);
217: if (tm != null) {
218: it.set(m_testClass.getFullName() + "." + method);
219: //m_softDependencies.add(tm);
220: if (tm.addSoftObserver(this ))
221: m_depCount++;
222: } else if ((tm = methods.get(method)) != null)
223: //m_softDependencies.add(tm);
224: if (tm.addSoftObserver(this ))
225: m_depCount++;
226: else
227: throw new MissingDependencyException(method);
228: }
229: }
230: }
231:
232: //---------------------------------------------------------------------------
233: public boolean isProcessMethod() {
234: return (m_processMethod);
235: }
236:
237: //---------------------------------------------------------------------------
238: public List<String> getHardDependencies() {
239: return (m_hdMethods);
240: }
241:
242: //---------------------------------------------------------------------------
243: public List<String> getSoftDependencies() {
244: return (m_sdMethods);
245: }
246:
247: //---------------------------------------------------------------------------
248: public String[] getGroups() {
249: return (m_groups);
250: }
251:
252: //---------------------------------------------------------------------------
253: public List<String> getCleanupMethods() {
254: return (m_cleanupMethods);
255: }
256:
257: //---------------------------------------------------------------------------
258: public void addCleanupMethod(String method) {
259: m_cleanupMethods.add(method);
260: }
261:
262: //---------------------------------------------------------------------------
263: public String getFullName() {
264: return (m_testClass.getFullName() + "." + m_method.getName());
265: }
266:
267: //---------------------------------------------------------------------------
268: public TestClass getTestClass() {
269: return (m_testClass);
270: }
271:
272: //---------------------------------------------------------------------------
273: public String getMethodName() {
274: return (m_method.getName());
275: }
276:
277: //---------------------------------------------------------------------------
278: public void addSoftDependency(String method) {
279: m_sdMethods.add(method);
280: }
281:
282: //---------------------------------------------------------------------------
283: public void addHardDependency(String method) {
284: m_hdMethods.add(method);
285: }
286:
287: //---------------------------------------------------------------------------
288: public void yourMyCleanupMethod(String setupMethod) {
289: addHardDependency(setupMethod);
290: m_setupMethods.add(setupMethod);
291: }
292:
293: //---------------------------------------------------------------------------
294: //Probably add more to this
295: public synchronized void setStatus(String status) {
296: if (m_status == null) {
297: m_status = status;
298: m_hardObservers.notifyObservers(status);
299: m_softObservers.notifyObservers(status);
300: }
301: }
302:
303: //---------------------------------------------------------------------------
304: private synchronized void reset() {
305: resetStatus();
306:
307: //Check for data driver and reset it
308: DataDriver dd = getTestClass().getDataDriver();
309: if (dd != null)
310: dd.internalReset();
311: }
312:
313: //---------------------------------------------------------------------------
314: public synchronized void resetStatus() {
315: if ((m_status != null) && (!m_status.equals(STATUS_NOT_RAN))) {
316: m_status = null;
317: m_hardObservers.reset();
318: m_softObservers.reset();
319: }
320: }
321:
322: //---------------------------------------------------------------------------
323: public String getStatus() {
324: return (m_status);
325: }
326:
327: //---------------------------------------------------------------------------
328: public int hashCode() {
329: return (getFullName().hashCode());
330: }
331:
332: //---------------------------------------------------------------------------
333: public synchronized void blockNRun() {
334: //System.out.println("Status = "+m_status);
335: //System.out.println("m_depCount = "+m_depCount);
336: //System.out.println("Method = "+getFullName());
337: while ((m_depCount != 0) && (m_status == null)) {
338: try {
339: wait();
340: } catch (InterruptedException ie) {
341: }
342: }
343: }
344:
345: //---------------------------------------------------------------------------
346: public void skipMethod(Map<String, Object> runParams)
347: throws InitializationException, ObjectCreationException {
348: //This needs to be done so the data provider will skip a data set
349: m_testClass.getClassInstance(runParams);
350: if (isLoopStart())
351: m_testClass.initialize();
352: }
353:
354: //---------------------------------------------------------------------------
355: public void callMethod(Map<String, Object> runParams)
356: throws ObjectCreationException, IllegalAccessException,
357: InvocationTargetException, InitializationException {
358: Object obj = m_testClass.getClassInstance(runParams);
359:
360: //Test for begining of a data loop, this means he is the first method of a class with a data provider
361: if (isLoopStart())
362: m_testClass.initialize();
363:
364: m_method.invoke(obj);
365: }
366:
367: //---------------------------------------------------------------------------
368: public void reportStatus(Document doc, Element test) {
369: test.setAttribute("name", "");
370: test.setAttribute("class", m_testClass.getFullName());
371: test.setAttribute("method", m_method.getName());
372: test.setAttribute("status", m_status);
373:
374: Element groups = doc.createElement("groups");
375: test.appendChild(groups);
376:
377: if (m_groups != null)
378: for (String groupName : m_groups) {
379: Element group = doc.createElement("group");
380: group.appendChild(doc.createTextNode(groupName));
381: groups.appendChild(group);
382: }
383:
384: }
385:
386: //---------------------------------------------------------------------------
387: public String toString() {
388: StringBuilder sb = new StringBuilder();
389: sb.append(m_method.getName());
390: return (sb.toString());
391: }
392:
393: //---------------------------------------------------------------------------
394: public String printStack(Throwable t) {
395: StringWriter sw = new StringWriter();
396: PrintWriter pw = new PrintWriter(sw);
397: boolean inMethod = false;
398:
399: String method = m_method.getName();
400: String klass = m_testClass.getFullName();
401: StackTraceElement[] stack = t.getStackTrace();
402: pw.println(t.getClass().getName() + ": " + t.getMessage());
403:
404: for (StackTraceElement e : stack) {
405: if (method.equals(e.getMethodName())
406: && klass.equals(e.getClassName()))
407: inMethod = true;
408: else if (inMethod)
409: break;
410:
411: pw.println(" at " + e.getClassName() + "."
412: + e.getMethodName() + "(" + e.getFileName() + ":"
413: + e.getLineNumber() + ")");
414: }
415:
416: pw.close();
417: return (sw.toString());
418: }
419: }
|