Skip to content
This repository
Browse code

initial commit of new Haskell test results view

  • Loading branch information...
commit 599399252be65e9705bfbaa2349132b5337b5c30 1 parent 27274b2
JP Moresmau authored November 14, 2012

Showing 38 changed files with 1,294 additions and 255 deletions. Show diff stats Hide diff stats

  1. 4  docs/file-templates.txt
  2. 3  net.sf.eclipsefp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/types/Location.java
  3. 6  net.sf.eclipsefp.haskell.debug.core/META-INF/MANIFEST.MF
  4. 2  net.sf.eclipsefp.haskell.debug.core/plugin.properties
  5. 1  net.sf.eclipsefp.haskell.debug.core/plugin.xml
  6. 218  net.sf.eclipsefp.haskell.debug.core/schema/interactiveDelegates.exsd
  7. 109  net.sf.eclipsefp.haskell.debug.core/schema/testListeners.exsd
  8. 2  net.sf.eclipsefp.haskell.debug.core/src/net/sf/eclipsefp/haskell/debug/core/internal/HaskellDebugCore.java
  9. 14  ...skell.debug.core/src/net/sf/eclipsefp/haskell/debug/core/internal/launch/AbstractHaskellLaunchDelegate.java
  10. 64  ...kell.debug.core/src/net/sf/eclipsefp/haskell/debug/core/internal/launch/TestSuiteHaskellLaunchDelegate.java
  11. 33  net.sf.eclipsefp.haskell.debug.core/src/net/sf/eclipsefp/haskell/debug/core/test/ITestListener.java
  12. 39  net.sf.eclipsefp.haskell.debug.core/src/net/sf/eclipsefp/haskell/debug/core/test/TestListenerManager.java
  13. 124  net.sf.eclipsefp.haskell.debug.core/src/net/sf/eclipsefp/haskell/debug/core/test/TestResult.java
  14. 19  net.sf.eclipsefp.haskell.debug.core/src/net/sf/eclipsefp/haskell/debug/core/test/TestStatus.java
  15. 131  net.sf.eclipsefp.haskell.debug.core/src/net/sf/eclipsefp/haskell/debug/core/test/TestSuite.java
  16. BIN  net.sf.eclipsefp.haskell.debug.ui/icons/eview16/haskell_test.png
  17. 2  net.sf.eclipsefp.haskell.debug.ui/plugin.properties
  18. 29  net.sf.eclipsefp.haskell.debug.ui/plugin.xml
  19. 76  net.sf.eclipsefp.haskell.debug.ui/src/net/sf/eclipsefp/haskell/debug/ui/internal/HaskellDebugUI.java
  20. 5  net.sf.eclipsefp.haskell.debug.ui/src/net/sf/eclipsefp/haskell/debug/ui/internal/util/UITexts.java
  21. 7  net.sf.eclipsefp.haskell.debug.ui/src/net/sf/eclipsefp/haskell/debug/ui/internal/util/uitexts.properties
  22. 96  net.sf.eclipsefp.haskell.debug.ui/src/net/sf/eclipsefp/haskell/debug/ui/test/TestResultCP.java
  23. 51  net.sf.eclipsefp.haskell.debug.ui/src/net/sf/eclipsefp/haskell/debug/ui/test/TestResultLP.java
  24. 201  net.sf.eclipsefp.haskell.debug.ui/src/net/sf/eclipsefp/haskell/debug/ui/test/TestResultView.java
  25. 90  net.sf.eclipsefp.haskell.debug.ui/src/net/sf/eclipsefp/haskell/debug/ui/test/ViewTestListener.java
  26. 1  net.sf.eclipsefp.haskell.ui/META-INF/MANIFEST.MF
  27. BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/correction.gif
  28. BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/terminatedlaunch_obj.gif
  29. BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/test.gif
  30. BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/testerr.gif
  31. BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/testfail.gif
  32. BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/testok.gif
  33. BIN  net.sf.eclipsefp.haskell.ui/icons/obj16/testrun.gif
  34. BIN  net.sf.eclipsefp.haskell.ui/icons/ovr16/failed_ovr.gif
  35. 193  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/HaskellPerspective.java
  36. 13  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/handlers/OpenDefinitionHandler.java
  37. 8  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/util/HaskellUIImages.java
  38. 8  net.sf.eclipsefp.haskell.ui/src/net/sf/eclipsefp/haskell/ui/util/IImageNames.java
4  docs/file-templates.txt
@@ -8,6 +8,6 @@ Cabal
8 8
 
9 9
 Haskell	
10 10
 	- module
11  
-	- Literate module
12  
-	- Tex module
  11
+	- Literate module NO, done via code
  12
+	- Tex module NO, done via code
13 13
 	- Main file referencing module
3  net.sf.eclipsefp.haskell.buildwrapper/src/net/sf/eclipsefp/haskell/buildwrapper/types/Location.java
... ...
@@ -1,5 +1,6 @@
1 1
 package net.sf.eclipsefp.haskell.buildwrapper.types;
2 2
 
  3
+import java.io.File;
3 4
 import java.io.FileInputStream;
4 5
 import java.io.IOException;
