<commit_before>#ifndef __PROCESS_GMOCK_HPP__
#define __PROCESS_GMOCK_HPP__

#include <pthread.h>

#include <gmock/gmock.h>

#include <process/dispatch.hpp>
#include <process/event.hpp>
#include <process/filter.hpp>
#include <process/pid.hpp>

#include <stout/exit.hpp>
#include <stout/nothing.hpp>

// NOTE: The gmock library relies on std::tr1::tuple. The gmock
// library provides multiple possible 'tuple' implementations but it
// still uses std::tr1::tuple as the "type" name, hence our use of it
// in this file.


// THIS IS DEPRECATED AND BROKEN! REPLACE ALL USES!
#define EXPECT_MESSAGE(name, from, to)                                  \
  EXPECT_CALL(*new process::MockFilter(),                              \
              filter(testing::A<const process::MessageEvent&>()))       \
    .With(process::MessageMatcher(name, from, to))


// THIS IS DEPRECATED AND BROKEN! REPLACE ALL USES!
#define EXPECT_DISPATCH(pid, method)                                    \
  EXPECT_CALL(*new process::MockFilter(),                              \
              filter(testing::A<const process::DispatchEvent&>()))      \
    .With(process::DispatchMatcher(pid, method))


#define FUTURE_MESSAGE(name, from, to)          \
  process::FutureMessage(name, from, to)

#define DROP_MESSAGE(name, from, to)            \
  process::FutureMessage(name, from, to, true)

#define FUTURE_DISPATCH(pid, method)            \
  process::FutureDispatch(pid, method)

#define DROP_DISPATCH(pid, method)              \
  process::FutureDispatch(pid, method, true)

#define DROP_MESSAGES(name, from, to)           \
  process::DropMessages(name, from, to)

#define EXPECT_NO_FUTURE_MESSAGES(name, from, to)       \
  process::ExpectNoFutureMessages(name, from, to)

#define DROP_DISPATCHES(pid, method)            \
  process::DropDispatches(pid, method)


ACTION_TEMPLATE(PromiseArg,
                HAS_1_TEMPLATE_PARAMS(int, k),
                AND_1_VALUE_PARAMS(promise))
{
  // TODO(benh): Use a shared_ptr for promise to defend against this
  // action getting invoked more than once (e.g., used via
  // WillRepeatedly). We won't be able to set it a second time but at
  // least we won't get a segmentation fault. We could also consider
  // warning users if they attempted to set it more than once.
  promise->set(std::tr1::get<k>(args));
  delete promise;
}


template <int index, typename T>
PromiseArgActionP<index, process::Promise<T>*> FutureArg(
    process::Future<T>* future)
{
  process::Promise<T>* promise = new process::Promise<T>();
  *future = promise->future();
  return PromiseArg<index>(promise);
}


ACTION_TEMPLATE(PromiseArgField,
                HAS_1_TEMPLATE_PARAMS(int, k),
                AND_2_VALUE_PARAMS(field, promise))
{
  // TODO(benh): Use a shared_ptr for promise to defend against this
  // action getting invoked more than once (e.g., used via
  // WillRepeatedly). We won't be able to set it a second time but at
  // least we won't get a segmentation fault. We could also consider
  // warning users if they attempted to set it more than once.
  promise->set(*(std::tr1::get<k>(args).*field));
  delete promise;
}


template <int index, typename Field, typename T>
PromiseArgFieldActionP2<index, Field, process::Promise<T>*> FutureArgField(
    Field field,
    process::Future<T>* future)
{
  process::Promise<T>* promise = new process::Promise<T>();
  *future = promise->future();
  return PromiseArgField<index>(field, promise);
}


ACTION_P2(PromiseSatisfy, promise, value)
{
  promise->set(value);
  delete promise;
}


template <typename T>
PromiseSatisfyActionP2<process::Promise<T>*, T> FutureSatisfy(
    process::Future<T>* future,
    T t)
{
  process::Promise<T>* promise = new process::Promise<T>();
  *future = promise->future();
  return PromiseSatisfy(promise, t);
}


