1 #![warn(rust_2018_idioms)]
2 #![cfg(feature = "full")]
3
4 macro_rules! ready {
5 ($e:expr $(,)?) => {
6 match $e {
7 std::task::Poll::Ready(t) => t,
8 std::task::Poll::Pending => return std::task::Poll::Pending,
9 }
10 };
11 }
12
13 #[macro_export]
14 macro_rules! cfg_fs {
15 ($($item:item)*) => { $($item)* }
16 }
17
18 #[macro_export]
19 macro_rules! cfg_io_std {
20 ($($item:item)*) => { $($item)* }
21 }
22
23 use futures::future;
24
25 // Load source
26 #[allow(warnings)]
27 #[path = "../src/fs/file.rs"]
28 mod file;
29 use file::File;
30
31 #[allow(warnings)]
32 #[path = "../src/io/blocking.rs"]
33 mod blocking;
34
35 // Load mocked types
36 mod support {
37 pub(crate) mod mock_file;
38 pub(crate) mod mock_pool;
39 }
40 pub(crate) use support::mock_pool as pool;
41
42 // Place them where the source expects them
43 pub(crate) mod io {
44 pub(crate) use tokio::io::*;
45
46 pub(crate) use crate::blocking;
47
48 pub(crate) mod sys {
49 pub(crate) use crate::support::mock_pool::{run, Blocking};
50 }
51 }
52 pub(crate) mod fs {
53 pub(crate) mod sys {
54 pub(crate) use crate::support::mock_file::File;
55 pub(crate) use crate::support::mock_pool::{run, Blocking};
56 }
57
58 pub(crate) use crate::support::mock_pool::asyncify;
59 }
60 pub(crate) mod sync {
61 pub(crate) use tokio::sync::Mutex;
62 }
63 use fs::sys;
64
65 use tokio::io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt};
66 use tokio_test::{assert_pending, assert_ready, assert_ready_err, assert_ready_ok, task};
67
68 use std::io::SeekFrom;
69
70 const HELLO: &[u8] = b"hello world...";
71 const FOO: &[u8] = b"foo bar baz...";
72
73 #[test]
open_read()74 fn open_read() {
75 let (mock, file) = sys::File::mock();
76 mock.read(HELLO);
77
78 let mut file = File::from_std(file);
79
80 let mut buf = [0; 1024];
81 let mut t = task::spawn(file.read(&mut buf));
82
83 assert_eq!(0, pool::len());
84 assert_pending!(t.poll());
85
86 assert_eq!(1, mock.remaining());
87 assert_eq!(1, pool::len());
88
89 pool::run_one();
90
91 assert_eq!(0, mock.remaining());
92 assert!(t.is_woken());
93
94 let n = assert_ready_ok!(t.poll());
95 assert_eq!(n, HELLO.len());
96 assert_eq!(&buf[..n], HELLO);
97 }
98
99 #[test]
read_twice_before_dispatch()100 fn read_twice_before_dispatch() {
101 let (mock, file) = sys::File::mock();
102 mock.read(HELLO);
103
104 let mut file = File::from_std(file);
105
106 let mut buf = [0; 1024];
107 let mut t = task::spawn(file.read(&mut buf));
108
109 assert_pending!(t.poll());
110 assert_pending!(t.poll());
111
112 assert_eq!(pool::len(), 1);
113 pool::run_one();
114
115 assert!(t.is_woken());
116
117 let n = assert_ready_ok!(t.poll());
118 assert_eq!(&buf[..n], HELLO);
119 }
120
121 #[test]
read_with_smaller_buf()122 fn read_with_smaller_buf() {
123 let (mock, file) = sys::File::mock();
124 mock.read(HELLO);
125
126 let mut file = File::from_std(file);
127
128 {
129 let mut buf = [0; 32];
130 let mut t = task::spawn(file.read(&mut buf));
131 assert_pending!(t.poll());
132 }
133
134 pool::run_one();
135
136 {
137 let mut buf = [0; 4];
138 let mut t = task::spawn(file.read(&mut buf));
139 let n = assert_ready_ok!(t.poll());
140 assert_eq!(n, 4);
141 assert_eq!(&buf[..], &HELLO[..n]);
142 }
143
144 // Calling again immediately succeeds with the rest of the buffer
145 let mut buf = [0; 32];
146 let mut t = task::spawn(file.read(&mut buf));
147 let n = assert_ready_ok!(t.poll());
148 assert_eq!(n, 10);
149 assert_eq!(&buf[..n], &HELLO[4..]);
150
151 assert_eq!(0, pool::len());
152 }
153
154 #[test]
read_with_bigger_buf()155 fn read_with_bigger_buf() {
156 let (mock, file) = sys::File::mock();
157 mock.read(&HELLO[..4]).read(&HELLO[4..]);
158
159 let mut file = File::from_std(file);
160
161 {
162 let mut buf = [0; 4];
163 let mut t = task::spawn(file.read(&mut buf));
164 assert_pending!(t.poll());
165 }
166
167 pool::run_one();
168
169 {
170 let mut buf = [0; 32];
171 let mut t = task::spawn(file.read(&mut buf));
172 let n = assert_ready_ok!(t.poll());
173 assert_eq!(n, 4);
174 assert_eq!(&buf[..n], &HELLO[..n]);
175 }
176
177 // Calling again immediately succeeds with the rest of the buffer
178 let mut buf = [0; 32];
179 let mut t = task::spawn(file.read(&mut buf));
180
181 assert_pending!(t.poll());
182
183 assert_eq!(1, pool::len());
184 pool::run_one();
185
186 assert!(t.is_woken());
187
188 let n = assert_ready_ok!(t.poll());
189 assert_eq!(n, 10);
190 assert_eq!(&buf[..n], &HELLO[4..]);
191
192 assert_eq!(0, pool::len());
193 }
194
195 #[test]
read_err_then_read_success()196 fn read_err_then_read_success() {
197 let (mock, file) = sys::File::mock();
198 mock.read_err().read(&HELLO);
199
200 let mut file = File::from_std(file);
201
202 {
203 let mut buf = [0; 32];
204 let mut t = task::spawn(file.read(&mut buf));
205 assert_pending!(t.poll());
206
207 pool::run_one();
208
209 assert_ready_err!(t.poll());
210 }
211
212 {
213 let mut buf = [0; 32];
214 let mut t = task::spawn(file.read(&mut buf));
215 assert_pending!(t.poll());
216
217 pool::run_one();
218
219 let n = assert_ready_ok!(t.poll());
220
221 assert_eq!(n, HELLO.len());
222 assert_eq!(&buf[..n], HELLO);
223 }
224 }
225
226 #[test]
open_write()227 fn open_write() {
228 let (mock, file) = sys::File::mock();
229 mock.write(HELLO);
230
231 let mut file = File::from_std(file);
232
233 let mut t = task::spawn(file.write(HELLO));
234
235 assert_eq!(0, pool::len());
236 assert_ready_ok!(t.poll());
237
238 assert_eq!(1, mock.remaining());
239 assert_eq!(1, pool::len());
240
241 pool::run_one();
242
243 assert_eq!(0, mock.remaining());
244 assert!(!t.is_woken());
245
246 let mut t = task::spawn(file.flush());
247 assert_ready_ok!(t.poll());
248 }
249
250 #[test]
flush_while_idle()251 fn flush_while_idle() {
252 let (_mock, file) = sys::File::mock();
253
254 let mut file = File::from_std(file);
255
256 let mut t = task::spawn(file.flush());
257 assert_ready_ok!(t.poll());
258 }
259
260 #[test]
read_with_buffer_larger_than_max()261 fn read_with_buffer_larger_than_max() {
262 // Chunks
263 let chunk_a = 16 * 1024;
264 let chunk_b = chunk_a * 2;
265 let chunk_c = chunk_a * 3;
266 let chunk_d = chunk_a * 4;
267
268 assert_eq!(chunk_d / 1024, 64);
269
270 let mut data = vec![];
271 for i in 0..(chunk_d - 1) {
272 data.push((i % 151) as u8);
273 }
274
275 let (mock, file) = sys::File::mock();
276 mock.read(&data[0..chunk_a])
277 .read(&data[chunk_a..chunk_b])
278 .read(&data[chunk_b..chunk_c])
279 .read(&data[chunk_c..]);
280
281 let mut file = File::from_std(file);
282
283 let mut actual = vec![0; chunk_d];
284 let mut pos = 0;
285
286 while pos < data.len() {
287 let mut t = task::spawn(file.read(&mut actual[pos..]));
288
289 assert_pending!(t.poll());
290 pool::run_one();
291 assert!(t.is_woken());
292
293 let n = assert_ready_ok!(t.poll());
294 assert!(n <= chunk_a);
295
296 pos += n;
297 }
298
299 assert_eq!(mock.remaining(), 0);
300 assert_eq!(data, &actual[..data.len()]);
301 }
302
303 #[test]
write_with_buffer_larger_than_max()304 fn write_with_buffer_larger_than_max() {
305 // Chunks
306 let chunk_a = 16 * 1024;
307 let chunk_b = chunk_a * 2;
308 let chunk_c = chunk_a * 3;
309 let chunk_d = chunk_a * 4;
310
311 assert_eq!(chunk_d / 1024, 64);
312
313 let mut data = vec![];
314 for i in 0..(chunk_d - 1) {
315 data.push((i % 151) as u8);
316 }
317
318 let (mock, file) = sys::File::mock();
319 mock.write(&data[0..chunk_a])
320 .write(&data[chunk_a..chunk_b])
321 .write(&data[chunk_b..chunk_c])
322 .write(&data[chunk_c..]);
323
324 let mut file = File::from_std(file);
325
326 let mut rem = &data[..];
327
328 let mut first = true;
329
330 while !rem.is_empty() {
331 let mut task = task::spawn(file.write(rem));
332
333 if !first {
334 assert_pending!(task.poll());
335 pool::run_one();
336 assert!(task.is_woken());
337 }
338
339 first = false;
340
341 let n = assert_ready_ok!(task.poll());
342
343 rem = &rem[n..];
344 }
345
346 pool::run_one();
347
348 assert_eq!(mock.remaining(), 0);
349 }
350
351 #[test]
write_twice_before_dispatch()352 fn write_twice_before_dispatch() {
353 let (mock, file) = sys::File::mock();
354 mock.write(HELLO).write(FOO);
355
356 let mut file = File::from_std(file);
357
358 let mut t = task::spawn(file.write(HELLO));
359 assert_ready_ok!(t.poll());
360
361 let mut t = task::spawn(file.write(FOO));
362 assert_pending!(t.poll());
363
364 assert_eq!(pool::len(), 1);
365 pool::run_one();
366
367 assert!(t.is_woken());
368
369 assert_ready_ok!(t.poll());
370
371 let mut t = task::spawn(file.flush());
372 assert_pending!(t.poll());
373
374 assert_eq!(pool::len(), 1);
375 pool::run_one();
376
377 assert!(t.is_woken());
378 assert_ready_ok!(t.poll());
379 }
380
381 #[test]
incomplete_read_followed_by_write()382 fn incomplete_read_followed_by_write() {
383 let (mock, file) = sys::File::mock();
384 mock.read(HELLO)
385 .seek_current_ok(-(HELLO.len() as i64), 0)
386 .write(FOO);
387
388 let mut file = File::from_std(file);
389
390 let mut buf = [0; 32];
391
392 let mut t = task::spawn(file.read(&mut buf));
393 assert_pending!(t.poll());
394
395 pool::run_one();
396
397 let mut t = task::spawn(file.write(FOO));
398 assert_ready_ok!(t.poll());
399
400 assert_eq!(pool::len(), 1);
401 pool::run_one();
402
403 let mut t = task::spawn(file.flush());
404 assert_ready_ok!(t.poll());
405 }
406
407 #[test]
incomplete_partial_read_followed_by_write()408 fn incomplete_partial_read_followed_by_write() {
409 let (mock, file) = sys::File::mock();
410 mock.read(HELLO).seek_current_ok(-10, 0).write(FOO);
411
412 let mut file = File::from_std(file);
413
414 let mut buf = [0; 32];
415 let mut t = task::spawn(file.read(&mut buf));
416 assert_pending!(t.poll());
417
418 pool::run_one();
419
420 let mut buf = [0; 4];
421 let mut t = task::spawn(file.read(&mut buf));
422 assert_ready_ok!(t.poll());
423
424 let mut t = task::spawn(file.write(FOO));
425 assert_ready_ok!(t.poll());
426
427 assert_eq!(pool::len(), 1);
428 pool::run_one();
429
430 let mut t = task::spawn(file.flush());
431 assert_ready_ok!(t.poll());
432 }
433
434 #[test]
incomplete_read_followed_by_flush()435 fn incomplete_read_followed_by_flush() {
436 let (mock, file) = sys::File::mock();
437 mock.read(HELLO)
438 .seek_current_ok(-(HELLO.len() as i64), 0)
439 .write(FOO);
440
441 let mut file = File::from_std(file);
442
443 let mut buf = [0; 32];
444
445 let mut t = task::spawn(file.read(&mut buf));
446 assert_pending!(t.poll());
447
448 pool::run_one();
449
450 let mut t = task::spawn(file.flush());
451 assert_ready_ok!(t.poll());
452
453 let mut t = task::spawn(file.write(FOO));
454 assert_ready_ok!(t.poll());
455
456 pool::run_one();
457 }
458
459 #[test]
incomplete_flush_followed_by_write()460 fn incomplete_flush_followed_by_write() {
461 let (mock, file) = sys::File::mock();
462 mock.write(HELLO).write(FOO);
463
464 let mut file = File::from_std(file);
465
466 let mut t = task::spawn(file.write(HELLO));
467 let n = assert_ready_ok!(t.poll());
468 assert_eq!(n, HELLO.len());
469
470 let mut t = task::spawn(file.flush());
471 assert_pending!(t.poll());
472
473 // TODO: Move under write
474 pool::run_one();
475
476 let mut t = task::spawn(file.write(FOO));
477 assert_ready_ok!(t.poll());
478
479 pool::run_one();
480
481 let mut t = task::spawn(file.flush());
482 assert_ready_ok!(t.poll());
483 }
484
485 #[test]
read_err()486 fn read_err() {
487 let (mock, file) = sys::File::mock();
488 mock.read_err();
489
490 let mut file = File::from_std(file);
491
492 let mut buf = [0; 1024];
493 let mut t = task::spawn(file.read(&mut buf));
494
495 assert_pending!(t.poll());
496
497 pool::run_one();
498 assert!(t.is_woken());
499
500 assert_ready_err!(t.poll());
501 }
502
503 #[test]
write_write_err()504 fn write_write_err() {
505 let (mock, file) = sys::File::mock();
506 mock.write_err();
507
508 let mut file = File::from_std(file);
509
510 let mut t = task::spawn(file.write(HELLO));
511 assert_ready_ok!(t.poll());
512
513 pool::run_one();
514
515 let mut t = task::spawn(file.write(FOO));
516 assert_ready_err!(t.poll());
517 }
518
519 #[test]
write_read_write_err()520 fn write_read_write_err() {
521 let (mock, file) = sys::File::mock();
522 mock.write_err().read(HELLO);
523
524 let mut file = File::from_std(file);
525
526 let mut t = task::spawn(file.write(HELLO));
527 assert_ready_ok!(t.poll());
528
529 pool::run_one();
530
531 let mut buf = [0; 1024];
532 let mut t = task::spawn(file.read(&mut buf));
533
534 assert_pending!(t.poll());
535
536 pool::run_one();
537
538 let mut t = task::spawn(file.write(FOO));
539 assert_ready_err!(t.poll());
540 }
541
542 #[test]
write_read_flush_err()543 fn write_read_flush_err() {
544 let (mock, file) = sys::File::mock();
545 mock.write_err().read(HELLO);
546
547 let mut file = File::from_std(file);
548
549 let mut t = task::spawn(file.write(HELLO));
550 assert_ready_ok!(t.poll());
551
552 pool::run_one();
553
554 let mut buf = [0; 1024];
555 let mut t = task::spawn(file.read(&mut buf));
556
557 assert_pending!(t.poll());
558
559 pool::run_one();
560
561 let mut t = task::spawn(file.flush());
562 assert_ready_err!(t.poll());
563 }
564
565 #[test]
write_seek_write_err()566 fn write_seek_write_err() {
567 let (mock, file) = sys::File::mock();
568 mock.write_err().seek_start_ok(0);
569
570 let mut file = File::from_std(file);
571
572 let mut t = task::spawn(file.write(HELLO));
573 assert_ready_ok!(t.poll());
574
575 pool::run_one();
576
577 {
578 let mut t = task::spawn(file.seek(SeekFrom::Start(0)));
579 assert_pending!(t.poll());
580 }
581
582 pool::run_one();
583
584 let mut t = task::spawn(file.write(FOO));
585 assert_ready_err!(t.poll());
586 }
587
588 #[test]
write_seek_flush_err()589 fn write_seek_flush_err() {
590 let (mock, file) = sys::File::mock();
591 mock.write_err().seek_start_ok(0);
592
593 let mut file = File::from_std(file);
594
595 let mut t = task::spawn(file.write(HELLO));
596 assert_ready_ok!(t.poll());
597
598 pool::run_one();
599
600 {
601 let mut t = task::spawn(file.seek(SeekFrom::Start(0)));
602 assert_pending!(t.poll());
603 }
604
605 pool::run_one();
606
607 let mut t = task::spawn(file.flush());
608 assert_ready_err!(t.poll());
609 }
610
611 #[test]
sync_all_ordered_after_write()612 fn sync_all_ordered_after_write() {
613 let (mock, file) = sys::File::mock();
614 mock.write(HELLO).sync_all();
615
616 let mut file = File::from_std(file);
617 let mut t = task::spawn(file.write(HELLO));
618 assert_ready_ok!(t.poll());
619
620 let mut t = task::spawn(file.sync_all());
621 assert_pending!(t.poll());
622
623 assert_eq!(1, pool::len());
624 pool::run_one();
625
626 assert!(t.is_woken());
627 assert_pending!(t.poll());
628
629 assert_eq!(1, pool::len());
630 pool::run_one();
631
632 assert!(t.is_woken());
633 assert_ready_ok!(t.poll());
634 }
635
636 #[test]
sync_all_err_ordered_after_write()637 fn sync_all_err_ordered_after_write() {
638 let (mock, file) = sys::File::mock();
639 mock.write(HELLO).sync_all_err();
640
641 let mut file = File::from_std(file);
642 let mut t = task::spawn(file.write(HELLO));
643 assert_ready_ok!(t.poll());
644
645 let mut t = task::spawn(file.sync_all());
646 assert_pending!(t.poll());
647
648 assert_eq!(1, pool::len());
649 pool::run_one();
650
651 assert!(t.is_woken());
652 assert_pending!(t.poll());
653
654 assert_eq!(1, pool::len());
655 pool::run_one();
656
657 assert!(t.is_woken());
658 assert_ready_err!(t.poll());
659 }
660
661 #[test]
sync_data_ordered_after_write()662 fn sync_data_ordered_after_write() {
663 let (mock, file) = sys::File::mock();
664 mock.write(HELLO).sync_data();
665
666 let mut file = File::from_std(file);
667 let mut t = task::spawn(file.write(HELLO));
668 assert_ready_ok!(t.poll());
669
670 let mut t = task::spawn(file.sync_data());
671 assert_pending!(t.poll());
672
673 assert_eq!(1, pool::len());
674 pool::run_one();
675
676 assert!(t.is_woken());
677 assert_pending!(t.poll());
678
679 assert_eq!(1, pool::len());
680 pool::run_one();
681
682 assert!(t.is_woken());
683 assert_ready_ok!(t.poll());
684 }
685
686 #[test]
sync_data_err_ordered_after_write()687 fn sync_data_err_ordered_after_write() {
688 let (mock, file) = sys::File::mock();
689 mock.write(HELLO).sync_data_err();
690
691 let mut file = File::from_std(file);
692 let mut t = task::spawn(file.write(HELLO));
693 assert_ready_ok!(t.poll());
694
695 let mut t = task::spawn(file.sync_data());
696 assert_pending!(t.poll());
697
698 assert_eq!(1, pool::len());
699 pool::run_one();
700
701 assert!(t.is_woken());
702 assert_pending!(t.poll());
703
704 assert_eq!(1, pool::len());
705 pool::run_one();
706
707 assert!(t.is_woken());
708 assert_ready_err!(t.poll());
709 }
710
711 #[test]
open_set_len_ok()712 fn open_set_len_ok() {
713 let (mock, file) = sys::File::mock();
714 mock.set_len(123);
715
716 let file = File::from_std(file);
717 let mut t = task::spawn(file.set_len(123));
718
719 assert_pending!(t.poll());
720 assert_eq!(1, mock.remaining());
721
722 pool::run_one();
723 assert_eq!(0, mock.remaining());
724
725 assert!(t.is_woken());
726 assert_ready_ok!(t.poll());
727 }
728
729 #[test]
open_set_len_err()730 fn open_set_len_err() {
731 let (mock, file) = sys::File::mock();
732 mock.set_len_err(123);
733
734 let file = File::from_std(file);
735 let mut t = task::spawn(file.set_len(123));
736
737 assert_pending!(t.poll());
738 assert_eq!(1, mock.remaining());
739
740 pool::run_one();
741 assert_eq!(0, mock.remaining());
742
743 assert!(t.is_woken());
744 assert_ready_err!(t.poll());
745 }
746
747 #[test]
partial_read_set_len_ok()748 fn partial_read_set_len_ok() {
749 let (mock, file) = sys::File::mock();
750 mock.read(HELLO)
751 .seek_current_ok(-14, 0)
752 .set_len(123)
753 .read(FOO);
754
755 let mut buf = [0; 32];
756 let mut file = File::from_std(file);
757
758 {
759 let mut t = task::spawn(file.read(&mut buf));
760 assert_pending!(t.poll());
761 }
762
763 pool::run_one();
764
765 {
766 let mut t = task::spawn(file.set_len(123));
767
768 assert_pending!(t.poll());
769 pool::run_one();
770 assert_ready_ok!(t.poll());
771 }
772
773 let mut t = task::spawn(file.read(&mut buf));
774 assert_pending!(t.poll());
775 pool::run_one();
776 let n = assert_ready_ok!(t.poll());
777
778 assert_eq!(n, FOO.len());
779 assert_eq!(&buf[..n], FOO);
780 }
781