diff options
Diffstat (limited to 'Ix/CPP/unittest/testbench.cpp')
-rw-r--r-- | Ix/CPP/unittest/testbench.cpp | 610 |
1 files changed, 0 insertions, 610 deletions
diff --git a/Ix/CPP/unittest/testbench.cpp b/Ix/CPP/unittest/testbench.cpp deleted file mode 100644 index f8a7899..0000000 --- a/Ix/CPP/unittest/testbench.cpp +++ /dev/null @@ -1,610 +0,0 @@ -// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. - -#include <iostream> -#include <iomanip> -#include <vector> -#include <functional> -#include <algorithm> -#include <numeric> -#include <iterator> -#include <string> -#include <complex> - -#include <ctime> -#include <cstddef> - -#include <boost/lambda/core.hpp> -#include <boost/lambda/lambda.hpp> -#include <boost/iterator.hpp> - -#include "cpplinq/linq.hpp" - -#include "testbench.hpp" - -using namespace std; -using namespace cpplinq; - -struct int_iter - : std::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t, int*, int> -{ - int_iter(value_type i = 0, value_type step = 1) : value(i), step(step) - {} - - value_type operator*() const { - return value; - } - int_iter& operator++() { - value+=step; return *this; - } - int_iter& operator--() { - value-=step; return *this; - } - int_iter& operator+=(std::ptrdiff_t offset) { - value += step*offset; return *this; - } - int_iter& operator-=(std::ptrdiff_t offset) { - value -= step*offset; return *this; - } - std::ptrdiff_t operator-(int_iter rhs) const { - return std::ptrdiff_t((value - rhs.value)/step); - } - bool operator==(int_iter other) const { - return value == other.value; - } - bool operator!=(int_iter other) const { - return !(*this == other); - } - bool operator<(int_iter other) const { return (*this - other) < 0; } - bool operator>(int_iter other) const { return (*this - other) > 0; } - bool operator<=(int_iter other) const { return (*this - other) <= 0; } - bool operator>=(int_iter other) const { return (*this - other) >= 0; } - - value_type value; - value_type step; -}; -int_iter operator+(int_iter lhs, std::ptrdiff_t rhs) { - return lhs+=rhs; -} -int_iter operator+(std::ptrdiff_t lhs, int_iter rhs) { - return rhs+=lhs; -} -int_iter operator-(int_iter lhs, std::ptrdiff_t rhs) { - return lhs-=rhs; -} -struct int_range -{ - typedef int_iter iterator; - typedef int_iter::value_type value_type; - int_range(value_type begin, value_type end, value_type step = 1) - : b(begin, step), e(end, step) - { - if (step == 0) { - throw std::logic_error("bad step"); - } - if (abs(end - begin) % abs(step) != 0) { - end -= (end-begin)%abs(step); - } - } - int_iter begin() const { return int_iter(b);} - int_iter end() const { return int_iter(e); } - - iterator b, e; -}; - -vector<int> vector_range(int start, int end) -{ - vector<int> v; - for (int i = start; i < end; ++i) - v.push_back(i); - return v; -} - -TEST(test_selection) -{ - vector<int> v = vector_range(0, 10); - - auto v2 = from(v) - .select([](int x) { return x*2; }); - - auto result = accumulate(begin(v2), end(v2), int(0)); - - VERIFY_EQ(90, result); -} - -TEST(test_where) -{ - vector<int> v = vector_range(0, 10); - auto v2 = from(v) - .where([](int x) { return x % 2;}); - - VERIFY_EQ(1, *v2.begin()); - - auto result = accumulate(begin(v2), end(v2), int(0)); - - VERIFY_EQ(25, result); -} - - -bool is_prime(int x) { - if (x < 2) {return false;} - if (x == 2) {return true;} - for (int i = x/2; i >= 2; --i) { - if (x % i == 0) { return false;} - } - return true; -}; - -template <class It> -void display(It start, It end) -{ - int i = 0; - for_each(start, end, [&](typename iterator_traits<It>::value_type x){ - if (++i % 10 == 0) { - cout << endl; - } - cout << x << " "; - }); - cout << endl; -} - -TEST(test_whereselect) -{ - auto xs = int_range(0,100); - auto ys = from(xs) - .where(is_prime) - .select([](int x){ return x*x; }); - auto result = accumulate(begin(ys), end(ys), int(0)); - - //display(begin(ys), end(ys)); - - // primes < 100 - VERIFY_EQ(65796, result); -} -TEST(test_where_modification) -{ - vector<int> xs = vector_range(0, 100); - - auto ys = from(xs) - .where(is_prime); - std::fill(begin(ys), end(ys), int(0)); - - auto result = accumulate(begin(xs), end(xs), int(0)); - - //display(begin(ys), end(ys)); - - // non-primes < 100 - VERIFY_EQ(3890, result); -} - -TEST(test_where_any) -{ - using namespace boost::lambda; - - vector<int> xs(200); - fill(begin(xs), end(xs), int(0)); - auto it = xs.begin(); - *it = 2; - - for(;;) { - auto last = *it++; - auto primes = from(int_range(last+1, -1)) - .where([&](int x){ - return from(begin(xs), it) - //.all([&](int d){return x%d;}); - .all(x % boost::lambda::_1); - }); - *it = *primes.begin(); - if ((*it)>=100) { - break; - } - }; - xs.erase(it, xs.end()); - - auto result = accumulate(begin(xs), end(xs), int(0)); - - //display(begin(xs), end(xs)); - - // primes < 100 - VERIFY_EQ(1060, result); -} - -TEST(test_take) -{ - auto zero_one = from(int_range(0, -1)) - .take(2); - - VERIFY_EQ(0, zero_one[0]); - VERIFY_EQ(1, zero_one[1]); - - auto ten = from(int_range(0, -1)) - .skip(10); - - VERIFY_EQ(10, ten[0]); - VERIFY_EQ(11, ten[1]); -} - -vector<int> some_primes(std::size_t howMany) -{ - auto xs = from(int_range(0, -1)) - .where(is_prime) - .take(howMany); - auto v = vector<int>(begin(xs), end(xs)); - return v; -} - -TEST(test_groupby) -{ - auto xs = some_primes(40); - //display(begin(xs), end(xs)); - - auto grouped = - from(xs) - .groupby([](int i){return i % 10; }); - - VERIFY_EQ(6, from(grouped).count()); - for(auto group = begin(grouped); group != end(grouped); ++group) { - //cout << "key = " << group->key << endl - // << "| "; - for (auto elem = group->begin(); elem != group->end(); ++elem) { - //cout << *elem << " "; - } - //cout << endl; - - switch(group->key) { - case 2: VERIFY_EQ(1, from(*group).count()); break; - case 3: VERIFY_EQ(11, from(*group).count()); break; - case 5: VERIFY_EQ(1, from(*group).count()); break; - case 7: VERIFY_EQ(11, from(*group).count()); break; - case 1: VERIFY_EQ(8, from(*group).count()); break; - case 9: VERIFY_EQ(8, from(*group).count()); break; - } - } -} - -TEST(test_symbolname) -{ - auto complexQuery = - from(int_range(0,100000)) - .select([](int x){ return x*2;}) - .where([](int x){ return x%7; }) - .skip(20); - - //cout << " type name: " << typeid(complexQuery1).name() << endl; - - - //auto complexQuery = - // complexQuery1.groupby([](int x) { return x%5; }) - // .take(3) - // ; - - - cout << "type name: " << typeid(complexQuery).name() << endl; - cout << "type name length: " << strlen(typeid(complexQuery).name()) << endl; - - auto iter = complexQuery.begin(); - cout << "iterator name: " << typeid(iter).name() << endl; - cout << "iterator name length: " << strlen(typeid(iter).name()) << endl; -} - -TEST(test_cast) -{ - auto q = from(int_range(0,10)) - .cast<bool>(); - VERIFY_EQ(false, q[0]); - VERIFY_EQ(true, q[1]); - VERIFY_EQ(true, q[2]); - VERIFY((std::is_same<decltype(q[0]), bool>::value)); -} - -TEST(test_contains) -{ - auto q = from(int_range(0,10)) - .select([](int x){return x*2;}); - VERIFY(q.contains(4)); - VERIFY(!q.contains(5)); -} - -TEST(test_element_accessors) -{ - vector<int> v(int_iter(0), int_iter(10)); - auto q = from(v) - .where([](int x){return x%2==0;}); - - VERIFY_EQ(0, q.first()); - VERIFY_EQ(8, q.last()); - VERIFY_EQ(6, q.element_at(3)); - - bool thrown = false; - try { q.element_at(5); } catch (std::logic_error&) { thrown = true; } - VERIFY(thrown); - - q.first() = 1; - q.last() = 42; - - // note: because the vector now contains { 1, 1, 2, 3, ... 7, 8, 42 }, the first - // even number is now '2' - VERIFY_EQ(2, q.first()); - VERIFY_EQ(42, q.last()); -} - -//////////////////// New style cursors //////////////////// - -TEST(test_cursor_dynamic) -{ - dynamic_cursor<int> dc(int_iter(0), int_iter(2)); - - VERIFY(!dc.empty()); - VERIFY_EQ(0, dc.get()); - dc.inc(); - VERIFY_EQ(1, dc.get()); - dc.inc(); - VERIFY(dc.empty()); -} - -TEST(test_selectmany) -{ - int_range range1(0, 3); - auto range2 = - - from(range1) - .select_many( - [](int x) - { - return int_range(0, x+1); - }); - - auto cur = range2.get_cursor(); - - // expected: 0, 0, 1, 0, 1, 2. - VERIFY(!cur.empty()); - - VERIFY_EQ(0, cur.get()); - cur.inc(); - VERIFY(!cur.empty()); - - VERIFY_EQ(0, cur.get()); - cur.inc(); - VERIFY(!cur.empty()); - - VERIFY_EQ(1, cur.get()); - cur.inc(); - VERIFY(!cur.empty()); - - VERIFY_EQ(0, cur.get()); - cur.inc(); - VERIFY(!cur.empty()); - - VERIFY_EQ(1, cur.get()); - cur.inc(); - VERIFY(!cur.empty()); - - VERIFY_EQ(2, cur.get()); - cur.inc(); - VERIFY(cur.empty()); -} - -TEST(test_cursor_selectmany2) -{ - int_range range1(0, 3); - auto range2 = from(range1) - .select_many( - [](int x) - { - return int_range(0, x+1); - }); - - // expected: 0, 0, 1, 0, 1, 2. - int expect[] = { 0, 0, 1, 0, 1, 2 }; - - VERIFY_EQ(_countof(expect), std::distance(range2.begin(), range2.end())); - VERIFY_EQ(_countof(expect), std::distance(range2.begin(), range2.end())); - - auto result = std::mismatch(expect, expect + _countof(expect), range2.begin()); - if (result.second != range2.end()) { - cout << "mismatch: " << *result.first << " != " << *result.second << endl; - } - VERIFY( result.second == range2.end()); -} - -TEST(test_late_bind) -{ - int_range range1(0, 100); - linq_driver<dynamic_collection<int>> range2 = from(range1).late_bind(); - - VERIFY_EQ(1, range2.element_at(1)); - - auto q1 = from(range1).select([](int x){ return x*2; }).where([](int x){ return x%10!=0; }); - - cout << "typeof q1 ==> " << typeid(q1).name() << endl; - cout << "typeof q1.late_bind() ==> " << typeid(q1.late_bind()).name() << endl; -} - -struct stopwatch -{ - time_t t0, t1; - void start() { - t1 = t0 = clock(); - } - void stop() { - t1 = clock(); - } - double value() const { - return double(t1-t0)/CLOCKS_PER_SEC; - } -}; - -template <class Fn> -void test_perf(Fn fn) -{ - // warmup - fn(10); - - int n = 100; - stopwatch sw; - for(;;) - { - cout << "trying n=" << n << endl; - sw.start(); - fn(n); - sw.stop(); - if (sw.value() > 2.0) { - break; - } - n *= 2; - } - cout << "time = " << sw.value() << " s\n"; - cout << "steps = " << n << "\n"; - cout << "t/step = " << (sw.value() * 1e9 / n) << " ns\n"; - cout << "step/t = " << (n / sw.value()) << " Hz\n"; -} - -TEST(test_performance) -{ - // http://projecteuler.net/problem=8 - // - // Find the greatest product of five consecutive digits in the 1000-digit number. - // - - static const char num[] = - "73167176531330624919225119674426574742355349194934" - "96983520312774506326239578318016984801869478851843" - "85861560789112949495459501737958331952853208805511" - "12540698747158523863050715693290963295227443043557" - "66896648950445244523161731856403098711121722383113" - "62229893423380308135336276614282806444486645238749" - "30358907296290491560440772390713810515859307960866" - "70172427121883998797908792274921901699720888093776" - "65727333001053367881220235421809751254540594752243" - "52584907711670556013604839586446706324415722155397" - "53697817977846174064955149290862569321978468622482" - "83972241375657056057490261407972968652414535100474" - "82166370484403199890008895243450658541227588666881" - "16427171479924442928230863465674813919123162824586" - "17866458359124566529476545682848912883142607690042" - "24219022671055626321111109370544217506941658960408" - "07198403850962455444362981230987879927244284909188" - "84580156166097919133875499200524063689912560717606" - "05886116467109405077541002256983155200055935729725" - "71636269561882670428252483600823257530420752963450"; - - auto task = [&](int n){ - for (int i = 0; i < n; ++i) { - auto range1 = int_range(0, _countof(num)-5); // 5 digit numbers, plus null terminator - - auto products = from(range1) - .select([&](int i){ return num+i;}) - .where([&](const char* s){ return !from(s, s+5).contains('0'); }) - .select([&](const char* s) { return from(s, s+5).select([](char c){ return c - '0'; }) - .aggregate(std::multiplies<int>()); }); - - auto result = products.max(); - if (n == 1) { - cout << "result = " << result << endl; - } - } - }; - cout << "length of input: " << (_countof(num)-1) << endl; - - task(1); - cout << endl; - -#ifdef PERF - test_perf(task); - cout << endl; -#endif -} - -// SUM TESTS - -TEST(test_sum_ints) -{ - vector<int> numbers{1, 2, 3, 4, 5}; - - auto result = cpplinq::from(numbers); - auto r2 = result.sum(); - - VERIFY_EQ(15, r2); -} - -TEST(test_sum_ints_with_seed) -{ - vector<int> numbers{1, 2, 3, 4, 5}; - - auto result = cpplinq::from(numbers).sum(10); - - VERIFY_EQ(25, result); -} - -TEST(test_sum_floats) { - vector<float> numbers{ 1.0f,2.0f,3.0f,4.0f,5.0f }; - - auto result = cpplinq::from(numbers).sum(); - - VERIFY_EQ(15.0f, result); -} - -TEST(test_sum_doubles) { - vector<double> numbers { 1.0,2.0,3.0,4.0,5.0 }; - - auto result = cpplinq::from(numbers).sum(); - - VERIFY_EQ(15.0, result); -} - -TEST(test_sum_complex) { - using namespace std::complex_literals; - - vector<complex<double>> numbers{ 1i, 1.0 + 2i, 2.0 + 3i }; - - auto sum = cpplinq::from(numbers).sum(); - - VERIFY_EQ(3.0, sum.real()); - VERIFY_EQ(6.0, sum.imag()); -} - -TEST(test_sum_with_projection_lambda) { - vector<tuple<int>> numbers { std::tuple<int>(0), std::tuple<int>(1), std::tuple<int>(2) }; - - auto result = cpplinq::from(numbers).sum([](std::tuple<int>& x){ - return std::get<0>(x); - }); - - VERIFY_EQ(3.0, result); -} - -TEST(test_sum_with_projection_lambda_and_seed) { - vector<tuple<int>> numbers { std::tuple<int>(0), std::tuple<int>(1), std::tuple<int>(2) }; - - auto result = cpplinq::from(numbers).sum([](std::tuple<int>& x){ - return std::get<0>(x); - }, 10); - - VERIFY_EQ(13.0, result); -} - -int getValue(std::tuple<int> x) -{ - return std::get<0>(x); -} - -TEST(test_sum_with_projection_function_pointer) { - vector<tuple<int>> numbers { std::tuple<int>(0), std::tuple<int>(1), std::tuple<int>(2) }; - - auto result = cpplinq::from(numbers).sum(getValue); - - VERIFY_EQ(3.0, result); -} - -int main(int argc, char** argv) -{ - std::size_t pass = 0, fail = 0; - testrange<0,__LINE__>().run(pass, fail); - - - cout << "pass: " << pass << ", fail: " << fail << endl; - if (fail){ - cerr << "ERRORS PRESENT." << endl; - } else if (!pass) { - cerr << "ERROR, no tests run" << endl; - } -} |