Bug 581338: [UnitTest] no markers for python test

  add markers for failures() and exceptions

Change-Id: Ia41dfa786449d0a837d0426a18ea43888cc1bf69
diff --git a/plugins/org.eclipse.ease.lang.python.py4j/pysrc/py4jdb.py b/plugins/org.eclipse.ease.lang.python.py4j/pysrc/py4jdb.py
index 7bfd0f3..f816d12 100644
--- a/plugins/org.eclipse.ease.lang.python.py4j/pysrc/py4jdb.py
+++ b/plugins/org.eclipse.ease.lang.python.py4j/pysrc/py4jdb.py
@@ -197,6 +197,7 @@
 
         # Caches for currently executed code parts
         self._current_frame = None
+        self._last_exception_frame = None
         self._current_file = None
 
         # Async continuation handling
@@ -206,6 +207,18 @@
         # TODO: Think about a better way to handle step return
         self._return_hack = False
 
+    def getCurrentFrame(self):
+        if self._current_frame is not None:
+        	  return _pyease_PyFrame(self._current_frame)
+        	  
+        return None
+    
+    def getExceptionFrame(self):
+        if self._last_exception_frame is not None:
+        	  return _pyease_PyFrame(self._last_exception_frame)
+
+        return None
+
     def setDebugger(self, debugger):
         '''
         Setter method for self._debugger.
@@ -228,7 +241,9 @@
         '''
         # Pre-filter to avoid issues with library internals
         if not _pyease_ignore_frame(frame):
+            self._current_frame = frame
             _pyease_bdb.Bdb.trace_dispatch(self, frame, event, arg)
+        
         return self.trace_dispatch
 
     def user_line(self, frame):
@@ -259,6 +274,12 @@
         self._continue_func = self.set_step
         self.dispatch(frame, 'return')
 
+    def dispatch_exception(self, frame, arg):
+        if not frame.f_code.co_filename.endswith("bdb.py"):
+            self._last_exception_frame = frame
+        
+        _pyease_bdb.Bdb.dispatch_exception(self, frame, arg)
+        
     def user_exception(self, frame, exc_info):
         '''
         Called when debugger thinks thrown exception is of interest.
@@ -266,9 +287,6 @@
         :param frame:    Current stack frame with exception information.
         :param exc_info:    ignored
         '''
-        # Cache exception
-        if self._debugger:
-            self._debugger.setExceptionStackTrace(_pyease_PyFrame(frame))
 
         self._continue_func = self.set_continue
         self.dispatch(frame, 'exception')
diff --git a/plugins/org.eclipse.ease.lang.python.py4j/src/org/eclipse/ease/lang/python/py4j/internal/ICodeTraceFilter.java b/plugins/org.eclipse.ease.lang.python.py4j/src/org/eclipse/ease/lang/python/py4j/internal/ICodeTraceFilter.java
index cef8ea8..243e1dd 100644
--- a/plugins/org.eclipse.ease.lang.python.py4j/src/org/eclipse/ease/lang/python/py4j/internal/ICodeTraceFilter.java
+++ b/plugins/org.eclipse.ease.lang.python.py4j/src/org/eclipse/ease/lang/python/py4j/internal/ICodeTraceFilter.java
@@ -16,6 +16,7 @@
 import org.eclipse.ease.IExecutionListener;
 import org.eclipse.ease.debugging.dispatcher.IEventProcessor;
 import org.eclipse.ease.lang.python.debugger.ICodeTracer;
+import org.eclipse.ease.lang.python.debugger.IPyFrame;
 import org.eclipse.ease.lang.python.debugger.PythonBreakpoint;
 import org.eclipse.ease.lang.python.debugger.PythonDebugger;
 
@@ -49,7 +50,7 @@
 
 	/**
 	 * Resume execution after filter has notified us that execution might need to be stopped.
-	 * 
+	 *
 	 * @param resumeType
 	 *            Resume type for execution continuation.
 	 */
@@ -59,4 +60,18 @@
 	 * Suspend execution after filter has notified us that execution might need to be stopped.
 	 */
 	void suspend();
