#include "iterator/indexed_iterator.h" #include #include #include "iterator/end_aware_iterator.h" #include "ranges.h" #include "xcode_gtest_helper.h" using iterator::end_aware_iterator; using iterator::indexed_iterator; 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(IndexedIteratorTest, CanCastCompatibleIterators) { std::vector v{1, 2, 3, 4, 5}; indexed_iterator eai(v.begin()); indexed_iterator::const_iterator>{eai}; } TEST(IndexedIteratorTest, CanLieAboutIndex) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; indexed_iterator it(vec.begin(), 3); EXPECT_THAT(it->first, 3); } TEST(IndexedIteratorTest, FakeIndexDoesntEffectEqualityCheck) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; EXPECT_THAT(indexed_iterator(vec.begin()), indexed_iterator(vec.begin(), 3)); EXPECT_THAT(indexed_iterator(vec.begin()) + 3, Ne(indexed_iterator(vec.begin(), 3))); } TEST(IndexedIteratorTest, DoesNotTrackByIndex) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; indexed_iterator end(vec.end()); EXPECT_THAT(decltype(end){}, Ne(end)); } TEST(IndexedIteratorTest, IteratorPropagatesAtEnd) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; indexed_iterator end(end_aware_iterator(vec.end(), vec.end())); EXPECT_EQ(end, iterator::sentinel); } TEST(IndexedIteratorTest, CanCompareIteratorOrder) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; indexed_iterator const begin(vec.begin()); indexed_iterator 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(IndexedIteratorTest, PreIncrementAdvancesIterator) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; indexed_iterator it(vec.begin() + 1); EXPECT_THAT(it->second, 3); EXPECT_THAT((++it)->second, 2); EXPECT_THAT(it->second, 2); } TEST(IndexedIteratorTest, PostIncrementReturnsCopyOfPrev) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; indexed_iterator it(vec.begin() + 1); EXPECT_THAT(it->second, 3); EXPECT_THAT((it++)->second, 3); EXPECT_THAT(it->second, 2); } TEST(IndexedIteratorTest, PreDecrementAdvancesIterator) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; indexed_iterator it(vec.begin() + 1); EXPECT_THAT(it->second, 3); EXPECT_THAT((--it)->second, 5); EXPECT_THAT(it->second, 5); } TEST(IndexedIteratorTest, PostDecrementReturnsCopyOfPrev) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; indexed_iterator it(vec.begin() + 1); EXPECT_THAT(it->second, 3); EXPECT_THAT((it--)->second, 3); EXPECT_THAT(it->second, 5); } TEST(IndexedIteratorTest, CanWalkNStepsForward) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; indexed_iterator const begin(vec.begin()); indexed_iterator it = begin; it += 4; EXPECT_THAT(ranges::distance(begin, it), 4); } TEST(IndexedIteratorTest, CanWalkNStepsBackwards) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; indexed_iterator const end(vec.end()); indexed_iterator it = end; it -= 4; EXPECT_THAT(ranges::distance(it, end), 4); } TEST(IndexedIteratorTest, RandomAccessIsPassthrough) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; EXPECT_THAT(indexed_iterator(vec.begin()) + 4, indexed_iterator(vec.begin() + 4)); EXPECT_THAT(indexed_iterator(vec.end()) - 4, indexed_iterator(vec.end() - 4)); } TEST(IndexedIteratorTest, 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(indexed_iterator(vec.begin()), indexed_iterator(vec.end())); EXPECT_THAT(result, expected); } TEST(IndexedIteratorTest, 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(indexed_iterator(vec.begin()), indexed_iterator(vec.end())); EXPECT_THAT(result, expected); } TEST(IndexedIteratorTest, CanMutatePointedToData) { std::vector vec{5, 3, 2, 8, 9, 11, 2, 4}; indexed_iterator(vec.begin() + 4, 4)->second = -1; EXPECT_THAT(vec[4], -1); }