from xml.xslt.Processor import Processor

SRC1 = """<dummy/>"""


def ApplyTest(src, sty_list, topLevelParams=None):
    tlp = topLevelParams or {}
    PROC = Processor()
    for sty in sty_list:
        PROC.appendStylesheetString(sty)
    result = PROC.runString(src, topLevelParams=tlp)
    return result


FUNCS = []


def TestNodeSet(tester):
    sty = """\
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:common="http://exslt.org/common"
  version="1.0"
>

  <xsl:output method="text"/>

  <xsl:template match="/">
    <xsl:variable name='spam'>
      <eggs/>
    </xsl:variable>
    <xsl:value-of select='count(common:node-set($spam))'/>
    <xsl:text> </xsl:text>
    <xsl:value-of select='name(common:node-set($spam))'/>
  </xsl:template>

</xsl:stylesheet>
"""
    tester.startTest("node-set")
    result = ApplyTest(SRC1, [sty])
    tester.compare("1 eggs",result)
    tester.testDone()
    return
    
FUNCS.append(TestNodeSet)


def TestObjectType(tester):
    sty = """\
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:common="http://exslt.org/common"
  version="1.0"
>

  <xsl:output method="text"/>

  <xsl:template match="/">
    <xsl:variable name='spam'>
      <eggs/>
    </xsl:variable>
    <xsl:value-of select='common:object-type($spam)'/>
    <xsl:text> </xsl:text>
    <xsl:value-of select='common:object-type(.)'/>
    <xsl:text> </xsl:text>
    <xsl:value-of select='common:object-type("1")'/>
    <xsl:text> </xsl:text>
    <xsl:value-of select='common:object-type(1)'/>
    <xsl:text> </xsl:text>
    <xsl:value-of select='common:object-type(1=1)'/>
  </xsl:template>

</xsl:stylesheet>
"""
    tester.startTest("object-type")
    result = ApplyTest(SRC1, [sty])
    tester.compare("RTF node-set string number boolean",result)
    tester.testDone()
    return
    
FUNCS.append(TestObjectType)

    
def TestDifference(tester):
    sty = """\
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:set="http://exslt.org/sets"
  xmlns:x="http://uche.ogbuji.net/dummy"
  version="1.0"
>

  <xsl:output method="text"/>

  <x:spam/>
  <x:eggs/>

  <xsl:variable name='self' select='document("")/*'/>

  <xsl:template match="/">
    <xsl:variable name='result' select='set:difference($self/x:*, $self/x:spam)'/>
    <xsl:value-of select='count($result)'/>
    <xsl:text> </xsl:text>
    <xsl:value-of select='name($result)'/>
  </xsl:template>

</xsl:stylesheet>
"""
    tester.startTest("set:difference")
    result = ApplyTest(SRC1, [sty])
    tester.compare("1 x:eggs",result)
    tester.testDone()
    return

FUNCS.append(TestDifference)


def TestHasSameNode(tester):
    test = "Test set:has-same-node"
    sty = """\
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:set="http://exslt.org/sets"
  xmlns:x="http://uche.ogbuji.net/dummy"
  version="1.0"
>

  <xsl:output method="text"/>

  <x:spam/>
  <x:eggs/>

  <xsl:variable name='self' select='document("")/*'/>
  <xsl:variable name='empty' select='/parent::*'/>

  <xsl:template match="/">
    <xsl:variable name='r1' select='set:has-same-node($self/x:*, $self/x:spam)'/>
    <xsl:choose>
      <xsl:when test='$r1'>
        <xsl:text>works</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:text>broken</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:text> </xsl:text>
    <xsl:variable name='r2' select='set:has-same-node($self/x:*, $empty)'/>
    <xsl:choose>
      <xsl:when test='$r2'>
        <xsl:text>broken</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:text>works</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>
"""

    tester.startTest("set:has-same-node")
    result = ApplyTest(SRC1, [sty])
    tester.compare("works works",result)
    tester.testDone()
    return

FUNCS.append(TestHasSameNode)

    
def TestIntersection(tester):
    sty = """\
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:set="http://exslt.org/sets"
  xmlns:x="http://uche.ogbuji.net/dummy"
  version="1.0"
>

  <xsl:output method="text"/>

  <x:spam/>
  <x:eggs/>

  <xsl:variable name='self' select='document("")/*'/>
  <xsl:variable name='empty' select='/parent::*'/>

  <xsl:template match="/">
    <xsl:variable name='result' select='set:intersection($self/x:*, $self/x:spam)'/>
    <xsl:value-of select='count($result)'/>
    <xsl:text> </xsl:text>
    <xsl:value-of select='name($result)'/>
  </xsl:template>

</xsl:stylesheet>
"""

    tester.startTest("set:intersection")
    result = ApplyTest(SRC1, [sty])
    tester.compare("1 x:spam",result)
    tester.testDone()
    return