+
+	/**
+	 * Get the current python frame.
+	 *
+	 * @return current python frame
+	 */
+	IPyFrame getCurrentFrame();
+
+	/**
+	 * Get the python frame of the last thrown exception.
+	 *
+	 * @return last exception python frame
+	 */
+	IPyFrame getExceptionFrame();
 }
diff --git a/plugins/org.eclipse.ease.lang.python.py4j/src/org/eclipse/ease/lang/python/py4j/internal/Py4jDebugger.java b/plugins/org.eclipse.ease.lang.python.py4j/src/org/eclipse/ease/lang/python/py4j/internal/Py4jDebugger.java
index 2b8bf6e..2c41659 100644
--- a/plugins/org.eclipse.ease.lang.python.py4j/src/org/eclipse/ease/lang/python/py4j/internal/Py4jDebugger.java
+++ b/plugins/org.eclipse.ease.lang.python.py4j/src/org/eclipse/ease/lang/python/py4j/internal/Py4jDebugger.java
@@ -23,11 +23,15 @@
 import org.eclipse.ease.IDebugEngine;
 import org.eclipse.ease.Script;
 import org.eclipse.ease.ScriptEngineCancellationException;
+import org.eclipse.ease.debugging.ScriptStackTrace;
 import org.eclipse.ease.debugging.events.debugger.IDebuggerEvent;
+import org.eclipse.ease.lang.python.debugger.IPyFrame;
 import org.eclipse.ease.lang.python.debugger.IPythonScriptRegistry;
 import org.eclipse.ease.lang.python.debugger.PythonBreakpoint;
 import org.eclipse.ease.lang.python.debugger.PythonDebugger;
 
+import py4j.Py4JException;
+
 /**
  * Extension of {@link PythonDebugger} with additional {@link ICodeTraceFilter} to lower amount of trace dispatches.
  */
@@ -35,11 +39,8 @@
 	/**
 	 * Extended code tracer doing pre-filtering.
 	 */
-	private ICodeTraceFilter fTraceFilter;
+	private ICodeTraceFilter fPythonDebuggerStub;
 
-	/**
-	 * @see PythonDebugger#PythonDebugger(IDebugEngine, boolean)
-	 */
 	public Py4jDebugger(IDebugEngine engine, boolean showDynamicCode) {
 		super(engine, showDynamicCode);
 	}
@@ -50,8 +51,8 @@
 	 * @param traceFilter
 	 *            Extended code tracer.
 	 */
