]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/unix/kernel_copy/tests.rs
Add 'compiler/rustc_smir/' from commit '9abcb5c7b574cf316eb23d3f469187bb86ba3019'
[rust.git] / library / std / src / sys / unix / kernel_copy / tests.rs
1 use crate::fs::OpenOptions;
2 use crate::io;
3 use crate::io::Result;
4 use crate::io::SeekFrom;
5 use crate::io::{BufRead, Read, Seek, Write};
6 use crate::os::unix::io::AsRawFd;
7 use crate::sys_common::io::test::tmpdir;
8
9 #[test]
10 fn copy_specialization() -> Result<()> {
11     use crate::io::{BufReader, BufWriter};
12
13     let tmp_path = tmpdir();
14     let source_path = tmp_path.join("copy-spec.source");
15     let sink_path = tmp_path.join("copy-spec.sink");
16
17     let result: Result<()> = try {
18         let mut source = crate::fs::OpenOptions::new()
19             .read(true)
20             .write(true)
21             .create(true)
22             .truncate(true)
23             .open(&source_path)?;
24         source.write_all(b"abcdefghiklmnopqr")?;
25         source.seek(SeekFrom::Start(8))?;
26         let mut source = BufReader::with_capacity(8, source.take(5));
27         source.fill_buf()?;
28         assert_eq!(source.buffer(), b"iklmn");
29         source.get_mut().set_limit(6);
30         source.get_mut().get_mut().seek(SeekFrom::Start(1))?; // "bcdefg"
31         let mut source = source.take(10); // "iklmnbcdef"
32
33         let mut sink = crate::fs::OpenOptions::new()
34             .read(true)
35             .write(true)
36             .create(true)
37             .truncate(true)
38             .open(&sink_path)?;
39         sink.write_all(b"000000")?;
40         let mut sink = BufWriter::with_capacity(5, sink);
41         sink.write_all(b"wxyz")?;
42         assert_eq!(sink.buffer(), b"wxyz");
43
44         let copied = crate::io::copy(&mut source, &mut sink)?;
45         assert_eq!(copied, 10, "copy obeyed limit imposed by Take");
46         assert_eq!(sink.buffer().len(), 0, "sink buffer was flushed");
47         assert_eq!(source.limit(), 0, "outer Take was exhausted");
48         assert_eq!(source.get_ref().buffer().len(), 0, "source buffer should be drained");
49         assert_eq!(
50             source.get_ref().get_ref().limit(),
51             1,
52             "inner Take allowed reading beyond end of file, some bytes should be left"
53         );
54
55         let mut sink = sink.into_inner()?;
56         sink.seek(SeekFrom::Start(0))?;
57         let mut copied = Vec::new();
58         sink.read_to_end(&mut copied)?;
59         assert_eq!(&copied, b"000000wxyziklmnbcdef");
60     };
61
62     let rm1 = crate::fs::remove_file(source_path);
63     let rm2 = crate::fs::remove_file(sink_path);
64
65     result.and(rm1).and(rm2)
66 }
67
68 #[test]
69 fn copies_append_mode_sink() -> Result<()> {
70     let tmp_path = tmpdir();
71     let source_path = tmp_path.join("copies_append_mode.source");
72     let sink_path = tmp_path.join("copies_append_mode.sink");
73     let mut source =
74         OpenOptions::new().create(true).truncate(true).write(true).read(true).open(&source_path)?;
75     write!(source, "not empty")?;
76     source.seek(SeekFrom::Start(0))?;
77     let mut sink = OpenOptions::new().create(true).append(true).open(&sink_path)?;
78
79     let copied = crate::io::copy(&mut source, &mut sink)?;
80
81     assert_eq!(copied, 9);
82
83     Ok(())
84 }
85
86 #[bench]
87 fn bench_file_to_file_copy(b: &mut test::Bencher) {
88     const BYTES: usize = 128 * 1024;
89     let temp_path = tmpdir();
90     let src_path = temp_path.join("file-copy-bench-src");
91     let mut src = crate::fs::OpenOptions::new()
92         .create(true)
93         .truncate(true)
94         .read(true)
95         .write(true)
96         .open(src_path)
97         .unwrap();
98     src.write(&vec![0u8; BYTES]).unwrap();
99
100     let sink_path = temp_path.join("file-copy-bench-sink");
101     let mut sink = crate::fs::OpenOptions::new()
102         .create(true)
103         .truncate(true)
104         .write(true)
105         .open(sink_path)
106         .unwrap();
107
108     b.bytes = BYTES as u64;
109     b.iter(|| {
110         src.seek(SeekFrom::Start(0)).unwrap();
111         sink.seek(SeekFrom::Start(0)).unwrap();
112         assert_eq!(BYTES as u64, io::copy(&mut src, &mut sink).unwrap());
113     });
114 }
115
116 #[bench]
117 fn bench_file_to_socket_copy(b: &mut test::Bencher) {
118     const BYTES: usize = 128 * 1024;
119     let temp_path = tmpdir();
120     let src_path = temp_path.join("pipe-copy-bench-src");
121     let mut src = OpenOptions::new()
122         .create(true)
123         .truncate(true)
124         .read(true)
125         .write(true)
126         .open(src_path)
127         .unwrap();
128     src.write(&vec![0u8; BYTES]).unwrap();
129
130     let sink_drainer = crate::net::TcpListener::bind("localhost:0").unwrap();
131     let mut sink = crate::net::TcpStream::connect(sink_drainer.local_addr().unwrap()).unwrap();
132     let mut sink_drainer = sink_drainer.accept().unwrap().0;
133
134     crate::thread::spawn(move || {
135         let mut sink_buf = vec![0u8; 1024 * 1024];
136         loop {
137             sink_drainer.read(&mut sink_buf[..]).unwrap();
138         }
139     });
140
141     b.bytes = BYTES as u64;
142     b.iter(|| {
143         src.seek(SeekFrom::Start(0)).unwrap();
144         assert_eq!(BYTES as u64, io::copy(&mut src, &mut sink).unwrap());
145     });
146 }
147
148 #[bench]
149 fn bench_file_to_uds_copy(b: &mut test::Bencher) {
150     const BYTES: usize = 128 * 1024;
151     let temp_path = tmpdir();
152     let src_path = temp_path.join("uds-copy-bench-src");
153     let mut src = OpenOptions::new()
154         .create(true)
155         .truncate(true)
156         .read(true)
157         .write(true)
158         .open(src_path)
159         .unwrap();
160     src.write(&vec![0u8; BYTES]).unwrap();
161
162     let (mut sink, mut sink_drainer) = crate::os::unix::net::UnixStream::pair().unwrap();
163
164     crate::thread::spawn(move || {
165         let mut sink_buf = vec![0u8; 1024 * 1024];
166         loop {
167             sink_drainer.read(&mut sink_buf[..]).unwrap();
168         }
169     });
170
171     b.bytes = BYTES as u64;
172     b.iter(|| {
173         src.seek(SeekFrom::Start(0)).unwrap();
174         assert_eq!(BYTES as u64, io::copy(&mut src, &mut sink).unwrap());
175     });
176 }
177
178 #[cfg(any(target_os = "linux", target_os = "android"))]
179 #[bench]
180 fn bench_socket_pipe_socket_copy(b: &mut test::Bencher) {
181     use super::CopyResult;
182     use crate::io::ErrorKind;
183     use crate::process::{ChildStdin, ChildStdout};
184     use crate::sys_common::FromInner;
185
186     let (read_end, write_end) = crate::sys::pipe::anon_pipe().unwrap();
187
188     let mut read_end = ChildStdout::from_inner(read_end);
189     let write_end = ChildStdin::from_inner(write_end);
190
191     let acceptor = crate::net::TcpListener::bind("localhost:0").unwrap();
192     let mut remote_end = crate::net::TcpStream::connect(acceptor.local_addr().unwrap()).unwrap();
193
194     let local_end = crate::sync::Arc::new(acceptor.accept().unwrap().0);
195
196     // the data flow in this benchmark:
197     //
198     //                      socket(tx)  local_source
199     // remote_end (write)  +-------->   (splice to)
200     //                                  write_end
201     //                                     +
202     //                                     |
203     //                                     | pipe
204     //                                     v
205     //                                  read_end
206     // remote_end (read)   <---------+  (splice to) *
207     //                      socket(rx)  local_end
208     //
209     // * benchmark loop using io::copy
210
211     crate::thread::spawn(move || {
212         let mut sink_buf = vec![0u8; 1024 * 1024];
213         remote_end.set_nonblocking(true).unwrap();
214         loop {
215             match remote_end.write(&mut sink_buf[..]) {
216                 Err(err) if err.kind() == ErrorKind::WouldBlock => {}
217                 Ok(_) => {}
218                 err => {
219                     err.expect("write failed");
220                 }
221             };
222             match remote_end.read(&mut sink_buf[..]) {
223                 Err(err) if err.kind() == ErrorKind::WouldBlock => {}
224                 Ok(_) => {}
225                 err => {
226                     err.expect("read failed");
227                 }
228             };
229         }
230     });
231
232     // check that splice works, otherwise the benchmark would hang
233     let probe = super::sendfile_splice(
234         super::SpliceMode::Splice,
235         local_end.as_raw_fd(),
236         write_end.as_raw_fd(),
237         1,
238     );
239
240     match probe {
241         CopyResult::Ended(1) => {
242             // splice works
243         }
244         _ => {
245             eprintln!("splice failed, skipping benchmark");
246             return;
247         }
248     }
249
250     let local_source = local_end.clone();
251     crate::thread::spawn(move || {
252         loop {
253             super::sendfile_splice(
254                 super::SpliceMode::Splice,
255                 local_source.as_raw_fd(),
256                 write_end.as_raw_fd(),
257                 u64::MAX,
258             );
259         }
260     });
261
262     const BYTES: usize = 128 * 1024;
263     b.bytes = BYTES as u64;
264     b.iter(|| {
265         assert_eq!(
266             BYTES as u64,
267             io::copy(&mut (&mut read_end).take(BYTES as u64), &mut &*local_end).unwrap()
268         );
269     });
270 }