diff options
Diffstat (limited to 'mojo/public/cpp/bindings/tests/validation_unittest.cc')
-rw-r--r-- | mojo/public/cpp/bindings/tests/validation_unittest.cc | 419 |
1 files changed, 0 insertions, 419 deletions
diff --git a/mojo/public/cpp/bindings/tests/validation_unittest.cc b/mojo/public/cpp/bindings/tests/validation_unittest.cc deleted file mode 100644 index 6507f21..0000000 --- a/mojo/public/cpp/bindings/tests/validation_unittest.cc +++ /dev/null @@ -1,419 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stdio.h> - -#include <algorithm> -#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 { -namespace test { -namespace { - -template <typename T> -void Append(std::vector<uint8_t>* data_vector, T data) { - size_t pos = data_vector->size(); - data_vector->resize(pos + sizeof(T)); - memcpy(&(*data_vector)[pos], &data, sizeof(T)); -} - -bool TestInputParser(const std::string& input, - bool expected_result, - const std::vector<uint8_t>& expected_data, - size_t expected_num_handles) { - std::vector<uint8_t> data; - size_t num_handles; - std::string error_message; - - bool result = - ParseValidationTestInput(input, &data, &num_handles, &error_message); - if (expected_result) { - if (result && error_message.empty() && expected_data == data && - expected_num_handles == num_handles) { - return true; - } - - // Compare with an empty string instead of checking |error_message.empty()|, - // so that the message will be printed out if the two are not equal. - EXPECT_EQ(std::string(), error_message); - EXPECT_EQ(expected_data, data); - EXPECT_EQ(expected_num_handles, num_handles); - return false; - } - - EXPECT_FALSE(error_message.empty()); - return !result && !error_message.empty(); -} - -std::vector<std::string> GetMatchingTests(const std::vector<std::string>& names, - const std::string& prefix) { - const std::string suffix = ".data"; - std::vector<std::string> tests; - for (size_t i = 0; i < names.size(); ++i) { - if (names[i].size() >= suffix.size() && - names[i].substr(0, prefix.size()) == prefix && - names[i].substr(names[i].size() - suffix.size()) == suffix) - tests.push_back(names[i].substr(0, names[i].size() - suffix.size())); - } - return tests; -} - -bool ReadFile(const std::string& path, std::string* result) { - FILE* fp = OpenSourceRootRelativeFile(path.c_str()); - if (!fp) { - ADD_FAILURE() << "File not found: " << path; - return false; - } - fseek(fp, 0, SEEK_END); - size_t size = static_cast<size_t>(ftell(fp)); - if (size == 0) { - result->clear(); - fclose(fp); - return true; - } - fseek(fp, 0, SEEK_SET); - result->resize(size); - size_t size_read = fread(&result->at(0), 1, size, fp); - fclose(fp); - return size == size_read; -} - -bool ReadAndParseDataFile(const std::string& path, - std::vector<uint8_t>* data, - size_t* num_handles) { - std::string input; - if (!ReadFile(path, &input)) - return false; - - std::string error_message; - if (!ParseValidationTestInput(input, data, num_handles, &error_message)) { - ADD_FAILURE() << error_message; - return false; - } - - return true; -} - -bool ReadResultFile(const std::string& path, std::string* result) { - if (!ReadFile(path, result)) - return false; - - // Result files are new-line delimited text files. Remove any CRs. - result->erase(std::remove(result->begin(), result->end(), '\r'), - result->end()); - - // Remove trailing LFs. - size_t pos = result->find_last_not_of('\n'); - if (pos == std::string::npos) - result->clear(); - else - result->resize(pos + 1); - - return true; -} - -std::string GetPath(const std::string& root, const std::string& suffix) { - return "mojo/public/interfaces/bindings/tests/data/validation/" + root + - suffix; -} - -// |message| should be a newly created object. -bool ReadTestCase(const std::string& test, - Message* message, - std::string* expected) { - std::vector<uint8_t> data; - size_t num_handles; - if (!ReadAndParseDataFile(GetPath(test, ".data"), &data, &num_handles) || - !ReadResultFile(GetPath(test, ".expected"), expected)) { - return false; - } - - message->AllocUninitializedData(static_cast<uint32_t>(data.size())); - if (!data.empty()) - memcpy(message->mutable_data(), &data[0], data.size()); - message->mutable_handles()->resize(num_handles); - - return true; -} - -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; - mojo_ignore_result(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 { - public: - bool Accept(Message* message) override { - return true; // Any message is OK. - } -}; - -class ValidationTest : public testing::Test { - public: - ~ValidationTest() override {} - - private: - Environment env_; -}; - -class ValidationIntegrationTest : public ValidationTest { - public: - ValidationIntegrationTest() : test_message_receiver_(nullptr) {} - - ~ValidationIntegrationTest() override {} - - void SetUp() override { - ScopedMessagePipeHandle tester_endpoint; - ASSERT_EQ(MOJO_RESULT_OK, - CreateMessagePipe(nullptr, &tester_endpoint, &testee_endpoint_)); - test_message_receiver_ = - new TestMessageReceiver(this, tester_endpoint.Pass()); - } - - void TearDown() override { - delete test_message_receiver_; - test_message_receiver_ = nullptr; - - // 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()) {} - ~TestMessageReceiver() override {} - - bool Accept(Message* message) override { - bool rv = connector_.Accept(message); - owner_->PumpMessages(); - return rv; - } - - public: - ValidationIntegrationTest* owner_; - mojo::internal::Connector connector_; - }; - - void PumpMessages() { loop_.RunUntilIdle(); } - - RunLoop loop_; - TestMessageReceiver* test_message_receiver_; - ScopedMessagePipeHandle testee_endpoint_; -}; - -class IntegrationTestInterface1Client : public IntegrationTestInterface1 { - public: - ~IntegrationTestInterface1Client() override {} - - void Method0(BasicStructPtr param0) override {} -}; - -class IntegrationTestInterface1Impl - : public InterfaceImpl<IntegrationTestInterface1> { - public: - ~IntegrationTestInterface1Impl() override {} - - void Method0(BasicStructPtr param0) override {} -}; - -TEST_F(ValidationTest, InputParser) { - { - // The parser, as well as Append() defined above, assumes that this code is - // running on a little-endian platform. Test whether that is true. - uint16_t x = 1; - ASSERT_EQ(1, *(reinterpret_cast<char*>(&x))); - } - { - // Test empty input. - std::string input; - std::vector<uint8_t> expected; - - EXPECT_TRUE(TestInputParser(input, true, expected, 0)); - } - { - // Test input that only consists of comments and whitespaces. - std::string input = " \t // hello world \n\r \t// the answer is 42 "; - std::vector<uint8_t> expected; - - EXPECT_TRUE(TestInputParser(input, true, expected, 0)); - } - { - std::string input = - "[u1]0x10// hello world !! \n\r \t [u2]65535 \n" - "[u4]65536 [u8]0xFFFFFFFFFFFFFFFF 0 0Xff"; - std::vector<uint8_t> expected; - Append(&expected, static_cast<uint8_t>(0x10)); - Append(&expected, static_cast<uint16_t>(65535)); - Append(&expected, static_cast<uint32_t>(65536)); - Append(&expected, static_cast<uint64_t>(0xffffffffffffffff)); - Append(&expected, static_cast<uint8_t>(0)); - Append(&expected, static_cast<uint8_t>(0xff)); - - EXPECT_TRUE(TestInputParser(input, true, expected, 0)); - } - { - std::string input = "[s8]-0x800 [s1]-128\t[s2]+0 [s4]-40"; - std::vector<uint8_t> expected; - Append(&expected, -static_cast<int64_t>(0x800)); - Append(&expected, static_cast<int8_t>(-128)); - Append(&expected, static_cast<int16_t>(0)); - Append(&expected, static_cast<int32_t>(-40)); - - EXPECT_TRUE(TestInputParser(input, true, expected, 0)); - } - { - std::string input = "[b]00001011 [b]10000000 // hello world\r [b]00000000"; - std::vector<uint8_t> expected; - Append(&expected, static_cast<uint8_t>(11)); - Append(&expected, static_cast<uint8_t>(128)); - Append(&expected, static_cast<uint8_t>(0)); - - EXPECT_TRUE(TestInputParser(input, true, expected, 0)); - } - { - std::string input = "[f]+.3e9 [d]-10.03"; - std::vector<uint8_t> expected; - Append(&expected, +.3e9f); - Append(&expected, -10.03); - - EXPECT_TRUE(TestInputParser(input, true, expected, 0)); - } - { - std::string input = "[dist4]foo 0 [dist8]bar 0 [anchr]foo [anchr]bar"; - std::vector<uint8_t> expected; - Append(&expected, static_cast<uint32_t>(14)); - Append(&expected, static_cast<uint8_t>(0)); - Append(&expected, static_cast<uint64_t>(9)); - Append(&expected, static_cast<uint8_t>(0)); - - EXPECT_TRUE(TestInputParser(input, true, expected, 0)); - } - { - std::string input = "// This message has handles! \n[handles]50 [u8]2"; - std::vector<uint8_t> expected; - Append(&expected, static_cast<uint64_t>(2)); - - EXPECT_TRUE(TestInputParser(input, true, expected, 50)); - } - - // Test some failure cases. - { - const char* error_inputs[] = {"/ hello world", - "[u1]x", - "[u2]-1000", - "[u1]0x100", - "[s2]-0x8001", - "[b]1", - "[b]1111111k", - "[dist4]unmatched", - "[anchr]hello [dist8]hello", - "[dist4]a [dist4]a [anchr]a", - "[dist4]a [anchr]a [dist4]a [anchr]a", - "0 [handles]50", - nullptr}; - - for (size_t i = 0; error_inputs[i]; ++i) { - std::vector<uint8_t> expected; - if (!TestInputParser(error_inputs[i], false, expected, 0)) - ADD_FAILURE() << "Unexpected test result for: " << error_inputs[i]; - } - } -} - -TEST_F(ValidationTest, Conformance) { - DummyMessageReceiver dummy_receiver; - mojo::internal::FilterChain validators(&dummy_receiver); - validators.Append<mojo::internal::MessageHeaderValidator>(); - validators.Append<ConformanceTestInterface::RequestValidator_>(); - - RunValidationTests("conformance_", validators.GetHead()); -} - -TEST_F(ValidationTest, NotImplemented) { - DummyMessageReceiver dummy_receiver; - mojo::internal::FilterChain validators(&dummy_receiver); - validators.Append<mojo::internal::MessageHeaderValidator>(); - validators.Append<ConformanceTestInterface::RequestValidator_>(); - - RunValidationTests("not_implemented_", 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_for_testing()->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_ - - // |interface1_impl| will delete itself when the pipe is closed. - IntegrationTestInterface1Impl* interface1_impl = - BindToPipe(new IntegrationTestInterface1Impl(), testee_endpoint().Pass()); - interface1_impl->internal_router()->EnableTestingMode(); - - RunValidationTests("integration_", test_message_receiver()); -} - -} // namespace -} // namespace test -} // namespace mojo |