1 | #![warn (rust_2018_idioms)] |
2 | #![cfg (all(feature = "full" , not(target_os = "wasi" )))] // WASI does not support all fs operations |
3 | |
4 | use std::io::prelude::*; |
5 | use std::io::IoSlice; |
6 | use tempfile::NamedTempFile; |
7 | use tokio::fs::File; |
8 | use tokio::io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt, SeekFrom}; |
9 | use tokio_test::task; |
10 | |
11 | const HELLO: &[u8] = b"hello world..." ; |
12 | |
13 | #[tokio::test ] |
14 | async fn basic_read() { |
15 | let mut tempfile = tempfile(); |
16 | tempfile.write_all(HELLO).unwrap(); |
17 | |
18 | let mut file = File::open(tempfile.path()).await.unwrap(); |
19 | |
20 | let mut buf = [0; 1024]; |
21 | let n = file.read(&mut buf).await.unwrap(); |
22 | |
23 | assert_eq!(n, HELLO.len()); |
24 | assert_eq!(&buf[..n], HELLO); |
25 | } |
26 | |
27 | #[tokio::test ] |
28 | async fn basic_write() { |
29 | let tempfile = tempfile(); |
30 | |
31 | let mut file = File::create(tempfile.path()).await.unwrap(); |
32 | |
33 | file.write_all(HELLO).await.unwrap(); |
34 | file.flush().await.unwrap(); |
35 | |
36 | let file = std::fs::read(tempfile.path()).unwrap(); |
37 | assert_eq!(file, HELLO); |
38 | } |
39 | |
40 | #[tokio::test ] |
41 | async fn basic_write_and_shutdown() { |
42 | let tempfile = tempfile(); |
43 | |
44 | let mut file = File::create(tempfile.path()).await.unwrap(); |
45 | |
46 | file.write_all(HELLO).await.unwrap(); |
47 | file.shutdown().await.unwrap(); |
48 | |
49 | let file = std::fs::read(tempfile.path()).unwrap(); |
50 | assert_eq!(file, HELLO); |
51 | } |
52 | |
53 | #[tokio::test ] |
54 | async fn write_vectored() { |
55 | let tempfile = tempfile(); |
56 | |
57 | let mut file = File::create(tempfile.path()).await.unwrap(); |
58 | |
59 | let ret = file |
60 | .write_vectored(&[IoSlice::new(HELLO), IoSlice::new(HELLO)]) |
61 | .await |
62 | .unwrap(); |
63 | assert_eq!(ret, HELLO.len() * 2); |
64 | file.flush().await.unwrap(); |
65 | |
66 | let file = std::fs::read(tempfile.path()).unwrap(); |
67 | assert_eq!(file, [HELLO, HELLO].concat()); |
68 | } |
69 | |
70 | #[tokio::test ] |
71 | async fn write_vectored_and_shutdown() { |
72 | let tempfile = tempfile(); |
73 | |
74 | let mut file = File::create(tempfile.path()).await.unwrap(); |
75 | |
76 | let ret = file |
77 | .write_vectored(&[IoSlice::new(HELLO), IoSlice::new(HELLO)]) |
78 | .await |
79 | .unwrap(); |
80 | assert_eq!(ret, HELLO.len() * 2); |
81 | file.shutdown().await.unwrap(); |
82 | |
83 | let file = std::fs::read(tempfile.path()).unwrap(); |
84 | assert_eq!(file, [HELLO, HELLO].concat()); |
85 | } |
86 | |
87 | #[tokio::test ] |
88 | async fn rewind_seek_position() { |
89 | let tempfile = tempfile(); |
90 | |
91 | let mut file = File::create(tempfile.path()).await.unwrap(); |
92 | |
93 | file.seek(SeekFrom::Current(10)).await.unwrap(); |
94 | |
95 | file.rewind().await.unwrap(); |
96 | |
97 | assert_eq!(file.stream_position().await.unwrap(), 0); |
98 | } |
99 | |
100 | #[tokio::test ] |
101 | async fn coop() { |
102 | let mut tempfile = tempfile(); |
103 | tempfile.write_all(HELLO).unwrap(); |
104 | |
105 | let mut task = task::spawn(async { |
106 | let mut file = File::open(tempfile.path()).await.unwrap(); |
107 | |
108 | let mut buf = [0; 1024]; |
109 | |
110 | loop { |
111 | let _ = file.read(&mut buf).await.unwrap(); |
112 | file.seek(std::io::SeekFrom::Start(0)).await.unwrap(); |
113 | } |
114 | }); |
115 | |
116 | for _ in 0..1_000 { |
117 | if task.poll().is_pending() { |
118 | return; |
119 | } |
120 | } |
121 | |
122 | panic!("did not yield" ); |
123 | } |
124 | |
125 | #[tokio::test ] |
126 | async fn write_to_clone() { |
127 | let tempfile = tempfile(); |
128 | |
129 | let file = File::create(tempfile.path()).await.unwrap(); |
130 | let mut clone = file.try_clone().await.unwrap(); |
131 | |
132 | clone.write_all(HELLO).await.unwrap(); |
133 | clone.flush().await.unwrap(); |
134 | |
135 | let contents = std::fs::read(tempfile.path()).unwrap(); |
136 | assert_eq!(contents, HELLO); |
137 | } |
138 | |
139 | #[tokio::test ] |
140 | async fn write_into_std() { |
141 | let tempfile = tempfile(); |
142 | |
143 | let file = File::create(tempfile.path()).await.unwrap(); |
144 | let mut std_file = file.into_std().await; |
145 | |
146 | std_file.write_all(HELLO).unwrap(); |
147 | |
148 | let contents = std::fs::read(tempfile.path()).unwrap(); |
149 | assert_eq!(contents, HELLO); |
150 | } |
151 | |
152 | #[tokio::test ] |
153 | async fn write_into_std_immediate() { |
154 | let tempfile = tempfile(); |
155 | |
156 | let file = File::create(tempfile.path()).await.unwrap(); |
157 | let mut std_file = file.try_into_std().unwrap(); |
158 | |
159 | std_file.write_all(HELLO).unwrap(); |
160 | |
161 | let contents = std::fs::read(tempfile.path()).unwrap(); |
162 | assert_eq!(contents, HELLO); |
163 | } |
164 | |
165 | #[tokio::test ] |
166 | async fn read_file_from_std() { |
167 | let mut tempfile = tempfile(); |
168 | tempfile.write_all(HELLO).unwrap(); |
169 | |
170 | let std_file = std::fs::File::open(tempfile.path()).unwrap(); |
171 | let mut file = File::from(std_file); |
172 | |
173 | let mut buf = [0; 1024]; |
174 | let n = file.read(&mut buf).await.unwrap(); |
175 | assert_eq!(n, HELLO.len()); |
176 | assert_eq!(&buf[..n], HELLO); |
177 | } |
178 | |
179 | fn tempfile() -> NamedTempFile { |
180 | NamedTempFile::new().unwrap() |
181 | } |
182 | |
183 | #[tokio::test ] |
184 | #[cfg (unix)] |
185 | async fn file_debug_fmt() { |
186 | let tempfile = tempfile(); |
187 | |
188 | let file = File::open(tempfile.path()).await.unwrap(); |
189 | |
190 | assert_eq!( |
191 | &format!("{:?}" , file)[0..33], |
192 | "tokio::fs::File { std: File { fd:" |
193 | ); |
194 | } |
195 | |
196 | #[tokio::test ] |
197 | #[cfg (windows)] |
198 | async fn file_debug_fmt() { |
199 | let tempfile = tempfile(); |
200 | |
201 | let file = File::open(tempfile.path()).await.unwrap(); |
202 | |
203 | assert_eq!( |
204 | &format!("{:?}" , file)[0..37], |
205 | "tokio::fs::File { std: File { handle:" |
206 | ); |
207 | } |
208 | |
209 | #[tokio::test ] |
210 | #[cfg (unix)] |
211 | async fn unix_fd_is_valid() { |
212 | use std::os::unix::io::AsRawFd; |
213 | let tempfile = tempfile(); |
214 | |
215 | let file = File::create(tempfile.path()).await.unwrap(); |
216 | assert!(file.as_raw_fd() as u64 > 0); |
217 | } |
218 | |
219 | #[tokio::test ] |
220 | #[cfg (unix)] |
221 | async fn read_file_from_unix_fd() { |
222 | use std::os::unix::io::{FromRawFd, IntoRawFd}; |
223 | |
224 | let mut tempfile = tempfile(); |
225 | tempfile.write_all(HELLO).unwrap(); |
226 | |
227 | let file1 = File::open(tempfile.path()).await.unwrap(); |
228 | let raw_fd = file1.into_std().await.into_raw_fd(); |
229 | assert!(raw_fd > 0); |
230 | |
231 | let mut file2 = unsafe { File::from_raw_fd(raw_fd) }; |
232 | |
233 | let mut buf = [0; 1024]; |
234 | let n = file2.read(&mut buf).await.unwrap(); |
235 | assert_eq!(n, HELLO.len()); |
236 | assert_eq!(&buf[..n], HELLO); |
237 | } |
238 | |
239 | #[tokio::test ] |
240 | #[cfg (windows)] |
241 | async fn windows_handle() { |
242 | use std::os::windows::io::AsRawHandle; |
243 | let tempfile = tempfile(); |
244 | |
245 | let file = File::create(tempfile.path()).await.unwrap(); |
246 | assert!(file.as_raw_handle() as u64 > 0); |
247 | } |
248 | |