# Features covered: Pull parser
#
# This file contains a collection of tests for the pull parser
# interface.
# Tested functionalities:
#    pp-1.*: Basics, interface
#    pp-2.*: Compare dom / pull parsing
#    pp-3.*: skip method
#    pp-4.*: find-element method
#    pp-5.*: CDATA section handling
#    pp-6.*: line/column methods
#
# Copyright (c) 2017-2018 Rolf Ade.

source [file join [file dir [info script]] loadtdom.tcl]

test pp-1.1 {Create} {
    tdom::pullparser pp
    pp delete
} {}

test pp-1.2 {Invalid create} {
    catch {tdom::pullparser pp foo}
} 1

test pp-1.3 {Reset freshly created parser} {
    tdom::pullparser pp
    pp reset
    pp reset
    pp delete
} {}

test pp-1.4 {State after creation} {
    tdom::pullparser pp
    set result [pp state]
    lappend result [pp state]
    pp delete
    set result
} {READY READY}

proc walkDOM {node} {
    set str ""
    switch [$node nodeType] {
        "ELEMENT_NODE" {
            append str [$node nodeName]
            # Because the dom builder arranges attributes so that the
            # xmlns attributes come first we need to ensure a unify
            # attribute order for comparsion.
            set attpairs [list]
            foreach att [$node attributes] {
                if {[llength $att] == 3} {
                    if {[lindex $att 2] eq ""} {
                        lappend attpairs [list \
                            xmlns:[lindex $att 0] \
                            [$node getAttribute xmlns:[lindex $att 0]]]
                    } else {
                        lappend attpairs [list \
                            [lindex $att 1]:[lindex $att 0] \
                            [$node getAttribute [lindex $att 1]:[lindex $att 0]]]
                    }
                } else {
                    lappend attpairs [list $att [$node getAttribute $att]]
                }
            }
            foreach {name value} [lsort -index 0 $attpairs] {
                append str $name $value
            }
            foreach child [$node childNodes] {
                append str [walkDOM $child]
            }
            append str /[$node nodeName]
        }
        "TEXT_NODE" {
            append str [$node nodeValue]
        }
        default {
            # Ignore anything else
        }
    }
    return $str
}

proc loopPull {} {
    while {[set state [pp next]] ne "END_DOCUMENT"} {
        switch $state {
            "START_TAG" {
                append pullstr [pp tag]
                set attpairs [list]
                foreach {attname attvalue} [pp attributes] {
                    lappend attpairs [list $attname $attvalue]
                }
                foreach {name value} [lsort -index 0 $attpairs] {
                    append pullstr $name $value
                }
            }
            "TEXT" {
                append pullstr [pp text]
            }
            "END_TAG" {
                append pullstr /[pp tag]
            }
        }
    }
    return $pullstr
}

proc comparewithDOM {data {inputMethod input}} {
    if {$inputMethod eq "input"} {
        dom parse $data doc
    } elseif {$inputMethod eq "inputchannel"} {
        dom parse -channel $data doc
    } else {
        dom parse -keepEmpties [::tdom::xmlReadFile $data] doc
    }
    set domstr [walkDOM [$doc documentElement]]
    $doc delete
    tdom::pullparser pp
    pp $inputMethod $data
    set pullstr [loopPull]
    if {$domstr eq $pullstr} {
        return 1
    } else {
        puts "*** DOM str:"
        puts $domstr
        puts "*** Pull str:"
        puts $pullstr
        return 0
    }
    pp delete
}

proc fdata {file} {
    file join [file dir [info script]] data/$file
}

test pp-2.1 {dom/pull comparsion: mondial-europe.xml} {longRunning} {
    comparewithDOM [fdata mondial-europe.xml] inputfile
} 1

test pp-2.2 {dom/pull comparsion: books.xml} {
    comparewithDOM [fdata books.xml] inputfile
} 1

test pp-2.3 {dom/pull comparsion: i18n_1.xml} {
    comparewithDOM [fdata i18n_1.xml] inputfile
} 1

