xref: /aosp_15_r20/external/crosvm/base/tests/linux/tube.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::time;
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker use base::deserialize_with_descriptors;
8*bb4ee6a4SAndroid Build Coastguard Worker use base::BlockingMode;
9*bb4ee6a4SAndroid Build Coastguard Worker use base::EventContext;
10*bb4ee6a4SAndroid Build Coastguard Worker use base::EventToken;
11*bb4ee6a4SAndroid Build Coastguard Worker use base::FramingMode;
12*bb4ee6a4SAndroid Build Coastguard Worker use base::FromRawDescriptor;
13*bb4ee6a4SAndroid Build Coastguard Worker use base::ReadNotifier;
14*bb4ee6a4SAndroid Build Coastguard Worker use base::SafeDescriptor;
15*bb4ee6a4SAndroid Build Coastguard Worker use base::SerializeDescriptors;
16*bb4ee6a4SAndroid Build Coastguard Worker use base::StreamChannel;
17*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube;
18*bb4ee6a4SAndroid Build Coastguard Worker use base::UnixSeqpacket;
19*bb4ee6a4SAndroid Build Coastguard Worker 
20*bb4ee6a4SAndroid Build Coastguard Worker #[derive(EventToken, Debug, Eq, PartialEq, Copy, Clone)]
21*bb4ee6a4SAndroid Build Coastguard Worker enum Token {
22*bb4ee6a4SAndroid Build Coastguard Worker     ReceivedData,
23*bb4ee6a4SAndroid Build Coastguard Worker }
24*bb4ee6a4SAndroid Build Coastguard Worker 
25*bb4ee6a4SAndroid Build Coastguard Worker const EVENT_WAIT_TIME: time::Duration = time::Duration::from_secs(10);
26*bb4ee6a4SAndroid Build Coastguard Worker 
27*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_serialize_tube_new()28*bb4ee6a4SAndroid Build Coastguard Worker fn test_serialize_tube_new() {
29*bb4ee6a4SAndroid Build Coastguard Worker     let (sock_send, sock_recv) =
30*bb4ee6a4SAndroid Build Coastguard Worker         StreamChannel::pair(BlockingMode::Nonblocking, FramingMode::Message).unwrap();
31*bb4ee6a4SAndroid Build Coastguard Worker     let tube_send = Tube::new(sock_send).unwrap();
32*bb4ee6a4SAndroid Build Coastguard Worker     let tube_recv = Tube::new(sock_recv).unwrap();
33*bb4ee6a4SAndroid Build Coastguard Worker 
34*bb4ee6a4SAndroid Build Coastguard Worker     // Serialize the Tube
35*bb4ee6a4SAndroid Build Coastguard Worker     let msg_serialize = SerializeDescriptors::new(&tube_send);
36*bb4ee6a4SAndroid Build Coastguard Worker     let serialized = serde_json::to_vec(&msg_serialize).unwrap();
37*bb4ee6a4SAndroid Build Coastguard Worker     let msg_descriptors = msg_serialize.into_descriptors();
38*bb4ee6a4SAndroid Build Coastguard Worker 
39*bb4ee6a4SAndroid Build Coastguard Worker     // Deserialize the Tube
40*bb4ee6a4SAndroid Build Coastguard Worker     let msg_descriptors_safe = msg_descriptors.into_iter().map(|v|
41*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: Safe because `v` is a valid descriptor
42*bb4ee6a4SAndroid Build Coastguard Worker             unsafe { SafeDescriptor::from_raw_descriptor(v) });
43*bb4ee6a4SAndroid Build Coastguard Worker     let tube_deserialized: Tube =
44*bb4ee6a4SAndroid Build Coastguard Worker         deserialize_with_descriptors(|| serde_json::from_slice(&serialized), msg_descriptors_safe)
45*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap();
46*bb4ee6a4SAndroid Build Coastguard Worker 
47*bb4ee6a4SAndroid Build Coastguard Worker     // Send a message through deserialized Tube
48*bb4ee6a4SAndroid Build Coastguard Worker     tube_deserialized.send(&"hi".to_string()).unwrap();
49*bb4ee6a4SAndroid Build Coastguard Worker 
50*bb4ee6a4SAndroid Build Coastguard Worker     // Wait for the message to arrive
51*bb4ee6a4SAndroid Build Coastguard Worker     let event_ctx: EventContext<Token> =
52*bb4ee6a4SAndroid Build Coastguard Worker         EventContext::build_with(&[(tube_recv.get_read_notifier(), Token::ReceivedData)]).unwrap();
53*bb4ee6a4SAndroid Build Coastguard Worker     let events = event_ctx.wait_timeout(EVENT_WAIT_TIME).unwrap();
54*bb4ee6a4SAndroid Build Coastguard Worker     let tokens: Vec<Token> = events
55*bb4ee6a4SAndroid Build Coastguard Worker         .iter()
56*bb4ee6a4SAndroid Build Coastguard Worker         .filter(|e| e.is_readable)
57*bb4ee6a4SAndroid Build Coastguard Worker         .map(|e| e.token)
58*bb4ee6a4SAndroid Build Coastguard Worker         .collect();
59*bb4ee6a4SAndroid Build Coastguard Worker     assert_eq!(tokens, vec! {Token::ReceivedData});
60*bb4ee6a4SAndroid Build Coastguard Worker 
61*bb4ee6a4SAndroid Build Coastguard Worker     assert_eq!(tube_recv.recv::<String>().unwrap(), "hi");
62*bb4ee6a4SAndroid Build Coastguard Worker }
63*bb4ee6a4SAndroid Build Coastguard Worker 
64*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_send_recv_new_from_seqpacket()65*bb4ee6a4SAndroid Build Coastguard Worker fn test_send_recv_new_from_seqpacket() {
66*bb4ee6a4SAndroid Build Coastguard Worker     let (sock_send, sock_recv) = UnixSeqpacket::pair().unwrap();
67*bb4ee6a4SAndroid Build Coastguard Worker     let tube_send = Tube::new_from_unix_seqpacket(sock_send).unwrap();
68*bb4ee6a4SAndroid Build Coastguard Worker     let tube_recv = Tube::new_from_unix_seqpacket(sock_recv).unwrap();
69*bb4ee6a4SAndroid Build Coastguard Worker 
70*bb4ee6a4SAndroid Build Coastguard Worker     tube_send.send(&"hi".to_string()).unwrap();
71*bb4ee6a4SAndroid Build Coastguard Worker 
72*bb4ee6a4SAndroid Build Coastguard Worker     // Wait for the message to arrive
73*bb4ee6a4SAndroid Build Coastguard Worker     let event_ctx: EventContext<Token> =
74*bb4ee6a4SAndroid Build Coastguard Worker         EventContext::build_with(&[(tube_recv.get_read_notifier(), Token::ReceivedData)]).unwrap();
75*bb4ee6a4SAndroid Build Coastguard Worker     let events = event_ctx.wait_timeout(EVENT_WAIT_TIME).unwrap();
76*bb4ee6a4SAndroid Build Coastguard Worker     let tokens: Vec<Token> = events
77*bb4ee6a4SAndroid Build Coastguard Worker         .iter()
78*bb4ee6a4SAndroid Build Coastguard Worker         .filter(|e| e.is_readable)
79*bb4ee6a4SAndroid Build Coastguard Worker         .map(|e| e.token)
80*bb4ee6a4SAndroid Build Coastguard Worker         .collect();
81*bb4ee6a4SAndroid Build Coastguard Worker     assert_eq!(tokens, vec! {Token::ReceivedData});
82*bb4ee6a4SAndroid Build Coastguard Worker 
83*bb4ee6a4SAndroid Build Coastguard Worker     assert_eq!(tube_recv.recv::<String>().unwrap(), "hi");
84*bb4ee6a4SAndroid Build Coastguard Worker }
85*bb4ee6a4SAndroid Build Coastguard Worker 
86*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_tube_new_byte_mode_error()87*bb4ee6a4SAndroid Build Coastguard Worker fn test_tube_new_byte_mode_error() {
88*bb4ee6a4SAndroid Build Coastguard Worker     let (sock_byte_mode, _) =
89*bb4ee6a4SAndroid Build Coastguard Worker         StreamChannel::pair(BlockingMode::Nonblocking, FramingMode::Byte).unwrap();
90*bb4ee6a4SAndroid Build Coastguard Worker     let tube_error = Tube::new(sock_byte_mode);
91*bb4ee6a4SAndroid Build Coastguard Worker 
92*bb4ee6a4SAndroid Build Coastguard Worker     assert!(tube_error.is_err());
93*bb4ee6a4SAndroid Build Coastguard Worker }
94