// Copyright (c) 2016 Google Inc. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and/or associated documentation files (the // "Materials"), to deal in the Materials without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Materials, and to // permit persons to whom the Materials are furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Materials. // // MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS // KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS // SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT // https://www.khronos.org/registry/ // // THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. #include #include #include "gmock/gmock.h" #include "opt/iterator.h" namespace { using namespace spvtools; 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)); } ir::UptrVectorIterator it(&data, data.begin()); ir::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)); } ir::UptrVectorIterator begin(&data, data.begin()); ir::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)); } ir::UptrVectorIterator it(&data, data.begin()); ir::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)); } ir::UptrVectorIterator begin(&data, data.begin()); ir::UptrVectorIterator end(&data, data.end()); ir::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)); } ir::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)); } ir::UptrVectorIterator it(&data, data.begin()); ir::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); ir::UptrVectorIterator begin(&data, data.begin()); auto insert_point = begin.InsertBefore(std::unique_ptr(new int(-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); ir::UptrVectorIterator end(&data, data.end()); end = end.InsertBefore(std::unique_ptr(new int(-77))); end = end.InsertBefore(std::unique_ptr(new int(-36))); end = end.InsertBefore(std::unique_ptr(new int(-42))); actual.clear(); begin = ir::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); ir::UptrVectorIterator it(&data, data.begin()); for (int i = 0; i < insert_pos; ++i) ++it; it = it.InsertBefore(std::unique_ptr(new int(-100))); it = it.InsertBefore(std::unique_ptr(new int(-42))); auto begin = ir::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 = ir::UptrVectorIterator(&data, data.begin()); auto e = ir::UptrVectorIterator(&data, data.end()); auto range = ir::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()); } } // anonymous namespace