test pp-2.4 {dom/pull comparsion: i18n_2.xml} {
    comparewithDOM [fdata i18n_2.xml] inputfile
} 1

test pp-2.5 {dom/pull comparsion: REC-xslt-19991116.xml} {longRunning} {
    comparewithDOM [fdata REC-xslt-19991116.xml] inputfile
} 1

test pp-2.6 {dom/pull comparsion: xslt_1.xsl} {
    comparewithDOM [fdata xslt_1.xsl] inputfile
} 1

test pp-2.7 {dom/pull comparsion} {
    comparewithDOM {<p>This specification defines the syntax and semantics of XSLT, which
is a language for transforming XML documents into other XML
        documents.</p>}
} 1

test pp-2.8 {dom/pull comparsion} {
    comparewithDOM {<p><termdef> (see <specref/>), which is
referred to in </termdef></p>}
} 1

test pp-2.9 {dom/pull comparsion} {
    comparewithDOM {<p>This specification defines the syntax and semantics of the XSLT
language.  A transformation in the XSLT language is expressed as a
well-formed XML document <bibref/>conforming </p>}
} 1


proc loopPullE {} {
    while {[set state [pullparser next]] ne "END_DOCUMENT"} {
        switch $state {
            "START_TAG" {
                append pullstr [pullparser tag]
                foreach {attname attvalue} [pullparser attributes] {
                    append pullstr $attname $attvalue
                }
            }
            "TEXT" {
                append pullstr [pullparser text]
            }
            "END_TAG" {
                append pullstr /[pullparser tag]
            }
        }
    }
    return $pullstr
}

proc elementstart {name atts} {
    global expatstr

    append expatstr $name
    foreach {attname attvalue} $atts {
        append expatstr $attname $attvalue
    }
}

proc elementend {name} {
    global expatstr

    append expatstr /$name
}

proc cdata {cdata} {
    global expatstr

    append expatstr $cdata
}

proc comparewithExpat {data {inputMethod ""}} {
    global expatstr

    set expatstr ""
    expat pushparser \
        -elementstartcommand elementstart \
        -elementendcommand elementend \
        -characterdatacommand cdata
    pushparser parse$inputMethod $data
    tdom::pullparser pullparser
    pullparser input$inputMethod $data
    set pullstr [loopPullE]
    if {$expatstr eq $pullstr} {
        return 1
    } else {
        puts $expatstr
        puts $pullstr
        return 0
    }
    pushparser free
    pullparser delete
}


test pp-2.10 {expat/pull comparsion: mondial-europe.xml} {longRunning} {
    comparewithExpat [fdata mondial-europe.xml] file
} 1

test pp-2.11 {expat/pull comparsion: books.xml} {
    comparewithExpat [fdata books.xml] file
} 1

test pp-2.12 {expat/pull comparsion: i18n_1.xml} {
    comparewithExpat [fdata i18n_1.xml] file
} 1

test pp-2.13 {expat/pull comparsion: i18n_2.xml} {
    comparewithExpat [fdata i18n_2.xml] file
} 1

test pp-2.14 {expat/pull comparsion: REC-xslt-19991116.xml} {longRunning} {
    comparewithExpat [fdata REC-xslt-19991116.xml] file
} 1

test pp-2.15 {expat/pull comparsion: xslt_1.xsl} {
    comparewithExpat [fdata xslt_1.xsl] file
} 1

test pp-2.16 {expat/pull comparsion} {
    comparewithExpat {<p>This specification defines the syntax and semantics of XSLT, which
is a language for transforming XML documents into other XML
        documents.</p>}
} 1

test pp-2.17 {expat/pull comparsion} {
    comparewithExpat {<p><termdef> (see <specref/>), which is
referred to in </termdef></p>}
} 1

test pp-2.18 {expat/pull comparsion} {
    comparewithExpat {<p>This specification defines the syntax and semantics of the XSLT
language.  A transformation in the XSLT language is expressed as a
well-formed XML document <bibref/>conforming </p>}
} 1

