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.
5 #ifndef GOOGLE_APIS_DRIVE_TEST_UTIL_H_
6 #define GOOGLE_APIS_DRIVE_TEST_UTIL_H_
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 "google_apis/drive/base_requests.h"
18 #include "google_apis/drive/gdata_errorcode.h"
19 #include "google_apis/drive/task_util.h"
30 namespace test_server
{
31 class BasicHttpResponse
;
37 namespace google_apis
{
40 // Runs the closure, and then quits the |run_loop|.
41 void RunAndQuit(base::RunLoop
* run_loop
, const base::Closure
& closure
);
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
);
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
,
56 // Returns the absolute path for a test file stored under
58 base::FilePath
GetTestFilePath(const std::string
& relative_path
);
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
);
64 // Writes the |content| to the file at |file_path|. Returns true on success,
66 bool WriteStringToFile(const base::FilePath
& file_path
,
67 const std::string
& content
);
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
72 // Returns true on success with the created file's |path| and |data|, otherwise
74 bool CreateFileOfSpecifiedSize(const base::FilePath
& temp_dir
,
79 // Loads a test JSON file as a base::Value, from a test file stored under
81 scoped_ptr
<base::Value
> LoadJSONFile(const std::string
& relative_path
);
83 // Returns a HttpResponse created from the given file path.
84 scoped_ptr
<net::test_server::BasicHttpResponse
> CreateHttpResponseFromFile(
85 const base::FilePath
& file_path
);
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(
93 net::test_server::HttpRequest
* out_request
,
94 const net::test_server::HttpRequest
& request
);
96 // Parses a value of Content-Range header, which looks like
97 // "bytes <start_position>-<end_position>/<length>".
98 // Returns true on success.
99 bool ParseContentRangeHeader(const std::string
& value
,
100 int64
* start_position
,
104 // Google API related code and Drive File System code work on asynchronous
105 // architecture and return the results via callbacks.
106 // Following code implements a callback to copy such results.
107 // Here is how to use:
109 // // Prepare result storage.
110 // ResultType1 result1;
111 // ResultType2 result2;
114 // PerformAsynchronousTask(
115 // param1, param2, ...,
116 // CreateCopyResultCallback(&result1, &result2, ...));
117 // base::RunLoop().RunUntilIdle(); // Run message loop to complete
118 // // the async task.
120 // // Hereafter, we can write expectation with results.
121 // EXPECT_EQ(expected_result1, result1);
122 // EXPECT_EQ(expected_result2, result2);
125 // Note: The max arity of the supported function is 4 based on the usage.
127 // Following helper templates are to support Chrome's move semantics.
128 // Their goal is defining helper methods which are similar to:
129 // void CopyResultCallback1(T1* out1, T1&& in1)
130 // void CopyResultCallback2(T1* out1, T2* out2, T1&& in1, T2&& in2)
134 // Declare if the type is movable or not. Currently limited to scoped_ptr only.
135 // We can add more types upon the usage.
136 template<typename T
> struct IsMovable
: base::false_type
{};
137 template<typename T
, typename D
>
138 struct IsMovable
<scoped_ptr
<T
, D
> > : base::true_type
{};
140 // InType is const T& if |UseConstRef| is true, otherwise |T|.
141 template<bool UseConstRef
, typename T
> struct InTypeHelper
{
142 typedef const T
& InType
;
144 template<typename T
> struct InTypeHelper
<false, T
> {
148 // Simulates the std::move function in C++11. We use pointer here for argument,
149 // instead of rvalue reference.
150 template<bool IsMovable
, typename T
> struct MoveHelper
{
151 static const T
& Move(const T
* in
) { return *in
; }
153 template<typename T
> struct MoveHelper
<true, T
> {
154 static T
Move(T
* in
) { return in
->Pass(); }
157 // Helper to handle Chrome's move semantics correctly.
159 struct CopyResultCallbackHelper
160 // It is necessary to calculate the exact signature of callbacks we want
161 // to create here. In our case, as we use value-parameters for primitive
162 // types and movable types in the callback declaration.
163 // Thus the incoming type is as follows:
164 // 1) If the argument type |T| is class type but doesn't movable,
165 // |InType| is const T&.
166 // 2) Otherwise, |T| as is.
168 base::is_class
<T
>::value
&& !IsMovable
<T
>::value
, // UseConstRef
170 MoveHelper
<IsMovable
<T
>::value
, T
> {
173 // Copies the |in|'s value to |out|.
174 template<typename T1
>
175 void CopyResultCallback(
177 typename CopyResultCallbackHelper
<T1
>::InType in
) {
178 *out
= CopyResultCallbackHelper
<T1
>::Move(&in
);
181 // Copies the |in1|'s value to |out1|, and |in2|'s to |out2|.
182 template<typename T1
, typename T2
>
183 void CopyResultCallback(
186 typename CopyResultCallbackHelper
<T1
>::InType in1
,
187 typename CopyResultCallbackHelper
<T2
>::InType in2
) {
188 *out1
= CopyResultCallbackHelper
<T1
>::Move(&in1
);
189 *out2
= CopyResultCallbackHelper
<T2
>::Move(&in2
);
192 // Copies the |in1|'s value to |out1|, |in2|'s to |out2|, and |in3|'s to |out3|.
193 template<typename T1
, typename T2
, typename T3
>
194 void CopyResultCallback(
198 typename CopyResultCallbackHelper
<T1
>::InType in1
,
199 typename CopyResultCallbackHelper
<T2
>::InType in2
,
200 typename CopyResultCallbackHelper
<T3
>::InType in3
) {
201 *out1
= CopyResultCallbackHelper
<T1
>::Move(&in1
);
202 *out2
= CopyResultCallbackHelper
<T2
>::Move(&in2
);
203 *out3
= CopyResultCallbackHelper
<T3
>::Move(&in3
);
206 // Holds the pointers for output. This is introduced for the workaround of
207 // the arity limitation of Callback.
208 template<typename T1
, typename T2
, typename T3
, typename T4
>
209 struct OutputParams
{
210 OutputParams(T1
* out1
, T2
* out2
, T3
* out3
, T4
* out4
)
211 : out1(out1
), out2(out2
), out3(out3
), out4(out4
) {}
218 // Copies the |in1|'s value to |output->out1|, |in2|'s to |output->out2|,
220 template<typename T1
, typename T2
, typename T3
, typename T4
>
221 void CopyResultCallback(
222 const OutputParams
<T1
, T2
, T3
, T4
>& output
,
223 typename CopyResultCallbackHelper
<T1
>::InType in1
,
224 typename CopyResultCallbackHelper
<T2
>::InType in2
,
225 typename CopyResultCallbackHelper
<T3
>::InType in3
,
226 typename CopyResultCallbackHelper
<T4
>::InType in4
) {
227 *output
.out1
= CopyResultCallbackHelper
<T1
>::Move(&in1
);
228 *output
.out2
= CopyResultCallbackHelper
<T2
>::Move(&in2
);
229 *output
.out3
= CopyResultCallbackHelper
<T3
>::Move(&in3
);
230 *output
.out4
= CopyResultCallbackHelper
<T4
>::Move(&in4
);
233 } // namespace internal
235 template<typename T1
>
236 base::Callback
<void(typename
internal::CopyResultCallbackHelper
<T1
>::InType
)>
237 CreateCopyResultCallback(T1
* out1
) {
238 return base::Bind(&internal::CopyResultCallback
<T1
>, out1
);
241 template<typename T1
, typename T2
>
242 base::Callback
<void(typename
internal::CopyResultCallbackHelper
<T1
>::InType
,
243 typename
internal::CopyResultCallbackHelper
<T2
>::InType
)>
244 CreateCopyResultCallback(T1
* out1
, T2
* out2
) {
245 return base::Bind(&internal::CopyResultCallback
<T1
, T2
>, out1
, out2
);
248 template<typename T1
, typename T2
, typename T3
>
249 base::Callback
<void(typename
internal::CopyResultCallbackHelper
<T1
>::InType
,
250 typename
internal::CopyResultCallbackHelper
<T2
>::InType
,
251 typename
internal::CopyResultCallbackHelper
<T3
>::InType
)>
252 CreateCopyResultCallback(T1
* out1
, T2
* out2
, T3
* out3
) {
254 &internal::CopyResultCallback
<T1
, T2
, T3
>, out1
, out2
, out3
);
257 template<typename T1
, typename T2
, typename T3
, typename T4
>
258 base::Callback
<void(typename
internal::CopyResultCallbackHelper
<T1
>::InType
,
259 typename
internal::CopyResultCallbackHelper
<T2
>::InType
,
260 typename
internal::CopyResultCallbackHelper
<T3
>::InType
,
261 typename
internal::CopyResultCallbackHelper
<T4
>::InType
)>
262 CreateCopyResultCallback(T1
* out1
, T2
* out2
, T3
* out3
, T4
* out4
) {
264 &internal::CopyResultCallback
<T1
, T2
, T3
, T4
>,
265 internal::OutputParams
<T1
, T2
, T3
, T4
>(out1
, out2
, out3
, out4
));
268 typedef std::pair
<int64
, int64
> ProgressInfo
;
270 // Helper utility for recording the results via ProgressCallback.
271 void AppendProgressCallbackResult(std::vector
<ProgressInfo
>* progress_values
,
275 // Helper utility for recording the content via GetContentCallback.
276 class TestGetContentCallback
{
278 TestGetContentCallback();
279 ~TestGetContentCallback();
281 const GetContentCallback
& callback() const { return callback_
; }
282 const ScopedVector
<std::string
>& data() const { return data_
; }
283 ScopedVector
<std::string
>* mutable_data() { return &data_
; }
284 std::string
GetConcatenatedData() const;
287 void OnGetContent(google_apis::GDataErrorCode error
,
288 scoped_ptr
<std::string
> data
);
290 const GetContentCallback callback_
;
291 ScopedVector
<std::string
> data_
;
293 DISALLOW_COPY_AND_ASSIGN(TestGetContentCallback
);
296 } // namespace test_util
297 } // namespace google_apis
299 #endif // GOOGLE_APIS_DRIVE_TEST_UTIL_H_