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

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

Issue 322003002: Mojo message validation tests: add integration tests and move existing conformance tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 6 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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 <stdio.h> 5 #include <stdio.h>
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <sstream>
9 #include <string> 8 #include <string>
10 #include <vector> 9 #include <vector>
11 10
11 #include "mojo/public/cpp/bindings/interface_impl.h"
12 #include "mojo/public/cpp/bindings/interface_ptr.h"
13 #include "mojo/public/cpp/bindings/lib/connector.h"
14 #include "mojo/public/cpp/bindings/lib/filter_chain.h"
12 #include "mojo/public/cpp/bindings/lib/message_header_validator.h" 15 #include "mojo/public/cpp/bindings/lib/message_header_validator.h"
16 #include "mojo/public/cpp/bindings/lib/router.h"
13 #include "mojo/public/cpp/bindings/lib/validation_errors.h" 17 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
18 #include "mojo/public/cpp/bindings/message.h"
14 #include "mojo/public/cpp/bindings/tests/validation_test_input_parser.h" 19 #include "mojo/public/cpp/bindings/tests/validation_test_input_parser.h"
20 #include "mojo/public/cpp/environment/environment.h"
21 #include "mojo/public/cpp/system/core.h"
15 #include "mojo/public/cpp/test_support/test_support.h" 22 #include "mojo/public/cpp/test_support/test_support.h"
23 #include "mojo/public/cpp/utility/run_loop.h"
24 #include "mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom .h"
16 #include "testing/gtest/include/gtest/gtest.h" 25 #include "testing/gtest/include/gtest/gtest.h"
17 26
18 namespace mojo { 27 namespace mojo {
19 namespace test { 28 namespace test {
20 namespace { 29 namespace {
21 30
22 template <typename T> 31 template <typename T>
23 void Append(std::vector<uint8_t>* data_vector, T data) { 32 void Append(std::vector<uint8_t>* data_vector, T data) {
24 size_t pos = data_vector->size(); 33 size_t pos = data_vector->size();
25 data_vector->resize(pos + sizeof(T)); 34 data_vector->resize(pos + sizeof(T));
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 size_t pos = result->find_last_not_of('\n'); 118 size_t pos = result->find_last_not_of('\n');
110 if (pos == std::string::npos) 119 if (pos == std::string::npos)
111 result->clear(); 120 result->clear();
112 else 121 else
113 result->resize(pos + 1); 122 result->resize(pos + 1);
114 123
115 return true; 124 return true;
116 } 125 }
117 126
118 std::string GetPath(const std::string& root, const std::string& suffix) { 127 std::string GetPath(const std::string& root, const std::string& suffix) {
119 return "mojo/public/interfaces/bindings/tests/data/" + root + suffix; 128 return "mojo/public/interfaces/bindings/tests/data/validation/" +
129 root + suffix;
120 } 130 }
121 131
122 void RunValidationTest(const std::string& root, std::string (*func)(Message*)) { 132 // |message| should be a newly created object.
133 bool ReadTestCase(const std::string& test,
134 Message* message,
135 std::string* expected) {
123 std::vector<uint8_t> data; 136 std::vector<uint8_t> data;
124 ASSERT_TRUE(ReadAndParseDataFile(GetPath(root, ".data"), &data)); 137 if (!ReadAndParseDataFile(GetPath(test, ".data"), &data) ||
138 !ReadResultFile(GetPath(test, ".expected"), expected)) {
139 return false;
140 }
125 141
126 std::string expected; 142 message->AllocUninitializedData(static_cast<uint32_t>(data.size()));
127 ASSERT_TRUE(ReadResultFile(GetPath(root, ".expected"), &expected)); 143 if (!data.empty())
144 memcpy(message->mutable_data(), &data[0], data.size());
128 145
129 Message message; 146 // TODO(yzshen): add support to specify the number of handles associated with
130 message.AllocUninitializedData(static_cast<uint32_t>(data.size())); 147 // the message.
131 if (!data.empty())
132 memcpy(message.mutable_data(), &data[0], data.size());
133 148
134 std::string result = func(&message); 149 return true;
135 EXPECT_EQ(expected, result) << "failed test: " << root; 150 }
151
152 void RunValidationTests(const std::string& prefix,
153 MessageReceiver* test_message_receiver) {
154 std::vector<std::string> names =
155 EnumerateSourceRootRelativeDirectory(GetPath("", ""));
156 std::vector<std::string> tests = GetMatchingTests(names, prefix);
157
158 for (size_t i = 0; i < tests.size(); ++i) {
159 Message message;
160 std::string expected;
161 ASSERT_TRUE(ReadTestCase(tests[i], &message, &expected));
162
163 std::string result;
164 mojo::internal::ValidationErrorObserverForTesting observer;
165 test_message_receiver->Accept(&message);
166 if (observer.last_error() == mojo::internal::VALIDATION_ERROR_NONE)
167 result = "PASS";
168 else
169 result = mojo::internal::ValidationErrorToString(observer.last_error());
170
171 EXPECT_EQ(expected, result) << "failed test: " << tests[i];
172 }
136 } 173 }
137 174
138 class DummyMessageReceiver : public MessageReceiver { 175 class DummyMessageReceiver : public MessageReceiver {
139 public: 176 public:
140 virtual bool Accept(Message* message) MOJO_OVERRIDE { 177 virtual bool Accept(Message* message) MOJO_OVERRIDE {
141 return true; // Any message is OK. 178 return true; // Any message is OK.
142 } 179 }
143 }; 180 };
144 181
145 std::string DumpMessageHeader(Message* message) { 182 class ValidationIntegrationTest : public testing::Test {
146 internal::ValidationErrorObserverForTesting observer; 183 public:
147 DummyMessageReceiver not_reached_receiver; 184 ValidationIntegrationTest() : test_message_receiver_(NULL) {
148 internal::MessageHeaderValidator validator(&not_reached_receiver);
149 bool rv = validator.Accept(message);
150 if (!rv) {
151 EXPECT_NE(internal::VALIDATION_ERROR_NONE, observer.last_error());
152 return internal::ValidationErrorToString(observer.last_error());
153 } 185 }
154 186
155 std::ostringstream os; 187 virtual ~ValidationIntegrationTest() {
156 os << "num_bytes: " << message->header()->num_bytes << "\n" 188 }
157 << "num_fields: " << message->header()->num_fields << "\n" 189
158 << "name: " << message->header()->name << "\n" 190 virtual void SetUp() MOJO_OVERRIDE {
159 << "flags: " << message->header()->flags; 191 ScopedMessagePipeHandle tester_endpoint;
160 return os.str(); 192 ASSERT_EQ(MOJO_RESULT_OK,
161 } 193 CreateMessagePipe(&tester_endpoint, &testee_endpoint_));
194 test_message_receiver_ =
195 new TestMessageReceiver(this, tester_endpoint.Pass());
196 }
197
198 virtual void TearDown() MOJO_OVERRIDE {
199 delete test_message_receiver_;
200 test_message_receiver_ = NULL;
201
202 // Make sure that the other end receives the OnConnectionError()
203 // notification.
204 PumpMessages();
205 }
206
207 MessageReceiver* test_message_receiver() {
208 return test_message_receiver_;
209 }
210
211 ScopedMessagePipeHandle testee_endpoint() {
212 return testee_endpoint_.Pass();
213 }
214
215 private:
216 class TestMessageReceiver : public MessageReceiver {
217 public:
218 TestMessageReceiver(ValidationIntegrationTest* owner,
219 ScopedMessagePipeHandle handle)
220 : owner_(owner),
221 connector_(handle.Pass()) {
222
darin (slow to review) 2014/06/12 23:06:56 nit: nuke extra newline
yzshen1 2014/06/12 23:12:21 Done.
223 }
224 virtual ~TestMessageReceiver() {
225 }
226
227 virtual bool Accept(Message* message) MOJO_OVERRIDE {
228 bool rv = connector_.Accept(message);
229 owner_->PumpMessages();
230 return rv;
231 }
232
233 public:
234 ValidationIntegrationTest* owner_;
235 mojo::internal::Connector connector_;
236 };
237
238 void PumpMessages() {
239 loop_.RunUntilIdle();
240 }
241
242 Environment env_;
243 RunLoop loop_;
244 TestMessageReceiver* test_message_receiver_;
245 ScopedMessagePipeHandle testee_endpoint_;
246 };
247
248 class IntegrationTestInterface1Client : public IntegrationTestInterface1 {
249 public:
250 virtual ~IntegrationTestInterface1Client() {
251 }
252
253 virtual void Method0(BasicStructPtr param0) MOJO_OVERRIDE {
254 }
255 };
256
257 class IntegrationTestInterface1Impl
258 : public InterfaceImpl<IntegrationTestInterface1> {
259 public:
260 virtual ~IntegrationTestInterface1Impl() {
261 }
262
263 virtual void Method0(BasicStructPtr param0) MOJO_OVERRIDE {
264 }
265
266 virtual void OnConnectionError() MOJO_OVERRIDE {
267 delete this;
268 }
269 };
162 270
163 TEST(ValidationTest, InputParser) { 271 TEST(ValidationTest, InputParser) {
164 { 272 {
165 // The parser, as well as Append() defined above, assumes that this code is 273 // The parser, as well as Append() defined above, assumes that this code is
166 // running on a little-endian platform. Test whether that is true. 274 // running on a little-endian platform. Test whether that is true.
167 uint16_t x = 1; 275 uint16_t x = 1;
168 ASSERT_EQ(1, *(reinterpret_cast<char*>(&x))); 276 ASSERT_EQ(1, *(reinterpret_cast<char*>(&x)));
169 } 277 }
170 { 278 {
171 // Test empty input. 279 // Test empty input.
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 }; 355 };
248 356
249 for (size_t i = 0; error_inputs[i]; ++i) { 357 for (size_t i = 0; error_inputs[i]; ++i) {
250 std::vector<uint8_t> expected; 358 std::vector<uint8_t> expected;
251 if (!TestInputParser(error_inputs[i], false, expected)) 359 if (!TestInputParser(error_inputs[i], false, expected))
252 ADD_FAILURE() << "Unexpected test result for: " << error_inputs[i]; 360 ADD_FAILURE() << "Unexpected test result for: " << error_inputs[i];
253 } 361 }
254 } 362 }
255 } 363 }
256 364
257 TEST(ValidationTest, TestAll) { 365 TEST(ValidationTest, Conformance) {
258 std::vector<std::string> names = 366 DummyMessageReceiver dummy_receiver;
259 EnumerateSourceRootRelativeDirectory(GetPath("", "")); 367 mojo::internal::FilterChain validators(&dummy_receiver);
368 validators.Append<mojo::internal::MessageHeaderValidator>();
369 validators.Append<ConformanceTestInterface::RequestValidator_>();
260 370
261 std::vector<std::string> header_tests = 371 // TODO(yzshen): add more conformance tests.
262 GetMatchingTests(names, "validate_header_"); 372 RunValidationTests("conformance_", validators.GetHead());
373 }
263 374
264 for (size_t i = 0; i < header_tests.size(); ++i) 375 TEST_F(ValidationIntegrationTest, InterfacePtr) {
265 RunValidationTest(header_tests[i], &DumpMessageHeader); 376 // Test that InterfacePtr<X> applies the correct validators and they don't
377 // conflict with each other:
378 // - MessageHeaderValidator
379 // - X::Client::RequestValidator_
380 // - X::ResponseValidator_
381
382 IntegrationTestInterface1Client interface1_client;
383 IntegrationTestInterface2Ptr interface2_ptr =
384 MakeProxy<IntegrationTestInterface2>(testee_endpoint().Pass());
385 interface2_ptr.set_client(&interface1_client);
386 interface2_ptr.internal_state()->router()->EnableTestingMode();
387
388 RunValidationTests("integration_", test_message_receiver());
389 }
390
391 TEST_F(ValidationIntegrationTest, InterfaceImpl) {
392 // Test that InterfaceImpl<X> applies the correct validators and they don't
393 // conflict with each other:
394 // - MessageHeaderValidator
395 // - X::RequestValidator_
396 // - X::Client::ResponseValidator_
397
398 // |interface1_impl| will delete itself when the pipe is closed.
399 IntegrationTestInterface1Impl* interface1_impl =
400 BindToPipe(new IntegrationTestInterface1Impl(), testee_endpoint().Pass());
401 interface1_impl->internal_state()->router()->EnableTestingMode();
402
403 RunValidationTests("integration_", test_message_receiver());
266 } 404 }
267 405
268 } // namespace 406 } // namespace
269 } // namespace test 407 } // namespace test
270 } // namespace mojo 408 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698