| /* |
| * 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 <assert.h> |
| #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<int(const int)> f, int v) { |
| return f(v); |
| } |
| |
| bool testLambda() { |
| const lambda<int(const int)> sq(square); |
| assert(sq(2) == 4); |
| assert(mapLambda(sq, 2) == 4); |
| assert(mapLambda(square, 2) == 4); |
| |
| const lambda<int(const int)> incf(inc(10)); |
| assert(incf(1) == 11); |
| assert(mapLambda(incf, 1) == 11); |
| assert(mapLambda(inc(10), 1) == 11); |
| |
| lambda<int(const int)> 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<int> (); |
| assert(str(os1) == "()"); |
| |
| ostringstream os2; |
| os2 << mklist(1, 2, 3); |
| assert(str(os2) == "(1 2 3)"); |
| return true; |
| } |
| |
| bool testEquals() { |
| assert(list<int>() == list<int>()); |
| assert(mklist(1, 2) == mklist(1, 2)); |
| assert(list<int>() != 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<int>())); |
| 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<int>() + 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<Complex> 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<int, int>(square, list<int>()))); |
| |
| const list<int> m = map<int, int>(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<int(const int, const int)> 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<int>(isPositive, mklist(1, -1, 2, -2))) == 1); |
| assert(cadr(filter<int>(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<int>()))); |
| 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<list<string> > l = mklist(mklist<string>("x", "X"), mklist<string>("a", "A"), mklist<string>("y", "Y"), mklist<string>("a", "AA")); |
| assert(assoc<string>("a", l) == mklist<string>("a", "A")); |
| assert(isNil(assoc<string>("z", l))); |
| |
| const list<list<value> > u = mklist(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y"), mklist<value>("a", "AA")); |
| assert(assoc<value>("a", u) == mklist<value>("a", "A")); |
| |
| const list<value> v = mklist<value>(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y"), mklist<value>("a", "AA")); |
| assert(assoc<value>("a", v) == mklist<value>("a", "A")); |
| return true; |
| } |
| |
| bool testZip() { |
| const list<string> k = mklist<string>("x", "a", "y", "a"); |
| const list<string> v = mklist<string>("X", "A", "Y", "AA"); |
| const list<list<string> > z = mklist(k, v); |
| const list<list<string> > u = mklist(mklist<string>("x", "X"), mklist<string>("a", "A"), mklist<string>("y", "Y"), mklist<string>("a", "AA")); |
| assert(zip(k, v) == u); |
| assert(unzip(u) == z); |
| return true; |
| } |
| |
| bool testTokenize() { |
| assert(tokenize("/", "") == list<string>()); |
| assert(tokenize("/", "aaa") == mklist<string>("aaa")); |
| assert(tokenize("/", "aaa/bbb/ccc/ddd") == mklist<string>("aaa", "bbb", "ccc", "ddd")); |
| assert(tokenize("/", "/bbb/ccc/ddd") == mklist<string>("", "bbb", "ccc", "ddd")); |
| assert(tokenize("/", "/bbb/ccc/") == mklist<string>("", "bbb", "ccc")); |
| assert(tokenize("/", "/bbb//ccc/") == mklist<string>("", "bbb", "", "ccc")); |
| assert(tokenize("/", "abc/def/") == mklist<string>("abc", "def")); |
| |
| assert(join("/", list<string>()) == ""); |
| assert(join("/", mklist<string>("aaa")) == "aaa"); |
| assert(join("/", mklist<string>("aaa", "bbb", "ccc", "ddd")) == "aaa/bbb/ccc/ddd"); |
| assert(join("/", mklist<string>("", "bbb", "ccc", "ddd")) == "/bbb/ccc/ddd"); |
| assert(join("/", mklist<string>("bbb", "ccc", "")) == "bbb/ccc/"); |
| assert(join("/", mklist<string>("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<double> s = seq(0.0, 1000.0); |
| assert(1001 == length(s)); |
| |
| assert(1001 == length(map<double, double>(testSeqMap, s))); |
| |
| assert(801 == length(member(200.0, s))); |
| assert(201 == length(member(200.0, reverse(s)))); |
| |
| assert(1001 == (reduce<double, double>(testSeqReduce, 0.0, s))); |
| return true; |
| } |
| |
| value valueSquare(list<value> 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<value(const list<value>&)> vl(valueSquare); |
| assert(value(vl) == value(vl)); |
| assert(value(mklist<value>(1, 2)) == value(mklist<value>(1, 2))); |
| |
| const list<value> v = mklist<value>(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y")); |
| assert(cadr((list<list<value> >)value(v)) == mklist<value>("a", "A")); |
| |
| const value pv(gc_ptr<value>(new (gc_new<value>()) value(1))); |
| assert(*(gc_ptr<value>)pv == value(1)); |
| |
| const list<value> lpv = mklist<value>(gc_ptr<value>(new (gc_new<value>()) value(1)), gc_ptr<value>(new (gc_new<value>()) value(2))); |
| assert(*(gc_ptr<value>)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<value> t = mktree<value>("a", list<value>(), list<value>()); |
| const list<value> ct = constree<value>("d", constree<value>("f", constree<value>("c", constree<value>("e", constree<value>("b", t))))); |
| const list<value> mt = mktree(mklist<value>("d", "f", "c", "e", "b", "a")); |
| assert(mt == ct); |
| const list<value> l = flatten<value>(mt); |
| assert(length(l) == 6); |
| assert(car(l) == "a"); |
| assert(car(reverse(l)) == "f"); |
| const list<value> bt = mkbtree<value>(l); |
| assert(car(bt) == "c"); |
| return true; |
| } |
| |
| const list<value> lta(const string& x) { |
| return mklist<value>(c_str(x), c_str(x + x)); |
| } |
| |
| bool testTreeAssoc() { |
| const list<value> t = mktree<value>(lta("a"), list<value>(), list<value>()); |
| const list<value> at = constree<value>(lta("d"), constree<value>(lta("f"), constree<value>(lta("c"), constree<value>(lta("e"), constree<value>(lta("b"), t))))); |
| const list<value> l = flatten<value>(at); |
| assert(length(l) == 6); |
| assert(car(l) == mklist<value>("a", "aa")); |
| assert(car(reverse(l)) == mklist<value>("f", "ff")); |
| const list<value> bt = mkbtree<value>(l); |
| assert(car(bt) == mklist<value>("c", "cc")); |
| assert(assoctree<value>("a", bt) == mklist<value>("a", "aa")); |
| assert(assoctree<value>("b", bt) == mklist<value>("b", "bb")); |
| assert(assoctree<value>("f", bt) == mklist<value>("f", "ff")); |
| assert(isNil(assoctree<value>("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<double> s = seq(0.0, 999.0); |
| list<double> r = map<double, double>(fib, s); |
| assert(1000 == length(r)); |
| return true; |
| } |
| }; |
| |
| struct nestedFibMapPerf { |
| const lambda<double(const double)> fib; |
| nestedFibMapPerf(const lambda<double(const double)>& fib) : fib(fib) { |
| } |
| const bool operator()() const { |
| list<double> s = seq(0.0, 999.0); |
| list<double> r = map<double, double>(fib, s); |
| assert(1000 == length(r)); |
| return true; |
| } |
| }; |
| |
| bool testCppPerf() { |
| { |
| const lambda<bool()> 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<bool()> nfml = nestedFibMapPerf(lambda<double(const double)>(nested::fib)); |
| cout << "Nested Fibonacci map test " << (time(nfml, 1, 1) / 1000) << " ms" << endl; |
| } |
| return true; |
| } |
| |
| const id<int> idF(const int v) { |
| return v * 2; |
| } |
| |
| const id<int> idG(const int v) { |
| return v * 3; |
| } |
| |
| const id<int> idH(const int v) { |
| return idF(v) >> idG; |
| } |
| |
| bool testIdMonad() { |
| const id<int> m(2); |
| assert(m >> idF == idF(2)); |
| assert(m >> unit<int>() == m); |
| assert(m >> idF >> idG == m >> idH); |
| return true; |
| } |
| |
| const maybe<int> maybeF(const int v) { |
| return v * 2; |
| } |
| |
| const maybe<int> maybeG(const int v) { |
| return v * 3; |
| } |
| |
| const maybe<int> maybeH(const int v) { |
| return maybeF(v) >> maybeG; |
| } |
| |
| bool testMaybeMonad() { |
| const maybe<int> m(2); |
| assert(m >> maybeF == maybeF(2)); |
| assert((m >> just<int>()) == m); |
| assert(m >> maybeF >> maybeG == m >> maybeH); |
| |
| assert(maybe<int>() >> maybeF >> maybeG == maybe<int>()); |
| return true; |
| } |
| |
| const failable<int> failableF(const int v) { |
| return v * 2; |
| } |
| |
| const failable<int> failableG(const int v) { |
| return v * 3; |
| } |
| |
| const failable<int> failableH(const int v) { |
| return failableF(v) >> failableG; |
| } |
| |
| bool testFailableMonad() { |
| const failable<int> m(2); |
| assert(m >> failableF == failableF(2)); |
| assert((m >> success<int, string>()) == m); |
| assert(m >> failableF >> failableG == m >> failableH); |
| |
| cout << "Failable monad test... " << endl; |
| failable<int> ooops = mkfailure<int>("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<int, double> operator()(int s) const { |
| return scp<int, double>(s + 1, v); |
| } |
| }; |
| |
| const state<int, double> tick(const double v) { |
| return transformer<int, double>(tickInc(v)); |
| } |
| |
| const state<int, double> stateF(const double v) { |
| return result<int, double>(v * 2.0) >> tick; |
| } |
| |
| const state<int, double> stateG(const double v) { |
| return result<int, double>(v + 5); |
| } |
| |
| const state<int, double> stateH(const double v) { |
| return stateF(v) >> stateG; |
| } |
| |
| bool testStateMonad() { |
| const lambda<state<int, double>(const double)> r(result<int, double>); |
| |
| state<int, double> m = result<int, double>(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<lambda<int(const int)> > sq(dynlambda<int(const int)>("csquare", dl)); |
| assert(hasContent(sq)); |
| lambda<int(const int)> l(content(sq)); |
| assert(l(2) == 4); |
| |
| const failable<lambda<lambda<int(const int)>()> > sql(dynlambda<lambda<int(const int)>()>("csquarel", dl)); |
| assert(hasContent(sql)); |
| lambda<lambda<int(const int)>()> 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; |
| } |