|  | // Copyright 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "base/stl_util.h" | 
|  |  | 
|  | #include <set> | 
|  |  | 
|  | #include "testing/gtest/include/gtest/gtest.h" | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | // Used as test case to ensure the various base::STLXxx functions don't require | 
|  | // more than operators "<" and "==" on values stored in containers. | 
|  | class ComparableValue { | 
|  | public: | 
|  | explicit ComparableValue(int value) : value_(value) {} | 
|  |  | 
|  | bool operator==(const ComparableValue& rhs) const { | 
|  | return value_ == rhs.value_; | 
|  | } | 
|  |  | 
|  | bool operator<(const ComparableValue& rhs) const { | 
|  | return value_ < rhs.value_; | 
|  | } | 
|  |  | 
|  | private: | 
|  | int value_; | 
|  | }; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | namespace base { | 
|  | namespace { | 
|  |  | 
|  | TEST(STLUtilTest, STLIsSorted) { | 
|  | { | 
|  | std::set<int> set; | 
|  | set.insert(24); | 
|  | set.insert(1); | 
|  | set.insert(12); | 
|  | EXPECT_TRUE(STLIsSorted(set)); | 
|  | } | 
|  |  | 
|  | { | 
|  | std::set<ComparableValue> set; | 
|  | set.insert(ComparableValue(24)); | 
|  | set.insert(ComparableValue(1)); | 
|  | set.insert(ComparableValue(12)); | 
|  | EXPECT_TRUE(STLIsSorted(set)); | 
|  | } | 
|  |  | 
|  | { | 
|  | std::vector<int> vector; | 
|  | vector.push_back(1); | 
|  | vector.push_back(1); | 
|  | vector.push_back(4); | 
|  | vector.push_back(64); | 
|  | vector.push_back(12432); | 
|  | EXPECT_TRUE(STLIsSorted(vector)); | 
|  | vector.back() = 1; | 
|  | EXPECT_FALSE(STLIsSorted(vector)); | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST(STLUtilTest, STLSetDifference) { | 
|  | std::set<int> a1; | 
|  | a1.insert(1); | 
|  | a1.insert(2); | 
|  | a1.insert(3); | 
|  | a1.insert(4); | 
|  |  | 
|  | std::set<int> a2; | 
|  | a2.insert(3); | 
|  | a2.insert(4); | 
|  | a2.insert(5); | 
|  | a2.insert(6); | 
|  | a2.insert(7); | 
|  |  | 
|  | { | 
|  | std::set<int> difference; | 
|  | difference.insert(1); | 
|  | difference.insert(2); | 
|  | EXPECT_EQ(difference, STLSetDifference<std::set<int> >(a1, a2)); | 
|  | } | 
|  |  | 
|  | { | 
|  | std::set<int> difference; | 
|  | difference.insert(5); | 
|  | difference.insert(6); | 
|  | difference.insert(7); | 
|  | EXPECT_EQ(difference, STLSetDifference<std::set<int> >(a2, a1)); | 
|  | } | 
|  |  | 
|  | { | 
|  | std::vector<int> difference; | 
|  | difference.push_back(1); | 
|  | difference.push_back(2); | 
|  | EXPECT_EQ(difference, STLSetDifference<std::vector<int> >(a1, a2)); | 
|  | } | 
|  |  | 
|  | { | 
|  | std::vector<int> difference; | 
|  | difference.push_back(5); | 
|  | difference.push_back(6); | 
|  | difference.push_back(7); | 
|  | EXPECT_EQ(difference, STLSetDifference<std::vector<int> >(a2, a1)); | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST(STLUtilTest, STLSetUnion) { | 
|  | std::set<int> a1; | 
|  | a1.insert(1); | 
|  | a1.insert(2); | 
|  | a1.insert(3); | 
|  | a1.insert(4); | 
|  |  | 
|  | std::set<int> a2; | 
|  | a2.insert(3); | 
|  | a2.insert(4); | 
|  | a2.insert(5); | 
|  | a2.insert(6); | 
|  | a2.insert(7); | 
|  |  | 
|  | { | 
|  | std::set<int> result; | 
|  | result.insert(1); | 
|  | result.insert(2); | 
|  | result.insert(3); | 
|  | result.insert(4); | 
|  | result.insert(5); | 
|  | result.insert(6); | 
|  | result.insert(7); | 
|  | EXPECT_EQ(result, STLSetUnion<std::set<int> >(a1, a2)); | 
|  | } | 
|  |  | 
|  | { | 
|  | std::set<int> result; | 
|  | result.insert(1); | 
|  | result.insert(2); | 
|  | result.insert(3); | 
|  | result.insert(4); | 
|  | result.insert(5); | 
|  | result.insert(6); | 
|  | result.insert(7); | 
|  | EXPECT_EQ(result, STLSetUnion<std::set<int> >(a2, a1)); | 
|  | } | 
|  |  | 
|  | { | 
|  | std::vector<int> result; | 
|  | result.push_back(1); | 
|  | result.push_back(2); | 
|  | result.push_back(3); | 
|  | result.push_back(4); | 
|  | result.push_back(5); | 
|  | result.push_back(6); | 
|  | result.push_back(7); | 
|  | EXPECT_EQ(result, STLSetUnion<std::vector<int> >(a1, a2)); | 
|  | } | 
|  |  | 
|  | { | 
|  | std::vector<int> result; | 
|  | result.push_back(1); | 
|  | result.push_back(2); | 
|  | result.push_back(3); | 
|  | result.push_back(4); | 
|  | result.push_back(5); | 
|  | result.push_back(6); | 
|  | result.push_back(7); | 
|  | EXPECT_EQ(result, STLSetUnion<std::vector<int> >(a2, a1)); | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST(STLUtilTest, STLSetIntersection) { | 
|  | std::set<int> a1; | 
|  | a1.insert(1); | 
|  | a1.insert(2); | 
|  | a1.insert(3); | 
|  | a1.insert(4); | 
|  |  | 
|  | std::set<int> a2; | 
|  | a2.insert(3); | 
|  | a2.insert(4); | 
|  | a2.insert(5); | 
|  | a2.insert(6); | 
|  | a2.insert(7); | 
|  |  | 
|  | { | 
|  | std::set<int> result; | 
|  | result.insert(3); | 
|  | result.insert(4); | 
|  | EXPECT_EQ(result, STLSetIntersection<std::set<int> >(a1, a2)); | 
|  | } | 
|  |  | 
|  | { | 
|  | std::set<int> result; | 
|  | result.insert(3); | 
|  | result.insert(4); | 
|  | EXPECT_EQ(result, STLSetIntersection<std::set<int> >(a2, a1)); | 
|  | } | 
|  |  | 
|  | { | 
|  | std::vector<int> result; | 
|  | result.push_back(3); | 
|  | result.push_back(4); | 
|  | EXPECT_EQ(result, STLSetIntersection<std::vector<int> >(a1, a2)); | 
|  | } | 
|  |  | 
|  | { | 
|  | std::vector<int> result; | 
|  | result.push_back(3); | 
|  | result.push_back(4); | 
|  | EXPECT_EQ(result, STLSetIntersection<std::vector<int> >(a2, a1)); | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST(STLUtilTest, STLIncludes) { | 
|  | std::set<int> a1; | 
|  | a1.insert(1); | 
|  | a1.insert(2); | 
|  | a1.insert(3); | 
|  | a1.insert(4); | 
|  |  | 
|  | std::set<int> a2; | 
|  | a2.insert(3); | 
|  | a2.insert(4); | 
|  |  | 
|  | std::set<int> a3; | 
|  | a3.insert(3); | 
|  | a3.insert(4); | 
|  | a3.insert(5); | 
|  |  | 
|  | EXPECT_TRUE(STLIncludes<std::set<int> >(a1, a2)); | 
|  | EXPECT_FALSE(STLIncludes<std::set<int> >(a1, a3)); | 
|  | EXPECT_FALSE(STLIncludes<std::set<int> >(a2, a1)); | 
|  | EXPECT_FALSE(STLIncludes<std::set<int> >(a2, a3)); | 
|  | EXPECT_FALSE(STLIncludes<std::set<int> >(a3, a1)); | 
|  | EXPECT_TRUE(STLIncludes<std::set<int> >(a3, a2)); | 
|  | } | 
|  |  | 
|  | TEST(StringAsArrayTest, Empty) { | 
|  | std::string empty; | 
|  | EXPECT_EQ(nullptr, string_as_array(&empty)); | 
|  | } | 
|  |  | 
|  | TEST(StringAsArrayTest, NullTerminated) { | 
|  | // If any std::string implementation is not null-terminated, this should | 
|  | // fail. All compilers we use return a null-terminated buffer, but please do | 
|  | // not rely on this fact in your code. | 
|  | std::string str("abcde"); | 
|  | str.resize(3); | 
|  | EXPECT_STREQ("abc", string_as_array(&str)); | 
|  | } | 
|  |  | 
|  | TEST(StringAsArrayTest, WriteCopy) { | 
|  | // With a COW implementation, this test will fail if | 
|  | // string_as_array(&str) is implemented as | 
|  | // const_cast<char*>(str->data()). | 
|  | std::string s1("abc"); | 
|  | const std::string s2(s1); | 
|  | string_as_array(&s1)[1] = 'x'; | 
|  | EXPECT_EQ("axc", s1); | 
|  | EXPECT_EQ("abc", s2); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  | }  // namespace base |