• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_TEST_FAKE_IASYNC_OPERATION_WIN_H_
6 #define BASE_TEST_FAKE_IASYNC_OPERATION_WIN_H_
7 
8 #include <wrl/client.h>
9 #include <wrl/implements.h>
10 
11 #include "base/notreached.h"
12 #include "base/win/winrt_foundation_helpers.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 
15 namespace base {
16 namespace win {
17 
18 namespace internal {
19 
20 // Templates used to allow easy reference to the correct types.
21 // See base/win/winrt_foundation_helpers.h for explanation.
22 template <typename T>
23 using AsyncOperationComplex =
24     typename ABI::Windows::Foundation::IAsyncOperation<T>::TResult_complex;
25 
26 template <typename T>
27 using AsyncOperationAbi = AbiType<AsyncOperationComplex<T>>;
28 
29 template <typename T>
30 using AsyncOperationOptionalStorage =
31     OptionalStorageType<AsyncOperationComplex<T>>;
32 
33 template <typename T>
34 using AsyncOperationStorage = StorageType<AsyncOperationComplex<T>>;
35 
36 }  // namespace internal
37 
38 // Provides an implementation of Windows::Foundation::IAsyncOperation for
39 // use in GTests.
40 template <typename T>
41 class FakeIAsyncOperation final
42     : public Microsoft::WRL::RuntimeClass<
43           Microsoft::WRL::RuntimeClassFlags<
44               Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>,
45           ABI::Windows::Foundation::IAsyncOperation<T>,
46           ABI::Windows::Foundation::IAsyncInfo> {
47  public:
48   FakeIAsyncOperation() = default;
49   FakeIAsyncOperation(const FakeIAsyncOperation&) = delete;
50   FakeIAsyncOperation& operator=(const FakeIAsyncOperation&) = delete;
51 
52   // ABI::Windows::Foundation::IAsyncOperation:
put_Completed(ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T> * handler)53   IFACEMETHODIMP put_Completed(
54       ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>* handler)
55       final {
56     EXPECT_EQ(nullptr, handler_)
57         << "put_Completed called on IAsyncOperation with a CompletedHandler "
58            "already defined.";
59     handler_ = handler;
60     return S_OK;
61   }
get_Completed(ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T> ** handler)62   IFACEMETHODIMP get_Completed(
63       ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>** handler)
64       final {
65     NOTREACHED();
66   }
GetResults(internal::AsyncOperationAbi<T> * results)67   IFACEMETHODIMP GetResults(internal::AsyncOperationAbi<T>* results) final {
68     if (!is_complete_) {
69       ADD_FAILURE() << "GetResults called on incomplete IAsyncOperation.";
70       return E_PENDING;
71     }
72     if (status_ != AsyncStatus::Completed && !results_includes_failure_)
73       return E_UNEXPECTED;
74     return base::win::internal::CopyTo(results_, results);
75   }
76 
77   // ABI::Windows::Foundation::IAsyncInfo:
get_Id(uint32_t * id)78   IFACEMETHODIMP get_Id(uint32_t* id) final { NOTREACHED(); }
get_Status(AsyncStatus * status)79   IFACEMETHODIMP get_Status(AsyncStatus* status) final {
80     *status = status_;
81     return S_OK;
82   }
get_ErrorCode(HRESULT * error_code)83   IFACEMETHODIMP get_ErrorCode(HRESULT* error_code) final {
84     EXPECT_FALSE(results_includes_failure_)
85         << "get_ErrorCode called on IAsyncOperation whose failure is expected "
86            "to be expressed through the results instead. If a case arises "
87            "where this is actually intended this check can be removed, but is "
88            "most likely an indication of incorrectly assuming the error_code "
89            "can be used in place of get_Status or GetResults for this kind of "
90            "IAsyncOperation.";
91     *error_code = error_code_;
92     return S_OK;
93   }
Cancel()94   IFACEMETHODIMP Cancel() final { NOTREACHED(); }
Close()95   IFACEMETHODIMP Close() final { NOTREACHED(); }
96 
97   // Completes the operation with |error_code|.
98   //
99   // The get_ErrorCode API will be set to return |error_code|, the remainder of
100   // the APIs will be set to represent an error state, and the CompletedHandler
101   // (if defined) will be run.
CompleteWithError(HRESULT error_code)102   void CompleteWithError(HRESULT error_code) {
103     error_code_ = error_code;
104     status_ = AsyncStatus::Error;
105     InvokeCompletedHandler();
106   }
107 
108   // Completes the operation with |results|, but with an AsyncStatus of Error.
109   // This is an uncommon combination only appropriate when |results| includes
110   // the failure information.
111   //
112   // The GetResults API will be set to return |results| and the get_ErrorCode
113   // API will be set to return S_OK, but the get_Status API will be set to
114   // return AsyncStatus::Error. Then the CompletedHandler (if defined) will be
115   // run.
CompleteWithErrorResult(internal::AsyncOperationStorage<T> results)116   void CompleteWithErrorResult(internal::AsyncOperationStorage<T> results) {
117     error_code_ = S_OK;
118     results_ = std::move(results);
119     results_includes_failure_ = true;
120     status_ = AsyncStatus::Error;
121     InvokeCompletedHandler();
122   }
123 
124   // Completes the operation with |results|.
125   //
126   // The GetResults API will be set to return |results|, the remainder of the
127   // APIs will be set to represent a successfully completed state, and the
128   // CompletedHandler (if defined) will be run.
CompleteWithResults(internal::AsyncOperationStorage<T> results)129   void CompleteWithResults(internal::AsyncOperationStorage<T> results) {
130     error_code_ = S_OK;
131     results_ = std::move(results);
132     status_ = AsyncStatus::Completed;
133     InvokeCompletedHandler();
134   }
135 
136  private:
InvokeCompletedHandler()137   void InvokeCompletedHandler() {
138     ASSERT_FALSE(is_complete_)
139         << "Attempted to invoke completion on an already "
140            "completed IAsyncOperation.";
141     is_complete_ = true;
142     if (handler_)
143       handler_->Invoke(this, status_);
144   }
145 
146   HRESULT error_code_ = S_OK;
147   Microsoft::WRL::ComPtr<
148       ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>>
149       handler_;
150   bool is_complete_ = false;
151   internal::AsyncOperationOptionalStorage<T> results_;
152   bool results_includes_failure_ = false;
153   AsyncStatus status_ = AsyncStatus::Started;
154 };
155 
156 }  // namespace win
157 }  // namespace base
158 
159 #endif  // BASE_TEST_FAKE_IASYNC_OPERATION_WIN_H_
160