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