5 6
 import java.io.InputStream;
@@ -265,6 +266,8 @@ public IFile getIFile(IProject p){
265 266
 		String loc=getFileName();
266 267
 		if (loc!=null && loc.startsWith(pl)){
267 268
 			return (IFile)p.getFile(loc.substring(pl.length()));
  269
+		} else if (!new File(loc).isAbsolute()) {
  270
+			return p.getFile(loc);
268 271
 		}
269 272
 		return null;
270 273
 	}
6  net.sf.eclipsefp.haskell.debug.core/META-INF/MANIFEST.MF
@@ -18,7 +18,8 @@ Require-Bundle: org.eclipse.core.runtime,
18 18
  org.eclipse.jdt.core;resolution:=optional,
19 19
  org.eclipse.jdt.junit;bundle-version="3.5.0";resolution:=optional,
20 20
  org.eclipse.ui.workbench.texteditor,
21  
- org.eclipse.ui.editors
  21
+ org.eclipse.ui.editors,
  22
+ net.sf.eclipsefp.haskell.buildwrapper
22 23
 Bundle-ActivationPolicy: lazy
23 24
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
24 25
 Bundle-Localization: plugin
@@ -28,6 +29,7 @@ Export-Package: net.sf.eclipsefp.haskell.debug.core.internal,
28 29
   x-friends:="net.sf.eclipsefp.haskell.haddock,
29 30
    net.sf.eclipsefp.haskell.ui,
30 31
    net.sf.eclipsefp.haskell.debug.ui,
31  
-   net.sf.eclipsefp.haskell.hugs"
  32
+   net.sf.eclipsefp.haskell.hugs",
  33
+ net.sf.eclipsefp.haskell.debug.core.test
32 34
 Bundle-ClassPath: .,
33 35
  lib/jdom.jar
2  net.sf.eclipsefp.haskell.debug.core/plugin.properties
@@ -4,7 +4,7 @@
4 4
 
5 5
 # extension points
6 6
 extPtInteractive_name = Interactive delegates
7  
-
  7
+extPtTestListeners_name = Test listeners
8 8
 
9 9
 # bundle manifest
10 10
 bundleVendor = The EclipseFP Project
1  net.sf.eclipsefp.haskell.debug.core/plugin.xml
@@ -2,6 +2,7 @@
2 2
 <?eclipse version="3.2"?>
3 3
 <plugin>
4 4
 	<extension-point id="interactiveDelegates" name="%extPtInteractive_name" schema="schema/interactiveDelegates.exsd"/>
  5
+ <extension-point id="testListeners" name="%extPtTestListeners_name" schema="schema/testListeners.exsd"/>
5 6
 
6 7
    <extension
7 8
          point="org.eclipse.debug.core.launchConfigurationTypes">
218  net.sf.eclipsefp.haskell.debug.core/schema/interactiveDelegates.exsd
... ...
@@ -1,109 +1,109 @@
1  
-<?xml version='1.0' encoding='UTF-8'?>
2  
-<!-- Schema file written by PDE -->
3  
-<schema targetNamespace="net.sf.eclipsefp.haskell.debug.core" xmlns="http://www.w3.org/2001/XMLSchema">
4  
-<annotation>
5  
-      <appInfo>
6  
-         <meta.schema plugin="net.sf.eclipsefp.haskell.debug.core" id="interactiveDelegates" name="Interactive Delegates"/>
7  
-      </appInfo>
8  
-      <documentation>
9  
-         Delegates for interactive launch operations: find the execution info at runtime
10  
-      </documentation>
11  
-   </annotation>
12  
-
13  
-   <element name="extension">
14  
-      <annotation>
15  
-         <appInfo>
16  
-            <meta.element />
17  
-         </appInfo>
18  
-      </annotation>
19  
-      <complexType>
20  
-         <sequence>
21  
-            <element ref="delegate" minOccurs="1" maxOccurs="unbounded"/>
22  
-         </sequence>
23  
-         <attribute name="point" type="string" use="required">
24  
-            <annotation>
25  
-               <documentation>
26  
-                  
27  
-               </documentation>
28  
-            </annotation>
29  
-         </attribute>
30  
-         <attribute name="id" type="string">
31  
-            <annotation>
32  
-               <documentation>
33  
-                  
34  
-               </documentation>
35  
-            </annotation>
36  
-         </attribute>
37  
-         <attribute name="name" type="string">
38  
-            <annotation>
39  
-               <documentation>
40  
-                  
41  
-               </documentation>
42  
-               <appInfo>
43  
-                  <meta.attribute translatable="true"/>
44  
-               </appInfo>
45  
-            </annotation>
46  
-         </attribute>
47  
-      </complexType>
48  
-   </element>
49  
-
50  
-   <element name="delegate">
51  
-      <complexType>
52  
-         <attribute name="id" type="string" use="required">
53  
-            <annotation>
54  
-               <documentation>
55  
-                  
56  
-               </documentation>
57  
-            </annotation>
58  
-         </attribute>
59  
-         <attribute name="class" type="string" use="required">
60  
-            <annotation>
61  
-               <documentation>
62  
-                  
63  
-               </documentation>
64  
-               <appInfo>
65  
-                  <meta.attribute kind="java" basedOn=":net.sf.eclipsefp.haskell.debug.core.internal.launch.IInteractiveLaunchOperationDelegate"/>
66  
-               </appInfo>
67  
-            </annotation>
68  
-         </attribute>
69  
-      </complexType>
70  
-   </element>
71  
-
72  
-   <annotation>
73  
-      <appInfo>
74  
-         <meta.section type="since"/>
75  
-      </appInfo>
76  
-      <documentation>
77  
-         1.109
78  
-      </documentation>
79  
-   </annotation>
80  
-
81  
-   <annotation>
82  
-      <appInfo>
83  
-         <meta.section type="examples"/>
84  
-      </appInfo>
85  
-      <documentation>
86  
-         [Enter extension point usage example here.]
87  
-      </documentation>
88  
-   </annotation>
89  
-
90  
-   <annotation>
91  
-      <appInfo>
92  
-         <meta.section type="apiinfo"/>
93  
-      </appInfo>
94  
-      <documentation>
95  
-         [Enter API information here.]
96  
-      </documentation>
97  
-   </annotation>
98  
-
99  
-   <annotation>
100  
-      <appInfo>
101  
-         <meta.section type="implementation"/>
102  
-      </appInfo>
103  
-      <documentation>
104  
-         [Enter information about supplied implementation of this extension point.]
105  
-      </documentation>
106  
-   </annotation>
107  
-
108  
-
109  
-</schema>
  1
