// Copyright (c) 2016 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include "gmock/gmock.h" #include "source/opt/iterator.h" #include "source/util/make_unique.h" namespace spvtools { namespace opt { namespace { using ::testing::ContainerEq; TEST(Iterator, IncrementDeref) { const int count = 100; std::vector> data; for (int i = 0; i < count; ++i) { data.emplace_back(new int(i)); } UptrVectorIterator it(&data, data.begin()); UptrVectorIterator end(&data, data.end()); EXPECT_EQ(*data[0], *it); for (int i = 1; i < count; ++i) { EXPECT_NE(end, it); EXPECT_EQ(*data[i], *(++it)); } EXPECT_EQ(end, ++it); } TEST(Iterator, DecrementDeref) { const int count = 100; std::vector> data; for (int i = 0; i < count; ++i) { data.emplace_back(new int(i)); } UptrVectorIterator begin(&data, data.begin()); UptrVectorIterator it(&data, data.end()); for (int i = count - 1; i >= 0; --i) { EXPECT_NE(begin, it); EXPECT_EQ(*data[i], *(--it)); } EXPECT_EQ(begin, it); } TEST(Iterator, PostIncrementDeref) { const int count = 100; std::vector> data; for (int i = 0; i < count; ++i) { data.emplace_back(new int(i)); } UptrVectorIterator it(&data, data.begin()); UptrVectorIterator end(&data, data.end()); for (int i = 0; i < count; ++i) { EXPECT_NE(end, it); EXPECT_EQ(*data[i], *(it++)); } EXPECT_EQ(end, it); } TEST(Iterator, PostDecrementDeref) { const int count = 100; std::vector> data; for (int i = 0; i < count; ++i) { data.emplace_back(new int(i)); } UptrVectorIterator begin(&data, data.begin()); UptrVectorIterator end(&data, data.end()); UptrVectorIterator it(&data, data.end()); EXPECT_EQ(end, it--); for (int i = count - 1; i >= 1; --i) { EXPECT_EQ(*data[i], *(it--)); } // Decrementing .begin() is undefined behavior. EXPECT_EQ(*data[0], *it); } TEST(Iterator, Access) { const int count = 100; std::vector> data; for (int i = 0; i < count; ++i) { data.emplace_back(new int(i)); } UptrVectorIterator it(&data, data.begin()); for (int i = 0; i < count; ++i) EXPECT_EQ(*data[i], it[i]); } TEST(Iterator, Comparison) { const int count = 100; std::vector> data; for (int i = 0; i < count; ++i) { data.emplace_back(new int(i)); } UptrVectorIterator it(&data, data.begin()); UptrVectorIterator end(&data, data.end()); for (int i = 0; i < count; ++i, ++it) EXPECT_TRUE(it < end); EXPECT_EQ(end, it); } TEST(Iterator, InsertBeginEnd) { const int count = 100; std::vector> data; std::vector expected; std::vector actual; for (int i = 0; i < count; ++i) { data.emplace_back(new int(i)); expected.push_back(i); } // Insert at the beginning expected.insert(expected.begin(), -100); UptrVectorIterator begin(&data, data.begin()); auto insert_point = begin.InsertBefore(MakeUnique(-100)); for (int i = 0; i < count + 1; ++i) { actual.push_back(*(insert_point++)); } EXPECT_THAT(actual, ContainerEq(expected)); // Insert at the end expected.push_back(-42); expected.push_back(-36); expected.push_back(-77); UptrVectorIterator end(&data, data.end()); end = end.InsertBefore(MakeUnique(-77)); end = end.InsertBefore(MakeUnique(-36)); end = end.InsertBefore(MakeUnique(-42)); actual.clear(); begin = UptrVectorIterator(&data, data.begin()); for (int i = 0; i < count + 4; ++i) { actual.push_back(*(begin++)); } EXPECT_THAT(actual, ContainerEq(expected)); } TEST(Iterator, InsertMiddle) { const int count = 100; std::vector> data; std::vector expected; std::vector actual; for (int i = 0; i < count; ++i) { data.emplace_back(new int(i)); expected.push_back(i); } const int insert_pos = 42; expected.insert(expected.begin() + insert_pos, -100); expected.insert(expected.begin() + insert_pos, -42); UptrVectorIterator it(&data, data.begin()); for (int i = 0; i < insert_pos; ++i) ++it; it = it.InsertBefore(MakeUnique(-100)); it = it.InsertBefore(MakeUnique(-42)); auto begin = UptrVectorIterator(&data, data.begin()); for (int i = 0; i < count + 2; ++i) { actual.push_back(*(begin++)); } EXPECT_THAT(actual, ContainerEq(expected)); } TEST(IteratorRange, Interface) { const uint32_t count = 100; std::vector> data; for (uint32_t i = 0; i < count; ++i) { data.emplace_back(new uint32_t(i)); } auto b = UptrVectorIterator(&data, data.begin()); auto e = UptrVectorIterator(&data, data.end()); auto range = IteratorRange(b, e); EXPECT_EQ(b, range.begin()); EXPECT_EQ(e, range.end()); EXPECT_FALSE(range.empty()); EXPECT_EQ(count, range.size()); EXPECT_EQ(0u, *range.begin()); EXPECT_EQ(99u, *(--range.end())); // IteratorRange itself is immutable. ++b, --e; EXPECT_EQ(count, range.size()); ++range.begin(), --range.end(); EXPECT_EQ(count, range.size()); } TEST(Iterator, FilterIterator) { struct Placeholder { int val; }; std::vector data = {{1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}}; // Predicate to only consider odd values. struct Predicate { bool operator()(const Placeholder& data) { return data.val % 2; } }; Predicate pred; auto filter_range = MakeFilterIteratorRange(data.begin(), data.end(), pred); EXPECT_EQ(filter_range.begin().Get(), data.begin()); EXPECT_EQ(filter_range.end(), filter_range.begin().GetEnd()); for (Placeholder& data : filter_range) { EXPECT_EQ(data.val % 2, 1); } for (auto it = filter_range.begin(); it != filter_range.end(); it++) { EXPECT_EQ(it->val % 2, 1); EXPECT_EQ((*it).val % 2, 1); } for (auto it = filter_range.begin(); it != filter_range.end(); ++it) { EXPECT_EQ(it->val % 2, 1); EXPECT_EQ((*it).val % 2, 1); } EXPECT_EQ(MakeFilterIterator(data.begin(), data.end(), pred).Get(), data.begin()); EXPECT_EQ(MakeFilterIterator(data.end(), data.end(), pred).Get(), data.end()); EXPECT_EQ(MakeFilterIterator(data.begin(), data.end(), pred).GetEnd(), MakeFilterIterator(data.end(), data.end(), pred)); EXPECT_NE(MakeFilterIterator(data.begin(), data.end(), pred), MakeFilterIterator(data.end(), data.end(), pred)); // Empty range: no values satisfies the predicate. auto empty_range = MakeFilterIteratorRange( data.begin(), data.end(), [](const Placeholder& data) { return data.val > 10; }); EXPECT_EQ(empty_range.begin(), empty_range.end()); } } // namespace } // namespace opt } // namespace spvtools