/* * 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 kernel functions. */ #include #include "string.hpp" #include "sstream.hpp" #include "function.hpp" #include "list.hpp" #include "tree.hpp" #include "value.hpp" #include "monad.hpp" #include "dynlib.hpp" #include "perf.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; } int mapLambda(lambda f, int v) { return f(v); } bool testLambda() { const lambda sq(square); assert(sq(2) == 4); assert(mapLambda(sq, 2) == 4); assert(mapLambda(square, 2) == 4); const lambda incf(inc(10)); assert(incf(1) == 11); assert(mapLambda(incf, 1) == 11); assert(mapLambda(inc(10), 1) == 11); lambda l; l = incf; assert(l(1) == 11); l = square; assert(l(2) == 4); return true; } bool testLambdaGC() { resetLambdaCounters(); { gc_scoped_pool gc; testLambda(); } assert(checkLambdaCounters()); 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; } }; ostream& operator<<(ostream& out, const Element& v) { out << v.i ; return out; } bool testCons() { assert(car(cons(2, mklist(3))) == 2); assert(car(cdr(cons(2, mklist(3)))) == 3); assert(isNil(cdr(cdr(cons(2, mklist(3)))))); assert(cons(Element(1), mklist(Element(2))) == mklist(Element(1), Element(2))); return true; } bool testListGC() { resetLambdaCounters(); resetListCounters(); countElements = 0; { gc_scoped_pool gc; testCons(); } assert(checkLambdaCounters()); assert(checkListCounters()); assert(countElements == 0); return true; } bool testOut() { ostringstream os1; os1 << list (); assert(str(os1) == "()"); ostringstream os2; os2 << mklist(1, 2, 3); assert(str(os2) == "(1 2 3)"); return true; } bool testEquals() { assert(list() == list()); assert(mklist(1, 2) == mklist(1, 2)); assert(list() != mklist(1, 2)); assert(mklist(1, 2, 3) == mklist(1, 2, 3)); assert(mklist(1, 2) != mklist(1, 2, 3)); return true; } bool testLength() { assert(0 == length(list())); assert(1 == length(mklist(1))); assert(2 == length(cons(1, mklist(2)))); return true; } bool testAppend() { assert(car(append(mklist(1), mklist(2))) == 1); assert(car(cdr(append(mklist(1), mklist(2)))) == 2); assert(car(cdr(cdr(append(mklist(1), mklist(2, 3))))) == 3); assert(isNil(cdr(cdr(cdr(append(mklist(1), mklist(2, 3))))))); assert(list() + 1 + 2 + 3 == mklist(1, 2, 3)); return true; } struct Complex { int x; int y; Complex() { } Complex(int x, int y) : x(x), y(y) { } }; ostream& operator<<(ostream& out, const Complex& v) { out << "[" << v.x << ":" << v.y << "]"; return out; } bool testComplex() { const list p = mklist(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(square, list()))); const list m = map(square, mklist(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, mklist(1, 2, 3)) == 6); return true; } bool isPositive(const int x) { if(x >= 0) return true; else return false; } bool testFilter() { assert(car(filter(isPositive, mklist(1, -1, 2, -2))) == 1); assert(cadr(filter(isPositive, mklist(1, -1, 2, -2))) == 2); return true; } bool testMember() { assert(isNil(member(4, mklist(1, 2, 3)))); assert(car(member(1, mklist(1, 2, 3))) == 1); assert(car(member(2, mklist(1, 2, 3))) == 2); assert(car(member(3, mklist(1, 2, 3))) == 3); return true; } bool testReverse() { assert(isNil(reverse(list()))); assert(car(reverse(mklist(1, 2, 3))) == 3); assert(cadr(reverse(mklist(1, 2, 3))) == 2); return true; } bool testListRef() { assert(listRef(mklist(1), 0) == 1); assert(listRef(mklist(1, 2, 3), 0) == 1); assert(listRef(mklist(1, 2, 3), 1) == 2); assert(listRef(mklist(1, 2, 3), 2) == 3); return true; } bool testAssoc() { const list > l = mklist(mklist("x", "X"), mklist("a", "A"), mklist("y", "Y"), mklist("a", "AA")); assert(assoc("a", l) == mklist("a", "A")); assert(isNil(assoc("z", l))); const list > u = mklist(mklist("x", "X"), mklist("a", "A"), mklist("y", "Y"), mklist("a", "AA")); assert(assoc("a", u) == mklist("a", "A")); const list v = mklist(mklist("x", "X"), mklist("a", "A"), mklist("y", "Y"), mklist("a", "AA")); assert(assoc("a", v) == mklist("a", "A")); return true; } bool testZip() { const list k = mklist("x", "a", "y", "a"); const list v = mklist("X", "A", "Y", "AA"); const list > z = mklist(k, v); const list > u = mklist(mklist("x", "X"), mklist("a", "A"), mklist("y", "Y"), mklist("a", "AA")); assert(zip(k, v) == u); assert(unzip(u) == z); return true; } bool testTokenize() { assert(tokenize("/", "") == list()); assert(tokenize("/", "aaa") == mklist("aaa")); assert(tokenize("/", "aaa/bbb/ccc/ddd") == mklist("aaa", "bbb", "ccc", "ddd")); assert(tokenize("/", "/bbb/ccc/ddd") == mklist("", "bbb", "ccc", "ddd")); assert(tokenize("/", "/bbb/ccc/") == mklist("", "bbb", "ccc")); assert(tokenize("/", "/bbb//ccc/") == mklist("", "bbb", "", "ccc")); assert(tokenize("/", "abc/def/") == mklist("abc", "def")); assert(join("/", list()) == ""); assert(join("/", mklist("aaa")) == "aaa"); assert(join("/", mklist("aaa", "bbb", "ccc", "ddd")) == "aaa/bbb/ccc/ddd"); assert(join("/", mklist("", "bbb", "ccc", "ddd")) == "/bbb/ccc/ddd"); assert(join("/", mklist("bbb", "ccc", "")) == "bbb/ccc/"); assert(join("/", mklist("bbb", "", "ccc")) == "bbb//ccc"); return true; } double testSeqMap(double x) { return x; } double testSeqReduce(unused double v, double accum) { return accum + 1.0; } bool testSeq() { resetLambdaCounters(); resetListCounters(); list s = seq(0.0, 1000.0); assert(1001 == length(s)); assert(1001 == length(map(testSeqMap, s))); assert(801 == length(member(200.0, s))); assert(201 == length(member(200.0, reverse(s)))); assert(1001 == (reduce(testSeqReduce, 0.0, s))); return true; } value valueSquare(list x) { return (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(mklist(1, 2)) == value(mklist(1, 2))); const list v = mklist(mklist("x", "X"), mklist("a", "A"), mklist("y", "Y")); assert(cadr((list >)value(v)) == mklist("a", "A")); const value pv(gc_ptr(new (gc_new()) value(1))); assert(*(gc_ptr)pv == value(1)); const list lpv = mklist(gc_ptr(new (gc_new()) value(1)), gc_ptr(new (gc_new()) value(2))); assert(*(gc_ptr)car(lpv) == value(1)); return true; } bool testValueGC() { resetLambdaCounters(); resetListCounters(); resetValueCounters(); { gc_scoped_pool gc; testValue(); } assert(checkValueCounters()); assert(checkLambdaCounters()); assert(checkListCounters()); return true; } bool testTree() { const list t = mktree("a", list(), list()); const list ct = constree("d", constree("f", constree("c", constree("e", constree("b", t))))); const list mt = mktree(mklist("d", "f", "c", "e", "b", "a")); assert(mt == ct); const list l = flatten(mt); assert(length(l) == 6); assert(car(l) == "a"); assert(car(reverse(l)) == "f"); const list bt = mkbtree(l); assert(car(bt) == "c"); return true; } const list lta(const string& x) { return mklist(c_str(x), c_str(x + x)); } bool testTreeAssoc() { const list t = mktree(lta("a"), list(), list()); const list at = constree(lta("d"), constree(lta("f"), constree(lta("c"), constree(lta("e"), constree(lta("b"), t))))); const list l = flatten(at); assert(length(l) == 6); assert(car(l) == mklist("a", "aa")); assert(car(reverse(l)) == mklist("f", "ff")); const list bt = mkbtree(l); assert(car(bt) == mklist("c", "cc")); assert(assoctree("a", bt) == mklist("a", "aa")); assert(assoctree("b", bt) == mklist("b", "bb")); assert(assoctree("f", bt) == mklist("f", "ff")); assert(isNil(assoctree("x", bt))); 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); } struct fibMapPerf { const bool operator()() const { list s = seq(0.0, 999.0); list r = map(fib, s); assert(1000 == length(r)); return true; } }; struct nestedFibMapPerf { const lambda fib; nestedFibMapPerf(const lambda& fib) : fib(fib) { } const bool operator()() const { list s = seq(0.0, 999.0); list r = map(fib, s); assert(1000 == length(r)); return true; } }; bool testCppPerf() { { const lambda fml = fibMapPerf(); cout << "Fibonacci map test " << (time(fml, 1, 1) / 1000) << " ms" << endl; } { struct nested { static double fib(double n) { struct nested { static double fib_aux(double n, double a, double b) { if(n == 0.0) return a; return fib_aux(n - 1.0, b, a + b); } }; return nested::fib_aux(n, 0.0, 1.0); } }; const lambda nfml = nestedFibMapPerf(lambda(nested::fib)); cout << "Nested Fibonacci map test " << (time(nfml, 1, 1) / 1000) << " ms" << endl; } return true; } const id idF(const int v) { return v * 2; } const id idG(const int v) { return v * 3; } const id idH(const int v) { return idF(v) >> idG; } bool testIdMonad() { const id m(2); assert(m >> idF == idF(2)); assert(m >> unit() == m); assert(m >> idF >> idG == m >> idH); return true; } const maybe maybeF(const int v) { return v * 2; } const maybe maybeG(const int v) { return v * 3; } const maybe maybeH(const int v) { return maybeF(v) >> maybeG; } bool testMaybeMonad() { const maybe m(2); assert(m >> maybeF == maybeF(2)); assert((m >> just()) == m); assert(m >> maybeF >> maybeG == m >> maybeH); assert(maybe() >> maybeF >> maybeG == maybe()); return true; } const failable failableF(const int v) { return v * 2; } const failable failableG(const int v) { return v * 3; } const failable failableH(const int v) { return failableF(v) >> failableG; } bool testFailableMonad() { const failable m(2); assert(m >> failableF == failableF(2)); assert((m >> success()) == m); assert(m >> failableF >> failableG == m >> failableH); cout << "Failable monad test... " << endl; failable ooops = mkfailure("test"); assert(reason(ooops) == "test"); assert(ooops >> failableF >> failableG == ooops); return true; } struct tickInc { const double v; tickInc(const double v) : v(v) { } const scp operator()(int s) const { return scp(s + 1, v); } }; const state tick(const double v) { return transformer(tickInc(v)); } const state stateF(const double v) { return result(v * 2.0) >> tick; } const state stateG(const double v) { return result(v + 5); } const state stateH(const double v) { return stateF(v) >> stateG; } bool testStateMonad() { const lambda(const double)> r(result); state m = result(2.0); assert((m >> stateF)(0) == stateF(2.0)(0)); assert(1 == (int)(m >> stateF)(0)); assert((m >> r)(0) == m(0)); assert((m >> stateF >> stateG)(0) == (m >> stateH)(0)); return true; } bool testDynLib() { const lib dl(string("./libdynlib-test") + dynlibExt); const failable > sq(dynlambda("csquare", dl)); assert(hasContent(sq)); lambda l(content(sq)); assert(l(2) == 4); const failable()> > sql(dynlambda()>("csquarel", dl)); assert(hasContent(sql)); lambda()> ll(content(sql)); assert(ll()(3) == 9); return true; } } int main() { tuscany::cout << "Testing..." << tuscany::endl; tuscany::testLambda(); tuscany::testLambdaGC(); 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::testListRef(); tuscany::testAssoc(); tuscany::testZip(); tuscany::testTokenize(); tuscany::testSeq(); tuscany::testValue(); tuscany::testValueGC(); tuscany::testTree(); tuscany::testTreeAssoc(); tuscany::testCppPerf(); tuscany::testIdMonad(); tuscany::testMaybeMonad(); tuscany::testFailableMonad(); tuscany::testStateMonad(); tuscany::testDynLib(); tuscany::cout << "OK" << tuscany::endl; return 0; }