• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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 // Serialization warnings are only recorded when DLOG is enabled.
6 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
7 
8 #include <stddef.h>
9 #include <utility>
10 
11 #include "mojo/public/cpp/bindings/array.h"
12 #include "mojo/public/cpp/bindings/lib/array_internal.h"
13 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
14 #include "mojo/public/cpp/bindings/lib/serialization.h"
15 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
16 #include "mojo/public/cpp/bindings/string.h"
17 #include "mojo/public/cpp/system/message_pipe.h"
18 #include "mojo/public/interfaces/bindings/tests/serialization_test_structs.mojom.h"
19 #include "mojo/public/interfaces/bindings/tests/test_unions.mojom.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 
22 namespace mojo {
23 namespace test {
24 namespace {
25 
26 using mojo::internal::ContainerValidateParams;
27 
28 // Creates an array of arrays of handles (2 X 3) for testing.
CreateTestNestedHandleArray()29 Array<Array<ScopedHandle>> CreateTestNestedHandleArray() {
30   Array<Array<ScopedHandle>> array(2);
31   for (size_t i = 0; i < array.size(); ++i) {
32     Array<ScopedHandle> nested_array(3);
33     for (size_t j = 0; j < nested_array.size(); ++j) {
34       MessagePipe pipe;
35       nested_array[j] = ScopedHandle::From(std::move(pipe.handle1));
36     }
37     array[i] = std::move(nested_array);
38   }
39 
40   return array;
41 }
42 
43 class SerializationWarningTest : public testing::Test {
44  public:
~SerializationWarningTest()45   ~SerializationWarningTest() override {}
46 
47  protected:
48   template <typename T>
TestWarning(T obj,mojo::internal::ValidationError expected_warning)49   void TestWarning(T obj, mojo::internal::ValidationError expected_warning) {
50     warning_observer_.set_last_warning(mojo::internal::VALIDATION_ERROR_NONE);
51 
52     mojo::internal::SerializationContext context;
53     mojo::internal::FixedBufferForTesting buf(
54         mojo::internal::PrepareToSerialize<T>(obj, &context));
55     typename mojo::internal::MojomTypeTraits<T>::Data* data;
56     mojo::internal::Serialize<T>(obj, &buf, &data, &context);
57 
58     EXPECT_EQ(expected_warning, warning_observer_.last_warning());
59   }
60 
61   template <typename T>
TestArrayWarning(T obj,mojo::internal::ValidationError expected_warning,const ContainerValidateParams * validate_params)62   void TestArrayWarning(T obj,
63                         mojo::internal::ValidationError expected_warning,
64                         const ContainerValidateParams* validate_params) {
65     warning_observer_.set_last_warning(mojo::internal::VALIDATION_ERROR_NONE);
66 
67     mojo::internal::SerializationContext context;
68     mojo::internal::FixedBufferForTesting buf(
69         mojo::internal::PrepareToSerialize<T>(obj, &context));
70     typename mojo::internal::MojomTypeTraits<T>::Data* data;
71     mojo::internal::Serialize<T>(obj, &buf, &data, validate_params, &context);
72 
73     EXPECT_EQ(expected_warning, warning_observer_.last_warning());
74   }
75 
76   template <typename T>
TestUnionWarning(T obj,mojo::internal::ValidationError expected_warning)77   void TestUnionWarning(T obj,
78                         mojo::internal::ValidationError expected_warning) {
79     warning_observer_.set_last_warning(mojo::internal::VALIDATION_ERROR_NONE);
80 
81     mojo::internal::SerializationContext context;
82     mojo::internal::FixedBufferForTesting buf(
83         mojo::internal::PrepareToSerialize<T>(obj, false, &context));
84     typename mojo::internal::MojomTypeTraits<T>::Data* data;
85     mojo::internal::Serialize<T>(obj, &buf, &data, false, &context);
86 
87     EXPECT_EQ(expected_warning, warning_observer_.last_warning());
88   }
89 
90   mojo::internal::SerializationWarningObserverForTesting warning_observer_;
91 };
92 
TEST_F(SerializationWarningTest,HandleInStruct)93 TEST_F(SerializationWarningTest, HandleInStruct) {
94   Struct2Ptr test_struct(Struct2::New());
95   EXPECT_FALSE(test_struct->hdl.is_valid());
96 
97   TestWarning(std::move(test_struct),
98               mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE);
99 
100   test_struct = Struct2::New();
101   MessagePipe pipe;
102   test_struct->hdl = ScopedHandle::From(std::move(pipe.handle1));
103 
104   TestWarning(std::move(test_struct), mojo::internal::VALIDATION_ERROR_NONE);
105 }
106 
TEST_F(SerializationWarningTest,StructInStruct)107 TEST_F(SerializationWarningTest, StructInStruct) {
108   Struct3Ptr test_struct(Struct3::New());
109   EXPECT_TRUE(!test_struct->struct_1);
110 
111   TestWarning(std::move(test_struct),
112               mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER);
113 
114   test_struct = Struct3::New();
115   test_struct->struct_1 = Struct1::New();
116 
117   TestWarning(std::move(test_struct), mojo::internal::VALIDATION_ERROR_NONE);
118 }
119 
TEST_F(SerializationWarningTest,ArrayOfStructsInStruct)120 TEST_F(SerializationWarningTest, ArrayOfStructsInStruct) {
121   Struct4Ptr test_struct(Struct4::New());
122   test_struct->data.resize(1);
123 
124   TestWarning(std::move(test_struct),
125               mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER);
126 
127   test_struct = Struct4::New();
128   test_struct->data.resize(0);
129 
130   TestWarning(std::move(test_struct), mojo::internal::VALIDATION_ERROR_NONE);
131 
132   test_struct = Struct4::New();
133   test_struct->data.resize(1);
134   test_struct->data[0] = Struct1::New();
135 
136   TestWarning(std::move(test_struct), mojo::internal::VALIDATION_ERROR_NONE);
137 }
138 
TEST_F(SerializationWarningTest,FixedArrayOfStructsInStruct)139 TEST_F(SerializationWarningTest, FixedArrayOfStructsInStruct) {
140   Struct5Ptr test_struct(Struct5::New());
141   test_struct->pair.resize(1);
142   test_struct->pair[0] = Struct1::New();
143 
144   TestWarning(std::move(test_struct),
145               mojo::internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER);
146 
147   test_struct = Struct5::New();
148   test_struct->pair.resize(2);
149   test_struct->pair[0] = Struct1::New();
150   test_struct->pair[1] = Struct1::New();
151 
152   TestWarning(std::move(test_struct), mojo::internal::VALIDATION_ERROR_NONE);
153 }
154 
TEST_F(SerializationWarningTest,ArrayOfArraysOfHandles)155 TEST_F(SerializationWarningTest, ArrayOfArraysOfHandles) {
156   Array<Array<ScopedHandle>> test_array = CreateTestNestedHandleArray();
157   test_array[0] = nullptr;
158   test_array[1][0] = ScopedHandle();
159 
160   ContainerValidateParams validate_params_0(
161       0, true, new ContainerValidateParams(0, true, nullptr));
162   TestArrayWarning(std::move(test_array), mojo::internal::VALIDATION_ERROR_NONE,
163                    &validate_params_0);
164 
165   test_array = CreateTestNestedHandleArray();
166   test_array[0] = nullptr;
167   ContainerValidateParams validate_params_1(
168       0, false, new ContainerValidateParams(0, true, nullptr));
169   TestArrayWarning(std::move(test_array),
170                    mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
171                    &validate_params_1);
172 
173   test_array = CreateTestNestedHandleArray();
174   test_array[1][0] = ScopedHandle();
175   ContainerValidateParams validate_params_2(
176       0, true, new ContainerValidateParams(0, false, nullptr));
177   TestArrayWarning(std::move(test_array),
178                    mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
179                    &validate_params_2);
180 }
181 
TEST_F(SerializationWarningTest,ArrayOfStrings)182 TEST_F(SerializationWarningTest, ArrayOfStrings) {
183   Array<String> test_array(3);
184   for (size_t i = 0; i < test_array.size(); ++i)
185     test_array[i] = "hello";
186 
187   ContainerValidateParams validate_params_0(
188       0, true, new ContainerValidateParams(0, false, nullptr));
189   TestArrayWarning(std::move(test_array), mojo::internal::VALIDATION_ERROR_NONE,
190                    &validate_params_0);
191 
192   test_array = Array<String>(3);
193   for (size_t i = 0; i < test_array.size(); ++i)
194     test_array[i] = nullptr;
195   ContainerValidateParams validate_params_1(
196       0, false, new ContainerValidateParams(0, false, nullptr));
197   TestArrayWarning(std::move(test_array),
198                    mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
199                    &validate_params_1);
200 
201   test_array = Array<String>(2);
202   ContainerValidateParams validate_params_2(
203       3, true, new ContainerValidateParams(0, false, nullptr));
204   TestArrayWarning(std::move(test_array),
205                    mojo::internal::VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER,
206                    &validate_params_2);
207 }
208 
TEST_F(SerializationWarningTest,StructInUnion)209 TEST_F(SerializationWarningTest, StructInUnion) {
210   DummyStructPtr dummy(nullptr);
211   ObjectUnionPtr obj(ObjectUnion::New());
212   obj->set_f_dummy(std::move(dummy));
213 
214   TestUnionWarning(std::move(obj),
215                    mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER);
216 }
217 
TEST_F(SerializationWarningTest,UnionInUnion)218 TEST_F(SerializationWarningTest, UnionInUnion) {
219   PodUnionPtr pod(nullptr);
220   ObjectUnionPtr obj(ObjectUnion::New());
221   obj->set_f_pod_union(std::move(pod));
222 
223   TestUnionWarning(std::move(obj),
224                    mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER);
225 }
226 
TEST_F(SerializationWarningTest,HandleInUnion)227 TEST_F(SerializationWarningTest, HandleInUnion) {
228   ScopedMessagePipeHandle pipe;
229   HandleUnionPtr handle(HandleUnion::New());
230   handle->set_f_message_pipe(std::move(pipe));
231 
232   TestUnionWarning(std::move(handle),
233                    mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE);
234 }
235 
236 }  // namespace
237 }  // namespace test
238 }  // namespace mojo
239 
240 #endif
241