]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/unix/kernel_copy/tests.rs
Use `summary_opts()` in another spot
[rust.git] / library / std / src / sys / unix / kernel_copy / tests.rs
1 use crate::env::temp_dir;
2 use crate::fs::OpenOptions;
3 use crate::io;
4 use crate::io::Result;
5 use crate::io::SeekFrom;
6 use crate::io::{BufRead, Read, Seek, Write};
7 use crate::os::unix::io::AsRawFd;
8
9 #[test]
10 fn copy_specialization() -> Result<()> {
11     use crate::io::{BufReader, BufWriter};
12
13     let path = crate::env::temp_dir();
14     let source_path = path.join("copy-spec.source");
15     let sink_path = 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);
46         assert_eq!(sink.buffer().len(), 0);
47
48         let mut sink = sink.into_inner()?;
49         sink.seek(SeekFrom::Start(0))?;
50         let mut copied = Vec::new();
51         sink.read_to_end(&mut copied)?;
52         assert_eq!(&copied, b"000000wxyziklmnbcdef");
53     };
54
55     let rm1 = crate::fs::remove_file(source_path);
56     let rm2 = crate::fs::remove_file(sink_path);
57
58     result.and(rm1).and(rm2)
59 }
60
61 #[bench]
62 fn bench_file_to_file_copy(b: &mut test::Bencher) {
63     const BYTES: usize = 128 * 1024;
64     let src_path = temp_dir().join("file-copy-bench-src");
65     let mut src = crate::fs::OpenOptions::new()
66         .create(true)
67         .truncate(true)
68         .read(true)
69         .write(true)
70         .open(src_path)
71         .unwrap();
72     src.write(&vec![0u8; BYTES]).unwrap();
73
74     let sink_path = temp_dir().join("file-copy-bench-sink");
75     let mut sink = crate::fs::OpenOptions::new()
76         .create(true)
77         .truncate(true)
78         .write(true)
79         .open(sink_path)
80         .unwrap();
81
82     b.bytes = BYTES as u64;
83     b.iter(|| {
84         src.seek(SeekFrom::Start(0)).unwrap();
85         sink.seek(SeekFrom::Start(0)).unwrap();
86         assert_eq!(BYTES as u64, io::copy(&mut src, &mut sink).unwrap());
87     });
88 }
89
90 #[bench]
91 fn bench_file_to_socket_copy(b: &mut test::Bencher) {
92     const BYTES: usize = 128 * 1024;
93     let src_path = temp_dir().join("pipe-copy-bench-src");
94     let mut src = OpenOptions::new()
95         .create(true)
96         .truncate(true)
97         .read(true)
98         .write(true)
99         .open(src_path)
100         .unwrap();
101     src.write(&vec![0u8; BYTES]).unwrap();
102
103     let sink_drainer = crate::net::TcpListener::bind("localhost:0").unwrap();
104     let mut sink = crate::net::TcpStream::connect(sink_drainer.local_addr().unwrap()).unwrap();
105     let mut sink_drainer = sink_drainer.accept().unwrap().0;
106
107     crate::thread::spawn(move || {
108         let mut sink_buf = vec![0u8; 1024 * 1024];
109         loop {
110             sink_drainer.read(&mut sink_buf[..]).unwrap();
111         }
112     });
113
114     b.bytes = BYTES as u64;
115     b.iter(|| {
116         src.seek(SeekFrom::Start(0)).unwrap();
117         assert_eq!(BYTES as u64, io::copy(&mut src, &mut sink).unwrap());
118     });
119 }
120
121 #[bench]
122 fn bench_file_to_uds_copy(b: &mut test::Bencher) {
123     const BYTES: usize = 128 * 1024;
124     let src_path = temp_dir().join("uds-copy-bench-src");
125     let mut src = OpenOptions::new()
126         .create(true)
127         .truncate(true)
128         .read(true)
129         .write(true)
130         .open(src_path)
131         .unwrap();
132     src.write(&vec![0u8; BYTES]).unwrap();
133
134     let (mut sink, mut sink_drainer) = crate::os::unix::net::UnixStream::pair().unwrap();
135
136     crate::thread::spawn(move || {
137         let mut sink_buf = vec![0u8; 1024 * 1024];
138         loop {
139             sink_drainer.read(&mut sink_buf[..]).unwrap();
140         }
141     });
142
143     b.bytes = BYTES as u64;
144     b.iter(|| {
145         src.seek(SeekFrom::Start(0)).unwrap();
146         assert_eq!(BYTES as u64, io::copy(&mut src, &mut sink).unwrap());
147     });
148 }
149
150 #[cfg(any(target_os = "linux", target_os = "android"))]
151 #[bench]
152 fn bench_socket_pipe_socket_copy(b: &mut test::Bencher) {
153     use super::CopyResult;
154     use crate::io::ErrorKind;
155     use crate::process::{ChildStdin, ChildStdout};
156     use crate::sys_common::FromInner;
157
158     let (read_end, write_end) = crate::sys::pipe::anon_pipe().unwrap();
159
160     let mut read_end = ChildStdout::from_inner(read_end);
161     let write_end = ChildStdin::from_inner(write_end);
162
163     let acceptor = crate::net::TcpListener::bind("localhost:0").unwrap();
164     let mut remote_end = crate::net::TcpStream::connect(acceptor.local_addr().unwrap()).unwrap();
165
166     let local_end = crate::sync::Arc::new(acceptor.accept().unwrap().0);
167
168     // the data flow in this benchmark:
169     //
170     //                      socket(tx)  local_source
171     // remote_end (write)  +-------->   (splice to)
172     //                                  write_end
173     //                                     +
174     //                                     |
175     //                                     | pipe
176     //                                     v
177     //                                  read_end
178     // remote_end (read)   <---------+  (splice to) *
179     //                      socket(rx)  local_end
180     //
181     // * benchmark loop using io::copy
182
183     crate::thread::spawn(move || {
184         let mut sink_buf = vec![0u8; 1024 * 1024];
185         remote_end.set_nonblocking(true).unwrap();
186         loop {
187             match remote_end.write(&mut sink_buf[..]) {
188                 Err(err) if err.kind() == ErrorKind::WouldBlock => {}
189                 Ok(_) => {}
190                 err => {
191                     err.expect("write failed");
192                 }
193             };
194             match remote_end.read(&mut sink_buf[..]) {
195                 Err(err) if err.kind() == ErrorKind::WouldBlock => {}
196                 Ok(_) => {}
197                 err => {
198                     err.expect("read failed");
199                 }
200             };
201         }
202     });
203
204     // check that splice works, otherwise the benchmark would hang
205     let probe = super::sendfile_splice(
206         super::SpliceMode::Splice,
207         local_end.as_raw_fd(),
208         write_end.as_raw_fd(),
209         1,
210     );
211
212     match probe {
213         CopyResult::Ended(Ok(1)) => {
214             // splice works
215         }
216         _ => {
217             eprintln!("splice failed, skipping benchmark");
218             return;
219         }
220     }
221
222     let local_source = local_end.clone();
223     crate::thread::spawn(move || {
224         loop {
225             super::sendfile_splice(
226                 super::SpliceMode::Splice,
227                 local_source.as_raw_fd(),
228                 write_end.as_raw_fd(),
229                 u64::MAX,
230             );
231         }
232     });
233
234     const BYTES: usize = 128 * 1024;
235     b.bytes = BYTES as u64;
236     b.iter(|| {
237         assert_eq!(
238             BYTES as u64,
239             io::copy(&mut (&mut read_end).take(BYTES as u64), &mut &*local_end).unwrap()
240         );
241     });
242 }