diff --git a/ylong_runtime/examples/ylong_runtime_task_hanging.rs b/ylong_runtime/examples/ylong_runtime_task_hanging.rs new file mode 100644 index 0000000000000000000000000000000000000000..5d2acfea478af8006b2a09c653ff4d20faf2d142 --- /dev/null +++ b/ylong_runtime/examples/ylong_runtime_task_hanging.rs @@ -0,0 +1,51 @@ +// Copyright (c) 2023 Huawei Device Co., Ltd. +// 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 +// +// http://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. + +//! A test for task hanging + +use std::sync::{Arc, Mutex}; +use std::thread; +use std::time::{Duration, Instant}; + +fn main() { + let resource_one = Arc::new(Mutex::new(1)); + let resource_two = Arc::new(Mutex::new(2)); + let r_one = resource_one.clone(); + let r_two = resource_two.clone(); + let start = Instant::now(); + let handle_one = ylong_runtime::spawn(async move { + let binding = resource_one.clone(); + let lock_one = binding.lock(); + thread::sleep(Duration::from_millis(100)); + drop(lock_one); + let binding = resource_two.clone(); + let _lock_two = binding.lock(); + 1 + }); + let handle_two = ylong_runtime::spawn(async move { + let binding = r_two.clone(); + let lock_two = binding.lock(); + thread::sleep(Duration::from_millis(100)); + drop(lock_two); + let binding = r_one.clone(); + let _lock_one = binding.lock(); + 2 + }); + + let one = ylong_runtime::block_on(handle_one).unwrap(); + let two = ylong_runtime::block_on(handle_two).unwrap(); + let dur = start.elapsed().as_millis(); + assert_eq!(one, 1); + assert_eq!(two, 2); + assert!(dur >= 100, "the duration should more than 100"); +} diff --git a/ylong_runtime/tests/tcp_test.rs b/ylong_runtime/tests/tcp_test.rs index c30981a665cb8ee2d8452abd64162d9a946c47c1..50f237cd64e40d54f0ec317e27b4a5a88f7d857a 100644 --- a/ylong_runtime/tests/tcp_test.rs +++ b/ylong_runtime/tests/tcp_test.rs @@ -13,6 +13,8 @@ #![cfg(feature = "net")] +use std::net::Shutdown; + use ylong_runtime::io::{AsyncReadExt, AsyncWriteExt}; use ylong_runtime::net::{TcpListener, TcpStream}; @@ -594,3 +596,42 @@ fn sdv_tcp_unexpected_eof() { client.cancel(); ylong_runtime::block_on(handle).unwrap(); } + +/// SDV case for IO operation failed +/// +/// # Breif +/// 1. Create a Tcp connection +/// 2. Close the client side before any data transmission +/// 3. Check if the server side gets an UnexpectedEof error +#[test] +#[cfg(feature = "time")] +fn sdv_tcp_server_client_close() { + let (tx, rx) = ylong_runtime::sync::oneshot::channel(); + let mut handles = Vec::new(); + handles.push(ylong_runtime::spawn(async move { + let tcp = TcpListener::bind(ADDR).await.unwrap(); + let addr = tcp.local_addr().unwrap(); + tx.send(addr).unwrap(); + let (mut stream, _) = tcp.accept().await.unwrap(); + let buf1 = [2; 10]; + stream.write_all(&buf1).await.unwrap(); + stream.shutdown(Shutdown::Both).unwrap(); + })); + handles.push(ylong_runtime::spawn(async move { + let addr = rx.await.unwrap(); + let mut tcp = TcpStream::connect(addr).await; + while tcp.is_err() { + tcp = TcpStream::connect(addr).await; + } + let mut tcp = tcp.unwrap(); + let mut buf2 = [0; 10]; + tcp.read_exact(&mut buf2).await.unwrap(); + assert_eq!(buf2, [2; 10]); + tcp.shutdown(Shutdown::Both).unwrap(); + let result = tcp.read_exact(&mut buf2).await.unwrap_err(); + assert_eq!(result.kind(), std::io::ErrorKind::UnexpectedEof); + })); + for handle in handles { + ylong_runtime::block_on(handle).unwrap(); + } +} \ No newline at end of file