FUNCS.append(TestIntersection)


def TestDistinct(tester):
    sty = """\
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:set="http://exslt.org/sets"
  xmlns:x="http://uche.ogbuji.net/dummy"
  version="1.0"
>

  <xsl:output method="text"/>

  <x:spam/>
  <x:eggs/>
  <x:spam/>

  <xsl:variable name='self' select='document("")/*'/>

  <xsl:template match="/">
    <xsl:variable name='result' select='set:distinct($self/x:*, "name()")'/>
    <xsl:value-of select='count($result)'/>
    <xsl:for-each select='$result'>
      <xsl:text> </xsl:text>
      <xsl:value-of select='name()'/>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>
"""

    tester.startTest("set:distinct")
    result = ApplyTest(SRC1, [sty])
    tester.compare("2 x:spam x:eggs",result)
    tester.testDone()

FUNCS.append(TestDistinct)

    
def TestLeading(tester):
    sty = """\
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:set="http://exslt.org/sets"
  xmlns:x="http://uche.ogbuji.net/dummy"
  version="1.0"
>

  <xsl:output method="text"/>

  <x:spam/>
  <x:eggs/>
  <x:bread/>
  <x:eggs/>
  <x:spam/>

  <xsl:variable name='self' select='document("")/*'/>

  <xsl:template match="/">
  <xsl:variable name='result' select='set:leading($self/x:*, "name()=&apos;x:bread&apos;")'/>
    <xsl:value-of select='count($result)'/>
    <xsl:for-each select='$result'>
      <xsl:text> </xsl:text>
      <xsl:value-of select='name()'/>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>
"""

    tester.startTest("set:leading")
    tester.warning("Not Supported")
    #result = ApplyTest(SRC1, [sty])
    #print result
    tester.testDone()

FUNCS.append(TestLeading)

    
def TestTrailing(tester):
    sty = """\
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:set="http://exslt.org/sets"
  xmlns:x="http://uche.ogbuji.net/dummy"
  version="1.0"
>

  <xsl:output method="text"/>

  <x:spam/>
  <x:eggs/>
  <x:bread/>
  <x:eggs/>
  <x:spam/>

  <xsl:variable name='self' select='document("")/*'/>

  <xsl:template match="/">
  <xsl:variable name='result' select='set:trailing($self/x:*, "name()=&apos;x:bread&apos;")'/>
    <xsl:value-of select='count($result)'/>
    <xsl:for-each select='$result'>
      <xsl:text> </xsl:text>
      <xsl:value-of select='name()'/>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>
"""

    tester.startTest("set:trailing")
    tester.warning("Not Supported")
    #result = ApplyTest(SRC1, [sty])
    #print result
    tester.testDone()
    
FUNCS.append(TestTrailing)

    
def TestExists(tester):
    sty = """\
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:set="http://exslt.org/sets"
  xmlns:x="http://uche.ogbuji.net/dummy"
  version="1.0"
>

  <xsl:output method="text"/>

  <x:spam/>
  <x:eggs/>
  <x:bread/>
  <x:eggs/>
  <x:spam/>

  <xsl:variable name='self' select='document("")/*'/>
  <xsl:variable name='empty' select='/parent::*'/>

  <xsl:template match="/">
    <xsl:variable name='r1' select='set:exists($self/x:*, "name()=&apos;x:bread&apos;")'/>
    <xsl:choose>
      <xsl:when test='$r1'>
        <xsl:text>works</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:text>broken</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:text> </xsl:text>
    <xsl:variable name='r2' select='set:exists($self/x:*, "name()=&apos;x:nought&apos;")'/>
    <xsl:choose>
      <xsl:when test='$r2'>
        <xsl:text>broken</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:text>works</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>
"""

    tester.startTest("set:exists")
    tester.warning("Not Supported")
    #result = ApplyTest(SRC1, [sty])
    #print result
    tester.testDone()

