This is the mail archive of the mauve-discuss@sources.redhat.com mailing list for the Mauve project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] xml output from mauve


Hello friends

I started hacking on kaffe a few days ago, and this lead me to looking
at mauve. While thinking about writing some scripts that do fun stuff
with the output from mauve test runs and had a look at the perl script
that lives in kaffe cvs I came to the conclusion that the mauve output
wasn't as easy to parse as I wanted it to be.

So, I did some afternoon hacking and came up with this patch to mauve
that outputs the results from a mauve run into an xml file for easy
parsing. I haven't written anything that does anything with the output
yet but I thought I could share this with you anyway.

Note that since this patch touches Makefile.am autoreconf should be re-
run also and the generated changes should go into cvs.

Where should I add documentation about this?

cheers/noa

-- 
And the lions ate the christians and the christians burned the witches,
and even I am out of explanations -- Ola Salo
gpg fingerprint: F3C4 AC90 B885 FE15 344B  4D05 220B 7662 A190 6F09
diff -urN mauve.vanilla/ChangeLog mauve/ChangeLog
--- mauve.vanilla/ChangeLog	2004-09-17 21:39:53.000000000 +0200
+++ mauve/ChangeLog	2004-09-17 23:04:50.477983188 +0200
@@ -1,3 +1,10 @@
+2004-09-17  Noa Resare  <noa@resare.com>
+
+	* gnu/testlet/TestResult.java: New file.
+	* gnu/testlet/TestReport.java: New file.
+	* gnu/testlet/SimpleTestHarness.java
+        support for writing test results to an xml file
+
 2004-09-01  Tom Tromey  <tromey@redhat.com>
 
 	* gnu/testlet/java/lang/reflect/sub/InvokeHelper.java: New file.
diff -urN mauve.vanilla/gnu/testlet/SimpleTestHarness.java mauve/gnu/testlet/SimpleTestHarness.java
--- mauve.vanilla/gnu/testlet/SimpleTestHarness.java	2004-09-17 21:39:54.000000000 +0200
+++ mauve/gnu/testlet/SimpleTestHarness.java	2004-09-17 23:16:26.509889216 +0200
@@ -42,6 +42,8 @@
   private boolean results_only=false;
   private String description;
   private String last_check;
+  private TestReport report = null;
+  private TestResult currentResult = null;
 
   private final String getDescription (String pf)
   {
@@ -60,6 +62,8 @@
     if (!result)
       {
 	String desc;
+	currentResult.addFail((last_check == null ? "" : last_check) +
+		" (number " + (count + 1) + ")");
 	if (!expected_xfails.contains(desc = getDescription("FAIL")))
 	  {
 	    System.out.println(desc);
@@ -71,17 +75,21 @@
 	    ++xfailures;
 	  }
       }
-    else if (verbose || results_only)
+    else
       {
-	if (expected_xfails.contains(getDescription("FAIL")))
+	currentResult.addPass();
+        if (verbose || results_only)
 	  {
-	    System.out.println(getDescription("XPASS"));
-	    ++xpasses;
-	  }
-	else
-	  {
-	    System.out.println(getDescription("PASS"));
-	  }
+	    if (expected_xfails.contains(getDescription("FAIL")))
+	      {
+		System.out.println(getDescription("XPASS"));
+		++xpasses;
+	      }
+	    else
+	      {
+		System.out.println(getDescription("PASS"));
+	      }
+          }
       }
     ++count;
     ++total;
@@ -221,6 +229,8 @@
     // Try to ensure we start off with a reasonably clean slate.
     System.gc();
     System.runFinalization();
+
+    currentResult = new TestResult(name);
     
     checkPoint(null);
     
@@ -238,6 +248,7 @@
     catch (Throwable ex)
       {
 	String d = "FAIL: uncaught exception loading " + name;
+	currentResult.addException(ex, "failed loading class " + name);
 	if (verbose)
 	  d += ": " + ex.toString();
 	System.out.println(d);
@@ -261,10 +272,11 @@
 	catch (Throwable ex)
 	  {
 	    removeSecurityManager();
+            String s = (last_check == null ? "" : "\"" + last_check +
+                    "\" number " + (count + 1));
 	    String d = ("FAIL: " + description + ": uncaught exception at " +
-		        ((last_check == null) ? "" :
-			 ("\"" + last_check + "\"")) +
-			" number " + (count + 1));
+                    s);
+	    currentResult.addException(ex, "uncaught exception at " + s);
 	    if (verbose)
 	      d += ": " + ex.toString();
 	    System.out.println(d);
@@ -273,6 +285,8 @@
 	    ++total;
 	  }
       }
+    if (report != null)
+      report.addTestResult(currentResult);
   }
   
   protected int done ()
