Page MenuHomePhorge

D113.1732569071.diff
No OneTemporary

Size
4 KB
Referenced Files
None
Subscribers
None

D113.1732569071.diff

diff --git a/src/tests/client/action-mock-utils.hpp b/src/tests/client/action-mock-utils.hpp
--- a/src/tests/client/action-mock-utils.hpp
+++ b/src/tests/client/action-mock-utils.hpp
@@ -101,6 +101,25 @@
using DataT = typename PromiseT::DataT;
using HandlerResultT = HandlerResult<PromiseT>;
+ /**
+ * A handler for mock dispatchers.
+ *
+ * It can be constructed from a function with the signature
+ * `HandlerResult<ContextT::PromiseT>(PH &, ContextT &, ActionT)`
+ * or it can be constructed from the following convenient
+ * forms called handler tags, where `ActionType` is a type in the variant ActionT:
+ *
+ * - `passDown<ActionType>()` will dispatch the action to the underlying context, and return the promise returned from the dispatch. Actions other than ActionType will not be matched.
+ * - `returnResolved<ActionType>(DataT data)` will return a Promise that is resolved and contains `data` when the action is of ActionType. Actions other than ActionType will not be matched.
+ * - `returnEmpty<ActionType>()` is equivalent to `returnResolved<ActionType>({}).
+ * - `makeHandler<ActionType>(Func func)`, where `func` has any of the following signature:
+ * 1. `HandlerResult<PromiseT>(PH &, ContextT &, ActionType)`. It will be called when the action is of ActionType, and the return value from it will be the result. Actions other than ActionType will not be matched and will not be executed on this function.
+ * 2. `PromiseT(PH &, ContextT &, ActionType)`. It will be called when the action is of ActionType, and in this case it will always be a match, and the result is a HandlerResult with the returned promise. Actions other than ActionType will not be matched and will not be executed on this function.
+ * 3. `HandlerResult<PromiseT>(ActionType)`. Same as the first case, but only the action is passed to the function, and not the promise handler and the context.
+ * 4. `PromiseT(ActionType)`. Same as the second case, but only the action is passed to the function, and not the promise handler and the context.
+ * 5. `DataT(ActionType)`. Same as the fourth case, but the promise returned is one that is resolved and contains the return value of the function.
+ * 6. `void(ActionType)`. Same as the fourth case, but the promise returned is one that is resolved and contains a default-constructed `DataT`.
+ */
struct Handler : public std::function<HandlerResultT(PH &, ContextT &, ActionT)>
{
using BaseT = std::function<HandlerResultT(PH &, ContextT &, ActionT)>;
@@ -220,6 +239,54 @@
std::shared_ptr<std::vector<ActionT>> actions{std::make_shared<std::vector<ActionT>>()};
};
+/**
+ * This is the main entry for getting a mocked dispatcher.
+ *
+ * The handlers are added sequentially, and each of them will
+ * be run with the action as the argument. It will stop at the
+ * first handler that *declares* a match. See
+ * MockDispatcher::Handler for more information on how to make
+ * a handler.
+ *
+ * A handler is a function of the signature `HandlerResult<ContextT::PromiseT>(PH &, ContextT &, ActionT)`.
+ * In the case of making a dispatcher for `Client`, `ActionT` is `ClientAction`.
+ *
+ * For a handler to match, it needs to return a `HandlerResult`
+ * that contains a Promise. If it returns a `HandlerResult`
+ * with `std::nullopt`, it is considered a no-match and the
+ * next handlers will continue execute until it gets a match.
+ * If no matches are found, it will throw an exception saying
+ * `unhandled action: <type>`.
+ *
+ * For example,
+ * ```
+ * getMockDispatcher(ph, ctx,
+ * passDown<A>(),
+ * returnResolved<B>({false, {}}),
+ * makeHandler<C>([](C) {
+ * std::cerr << "C" << std::endl;
+ * return HandlerResult<Promise>(std::nullopt);
+ * }),
+ * makeHandler<D>([&](D) {
+ * std::cerr << "D" << std::endl;
+ * return ctx.createResolved({});
+ * }),
+ * returnEmpty<B>())
+ * ```
+ *
+ * This should pass down action `A` to `ctx`, return a resolved
+ * failed promise for action `B`. For action `C`, it will print out "C" and throw an exception saying `unhandled action: C`
+ * (because the handler does not match, as it returns a result
+ * containing std::nullopt). For action `D`, it will print out
+ * "D" and return a resolved empty promise. For all other actions
+ * it will throw an exception saying `unhandled action: <type>`.
+ *
+ * @param ph The promise handler.
+ * @param ctx The original context that can be used to dispatch
+ * actions. This is needed for `passDown` handlers.
+ * @param handlers The handlers you want to add.
+ * @return A mocked dispatcher.
+ */
template<class PH, class ContextT, class ...Handlers>
auto getMockDispatcher(PH &ph, ContextT &ctx, Handlers ...handlers)
{

File Metadata

Mime Type
text/plain
Expires
Mon, Nov 25, 1:11 PM (10 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39553
Default Alt Text
D113.1732569071.diff (4 KB)

Event Timeline