1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_FEED_CORE_V2_TEST_CALLBACK_RECEIVER_H_
#define COMPONENTS_FEED_CORE_V2_TEST_CALLBACK_RECEIVER_H_
#include <memory>
#include <optional>
#include <tuple>
#include <utility>
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
namespace feed {
namespace internal {
template <typename T>
std::optional<T> Nullopt() {
return std::nullopt;
}
class CallbackReceiverBase {
public:
explicit CallbackReceiverBase(base::RunLoop* run_loop = nullptr)
: run_loop_(run_loop) {}
void Clear() { called_ = false; }
bool called() const { return called_; }
void RunUntilCalled();
void Done();
private:
bool called_ = false;
raw_ptr<base::RunLoop> run_loop_;
};
} // namespace internal
template <typename... T>
class CallbackReceiver : public internal::CallbackReceiverBase {
public:
explicit CallbackReceiver(base::RunLoop* run_loop = nullptr)
: CallbackReceiverBase(run_loop) {}
void Done(T... results) {
results_ = std::make_tuple(std::move(results)...);
CallbackReceiverBase::Done();
}
base::OnceCallback<void(T...)> Bind() {
return base::BindOnce(&CallbackReceiver::Done, GetWeakPtr());
}
base::RepeatingCallback<void(T...)> BindRepeating() {
return base::BindRepeating(&CallbackReceiver::Done, GetWeakPtr());
}
void Clear() {
CallbackReceiverBase::Clear();
results_ = std::make_tuple(internal::Nullopt<T>()...);
}
// Get a result by its position in the arguments to Done().
// Call GetResult() for the first argument or GetResult<I>().
template <size_t I = 0>
typename std::tuple_element<I, std::tuple<std::optional<T>...>>::type&
GetResult() {
return std::get<I>(results_);
}
template <size_t I = 0>
typename std::tuple_element<I, std::tuple<T...>>::type& RunAndGetResult() {
RunUntilCalled();
return std::get<I>(results_).value();
}
// Get a result by its type. Won't compile if there is more than one matching
// type.
template <class C>
std::optional<C>& GetResult() {
return std::get<std::optional<C>>(results_);
}
private:
base::WeakPtr<CallbackReceiver> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
std::tuple<std::optional<T>...> results_;
base::WeakPtrFactory<CallbackReceiver> weak_ptr_factory_{this};
};
template <>
class CallbackReceiver<> : public internal::CallbackReceiverBase {
public:
explicit CallbackReceiver(base::RunLoop* run_loop = nullptr)
: CallbackReceiverBase(run_loop) {}
base::OnceClosure Bind() {
return base::BindOnce(&CallbackReceiverBase::Done, base::Unretained(this));
}
base::RepeatingClosure BindRepeating() {
return base::BindRepeating(&CallbackReceiverBase::Done,
base::Unretained(this));
}
};
} // namespace feed
#endif // COMPONENTS_FEED_CORE_V2_TEST_CALLBACK_RECEIVER_H_
|