| // Copyright 2016 The Android Open Source Project |
| // |
| // This software is licensed under the terms of the GNU General Public |
| // License version 2, as published by the Free Software Foundation, and |
| // may be copied, distributed, and modified under those terms. |
| // |
| // This program is distributed in the hope that it will be useful, |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| // GNU General Public License for more details. |
| |
| #include "android/base/containers/SmallVector.h" |
| |
| #include "android/base/memory/ScopedPtr.h" |
| #include "android/base/testing/GTestUtils.h" |
| |
| #include <gtest/gtest.h> |
| |
| #include <string> |
| |
| namespace android { |
| namespace base { |
| |
| TEST(SmallVector, basic) { |
| SmallFixedVector<char, 10> sv; |
| EXPECT_EQ(sv.size(), 0); |
| EXPECT_TRUE(sv.empty()); |
| |
| EXPECT_EQ(10, sv.capacity()); |
| EXPECT_FALSE(sv.isAllocated()); |
| |
| const int values[] = {1, 2, 3}; |
| sv = SmallFixedVector<char, 10>(values, values + 3); |
| EXPECT_EQ(3, sv.size()); |
| EXPECT_FALSE(sv.empty()); |
| EXPECT_EQ(10, sv.capacity()); |
| EXPECT_FALSE(sv.isAllocated()); |
| EXPECT_TRUE(RangesMatch(values, sv)); |
| |
| sv.clear(); |
| EXPECT_EQ(0, sv.size()); |
| EXPECT_TRUE(sv.empty()); |
| |
| const char str[] = "this is a long string for insertion"; |
| sv = SmallFixedVector<char, 10>(str); |
| EXPECT_EQ(sizeof(str), sv.size()); |
| EXPECT_GT(sv.capacity(), 10); |
| EXPECT_TRUE(sv.isAllocated()); |
| EXPECT_TRUE(RangesMatch(str, sv)); |
| |
| // make sure explicit loops over indices and iterators work |
| for (size_t i = 0; i != sv.size(); ++i) { |
| EXPECT_EQ(str[i], sv[i]); |
| } |
| const char* c = str; |
| for (auto i : sv) { |
| EXPECT_EQ(*c++, i); |
| } |
| c = str; |
| for (auto it = sv.begin(); it != sv.end(); ++it, ++c) { |
| EXPECT_EQ(*c, *it); |
| } |
| |
| c = str; |
| for (auto it = sv.data(); it != sv.data() + sv.size(); ++it, ++c) { |
| EXPECT_EQ(*c, *it); |
| } |
| } |
| |
| TEST(SmallVector, ctor) { |
| { |
| SmallFixedVector<int, 1> sv; |
| EXPECT_EQ(sv.size(), 0); |
| } |
| |
| { |
| const int values[] = {1, 2, 3}; |
| SmallFixedVector<int, 10> sv(values, values + 3); |
| EXPECT_TRUE(RangesMatch(values, sv)); |
| } |
| |
| { |
| const int values[] = {1, 2, 3}; |
| SmallFixedVector<int, 10> sv(values); |
| EXPECT_TRUE(RangesMatch(values, sv)); |
| } |
| |
| { |
| const int values[] = {1, 2, 3}; |
| SmallFixedVector<int, 10> sv(values); |
| EXPECT_TRUE(RangesMatch(values, sv)); |
| } |
| |
| { |
| const int values[] = {1, 2, 3}; |
| SmallFixedVector<int, 10> sv = {1, 2, 3}; |
| EXPECT_TRUE(RangesMatch(values, sv)); |
| } |
| |
| { |
| const int values[] = {1, 2, 3}; |
| SmallFixedVector<int, 10> sv1(values); |
| SmallFixedVector<int, 10> sv2(sv1); |
| |
| EXPECT_TRUE(RangesMatch(values, sv1)); |
| EXPECT_TRUE(RangesMatch(sv2, sv1)); |
| |
| SmallFixedVector<int, 10> sv3(std::move(sv1)); |
| EXPECT_TRUE(RangesMatch(sv3, values)); |
| // don't check |sv1| - it is not required to be empty. |
| } |
| } |
| |
| TEST(SmallVector, dtor) { |
| // Count all destructor calls for the elements and make sure they're called |
| // enough times. |
| int destructedTimes = 0; |
| auto deleter = [](int* p) { ++(*p); }; |
| auto item1 = makeCustomScopedPtr(&destructedTimes, deleter); |
| auto item2 = makeCustomScopedPtr(&destructedTimes, deleter); |
| auto item3 = makeCustomScopedPtr(&destructedTimes, deleter); |
| |
| { |
| SmallFixedVector<decltype(item1), 1> sv; |
| sv.emplace_back(std::move(item1)); |
| sv.emplace_back(std::move(item2)); |
| // this one is already empty, so it won't add to |destructedTimes|. |
| sv.emplace_back(std::move(item2)); |
| sv.emplace_back(std::move(item3)); |
| } |
| |
| EXPECT_EQ(3, destructedTimes); |
| } |
| |
| TEST(SmallVector, modifiers) { |
| SmallFixedVector<unsigned, 5> sv; |
| |
| EXPECT_EQ(0, sv.size()); |
| EXPECT_EQ(5, sv.capacity()); |
| |
| sv.reserve(4); |
| EXPECT_EQ(0, sv.size()); |
| EXPECT_EQ(5, sv.capacity()); |
| EXPECT_FALSE(sv.isAllocated()); |
| |
| sv.reserve(6); |
| EXPECT_EQ(0, sv.size()); |
| EXPECT_EQ(6, sv.capacity()); |
| EXPECT_TRUE(sv.isAllocated()); |
| |
| sv.resize(3); |
| EXPECT_EQ(3, sv.size()); |
| EXPECT_EQ(6, sv.capacity()); |
| EXPECT_TRUE(sv.isAllocated()); |
| |
| sv.resize(10); |
| EXPECT_EQ(10, sv.size()); |
| EXPECT_GE(sv.capacity(), 10); |
| EXPECT_TRUE(sv.isAllocated()); |
| |
| sv.push_back(1); |
| EXPECT_EQ(11, sv.size()); |
| EXPECT_GE(sv.capacity(), 11); |
| |
| sv.emplace_back(2); |
| EXPECT_EQ(12, sv.size()); |
| EXPECT_GE(sv.capacity(), 12); |
| |
| sv.clear(); |
| EXPECT_EQ(0, sv.size()); |
| EXPECT_GE(sv.capacity(), 12); |
| |
| // resize_noinit() doesn't really have anything specific we can test |
| // compared to resize() |
| sv.resize_noinit(1); |
| EXPECT_EQ(1, sv.size()); |
| EXPECT_GE(sv.capacity(), 12); |
| |
| sv.resize_noinit(100); |
| EXPECT_EQ(100, sv.size()); |
| EXPECT_GE(sv.capacity(), 100); |
| |
| SmallFixedVector<std::string, 5> strings = {"a", "b", "c"}; |
| strings.emplace_back("d"); |
| strings.push_back("e"); |
| EXPECT_EQ(5, strings.size()); |
| EXPECT_EQ(5, strings.capacity()); |
| EXPECT_FALSE(strings.isAllocated()); |
| |
| strings.push_back(std::string("e")); |
| EXPECT_EQ(6, strings.size()); |
| EXPECT_GE(strings.capacity(), 6); |
| EXPECT_TRUE(strings.isAllocated()); |
| } |
| |
| TEST(SmallVector, useThroughInterface) { |
| SmallFixedVector<int, 10> sfv = {1, 2, 3}; |
| SmallVector<int>& sv = sfv; |
| EXPECT_TRUE(RangesMatch(sv, sfv)); |
| EXPECT_EQ(sv.isAllocated(), sfv.isAllocated()); |
| |
| sv.reserve(20); |
| EXPECT_TRUE(sv.isAllocated()); |
| EXPECT_EQ(sv.isAllocated(), sfv.isAllocated()); |
| |
| // now make sure that deleting through base class cleans up the memory |
| { |
| int destructedTimes = 0; |
| auto deleter = [](int* p) { ++(*p); }; |
| auto item1 = makeCustomScopedPtr(&destructedTimes, deleter); |
| auto item2 = makeCustomScopedPtr(&destructedTimes, deleter); |
| SmallVector<decltype(item1)>* sv = |
| new SmallFixedVector<decltype(item1), 1>(); |
| sv->push_back(std::move(item1)); |
| sv->emplace_back(std::move(item2)); |
| delete sv; |
| EXPECT_EQ(2, destructedTimes); |
| } |
| } |
| |
| } // namespace android |
| } // namespace base |