-	public void setTraceFilter(ICodeTraceFilter traceFilter) {
-		fTraceFilter = traceFilter;
+	public void setPythonDebuggerStub(ICodeTraceFilter traceFilter) {
+		fPythonDebuggerStub = traceFilter;
 	}
 
 	/**
@@ -70,30 +71,32 @@
 				final List<IBreakpoint> breakpoints = fBreakpoints.get(script);
 				if (breakpoints != null) {
 					final List<PythonBreakpoint> pythonBreakpoints = new ArrayList<>();
+
 					for (final IBreakpoint breakpoint : breakpoints) {
-						final int lineno = breakpoint.getMarker().getAttribute(IMarker.LINE_NUMBER, -1);
-						pythonBreakpoints.add(new PythonBreakpoint(filename, lineno));
+						final int lineNumber = breakpoint.getMarker().getAttribute(IMarker.LINE_NUMBER, -1);
+						pythonBreakpoints.add(new PythonBreakpoint(filename, lineNumber));
 					}
+
 					return pythonBreakpoints;
 				}
 			}
 		}
 
-		return Collections.<PythonBreakpoint> emptyList();
-
+		return Collections.emptyList();
 	}
 
 	@Override
 	protected void suspend(IDebuggerEvent event) {
-		fTraceFilter.suspend();
-		super.suspend(event);
+		fPythonDebuggerStub.suspend();
 
+		super.suspend(event);
 	}
 
 	@Override
 	protected void resume(int resumeType, Object thread) {
 		super.resume(resumeType, thread);
-		fTraceFilter.resume(resumeType);
+
+		fPythonDebuggerStub.resume(resumeType);
 	}
 
 	@Override
@@ -105,7 +108,8 @@
 				registry.put(script);
 				reference = registry.getReference(script);
 			}
-			return fTraceFilter.run(script, reference);
+
+			return fPythonDebuggerStub.run(script, reference);
 
 		} catch (final Exception e) {
 			/*
@@ -118,10 +122,18 @@
 			if (getThreadState(getThread()).fResumeType == DebugEvent.STEP_END) {
 				throw new ScriptEngineCancellationException();
 			}
+
+			if (e instanceof Py4JException)
+				throw new Py4JException(beautifyExceptionMessage(e.getMessage()));
+
 			throw e;
 		}
 	}
 
+	private String beautifyExceptionMessage(String message) {
+		return message;
+	}
+
 	@Override
 	protected void breakpointAdded(final Script script, final IBreakpoint breakpoint) {
 		final IPythonScriptRegistry registry = getScriptRegistry();
@@ -131,11 +143,10 @@
 
 		final String reference = registry.getReference(script);
 		if (reference != null) {
-			final int linenumber = breakpoint.getMarker().getAttribute(IMarker.LINE_NUMBER, -1);
+			final int lineNumber = breakpoint.getMarker().getAttribute(IMarker.LINE_NUMBER, -1);
 
-			if (linenumber != -1) {
-				fTraceFilter.setBreakpoint(new PythonBreakpoint(reference, linenumber));
-			}
+			if (lineNumber != -1)
+				fPythonDebuggerStub.setBreakpoint(new PythonBreakpoint(reference, lineNumber));
 		}
 	}
 
@@ -148,11 +159,32 @@
 
 		final String reference = registry.getReference(script);
 		if (reference != null) {
-			final int linenumber = breakpoint.getMarker().getAttribute(IMarker.LINE_NUMBER, -1);
+			final int lineNumber = breakpoint.getMarker().getAttribute(IMarker.LINE_NUMBER, -1);
 
-			if (linenumber != -1) {
-				fTraceFilter.removeBreakpoint(new PythonBreakpoint(reference, linenumber));
-			}
+			if (lineNumber != -1)
+				fPythonDebuggerStub.removeBreakpoint(new PythonBreakpoint(reference, lineNumber));
 		}
 	}
+
+	@Override
+	public ScriptStackTrace getStacktrace() {
+		return toStackTrace(fPythonDebuggerStub.getCurrentFrame());
+	}
+
+	@Override
+	public ScriptStackTrace getExceptionStacktrace() {
+		return toStackTrace(fPythonDebuggerStub.getExceptionFrame());
+	}
+
+	private ScriptStackTrace toStackTrace(IPyFrame frame) {
+		final ScriptStackTrace trace = new ScriptStackTrace();
+
+		while (frame != null) {
+			trace.add(new PythonDebugFrame(frame));
+
+			frame = frame.getParent();
+		}
+
+		return trace;
+	}
 }
diff --git a/plugins/org.eclipse.ease.lang.python.py4j/src/org/eclipse/ease/lang/python/py4j/internal/Py4jDebuggerEngine.java b/plugins/org.eclipse.ease.lang.python.py4j/src/org/eclipse/ease/lang/python/py4j/internal/Py4jDebuggerEngine.java
index a82c470..34c0759 100644
--- a/plugins/org.eclipse.ease.lang.python.py4j/src/org/eclipse/ease/lang/python/py4j/internal/Py4jDebuggerEngine.java
+++ b/plugins/org.eclipse.ease.lang.python.py4j/src/org/eclipse/ease/lang/python/py4j/internal/Py4jDebuggerEngine.java
@@ -27,6 +27,7 @@
 import org.eclipse.ease.lang.python.debugger.IPythonDebugEngine;
 import org.eclipse.ease.lang.python.debugger.PythonDebugger;
 import org.eclipse.ease.lang.python.debugger.PythonEventDispatchJob;
+import org.eclipse.ease.lang.python.debugger.PythonScriptRegistry;
 import org.eclipse.ease.lang.python.debugger.ResourceHelper;
 import org.eclipse.ease.lang.python.debugger.model.PythonDebugTarget;
 
@@ -41,7 +42,6 @@
 	public static final String ENGINE_ID = "org.eclipse.ease.lang.python.py4j.debugger.engine";
 
 	private Py4jDebugger fDebugger = null;
-	private ICodeTraceFilter fPyDebugger = null;
 
 	@Override
 	public void setDebugger(final PythonDebugger debugger) {
@@ -56,16 +56,22 @@
 	protected void setupEngine() throws ScriptEngineException {
 		super.setupEngine();
 
+		if (fDebugger == null) {
+			final Py4jDebugger debugger = new Py4jDebugger(this, false);
+			debugger.setScriptRegistry(new PythonScriptRegistry());
+			setDebugger(debugger);
+		}
+
 		// in case we were called using "Run as"
 		if (fDebugger != null) {
 			try {
 				// load python part of debugger
 				final InputStream stream = ResourceHelper.getResourceStream("org.eclipse.ease.lang.python.py4j", "pysrc/py4jdb.py");
-				fPyDebugger = (ICodeTraceFilter) super.internalExecute(new Script("Load Python debugger", stream), null);
+				final ICodeTraceFilter pythonDebugger = (ICodeTraceFilter) super.internalExecute(new Script("Load Python debugger", stream), null);
 
 				// Connect both sides
-				fPyDebugger.setDebugger(fDebugger);
-				fDebugger.setTraceFilter(fPyDebugger);
+				pythonDebugger.setDebugger(fDebugger);
+				fDebugger.setPythonDebuggerStub(pythonDebugger);
 
 			} catch (final Throwable e) {
 				throw new ScriptEngineException("Failed to load Python Debugger", e);
@@ -77,16 +83,17 @@
 	protected void teardownEngine() {
 		super.teardownEngine();
 
-		fPyDebugger = null;
 		fDebugger = null;
 	}
 
 	@Override
 	protected Object internalExecute(final Script script, final String fileName) throws Throwable {
-		if (fDebugger != null)
-			return fDebugger.execute(script);
+		return fDebugger.execute(script);
+	}
 
-		return super.internalExecute(script, fileName);
+	@Override
+	public ScriptStackTrace getStackTrace() {
+		return fDebugger.getStacktrace();
 	}
 
 	@Override
@@ -108,8 +115,7 @@
 
 	@Override
 	public ScriptStackTrace getExceptionStackTrace(Object thread) {
-		// FIXME to be implemented
-		return null;
+		return fDebugger.getExceptionStacktrace();
 	}
 
 	@Override
@@ -134,11 +140,4 @@
 
 		return variables;
 	}
-
-	@Override
-	protected EaseDebugVariable createVariable(String name, Object value) {
-		final EaseDebugVariable variable = super.createVariable(name, value);
-
-		return variable;
-	}
 }
diff --git a/plugins/org.eclipse.ease.lang.python/src/org/eclipse/ease/lang/python/debugger/PythonDebugger.java b/plugins/org.eclipse.ease.lang.python/src/org/eclipse/ease/lang/python/debugger/PythonDebugger.java
index 6af4766..3bc5e0b 100644
--- a/plugins/org.eclipse.ease.lang.python/src/org/eclipse/ease/lang/python/debugger/PythonDebugger.java
+++ b/plugins/org.eclipse.ease.lang.python/src/org/eclipse/ease/lang/python/debugger/PythonDebugger.java
@@ -53,27 +53,28 @@
 		public PythonDebugFrame(final IPyFrame frame) {
 			super(getScriptRegistry() != null ? getScriptRegistry().getScript(frame.getFilename()) : null, frame.getLineNumber(), TYPE_FILE);
 			fFrame = frame;
-
 		}
 
 		@Override
 		public String getName() {
 			final Script script = getScript();
-			if (script.isDynamic()) {
-				// dynamic script
-				final String title = getScript().getTitle();
-				return (title != null) ? "Dynamic: " + title : "(Dynamic)";
+			if (script != null) {
+				if (script.isDynamic()) {
+					// dynamic script
+					final String title = getScript().getTitle();
+					return (title != null) ? "Dynamic: " + title : "(Dynamic)";
 
-			} else {
-				final Object command = getScript().getCommand();
-				if (command != null) {
-					if (command instanceof IFile)
-						return ((IFile) command).getName();
+				} else {
+					final Object command = getScript().getCommand();
+					if (command != null) {
+						if (command instanceof IFile)
+							return ((IFile) command).getName();
 
-					else if (command instanceof File)
-						return ((File) command).getName();
+						else if (command instanceof File)
+							return ((File) command).getName();
 
-					return command.toString();
+						return command.toString();
+					}
 				}
 			}