From e4e3c57e4607b6ec9903e3bd67e643cf43f13562 Mon Sep 17 00:00:00 2001 From: jsdelfino Date: Sat, 26 Sep 2009 21:31:32 +0000 Subject: Added some test cases, util functions to read/write XML and a command line test program to help validate SCDL against the schemas. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@819221 13f79535-47bb-0310-9956-ffa450edef68 --- cpp/etc/git-exclude | 3 + cpp/sca/configure.ac | 1 + cpp/sca/runtime/core/Makefile.am | 2 +- cpp/sca/runtime/core/src/tuscany/xml.hpp | 385 ++++++++++++++++++++ cpp/sca/runtime/core/test/Makefile.am | 11 +- cpp/sca/runtime/core/test/tuscany/core-test.cpp | 444 ++++++++++++++++++++++++ cpp/sca/runtime/core/test/tuscany/xml-test.cpp | 104 ++++++ 7 files changed, 948 insertions(+), 2 deletions(-) create mode 100644 cpp/sca/runtime/core/src/tuscany/xml.hpp create mode 100644 cpp/sca/runtime/core/test/tuscany/core-test.cpp create mode 100644 cpp/sca/runtime/core/test/tuscany/xml-test.cpp diff --git a/cpp/etc/git-exclude b/cpp/etc/git-exclude index fc8102f696..dd9e85e738 100644 --- a/cpp/etc/git-exclude +++ b/cpp/etc/git-exclude @@ -63,4 +63,7 @@ account_client calculator_client sdo_misc store-test +store2-test +core-test +xml-test diff --git a/cpp/sca/configure.ac b/cpp/sca/configure.ac index 4daeef1985..7cb2e76a50 100644 --- a/cpp/sca/configure.ac +++ b/cpp/sca/configure.ac @@ -258,6 +258,7 @@ AC_CONFIG_FILES([Makefile runtime/Makefile runtime/core/Makefile runtime/core/src/Makefile + runtime/core/test/Makefile runtime/extensions/Makefile runtime/extensions/cpp/Makefile runtime/extensions/cpp/src/Makefile diff --git a/cpp/sca/runtime/core/Makefile.am b/cpp/sca/runtime/core/Makefile.am index 75797d6490..f833a2cb08 100644 --- a/cpp/sca/runtime/core/Makefile.am +++ b/cpp/sca/runtime/core/Makefile.am @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -SUBDIRS = src +SUBDIRS = src test nobase_data_DATA = xsd/*.* EXTRA_DIST = xsd diff --git a/cpp/sca/runtime/core/src/tuscany/xml.hpp b/cpp/sca/runtime/core/src/tuscany/xml.hpp new file mode 100644 index 0000000000..b4a3b87ad1 --- /dev/null +++ b/cpp/sca/runtime/core/src/tuscany/xml.hpp @@ -0,0 +1,385 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + +#ifndef tuscany_xml_hpp +#define tuscany_xml_hpp + +/** + * XML read/write functions. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "list.hpp" + +namespace tuscany { + +/** + * Encapsulates a libxml2 xmlTextReader and its state. + */ +class XmlReader { +public: + enum TokenType { + None = 0, Element = 1, Attribute = 2, EndElement = 15, Identifier = 100, Text = 101, End = 103 + }; + + explicit XmlReader(xmlTextReaderPtr xml) : xml(xml), tokenType(None) { + xmlTextReaderSetParserProp(xml, XML_PARSER_DEFAULTATTRS, 1); + xmlTextReaderSetParserProp(xml, XML_PARSER_SUBST_ENTITIES, 1); + } + + ~XmlReader() { + xmlFreeTextReader(xml); + } + + /** + * Read the next token and return its type. + */ + int read() { + if (tokenType == End) + return tokenType; + if (tokenType == Element) { + isEmptyElement = xmlTextReaderIsEmptyElement(xml); + hasValue = xmlTextReaderHasValue(xml); + hasAttributes = xmlTextReaderHasAttributes(xml); + return tokenType = Identifier; + } + if (hasValue && tokenType == Identifier) + return tokenType = Text; + if (hasAttributes && (tokenType == Identifier || tokenType == Text) && xmlTextReaderMoveToFirstAttribute(xml) == 1) + return tokenType = Attribute; + if (tokenType == Attribute && xmlTextReaderMoveToNextAttribute(xml) == 1) + return tokenType = Attribute; + if (isEmptyElement && (tokenType == Identifier || tokenType == Text || tokenType == Attribute)) + return tokenType = EndElement; + if (!xmlTextReaderRead(xml)) + return tokenType = End; + return tokenType = xmlTextReaderNodeType(xml); + } + + operator xmlTextReaderPtr() const { + return xml; + } + +private: + const xmlTextReaderPtr xml; + int tokenType; + bool isEmptyElement; + bool hasValue; + bool hasAttributes; +}; + +/** + * Constants used to tag XML tokens. + */ +const value endElement("<"); +const value startElement(">"); +const value attribute("attribute"); +const value element("element"); + +/** + * Read an XML identifier. + */ +const value readIdentifier(XmlReader& reader) { + const char* name = (const char*)xmlTextReaderConstName(reader); + return value(name); +} + +/** + * Read XML text. + */ +const value readText(XmlReader& reader) { + const char *val = (const char*)xmlTextReaderConstValue(reader); + return value(std::string(val)); +} + +/** + * Read an XML attribute. + */ +const value readAttribute(XmlReader& reader) { + const char *name = (const char*)xmlTextReaderConstName(reader); + const char *val = (const char*)xmlTextReaderConstValue(reader); + return value(makeList(attribute, value(name), value(std::string(val)))); +} + +/** + * Read an XML token. + */ +const value readToken(XmlReader& reader) { + const int tokenType = reader.read(); + if (tokenType == XmlReader::End) + return value(); + if (tokenType == XmlReader::Element) + return startElement; + if (tokenType == XmlReader::Identifier) + return readIdentifier(reader); + if (tokenType == XmlReader::Attribute) + return readAttribute(reader); + if (tokenType == XmlReader::Text) + return readText(reader); + if (tokenType == XmlReader::EndElement) + return endElement; + return readToken(reader); +} + +/** + * Read a list of XML tokens. + */ +const list readList(const list& listSoFar, XmlReader& reader) { + const value token = readToken(reader); + if(isNil(token) || endElement == token) + return reverse(listSoFar); + if(startElement == token) + return readList(cons(value(readList(makeList(element), reader)), listSoFar), reader); + return readList(cons(token, listSoFar), reader); +} + +/** + * Read an XML document from a libxml2 XML reader. + */ +const list read(XmlReader& reader) { + value nextToken = readToken(reader); + if (startElement == nextToken) + return makeList(value(readList(makeList(element), reader))); + return list(); +} + +/** + * Callback function called by libxml2 to read the XML input stream. + */ +int readCallback(void *context, char* buffer, int len) { + std::istream* is = static_cast(context); + is->read(buffer, len); + if (!is->eof() && (is->fail() || is->bad())) + return -1; + const int n = is->gcount(); + return n; +} + +/** + * Read an XML document from an input stream. + */ +const list readXML(std::istream& is) { + xmlTextReaderPtr xml = xmlReaderForIO(readCallback, NULL, &is, NULL, NULL, XML_PARSE_NONET); + if (xml == NULL) + return list(); + XmlReader reader(xml); + return read(reader); +} + +/** + * Callback function called by libxml2 to read the XML file input stream. + */ +int readFileCallback(void *context, char* buffer, int len) { + std::ifstream* is = static_cast(context); + is->read(buffer, len); + if (is->fail() || is->bad()) + return -1; + return is->gcount(); +} + +/** + * Callback function called by libxml2 to close the XML file input stream. + */ +int readCloseFileCallback(void *context) { + std::ifstream* fis = static_cast(context); + fis->close(); + return 0; +} + +/** + * Read an XML document from a file input stream. + */ +const list readXML(std::ifstream& is) { + xmlTextReaderPtr xml = xmlReaderForIO(readFileCallback, readCloseFileCallback, &is, NULL, NULL, XML_PARSE_NONET); + if (xml == NULL) + return list(); + XmlReader reader(xml); + return read(reader); +} + +/** + * Returns true if a value is an XML attribute. + */ +const bool isAttribute(const list& l) { + return !isNil(l) && car(l) == attribute; +} + +/** + * Returns the name of an XML attribute. + */ +const std::string attributeName(const list& l) { + return cadr(l); +} + +/** + * Returns the text value of an XML attribute. + */ +const std::string attributeText(const list& l) { + return caddr(l); +} + +/** + * Returns true if a value is an XML element. + */ +const bool isElement(const list& l) { + return !isNil(l) && car(l) == element; +} + +/** + * Returns the name of an XML element. + */ +const std::string elementName(const list& l) { + return cadr(l); +} + +/** + * Returns true if an XML element contains text content. + */ +const bool elementHasText(const list& l) { + if (isNil(cddr(l))) + return false; + return isString(caddr(l)); +} + +/** + * Returns the text content of an XML element. + */ +const std::string elementText(const list& l) { + return caddr(l); +} + +/** + * Returns the children of an XML element. + */ +const list elementChildren(const list& l) { + return cddr(l); +} + +/** + * Default encoding used to write XML documents. + */ +const char* encoding = "UTF-8"; + +/** + * Write a list of XML element or attribute tokens. + */ +const bool writeList(const list& l, const xmlTextWriterPtr xml) { + if (isNil(l)) + return true; + + // Write an attribute + const list token(car(l)); + if (isAttribute(token)) { + if (xmlTextWriterWriteAttribute(xml, (const xmlChar*)attributeName(token).c_str(), (const xmlChar*)attributeText(token).c_str()) < 0) + return false; + + } else if (isElement(token)) { + + // Write an element + if (xmlTextWriterStartElement(xml, (const xmlChar*)elementName(token).c_str()) < 0) + return false; + if (elementHasText(token) && xmlTextWriterWriteString(xml, (const xmlChar*)elementText(token).c_str()) < 0) + return false; + + // Write its children + writeList(elementChildren(token), xml); + + if (xmlTextWriterEndElement(xml) < 0) + return false; + } + + // Go on + return writeList(cdr(l), xml); +} + +/** + * Write an XML document to a libxml2 XML writer. + */ +const bool write(const list& l, const xmlTextWriterPtr xml) { + if (xmlTextWriterStartDocument(xml, NULL, encoding, NULL) < 0) + return false; + writeList(l, xml); + if (xmlTextWriterEndDocument(xml) < 0) + return false; + return true; +} + +/** + * Callback function called by libxml2 to write to the XML output stream. + */ +int writeCallback(void *context, const char* buffer, int len) { + std::ostream* os = static_cast(context); + os->write(buffer, len); + if (os->fail() || os->bad()) + return -1; + return len; +} + +/** + * Write an XML document to an output stream. + */ +const bool writeXML(const list& l, std::ostream& os) { + xmlOutputBufferPtr out = xmlOutputBufferCreateIO(writeCallback, NULL, &os, NULL); + xmlTextWriterPtr xml = xmlNewTextWriter(out); + if (xml == NULL) + return false; + return write(l, xml); +} + +/** + * Callback function called by libxml2 to write to the XML file output stream. + */ +int writeFileCallback(void *context, const char* buffer, int len) { + std::ofstream* os = static_cast(context); + os->write(buffer, len); + if (os->fail() || os->bad()) + return -1; + return len; +} + +/** + * Callback function called by libxml2 to close the XML file output stream. + */ +int writeCloseFileCallback(void *context) { + std::ofstream* fos = static_cast(context); + fos->close(); + return 0; +} + +/** + * Write an XML document to a file output stream. + */ +const bool writeXML(const list& l, std::ofstream& os) { + xmlOutputBufferPtr out = xmlOutputBufferCreateIO(writeFileCallback, writeCloseFileCallback, &os, NULL); + xmlTextWriterPtr xml = xmlNewTextWriter(out); + if (xml == NULL) + return false; + return write(l, xml); +} + +} +#endif /* tuscany_xml_hpp */ diff --git a/cpp/sca/runtime/core/test/Makefile.am b/cpp/sca/runtime/core/test/Makefile.am index 24292e8033..55fe571687 100644 --- a/cpp/sca/runtime/core/test/Makefile.am +++ b/cpp/sca/runtime/core/test/Makefile.am @@ -15,4 +15,13 @@ # specific language governing permissions and limitations # under the License. -SUBDIRS = ws.service.interop +noinst_PROGRAMS = core-test xml-test + +INCLUDES = -I. -I$(top_builddir)/runtime/core/src -I${LIBXML2_INCLUDE} + +core_test_SOURCES = tuscany/core-test.cpp +core_test_LDADD = -L${TUSCANY_SCACPP}/lib -ltuscany_sca + +xml_test_SOURCES = tuscany/xml-test.cpp +xml_test_LDADD = -L${TUSCANY_SCACPP}/lib -ltuscany_sca + diff --git a/cpp/sca/runtime/core/test/tuscany/core-test.cpp b/cpp/sca/runtime/core/test/tuscany/core-test.cpp new file mode 100644 index 0000000000..a0b32fa576 --- /dev/null +++ b/cpp/sca/runtime/core/test/tuscany/core-test.cpp @@ -0,0 +1,444 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + +/** + * Test core utils. + */ + +#include +#include +#include +#include +#include +#include +#include "tuscany/function.hpp" +#include "tuscany/list.hpp" +#include "tuscany/parallel.hpp" +#include "tuscany/value.hpp" +#include "tuscany/xml.hpp" + +namespace tuscany { + +struct inc { + int i; + inc(int i) : + i(i) { + } + const int operator()(const int x) const { + return x + i; + } +}; + +const int square(const int x) { + return x * x; +} + +bool testFunction() { + const lambda sq(square); + assert(sq(2) == 4); + + const lambda incf(inc(10)); + assert(incf(1) == 11); + return true; +} + +bool testFunctionGC() { + resetLambdaCounters(); + testFunction(); + assert(countLambdas == 0); + return true; +} + +int countElements = 0; + +struct Element { + int i; + + Element() : + i(0) { + countElements++; + } + + Element(int i) : + i(i) { + countElements++; + } + + Element(const Element& o) : + i(o.i) { + countElements++; + } + + ~Element() { + countElements--; + } + + const bool operator==(const Element& o) const { + return o.i == i; + } +}; + +bool testCons() { + assert(car(cons(2, makeList(3))) == 2); + assert(car(cdr(cons(2, makeList(3)))) == 3); + assert(isNil(cdr(cdr(cons(2, makeList(3)))))); + + assert(cons(Element(1), makeList(Element(2))) == makeList(Element(1), Element(2))); + return true; +} + +bool testlistGC() { + resetLambdaCounters(); + resetlistCounters(); + countElements = 0; + testCons(); + assert(countLambdas == 0); + assert(countlists == 0); + assert(countElements == 0); + return true; +} + +bool testOut() { + std::ostringstream os1; + os1 << list (); + assert(os1.str() == "()"); + + std::ostringstream os2; + os2 << makeList(1, 2, 3); + assert(os2.str() == "(1, (2, (3, ())))"); + return true; +} + +bool testEquals() { + assert(list() == list()); + assert(makeList(1, 2) == makeList(1, 2)); + assert(list() != makeList(1, 2)); + assert(makeList(1, 2, 3) == makeList(1, 2, 3)); + assert(makeList(1, 2) != makeList(1, 2, 3)); + return true; +} + +bool testLength() { + assert(0 == length(list())); + assert(1 == length(makeList(1))); + assert(2 == length(cons(1, makeList(2)))); + return true; +} + +bool testAppend() { + assert(car(append(makeList(1), makeList(2))) == 1); + assert(car(cdr(append(makeList(1), makeList(2)))) == 2); + assert(car(cdr(cdr(append(makeList(1), makeList(2, 3))))) == 3); + assert(isNil(cdr(cdr(cdr(append(makeList(1), makeList(2, 3))))))); + return true; +} + +struct Complex { + int x; + int y; + Complex() { + } + Complex(int x, int y) : + x(x), y(y) { + } +}; + +bool testComplex() { + const list p = makeList(Complex(1, 2), Complex(3, 4)); + assert(car(p).x == 1); + assert(car(cdr(p)).x == 3); + assert(isNil(cdr(cdr(p)))); + return true; +} + +bool testMap() { + assert(isNil(map((lambda)square, list()))); + + const list m = map((lambda )square, makeList(2, 3)); + assert(car(m) == 4); + assert(car(cdr(m)) == 9); + + return true; +} + +const int add(const int x, const int y) { + return x + y; +} + +bool testReduce() { + const lambda r(add); + assert(reduce(r, 0, makeList(1, 2, 3)) == 6); + return true; +} + +bool isPositive(int x) { + if(x >= 0) + return true; + else + return false; +} + +bool testFilter() { + lambda f(isPositive); + assert(car(filter(f, makeList(1, -1, 2, -2))) == 1); + assert(cadr(filter(f, makeList(1, -1, 2, -2))) == 2); + return true; +} + +bool testMember() { + assert(isNil(member(4, makeList(1, 2, 3)))); + assert(car(member(1, makeList(1, 2, 3))) == 1); + assert(car(member(2, makeList(1, 2, 3))) == 2); + assert(car(member(3, makeList(1, 2, 3))) == 3); + return true; +} + +bool testReverse() { + assert(isNil(reverse(list()))); + assert(car(reverse(makeList(1, 2, 3))) == 3); + assert(cadr(reverse(makeList(1, 2, 3))) == 2); + return true; +} + +double testSeqMap(double x) { + return x; +} + +double testSeqReduce(double v, double accum) { + return accum + 1.0; +} + +bool testSeq() { + //resetLambdaCounters(); + //resetlistCounters(); + + list s = seq(0.0, 1000.0); + assert(1001 == length(s)); + //printLambdaCounters(); + //printlistCounters(); + + assert(1001 == length(map(lambda(testSeqMap), s))); + + assert(801 == length(member(200.0, s))); + assert(201 == length(member(200.0, reverse(s)))); + + assert(1001 == reduce(lambda(testSeqReduce), 0.0, s)); + //printLambdaCounters(); + //printlistCounters(); + + return true; +} + +value valueSquare(list x) { + return value((int)car(x) * (int)car(x)); +} + +bool testValue() { + assert(value(true) == value(true)); + assert(value(1) == value(1)); + assert(value("abcd") == value("abcd")); + lambda&)> vl(valueSquare); + assert(value(vl) == value(vl)); + assert(value(makeList(value(1), value(2))) == value(makeList(value(1), value(2)))); + return true; +} + +bool testValueGC() { + resetValueCounters(); + resetLambdaCounters(); + resetlistCounters(); + testValue(); + assert(countValues == 0); + assert(countLambdas == 0); + assert(countlists == 0); + return true; +} + +double fib_aux(double n, double a, double b) { + if(n == 0.0) + return a; + return fib_aux(n - 1.0, b, a + b); +} + +double fib(double n) { + return fib_aux(n, 0.0, 1.0); +} + +bool testCppPerf() { + struct timeval start; + struct timeval end; + gettimeofday(&start, NULL); + + list s = seq(0.0, 999.0); + list r = map((lambda )fib, s); + assert(1000 == length(r)); + + gettimeofday(&end, NULL); + long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000); + //std::cout << "Fib cpp perf test " << t << " ms" << std::endl; + return true; +} + +bool testAtomicPerf() { + struct timeval start; + struct timeval end; + { + gettimeofday(&start, NULL); + for(int i = 0; i < 10000000;) + i = i + 1; + gettimeofday(&end, NULL); + long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000); + //std::cout << "Loop test " << t << " ms" << std::endl; + } + { + gettimeofday(&start, NULL); + for(int i = 0; i < 10000000;) + __sync_add_and_fetch(&i, 1); + gettimeofday(&end, NULL); + long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000); + //std::cout << "Loop atomic test " << t << " ms" << std::endl; + } + { + pthread_mutex_t mutex; + pthread_mutex_init(&mutex, NULL); + gettimeofday(&start, NULL); + for(int i = 0; i < 10000000;) { + pthread_mutex_lock(&mutex); + i = i + 1; + pthread_mutex_unlock(&mutex); + } + gettimeofday(&end, NULL); + pthread_mutex_destroy(&mutex); + long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000); + //std::cout << "Loop mutex test " << t << " ms" << std::endl; + } + return true; +} + +const int mtsquare(const int x) { + //std::cout << "thread " << threadId() << " mtsquare(" << x << ")\n"; + for(int i = 0; i < 10000000; i++) + ; + return x * x; +} + +bool testWorker() { + worker w(10); + { + const lambda func = curry(lambda (mtsquare), 2); + assert(submit(w, func) == 4); + } + { + const int max = 10; + + list > r; + for(int i = 0; i < max; i++) { + const lambda func = curry(lambda (mtsquare), i); + r = cons(submit(w, func), r); + } + for(int i = max - 1; i >= 0; i--) { + assert(car(r) == i * i); + r = cdr(r); + } + } + shutdown(w); + return true; +} + +const std::string currencyXML = +"\n" +"" +"" +"" +"" +"" +"" +"" +"" +"" +"" +"" +"" +"" +"" +"\n"; + +const bool isName(const value& token) { + return isAttribute(token) && attributeName(token) == "name"; +} + +bool testReadXML() { + std::istringstream is(currencyXML); + const list currency = value(readXML(is)); + + const value composite = car(currency); + assert(isElement(composite)); + assert(elementName(composite) == "composite"); + assert(!elementHasText(composite)); + + assert(attributeText(car(filter(lambda(isName), elementChildren(composite)))) == "currency"); + return true; +} + +bool testWriteXML() { + std::istringstream is(currencyXML); + const list currency = value(readXML(is)); + std::ostringstream os; + writeXML(currency, os); + assert(os.str() == currencyXML); + return true; +} + +} + +int main() { + std::cout << "Testing..." << std::endl; + + tuscany::testFunction(); + tuscany::testFunctionGC(); + tuscany::testCons(); + tuscany::testlistGC(); + tuscany::testOut(); + tuscany::testEquals(); + tuscany::testLength(); + tuscany::testAppend(); + tuscany::testComplex(); + tuscany::testMap(); + tuscany::testReduce(); + tuscany::testFilter(); + tuscany::testMember(); + tuscany::testReverse(); + tuscany::testSeq(); + tuscany::testValue(); + tuscany::testValueGC(); + tuscany::testCppPerf(); + tuscany::testAtomicPerf(); + tuscany::testWorker(); + tuscany::testReadXML(); + tuscany::testWriteXML(); + + std::cout << "OK" << std::endl; + + return 0; +} diff --git a/cpp/sca/runtime/core/test/tuscany/xml-test.cpp b/cpp/sca/runtime/core/test/tuscany/xml-test.cpp new file mode 100644 index 0000000000..af2308a321 --- /dev/null +++ b/cpp/sca/runtime/core/test/tuscany/xml-test.cpp @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + +/** + * Test validation of a composite file against an SCDL schema. + */ + +#include +#include +#include +#include + +namespace tuscany { + +bool printNode(xmlTextReaderPtr reader) { + const xmlChar* name = xmlTextReaderConstName(reader); + if(name == NULL) + name = (xmlChar *)""; + const xmlChar* value = xmlTextReaderConstValue(reader); + std::cout << xmlTextReaderDepth(reader) << " " << xmlTextReaderNodeType(reader) << " " << name << " " + << xmlTextReaderIsEmptyElement(reader) << " " << xmlTextReaderHasValue(reader); + if(value == NULL) + std::cout << std::endl; + else + std::cout << value << std::endl; + return true; +} + +int xmlRead(void *context, char* buffer, int len) { + return fread(buffer, 1, len, (FILE*)context); +} + +int xmlClose(void *context) { + fclose((FILE*)context); + return 0; +} + +bool readFile(const char*xsdfilename, const char *filename) { + std::cout << "Loading schemas\n"; + const xmlDocPtr xsddoc = xmlReadFile(xsdfilename, NULL, XML_PARSE_NONET); + const xmlSchemaParserCtxtPtr xsdctx = xmlSchemaNewDocParserCtxt(xsddoc); + const xmlSchemaPtr xsd = xmlSchemaParse(xsdctx); + const xmlSchemaValidCtxtPtr validctx = xmlSchemaNewValidCtxt(xsd); + std::cout << "Loaded schemas\n"; + + FILE* file = fopen(filename, "r"); + const xmlTextReaderPtr reader = xmlReaderForIO(xmlRead, xmlClose, file, filename, NULL, XML_PARSE_NONET); + xmlTextReaderSetParserProp(reader, XML_PARSER_DEFAULTATTRS, 1); + xmlTextReaderSetParserProp(reader, XML_PARSER_SUBST_ENTITIES, 1); + + if(reader != NULL) { + xmlTextReaderSchemaValidateCtxt(reader, validctx, 0); + + int rc; + while((rc = xmlTextReaderRead(reader)) == 0) { + printNode(reader); + } + if(xmlTextReaderIsValid(reader) != 1) + std::cout << "Could not validate document" << std::endl; + xmlFreeTextReader(reader); + if(rc != 0) + std::cout << "Could not parse document" << std::endl; + } else + std::cout << "Could not open document" << std::endl; + + xmlSchemaFreeValidCtxt(validctx); + xmlSchemaFree(xsd); + xmlSchemaFreeParserCtxt(xsdctx); + + return true; +} + +} + +int main(int argc, char **argv) { + std::cout << "Testing..." << std::endl; + if(argc != 3) + return 1; + + tuscany::readFile(argv[1], argv[2]); + + xmlCleanupParser(); + + std::cout << "OK" << std::endl; + return 0; +} -- cgit v1.2.3