FUNCS.append(TestExists)

    
def TestForAll(tester):
    sty = """\
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:set="http://exslt.org/sets"
  xmlns:x="http://uche.ogbuji.net/dummy"
  version="1.0"
>

  <xsl:output method="text"/>

  <x:spam/>
  <x:eggs/>
  <x:bread/>
  <x:eggs/>
  <x:spam/>

  <xsl:variable name='self' select='document("")/*'/>

  <xsl:template match="/">
    <xsl:variable name='r1' select='set:for-all($self/x:*, "namespace-uri()=&apos;http://uche.ogbuji.net/dummy&apos;")'/>
    <xsl:choose>
      <xsl:when test='$r1'>
        <xsl:text>works</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:text>broken</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:text> </xsl:text>
    <xsl:variable name='r2' select='set:for-all($self/x:*, "name()=&apos;x:spam&apos;")'/>
    <xsl:choose>
      <xsl:when test='$r2'>
        <xsl:text>broken</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:text>works</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>
"""

    tester.startTest("set:for-all")
    tester.warning("Not Supported")
    #result = ApplyTest(SRC1, [sty])
    #print result
    tester.testDone()

FUNCS.append(TestForAll)


def TestMax(tester):
    sty = """\
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:math="http://exslt.org/math"
  xmlns:common="http://exslt.org/common"
  xmlns:x="http://uche.ogbuji.net/dummy"
  version="1.0"
>

  <xsl:output method="text"/>

  <x:spam>2</x:spam>
  <x:eggs>12.0</x:eggs>
  <x:bread>100</x:bread>

  <xsl:variable name='self' select='document("")/*'/>

  <xsl:template match="/">
    <xsl:variable name='result' select='math:max($self/x:*, "number()")'/>
    <xsl:value-of select='common:object-type($result)'/>
    <xsl:text> </xsl:text>
    <xsl:value-of select='$result'/>
  </xsl:template>

</xsl:stylesheet>
"""
    tester.startTest("math:max")
    result = ApplyTest(SRC1, [sty])
    tester.compare("number 100",result)
    tester.testDone()

FUNCS.append(TestMax)

    
def TestMin(tester):
    sty = """\
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:math="http://exslt.org/math"
  xmlns:common="http://exslt.org/common"
  xmlns:x="http://uche.ogbuji.net/dummy"
  version="1.0"
>

  <xsl:output method="text"/>

  <x:spam>2</x:spam>
  <x:eggs>12.0</x:eggs>
  <x:bread>100</x:bread>

  <xsl:variable name='self' select='document("")/*'/>

  <xsl:template match="/">
    <xsl:variable name='result' select='math:min($self/x:*, "number()")'/>
    <xsl:value-of select='common:object-type($result)'/>
    <xsl:text> </xsl:text>
    <xsl:value-of select='$result'/>
  </xsl:template>

</xsl:stylesheet>
"""
    tester.startTest("math:min")
    result = ApplyTest(SRC1, [sty])
    tester.compare("number 2",result)
    tester.testDone()

FUNCS.append(TestMin)

    
def TestHighest(tester):
    sty = """\
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:math="http://exslt.org/math"
  xmlns:common="http://exslt.org/common"
  xmlns:x="http://uche.ogbuji.net/dummy"
  version="1.0"
>

  <xsl:output method="text"/>

  <x:spam>2</x:spam>
  <x:bread>100</x:bread>
  <x:eggs>12.0</x:eggs>

  <xsl:variable name='self' select='document("")/*'/>

  <xsl:template match="/">
    <xsl:variable name='result' select='math:highest($self/x:*, "number()")'/>
    <xsl:value-of select='name($result)'/>
  </xsl:template>

</xsl:stylesheet>
"""
    tester.startTest("math:highest")
    result = ApplyTest(SRC1, [sty])
    tester.compare("x:bread",result)
    tester.testDone()
    return

FUNCS.append(TestHighest)

    
def TestLowest(tester):
    sty = """\
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:math="http://exslt.org/math"
  xmlns:common="http://exslt.org/common"
  xmlns:x="http://uche.ogbuji.net/dummy"
  version="1.0"
>

  <xsl:output method="text"/>

  <x:spam>2</x:spam>
  <x:bread>100</x:bread>
  <x:eggs>12.0</x:eggs>

  <xsl:variable name='self' select='document("")/*'/>

  <xsl:template match="/">
    <xsl:variable name='result' select='math:lowest($self/x:*, "number()")'/>
    <xsl:value-of select='name($result)'/>
  </xsl:template>

</xsl:stylesheet>
"""
    tester.startTest("math:lowest")
    result = ApplyTest(SRC1, [sty])
    tester.compare("x:spam",result)
    tester.testDone()
    return

