1 // Copyright 2018 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 <string> 6 #include <utility> 7 8 #include "base/test/gtest_util.h" 9 #include "base/values.h" 10 #include "mojo/public/cpp/base/values_mojom_traits.h" 11 #include "mojo/public/cpp/test_support/test_utils.h" 12 #include "mojo/public/mojom/base/values.mojom.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 15 namespace mojo_base { 16 17 TEST(ValuesStructTraitsTest, NullValue) { 18 base::Value in; 19 base::Value out; 20 ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); 21 EXPECT_EQ(in, out); 22 } 23 24 TEST(ValuesStructTraitsTest, BoolValue) { 25 static constexpr bool kTestCases[] = {true, false}; 26 for (auto& test_case : kTestCases) { 27 base::Value in(test_case); 28 base::Value out; 29 ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); 30 EXPECT_EQ(in, out); 31 } 32 } 33 34 TEST(ValuesStructTraitsTest, IntValue) { 35 static constexpr int kTestCases[] = {0, -1, 1, 36 std::numeric_limits<int>::min(), 37 std::numeric_limits<int>::max()}; 38 for (auto& test_case : kTestCases) { 39 base::Value in(test_case); 40 base::Value out; 41 ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); 42 EXPECT_EQ(in, out); 43 } 44 } 45 46 TEST(ValuesStructTraitsTest, DoubleValue) { 47 static constexpr double kTestCases[] = {-0.0, 48 +0.0, 49 -1.0, 50 +1.0, 51 std::numeric_limits<double>::min(), 52 std::numeric_limits<double>::max()}; 53 for (auto& test_case : kTestCases) { 54 base::Value in(test_case); 55 base::Value out; 56 ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); 57 EXPECT_EQ(in, out); 58 } 59 } 60 61 TEST(ValuesStructTraitsTest, StringValue) { 62 static constexpr const char* kTestCases[] = { 63 "", "ascii", 64 // : Unicode FIREWORKS 65 "\xf0\x9f\x8e\x86", 66 }; 67 for (auto* test_case : kTestCases) { 68 base::Value in(test_case); 69 base::Value out; 70 ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); 71 EXPECT_EQ(in, out); 72 } 73 } 74 75 TEST(ValuesStructTraitsTest, BinaryValue) { 76 std::vector<char> kBinaryData = {'\x00', '\x80', '\xff', '\x7f', '\x01'}; 77 base::Value in(std::move(kBinaryData)); 78 base::Value out; 79 ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); 80 EXPECT_EQ(in, out); 81 } 82 83 TEST(ValuesStructTraitsTest, DictionaryValue) { 84 // Note: here and below, it would be nice to use an initializer list, but 85 // move-only types and initializer lists don't mix. Initializer lists can't be 86 // modified: thus it's not possible to move. 87 std::vector<base::Value::DictStorage::value_type> storage; 88 storage.emplace_back("null", std::make_unique<base::Value>()); 89 storage.emplace_back("bool", std::make_unique<base::Value>(false)); 90 storage.emplace_back("int", std::make_unique<base::Value>(0)); 91 storage.emplace_back("double", std::make_unique<base::Value>(0.0)); 92 storage.emplace_back("string", std::make_unique<base::Value>("0")); 93 storage.emplace_back( 94 "binary", std::make_unique<base::Value>(base::Value::BlobStorage({0}))); 95 storage.emplace_back( 96 "dictionary", std::make_unique<base::Value>(base::Value::DictStorage())); 97 storage.emplace_back( 98 "list", std::make_unique<base::Value>(base::Value::ListStorage())); 99 100 base::Value in( 101 base::Value::DictStorage(std::move(storage), base::KEEP_LAST_OF_DUPES)); 102 base::Value out; 103 ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); 104 EXPECT_EQ(in, out); 105 106 ASSERT_TRUE( 107 mojo::test::SerializeAndDeserialize<mojom::DictionaryValue>(&in, &out)); 108 EXPECT_EQ(in, out); 109 } 110 111 TEST(ValuesStructTraitsTest, SerializeInvalidDictionaryValue) { 112 base::Value in; 113 ASSERT_FALSE(in.is_dict()); 114 115 base::Value out; 116 EXPECT_DCHECK_DEATH( 117 mojo::test::SerializeAndDeserialize<mojom::DictionaryValue>(&in, &out)); 118 } 119 120 TEST(ValuesStructTraitsTest, ListValue) { 121 base::Value::ListStorage storage; 122 storage.emplace_back(); 123 storage.emplace_back(false); 124 storage.emplace_back(0); 125 storage.emplace_back(0.0); 126 storage.emplace_back("0"); 127 storage.emplace_back(base::Value::BlobStorage({0})); 128 storage.emplace_back(base::Value::DictStorage()); 129 storage.emplace_back(base::Value::ListStorage()); 130 base::Value in(std::move(storage)); 131 base::Value out; 132 ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); 133 EXPECT_EQ(in, out); 134 135 ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::ListValue>(&in, &out)); 136 EXPECT_EQ(in, out); 137 } 138 139 TEST(ValuesStructTraitsTest, SerializeInvalidListValue) { 140 base::Value in; 141 ASSERT_FALSE(in.is_dict()); 142 143 base::Value out; 144 EXPECT_DCHECK_DEATH( 145 mojo::test::SerializeAndDeserialize<mojom::ListValue>(&in, &out)); 146 } 147 148 // A deeply nested base::Value should trigger a deserialization error. 149 TEST(ValuesStructTraitsTest, DeeplyNestedValue) { 150 base::Value in; 151 for (int i = 0; i < 100; ++i) { 152 base::Value::ListStorage storage; 153 storage.emplace_back(std::move(in)); 154 in = base::Value(std::move(storage)); 155 } 156 base::Value out; 157 ASSERT_FALSE(mojo::test::SerializeAndDeserialize<mojom::Value>(&in, &out)); 158 } 159 160 } // namespace mojo_base 161