xref: /aosp_15_r20/external/cronet/base/test/fake_iasync_operation_win.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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     return E_NOTIMPL;
67   }
GetResults(internal::AsyncOperationAbi<T> * results)68   IFACEMETHODIMP GetResults(internal::AsyncOperationAbi<T>* results) final {
69     if (!is_complete_) {
70       ADD_FAILURE() << "GetResults called on incomplete IAsyncOperation.";
71       return E_PENDING;
72     }
73     if (status_ != AsyncStatus::Completed && !results_includes_failure_)
74       return E_UNEXPECTED;
75     return base::win::internal::CopyTo(results_, results);
76   }
77 
78   // ABI::Windows::Foundation::IAsyncInfo:
get_Id(uint32_t * id)79   IFACEMETHODIMP get_Id(uint32_t* id) final {
80     NOTREACHED();
81     return E_NOTIMPL;
82   }
get_Status(AsyncStatus * status)83   IFACEMETHODIMP get_Status(AsyncStatus* status) final {
84     *status = status_;
85     return S_OK;
86   }
get_ErrorCode(HRESULT * error_code)87   IFACEMETHODIMP get_ErrorCode(HRESULT* error_code) final {
88     EXPECT_FALSE(results_includes_failure_)
89         << "get_ErrorCode called on IAsyncOperation whose failure is expected "
90            "to be expressed through the results instead. If a case arises "
91            "where this is actually intended this check can be removed, but is "
92            "most likely an indication of incorrectly assuming the error_code "
93            "can be used in place of get_Status or GetResults for this kind of "
94            "IAsyncOperation.";
95     *error_code = error_code_;
96     return S_OK;
97   }
Cancel()98   IFACEMETHODIMP Cancel() final {
99     NOTREACHED();
100     return E_NOTIMPL;
101   }
Close()102   IFACEMETHODIMP Close() final {
103     NOTREACHED();
104     return E_NOTIMPL;
105   }
106 
107   // Completes the operation with |error_code|.
108   //
109   // The get_ErrorCode API will be set to return |error_code|, the remainder of
110   // the APIs will be set to represent an error state, and the CompletedHandler
111   // (if defined) will be run.
CompleteWithError(HRESULT error_code)112   void CompleteWithError(HRESULT error_code) {
113     error_code_ = error_code;
114     status_ = AsyncStatus::Error;
115     InvokeCompletedHandler();
116   }
117 
118   // Completes the operation with |results|, but with an AsyncStatus of Error.
119   // This is an uncommon combination only appropriate when |results| includes
120   // the failure information.
121   //
122   // The GetResults API will be set to return |results| and the get_ErrorCode
123   // API will be set to return S_OK, but the get_Status API will be set to
124   // return AsyncStatus::Error. Then the CompletedHandler (if defined) will be
125   // run.
CompleteWithErrorResult(internal::AsyncOperationStorage<T> results)126   void CompleteWithErrorResult(internal::AsyncOperationStorage<T> results) {
127     error_code_ = S_OK;
128     results_ = std::move(results);
129     results_includes_failure_ = true;
130     status_ = AsyncStatus::Error;
131     InvokeCompletedHandler();
132   }
133 
134   // Completes the operation with |results|.
135   //
136   // The GetResults API will be set to return |results|, the remainder of the
137   // APIs will be set to represent a successfully completed state, and the
138   // CompletedHandler (if defined) will be run.
CompleteWithResults(internal::AsyncOperationStorage<T> results)139   void CompleteWithResults(internal::AsyncOperationStorage<T> results) {
140     error_code_ = S_OK;
141     results_ = std::move(results);
142     status_ = AsyncStatus::Completed;
143     InvokeCompletedHandler();
144   }
145 
146  private:
InvokeCompletedHandler()147   void InvokeCompletedHandler() {
148     ASSERT_FALSE(is_complete_)
149         << "Attempted to invoke completion on an already "
150            "completed IAsyncOperation.";
151     is_complete_ = true;
152     if (handler_)
153       handler_->Invoke(this, status_);
154   }
155 
156   HRESULT error_code_ = S_OK;
157   Microsoft::WRL::ComPtr<
158       ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>>
159       handler_;
160   bool is_complete_ = false;
161   internal::AsyncOperationOptionalStorage<T> results_;
162   bool results_includes_failure_ = false;
163   AsyncStatus status_ = AsyncStatus::Started;
164 };
165 
166 }  // namespace win
167 }  // namespace base
168 
169 #endif  // BASE_TEST_FAKE_IASYNC_OPERATION_WIN_H_
170