Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ppapi / tests / test_url_request.cc
blob7c9847b770ff3e816264ab5968ce87a2a79d19de
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 // Tests PPB_URLRequestInfo interface.
7 #include "ppapi/tests/test_url_request.h"
9 #include <string.h>
10 #include <string>
12 #include "ppapi/c/ppb_file_io.h"
13 #include "ppapi/cpp/completion_callback.h"
14 #include "ppapi/cpp/file_io.h"
15 #include "ppapi/cpp/file_ref.h"
16 #include "ppapi/cpp/file_system.h"
17 #include "ppapi/cpp/instance.h"
18 #include "ppapi/cpp/var.h"
19 #include "ppapi/tests/test_utils.h"
20 #include "ppapi/tests/testing_instance.h"
22 REGISTER_TEST_CASE(URLRequest);
24 namespace {
25 // TODO(polina): move these to test_case.h/cc since other NaCl tests use them?
27 const PP_Resource kInvalidResource = 0;
28 const PP_Instance kInvalidInstance = 0;
30 // These should not exist.
31 // The bottom 2 bits are used to differentiate between different id types.
32 // 00 - module, 01 - instance, 10 - resource, 11 - var.
33 const PP_Instance kNotAnInstance = 0xFFFFF0;
34 const PP_Resource kNotAResource = 0xAAAAA0;
37 TestURLRequest::TestURLRequest(TestingInstance* instance)
38 : TestCase(instance),
39 ppb_url_request_interface_(NULL),
40 ppb_url_loader_interface_(NULL),
41 ppb_url_response_interface_(NULL),
42 ppb_core_interface_(NULL),
43 ppb_var_interface_(NULL) {
46 bool TestURLRequest::Init() {
47 ppb_url_request_interface_ = static_cast<const PPB_URLRequestInfo*>(
48 pp::Module::Get()->GetBrowserInterface(PPB_URLREQUESTINFO_INTERFACE));
49 ppb_url_loader_interface_ = static_cast<const PPB_URLLoader*>(
50 pp::Module::Get()->GetBrowserInterface(PPB_URLLOADER_INTERFACE));
51 ppb_url_response_interface_ = static_cast<const PPB_URLResponseInfo*>(
52 pp::Module::Get()->GetBrowserInterface(PPB_URLRESPONSEINFO_INTERFACE));
53 ppb_core_interface_ = static_cast<const PPB_Core*>(
54 pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE));
55 ppb_var_interface_ = static_cast<const PPB_Var*>(
56 pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE));
57 if (!ppb_url_request_interface_)
58 instance_->AppendError("PPB_URLRequestInfo interface not available");
59 if (!ppb_url_response_interface_)
60 instance_->AppendError("PPB_URLResponseInfo interface not available");
61 if (!ppb_core_interface_)
62 instance_->AppendError("PPB_Core interface not available");
63 if (!ppb_var_interface_)
64 instance_->AppendError("PPB_Var interface not available");
65 if (!ppb_url_loader_interface_) {
66 instance_->AppendError("PPB_URLLoader interface not available");
68 return EnsureRunningOverHTTP();
71 void TestURLRequest::RunTests(const std::string& filter) {
72 RUN_TEST(CreateAndIsURLRequestInfo, filter);
73 RUN_TEST(SetProperty, filter);
74 RUN_TEST(AppendDataToBody, filter);
75 RUN_TEST(AppendFileToBody, filter);
76 RUN_TEST(Stress, filter);
79 PP_Var TestURLRequest::PP_MakeString(const char* s) {
80 return ppb_var_interface_->VarFromUtf8(s, static_cast<int32_t>(strlen(s)));
83 // Tests
84 // PP_Resource Create(PP_Instance instance)
85 // PP_Bool IsURLRequestInfo(PP_Resource resource)
86 std::string TestURLRequest::TestCreateAndIsURLRequestInfo() {
87 // Create: Invalid / non-existent instance -> invalid resource.
88 ASSERT_EQ(ppb_url_request_interface_->Create(kInvalidInstance),
89 kInvalidResource);
90 ASSERT_EQ(ppb_url_request_interface_->Create(kNotAnInstance),
91 kInvalidResource);
93 // Create: Valid instance -> valid resource.
94 PP_Resource url_request = ppb_url_request_interface_->Create(
95 instance_->pp_instance());
96 ASSERT_NE(url_request, kInvalidResource);
98 // IsURLRequestInfo:
99 // Invalid / non-existent / non-URLRequestInfo resource -> false.
100 ASSERT_NE(PP_TRUE,
101 ppb_url_request_interface_->IsURLRequestInfo(kInvalidResource));
102 ASSERT_NE(PP_TRUE,
103 ppb_url_request_interface_->IsURLRequestInfo(kNotAResource));
105 PP_Resource url_loader =
106 ppb_url_loader_interface_->Create(instance_->pp_instance());
107 ASSERT_NE(kInvalidResource, url_loader);
109 ASSERT_NE(PP_TRUE, ppb_url_request_interface_->IsURLRequestInfo(url_loader));
110 ppb_url_loader_interface_->Close(url_loader);
111 ppb_core_interface_->ReleaseResource(url_loader);
113 // IsURLRequestInfo: Current URLRequestInfo resource -> true.
114 std::string error;
115 if (PP_FALSE == ppb_url_request_interface_->IsURLRequestInfo(url_request))
116 error = "IsURLRequestInfo() failed with a current URLRequestInfo resource";
118 // IsURLRequestInfo: Released URLRequestInfo resource -> false.
119 ppb_core_interface_->ReleaseResource(url_request);
120 ASSERT_NE(PP_TRUE, ppb_url_request_interface_->IsURLRequestInfo(url_request));
122 return error; // == PASS() if empty.
125 // Tests
126 // PP_Bool SetProperty(PP_Resource request,
127 // PP_URLRequestProperty property,
128 // struct PP_Var value);
129 std::string TestURLRequest::TestSetProperty() {
130 struct PropertyTestData {
131 PropertyTestData(PP_URLRequestProperty prop,
132 const std::string& name,
133 PP_Var value, PP_Bool expected) :
134 property(prop), property_name(name),
135 var(value), expected_value(expected) {
136 // var has ref count of 1 on creation.
138 PP_URLRequestProperty property;
139 std::string property_name;
140 PP_Var var; // Instance owner is responsible for releasing this var.
141 PP_Bool expected_value;
144 // All bool properties should accept PP_TRUE and PP_FALSE, while rejecting
145 // all other variable types.
146 #define TEST_BOOL(_name) \
147 PropertyTestData(ID_STR(_name), PP_MakeBool(PP_TRUE), PP_TRUE), \
148 PropertyTestData(ID_STR(_name), PP_MakeBool(PP_FALSE), PP_TRUE), \
149 PropertyTestData(ID_STR(_name), PP_MakeUndefined(), PP_FALSE), \
150 PropertyTestData(ID_STR(_name), PP_MakeNull(), PP_FALSE), \
151 PropertyTestData(ID_STR(_name), PP_MakeInt32(0), PP_FALSE), \
152 PropertyTestData(ID_STR(_name), PP_MakeDouble(0.0), PP_FALSE)
154 // These property types are always invalid for string properties.
155 #define TEST_STRING_INVALID(_name) \
156 PropertyTestData(ID_STR(_name), PP_MakeNull(), PP_FALSE), \
157 PropertyTestData(ID_STR(_name), PP_MakeBool(PP_FALSE), PP_FALSE), \
158 PropertyTestData(ID_STR(_name), PP_MakeInt32(0), PP_FALSE), \
159 PropertyTestData(ID_STR(_name), PP_MakeDouble(0.0), PP_FALSE)
161 #define TEST_INT_INVALID(_name) \
162 PropertyTestData(ID_STR(_name), PP_MakeUndefined(), PP_FALSE), \
163 PropertyTestData(ID_STR(_name), PP_MakeNull(), PP_FALSE), \
164 PropertyTestData(ID_STR(_name), PP_MakeBool(PP_FALSE), PP_FALSE), \
165 PropertyTestData(ID_STR(_name), PP_MakeString("notint"), PP_FALSE), \
166 PropertyTestData(ID_STR(_name), PP_MakeDouble(0.0), PP_FALSE)
168 // SetProperty accepts plenty of invalid values (malformed urls, negative
169 // thresholds, etc). Error checking is delayed until request opening (aka url
170 // loading).
171 #define ID_STR(arg) arg, #arg
172 PropertyTestData test_data[] = {
173 TEST_BOOL(PP_URLREQUESTPROPERTY_STREAMTOFILE),
174 TEST_BOOL(PP_URLREQUESTPROPERTY_FOLLOWREDIRECTS),
175 TEST_BOOL(PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS),
176 TEST_BOOL(PP_URLREQUESTPROPERTY_RECORDUPLOADPROGRESS),
177 TEST_BOOL(PP_URLREQUESTPROPERTY_ALLOWCROSSORIGINREQUESTS),
178 TEST_BOOL(PP_URLREQUESTPROPERTY_ALLOWCREDENTIALS),
179 TEST_STRING_INVALID(PP_URLREQUESTPROPERTY_URL),
180 TEST_STRING_INVALID(PP_URLREQUESTPROPERTY_METHOD),
181 TEST_STRING_INVALID(PP_URLREQUESTPROPERTY_HEADERS),
182 TEST_STRING_INVALID(PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL),
183 TEST_STRING_INVALID(PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING),
184 TEST_STRING_INVALID(PP_URLREQUESTPROPERTY_CUSTOMUSERAGENT),
185 TEST_INT_INVALID(PP_URLREQUESTPROPERTY_PREFETCHBUFFERUPPERTHRESHOLD),
186 TEST_INT_INVALID(PP_URLREQUESTPROPERTY_PREFETCHBUFFERLOWERTHRESHOLD),
187 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_URL),
188 PP_MakeString("http://www.google.com"), PP_TRUE),
189 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_URL),
190 PP_MakeString("foo.jpg"), PP_TRUE),
191 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_METHOD),
192 PP_MakeString("GET"), PP_TRUE),
193 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_METHOD),
194 PP_MakeString("POST"), PP_TRUE),
195 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_HEADERS),
196 PP_MakeString("Accept: text/plain"), PP_TRUE),
197 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_HEADERS),
198 PP_MakeString(""), PP_TRUE),
199 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL),
200 PP_MakeString("http://www.google.com"), PP_TRUE),
201 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL),
202 PP_MakeString(""), PP_TRUE),
203 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL),
204 PP_MakeUndefined(), PP_TRUE),
205 PropertyTestData(
206 ID_STR(PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING),
207 PP_MakeString("base64"), PP_TRUE),
208 PropertyTestData(
209 ID_STR(PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING),
210 PP_MakeString(""), PP_TRUE),
211 PropertyTestData(
212 ID_STR(PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING),
213 PP_MakeUndefined(), PP_TRUE),
214 PropertyTestData(
215 ID_STR(PP_URLREQUESTPROPERTY_CUSTOMUSERAGENT),
216 PP_MakeString("My Crazy Plugin"), PP_TRUE),
217 PropertyTestData(
218 ID_STR(PP_URLREQUESTPROPERTY_CUSTOMUSERAGENT),
219 PP_MakeString(""), PP_TRUE),
220 PropertyTestData(
221 ID_STR(PP_URLREQUESTPROPERTY_CUSTOMUSERAGENT),
222 PP_MakeUndefined(), PP_TRUE),
223 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_URL),
224 PP_MakeUndefined(), PP_FALSE),
225 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_METHOD),
226 PP_MakeUndefined(), PP_FALSE),
227 PropertyTestData(
228 ID_STR(PP_URLREQUESTPROPERTY_HEADERS),
229 PP_MakeString("Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA=="),
230 PP_TRUE),
231 PropertyTestData(
232 ID_STR(PP_URLREQUESTPROPERTY_HEADERS),
233 PP_MakeString("Accept-Encoding: *\n"
234 "Accept-Charset: iso-8859-5, unicode-1-1;q=0.8"),
235 PP_TRUE),
236 PropertyTestData(
237 ID_STR(PP_URLREQUESTPROPERTY_PREFETCHBUFFERUPPERTHRESHOLD),
238 PP_MakeInt32(0), PP_TRUE),
239 PropertyTestData(
240 ID_STR(PP_URLREQUESTPROPERTY_PREFETCHBUFFERUPPERTHRESHOLD),
241 PP_MakeInt32(100), PP_TRUE),
242 PropertyTestData(
243 ID_STR(PP_URLREQUESTPROPERTY_PREFETCHBUFFERLOWERTHRESHOLD),
244 PP_MakeInt32(0), PP_TRUE),
245 PropertyTestData(
246 ID_STR(PP_URLREQUESTPROPERTY_PREFETCHBUFFERLOWERTHRESHOLD),
247 PP_MakeInt32(100), PP_TRUE),
248 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_URL),
249 PP_MakeString("::::::::::::"), PP_TRUE),
250 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_METHOD),
251 PP_MakeString("INVALID"), PP_TRUE),
252 PropertyTestData(
253 ID_STR(PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING),
254 PP_MakeString("invalid"), PP_TRUE),
255 PropertyTestData(
256 ID_STR(PP_URLREQUESTPROPERTY_PREFETCHBUFFERUPPERTHRESHOLD),
257 PP_MakeInt32(-100), PP_TRUE),
258 PropertyTestData(
259 ID_STR(PP_URLREQUESTPROPERTY_PREFETCHBUFFERLOWERTHRESHOLD),
260 PP_MakeInt32(-100), PP_TRUE),
263 std::string error;
265 PP_Resource url_request = ppb_url_request_interface_->Create(
266 instance_->pp_instance());
267 if (url_request == kInvalidResource)
268 error = "Failed to create a URLRequestInfo";
270 // Loop over all test data even if we encountered an error to release vars.
271 for (size_t i = 0;
272 i < sizeof(test_data) / sizeof(test_data[0]);
273 ++i) {
274 if (error.empty() && test_data[i].expected_value !=
275 ppb_url_request_interface_->SetProperty(url_request,
276 test_data[i].property,
277 test_data[i].var)) {
278 pp::Var var(pp::Var::DontManage(), test_data[i].var);
279 error = std::string("Setting property ") +
280 test_data[i].property_name + " to " + var.DebugString() +
281 " did not return " + (test_data[i].expected_value ? "True" : "False");
282 error = test_data[i].property_name;
284 ppb_var_interface_->Release(test_data[i].var);
287 ppb_core_interface_->ReleaseResource(url_request);
288 return error; // == PASS() if empty.
291 std::string TestURLRequest::LoadAndCompareBody(
292 PP_Resource url_request, const std::string& expected_body) {
293 TestCompletionCallback callback(instance_->pp_instance(), PP_REQUIRED);
295 PP_Resource url_loader =
296 ppb_url_loader_interface_->Create(instance_->pp_instance());
297 ASSERT_NE(kInvalidResource, url_loader);
299 callback.WaitForResult(ppb_url_loader_interface_->Open(
300 url_loader, url_request,
301 callback.GetCallback().pp_completion_callback()));
302 CHECK_CALLBACK_BEHAVIOR(callback);
303 ASSERT_EQ(PP_OK, callback.result());
305 std::string error;
306 PP_Resource url_response =
307 ppb_url_loader_interface_->GetResponseInfo(url_loader);
308 if (url_response == kInvalidResource) {
309 error = "PPB_URLLoader::GetResponseInfo() returned invalid resource";
310 } else {
311 PP_Var status = ppb_url_response_interface_->GetProperty(
312 url_response, PP_URLRESPONSEPROPERTY_STATUSCODE);
313 if (status.type != PP_VARTYPE_INT32 && status.value.as_int != 200)
314 error = ReportError("PPB_URLLoader::Open() status", status.value.as_int);
316 std::string actual_body;
317 for (; error.empty();) { // Read the entire body in this loop.
318 const size_t kBufferSize = 32;
319 char buf[kBufferSize];
320 callback.WaitForResult(ppb_url_loader_interface_->ReadResponseBody(
321 url_loader, buf, kBufferSize,
322 callback.GetCallback().pp_completion_callback()));
323 if (callback.failed())
324 error.assign(callback.errors());
325 else if (callback.result() < PP_OK)
326 error.assign(ReportError("PPB_URLLoader::ReadResponseBody()",
327 callback.result()));
328 if (callback.result() <= PP_OK || callback.failed())
329 break;
330 actual_body.append(buf, callback.result());
332 if (actual_body != expected_body)
333 error = "PPB_URLLoader::ReadResponseBody() read unexpected response.";
335 ppb_core_interface_->ReleaseResource(url_response);
337 ppb_url_loader_interface_->Close(url_loader);
338 ppb_core_interface_->ReleaseResource(url_loader);
339 return error;
342 // Tests
343 // PP_Bool AppendDataToBody(
344 // PP_Resource request, const void* data, uint32_t len);
345 std::string TestURLRequest::TestAppendDataToBody() {
346 PP_Resource url_request = ppb_url_request_interface_->Create(
347 instance_->pp_instance());
348 ASSERT_NE(url_request, kInvalidResource);
350 std::string postdata("sample postdata");
351 PP_Var post_string_var = PP_MakeString("POST");
352 PP_Var echo_string_var = PP_MakeString("/echo");
354 // NULL pointer causes a crash. In general PPAPI implementation does not
355 // test for NULL because they are just a special case of bad pointers that
356 // are not detectable if set to point to an object that does not exist.
358 // Invalid resource should fail.
359 ASSERT_EQ(PP_FALSE, ppb_url_request_interface_->AppendDataToBody(
360 kInvalidResource, postdata.data(),
361 static_cast<uint32_t>(postdata.length())));
363 // Append data and POST to echoing web server.
364 ASSERT_EQ(PP_TRUE, ppb_url_request_interface_->SetProperty(
365 url_request, PP_URLREQUESTPROPERTY_METHOD, post_string_var));
366 ASSERT_EQ(PP_TRUE, ppb_url_request_interface_->SetProperty(
367 url_request, PP_URLREQUESTPROPERTY_URL, echo_string_var));
369 // Append data to body and verify the body is what we expect.
370 ASSERT_EQ(PP_TRUE, ppb_url_request_interface_->AppendDataToBody(
371 url_request, postdata.data(),
372 static_cast<uint32_t>(postdata.length())));
373 std::string error = LoadAndCompareBody(url_request, postdata);
375 ppb_var_interface_->Release(post_string_var);
376 ppb_var_interface_->Release(echo_string_var);
377 ppb_core_interface_->ReleaseResource(url_request);
378 return error; // == PASS() if empty.
381 std::string TestURLRequest::TestAppendFileToBody() {
382 PP_Resource url_request = ppb_url_request_interface_->Create(
383 instance_->pp_instance());
384 ASSERT_NE(url_request, kInvalidResource);
386 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
388 pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
389 callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
390 CHECK_CALLBACK_BEHAVIOR(callback);
391 ASSERT_EQ(PP_OK, callback.result());
393 pp::FileRef ref(file_system, "/test_file");
394 pp::FileIO io(instance_);
395 callback.WaitForResult(io.Open(ref,
396 PP_FILEOPENFLAG_CREATE | PP_FILEOPENFLAG_WRITE,
397 callback.GetCallback()));
398 CHECK_CALLBACK_BEHAVIOR(callback);
399 ASSERT_EQ(PP_OK, callback.result());
401 std::string append_data = "hello\n";
402 callback.WaitForResult(io.Write(0,
403 append_data.c_str(),
404 static_cast<int32_t>(append_data.size()),
405 callback.GetCallback()));
406 CHECK_CALLBACK_BEHAVIOR(callback);
407 ASSERT_EQ(static_cast<int32_t>(append_data.size()), callback.result());
409 PP_Var post_string_var = PP_MakeString("POST");
410 PP_Var echo_string_var = PP_MakeString("/echo");
412 // NULL pointer causes a crash. In general PPAPI implementation does not
413 // test for NULL because they are just a special case of bad pointers that
414 // are not detectable if set to point to an object that does not exist.
416 // Invalid resource should fail.
417 ASSERT_EQ(PP_FALSE, ppb_url_request_interface_->AppendFileToBody(
418 kInvalidResource, ref.pp_resource(), 0, -1, 0));
420 // Append data and POST to echoing web server.
421 ASSERT_EQ(PP_TRUE, ppb_url_request_interface_->SetProperty(
422 url_request, PP_URLREQUESTPROPERTY_METHOD, post_string_var));
423 ASSERT_EQ(PP_TRUE, ppb_url_request_interface_->SetProperty(
424 url_request, PP_URLREQUESTPROPERTY_URL, echo_string_var));
426 // Append file to body and verify the body is what we expect.
427 ASSERT_EQ(PP_TRUE, ppb_url_request_interface_->AppendFileToBody(
428 url_request, ref.pp_resource(), 0, -1, 0));
429 std::string error = LoadAndCompareBody(url_request, append_data);
431 ppb_var_interface_->Release(post_string_var);
432 ppb_var_interface_->Release(echo_string_var);
433 ppb_core_interface_->ReleaseResource(url_request);
434 return error; // == PASS() if empty.
437 // Allocates and manipulates a large number of resources.
438 std::string TestURLRequest::TestStress() {
439 const int kManyResources = 500;
440 PP_Resource url_request_info[kManyResources];
442 std::string error;
443 int num_created = kManyResources;
444 for (int i = 0; i < kManyResources; i++) {
445 url_request_info[i] = ppb_url_request_interface_->Create(
446 instance_->pp_instance());
447 if (url_request_info[i] == kInvalidResource) {
448 error = "Create() failed";
449 } else if (PP_FALSE == ppb_url_request_interface_->IsURLRequestInfo(
450 url_request_info[i])) {
451 error = "IsURLRequestInfo() failed";
452 } else if (PP_FALSE == ppb_url_request_interface_->SetProperty(
453 url_request_info[i],
454 PP_URLREQUESTPROPERTY_STREAMTOFILE,
455 PP_MakeBool(PP_FALSE))) {
456 error = "SetProperty() failed";
458 if (!error.empty()) {
459 num_created = i + 1;
460 break;
463 for (int i = 0; i < num_created; i++) {
464 ppb_core_interface_->ReleaseResource(url_request_info[i]);
465 if (PP_TRUE ==
466 ppb_url_request_interface_->IsURLRequestInfo(url_request_info[i]))
467 error = "IsURLREquestInfo() succeeded after release";
469 return error; // == PASS() if empty.