// // stream_td.hpp // stream // // Created by Sam Jaffe on 1/28/17. // #include #include #include #include "stream/streams.hpp" using ::testing::Eq; // Workaround for OSX and pointer-to-member-functions template class std::basic_string; using int_t = int const &; TEST(StreamTest, IteratorPreservesElements) { std::vector v{1, 2, 3, 4, 5}; auto s = stream::make_stream(v); std::vector o{s.begin(), s.end()}; EXPECT_THAT(v, o); } TEST(StreamTest, CollectPreservesElements) { std::vector v{1, 2, 3, 4, 5}; auto s = stream::make_stream(v); std::vector o{s.begin(), s.end()}; std::vector o2{s.collect()}; EXPECT_THAT(v, o); EXPECT_THAT(v, o2); } TEST(StreamTest, CollectToObjectPreservesElements) { std::vector v{1, 2, 3, 4, 5}; auto s = stream::make_stream(v); std::set o{}; s.collect(o); for (int i : v) { EXPECT_THAT(o.count(i), Eq(1)); } } TEST(StreamTest, MapToSelfIsSelfs) { std::vector v{1, 2, 3, 4, 5}; auto identity = [](int_t i) { return i; }; auto s = stream::make_stream(v).map( identity ); std::vector o{s.begin(), s.end()}; EXPECT_THAT(v, o); } TEST(StreamTest, MapCanAlterValues) { std::vector v{1, 2, 3, 4, 5}; std::vector expected{3, 5, 7, 9, 11}; auto fmap = [](int_t i) { return 2*i+1; }; auto s = stream::make_stream(v).map( fmap ); std::vector o{s.begin(), s.end()}; EXPECT_THAT(expected, o); } TEST(StreamTest, CanBuildFromSingleElement) { int_t value = 11; auto even = [](int_t i) { return i%2==0; }; auto s = stream::make_stream(&value).filter( even ); EXPECT_TRUE(s.empty()); } TEST(StreamTest, CanBuildFromIterators) { std::vector v{1, 2, 3, 4, 5}; std::vector 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); std::vector o{s.begin(), s.end()}; EXPECT_THAT(o, Eq(expected)); } TEST(StreamTest, NoOpFilterReturnOriginal) { std::vector v{1, 2, 3, 4, 5}; auto pass = [](int_t) { return true; }; auto s = stream::make_stream(v).filter( pass ); std::vector o{s.begin(), s.end()}; EXPECT_THAT(o, Eq(v)); } TEST(StreamTest, CanFilterOutElements) { std::vector v{1, 2, 3, 4, 5}; std::vector expected{2, 4}; auto even = [](int_t i) { return i%2 == 0; }; auto s = stream::make_stream(v).filter(even); std::vector o{s.begin(), s.end()}; EXPECT_THAT(o, Eq(expected)); } TEST(StreamTest, AccumulateDefaultsToAdd) { std::vector v{1, 2, 3, 4, 5}; auto even = [](int_t i) { return i%2 == 0; }; auto s = stream::make_stream(v).filter( even ); EXPECT_THAT(s.accumulate(0), Eq(6)); } TEST(StreamTest, AccumulateCanTakeCustomAccumulator) { std::vector 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); EXPECT_THAT(s.accumulate(prod, 0), Eq(0)); EXPECT_THAT(s.accumulate(prod, 1), Eq(8)); } TEST(StreamTest, FlatmapJoinsIterableOutputs) { std::vector vv{1, 2, 3, 4, 5}; auto next3 = [](int_t i) { return std::vector{i, i+1, i+2}; }; std::vector expected{1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 6, 5, 6, 7}; auto s = stream::make_stream(vv).flatmap(next3); std::vector o{s.begin(), s.end()}; EXPECT_THAT(o, Eq(expected)); } TEST(StreamTest, CanDereferenceElements) { int val = 5; std::vector v{&val}; auto data = stream::make_stream(v).deref().collect(); EXPECT_THAT(data.front(), val); } TEST(StreamTest, CanForEachConsume) { int hits = 0; std::vector v{1, 2, 3, 4, 5}; stream::make_stream(v).each([&hits](int_t){ ++hits; }); EXPECT_THAT(hits, 5); } TEST(StreamTest, CanFetchMemPtr) { struct test { int val; }; std::vector v{{1}, {3}, {2}}; std::vector expected{1, 3, 2}; auto out = stream::make_stream(v).map(&test::val).collect(); EXPECT_THAT(out, Eq(expected)); } TEST(StreamTest, CanMapToMemFn) { std::vector v{"hello", "goodbye"}; std::vector expected{5, 7}; auto out = stream::make_stream(v).map(&std::string::size).collect(); EXPECT_THAT(out, Eq(expected)); } TEST(StreamTest, CastStreamToParentType) { 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(); EXPECT_THAT(first, second); }