Adapted the XS tests to use the new release of tests and test-definitions.

* xstc/Makefile.am xstc.py xstc-to-python.xsl: Adapted the
  XS tests to use the new release of tests and test-definitions.
diff --git a/ChangeLog b/ChangeLog
index 3c01138..e6a796c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Wed Jun  8 19:11:42 CEST 2005 Kasimier Buchcik <libxml2-cvs@cazic.net>
+
+	* xstc/Makefile.am xstc.py xstc-to-python.xsl: Adapted the
+	  XS tests to use the new release of tests and test-definitions.
+
 2005-06-07  Aleksey Sanin <aleksey@aleksey.com>
 
 	* c14n.c: fix rendering of attributes when parent node
diff --git a/xstc/Makefile.am b/xstc/Makefile.am
index 6927abb..7627d73 100644
--- a/xstc/Makefile.am
+++ b/xstc/Makefile.am
@@ -2,16 +2,23 @@
 # Definition for the tests from W3C
 #
 PYSCRIPTS=nist-test.py ms-test.py sun-test.py
-TESTDIRS=msxsdtest nisttest suntest
-TARBALL=XSTC-20020116.tar.gz
-TARBALLURL=http://www.w3.org/2001/05/xmlschema-test-collection/$(TARBALL)
+TESTDIR=Tests
+TESTDIRS=$(TESTDIR)/msxsdtest $(TESTDIR)/suntest $(TESTDIR)/Datatypes
+TARBALL=xsts-2002-01-16.tar.gz
+TARBALL_2=xsts-2004-01-14.tar.gz
+TSNAME=xmlschema2002-01-16
+TSNAME_2=xmlschema2004-01-14
+TARBALLURL=http://www.w3.org/XML/2004/xml-schema-test-suite/$(TSNAME)/$(TARBALL)
+TARBALLURL_2=http://www.w3.org/XML/2004/xml-schema-test-suite/$(TSNAME_2)/$(TARBALL_2)
+MSTESTDEF=MSXMLSchema1-0-20020116.testSet
+SUNTESTDEF=SunXMLSchema1-0-20020116.testSet
+NISTTESTDEF=NISTXMLSchema1-0-20020116.testSet
+NISTTESTDEF_2=NISTXMLSchemaDatatypes.testSet
 
 #
 # The local data and scripts
 #
-EXTRA_DIST=xstc.py sun-test-def.xml ms-test-def.xml nist-test-def.xml	\
-	   xstc-to-python.xsl
-
+EXTRA_DIST=xstc.py xstc-to-python.xsl
 #
 # Nothing is done by make, only make tests and
 # only if Python and Schemas are enabled.
@@ -19,72 +26,82 @@
 all:
 
 #
-# The python tests are generated via XSLT
-#
-nist-test.py: nist-test-def.xml xstc-to-python.xsl
-	-@(if [ -x $(XSLTPROC) ] ; then				\
-	  echo "Rebuilding script" $@ ;					\
-	  $(XSLTPROC) --nonet $(srcdir)/xstc-to-python.xsl	\
-	                     $(srcdir)/nist-test-def.xml > $@ ;		\
-	  chmod +x $@ ; fi )
-
-ms-test.py: ms-test-def.xml xstc-to-python.xsl
-	-@(if [ -x $(XSLTPROC) ] ; then				\
-	  echo "Rebuilding script" $@ ;					\
-	  $(XSLTPROC) --nonet $(srcdir)/xstc-to-python.xsl	\
-	                     $(srcdir)/ms-test-def.xml > $@ ;		\
-	  chmod +x $@ ; fi )
-
-sun-test.py: sun-test-def.xml xstc-to-python.xsl
-	-@(if [ -x $(XSLTPROC) ] ; then				\
-	  echo "Rebuilding script" $@ ;					\
-	  $(XSLTPROC) --nonet $(srcdir)/xstc-to-python.xsl	\
-	                     $(srcdir)/sun-test-def.xml > $@ ;		\
-	  chmod +x $@ ; fi )
-
-#
 # Rule to load the test description and extract the informations
 #
