OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "mojo/public/cpp/bindings/array.h" |
| 6 #include "mojo/public/cpp/bindings/lib/array_serialization.h" |
| 7 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h" |
| 8 #include "mojo/public/cpp/bindings/map.h" |
| 9 #include "mojo/public/cpp/bindings/string.h" |
| 10 #include "mojo/public/cpp/environment/environment.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" |
| 12 |
| 13 namespace mojo { |
| 14 namespace test { |
| 15 |
| 16 namespace { |
| 17 |
| 18 struct StringIntData { |
| 19 const char* string_data; |
| 20 int int_data; |
| 21 } kStringIntData[] = { |
| 22 { "one", 1 }, |
| 23 { "two", 2 }, |
| 24 { "three", 3 }, |
| 25 { "four", 4 }, |
| 26 }; |
| 27 |
| 28 const size_t kStringIntDataSize = 4; |
| 29 |
| 30 class CopyableType { |
| 31 public: |
| 32 CopyableType() : copied_(false), ptr_(this) { num_instances_++; } |
| 33 CopyableType(const CopyableType& other) : copied_(true), ptr_(other.ptr()) { |
| 34 num_instances_++; |
| 35 } |
| 36 CopyableType& operator=(const CopyableType& other) { |
| 37 copied_ = true; |
| 38 ptr_ = other.ptr(); |
| 39 return *this; |
| 40 } |
| 41 ~CopyableType() { num_instances_--; } |
| 42 |
| 43 bool copied() const { return copied_; } |
| 44 static size_t num_instances() { return num_instances_; } |
| 45 CopyableType* ptr() const { return ptr_; } |
| 46 void ResetCopied() { copied_ = false; } |
| 47 |
| 48 private: |
| 49 bool copied_; |
| 50 static size_t num_instances_; |
| 51 CopyableType* ptr_; |
| 52 }; |
| 53 |
| 54 size_t CopyableType::num_instances_ = 0; |
| 55 |
| 56 class MoveOnlyType { |
| 57 MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(MoveOnlyType, RValue) |
| 58 public: |
| 59 typedef MoveOnlyType Data_; |
| 60 MoveOnlyType() : moved_(false), ptr_(this) { num_instances_++; } |
| 61 MoveOnlyType(RValue other) : moved_(true), ptr_(other.object->ptr()) { |
| 62 num_instances_++; |
| 63 } |
| 64 MoveOnlyType& operator=(RValue other) { |
| 65 moved_ = true; |
| 66 ptr_ = other.object->ptr(); |
| 67 return *this; |
| 68 } |
| 69 ~MoveOnlyType() { num_instances_--; } |
| 70 |
| 71 bool moved() const { return moved_; } |
| 72 static size_t num_instances() { return num_instances_; } |
| 73 MoveOnlyType* ptr() const { return ptr_; } |
| 74 void ResetMoved() { moved_ = false; } |
| 75 |
| 76 private: |
| 77 bool moved_; |
| 78 static size_t num_instances_; |
| 79 MoveOnlyType* ptr_; |
| 80 }; |
| 81 |
| 82 size_t MoveOnlyType::num_instances_ = 0; |
| 83 |
| 84 class MapTest : public testing::Test { |
| 85 public: |
| 86 virtual ~MapTest() {} |
| 87 |
| 88 private: |
| 89 Environment env_; |
| 90 }; |
| 91 |
| 92 // Tests that basic Map operations work. |
| 93 TEST_F(MapTest, InsertWorks) { |
| 94 Map<String, int> map; |
| 95 for (size_t i = 0; i < kStringIntDataSize; ++i) |
| 96 map.insert(kStringIntData[i].string_data, kStringIntData[i].int_data); |
| 97 |
| 98 for (size_t i = 0; i < kStringIntDataSize; ++i) { |
| 99 EXPECT_EQ(kStringIntData[i].int_data, |
| 100 map.at(kStringIntData[i].string_data)); |
| 101 } |
| 102 } |
| 103 |
| 104 TEST_F(MapTest, ConstructedFromArray) { |
| 105 Array<String> keys(kStringIntDataSize); |
| 106 Array<int> values(kStringIntDataSize); |
| 107 for (size_t i = 0; i < kStringIntDataSize; ++i) { |
| 108 keys[i] = kStringIntData[i].string_data; |
| 109 values[i] = kStringIntData[i].int_data; |
| 110 } |
| 111 |
| 112 Map<String, int> map(keys.Pass(), values.Pass()); |
| 113 |
| 114 for (size_t i = 0; i < kStringIntDataSize; ++i) { |
| 115 EXPECT_EQ(kStringIntData[i].int_data, |
| 116 map.at(mojo::String(kStringIntData[i].string_data))); |
| 117 } |
| 118 } |
| 119 |
| 120 TEST_F(MapTest, DecomposeMapTo) { |
| 121 Array<String> keys(kStringIntDataSize); |
| 122 Array<int> values(kStringIntDataSize); |
| 123 for (size_t i = 0; i < kStringIntDataSize; ++i) { |
| 124 keys[i] = kStringIntData[i].string_data; |
| 125 values[i] = kStringIntData[i].int_data; |
| 126 } |
| 127 |
| 128 Map<String, int> map(keys.Pass(), values.Pass()); |
| 129 EXPECT_EQ(kStringIntDataSize, map.size()); |
| 130 |
| 131 Array<String> keys2; |
| 132 Array<int> values2; |
| 133 map.DecomposeMapTo(&keys2, &values2); |
| 134 EXPECT_EQ(0u, map.size()); |
| 135 |
| 136 EXPECT_EQ(kStringIntDataSize, keys2.size()); |
| 137 EXPECT_EQ(kStringIntDataSize, values2.size()); |
| 138 |
| 139 for (size_t i = 0; i < kStringIntDataSize; ++i) { |
| 140 // We are not guaranteed that the copies have the same sorting as the |
| 141 // originals. |
| 142 String key = kStringIntData[i].string_data; |
| 143 int value = kStringIntData[i].int_data; |
| 144 |
| 145 bool found = false; |
| 146 for (size_t j = 0; j < keys2.size(); ++j) { |
| 147 if (keys2[j] == key) { |
| 148 EXPECT_EQ(value, values2[j]); |
| 149 found = true; |
| 150 break; |
| 151 } |
| 152 } |
| 153 |
| 154 EXPECT_TRUE(found); |
| 155 } |
| 156 } |
| 157 |
| 158 TEST_F(MapTest, Insert_Copyable) { |
| 159 ASSERT_EQ(0u, CopyableType::num_instances()); |
| 160 mojo::Map<mojo::String, CopyableType> map; |
| 161 std::vector<CopyableType*> value_ptrs; |
| 162 |
| 163 for (size_t i = 0; i < kStringIntDataSize; ++i) { |
| 164 const char* key = kStringIntData[i].string_data; |
| 165 CopyableType value; |
| 166 value_ptrs.push_back(value.ptr()); |
| 167 map.insert(key, value); |
| 168 ASSERT_EQ(i + 1, map.size()); |
| 169 ASSERT_EQ(i + 1, value_ptrs.size()); |
| 170 EXPECT_EQ(map.size() + 1, CopyableType::num_instances()); |
| 171 EXPECT_TRUE(map.at(key).copied()); |
| 172 EXPECT_EQ(value_ptrs[i], map.at(key).ptr()); |
| 173 map.at(key).ResetCopied(); |
| 174 EXPECT_TRUE(map); |
| 175 } |
| 176 |
| 177 // std::map doesn't have a capacity() method like std::vector so this test is |
| 178 // a lot more boring. |
| 179 |
| 180 map.reset(); |
| 181 EXPECT_EQ(0u, CopyableType::num_instances()); |
| 182 } |
| 183 |
| 184 TEST_F(MapTest, Insert_MoveOnly) { |
| 185 ASSERT_EQ(0u, MoveOnlyType::num_instances()); |
| 186 mojo::Map<mojo::String, MoveOnlyType> map; |
| 187 std::vector<MoveOnlyType*> value_ptrs; |
| 188 |
| 189 for (size_t i = 0; i < kStringIntDataSize; ++i) { |
| 190 const char* key = kStringIntData[i].string_data; |
| 191 MoveOnlyType value; |
| 192 value_ptrs.push_back(value.ptr()); |
| 193 map.insert(key, value.Pass()); |
| 194 ASSERT_EQ(i + 1, map.size()); |
| 195 ASSERT_EQ(i + 1, value_ptrs.size()); |
| 196 EXPECT_EQ(map.size() + 1, MoveOnlyType::num_instances()); |
| 197 EXPECT_TRUE(map.at(key).moved()); |
| 198 EXPECT_EQ(value_ptrs[i], map.at(key).ptr()); |
| 199 map.at(key).ResetMoved(); |
| 200 EXPECT_TRUE(map); |
| 201 } |
| 202 |
| 203 // std::map doesn't have a capacity() method like std::vector so this test is |
| 204 // a lot more boring. |
| 205 |
| 206 map.reset(); |
| 207 EXPECT_EQ(0u, CopyableType::num_instances()); |
| 208 } |
| 209 |
| 210 TEST_F(MapTest, STLToMojo) { |
| 211 std::map<std::string, int> stl_data; |
| 212 for (size_t i = 0; i < kStringIntDataSize; ++i) |
| 213 stl_data[kStringIntData[i].string_data] = kStringIntData[i].int_data; |
| 214 |
| 215 Map<String, int32_t> mojo_data = Map<String, int32_t>::From(stl_data); |
| 216 |
| 217 for (size_t i = 0; i < kStringIntDataSize; ++i) { |
| 218 EXPECT_EQ(kStringIntData[i].int_data, |
| 219 mojo_data.at(kStringIntData[i].string_data)); |
| 220 } |
| 221 } |
| 222 |
| 223 TEST_F(MapTest, MojoToSTL) { |
| 224 Map<String, int32_t> mojo_map; |
| 225 for (size_t i = 0; i < kStringIntDataSize; ++i) |
| 226 mojo_map.insert(kStringIntData[i].string_data, kStringIntData[i].int_data); |
| 227 |
| 228 std::map<std::string, int> stl_map = |
| 229 mojo_map.To<std::map<std::string, int> >(); |
| 230 for (size_t i = 0; i < kStringIntDataSize; ++i) { |
| 231 auto it = stl_map.find(kStringIntData[i].string_data); |
| 232 ASSERT_TRUE(it != stl_map.end()); |
| 233 EXPECT_EQ(kStringIntData[i].int_data, it->second); |
| 234 } |
| 235 } |
| 236 |
| 237 } // namespace |
| 238 } // namespace test |
| 239 } // namespace mojo |
| 240 |
OLD | NEW |