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