-$(TESTDIRS):
-	-@(if [ ! -f $(TARBALL) ] ; then 				\
-	   echo "Missing the test suite description, trying to fetch it" ;\
-	   if [ -x /usr/bin/wget ] ; then 				\
-	   wget $(TARBALLURL) ; 					\
+$(TESTDIRS) Tests/$(NISTTESTDEF_2) Tests/$(MSTTESTDEF) Tests/$(SUNTESTDEF):
+	-@(if [ ! -d Tests ] ; then \
+	   mkdir Tests ; \
+	   fi)
+	-@(if [ ! -f $(TARBALL) ] ; then \
+	   echo "Missing the test suite description (2002-01-16), trying to fetch it" ;\
+	   if [ -x /usr/bin/wget ] ; then \
+	   wget $(TARBALLURL) ; \
 	   else echo "Dont' know how to fetch $(TARBALLURL)" ; fi ; fi)
-	-@(if [ -f $(TARBALL) ] ; then 					\
-	   echo -n "extracting tests directories..." ;			\
-	   $(TAR) -xzf $(TARBALL) $(TESTDIRS) ;				\
-	   echo "done" ;						\
-	   fi);
-	-@(if [ -x fixup-tests.py ] ; then				\
-	   chmod -R u+w msxsdtest;					\
-	   echo "## Microsoft tests fixups";				\
-	   PYTHONPATH="../python:../python/.libs:..:../libs:$$PYTHONPATH" ;\
-	   export PYTHONPATH;						\
-	   LD_LIBRARY_PATH="$(top_builddir)/.libs:$$LD_LIBRARY_PATH" ;  \
-	   $(PYTHON) fixup-tests.py ; fi)
+	-@(if [ -f $(TARBALL) ] ; then \
+	   echo -n "extracting test data (Sun, Microsoft)..." ; \
+	   $(TAR) -C Tests --strip-path 1 -xzf $(TARBALL) '*/suntest' '*/msxsdtest' '*/$(MSTESTDEF)' '*/$(SUNTESTDEF)' ; \
+	   echo "done" ; \
+	   fi)
+	-@(if [ ! -f $(TARBALL_2) ] ; then \
+	   echo "Missing the test suite description (2004-01-14), trying to fetch it" ;\
+	   if [ -x /usr/bin/wget ] ; then \
+	   wget $(TARBALLURL_2) ; \
+	   else echo "Dont' know how to fetch $(TARBALLURL_2)" ; fi ; fi)
+	-@(if [ -f $(TARBALL_2) ] ; then \
+	   echo -n "extracting test data (NIST)..." ; \
+	   $(TAR) -C Tests --strip-path 1 -xzf $(TARBALL_2) '*/Datatypes' ; \
+	   $(TAR) -C Tests --strip-path 2 -xzf $(TARBALL_2) '*/Metadata/$(NISTTESTDEF_2)' ; \
+	   echo "done" ; \
+	   fi)
+
+#
+# The python tests are generated via XSLT
+#
+nist-test.py: Tests/$(NISTTESTDEF_2) xstc-to-python.xsl
+	-@(if [ -x $(XSLTPROC) ] ; then \
+	  echo "Rebuilding script (NIST)" $@ ; \
+	  $(XSLTPROC) --nonet --stringparam vendor NIST-2 \
+	                     $(srcdir)/xstc-to-python.xsl \
+	                     $(srcdir)/Tests/$(NISTTESTDEF_2) > $@ ; \
+	  chmod +x $@ ; fi )
+
+ms-test.py: Tests/$(MSTTESTDEF) xstc-to-python.xsl
+	-@(if [ -x $(XSLTPROC) ] ; then \
+	  echo "Rebuilding script (Microsoft)" $@ ; \
+	  $(XSLTPROC) --nonet --stringparam vendor MS \
+	                     $(srcdir)/xstc-to-python.xsl \
+	                     $(srcdir)/Tests/$(MSTESTDEF) > $@ ; \
+	  chmod +x $@ ; fi )
+
+sun-test.py: Tests/$(SUNTESTDEF) xstc-to-python.xsl
+	-@(if [ -x $(XSLTPROC) ] ; then \
+	  echo "Rebuilding script (Sun)" $@ ; \
+	  $(XSLTPROC) --nonet --stringparam vendor SUN \
+	                     $(srcdir)/xstc-to-python.xsl \
+	                     $(srcdir)/Tests/$(SUNTESTDEF) > $@ ; \
+	  chmod +x $@ ; fi )
 
 #
 # The actual test run if present. PYTHONPATH is updated to make sure
 # we run the version from the loacl build and not preinstalled bindings
 #
 pytests: $(PYSCRIPTS) $(TESTDIRS)
-	-@(if [ -x nist-test.py -a -d nisttest ] ; then 		\
-	   echo "## Running NIST Schemas tests";			\
+	-@(if [ -x nist-test.py -a -d $(TESTDIR)/Datatypes ] ; then 		\
+	   echo "## Running XML Schema tests (NIST)";			\
 	   PYTHONPATH="../python:../python/.libs:..:../libs:$$PYTHONPATH" ;\
 	   export PYTHONPATH;						\
 	   LD_LIBRARY_PATH="$(top_builddir)/.libs:$$LD_LIBRARY_PATH" ;	\
 	   export LD_LIBRARY_PATH;					\
 	   $(CHECKER) $(PYTHON) nist-test.py -s -b $(srcdir) ; fi)
-	-@(if [ -x sun-test.py -a -d suntest ] ; then 			\
-	   echo "## Running Sun Schemas tests";				\
+	-@(if [ -x sun-test.py -a -d $(TESTDIR)/suntest ] ; then 			\
+	   echo "## Running Schema tests (Sun)";				\
 	   PYTHONPATH="../python:../python/.libs:..:../libs:$$PYTHONPATH" ;\
 	   export PYTHONPATH;						\
 	   LD_LIBRARY_PATH="$(top_builddir)/.libs:$$LD_LIBRARY_PATH" ;	\
 	   export LD_LIBRARY_PATH;					\
 	   $(CHECKER) $(PYTHON) sun-test.py -s -b $(srcdir) ; fi)
-	-@(if [ -x ms-test.py -a -d msxsdtest ] ; then 			\
-	   echo "## Running Microsoft Schemas tests";			\
+	-@(if [ -x ms-test.py -a -d $(TESTDIR)/msxsdtest ] ; then 			\
+	   echo "## Running Schema tests (Microsoft)";			\
 	   PYTHONPATH="../python:../python/.libs:..:../libs:$$PYTHONPATH" ;\
 	   export PYTHONPATH;						\
 	   LD_LIBRARY_PATH="$(top_builddir)/.libs:$$LD_LIBRARY_PATH" ;	\
diff --git a/xstc/xstc-to-python.xsl b/xstc/xstc-to-python.xsl
index 31fe038..e148ff9 100755
--- a/xstc/xstc-to-python.xsl
+++ b/xstc/xstc-to-python.xsl
@@ -1,65 +1,118 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
-    <xsl:output method="text"/>   
-    <!-- Main template. -->
-    <xsl:template match="/">
-        <xsl:text>#!/usr/bin/python -u
-#
-# This file is generated from the W3C test suite description file.
-#
-
-from xstc import MSTestRunner, MSTestCase
-
-r = MSTestRunner()
-                                 
-</xsl:text>         
-        <xsl:apply-templates select="tests/test"/>
-        <xsl:text>
-           
-r.run() 
-    
-##################
-# Display results.      
-#
-
-</xsl:text>
-            
-    </xsl:template>
-        
-    <!-- Test template. --> 
-
-    <xsl:template match="file">
-        <xsl:text>"</xsl:text>
-        <xsl:value-of select="@folder"/><xsl:text>", "</xsl:text>
-        <xsl:value-of select="@fileName"/><xsl:text>", </xsl:text>
-        <xsl:value-of select="@validity"/>
-    </xsl:template>
-                    
-    <xsl:template match="test">
-        <xsl:text>r.addTest(MSTestCase("</xsl:text>
-        <xsl:value-of select="@id"/>
-        <xsl:text>", """</xsl:text>   
-        <xsl:value-of select="description/text()"/>
-        <xsl:text>""", "</xsl:text>       
-        <xsl:value-of select="files/file[@role='schema']/@tsDir"/>
-        <xsl:text>", </xsl:text>
-        <xsl:choose>
-            <xsl:when test="count(files/file[@role='schema']) = 1">
-                <xsl:apply-templates select="files/file[@role='schema']"/>
-            </xsl:when>
-            <xsl:otherwise>
-                <xsl:text>"", "", 0</xsl:text>
-            </xsl:otherwise>
-        </xsl:choose>
-        <xsl:choose>
-            <xsl:when test="count(files/file[@role='instance']) = 1">
-                <xsl:text>, 1, </xsl:text>
-                <xsl:apply-templates select="files/file[@role='instance']"/>
-            </xsl:when>
-            <xsl:otherwise>, 0, "", "", 0</xsl:otherwise>
-        </xsl:choose>
-        <xsl:text>))
-</xsl:text>     
-    </xsl:template>             
-        
-</xsl:stylesheet>
+<?xml version="1.0" encoding="UTF-8" ?>

+<xsl:stylesheet 

+	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

+	xmlns:ts="TestSuite" version="1.0"

+	xmlns:xl="http://www.w3.org/1999/xlink">

+	<xsl:param name="vendor" select="'NIST'"/>

+    <xsl:output method="text"/>   

+

+    <xsl:template match="/">

+        <xsl:text>#!/usr/bin/python -u

+# -*- coding: UTF-8 -*-

+#

+# This file is generated from the W3C test suite description file.

+#

+

+import xstc

+from xstc import XSTCTestRunner, XSTCTestGroup, XSTCSchemaTest, XSTCInstanceTest

+

+xstc.vendor = "</xsl:text><xsl:value-of select="$vendor"/><xsl:text>"

+

+r = XSTCTestRunner()

+

+# Group definitions.

+                                 

+</xsl:text>

+		      

+        <xsl:apply-templates select="ts:testSet/ts:testGroup" mode="group-def"/>

+<xsl:text>

+

+# Test definitions.

+

+</xsl:text>

+		<xsl:apply-templates select="ts:testSet/ts:testGroup" mode="test-def"/>

+        <xsl:text>

+           

+r.run()    

+

+</xsl:text>

+            

+    </xsl:template>       

+

+	<!-- groupName, descr -->

+    <xsl:template match="ts:testGroup" mode="group-def">

+		<xsl:text>r.addGroup(XSTCTestGroup("</xsl:text>

+		<!-- group -->

+		<xsl:value-of select="@name"/><xsl:text>", "</xsl:text>

+		<!-- main schema -->

+		<xsl:value-of select="ts:schemaTest[1]/ts:schemaDocument/@xl:href"/><xsl:text>", """</xsl:text>

+		<!-- group-description -->

+		<xsl:call-template name="str">

+			<xsl:with-param name="str" select="ts:annotation/ts:documentation/text()"/>

+		</xsl:call-template>

+		<xsl:text>"""))

+</xsl:text>

+	</xsl:template>

+	

+	<xsl:template name="str">

+		<xsl:param name="str"/>

+		<xsl:choose>

+			<xsl:when test="contains($str, '&quot;')">

+				<xsl:call-template name="str">

+					<xsl:with-param name="str" select="substring-before($str, '&quot;')"/>

+				</xsl:call-template>

+				<xsl:text>'</xsl:text>

+				<xsl:call-template name="str">

+					<xsl:with-param name="str" select="substring-after($str, '&quot;')"/>

+				</xsl:call-template>

+			

+			</xsl:when>

+			<xsl:otherwise>

+				<xsl:value-of select="$str"/>

+			</xsl:otherwise>

+		</xsl:choose>

+	</xsl:template>

+

+	<xsl:template match="ts:testGroup" mode="test-def">	    

+		<xsl:param name="group" select="@name"/>

+		<xsl:for-each select="ts:schemaTest">

+			<!-- groupName, isSchema, Name, Accepted, File, Val, Descr -->

+			<xsl:text>r.addTest(XSTCSchemaTest("</xsl:text>

+			<!-- group -->

+			<xsl:value-of select="$group"/><xsl:text>", "</xsl:text>

+			<!-- test-name -->

+			<xsl:value-of select="@name"/><xsl:text>", </xsl:text>

+			<!-- accepted -->

+			<xsl:value-of select="number(ts:current/@status = 'accepted')"/><xsl:text>, "</xsl:text>

+			<!-- filename -->			

+			<xsl:value-of select="ts:schemaDocument/@xl:href"/><xsl:text>", </xsl:text>

+			<!-- validity -->

+			<xsl:value-of select="number(ts:expected/@validity = 'valid')"/><xsl:text>, "</xsl:text>

+			<!-- test-description -->

+			<xsl:value-of select="ts:annotation/ts:documentation/text()"/><xsl:text>"))

+</xsl:text>

+		</xsl:for-each>

+		<xsl:for-each select="ts:instanceTest">

+			<!-- groupName, isSchema, Name, Accepted, File, Val, Descr -->

+			<xsl:text>r.addTest(XSTCInstanceTest("</xsl:text>

+			<!-- group -->

+			<xsl:value-of select="$group"/><xsl:text>", "</xsl:text>

+			<!-- test-name -->

+			<xsl:value-of select="@name"/><xsl:text>", </xsl:text>

+			<!-- accepted -->

+			<xsl:value-of select="number(ts:current/@status = 'accepted')"/><xsl:text>, "</xsl:text>

+			<!-- filename -->			

+			<xsl:value-of select="ts:instanceDocument/@xl:href"/><xsl:text>", </xsl:text>

+			<!-- validity -->

+			<xsl:value-of select="number(ts:expected/@validity = 'valid')"/><xsl:text>, "</xsl:text>

+			<!-- test-description -->

+			<xsl:value-of select="ts:annotation/ts:documentation/text()"/><xsl:text>"))

+</xsl:text>

+		</xsl:for-each>

+	</xsl:template>                     

+        

+</xsl:stylesheet><!-- Stylus Studio meta-information - (c)1998-2004. Sonic Software Corporation. All rights reserved.

+<metaInformation>

+<scenarios/><MapperInfo srcSchemaPathIsRelative="yes" srcSchemaInterpretAsXML="no" destSchemaPath="" destSchemaRoot="" destSchemaPathIsRelative="yes" destSchemaInterpretAsXML="no"/>

+</metaInformation>

+-->
\ No newline at end of file
diff --git a/xstc/xstc.py b/xstc/xstc.py
index 024ba0e..49719dd 100755
--- a/xstc/xstc.py
+++ b/xstc/xstc.py
@@ -1,550 +1,682 @@
-#!/usr/bin/env python

-

-#

-# This is the MS subset of the W3C test suite for XML Schemas.

-# This file is generated from the MS W3c test suite description file.

-#

-

-import sys, os

-import exceptions, optparse

-import libxml2

-

-opa = optparse.OptionParser()

-

-opa.add_option("-b", "--base", action="store", type="string", dest="baseDir",

-               default="",

-               help="""The base directory; i.e. the parent folder of the

-               "nisttest", "suntest" and "msxsdtest" directories.""")

-

-opa.add_option("-o", "--out", action="store", type="string", dest="logFile",

-               default="test.log",

-               help="The filepath of the log file to be created")

-               

-opa.add_option("--no-log", action="store_true", dest="disableLog",

-               default=False,

-               help="The filepath of the log file to be created")    

-               

-opa.add_option("--no-test-out", action="store_true", dest="disableTestStdOut",

-               default=False,

-               help="The filepath of the log file to be created")                           

-

-opa.add_option("-s", "--silent", action="store_true", dest="silent", default=False,

-               help="Disables display of all tests")

-

-opa.add_option("-v", "--verbose", action="store_true", dest="verbose",

-               default=False,

-               help="Displays all tests (only if --silent is not set)")

-

-opa.add_option("-x", "--max", type="int", dest="maxTestCount",

-               default="-1",

-               help="The maximum number of tests to be run")

-

-opa.add_option("-t", "--test", type="string", dest="singleTest",

-               default=None,

-               help="Runs the specified test only")

-               

-opa.add_option("--rieo", "--report-internal-errors-only", action="store_true",

-               dest="reportInternalErrOnly", default=False,

-               help="Display erroneous tests of type 'internal' only")

-               

-opa.add_option("--rmleo", "--report-mem-leak-errors-only", action="store_true",

-               dest="reportMemLeakErrOnly", default=False,

-               help="Display erroneous tests of type 'memory leak' only")

-

-opa.add_option("-c", "--combines", type="string", dest="combines",

-               default=None,

-               help="Combines to be run (all if omitted)")

-

-opa.add_option("--rc", "--report-combines", action="store_true",

-               dest="reportCombines", default=False,

-               help="Display combine reports")

-

-opa.add_option("--rec", "--report-err-combines", action="store_true",

-               dest="reportErrCombines", default=False,

-               help="Display erroneous combine reports only")

-

-opa.add_option("--debug", action="store_true",

-               dest="debugEnabled", default=False,

-               help="Displays debug messages")

-               

-opa.add_option("--info", action="store_true",

-               dest="info", default=False,

-               help="Displays info on the suite only. Does not run any test.")            

-

-(options, args) = opa.parse_args()

-

-if options.combines is not None:

-    options.combines = options.combines.split()

-    

-################################################

-# The vars below are not intended to be changed.

-#

-

-msgSchemaNotValidButShould =  "The schema should be valid."

-msgSchemaValidButShouldNot = "The schema should be invalid."

-msgInstanceNotValidButShould = "The instance should be valid."

-msgInstanceValidButShouldNot = "The instance should be invalid."

-testFolderNIST = "nisttest"

-testFolderMS   = "msxsdtest"

-testFolderSUN  = "suntest"

-

-###################

-# Helper functions.

-#

-

-def handleError(test, msg):

-    test.addLibLog("'%s'   LIB: %s" % (test.name, msg))

-    if msg.find("Unimplemented") > -1:

-        test.failUnimplemented()

-    elif msg.find("Internal") > -1:

-        test.failInternal()        

-    

-

-##################

-# Test case class.

-#

-

-class MSTestCase:

-           

-    def __init__(self, name, descr, tFolder, sFolder, sFile, sVal, iExists, iFolder, iFile, iVal):

-        global testFolderNIST, testFolderSUN, testFolderMS

-        #

-        # Init.

-        #

-        self.name = name

-        self.descr = descr

-        self.test_Folder = tFolder

-        self.schema_Folder = sFolder

-        self.schema_File = sFile

-        self.schema_Val = sVal

-        self.instance_Exists = iExists

-        self.instance_Folder = iFolder

-        self.instance_File = iFile

-        self.instance_Val = iVal

-        self.failed = False

-        self.log = []

-        self.libLog = []

-        self.phase = ""

-        self.initialMemUsed = 0

-        self.memLeak = 0

-        self.excepted = False

-        self.bad = False

-        self.unimplemented = False

-        self.internalErr = False

-        #

-        # Compute combine name of this test.

-        #       

-        if self.test_Folder == testFolderMS or self.test_Folder == testFolderSUN:

-            #

-            # Use the last given directory for the combine name.

-            #

-            dirs = self.schema_Folder.split("/")

-            self.combineName = dirs[len(dirs) -1]

-	    if self.test_Folder == testFolderMS:

-	        if self.combineName == "group":		    

-	            self.schema_Folder = "Group"

-		    self.instance_Folder = "Group"

-        elif self.test_Folder == testFolderNIST:

-            #

-            # NIST files are named in the following form: 

-            # "NISTSchema-short-pattern-1.xsd"

-            #

-            tokens = self.schema_File.split("-")

-            self.combineName = tokens[1]            

-        else:

-            self.combineName = "unkown"

-            raise Exception("Could not compute the combine name of a test.")

-        #

-        # Init the log.

-        #

-        self.log.append("'%s'   descr: %s\n" % (self.name, self.descr))

-        self.log.append("'%s'   exp schema   valid: %d\n" % (self.name, self.schema_Val))

-        if (self.instance_Exists):

-            self.log.append("'%s'   exp instance valid: %d\n" % (self.name, self.instance_Val))                       

-       

-    def addLibLog(self, msg):

-        """This one is intended to be used by the error handler

-        function"""

-        self.libLog.append(msg)

-

-    def fail(self, msg):       

-        self.failed = True         

-        self.log.append("'%s' ( FAILED: %s\n" % (self.name, msg))

-        

-    def failInternal(self):

-        self.failed = True

-        self.internalErr = True

-        self.log.append("'%s' * INTERNAL\n" % self.name)

-        

-    def failUnimplemented(self):

-        self.failed = True

-        self.unimplemented = True

-        self.log.append("'%s' ? UNIMPLEMENTED\n" % self.name)

-

-    def failCritical(self, msg):        

-        self.failed = True

-        self.bad = True

-        self.log.append("'%s' ! BAD: %s\n" % (self.name, msg))  

-

-    def failExcept(self, e):      

-        self.failed = True

-        self.excepted = True

-        self.log.append("'%s' # EXCEPTION: %s\n" % (self.name, e.__str__()))

-    

-    def setUp(self):            

-        #

-        # Set up Libxml2.

-        #   

-        self.initialMemUsed = libxml2.debugMemory(1)

-        libxml2.initParser()

-        libxml2.lineNumbersDefault(1)

-        libxml2.registerErrorHandler(handleError, self)

-        

-    def tearDown(self):        

-        libxml2.schemaCleanupTypes()

-        libxml2.cleanupParser()      

-        self.memLeak = libxml2.debugMemory(1) - self.initialMemUsed

-

-    def isIOError(self, file, docType):

-        err = None

-        try:

-            err = libxml2.lastError()

-        except:

-            # Suppress exceptions.

-            pass

-        if (err is None):

-            return False

-        if err.domain() == libxml2.XML_FROM_IO:

-            self.failCritical("failed to access the %s resource '%s'\n" % (docType, file))

-

-    def debugMsg(self, msg):

-        global options 

-        if options.debugEnabled:

-            sys.stdout.write("'%s'   DEBUG: %s\n" % (self.name, msg))

-            

-    def finalize(self):

-        """Adds additional info to the log."""

-        #

-        # Add libxml2 messages.

-        #

-        self.log.extend(self.libLog)

-        #

-        # Add memory leaks.

-        #        

-        if self.memLeak != 0:            

-            self.log.append("%s + memory leak: %d bytes\n" % (self.name, self.memLeak))

-            

-    def processSchema(self, filePath):

-        global msgSchemaNotValidButShould, msgSchemaValidButShouldNot

-        schema = None

-        

-        #

-        # Parse the schema.

-        #

-        self.debugMsg("loading schema: %s" % filePath)

-        schema_ParserCtxt = libxml2.schemaNewParserCtxt(filePath)

-        try:

-            try:

-                schema = schema_ParserCtxt.schemaParse()

-            except:

-                pass

-        finally:

-            self.debugMsg("after loading schema")

-            del schema_ParserCtxt

-        if schema is None:

-            self.debugMsg("schema is None")

-            self.debugMsg("checking for IO errors...")

-            if self.isIOError(file, "schema"):

-                return None

-        self.debugMsg("checking schema result")

-        if (schema is None and self.schema_Val) or (schema is not None and self.schema_Val == 0):

-            self.debugMsg("schema result is BAD")

-            if (schema == None):

-                self.fail(msgSchemaNotValidButShould)

-            else:

-                self.fail(msgSchemaValidButShouldNot)

-        else:

-	    self.debugMsg("schema result is OK")

-            return schema

-

-    def processInstance(self, filePath, schema):

-        global msgInstanceNotValidButShould, msgInstanceValidButShouldNot

-        

-        instance = None

-        self.debugMsg("loading instance: %s" % filePath)            

-        instance_parserCtxt = libxml2.newParserCtxt()

-        if (instance_parserCtxt is None):

-            # TODO: Is this one necessary, or will an exception 

-            # be already raised?

-            raise Exception("Could not create the instance parser context.")

-        try:

-            try:

-                instance = instance_parserCtxt.ctxtReadFile(filePath, None, libxml2.XML_PARSE_NOWARNING)

-            except:

-                # Suppress exceptions.

-                pass

-        finally:

-            del instance_parserCtxt

-        self.debugMsg("after loading instance")

-        if instance is None:

-            self.debugMsg("instance is None")

-            self.failCritical("Failed to parse the instance for unknown reasons.")

-            return

-        else:

-            try:

-                #

-                # Validate the instance.

-                #

-		

-                validation_Ctxt = schema.schemaNewValidCtxt()

-		#validation_Ctxt = libxml2.schemaNewValidCtxt(None)

-                if (validation_Ctxt is None):

-                    self.failCritical("Could not create the validation context.")

-                    return

-                try:

-                    self.debugMsg("validating instance") 

-                    instance_Err = validation_Ctxt.schemaValidateDoc(instance)

-                    self.debugMsg("after instance validation") 

-                    self.debugMsg("instance-err: %d" % instance_Err)

-                    if (instance_Err != 0 and self.instance_Val == 1) or (instance_Err == 0 and self.instance_Val == 0):

-                        self.debugMsg("instance result is BAD")

-                        if (instance_Err != 0):

-                            self.fail(msgInstanceNotValidButShould)

-                        else:

-                            self.fail(msgInstanceValidButShouldNot)

-                            

-                    else:                        

-                                self.debugMsg("instance result is OK")

-                finally:

-                    del validation_Ctxt

-            finally:

-                instance.freeDoc()

-            

-

-    def run(self):

-        """Runs a test.""" 

-        global options

-        

-        # os.path.join(options.baseDir, self.test_Folder, self.schema_Folder, self.schema_File)

-        filePath = "%s/%s/%s/%s" % (options.baseDir, self.test_Folder, self.schema_Folder, self.schema_File)

-        schema = None

-        try:                

-            schema = self.processSchema(filePath)

-            try:

-                if self.instance_Exists and (schema is not None) and (not self.failed):

-                    filePath = "%s/%s/%s/%s" % (options.baseDir, self.test_Folder, self.instance_Folder, self.instance_File)

-                    self.processInstance(filePath, schema)

-            finally:

-                if schema is not None:

-                   del schema

-

-        except (Exception, libxml2.parserError, libxml2.treeError), e:

-            self.failExcept(e)

-

-            

-####################

-# Test runner class.

-#

-              

-class MSTestRunner:

-

-    CNT_TOTAL = 0

-    CNT_RAN = 1

-    CNT_SUCCEEDED = 2

-    CNT_FAILED = 3

-    CNT_UNIMPLEMENTED = 4

-    CNT_INTERNAL = 5

-    CNT_BAD = 6

-    CNT_EXCEPTED = 7

-    CNT_MEMLEAK = 8

-

-    def __init__(self):

-        self.logFile = None

-        self.counters = self.createCounters()

-        self.testList = []

-        self.combinesRan = {}

-        

-    def createCounters(self):

-        counters = {self.CNT_TOTAL:0, self.CNT_RAN:0, self.CNT_SUCCEEDED:0,

-        self.CNT_FAILED:0, self.CNT_UNIMPLEMENTED:0, self.CNT_INTERNAL:0, self.CNT_BAD:0, 

-        self.CNT_EXCEPTED:0, self.CNT_MEMLEAK:0}

-        

-        return counters

-

-    def addTest(self, test):

-        self.testList.append(test)

-        

-    def updateCounters(self, test, counters):

-        if test.memLeak != 0:

-           counters[self.CNT_MEMLEAK] += 1

-        if not test.failed:

-           counters[self.CNT_SUCCEEDED] +=1

-        if test.failed:

-           counters[self.CNT_FAILED] += 1

-        if test.bad:

-           counters[self.CNT_BAD] += 1

-        if test.unimplemented:

-           counters[self.CNT_UNIMPLEMENTED] += 1   

-        if test.internalErr:

-           counters[self.CNT_INTERNAL] += 1                      

-        if test.excepted:

-           counters[self.CNT_EXCEPTED] += 1

-        return counters

-           

-    def displayResults(self, out, all, combName, counters):

-        out.write("\n")

-        if all:

-            if options.combines is not None:

-                out.write("combine(s): %s\n" % str(options.combines))

-        elif combName is not None:             

-            out.write("combine : %s\n" % combName)

-        out.write("  total             : %d\n" % counters[self.CNT_TOTAL])

-        if all or options.combines is not None:

-            out.write("    ran             : %d\n" % counters[self.CNT_RAN])

-        # out.write("    succeeded       : %d\n" % counters[self.CNT_SUCCEEDED])

-        if counters[self.CNT_FAILED] > 0:

-            out.write("    failed          : %d\n" % counters[self.CNT_FAILED])

-            out.write("     -> internal    : %d\n" % counters[self.CNT_INTERNAL])

-            out.write("     -> unimpl.     : %d\n" % counters[self.CNT_UNIMPLEMENTED])

-            out.write("     -> bad         : %d\n" % counters[self.CNT_BAD])            

-            out.write("     -> exceptions  : %d\n" % counters[self.CNT_EXCEPTED])

-        if counters[self.CNT_MEMLEAK] > 0:

-            out.write("    memory leaks    : %d\n" % counters[self.CNT_MEMLEAK])

-

-    def displayShortResults(self, out, all, combName, counters):

-        out.write("Ran %d of %d tests:" % (counters[self.CNT_RAN],

-                  counters[self.CNT_TOTAL]))

-        # out.write("    succeeded       : %d\n" % counters[self.CNT_SUCCEEDED])

-        if counters[self.CNT_FAILED] > 0 or counters[self.CNT_MEMLEAK] > 0:

-            out.write(" %d failed" % (counters[self.CNT_FAILED]))

-            if counters[self.CNT_INTERNAL] > 0:

-                out.write(" %d internal" % (counters[self.CNT_INTERNAL]))

-            if counters[self.CNT_UNIMPLEMENTED] > 0:

-                out.write(" %d unimplemented" % (counters[self.CNT_UNIMPLEMENTED]))

-            if counters[self.CNT_BAD] > 0:

-                out.write(" %d bad" % (counters[self.CNT_BAD]))

-            if counters[self.CNT_EXCEPTED] > 0:

-                out.write(" %d exception" % (counters[self.CNT_EXCEPTED]))

-            if counters[self.CNT_MEMLEAK] > 0:

-                out.write(" %d leaks" % (counters[self.CNT_MEMLEAK]))

-            out.write("\n")

-        else:

-            out.write(" all passed\n")

-    

-    def reportCombine(self, combName):

-        global options

-        

-        counters = self.createCounters()

-        #

-        # Compute evaluation counters.

-        #

-        for test in self.combinesRan[combName]:

-            counters[self.CNT_TOTAL] += 1

-            counters[self.CNT_RAN] += 1

-            counters = self.updateCounters(test, counters)

-        if options.reportErrCombines and (counters[self.CNT_FAILED] == 0) and (counters[self.CNT_MEMLEAK] == 0):

-            pass

-        else:

-            if not options.disableLog:

-                self.displayResults(self.logFile, False, combName, counters)

-            self.displayResults(sys.stdout, False, combName, counters)

-        

-    def displayTestLog(self, test):

-        sys.stdout.writelines(test.log)

-        sys.stdout.write("~~~~~~~~~~\n")

-    

-    def reportTest(self, test):

-        global options

-        

-        error = test.failed or test.memLeak != 0

-        #

-        # Only erroneous tests will be written to the log,

-        # except @verbose is switched on.

-        #        

-        if not options.disableLog and (options.verbose or error):

-            self.logFile.writelines(test.log)

-            self.logFile.write("~~~~~~~~~~\n")

-        #

-        # if not @silent, only erroneous tests will be

-        # written to stdout, except @verbose is switched on.

-        #

-        if not options.silent: 

-            if options.reportInternalErrOnly and test.internalErr:

-                self.displayTestLog(test)

-            if options.reportMemLeakErrOnly and test.memLeak != 0: 

-                self.displayTestLog(test)

-            if (options.verbose or error) and (not options.reportInternalErrOnly) and (not options.reportMemLeakErrOnly):

-                self.displayTestLog(test)

-                

-    def addToCombines(self, test):

-        found = False

-        if self.combinesRan.has_key(test.combineName):

-            self.combinesRan[test.combineName].append(test)

-        else:

-            self.combinesRan[test.combineName] = [test]

-

-    def run(self):

-

-        global options

-        

-        if options.info:

-            for test in self.testList:

-                self.addToCombines(test)               

-            sys.stdout.write("Combines: %d\n" % len(self.combinesRan))

-            sys.stdout.write("%s\n" % self.combinesRan.keys())

-            return

-        

-        if not options.disableLog:

-            self.logFile = open(options.logFile, "w")

-        try:

-            for test in self.testList:

-                self.counters[self.CNT_TOTAL] += 1

-                #

-                # Filter tests.

-                #   

-                if options.singleTest is not None and options.singleTest != "":

-                    if (test.name != options.singleTest):

-                        continue

-                elif options.combines is not None:

-                    if not options.combines.__contains__(test.combineName):

-                        continue

-                if options.maxTestCount != -1 and self.counters[self.CNT_RAN] >= options.maxTestCount:

-                    break

-                self.counters[self.CNT_RAN] += 1

-                #

-                # Run the thing, dammit.

-                #

-                try:

-                    test.setUp()

-                    try:

-                        test.run()

-                    finally:

-                        test.tearDown()

-                finally:

-                    #

-                    # Evaluate.

-                    #

-                    test.finalize()

-                    self.reportTest(test)

-                    if options.reportCombines or options.reportErrCombines:

-                        self.addToCombines(test)

-                    self.counters = self.updateCounters(test, self.counters)

-        finally:        

-            if options.reportCombines or options.reportErrCombines:

-                #

-                # Build a report for every single combine.

-                #

-                # TODO: How to sort a dict?

-                #

-                self.combinesRan.keys().sort(None)

-                for key in self.combinesRan.keys():

-                    self.reportCombine(key)

-            

-            #

-            # Display the final report.

-            #

-            if options.silent:

-                self.displayShortResults(sys.stdout, True, None, self.counters)

-            else:

-                sys.stdout.write("===========================\n")

-                self.displayResults(sys.stdout, True, None, self.counters)

+#!/usr/bin/env python
+
+#
+# This is the MS subset of the W3C test suite for XML Schemas.
+# This file is generated from the MS W3c test suite description file.
+#
+
+import sys, os
+import exceptions, optparse
+import libxml2
+
+opa = optparse.OptionParser()
+
+opa.add_option("-b", "--base", action="store", type="string", dest="baseDir",
+			   default="",
+			   help="""The base directory; i.e. the parent folder of the
+			   "nisttest", "suntest" and "msxsdtest" directories.""")
+
+opa.add_option("-o", "--out", action="store", type="string", dest="logFile",
+			   default="test.log",
+			   help="The filepath of the log file to be created")
+
+opa.add_option("--log", action="store_true", dest="enableLog",
+			   default=False,
+			   help="Create the log file")
+
+opa.add_option("--no-test-out", action="store_true", dest="disableTestStdOut",
+			   default=False,
+			   help="Don't output test results")
+
+opa.add_option("-s", "--silent", action="store_true", dest="silent", default=False,
+			   help="Disables display of all tests")
+
+opa.add_option("-v", "--verbose", action="store_true", dest="verbose",
+			   default=False,
+			   help="Displays all tests (only if --silent is not set)")
+
+opa.add_option("-x", "--max", type="int", dest="maxTestCount",
+			   default="-1",
+			   help="The maximum number of tests to be run")
+
+opa.add_option("-t", "--test", type="string", dest="singleTest",
+			   default=None,
+			   help="Runs the specified test only")
+			   
+opa.add_option("--tsw", "--test-starts-with", type="string", dest="testStartsWith",
+			   default=None,
+			   help="Runs the specified test(s), starting with the given string")
+
+opa.add_option("--rieo", "--report-internal-errors-only", action="store_true",
+			   dest="reportInternalErrOnly", default=False,
+			   help="Display erroneous tests of type 'internal' only")
+
+opa.add_option("--rueo", "--report-unimplemented-errors-only", action="store_true",
+			   dest="reportUnimplErrOnly", default=False,
+			   help="Display erroneous tests of type 'unimplemented' only")
+
+opa.add_option("--rmleo", "--report-mem-leak-errors-only", action="store_true",
+			   dest="reportMemLeakErrOnly", default=False,
+			   help="Display erroneous tests of type 'memory leak' only")
+
+opa.add_option("-c", "--combines", type="string", dest="combines",
+			   default=None,
+			   help="Combines to be run (all if omitted)")
+			   
+opa.add_option("--csw", "--csw", type="string", dest="combineStartsWith",
+			   default=None,
+			   help="Combines to be run (all if omitted)")			   
+
+opa.add_option("--rc", "--report-combines", action="store_true",
+			   dest="reportCombines", default=False,
+			   help="Display combine reports")
+
+opa.add_option("--rec", "--report-err-combines", action="store_true",
+			   dest="reportErrCombines", default=False,
+			   help="Display erroneous combine reports only")
+
+opa.add_option("--debug", action="store_true",
+			   dest="debugEnabled", default=False,
+			   help="Displays debug messages")
+
+opa.add_option("--info", action="store_true",
+			   dest="info", default=False,
+			   help="Displays info on the suite only. Does not run any test.")
+
+(options, args) = opa.parse_args()
+
+if options.combines is not None:
+	options.combines = options.combines.split()
+
+################################################
+# The vars below are not intended to be changed.
+#
+
+msgSchemaNotValidButShould =  "The schema should be valid."
+msgSchemaValidButShouldNot = "The schema should be invalid."
+msgInstanceNotValidButShould = "The instance should be valid."
+msgInstanceValidButShouldNot = "The instance should be invalid."
+vendorNIST = "NIST"
+vendorNIST_2 = "NIST-2"
+vendorSUN  = "SUN"
+vendorMS   = "MS"
+
+###################
+# Helper functions.
+#
+vendor = None
+
+def handleError(test, msg):
+	global options
+	if not options.silent:
+		test.addLibLog("'%s'   LIB: %s" % (test.name, msg))
+	if msg.find("Unimplemented") > -1:
+		test.failUnimplemented()
+	elif msg.find("Internal") > -1:
+		test.failInternal()
+		
+	
+def fixFileNames(fileName):
+	if (fileName is None) or (fileName == ""):
+		return ""
+	dirs = fileName.split("/")
+	if dirs[1] != "Tests":
+		fileName = os.path.join(".", "Tests")
+		for dir in dirs[1:]:
+			fileName = os.path.join(fileName, dir)	
+	return fileName
+
+class XSTCTestGroup:
+	def __init__(self, name, schemaFileName, descr):
+		global vendor, vendorNIST_2
+		self.name = name
+		self.descr = descr
+		self.mainSchema = True
+		self.schemaFileName = fixFileNames(schemaFileName)
+		self.schemaParsed = False
+		self.schemaTried = False
+
+	def setSchema(self, schemaFileName, parsed):
+		if not self.mainSchema:			
+			return
+		self.mainSchema = False
+		self.schemaParsed = parsed
+		self.schemaTried = True
+
+class XSTCTestCase:
+
+		   # <!-- groupName, Name, Accepted, File, Val, Descr
+	def __init__(self, isSchema, groupName, name, accepted, file, val, descr):
+		global options
+		#
+		# Constructor.
+		#
+		self.testRunner = None
+		self.isSchema = isSchema
+		self.groupName = groupName
+		self.name = name
+		self.accepted = accepted		
+		self.fileName = fixFileNames(file)
+		self.val = val
+		self.descr = descr
+		self.failed = False
+		self.combineName = None
+
+		self.log = []
+		self.libLog = []
+		self.initialMemUsed = 0
+		self.memLeak = 0
+		self.excepted = False
+		self.bad = False
+		self.unimplemented = False
+		self.internalErr = False
+		self.noSchemaErr = False
+		self.failed = False
+		#
+		# Init the log.
+		#
+		if not options.silent:
+			if self.descr is not None:
+				self.log.append("'%s'   descr: %s\n" % (self.name, self.descr))		
+			self.log.append("'%s'   exp validity: %d\n" % (self.name, self.val))
+
+	def initTest(self, runner):
+		global vendorNIST, vendorSUN, vendorMS, vendorNIST_2, options, vendor
+		#
+		# Get the test-group.
+		#
+		self.runner = runner
+		self.group = runner.getGroup(self.groupName)				
+		if vendor == vendorMS or vendor == vendorSUN:
+			#
+			# Use the last given directory for the combine name.
+			#
+			dirs = self.fileName.split("/")
+			self.combineName = dirs[len(dirs) -2]					
+		elif vendor == vendorNIST:
+			#
+			# NIST files are named in the following form:
+			# "NISTSchema-short-pattern-1.xsd"
+			#						
+			tokens = self.name.split("-")
+			self.combineName = tokens[1]
+		elif vendor == vendorNIST_2:
+			#
+			# Group-names have the form: "atomic-normalizedString-length-1"
+			#
+			tokens = self.groupName.split("-")
+			self.combineName = "%s-%s" % (tokens[0], tokens[1])
+		else:
+			self.combineName = "unkown"
+			raise Exception("Could not compute the combine name of a test.")
+		if (not options.silent) and (self.group.descr is not None):
+			self.log.append("'%s'   group-descr: %s\n" % (self.name, self.group.descr))
+		
+
+	def addLibLog(self, msg):		
+		"""This one is intended to be used by the error handler
+		function"""
+		global options		
+		if not options.silent:
+			self.libLog.append(msg)
+
+	def fail(self, msg):
+		global options
+		self.failed = True
+		if not options.silent:
+			self.log.append("'%s' ( FAILED: %s\n" % (self.name, msg))
+
+	def failNoSchema(self):
+		global options
+		self.failed = True
+		self.noSchemaErr = True
+		if not options.silent:
+			self.log.append("'%s' X NO-SCHEMA\n" % (self.name))
+
+	def failInternal(self):
+		global options
+		self.failed = True
+		self.internalErr = True
+		if not options.silent:
+			self.log.append("'%s' * INTERNAL\n" % self.name)
+
+	def failUnimplemented(self):
+		global options
+		self.failed = True
+		self.unimplemented = True
+		if not options.silent:
+			self.log.append("'%s' ? UNIMPLEMENTED\n" % self.name)
+
+	def failCritical(self, msg):
+		global options
+		self.failed = True
+		self.bad = True
+		if not options.silent:
+			self.log.append("'%s' ! BAD: %s\n" % (self.name, msg))
+
+	def failExcept(self, e):
+		global options
+		self.failed = True
+		self.excepted = True
+		if not options.silent:
+			self.log.append("'%s' # EXCEPTION: %s\n" % (self.name, e.__str__()))
+
+	def setUp(self):
+		#
+		# Set up Libxml2.
+		#
+		self.initialMemUsed = libxml2.debugMemory(1)
+		libxml2.initParser()
+		libxml2.lineNumbersDefault(1)
+		libxml2.registerErrorHandler(handleError, self)
+
+	def tearDown(self):
+		libxml2.schemaCleanupTypes()
+		libxml2.cleanupParser()
+		self.memLeak = libxml2.debugMemory(1) - self.initialMemUsed
+
+	def isIOError(self, file, docType):
+		err = None
+		try:
+			err = libxml2.lastError()
+		except:
+			# Suppress exceptions.
+			pass
+		if (err is None):
+			return False
+		if err.domain() == libxml2.XML_FROM_IO:
+			self.failCritical("failed to access the %s resource '%s'\n" % (docType, file))
+
+	def debugMsg(self, msg):
+		global options
+		if options.debugEnabled:
+			sys.stdout.write("'%s'   DEBUG: %s\n" % (self.name, msg))
+
+	def finalize(self):
+		global options
+		"""Adds additional info to the log."""
+		#
+		# Add libxml2 messages.
+		#
+		if not options.silent:
+			self.log.extend(self.libLog)
+			#
+			# Add memory leaks.
+			#
+			if self.memLeak != 0:
+				self.log.append("%s + memory leak: %d bytes\n" % (self.name, self.memLeak))
+
+	def run(self):
+		"""Runs a test."""
+		global options
+
+		##filePath = os.path.join(options.baseDir, self.fileName)
+		# filePath = "%s/%s/%s/%s" % (options.baseDir, self.test_Folder, self.schema_Folder, self.schema_File)
+		try:
+			self.validate()
+		except (Exception, libxml2.parserError, libxml2.treeError), e:
+			self.failExcept(e)
+			
+def parseSchema(fileName):
+	schema = None
+	ctxt = libxml2.schemaNewParserCtxt(fileName)
+	try:
+		try:
+			schema = ctxt.schemaParse()
+		except:
+			pass
+	finally:		
+		del ctxt
+		return schema
+				
+
+class XSTCSchemaTest(XSTCTestCase):
+
+	def __init__(self, groupName, name, accepted, file, val, descr):
+		XSTCTestCase.__init__(self, 1, groupName, name, accepted, file, val, descr)
+
+	def validate(self):
+		global msgSchemaNotValidButShould, msgSchemaValidButShouldNot
+		schema = None
+		filePath = self.fileName
+		# os.path.join(options.baseDir, self.fileName)
+		valid = 0
+		try:
+			#
+			# Parse the schema.
+			#
+			self.debugMsg("loading schema: %s" % filePath)
+			schema = parseSchema(filePath)
+			self.debugMsg("after loading schema")						
+			if schema is None:
+				self.debugMsg("schema is None")
+				self.debugMsg("checking for IO errors...")
+				if self.isIOError(file, "schema"):
+					return
+			self.debugMsg("checking schema result")
+			if (schema is None and self.val) or (schema is not None and self.val == 0):
+				self.debugMsg("schema result is BAD")
+				if (schema == None):
+					self.fail(msgSchemaNotValidButShould)
+				else:
+					self.fail(msgSchemaValidButShouldNot)
+			else:
+				self.debugMsg("schema result is OK")
+		finally:
+			self.group.setSchema(self.fileName, schema is not None)
+			del schema
+
+class XSTCInstanceTest(XSTCTestCase):
+
+	def __init__(self, groupName, name, accepted, file, val, descr):
+		XSTCTestCase.__init__(self, 0, groupName, name, accepted, file, val, descr)
+
+	def validate(self):
+		instance = None
+		schema = None
+		filePath = self.fileName
+		# os.path.join(options.baseDir, self.fileName)
+
+		if not self.group.schemaParsed and self.group.schemaTried:
+			self.failNoSchema()
+			return
+					
+		self.debugMsg("loading instance: %s" % filePath)
+		parserCtxt = libxml2.newParserCtxt()
+		if (parserCtxt is None):
+			# TODO: Is this one necessary, or will an exception
+			# be already raised?
+			raise Exception("Could not create the instance parser context.")
+		try:
+			try:
+				instance = parserCtxt.ctxtReadFile(filePath, None, libxml2.XML_PARSE_NOWARNING)
+			except:
+				# Suppress exceptions.
+				pass
+		finally:
+			del parserCtxt
+		self.debugMsg("after loading instance")
+
+		if instance is None:
+			self.debugMsg("instance is None")
+			self.failCritical("Failed to parse the instance for unknown reasons.")
+			return
+		else:
+			try:
+				#
+				# Validate the instance.
+				#
+				self.debugMsg("loading schema: %s" % self.group.schemaFileName)
+				schema = parseSchema(self.group.schemaFileName)
+				try:
+					validationCtxt = schema.schemaNewValidCtxt()
+					#validationCtxt = libxml2.schemaNewValidCtxt(None)
+					if (validationCtxt is None):
+						self.failCritical("Could not create the validation context.")
+						return
+					try:
+						self.debugMsg("validating instance")
+						instance_Err = validationCtxt.schemaValidateDoc(instance)
+						self.debugMsg("after instance validation")
+						self.debugMsg("instance-err: %d" % instance_Err)
+						if (instance_Err != 0 and self.val == 1) or (instance_Err == 0 and self.val == 0):
+							self.debugMsg("instance result is BAD")
+							if (instance_Err != 0):
+								self.fail(msgInstanceNotValidButShould)
+							else:
+								self.fail(msgInstanceValidButShouldNot)
+	
+						else:
+									self.debugMsg("instance result is OK")
+					finally:
+						del validationCtxt
+				finally:
+					del schema
+			finally:
+				instance.freeDoc()
+
+
+####################
+# Test runner class.
+#
+
+class XSTCTestRunner:
+
+	CNT_TOTAL = 0
+	CNT_RAN = 1
+	CNT_SUCCEEDED = 2
+	CNT_FAILED = 3
+	CNT_UNIMPLEMENTED = 4
+	CNT_INTERNAL = 5
+	CNT_BAD = 6
+	CNT_EXCEPTED = 7
+	CNT_MEMLEAK = 8
+	CNT_NOSCHEMA = 9
+	CNT_NOTACCEPTED = 10
+	CNT_SCHEMA_TEST = 11
+
+	def __init__(self):
+		self.logFile = None
+		self.counters = self.createCounters()
+		self.testList = []
+		self.combinesRan = {}
+		self.groups = {}
+		self.curGroup = None
+
+	def createCounters(self):
+		counters = {self.CNT_TOTAL:0, self.CNT_RAN:0, self.CNT_SUCCEEDED:0,
+		self.CNT_FAILED:0, self.CNT_UNIMPLEMENTED:0, self.CNT_INTERNAL:0, self.CNT_BAD:0,
+		self.CNT_EXCEPTED:0, self.CNT_MEMLEAK:0, self.CNT_NOSCHEMA:0, self.CNT_NOTACCEPTED:0,
+		self.CNT_SCHEMA_TEST:0}
+
+		return counters
+
+	def addTest(self, test):
+		self.testList.append(test)
+		test.initTest(self)
+
+	def getGroup(self, groupName):
+		return self.groups[groupName]
+
+	def addGroup(self, group):
+		self.groups[group.name] = group
+
+	def updateCounters(self, test, counters):
+		if test.memLeak != 0:
+			counters[self.CNT_MEMLEAK] += 1
+		if not test.failed:
+			counters[self.CNT_SUCCEEDED] +=1
+		if test.failed:
+			counters[self.CNT_FAILED] += 1
+		if test.bad:
+			counters[self.CNT_BAD] += 1
+		if test.unimplemented:
+			counters[self.CNT_UNIMPLEMENTED] += 1
+		if test.internalErr:
+			counters[self.CNT_INTERNAL] += 1
+		if test.noSchemaErr:
+			counters[self.CNT_NOSCHEMA] += 1
+		if test.excepted:
+			counters[self.CNT_EXCEPTED] += 1
+		if not test.accepted:
+			counters[self.CNT_NOTACCEPTED] += 1
+		if test.isSchema:
+			counters[self.CNT_SCHEMA_TEST] += 1
+		return counters
+
+	def displayResults(self, out, all, combName, counters):
+		out.write("\n")
+		if all:
+			if options.combines is not None:
+				out.write("combine(s): %s\n" % str(options.combines))
+		elif combName is not None:
+			out.write("combine : %s\n" % combName)
+		out.write("  total           : %d\n" % counters[self.CNT_TOTAL])
+		if all or options.combines is not None:
+			out.write("  ran             : %d\n" % counters[self.CNT_RAN])
+			out.write("    (schemata)    : %d\n" % counters[self.CNT_SCHEMA_TEST])
+		# out.write("    succeeded       : %d\n" % counters[self.CNT_SUCCEEDED])
+		out.write("  not accepted    : %d\n" % counters[self.CNT_NOTACCEPTED])
+		if counters[self.CNT_FAILED] > 0:		    
+			out.write("    failed                  : %d\n" % counters[self.CNT_FAILED])
+			out.write("     -> internal            : %d\n" % counters[self.CNT_INTERNAL])
+			out.write("     -> unimpl.             : %d\n" % counters[self.CNT_UNIMPLEMENTED])
+			out.write("     -> skip-invalid-schema : %d\n" % counters[self.CNT_NOSCHEMA])
+			out.write("     -> bad                 : %d\n" % counters[self.CNT_BAD])
+			out.write("     -> exceptions          : %d\n" % counters[self.CNT_EXCEPTED])
+			out.write("    memory leaks            : %d\n" % counters[self.CNT_MEMLEAK])
+
+	def displayShortResults(self, out, all, combName, counters):
+		out.write("Ran %d of %d tests (%d schemata):" % (counters[self.CNT_RAN],
+				  counters[self.CNT_TOTAL], counters[self.CNT_SCHEMA_TEST]))
+		# out.write("    succeeded       : %d\n" % counters[self.CNT_SUCCEEDED])
+		if counters[self.CNT_NOTACCEPTED] > 0:
+			out.write(" %d not accepted" % (counters[self.CNT_NOTACCEPTED]))
+		if counters[self.CNT_FAILED] > 0 or counters[self.CNT_MEMLEAK] > 0:
+			if counters[self.CNT_FAILED] > 0:
+				out.write(" %d failed" % (counters[self.CNT_FAILED]))
+				out.write(" (")
+				if counters[self.CNT_INTERNAL] > 0:
+					out.write(" %d internal" % (counters[self.CNT_INTERNAL]))
+				if counters[self.CNT_UNIMPLEMENTED] > 0:
+					out.write(" %d unimplemented" % (counters[self.CNT_UNIMPLEMENTED]))
+				if counters[self.CNT_NOSCHEMA] > 0:
+					out.write(" %d skip-invalid-schema" % (counters[self.CNT_NOSCHEMA]))
+				if counters[self.CNT_BAD] > 0:
+					out.write(" %d bad" % (counters[self.CNT_BAD]))
+				if counters[self.CNT_EXCEPTED] > 0:
+					out.write(" %d exception" % (counters[self.CNT_EXCEPTED]))
+				out.write(" )")
+			if counters[self.CNT_MEMLEAK] > 0:
+				out.write(" %d leaks" % (counters[self.CNT_MEMLEAK]))			
+			out.write("\n")
+		else:
+			out.write(" all passed\n")
+
+	def reportCombine(self, combName):
+		global options
+
+		counters = self.createCounters()
+		#
+		# Compute evaluation counters.
+		#
+		for test in self.combinesRan[combName]:
+			counters[self.CNT_TOTAL] += 1
+			counters[self.CNT_RAN] += 1
+			counters = self.updateCounters(test, counters)
+		if options.reportErrCombines and (counters[self.CNT_FAILED] == 0) and (counters[self.CNT_MEMLEAK] == 0):
+			pass
+		else:
+			if options.enableLog:
+				self.displayResults(self.logFile, False, combName, counters)				
+			self.displayResults(sys.stdout, False, combName, counters)
+
+	def displayTestLog(self, test):
+		sys.stdout.writelines(test.log)
+		sys.stdout.write("~~~~~~~~~~\n")
+
+	def reportTest(self, test):
+		global options
+
+		error = test.failed or test.memLeak != 0
+		#
+		# Only erroneous tests will be written to the log,
+		# except @verbose is switched on.
+		#
+		if options.enableLog and (options.verbose or error):
+			self.logFile.writelines(test.log)
+			self.logFile.write("~~~~~~~~~~\n")
+		#
+		# if not @silent, only erroneous tests will be
+		# written to stdout, except @verbose is switched on.
+		#
+		if not options.silent:
+			if options.reportInternalErrOnly and test.internalErr:
+				self.displayTestLog(test)
+			if options.reportMemLeakErrOnly and test.memLeak != 0:
+				self.displayTestLog(test)
+			if options.reportUnimplErrOnly and test.unimplemented:
+				self.displayTestLog(test)
+			if (options.verbose or error) and (not options.reportInternalErrOnly) and (not options.reportMemLeakErrOnly) and (not options.reportUnimplErrOnly):
+				self.displayTestLog(test)
+
+
+	def addToCombines(self, test):
+		found = False
+		if self.combinesRan.has_key(test.combineName):
+			self.combinesRan[test.combineName].append(test)
+		else:
+			self.combinesRan[test.combineName] = [test]
+
+	def run(self):
+
+		global options
+
+		if options.info:
+			for test in self.testList:
+				self.addToCombines(test)
+			sys.stdout.write("Combines: %d\n" % len(self.combinesRan))
+			sys.stdout.write("%s\n" % self.combinesRan.keys())
+			return
+
+		if options.enableLog:
+			self.logFile = open(options.logFile, "w")
+		try:
+			for test in self.testList:
+				self.counters[self.CNT_TOTAL] += 1
+				#
+				# Filter tests.
+				#
+				if options.singleTest is not None and options.singleTest != "":
+					if (test.name != options.singleTest):
+						continue
+				elif options.combines is not None:
+					if not options.combines.__contains__(test.combineName):
+						continue
+				elif options.testStartsWith is not None:
+					if not test.name.startswith(options.testStartsWith):
+						continue
+				elif options.combineStartsWith is not None:
+					if not test.combineName.startswith(options.combineStartsWith):
+						continue
+				
+				if options.maxTestCount != -1 and self.counters[self.CNT_RAN] >= options.maxTestCount:
+					break
+				self.counters[self.CNT_RAN] += 1
+				#
+				# Run the thing, dammit.
+				#
+				try:
+					test.setUp()
+					try:
+						test.run()
+					finally:
+						test.tearDown()
+				finally:
+					#
+					# Evaluate.
+					#
+					test.finalize()
+					self.reportTest(test)
+					if options.reportCombines or options.reportErrCombines:
+						self.addToCombines(test)
+					self.counters = self.updateCounters(test, self.counters)
+		finally:
+			if options.reportCombines or options.reportErrCombines:
+				#
+				# Build a report for every single combine.
+				#
+				# TODO: How to sort a dict?
+				#
+				self.combinesRan.keys().sort(None)
+				for key in self.combinesRan.keys():
+					self.reportCombine(key)
+
+			#
+			# Display the final report.
+			#
+			if options.silent:
+				self.displayShortResults(sys.stdout, True, None, self.counters)
+			else:
+				sys.stdout.write("===========================\n")
+				self.displayResults(sys.stdout, True, None, self.counters)