| Index: chrome/browser/google_apis/test_util.h
|
| diff --git a/chrome/browser/google_apis/test_util.h b/chrome/browser/google_apis/test_util.h
|
| index d76f360114ee36f398b5e28d052c56381f5815bc..8127dad9b43950652010acb423a753e0b211afb2 100644
|
| --- a/chrome/browser/google_apis/test_util.h
|
| +++ b/chrome/browser/google_apis/test_util.h
|
| @@ -7,7 +7,10 @@
|
|
|
| #include <string>
|
|
|
| +#include "base/bind.h"
|
| +#include "base/callback.h"
|
| #include "base/memory/scoped_ptr.h"
|
| +#include "base/template_util.h"
|
| #include "chrome/browser/google_apis/gdata_errorcode.h"
|
|
|
| class GURL;
|
| @@ -43,6 +46,9 @@ namespace test_util {
|
| // repeatedly.
|
| void RunBlockingPoolTask();
|
|
|
| +// Runs the closure, and then quits the current MessageLoop.
|
| +void RunAndQuit(const base::Closure& closure);
|
| +
|
| // Removes |prefix| from |input| and stores the result in |output|. Returns
|
| // true if the prefix is removed.
|
| bool RemovePrefix(const std::string& input,
|
| @@ -185,6 +191,135 @@ bool ParseContentRangeHeader(const std::string& value,
|
| int64* end_position,
|
| int64* length);
|
|
|
| +// Google API related code and Drive File System code work on asynchronous
|
| +// architecture and return the results via callbacks.
|
| +// Following code implements a callback to copy such results.
|
| +// Here is how to use:
|
| +//
|
| +// // Prepare result storage.
|
| +// ResultType1 result1;
|
| +// ResultType2 result2;
|
| +// :
|
| +//
|
| +// PerformAsynchronousTask(
|
| +// param1, param2, ...,
|
| +// CreateCopyResultCallback(&result1, &result2, ...));
|
| +// RunBlockingPoolTask(); // Run message loop to complete the async task.
|
| +//
|
| +// // Hereafter, we can write expectation with results.
|
| +// EXPECT_EQ(expected_result1, result1);
|
| +// EXPECT_EQ(expected_result2, result2);
|
| +// :
|
| +//
|
| +// Note: The max arity of the supported function is 3. The limitation comes
|
| +// from the max arity of base::Callback, which is 7. A created callback
|
| +// consumes two arguments for each input type.
|
| +// TODO(hidehiko): Use replace CopyResultFromXxxCallback method defined above
|
| +// by this one. (crbug.com/180569).
|
| +namespace internal {
|
| +// Following helper templates are to support Chrome's move semantics.
|
| +// Their goal is defining helper methods which are similar to:
|
| +// void CopyResultCallback1(T1* out1, T1&& in1)
|
| +// void CopyResultCallback2(T1* out1, T2* out2, T1&& in1, T2&& in2)
|
| +// :
|
| +// in C++11.
|
| +
|
| +// Declare if the type is movable or not. Currently limited to scoped_ptr only.
|
| +// We can add more types upon the usage.
|
| +template<typename T> struct IsMovable : base::false_type {};
|
| +template<typename T, typename D>
|
| +struct IsMovable<scoped_ptr<T, D> > : base::true_type {};
|
| +
|
| +// InType is const T& if |UseConstRef| is true, otherwise |T|.
|
| +template<bool UseConstRef, typename T> struct InTypeHelper {
|
| + typedef const T& InType;
|
| +};
|
| +template<typename T> struct InTypeHelper<false, T> {
|
| + typedef T InType;
|
| +};
|
| +
|
| +// Simulates the std::move operation in C++11. We use pointer here for argument,
|
| +// instead of rvalue reference.
|
| +template<bool IsMovable, typename T> struct MoveHelper {
|
| + static const T& Move(const T* in) { return *in; }
|
| +};
|
| +template<typename T> struct MoveHelper<true, T> {
|
| + static T Move(T* in) { return in->Pass(); }
|
| +};
|
| +
|
| +// Helper to handle Chrome's move semantics correctly.
|
| +template<typename T>
|
| +struct CopyResultCallbackHelper
|
| + // It is necessary to calculate the exact signature of callbacks we want
|
| + // to create here. In our case, as we use value-parameters for primitive
|
| + // types and movable types in the callback declaration.
|
| + // Thus the incoming type is as follows:
|
| + // 1) If the argument type |T| is class type but doesn't movable,
|
| + // |InType| is const T&.
|
| + // 2) Otherwise, |T| as is.
|
| + : InTypeHelper<
|
| + base::is_class<T>::value && !IsMovable<T>::value, // UseConstRef
|
| + T>,
|
| + MoveHelper<IsMovable<T>::value, T> {
|
| +};
|
| +
|
| +// Copies the |in|'s value to |out|.
|
| +template<typename T1>
|
| +void CopyResultCallback(
|
| + T1* out,
|
| + typename CopyResultCallbackHelper<T1>::InType in) {
|
| + *out = CopyResultCallbackHelper<T1>::Move(&in);
|
| +}
|
| +
|
| +// Copies the |in1|'s value to |out1|, and |in2|'s to |out2|.
|
| +template<typename T1, typename T2>
|
| +void CopyResultCallback(
|
| + T1* out1,
|
| + T2* out2,
|
| + typename CopyResultCallbackHelper<T1>::InType in1,
|
| + typename CopyResultCallbackHelper<T2>::InType in2) {
|
| + *out1 = CopyResultCallbackHelper<T1>::Move(&in1);
|
| + *out2 = CopyResultCallbackHelper<T2>::Move(&in2);
|
| +}
|
| +
|
| +// Copies the |in1|'s value to |out1|, |in2|'s to |out2|, and |in3|'s to |out3|.
|
| +template<typename T1, typename T2, typename T3>
|
| +void CopyResultCallback(
|
| + T1* out1,
|
| + T2* out2,
|
| + T3* out3,
|
| + typename CopyResultCallbackHelper<T1>::InType in1,
|
| + typename CopyResultCallbackHelper<T2>::InType in2,
|
| + typename CopyResultCallbackHelper<T3>::InType in3) {
|
| + *out1 = CopyResultCallbackHelper<T1>::Move(&in1);
|
| + *out2 = CopyResultCallbackHelper<T2>::Move(&in2);
|
| + *out3 = CopyResultCallbackHelper<T3>::Move(&in3);
|
| +}
|
| +
|
| +} // namespace internal
|
| +
|
| +template<typename T1>
|
| +base::Callback<void(typename internal::CopyResultCallbackHelper<T1>::InType)>
|
| +CreateCopyResultCallback(T1* out1) {
|
| + return base::Bind(&internal::CopyResultCallback<T1>, out1);
|
| +}
|
| +
|
| +template<typename T1, typename T2>
|
| +base::Callback<void(typename internal::CopyResultCallbackHelper<T1>::InType,
|
| + typename internal::CopyResultCallbackHelper<T2>::InType)>
|
| +CreateCopyResultCallback(T1* out1, T2* out2) {
|
| + return base::Bind(&internal::CopyResultCallback<T1, T2>, out1, out2);
|
| +}
|
| +
|
| +template<typename T1, typename T2, typename T3>
|
| +base::Callback<void(typename internal::CopyResultCallbackHelper<T1>::InType,
|
| + typename internal::CopyResultCallbackHelper<T2>::InType,
|
| + typename internal::CopyResultCallbackHelper<T3>::InType)>
|
| +CreateCopyResultCallback(T1* out1, T2* out2, T3* out3) {
|
| + return base::Bind(
|
| + &internal::CopyResultCallback<T1, T2, T3>, out1, out2, out3);
|
| +}
|
| +
|
| } // namespace test_util
|
| } // namespace google_apis
|
|
|
|
|