Home | History | Annotate | Download | only in google_apis
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CHROME_BROWSER_GOOGLE_APIS_TEST_UTIL_H_
      6 #define CHROME_BROWSER_GOOGLE_APIS_TEST_UTIL_H_
      7 
      8 #include <string>
      9 #include <utility>
     10 #include <vector>
     11 
     12 #include "base/bind.h"
     13 #include "base/callback.h"
     14 #include "base/memory/scoped_ptr.h"
     15 #include "base/memory/scoped_vector.h"
     16 #include "base/template_util.h"
     17 #include "chrome/browser/google_apis/base_requests.h"
     18 #include "chrome/browser/google_apis/gdata_errorcode.h"
     19 #include "chrome/browser/google_apis/task_util.h"
     20 
     21 class GURL;
     22 
     23 namespace base {
     24 class FilePath;
     25 class RunLoop;
     26 class Value;
     27 }
     28 
     29 namespace net {
     30 namespace test_server {
     31 class BasicHttpResponse;
     32 class HttpResponse;
     33 struct HttpRequest;
     34 }
     35 }
     36 
     37 namespace google_apis {
     38 namespace test_util {
     39 
     40 // Runs the closure, and then quits the |run_loop|.
     41 void RunAndQuit(base::RunLoop* run_loop, const base::Closure& closure);
     42 
     43 // Returns callback which runs the given |callback| and then quits |run_loop|.
     44 template<typename CallbackType>
     45 CallbackType CreateQuitCallback(base::RunLoop* run_loop,
     46                                 const CallbackType& callback) {
     47   return CreateComposedCallback(base::Bind(&RunAndQuit, run_loop), callback);
     48 }
     49 
     50 // Removes |prefix| from |input| and stores the result in |output|. Returns
     51 // true if the prefix is removed.
     52 bool RemovePrefix(const std::string& input,
     53                   const std::string& prefix,
     54                   std::string* output);
     55 
     56 // Returns the absolute path for a test file stored under
     57 // chrome/test/data.
     58 base::FilePath GetTestFilePath(const std::string& relative_path);
     59 
     60 // Returns the base URL for communicating with the local test server for
     61 // testing, running at the specified port number.
     62 GURL GetBaseUrlForTesting(int port);
     63 
     64 // Writes the |content| to the file at |file_path|. Returns true on success,
     65 // otherwise false.
     66 bool WriteStringToFile(const base::FilePath& file_path,
     67                        const std::string& content);
     68 
     69 // Creates a |size| byte file. The file is filled with random bytes so that
     70 // the test assertions can identify correct portion/position of the file is
     71 // used.
     72 // Returns true on success with the created file's |path| and |data|, otherwise
     73 // false.
     74 bool CreateFileOfSpecifiedSize(const base::FilePath& temp_dir,
     75                                size_t size,
     76                                base::FilePath* path,
     77                                std::string* data);
     78 
     79 // Loads a test JSON file as a base::Value, from a test file stored under
     80 // chrome/test/data.
     81 scoped_ptr<base::Value> LoadJSONFile(const std::string& relative_path);
     82 
     83 // Returns a HttpResponse created from the given file path.
     84 scoped_ptr<net::test_server::BasicHttpResponse> CreateHttpResponseFromFile(
     85     const base::FilePath& file_path);
     86 
     87 // Handles a request for downloading a file. Reads a file from the test
     88 // directory and returns the content. Also, copies the |request| to the memory
     89 // pointed by |out_request|.
     90 // |base_url| must be set to the server's base url.
     91 scoped_ptr<net::test_server::HttpResponse> HandleDownloadFileRequest(
     92     const GURL& base_url,
     93     net::test_server::HttpRequest* out_request,
     94     const net::test_server::HttpRequest& request);
     95 
     96 // Returns true if |json_data| is not NULL and equals to the content in
     97 // |expected_json_file_path|. The failure reason will be logged into LOG(ERROR)
     98 // if necessary.
     99 bool VerifyJsonData(const base::FilePath& expected_json_file_path,
    100                     const base::Value* json_data);
    101 
    102 // Parses a value of Content-Range header, which looks like
    103 // "bytes <start_position>-<end_position>/<length>".
    104 // Returns true on success.
    105 bool ParseContentRangeHeader(const std::string& value,
    106                              int64* start_position,
    107                              int64* end_position,
    108                              int64* length);
    109 
    110 // Google API related code and Drive File System code work on asynchronous
    111 // architecture and return the results via callbacks.
    112 // Following code implements a callback to copy such results.
    113 // Here is how to use:
    114 //
    115 //   // Prepare result storage.
    116 //   ResultType1 result1;
    117 //   ResultType2 result2;
    118 //           :
    119 //
    120 //   PerformAsynchronousTask(
    121 //       param1, param2, ...,
    122 //       CreateCopyResultCallback(&result1, &result2, ...));
    123 //   base::RunLoop().RunUntilIdle();  // Run message loop to complete
    124 //                                    // the async task.
    125 //
    126 //   // Hereafter, we can write expectation with results.
    127 //   EXPECT_EQ(expected_result1, result1);
    128 //   EXPECT_EQ(expected_result2, result2);
    129 //                     :
    130 //
    131 // Note: The max arity of the supported function is 4 based on the usage.
    132 // TODO(hidehiko): Use replace CopyResultFromXxxCallback method defined above
    133 //   by this one. (crbug.com/180569).
    134 namespace internal {
    135 // Following helper templates are to support Chrome's move semantics.
    136 // Their goal is defining helper methods which are similar to:
    137 //   void CopyResultCallback1(T1* out1, T1&& in1)
    138 //   void CopyResultCallback2(T1* out1, T2* out2, T1&& in1, T2&& in2)
    139 //            :
    140 // in C++11.
    141 
    142 // Declare if the type is movable or not. Currently limited to scoped_ptr only.
    143 // We can add more types upon the usage.
    144 template<typename T> struct IsMovable : base::false_type {};
    145 template<typename T, typename D>
    146 struct IsMovable<scoped_ptr<T, D> > : base::true_type {};
    147 
    148 // InType is const T& if |UseConstRef| is true, otherwise |T|.
    149 template<bool UseConstRef, typename T> struct InTypeHelper {
    150   typedef const T& InType;
    151 };
    152 template<typename T> struct InTypeHelper<false, T> {
    153   typedef T InType;
    154 };
    155 
    156 // Simulates the std::move function in C++11. We use pointer here for argument,
    157 // instead of rvalue reference.
    158 template<bool IsMovable, typename T> struct MoveHelper {
    159   static const T& Move(const T* in) { return *in; }
    160 };
    161 template<typename T> struct MoveHelper<true, T> {
    162   static T Move(T* in) { return in->Pass(); }
    163 };
    164 
    165 // Helper to handle Chrome's move semantics correctly.
    166 template<typename T>
    167 struct CopyResultCallbackHelper
    168       // It is necessary to calculate the exact signature of callbacks we want
    169       // to create here. In our case, as we use value-parameters for primitive
    170       // types and movable types in the callback declaration.
    171       // Thus the incoming type is as follows:
    172       // 1) If the argument type |T| is class type but doesn't movable,
    173       //    |InType| is const T&.
    174       // 2) Otherwise, |T| as is.
    175     : InTypeHelper<
    176           base::is_class<T>::value && !IsMovable<T>::value,  // UseConstRef
    177           T>,
    178       MoveHelper<IsMovable<T>::value, T> {
    179 };
    180 
    181 // Copies the |in|'s value to |out|.
    182 template<typename T1>
    183 void CopyResultCallback(
    184     T1* out,
    185     typename CopyResultCallbackHelper<T1>::InType in) {
    186   *out = CopyResultCallbackHelper<T1>::Move(&in);
    187 }
    188 
    189 // Copies the |in1|'s value to |out1|, and |in2|'s to |out2|.
    190 template<typename T1, typename T2>
    191 void CopyResultCallback(
    192     T1* out1,
    193     T2* out2,
    194     typename CopyResultCallbackHelper<T1>::InType in1,
    195     typename CopyResultCallbackHelper<T2>::InType in2) {
    196   *out1 = CopyResultCallbackHelper<T1>::Move(&in1);
    197   *out2 = CopyResultCallbackHelper<T2>::Move(&in2);
    198 }
    199 
    200 // Copies the |in1|'s value to |out1|, |in2|'s to |out2|, and |in3|'s to |out3|.
    201 template<typename T1, typename T2, typename T3>
    202 void CopyResultCallback(
    203     T1* out1,
    204     T2* out2,
    205     T3* out3,
    206     typename CopyResultCallbackHelper<T1>::InType in1,
    207     typename CopyResultCallbackHelper<T2>::InType in2,
    208     typename CopyResultCallbackHelper<T3>::InType in3) {
    209   *out1 = CopyResultCallbackHelper<T1>::Move(&in1);
    210   *out2 = CopyResultCallbackHelper<T2>::Move(&in2);
    211   *out3 = CopyResultCallbackHelper<T3>::Move(&in3);
    212 }
    213 
    214 // Holds the pointers for output. This is introduced for the workaround of
    215 // the arity limitation of Callback.
    216 template<typename T1, typename T2, typename T3, typename T4>
    217 struct OutputParams {
    218   OutputParams(T1* out1, T2* out2, T3* out3, T4* out4)
    219       : out1(out1), out2(out2), out3(out3), out4(out4) {}
    220   T1* out1;
    221   T2* out2;
    222   T3* out3;
    223   T4* out4;
    224 };
    225 
    226 // Copies the |in1|'s value to |output->out1|, |in2|'s to |output->out2|,
    227 // and so on.
    228 template<typename T1, typename T2, typename T3, typename T4>
    229 void CopyResultCallback(
    230     const OutputParams<T1, T2, T3, T4>& output,
    231     typename CopyResultCallbackHelper<T1>::InType in1,
    232     typename CopyResultCallbackHelper<T2>::InType in2,
    233     typename CopyResultCallbackHelper<T3>::InType in3,
    234     typename CopyResultCallbackHelper<T4>::InType in4) {
    235   *output.out1 = CopyResultCallbackHelper<T1>::Move(&in1);
    236   *output.out2 = CopyResultCallbackHelper<T2>::Move(&in2);
    237   *output.out3 = CopyResultCallbackHelper<T3>::Move(&in3);
    238   *output.out4 = CopyResultCallbackHelper<T4>::Move(&in4);
    239 }
    240 
    241 }  // namespace internal
    242 
    243 template<typename T1>
    244 base::Callback<void(typename internal::CopyResultCallbackHelper<T1>::InType)>
    245 CreateCopyResultCallback(T1* out1) {
    246   return base::Bind(&internal::CopyResultCallback<T1>, out1);
    247 }
    248 
    249 template<typename T1, typename T2>
    250 base::Callback<void(typename internal::CopyResultCallbackHelper<T1>::InType,
    251                     typename internal::CopyResultCallbackHelper<T2>::InType)>
    252 CreateCopyResultCallback(T1* out1, T2* out2) {
    253   return base::Bind(&internal::CopyResultCallback<T1, T2>, out1, out2);
    254 }
    255 
    256 template<typename T1, typename T2, typename T3>
    257 base::Callback<void(typename internal::CopyResultCallbackHelper<T1>::InType,
    258                     typename internal::CopyResultCallbackHelper<T2>::InType,
    259                     typename internal::CopyResultCallbackHelper<T3>::InType)>
    260 CreateCopyResultCallback(T1* out1, T2* out2, T3* out3) {
    261   return base::Bind(
    262       &internal::CopyResultCallback<T1, T2, T3>, out1, out2, out3);
    263 }
    264 
    265 template<typename T1, typename T2, typename T3, typename T4>
    266 base::Callback<void(typename internal::CopyResultCallbackHelper<T1>::InType,
    267                     typename internal::CopyResultCallbackHelper<T2>::InType,
    268                     typename internal::CopyResultCallbackHelper<T3>::InType,
    269                     typename internal::CopyResultCallbackHelper<T4>::InType)>
    270 CreateCopyResultCallback(T1* out1, T2* out2, T3* out3, T4* out4) {
    271   return base::Bind(
    272       &internal::CopyResultCallback<T1, T2, T3, T4>,
    273       internal::OutputParams<T1, T2, T3, T4>(out1, out2, out3, out4));
    274 }
    275 
    276 typedef std::pair<int64, int64> ProgressInfo;
    277 
    278 // Helper utility for recording the results via ProgressCallback.
    279 void AppendProgressCallbackResult(std::vector<ProgressInfo>* progress_values,
    280                                   int64 progress,
    281                                   int64 total);
    282 
    283 // Helper utility for recording the content via GetContentCallback.
    284 class TestGetContentCallback {
    285  public:
    286   TestGetContentCallback();
    287   ~TestGetContentCallback();
    288 
    289   const GetContentCallback& callback() const { return callback_; }
    290   const ScopedVector<std::string>& data() const { return data_; }
    291   ScopedVector<std::string>* mutable_data() { return &data_; }
    292   std::string GetConcatenatedData() const;
    293 
    294  private:
    295   void OnGetContent(google_apis::GDataErrorCode error,
    296                     scoped_ptr<std::string> data);
    297 
    298   const GetContentCallback callback_;
    299   ScopedVector<std::string> data_;
    300 
    301   DISALLOW_COPY_AND_ASSIGN(TestGetContentCallback);
    302 };
    303 
    304 }  // namespace test_util
    305 }  // namespace google_apis
    306 
    307 #endif  // CHROME_BROWSER_GOOGLE_APIS_TEST_UTIL_H_
    308