// Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. extern crate env_logger; extern crate log; extern crate zmodem; #[macro_use] extern crate lazy_static; extern crate rand; use std::fs::{remove_file, File, OpenOptions}; use std::io::*; use std::process::*; use std::result; use std::thread::{sleep, spawn}; use std::time::*; extern crate kata_io; fn forget_err(_e: std::io::Error) -> kata_io::Error { kata_io::Error {} } struct ReadWrapper { r: R, } impl kata_io::Read for ReadWrapper { fn read(&mut self, buf: &mut [u8]) -> kata_io::Result { self.r.read(buf).map_err(forget_err) } } struct WriteWrapper { w: W, } impl kata_io::Write for WriteWrapper { fn write(&mut self, buf: &[u8]) -> kata_io::Result { self.w.write(buf).map_err(forget_err) } fn flush(&mut self) -> kata_io::Result<()> { self.w.flush().map_err(forget_err) } } struct SendInput { t: T, } impl kata_io::Read for SendInput { fn read(&mut self, buf: &mut [u8]) -> kata_io::Result { self.t.read(buf).map_err(forget_err) } } impl kata_io::Seek for SendInput { fn seek(&mut self, pos: kata_io::SeekFrom) -> kata_io::Result { let std_pos = match pos { kata_io::SeekFrom::Start(n) => std::io::SeekFrom::Start(n), kata_io::SeekFrom::End(n) => std::io::SeekFrom::End(n), kata_io::SeekFrom::Current(n) => std::io::SeekFrom::Current(n), }; self.t.seek(std_pos).map_err(forget_err) } } lazy_static! { static ref LOG_INIT: result::Result<(), log::SetLoggerError> = Ok(env_logger::init()); static ref RND_VALUES: Vec = { use rand::Rng; let mut rng = rand::thread_rng(); let mut buf = vec![0; 1024 * 1024 * 11]; rng.fill_bytes(&mut buf); buf }; } #[test] #[cfg(unix)] fn recv_from_sz() { let _ = LOG_INIT.is_ok(); let mut f = File::create("recv_from_sz").unwrap(); f.write_all(&RND_VALUES).unwrap(); let sz = Command::new("sz") .arg("recv_from_sz") .stdout(Stdio::piped()) .stdin(Stdio::piped()) .spawn() .expect("sz failed to run"); let mut c = Cursor::new(Vec::new()); zmodem::recv::recv( ReadWrapper { r: sz.stdout.unwrap(), }, WriteWrapper { w: sz.stdin.unwrap(), }, WriteWrapper { w: &mut c }, ) .unwrap(); sleep(Duration::from_millis(300)); remove_file("recv_from_sz").unwrap(); assert_eq!(RND_VALUES.clone(), c.into_inner()); } #[test] #[cfg(unix)] fn send_to_rz() { let _ = LOG_INIT.is_ok(); let _ = remove_file("send_to_rz"); let rz = Command::new("rz") .stdout(Stdio::piped()) .stdin(Stdio::piped()) .spawn() .expect("rz failed to run"); let len = RND_VALUES.len() as u32; let copy = RND_VALUES.clone(); sleep(Duration::from_millis(300)); zmodem::send::send( ReadWrapper { r: rz.stdout.unwrap(), }, WriteWrapper { w: rz.stdin.unwrap(), }, SendInput { t: Cursor::new(©), }, "send_to_rz", Some(len), ) .unwrap(); sleep(Duration::from_millis(300)); let mut f = File::open("send_to_rz").expect("open 'send_to_rz'"); let mut received = Vec::new(); f.read_to_end(&mut received).unwrap(); remove_file("send_to_rz").unwrap(); assert!(copy == received); } #[test] #[cfg(unix)] fn lib_send_recv() { let _ = LOG_INIT; let _ = remove_file("test-fifo1"); let _ = remove_file("test-fifo2"); let _ = Command::new("mkfifo") .arg("test-fifo1") .spawn() .expect("mkfifo failed to run") .wait(); let _ = Command::new("mkfifo") .arg("test-fifo2") .spawn() .expect("mkfifo failed to run") .wait(); sleep(Duration::from_millis(300)); spawn(move || { let outf = OpenOptions::new().write(true).open("test-fifo1").unwrap(); zmodem::send::send( ReadWrapper { r: File::open("test-fifo2").unwrap(), }, WriteWrapper { w: outf }, SendInput { t: Cursor::new(&RND_VALUES.clone()), }, "test", None, ) .unwrap(); }); let mut c = Cursor::new(Vec::new()); zmodem::recv::recv( ReadWrapper { r: File::open("test-fifo1").unwrap(), }, WriteWrapper { w: OpenOptions::new().write(true).open("test-fifo2").unwrap(), }, WriteWrapper { w: &mut c }, ) .unwrap(); let _ = remove_file("test-fifo1"); let _ = remove_file("test-fifo2"); assert_eq!(RND_VALUES.clone(), c.into_inner()); }