FUNCS.append(TestLowest)

    
def TestSum(tester):
    sty = """\
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:math="http://exslt.org/math"
  xmlns:common="http://exslt.org/common"
  xmlns:x="http://uche.ogbuji.net/dummy"
  version="1.0"
>

  <xsl:output method="text"/>

  <x:spam>2</x:spam>
  <x:bread>100</x:bread>
  <x:eggs>12.0</x:eggs>

  <xsl:variable name='self' select='document("")/*'/>

  <xsl:template match="/">
    <xsl:variable name='result' select='math:sum($self/x:*, "number()")'/>
    <xsl:value-of select='$result'/>
  </xsl:template>

</xsl:stylesheet>
"""
    tester.startTest("math:sum")
    tester.warning("Not Supported")
    #result = ApplyTest(SRC1, [sty])
    #print result
    tester.testDone()
    return
 
FUNCS.append(TestSum)

def TestFunction(tester):
    sty = """\
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:x="http://uche.ogbuji.net/dummy"
  xmlns:func="http://exslt.org/functions"
  extension-element-prefixes="func"
  version="1.0"
>

  <func:function name="x:count-elements">
    <xsl:for-each select="(//*)[1]">
      <func:result select="count(//*)" />
    </xsl:for-each>
  </func:function>

  <xsl:template match="/">
    <out>
      <xsl:value-of select="x:count-elements()" />
    </out>
  </xsl:template>

</xsl:stylesheet>
"""

    src = """\
<doc>
                              <section index="section1"
                                       index2="atr2val">
                                 <section index="subSection1.1">
                                    <p>Hello</p>
                                    <p>Hello again.</p>
                                 </section>
                              </section>
                              <section index="section2">
                                 <p>Hello2</p>
                                 <section index="subSection2.1">
                                    <p>Hello</p>
                                    <p>Hello again.</p>
                                 </section>
                                 <section index="subSection2.2">
                                    <p>Hello</p>
                                    <p>Hello again.</p>
                                 </section>
                                 <p>Hello2 again.</p>
                                 <section index="subSection2.3">
                                    <p>Hello</p>
                                    <p>Hello again.</p>
                                 </section>
                              </section>
                           </doc>
                           """
    expected = """<?xml version='1.0' encoding='UTF-8'?>
<out xmlns:x='http://uche.ogbuji.net/dummy'>17</out>"""
    tester.startTest("func:functions")
    result = ApplyTest(src, [sty])
    tester.compare(expected,result)
    tester.testDone()
    return
 
FUNCS.append(TestFunction)


def TestDocument(tester):
    sty = """\
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
    xmlns:common="http://exslt.org/common"
    extension-element-prefixes="common">

<xsl:output method="xml" indent="yes" encoding="ISO-8859-1"/>
<xsl:param name="filebase"/>

<xsl:template match="/">
  <xsl:apply-templates select="test"/>
</xsl:template>

<xsl:template match="test">
  <testout>
    <xsl:apply-templates select="data"/>
  </testout>
</xsl:template>

<xsl:template match="data">
  <xsl:variable name="file" select="concat($filebase, ., '.xml')"/>
  <datafile>
    <xsl:text>Writing data file </xsl:text>
    <xsl:value-of select="."/>
  </datafile>
  <common:document href="{$file}" method="xml" indent="yes" encoding="ISO-8859-1">
        <datatree>
          <name><xsl:value-of select="."/></name>
          <what>test</what>
        </datatree>
  </common:document>
</xsl:template>

</xsl:stylesheet>"""

    src = """\
<?xml version="1.0" encoding="ISO-8859-1"?>

<test>
  <data>11</data>
  <data>12</data>
  <data>13</data>
  <data>14</data>
  <data>15</data>
</test>
"""
    
    expected = """<?xml version='1.0' encoding='ISO-8859-1'?>
<testout>
  <datafile>Writing data file 11</datafile>
  <datafile>Writing data file 12</datafile>
  <datafile>Writing data file 13</datafile>
  <datafile>Writing data file 14</datafile>
  <datafile>Writing data file 15</datafile>
</testout>"""

    file_expected = """<?xml version='1.0' encoding='ISO-8859-1'?>
<datatree>
  <name>%s</name>
  <what>test</what>
</datatree>"""

    import tempfile, os

    fileName = tempfile.mktemp()
    tester.startTest("common:document")
    result = ApplyTest(src, [sty], topLevelParams={('','filebase') : fileName})
    tester.compare(expected, result)
    for data in range(11, 16):
        file = '%s%d.xml' % (fileName, data)
        tester.compare(1, os.path.exists(file))
        fileData = open(file,'r').read()
        tester.compare(file_expected % data, fileData)
        if os.path.exists(file):
            os.unlink(file)
        
    tester.testDone()
    return
 
FUNCS.append(TestDocument)


def Test(tester):
    tester.startGroup("EXSLT")
    for f in FUNCS:
        apply(f,(tester,))
    tester.groupDone()