@@ -293,15 +307,16 @@
   
   protected SimpleTestHarness (boolean verbose, boolean debug)
   {
-    this(verbose, debug, false);
+    this(verbose, debug, false, null);
   }
   
   protected SimpleTestHarness (boolean verbose, boolean debug,
-		               boolean results_only)
+		               boolean results_only, TestReport report)
   {
     this.verbose = verbose;
     this.debug = debug;
     this.results_only = results_only;
+    this.report = report;
     
     try
       {
@@ -327,6 +342,8 @@
     boolean debug = false;
     boolean results_only = false;
     String file = null;
+    String xmlfile = null;
+    TestReport report = null;
     int i;
     
     for (i = 0; i < args.length; i++)
@@ -346,12 +363,21 @@
 	    throw new RuntimeException("No file path after '-file'.  Exit");
           file = args[i];
 	}
+	else if (args[i].equals("-xmlout"))
+	  {
+	    if (++i >= args.length)
+	      throw new RuntimeException("No file path after '-xmlout'.");
+	    xmlfile = args[i];
+          }
 	else
 	  break;
       }
+    if (xmlfile != null) {
+      report = new TestReport(System.getProperties());
+    }
     
     SimpleTestHarness harness =
-      new SimpleTestHarness(verbose, debug, results_only);
+      new SimpleTestHarness(verbose, debug, results_only, report);
     
     BufferedReader r = null;
     if (file != null)
@@ -385,9 +411,22 @@
 	  System.out.println("----");
 	harness.runtest(cname);
       }
+
+    int retval = harness.done();
     
-    System.exit(harness.done());
+    if (report != null)
+      {
+	File f = new File(xmlfile);
+	try
+	  {
+	    report.writeXml(f);
+	  }
+	catch (IOException e)
+	  {
+	    throw new Error("Failed to write data to xml file: " + 
+		    e.getMessage());
+	  }
+      }
+    System.exit(retval);
   }
 }