test pp-3.1 {skip} {
    tdom::pullparser pp
    pp input <doc/>
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp skip]
    lappend result [pp tag]
    lappend result [pp next]
    pp delete
    set result
} {START_TAG doc END_TAG doc END_DOCUMENT}

test pp-3.1.1 {skip} {
    tdom::pullparser pp
    pp input {<doc><e/></doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp skip]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    pp delete
    set result
} {START_TAG doc START_TAG e END_TAG e END_TAG doc END_DOCUMENT}

test pp-3.1.2 {skip} {
    tdom::pullparser pp
    pp input {<doc>text<e/>text</doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp text]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp skip]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp text]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    pp delete
    set result
} {START_TAG doc TEXT text START_TAG e END_TAG e TEXT text END_TAG doc END_DOCUMENT}

test pp-3.1.3 {skip} {
    tdom::pullparser pp
    pp input {<doc>text<e>bar<b><c/><c>baz</c></b><b>text</b></e>text</doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp text]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp skip]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp text]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    pp delete
    set result
} {START_TAG doc TEXT text START_TAG e END_TAG e TEXT text END_TAG doc END_DOCUMENT}

test pp-3.1.4 {skip} {
    tdom::pullparser pp
    pp input <doc></doc>
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp skip]
    lappend result [pp tag]
    lappend result [pp next]
    pp delete
    set result
} {START_TAG doc END_TAG doc END_DOCUMENT}

test pp-3.1.5 {skip} {
    tdom::pullparser pp
    pp input {<doc> </doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp skip]
    lappend result [pp tag]
    lappend result [pp next]
    pp delete
    set result
} {START_TAG doc END_TAG doc END_DOCUMENT}

test pp-3.1.5 {skip} {
    tdom::pullparser pp -ignorewhitecdata
    pp input {<doc> </doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp skip]
    lappend result [pp tag]
    lappend result [pp next]
    pp delete
    set result
} {START_TAG doc END_TAG doc END_DOCUMENT}

test pp-3.2 {skip} {
    tdom::pullparser pp
    pp input {<doc><e/></doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp skip]
    lappend result [pp tag]
    lappend result [pp next]
    pp delete
    set result
} {START_TAG doc END_TAG doc END_DOCUMENT}

test pp-3.3 {skip} {
    tdom::pullparser pp
    pp input {<doc>foo bar<e/></doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp skip]
    lappend result [pp tag]
    lappend result [pp next]
    pp delete
    set result
} {START_TAG doc END_TAG doc END_DOCUMENT}

test pp-3.4 {skip} {
    tdom::pullparser pp
    pp input {<doc>foo bar<e/><e>bar<e/></e><e></e></doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp skip]
    lappend result [pp tag]
    lappend result [pp next]
    pp delete
    set result
} {START_TAG doc END_TAG doc END_DOCUMENT}

test pp-3.5 {skip} {
    tdom::pullparser pp
    pp input {<doc>foo bar<e/><e>bar<e/></e><e></e></doc>}
    set result [list]
    while {[set state [pp next]] ne "END_DOCUMENT"} {
        lappend result $state
        if {$state eq "START_TAG"} {
            lappend result [pp tag]
            if {[pp tag] eq "e"} {
                pp skip
                continue
            }
        }
        if {[pp state] eq "END_TAG"} {
            lappend result [pp tag]
        }
    }
    pp delete
    set result
} {START_TAG doc TEXT START_TAG e START_TAG e START_TAG e END_TAG doc}

test pp-3.6 {skip} {
    tdom::pullparser pp
    pp input {<doc>foo bar<e/><e>bar<e/></e><e></e>baz</doc>}
    set result [list]
    while {[set state [pp next]] ne "END_DOCUMENT"} {
        lappend result $state
        if {$state eq "START_TAG"} {
            lappend result [pp tag]
            if {[pp tag] eq "e"} {
                pp skip
                continue
            }
        }
        if {[pp state] eq "END_TAG"} {
            lappend result [pp tag]
        }
        if {[pp state] eq "TEXT"} {
            lappend result [pp text]
        }
    }
    pp delete
    set result
} {START_TAG doc TEXT {foo bar} START_TAG e START_TAG e START_TAG e TEXT baz END_TAG doc}