+<?xml version='1.0' encoding='UTF-8'?>
  2
+<!-- Schema file written by PDE -->
  3
+<schema targetNamespace="net.sf.eclipsefp.haskell.debug.core" xmlns="http://www.w3.org/2001/XMLSchema">
  4
+<annotation>
  5
+      <appInfo>
  6
+         <meta.schema plugin="net.sf.eclipsefp.haskell.debug.core" id="interactiveDelegates" name="Interactive Delegates"/>
  7
+      </appInfo>
  8
+      <documentation>
  9
+         Delegates for interactive launch operations: find the execution info at runtime
  10
+      </documentation>
  11
+   </annotation>
  12
+
  13
+   <element name="extension">
  14
+      <annotation>
  15
+         <appInfo>
  16
+            <meta.element />
  17
+         </appInfo>
  18
+      </annotation>
  19
+      <complexType>
  20
+         <sequence>
  21
+            <element ref="delegate" minOccurs="1" maxOccurs="unbounded"/>
  22
+         </sequence>
  23
+         <attribute name="point" type="string" use="required">
  24
+            <annotation>
  25
+               <documentation>
  26
+                  
  27
+               </documentation>
  28
+            </annotation>
  29
+         </attribute>
  30
+         <attribute name="id" type="string">
  31
+            <annotation>
  32
+               <documentation>
  33
+                  
  34
+               </documentation>
  35
+            </annotation>
  36
+         </attribute>
  37
+         <attribute name="name" type="string">
  38
+            <annotation>
  39
+               <documentation>
  40
+                  
  41
+               </documentation>
  42
+               <appInfo>
  43
+                  <meta.attribute translatable="true"/>
  44
+               </appInfo>
  45
+            </annotation>
  46
+         </attribute>
  47
+      </complexType>
  48
+   </element>
  49
+
  50
+   <element name="delegate">
  51
+      <complexType>
  52
+         <attribute name="id" type="string" use="required">
  53
+            <annotation>
  54
+               <documentation>
  55
+                  
  56
+               </documentation>
  57
+            </annotation>
  58
+         </attribute>
  59
+         <attribute name="class" type="string" use="required">
  60
+            <annotation>
  61
+               <documentation>
  62
+                  
  63
+               </documentation>
  64
+               <appInfo>
  65
+                  <meta.attribute kind="java" basedOn=":net.sf.eclipsefp.haskell.debug.core.internal.launch.IInteractiveLaunchOperationDelegate"/>
  66
+               </appInfo>
  67
+            </annotation>
  68
+         </attribute>
  69
+      </complexType>
  70
+   </element>
  71
+
  72
+   <annotation>
  73
+      <appInfo>
  74
+         <meta.section type="since"/>
  75
+      </appInfo>
  76
+      <documentation>
  77
+         1.109
  78
+      </documentation>
  79
+   </annotation>
  80
+
  81
+   <annotation>
  82
+      <appInfo>
  83
+         <meta.section type="examples"/>
  84
+      </appInfo>
  85
+      <documentation>
  86
+         [Enter extension point usage example here.]
  87
+      </documentation>
  88
+   </annotation>
  89
+
  90
+   <annotation>
  91
+      <appInfo>
  92
+         <meta.section type="apiinfo"/>
  93
+      </appInfo>
  94
+      <documentation>
  95
+         [Enter API information here.]
  96
+      </documentation>
  97
+   </annotation>
  98
+
  99
+   <annotation>
  100
+      <appInfo>
  101
+         <meta.section type="implementation"/>
  102
+      </appInfo>
  103
+      <documentation>
  104
+         [Enter information about supplied implementation of this extension point.]
  105
