1cac7dca0Sopenharmony_ci// Copyright (c) 2023 Huawei Device Co., Ltd. 2cac7dca0Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 3cac7dca0Sopenharmony_ci// you may not use this file except in compliance with the License. 4cac7dca0Sopenharmony_ci// You may obtain a copy of the License at 5cac7dca0Sopenharmony_ci// 6cac7dca0Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 7cac7dca0Sopenharmony_ci// 8cac7dca0Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 9cac7dca0Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 10cac7dca0Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11cac7dca0Sopenharmony_ci// See the License for the specific language governing permissions and 12cac7dca0Sopenharmony_ci// limitations under the License. 13cac7dca0Sopenharmony_ci 14cac7dca0Sopenharmony_ci#![cfg(target_os = "linux")] 15cac7dca0Sopenharmony_ci 16cac7dca0Sopenharmony_ciuse std::collections::HashMap; 17cac7dca0Sopenharmony_ciuse std::io; 18cac7dca0Sopenharmony_ciuse std::io::{IoSlice, IoSliceMut, Read, Write}; 19cac7dca0Sopenharmony_ciuse std::net::Shutdown; 20cac7dca0Sopenharmony_ciuse std::os::fd::{FromRawFd, IntoRawFd}; 21cac7dca0Sopenharmony_ciuse std::str::from_utf8; 22cac7dca0Sopenharmony_ci 23cac7dca0Sopenharmony_ciuse ylong_io::{EventTrait, Events, Interest, Poll, Token, UnixDatagram, UnixListener, UnixStream}; 24cac7dca0Sopenharmony_ci 25cac7dca0Sopenharmony_ciconst PATH: &str = "/tmp/io_uds_path1"; 26cac7dca0Sopenharmony_ciconst SERVER: Token = Token(0); 27cac7dca0Sopenharmony_ci 28cac7dca0Sopenharmony_ci/// SDV test for UnixStream. 29cac7dca0Sopenharmony_ci/// 30cac7dca0Sopenharmony_ci/// # Brief 31cac7dca0Sopenharmony_ci/// 1. Create a pair of UnixStream. 32cac7dca0Sopenharmony_ci/// 2. Server sends "Hello client". 33cac7dca0Sopenharmony_ci/// 3. Client reads the message and sends "Hello server". 34cac7dca0Sopenharmony_ci/// 4. Server receives the message 35cac7dca0Sopenharmony_ci#[test] 36cac7dca0Sopenharmony_cifn sdv_uds_stream_test() { 37cac7dca0Sopenharmony_ci let _ = std::fs::remove_file(PATH); 38cac7dca0Sopenharmony_ci 39cac7dca0Sopenharmony_ci let handle = std::thread::spawn(server); 40cac7dca0Sopenharmony_ci 41cac7dca0Sopenharmony_ci let mut stream = loop { 42cac7dca0Sopenharmony_ci if let Ok(stream) = UnixStream::connect(PATH) { 43cac7dca0Sopenharmony_ci break stream; 44cac7dca0Sopenharmony_ci } 45cac7dca0Sopenharmony_ci }; 46cac7dca0Sopenharmony_ci loop { 47cac7dca0Sopenharmony_ci let mut buffer = [0_u8; 1024]; 48cac7dca0Sopenharmony_ci let slice = IoSliceMut::new(&mut buffer); 49cac7dca0Sopenharmony_ci std::thread::sleep(std::time::Duration::from_micros(300)); 50cac7dca0Sopenharmony_ci match stream.read_vectored(&mut [slice]) { 51cac7dca0Sopenharmony_ci Ok(n) => { 52cac7dca0Sopenharmony_ci assert_eq!(from_utf8(&buffer[0..n]).unwrap(), "Hello client"); 53cac7dca0Sopenharmony_ci break; 54cac7dca0Sopenharmony_ci } 55cac7dca0Sopenharmony_ci Err(_) => continue, 56cac7dca0Sopenharmony_ci } 57cac7dca0Sopenharmony_ci } 58cac7dca0Sopenharmony_ci 59cac7dca0Sopenharmony_ci let buf = b"Hello server"; 60cac7dca0Sopenharmony_ci let slice = IoSlice::new(buf); 61cac7dca0Sopenharmony_ci let n = stream.write_vectored(&[slice]).unwrap(); 62cac7dca0Sopenharmony_ci assert_eq!(n, 12); 63cac7dca0Sopenharmony_ci 64cac7dca0Sopenharmony_ci handle.join().unwrap().unwrap(); 65cac7dca0Sopenharmony_ci stream.shutdown(Shutdown::Both).unwrap(); 66cac7dca0Sopenharmony_ci std::fs::remove_file(PATH).unwrap(); 67cac7dca0Sopenharmony_ci} 68cac7dca0Sopenharmony_ci 69cac7dca0Sopenharmony_cifn server() -> io::Result<()> { 70cac7dca0Sopenharmony_ci let poll = Poll::new()?; 71cac7dca0Sopenharmony_ci let mut server = UnixListener::bind(PATH)?; 72cac7dca0Sopenharmony_ci 73cac7dca0Sopenharmony_ci poll.register(&mut server, SERVER, Interest::READABLE)?; 74cac7dca0Sopenharmony_ci let mut events = Events::with_capacity(128); 75cac7dca0Sopenharmony_ci // Map of `Token` -> `UnixListener`. 76cac7dca0Sopenharmony_ci let mut connections = HashMap::new(); 77cac7dca0Sopenharmony_ci let mut unique_token = Token(SERVER.0 + 1); 78cac7dca0Sopenharmony_ci for _ in 0..3 { 79cac7dca0Sopenharmony_ci poll.poll(&mut events, None)?; 80cac7dca0Sopenharmony_ci 81cac7dca0Sopenharmony_ci for event in events.iter() { 82cac7dca0Sopenharmony_ci if SERVER == event.token() { 83cac7dca0Sopenharmony_ci let (mut stream, _) = server.accept()?; 84cac7dca0Sopenharmony_ci let token = Token(unique_token.0 + 1); 85cac7dca0Sopenharmony_ci unique_token = Token(unique_token.0 + 1); 86cac7dca0Sopenharmony_ci poll.register(&mut stream, token, Interest::READABLE | Interest::WRITABLE)?; 87cac7dca0Sopenharmony_ci connections.insert(token, stream); 88cac7dca0Sopenharmony_ci } else { 89cac7dca0Sopenharmony_ci match connections.get_mut(&event.token()) { 90cac7dca0Sopenharmony_ci Some(connection) => { 91cac7dca0Sopenharmony_ci if event.is_writable() { 92cac7dca0Sopenharmony_ci match connection.write(b"Hello client") { 93cac7dca0Sopenharmony_ci Err(_) => { 94cac7dca0Sopenharmony_ci poll.deregister(connection)?; 95cac7dca0Sopenharmony_ci poll.register(connection, event.token(), Interest::READABLE)?; 96cac7dca0Sopenharmony_ci break; 97cac7dca0Sopenharmony_ci } 98cac7dca0Sopenharmony_ci Ok(_) => { 99cac7dca0Sopenharmony_ci poll.deregister(connection)?; 100cac7dca0Sopenharmony_ci poll.register(connection, event.token(), Interest::READABLE)?; 101cac7dca0Sopenharmony_ci break; 102cac7dca0Sopenharmony_ci } 103cac7dca0Sopenharmony_ci } 104cac7dca0Sopenharmony_ci } else if event.is_readable() { 105cac7dca0Sopenharmony_ci let mut msg_buf = [0_u8; 100]; 106cac7dca0Sopenharmony_ci match connection.read(&mut msg_buf) { 107cac7dca0Sopenharmony_ci Ok(0) => poll.deregister(connection)?, 108cac7dca0Sopenharmony_ci Ok(n) => { 109cac7dca0Sopenharmony_ci if let Ok(str_buf) = from_utf8(&msg_buf[0..n]) { 110cac7dca0Sopenharmony_ci assert_eq!(str_buf, "Hello server"); 111cac7dca0Sopenharmony_ci } else { 112cac7dca0Sopenharmony_ci println!("Received (none UTF-8) data: {:?}", &msg_buf); 113cac7dca0Sopenharmony_ci } 114cac7dca0Sopenharmony_ci } 115cac7dca0Sopenharmony_ci Err(_n) => { 116cac7dca0Sopenharmony_ci poll.deregister(connection)?; 117cac7dca0Sopenharmony_ci break; 118cac7dca0Sopenharmony_ci } 119cac7dca0Sopenharmony_ci } 120cac7dca0Sopenharmony_ci } 121cac7dca0Sopenharmony_ci } 122cac7dca0Sopenharmony_ci None => break, 123cac7dca0Sopenharmony_ci } 124cac7dca0Sopenharmony_ci } 125cac7dca0Sopenharmony_ci } 126cac7dca0Sopenharmony_ci } 127cac7dca0Sopenharmony_ci Ok(()) 128cac7dca0Sopenharmony_ci} 129cac7dca0Sopenharmony_ci 130cac7dca0Sopenharmony_ci/// SDV test for UnixDatagram. 131cac7dca0Sopenharmony_ci/// 132cac7dca0Sopenharmony_ci/// # Brief 133cac7dca0Sopenharmony_ci/// 1. Create a pair of UnixDatagram. 134cac7dca0Sopenharmony_ci/// 2. Sender sends message first. 135cac7dca0Sopenharmony_ci/// 3. Receiver receives message. 136cac7dca0Sopenharmony_ci/// 4. Check if the test results are correct. 137cac7dca0Sopenharmony_ci#[test] 138cac7dca0Sopenharmony_cifn sdv_uds_send_recv() { 139cac7dca0Sopenharmony_ci let (sender, _) = UnixDatagram::pair().unwrap(); 140cac7dca0Sopenharmony_ci let addr = sender.local_addr().unwrap(); 141cac7dca0Sopenharmony_ci let fmt = format!("{addr:?}"); 142cac7dca0Sopenharmony_ci assert_eq!(&fmt, "(unnamed)"); 143cac7dca0Sopenharmony_ci 144cac7dca0Sopenharmony_ci let addr = sender.peer_addr().unwrap(); 145cac7dca0Sopenharmony_ci let fmt = format!("{addr:?}"); 146cac7dca0Sopenharmony_ci assert_eq!(&fmt, "(unnamed)"); 147cac7dca0Sopenharmony_ci 148cac7dca0Sopenharmony_ci let sender2 = sender.try_clone().unwrap(); 149cac7dca0Sopenharmony_ci sender2.shutdown(Shutdown::Write).unwrap(); 150cac7dca0Sopenharmony_ci let n = sender2.send(b"Hello"); 151cac7dca0Sopenharmony_ci assert_eq!(n.unwrap_err().kind(), io::ErrorKind::BrokenPipe); 152cac7dca0Sopenharmony_ci 153cac7dca0Sopenharmony_ci let (sender, receiver) = UnixDatagram::pair().unwrap(); 154cac7dca0Sopenharmony_ci let n = sender.send(b"Hello").expect("sender send failed"); 155cac7dca0Sopenharmony_ci assert_eq!(n, "Hello".len()); 156cac7dca0Sopenharmony_ci let mut buf = [0; 5]; 157cac7dca0Sopenharmony_ci let ret = sender2.recv(&mut buf); 158cac7dca0Sopenharmony_ci assert!(ret.is_err()); 159cac7dca0Sopenharmony_ci 160cac7dca0Sopenharmony_ci let mut recv_buf = [0_u8; 12]; 161cac7dca0Sopenharmony_ci let fd = receiver.into_raw_fd(); 162cac7dca0Sopenharmony_ci let receiver = unsafe { UnixDatagram::from_raw_fd(fd) }; 163cac7dca0Sopenharmony_ci let len = loop { 164cac7dca0Sopenharmony_ci match receiver.recv_from(&mut recv_buf[..]) { 165cac7dca0Sopenharmony_ci Ok((n, addr)) => { 166cac7dca0Sopenharmony_ci let fmt = format!("{addr:?}"); 167cac7dca0Sopenharmony_ci assert_eq!(&fmt, "(unnamed)"); 168cac7dca0Sopenharmony_ci break n; 169cac7dca0Sopenharmony_ci } 170cac7dca0Sopenharmony_ci Err(e) if e.kind() == io::ErrorKind::WouldBlock => {} 171cac7dca0Sopenharmony_ci Err(e) => panic!("{:?}", e), 172cac7dca0Sopenharmony_ci } 173cac7dca0Sopenharmony_ci }; 174cac7dca0Sopenharmony_ci let fmt = format!("{receiver:?}"); 175cac7dca0Sopenharmony_ci let expected = format!("fd: FileDesc(OwnedFd {{ fd: {fd} }})"); 176cac7dca0Sopenharmony_ci assert!(fmt.contains(&expected)); 177cac7dca0Sopenharmony_ci assert!(fmt.contains("local: (unnamed), peer: (unnamed)")); 178cac7dca0Sopenharmony_ci 179cac7dca0Sopenharmony_ci assert_eq!(&recv_buf[..len], b"Hello"); 180cac7dca0Sopenharmony_ci} 181