test pp-3.7 {skip} {
    tdom::pullparser pp
    pp input {<doc>foo bar<e/><e>bar</wrong><e></e></doc>}
    set result [pp next]
    lappend result [pp next]; # TEXT "foo bar"
    lappend result [pp next]; # START_TAG
    lappend result [pp tag];  # e
    lappend result [pp next]; # END_TAG
    lappend result [pp tag];  # e
    lappend result [pp next]; # START_TAG
    lappend result [pp tag];  # e
    lappend result [catch {pp skip} errMsg]
    lappend result $errMsg
    pp delete
    set result
} {START_TAG TEXT START_TAG e END_TAG e START_TAG e 1 {error "mismatched tag" at line 1 character 24}}

test pp-3.8 {skip} {
    tdom::pullparser pp
    pp input {<doc>foo bar<e/><e>bar</e></doc>}
    set result [pp next]
    lappend result [pp skip]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [catch {pp next} errMsg]
    lappend result $errMsg
    pp delete
    set result
} {START_TAG END_TAG doc END_DOCUMENT 1 {No next event after END_DOCUMENT}}

test pp-4.1 {find-element} {
    tdom::pullparser pp
    pp input {<doc><a>foo bar</a><b>baz</b><c>grill</c><d>here</d></doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp find-element d]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp text]
    lappend result [pp next]
    lappend result [pp tag]    
    while {[pp next] ne "END_DOCUMENT"} {}
    pp delete
    set result
} {START_TAG doc START_TAG a START_TAG d TEXT here END_TAG d}

test pp-4.2 {find-element} {
    tdom::pullparser pp
    pp input {<doc><a>foo bar</a><b>baz</b><c>grill</c><d></d></doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp find-element d]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp tag]    
    while {[pp next] ne "END_DOCUMENT"} {}
    pp delete
    set result
} {START_TAG doc START_TAG a START_TAG d END_TAG d}

test pp-4.3 {find-element} {
    tdom::pullparser pp
    pp input {<doc><a>foo bar</a><b>baz</b><c>grill</c>some<d/></doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp find-element d]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp tag]    
    while {[pp next] ne "END_DOCUMENT"} {}
    pp delete
    set result
} {START_TAG doc START_TAG a START_TAG d END_TAG d}

test pp-4.4 {find-element} {
    tdom::pullparser pp
    pp input {<doc><a><b><c><d>grill</d></c></b></a></doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp find-element d]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp text]
    lappend result [pp next]
    lappend result [pp tag]    
    lappend result [pp next]
    lappend result [pp tag]    
    while {[pp next] ne "END_DOCUMENT"} {}
    pp delete
    set result
} {START_TAG doc START_TAG d TEXT grill END_TAG d END_TAG c}

test pp-4.5 {find-element} {
    tdom::pullparser pp
    pp input {<doc><a><b><c><d></d></c></b></a></doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp find-element d]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp tag]    
    lappend result [pp next]
    lappend result [pp tag]    
    while {[pp next] ne "END_DOCUMENT"} {}
    pp delete
    set result
} {START_TAG doc START_TAG d END_TAG d END_TAG c}

test pp-4.6 {find-element} {
    tdom::pullparser pp
    pp input {<doc><a><b><c><d/></c></b></a></doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp find-element d]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp tag]    
    lappend result [pp next]
    lappend result [pp tag]    
    while {[pp next] ne "END_DOCUMENT"} {}
    pp delete
    set result
} {START_TAG doc START_TAG d END_TAG d END_TAG c}


