--------------------------------------------------------------------------------
-- $Id: TestXml.hs,v 1.35 2004/07/13 17:32:29 graham Exp $
--
-- Copyright (c) 2004, G. KLYNE. All rights reserved.
-- See end of this file for licence information.
--------------------------------------------------------------------------------
-- |
-- Module : TestXml
-- Copyright : (c) 2004, Graham Klyne
-- License : LGPL V2
--
-- Maintainer : Graham Klyne
-- Stability : provisional
-- Portability : H98
--
-- This module contains test cases for XML parsing and XML handling libraries.
--
-- The test cases make reference to externally stored test data files.
--
-- The module is designed to be retargetable to alternative XML libraries
-- with reasonable effort: the main body of test cases is isolated from the
-- details of the XML library used.
--
--------------------------------------------------------------------------------
module Main where
import Text.XML.HaXml.Parse
( xmlParse'
)
import Text.XML.HaXml.SubstitutePE
( subIntParamEntities
)
import Text.XML.HaXml.SubstituteGEFilter
( subIntGenEntities
, subExtGenEntities
)
import Text.XML.HaXml.Validate
( validate
)
import Text.XML.HaXml.Namespace
( processNamespaces
)
import Text.XML.HaXml.XmlBase
( processXmlBase
)
import Text.XML.HaXml.XmlLang
( processXmlLang
)
import Text.XML.HaXml.Lex
( xmlLex
, xmlLexTextDecl
, xmlLexEntity
, Posn(..), testPosn
)
import Text.XML.HaXml.Traverse
( docReplaceContent
, docErrorContent
, xmlTreeElements
, xmlListElements
, xmlListTextContent
, filterSingle
, docContent
)
import Text.XML.HaXml.Pretty
( document
)
import Text.XML.HaXml.QName
( makeQN, showQN
)
import Text.XML.HaXml.Types
import HUnit
( Test(TestCase,TestList,TestLabel)
, Assertable(..)
, Assertion
, assertBool, assertEqual, assertString, assertFailure
, runTestTT, runTestText, putTextToHandle
)
import IO
( Handle, IOMode(WriteMode)
, openFile, hClose, hPutStr, hPutStrLn
)
import List
( (\\)
)
------------------------------------------------------------
-- XML handling interfaces
------------------------------------------------------------
--
-- Subsequent tests are based on these interfaces.
-- Re-implement these interfaces to use the XML package
-- under test.
--
doXmlLexOK :: String -> String -> Bool
doXmlLexOK filepath filedata = not $ null (xmlLex filepath filedata)
doXmlPreOK :: String -> String -> Bool
doXmlPreOK filepath filedata = not $ null $
(subIntParamEntities filepath . xmlLex filepath) filedata
doXmlParseOK :: String -> String -> Bool
doXmlParseOK filepath filedata =
either (const False) (const True) (xmlParse' filepath filedata)
doXmlParseFormat :: String -> String -> String
doXmlParseFormat filepath filedata =
either ("Error: "++) (show . document) (xmlParse' filepath filedata)
doXmlParseGESub :: String -> String -> String
doXmlParseGESub filepath filedata =
either ("Error: "++) (show . document . replaceContent) (xmlParse' filepath filedata)
where
replaceContent (Document p s e) = Document p s (docContent (subExtGenEntities s (CElem e)))
docContent [CElem e] = e
docContent [] = errElem "produced no output"
docContent _ = errElem "produced more than one output"
errElem err = Elem (makeQN "error") () [] [CErr err]
doXmlParseGESub1 :: String -> String -> String
doXmlParseGESub1 filepath filedata =
either ("Error: "++) (show . document . replaceContent) (xmlParse' filepath filedata)
where
replaceContent (Document p s e) =
processXmlLang .
processXmlBase .
processNamespaces $
Document p s (docContent (subExtGenEntities s (CElem e)))
docContent [CElem e] = e
docContent [] = errElem "produced no output"
docContent _ = errElem "produced more than one output"
errElem err = Elem (makeQN "error") () [] [CErr err]
doXmlValidate :: String -> String -> [String]
doXmlValidate filepath filedata =
either (return . ("Error: "++))
(doValidate . replaceContent) (xmlParse' filepath filedata)
where
replaceContent (Document p s e) = Document p s (docContent (subExtGenEntities s (CElem e)))
docContent [CElem e] = e
docContent [] = errElem "produced no output"
docContent _ = errElem "produced more than one output"
errElem err = Elem (makeQN "error") () [] [CErr err]
doValidate (Document (Prolog _ _ (Just dtd)) s e) = validate dtd e
doValidate _ = ["No DTD in document for validation"]
parseGESubDocument :: String -> String -> Document
parseGESubDocument filepath filedata =
subContent . either docErrorContent id $ (xmlParse' filepath filedata)
where
subContent doc@(Document p s e) =
docReplaceContent (subExtGenEntities s) doc
------------------------------------------------------------
-- Test case helpers
------------------------------------------------------------
testEq :: (Eq a, Show a) => String -> a -> a -> Test
testEq lab a1 a2 =
TestCase ( assertEqual ("testEq:"++lab) a1 a2 )
assertParseOK :: String -> Bool -> (Either String Document) -> Assertion
assertParseOK lab ok result =
if ok then assertEqual lab "OK" (either id (const "OK") result)
else assertEqual lab "error" (either (const "error") (const "OK") result)
assertValid :: String -> Bool -> [String] -> Assertion
assertValid lab ok [] =
assertEqual lab (if ok then [] else ["error"]) []
assertValid lab ok result =
assertEqual lab (if ok then [] else result) result
------------------------------------------------------------
-- XML test case functions
------------------------------------------------------------
testXmlLexOK :: String -> Bool -> String -> Test
testXmlLexOK lab ok filepath = TestCase $
do { -- putStrLn ("\nTest "++lab)
; s <- catch (readFile filepath) (error ("Failed reading file "++filepath))
; assertEqual lab ok (doXmlLexOK filepath s)
}
testXmlPreOK :: String -> Bool -> String -> Test
testXmlPreOK lab ok filepath = TestCase $
do { -- putStrLn ("\nTest "++lab)
; s <- catch (readFile filepath) (error ("Failed reading file "++filepath))
; assertEqual lab ok (doXmlPreOK filepath s)
}
testXmlParseOK :: String -> Bool -> String -> Test
testXmlParseOK lab ok filepath = TestCase $
do { -- putStrLn ("\nTest "++lab)
; s <- catch (readFile filepath) (error ("Failed reading file "++filepath))
; assertParseOK lab ok (xmlParse' filepath s)
}
testXmlFormat :: String -> String -> String -> Test
testXmlFormat lab filepathI filepathF = TestCase $
do { si <- readFile filepathI
-- ; writeFile (filepathF++".tmp") (doXmlParseFormat filepathI si)
; sf <- readFile filepathF
; assertEqual lab sf (doXmlParseFormat filepathI si)
}
-- Test substitution of General Entities
testXmlGESub :: String -> String -> String -> Test
testXmlGESub lab filepathI filepathF = TestCase $
do { si <- readFile filepathI
-- ; writeFile (filepathF++".tmp") (doXmlParseGESub filepathI si)
; sf <- readFile filepathF
; assertEqual lab sf (doXmlParseGESub filepathI si)
}
-- Test substitution of General Entities
testXmlGESub1 :: String -> String -> String -> Test
testXmlGESub1 lab filepathI filepathF = TestCase $
do { si <- readFile filepathI
-- ; writeFile (filepathF++".tmp") (doXmlParseGESub1 filepathI si)
; sf <- readFile filepathF
; assertEqual lab sf (doXmlParseGESub1 filepathI si)
}
-- Test validation following substitution of General Entities
testXmlValid :: String -> Bool -> String -> Test
testXmlValid lab ok filepathI = TestCase $
do { si <- readFile filepathI
-- ; writeFile (filepathF++".tmp") (doXmlValidate filepathI si)
; assertValid lab ok (doXmlValidate filepathI si)
}
-- Test namespace handling. This test works by namespace-processing a file,
-- building a list of QNames correspondingto the elements and attributes
-- within the file, and comparing that list with a supplied value.
testXmlQNames :: String -> String -> [QName] -> Test
testXmlQNames lab filepathI qns = TestCase $
do { si <- readFile filepathI
; let doc = parseGESubDocument filepathI si
; let docns = processNamespaces doc
; let docqns = concatMap elemQNs (xmlListElements docns)
; assertEqual lab qns docqns
}
where
elemQNs (CElem (Elem en _ ats _)) = en:(map attrQN ats)
elemQNs _ = []
attrQN (an,_) = an
egns, egns1, egns2 :: Namespace
egns = NS "eg" "http://id.example.org/namespace"
egns1 = NS "eg" "http://id.example.org/ns1"
egns2 = NS "eg" "http://id.example.org/ns2"
mknsQN :: Namespace -> String -> QName
mknsQN ns ln = QN ln (Just ns)
-- Test XML base. This works like the namespace test
-- (to confirm xml:base attributes are removed), but also
-- includes the xml:base QName for each element in the
-- resulting list.
testXmlBase :: String -> String -> [QName] -> Test
testXmlBase lab filepathI qns = TestCase $
do { si <- readFile filepathI
; let doc = parseGESubDocument filepathI si
; let docns = processNamespaces doc
; let docbas = processXmlBase docns
; let docqns = concatMap elemQNs (xmlListElements docbas)
; assertEqual lab qns docqns
}
where
elemQNs (CElem (Elem en ei ats _)) = en:baseQN ei:(map attrQN ats)
elemQNs _ = []
baseQN = makeQN . eiBase
attrQN (an,_) = an
egbas = NS "egbas" "http://id.example.org/"
-- Test XML language. This works like the namespace test
-- (to confirm xml:base attributes are removed), but also
-- includes an xml:lang-basedQName for each element in the
-- resulting list.
testXmlLang :: String -> String -> [QName] -> Test
testXmlLang lab filepathI qns = TestCase $
do { si <- readFile filepathI
; let doc = parseGESubDocument filepathI si
; let docns = processNamespaces doc
; let docbas = processXmlBase docns
; let doclng = processXmlLang docbas
; let docqns = concatMap elemQNs (xmlListElements doclng)
; assertEqual lab qns docqns
}
where
elemQNs (CElem (Elem en ei ats _)) = en:baseQN ei:langQN ei
:(map attrQN ats)
elemQNs _ = []
baseQN = makeQN . eiBase
langQN = makeQN . eiLang
attrQN (an,_) = an
-- Test attribute values.
-- Read, parse and namespace-process an XML file,
-- then list all attribute values, checking that each attribute
-- is a single string value.
testAttributes :: String -> String -> [String] -> Test
testAttributes lab filepathI qns = TestCase $
do { si <- readFile filepathI
; let doc = parseGESubDocument filepathI si
; let docns = processNamespaces doc
; let docqns = concatMap elemAttrs (xmlListElements docns)
; assertEqual lab qns docqns
}
where
elemAttrs (CElem (Elem en ei ats _)) = (map attrVal ats)
elemAttrs _ = []
attrVal (_,AttValue [Left av]) = av
attrVal (_,av) = "Bad attr: "++show av
-- Test free-text content
-- Read, parse and namespace-process an XML file,
-- then list all free-text values
testFreetext :: String -> String -> [String] -> Test
testFreetext lab filepathI qns = TestCase $
do { si <- readFile filepathI
; let doc = parseGESubDocument filepathI si
; let docns = processNamespaces doc
; let docqns = map elemText (xmlListTextContent docns)
; assertEqual lab qns docqns
}
where
elemText (CString _ txt) = txt
elemText (CRef (RefEntity ref)) = "&"++ref++";"
elemText (CRef (RefChar code)) = "&#"++show code++";"
-- Construct test suites from file and list of suffixes
makeTestXmlParseOK :: String -> Bool -> String -> [String] -> Test
makeTestXmlParseOK lab ok fileroot suffixes =
TestList [ testXmlParseOK (lab++s) ok (fileroot++s++".xml") | s <- suffixes ]
makeTestXmlValidOK :: String -> Bool -> String -> [String] -> Test
makeTestXmlValidOK lab ok fileroot suffixes =
TestList [ testXmlValid (lab++s) ok (fileroot++s++".xml") | s <- suffixes ]
------------------------------------------------------------
-- Basic XML parsing tests
------------------------------------------------------------
testXmlLex01 = testXmlLexOK "TestXmlLex01" True "9x9/xmlData01I.xml"
testXmlLex06 = testXmlPreOK "TestXmlLex06" True "9x9/xmlData06I.xml"
testXmlLex07 = testXmlPreOK "TestXmlLex07" True "9x9/xmlData07I.xml"
testXmlLex22 = testXmlPreOK "TestXmlLex22" True "9x9/xmlData22I.xml"
testXmlParse01 = testXmlParseOK "TestXmlParse01" True "9x9/xmlData01I.xml"
testXmlParse02 = testXmlParseOK "TestXmlParse02" True "9x9/xmlData02I.xml"
testXmlParse03 = testXmlParseOK "TestXmlParse03" False "9x9/xmlData03I.xml"
testXmlParse04 = testXmlParseOK "TestXmlParse04" False "9x9/xmlData04I.xml"
testXmlParse05 = testXmlParseOK "TestXmlParse05" False "9x9/xmlData05I.xml"
testXmlParse06 = testXmlParseOK "TestXmlParse06" False "9x9/xmlData06I.xml"
testXmlParse07 = testXmlParseOK "TestXmlParse07" True "9x9/xmlData07I.xml"
testXmlParse08 = testXmlParseOK "TestXmlParse08" True "9x9/xmlData08I.xml"
testXmlParse09 = testXmlParseOK "TestXmlParse09" False "9x9/xmlData09I.xml"
-- Internal subset tests
testXmlParse20 = testXmlParseOK "TestXmlParse20" True "9x9/KAoSOntologiesI.owl"
testXmlParse21 = testXmlParseOK "TestXmlParse21" True "9x9/xmlData21I.xml"
testXmlParse22 = testXmlParseOK "TestXmlParse22" True "9x9/xmlData22I.xml"
testXmlParse23 = testXmlParseOK "TestXmlParse23" True "9x9/xmlData23I.xml"
testXmlParse24 = testXmlParseOK "TestXmlParse24" True "9x9/xmlData24I.xml"
testXmlParse25 = testXmlParseOK "TestXmlParse25" True "9x9/xmlData25I.xml"
testXmlParse26 = testXmlParseOK "TestXmlParse26" True "9x9/xmlData26I.xml"
testXmlParse27 = testXmlParseOK "TestXmlParse27" True "9x9/xmlData27I.xml"
testXmlParse28 = testXmlParseOK "TestXmlParse28" True "9x9/xmlData28I.xml"
testXmlParse29 = testXmlParseOK "TestXmlParse29" True "9x9/xmlData29I.xml"
-- External subset tests
testXmlParse31 = testXmlParseOK "TestXmlParse31" True "9x9/xmlconf_xmltest_097I.xml"
-- This test requires Internet/HTTP access:
test32uri = "http://dev.w3.org/cvsweb/~checkout~/2001/XML-Test-Suite/xmlconf/xmltest/valid/sa/097.ent?rev=1.1&content-type=text/plain"
testXmlParse32 = testXmlParseOK "TestXmlParse32" True "9x9/xmlData32I.xml"
--
testXmlParse33 = testXmlParseOK "TestXmlParse33" True "9x9/xmlData33I.xml"
-- Check namespace tests parse OK
testXmlParse41 = testXmlParseOK "TestXmlParse41" True "9x9/xmlNamespace01.xml"
testXmlParse42 = testXmlParseOK "TestXmlParse42" True "9x9/xmlNamespace02.xml"
testXmlParse43 = testXmlParseOK "TestXmlParse43" True "9x9/xmlNamespace03.xml"
testXmlParse44 = testXmlParseOK "TestXmlParse44" True "9x9/xmlNamespace04.xml"
testXmlParse45 = testXmlParseOK "TestXmlParse45" True "9x9/xmlNamespace05.xml"
testXmlParse46 = testXmlParseOK "TestXmlParse46" True "9x9/xmlNamespace06.xml"
testXmlParse47 = testXmlParseOK "TestXmlParse47" True "9x9/xmlNamespace07.xml"
testXmlParse48 = testXmlParseOK "TestXmlParse48" True "9x9/xmlNamespace08.xml"
testXmlParse49 = testXmlParseOK "TestXmlParse49" True "9x9/xmlNamespace09.xml"
testXmlParse50 = testXmlParseOK "TestXmlParse50" True "9x9/simple.rdf"
testXmlFormat01 = testXmlFormat "TestXmlFormat01" "9x9/xmlData01I.xml" "9x9/xmlData01F.xml"
testXmlFormat02 = testXmlFormat "TestXmlFormat02" "9x9/xmlData02I.xml" "9x9/xmlData02F.xml"
testXmlFormat03 = testXmlFormat "TestXmlFormat03" "9x9/xmlData03I.xml" "9x9/xmlData03F.xml"
testXmlFormat04 = testXmlFormat "TestXmlFormat04" "9x9/xmlData04I.xml" "9x9/xmlData04F.xml"
testXmlFormat05 = testXmlFormat "TestXmlFormat05" "9x9/xmlData05I.xml" "9x9/xmlData05F.xml"
testXmlFormat06 = testXmlFormat "TestXmlFormat06" "9x9/xmlData06I.xml" "9x9/xmlData06F.xml"
testXmlFormat07 = testXmlFormat "TestXmlFormat07" "9x9/xmlData07I.xml" "9x9/xmlData07F.xml"
testXmlFormat08 = testXmlFormat "TestXmlFormat08" "9x9/xmlData08I.xml" "9x9/xmlData08F.xml"
testXmlFormat09 = testXmlFormat "TestXmlFormat09" "9x9/xmlData09I.xml" "9x9/xmlData09F.xml"
-- Internal subset tests
testXmlFormat20 = testXmlFormat "TestXmlFormat20" "9x9/KAoSOntologiesI.owl" "9x9/KAoSOntologiesF.owl"
testXmlFormat21 = testXmlFormat "TestXmlFormat21" "9x9/xmlData21I.xml" "9x9/xmlData21F.xml"
testXmlFormat22 = testXmlGESub "TestXmlFormat22" "9x9/xmlData22I.xml" "9x9/xmlData22F.xml"
testXmlFormat23 = testXmlGESub "TestXmlFormat23" "9x9/xmlData23I.xml" "9x9/xmlData23F.xml"
testXmlFormat24 = testXmlGESub "TestXmlFormat24" "9x9/xmlData24I.xml" "9x9/xmlData24F.xml"
testXmlFormat25 = testXmlGESub "TestXmlFormat25" "9x9/xmlData25I.xml" "9x9/xmlData25F.xml"
testXmlFormat26 = testXmlGESub "TestXmlFormat26" "9x9/xmlData26I.xml" "9x9/xmlData26F.xml"
testXmlFormat27 = testXmlGESub "TestXmlFormat27" "9x9/xmlData27I.xml" "9x9/xmlData27F.xml"
testXmlFormat28 = testXmlGESub "TestXmlFormat28" "9x9/xmlData28I.xml" "9x9/xmlData28F.xml"
testXmlFormat29 = testXmlGESub "TestXmlFormat29" "9x9/xmlData29I.xml" "9x9/xmlData29F.xml"
-- External subset tests
testXmlFormat31 = testXmlFormat "TestXmlFormat31" "9x9/xmlconf_xmltest_097I.xml" "9x9/xmlconf_xmltest_097F.xml"
testXmlFormat32 = testXmlFormat "TestXmlFormat32" "9x9/xmlData32I.xml" "9x9/xmlData32F.xml"
testXmlFormat33 = testXmlGESub "TestXmlFormat33" "9x9/xmlData33I.xml" "9x9/xmlData33F.xml"
-- Namespace tests
testXmlFormat41 = testXmlGESub "TestXmlFormat41" "9x9/xmlNamespace01.xml" "9x9/xmlNamespace01F.xml"
testXmlFormat42 = testXmlGESub "TestXmlFormat42" "9x9/xmlNamespace02.xml" "9x9/xmlNamespace02F.xml"
testXmlFormat43 = testXmlGESub "TestXmlFormat43" "9x9/xmlNamespace03.xml" "9x9/xmlNamespace03F.xml"
testXmlFormat44 = testXmlGESub "TestXmlFormat44" "9x9/xmlNamespace04.xml" "9x9/xmlNamespace04F.xml"
testXmlFormat45 = testXmlGESub "TestXmlFormat45" "9x9/xmlNamespace05.xml" "9x9/xmlNamespace05F.xml"
testXmlFormat46 = testXmlGESub "TestXmlFormat46" "9x9/xmlNamespace06.xml" "9x9/xmlNamespace06F.xml"
testXmlFormat47 = testXmlGESub "TestXmlFormat47" "9x9/xmlNamespace07.xml" "9x9/xmlNamespace07F.xml"
testXmlFormat48 = testXmlGESub "TestXmlFormat48" "9x9/xmlNamespace08.xml" "9x9/xmlNamespace08F.xml"
testXmlFormat49 = testXmlGESub "TestXmlFormat49" "9x9/xmlNamespace09.xml" "9x9/xmlNamespace09F.xml"
testXmlFormat50 = testXmlGESub "testXmlFormat50" "9x9/simple.rdf" "9x9/simpleF.rdf"
testXmlFormat51 = testXmlGESub1 "testXmlFormat51" "9x9/XmlBase01.xml" "9x9/XmlBase01F.xml"
testXmlFormat52 = testXmlGESub1 "testXmlFormat52" "9x9/XmlBase02.xml" "9x9/XmlBase02F.xml"
testXmlFormat53 = testXmlGESub1 "testXmlFormat53" "9x9/XmlBase03.xml" "9x9/XmlBase03F.xml"
testXmlFormat54 = testXmlGESub1 "testXmlFormat54" "9x9/XmlBase04.xml" "9x9/XmlBase04F.xml"
testXmlFormat61 = testXmlGESub1 "testXmlFormat61" "9x9/XmlLang01.xml" "9x9/XmlLang01F.xml"
testXmlFormat62 = testXmlGESub1 "testXmlFormat62" "9x9/XmlLang02.xml" "9x9/XmlLang02F.xml"
testXmlFormat63 = testXmlGESub1 "testXmlFormat63" "9x9/XmlLang03.xml" "9x9/XmlLang03F.xml"
testXmlFormat64 = testXmlGESub1 "testXmlFormat64" "9x9/XmlLang04.xml" "9x9/XmlLang04F.xml"
-- Validation tests
testXmlValid07 = testXmlValid "testXmlValid07" True "9x9/xmlData07I.xml"
testXmlValid21 = testXmlValid "testXmlValid21" True "9x9/xmlData21I.xml"
testXmlValid22 = testXmlValid "testXmlValid22" False "9x9/xmlData22I.xml"
testXmlValid23 = testXmlValid "testXmlValid23" False "9x9/xmlData23I.xml"
testXmlValid24 = testXmlValid "testXmlValid24" False "9x9/xmlData24I.xml"
testXmlValid25 = testXmlValid "testXmlValid25" True "9x9/xmlData25I.xml"
testXmlValid26 = testXmlValid "testXmlValid26" False "9x9/xmlData26I.xml"
testXmlValid27 = testXmlValid "testXmlValid27" False "9x9/xmlData27I.xml"
testXmlValid28 = testXmlValid "testXmlValid28" True "9x9/xmlData28I.xml"
testXmlValid29 = testXmlValid "testXmlValid29" True "9x9/xmlData29I.xml"
-- Namespace tests
testXmlNamespace01 = testXmlQNames "testXmlNamespace01" "9x9/xmlNamespace01.xml"
[ mknsQN egns "doc" ]
testXmlNamespace02 = testXmlQNames "testXmlNamespace02" "9x9/xmlNamespace02.xml"
[ makeQN "doc", mknsQN egns "a1" ]
testXmlNamespace03 = testXmlQNames "testXmlNamespace03" "9x9/xmlNamespace03.xml"
[ makeQN "doc"
, mknsQN egns "inner", mknsQN egns "a2"
, mknsQN egns "deeper", mknsQN egns "a3"
]
testXmlNamespace04 = testXmlQNames "testXmlNamespace04" "9x9/xmlNamespace04.xml"
[ mknsQN egns "doc"
, mknsQN egns "inner", makeQN "a2"
, mknsQN egns "deeper", makeQN "a3"
]
testXmlNamespace05 = testXmlQNames "testXmlNamespace05" "9x9/xmlNamespace05.xml"
[ mknsQN egns "doc"
, mknsQN egns "inner", mknsQN egns "a2"
, mknsQN egns "deeper", mknsQN egns "a3"
]
testXmlNamespace06 = testXmlQNames "testXmlNamespace06" "9x9/xmlNamespace06.xml"
[ mknsQN egns "doc"
, mknsQN egns "inner", mknsQN egns "a2"
, mknsQN egns "deeper", mknsQN egns "a3"
]
testXmlNamespace07 = testXmlQNames "testXmlNamespace07" "9x9/xmlNamespace07.xml"
[ mknsQN egns "doc"
, mknsQN egns "inner", mknsQN egns "a2"
, mknsQN egns "deeper", mknsQN egns "a3"
]
testXmlNamespace08 = testXmlQNames "testXmlNamespace08" "9x9/xmlNamespace08.xml"
[ mknsQN egns "doc"
, mknsQN egns1 "inner", mknsQN egns1 "a2"
, mknsQN egns2 "deeper", mknsQN egns2 "a3"
]
testXmlNamespace09 = testXmlQNames "testXmlNamespace09" "9x9/xmlNamespace09.xml"
[ mknsQN egns "doc"
, mknsQN egns1 "inner", mknsQN egns1 "a2"
]
-- xml:base tests
testXmlBase01 = testXmlBase "testXmlBase01" "9x9/XmlBase01.xml"
[ makeQN "doc", makeQN "9x9/XmlBase01.xml"
, mknsQN egns "inner", makeQN "9x9/XmlBase01.xml", mknsQN egns "a2"
, mknsQN egns "deeper", makeQN "9x9/XmlBase01.xml", mknsQN egns "a3"
]
testXmlBase02 = testXmlBase "testXmlBase02" "9x9/XmlBase02.xml"
[ makeQN "doc", mknsQN egbas "base1"
, mknsQN egns "inner", mknsQN egbas "base1", mknsQN egns "a2"
, mknsQN egns "deeper", mknsQN egbas "base1", mknsQN egns "a3"
]
testXmlBase03 = testXmlBase "testXmlBase03" "9x9/XmlBase03.xml"
[ makeQN "doc", makeQN "9x9/XmlBase03.xml"
, mknsQN egns "inner", mknsQN egbas "base1", mknsQN egns "a2"
, mknsQN egns "deeper", mknsQN egbas "base2", mknsQN egns "a3"
, mknsQN egns "evendeeper", mknsQN egbas "base2"
]
testXmlBase04 = testXmlBase "testXmlBase04" "9x9/XmlBase04.xml"
[ makeQN "doc", makeQN "9x9/XmlBase04.xml"
, mknsQN egns "inner", mknsQN egbas "base1", mknsQN egns "a2"
, mknsQN egns "deeper", mknsQN egbas "base2", mknsQN egns "a3"
, mknsQN egns "evendeeper", mknsQN egbas "base2"
, mknsQN egns "anotherdeeper", mknsQN egbas "base1"
]
-- xml:lang tests
testXmlLang01 = testXmlLang "testXmlLang01" "9x9/XmlLang01.xml"
[ makeQN "doc", makeQN "9x9/XmlLang01.xml", makeQN ""
, mknsQN egns "inner", makeQN "9x9/XmlLang01.xml", makeQN ""
, mknsQN egns "a2"
, mknsQN egns "deeper", makeQN "9x9/XmlLang01.xml", makeQN ""
, mknsQN egns "a3"
]
testXmlLang02 = testXmlLang "testXmlLang02" "9x9/XmlLang02.xml"
[ makeQN "doc", mknsQN egbas "base1", makeQN "en"
, mknsQN egns "inner", mknsQN egbas "base1", makeQN "en"
, mknsQN egns "a2"
, mknsQN egns "deeper", mknsQN egbas "base1", makeQN "en"
, mknsQN egns "a3"
]
testXmlLang03 = testXmlLang "testXmlLang03" "9x9/XmlLang03.xml"
[ makeQN "doc", makeQN "9x9/XmlLang03.xml", makeQN ""
, mknsQN egns "inner", mknsQN egbas "base1", makeQN "fr"
, mknsQN egns "a2"
, mknsQN egns "deeper", mknsQN egbas "base2", makeQN "de"
, mknsQN egns "a3"
, mknsQN egns "evendeeper", mknsQN egbas "base2", makeQN "de"
]
testXmlLang04 = testXmlLang "testXmlLang04" "9x9/XmlLang04.xml"
[ makeQN "doc", makeQN "9x9/XmlLang04.xml", makeQN ""
, mknsQN egns "inner", mknsQN egbas "base1", makeQN "fr"
, mknsQN egns "a2"
, mknsQN egns "deeper", mknsQN egbas "base2", makeQN "de"
, mknsQN egns "a3"
, mknsQN egns "evendeeper", mknsQN egbas "base2", makeQN "de"
, mknsQN egns "anotherdeeper", mknsQN egbas "base1", makeQN "fr"
, mknsQN egns "evendeeper", makeQN "", makeQN ""
]
-- Attribute-value tests
testXmlAttributes01 = testAttributes "testXmlAttributes01" "9x9/SchemaPart.rdf"
[ "Resource"
, "en"
, "fr"
, "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
, "en"
, "fr"
, "#Class"
, "subPropertyOf"
, "en"
, "fr"
, "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"
, "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"
]
-- Text-content-value tests
testXmlFreetext01 = testFreetext "testXmlFreetext01" "9x9/SchemaPart.rdf"
[ "Resource"
, "Ressource"
, "The most general class"
, "type"
, "type"
, "Indicates membership of a class"
, "subPropertyOf"
, "sousPropri\233\&t\233\&De"
, "Indicates specialization of properties"
]
-- Complete test suite
testXmlParseSuite = TestList
[ testXmlLex01
, testXmlLex06
, testXmlLex07
, testXmlLex22
, testXmlParse01
, testXmlParse02
, testXmlParse03
, testXmlParse04
, testXmlParse05
, testXmlParse06
, testXmlParse07
, testXmlParse08
, testXmlParse09
, testXmlParse20
, testXmlParse21
, testXmlParse22
, testXmlParse23
, testXmlParse24
, testXmlParse25
, testXmlParse26
, testXmlParse27
, testXmlParse28
, testXmlParse29
, testXmlParse31
-- , testXmlParse32 -- requires internet access, see below
, testXmlParse33
, testXmlParse41
, testXmlParse42
, testXmlParse43
, testXmlParse44
, testXmlParse45
, testXmlParse46
, testXmlParse47
, testXmlParse48
, testXmlParse49
, testXmlParse50
, testXmlFormat01
, testXmlFormat02
, testXmlFormat03
, testXmlFormat04
, testXmlFormat05
, testXmlFormat06
, testXmlFormat07
, testXmlFormat08
, testXmlFormat09
, testXmlFormat20
, testXmlFormat21
, testXmlFormat22
, testXmlFormat23
, testXmlFormat24
, testXmlFormat25
, testXmlFormat26
, testXmlFormat27
, testXmlFormat28
, testXmlFormat29
, testXmlFormat31
-- , testXmlFormat32 -- requires internet access, see below
, testXmlFormat33
, testXmlFormat41
, testXmlFormat42
, testXmlFormat43
, testXmlFormat44
, testXmlFormat45
, testXmlFormat46
, testXmlFormat47
, testXmlFormat48
, testXmlFormat49
, testXmlFormat50
, testXmlFormat51
, testXmlFormat52
, testXmlFormat53
, testXmlFormat54
, testXmlFormat61
, testXmlFormat62
, testXmlFormat63
, testXmlFormat64
, testXmlValid07
, testXmlValid21
, testXmlValid22
, testXmlValid23
, testXmlValid24
, testXmlValid25
, testXmlValid26
, testXmlValid27
, testXmlValid28
, testXmlValid29
, testXmlNamespace01
, testXmlNamespace02
, testXmlNamespace03
, testXmlNamespace04
, testXmlNamespace05
, testXmlNamespace06
, testXmlNamespace07
, testXmlNamespace08
, testXmlNamespace09
, testXmlBase01
, testXmlBase02
, testXmlBase03
, testXmlBase04
, testXmlLang01
, testXmlLang02
, testXmlLang03
, testXmlLang04
, testXmlAttributes01
, testXmlFreetext01
]
testXmlHTTPSuite = TestList
[ testXmlParse32 -- HTTP access test
, testXmlFormat32 -- HTTP access test
]
-- The following tests are designed to work with files from the
-- W3C XML test suite, which can be obtained from:
-- http://www.w3.org/XML/Test/
-- Retrieve the test suite archive and unpack the directory structure
-- into a directory from which the test program is run (I use the source
-- code directory: the archive has all its content in subdirectories).
--
-- The tests are generated from the 3-digit number that is used to form
-- the test suite filename in each case, with tests known not to work being
-- removed from the list. I expect these omissions to be removed as the
-- parser is refined.
--
-- Note: at this time, the "Valid" XML test suite is used only for testing
-- well-formedness chacks by the parser. Additional tests may perform validity
-- checking.
jamesClarkParseSASuite =
makeTestXmlParseOK "JamesClarkParseWFSA" True "xml-conformance/xmltest/valid/sa/"
( map (showNDigits 3) [1..119]
)
jamesClarkNotWfSASuite =
makeTestXmlParseOK "jamesClarkNotWfSA" False "xml-conformance/xmltest/not-wf/sa/"
( map (showNDigits 3) [1..186] \\
["006" -- comment containing '--'
,"014" -- Literal '<' in attribute value
,"025","026","029" -- content containing ']]>'
,"038" -- duplicate attr name (is XML WFC)
,"061","062","064","065","066","067","068","069" -- Missing spaces in DTD
,"070" -- <!-- ... --->
,"071","075","079","080" -- Mutually recursive entities
,"072","073","076","077","078" -- Entity not declared
,"074" -- Entity closes containing element
,"081","082" -- Attribute ref external entity
,"083","084" -- Entity reference unparsed entity
,"090" -- Char ref makes ill-formed content
,"092" -- Char ref makes ill-formed attribute
,"096" -- Missing space in ?XML PI
,"101" -- encoding name format
,"102" -- version number format
,"103" -- Char ref in entity makes ill-formed
,"113" -- Unused PE has ill-formed content
,"115","116","117","119","120" -- Char ref makes ill-formed ent value
,"133","134" -- Extra spaces between tokens
,"137" -- Missing space
,"140","141" -- Char ref makes bad element name
,"147" -- Whitespace before <?xml ... ?>
,"153" -- Entity gives invalid <?xml ... ?>
,"160","161" -- Violates use of PE in internal subset
,"162" -- Unused indirect PE has bad content
,"165" -- Missing space before %
,"180" -- Entity used before declaration: fix when processing entities
,"181","182" -- Entity value not "content" production: fix when processing entities
,"185" -- External entity in standalone document: fix when processing entities
,"186" -- Missing whitespace between attrs
]
)
jamesClarkValidSASuite =
makeTestXmlValidOK "JamesClarkValidSA" True "xml-conformance/xmltest/valid/sa/"
( map (showNDigits 3) [1..119]
)
showNDigits :: Int -> Int -> String
showNDigits places val = pad places (show val)
where
pad places str = replicate (places-length str) '0' ++ str
------------------------------------------------------------
-- All tests
------------------------------------------------------------
allTests = TestList
[ testXmlParseSuite
-- , testXmlHTTPSuite -- requires Internet/HTTP access
, jamesClarkParseSASuite
, jamesClarkNotWfSASuite
, jamesClarkValidSASuite
]
main = runTestTT allTests
nwf = runTestTT jamesClarkNotWfSASuite
check = runTestTT testXmlParseSuite
testValid s = makeTestXmlParseOK "JamesClarkValidSA" True "xml-conformance/xmltest/valid/sa/" [s]
runTestFile t = do
h <- openFile "a.tmp" WriteMode
runTestText (putTextToHandle h False) t
hClose h
tf = runTestFile
tt = runTestTT
xmlLexData :: String -> IO String
xmlLexData filepath =
do { s <- catch (readFile filepath) (error ("Failed reading file "++filepath))
; let l = xmlLex filepath s
; let r = show (length l) ++ "\n**\n" ++ concatMap ((++"\n") . show) l ++ "\n**\n"
; putStrLn r
; return r
}
xmlEntData :: String -> IO String
xmlEntData filepath =
do { s <- catch (readFile filepath) (error ("Failed reading file "++filepath))
; let l = xmlLexTextDecl filepath Nothing s
; let r = show (length l) ++ "\n**\n" ++ concatMap ((++"\n") . show) l ++ "\n**\n"
; putStrLn r
; return r
}
xmlPreData :: String -> String -> IO String
xmlPreData p f =
do { let filepath = p++f
; filedata <- catch (readFile filepath) (error ("Failed reading file "++filepath))
; let l = (subIntParamEntities filepath . xmlLex filepath) filedata
; let r = show (length l) ++ "\n**\n" ++ concatMap ((++"\n") . show) l ++ "\n**\n"
; putStrLn r
; return r
}
xmlSymData :: String -> String -> IO String
xmlSymData p f =
do { let filepath = p++f
; filedata <- catch (readFile filepath) (error ("Failed reading file "++filepath))
; let p = (xmlParse' filepath filedata)
; let r = case p of
(Left err) -> ("Error: "++err)
(Right (Document pro sym root)) ->
show (length sym) ++ "\n**\n" ++ concatMap ((++"\n") . showste) sym ++ "\n**\n"
; putStrLn r
; return r
}
where
showste (nam,entdef) = nam++": "++showent entdef++"\n"
showent (DefEntityValue (EntityValue evs)) = concatMap (("\n "++) . showev) evs
showent (DefExternalID bas eid _ ) = ("\n External base="++bas++", eid="++showeid eid)
showeid (SYSTEM (SystemLiteral uri)) = uri
showeid (PUBLIC _ (SystemLiteral uri)) = uri
showev (EVString str) = str
showev (EVRef (RefEntity nam)) = "&"++nam++";"
showev (EVRef (RefChar code)) = "&#"++show code++";"
xmlDocData :: String -> String -> IO String
xmlDocData p f =
do { let filepath = p++f
; filedata <- catch (readFile filepath) (error ("Failed reading file "++filepath))
; let p = (xmlParse' filepath filedata)
; let r = case p of
(Left err) -> ("Error: "++err)
(Right doc) -> (show . document) doc
; putStrLn r
; return r
}
xmlSubData :: String -> String -> IO String
xmlSubData p f =
do { let filepath = p++f
; filedata <- catch (readFile filepath) (error ("Failed reading file "++filepath))
; let p = (xmlParse' filepath filedata)
; let r = case p of
(Left err) -> ("Error: "++err)
(Right doc) -> (show . document) (subContent doc)
; putStrLn r
; return r
}
where
subContent doc@(Document _ s _) =
docReplaceContent (subExtGenEntities s) doc
validPath = "xml-conformance/xmltest/valid/sa/"
notwfPath = "xml-conformance/xmltest/not-wf/sa/"
localPath = ""
entdata = xmlEntData "9x9/xmlconf_xmltest_097.ent"
lexdata = xmlLexData "9x9/xmlData26I.xml"
predata = xmlPreData localPath "9x9/xmlNamespace05.xml"
symdata = xmlSymData localPath "9x9/xmlNamespace05.xml"
docdata = xmlDocData localPath "9x9/xmlNamespace05.xml"
subdata = xmlSubData localPath "9x9/xmlNamespace05.xml"
lexent = xmlLexEntity testPosn "abc &def; ghi %jkl; mno"
--------------------------------------------------------------------------------
--
-- Copyright (c) 2004, G. KLYNE. All rights reserved.
--
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 2.1 of the License, or (at your option) any later version.
--
-- This library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public
-- License along with this library; if not, write to:
-- The Free Software Foundation, Inc.,
-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-- or view the web page at:
-- http://www.gnu.org/copyleft/lesser.html
--
--------------------------------------------------------------------------------
-- $Source: /file/cvsdev/HaskellUtils/HaXml-1.12/test/TestXml.hs,v $
-- $Author: graham $
-- $Revision: 1.35 $
-- $Log: TestXml.hs,v $
-- Revision 1.35 2004/07/13 17:32:29 graham
-- Add xml:lang processing filter test cases. Fix some old test cases.
--
-- Revision 1.34 2004/07/12 22:20:09 graham
-- New XML parser test cases.
--
-- Revision 1.33 2004/07/06 21:09:28 graham
-- Add specific Show instances for Namespace and QName.
--
-- Revision 1.32 2004/06/28 20:20:21 graham
-- Added new test cases for recursive substutition detection, and
-- document reformatting after
-- namespace processing.
--
-- Revision 1.31 2004/06/28 20:15:54 graham
-- Reorganized general entity substitution logic to separate traversal from
-- substitution, reprocessing and recursive reprocessing logic.
-- Added detection of recursive entity substitution.
--
-- Revision 1.30 2004/06/24 17:48:36 graham
-- Include document filename/URI in parsed document prolog,
-- for subsequent use as a base URI.
--
-- Revision 1.29 2004/06/24 14:06:57 graham
-- Rearranged various lexing functions to be slightly less obscure in their usage.
-- Factored out common code from entity value and attribute value parsing as
-- a new function 'parseString'.
--
-- Revision 1.28 2004/06/22 14:38:53 graham
-- Basic namespace processing is working.
-- Some problems with attribute handling/normalization still to be fixed.
--
-- Revision 1.27 2004/06/18 15:27:46 graham
-- Validation test suote added. Minor validation bug fixed. All tests pass.
--
-- Revision 1.26 2004/06/17 17:20:37 graham
-- Substitution of external general entities tested.
--
-- Revision 1.25 2004/06/17 17:08:38 graham
-- Refactored SubstitutePE.hs into SubstitutePE.hs and EntityHelpers.hs,
-- so common functions can be shared between PE and GE substitution code.
--
-- Revision 1.24 2004/06/17 15:11:35 graham
-- Pass test cases for general entity substitution in attribute values.
--
-- Revision 1.23 2004/06/17 11:40:43 graham
-- Internal general entity substitution now passes all test cases.
--
-- Revision 1.22 2004/06/16 18:17:15 graham
-- Parameter entity and lexical phases re-worked to better support
-- general entity substitution.
-- Passes all but two tricky GE substitution
-- regression tests.
--
-- Revision 1.21 2004/06/15 20:01:39 graham
-- First steps of internal general entity substitution filter are working.
-- Some of the parsing has been re-worked to support this.
-- All regression tests still pass.
--
-- Revision 1.20 2004/06/09 10:30:26 graham
-- HTTP access to external entity tested.
--
-- Revision 1.19 2004/06/08 21:21:59 graham
-- Fixed up grammar for 'contentspec'. Another test case passes.
--
-- Revision 1.18 2004/06/08 20:20:11 graham
-- Relative filename handling for external entitities now works.
-- URI handling and HTTP access is coded, not fully tested.
--
-- Revision 1.17 2004/06/08 11:35:59 graham
-- External parameter entity substitution test passes.
--
-- Revision 1.16 2004/06/08 11:00:06 graham
-- Internal subset PE tests all pass.
-- NOTE changes from previous test cases:
-- PE definitions are stripped out by PE substitution processing,
-- Ill-formed content in unused PEs is not detected.
--
-- Revision 1.15 2004/06/08 10:42:50 graham
-- Parameter entity definition body submitted to full reLex when defined.
--
-- Revision 1.14 2004/06/07 16:42:28 graham
-- Substitution logic now compiles, but not yet built into PE handling code.
-- Two non-well-formed test cases now fail.
-- Not yet decided if they're important enough to fix.
--
-- Revision 1.13 2004/06/03 14:55:37 graham
-- Re-arrange parameter entity handling to distinguish internal subset usage
-- in the syntax, and to leave parameter entities un-substituted in the parse
-- tree. Test case testXmlFormat21 changes as a result.
--
-- Revision 1.12 2004/06/03 12:52:21 graham
-- First stage of parameter entity re-work:
-- limit recognition of PEs to designated places in syntax.
--
-- Revision 1.11 2004/06/03 10:44:55 graham
-- Modified Unicode module to return a null character when an invalid or
-- out-of-range UTF-8 sequence is encountered.
--
-- Revision 1.10 2004/06/02 19:34:18 graham
-- Various small XML conformance improvements.
--
-- Revision 1.9 2004/06/02 15:14:37 graham
-- Restricted characters allowed in public identifier literal
--
-- Revision 1.8 2004/06/02 13:49:18 graham
-- Fixed Lex.hs to reject illegal XML characters. This also fixes some
-- run-time failures occurring when documents containing
-- formfeed
-- characters are presented.
--
-- Revision 1.7 2004/06/02 11:00:43 graham
-- Fixed up some comments and code layout.
--
-- Revision 1.6 2004/06/02 08:39:05 graham
-- Re-worked handling of attribute values so that entitry references
-- can be recognized.
--
-- Revision 1.5 2004/05/28 15:28:16 graham
-- Improved conformance with XML, per conformance tests.
-- All but one of the xmltext/valid/sa tests now pass.
-- There are still several xmltext/not-wf/sa tests that are not detected as
-- incorrect XML, notably problems with attribute value handling.
--
-- Revision 1.4 2004/05/28 10:47:48 graham
-- Changed test harness to report error diagnostics on failure (foir debugging).
-- Fixed lexing problem for names beginning with ':' and '_'.
-- Two additional test cases (012,013) passed.
--
-- Revision 1.3 2004/05/25 21:29:48 graham
-- Refactored parser diagnostics handling.
-- Added new type classes to isolate token details.
-- All previous conformance tests still passed.
--
-- Revision 1.2 2004/05/24 12:42:37 graham
-- Create new module ExtEntity to isolate acess to external entity data.
-- Updated parse module to use this. All tests passed.
--
-- Revision 1.1 2004/05/24 11:54:03 graham
-- Add HaXml 1.12 to local CVS repository, prior to refactoring.
-- Added CVS tags to source files to help track changes.
--
|