| Index: mojo/public/cpp/bindings/tests/map_unittest.cc
|
| diff --git a/mojo/public/cpp/bindings/tests/map_unittest.cc b/mojo/public/cpp/bindings/tests/map_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..dd4ff071b82faf334b6667dadf95e15e39e1048e
|
| --- /dev/null
|
| +++ b/mojo/public/cpp/bindings/tests/map_unittest.cc
|
| @@ -0,0 +1,240 @@
|
| +// Copyright 2014 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 "mojo/public/cpp/bindings/array.h"
|
| +#include "mojo/public/cpp/bindings/lib/array_serialization.h"
|
| +#include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
|
| +#include "mojo/public/cpp/bindings/map.h"
|
| +#include "mojo/public/cpp/bindings/string.h"
|
| +#include "mojo/public/cpp/environment/environment.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace mojo {
|
| +namespace test {
|
| +
|
| +namespace {
|
| +
|
| +struct StringIntData {
|
| + const char* string_data;
|
| + int int_data;
|
| +} kStringIntData[] = {
|
| + { "one", 1 },
|
| + { "two", 2 },
|
| + { "three", 3 },
|
| + { "four", 4 },
|
| +};
|
| +
|
| +const size_t kStringIntDataSize = 4;
|
| +
|
| +class CopyableType {
|
| + public:
|
| + CopyableType() : copied_(false), ptr_(this) { num_instances_++; }
|
| + CopyableType(const CopyableType& other) : copied_(true), ptr_(other.ptr()) {
|
| + num_instances_++;
|
| + }
|
| + CopyableType& operator=(const CopyableType& other) {
|
| + copied_ = true;
|
| + ptr_ = other.ptr();
|
| + return *this;
|
| + }
|
| + ~CopyableType() { num_instances_--; }
|
| +
|
| + bool copied() const { return copied_; }
|
| + static size_t num_instances() { return num_instances_; }
|
| + CopyableType* ptr() const { return ptr_; }
|
| + void ResetCopied() { copied_ = false; }
|
| +
|
| + private:
|
| + bool copied_;
|
| + static size_t num_instances_;
|
| + CopyableType* ptr_;
|
| +};
|
| +
|
| +size_t CopyableType::num_instances_ = 0;
|
| +
|
| +class MoveOnlyType {
|
| + MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(MoveOnlyType, RValue)
|
| + public:
|
| + typedef MoveOnlyType Data_;
|
| + MoveOnlyType() : moved_(false), ptr_(this) { num_instances_++; }
|
| + MoveOnlyType(RValue other) : moved_(true), ptr_(other.object->ptr()) {
|
| + num_instances_++;
|
| + }
|
| + MoveOnlyType& operator=(RValue other) {
|
| + moved_ = true;
|
| + ptr_ = other.object->ptr();
|
| + return *this;
|
| + }
|
| + ~MoveOnlyType() { num_instances_--; }
|
| +
|
| + bool moved() const { return moved_; }
|
| + static size_t num_instances() { return num_instances_; }
|
| + MoveOnlyType* ptr() const { return ptr_; }
|
| + void ResetMoved() { moved_ = false; }
|
| +
|
| + private:
|
| + bool moved_;
|
| + static size_t num_instances_;
|
| + MoveOnlyType* ptr_;
|
| +};
|
| +
|
| +size_t MoveOnlyType::num_instances_ = 0;
|
| +
|
| +class MapTest : public testing::Test {
|
| + public:
|
| + virtual ~MapTest() {}
|
| +
|
| + private:
|
| + Environment env_;
|
| +};
|
| +
|
| +// Tests that basic Map operations work.
|
| +TEST_F(MapTest, InsertWorks) {
|
| + Map<String, int> map;
|
| + for (size_t i = 0; i < kStringIntDataSize; ++i)
|
| + map.insert(kStringIntData[i].string_data, kStringIntData[i].int_data);
|
| +
|
| + for (size_t i = 0; i < kStringIntDataSize; ++i) {
|
| + EXPECT_EQ(kStringIntData[i].int_data,
|
| + map.at(kStringIntData[i].string_data));
|
| + }
|
| +}
|
| +
|
| +TEST_F(MapTest, ConstructedFromArray) {
|
| + Array<String> keys(kStringIntDataSize);
|
| + Array<int> values(kStringIntDataSize);
|
| + for (size_t i = 0; i < kStringIntDataSize; ++i) {
|
| + keys[i] = kStringIntData[i].string_data;
|
| + values[i] = kStringIntData[i].int_data;
|
| + }
|
| +
|
| + Map<String, int> map(keys.Pass(), values.Pass());
|
| +
|
| + for (size_t i = 0; i < kStringIntDataSize; ++i) {
|
| + EXPECT_EQ(kStringIntData[i].int_data,
|
| + map.at(mojo::String(kStringIntData[i].string_data)));
|
| + }
|
| +}
|
| +
|
| +TEST_F(MapTest, DecomposeMapTo) {
|
| + Array<String> keys(kStringIntDataSize);
|
| + Array<int> values(kStringIntDataSize);
|
| + for (size_t i = 0; i < kStringIntDataSize; ++i) {
|
| + keys[i] = kStringIntData[i].string_data;
|
| + values[i] = kStringIntData[i].int_data;
|
| + }
|
| +
|
| + Map<String, int> map(keys.Pass(), values.Pass());
|
| + EXPECT_EQ(kStringIntDataSize, map.size());
|
| +
|
| + Array<String> keys2;
|
| + Array<int> values2;
|
| + map.DecomposeMapTo(&keys2, &values2);
|
| + EXPECT_EQ(0u, map.size());
|
| +
|
| + EXPECT_EQ(kStringIntDataSize, keys2.size());
|
| + EXPECT_EQ(kStringIntDataSize, values2.size());
|
| +
|
| + for (size_t i = 0; i < kStringIntDataSize; ++i) {
|
| + // We are not guaranteed that the copies have the same sorting as the
|
| + // originals.
|
| + String key = kStringIntData[i].string_data;
|
| + int value = kStringIntData[i].int_data;
|
| +
|
| + bool found = false;
|
| + for (size_t j = 0; j < keys2.size(); ++j) {
|
| + if (keys2[j] == key) {
|
| + EXPECT_EQ(value, values2[j]);
|
| + found = true;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + EXPECT_TRUE(found);
|
| + }
|
| +}
|
| +
|
| +TEST_F(MapTest, Insert_Copyable) {
|
| + ASSERT_EQ(0u, CopyableType::num_instances());
|
| + mojo::Map<mojo::String, CopyableType> map;
|
| + std::vector<CopyableType*> value_ptrs;
|
| +
|
| + for (size_t i = 0; i < kStringIntDataSize; ++i) {
|
| + const char* key = kStringIntData[i].string_data;
|
| + CopyableType value;
|
| + value_ptrs.push_back(value.ptr());
|
| + map.insert(key, value);
|
| + ASSERT_EQ(i + 1, map.size());
|
| + ASSERT_EQ(i + 1, value_ptrs.size());
|
| + EXPECT_EQ(map.size() + 1, CopyableType::num_instances());
|
| + EXPECT_TRUE(map.at(key).copied());
|
| + EXPECT_EQ(value_ptrs[i], map.at(key).ptr());
|
| + map.at(key).ResetCopied();
|
| + EXPECT_TRUE(map);
|
| + }
|
| +
|
| + // std::map doesn't have a capacity() method like std::vector so this test is
|
| + // a lot more boring.
|
| +
|
| + map.reset();
|
| + EXPECT_EQ(0u, CopyableType::num_instances());
|
| +}
|
| +
|
| +TEST_F(MapTest, Insert_MoveOnly) {
|
| + ASSERT_EQ(0u, MoveOnlyType::num_instances());
|
| + mojo::Map<mojo::String, MoveOnlyType> map;
|
| + std::vector<MoveOnlyType*> value_ptrs;
|
| +
|
| + for (size_t i = 0; i < kStringIntDataSize; ++i) {
|
| + const char* key = kStringIntData[i].string_data;
|
| + MoveOnlyType value;
|
| + value_ptrs.push_back(value.ptr());
|
| + map.insert(key, value.Pass());
|
| + ASSERT_EQ(i + 1, map.size());
|
| + ASSERT_EQ(i + 1, value_ptrs.size());
|
| + EXPECT_EQ(map.size() + 1, MoveOnlyType::num_instances());
|
| + EXPECT_TRUE(map.at(key).moved());
|
| + EXPECT_EQ(value_ptrs[i], map.at(key).ptr());
|
| + map.at(key).ResetMoved();
|
| + EXPECT_TRUE(map);
|
| + }
|
| +
|
| + // std::map doesn't have a capacity() method like std::vector so this test is
|
| + // a lot more boring.
|
| +
|
| + map.reset();
|
| + EXPECT_EQ(0u, CopyableType::num_instances());
|
| +}
|
| +
|
| +TEST_F(MapTest, STLToMojo) {
|
| + std::map<std::string, int> stl_data;
|
| + for (size_t i = 0; i < kStringIntDataSize; ++i)
|
| + stl_data[kStringIntData[i].string_data] = kStringIntData[i].int_data;
|
| +
|
| + Map<String, int32_t> mojo_data = Map<String, int32_t>::From(stl_data);
|
| +
|
| + for (size_t i = 0; i < kStringIntDataSize; ++i) {
|
| + EXPECT_EQ(kStringIntData[i].int_data,
|
| + mojo_data.at(kStringIntData[i].string_data));
|
| + }
|
| +}
|
| +
|
| +TEST_F(MapTest, MojoToSTL) {
|
| + Map<String, int32_t> mojo_map;
|
| + for (size_t i = 0; i < kStringIntDataSize; ++i)
|
| + mojo_map.insert(kStringIntData[i].string_data, kStringIntData[i].int_data);
|
| +
|
| + std::map<std::string, int> stl_map =
|
| + mojo_map.To<std::map<std::string, int> >();
|
| + for (size_t i = 0; i < kStringIntDataSize; ++i) {
|
| + auto it = stl_map.find(kStringIntData[i].string_data);
|
| + ASSERT_TRUE(it != stl_map.end());
|
| + EXPECT_EQ(kStringIntData[i].int_data, it->second);
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
| +} // namespace test
|
| +} // namespace mojo
|
| +
|
|
|