test pp-4.7 {find-element} {
    tdom::pullparser pp
    pp input {<doc><a><b/></a><a><b><c/></b></a><a><b/></a></doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp find-element b]
    lappend result [pp tag]
    lappend result [pp find-element c]
    lappend result [pp tag]
    lappend result [pp find-element a]
    lappend result [pp tag]
    while {[pp next] ne "END_DOCUMENT"} {}
    pp delete
    set result
} {START_TAG doc START_TAG b START_TAG c START_TAG a}

test pp-4.8 {find-element} {
    tdom::pullparser pp
    pp input {<doc/>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp find-element b]
    pp delete
    set result
} {START_TAG doc END_TAG doc END_DOCUMENT}

test pp-4.8.1 {find-element} {
    tdom::pullparser pp
    pp input {<doc></doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp find-element b]
    pp delete
    set result
} {START_TAG doc END_TAG doc END_DOCUMENT}

test pp-4.8.2 {find-element} {
    tdom::pullparser pp
    pp input {<doc> </doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp find-element b]
    pp delete
    set result
} {START_TAG doc TEXT END_TAG doc END_DOCUMENT}

test pp-4.8.3 {find-element} {
    tdom::pullparser pp -ignorewhitecdata
    pp input {<doc> </doc>}
    set result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp find-element b]
    pp delete
    set result
} {START_TAG doc END_TAG doc END_DOCUMENT}

test pp-4.9 {find-element} {
    tdom::pullparser pp
    pp input {<doc><a><b/></a><a><b><c/></b></a><a><b/></a></doc>}
    set result [pp next]; # START_TAG
    lappend result [pp tag]; # doc
    lappend result [pp next]; # START_TAG
    lappend result [pp tag]; # a
    lappend result [pp find-element b]; # START_TAG
    lappend result [pp tag]; #b 
    lappend result [pp find-element c]; # START_TAG
    lappend result [pp tag]; #c
    lappend result [pp next]; # END_TAG
    lappend result [pp tag]; # c
    lappend result [pp find-element a]; # START_TAG
    lappend result [pp tag]; # a
    while {[pp next] ne "END_DOCUMENT"} {}
    pp delete
    set result
} {START_TAG doc START_TAG a START_TAG b START_TAG c END_TAG c START_TAG a}

test pp-4.10 {find-element} {
    tdom::pullparser pp
    pp input {<doc>foo<a/>bar<b>grill<a/>baz</b></doc>}
    set result [pp next]; # START_TAG
    lappend result [pp tag]; # doc
    lappend result [pp find-element a]; # START_TAG
    lappend result [pp tag]; # a
    lappend result [pp next]; # END_TAG
    lappend result [pp tag]; # a
    lappend result [pp find-element a]; # START_TAG
    lappend result [pp tag]; #a 
    lappend result [pp next]; # END_TAG
    lappend result [pp tag]; # a 
    lappend result [pp next]; # TEXT 
    lappend result [pp text]; # baz 
    lappend result [pp next]; # END_TAG 
    lappend result [pp tag]; # b
    while {[pp next] ne "END_DOCUMENT"} {}
    pp delete
    set result
} {START_TAG doc START_TAG a END_TAG a START_TAG a END_TAG a TEXT baz END_TAG b}

test pp-4.11 {find-element} {
    tdom::pullparser pp
    pp input {<doc>foo<a/>bar<b>grill<a/>baz</b></doc>}
    set result [pp state]
    lappend result [pp find-element a]; # START_TAG
    lappend result [pp tag]; # a
    lappend result [pp next]; # END_TAG
    lappend result [pp tag]; # a
    lappend result [pp find-element a]; # START_TAG
    lappend result [pp tag]; #a 
    lappend result [pp next]; # END_TAG
    lappend result [pp tag]; # a 
    lappend result [pp next]; # TEXT 
    lappend result [pp text]; # baz 
    lappend result [pp next]; # END_TAG 
    lappend result [pp tag]; # b
    while {[pp next] ne "END_DOCUMENT"} {}
    pp delete
    set result
} {START_DOCUMENT START_TAG a END_TAG a START_TAG a END_TAG a TEXT baz END_TAG b}

