summaryrefslogtreecommitdiffstats
path: root/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp')
-rw-r--r--cpp/etc/git-exclude3
-rw-r--r--cpp/sca/configure.ac1
-rw-r--r--cpp/sca/runtime/core/Makefile.am2
-rw-r--r--cpp/sca/runtime/core/src/tuscany/xml.hpp385
-rw-r--r--cpp/sca/runtime/core/test/Makefile.am11
-rw-r--r--cpp/sca/runtime/core/test/tuscany/core-test.cpp444
-rw-r--r--cpp/sca/runtime/core/test/tuscany/xml-test.cpp104
7 files changed, 948 insertions, 2 deletions
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 <libxml/xmlreader.h>
+#include <libxml/xmlwriter.h>
+#include <libxml/xmlschemas.h>
+#include <libxml/globals.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+#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<value> readList(const list<value>& 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<value> read(XmlReader& reader) {
+ value nextToken = readToken(reader);
+ if (startElement == nextToken)
+ return makeList(value(readList(makeList(element), reader)));
+ return list<value>();
+}
+
+/**
+ * Callback function called by libxml2 to read the XML input stream.
+ */
+int readCallback(void *context, char* buffer, int len) {
+ std::istream* is = static_cast<std::istream*>(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<value> readXML(std::istream& is) {
+ xmlTextReaderPtr xml = xmlReaderForIO(readCallback, NULL, &is, NULL, NULL, XML_PARSE_NONET);
+ if (xml == NULL)
+ return list<value>();
+ 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<std::ifstream*>(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<std::ifstream*>(context);
+ fis->close();
+ return 0;
+}
+
+/**
+ * Read an XML document from a file input stream.
+ */
+const list<value> readXML(std::ifstream& is) {
+ xmlTextReaderPtr xml = xmlReaderForIO(readFileCallback, readCloseFileCallback, &is, NULL, NULL, XML_PARSE_NONET);
+ if (xml == NULL)
+ return list<value>();
+ XmlReader reader(xml);
+ return read(reader);
+}
+
+/**
+ * Returns true if a value is an XML attribute.
+ */
+const bool isAttribute(const list<value>& l) {
+ return !isNil(l) && car(l) == attribute;
+}
+
+/**
+ * Returns the name of an XML attribute.
+ */
+const std::string attributeName(const list<value>& l) {
+ return cadr(l);
+}
+
+/**
+ * Returns the text value of an XML attribute.
+ */
+const std::string attributeText(const list<value>& l) {
+ return caddr(l);
+}
+
+/**
+ * Returns true if a value is an XML element.
+ */
+const bool isElement(const list<value>& l) {
+ return !isNil(l) && car(l) == element;
+}
+
+/**
+ * Returns the name of an XML element.
+ */
+const std::string elementName(const list<value>& l) {
+ return cadr(l);
+}
+
+/**
+ * Returns true if an XML element contains text content.
+ */
+const bool elementHasText(const list<value>& 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<value>& l) {
+ return caddr(l);
+}
+
+/**
+ * Returns the children of an XML element.
+ */
+const list<value> elementChildren(const list<value>& 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<value>& l, const xmlTextWriterPtr xml) {
+ if (isNil(l))
+ return true;
+
+ // Write an attribute
+ const list<value> 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<value>& 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<std::ostream*>(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<value>& 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<std::ofstream*>(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<std::ofstream*>(context);
+ fos->close();
+ return 0;
+}
+
+/**
+ * Write an XML document to a file output stream.
+ */
+const bool writeXML(const list<value>& 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 <assert.h>
+#include <sys/time.h>
+#include <time.h>
+#include <iostream>
+#include <string>
+#include <sstream>
+#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<int(int)> sq(square);
+ assert(sq(2) == 4);
+
+ const lambda<int(int i)> 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<int> ();
+ assert(os1.str() == "()");
+
+ std::ostringstream os2;
+ os2 << makeList(1, 2, 3);
+ assert(os2.str() == "(1, (2, (3, ())))");
+ return true;
+}
+
+bool testEquals() {
+ assert(list<int>() == list<int>());
+ assert(makeList(1, 2) == makeList(1, 2));
+ assert(list<int>() != 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<int>()));
+ 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<Complex> 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<int(int)>)square, list<int>())));
+
+ const list<int> m = map((lambda<int(int)> )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<int(int, int)> 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<bool(int)> 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<int>())));
+ 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<double> s = seq(0.0, 1000.0);
+ assert(1001 == length(s));
+ //printLambdaCounters();
+ //printlistCounters();
+
+ assert(1001 == length(map(lambda<double(double)>(testSeqMap), s)));
+
+ assert(801 == length(member(200.0, s)));
+ assert(201 == length(member(200.0, reverse(s))));
+
+ assert(1001 == reduce(lambda<double(double, double)>(testSeqReduce), 0.0, s));
+ //printLambdaCounters();
+ //printlistCounters();
+
+ return true;
+}
+
+value valueSquare(list<value> 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<value(list<value>&)> 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<double> s = seq(0.0, 999.0);
+ list<double> r = map((lambda<double(double)> )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<int()> func = curry(lambda<int(int)> (mtsquare), 2);
+ assert(submit(w, func) == 4);
+ }
+ {
+ const int max = 10;
+
+ list<future<int> > r;
+ for(int i = 0; i < max; i++) {
+ const lambda<int()> func = curry(lambda<int(int)> (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 =
+"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+"<composite xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200903\" "
+"xmlns:t=\"http://tuscany.apache.org/xmlns/sca/1.1\" "
+"targetNamespace=\"http://services\" "
+"name=\"currency\">"
+"<component name=\"CurrencyConverterWebService\">"
+"<implementation.java class=\"services.CurrencyConverterImpl\"/>"
+"<service name=\"CurrencyConverter\">"
+"<binding.ws/>"
+"</service>"
+"</component>"
+"<component name=\"CurrencyConverterWebService2\">"
+"<implementation.java class=\"services.CurrencyConverterImpl2\"/>"
+"<service name=\"CurrencyConverter2\">"
+"<binding.atom/>"
+"</service>"
+"</component>"
+"</composite>"
+"\n";
+
+const bool isName(const value& token) {
+ return isAttribute(token) && attributeName(token) == "name";
+}
+
+bool testReadXML() {
+ std::istringstream is(currencyXML);
+ const list<value> currency = value(readXML(is));
+
+ const value composite = car(currency);
+ assert(isElement(composite));
+ assert(elementName(composite) == "composite");
+ assert(!elementHasText(composite));
+
+ assert(attributeText(car(filter(lambda<bool(value)>(isName), elementChildren(composite)))) == "currency");
+ return true;
+}
+
+bool testWriteXML() {
+ std::istringstream is(currencyXML);
+ const list<value> 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 <iostream>
+#include <string>
+#include <libxml/xmlreader.h>
+#include <libxml/xmlschemas.h>
+
+namespace tuscany {
+
+bool printNode(xmlTextReaderPtr reader) {
+ const xmlChar* name = xmlTextReaderConstName(reader);
+ if(name == NULL)
+ name = (xmlChar *)"<unknown>";
+ 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;
+}