| Index: mojo/public/cpp/bindings/tests/validation_unittest.cc
|
| diff --git a/mojo/public/cpp/bindings/tests/validation_unittest.cc b/mojo/public/cpp/bindings/tests/validation_unittest.cc
|
| index f111091472309c9e0b19aa7faf14f03f908a486c..f1e1b0bbe7d5b99bc44764ec28223b5395aa6cd7 100644
|
| --- a/mojo/public/cpp/bindings/tests/validation_unittest.cc
|
| +++ b/mojo/public/cpp/bindings/tests/validation_unittest.cc
|
| @@ -5,14 +5,24 @@
|
| #include <stdio.h>
|
|
|
| #include <algorithm>
|
| -#include <sstream>
|
| #include <string>
|
| #include <vector>
|
|
|
| +#include "mojo/public/c/system/macros.h"
|
| +#include "mojo/public/cpp/bindings/interface_impl.h"
|
| +#include "mojo/public/cpp/bindings/interface_ptr.h"
|
| +#include "mojo/public/cpp/bindings/lib/connector.h"
|
| +#include "mojo/public/cpp/bindings/lib/filter_chain.h"
|
| #include "mojo/public/cpp/bindings/lib/message_header_validator.h"
|
| +#include "mojo/public/cpp/bindings/lib/router.h"
|
| #include "mojo/public/cpp/bindings/lib/validation_errors.h"
|
| +#include "mojo/public/cpp/bindings/message.h"
|
| #include "mojo/public/cpp/bindings/tests/validation_test_input_parser.h"
|
| +#include "mojo/public/cpp/environment/environment.h"
|
| +#include "mojo/public/cpp/system/core.h"
|
| #include "mojo/public/cpp/test_support/test_support.h"
|
| +#include "mojo/public/cpp/utility/run_loop.h"
|
| +#include "mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| namespace mojo {
|
| @@ -116,23 +126,51 @@ bool ReadResultFile(const std::string& path, std::string* result) {
|
| }
|
|
|
| std::string GetPath(const std::string& root, const std::string& suffix) {
|
| - return "mojo/public/interfaces/bindings/tests/data/" + root + suffix;
|
| + return "mojo/public/interfaces/bindings/tests/data/validation/" +
|
| + root + suffix;
|
| }
|
|
|
| -void RunValidationTest(const std::string& root, std::string (*func)(Message*)) {
|
| +// |message| should be a newly created object.
|
| +bool ReadTestCase(const std::string& test,
|
| + Message* message,
|
| + std::string* expected) {
|
| std::vector<uint8_t> data;
|
| - ASSERT_TRUE(ReadAndParseDataFile(GetPath(root, ".data"), &data));
|
| -
|
| - std::string expected;
|
| - ASSERT_TRUE(ReadResultFile(GetPath(root, ".expected"), &expected));
|
| + if (!ReadAndParseDataFile(GetPath(test, ".data"), &data) ||
|
| + !ReadResultFile(GetPath(test, ".expected"), expected)) {
|
| + return false;
|
| + }
|
|
|
| - Message message;
|
| - message.AllocUninitializedData(static_cast<uint32_t>(data.size()));
|
| + message->AllocUninitializedData(static_cast<uint32_t>(data.size()));
|
| if (!data.empty())
|
| - memcpy(message.mutable_data(), &data[0], data.size());
|
| + memcpy(message->mutable_data(), &data[0], data.size());
|
| +
|
| + // TODO(yzshen): add support to specify the number of handles associated with
|
| + // the message.
|
| +
|
| + return true;
|
| +}
|
|
|
| - std::string result = func(&message);
|
| - EXPECT_EQ(expected, result) << "failed test: " << root;
|
| +void RunValidationTests(const std::string& prefix,
|
| + MessageReceiver* test_message_receiver) {
|
| + std::vector<std::string> names =
|
| + EnumerateSourceRootRelativeDirectory(GetPath("", ""));
|
| + std::vector<std::string> tests = GetMatchingTests(names, prefix);
|
| +
|
| + for (size_t i = 0; i < tests.size(); ++i) {
|
| + Message message;
|
| + std::string expected;
|
| + ASSERT_TRUE(ReadTestCase(tests[i], &message, &expected));
|
| +
|
| + std::string result;
|
| + mojo::internal::ValidationErrorObserverForTesting observer;
|
| + bool unused MOJO_ALLOW_UNUSED = test_message_receiver->Accept(&message);
|
| + if (observer.last_error() == mojo::internal::VALIDATION_ERROR_NONE)
|
| + result = "PASS";
|
| + else
|
| + result = mojo::internal::ValidationErrorToString(observer.last_error());
|
| +
|
| + EXPECT_EQ(expected, result) << "failed test: " << tests[i];
|
| + }
|
| }
|
|
|
| class DummyMessageReceiver : public MessageReceiver {
|
| @@ -142,23 +180,93 @@ class DummyMessageReceiver : public MessageReceiver {
|
| }
|
| };
|
|
|
| -std::string DumpMessageHeader(Message* message) {
|
| - internal::ValidationErrorObserverForTesting observer;
|
| - DummyMessageReceiver not_reached_receiver;
|
| - internal::MessageHeaderValidator validator(¬_reached_receiver);
|
| - bool rv = validator.Accept(message);
|
| - if (!rv) {
|
| - EXPECT_NE(internal::VALIDATION_ERROR_NONE, observer.last_error());
|
| - return internal::ValidationErrorToString(observer.last_error());
|
| +class ValidationIntegrationTest : public testing::Test {
|
| + public:
|
| + ValidationIntegrationTest() : test_message_receiver_(NULL) {
|
| }
|
|
|
| - std::ostringstream os;
|
| - os << "num_bytes: " << message->header()->num_bytes << "\n"
|
| - << "num_fields: " << message->header()->num_fields << "\n"
|
| - << "name: " << message->header()->name << "\n"
|
| - << "flags: " << message->header()->flags;
|
| - return os.str();
|
| -}
|
| + virtual ~ValidationIntegrationTest() {
|
| + }
|
| +
|
| + virtual void SetUp() MOJO_OVERRIDE {
|
| + ScopedMessagePipeHandle tester_endpoint;
|
| + ASSERT_EQ(MOJO_RESULT_OK,
|
| + CreateMessagePipe(NULL, &tester_endpoint, &testee_endpoint_));
|
| + test_message_receiver_ =
|
| + new TestMessageReceiver(this, tester_endpoint.Pass());
|
| + }
|
| +
|
| + virtual void TearDown() MOJO_OVERRIDE {
|
| + delete test_message_receiver_;
|
| + test_message_receiver_ = NULL;
|
| +
|
| + // Make sure that the other end receives the OnConnectionError()
|
| + // notification.
|
| + PumpMessages();
|
| + }
|
| +
|
| + MessageReceiver* test_message_receiver() {
|
| + return test_message_receiver_;
|
| + }
|
| +
|
| + ScopedMessagePipeHandle testee_endpoint() {
|
| + return testee_endpoint_.Pass();
|
| + }
|
| +
|
| + private:
|
| + class TestMessageReceiver : public MessageReceiver {
|
| + public:
|
| + TestMessageReceiver(ValidationIntegrationTest* owner,
|
| + ScopedMessagePipeHandle handle)
|
| + : owner_(owner),
|
| + connector_(handle.Pass()) {
|
| + }
|
| + virtual ~TestMessageReceiver() {
|
| + }
|
| +
|
| + virtual bool Accept(Message* message) MOJO_OVERRIDE {
|
| + bool rv = connector_.Accept(message);
|
| + owner_->PumpMessages();
|
| + return rv;
|
| + }
|
| +
|
| + public:
|
| + ValidationIntegrationTest* owner_;
|
| + mojo::internal::Connector connector_;
|
| + };
|
| +
|
| + void PumpMessages() {
|
| + loop_.RunUntilIdle();
|
| + }
|
| +
|
| + Environment env_;
|
| + RunLoop loop_;
|
| + TestMessageReceiver* test_message_receiver_;
|
| + ScopedMessagePipeHandle testee_endpoint_;
|
| +};
|
| +
|
| +class IntegrationTestInterface1Client : public IntegrationTestInterface1 {
|
| + public:
|
| + virtual ~IntegrationTestInterface1Client() {
|
| + }
|
| +
|
| + virtual void Method0(BasicStructPtr param0) MOJO_OVERRIDE {
|
| + }
|
| +};
|
| +
|
| +class IntegrationTestInterface1Impl
|
| + : public InterfaceImpl<IntegrationTestInterface1> {
|
| + public:
|
| + virtual ~IntegrationTestInterface1Impl() {
|
| + }
|
| +
|
| + virtual void Method0(BasicStructPtr param0) MOJO_OVERRIDE {
|
| + }
|
| +
|
| + virtual void OnConnectionError() MOJO_OVERRIDE {
|
| + delete this;
|
| + }
|
| +};
|
|
|
| TEST(ValidationTest, InputParser) {
|
| {
|
| @@ -254,15 +362,45 @@ TEST(ValidationTest, InputParser) {
|
| }
|
| }
|
|
|
| -TEST(ValidationTest, TestAll) {
|
| - std::vector<std::string> names =
|
| - EnumerateSourceRootRelativeDirectory(GetPath("", ""));
|
| +TEST(ValidationTest, Conformance) {
|
| + DummyMessageReceiver dummy_receiver;
|
| + mojo::internal::FilterChain validators(&dummy_receiver);
|
| + validators.Append<mojo::internal::MessageHeaderValidator>();
|
| + validators.Append<ConformanceTestInterface::RequestValidator_>();
|
| +
|
| + // TODO(yzshen): add more conformance tests.
|
| + RunValidationTests("conformance_", validators.GetHead());
|
| +}
|
| +
|
| +TEST_F(ValidationIntegrationTest, InterfacePtr) {
|
| + // Test that InterfacePtr<X> applies the correct validators and they don't
|
| + // conflict with each other:
|
| + // - MessageHeaderValidator
|
| + // - X::Client::RequestValidator_
|
| + // - X::ResponseValidator_
|
| +
|
| + IntegrationTestInterface1Client interface1_client;
|
| + IntegrationTestInterface2Ptr interface2_ptr =
|
| + MakeProxy<IntegrationTestInterface2>(testee_endpoint().Pass());
|
| + interface2_ptr.set_client(&interface1_client);
|
| + interface2_ptr.internal_state()->router()->EnableTestingMode();
|
| +
|
| + RunValidationTests("integration_", test_message_receiver());
|
| +}
|
| +
|
| +TEST_F(ValidationIntegrationTest, InterfaceImpl) {
|
| + // Test that InterfaceImpl<X> applies the correct validators and they don't
|
| + // conflict with each other:
|
| + // - MessageHeaderValidator
|
| + // - X::RequestValidator_
|
| + // - X::Client::ResponseValidator_
|
|
|
| - std::vector<std::string> header_tests =
|
| - GetMatchingTests(names, "validate_header_");
|
| + // |interface1_impl| will delete itself when the pipe is closed.
|
| + IntegrationTestInterface1Impl* interface1_impl =
|
| + BindToPipe(new IntegrationTestInterface1Impl(), testee_endpoint().Pass());
|
| + interface1_impl->internal_state()->router()->EnableTestingMode();
|
|
|
| - for (size_t i = 0; i < header_tests.size(); ++i)
|
| - RunValidationTest(header_tests[i], &DumpMessageHeader);
|
| + RunValidationTests("integration_", test_message_receiver());
|
| }
|
|
|
| } // namespace
|
|
|