Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(473)

Side by Side Diff: ppapi/tests/test_file_mapping.cc

Issue 69663002: PPAPI: Implement PPB_FileMapping on POSIX (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix Windows build? Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 #include "ppapi/tests/test_file_mapping.h"
6
7 #include <string.h>
8
9 #include <limits>
10 #include <string>
11
12 #include "ppapi/c/pp_errors.h"
13 #include "ppapi/c/ppb_file_io.h"
14 #include "ppapi/c/ppb_file_mapping.h"
15 #include "ppapi/cpp/file_io.h"
16 #include "ppapi/cpp/file_ref.h"
17 #include "ppapi/cpp/file_system.h"
18 #include "ppapi/cpp/instance.h"
19 #include "ppapi/cpp/module.h"
20 #include "ppapi/tests/test_utils.h"
21
22 REGISTER_TEST_CASE(FileMapping);
23
24 namespace {
25
26 // TODO(dmichael): Move these to test_utils so we can share them?
27 int32_t ReadEntireFile(PP_Instance instance,
28 pp::FileIO* file_io,
29 int32_t offset,
30 std::string* data,
31 CallbackType callback_type) {
32 TestCompletionCallback callback(instance, callback_type);
33 char buf[256];
34 int32_t read_offset = offset;
35
36 for (;;) {
37 callback.WaitForResult(
38 file_io->Read(read_offset, buf, sizeof(buf), callback.GetCallback()));
39 if (callback.result() < 0)
40 return callback.result();
41 if (callback.result() == 0)
42 break;
43 read_offset += callback.result();
44 data->append(buf, callback.result());
45 }
46
47 return PP_OK;
48 }
49
50 int32_t WriteEntireBuffer(PP_Instance instance,
51 pp::FileIO* file_io,
52 int32_t offset,
53 const std::string& data,
54 CallbackType callback_type) {
55 TestCompletionCallback callback(instance, callback_type);
56 int32_t write_offset = offset;
57 const char* buf = data.c_str();
58 int32_t size = data.size();
59
60 while (write_offset < offset + size) {
61 callback.WaitForResult(file_io->Write(write_offset,
62 &buf[write_offset - offset],
63 size - write_offset + offset,
64 callback.GetCallback()));
65 if (callback.result() < 0)
66 return callback.result();
67 if (callback.result() == 0)
68 return PP_ERROR_FAILED;
69 write_offset += callback.result();
70 }
71 callback.WaitForResult(file_io->Flush(callback.GetCallback()));
72 return callback.result();
73 }
74
75 } // namespace
76
77 std::string TestFileMapping::MapAndCheckResults(uint32_t prot,
78 uint32_t flags) {
79 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
80
81 pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
82 pp::FileRef file_ref(file_system, "/mapped_file");
83
84 callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
85 ASSERT_EQ(PP_OK, callback.result());
86
87 const int64_t page_size =
88 file_mapping_if_->GetMapPageSize(instance_->pp_instance());
89 const int64_t kNumPages = 4;
90 // Make a string that's big enough that it spans all of the first |n-1| pages,
91 // plus a little bit of the |nth| page.
92 std::string file_contents((page_size * (kNumPages - 1)) + 128, 'a');
93
94 pp::FileIO file_io(instance_);
95 callback.WaitForResult(file_io.Open(file_ref,
96 PP_FILEOPENFLAG_CREATE |
97 PP_FILEOPENFLAG_TRUNCATE |
98 PP_FILEOPENFLAG_READ |
99 PP_FILEOPENFLAG_WRITE,
100 callback.GetCallback()));
101 ASSERT_EQ(PP_OK, callback.result());
102 ASSERT_EQ(PP_OK, WriteEntireBuffer(instance_->pp_instance(),
103 &file_io,
104 0,
105 file_contents,
106 callback_type()));
107
108 // TODO(dmichael): Use C++ interface.
109 void* address = NULL;
110 callback.WaitForResult(
111 file_mapping_if_->Map(
112 instance_->pp_instance(),
113 file_io.pp_resource(),
114 kNumPages * page_size,
115 prot,
116 flags,
117 0,
118 &address,
119 callback.GetCallback().pp_completion_callback()));
120 CHECK_CALLBACK_BEHAVIOR(callback);
121 ASSERT_EQ(PP_OK, callback.result());
122 ASSERT_NE(NULL, address);
123
124 if (prot & PP_FILEMAPPROTECTION_READ) {
125 // Make sure we can read.
126 std::string mapped_data(static_cast<char*>(address), file_contents.size());
127 // The initial data should match.
128 ASSERT_EQ(file_contents, mapped_data);
129
130 // Now write some data and flush it.
131 const std::string file_contents2(file_contents.size(), 'x');
132 ASSERT_EQ(PP_OK, WriteEntireBuffer(instance_->pp_instance(),
133 &file_io,
134 0,
135 file_contents2,
136 callback_type()));
137 // If the region was mapped SHARED, it should get updated.
138 std::string mapped_data2(static_cast<char*>(address), file_contents.size());
139 if (flags & PP_FILEMAPFLAG_SHARED)
140 ASSERT_EQ(file_contents2, mapped_data2);
141 // In POSIX, it is unspecified in the PRIVATE case whether changes to the
142 // file are visible to the mapped region. So we can't really test anything
143 // here in that case.
144 // FIXME(dmichael): Make sure our Pepper documentation reflects this.
145 }
146 if (prot & PP_FILEMAPPROTECTION_WRITE) {
147 std::string old_file_contents;
148 ASSERT_EQ(PP_OK, ReadEntireFile(instance_->pp_instance(),
149 &file_io,
150 0,
151 &old_file_contents,
152 callback_type()));
153 // Write something else to the mapped region, then unmap, and see if it
154 // gets written to the file. (Note we have to Unmap to make sure that the
155 // write is committed).
156 memset(address, 'y', file_contents.size());
157 // Note, we might not have read access to the mapped region here, so we
158 // make a string with the same contents without actually reading.
159 std::string mapped_data3(file_contents.size(), 'y');
160 callback.WaitForResult(
161 file_mapping_if_->Unmap(
162 instance_->pp_instance(), address, file_contents.size(),
163 callback.GetCallback().pp_completion_callback()));
164 CHECK_CALLBACK_BEHAVIOR(callback);
165 ASSERT_EQ(PP_OK, callback.result());
166 std::string new_file_contents;
167 ASSERT_EQ(PP_OK, ReadEntireFile(instance_->pp_instance(),
168 &file_io,
169 0,
170 &new_file_contents,
171 callback_type()));
172
173 // Sanity-check that the data we wrote isn't the same as what was already
174 // there, otherwise our test is invalid.
175 ASSERT_NE(mapped_data3, old_file_contents);
176 // If it's SHARED, the file should match what we wrote to the mapped region.
177 // Otherwise, it should not have changed.
178 if (flags & PP_FILEMAPFLAG_SHARED)
179 ASSERT_EQ(mapped_data3, new_file_contents);
180 else
181 ASSERT_EQ(old_file_contents, new_file_contents);
182 } else {
183 // We didn't do the "WRITE" test, but we still want to Unmap.
184 callback.WaitForResult(
185 file_mapping_if_->Unmap(
186 instance_->pp_instance(), address, file_contents.size(),
187 callback.GetCallback().pp_completion_callback()));
188 CHECK_CALLBACK_BEHAVIOR(callback);
189 ASSERT_EQ(PP_OK, callback.result());
190 }
191 PASS();
192 }
193
194 bool TestFileMapping::Init() {
195 // TODO(dmichael): Use unversioned string when this goes to stable?
196 file_mapping_if_ = static_cast<const PPB_FileMapping_0_1*>(
197 pp::Module::Get()->GetBrowserInterface(PPB_FILEMAPPING_INTERFACE_0_1));
198 return !!file_mapping_if_ && CheckTestingInterface() &&
199 EnsureRunningOverHTTP();
200 }
201
202 void TestFileMapping::RunTests(const std::string& filter) {
203 // TODO(dmichael): Tests to write:
204 // - Unmapping partial regions
205 // RUN_CALLBACK_TEST(TestFileMapping, BadParameters, filter);
206 RUN_CALLBACK_TEST(TestFileMapping, Map, filter);
207 }
208
209 std::string TestFileMapping::TestBadParameters() {
210 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
211
212 pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
213 pp::FileRef file_ref(file_system, "/mapped_file");
214
215 callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
216 ASSERT_EQ(PP_OK, callback.result());
217
218 const int64_t page_size =
219 file_mapping_if_->GetMapPageSize(instance_->pp_instance());
220 // const int64_t kNumPages = 4;
221 // Make a string that's big enough that it spans 3 pages, plus a little extra.
222 //std::string file_contents((page_size * (kNumPages - 1)) + 128, 'a');
223 std::string file_contents(page_size, 'a');
224
225 pp::FileIO file_io(instance_);
226 callback.WaitForResult(file_io.Open(file_ref,
227 PP_FILEOPENFLAG_CREATE |
228 PP_FILEOPENFLAG_TRUNCATE |
229 PP_FILEOPENFLAG_READ |
230 PP_FILEOPENFLAG_WRITE,
231 callback.GetCallback()));
232 ASSERT_EQ(PP_OK, callback.result());
233 ASSERT_EQ(PP_OK, WriteEntireBuffer(instance_->pp_instance(),
234 &file_io,
235 0,
236 file_contents,
237 callback_type()));
238
239 // Bad instance.
240 void* address = NULL;
241 callback.WaitForResult(
242 file_mapping_if_->Map(
243 PP_Instance(0xbadbad),
244 file_io.pp_resource(),
245 page_size,
246 PP_FILEMAPPROTECTION_READ,
247 PP_FILEMAPFLAG_PRIVATE,
248 0,
249 &address,
250 callback.GetCallback().pp_completion_callback()));
251 CHECK_CALLBACK_BEHAVIOR(callback);
252 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
253 ASSERT_EQ(NULL, address);
254
255 // Bad resource.
256 callback.WaitForResult(
257 file_mapping_if_->Map(
258 instance_->pp_instance(),
259 PP_Resource(0xbadbad),
260 page_size,
261 PP_FILEMAPPROTECTION_READ,
262 PP_FILEMAPFLAG_PRIVATE,
263 0,
264 &address,
265 callback.GetCallback().pp_completion_callback()));
266 CHECK_CALLBACK_BEHAVIOR(callback);
267 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
268 ASSERT_EQ(NULL, address);
269
270 // Length too big.
271 callback.WaitForResult(
272 file_mapping_if_->Map(
273 instance_->pp_instance(),
274 file_io.pp_resource(),
275 std::numeric_limits<int64_t>::max(),
276 PP_FILEMAPPROTECTION_READ,
277 PP_FILEMAPFLAG_PRIVATE,
278 0,
279 &address,
280 callback.GetCallback().pp_completion_callback()));
281 CHECK_CALLBACK_BEHAVIOR(callback);
282 ASSERT_EQ(PP_ERROR_NOMEMORY, callback.result());
283 ASSERT_EQ(NULL, address);
284
285 // Length too small.
286 callback.WaitForResult(
287 file_mapping_if_->Map(
288 instance_->pp_instance(),
289 file_io.pp_resource(),
290 -1,
291 PP_FILEMAPPROTECTION_READ,
292 PP_FILEMAPFLAG_PRIVATE,
293 0,
294 &address,
295 callback.GetCallback().pp_completion_callback()));
296 CHECK_CALLBACK_BEHAVIOR(callback);
297 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
298 ASSERT_EQ(NULL, address);
299 // TODO(dmichael): Check & test length that is not a multiple of page size???
300
301 // Bad protection.
302 callback.WaitForResult(
303 file_mapping_if_->Map(
304 instance_->pp_instance(),
305 file_io.pp_resource(),
306 page_size,
307 ~PP_FILEMAPPROTECTION_READ,
308 PP_FILEMAPFLAG_PRIVATE,
309 0,
310 &address,
311 callback.GetCallback().pp_completion_callback()));
312 CHECK_CALLBACK_BEHAVIOR(callback);
313 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
314 ASSERT_EQ(NULL, address);
315
316 // No flags.
317 callback.WaitForResult(
318 file_mapping_if_->Map(
319 instance_->pp_instance(),
320 file_io.pp_resource(),
321 page_size,
322 PP_FILEMAPPROTECTION_READ,
323 0,
324 0,
325 &address,
326 callback.GetCallback().pp_completion_callback()));
327 CHECK_CALLBACK_BEHAVIOR(callback);
328 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
329 ASSERT_EQ(NULL, address);
330
331 // Both flags.
332 callback.WaitForResult(
333 file_mapping_if_->Map(
334 instance_->pp_instance(),
335 file_io.pp_resource(),
336 page_size,
337 PP_FILEMAPPROTECTION_READ,
338 PP_FILEMAPFLAG_SHARED | PP_FILEMAPFLAG_PRIVATE,
339 0,
340 &address,
341 callback.GetCallback().pp_completion_callback()));
342 CHECK_CALLBACK_BEHAVIOR(callback);
343 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
344 ASSERT_EQ(NULL, address);
345
346 // Bad flags.
347 callback.WaitForResult(
348 file_mapping_if_->Map(
349 instance_->pp_instance(),
350 file_io.pp_resource(),
351 page_size,
352 PP_FILEMAPPROTECTION_READ,
353 ~PP_FILEMAPFLAG_SHARED,
354 0,
355 &address,
356 callback.GetCallback().pp_completion_callback()));
357 CHECK_CALLBACK_BEHAVIOR(callback);
358 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
359 ASSERT_EQ(NULL, address);
360
361 // Bad offset; not a multiple of page size.
362 callback.WaitForResult(
363 file_mapping_if_->Map(
364 instance_->pp_instance(),
365 file_io.pp_resource(),
366 page_size,
367 PP_FILEMAPPROTECTION_READ,
368 ~PP_FILEMAPFLAG_SHARED,
369 1,
370 &address,
371 callback.GetCallback().pp_completion_callback()));
372 CHECK_CALLBACK_BEHAVIOR(callback);
373 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
374 ASSERT_EQ(NULL, address);
375
376 // Unmap NULL.
377 callback.WaitForResult(
378 file_mapping_if_->Unmap(
379 instance_->pp_instance(),
380 NULL,
381 page_size,
382 callback.GetCallback().pp_completion_callback()));
383 CHECK_CALLBACK_BEHAVIOR(callback);
384 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
385
386 // Unmap bad address.
387 callback.WaitForResult(
388 file_mapping_if_->Unmap(
389 instance_->pp_instance(),
390 reinterpret_cast<const void*>(0xdeadbeef),
391 page_size,
392 callback.GetCallback().pp_completion_callback()));
393 CHECK_CALLBACK_BEHAVIOR(callback);
394 ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
395
396 PASS();
397 }
398
399 std::string TestFileMapping::TestMap() {
400 ASSERT_SUBTEST_SUCCESS(MapAndCheckResults(PP_FILEMAPPROTECTION_READ,
401 PP_FILEMAPFLAG_SHARED));
402 ASSERT_SUBTEST_SUCCESS(MapAndCheckResults(PP_FILEMAPPROTECTION_WRITE,
403 PP_FILEMAPFLAG_SHARED));
404 ASSERT_SUBTEST_SUCCESS(
405 MapAndCheckResults(PP_FILEMAPPROTECTION_WRITE | PP_FILEMAPPROTECTION_READ,
406 PP_FILEMAPFLAG_SHARED));
407 ASSERT_SUBTEST_SUCCESS(MapAndCheckResults(PP_FILEMAPPROTECTION_READ,
408 PP_FILEMAPFLAG_PRIVATE));
409 ASSERT_SUBTEST_SUCCESS(MapAndCheckResults(PP_FILEMAPPROTECTION_WRITE,
410 PP_FILEMAPFLAG_PRIVATE));
411 ASSERT_SUBTEST_SUCCESS(
412 MapAndCheckResults(PP_FILEMAPPROTECTION_WRITE | PP_FILEMAPPROTECTION_READ,
413 PP_FILEMAPFLAG_PRIVATE));
414 // FIXME(dmichael) How to test FIXED??
415 PASS();
416 }
417
418 std::string TestFileMapping::TestPartialRegions() {
419 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
420
421 pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
422 pp::FileRef file_ref1(file_system, "/mapped_file1");
423 pp::FileRef file_ref2(file_system, "/mapped_file2");
424
425 callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
426 ASSERT_EQ(PP_OK, callback.result());
427
428 const int64_t page_size =
429 file_mapping_if_->GetMapPageSize(instance_->pp_instance());
430 const int64_t kNumPages = 3;
431 std::string file_contents1(kNumPages * page_size, 'a');
432
433 pp::FileIO file_io1(instance_);
434 callback.WaitForResult(file_io1.Open(file_ref1,
435 PP_FILEOPENFLAG_CREATE |
436 PP_FILEOPENFLAG_TRUNCATE |
437 PP_FILEOPENFLAG_READ |
438 PP_FILEOPENFLAG_WRITE,
439 callback.GetCallback()));
440 ASSERT_EQ(PP_OK, callback.result());
441 ASSERT_EQ(PP_OK, WriteEntireBuffer(instance_->pp_instance(),
442 &file_io1,
443 0,
444 file_contents1,
445 callback_type()));
446
447 // TODO(dmichael): Use C++ interface.
448 void* address = NULL;
449 callback.WaitForResult(
450 file_mapping_if_->Map(
451 instance_->pp_instance(),
452 file_io1.pp_resource(),
453 kNumPages * page_size,
454 PP_FILEMAPPROTECTION_WRITE | PP_FILEMAPPROTECTION_READ,
455 PP_FILEMAPFLAG_SHARED,
456 0,
457 &address,
458 callback.GetCallback().pp_completion_callback()));
459 CHECK_CALLBACK_BEHAVIOR(callback);
460 ASSERT_EQ(PP_OK, callback.result());
461 ASSERT_NE(NULL, address);
462
463 // Unmap only the middle page.
464 void* address_of_middle_page =
465 reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(address) + page_size);
466 callback.WaitForResult(
467 file_mapping_if_->Unmap(
468 instance_->pp_instance(),
469 address_of_middle_page,
470 page_size,
471 callback.GetCallback().pp_completion_callback()));
472 CHECK_CALLBACK_BEHAVIOR(callback);
473 ASSERT_EQ(PP_OK, callback.result());
474
475 // Write another file, map it in to the middle hole that was left above.
476 pp::FileIO file_io2(instance_);
477 callback.WaitForResult(file_io2.Open(file_ref2,
478 PP_FILEOPENFLAG_CREATE |
479 PP_FILEOPENFLAG_TRUNCATE |
480 PP_FILEOPENFLAG_READ |
481 PP_FILEOPENFLAG_WRITE,
482 callback.GetCallback()));
483 ASSERT_EQ(PP_OK, callback.result());
484 // This second file will have 1 page worth of data.
485 std::string file_contents2(page_size, 'b');
486 ASSERT_EQ(PP_OK, WriteEntireBuffer(instance_->pp_instance(),
487 &file_io2,
488 0,
489 file_contents2,
490 callback_type()));
491 callback.WaitForResult(
492 file_mapping_if_->Map(
493 instance_->pp_instance(),
494 file_io2.pp_resource(),
495 page_size,
496 PP_FILEMAPPROTECTION_WRITE | PP_FILEMAPPROTECTION_READ,
497 PP_FILEMAPFLAG_SHARED | PP_FILEMAPFLAG_FIXED,
498 0,
499 &address_of_middle_page,
500 callback.GetCallback().pp_completion_callback()));
501 CHECK_CALLBACK_BEHAVIOR(callback);
502 ASSERT_EQ(PP_OK, callback.result());
503 PASS();
504
505 // Write something else to the mapped region, then unmap, and see if it
506 // gets written to both files. (Note we have to Unmap to make sure that the
507 // write is committed).
508 memset(address, 'c', kNumPages * page_size);
509 // TODO(dmichael): I'm actually unmapping two different files in one call.
510 // Seems like that should be OK, right?
511 callback.WaitForResult(
512 file_mapping_if_->Unmap(
513 instance_->pp_instance(), address, kNumPages * page_size,
514 callback.GetCallback().pp_completion_callback()));
515 CHECK_CALLBACK_BEHAVIOR(callback);
516 ASSERT_EQ(PP_OK, callback.result());
517 // The first and third page should have been written with 'c', but the
518 // second page should be untouched.
519 std::string expected_file_contents1 = std::string(page_size, 'c') +
520 std::string(page_size, 'a') +
521 std::string(page_size, 'c');
522 std::string new_file_contents1;
523 ASSERT_EQ(PP_OK, ReadEntireFile(instance_->pp_instance(),
524 &file_io1,
525 0,
526 &new_file_contents1,
527 callback_type()));
528 ASSERT_EQ(expected_file_contents1, new_file_contents1);
529
530 // The second file should have been entirely over-written.
531 std::string expected_file_contents2 = std::string(page_size, 'c');
532 std::string new_file_contents2;
533 ASSERT_EQ(PP_OK, ReadEntireFile(instance_->pp_instance(),
534 &file_io2,
535 0,
536 &new_file_contents2,
537 callback_type()));
538 ASSERT_EQ(expected_file_contents2, new_file_contents2);
539
540 // TODO(dmichael): Test non-zero offset
541 }
542
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698