package hu.advancedweb.scott.runtime;

import java.lang.reflect.Field;

import org.junit.runner.Description;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;

/**
 * An alternative way to produce the detailed failure reports is to register this JUnit listener.
 * 
 * @see ScottReportingRule
 * @author David Csakvari
 */
public class ScottRunListener extends RunListener {
	
	private Description description;
	
	@Override
	public void testStarted(Description description) throws Exception {
		this.description = description;
		super.testStarted(description);
	}
	
	@Override
	public void testFailure(Failure failure) throws Exception {
		String scottReport = FailureRenderer.render(description, failure.getException());
		setExceptionMessage(failure.getException(), scottReport);
		super.testFailure(failure);
	}
	
	private void setExceptionMessage(Object object, Object fieldValue) {
	    final String fieldName = "detailMessage";
		Class<?> clazz = object.getClass();
	    while (clazz != null) {
	        try {
	            Field field = clazz.getDeclaredField(fieldName);
	            field.setAccessible(true);
	            field.set(object, fieldValue);
	            return;
	        } catch (NoSuchFieldException e) {
	            clazz = clazz.getSuperclass();
	        } catch (Exception e) {
	            throw new IllegalStateException(e);
	        }
	    }
	}
}

@@ -63,16 +63,64 @@
 t.Field;
+%0Aimport java.util.HashSet;%0Aimport java.util.Set;
 %0A%0Aimport
@@ -500,16 +500,222 @@
 tion;%0A%09%0A
+%09/**%0A%09 * Sometimes testFailure is called multiple times for a single test,%0A%09 * so we has to track the already augmented Exception objects.%0A%09 */%0A%09private Set%3CObject%3E augmentedExceptions = new HashSet%3C%3E();%0A%09%0A
 %09@Overri
@@ -820,16 +820,50 @@
 iption;%0A
+%09%09augmentedExceptions.clear();%0A%09%09%0A
 %09%09super.
@@ -1215,20 +1215,101 @@
 lue) %7B%0A%09
-    
+%09if (!augmentedExceptions.contains(object)) %7B%0A%09%09%09augmentedExceptions.add(object);%0A%09%09%09
 final St
@@ -1344,16 +1344,17 @@
 age%22;%0A%09%09
+%09
 Class%3C?%3E
@@ -1382,20 +1382,18 @@
 ass();%0A%09
-    
+%09%09
 while (c
@@ -1413,35 +1413,22 @@
  %7B%0A%09
-        try %7B%0A%09            
+%09%09%09try %7B%0A%09%09%09%09%09
 Fiel
@@ -1469,36 +1469,28 @@
 ieldName);%0A%09
-            
+%09%09%09%09
 field.setAcc
@@ -1505,28 +1505,20 @@
 true);%0A%09
-            
+%09%09%09%09
 field.se
@@ -1541,28 +1541,20 @@
 alue);%0A%09
-            
+%09%09%09%09
 return;%0A
@@ -1554,24 +1554,19 @@
 eturn;%0A%09
-        
+%09%09%09
 %7D catch 
@@ -1593,28 +1593,20 @@
 n e) %7B%0A%09
-            
+%09%09%09%09
 clazz = 
@@ -1629,24 +1629,19 @@
 ass();%0A%09
-        
+%09%09%09
 %7D catch 
@@ -1661,20 +1661,12 @@
  %7B%0A%09
-            
+%09%09%09%09
 thro
@@ -1702,23 +1702,20 @@
 );%0A%09
-        %7D%0A%09    
+%09%09%09%7D%0A%09%09%09%7D%0A%09%09
 %7D%0A%09%7D

Fix exception message augmentation in run listener to avoid multiple augmentations.