Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(350)

Side by Side Diff: mojo/public/cpp/bindings/tests/validation_unittest.cc

Issue 2250183003: Make the fuchsia mojo/public repo the source of truth. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 #include <stdio.h>
6
7 #include <algorithm>
8 #include <string>
9 #include <utility>
10 #include <vector>
11
12 #include "gtest/gtest.h"
13 #include "mojo/public/cpp/bindings/binding.h"
14 #include "mojo/public/cpp/bindings/interface_ptr.h"
15 #include "mojo/public/cpp/bindings/lib/connector.h"
16 #include "mojo/public/cpp/bindings/lib/message_header_validator.h"
17 #include "mojo/public/cpp/bindings/lib/router.h"
18 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
19 #include "mojo/public/cpp/bindings/message.h"
20 #include "mojo/public/cpp/bindings/tests/validation_test_input_parser.h"
21 #include "mojo/public/cpp/bindings/tests/validation_util.h"
22 #include "mojo/public/cpp/system/macros.h"
23 #include "mojo/public/cpp/system/message_pipe.h"
24 #include "mojo/public/cpp/test_support/test_support.h"
25 #include "mojo/public/cpp/utility/run_loop.h"
26 #include "mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom .h"
27
28 namespace mojo {
29
30 using internal::MessageValidator;
31 using internal::MessageValidatorList;
32 using internal::ValidationError;
33 using internal::ValidationErrorToString;
34
35 namespace test {
36 namespace {
37
38 template <typename T>
39 void Append(std::vector<uint8_t>* data_vector, T data) {
40 size_t pos = data_vector->size();
41 data_vector->resize(pos + sizeof(T));
42 memcpy(&(*data_vector)[pos], &data, sizeof(T));
43 }
44
45 bool TestInputParser(const std::string& input,
46 bool expected_result,
47 const std::vector<uint8_t>& expected_data,
48 size_t expected_num_handles) {
49 std::vector<uint8_t> data;
50 size_t num_handles;
51 std::string error_message;
52
53 bool result =
54 ParseValidationTestInput(input, &data, &num_handles, &error_message);
55 if (expected_result) {
56 if (result && error_message.empty() && expected_data == data &&
57 expected_num_handles == num_handles) {
58 return true;
59 }
60
61 // Compare with an empty string instead of checking |error_message.empty()|,
62 // so that the message will be printed out if the two are not equal.
63 EXPECT_EQ(std::string(), error_message);
64 EXPECT_EQ(expected_data, data);
65 EXPECT_EQ(expected_num_handles, num_handles);
66 return false;
67 }
68
69 EXPECT_FALSE(error_message.empty());
70 return !result && !error_message.empty();
71 }
72
73 void RunValidationTests(const std::string& prefix,
74 const MessageValidatorList& validators,
75 MessageReceiver* test_message_receiver) {
76 std::vector<std::string> tests = validation_util::GetMatchingTests(prefix);
77
78 for (size_t i = 0; i < tests.size(); ++i) {
79 std::string expected;
80 std::vector<uint8_t> data;
81 size_t num_handles;
82 ASSERT_TRUE(validation_util::ReadTestCase(tests[i], &data, &num_handles,
83 &expected));
84
85 Message message;
86 message.AllocUninitializedData(data.size());
87 if (!data.empty())
88 memcpy(message.mutable_data(), &data[0], data.size());
89 message.mutable_handles()->resize(num_handles);
90
91 std::string actual;
92 auto result = RunValidatorsOnMessage(validators, &message, nullptr);
93 if (result == ValidationError::NONE) {
94 ignore_result(test_message_receiver->Accept(&message));
95 actual = "PASS";
96 } else {
97 actual = ValidationErrorToString(result);
98 }
99
100 EXPECT_EQ(expected, actual) << "failed test: " << tests[i];
101 }
102 }
103
104 class DummyMessageReceiver : public MessageReceiver {
105 public:
106 bool Accept(Message* message) override {
107 return true; // Any message is OK.
108 }
109 };
110
111 class ValidationIntegrationTest : public testing::Test {
112 public:
113 ValidationIntegrationTest() : test_message_receiver_(nullptr) {}
114
115 ~ValidationIntegrationTest() override {}
116
117 void SetUp() override {
118 ScopedMessagePipeHandle tester_endpoint;
119 ASSERT_EQ(MOJO_RESULT_OK,
120 CreateMessagePipe(nullptr, &tester_endpoint, &testee_endpoint_));
121 test_message_receiver_ =
122 new TestMessageReceiver(this, tester_endpoint.Pass());
123 }
124
125 void TearDown() override {
126 delete test_message_receiver_;
127 test_message_receiver_ = nullptr;
128
129 // Make sure that the other end receives the OnConnectionError()
130 // notification.
131 PumpMessages();
132 }
133
134 MessageReceiver* test_message_receiver() { return test_message_receiver_; }
135
136 ScopedMessagePipeHandle testee_endpoint() { return testee_endpoint_.Pass(); }
137
138 private:
139 class TestMessageReceiver : public MessageReceiver {
140 public:
141 TestMessageReceiver(ValidationIntegrationTest* owner,
142 ScopedMessagePipeHandle handle)
143 : owner_(owner), connector_(handle.Pass()) {
144 connector_.set_enforce_errors_from_incoming_receiver(false);
145 }
146 ~TestMessageReceiver() override {}
147
148 bool Accept(Message* message) override {
149 bool rv = connector_.Accept(message);
150 owner_->PumpMessages();
151 return rv;
152 }
153
154 public:
155 ValidationIntegrationTest* owner_;
156 mojo::internal::Connector connector_;
157 };
158
159 void PumpMessages() { loop_.RunUntilIdle(); }
160
161 RunLoop loop_;
162 TestMessageReceiver* test_message_receiver_;
163 ScopedMessagePipeHandle testee_endpoint_;
164 };
165
166 class IntegrationTestInterfaceImpl : public IntegrationTestInterface {
167 public:
168 ~IntegrationTestInterfaceImpl() override {}
169
170 void Method0(BasicStructPtr param0,
171 const Method0Callback& callback) override {
172 callback.Run(Array<uint8_t>::New(0u));
173 }
174 };
175
176 class FailingValidator : public mojo::internal::MessageValidator {
177 public:
178 explicit FailingValidator(ValidationError err) : err_(err) {}
179 ValidationError Validate(const Message* message, std::string* err) override {
180 return err_;
181 }
182
183 private:
184 ValidationError err_;
185 };
186
187 TEST(ValidationTest, InputParser) {
188 {
189 // The parser, as well as Append() defined above, assumes that this code is
190 // running on a little-endian platform. Test whether that is true.
191 uint16_t x = 1;
192 ASSERT_EQ(1, *(reinterpret_cast<char*>(&x)));
193 }
194 {
195 // Test empty input.
196 std::string input;
197 std::vector<uint8_t> expected;
198
199 EXPECT_TRUE(TestInputParser(input, true, expected, 0));
200 }
201 {
202 // Test input that only consists of comments and whitespaces.
203 std::string input = " \t // hello world \n\r \t// the answer is 42 ";
204 std::vector<uint8_t> expected;
205
206 EXPECT_TRUE(TestInputParser(input, true, expected, 0));
207 }
208 {
209 std::string input =
210 "[u1]0x10// hello world !! \n\r \t [u2]65535 \n"
211 "[u4]65536 [u8]0xFFFFFFFFFFFFFFFF 0 0Xff";
212 std::vector<uint8_t> expected;
213 Append(&expected, static_cast<uint8_t>(0x10));
214 Append(&expected, static_cast<uint16_t>(65535));
215 Append(&expected, static_cast<uint32_t>(65536));
216 Append(&expected, static_cast<uint64_t>(0xffffffffffffffff));
217 Append(&expected, static_cast<uint8_t>(0));
218 Append(&expected, static_cast<uint8_t>(0xff));
219
220 EXPECT_TRUE(TestInputParser(input, true, expected, 0));
221 }
222 {
223 std::string input = "[s8]-0x800 [s1]-128\t[s2]+0 [s4]-40";
224 std::vector<uint8_t> expected;
225 Append(&expected, -static_cast<int64_t>(0x800));
226 Append(&expected, static_cast<int8_t>(-128));
227 Append(&expected, static_cast<int16_t>(0));
228 Append(&expected, static_cast<int32_t>(-40));
229
230 EXPECT_TRUE(TestInputParser(input, true, expected, 0));
231 }
232 {
233 std::string input = "[b]00001011 [b]10000000 // hello world\r [b]00000000";
234 std::vector<uint8_t> expected;
235 Append(&expected, static_cast<uint8_t>(11));
236 Append(&expected, static_cast<uint8_t>(128));
237 Append(&expected, static_cast<uint8_t>(0));
238
239 EXPECT_TRUE(TestInputParser(input, true, expected, 0));
240 }
241 {
242 std::string input = "[f]+.3e9 [d]-10.03";
243 std::vector<uint8_t> expected;
244 Append(&expected, +.3e9f);
245 Append(&expected, -10.03);
246
247 EXPECT_TRUE(TestInputParser(input, true, expected, 0));
248 }
249 {
250 std::string input = "[dist4]foo 0 [dist8]bar 0 [anchr]foo [anchr]bar";
251 std::vector<uint8_t> expected;
252 Append(&expected, static_cast<uint32_t>(14));
253 Append(&expected, static_cast<uint8_t>(0));
254 Append(&expected, static_cast<uint64_t>(9));
255 Append(&expected, static_cast<uint8_t>(0));
256
257 EXPECT_TRUE(TestInputParser(input, true, expected, 0));
258 }
259 {
260 std::string input = "// This message has handles! \n[handles]50 [u8]2";
261 std::vector<uint8_t> expected;
262 Append(&expected, static_cast<uint64_t>(2));
263
264 EXPECT_TRUE(TestInputParser(input, true, expected, 50));
265 }
266
267 // Test some failure cases.
268 {
269 const char* error_inputs[] = {"/ hello world",
270 "[u1]x",
271 "[u2]-1000",
272 "[u1]0x100",
273 "[s2]-0x8001",
274 "[b]1",
275 "[b]1111111k",
276 "[dist4]unmatched",
277 "[anchr]hello [dist8]hello",
278 "[dist4]a [dist4]a [anchr]a",
279 "[dist4]a [anchr]a [dist4]a [anchr]a",
280 "0 [handles]50",
281 nullptr};
282
283 for (size_t i = 0; error_inputs[i]; ++i) {
284 std::vector<uint8_t> expected;
285 if (!TestInputParser(error_inputs[i], false, expected, 0))
286 ADD_FAILURE() << "Unexpected test result for: " << error_inputs[i];
287 }
288 }
289 }
290
291 TEST(ValidationTest, Conformance) {
292 DummyMessageReceiver dummy_receiver;
293 MessageValidatorList validators;
294 validators.push_back(std::unique_ptr<MessageValidator>(
295 new mojo::internal::MessageHeaderValidator));
296 validators.push_back(std::unique_ptr<MessageValidator>(
297 new ConformanceTestInterface::RequestValidator_));
298
299 RunValidationTests("conformance_", validators, &dummy_receiver);
300 }
301
302 // This test is similar to Conformance test but its goal is specifically
303 // do bounds-check testing of message validation. For example we test the
304 // detection of off-by-one errors in method ordinals.
305 TEST(ValidationTest, BoundsCheck) {
306 DummyMessageReceiver dummy_receiver;
307 MessageValidatorList validators;
308 validators.push_back(std::unique_ptr<MessageValidator>(
309 new mojo::internal::MessageHeaderValidator));
310 validators.push_back(std::unique_ptr<MessageValidator>(
311 new BoundsCheckTestInterface::RequestValidator_));
312
313 RunValidationTests("boundscheck_", validators, &dummy_receiver);
314 }
315
316 // This test is similar to the Conformance test but for responses.
317 TEST(ValidationTest, ResponseConformance) {
318 DummyMessageReceiver dummy_receiver;
319 MessageValidatorList validators;
320 validators.push_back(std::unique_ptr<MessageValidator>(
321 new mojo::internal::MessageHeaderValidator));
322 validators.push_back(std::unique_ptr<MessageValidator>(
323 new ConformanceTestInterface::ResponseValidator_));
324
325 RunValidationTests("resp_conformance_", validators, &dummy_receiver);
326 }
327
328 // This test is similar to the BoundsCheck test but for responses.
329 TEST(ValidationTest, ResponseBoundsCheck) {
330 DummyMessageReceiver dummy_receiver;
331 MessageValidatorList validators;
332 validators.push_back(std::unique_ptr<MessageValidator>(
333 new mojo::internal::MessageHeaderValidator));
334 validators.push_back(std::unique_ptr<MessageValidator>(
335 new BoundsCheckTestInterface::ResponseValidator_));
336
337 RunValidationTests("resp_boundscheck_", validators, &dummy_receiver);
338 }
339
340 // Test that InterfacePtr<X> applies the correct validators and they don't
341 // conflict with each other:
342 // - MessageHeaderValidator
343 // - X::ResponseValidator_
344 TEST_F(ValidationIntegrationTest, InterfacePtr) {
345 IntegrationTestInterfacePtr interface_ptr =
346 IntegrationTestInterfacePtr::Create(
347 InterfaceHandle<IntegrationTestInterface>(testee_endpoint(), 0u));
348 interface_ptr.internal_state()->router_for_testing()->EnableTestingMode();
349
350 mojo::internal::MessageValidatorList validators;
351 validators.push_back(std::unique_ptr<MessageValidator>(
352 new mojo::internal::MessageHeaderValidator));
353 validators.push_back(std::unique_ptr<MessageValidator>(
354 new typename IntegrationTestInterface::ResponseValidator_));
355
356 RunValidationTests("integration_intf_resp", validators,
357 test_message_receiver());
358 RunValidationTests("integration_msghdr", validators, test_message_receiver());
359 }
360
361 // Test that Binding<X> applies the correct validators and they don't
362 // conflict with each other:
363 // - MessageHeaderValidator
364 // - X::RequestValidator_
365 TEST_F(ValidationIntegrationTest, Binding) {
366 IntegrationTestInterfaceImpl interface_impl;
367 Binding<IntegrationTestInterface> binding(
368 &interface_impl,
369 InterfaceRequest<IntegrationTestInterface>(testee_endpoint().Pass()));
370 binding.internal_router()->EnableTestingMode();
371
372 mojo::internal::MessageValidatorList validators;
373 validators.push_back(std::unique_ptr<MessageValidator>(
374 new mojo::internal::MessageHeaderValidator));
375 validators.push_back(std::unique_ptr<MessageValidator>(
376 new typename IntegrationTestInterface::RequestValidator_));
377
378 RunValidationTests("integration_intf_rqst", validators,
379 test_message_receiver());
380 RunValidationTests("integration_msghdr", validators, test_message_receiver());
381 }
382
383 // Test pointer validation (specifically, that the encoded offset is 32-bit)
384 TEST(ValidationTest, ValidateEncodedPointer) {
385 uint64_t offset;
386
387 offset = 0ULL;
388 EXPECT_TRUE(mojo::internal::ValidateEncodedPointer(&offset));
389
390 offset = 1ULL;
391 EXPECT_TRUE(mojo::internal::ValidateEncodedPointer(&offset));
392
393 // offset must be <= 32-bit.
394 offset = std::numeric_limits<uint32_t>::max() + 1ULL;
395 EXPECT_FALSE(mojo::internal::ValidateEncodedPointer(&offset));
396 }
397
398 TEST(ValidationTest, RunValidatorsOnMessageTest) {
399 Message msg;
400 mojo::internal::MessageValidatorList validators;
401
402 validators.push_back(std::unique_ptr<MessageValidator>(
403 new mojo::internal::PassThroughValidator));
404 EXPECT_EQ(ValidationError::NONE,
405 RunValidatorsOnMessage(validators, &msg, nullptr));
406
407 validators.push_back(std::unique_ptr<MessageValidator>(
408 new FailingValidator(ValidationError::MESSAGE_HEADER_INVALID_FLAGS)));
409 EXPECT_EQ(ValidationError::MESSAGE_HEADER_INVALID_FLAGS,
410 RunValidatorsOnMessage(validators, &msg, nullptr));
411
412 validators.insert(validators.begin(),
413 std::unique_ptr<MessageValidator>(
414 new FailingValidator(ValidationError::ILLEGAL_HANDLE)));
415 EXPECT_EQ(ValidationError::ILLEGAL_HANDLE,
416 RunValidatorsOnMessage(validators, &msg, nullptr));
417 }
418
419 // Tests the IsValidValue() function generated for BasicEnum.
420 TEST(EnumValueValidationTest, BasicEnum) {
421 // BasicEnum can have -3,0,1,10 as possible integral values.
422 EXPECT_FALSE(BasicEnum_IsValidValue(static_cast<BasicEnum>(-4)));
423 EXPECT_TRUE(BasicEnum_IsValidValue(static_cast<BasicEnum>(-3)));
424 EXPECT_FALSE(BasicEnum_IsValidValue(static_cast<BasicEnum>(-2)));
425 EXPECT_FALSE(BasicEnum_IsValidValue(static_cast<BasicEnum>(-1)));
426 EXPECT_TRUE(BasicEnum_IsValidValue(static_cast<BasicEnum>(0)));
427 EXPECT_TRUE(BasicEnum_IsValidValue(static_cast<BasicEnum>(1)));
428 EXPECT_FALSE(BasicEnum_IsValidValue(static_cast<BasicEnum>(2)));
429 EXPECT_FALSE(BasicEnum_IsValidValue(static_cast<BasicEnum>(9)));
430 // In the mojom, we represent this value as hex (0xa).
431 EXPECT_TRUE(BasicEnum_IsValidValue(static_cast<BasicEnum>(10)));
432 EXPECT_FALSE(BasicEnum_IsValidValue(static_cast<BasicEnum>(11)));
433 }
434
435 // Tests the IsValidValue() method generated for StructWithEnum.
436 TEST(EnumValueValidationTest, EnumWithin) {
437 // StructWithEnum::EnumWithin can have [0,4] as possible integral values.
438 EXPECT_FALSE(StructWithEnum::EnumWithin_IsValidValue(
439 static_cast<StructWithEnum::EnumWithin>(-1)));
440 EXPECT_TRUE(StructWithEnum::EnumWithin_IsValidValue(
441 static_cast<StructWithEnum::EnumWithin>(0)));
442 EXPECT_TRUE(StructWithEnum::EnumWithin_IsValidValue(
443 static_cast<StructWithEnum::EnumWithin>(1)));
444 EXPECT_TRUE(StructWithEnum::EnumWithin_IsValidValue(
445 static_cast<StructWithEnum::EnumWithin>(2)));
446 EXPECT_TRUE(StructWithEnum::EnumWithin_IsValidValue(
447 static_cast<StructWithEnum::EnumWithin>(3)));
448 EXPECT_FALSE(StructWithEnum::EnumWithin_IsValidValue(
449 static_cast<StructWithEnum::EnumWithin>(4)));
450 }
451
452 } // namespace
453 } // namespace test
454 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/public/cpp/bindings/tests/validation_test_input_parser.cc ('k') | mojo/public/cpp/bindings/tests/validation_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698