Home | History | Annotate | Download | only in tests
      1 // Copyright 2016 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/fixed_buffer.h"
      7 #include "mojo/public/cpp/bindings/lib/serialization.h"
      8 #include "mojo/public/cpp/bindings/lib/validate_params.h"
      9 #include "mojo/public/cpp/bindings/map.h"
     10 #include "mojo/public/cpp/bindings/string.h"
     11 #include "mojo/public/cpp/bindings/tests/container_test_util.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 
     14 namespace WTF {
     15 class String;
     16 }
     17 
     18 namespace mojo {
     19 
     20 template <typename T>
     21 class WTFArray;
     22 
     23 template <typename K, typename V>
     24 class WTFMap;
     25 
     26 namespace test {
     27 namespace {
     28 
     29 struct StringIntData {
     30   const char* string_data;
     31   int int_data;
     32 } kStringIntData[] = {
     33     {"one", 1},
     34     {"two", 2},
     35     {"three", 3},
     36     {"four", 4},
     37 };
     38 
     39 const size_t kStringIntDataSize = 4;
     40 
     41 }  // namespace
     42 
     43 template <template <typename...> class MapType>
     44 struct TypeTraits;
     45 
     46 template <>
     47 struct TypeTraits<Map> {
     48   using StringType = mojo::String;
     49   template <typename T>
     50   using ArrayType = Array<T>;
     51 };
     52 
     53 template <>
     54 struct TypeTraits<WTFMap> {
     55   using StringType = WTF::String;
     56   template <typename T>
     57   using ArrayType = WTFArray<T>;
     58 };
     59 
     60 // Common tests for both mojo::Map and mojo::WTFMap.
     61 template <template <typename...> class MapType>
     62 class MapCommonTest {
     63  public:
     64   using StringType = typename TypeTraits<MapType>::StringType;
     65   template <typename T>
     66   using ArrayType = typename TypeTraits<MapType>::template ArrayType<T>;
     67 
     68   // Tests null and empty maps.
     69   static void NullAndEmpty() {
     70     MapType<char, char> map0;
     71     EXPECT_TRUE(map0.empty());
     72     EXPECT_FALSE(map0.is_null());
     73     map0 = nullptr;
     74     EXPECT_TRUE(map0.is_null());
     75     EXPECT_FALSE(map0.empty());
     76 
     77     MapType<char, char> map1(nullptr);
     78     EXPECT_TRUE(map1.is_null());
     79     EXPECT_FALSE(map1.empty());
     80     map1.SetToEmpty();
     81     EXPECT_TRUE(map1.empty());
     82     EXPECT_FALSE(map1.is_null());
     83   }
     84 
     85   // Tests that basic Map operations work.
     86   static void InsertWorks() {
     87     MapType<StringType, int> map;
     88     for (size_t i = 0; i < kStringIntDataSize; ++i)
     89       map.insert(kStringIntData[i].string_data, kStringIntData[i].int_data);
     90 
     91     for (size_t i = 0; i < kStringIntDataSize; ++i) {
     92       EXPECT_EQ(kStringIntData[i].int_data,
     93                 map.at(kStringIntData[i].string_data));
     94     }
     95   }
     96 
     97   static void TestIndexOperator() {
     98     MapType<StringType, int> map;
     99     for (size_t i = 0; i < kStringIntDataSize; ++i)
    100       map[kStringIntData[i].string_data] = kStringIntData[i].int_data;
    101 
    102     for (size_t i = 0; i < kStringIntDataSize; ++i) {
    103       EXPECT_EQ(kStringIntData[i].int_data,
    104                 map.at(kStringIntData[i].string_data));
    105     }
    106   }
    107 
    108   static void TestIndexOperatorAsRValue() {
    109     MapType<StringType, int> map;
    110     for (size_t i = 0; i < kStringIntDataSize; ++i)
    111       map.insert(kStringIntData[i].string_data, kStringIntData[i].int_data);
    112 
    113     for (size_t i = 0; i < kStringIntDataSize; ++i) {
    114       EXPECT_EQ(kStringIntData[i].int_data, map[kStringIntData[i].string_data]);
    115     }
    116   }
    117 
    118   static void TestIndexOperatorMoveOnly() {
    119     ASSERT_EQ(0u, MoveOnlyType::num_instances());
    120     MapType<StringType, ArrayType<int32_t>> map;
    121 
    122     for (size_t i = 0; i < kStringIntDataSize; ++i) {
    123       const char* key = kStringIntData[i].string_data;
    124       ArrayType<int32_t> array(1);
    125       array[0] = kStringIntData[i].int_data;
    126       map[key] = std::move(array);
    127       EXPECT_TRUE(map);
    128     }
    129 
    130     // We now read back that data, to test the behavior of operator[].
    131     for (size_t i = 0; i < kStringIntDataSize; ++i) {
    132       auto& value = map[kStringIntData[i].string_data];
    133       ASSERT_EQ(1u, value.size());
    134       EXPECT_EQ(kStringIntData[i].int_data, value[0]);
    135     }
    136   }
    137 
    138   static void MapArrayClone() {
    139     MapType<StringType, ArrayType<StringType>> m;
    140     for (size_t i = 0; i < kStringIntDataSize; ++i) {
    141       ArrayType<StringType> s(1);
    142       s[0] = StringType(kStringIntData[i].string_data);
    143       m.insert(kStringIntData[i].string_data, std::move(s));
    144     }
    145 
    146     MapType<StringType, ArrayType<StringType>> m2 = m.Clone();
    147 
    148     for (size_t i = 0; i < kStringIntDataSize; ++i) {
    149       ASSERT_NE(m2.end(), m2.find(kStringIntData[i].string_data));
    150       ASSERT_EQ(1u, m2[kStringIntData[i].string_data].size());
    151       EXPECT_EQ(StringType(kStringIntData[i].string_data),
    152                 m2[kStringIntData[i].string_data][0]);
    153     }
    154   }
    155 
    156   static void ArrayOfMap() {
    157     {
    158       using MojomType = Array<Map<int32_t, int8_t>>;
    159       using UserType = ArrayType<MapType<int32_t, int8_t>>;
    160 
    161       UserType array(1);
    162       array[0].insert(1, 42);
    163 
    164       mojo::internal::SerializationContext context;
    165       size_t size =
    166           mojo::internal::PrepareToSerialize<MojomType>(array, &context);
    167       mojo::internal::FixedBufferForTesting buf(size);
    168       typename mojo::internal::MojomTypeTraits<MojomType>::Data* data;
    169       mojo::internal::ContainerValidateParams validate_params(
    170           0, false,
    171           new mojo::internal::ContainerValidateParams(
    172               new mojo::internal::ContainerValidateParams(0, false, nullptr),
    173               new mojo::internal::ContainerValidateParams(0, false, nullptr)));
    174 
    175       mojo::internal::Serialize<MojomType>(array, &buf, &data, &validate_params,
    176                                            &context);
    177 
    178       UserType deserialized_array;
    179       mojo::internal::Deserialize<MojomType>(data, &deserialized_array,
    180                                              &context);
    181 
    182       ASSERT_EQ(1u, deserialized_array.size());
    183       ASSERT_EQ(1u, deserialized_array[0].size());
    184       ASSERT_EQ(42, deserialized_array[0].at(1));
    185     }
    186 
    187     {
    188       using MojomType = Array<Map<String, Array<bool>>>;
    189       using UserType = ArrayType<MapType<StringType, ArrayType<bool>>>;
    190 
    191       UserType array(1);
    192       ArrayType<bool> map_value(2);
    193       map_value[0] = false;
    194       map_value[1] = true;
    195       array[0].insert("hello world", std::move(map_value));
    196 
    197       mojo::internal::SerializationContext context;
    198       size_t size =
    199           mojo::internal::PrepareToSerialize<MojomType>(array, &context);
    200       mojo::internal::FixedBufferForTesting buf(size);
    201       typename mojo::internal::MojomTypeTraits<MojomType>::Data* data;
    202       mojo::internal::ContainerValidateParams validate_params(
    203           0, false,
    204           new mojo::internal::ContainerValidateParams(
    205               new mojo::internal::ContainerValidateParams(
    206                   0, false, new mojo::internal::ContainerValidateParams(
    207                                 0, false, nullptr)),
    208               new mojo::internal::ContainerValidateParams(
    209                   0, false, new mojo::internal::ContainerValidateParams(
    210                                 0, false, nullptr))));
    211       mojo::internal::Serialize<MojomType>(array, &buf, &data, &validate_params,
    212                                            &context);
    213 
    214       UserType deserialized_array;
    215       mojo::internal::Deserialize<MojomType>(data, &deserialized_array,
    216                                              &context);
    217 
    218       ASSERT_EQ(1u, deserialized_array.size());
    219       ASSERT_EQ(1u, deserialized_array[0].size());
    220       ASSERT_FALSE(deserialized_array[0].at("hello world")[0]);
    221       ASSERT_TRUE(deserialized_array[0].at("hello world")[1]);
    222     }
    223   }
    224 };
    225 
    226 #define MAP_COMMON_TEST(MapType, test_name) \
    227   TEST_F(MapType##Test, test_name) { MapCommonTest<MapType>::test_name(); }
    228 
    229 }  // namespace test
    230 }  // namespace mojo
    231