test pp-4.12 {find-element} {
    tdom::pullparser pp
    pp input {<doc>foo<a/>bar<b>grill<a/>baz</b></doc>}
    set result [pp state]
    pp find-element a
    lappend result [pp find-element a]; # START_TAG
    lappend result [pp tag]; #a 
    lappend result [pp next]; # END_TAG
    lappend result [pp tag]; # a 
    lappend result [pp next]; # TEXT 
    lappend result [pp text]; # baz 
    lappend result [pp next]; # END_TAG 
    lappend result [pp tag]; # b
    while {[pp next] ne "END_DOCUMENT"} {}
    pp delete
    set result
} {START_DOCUMENT START_TAG a END_TAG a TEXT baz END_TAG b}

test pp-4.13 {find-element} {
    tdom::pullparser pp
    pp input {<doc/>}
    set result [pp state]
    lappend result [pp find-element a]
    pp delete
    set result
} {START_DOCUMENT END_DOCUMENT}    

test pp-4.14 {find-element} {
    tdom::pullparser pp
    pp input {<doc>foo bar<e/><e>bar</e></doc>}
    set result [pp next]
    lappend result [pp skip]
    lappend result [pp tag]
    lappend result [pp find-element b]
    lappend result [catch {pp next} errMsg]
    lappend result $errMsg
    pp delete
    set result
} {START_TAG END_TAG doc END_DOCUMENT 1 {No next event after END_DOCUMENT}}
    
test pp-5.1 {CDATA section} {
    tdom::pullparser pp
    pp input {<doc><![CDATA[ some text  ]]></doc>}
    set result [pp state]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp text]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    
    pp delete
    set result
} {START_DOCUMENT START_TAG doc TEXT { some text  } END_TAG doc END_DOCUMENT}

test pp-5.2 {CDATA section inside of text} {
    tdom::pullparser pp
    pp input {<doc>before<![CDATA[ some text  ]]>after</doc>}
    set result [pp state]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp text]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    
    pp delete
    set result
} {START_DOCUMENT START_TAG doc TEXT {before some text  after} END_TAG doc END_DOCUMENT}

test pp-5.3 {CDATA section after text} {
    tdom::pullparser pp
    pp input {<doc>before<![CDATA[ some text  ]]></doc>}
    set result [pp state]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp text]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    
    pp delete
    set result
} {START_DOCUMENT START_TAG doc TEXT {before some text  } END_TAG doc END_DOCUMENT}

test pp-5.4 {CDATA section before text} {
    tdom::pullparser pp
    pp input {<doc><![CDATA[ some text  ]]>after</doc>}
    set result [pp state]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp text]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    
    pp delete
    set result
} {START_DOCUMENT START_TAG doc TEXT { some text  after} END_TAG doc END_DOCUMENT}

test pp-5.5 {White space only CDATA section inside text} {
    tdom::pullparser pp
    pp input {<doc>before <![CDATA[  ]]> after</doc>}
    set result [pp state]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp text]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    
    pp delete
    set result
} {START_DOCUMENT START_TAG doc TEXT {before    after} END_TAG doc END_DOCUMENT}

test pp-5.6 {White space only CDATA section inside text with -ignorewhitecdata} {
    tdom::pullparser pp -ignorewhitecdata
    pp input {<doc>before <![CDATA[  ]]> after</doc>}
    set result [pp state]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp text]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    
    pp delete
    set result
} {START_DOCUMENT START_TAG doc TEXT {before    after} END_TAG doc END_DOCUMENT}

test pp-5.6 {White space only CDATA section inside text with -ignorewhitecdata} {
    tdom::pullparser pp -ignorewhitecdata
    pp input {<doc>before <![CDATA[  ]]> after</doc>}
    set result [pp state]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp text]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    
    pp delete
    set result
} {START_DOCUMENT START_TAG doc TEXT {before    after} END_TAG doc END_DOCUMENT}

