1 // Copyright 2012 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 NET_BASE_TEST_COMPLETION_CALLBACK_H_ 6 #define NET_BASE_TEST_COMPLETION_CALLBACK_H_ 7 8 #include <stdint.h> 9 10 #include <memory> 11 #include <optional> 12 #include <utility> 13 14 #include "base/compiler_specific.h" 15 #include "base/functional/callback.h" 16 #include "base/memory/raw_ptr.h" 17 #include "net/base/completion_once_callback.h" 18 #include "net/base/net_errors.h" 19 20 //----------------------------------------------------------------------------- 21 // completion callback helper 22 23 // A helper class for completion callbacks, designed to make it easy to run 24 // tests involving asynchronous operations. Just call WaitForResult to wait 25 // for the asynchronous operation to complete. Uses a RunLoop to spin the 26 // current MessageLoop while waiting. The callback must be invoked on the same 27 // thread WaitForResult is called on. 28 // 29 // NOTE: Since this runs a message loop to wait for the completion callback, 30 // there could be other side-effects resulting from WaitForResult. For this 31 // reason, this class is probably not ideal for a general application. 32 // 33 namespace base { 34 class RunLoop; 35 } 36 37 namespace net { 38 39 class IOBuffer; 40 41 namespace internal { 42 43 class TestCompletionCallbackBaseInternal { 44 public: 45 TestCompletionCallbackBaseInternal( 46 const TestCompletionCallbackBaseInternal&) = delete; 47 TestCompletionCallbackBaseInternal& operator=( 48 const TestCompletionCallbackBaseInternal&) = delete; have_result()49 bool have_result() const { return have_result_; } 50 51 protected: 52 TestCompletionCallbackBaseInternal(); 53 virtual ~TestCompletionCallbackBaseInternal(); 54 55 void DidSetResult(); 56 void WaitForResult(); 57 58 private: 59 // RunLoop. Only non-NULL during the call to WaitForResult, so the class is 60 // reusable. 61 std::unique_ptr<base::RunLoop> run_loop_; 62 bool have_result_ = false; 63 }; 64 65 template <typename R> 66 struct NetErrorIsPendingHelper { operatorNetErrorIsPendingHelper67 bool operator()(R status) const { return status == ERR_IO_PENDING; } 68 }; 69 70 template <typename R, typename IsPendingHelper = NetErrorIsPendingHelper<R>> 71 class TestCompletionCallbackTemplate 72 : public TestCompletionCallbackBaseInternal { 73 public: 74 TestCompletionCallbackTemplate(const TestCompletionCallbackTemplate&) = 75 delete; 76 TestCompletionCallbackTemplate& operator=( 77 const TestCompletionCallbackTemplate&) = delete; 78 ~TestCompletionCallbackTemplate() override = default; 79 WaitForResult()80 R WaitForResult() { 81 TestCompletionCallbackBaseInternal::WaitForResult(); 82 return std::move(result_); 83 } 84 GetResult(R result)85 R GetResult(R result) { 86 IsPendingHelper check_pending; 87 if (!check_pending(result)) 88 return std::move(result); 89 return WaitForResult(); 90 } 91 92 protected: TestCompletionCallbackTemplate()93 TestCompletionCallbackTemplate() : result_(R()) {} 94 95 // Override this method to gain control as the callback is running. SetResult(R result)96 virtual void SetResult(R result) { 97 result_ = std::move(result); 98 DidSetResult(); 99 } 100 101 private: 102 R result_; 103 }; 104 105 } // namespace internal 106 107 class TestClosure : public internal::TestCompletionCallbackBaseInternal { 108 public: 109 using internal::TestCompletionCallbackBaseInternal::WaitForResult; 110 111 TestClosure() = default; 112 TestClosure(const TestClosure&) = delete; 113 TestClosure& operator=(const TestClosure&) = delete; 114 ~TestClosure() override; 115 closure()116 base::OnceClosure closure() { 117 return base::BindOnce(&TestClosure::DidSetResult, base::Unretained(this)); 118 } 119 }; 120 121 // Base class overridden by custom implementations of TestCompletionCallback. 122 typedef internal::TestCompletionCallbackTemplate<int> 123 TestCompletionCallbackBase; 124 125 typedef internal::TestCompletionCallbackTemplate<int64_t> 126 TestInt64CompletionCallbackBase; 127 128 class TestCompletionCallback : public TestCompletionCallbackBase { 129 public: 130 TestCompletionCallback() = default; 131 TestCompletionCallback(const TestCompletionCallback&) = delete; 132 TestCompletionCallback& operator=(const TestCompletionCallback&) = delete; 133 ~TestCompletionCallback() override; 134 callback()135 CompletionOnceCallback callback() { 136 return base::BindOnce(&TestCompletionCallback::SetResult, 137 base::Unretained(this)); 138 } 139 }; 140 141 class TestInt64CompletionCallback : public TestInt64CompletionCallbackBase { 142 public: 143 TestInt64CompletionCallback() = default; 144 TestInt64CompletionCallback(const TestInt64CompletionCallback&) = delete; 145 TestInt64CompletionCallback& operator=(const TestInt64CompletionCallback&) = 146 delete; 147 ~TestInt64CompletionCallback() override; 148 callback()149 Int64CompletionOnceCallback callback() { 150 return base::BindOnce(&TestInt64CompletionCallback::SetResult, 151 base::Unretained(this)); 152 } 153 }; 154 155 // Makes sure that the buffer is not referenced when the callback runs. 156 class ReleaseBufferCompletionCallback: public TestCompletionCallback { 157 public: 158 explicit ReleaseBufferCompletionCallback(IOBuffer* buffer); 159 ReleaseBufferCompletionCallback(const ReleaseBufferCompletionCallback&) = 160 delete; 161 ReleaseBufferCompletionCallback& operator=( 162 const ReleaseBufferCompletionCallback&) = delete; 163 ~ReleaseBufferCompletionCallback() override; 164 165 private: 166 void SetResult(int result) override; 167 168 raw_ptr<IOBuffer> buffer_; 169 }; 170 171 } // namespace net 172 173 #endif // NET_BASE_TEST_COMPLETION_CALLBACK_H_ 174