1 // Copyright 2015 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <string> 6 #include <utility> 7 8 #include "base/bind.h" 9 #include "base/callback.h" 10 #include "base/logging.h" 11 #include "base/message_loop/message_loop.h" 12 #include "base/run_loop.h" 13 #include "mojo/public/cpp/bindings/binding_set.h" 14 #include "mojo/public/cpp/bindings/interface_request.h" 15 #include "mojo/public/cpp/bindings/tests/pickled_types_blink.h" 16 #include "mojo/public/cpp/bindings/tests/pickled_types_chromium.h" 17 #include "mojo/public/cpp/bindings/tests/variant_test_util.h" 18 #include "mojo/public/interfaces/bindings/tests/test_native_types.mojom-blink.h" 19 #include "mojo/public/interfaces/bindings/tests/test_native_types.mojom.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 22 namespace mojo { 23 namespace test { 24 namespace { 25 26 template <typename T> 27 void DoExpectResult(int foo, 28 int bar, 29 const base::Closure& callback, 30 const T& actual) { 31 EXPECT_EQ(foo, actual.foo()); 32 EXPECT_EQ(bar, actual.bar()); 33 callback.Run(); 34 } 35 36 template <typename T> 37 base::Callback<void(const T&)> ExpectResult(const T& t, 38 const base::Closure& callback) { 39 return base::Bind(&DoExpectResult<T>, t.foo(), t.bar(), callback); 40 } 41 42 template <typename T> 43 void DoFail(const std::string& reason, const T&) { 44 EXPECT_TRUE(false) << reason; 45 } 46 47 template <typename T> 48 base::Callback<void(const T&)> Fail(const std::string& reason) { 49 return base::Bind(&DoFail<T>, reason); 50 } 51 52 template <typename T> 53 void DoExpectEnumResult(T expected, const base::Closure& callback, T actual) { 54 EXPECT_EQ(expected, actual); 55 callback.Run(); 56 } 57 58 template <typename T> 59 base::Callback<void(T)> ExpectEnumResult(T t, const base::Closure& callback) { 60 return base::Bind(&DoExpectEnumResult<T>, t, callback); 61 } 62 63 template <typename T> 64 void DoEnumFail(const std::string& reason, T) { 65 EXPECT_TRUE(false) << reason; 66 } 67 68 template <typename T> 69 base::Callback<void(T)> EnumFail(const std::string& reason) { 70 return base::Bind(&DoEnumFail<T>, reason); 71 } 72 73 template <typename T> 74 void ExpectError(InterfacePtr<T>* proxy, const base::Closure& callback) { 75 proxy->set_connection_error_handler(callback); 76 } 77 78 template <typename Func, typename Arg> 79 void RunSimpleLambda(Func func, Arg arg) { func(std::move(arg)); } 80 81 template <typename Arg, typename Func> 82 base::Callback<void(Arg)> BindSimpleLambda(Func func) { 83 return base::Bind(&RunSimpleLambda<Func, Arg>, func); 84 } 85 86 // This implements the generated Chromium variant of PicklePasser. 87 class ChromiumPicklePasserImpl : public PicklePasser { 88 public: 89 ChromiumPicklePasserImpl() {} 90 91 // mojo::test::PicklePasser: 92 void PassPickledStruct(const PickledStructChromium& pickle, 93 const PassPickledStructCallback& callback) override { 94 callback.Run(pickle); 95 } 96 97 void PassPickledEnum(PickledEnumChromium pickle, 98 const PassPickledEnumCallback& callback) override { 99 callback.Run(pickle); 100 } 101 102 void PassPickleContainer( 103 PickleContainerPtr container, 104 const PassPickleContainerCallback& callback) override { 105 callback.Run(std::move(container)); 106 } 107 108 void PassPickles(const std::vector<PickledStructChromium>& pickles, 109 const PassPicklesCallback& callback) override { 110 callback.Run(pickles); 111 } 112 113 void PassPickleArrays( 114 const std::vector<std::vector<PickledStructChromium>>& pickle_arrays, 115 const PassPickleArraysCallback& callback) override { 116 callback.Run(pickle_arrays); 117 } 118 }; 119 120 // This implements the generated Blink variant of PicklePasser. 121 class BlinkPicklePasserImpl : public blink::PicklePasser { 122 public: 123 BlinkPicklePasserImpl() {} 124 125 // mojo::test::blink::PicklePasser: 126 void PassPickledStruct(const PickledStructBlink& pickle, 127 const PassPickledStructCallback& callback) override { 128 callback.Run(pickle); 129 } 130 131 void PassPickledEnum(PickledEnumBlink pickle, 132 const PassPickledEnumCallback& callback) override { 133 callback.Run(pickle); 134 } 135 136 void PassPickleContainer( 137 blink::PickleContainerPtr container, 138 const PassPickleContainerCallback& callback) override { 139 callback.Run(std::move(container)); 140 } 141 142 void PassPickles(const WTF::Vector<PickledStructBlink>& pickles, 143 const PassPicklesCallback& callback) override { 144 callback.Run(pickles); 145 } 146 147 void PassPickleArrays( 148 const WTF::Vector<WTF::Vector<PickledStructBlink>>& pickle_arrays, 149 const PassPickleArraysCallback& callback) override { 150 callback.Run(pickle_arrays); 151 } 152 }; 153 154 // A test which runs both Chromium and Blink implementations of the 155 // PicklePasser service. 156 class PickleTest : public testing::Test { 157 public: 158 PickleTest() {} 159 160 template <typename ProxyType = PicklePasser> 161 InterfacePtr<ProxyType> ConnectToChromiumService() { 162 InterfacePtr<ProxyType> proxy; 163 InterfaceRequest<ProxyType> request = GetProxy(&proxy); 164 chromium_bindings_.AddBinding( 165 &chromium_service_, 166 ConvertInterfaceRequest<PicklePasser>(std::move(request))); 167 return proxy; 168 } 169 170 template <typename ProxyType = blink::PicklePasser> 171 InterfacePtr<ProxyType> ConnectToBlinkService() { 172 InterfacePtr<ProxyType> proxy; 173 InterfaceRequest<ProxyType> request = GetProxy(&proxy); 174 blink_bindings_.AddBinding( 175 &blink_service_, 176 ConvertInterfaceRequest<blink::PicklePasser>(std::move(request))); 177 return proxy; 178 } 179 180 private: 181 base::MessageLoop loop_; 182 ChromiumPicklePasserImpl chromium_service_; 183 BindingSet<PicklePasser> chromium_bindings_; 184 BlinkPicklePasserImpl blink_service_; 185 BindingSet<blink::PicklePasser> blink_bindings_; 186 }; 187 188 } // namespace 189 190 TEST_F(PickleTest, ChromiumProxyToChromiumService) { 191 auto chromium_proxy = ConnectToChromiumService(); 192 { 193 base::RunLoop loop; 194 chromium_proxy->PassPickledStruct( 195 PickledStructChromium(1, 2), 196 ExpectResult(PickledStructChromium(1, 2), loop.QuitClosure())); 197 loop.Run(); 198 } 199 { 200 base::RunLoop loop; 201 chromium_proxy->PassPickledStruct( 202 PickledStructChromium(4, 5), 203 ExpectResult(PickledStructChromium(4, 5), loop.QuitClosure())); 204 loop.Run(); 205 } 206 207 { 208 base::RunLoop loop; 209 chromium_proxy->PassPickledEnum( 210 PickledEnumChromium::VALUE_1, 211 ExpectEnumResult(PickledEnumChromium::VALUE_1, loop.QuitClosure())); 212 loop.Run(); 213 } 214 } 215 216 TEST_F(PickleTest, ChromiumProxyToBlinkService) { 217 auto chromium_proxy = ConnectToBlinkService<PicklePasser>(); 218 { 219 base::RunLoop loop; 220 chromium_proxy->PassPickledStruct( 221 PickledStructChromium(1, 2), 222 ExpectResult(PickledStructChromium(1, 2), loop.QuitClosure())); 223 loop.Run(); 224 } 225 { 226 base::RunLoop loop; 227 chromium_proxy->PassPickledStruct( 228 PickledStructChromium(4, 5), 229 ExpectResult(PickledStructChromium(4, 5), loop.QuitClosure())); 230 loop.Run(); 231 } 232 // The Blink service should drop our connection because the 233 // PickledStructBlink ParamTraits deserializer rejects negative values. 234 { 235 base::RunLoop loop; 236 chromium_proxy->PassPickledStruct( 237 PickledStructChromium(-1, -1), 238 Fail<PickledStructChromium>("Blink service should reject this.")); 239 ExpectError(&chromium_proxy, loop.QuitClosure()); 240 loop.Run(); 241 } 242 243 chromium_proxy = ConnectToBlinkService<PicklePasser>(); 244 { 245 base::RunLoop loop; 246 chromium_proxy->PassPickledEnum( 247 PickledEnumChromium::VALUE_0, 248 ExpectEnumResult(PickledEnumChromium::VALUE_0, loop.QuitClosure())); 249 loop.Run(); 250 } 251 252 // The Blink service should drop our connection because the 253 // PickledEnumBlink ParamTraits deserializer rejects this value. 254 { 255 base::RunLoop loop; 256 chromium_proxy->PassPickledEnum( 257 PickledEnumChromium::VALUE_2, 258 EnumFail<PickledEnumChromium>("Blink service should reject this.")); 259 ExpectError(&chromium_proxy, loop.QuitClosure()); 260 loop.Run(); 261 } 262 } 263 264 TEST_F(PickleTest, BlinkProxyToBlinkService) { 265 auto blink_proxy = ConnectToBlinkService(); 266 { 267 base::RunLoop loop; 268 blink_proxy->PassPickledStruct( 269 PickledStructBlink(1, 1), 270 ExpectResult(PickledStructBlink(1, 1), loop.QuitClosure())); 271 loop.Run(); 272 } 273 274 { 275 base::RunLoop loop; 276 blink_proxy->PassPickledEnum( 277 PickledEnumBlink::VALUE_0, 278 ExpectEnumResult(PickledEnumBlink::VALUE_0, loop.QuitClosure())); 279 loop.Run(); 280 } 281 } 282 283 TEST_F(PickleTest, BlinkProxyToChromiumService) { 284 auto blink_proxy = ConnectToChromiumService<blink::PicklePasser>(); 285 { 286 base::RunLoop loop; 287 blink_proxy->PassPickledStruct( 288 PickledStructBlink(1, 1), 289 ExpectResult(PickledStructBlink(1, 1), loop.QuitClosure())); 290 loop.Run(); 291 } 292 293 { 294 base::RunLoop loop; 295 blink_proxy->PassPickledEnum( 296 PickledEnumBlink::VALUE_1, 297 ExpectEnumResult(PickledEnumBlink::VALUE_1, loop.QuitClosure())); 298 loop.Run(); 299 } 300 } 301 302 TEST_F(PickleTest, PickleArray) { 303 auto proxy = ConnectToChromiumService(); 304 auto pickles = Array<PickledStructChromium>::New(2); 305 pickles[0].set_foo(1); 306 pickles[0].set_bar(2); 307 pickles[0].set_baz(100); 308 pickles[1].set_foo(3); 309 pickles[1].set_bar(4); 310 pickles[1].set_baz(100); 311 { 312 base::RunLoop run_loop; 313 // Verify that the array of pickled structs can be serialized and 314 // deserialized intact. This ensures that the ParamTraits are actually used 315 // rather than doing a byte-for-byte copy of the element data, beacuse the 316 // |baz| field should never be serialized. 317 proxy->PassPickles( 318 std::move(pickles), 319 BindSimpleLambda<const std::vector<PickledStructChromium>&>( 320 [&](const std::vector<PickledStructChromium>& passed) { 321 ASSERT_EQ(2u, passed.size()); 322 EXPECT_EQ(1, passed[0].foo()); 323 EXPECT_EQ(2, passed[0].bar()); 324 EXPECT_EQ(0, passed[0].baz()); 325 EXPECT_EQ(3, passed[1].foo()); 326 EXPECT_EQ(4, passed[1].bar()); 327 EXPECT_EQ(0, passed[1].baz()); 328 run_loop.Quit(); 329 })); 330 run_loop.Run(); 331 } 332 } 333 334 TEST_F(PickleTest, PickleArrayArray) { 335 auto proxy = ConnectToChromiumService(); 336 auto pickle_arrays = std::vector<std::vector<PickledStructChromium>>(2); 337 for (size_t i = 0; i < 2; ++i) 338 pickle_arrays[i] = std::vector<PickledStructChromium>(2); 339 340 pickle_arrays[0][0].set_foo(1); 341 pickle_arrays[0][0].set_bar(2); 342 pickle_arrays[0][0].set_baz(100); 343 pickle_arrays[0][1].set_foo(3); 344 pickle_arrays[0][1].set_bar(4); 345 pickle_arrays[0][1].set_baz(100); 346 pickle_arrays[1][0].set_foo(5); 347 pickle_arrays[1][0].set_bar(6); 348 pickle_arrays[1][0].set_baz(100); 349 pickle_arrays[1][1].set_foo(7); 350 pickle_arrays[1][1].set_bar(8); 351 pickle_arrays[1][1].set_baz(100); 352 { 353 base::RunLoop run_loop; 354 // Verify that the array-of-arrays serializes and deserializes properly. 355 proxy->PassPickleArrays( 356 pickle_arrays, 357 BindSimpleLambda< 358 const std::vector<std::vector<PickledStructChromium>>&>( 359 [&](const std::vector<std::vector<PickledStructChromium>>& passed) { 360 ASSERT_EQ(2u, passed.size()); 361 ASSERT_EQ(2u, passed[0].size()); 362 ASSERT_EQ(2u, passed[1].size()); 363 EXPECT_EQ(1, passed[0][0].foo()); 364 EXPECT_EQ(2, passed[0][0].bar()); 365 EXPECT_EQ(0, passed[0][0].baz()); 366 EXPECT_EQ(3, passed[0][1].foo()); 367 EXPECT_EQ(4, passed[0][1].bar()); 368 EXPECT_EQ(0, passed[0][1].baz()); 369 EXPECT_EQ(5, passed[1][0].foo()); 370 EXPECT_EQ(6, passed[1][0].bar()); 371 EXPECT_EQ(0, passed[1][0].baz()); 372 EXPECT_EQ(7, passed[1][1].foo()); 373 EXPECT_EQ(8, passed[1][1].bar()); 374 EXPECT_EQ(0, passed[1][1].baz()); 375 run_loop.Quit(); 376 })); 377 run_loop.Run(); 378 } 379 } 380 381 TEST_F(PickleTest, PickleContainer) { 382 auto proxy = ConnectToChromiumService(); 383 PickleContainerPtr pickle_container = PickleContainer::New(); 384 pickle_container->f_struct.set_foo(42); 385 pickle_container->f_struct.set_bar(43); 386 pickle_container->f_struct.set_baz(44); 387 pickle_container->f_enum = PickledEnumChromium::VALUE_1; 388 EXPECT_TRUE(pickle_container.Equals(pickle_container)); 389 EXPECT_FALSE(pickle_container.Equals(PickleContainer::New())); 390 { 391 base::RunLoop run_loop; 392 proxy->PassPickleContainer(std::move(pickle_container), 393 BindSimpleLambda<PickleContainerPtr>( 394 [&](PickleContainerPtr passed) { 395 ASSERT_FALSE(passed.is_null()); 396 EXPECT_EQ(42, passed->f_struct.foo()); 397 EXPECT_EQ(43, passed->f_struct.bar()); 398 EXPECT_EQ(0, passed->f_struct.baz()); 399 EXPECT_EQ(PickledEnumChromium::VALUE_1, 400 passed->f_enum); 401 run_loop.Quit(); 402 })); 403 run_loop.Run(); 404 } 405 } 406 407 } // namespace test 408 } // namespace mojo 409