-
-
diff -urN mauve.vanilla/gnu/testlet/TestReport.java mauve/gnu/testlet/TestReport.java
--- mauve.vanilla/gnu/testlet/TestReport.java	1970-01-01 01:00:00.000000000 +0100
+++ mauve/gnu/testlet/TestReport.java	2004-09-17 22:43:52.508012163 +0200
@@ -0,0 +1,106 @@
+// Copyright (c) 2004 Noa Resare.
+// Written by Noa Resre <noa@resare.com>
+									       
+// This file is part of Mauve.
+									       
+// Mauve is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+									       
+// Mauve is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+									       
+// You should have received a copy of the GNU General Public License
+// along with Mauve; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+package gnu.testlet;
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * A TestReport represents all the results of a test run. The TestReport
+ * can be serialized to xml with the writeXml method.
+ */
+public class TestReport
+{
+  private Properties systemProperties;
+  private List testResults;
+
+  private static final String ENCODING = "UTF-8";
+
+
+  /**
+   * Creates a new TestReport object with jvmName and jvmVersion set.
+   *
+   * @param systemProperties the Properties object returned from
+   * System.getProperties() of the jvm that is tested.
+   */
+  public TestReport(Properties systemProperties)
+  {
+    this.systemProperties = systemProperties;
+    this.testResults = new ArrayList();
+  }
+
+  /**
+   * Adds a TestResult object to this TestReport.
+   *
+   * @param result the TestResult object to be added
+   */
+  public void addTestResult(TestResult result)
+  {
+    this.testResults.add(result);
+  }
+
+  /**
+   * Writes a representation of this TestReport object in xml format.
+   *
+   * @param f the file where the xml stream gets written
+   */
+  public void writeXml(File f)
+    throws IOException
+  {
+    Writer out = new OutputStreamWriter(new FileOutputStream(f), ENCODING);
+    out.write("<?xml version='1.0' encoding='" + ENCODING + "'?>\n");
+    out.write("<testreport version='0.1'>\n  <jvm name='" +
+	    systemProperties.get("java.vm.vendor") + "'\n    version='" +
+	    systemProperties.get("java.vm.version") + "' \n" +
+	    "    os='" + systemProperties.get("os.name") + " " +
+	    systemProperties.get("os.version") + " " +
+	    systemProperties.get("os.arch") + "' />\n");
+    Collections.sort(testResults);
+    Iterator results = testResults.iterator();
+    while (results.hasNext())
+      {
+	TestResult tr = (TestResult) results.next();
+	String[] failures = tr.getFailMessags();
+	out.write("  <testresult testlet='" + tr.getTestletName() +
+		 "' passcount='" + tr.getPassCount());
+	if (failures.length > 0 || tr.getException() != null)
+	  out.write("'>\n");
+	else 
+	  out.write("'/>\n");
+
+	for (int i = 0; i < failures.length; i++)
+	  out.write("    <failure>" + failures[i] + "</failure>\n");
+
+	if (tr.getException() != null)
+	  {
+	    Throwable t = tr.getException();
+	    out.write("    <exception class='" + t.getClass().getName() +
+		    "'>\n      <reason>" + tr.getExceptionMessage() +
+		    "</reason>\n      <message>" + t.getMessage() +
+		    "</message>\n    </exception>\n");
+	  }
+	if (failures.length > 0 || tr.getException() != null) 
+	  out.write("  </testresult>\n");
+      }
+    out.write("</testreport>\n");
+    out.close();
+  }
+}
diff -urN mauve.vanilla/gnu/testlet/TestResult.java mauve/gnu/testlet/TestResult.java
--- mauve.vanilla/gnu/testlet/TestResult.java	1970-01-01 01:00:00.000000000 +0100
+++ mauve/gnu/testlet/TestResult.java	2004-09-17 22:44:10.529576676 +0200
@@ -0,0 +1,144 @@
+// Copyright (c) 2004 Noa Resare.
+// Written by Noa Resre <noa@resare.com>
+                                                                               
+// This file is part of Mauve.
+                                                                               
+// Mauve is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+                                                                               
+// Mauve is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+                                                                               
+// You should have received a copy of the GNU General Public License
+// along with Mauve; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+package gnu.testlet;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * A TestResult object represents the results a run of one Testlet. TestResult
+ * objects are normally agregated in a TestReport. The natural ordering of
+ * TestResult is defined to be the same as the natural order of their 
+ * respective testletName field.
+ */
+public class TestResult
+  implements Comparable
+{
+  private String testletName = null;
+  private int passCount = 0;
+  private List failMessages = new ArrayList();
+  private Throwable exception = null;
+  private String exceptionMessage = null;
+
+  /**
+   * Constructs a TestResult instance with testletName set to the given name.
+   *
+   * @param testletName the name of the testlet that produced this TestResult
+   */
+  public TestResult(String testletName)
+  {
+    if (testletName == null)
+      throw new IllegalArgumentException("testletName can not be null");
+    this.testletName = testletName;
+  }
+
+  /**
+   * Adds one to the counter of the number of tests that has passed. Should
+   * be called when a test passses.
+   */
+  public void addPass()
+  {
+    passCount++;
+  }
+
+  /**
+   * Adds a failure message identifying a failing test. Should be called when
+   * a test fails. 
+   *
+   * @param message a String that identifies the test that failed inside
+   * this servlet
+   */
+  public void addFail(String message)
+  {
+    failMessages.add(message);
+  }
+
+  /**
+   * Adds an Exception and optional identification message to this TestResult
+   * object. Should be called when the instantiation or execution of a Testlet
+   * results in an exception.
+   *
+   * @param exception The exception that was thrown
+   * @param message A message that identifies the test that caused the
+   * exception to be thrown
+   */
+  public void addException(Throwable exception, String message)
+  {
+    if (this.exception != null)
+      throw new IllegalArgumentException("trying to add more than one " +
+               "exception to TestResult");           
+    this.exception = exception;
+    this.exceptionMessage = message;
+  }
+
+  /**
+   * The number of tests that have preformed without failure or exceptions.
+   */
+  public int getPassCount()
+  {
+    return passCount;
+  }
+
+  /**
+   * An array of Strings that holds the identifying messages for all failed
+   * tests.
+   */
+  public String[] getFailMessags()
+  {
+    return (String[]) failMessages.toArray(new String[0]);
+  }
+
+  /**
+   * The name of the Testlet that this TestResult holds information about.
+   */
+  public String getTestletName()
+  {
+    return testletName;
+  }
+
+  /**
+   * If an Exception was thrown when the Testlet was instantiated or run it
+   * is returned, else null is returned.
+   */
+  public Throwable getException()
+  {
+    return exception;
+  }
+
+  /**
+   * If an Exception was thrown when the Testlet was instantiated or run,
+   * this String identifies what test (or other contition) caused the test.
+   */
+  public String getExceptionMessage()
+  {
+    return exceptionMessage;
+  }
+
+  /**
+   * Compares one TestResult object to another. TestResult objects compare
+   * the same as their testletName fields.
+   */ 
+  public int compareTo(Object o)
+  {
+    TestResult other = (TestResult)o;
+    return testletName.compareTo(other.testletName);
+  }
+}
diff -urN mauve.vanilla/Makefile.am mauve/Makefile.am
--- mauve.vanilla/Makefile.am	2004-09-17 21:39:54.000000000 +0200
+++ mauve/Makefile.am	2004-09-17 23:06:36.836605670 +0200
@@ -13,7 +13,9 @@
 	gnu/testlet/TestHarness.java gnu/testlet/Testlet.java \
 	gnu/testlet/TestSecurityManager.java \
 	gnu/testlet/TestSecurityManager2.java \
-	gnu/testlet/ResourceNotFoundException.java
+	gnu/testlet/ResourceNotFoundException.java \
+	gnu/testlet/TestReport.java \
+	gnu/testlet/TestResult.java
 
 ## FIXME: leading space makes automake ignore this.  Bleah.
  include choices

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]