| OLD | NEW |
| 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/c/system/macros.h" |
| 12 #include "mojo/public/cpp/bindings/interface_impl.h" |
| 13 #include "mojo/public/cpp/bindings/interface_ptr.h" |
| 14 #include "mojo/public/cpp/bindings/lib/connector.h" |
| 15 #include "mojo/public/cpp/bindings/lib/filter_chain.h" |
| 12 #include "mojo/public/cpp/bindings/lib/message_header_validator.h" | 16 #include "mojo/public/cpp/bindings/lib/message_header_validator.h" |
| 17 #include "mojo/public/cpp/bindings/lib/router.h" |
| 13 #include "mojo/public/cpp/bindings/lib/validation_errors.h" | 18 #include "mojo/public/cpp/bindings/lib/validation_errors.h" |
| 19 #include "mojo/public/cpp/bindings/message.h" |
| 14 #include "mojo/public/cpp/bindings/tests/validation_test_input_parser.h" | 20 #include "mojo/public/cpp/bindings/tests/validation_test_input_parser.h" |
| 21 #include "mojo/public/cpp/environment/environment.h" |
| 22 #include "mojo/public/cpp/system/core.h" |
| 15 #include "mojo/public/cpp/test_support/test_support.h" | 23 #include "mojo/public/cpp/test_support/test_support.h" |
| 24 #include "mojo/public/cpp/utility/run_loop.h" |
| 25 #include "mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom
.h" |
| 16 #include "testing/gtest/include/gtest/gtest.h" | 26 #include "testing/gtest/include/gtest/gtest.h" |
| 17 | 27 |
| 18 namespace mojo { | 28 namespace mojo { |
| 19 namespace test { | 29 namespace test { |
| 20 namespace { | 30 namespace { |
| 21 | 31 |
| 22 template <typename T> | 32 template <typename T> |
| 23 void Append(std::vector<uint8_t>* data_vector, T data) { | 33 void Append(std::vector<uint8_t>* data_vector, T data) { |
| 24 size_t pos = data_vector->size(); | 34 size_t pos = data_vector->size(); |
| 25 data_vector->resize(pos + sizeof(T)); | 35 data_vector->resize(pos + sizeof(T)); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 size_t pos = result->find_last_not_of('\n'); | 119 size_t pos = result->find_last_not_of('\n'); |
| 110 if (pos == std::string::npos) | 120 if (pos == std::string::npos) |
| 111 result->clear(); | 121 result->clear(); |
| 112 else | 122 else |
| 113 result->resize(pos + 1); | 123 result->resize(pos + 1); |
| 114 | 124 |
| 115 return true; | 125 return true; |
| 116 } | 126 } |
| 117 | 127 |
| 118 std::string GetPath(const std::string& root, const std::string& suffix) { | 128 std::string GetPath(const std::string& root, const std::string& suffix) { |
| 119 return "mojo/public/interfaces/bindings/tests/data/" + root + suffix; | 129 return "mojo/public/interfaces/bindings/tests/data/validation/" + |
| 130 root + suffix; |
| 120 } | 131 } |
| 121 | 132 |
| 122 void RunValidationTest(const std::string& root, std::string (*func)(Message*)) { | 133 // |message| should be a newly created object. |
| 134 bool ReadTestCase(const std::string& test, |
| 135 Message* message, |
| 136 std::string* expected) { |
| 123 std::vector<uint8_t> data; | 137 std::vector<uint8_t> data; |
| 124 ASSERT_TRUE(ReadAndParseDataFile(GetPath(root, ".data"), &data)); | 138 if (!ReadAndParseDataFile(GetPath(test, ".data"), &data) || |
| 139 !ReadResultFile(GetPath(test, ".expected"), expected)) { |
| 140 return false; |
| 141 } |
| 125 | 142 |
| 126 std::string expected; | 143 message->AllocUninitializedData(static_cast<uint32_t>(data.size())); |
| 127 ASSERT_TRUE(ReadResultFile(GetPath(root, ".expected"), &expected)); | 144 if (!data.empty()) |
| 145 memcpy(message->mutable_data(), &data[0], data.size()); |
| 128 | 146 |
| 129 Message message; | 147 // TODO(yzshen): add support to specify the number of handles associated with |
| 130 message.AllocUninitializedData(static_cast<uint32_t>(data.size())); | 148 // the message. |
| 131 if (!data.empty()) | |
| 132 memcpy(message.mutable_data(), &data[0], data.size()); | |
| 133 | 149 |
| 134 std::string result = func(&message); | 150 return true; |
| 135 EXPECT_EQ(expected, result) << "failed test: " << root; | 151 } |
| 152 |
| 153 void RunValidationTests(const std::string& prefix, |
| 154 MessageReceiver* test_message_receiver) { |
| 155 std::vector<std::string> names = |
| 156 EnumerateSourceRootRelativeDirectory(GetPath("", "")); |
| 157 std::vector<std::string> tests = GetMatchingTests(names, prefix); |
| 158 |
| 159 for (size_t i = 0; i < tests.size(); ++i) { |
| 160 Message message; |
| 161 std::string expected; |
| 162 ASSERT_TRUE(ReadTestCase(tests[i], &message, &expected)); |
| 163 |
| 164 std::string result; |
| 165 mojo::internal::ValidationErrorObserverForTesting observer; |
| 166 bool unused MOJO_ALLOW_UNUSED = test_message_receiver->Accept(&message); |
| 167 if (observer.last_error() == mojo::internal::VALIDATION_ERROR_NONE) |
| 168 result = "PASS"; |
| 169 else |
| 170 result = mojo::internal::ValidationErrorToString(observer.last_error()); |
| 171 |
| 172 EXPECT_EQ(expected, result) << "failed test: " << tests[i]; |
| 173 } |
| 136 } | 174 } |
| 137 | 175 |
| 138 class DummyMessageReceiver : public MessageReceiver { | 176 class DummyMessageReceiver : public MessageReceiver { |
| 139 public: | 177 public: |
| 140 virtual bool Accept(Message* message) MOJO_OVERRIDE { | 178 virtual bool Accept(Message* message) MOJO_OVERRIDE { |
| 141 return true; // Any message is OK. | 179 return true; // Any message is OK. |
| 142 } | 180 } |
| 143 }; | 181 }; |
| 144 | 182 |
| 145 std::string DumpMessageHeader(Message* message) { | 183 class ValidationIntegrationTest : public testing::Test { |
| 146 internal::ValidationErrorObserverForTesting observer; | 184 public: |
| 147 DummyMessageReceiver not_reached_receiver; | 185 ValidationIntegrationTest() : test_message_receiver_(NULL) { |
| 148 internal::MessageHeaderValidator validator(¬_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 } | 186 } |
| 154 | 187 |
| 155 std::ostringstream os; | 188 virtual ~ValidationIntegrationTest() { |
| 156 os << "num_bytes: " << message->header()->num_bytes << "\n" | 189 } |
| 157 << "num_fields: " << message->header()->num_fields << "\n" | 190 |
| 158 << "name: " << message->header()->name << "\n" | 191 virtual void SetUp() MOJO_OVERRIDE { |
| 159 << "flags: " << message->header()->flags; | 192 ScopedMessagePipeHandle tester_endpoint; |
| 160 return os.str(); | 193 ASSERT_EQ(MOJO_RESULT_OK, |
| 161 } | 194 CreateMessagePipe(NULL, &tester_endpoint, &testee_endpoint_)); |
| 195 test_message_receiver_ = |
| 196 new TestMessageReceiver(this, tester_endpoint.Pass()); |
| 197 } |
| 198 |
| 199 virtual void TearDown() MOJO_OVERRIDE { |
| 200 delete test_message_receiver_; |
| 201 test_message_receiver_ = NULL; |
| 202 |
| 203 // Make sure that the other end receives the OnConnectionError() |
| 204 // notification. |
| 205 PumpMessages(); |
| 206 } |
| 207 |
| 208 MessageReceiver* test_message_receiver() { |
| 209 return test_message_receiver_; |
| 210 } |
| 211 |
| 212 ScopedMessagePipeHandle testee_endpoint() { |
| 213 return testee_endpoint_.Pass(); |
| 214 } |
| 215 |
| 216 private: |
| 217 class TestMessageReceiver : public MessageReceiver { |
| 218 public: |
| 219 TestMessageReceiver(ValidationIntegrationTest* owner, |
| 220 ScopedMessagePipeHandle handle) |
| 221 : owner_(owner), |
| 222 connector_(handle.Pass()) { |
| 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 Loading... |
| 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 |
| OLD | NEW |