Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "mojo/public/cpp/bindings/array.h" | 5 #include "mojo/public/cpp/bindings/array.h" |
| 6 #include "mojo/public/cpp/bindings/lib/array_serialization.h" | 6 #include "mojo/public/cpp/bindings/lib/array_serialization.h" |
| 7 #include "mojo/public/cpp/bindings/lib/validation_errors.h" | 7 #include "mojo/public/cpp/bindings/lib/validation_errors.h" |
| 8 #include "mojo/public/cpp/system/message_pipe.h" | 8 #include "mojo/public/cpp/system/message_pipe.h" |
| 9 #include "mojo/public/interfaces/bindings/tests/rect.mojom.h" | 9 #include "mojo/public/interfaces/bindings/tests/rect.mojom.h" |
| 10 #include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h" | 10 #include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
| 12 | 12 |
| 13 namespace mojo { | 13 namespace mojo { |
| 14 namespace test { | 14 namespace test { |
| 15 namespace { | 15 namespace { |
| 16 | 16 |
| 17 class StructSerializationAPITest : public testing::Test { | 17 class StructSerializationAPITest : public testing::Test { |
| 18 public: | 18 public: |
| 19 // We Serialize and Deserialize the given |Type|, and expect the given | 19 // We Serialize and Deserialize the given |Type|, and expect the given |
| 20 // serialization warnings. We also validate (and expect a given error) in | 20 // serialization warnings. We also validate (and expect a given error) in |
| 21 // between serialization and deserialization. | 21 // between serialization and deserialization. |
| 22 template <typename Type> | 22 template <typename Type> |
| 23 void SerializeAndDeserialize( | 23 void SerializeAndDeserialize( |
| 24 Type* val, | 24 Type* val, |
| 25 mojo::internal::ValidationError expected_validation_error) { | 25 mojo::internal::ValidationError expected_validation_error) { |
| 26 size_t bytes_written = 0; | |
| 26 size_t num_bytes = val->GetSerializedSize(); | 27 size_t num_bytes = val->GetSerializedSize(); |
| 27 std::vector<uint8_t> bytes(num_bytes + 1); | 28 std::vector<uint8_t> bytes(num_bytes + 1); |
| 28 | 29 |
| 29 // Last byte is a magic value, helps catch a buffer overflow for | 30 // Last byte is a magic value, helps catch a buffer overflow for |
| 30 // serialization. | 31 // serialization. |
| 31 bytes[num_bytes] = 170; | 32 bytes[num_bytes] = 170; |
| 32 val->Serialize(bytes.data(), num_bytes); | 33 val->Serialize(bytes.data(), num_bytes, &bytes_written); |
| 33 EXPECT_EQ(170u, bytes[num_bytes]); | 34 EXPECT_EQ(170u, bytes[num_bytes]); |
| 35 EXPECT_EQ(num_bytes, bytes_written); | |
| 34 | 36 |
| 35 mojo::internal::BoundsChecker bounds_checker(bytes.data(), num_bytes, 0); | 37 mojo::internal::BoundsChecker bounds_checker(bytes.data(), num_bytes, 0); |
| 36 auto actual_validation_error = | 38 auto actual_validation_error = |
| 37 Type::Data_::Validate(bytes.data(), &bounds_checker, nullptr); | 39 Type::Data_::Validate(bytes.data(), &bounds_checker, nullptr); |
| 38 EXPECT_EQ(expected_validation_error, actual_validation_error); | 40 EXPECT_EQ(expected_validation_error, actual_validation_error); |
| 39 | 41 |
| 42 Type out_val; | |
| 43 bool deserialize_ret = out_val.Deserialize(bytes.data(), bytes.size()); | |
| 40 if (actual_validation_error == mojo::internal::ValidationError::NONE) { | 44 if (actual_validation_error == mojo::internal::ValidationError::NONE) { |
| 41 Type out_val; | |
| 42 out_val.Deserialize(bytes.data()); | |
| 43 EXPECT_TRUE(val->Equals(out_val)); | 45 EXPECT_TRUE(val->Equals(out_val)); |
| 44 } | 46 } |
| 47 EXPECT_EQ(actual_validation_error == mojo::internal::ValidationError::NONE, | |
| 48 deserialize_ret); | |
| 45 } | 49 } |
| 46 | 50 |
| 47 private: | 51 private: |
| 48 Environment env_; | 52 Environment env_; |
| 49 }; | 53 }; |
| 50 | 54 |
| 51 TEST_F(StructSerializationAPITest, GetSerializedSize) { | 55 TEST_F(StructSerializationAPITest, GetSerializedSize) { |
| 52 Rect rect; | 56 Rect rect; |
| 53 // 8 byte struct header | 57 // 8 byte struct header |
| 54 // + 16 bytes worth of fields | 58 // + 16 bytes worth of fields |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 83 rect.height = 999; | 87 rect.height = 999; |
| 84 SerializeAndDeserialize(&rect, mojo::internal::ValidationError::NONE); | 88 SerializeAndDeserialize(&rect, mojo::internal::ValidationError::NONE); |
| 85 } | 89 } |
| 86 | 90 |
| 87 { | 91 { |
| 88 SCOPED_TRACE("DefaultFieldValues"); | 92 SCOPED_TRACE("DefaultFieldValues"); |
| 89 DefaultFieldValues default_values; | 93 DefaultFieldValues default_values; |
| 90 SerializeAndDeserialize(&default_values, | 94 SerializeAndDeserialize(&default_values, |
| 91 mojo::internal::ValidationError::NONE); | 95 mojo::internal::ValidationError::NONE); |
| 92 } | 96 } |
| 97 | |
| 98 { | |
| 99 SCOPED_TRACE("NoDefaultFieldValues.Serialize() should fail"); | |
| 100 NoDefaultFieldValues nd; | |
| 101 nd.f0 = true; | |
| 102 nd.f23 = mojo::Array<mojo::String>::New(10); | |
| 103 | |
| 104 char buf[1000]; | |
|
viettrungluu
2016/03/30 17:49:01
Please initialize this (|= {}| is sufficient).
vardhan
2016/03/30 22:49:07
Done.
| |
| 105 EXPECT_FALSE(nd.Serialize(buf, sizeof(buf))); | |
| 106 | |
| 107 size_t bytes_written; | |
|
viettrungluu
2016/03/30 17:49:01
Please initialize this, preferably to something th
vardhan
2016/03/30 22:49:07
Done.
| |
| 108 EXPECT_FALSE(nd.Serialize(buf, sizeof(buf), &bytes_written)); | |
| 109 EXPECT_EQ(160UL, bytes_written); | |
| 110 // The Serialize() shouldn't get around to reserving space for the |f23| | |
| 111 // array field. | |
| 112 EXPECT_LT(bytes_written, nd.GetSerializedSize()); | |
| 113 } | |
| 93 } | 114 } |
| 94 | 115 |
| 95 // This tests serialization of handles -- These should be deaths or | 116 // This tests serialization of handles -- These should be deaths or |
| 96 TEST_F(StructSerializationAPITest, HandlesSerialization) { | 117 TEST_F(StructSerializationAPITest, HandlesSerialization) { |
| 97 { | 118 { |
| 98 SCOPED_TRACE("Uninitialized Array"); | 119 SCOPED_TRACE("Uninitialized Array"); |
| 99 HandleStruct handle_struct; | 120 HandleStruct handle_struct; |
| 100 // TODO(vardhan): Once handles and pointers are encoded inline with | 121 // TODO(vardhan): Once handles and pointers are encoded inline with |
| 101 // serialization, validation should fail at | 122 // serialization, validation should fail at |
| 102 // ValidationError::UNEXPECTED_NULL_POINTER (which happens after the | 123 // ValidationError::UNEXPECTED_NULL_POINTER (which happens after the |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 135 | 156 |
| 136 // We should be able to Serialize/Deserialize a struct that has a nullable | 157 // We should be able to Serialize/Deserialize a struct that has a nullable |
| 137 // handle which is null. | 158 // handle which is null. |
| 138 TEST_F(StructSerializationAPITest, NullableHandleSerialization) { | 159 TEST_F(StructSerializationAPITest, NullableHandleSerialization) { |
| 139 NullableHandleStruct handle_struct; | 160 NullableHandleStruct handle_struct; |
| 140 handle_struct.data = 16; | 161 handle_struct.data = 16; |
| 141 SerializeAndDeserialize(&handle_struct, | 162 SerializeAndDeserialize(&handle_struct, |
| 142 mojo::internal::ValidationError::NONE); | 163 mojo::internal::ValidationError::NONE); |
| 143 } | 164 } |
| 144 | 165 |
| 166 // Test that |Deserialize()| appropriately fails on validation. | |
| 167 TEST_F(StructSerializationAPITest, DeserializationFailure) { | |
| 168 char* buf[100]; | |
|
viettrungluu
2016/03/30 17:49:01
a) Why is this an array of pointers?
b) Please ini
vardhan
2016/03/30 22:49:07
Oops! thanks for catching this, bad typo.
| |
| 169 EmptyStruct es; | |
| 170 | |
| 171 // Bounds checker should fail this, since buf_size is too small. | |
| 172 EXPECT_FALSE(es.Deserialize(buf, 1)); | |
| 173 | |
| 174 es.Serialize(buf, sizeof(buf)); | |
| 175 EXPECT_TRUE(es.Deserialize(buf, sizeof(buf))); | |
| 176 | |
| 177 // Invalid struct header: this should happen inside | |
| 178 // EmptyStruct::Data_::Validate()). | |
| 179 es.Serialize(buf, sizeof(buf)); | |
| 180 EmptyStruct::Data_* es_data = reinterpret_cast<EmptyStruct::Data_*>(buf); | |
|
viettrungluu
2016/03/30 17:49:01
buf being an array of char*'s makes this UB.
vardhan
2016/03/30 22:49:07
Acknowledged.
| |
| 181 es_data->header_.num_bytes = 0; | |
| 182 EXPECT_FALSE(es.Deserialize(buf, sizeof(buf))); | |
| 183 } | |
| 184 | |
| 185 TEST_F(StructSerializationAPITest, DeserializationWithoutValidation) { | |
| 186 const int32_t kMagic = 456; | |
| 187 char* buf[100]; | |
|
viettrungluu
2016/03/30 17:49:01
"
vardhan
2016/03/30 22:49:07
Done.
| |
| 188 ContainsOther::Data_* co_data = reinterpret_cast<ContainsOther::Data_*>(buf); | |
| 189 ContainsOther co; | |
| 190 | |
| 191 // Success case. | |
| 192 co.other = kMagic; | |
| 193 memset(buf, 0, sizeof(buf)); | |
|
viettrungluu
2016/03/30 17:49:01
And by initializing, you can skip this.
vardhan
2016/03/30 22:49:07
Done.
| |
| 194 EXPECT_TRUE(co.Serialize(buf, sizeof(buf))); | |
| 195 co.other = 0; | |
| 196 co.DeserializeWithoutValidation(buf); | |
| 197 EXPECT_EQ(kMagic, co.other); | |
| 198 | |
| 199 // Invalid struct header, but will pass (i.e., won't crash) anyway because we | |
| 200 // don't Validate. | |
| 201 co_data->header_.num_bytes = 0u; | |
| 202 co.DeserializeWithoutValidation(buf); | |
| 203 EXPECT_EQ(kMagic, co_data->other); | |
| 204 EXPECT_EQ(0u, co_data->header_.num_bytes); | |
| 205 } | |
| 206 | |
| 145 } // namespace | 207 } // namespace |
| 146 } // namespace test | 208 } // namespace test |
| 147 } // namespace mojo | 209 } // namespace mojo |
| OLD | NEW |