mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
324 lines
9.7 KiB
C++
324 lines
9.7 KiB
C++
// 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/bindings_internal.h"
|
|
#include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
|
|
#include "mojo/public/cpp/bindings/lib/validate_params.h"
|
|
#include "mojo/public/cpp/bindings/map.h"
|
|
#include "mojo/public/cpp/bindings/string.h"
|
|
#include "mojo/public/cpp/bindings/tests/container_test_util.h"
|
|
#include "mojo/public/cpp/environment/environment.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
namespace mojo {
|
|
namespace test {
|
|
|
|
namespace {
|
|
|
|
using mojo::internal::Array_Data;
|
|
using mojo::internal::ArrayValidateParams;
|
|
using mojo::internal::FixedBuffer;
|
|
using mojo::internal::Map_Data;
|
|
using mojo::internal::String_Data;
|
|
|
|
struct StringIntData {
|
|
const char* string_data;
|
|
int int_data;
|
|
} kStringIntData[] = {
|
|
{"one", 1},
|
|
{"two", 2},
|
|
{"three", 3},
|
|
{"four", 4},
|
|
};
|
|
|
|
const size_t kStringIntDataSize = 4;
|
|
|
|
class MapTest : public testing::Test {
|
|
public:
|
|
~MapTest() override {}
|
|
|
|
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, TestIndexOperator) {
|
|
Map<String, int> map;
|
|
for (size_t i = 0; i < kStringIntDataSize; ++i)
|
|
map[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, TestIndexOperatorAsRValue) {
|
|
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[kStringIntData[i].string_data]);
|
|
}
|
|
}
|
|
|
|
TEST_F(MapTest, TestIndexOperatorMoveOnly) {
|
|
ASSERT_EQ(0u, MoveOnlyType::num_instances());
|
|
mojo::Map<mojo::String, mojo::Array<int32_t>> map;
|
|
std::vector<MoveOnlyType*> value_ptrs;
|
|
|
|
for (size_t i = 0; i < kStringIntDataSize; ++i) {
|
|
const char* key = kStringIntData[i].string_data;
|
|
Array<int32_t> array(1);
|
|
array[0] = kStringIntData[i].int_data;
|
|
map[key] = array.Pass();
|
|
EXPECT_TRUE(map);
|
|
}
|
|
|
|
// We now read back that data, to test the behavior of operator[].
|
|
for (size_t i = 0; i < kStringIntDataSize; ++i) {
|
|
auto it = map.find(kStringIntData[i].string_data);
|
|
ASSERT_TRUE(it != map.end());
|
|
ASSERT_EQ(1u, it.GetValue().size());
|
|
EXPECT_EQ(kStringIntData[i].int_data, it.GetValue()[0]);
|
|
}
|
|
}
|
|
|
|
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, MoveOnlyType::num_instances());
|
|
}
|
|
|
|
TEST_F(MapTest, IndexOperator_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[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, MoveOnlyType::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);
|
|
}
|
|
}
|
|
|
|
TEST_F(MapTest, MapArrayClone) {
|
|
Map<String, Array<String>> m;
|
|
for (size_t i = 0; i < kStringIntDataSize; ++i) {
|
|
Array<String> s;
|
|
s.push_back(kStringIntData[i].string_data);
|
|
m.insert(kStringIntData[i].string_data, s.Pass());
|
|
}
|
|
|
|
Map<String, Array<String>> m2 = m.Clone();
|
|
|
|
for (auto it = m2.begin(); it != m2.end(); ++it) {
|
|
ASSERT_EQ(1u, it.GetValue().size());
|
|
EXPECT_EQ(it.GetKey(), it.GetValue().at(0));
|
|
}
|
|
}
|
|
|
|
TEST_F(MapTest, ArrayOfMap) {
|
|
{
|
|
Array<Map<int32_t, int8_t>> array(1);
|
|
array[0].insert(1, 42);
|
|
|
|
size_t size = GetSerializedSize_(array);
|
|
FixedBuffer buf(size);
|
|
Array_Data<Map_Data<int32_t, int8_t>*>* data;
|
|
ArrayValidateParams validate_params(
|
|
0, false, new ArrayValidateParams(0, false, nullptr));
|
|
SerializeArray_(array.Pass(), &buf, &data, &validate_params);
|
|
|
|
Array<Map<int32_t, int8_t>> deserialized_array;
|
|
Deserialize_(data, &deserialized_array);
|
|
|
|
ASSERT_EQ(1u, deserialized_array.size());
|
|
ASSERT_EQ(1u, deserialized_array[0].size());
|
|
ASSERT_EQ(42, deserialized_array[0].at(1));
|
|
}
|
|
|
|
{
|
|
Array<Map<String, Array<bool>>> array(1);
|
|
Array<bool> map_value(2);
|
|
map_value[0] = false;
|
|
map_value[1] = true;
|
|
array[0].insert("hello world", map_value.Pass());
|
|
|
|
size_t size = GetSerializedSize_(array);
|
|
FixedBuffer buf(size);
|
|
Array_Data<Map_Data<String_Data*, Array_Data<bool>*>*>* data;
|
|
ArrayValidateParams validate_params(
|
|
0, false, new ArrayValidateParams(
|
|
0, false, new ArrayValidateParams(0, false, nullptr)));
|
|
SerializeArray_(array.Pass(), &buf, &data, &validate_params);
|
|
|
|
Array<Map<String, Array<bool>>> deserialized_array;
|
|
Deserialize_(data, &deserialized_array);
|
|
|
|
ASSERT_EQ(1u, deserialized_array.size());
|
|
ASSERT_EQ(1u, deserialized_array[0].size());
|
|
ASSERT_FALSE(deserialized_array[0].at("hello world")[0]);
|
|
ASSERT_TRUE(deserialized_array[0].at("hello world")[1]);
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace test
|
|
} // namespace mojo
|