inline PromiseSatisfyActionP2<process::Promise<Nothing>*, Nothing>
FutureSatisfy(process::Future<Nothing>* future)
{
  process::Promise<Nothing>* promise = new process::Promise<Nothing>();
  *future = promise->future();
  return PromiseSatisfy(promise, Nothing());<commit_msg>Introduced a FutureResult action.<commit_after>#ifndef __PROCESS_GMOCK_HPP__
#define __PROCESS_GMOCK_HPP__

#include <pthread.h>

#include <gmock/gmock.h>

#include <process/dispatch.hpp>
#include <process/event.hpp>
#include <process/filter.hpp>
#include <process/pid.hpp>

#include <stout/exit.hpp>
#include <stout/nothing.hpp>

// NOTE: The gmock library relies on std::tr1::tuple. The gmock
// library provides multiple possible 'tuple' implementations but it
// still uses std::tr1::tuple as the "type" name, hence our use of it
// in this file.


// THIS IS DEPRECATED AND BROKEN! REPLACE ALL USES!
#define EXPECT_MESSAGE(name, from, to)                                  \
  EXPECT_CALL(*new process::MockFilter(),                              \
              filter(testing::A<const process::MessageEvent&>()))       \
    .With(process::MessageMatcher(name, from, to))


// THIS IS DEPRECATED AND BROKEN! REPLACE ALL USES!
#define EXPECT_DISPATCH(pid, method)                                    \
  EXPECT_CALL(*new process::MockFilter(),                              \
              filter(testing::A<const process::DispatchEvent&>()))      \
    .With(process::DispatchMatcher(pid, method))


#define FUTURE_MESSAGE(name, from, to)          \
  process::FutureMessage(name, from, to)

#define DROP_MESSAGE(name, from, to)            \
  process::FutureMessage(name, from, to, true)

#define FUTURE_DISPATCH(pid, method)            \
  process::FutureDispatch(pid, method)

#define DROP_DISPATCH(pid, method)              \
  process::FutureDispatch(pid, method, true)

#define DROP_MESSAGES(name, from, to)           \
  process::DropMessages(name, from, to)

#define EXPECT_NO_FUTURE_MESSAGES(name, from, to)       \
  process::ExpectNoFutureMessages(name, from, to)

#define DROP_DISPATCHES(pid, method)            \
  process::DropDispatches(pid, method)


ACTION_TEMPLATE(PromiseArg,
                HAS_1_TEMPLATE_PARAMS(int, k),
                AND_1_VALUE_PARAMS(promise))
{
  // TODO(benh): Use a shared_ptr for promise to defend against this
  // action getting invoked more than once (e.g., used via
  // WillRepeatedly). We won't be able to set it a second time but at
  // least we won't get a segmentation fault. We could also consider
  // warning users if they attempted to set it more than once.
  promise->set(std::tr1::get<k>(args));
  delete promise;
}


template <int index, typename T>
PromiseArgActionP<index, process::Promise<T>*> FutureArg(
    process::Future<T>* future)
{
  process::Promise<T>* promise = new process::Promise<T>();
  *future = promise->future();
  return PromiseArg<index>(promise);
}


ACTION_TEMPLATE(PromiseArgField,
                HAS_1_TEMPLATE_PARAMS(int, k),
                AND_2_VALUE_PARAMS(field, promise))
{
  // TODO(benh): Use a shared_ptr for promise to defend against this
  // action getting invoked more than once (e.g., used via
  // WillRepeatedly). We won't be able to set it a second time but at
  // least we won't get a segmentation fault. We could also consider
  // warning users if they attempted to set it more than once.
  promise->set(*(std::tr1::get<k>(args).*field));
  delete promise;
}


template <int index, typename Field, typename T>
PromiseArgFieldActionP2<index, Field, process::Promise<T>*> FutureArgField(
    Field field,
    process::Future<T>* future)
{
  process::Promise<T>* promise = new process::Promise<T>();
  *future = promise->future();
  return PromiseArgField<index>(field, promise);
}


ACTION_P2(PromiseSatisfy, promise, value)
{
  promise->set(value);
  delete promise;
}


template <typename T>
PromiseSatisfyActionP2<process::Promise<T>*, T> FutureSatisfy(
    process::Future<T>* future,
    T t)
{
  process::Promise<T>* promise = new process::Promise<T>();
  *future = promise->future();
  return PromiseSatisfy(promise, t);
}


inline PromiseSatisfyActionP2<process::Promise<Nothing>*, Nothing>
FutureSatisfy(process::Future<Nothing>* future)
{
  process::Promise<Nothing>* promise = new process::Promise<Nothing>();
  *future = promise->future();
  return PromiseSatisfy(promise, Nothing());
}


// This action invokes an "inner" action but captures the result and
// stores a copy of it in a future. Note that this is implemented
// similarly to the IgnoreResult action, which relies on the cast
// operator to Action<F> which must occur (implicitly) before the
// expression has completed, hence we can pass the Future<R>* all the
// way through to our action "implementation".
template <typename R, typename A>
class FutureResultAction
{
public:
  explicit FutureResultAction(process::Future<R>* future, const A& action)
    : future(future),
      action(action) {}

  template <typename F>
  operator ::testing::Action<F>() const
  {
    return ::testing::Action<F>(new Implementation<F>(future, action));
  }

private:
  template <typename F>
  class Implementation : public ::testing::ActionInterface<F>
  {
  public:
    explicit Implementation(process::Future<R>* future, const A& action)
      : action(action)
    {
      *future = promise.future();
    }

    virtual typename ::testing::ActionInterface<F>::Result Perform(
        const typename ::testing::ActionInterface<F>::ArgumentTuple& args)
    {
      const typename ::testing::ActionInterface<F>::Result& result =
        action.Perform(args);
      promise.set(result);
      return result;
    }

  private:
    // Not copyable, not assignable.
    Implementation(const Implementation&);
    Implementation& operator = (const Implementation&);

    process::Promise<R> promise;
    const ::testing::Action<F> action;
  };

  process::Future<R>* future;
  const A action;
};


template <typename R, typename A>
FutureResultAction<R, A> FutureResult(
    process::Future<R>* future,
    const A& action)
{
  return FutureResultAction<R, A>(future, action);
{'fraction_non_alphanumeric': 0.12579249270403542, 'fraction_numerical': 0.00241521585991748, 'mean_word_length': 3.5987968533086536, 'pattern_counts': {'":': 0, '<': 98, '<?xml version=': 0, '>': 112, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6531221', 'n_tokens_mistral': 3111, 'n_tokens_neox': 3027, 'n_words': 834}