Move StartsWith[ASCII] to base namespace.
[chromium-blink-merge.git] / components / filesystem / file_impl_unittest.cc
blobc55e51660b7dcb8aaf94297cc383caaa85c8d67a
1 // Copyright 2015 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 #include <vector>
7 #include "base/files/file.h"
8 #include "components/filesystem/files_test_base.h"
9 #include "mojo/platform_handle/platform_handle_functions.h"
10 #include "mojo/public/cpp/bindings/interface_request.h"
11 #include "mojo/public/cpp/bindings/type_converter.h"
13 namespace filesystem {
14 namespace {
16 using FileImplTest = FilesTestBase;
18 TEST_F(FileImplTest, CreateWriteCloseRenameOpenRead) {
19 DirectoryPtr directory;
20 GetTemporaryRoot(&directory);
21 FileError error;
24 // Create my_file.
25 FilePtr file;
26 error = FILE_ERROR_FAILED;
27 directory->OpenFile("my_file", GetProxy(&file), kFlagWrite | kFlagCreate,
28 Capture(&error));
29 ASSERT_TRUE(directory.WaitForIncomingResponse());
30 EXPECT_EQ(FILE_ERROR_OK, error);
32 // Write to it.
33 std::vector<uint8_t> bytes_to_write;
34 bytes_to_write.push_back(static_cast<uint8_t>('h'));
35 bytes_to_write.push_back(static_cast<uint8_t>('e'));
36 bytes_to_write.push_back(static_cast<uint8_t>('l'));
37 bytes_to_write.push_back(static_cast<uint8_t>('l'));
38 bytes_to_write.push_back(static_cast<uint8_t>('o'));
39 error = FILE_ERROR_FAILED;
40 uint32_t num_bytes_written = 0;
41 file->Write(mojo::Array<uint8_t>::From(bytes_to_write), 0,
42 WHENCE_FROM_CURRENT, Capture(&error, &num_bytes_written));
43 ASSERT_TRUE(file.WaitForIncomingResponse());
44 EXPECT_EQ(FILE_ERROR_OK, error);
45 EXPECT_EQ(bytes_to_write.size(), num_bytes_written);
47 // Close it.
48 error = FILE_ERROR_FAILED;
49 file->Close(Capture(&error));
50 ASSERT_TRUE(file.WaitForIncomingResponse());
51 EXPECT_EQ(FILE_ERROR_OK, error);
54 // Rename it.
55 error = FILE_ERROR_FAILED;
56 directory->Rename("my_file", "your_file", Capture(&error));
57 ASSERT_TRUE(directory.WaitForIncomingResponse());
58 EXPECT_EQ(FILE_ERROR_OK, error);
61 // Open my_file again.
62 FilePtr file;
63 error = FILE_ERROR_FAILED;
64 directory->OpenFile("your_file", GetProxy(&file), kFlagRead | kFlagOpen,
65 Capture(&error));
66 ASSERT_TRUE(directory.WaitForIncomingResponse());
67 EXPECT_EQ(FILE_ERROR_OK, error);
69 // Read from it.
70 mojo::Array<uint8_t> bytes_read;
71 error = FILE_ERROR_FAILED;
72 file->Read(3, 1, WHENCE_FROM_BEGIN, Capture(&error, &bytes_read));
73 ASSERT_TRUE(file.WaitForIncomingResponse());
74 EXPECT_EQ(FILE_ERROR_OK, error);
75 ASSERT_EQ(3u, bytes_read.size());
76 EXPECT_EQ(static_cast<uint8_t>('e'), bytes_read[0]);
77 EXPECT_EQ(static_cast<uint8_t>('l'), bytes_read[1]);
78 EXPECT_EQ(static_cast<uint8_t>('l'), bytes_read[2]);
81 // TODO(vtl): Test read/write offset options.
84 TEST_F(FileImplTest, CantWriteInReadMode) {
85 DirectoryPtr directory;
86 GetTemporaryRoot(&directory);
87 FileError error;
89 std::vector<uint8_t> bytes_to_write;
90 bytes_to_write.push_back(static_cast<uint8_t>('h'));
91 bytes_to_write.push_back(static_cast<uint8_t>('e'));
92 bytes_to_write.push_back(static_cast<uint8_t>('l'));
93 bytes_to_write.push_back(static_cast<uint8_t>('l'));
94 bytes_to_write.push_back(static_cast<uint8_t>('o'));
97 // Create my_file.
98 FilePtr file;
99 error = FILE_ERROR_FAILED;
100 directory->OpenFile("my_file", GetProxy(&file), kFlagWrite | kFlagCreate,
101 Capture(&error));
102 ASSERT_TRUE(directory.WaitForIncomingResponse());
103 EXPECT_EQ(FILE_ERROR_OK, error);
105 // Write to it.
106 error = FILE_ERROR_FAILED;
107 uint32_t num_bytes_written = 0;
108 file->Write(mojo::Array<uint8_t>::From(bytes_to_write), 0,
109 WHENCE_FROM_CURRENT, Capture(&error, &num_bytes_written));
110 ASSERT_TRUE(file.WaitForIncomingResponse());
111 EXPECT_EQ(FILE_ERROR_OK, error);
112 EXPECT_EQ(bytes_to_write.size(), num_bytes_written);
114 // Close it.
115 error = FILE_ERROR_FAILED;
116 file->Close(Capture(&error));
117 ASSERT_TRUE(file.WaitForIncomingResponse());
118 EXPECT_EQ(FILE_ERROR_OK, error);
122 // Open my_file again, this time with read only mode.
123 FilePtr file;
124 error = FILE_ERROR_FAILED;
125 directory->OpenFile("my_file", GetProxy(&file), kFlagRead | kFlagOpen,
126 Capture(&error));
127 ASSERT_TRUE(directory.WaitForIncomingResponse());
128 EXPECT_EQ(FILE_ERROR_OK, error);
130 // Try to write in read mode; it should fail.
131 error = FILE_ERROR_OK;
132 uint32_t num_bytes_written = 0;
133 file->Write(mojo::Array<uint8_t>::From(bytes_to_write), 0,
134 WHENCE_FROM_CURRENT, Capture(&error, &num_bytes_written));
136 ASSERT_TRUE(file.WaitForIncomingResponse());
137 EXPECT_EQ(FILE_ERROR_FAILED, error);
138 EXPECT_EQ(0u, num_bytes_written);
140 // Close it.
141 error = FILE_ERROR_FAILED;
142 file->Close(Capture(&error));
143 ASSERT_TRUE(file.WaitForIncomingResponse());
144 EXPECT_EQ(FILE_ERROR_OK, error);
148 TEST_F(FileImplTest, OpenInAppendMode) {
149 DirectoryPtr directory;
150 GetTemporaryRoot(&directory);
151 FileError error;
154 // Create my_file.
155 FilePtr file;
156 error = FILE_ERROR_FAILED;
157 directory->OpenFile("my_file", GetProxy(&file), kFlagWrite | kFlagCreate,
158 Capture(&error));
159 ASSERT_TRUE(directory.WaitForIncomingResponse());
160 EXPECT_EQ(FILE_ERROR_OK, error);
162 // Write to it.
163 std::vector<uint8_t> bytes_to_write;
164 bytes_to_write.push_back(static_cast<uint8_t>('h'));
165 bytes_to_write.push_back(static_cast<uint8_t>('e'));
166 bytes_to_write.push_back(static_cast<uint8_t>('l'));
167 bytes_to_write.push_back(static_cast<uint8_t>('l'));
168 bytes_to_write.push_back(static_cast<uint8_t>('o'));
169 error = FILE_ERROR_FAILED;
170 uint32_t num_bytes_written = 0;
171 file->Write(mojo::Array<uint8_t>::From(bytes_to_write), 0,
172 WHENCE_FROM_CURRENT, Capture(&error, &num_bytes_written));
173 ASSERT_TRUE(file.WaitForIncomingResponse());
174 EXPECT_EQ(FILE_ERROR_OK, error);
175 EXPECT_EQ(bytes_to_write.size(), num_bytes_written);
177 // Close it.
178 error = FILE_ERROR_FAILED;
179 file->Close(Capture(&error));
180 ASSERT_TRUE(file.WaitForIncomingResponse());
181 EXPECT_EQ(FILE_ERROR_OK, error);
185 // Append to my_file.
186 FilePtr file;
187 error = FILE_ERROR_FAILED;
188 directory->OpenFile("my_file", GetProxy(&file), kFlagAppend | kFlagOpen,
189 Capture(&error));
190 ASSERT_TRUE(directory.WaitForIncomingResponse());
191 EXPECT_EQ(FILE_ERROR_OK, error);
193 // Write to it.
194 std::vector<uint8_t> bytes_to_write;
195 bytes_to_write.push_back(static_cast<uint8_t>('g'));
196 bytes_to_write.push_back(static_cast<uint8_t>('o'));
197 bytes_to_write.push_back(static_cast<uint8_t>('o'));
198 bytes_to_write.push_back(static_cast<uint8_t>('d'));
199 bytes_to_write.push_back(static_cast<uint8_t>('b'));
200 bytes_to_write.push_back(static_cast<uint8_t>('y'));
201 bytes_to_write.push_back(static_cast<uint8_t>('e'));
202 error = FILE_ERROR_FAILED;
203 uint32_t num_bytes_written = 0;
204 file->Write(mojo::Array<uint8_t>::From(bytes_to_write), 0,
205 WHENCE_FROM_CURRENT, Capture(&error, &num_bytes_written));
206 ASSERT_TRUE(file.WaitForIncomingResponse());
207 EXPECT_EQ(FILE_ERROR_OK, error);
208 EXPECT_EQ(bytes_to_write.size(), num_bytes_written);
210 // Close it.
211 error = FILE_ERROR_FAILED;
212 file->Close(Capture(&error));
213 ASSERT_TRUE(file.WaitForIncomingResponse());
214 EXPECT_EQ(FILE_ERROR_OK, error);
218 // Open my_file again.
219 FilePtr file;
220 error = FILE_ERROR_FAILED;
221 directory->OpenFile("my_file", GetProxy(&file), kFlagRead | kFlagOpen,
222 Capture(&error));
223 ASSERT_TRUE(directory.WaitForIncomingResponse());
224 EXPECT_EQ(FILE_ERROR_OK, error);
226 // Read from it.
227 mojo::Array<uint8_t> bytes_read;
228 error = FILE_ERROR_FAILED;
229 file->Read(12, 0, WHENCE_FROM_BEGIN, Capture(&error, &bytes_read));
230 ASSERT_TRUE(file.WaitForIncomingResponse());
231 EXPECT_EQ(FILE_ERROR_OK, error);
232 ASSERT_EQ(12u, bytes_read.size());
233 EXPECT_EQ(static_cast<uint8_t>('l'), bytes_read[3]);
234 EXPECT_EQ(static_cast<uint8_t>('o'), bytes_read[4]);
235 EXPECT_EQ(static_cast<uint8_t>('g'), bytes_read[5]);
236 EXPECT_EQ(static_cast<uint8_t>('o'), bytes_read[6]);
240 TEST_F(FileImplTest, OpenInTruncateMode) {
241 DirectoryPtr directory;
242 GetTemporaryRoot(&directory);
243 FileError error;
246 // Create my_file.
247 FilePtr file;
248 error = FILE_ERROR_FAILED;
249 directory->OpenFile("my_file", GetProxy(&file), kFlagWrite | kFlagCreate,
250 Capture(&error));
251 ASSERT_TRUE(directory.WaitForIncomingResponse());
252 EXPECT_EQ(FILE_ERROR_OK, error);
254 // Write to it.
255 std::vector<uint8_t> bytes_to_write;
256 bytes_to_write.push_back(static_cast<uint8_t>('h'));
257 bytes_to_write.push_back(static_cast<uint8_t>('e'));
258 bytes_to_write.push_back(static_cast<uint8_t>('l'));
259 bytes_to_write.push_back(static_cast<uint8_t>('l'));
260 bytes_to_write.push_back(static_cast<uint8_t>('o'));
261 error = FILE_ERROR_FAILED;
262 uint32_t num_bytes_written = 0;
263 file->Write(mojo::Array<uint8_t>::From(bytes_to_write), 0,
264 WHENCE_FROM_CURRENT, Capture(&error, &num_bytes_written));
265 ASSERT_TRUE(file.WaitForIncomingResponse());
266 EXPECT_EQ(FILE_ERROR_OK, error);
267 EXPECT_EQ(bytes_to_write.size(), num_bytes_written);
269 // Close it.
270 error = FILE_ERROR_FAILED;
271 file->Close(Capture(&error));
272 ASSERT_TRUE(file.WaitForIncomingResponse());
273 EXPECT_EQ(FILE_ERROR_OK, error);
277 // Append to my_file.
278 FilePtr file;
279 error = FILE_ERROR_FAILED;
280 directory->OpenFile("my_file", GetProxy(&file),
281 kFlagWrite | kFlagOpenTruncated, Capture(&error));
282 ASSERT_TRUE(directory.WaitForIncomingResponse());
283 EXPECT_EQ(FILE_ERROR_OK, error);
285 // Write to it.
286 std::vector<uint8_t> bytes_to_write;
287 bytes_to_write.push_back(static_cast<uint8_t>('g'));
288 bytes_to_write.push_back(static_cast<uint8_t>('o'));
289 bytes_to_write.push_back(static_cast<uint8_t>('o'));
290 bytes_to_write.push_back(static_cast<uint8_t>('d'));
291 bytes_to_write.push_back(static_cast<uint8_t>('b'));
292 bytes_to_write.push_back(static_cast<uint8_t>('y'));
293 bytes_to_write.push_back(static_cast<uint8_t>('e'));
294 error = FILE_ERROR_FAILED;
295 uint32_t num_bytes_written = 0;
296 file->Write(mojo::Array<uint8_t>::From(bytes_to_write), 0,
297 WHENCE_FROM_CURRENT, Capture(&error, &num_bytes_written));
298 ASSERT_TRUE(file.WaitForIncomingResponse());
299 EXPECT_EQ(FILE_ERROR_OK, error);
300 EXPECT_EQ(bytes_to_write.size(), num_bytes_written);
302 // Close it.
303 error = FILE_ERROR_FAILED;
304 file->Close(Capture(&error));
305 ASSERT_TRUE(file.WaitForIncomingResponse());
306 EXPECT_EQ(FILE_ERROR_OK, error);
310 // Open my_file again.
311 FilePtr file;
312 error = FILE_ERROR_FAILED;
313 directory->OpenFile("my_file", GetProxy(&file), kFlagRead | kFlagOpen,
314 Capture(&error));
315 ASSERT_TRUE(directory.WaitForIncomingResponse());
316 EXPECT_EQ(FILE_ERROR_OK, error);
318 // Read from it.
319 mojo::Array<uint8_t> bytes_read;
320 error = FILE_ERROR_FAILED;
321 file->Read(7, 0, WHENCE_FROM_BEGIN, Capture(&error, &bytes_read));
322 ASSERT_TRUE(file.WaitForIncomingResponse());
323 EXPECT_EQ(FILE_ERROR_OK, error);
324 ASSERT_EQ(7u, bytes_read.size());
325 EXPECT_EQ(static_cast<uint8_t>('g'), bytes_read[0]);
326 EXPECT_EQ(static_cast<uint8_t>('o'), bytes_read[1]);
327 EXPECT_EQ(static_cast<uint8_t>('o'), bytes_read[2]);
328 EXPECT_EQ(static_cast<uint8_t>('d'), bytes_read[3]);
332 // Note: Ignore nanoseconds, since it may not always be supported. We expect at
333 // least second-resolution support though.
334 TEST_F(FileImplTest, StatTouch) {
335 DirectoryPtr directory;
336 GetTemporaryRoot(&directory);
337 FileError error;
339 // Create my_file.
340 FilePtr file;
341 error = FILE_ERROR_FAILED;
342 directory->OpenFile("my_file", GetProxy(&file), kFlagWrite | kFlagCreate,
343 Capture(&error));
344 ASSERT_TRUE(directory.WaitForIncomingResponse());
345 EXPECT_EQ(FILE_ERROR_OK, error);
347 // Stat it.
348 error = FILE_ERROR_FAILED;
349 FileInformationPtr file_info;
350 file->Stat(Capture(&error, &file_info));
351 ASSERT_TRUE(file.WaitForIncomingResponse());
352 EXPECT_EQ(FILE_ERROR_OK, error);
353 ASSERT_FALSE(file_info.is_null());
354 EXPECT_EQ(FS_FILE_TYPE_REGULAR_FILE, file_info->type);
355 EXPECT_EQ(0, file_info->size);
356 EXPECT_GT(file_info->atime, 0); // Expect that it's not 1970-01-01.
357 EXPECT_GT(file_info->mtime, 0);
358 double first_mtime = file_info->mtime;
360 // Touch only the atime.
361 error = FILE_ERROR_FAILED;
362 TimespecOrNowPtr t(TimespecOrNow::New());
363 t->now = false;
364 const int64_t kPartyTime1 = 1234567890; // Party like it's 2009-02-13.
365 t->seconds = kPartyTime1;
366 file->Touch(t.Pass(), nullptr, Capture(&error));
367 ASSERT_TRUE(file.WaitForIncomingResponse());
368 EXPECT_EQ(FILE_ERROR_OK, error);
370 // Stat again.
371 error = FILE_ERROR_FAILED;
372 file_info.reset();
373 file->Stat(Capture(&error, &file_info));
374 ASSERT_TRUE(file.WaitForIncomingResponse());
375 EXPECT_EQ(FILE_ERROR_OK, error);
376 ASSERT_FALSE(file_info.is_null());
377 EXPECT_EQ(kPartyTime1, file_info->atime);
378 EXPECT_EQ(first_mtime, file_info->mtime);
380 // Touch only the mtime.
381 t = TimespecOrNow::New();
382 t->now = false;
383 const int64_t kPartyTime2 = 1425059525; // No time like the present.
384 t->seconds = kPartyTime2;
385 file->Touch(nullptr, t.Pass(), Capture(&error));
386 ASSERT_TRUE(file.WaitForIncomingResponse());
387 EXPECT_EQ(FILE_ERROR_OK, error);
389 // Stat again.
390 error = FILE_ERROR_FAILED;
391 file_info.reset();
392 file->Stat(Capture(&error, &file_info));
393 ASSERT_TRUE(file.WaitForIncomingResponse());
394 EXPECT_EQ(FILE_ERROR_OK, error);
395 ASSERT_FALSE(file_info.is_null());
396 EXPECT_EQ(kPartyTime1, file_info->atime);
397 EXPECT_EQ(kPartyTime2, file_info->mtime);
399 // TODO(vtl): Also test non-zero file size.
400 // TODO(vtl): Also test Touch() "now" options.
401 // TODO(vtl): Also test touching both atime and mtime.
404 TEST_F(FileImplTest, TellSeek) {
405 DirectoryPtr directory;
406 GetTemporaryRoot(&directory);
407 FileError error;
409 // Create my_file.
410 FilePtr file;
411 error = FILE_ERROR_FAILED;
412 directory->OpenFile("my_file", GetProxy(&file), kFlagWrite | kFlagCreate,
413 Capture(&error));
414 ASSERT_TRUE(directory.WaitForIncomingResponse());
415 EXPECT_EQ(FILE_ERROR_OK, error);
417 // Write to it.
418 std::vector<uint8_t> bytes_to_write(1000, '!');
419 error = FILE_ERROR_FAILED;
420 uint32_t num_bytes_written = 0;
421 file->Write(mojo::Array<uint8_t>::From(bytes_to_write), 0,
422 WHENCE_FROM_CURRENT, Capture(&error, &num_bytes_written));
423 ASSERT_TRUE(file.WaitForIncomingResponse());
424 EXPECT_EQ(FILE_ERROR_OK, error);
425 EXPECT_EQ(bytes_to_write.size(), num_bytes_written);
426 const int size = static_cast<int>(num_bytes_written);
428 // Tell.
429 error = FILE_ERROR_FAILED;
430 int64_t position = -1;
431 file->Tell(Capture(&error, &position));
432 ASSERT_TRUE(file.WaitForIncomingResponse());
433 // Should be at the end.
434 EXPECT_EQ(FILE_ERROR_OK, error);
435 EXPECT_EQ(size, position);
437 // Seek back 100.
438 error = FILE_ERROR_FAILED;
439 position = -1;
440 file->Seek(-100, WHENCE_FROM_CURRENT, Capture(&error, &position));
441 ASSERT_TRUE(file.WaitForIncomingResponse());
442 EXPECT_EQ(FILE_ERROR_OK, error);
443 EXPECT_EQ(size - 100, position);
445 // Tell.
446 error = FILE_ERROR_FAILED;
447 position = -1;
448 file->Tell(Capture(&error, &position));
449 ASSERT_TRUE(file.WaitForIncomingResponse());
450 EXPECT_EQ(FILE_ERROR_OK, error);
451 EXPECT_EQ(size - 100, position);
453 // Seek to 123 from start.
454 error = FILE_ERROR_FAILED;
455 position = -1;
456 file->Seek(123, WHENCE_FROM_BEGIN, Capture(&error, &position));
457 ASSERT_TRUE(file.WaitForIncomingResponse());
458 EXPECT_EQ(FILE_ERROR_OK, error);
459 EXPECT_EQ(123, position);
461 // Tell.
462 error = FILE_ERROR_FAILED;
463 position = -1;
464 file->Tell(Capture(&error, &position));
465 ASSERT_TRUE(file.WaitForIncomingResponse());
466 EXPECT_EQ(FILE_ERROR_OK, error);
467 EXPECT_EQ(123, position);
469 // Seek to 123 back from end.
470 error = FILE_ERROR_FAILED;
471 position = -1;
472 file->Seek(-123, WHENCE_FROM_END, Capture(&error, &position));
473 ASSERT_TRUE(file.WaitForIncomingResponse());
474 EXPECT_EQ(FILE_ERROR_OK, error);
475 EXPECT_EQ(size - 123, position);
477 // Tell.
478 error = FILE_ERROR_FAILED;
479 position = -1;
480 file->Tell(Capture(&error, &position));
481 ASSERT_TRUE(file.WaitForIncomingResponse());
482 EXPECT_EQ(FILE_ERROR_OK, error);
483 EXPECT_EQ(size - 123, position);
485 // TODO(vtl): Check that seeking actually affects reading/writing.
486 // TODO(vtl): Check that seeking can extend the file?
489 TEST_F(FileImplTest, Dup) {
490 DirectoryPtr directory;
491 GetTemporaryRoot(&directory);
492 FileError error;
494 // Create my_file.
495 FilePtr file1;
496 error = FILE_ERROR_FAILED;
497 directory->OpenFile("my_file", GetProxy(&file1),
498 kFlagRead | kFlagWrite | kFlagCreate, Capture(&error));
499 ASSERT_TRUE(directory.WaitForIncomingResponse());
500 EXPECT_EQ(FILE_ERROR_OK, error);
502 // Write to it.
503 std::vector<uint8_t> bytes_to_write;
504 bytes_to_write.push_back(static_cast<uint8_t>('h'));
505 bytes_to_write.push_back(static_cast<uint8_t>('e'));
506 bytes_to_write.push_back(static_cast<uint8_t>('l'));
507 bytes_to_write.push_back(static_cast<uint8_t>('l'));
508 bytes_to_write.push_back(static_cast<uint8_t>('o'));
509 error = FILE_ERROR_FAILED;
510 uint32_t num_bytes_written = 0;
511 file1->Write(mojo::Array<uint8_t>::From(bytes_to_write), 0,
512 WHENCE_FROM_CURRENT, Capture(&error, &num_bytes_written));
513 ASSERT_TRUE(file1.WaitForIncomingResponse());
514 EXPECT_EQ(FILE_ERROR_OK, error);
515 EXPECT_EQ(bytes_to_write.size(), num_bytes_written);
516 const int end_hello_pos = static_cast<int>(num_bytes_written);
518 // Dup it.
519 FilePtr file2;
520 error = FILE_ERROR_FAILED;
521 file1->Dup(GetProxy(&file2), Capture(&error));
522 ASSERT_TRUE(file1.WaitForIncomingResponse());
523 EXPECT_EQ(FILE_ERROR_OK, error);
525 // |file2| should have the same position.
526 error = FILE_ERROR_FAILED;
527 int64_t position = -1;
528 file2->Tell(Capture(&error, &position));
529 ASSERT_TRUE(file2.WaitForIncomingResponse());
530 EXPECT_EQ(FILE_ERROR_OK, error);
531 EXPECT_EQ(end_hello_pos, position);
533 // Write using |file2|.
534 std::vector<uint8_t> more_bytes_to_write;
535 more_bytes_to_write.push_back(static_cast<uint8_t>('w'));
536 more_bytes_to_write.push_back(static_cast<uint8_t>('o'));
537 more_bytes_to_write.push_back(static_cast<uint8_t>('r'));
538 more_bytes_to_write.push_back(static_cast<uint8_t>('l'));
539 more_bytes_to_write.push_back(static_cast<uint8_t>('d'));
540 error = FILE_ERROR_FAILED;
541 num_bytes_written = 0;
542 file2->Write(mojo::Array<uint8_t>::From(more_bytes_to_write), 0,
543 WHENCE_FROM_CURRENT, Capture(&error, &num_bytes_written));
544 ASSERT_TRUE(file2.WaitForIncomingResponse());
545 EXPECT_EQ(FILE_ERROR_OK, error);
546 EXPECT_EQ(more_bytes_to_write.size(), num_bytes_written);
547 const int end_world_pos = end_hello_pos + static_cast<int>(num_bytes_written);
549 // |file1| should have the same position.
550 error = FILE_ERROR_FAILED;
551 position = -1;
552 file1->Tell(Capture(&error, &position));
553 ASSERT_TRUE(file1.WaitForIncomingResponse());
554 EXPECT_EQ(FILE_ERROR_OK, error);
555 EXPECT_EQ(end_world_pos, position);
557 // Close |file1|.
558 error = FILE_ERROR_FAILED;
559 file1->Close(Capture(&error));
560 ASSERT_TRUE(file1.WaitForIncomingResponse());
561 EXPECT_EQ(FILE_ERROR_OK, error);
563 // Read everything using |file2|.
564 mojo::Array<uint8_t> bytes_read;
565 error = FILE_ERROR_FAILED;
566 file2->Read(1000, 0, WHENCE_FROM_BEGIN, Capture(&error, &bytes_read));
567 ASSERT_TRUE(file2.WaitForIncomingResponse());
568 EXPECT_EQ(FILE_ERROR_OK, error);
569 ASSERT_EQ(static_cast<size_t>(end_world_pos), bytes_read.size());
570 // Just check the first and last bytes.
571 EXPECT_EQ(static_cast<uint8_t>('h'), bytes_read[0]);
572 EXPECT_EQ(static_cast<uint8_t>('d'), bytes_read[end_world_pos - 1]);
574 // TODO(vtl): Test that |file2| has the same open options as |file1|.
577 TEST_F(FileImplTest, Truncate) {
578 const uint32_t kInitialSize = 1000;
579 const uint32_t kTruncatedSize = 654;
581 DirectoryPtr directory;
582 GetTemporaryRoot(&directory);
583 FileError error;
585 // Create my_file.
586 FilePtr file;
587 error = FILE_ERROR_FAILED;
588 directory->OpenFile("my_file", GetProxy(&file), kFlagWrite | kFlagCreate,
589 Capture(&error));
590 ASSERT_TRUE(directory.WaitForIncomingResponse());
591 EXPECT_EQ(FILE_ERROR_OK, error);
593 // Write to it.
594 std::vector<uint8_t> bytes_to_write(kInitialSize, '!');
595 error = FILE_ERROR_FAILED;
596 uint32_t num_bytes_written = 0;
597 file->Write(mojo::Array<uint8_t>::From(bytes_to_write), 0,
598 WHENCE_FROM_CURRENT, Capture(&error, &num_bytes_written));
599 ASSERT_TRUE(file.WaitForIncomingResponse());
600 EXPECT_EQ(FILE_ERROR_OK, error);
601 EXPECT_EQ(kInitialSize, num_bytes_written);
603 // Stat it.
604 error = FILE_ERROR_FAILED;
605 FileInformationPtr file_info;
606 file->Stat(Capture(&error, &file_info));
607 ASSERT_TRUE(file.WaitForIncomingResponse());
608 EXPECT_EQ(FILE_ERROR_OK, error);
609 ASSERT_FALSE(file_info.is_null());
610 EXPECT_EQ(kInitialSize, file_info->size);
612 // Truncate it.
613 error = FILE_ERROR_FAILED;
614 file->Truncate(kTruncatedSize, Capture(&error));
615 ASSERT_TRUE(file.WaitForIncomingResponse());
616 EXPECT_EQ(FILE_ERROR_OK, error);
618 // Stat again.
619 error = FILE_ERROR_FAILED;
620 file_info.reset();
621 file->Stat(Capture(&error, &file_info));
622 ASSERT_TRUE(file.WaitForIncomingResponse());
623 EXPECT_EQ(FILE_ERROR_OK, error);
624 ASSERT_FALSE(file_info.is_null());
625 EXPECT_EQ(kTruncatedSize, file_info->size);
628 TEST_F(FileImplTest, AsHandle) {
629 DirectoryPtr directory;
630 GetTemporaryRoot(&directory);
631 FileError error;
634 // Create my_file.
635 FilePtr file1;
636 error = FILE_ERROR_FAILED;
637 directory->OpenFile("my_file", GetProxy(&file1),
638 kFlagRead | kFlagWrite | kFlagCreate, Capture(&error));
639 ASSERT_TRUE(directory.WaitForIncomingResponse());
640 EXPECT_EQ(FILE_ERROR_OK, error);
642 // Fetch the handle
643 error = FILE_ERROR_FAILED;
644 mojo::ScopedHandle handle;
645 file1->AsHandle(Capture(&error, &handle));
646 ASSERT_TRUE(file1.WaitForIncomingResponse());
647 EXPECT_EQ(FILE_ERROR_OK, error);
649 // Pull a file descriptor out of the scoped handle.
650 MojoPlatformHandle platform_handle;
651 MojoResult extract_result =
652 MojoExtractPlatformHandle(handle.release().value(), &platform_handle);
653 EXPECT_EQ(MOJO_RESULT_OK, extract_result);
655 // Pass this raw file descriptor to a base::File.
656 base::File raw_file(platform_handle);
657 ASSERT_TRUE(raw_file.IsValid());
658 EXPECT_EQ(5, raw_file.WriteAtCurrentPos("hello", 5));
662 // Reopen my_file.
663 FilePtr file2;
664 error = FILE_ERROR_FAILED;
665 directory->OpenFile("my_file", GetProxy(&file2), kFlagRead | kFlagOpen,
666 Capture(&error));
667 ASSERT_TRUE(directory.WaitForIncomingResponse());
668 EXPECT_EQ(FILE_ERROR_OK, error);
670 // Verify that we wrote data raw on the file descriptor.
671 mojo::Array<uint8_t> bytes_read;
672 error = FILE_ERROR_FAILED;
673 file2->Read(5, 0, WHENCE_FROM_BEGIN, Capture(&error, &bytes_read));
674 ASSERT_TRUE(file2.WaitForIncomingResponse());
675 EXPECT_EQ(FILE_ERROR_OK, error);
676 ASSERT_EQ(5u, bytes_read.size());
677 EXPECT_EQ(static_cast<uint8_t>('h'), bytes_read[0]);
678 EXPECT_EQ(static_cast<uint8_t>('e'), bytes_read[1]);
679 EXPECT_EQ(static_cast<uint8_t>('l'), bytes_read[2]);
680 EXPECT_EQ(static_cast<uint8_t>('l'), bytes_read[3]);
681 EXPECT_EQ(static_cast<uint8_t>('o'), bytes_read[4]);
685 } // namespace
686 } // namespace filesystem