diff --git a/examples/XSLT/mangle.cpp b/examples/XSLT/mangle.cpp index e6d1fd1a..2d787e2d 100755 --- a/examples/XSLT/mangle.cpp +++ b/examples/XSLT/mangle.cpp @@ -7,6 +7,7 @@ #include #include +#include #include void test_suite(int argc, const char* argv[]); @@ -44,6 +45,16 @@ int main(int argc, const char* argv[]) } // if ... document.normalize(); stylesheet->execute(document); + + std::cout << "==============" << std::endl; + + Arabica::XSLT::DOMSink output; + stylesheet->set_output(output); + + stylesheet->execute(document); + + Arabica::DOM::Node node = output.node(); + std::cout << node << std::endl; } catch(const std::runtime_error& ex) { diff --git a/include/XSLT/impl/xslt_stylesheet_compiler.hpp b/include/XSLT/impl/xslt_stylesheet_compiler.hpp index 923b58d2..74b4674a 100755 --- a/include/XSLT/impl/xslt_stylesheet_compiler.hpp +++ b/include/XSLT/impl/xslt_stylesheet_compiler.hpp @@ -76,7 +76,6 @@ public: return; } // if ... - throw SAX::SAXException("xsl:stylesheet does not allowed " + qName + " here."); } // startElement virtual void endElement(const std::string& namespaceURI, diff --git a/tests/XSLT/Makefile.am b/tests/XSLT/Makefile.am index 23d5c570..0a5307ba 100755 --- a/tests/XSLT/Makefile.am +++ b/tests/XSLT/Makefile.am @@ -11,7 +11,9 @@ LIBSILLY = ../CppUnit/libsillystring.la TESTLIBS = $(LIBARABICA) ../CppUnit/libcppunit.la test_sources = scope_test.hpp \ - xslt_test.hpp + xslt_test.hpp \ + xslt_test.cpp + xslt_test_SOURCES = main.cpp \ $(test_sources) diff --git a/tests/XSLT/main.cpp b/tests/XSLT/main.cpp index 300daeb5..b22de050 100755 --- a/tests/XSLT/main.cpp +++ b/tests/XSLT/main.cpp @@ -5,9 +5,6 @@ #include #include -#include -#include -#include /////////////////////////////////////////////// #include "../CppUnit/TestRunner.hpp" @@ -18,15 +15,18 @@ // #include "scope_test.hpp" #include "xslt_test.hpp" +/* typedef std::string string_type; typedef Arabica::default_string_adaptor string_adaptor; +*/ int main(int argc, const char* argv[]) { TestRunner runner; // runner.addTest("ScopeTest", ScopeTest_suite()); - + // Xalan supplied test cases +/* //runner.addTest("attribset", XSLTTest_suite("attribset")); runner.addTest("attribvaltemplate", XSLTTest_suite("attribvaltemplate")); runner.addTest("axes", XSLTTest_suite("axes")); @@ -38,7 +38,9 @@ int main(int argc, const char* argv[]) runner.addTest("expression", XSLTTest_suite("expression")); runner.addTest("extend", XSLTTest_suite("extend")); //runner.addTest("idkey", XSLTTest_suite("idkey")); +*/ runner.addTest("impincl", XSLTTest_suite("impincl")); +/* runner.addTest("lre", XSLTTest_suite("lre")); runner.addTest("match", XSLTTest_suite("match")); runner.addTest("math", XSLTTest_suite("math")); @@ -61,7 +63,47 @@ int main(int argc, const char* argv[]) runner.addTest("variable", XSLTTest_suite("variable")); runner.addTest("ver", XSLTTest_suite("ver")); runner.addTest("whitespace", XSLTTest_suite("whitespace")); - + + // MSFT supplied test cases + runner.addTest("AVTs", XSLTTest_suite("AVTs")); + //runner.addTest("AttributeSets", XSLTTest_suite("AttributeSets")); + runner.addTest("Attributes", XSLTTest_suite("Attributes")); + runner.addTest("BVTs", XSLTTest_suite("BVTs")); + runner.addTest("Comment", XSLTTest_suite("Comment")); + runner.addTest("Completeness", XSLTTest_suite("Completeness")); + runner.addTest("ConflictResolution", XSLTTest_suite("ConflictResolution")); + runner.addTest("Copying", XSLTTest_suite("Copying")); + runner.addTest("Elements", XSLTTest_suite("Elements")); +*/ + runner.addTest("Errors", XSLTTest_suite("Errors")); +/* + runner.addTest("Fallback", XSLTTest_suite("Fallback")); + runner.addTest("ForEach", XSLTTest_suite("ForEach")); + //runner.addTest("FormatNumber", XSLTTest_suite("FormatNumber")); + runner.addTest("ForwardComp", XSLTTest_suite("ForwardComp")); + runner.addTest("Import", XSLTTest_suite("Import")); + //runner.addTest("Keys", XSLTTest_suite("Keys")); + runner.addTest("Messages", XSLTTest_suite("Messages")); + runner.addTest("Miscellaneous", XSLTTest_suite("Miscellaneous")); + runner.addTest("Modes", XSLTTest_suite("Modes")); + runner.addTest("NamedTemplates", XSLTTest_suite("NamedTemplates")); + runner.addTest("Namespace", XSLTTest_suite("Namespace")); + runner.addTest("Namespace-alias", XSLTTest_suite("Namespace-alias")); + runner.addTest("Namespace_XPath", XSLTTest_suite("Namespace_XPath")); + //runner.addTest("Number", XSLTTest_suite("Number")); + runner.addTest("Output", XSLTTest_suite("Output")); + runner.addTest("ProcessingInstruction", XSLTTest_suite("ProcessingInstruction")); + runner.addTest("RTF", XSLTTest_suite("RTF")); + runner.addTest("Sorting", XSLTTest_suite("Sorting")); + runner.addTest("Stylesheet", XSLTTest_suite("Stylesheet")); + runner.addTest("Template", XSLTTest_suite("Template")); + runner.addTest("Text", XSLTTest_suite("Text")); + runner.addTest("Valueof", XSLTTest_suite("Valueof")); + runner.addTest("Variables", XSLTTest_suite("Variables")); + runner.addTest("Whitespaces", XSLTTest_suite("Whitespaces")); + runner.addTest("XSLTFunctions", XSLTTest_suite("XSLTFunctions")); +*/ + runner.run(argc, argv); return 77; diff --git a/tests/XSLT/testsuite/TESTS/arabica-expected-fails.xml b/tests/XSLT/testsuite/TESTS/arabica-expected-fails.xml index f09e446d..84ade238 100644 --- a/tests/XSLT/testsuite/TESTS/arabica-expected-fails.xml +++ b/tests/XSLT/testsuite/TESTS/arabica-expected-fails.xml @@ -150,4 +150,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/XSLT/xslt_test.cpp b/tests/XSLT/xslt_test.cpp new file mode 100755 index 00000000..33c06502 --- /dev/null +++ b/tests/XSLT/xslt_test.cpp @@ -0,0 +1,638 @@ +#ifndef XSLT_XSLT_TEST_HPP +#define XSLT_XSLT_TEST_HPP + +#include +#include +#include +#include +#include + +#include "../CppUnit/framework/Test.h" +#include "../CppUnit/framework/TestCase.h" +#include "../CppUnit/framework/TestSuite.h" + +//#include +//#include +//#include +//#include + +#ifdef ARABICA_WINDOWS +const std::string PATH_PREFIX="../tests/XSLT/testsuite/TESTS/"; +const std::string SEPERATOR = "/"; +#else +#include "test_path.hpp" +const std::string PATH_PREFIX=test_path; +const std::string SEPERATOR = "/"; +#endif + +Arabica::DOM::Document buildDOM(const std::string& filename) +{ + Arabica::SAX::InputSource is(filename); + Arabica::SAX2DOM::Parser parser; + parser.parse(is); + + Arabica::DOM::Document d = parser.getDocument(); + if(d != 0) + d.normalize(); + return d; +} // buildDOM + +Arabica::DOM::Document buildDOMFromString(const std::string& xml) +{ + std::stringstream ss; + ss << xml; + Arabica::SAX::InputSource is(ss); + + Arabica::SAX2DOM::Parser parser; + parser.parse(is); + + Arabica::DOM::Document d = parser.getDocument(); + if(d != 0) + d.normalize(); + return d; +} // buildDOMFromString + +std::string readFile(const std::string& filename) +{ + std::ifstream in(filename.c_str()); + std::string file = std::string(std::istreambuf_iterator(in), std::istreambuf_iterator()); + if((file[0] == (char)0xff) && (file[1] == (char)0xfe)) // UTF16 BOM + { + // this is absolutely not a sensible thing to do + // in this case, I know it's ok for the test data but in the general case don't even think about it + file.erase(0, 2); + for(std::string::size_type i = file.length() - 1; i != std::string::npos; i -= 2) + file.erase(i, 1); + } // if ... + if((file[0] == (char)0xef) && (file[1] == (char)0xbb) && (file[2] == (char)0xbf)) // UTF-8 BOM + file.erase(0, 3); + return file; +} // readFile + +std::string readFragment(const std::string& filename) +{ + std::string frag = readFile(filename); + if(frag.find("") + 2); + + return frag; +} // readFragment + +Arabica::XPath::NodeSet selectNodes(const std::string& path, const Arabica::DOM::Node& node) +{ + Arabica::XPath::XPath xpath; + return xpath.evaluate(path, node).asNodeSet(); +} // selectNodes + +Arabica::DOM::Node selectNode(const std::string& path, const Arabica::DOM::Node& node) +{ + return selectNodes(path, node)[0]; +} // selectNode + +std::string selectString(const std::string& path, const Arabica::DOM::Node& node) +{ + Arabica::XPath::XPath xpath; + return xpath.evaluate_expr(path, node).asString(); +} // selectString + +std::string make_path(const std::string& path, const std::string& filename) +{ + return PATH_PREFIX + path + SEPERATOR + filename; +} // make_path + +class SkipTest : public TestCase +{ +public: + SkipTest(const std::string& name, + const std::string& reason) : + TestCase(name), + reason_(reason) + { + } // SkipTest + +protected: + virtual void runTest() + { + throw SkipException(reason_); + } // runTest + +private: + std::string reason_; +}; // class SkipTest + +class CompileFailsTest : public TestCase +{ +public: + CompileFailsTest(const std::string& name, + const std::string& input_xslt, + const std::string& reason) : + TestCase(name), + input_xslt_(input_xslt), + reason_(reason) + { + } // CompileFailsTest + +protected: + virtual void runTest() + { + Arabica::XSLT::StylesheetCompiler compiler; + + Arabica::SAX::InputSource source(input_xslt_); + std::auto_ptr stylesheet = compiler.compile(source); + if(stylesheet.get() != 0) + assertImplementation(false, "Expected " + input_xslt_ + " not to compile. But it did :o"); + throw SkipException(reason_ + " : " + compiler.error()); + } // runTest + +private: + std::string input_xslt_; + std::string reason_; +}; // CompileFailsTest + +class RunFailsTest : public TestCase +{ +public: + RunFailsTest(const std::string& name, + const std::string& input_xml, + const std::string& input_xslt, + const std::string& reason) : + TestCase(name), + input_xml_(input_xml), + input_xslt_(input_xslt), + reason_(reason) + { + } // RunFailsTest + +protected: + virtual void runTest() + { + Arabica::XSLT::StylesheetCompiler compiler; + + Arabica::SAX::InputSource source(input_xslt_); + std::auto_ptr stylesheet = compiler.compile(source); + if(stylesheet.get() == 0) + assertImplementation(false, "Failed to compile " + input_xslt_ + " : " + compiler.error()); + + Arabica::XSLT::DOMSink output; + stylesheet->set_output(output); + + std::ostringstream errors; + stylesheet->set_error_output(errors); + + Arabica::DOM::Document document = buildDOM(input_xml_); + try { + stylesheet->execute(document); + } + catch(const std::exception& e) { + throw SkipException(reason_ + " : " + e.what()); + } + assertImplementation(false, "Expected " + input_xslt_ + " to fail to execute. But it did :o"); + } // runTest + +private: + std::string input_xml_; + std::string input_xslt_; + std::string reason_; +}; // RunFailsTest + +class ExecutionErrorTest : public TestCase +{ +public: + ExecutionErrorTest(const std::string& name, + const std::string& input_xml, + const std::string& input_xslt) : + TestCase(name), + input_xml_(input_xml), + input_xslt_(input_xslt) + { + } // ExecutionErrorTest + +protected: + virtual void runTest() + { + Arabica::XSLT::StylesheetCompiler compiler; + + Arabica::SAX::InputSource source(input_xslt_); + std::auto_ptr stylesheet = compiler.compile(source); + if(stylesheet.get() == 0) + return; + + Arabica::XSLT::DOMSink output; + stylesheet->set_output(output); + + std::ostringstream errors; + stylesheet->set_error_output(errors); + + Arabica::DOM::Document document = buildDOM(input_xml_); + try { + stylesheet->execute(document); + } + catch(const std::exception& e) { + return; + } + assertImplementation(false, "Marked in catalog.xml as an execution error, but actually ran."); + } // runTest + +private: + std::string input_xml_; + std::string input_xslt_; +}; // ExecutionErrorTest + +class CompareAsTextXSLTTest : public TestCase +{ +public: + CompareAsTextXSLTTest(const std::string& name, + const std::string& input_xml, + const std::string& input_xslt, + const std::string& output_xml) : + TestCase(name), + input_xml_(input_xml), + input_xslt_(input_xslt), + output_xml_(output_xml) + { + } // CompareAsTextXSLTTest + +protected: + virtual void runTest() + { + Arabica::XSLT::StylesheetCompiler compiler; + + Arabica::SAX::InputSource source(input_xslt_); + std::auto_ptr stylesheet = compiler.compile(source); + if(stylesheet.get() == 0) + assertImplementation(false, "Failed to compile " + input_xslt_ + " : " + compiler.error()); + + std::ostringstream xml_output; + Arabica::XSLT::StreamSink output(xml_output); + stylesheet->set_output(output); + + std::ostringstream errors; + stylesheet->set_error_output(errors); + + Arabica::DOM::Document document = buildDOM(input_xml_); + try { + stylesheet->execute(document); + } + catch(const std::exception& e) { + assertImplementation(false, "Failed to run " + input_xslt_ + " : " + e.what()); + } // catch + + std::string ref = readFile(output_xml_); + std::string out = xml_output.str(); + + if(ref == out) + return; + + std::string refs = trimXMLDecl(ref); + std::string outs = trimXMLDecl(out); + + if(refs == outs) + return; + + refs = stripWhitespace(refs); + outs = stripWhitespace(outs); + + if(refs == outs) + return; + + assertImplementation(false, "Expected text:\n" + ref + "\nbut got:\n" + out + "\n" + refs + "\nbut got:" + outs + "\n====="); + } // runTest + +private: + std::string stripWhitespace(const std::string& str) + { + std::string s = Arabica::text::normalize_whitespace >(str); + + std::string::size_type i = s.find("> "); + while(i != std::string::npos) + { + s.erase(i+1, 1); + i = s.find("> "); + } // while .. + + i = s.find(" <"); + while(i != std::string::npos) + { + s.erase(i, 1); + i = s.find(" <"); + } // while .. + + return s; + } // stripWhitespace + + std::string trimXMLDecl(const std::string& str) + { + if(str.find("") + 2); + } // trimXMLDecl + + std::string input_xml_; + std::string input_xslt_; + std::string output_xml_; +}; // class CompareAsTextXSLTTest + +class CompareAsXMLFragmentXSLTTest : public TestCase +{ +public: + CompareAsXMLFragmentXSLTTest(const std::string& name, + const std::string& input_xml, + const std::string& input_xslt, + const std::string& output_xml) : + TestCase(name), + input_xml_(input_xml), + input_xslt_(input_xslt), + output_xml_(output_xml) + { + } // + +protected: + virtual void runTest() + { + Arabica::XSLT::StylesheetCompiler compiler; + + Arabica::SAX::InputSource source(input_xslt_); + std::auto_ptr stylesheet = compiler.compile(source); + if(stylesheet.get() == 0) + assertImplementation(false, "Failed to compile " + input_xslt_ + " : " + compiler.error()); + + Arabica::XSLT::DOMSink output; + stylesheet->set_output(output); + + std::ostringstream errors; + stylesheet->set_error_output(errors); + + Arabica::DOM::Document document = buildDOM(input_xml_); + try { + stylesheet->execute(document); + } + catch(const std::exception& e) { + assertImplementation(false, "Failed to run " + input_xslt_ + " : " + e.what()); + } + + std::string refStr = "" + readFragment(output_xml_) + ""; + Arabica::DOM::Document refDoc = buildDOMFromString(refStr); + if(refDoc == 0) + assertImplementation(false, "Couldn't read " + output_xml_ + ". Perhaps it isn't well-formed XML?"); + Arabica::DOM::DocumentFragment ref = refDoc.createDocumentFragment(); + for(Arabica::DOM::Node n = refDoc.getDocumentElement().getFirstChild(); n != 0; n = refDoc.getDocumentElement().getFirstChild()) + ref.appendChild(n); + + Arabica::DOM::Node out = output.node(); + out.normalize(); + + std::string refs = docToString(ref); + std::string outs = docToString(out); + + if(refs == outs) + return; + + stripWhitespace(ref); + stripWhitespace(out); + std::string refs2 = docToString(ref); + std::string outs2 = docToString(out); + + if(refs2 == outs2) + return; + + assertImplementation(false, "Expected:\n" + refs + "\nbut got:\n" + outs); + } // runTest + + std::string docToString(Arabica::DOM::Node node) + { + std::ostringstream ss; + ss << node; + return Arabica::text::normalize_whitespace >(ss.str()); + } // docToString + + void stripWhitespace(Arabica::DOM::Node doc) + { + Arabica::XPath::NodeSet textNodes = selectNodes("//text()", doc); + for(int i = 0; i != textNodes.size(); ++i) + { + Arabica::DOM::Node t = textNodes[i]; + std::string text = t.getNodeValue(); + text = Arabica::text::normalize_whitespace >(text); + size_t index = text.find_first_of(" "); + while(index != std::string::npos) + { + text.replace(index, 1, ""); + index = text.find_first_of(" "); + } + t.setNodeValue(text); + } + } // stripWhitespace + + std::string input_xml_; + std::string input_xslt_; + std::string output_xml_; +}; // class CompareAsXMLFragment + +class StandardXSLTTest : public TestCase +{ +public: + StandardXSLTTest(const std::string& name, + const std::string& input_xml, + const std::string& input_xslt, + const std::string& output_xml) : + TestCase(name), + input_xml_(input_xml), + input_xslt_(input_xslt), + output_xml_(output_xml) + { + } // StandardXSLTTest + +protected: + virtual void runTest() + { + Arabica::XSLT::StylesheetCompiler compiler; + + Arabica::SAX::InputSource source(input_xslt_); + std::auto_ptr stylesheet = compiler.compile(source); + if(stylesheet.get() == 0) + assertImplementation(false, "Failed to compile " + input_xslt_ + " : " + compiler.error()); + + Arabica::XSLT::DOMSink output; + stylesheet->set_output(output); + + std::ostringstream errors; + stylesheet->set_error_output(errors); + + Arabica::DOM::Document document = buildDOM(input_xml_); + if(document == 0) + assertImplementation(false, "Couldn't read " + input_xml_ + ". Perhaps it isn't well-formed XML?"); + try { + stylesheet->execute(document); + } + catch(const std::exception& e) { + assertImplementation(false, "Failed to run " + input_xslt_ + " : " + e.what()); + } + + Arabica::DOM::Document ref = buildDOM(output_xml_); + if(ref == 0) + assertImplementation(false, "Couldn't read " + output_xml_ + ". Perhaps it isn't well-formed XML?"); + Arabica::DOM::Node out = output.node(); + out.normalize(); + + std::string refs = docToString(ref); + std::string outs = docToString(out); + + if(refs == outs) + return; + + stripWhitespace(ref); + stripWhitespace(out); + std::string refs2 = docToString(ref); + std::string outs2 = docToString(out); + + if(refs2 == outs2) + return; + + assertImplementation(false, "Expected:\n" + refs + "\nbut got:\n" + outs); + } // runTest + + std::string docToString(Arabica::DOM::Node node) + { + std::ostringstream ss; + ss << node; + std::string xml = Arabica::text::normalize_whitespace >(ss.str()); + if(xml.find(" ") == 0) + xml.replace(0, 22, ""); + return xml; + } // docToString + + void stripWhitespace(Arabica::DOM::Node doc) + { + Arabica::XPath::NodeSet textNodes = selectNodes("//text()", doc); + for(int i = 0; i != textNodes.size(); ++i) + { + Arabica::DOM::Node t = textNodes[i]; + std::string text = t.getNodeValue(); + text = Arabica::text::normalize_whitespace >(text); + size_t index = text.find_first_of(" "); + while(index != std::string::npos) + { + text.replace(index, 1, ""); + index = text.find_first_of(" "); + } + t.setNodeValue(text); + } + } // stripWhitespace + + std::string input_xml_; + std::string input_xslt_; + std::string output_xml_; +}; // class StandardXSLTTest + +class Expected +{ +public: + Expected() + { + Arabica::DOM::Document fail_doc = buildDOM(PATH_PREFIX + "arabica-expected-fails.xml"); + Arabica::XPath::NodeSet failcases = selectNodes("/test-suite/test-case", fail_doc); + for(int i = 0; i != failcases.size(); ++i) + { + std::string name = selectString("@id", failcases[i]); + std::string compiles = selectString("@compiles", failcases[i]); + std::string runs = selectString("@runs", failcases[i]); + std::string skip = selectString("@skip", failcases[i]); + std::string reason = selectString("@reason", failcases[i]); + std::string compare = selectString("@compare", failcases[i]); + + if(compiles == "no") + fails[name] = "compile"; + else if(runs == "no") + fails[name] = "run"; + else if(skip == "yes") + fails[name] = "skip"; + else if(compare == "text") + fails[name] = "text"; + else if(compare == "fragment") + fails[name] = "fragment"; + reasons[name] = reason; + } // for ... + } + + std::map& Fails() { return fails; } + std::map& Reasons() { return reasons; } + +private: + std::map fails; + std::map reasons; +}; + +static Expected expected; + +TestSuite* XSLTTest_suite(const std::string& path) +{ +//#define new ELEPHANTNEW +// using namespace elephant; +// LeakDetector leakDetector; +// MemoryMonitorHolder().Instance().AddObserver(&leakDetector); +// +// poo(); +// +// MemoryMonitorHolder().Instance().RemoveObserver(&leakDetector); +// LeakDisplayFunc leakDisplay(std::cout); +// std::for_each(leakDetector.begin(), leakDetector.end(), leakDisplay); +//#undef new + + static Arabica::DOM::Document catalog = buildDOM(PATH_PREFIX + "catalog.xml"); + + TestSuite *suiteOfTests = new TestSuite; + + Arabica::XPath::NodeSet tests = +// selectNodes("/test-suite/test-catalog/test-case[scenario/@operation='standard']", catalog); +// selectNodes("/test-suite/test-catalog/test-case[@id='boolean_boolean86']", catalog); + selectNodes("/test-suite/test-catalog/test-case[file-path='" + path + "']", catalog); + for(int i = 0; i != tests.size(); ++i) + { + std::string operation = selectString("scenario/@operation", tests[i]); + std::string name = selectString("@id", tests[i]); + std::string path = selectString("concat(../major-path, '" + SEPERATOR + "', file-path)", tests[i]); + std::string out_path = selectString("concat(../major-path, '" + SEPERATOR + "REF_OUT" + SEPERATOR + "', file-path)", tests[i]); + std::string input_xml = selectString(".//input-file[@role='principal-data']", tests[i]); + std::string input_xslt = selectString(".//input-file[@role='principal-stylesheet']", tests[i]); + std::string output_xml = selectString(".//output-file[@role='principal']", tests[i]); + + if(expected.Fails().find(name) == expected.Fails().end()) + { + if(operation == "execution-error") + suiteOfTests->addTest(new ExecutionErrorTest(name, + make_path(path, input_xml), + make_path(path, input_xslt))); + else + suiteOfTests->addTest(new StandardXSLTTest(name, + make_path(path, input_xml), + make_path(path, input_xslt), + make_path(out_path, output_xml))); + } + else if(expected.Fails()[name] == "compile") + suiteOfTests->addTest(new CompileFailsTest(name, + make_path(path, input_xslt), + expected.Reasons()[name])); + else if(expected.Fails()[name] == "run") + suiteOfTests->addTest(new RunFailsTest(name, + make_path(path, input_xml), + make_path(path, input_xslt), + expected.Reasons()[name])); + else if(expected.Fails()[name] == "skip") + suiteOfTests->addTest(new SkipTest(name, expected.Reasons()[name])); + else if(expected.Fails()[name] == "text") + suiteOfTests->addTest(new CompareAsTextXSLTTest(name, + make_path(path, input_xml), + make_path(path, input_xslt), + make_path(out_path, output_xml))); + else if(expected.Fails()[name] == "fragment") + suiteOfTests->addTest(new CompareAsXMLFragmentXSLTTest(name, + make_path(path, input_xml), + make_path(path, input_xslt), + make_path(out_path, output_xml))); + } // for ... + + return suiteOfTests; +} // XSLTTest_suite + +#endif diff --git a/tests/XSLT/xslt_test.hpp b/tests/XSLT/xslt_test.hpp index 2fe98d30..e71a44f7 100644 --- a/tests/XSLT/xslt_test.hpp +++ b/tests/XSLT/xslt_test.hpp @@ -1,440 +1,6 @@ #ifndef XSLT_XSLT_TEST_HPP #define XSLT_XSLT_TEST_HPP -#include -#include -#include -#include -#include - -//#include -//#include -//#include -//#include - -#ifdef ARABICA_WINDOWS -const std::string PATH_PREFIX="../tests/XSLT/testsuite/TESTS/"; -const std::string SEPERATOR = "/"; -#else -#include "test_path.hpp" -const std::string PATH_PREFIX=test_path; -const std::string SEPERATOR = "/"; -#endif - -Arabica::DOM::Document buildDOM(const std::string& filename) -{ - Arabica::SAX::InputSource is(filename); - Arabica::SAX2DOM::Parser parser; - parser.parse(is); - - Arabica::DOM::Document d = parser.getDocument(); - if(d != 0) - d.normalize(); - return d; -} // buildDOM - -std::string readFile(const std::string& filename) -{ - std::ifstream in(filename.c_str()); - return std::string(std::istreambuf_iterator(in), std::istreambuf_iterator()); -} // readFile - -Arabica::XPath::NodeSet selectNodes(const std::string& path, const Arabica::DOM::Node& node) -{ - Arabica::XPath::XPath xpath; - return xpath.evaluate(path, node).asNodeSet(); -} // selectNodes - -Arabica::DOM::Node selectNode(const std::string& path, const Arabica::DOM::Node& node) -{ - return selectNodes(path, node)[0]; -} // selectNode - -std::string selectString(const std::string& path, const Arabica::DOM::Node& node) -{ - Arabica::XPath::XPath xpath; - return xpath.evaluate_expr(path, node).asString(); -} // selectString - -std::string make_path(const std::string& path, const std::string& filename) -{ - return PATH_PREFIX + path + SEPERATOR + filename; -} // make_path - -class SkipTest : public TestCase -{ -public: - SkipTest(const std::string& name, - const std::string& reason) : - TestCase(name), - reason_(reason) - { - } // SkipTest - -protected: - virtual void runTest() - { - throw SkipException(reason_); - } // runTest - -private: - std::string reason_; -}; // class SkipTest - -class CompileFailsTest : public TestCase -{ -public: - CompileFailsTest(const std::string& name, - const std::string& input_xslt, - const std::string& reason) : - TestCase(name), - input_xslt_(input_xslt), - reason_(reason) - { - } // CompileFailsTest - -protected: - virtual void runTest() - { - Arabica::XSLT::StylesheetCompiler compiler; - - Arabica::SAX::InputSource source(input_xslt_); - std::auto_ptr stylesheet = compiler.compile(source); - if(stylesheet.get() != 0) - assertImplementation(false, "Expected " + input_xslt_ + " not to compile. But it did :o"); - throw SkipException(reason_ + " : " + compiler.error()); - } // runTest - -private: - std::string input_xslt_; - std::string reason_; -}; // CompileFailsTest - -class RunFailsTest : public TestCase -{ -public: - RunFailsTest(const std::string& name, - const std::string& input_xml, - const std::string& input_xslt, - const std::string& reason) : - TestCase(name), - input_xml_(input_xml), - input_xslt_(input_xslt), - reason_(reason) - { - } // RunFailsTest - -protected: - virtual void runTest() - { - Arabica::XSLT::StylesheetCompiler compiler; - - Arabica::SAX::InputSource source(input_xslt_); - std::auto_ptr stylesheet = compiler.compile(source); - if(stylesheet.get() == 0) - assertImplementation(false, "Failed to compile " + input_xslt_ + " : " + compiler.error()); - - Arabica::XSLT::DOMSink output; - stylesheet->set_output(output); - - std::ostringstream errors; - stylesheet->set_error_output(errors); - - Arabica::DOM::Document document = buildDOM(input_xml_); - try { - stylesheet->execute(document); - } - catch(const std::exception& e) { - throw SkipException(reason_ + " : " + e.what()); - } - assertImplementation(false, "Expected " + input_xslt_ + " to fail to execute. But it did :o"); - } // runTest - -private: - std::string input_xml_; - std::string input_xslt_; - std::string reason_; -}; // RunFailsTest - -class CompareAsTextXSLTTest : public TestCase -{ -public: - CompareAsTextXSLTTest(const std::string& name, - const std::string& input_xml, - const std::string& input_xslt, - const std::string& output_xml) : - TestCase(name), - input_xml_(input_xml), - input_xslt_(input_xslt), - output_xml_(output_xml) - { - } // CompareAsTextXSLTTest - -protected: - virtual void runTest() - { - Arabica::XSLT::StylesheetCompiler compiler; - - Arabica::SAX::InputSource source(input_xslt_); - std::auto_ptr stylesheet = compiler.compile(source); - if(stylesheet.get() == 0) - assertImplementation(false, "Failed to compile " + input_xslt_ + " : " + compiler.error()); - - std::ostringstream xml_output; - Arabica::XSLT::StreamSink output(xml_output); - stylesheet->set_output(output); - - std::ostringstream errors; - stylesheet->set_error_output(errors); - - Arabica::DOM::Document document = buildDOM(input_xml_); - try { - stylesheet->execute(document); - } - catch(const std::exception& e) { - assertImplementation(false, "Failed to run " + input_xslt_ + " : " + e.what()); - } // catch - - std::string ref = readFile(output_xml_); - std::string out = xml_output.str(); - - if(ref == out) - return; - - std::string refs = trimXMLDecl(ref); - std::string outs = trimXMLDecl(out); - - if(refs == outs) - return; - - refs = stripWhitespace(refs); - outs = stripWhitespace(outs); - - if(refs == outs) - return; - - assertImplementation(false, "Expected text:\n" + ref + "\nbut got:\n" + out + "\n" + refs + "\nbut got:" + outs + "\n====="); - } // runTest - -private: - std::string stripWhitespace(const std::string& str) - { - std::string s = Arabica::text::normalize_whitespace >(str); - - std::string::size_type i = s.find("> "); - while(i != std::string::npos) - { - s.erase(i+1, 1); - i = s.find("> "); - } // while .. - - i = s.find(" <"); - while(i != std::string::npos) - { - s.erase(i, 1); - i = s.find(" <"); - } // while .. - - return s; - } // stripWhitespace - - std::string trimXMLDecl(const std::string& str) - { - if(str.find("") + 2); - } // trimXMLDecl - - std::string input_xml_; - std::string input_xslt_; - std::string output_xml_; -}; // class CompareAsTextXSLTTest - -class StandardXSLTTest : public TestCase -{ -public: - StandardXSLTTest(const std::string& name, - const std::string& input_xml, - const std::string& input_xslt, - const std::string& output_xml) : - TestCase(name), - input_xml_(input_xml), - input_xslt_(input_xslt), - output_xml_(output_xml) - { - } // StandardXSLTTest - -protected: - virtual void runTest() - { - Arabica::XSLT::StylesheetCompiler compiler; - - Arabica::SAX::InputSource source(input_xslt_); - std::auto_ptr stylesheet = compiler.compile(source); - if(stylesheet.get() == 0) - assertImplementation(false, "Failed to compile " + input_xslt_ + " : " + compiler.error()); - - Arabica::XSLT::DOMSink output; - stylesheet->set_output(output); - - std::ostringstream errors; - stylesheet->set_error_output(errors); - - Arabica::DOM::Document document = buildDOM(input_xml_); - try { - stylesheet->execute(document); - } - catch(const std::exception& e) { - assertImplementation(false, "Failed to run " + input_xslt_ + " : " + e.what()); - } - - Arabica::DOM::Document ref = buildDOM(output_xml_); - if(ref == 0) - assertImplementation(false, "Couldn't read " + output_xml_ + ". Perhaps it isn't well-formed XML?"); - Arabica::DOM::Node out = output.node(); - out.normalize(); - - std::string refs = docToString(ref.getFirstChild()); - std::string outs = docToString(out.getFirstChild()); - - if(refs == outs) - return; - - stripWhitespace(ref); - stripWhitespace(out); - std::string refs2 = docToString(ref.getFirstChild()); - std::string outs2 = docToString(out.getFirstChild()); - - if(refs2 == outs2) - return; - - assertImplementation(false, "Expected:\n" + refs + "\nbut got:\n" + outs); - } // runTest - - std::string docToString(Arabica::DOM::Node node) - { - std::ostringstream ss; - ss << node; - return Arabica::text::normalize_whitespace >(ss.str()); - } // docToString - - void stripWhitespace(Arabica::DOM::Node doc) - { - Arabica::XPath::NodeSet textNodes = selectNodes("//text()", doc); - for(int i = 0; i != textNodes.size(); ++i) - { - Arabica::DOM::Node t = textNodes[i]; - std::string text = t.getNodeValue(); - text = Arabica::text::normalize_whitespace >(text); - size_t index = text.find_first_of(" "); - while(index != std::string::npos) - { - text.replace(index, 1, ""); - index = text.find_first_of(" "); - } - t.setNodeValue(text); - } - } // stripWhitespace - - std::string input_xml_; - std::string input_xslt_; - std::string output_xml_; -}; // class StandardXSLTTest - -class Expected -{ -public: - Expected() - { - Arabica::DOM::Document fail_doc = buildDOM(PATH_PREFIX + "arabica-expected-fails.xml"); - Arabica::XPath::NodeSet failcases = selectNodes("/test-suite/test-case", fail_doc); - for(int i = 0; i != failcases.size(); ++i) - { - std::string name = selectString("@id", failcases[i]); - std::string compiles = selectString("@compiles", failcases[i]); - std::string runs = selectString("@runs", failcases[i]); - std::string skip = selectString("@skip", failcases[i]); - std::string reason = selectString("@reason", failcases[i]); - std::string compare = selectString("@compare", failcases[i]); - - if(compiles == "no") - fails[name] = "compile"; - else if(runs == "no") - fails[name] = "run"; - else if(skip == "yes") - fails[name] = "skip"; - else if(compare == "text") - fails[name] = "text"; - reasons[name] = reason; - } // for ... - } - - std::map& Fails() { return fails; } - std::map& Reasons() { return reasons; } - -private: - std::map fails; - std::map reasons; -}; - -static Expected expected; - -TestSuite* XSLTTest_suite(const std::string& path) -{ -//#define new ELEPHANTNEW -// using namespace elephant; -// LeakDetector leakDetector; -// MemoryMonitorHolder().Instance().AddObserver(&leakDetector); -// -// poo(); -// -// MemoryMonitorHolder().Instance().RemoveObserver(&leakDetector); -// LeakDisplayFunc leakDisplay(std::cout); -// std::for_each(leakDetector.begin(), leakDetector.end(), leakDisplay); -//#undef new - - static Arabica::DOM::Document catalog = buildDOM(PATH_PREFIX + "catalog.xml"); - - TestSuite *suiteOfTests = new TestSuite; - - Arabica::XPath::NodeSet tests = -// selectNodes("/test-suite/test-catalog/test-case[scenario/@operation='standard']", catalog); -// selectNodes("/test-suite/test-catalog/test-case[@id='boolean_boolean86']", catalog); - selectNodes("/test-suite/test-catalog/test-case[scenario/@operation='standard' and file-path='" + path + "']", catalog); - for(int i = 0; i != tests.size(); ++i) - { - std::string name = selectString("@id", tests[i]); - std::string path = selectString("concat(../major-path, '" + SEPERATOR + "', file-path)", tests[i]); - std::string out_path = selectString("concat(../major-path, '" + SEPERATOR + "REF_OUT" + SEPERATOR + "', file-path)", tests[i]); - std::string input_xml = selectString(".//input-file[@role='principal-data']", tests[i]); - std::string input_xslt = selectString(".//input-file[@role='principal-stylesheet']", tests[i]); - std::string output_xml = selectString(".//output-file[@role='principal']", tests[i]); - - if(expected.Fails().find(name) == expected.Fails().end()) - suiteOfTests->addTest(new StandardXSLTTest(name, - make_path(path, input_xml), - make_path(path, input_xslt), - make_path(out_path, output_xml))); - else if(expected.Fails()[name] == "compile") - suiteOfTests->addTest(new CompileFailsTest(name, - make_path(path, input_xslt), - expected.Reasons()[name])); - else if(expected.Fails()[name] == "run") - suiteOfTests->addTest(new RunFailsTest(name, - make_path(path, input_xml), - make_path(path, input_xslt), - expected.Reasons()[name])); - else if(expected.Fails()[name] == "skip") - suiteOfTests->addTest(new SkipTest(name, expected.Reasons()[name])); - else if(expected.Fails()[name] == "text") - suiteOfTests->addTest(new CompareAsTextXSLTTest(name, - make_path(path, input_xml), - make_path(path, input_xslt), - make_path(out_path, output_xml))); - } // for ... - - return suiteOfTests; -} // XSLTTest_suitoo +TestSuite* XSLTTest_suite(const std::string& path); #endif