blob: 962642205638f52067f4e92433bc9912ec664b3b [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_PUBLIC_CPP_TEST_SUPPORT_WAITER_H_
#define MOJO_PUBLIC_CPP_TEST_SUPPORT_WAITER_H_
#include <utility>
#include "base/bind.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/run_loop.h"
namespace mojo {
namespace test {
namespace internal {
template <typename CallbackType, typename OutArgTuple>
struct WaiterHelper;
template <typename... InArgs, typename... OutArgs>
struct WaiterHelper<base::OnceCallback<void(InArgs...)>,
std::tuple<OutArgs...>> {
static void MoveOrCopyInputs(base::OnceClosure continuation,
OutArgs*... outputs,
InArgs... inputs) {
int ignored[] = {0, MoveOrCopy(std::forward<InArgs>(inputs), outputs)...};
ALLOW_UNUSED_LOCAL(ignored);
std::move(continuation).Run();
}
private:
template <typename InputType>
using InputTypeToOutputType = typename std::remove_const<
typename std::remove_reference<InputType>::type>::type;
template <typename InputType>
static int MoveOrCopy(InputType&& input,
InputTypeToOutputType<InputType>* output) {
*output = std::move(input);
return 0;
}
};
} // namespace internal
// Waits for a mojo method callback and captures the results. Allows test code
// to be written in a synchronous style, but does not block the current thread
// like [Sync] mojo methods do.
//
// For mojom method:
//
// interface Foo {
// DoFoo() => (int32 i, bool b);
// };
//
// TEST(FooBarTest) {
// Waiter waiter;
// int i = 0;
// bool b = false;
// interface_ptr->DoFoo(
// waiter.CaptureNext<mojom::Foo::DoFooCallback>(&i, &b));
// waiter.Wait();
// EXPECT_EQ(0, i);
// EXPECT_TRUE(b);
// }
class Waiter {
public:
Waiter();
~Waiter();
// Stores |outputs| to be captured later. Can be called more than once.
// Can be used with an empty argument list.
template <typename CallbackType, typename... OutArgs>
CallbackType CaptureNext(OutArgs*... outputs) {
DCHECK(!loop_ || !loop_->running());
loop_ = std::make_unique<base::RunLoop>();
using Helper = internal::WaiterHelper<CallbackType, std::tuple<OutArgs...>>;
return base::BindOnce(&Helper::MoveOrCopyInputs, loop_->QuitClosure(),
outputs...);
}
// Runs the run loop to wait for results.
void Wait();
private:
std::unique_ptr<base::RunLoop> loop_;
DISALLOW_COPY_AND_ASSIGN(Waiter);
};
} // namespace test
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_TEST_SUPPORT_WAITER_H_