#include "iterator/recursive_iterator.h" #include #include #include #include #include "ranges.h" #include "xcode_gtest_helper.h" using iterator::bounded; using iterator::EndAwareIterator; using iterator::RecursiveIterator; using testing::ElementsAreArray; using testing::Not; using testing::StaticAssertTypeEq; TEST(RecursiveIterator, DoesNotUnwrapString) { std::vector obj{"A", "B", "C", "D"}; auto rit = RecursiveIterator(obj); StaticAssertTypeEq()), std::string *>(); EXPECT_THAT(obj | views::recursive | ranges::to(), ElementsAreArray(obj)); } TEST(RecursiveIterator, CanArrowMultiVector) { std::vector> obj{{{0, 1}}, {{2, 3}}}; auto rit = RecursiveIterator(obj); StaticAssertTypeEq()), int *>(); EXPECT_THAT(rit.operator->(), &obj[0][0]); } TEST(RecursiveIterator, CanAccessOuterterator) { std::map> obj{{1, {{0, 1}}}, {2, {{2, 3}}}}; auto rit = RecursiveIterator(obj); EndAwareIterator inner = rit; EXPECT_THAT(&std::get<0>(*rit), &(inner->first)); } TEST(RecursiveIterator, CanAccessInnerIterator) { std::map> obj{{1, {{0, 1}}}, {2, {{2, 3}}}}; auto rit = RecursiveIterator(obj); EndAwareIterator::iterator> inner = rit; EXPECT_THAT(&std::get<1>(*rit), &*inner); } TEST(RecursiveIterator, CanStdGetToAllLayersOfInternalIteration) { std::map>> obj{ {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps {2, {{{3, 3}, {4, 4}}}} // 1 2-element map }; auto rit = RecursiveIterator(obj); using mvm_iterator = std::map>>::iterator; StaticAssertTypeEq(rit)), EndAwareIterator>(); using vm_iterator = std::vector>::iterator; StaticAssertTypeEq(rit)), EndAwareIterator>(); using m_iterator = std::map::iterator; StaticAssertTypeEq(rit)), EndAwareIterator>(); using tup_i_i_i = std::tuple; StaticAssertTypeEq(); } TEST(RecursiveIterator, CanAccessInternalIteratorsWithGet) { std::map>> obj{ {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps {2, {{{3, 3}, {4, 4}}}} // 1 2-element map }; auto rit = RecursiveIterator(obj); EXPECT_THAT(std::get<0>(rit), EndAwareIterator(obj)); EXPECT_THAT(std::get<1>(rit), EndAwareIterator(obj[1])); EXPECT_THAT(std::get<2>(rit), EndAwareIterator(obj[1][0])); } // TODO: This ought to be implemented as a compiles-test TEST(RecursiveIterator, CanCastCompatibleIterators) { std::map>> obj{ {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps {2, {{{3, 3}, {4, 4}}}} // 1 2-element map }; auto rit = RecursiveIterator(obj); iterator::RecursiveIterator cit(rit); } TEST(RecursiveIterator, EmptyCtorIsEnd) { std::map>> obj{ {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps {2, {{{3, 3}, {4, 4}}}} // 1 2-element map }; auto rit = RecursiveIterator(obj); EXPECT_THAT(rit, Not(iterator::sentinel)); EXPECT_THAT(ranges::distance(rit, iterator::sentinel), 4); std::advance(rit, 4); EXPECT_THAT(rit, iterator::sentinel); } TEST(RecursiveIterator_Bounded, CanStdGetToNLayersOfInternalIteration) { std::map>> obj{ {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps {2, {{{3, 3}, {4, 4}}}} // 1 2-element map }; auto rit = RecursiveIterator(obj, bounded<2>{}); using mvm_iterator = std::map>>::iterator; StaticAssertTypeEq(rit)), EndAwareIterator>(); using vm_iterator = std::vector>::iterator; StaticAssertTypeEq(rit)), EndAwareIterator>(); using tup_i_mii = std::tuple &>; StaticAssertTypeEq(); } TEST(RecursiveIterator_Bounded, CanAccessInternalIteratorsWithGet) { std::map>> obj{ {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps {2, {{{3, 3}, {4, 4}}}} // 1 2-element map }; auto rit = RecursiveIterator(obj, bounded<2>{}); EXPECT_THAT(std::get<0>(rit), EndAwareIterator(obj)); EXPECT_THAT(std::get<1>(rit), EndAwareIterator(obj[1])); } // TODO: This ought to be implemented as a compiles-test TEST(RecursiveIterator_Bounded, CanCastCompatibleIterators) { std::map>> obj{ {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps {2, {{{3, 3}, {4, 4}}}} // 1 2-element map }; auto rit = RecursiveIterator(obj, bounded<2>{}); iterator::RecursiveIteratorN cit(rit); } TEST(RecursiveIterator_Bounded, EmptyCtorIsEnd) { std::map>> obj{ {1, {{{1, 1}}, {{2, 2}}}}, // 2 1-element maps {2, {{{3, 3}, {4, 4}}}} // 1 2-element map }; auto rit = RecursiveIterator(obj, bounded<3>{}); EXPECT_THAT(rit, Not(iterator::sentinel)); EXPECT_THAT(ranges::distance(rit, iterator::sentinel), 4); std::advance(rit, 4); EXPECT_THAT(rit, iterator::sentinel); } TEST(RecursiveIterator_Bounded, CanFetchInnerCollections) { std::vector>> obj{ {{{{1, 1}}, {{2, 2}}}}, // 2 1-element maps {{{{3, 3}, {4, 4}}}} // 1 2-element map }; auto rit = RecursiveIterator(obj, bounded<2>{}); EXPECT_THAT(*rit, obj[0][0]); }