async_operation_unittest.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. // Copyright 2018 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. #include "base/win/async_operation.h"
  5. #include <utility>
  6. #include "base/test/gtest_util.h"
  7. #include "testing/gtest/include/gtest/gtest.h"
  8. namespace WRL = Microsoft::WRL;
  9. using ABI::Windows::Foundation::IAsyncOperation;
  10. using ABI::Windows::Foundation::IAsyncOperationCompletedHandler;
  11. // In order to exercise the interface logic of AsyncOperation we define an empty
  12. // dummy interface, its implementation, and the necessary boilerplate to hook it
  13. // up with IAsyncOperation and IAsyncOperationCompletedHandler.
  14. namespace {
  15. // Chosen by fair `uuidgen` invocation. Also applies to the UUIDs below.
  16. MIDL_INTERFACE("756358C7-8083-4D78-9D27-9278B76096d4")
  17. IFooBar : public IInspectable{};
  18. class FooBar
  19. : public WRL::RuntimeClass<
  20. WRL::RuntimeClassFlags<WRL::WinRt | WRL::InhibitRoOriginateError>,
  21. IFooBar> {};
  22. } // namespace
  23. namespace ABI {
  24. namespace Windows {
  25. namespace Foundation {
  26. // Provide the required template specializations to register
  27. // IAsyncOperation<Foobar*> as an AggregateType. This is similar to how it is
  28. // done for UWP classes.
  29. template <>
  30. struct DECLSPEC_UUID("124858e4-f97e-409c-86ae-418c4781144c")
  31. IAsyncOperation<FooBar*>
  32. : IAsyncOperation_impl<Internal::AggregateType<FooBar*, IFooBar*>> {
  33. static const wchar_t* z_get_rc_name_impl() {
  34. return L"Windows.Foundation.IAsyncOperation<FooBar>";
  35. }
  36. };
  37. template <>
  38. struct DECLSPEC_UUID("9e49373c-200c-4715-abd7-4214ba669c81")
  39. IAsyncOperationCompletedHandler<FooBar*>
  40. : IAsyncOperationCompletedHandler_impl<
  41. Internal::AggregateType<FooBar*, IFooBar*>> {
  42. static const wchar_t* z_get_rc_name_impl() {
  43. return L"Windows.Foundation.AsyncOperationCompletedHandler<FooBar>";
  44. }
  45. };
  46. #ifdef NTDDI_WIN10_VB // Windows 10.0.19041
  47. // Specialization templates that used to be in windows.foundation.h, removed in
  48. // the 10.0.19041.0 SDK, so placed here instead.
  49. template <>
  50. struct __declspec(uuid("968b9665-06ed-5774-8f53-8edeabd5f7b5"))
  51. IAsyncOperation<int> : IAsyncOperation_impl<int> {};
  52. template <>
  53. struct __declspec(uuid("d60cae9d-88cb-59f1-8576-3fba44796be8"))
  54. IAsyncOperationCompletedHandler<int>
  55. : IAsyncOperationCompletedHandler_impl<int> {};
  56. #endif
  57. } // namespace Foundation
  58. } // namespace Windows
  59. } // namespace ABI
  60. namespace base {
  61. namespace win {
  62. namespace {
  63. // Utility method to add a completion callback to |async_op|. |*called_cb| will
  64. // be set to true once the callback is invoked.
  65. template <typename T>
  66. void PutCallback(AsyncOperation<T>* async_op, bool* called_cb) {
  67. async_op->put_Completed(
  68. WRL::Callback<IAsyncOperationCompletedHandler<T>>(
  69. [=](IAsyncOperation<T>* iasync_op, AsyncStatus status) {
  70. EXPECT_EQ(async_op, iasync_op);
  71. *called_cb = true;
  72. return S_OK;
  73. })
  74. .Get());
  75. }
  76. } // namespace
  77. TEST(AsyncOperationTest, TestInt) {
  78. bool called_cb = false;
  79. auto int_op = WRL::Make<AsyncOperation<int>>();
  80. PutCallback(int_op.Get(), &called_cb);
  81. int results;
  82. EXPECT_TRUE(FAILED(int_op->GetResults(&results)));
  83. EXPECT_FALSE(called_cb);
  84. int_op->callback().Run(123);
  85. EXPECT_TRUE(called_cb);
  86. EXPECT_TRUE(SUCCEEDED(int_op->GetResults(&results)));
  87. EXPECT_EQ(123, results);
  88. // GetResults should be idempotent.
  89. EXPECT_TRUE(SUCCEEDED(int_op->GetResults(&results)));
  90. EXPECT_EQ(123, results);
  91. }
  92. TEST(AsyncOperationTest, TestBool) {
  93. bool called_cb = false;
  94. auto bool_op = WRL::Make<AsyncOperation<bool>>();
  95. PutCallback(bool_op.Get(), &called_cb);
  96. // AsyncOperation<bool> is an aggregate of bool and boolean, and requires a
  97. // pointer to the latter to get the results.
  98. boolean results;
  99. EXPECT_TRUE(FAILED(bool_op->GetResults(&results)));
  100. EXPECT_FALSE(called_cb);
  101. bool_op->callback().Run(true);
  102. EXPECT_TRUE(called_cb);
  103. EXPECT_TRUE(SUCCEEDED(bool_op->GetResults(&results)));
  104. EXPECT_TRUE(results);
  105. }
  106. TEST(AsyncOperationTest, TestInterface) {
  107. bool called_cb = false;
  108. auto foobar_op = WRL::Make<AsyncOperation<FooBar*>>();
  109. PutCallback(foobar_op.Get(), &called_cb);
  110. // AsyncOperation<FooBar*> is an aggregate of FooBar* and IFooBar*.
  111. WRL::ComPtr<IFooBar> results;
  112. EXPECT_TRUE(FAILED(foobar_op->GetResults(&results)));
  113. EXPECT_FALSE(called_cb);
  114. auto foobar = WRL::Make<FooBar>();
  115. IFooBar* foobar_ptr = foobar.Get();
  116. foobar_op->callback().Run(std::move(foobar));
  117. EXPECT_TRUE(called_cb);
  118. EXPECT_TRUE(SUCCEEDED(foobar_op->GetResults(&results)));
  119. EXPECT_EQ(foobar_ptr, results.Get());
  120. }
  121. TEST(AsyncOperationTest, TestIdempotence) {
  122. bool called_cb = false;
  123. auto int_op = WRL::Make<AsyncOperation<int>>();
  124. PutCallback(int_op.Get(), &called_cb);
  125. int results;
  126. EXPECT_TRUE(FAILED(int_op->GetResults(&results)));
  127. EXPECT_FALSE(called_cb);
  128. // Calling GetResults twice shouldn't change the result.
  129. EXPECT_TRUE(FAILED(int_op->GetResults(&results)));
  130. EXPECT_FALSE(called_cb);
  131. int_op->callback().Run(42);
  132. EXPECT_TRUE(called_cb);
  133. EXPECT_TRUE(SUCCEEDED(int_op->GetResults(&results)));
  134. EXPECT_EQ(42, results);
  135. // Calling GetResults twice shouldn't change the result.
  136. EXPECT_TRUE(SUCCEEDED(int_op->GetResults(&results)));
  137. EXPECT_EQ(42, results);
  138. }
  139. TEST(AsyncOperationTest, DoubleCallbackFails) {
  140. auto int_op = WRL::Make<AsyncOperation<int>>();
  141. auto cb = int_op->callback();
  142. // Obtaining another callback should result in a DCHECK failure.
  143. EXPECT_DCHECK_DEATH(int_op->callback());
  144. }
  145. } // namespace win
  146. } // namespace base