+      </documentation>
  106
+   </annotation>
  107
+
  108
+
  109
+</schema>
109  net.sf.eclipsefp.haskell.debug.core/schema/testListeners.exsd
... ...
@@ -0,0 +1,109 @@
  1
+<?xml version='1.0' encoding='UTF-8'?>
  2
+<!-- Schema file written by PDE -->
  3
+<schema targetNamespace="net.sf.eclipsefp.haskell.debug.core" xmlns="http://www.w3.org/2001/XMLSchema">
  4
+<annotation>
  5
+      <appInfo>
  6
+         <meta.schema plugin="net.sf.eclipsefp.haskell.debug.core" id="testListeners" name="Test Listeners"/>
  7
+      </appInfo>
  8
+      <documentation>
  9
+         Delegates for test listener
  10
+      </documentation>
  11
+   </annotation>
  12
+
  13
+   <element name="extension">
  14
+      <annotation>
  15
+         <appInfo>
  16
+            <meta.element />
  17
+         </appInfo>
  18
+      </annotation>
  19
+      <complexType>
  20
+         <sequence>
  21
+            <element ref="delegate" minOccurs="1" maxOccurs="unbounded"/>
  22
+         </sequence>
  23
+         <attribute name="point" type="string" use="required">
  24
+            <annotation>
  25
+               <documentation>
  26
+                  
  27
+               </documentation>
  28
+            </annotation>
  29
+         </attribute>
  30
+         <attribute name="id" type="string">
  31
+            <annotation>
  32
+               <documentation>
  33
+                  
  34
+               </documentation>
  35
+            </annotation>
  36
+         </attribute>
  37
+         <attribute name="name" type="string">
  38
+            <annotation>
  39
+               <documentation>
  40
+                  
  41
+               </documentation>
  42
+               <appInfo>
  43
+                  <meta.attribute translatable="true"/>
  44
+               </appInfo>
  45
+            </annotation>
  46
+         </attribute>
  47
+      </complexType>
  48
+   </element>
  49
+
  50
+   <element name="delegate">
  51
+      <complexType>
  52
+         <attribute name="id" type="string" use="required">
  53
+            <annotation>
  54
+               <documentation>
  55
+                  
  56
+               </documentation>
  57
+            </annotation>
  58
+         </attribute>
  59
+         <attribute name="class" type="string" use="required">
  60
+            <annotation>
  61
+               <documentation>
  62
+                  
  63
+               </documentation>
  64
+               <appInfo>
  65
+                  <meta.attribute kind="java" basedOn=":net.sf.eclipsefp.haskell.debug.core.test.ITestListener"/>
  66
+               </appInfo>
  67
+            </annotation>
  68
+         </attribute>
  69
+      </complexType>
  70
+   </element>
  71
+
  72
+   <annotation>
  73
+      <appInfo>
  74
+         <meta.section type="since"/>
  75
+      </appInfo>
  76
+      <documentation>
  77
+         2.3.3
  78
+      </documentation>
  79
+   </annotation>
  80
+
  81
+   <annotation>
  82
+      <appInfo>
  83
+         <meta.section type="examples"/>
  84
+      </appInfo>
  85
+      <documentation>
  86
+         [Enter extension point usage example here.]
  87
+      </documentation>
  88
+   </annotation>
  89
+
  90
+   <annotation>
  91
+      <appInfo>
  92
+         <meta.section type="apiinfo"/>
  93
+      </appInfo>
  94
+      <documentation>
  95
+         [Enter API information here.]
  96
+      </documentation>
  97
+   </annotation>
  98
+
  99
+   <annotation>
  100
+      <appInfo>
  101
+         <meta.section type="implementation"/>
  102
+      </appInfo>
  103
+      <documentation>
  104
+         [Enter information about supplied implementation of this extension point.]
  105
+      </documentation>
  106
+   </annotation>
  107
+
  108
+
  109
+</schema>
2  net.sf.eclipsefp.haskell.debug.core/src/net/sf/eclipsefp/haskell/debug/core/internal/HaskellDebugCore.java
@@ -20,7 +20,7 @@
20 20
   public static final String ID_HASKELL_DEBUG_MODEL = "net.sf.eclipsefp.haskell.debug"; //$NON-NLS-1$
21 21
 
22 22
   public static final String ID_EXT_POINT_INTERACTIVE_DELEGATES = "interactiveDelegates"; //$NON-NLS-1$
23  
-
  23
+  public static final String ID_EXT_POINT_TEST_LISTENERS = "testListeners"; //$NON-NLS-1$
24 24
   /**
25 25
    * constant for command history enablement on process
26 26
    */
