#include "iterator/enumerate_iterator.h" #include #include #include "iterator/end_aware_iterator.h" #include "ranges.h" #include "xcode_gtest_helper.h" using iterator::EndAwareIterator; using iterator::EnumerateIterator; using testing::Ge; using testing::Gt; using testing::Le; using testing::Lt; using testing::Ne; // TODO: This ought to be implemented as a compiles-test TEST(EnumerateIteartor, CanCastCompatibleIterators) { std::vector v{1, 2, 3, 4, 5}; EnumerateIterator eai(v.begin()); EnumerateIterator::const_iterator>{eai}; } TEST(EnumerateIteartor, CanLieAboutIndex) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; EnumerateIterator it(vec.begin(), 3); EXPECT_THAT(it->first, 3); } TEST(EnumerateIteartor, FakeIndexDoesntEffectEqualityCheck) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; EXPECT_THAT(EnumerateIterator(vec.begin()), EnumerateIterator(vec.begin(), 3)); EXPECT_THAT(EnumerateIterator(vec.begin()) + 3, Ne(EnumerateIterator(vec.begin(), 3))); } TEST(EnumerateIteartor, DoesNotTrackByIndex) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; EnumerateIterator end(vec.end()); EXPECT_THAT(decltype(end){}, Ne(end)); } TEST(EnumerateIteartor, IteratorPropagatesAtEnd) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; EnumerateIterator end(EndAwareIterator(vec.end(), vec.end())); EXPECT_THAT(end, iterator::sentinel); } TEST(EnumerateIteartor, CanCompareIteratorOrder) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; EnumerateIterator const begin(vec.begin()); EnumerateIterator const it = begin + 3; EXPECT_THAT(begin, Lt(it)); EXPECT_THAT(begin, Le(it)); EXPECT_THAT(it, Le(it)); EXPECT_THAT(it, Gt(begin)); EXPECT_THAT(it, Ge(begin)); EXPECT_THAT(it, Ge(it)); } TEST(EnumerateIteartor, PreIncrementAdvancesIterator) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; EnumerateIterator it(vec.begin() + 1); EXPECT_THAT(it->second, 3); EXPECT_THAT((++it)->second, 2); EXPECT_THAT(it->second, 2); } TEST(EnumerateIteartor, PostIncrementReturnsCopyOfPrev) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; EnumerateIterator it(vec.begin() + 1); EXPECT_THAT(it->second, 3); EXPECT_THAT((it++)->second, 3); EXPECT_THAT(it->second, 2); } TEST(EnumerateIteartor, PreDecrementAdvancesIterator) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; EnumerateIterator it(vec.begin() + 1); EXPECT_THAT(it->second, 3); EXPECT_THAT((--it)->second, 5); EXPECT_THAT(it->second, 5); } TEST(EnumerateIteartor, PostDecrementReturnsCopyOfPrev) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; EnumerateIterator it(vec.begin() + 1); EXPECT_THAT(it->second, 3); EXPECT_THAT((it--)->second, 3); EXPECT_THAT(it->second, 5); } TEST(EnumerateIteartor, CanWalkNStepsForward) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; EnumerateIterator const begin(vec.begin()); EnumerateIterator it = begin; it += 4; EXPECT_THAT(ranges::distance(begin, it), 4); } TEST(EnumerateIteartor, CanWalkNStepsBackwards) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; EnumerateIterator const end(vec.end()); EnumerateIterator it = end; it -= 4; EXPECT_THAT(ranges::distance(it, end), 4); } TEST(EnumerateIteartor, RandomAccessIsPassthrough) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; EXPECT_THAT(EnumerateIterator(vec.begin()) + 4, EnumerateIterator(vec.begin() + 4)); EXPECT_THAT(EnumerateIterator(vec.end()) - 4, EnumerateIterator(vec.end() - 4)); } TEST(EnumerateIteartor, TreatsVectorIteratorAsPairIdxValue) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; std::vector> const expected{ {0, 5}, {1, 3}, {2, 2}, {3, 8}, {4, 9}, {5, 11}, {6, 2}, {7, 4}}; std::vector> const result(EnumerateIterator(vec.begin()), EnumerateIterator(vec.end())); EXPECT_THAT(result, expected); } TEST(EnumerateIteartor, TreatsVectorIteratorAsMapIdxToValue) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; std::map const expected{{0, 5}, {1, 3}, {2, 2}, {3, 8}, {4, 9}, {5, 11}, {6, 2}, {7, 4}}; std::map const result(EnumerateIterator(vec.begin()), EnumerateIterator(vec.end())); EXPECT_THAT(result, expected); } TEST(EnumerateIteartor, CanMutatePointedToData) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; EnumerateIterator(vec.begin() + 4, 4)->second = -1; EXPECT_THAT(vec[4], -1); }