test pp-5.7 {White space only CDATA section inside white space only text w/ -ignorewhitecdata} {
    tdom::pullparser pp -ignorewhitecdata
    pp input {<doc> <![CDATA[  ]]>
        </doc>}
    set result [pp state]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    
    pp delete
    set result
} {START_DOCUMENT START_TAG doc END_TAG doc END_DOCUMENT}

test pp-5.8 {White space only CDATA section before text w/ -ignorewhitecdata} {
    tdom::pullparser pp -ignorewhitecdata
    pp input {<doc> <![CDATA[  ]]> after</doc>}
    set result [pp state]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp text]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    
    pp delete
    set result
} {START_DOCUMENT START_TAG doc TEXT {    after} END_TAG doc END_DOCUMENT}

test pp-5.9 {Successive CDATA sections} {
    tdom::pullparser pp
    pp input {<doc> <![CDATA[one]]><![CDATA[two]]><![CDATA[  ]]> after</doc>}
    set result [pp state]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    lappend result [pp text]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp next]
    
    pp delete
    set result
} {START_DOCUMENT START_TAG doc TEXT { onetwo   after} END_TAG doc END_DOCUMENT}

test pp-6.1 {line} {
    tdom::pullparser pp
    set result [catch {pp line}]
    pp input {<doc> <![CDATA[one]]><![CDATA[two]]><![CDATA[  ]]> after</doc>}
    lappend result [pp line]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp line]
    lappend result [pp next]
    lappend result [pp text]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp line]
    lappend result [pp next]
    lappend result [pp line]
    pp delete
    set result
} {1 0 START_TAG doc 1 TEXT { onetwo   after} END_TAG doc 1 END_DOCUMENT 1}

test pp-6.2 {column} {
    tdom::pullparser pp
    set result [catch {pp column}]
    pp input {<doc> <![CDATA[one]]><![CDATA[two]]><![CDATA[  ]]> after</doc>}
    lappend result [pp column]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp column]
    lappend result [pp next]
    lappend result [pp text]
    lappend result [pp next]
    lappend result [pp tag]
    lappend result [pp column]
    lappend result [pp next]
    lappend result [pp column]
    pp delete
    set result
} {1 0 START_TAG doc 5 TEXT { onetwo   after} END_TAG doc 62 END_DOCUMENT 62}

test pp-6.3 {column} {
    tdom::pullparser pp
    pp input {<doc>foo<b>bar</b>grill</doc>}
    set result [list]
    while {[pp next] ne "END_DOCUMENT"} {
        if {[pp state] eq "TEXT"} {
            lappend result [pp text]
        } else {
            lappend result [pp tag]
            lappend result [pp column]
        }
    }
    pp delete
    set result
} {doc 5 foo b 11 bar b 18 grill doc 29}

test pp-6.4 {line/column} {
    tdom::pullparser pp
    pp input {<doc>foo
<b>bar
</b>grill</doc>}
    set result [list]
    while {[pp next] ne "END_DOCUMENT"} {
        if {[pp state] eq "TEXT"} {
            lappend result [pp text]
        } else {
            lappend result [pp tag]
            lappend result [pp line]/[pp column]
        }
    }
    pp delete
    set result
} {doc 1/5 {foo
} b 2/3 {bar
} b 3/4 grill doc 3/15}

test pp-6.5 {column} {
    tdom::pullparser pp
    pp input {<doc att="attvalue">foo<b att="boo">bar</b>grill</doc>}
    set result [list]
    while {[pp next] ne "END_DOCUMENT"} {
        if {[pp state] eq "TEXT"} {
            lappend result [pp text]
        } else {
            lappend result [pp tag]
            lappend result [pp column]
        }
    }
    lappend result [pp column]
    pp delete
    set result
} {doc 20 foo b 36 bar b 43 grill doc 54 54}

test pp-6.6 {line/column after parsing error} {
    tdom::pullparser pp
    pp input {<doc>an
        < xml error </doc>}
    pp next
    set result [catch {pp skip}]
    lappend result [pp line]/[pp column]
    pp delete
    set result
} {1 2/9}
