diff options
Diffstat (limited to 'mojo/public/cpp/bindings/tests/pickle_unittest.cc')
-rw-r--r-- | mojo/public/cpp/bindings/tests/pickle_unittest.cc | 403 |
1 files changed, 403 insertions, 0 deletions
diff --git a/mojo/public/cpp/bindings/tests/pickle_unittest.cc b/mojo/public/cpp/bindings/tests/pickle_unittest.cc new file mode 100644 index 0000000000..a5947ce9ed --- /dev/null +++ b/mojo/public/cpp/bindings/tests/pickle_unittest.cc @@ -0,0 +1,403 @@ +// Copyright 2015 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 <string> +#include <utility> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/interface_request.h" +#include "mojo/public/cpp/bindings/tests/pickled_types_blink.h" +#include "mojo/public/cpp/bindings/tests/pickled_types_chromium.h" +#include "mojo/public/cpp/bindings/tests/variant_test_util.h" +#include "mojo/public/interfaces/bindings/tests/test_native_types.mojom-blink.h" +#include "mojo/public/interfaces/bindings/tests/test_native_types.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace test { +namespace { + +template <typename T> +void DoExpectResult(int foo, int bar, const base::Closure& callback, T actual) { + EXPECT_EQ(foo, actual.foo()); + EXPECT_EQ(bar, actual.bar()); + callback.Run(); +} + +template <typename T> +base::Callback<void(T)> ExpectResult(const T& t, + const base::Closure& callback) { + return base::Bind(&DoExpectResult<T>, t.foo(), t.bar(), callback); +} + +template <typename T> +void DoFail(const std::string& reason, T) { + EXPECT_TRUE(false) << reason; +} + +template <typename T> +base::Callback<void(T)> Fail(const std::string& reason) { + return base::Bind(&DoFail<T>, reason); +} + +template <typename T> +void DoExpectEnumResult(T expected, const base::Closure& callback, T actual) { + EXPECT_EQ(expected, actual); + callback.Run(); +} + +template <typename T> +base::Callback<void(T)> ExpectEnumResult(T t, const base::Closure& callback) { + return base::Bind(&DoExpectEnumResult<T>, t, callback); +} + +template <typename T> +void DoEnumFail(const std::string& reason, T) { + EXPECT_TRUE(false) << reason; +} + +template <typename T> +base::Callback<void(T)> EnumFail(const std::string& reason) { + return base::Bind(&DoEnumFail<T>, reason); +} + +template <typename T> +void ExpectError(InterfacePtr<T>* proxy, const base::Closure& callback) { + proxy->set_connection_error_handler(callback); +} + +template <typename Func, typename Arg> +void RunSimpleLambda(Func func, Arg arg) { func(std::move(arg)); } + +template <typename Arg, typename Func> +base::Callback<void(Arg)> BindSimpleLambda(Func func) { + return base::Bind(&RunSimpleLambda<Func, Arg>, func); +} + +// This implements the generated Chromium variant of PicklePasser. +class ChromiumPicklePasserImpl : public PicklePasser { + public: + ChromiumPicklePasserImpl() {} + + // mojo::test::PicklePasser: + void PassPickledStruct(PickledStructChromium pickle, + const PassPickledStructCallback& callback) override { + callback.Run(std::move(pickle)); + } + + void PassPickledEnum(PickledEnumChromium pickle, + const PassPickledEnumCallback& callback) override { + callback.Run(pickle); + } + + void PassPickleContainer( + PickleContainerPtr container, + const PassPickleContainerCallback& callback) override { + callback.Run(std::move(container)); + } + + void PassPickles(std::vector<PickledStructChromium> pickles, + const PassPicklesCallback& callback) override { + callback.Run(std::move(pickles)); + } + + void PassPickleArrays( + std::vector<std::vector<PickledStructChromium>> pickle_arrays, + const PassPickleArraysCallback& callback) override { + callback.Run(std::move(pickle_arrays)); + } +}; + +// This implements the generated Blink variant of PicklePasser. +class BlinkPicklePasserImpl : public blink::PicklePasser { + public: + BlinkPicklePasserImpl() {} + + // mojo::test::blink::PicklePasser: + void PassPickledStruct(PickledStructBlink pickle, + const PassPickledStructCallback& callback) override { + callback.Run(std::move(pickle)); + } + + void PassPickledEnum(PickledEnumBlink pickle, + const PassPickledEnumCallback& callback) override { + callback.Run(pickle); + } + + void PassPickleContainer( + blink::PickleContainerPtr container, + const PassPickleContainerCallback& callback) override { + callback.Run(std::move(container)); + } + + void PassPickles(WTF::Vector<PickledStructBlink> pickles, + const PassPicklesCallback& callback) override { + callback.Run(std::move(pickles)); + } + + void PassPickleArrays( + WTF::Vector<WTF::Vector<PickledStructBlink>> pickle_arrays, + const PassPickleArraysCallback& callback) override { + callback.Run(std::move(pickle_arrays)); + } +}; + +// A test which runs both Chromium and Blink implementations of the +// PicklePasser service. +class PickleTest : public testing::Test { + public: + PickleTest() {} + + template <typename ProxyType = PicklePasser> + InterfacePtr<ProxyType> ConnectToChromiumService() { + InterfacePtr<ProxyType> proxy; + InterfaceRequest<ProxyType> request(&proxy); + chromium_bindings_.AddBinding( + &chromium_service_, + ConvertInterfaceRequest<PicklePasser>(std::move(request))); + return proxy; + } + + template <typename ProxyType = blink::PicklePasser> + InterfacePtr<ProxyType> ConnectToBlinkService() { + InterfacePtr<ProxyType> proxy; + InterfaceRequest<ProxyType> request(&proxy); + blink_bindings_.AddBinding( + &blink_service_, + ConvertInterfaceRequest<blink::PicklePasser>(std::move(request))); + return proxy; + } + + private: + base::MessageLoop loop_; + ChromiumPicklePasserImpl chromium_service_; + BindingSet<PicklePasser> chromium_bindings_; + BlinkPicklePasserImpl blink_service_; + BindingSet<blink::PicklePasser> blink_bindings_; +}; + +} // namespace + +TEST_F(PickleTest, ChromiumProxyToChromiumService) { + auto chromium_proxy = ConnectToChromiumService(); + { + base::RunLoop loop; + chromium_proxy->PassPickledStruct( + PickledStructChromium(1, 2), + ExpectResult(PickledStructChromium(1, 2), loop.QuitClosure())); + loop.Run(); + } + { + base::RunLoop loop; + chromium_proxy->PassPickledStruct( + PickledStructChromium(4, 5), + ExpectResult(PickledStructChromium(4, 5), loop.QuitClosure())); + loop.Run(); + } + + { + base::RunLoop loop; + chromium_proxy->PassPickledEnum( + PickledEnumChromium::VALUE_1, + ExpectEnumResult(PickledEnumChromium::VALUE_1, loop.QuitClosure())); + loop.Run(); + } +} + +TEST_F(PickleTest, ChromiumProxyToBlinkService) { + auto chromium_proxy = ConnectToBlinkService<PicklePasser>(); + { + base::RunLoop loop; + chromium_proxy->PassPickledStruct( + PickledStructChromium(1, 2), + ExpectResult(PickledStructChromium(1, 2), loop.QuitClosure())); + loop.Run(); + } + { + base::RunLoop loop; + chromium_proxy->PassPickledStruct( + PickledStructChromium(4, 5), + ExpectResult(PickledStructChromium(4, 5), loop.QuitClosure())); + loop.Run(); + } + // The Blink service should drop our connection because the + // PickledStructBlink ParamTraits deserializer rejects negative values. + { + base::RunLoop loop; + chromium_proxy->PassPickledStruct( + PickledStructChromium(-1, -1), + Fail<PickledStructChromium>("Blink service should reject this.")); + ExpectError(&chromium_proxy, loop.QuitClosure()); + loop.Run(); + } + + chromium_proxy = ConnectToBlinkService<PicklePasser>(); + { + base::RunLoop loop; + chromium_proxy->PassPickledEnum( + PickledEnumChromium::VALUE_0, + ExpectEnumResult(PickledEnumChromium::VALUE_0, loop.QuitClosure())); + loop.Run(); + } + + // The Blink service should drop our connection because the + // PickledEnumBlink ParamTraits deserializer rejects this value. + { + base::RunLoop loop; + chromium_proxy->PassPickledEnum( + PickledEnumChromium::VALUE_2, + EnumFail<PickledEnumChromium>("Blink service should reject this.")); + ExpectError(&chromium_proxy, loop.QuitClosure()); + loop.Run(); + } +} + +TEST_F(PickleTest, BlinkProxyToBlinkService) { + auto blink_proxy = ConnectToBlinkService(); + { + base::RunLoop loop; + blink_proxy->PassPickledStruct( + PickledStructBlink(1, 1), + ExpectResult(PickledStructBlink(1, 1), loop.QuitClosure())); + loop.Run(); + } + + { + base::RunLoop loop; + blink_proxy->PassPickledEnum( + PickledEnumBlink::VALUE_0, + ExpectEnumResult(PickledEnumBlink::VALUE_0, loop.QuitClosure())); + loop.Run(); + } +} + +TEST_F(PickleTest, BlinkProxyToChromiumService) { + auto blink_proxy = ConnectToChromiumService<blink::PicklePasser>(); + { + base::RunLoop loop; + blink_proxy->PassPickledStruct( + PickledStructBlink(1, 1), + ExpectResult(PickledStructBlink(1, 1), loop.QuitClosure())); + loop.Run(); + } + + { + base::RunLoop loop; + blink_proxy->PassPickledEnum( + PickledEnumBlink::VALUE_1, + ExpectEnumResult(PickledEnumBlink::VALUE_1, loop.QuitClosure())); + loop.Run(); + } +} + +TEST_F(PickleTest, PickleArray) { + auto proxy = ConnectToChromiumService(); + auto pickles = std::vector<PickledStructChromium>(2); + pickles[0].set_foo(1); + pickles[0].set_bar(2); + pickles[0].set_baz(100); + pickles[1].set_foo(3); + pickles[1].set_bar(4); + pickles[1].set_baz(100); + { + base::RunLoop run_loop; + // Verify that the array of pickled structs can be serialized and + // deserialized intact. This ensures that the ParamTraits are actually used + // rather than doing a byte-for-byte copy of the element data, beacuse the + // |baz| field should never be serialized. + proxy->PassPickles(std::move(pickles), + BindSimpleLambda<std::vector<PickledStructChromium>>( + [&](std::vector<PickledStructChromium> passed) { + ASSERT_EQ(2u, passed.size()); + EXPECT_EQ(1, passed[0].foo()); + EXPECT_EQ(2, passed[0].bar()); + EXPECT_EQ(0, passed[0].baz()); + EXPECT_EQ(3, passed[1].foo()); + EXPECT_EQ(4, passed[1].bar()); + EXPECT_EQ(0, passed[1].baz()); + run_loop.Quit(); + })); + run_loop.Run(); + } +} + +TEST_F(PickleTest, PickleArrayArray) { + auto proxy = ConnectToChromiumService(); + auto pickle_arrays = std::vector<std::vector<PickledStructChromium>>(2); + for (size_t i = 0; i < 2; ++i) + pickle_arrays[i] = std::vector<PickledStructChromium>(2); + + pickle_arrays[0][0].set_foo(1); + pickle_arrays[0][0].set_bar(2); + pickle_arrays[0][0].set_baz(100); + pickle_arrays[0][1].set_foo(3); + pickle_arrays[0][1].set_bar(4); + pickle_arrays[0][1].set_baz(100); + pickle_arrays[1][0].set_foo(5); + pickle_arrays[1][0].set_bar(6); + pickle_arrays[1][0].set_baz(100); + pickle_arrays[1][1].set_foo(7); + pickle_arrays[1][1].set_bar(8); + pickle_arrays[1][1].set_baz(100); + { + base::RunLoop run_loop; + // Verify that the array-of-arrays serializes and deserializes properly. + proxy->PassPickleArrays( + std::move(pickle_arrays), + BindSimpleLambda<std::vector<std::vector<PickledStructChromium>>>( + [&](std::vector<std::vector<PickledStructChromium>> passed) { + ASSERT_EQ(2u, passed.size()); + ASSERT_EQ(2u, passed[0].size()); + ASSERT_EQ(2u, passed[1].size()); + EXPECT_EQ(1, passed[0][0].foo()); + EXPECT_EQ(2, passed[0][0].bar()); + EXPECT_EQ(0, passed[0][0].baz()); + EXPECT_EQ(3, passed[0][1].foo()); + EXPECT_EQ(4, passed[0][1].bar()); + EXPECT_EQ(0, passed[0][1].baz()); + EXPECT_EQ(5, passed[1][0].foo()); + EXPECT_EQ(6, passed[1][0].bar()); + EXPECT_EQ(0, passed[1][0].baz()); + EXPECT_EQ(7, passed[1][1].foo()); + EXPECT_EQ(8, passed[1][1].bar()); + EXPECT_EQ(0, passed[1][1].baz()); + run_loop.Quit(); + })); + run_loop.Run(); + } +} + +TEST_F(PickleTest, PickleContainer) { + auto proxy = ConnectToChromiumService(); + PickleContainerPtr pickle_container = PickleContainer::New(); + pickle_container->f_struct.set_foo(42); + pickle_container->f_struct.set_bar(43); + pickle_container->f_struct.set_baz(44); + pickle_container->f_enum = PickledEnumChromium::VALUE_1; + EXPECT_TRUE(pickle_container.Equals(pickle_container)); + EXPECT_FALSE(pickle_container.Equals(PickleContainer::New())); + { + base::RunLoop run_loop; + proxy->PassPickleContainer(std::move(pickle_container), + BindSimpleLambda<PickleContainerPtr>( + [&](PickleContainerPtr passed) { + ASSERT_FALSE(passed.is_null()); + EXPECT_EQ(42, passed->f_struct.foo()); + EXPECT_EQ(43, passed->f_struct.bar()); + EXPECT_EQ(0, passed->f_struct.baz()); + EXPECT_EQ(PickledEnumChromium::VALUE_1, + passed->f_enum); + run_loop.Quit(); + })); + run_loop.Run(); + } +} + +} // namespace test +} // namespace mojo |