14  ...ll.debug.core/src/net/sf/eclipsefp/haskell/debug/core/internal/launch/AbstractHaskellLaunchDelegate.java
@@ -195,9 +195,17 @@ private IProcess createProcess( final ILaunchConfiguration configuration,
195 195
       Process proc = pb.start();
196 196
       if( proc != null ) {
197 197
         //String loc = location.toOSString();
198  
-        process = DebugPlugin.newProcess( launch, proc, configuration.getName(), processAttrs );
199  
-        process.setAttribute( IProcess.ATTR_CMDLINE, CommandLineUtil
200  
-            .renderCommandLine( cmdLine ) );
  198
+//        process = new RuntimeProcess( launch, proc, configuration.getName(), processAttrs){
  199
+//          @Override
  200
+//          protected org.eclipse.debug.core.model.IStreamsProxy createStreamsProxy() {
  201
+//
  202
+//              String encoding = getLaunch().getAttribute(DebugPlugin.ATTR_CONSOLE_ENCODING);
  203
+//              return new DelayedStreamsProxy(getSystemProcess(), encoding);
  204
+//          }
  205
+//        };
  206
+          process=DebugPlugin.newProcess( launch, proc, configuration.getName(), processAttrs );
  207
+          process.setAttribute( IProcess.ATTR_CMDLINE, CommandLineUtil
  208
+                .renderCommandLine( cmdLine ) );
201 209
       }
202 210
       return process;
203 211
     } catch( IOException e ) {
64  ...l.debug.core/src/net/sf/eclipsefp/haskell/debug/core/internal/launch/TestSuiteHaskellLaunchDelegate.java
@@ -3,8 +3,14 @@
3 3
 import java.io.File;
4 4
 import java.util.Map;
5 5
 import java.util.Random;
  6
+import javax.xml.parsers.DocumentBuilderFactory;
6 7
 import net.sf.eclipsefp.haskell.debug.core.internal.HaskellDebugCore;
7 8
 import net.sf.eclipsefp.haskell.debug.core.internal.util.CoreTexts;
  9
+import net.sf.eclipsefp.haskell.debug.core.test.ITestListener;
  10
+import net.sf.eclipsefp.haskell.debug.core.test.TestListenerManager;
  11
+import net.sf.eclipsefp.haskell.debug.core.test.TestResult;
  12
+import net.sf.eclipsefp.haskell.debug.core.test.TestStatus;
  13
+import net.sf.eclipsefp.haskell.debug.core.test.TestSuite;
8 14
 import org.eclipse.core.runtime.CoreException;
9 15
 import org.eclipse.debug.core.ILaunch;
10 16
 import org.eclipse.debug.core.ILaunchConfiguration;
@@ -14,11 +20,15 @@
14 20
 import org.eclipse.swt.widgets.Display;
15 21
 import org.eclipse.ui.IWorkbenchPage;
16 22
 import org.eclipse.ui.PlatformUI;
  23
+import org.w3c.dom.Document;
  24
+import org.w3c.dom.Element;
  25
+import org.w3c.dom.NodeList;
17 26
 
18 27
 /**
19 28
  * launch delegate for test-framework test suites
20 29
  *
21 30
  * @author Alejandro Serrano
  31
+ * @author JP Moresmau
22 32
  *
23 33
  */
24 34
 public class TestSuiteHaskellLaunchDelegate extends
@@ -50,11 +60,10 @@ protected void preProcessCreation( final ILaunchConfiguration configuration,
50 60
     // NOOP
51 61
 
52 62
   }
53  
-
54 63
   @Override
55 64
   protected void postProcessCreation( final ILaunchConfiguration configuration,
56 65
       final String mode, final ILaunch launch, final IProcess process ) {
57  
-    // NOOP
  66
+   // NOOP
58 67
   }
59 68
 
60 69
   @Override
@@ -64,11 +73,62 @@ protected void preProcessDefinitionCreation(
64 73
 
65 74
   }
66 75
 
  76
+  /**
  77
+   * Parse JUnit compatible XML element into a test result
  78
+   * @param et
  79
+   * @return
  80
+   */
  81
+  private TestResult parseTestResult(final Element et){
  82
+    String name=et.getAttribute( "name" ); //$NON-NLS-1$
  83
+    if (name!=null){
  84
+      TestResult ts=new TestResult(name);
  85
+      NodeList nl=et.getChildNodes();
  86
+
  87
+      for (int a=0;a<nl.getLength();a++){
  88
+        if (nl.item( a ) instanceof Element){
  89
+          Element e=(Element)nl.item(a);
  90
+          if (e.getTagName().equals( "failure" )){//$NON-NLS-1$
  91
+            ts.setStatus( TestStatus.FAILURE );
  92
+            ts.setText( e.getTextContent() );
  93
+          } else if (e.getTagName().equals( "error" )){//$NON-NLS-1$
  94
+            ts.setStatus( TestStatus.ERROR );
  95
+            ts.setText( e.getTextContent() );
  96
+          } else {
  97
+            TestResult ctr=parseTestResult(e);
  98
+            if (ctr!=null){
  99
+              ts.getChildren().add( ctr );
  100
+            }
  101
+          }
  102
+        }
  103
+      }
  104
+      if (nl.getLength()==0){
  105
+        ts.setStatus( TestStatus.OK );
  106
+      }
  107
+      return ts;
  108
+    }
  109
+    return null;
  110
+  }
  111
+
67 112
   @Override
68 113
   protected void postProcessFinished(final ILaunchConfiguration configuration) {
69 114
     // Get file and parse output
70 115
     final String fname = getFilename();
71 116
     final File file = new File( fname );
  117
+
  118
+    try {
  119
+      Document d=DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( file );
  120
+
  121
+      TestResult root=parseTestResult( d.getDocumentElement() );
  122
+      TestSuite ts=new TestSuite( root );
  123
+
  124
+      for (ITestListener l:TestListenerManager.getContributors().values()){
  125
+        l.start(ts);
  126
+        l.end( ts);
  127
+      }
  128
+    } catch (Throwable t){
  129
+      HaskellDebugCore.log( t.getLocalizedMessage(), t );
  130
+    }
  131
+
72 132
     // final TestSuiteAndSession session = TestSuiteAndSession.parseFile( file );
73 133
 
74 134
     if (canShowJUnit()) {
33  net.sf.eclipsefp.haskell.debug.core/src/net/sf/eclipsefp/haskell/debug/core/test/ITestListener.java
... ...
@@ -0,0 +1,33 @@
  1
+/**
  2
+ * Copyright (c) 2012 by JP Moresmau
  3
+ * This code is made available under the terms of the Eclipse Public License,
  4
+ * version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
  5
+ */
  6
+package net.sf.eclipsefp.haskell.debug.core.test;
  7
+
  8
+
  9
+
  10
+/**
  11
+ * Test listener for UI viewing, etc...
  12
+ * @author JP Moresmau
  13
+ *
  14
+ */
  15
+public interface ITestListener {
  16
+  /**
  17
+   * start a test suite
  18
+   * @param suite
  19
+   */
  20
+  public void start(TestSuite suite);
  21
+
  22
+  /**
  23
+   * test suite updated
  24
+   * @param suite
  25
+   */
  26
+  public void update(TestSuite suite);
  27
+
  28
+  /**
  29
+   * test suite complete
  30
+   * @param suite
  31
+   */
  32
+  public void end(TestSuite suite);
  33
+}
39  net.sf.eclipsefp.haskell.debug.core/src/net/sf/eclipsefp/haskell/debug/core/test/TestListenerManager.java
... ...
@@ -0,0 +1,39 @@
  1
+/**
  2
+ * Copyright (c) 2012 by JP Moresmau
  3
+ * This code is made available under the terms of the Eclipse Public License,
  4
+ * version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
  5
+ */
  6
+package net.sf.eclipsefp.haskell.debug.core.test;
  7
+
  8
+import java.util.HashMap;
  9
+import java.util.Map;
  10
+import net.sf.eclipsefp.haskell.core.HaskellCorePlugin;
  11
+import net.sf.eclipsefp.haskell.debug.core.internal.HaskellDebugCore;
  12
+import org.eclipse.core.runtime.CoreException;
  13
+import org.eclipse.core.runtime.IConfigurationElement;
  14
+
  15
+
  16
+/**
  17
+ * Helper for test listener extensions
  18
+ * @author JP Moresmau
  19
+ *
  20
+ */
  21
+public class TestListenerManager {
  22
+  private static Map<String,ITestListener> contribs=null;
  23
+
  24
+  public static Map<String,ITestListener> getContributors(){
  25
+    if (contribs==null){
  26
+      IConfigurationElement[] elts=HaskellDebugCore.getDefault().getExtensions( HaskellDebugCore.ID_EXT_POINT_TEST_LISTENERS );
  27
+      contribs=new HashMap<String, ITestListener>();
  28
+      for (IConfigurationElement elem:elts){
  29
+        try {
  30
+          Object o = elem.createExecutableExtension(HaskellCorePlugin.ATT_CLASS);
  31
+          contribs.put(o.getClass().getName(), (ITestListener )o);
  32
+        } catch (CoreException cex) {
  33
+          HaskellCorePlugin.log( cex );
  34
+        }
  35
+      }
  36
+    }
  37
+    return contribs;
  38
+  }
  39
+}
124  net.sf.eclipsefp.haskell.debug.core/src/net/sf/eclipsefp/haskell/debug/core/test/TestResult.java
... ...
@@ -0,0 +1,124 @@
  1
+/**
  2
+ * Copyright (c) 2012 by JP Moresmau
  3
+ * This code is made available under the terms of the Eclipse Public License,
  4
+ * version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
  5
+ */
  6
+package net.sf.eclipsefp.haskell.debug.core.test;
  7
+
  8
+import java.io.Serializable;
  9
+import java.util.LinkedList;
  10
+import java.util.List;
  11
+import net.sf.eclipsefp.haskell.buildwrapper.types.Location;
  12
+import org.eclipse.core.resources.IProject;
  13
+
  14
+
  15
+/**
  16
+ * A test result, possibly with sub tests
  17
+ * @author JP Moresmau
  18
+ *
  19
+ */
  20
+public class TestResult implements Serializable {
  21
+  /**
  22
+   *
  23
+   */
  24
+  private static final long serialVersionUID = 3219320400432673266L;
  25
+
  26
+  /**
  27
+   * the status
  28
+   */
  29
+  private TestStatus status=TestStatus.PENDING;
  30
+  /**
  31
+   * the test name
  32
+   */
  33
+  private final String name;
  34
+  /**
  35
+   * the relevant source code location, if any
  36
+   */
  37
+  private Location location;
  38
+  /**
  39
+   * the detail text, if any
  40
+   */
  41
+  private String text;
  42
+  /**
  43
+   * the related project, if any
  44
+   */
  45
+  private IProject project;
  46
+
  47
+  /**
  48
+   * the children
  49
+   */
  50
+  private final List<TestResult> children=new LinkedList<TestResult>();
  51
+
  52
+  public TestResult( final String name ) {
  53
+    super();
  54
+    this.name = name;
  55
+  }
  56
+
  57
+
  58
+  /**
  59
+   * get the status
  60
+   * if there are sub tests, the status depends on the status of the children
  61
+   * @return
  62
+   */
  63
+  public TestStatus getStatus() {
  64
+    TestStatus stat=children.size()>0?TestStatus.OK:status;
  65
+    for (TestResult child:children){
  66
+      if (child.getStatus()!=null && stat==null || child.getStatus().ordinal()>stat.ordinal()){
  67
+        stat=child.getStatus();
  68
+      }
  69
+    }
  70
+    return stat;
  71
+  }
  72
+
  73
+  public void setStatus( final TestStatus status ) {
  74
+    this.status = status;
  75
+  }
  76
+
  77
+  public String getName() {
  78
+    return name;
  79
+  }
  80
+
  81
+  public String getText() {
  82
+    return text;
  83
+  }
  84
+
  85
+  public void setText( final String text ) {
  86
+    this.text = text;
  87
+  }
  88
+
  89
+  /* (non-Javadoc)
  90
+   * @see java.lang.Object#toString()
  91
+   */
  92
+  @Override
  93
+  public String toString() {
  94
+   return getName();
  95
+  }
  96
+
  97
+
  98
+  public Location getLocation() {
  99
+    return location;
  100
+  }
  101
+
  102
+
  103
+  public void setLocation( final Location location ) {
  104
+    this.location = location;
  105
+  }
  106
+
  107
+
  108
+  public IProject getProject() {
  109
+    return project;
  110
+  }
  111
+
  112
+
  113
+  public void setProject( final IProject project ) {
  114
+    this.project = project;
  115
+  }
  116
+
  117
+
  118
+  /**
  119
+   * @return the children
  120
+   */
  121
+  public List<TestResult> getChildren() {
  122
+    return children;
  123
+  }
  124
+}
19  net.sf.eclipsefp.haskell.debug.core/src/net/sf/eclipsefp/haskell/debug/core/test/TestStatus.java
... ...
@@ -0,0 +1,19 @@
  1
+/**
  2
+ * Copyright (c) 2012 by JP Moresmau
  3
+ * This code is made available under the terms of the Eclipse Public License,
  4
+ * version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
  5
+ */
  6
+package net.sf.eclipsefp.haskell.debug.core.test;
  7
+
  8
+
  9
+/**
  10
+ * Status of a test
  11
+ * @author JP Moresmau
  12
+ *
  13
+ */
  14
+public enum TestStatus {
  15
+  OK,
  16
+  PENDING,
  17
+  ERROR,
  18
+  FAILURE
  19
+}
131  net.sf.eclipsefp.haskell.debug.core/src/net/sf/eclipsefp/haskell/debug/core/test/TestSuite.java
... ...
@@ -0,0 +1,131 @@
  1
+/**
  2
+ * Copyright (c) 2012 by JP Moresmau
  3
+ * This code is made available under the terms of the Eclipse Public License,
  4
+ * version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
  5
+ */
  6
+package net.sf.eclipsefp.haskell.debug.core.test;
  7
+
  8
+import java.io.Serializable;
  9
+import java.util.List;
  10
+import java.util.concurrent.atomic.AtomicInteger;
  11
+
  12
+
  13
+/**
  14
+ * Top level structure for tests
  15
+ * @author JP Moresmau
  16
+ *
  17
+ */
  18
+public class TestSuite implements Serializable {
  19
+  /**
  20
+   *
  21
+   */
  22
+  private static final long serialVersionUID = -611295970696203914L;
  23
+  static final AtomicInteger allRunIDs=new AtomicInteger(0);
  24
+  /**
  25
+   * unique ID
  26
+   */
  27
+  private final int id=allRunIDs.getAndIncrement();
  28
+
  29
+  /**
  30
+   * the root test result
  31
+   */
  32
+  private final TestResult root;
  33
+  private int runs=0;
  34
+  private int errors=0;
  35
+  private int failures=0;
  36
+
  37
+  public TestSuite(final TestResult root){
  38
+    this.root=root;
  39
+    count(root);
  40
+  }
  41
+
  42
+  /**
  43
+   * calculate stats
  44
+   * @param tr
  45
+   */
  46
+  private void count(final TestResult tr){
  47
+    List<TestResult> cs=tr.getChildren();
  48
+    if (cs.isEmpty()){
  49
+      switch (tr.getStatus()){
  50
+        case ERROR:
  51
+            errors++;
  52
+            runs++;
  53
+            break;
  54
+        case FAILURE:
  55
+            failures++;
  56
+            runs++;
  57
+            break;
  58
+        case OK:
  59
+            runs++;
  60
+            break;
  61
+        case PENDING:
  62
+          break;
  63
+      }
  64
+
  65
+    } else {
  66
+      for (TestResult c:cs){
  67
+        count(c);
  68
+      }
  69
+    }
  70
+  }
  71
+
  72
+
  73
+  /**
  74
+   * @return the runID
  75
+   */
  76
+  public int getID() {
  77
+    return id;
  78
+  }
  79
+
  80
+  /**
  81
+   * @return the root
  82
+   */
  83
+  public TestResult getRoot() {
  84
+    return root;
  85
+  }
  86
+
  87
+  public String getName(){
  88
+    return getRoot().getName();
  89
+  }
  90
+
  91
+
  92
+  public int getRuns() {
  93
+    return runs;
  94
+  }
  95
+
  96
+
  97
+  public int getErrors() {
  98
+    return errors;
  99
+  }
  100
+
  101
+
  102
+  public int getFailures() {
  103
+    return failures;
  104
+  }
  105
+
  106
+  @Override
  107
+  public int hashCode() {
  108
+    final int prime = 31;
  109
+    int result = 1;
  110
+    result = prime * result + id;
  111
+    return result;
  112
+  }
  113
+
  114
+  @Override
  115
+  public boolean equals( final Object obj ) {
  116
+    if( this == obj ) {
  117
+      return true;
  118
+    }
  119
+    if( obj == null ) {
  120
+      return false;
  121
+    }
  122
+    if( getClass() != obj.getClass() ) {
  123
+      return false;
  124
+    }
  125
+    TestSuite other = ( TestSuite )obj;
  126
+    if( id != other.id ) {
  127
+      return false;
  128
+    }
  129
+    return true;
  130
+  }
  131
+}
BIN  net.sf.eclipsefp.haskell.debug.ui/icons/eview16/haskell_test.png
2  net.sf.eclipsefp.haskell.debug.ui/plugin.properties
@@ -42,3 +42,5 @@ runHaskellProfilingShortcut_desc = Executes the built executable from this proje
42 42
 toggle_breakpoint=Toggle Breakpoint
43 43
 
44 44
 haskellInteractiveLaunchType_name = Haskell interactive session
  45
+
  46
+test_result_view=Haskell test results
29  net.sf.eclipsefp.haskell.debug.ui/plugin.xml
@@ -169,7 +169,7 @@
169 169
       </launchConfigurationTypeImage>
170 170
       <launchConfigurationTypeImage
171 171
             configTypeID="net.sf.eclipsefp.haskell.debug.core.internal.launch.TestSuiteHaskellLaunchDelegate"
172  
-            icon="icons/etool16/hsexe16.gif"
  172
+            icon="icons/eview16/haskell_test.png"
173 173
             id="net.sf.eclipsefp.haskell.ui.launch.launchTestSuiteIcon">
174 174
       </launchConfigurationTypeImage>
175 175
    </extension>
@@ -308,7 +308,7 @@
308 308
       </shortcut>
309 309
       <shortcut
310 310
             class="net.sf.eclipsefp.haskell.debug.ui.internal.launch.TestSuiteLaunchShortcut"
311  
-            icon="icons/etool16/hsexe16.gif"
  311
+            icon="icons/eview16/haskell_test.png"
312 312
             id="net.sf.eclipsefp.haskell.debug.ui.internal.launch.TestSuiteLaunchShortcut"
313 313
             label="%testSuiteLaunchShortcut_label"
314 314
             modes="run">
@@ -438,4 +438,29 @@
438 438
          </enablement>
439 439
       </consolePageParticipant>
440 440
    </extension> 
  441
+   
  442
+   <extension
  443
+         point="org.eclipse.ui.views">
  444
+      <view
  445
+            category="net.sf.eclipsefp.haskell"
  446
+            class="net.sf.eclipsefp.haskell.debug.ui.test.TestResultView"
  447
+            icon="icons/eview16/haskell_test.png"
  448
+            id="net.sf.eclipsefp.haskell.debug.ui.test.TestResultView"
  449
+            name="%test_result_view"
  450
+            restorable="true">
  451
+      </view>
  452
+   </extension>
  453
+   
  454
+    <extension point="org.eclipse.ui.perspectiveExtensions">
  455
+		<perspectiveExtension targetID="net.sf.eclipsefp.haskell.ui.HaskellPerspective">
  456
+			<viewShortcut id="net.sf.eclipsefp.haskell.debug.ui.test.TestResultView"/>
  457
+		</perspectiveExtension>
  458
+	</extension>
  459
+    <extension
  460
+          point="net.sf.eclipsefp.haskell.debug.core.testListeners">
  461
+       <delegate
  462
+             class="net.sf.eclipsefp.haskell.debug.ui.test.ViewTestListener"
  463
+             id="net.sf.eclipsefp.haskell.debug.ui.test.ViewTestListener">
  464
+       </delegate>
  465
+    </extension>
441 466
 </plugin>
76  net.sf.eclipsefp.haskell.debug.ui/src/net/sf/eclipsefp/haskell/debug/ui/internal/HaskellDebugUI.java
... ...
@@ -1,37 +1,39 @@