// // stream_td.hpp // stream // // Created by Sam Jaffe on 1/28/17. // #pragma once #include #include #include #include "streams.hpp" // Workaround for OSX and pointer-to-member-functions template class std::basic_string; class stream_TestSuite : public CxxTest::TestSuite { public: using int_t = int const &; using vec_t = std::vector; public: void test_preserved() { vec_t v{1, 2, 3, 4, 5}; auto s = stream::make_stream(v); vec_t o{s.begin(), s.end()}; TS_ASSERT_EQUALS(v, o); } void test_collect_preserves() { vec_t v{1, 2, 3, 4, 5}; auto s = stream::make_stream(v); vec_t o{s.begin(), s.end()}; vec_t o2{s.collect()}; TS_ASSERT_EQUALS(v, o); TS_ASSERT_EQUALS(v, o2); } void test_collect_arg_preserves() { vec_t v{1, 2, 3, 4, 5}; auto s = stream::make_stream(v); std::set o{}; s.collect(o); for ( int i : v ) { TS_ASSERT_EQUALS(o.count( i ), 1); } } void test_map_identity() { vec_t v{1, 2, 3, 4, 5}; auto identity = [](int_t i) { return i; }; auto s = stream::make_stream(v).map( identity ); vec_t o{s.begin(), s.end()}; TS_ASSERT_EQUALS(v, o); } void test_map_change() { vec_t v{1, 2, 3, 4, 5}; vec_t expected{3, 5, 7, 9, 11}; auto fmap = [](int_t i) { return 2*i+1; }; auto s = stream::make_stream(v).map( fmap ); vec_t o{s.begin(), s.end()}; TS_ASSERT_EQUALS(expected, o); } void test_singleton_stream() { int_t value = 11; auto even = [](int_t i) { return i%2==0; }; auto s = stream::make_stream(&value).filter( even ); TS_ASSERT(s.empty()); } void test_stream_on_subrange() { vec_t v{1, 2, 3, 4, 5}; vec_t expected{5, 7}; auto fmap = [](int_t i) { return 2*i+1; }; auto s = stream::make_stream(v.begin()+1, v.begin()+3).map( fmap ); vec_t o{s.begin(), s.end()}; TS_ASSERT_EQUALS(expected, o); } void test_filter_noop() { vec_t v{1, 2, 3, 4, 5}; auto pass = [](int_t) { return true; }; auto s = stream::make_stream(v).filter( pass ); vec_t o{s.begin(), s.end()}; TS_ASSERT_EQUALS(v, o); } void test_filter_value() { vec_t v{1, 2, 3, 4, 5}; vec_t expected{2, 4}; auto even = [](int_t i) { return i%2 == 0; }; auto s = stream::make_stream(v).filter( even ); vec_t o{s.begin(), s.end()}; TS_ASSERT_EQUALS(expected, o); } void test_accumulate() { vec_t v{1, 2, 3, 4, 5}; auto even = [](int_t i) { return i%2 == 0; }; auto s = stream::make_stream(v).filter( even ); TS_ASSERT_EQUALS( 6 , s.accumulate(0) ); } void test_accumulate_custom_function() { vec_t v{1, 2, 3, 4, 5}; auto even = [](int_t i) { return i%2 == 0; }; auto prod =[](int_t lhs, int_t rhs) { return lhs * rhs; }; auto s = stream::make_stream(v).filter( even ); TS_ASSERT_EQUALS( 8 , s.accumulate(prod, 1) ); } void test_flatmap_joins_lists() { vec_t vv{1, 2, 3, 4, 5}; auto next3 = [](int_t i) { return vec_t{i, i+1, i+2}; }; vec_t expected{1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 6, 5, 6, 7}; auto s = stream::make_stream(vv).flatmap( next3 ); vec_t o{s.begin(), s.end()}; TS_ASSERT_EQUALS(expected, o); } void test_dereference() { int val = 5; std::vector v{&val}; auto data = stream::make_stream(v).deref().collect(); TS_ASSERT_EQUALS(data.front(), val); } void test_foreach() { int hits = 0; vec_t v{1, 2, 3, 4, 5}; stream::make_stream(v).each([&hits](int_t){ ++hits; }); TS_ASSERT_EQUALS(hits, 5); } void test_getmember() { struct test { int val; }; std::vector v{{1}, {3}, {2}}; vec_t expected{1, 3, 2}; auto out = stream::make_stream(v).map(&test::val).collect(); TS_ASSERT_EQUALS(out, expected); } void test_memberfunction() { std::vector v{"hello", "goodbye"}; std::vector expected{5, 7}; auto out = stream::make_stream(v).map(&std::string::size).collect(); TS_ASSERT_EQUALS(out, expected); } void test_cast() { struct base { char cat[4] = "cat"; }; struct test : base { test(int v) : val(v) {} int val; }; std::vector v{{1}, {3}, {2}}; auto strm = stream::make_stream(v).cast(); auto first = stream::make_stream(v).map([](test const & t) { return (void*)&t; }).collect(); auto second = strm.map([](base const & t) { return (void*)&t; }).collect(); TS_ASSERT_EQUALS(first, second); } };