Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / ppapi / tests / test_url_request.cc
blobfebc867d29664209787851a09bda7027c90eb741
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),
44 url_loader_(kInvalidResource) {
47 bool TestURLRequest::Init() {
48 ppb_url_request_interface_ = static_cast<const PPB_URLRequestInfo*>(
49 pp::Module::Get()->GetBrowserInterface(PPB_URLREQUESTINFO_INTERFACE));
50 ppb_url_loader_interface_ = static_cast<const PPB_URLLoader*>(
51 pp::Module::Get()->GetBrowserInterface(PPB_URLLOADER_INTERFACE));
52 ppb_url_response_interface_ = static_cast<const PPB_URLResponseInfo*>(
53 pp::Module::Get()->GetBrowserInterface(PPB_URLRESPONSEINFO_INTERFACE));
54 ppb_core_interface_ = static_cast<const PPB_Core*>(
55 pp::Module::Get()->GetBrowserInterface(PPB_CORE_INTERFACE));
56 ppb_var_interface_ = static_cast<const PPB_Var*>(
57 pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE));
58 if (!ppb_url_request_interface_)
59 instance_->AppendError("PPB_URLRequestInfo interface not available");
60 if (!ppb_url_response_interface_)
61 instance_->AppendError("PPB_URLResponseInfo interface not available");
62 if (!ppb_core_interface_)
63 instance_->AppendError("PPB_Core interface not available");
64 if (!ppb_var_interface_)
65 instance_->AppendError("PPB_Var interface not available");
66 if (!ppb_url_loader_interface_) {
67 instance_->AppendError("PPB_URLLoader interface not available");
68 } else {
69 url_loader_ = ppb_url_loader_interface_->Create(instance_->pp_instance());
70 if (url_loader_ == kInvalidResource)
71 instance_->AppendError("Failed to create URLLoader");
73 return EnsureRunningOverHTTP();
76 void TestURLRequest::RunTests(const std::string& filter) {
77 RUN_TEST(CreateAndIsURLRequestInfo, filter);
78 RUN_TEST(SetProperty, filter);
79 RUN_TEST(AppendDataToBody, filter);
80 RUN_TEST(AppendFileToBody, filter);
81 RUN_TEST(Stress, filter);
84 PP_Var TestURLRequest::PP_MakeString(const char* s) {
85 return ppb_var_interface_->VarFromUtf8(s, strlen(s));
88 // Tests
89 // PP_Resource Create(PP_Instance instance)
90 // PP_Bool IsURLRequestInfo(PP_Resource resource)
91 std::string TestURLRequest::TestCreateAndIsURLRequestInfo() {
92 // Create: Invalid / non-existent instance -> invalid resource.
93 ASSERT_EQ(ppb_url_request_interface_->Create(kInvalidInstance),
94 kInvalidResource);
95 ASSERT_EQ(ppb_url_request_interface_->Create(kNotAnInstance),
96 kInvalidResource);
98 // Create: Valid instance -> valid resource.
99 PP_Resource url_request = ppb_url_request_interface_->Create(
100 instance_->pp_instance());
101 ASSERT_NE(url_request, kInvalidResource);
103 // IsURLRequestInfo:
104 // Invalid / non-existent / non-URLRequestInfo resource -> false.
105 ASSERT_NE(PP_TRUE,
106 ppb_url_request_interface_->IsURLRequestInfo(kInvalidResource));
107 ASSERT_NE(PP_TRUE,
108 ppb_url_request_interface_->IsURLRequestInfo(kNotAResource));
109 ASSERT_NE(PP_TRUE, ppb_url_request_interface_->IsURLRequestInfo(url_loader_));
111 // IsURLRequestInfo: Current URLRequestInfo resource -> true.
112 std::string error;
113 if (PP_FALSE == ppb_url_request_interface_->IsURLRequestInfo(url_request))
114 error = "IsURLRequestInfo() failed with a current URLRequestInfo resource";
116 // IsURLRequestInfo: Released URLRequestInfo resource -> false.
117 ppb_core_interface_->ReleaseResource(url_request);
118 ASSERT_NE(PP_TRUE, ppb_url_request_interface_->IsURLRequestInfo(url_request));
120 return error; // == PASS() if empty.
123 // Tests
124 // PP_Bool SetProperty(PP_Resource request,
125 // PP_URLRequestProperty property,
126 // struct PP_Var value);
127 std::string TestURLRequest::TestSetProperty() {
128 struct PropertyTestData {
129 PropertyTestData(PP_URLRequestProperty prop,
130 const std::string& name,
131 PP_Var value, PP_Bool expected) :
132 property(prop), property_name(name),
133 var(value), expected_value(expected) {
134 // var has ref count of 1 on creation.
136 PP_URLRequestProperty property;
137 std::string property_name;
138 PP_Var var; // Instance owner is responsible for releasing this var.
139 PP_Bool expected_value;
142 // All bool properties should accept PP_TRUE and PP_FALSE, while rejecting
143 // all other variable types.
144 #define TEST_BOOL(_name) \
145 PropertyTestData(ID_STR(_name), PP_MakeBool(PP_TRUE), PP_TRUE), \
146 PropertyTestData(ID_STR(_name), PP_MakeBool(PP_FALSE), PP_TRUE), \
147 PropertyTestData(ID_STR(_name), PP_MakeUndefined(), PP_FALSE), \
148 PropertyTestData(ID_STR(_name), PP_MakeNull(), PP_FALSE), \
149 PropertyTestData(ID_STR(_name), PP_MakeInt32(0), PP_FALSE), \
150 PropertyTestData(ID_STR(_name), PP_MakeDouble(0.0), PP_FALSE)
152 // These property types are always invalid for string properties.
153 #define TEST_STRING_INVALID(_name) \
154 PropertyTestData(ID_STR(_name), PP_MakeNull(), PP_FALSE), \
155 PropertyTestData(ID_STR(_name), PP_MakeBool(PP_FALSE), PP_FALSE), \
156 PropertyTestData(ID_STR(_name), PP_MakeInt32(0), PP_FALSE), \
157 PropertyTestData(ID_STR(_name), PP_MakeDouble(0.0), PP_FALSE)
159 #define TEST_INT_INVALID(_name) \
160 PropertyTestData(ID_STR(_name), PP_MakeUndefined(), PP_FALSE), \
161 PropertyTestData(ID_STR(_name), PP_MakeNull(), PP_FALSE), \
162 PropertyTestData(ID_STR(_name), PP_MakeBool(PP_FALSE), PP_FALSE), \
163 PropertyTestData(ID_STR(_name), PP_MakeString("notint"), PP_FALSE), \
164 PropertyTestData(ID_STR(_name), PP_MakeDouble(0.0), PP_FALSE)
166 // SetProperty accepts plenty of invalid values (malformed urls, negative
167 // thresholds, etc). Error checking is delayed until request opening (aka url
168 // loading).
169 #define ID_STR(arg) arg, #arg
170 PropertyTestData test_data[] = {
171 TEST_BOOL(PP_URLREQUESTPROPERTY_STREAMTOFILE),
172 TEST_BOOL(PP_URLREQUESTPROPERTY_FOLLOWREDIRECTS),
173 TEST_BOOL(PP_URLREQUESTPROPERTY_RECORDDOWNLOADPROGRESS),
174 TEST_BOOL(PP_URLREQUESTPROPERTY_RECORDUPLOADPROGRESS),
175 TEST_BOOL(PP_URLREQUESTPROPERTY_ALLOWCROSSORIGINREQUESTS),
176 TEST_BOOL(PP_URLREQUESTPROPERTY_ALLOWCREDENTIALS),
177 TEST_STRING_INVALID(PP_URLREQUESTPROPERTY_URL),
178 TEST_STRING_INVALID(PP_URLREQUESTPROPERTY_METHOD),
179 TEST_STRING_INVALID(PP_URLREQUESTPROPERTY_HEADERS),
180 TEST_STRING_INVALID(PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL),
181 TEST_STRING_INVALID(PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING),
182 TEST_STRING_INVALID(PP_URLREQUESTPROPERTY_CUSTOMUSERAGENT),
183 TEST_INT_INVALID(PP_URLREQUESTPROPERTY_PREFETCHBUFFERUPPERTHRESHOLD),
184 TEST_INT_INVALID(PP_URLREQUESTPROPERTY_PREFETCHBUFFERLOWERTHRESHOLD),
185 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_URL),
186 PP_MakeString("http://www.google.com"), PP_TRUE),
187 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_URL),
188 PP_MakeString("foo.jpg"), PP_TRUE),
189 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_METHOD),
190 PP_MakeString("GET"), PP_TRUE),
191 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_METHOD),
192 PP_MakeString("POST"), PP_TRUE),
193 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_HEADERS),
194 PP_MakeString("Accept: text/plain"), PP_TRUE),
195 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_HEADERS),
196 PP_MakeString(""), PP_TRUE),
197 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL),
198 PP_MakeString("http://www.google.com"), PP_TRUE),
199 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL),
200 PP_MakeString(""), PP_TRUE),
201 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_CUSTOMREFERRERURL),
202 PP_MakeUndefined(), PP_TRUE),
203 PropertyTestData(
204 ID_STR(PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING),
205 PP_MakeString("base64"), PP_TRUE),
206 PropertyTestData(
207 ID_STR(PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING),
208 PP_MakeString(""), PP_TRUE),
209 PropertyTestData(
210 ID_STR(PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING),
211 PP_MakeUndefined(), PP_TRUE),
212 PropertyTestData(
213 ID_STR(PP_URLREQUESTPROPERTY_CUSTOMUSERAGENT),
214 PP_MakeString("My Crazy Plugin"), PP_TRUE),
215 PropertyTestData(
216 ID_STR(PP_URLREQUESTPROPERTY_CUSTOMUSERAGENT),
217 PP_MakeString(""), PP_TRUE),
218 PropertyTestData(
219 ID_STR(PP_URLREQUESTPROPERTY_CUSTOMUSERAGENT),
220 PP_MakeUndefined(), PP_TRUE),
221 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_URL),
222 PP_MakeUndefined(), PP_FALSE),
223 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_METHOD),
224 PP_MakeUndefined(), PP_FALSE),
225 PropertyTestData(
226 ID_STR(PP_URLREQUESTPROPERTY_HEADERS),
227 PP_MakeString("Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA=="),
228 PP_TRUE),
229 PropertyTestData(
230 ID_STR(PP_URLREQUESTPROPERTY_HEADERS),
231 PP_MakeString("Accept-Encoding: *\n"
232 "Accept-Charset: iso-8859-5, unicode-1-1;q=0.8"),
233 PP_TRUE),
234 PropertyTestData(
235 ID_STR(PP_URLREQUESTPROPERTY_PREFETCHBUFFERUPPERTHRESHOLD),
236 PP_MakeInt32(0), PP_TRUE),
237 PropertyTestData(
238 ID_STR(PP_URLREQUESTPROPERTY_PREFETCHBUFFERUPPERTHRESHOLD),
239 PP_MakeInt32(100), PP_TRUE),
240 PropertyTestData(
241 ID_STR(PP_URLREQUESTPROPERTY_PREFETCHBUFFERLOWERTHRESHOLD),
242 PP_MakeInt32(0), PP_TRUE),
243 PropertyTestData(
244 ID_STR(PP_URLREQUESTPROPERTY_PREFETCHBUFFERLOWERTHRESHOLD),
245 PP_MakeInt32(100), PP_TRUE),
246 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_URL),
247 PP_MakeString("::::::::::::"), PP_TRUE),
248 PropertyTestData(ID_STR(PP_URLREQUESTPROPERTY_METHOD),
249 PP_MakeString("INVALID"), PP_TRUE),
250 PropertyTestData(
251 ID_STR(PP_URLREQUESTPROPERTY_CUSTOMCONTENTTRANSFERENCODING),
252 PP_MakeString("invalid"), PP_TRUE),
253 PropertyTestData(
254 ID_STR(PP_URLREQUESTPROPERTY_PREFETCHBUFFERUPPERTHRESHOLD),
255 PP_MakeInt32(-100), PP_TRUE),
256 PropertyTestData(
257 ID_STR(PP_URLREQUESTPROPERTY_PREFETCHBUFFERLOWERTHRESHOLD),
258 PP_MakeInt32(-100), PP_TRUE),
261 std::string error;
263 PP_Resource url_request = ppb_url_request_interface_->Create(
264 instance_->pp_instance());
265 if (url_request == kInvalidResource)
266 error = "Failed to create a URLRequestInfo";
268 // Loop over all test data even if we encountered an error to release vars.
269 for (size_t i = 0;
270 i < sizeof(test_data) / sizeof(test_data[0]);
271 ++i) {
272 if (error.empty() && test_data[i].expected_value !=
273 ppb_url_request_interface_->SetProperty(url_request,
274 test_data[i].property,
275 test_data[i].var)) {
276 pp::Var var(pp::Var::DontManage(), test_data[i].var);
277 error = std::string("Setting property ") +
278 test_data[i].property_name + " to " + var.DebugString() +
279 " did not return " + (test_data[i].expected_value ? "True" : "False");
280 error = test_data[i].property_name;
282 ppb_var_interface_->Release(test_data[i].var);
285 ppb_core_interface_->ReleaseResource(url_request);
286 return error; // == PASS() if empty.
289 std::string TestURLRequest::LoadAndCompareBody(
290 PP_Resource url_request, const std::string& expected_body) {
291 TestCompletionCallback callback(instance_->pp_instance(), PP_REQUIRED);
292 callback.WaitForResult(ppb_url_loader_interface_->Open(
293 url_loader_, url_request,
294 callback.GetCallback().pp_completion_callback()));
295 CHECK_CALLBACK_BEHAVIOR(callback);
296 ASSERT_EQ(PP_OK, callback.result());
298 std::string error;
299 PP_Resource url_response =
300 ppb_url_loader_interface_->GetResponseInfo(url_loader_);
301 if (url_response == kInvalidResource) {
302 error = "PPB_URLLoader::GetResponseInfo() returned invalid resource";
303 } else {
304 PP_Var status = ppb_url_response_interface_->GetProperty(
305 url_response, PP_URLRESPONSEPROPERTY_STATUSCODE);
306 if (status.type != PP_VARTYPE_INT32 && status.value.as_int != 200)
307 error = ReportError("PPB_URLLoader::Open() status", status.value.as_int);
309 std::string actual_body;
310 for (; error.empty();) { // Read the entire body in this loop.
311 const size_t kBufferSize = 32;
312 char buf[kBufferSize];
313 callback.WaitForResult(ppb_url_loader_interface_->ReadResponseBody(
314 url_loader_, buf, kBufferSize,
315 callback.GetCallback().pp_completion_callback()));
316 if (callback.failed())
317 error.assign(callback.errors());
318 else if (callback.result() < PP_OK)
319 error.assign(ReportError("PPB_URLLoader::ReadResponseBody()",
320 callback.result()));
321 if (callback.result() <= PP_OK || callback.failed())
322 break;
323 actual_body.append(buf, callback.result());
325 if (actual_body != expected_body)
326 error = "PPB_URLLoader::ReadResponseBody() read unexpected response.";
328 ppb_core_interface_->ReleaseResource(url_response);
330 ppb_url_loader_interface_->Close(url_loader_);
331 return error;
334 // Tests
335 // PP_Bool AppendDataToBody(
336 // PP_Resource request, const void* data, uint32_t len);
337 std::string TestURLRequest::TestAppendDataToBody() {
338 PP_Resource url_request = ppb_url_request_interface_->Create(
339 instance_->pp_instance());
340 ASSERT_NE(url_request, kInvalidResource);
342 std::string postdata("sample postdata");
343 PP_Var post_string_var = PP_MakeString("POST");
344 PP_Var echo_string_var = PP_MakeString("/echo");
346 // NULL pointer causes a crash. In general PPAPI implementation does not
347 // test for NULL because they are just a special case of bad pointers that
348 // are not detectable if set to point to an object that does not exist.
350 // Invalid resource should fail.
351 ASSERT_EQ(PP_FALSE, ppb_url_request_interface_->AppendDataToBody(
352 kInvalidResource, postdata.data(), postdata.length()));
354 // Append data and POST to echoing web server.
355 ASSERT_EQ(PP_TRUE, ppb_url_request_interface_->SetProperty(
356 url_request, PP_URLREQUESTPROPERTY_METHOD, post_string_var));
357 ASSERT_EQ(PP_TRUE, ppb_url_request_interface_->SetProperty(
358 url_request, PP_URLREQUESTPROPERTY_URL, echo_string_var));
360 // Append data to body and verify the body is what we expect.
361 ASSERT_EQ(PP_TRUE, ppb_url_request_interface_->AppendDataToBody(
362 url_request, postdata.data(), postdata.length()));
363 std::string error = LoadAndCompareBody(url_request, postdata);
365 ppb_var_interface_->Release(post_string_var);
366 ppb_var_interface_->Release(echo_string_var);
367 ppb_core_interface_->ReleaseResource(url_request);
368 return error; // == PASS() if empty.
371 std::string TestURLRequest::TestAppendFileToBody() {
372 PP_Resource url_request = ppb_url_request_interface_->Create(
373 instance_->pp_instance());
374 ASSERT_NE(url_request, kInvalidResource);
376 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
378 pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
379 callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
380 CHECK_CALLBACK_BEHAVIOR(callback);
381 ASSERT_EQ(PP_OK, callback.result());
383 pp::FileRef ref(file_system, "/test_file");
384 pp::FileIO io(instance_);
385 callback.WaitForResult(io.Open(ref,
386 PP_FILEOPENFLAG_CREATE | PP_FILEOPENFLAG_WRITE,
387 callback.GetCallback()));
388 CHECK_CALLBACK_BEHAVIOR(callback);
389 ASSERT_EQ(PP_OK, callback.result());
391 std::string append_data = "hello\n";
392 callback.WaitForResult(io.Write(0,
393 append_data.c_str(),
394 append_data.size(),
395 callback.GetCallback()));
396 CHECK_CALLBACK_BEHAVIOR(callback);
397 ASSERT_EQ(static_cast<int32_t>(append_data.size()), callback.result());
399 PP_Var post_string_var = PP_MakeString("POST");
400 PP_Var echo_string_var = PP_MakeString("/echo");
402 // NULL pointer causes a crash. In general PPAPI implementation does not
403 // test for NULL because they are just a special case of bad pointers that
404 // are not detectable if set to point to an object that does not exist.
406 // Invalid resource should fail.
407 ASSERT_EQ(PP_FALSE, ppb_url_request_interface_->AppendFileToBody(
408 kInvalidResource, ref.pp_resource(), 0, -1, 0));
410 // Append data and POST to echoing web server.
411 ASSERT_EQ(PP_TRUE, ppb_url_request_interface_->SetProperty(
412 url_request, PP_URLREQUESTPROPERTY_METHOD, post_string_var));
413 ASSERT_EQ(PP_TRUE, ppb_url_request_interface_->SetProperty(
414 url_request, PP_URLREQUESTPROPERTY_URL, echo_string_var));
416 // Append file to body and verify the body is what we expect.
417 ASSERT_EQ(PP_TRUE, ppb_url_request_interface_->AppendFileToBody(
418 url_request, ref.pp_resource(), 0, -1, 0));
419 std::string error = LoadAndCompareBody(url_request, append_data);
421 ppb_var_interface_->Release(post_string_var);
422 ppb_var_interface_->Release(echo_string_var);
423 ppb_core_interface_->ReleaseResource(url_request);
424 return error; // == PASS() if empty.
427 // Allocates and manipulates a large number of resources.
428 std::string TestURLRequest::TestStress() {
429 const int kManyResources = 500;
430 PP_Resource url_request_info[kManyResources];
432 std::string error;
433 int num_created = kManyResources;
434 for (int i = 0; i < kManyResources; i++) {
435 url_request_info[i] = ppb_url_request_interface_->Create(
436 instance_->pp_instance());
437 if (url_request_info[i] == kInvalidResource) {
438 error = "Create() failed";
439 } else if (PP_FALSE == ppb_url_request_interface_->IsURLRequestInfo(
440 url_request_info[i])) {
441 error = "IsURLRequestInfo() failed";
442 } else if (PP_FALSE == ppb_url_request_interface_->SetProperty(
443 url_request_info[i],
444 PP_URLREQUESTPROPERTY_STREAMTOFILE,
445 PP_MakeBool(PP_FALSE))) {
446 error = "SetProperty() failed";
448 if (!error.empty()) {
449 num_created = i + 1;
450 break;
453 for (int i = 0; i < num_created; i++) {
454 ppb_core_interface_->ReleaseResource(url_request_info[i]);
455 if (PP_TRUE ==
456 ppb_url_request_interface_->IsURLRequestInfo(url_request_info[i]))
457 error = "IsURLREquestInfo() succeeded after release";
459 return error; // == PASS() if empty.