Skip to content

Commit 7ca9723

Browse files
committed
add test for io sequence
Signed-off-by: uchouT <i@uchout.moe>
1 parent b96e148 commit 7ca9723

6 files changed

Lines changed: 987 additions & 21 deletions

File tree

crates/ironrdp-testsuite-core/tests/rdpeusb/client.rs

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,7 @@ use ironrdp_rdpeusb::pdu::{
1818
UrbdrcClientControlPdu, UrbdrcClientDevicePdu, UrbdrcServerControlPdu, UrbdrcServerDevicePdu,
1919
};
2020

21-
use super::simple_device_info;
22-
23-
const STREAM_ID_PROXY: u32 = 1;
24-
25-
fn proxy_iface_id(iface: InterfaceId) -> u32 {
26-
u32::from(iface) | (STREAM_ID_PROXY << 30)
27-
}
28-
29-
fn encode_pdu<T: ironrdp_core::Encode>(pdu: &T) -> Vec<u8> {
30-
encode_vec(pdu).expect("encode should succeed")
31-
}
21+
use super::{encode_pdu, proxy_iface_id, simple_device_info};
3222

3323
fn decode_control_msg(message: &DvcMessage) -> UrbdrcClientControlPdu {
3424
let encoded = encode_vec(message.as_ref()).expect("encode should succeed");
@@ -98,13 +88,11 @@ impl UrbdrcDeviceBackend for TestDeviceBackend {
9888

9989
fn cancel_request(&mut self, _request_id: RequestId, _channel_id: u32) {}
10090

101-
fn query_device_text(
102-
&mut self,
103-
_channel_id: u32,
104-
_text_type: u32,
105-
_locale_id: u32,
106-
) -> PduResult<Option<DeviceText>> {
107-
Ok(None)
91+
fn query_device_text(&mut self, _channel_id: u32, _text_type: u32, _locale_id: u32) -> PduResult<DeviceText> {
92+
Ok(DeviceText {
93+
hresult: 0,
94+
description: String::new(),
95+
})
10896
}
10997

11098
fn io_control(
Lines changed: 342 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
use std::sync::mpsc::{self, Receiver, Sender};
2+
3+
use ironrdp_core::encode_vec;
4+
use ironrdp_dvc::{DvcMessage, DvcProcessor as _};
5+
use ironrdp_pdu::PduResult;
6+
use ironrdp_rdpeusb::client::{UrbdrcDeviceBackend, UrbdrcDeviceClient};
7+
use ironrdp_rdpeusb::io::{
8+
DeviceAnnounce, DeviceText, InternalIoControlPacket, IoControlCompletionResult, IoControlPacket, RequestId,
9+
TransferInCompletionResult, TransferInPacket, TransferOutCompletionResult, TransferOutPacket,
10+
};
11+
use ironrdp_rdpeusb::pdu::header::InterfaceId;
12+
use ironrdp_rdpeusb::server::{UrbdrcDeviceServer, UrbdrcDeviceServerBackend};
13+
14+
use super::simple_device_info;
15+
16+
const CHANNEL_ID: u32 = 11;
17+
const DEVICE_TEXT_DESCRIPTION: &str = "Test USB device";
18+
const DEVICE_TEXT_HRESULT: u32 = 0;
19+
20+
#[derive(Debug)]
21+
enum ClientEvent {
22+
QueryDeviceText {
23+
channel_id: u32,
24+
text_type: u32,
25+
locale_id: u32,
26+
},
27+
IoControl {
28+
channel_id: u32,
29+
request_id: RequestId,
30+
request: IoControlPacket,
31+
},
32+
InternalIoControl {
33+
channel_id: u32,
34+
request_id: RequestId,
35+
request: InternalIoControlPacket,
36+
},
37+
TransferIn {
38+
channel_id: u32,
39+
request_id: RequestId,
40+
request: TransferInPacket,
41+
},
42+
TransferOut {
43+
channel_id: u32,
44+
request_id: RequestId,
45+
request: TransferOutPacket,
46+
},
47+
TransferOutNoAck {
48+
channel_id: u32,
49+
request_id: RequestId,
50+
request: TransferOutPacket,
51+
},
52+
Cancel {
53+
channel_id: u32,
54+
request_id: RequestId,
55+
},
56+
}
57+
58+
#[derive(Debug)]
59+
enum ServerEvent {
60+
DeviceText(DeviceText),
61+
IoControlCompleted {
62+
channel_id: u32,
63+
request_id: RequestId,
64+
completion: IoControlCompletionResult,
65+
},
66+
InternalIoControlCompleted {
67+
channel_id: u32,
68+
request_id: RequestId,
69+
completion: IoControlCompletionResult,
70+
},
71+
TransferInCompleted {
72+
channel_id: u32,
73+
request_id: RequestId,
74+
completion: TransferInCompletionResult,
75+
},
76+
TransferOutCompleted {
77+
channel_id: u32,
78+
request_id: RequestId,
79+
completion: TransferOutCompletionResult,
80+
},
81+
}
82+
83+
struct TestClientBackend {
84+
events: Sender<ClientEvent>,
85+
}
86+
87+
impl TestClientBackend {
88+
fn send(&self, event: ClientEvent) {
89+
self.events
90+
.send(event)
91+
.expect("client event receiver should remain connected");
92+
}
93+
}
94+
95+
impl UrbdrcDeviceBackend for TestClientBackend {
96+
fn device_info(&mut self, _channel_id: u32) -> PduResult<ironrdp_rdpeusb::io::DeviceInfo> {
97+
Ok(simple_device_info())
98+
}
99+
100+
fn cancel_request(&mut self, request_id: RequestId, channel_id: u32) {
101+
self.send(ClientEvent::Cancel { channel_id, request_id });
102+
}
103+
104+
fn query_device_text(&mut self, channel_id: u32, text_type: u32, locale_id: u32) -> PduResult<DeviceText> {
105+
self.send(ClientEvent::QueryDeviceText {
106+
channel_id,
107+
text_type,
108+
locale_id,
109+
});
110+
Ok(DeviceText {
111+
hresult: DEVICE_TEXT_HRESULT,
112+
description: DEVICE_TEXT_DESCRIPTION.to_owned(),
113+
})
114+
}
115+
116+
fn io_control(
117+
&mut self,
118+
channel_id: u32,
119+
request_id: RequestId,
120+
request: IoControlPacket,
121+
) -> PduResult<Option<IoControlCompletionResult>> {
122+
self.send(ClientEvent::IoControl {
123+
channel_id,
124+
request_id,
125+
request,
126+
});
127+
Ok(None)
128+
}
129+
130+
fn internal_io_control(
131+
&mut self,
132+
channel_id: u32,
133+
request_id: RequestId,
134+
request: InternalIoControlPacket,
135+
) -> PduResult<Option<IoControlCompletionResult>> {
136+
self.send(ClientEvent::InternalIoControl {
137+
channel_id,
138+
request_id,
139+
request,
140+
});
141+
Ok(None)
142+
}
143+
144+
fn transfer_in(
145+
&mut self,
146+
channel_id: u32,
147+
request_id: RequestId,
148+
request: TransferInPacket,
149+
) -> PduResult<Option<TransferInCompletionResult>> {
150+
self.send(ClientEvent::TransferIn {
151+
channel_id,
152+
request_id,
153+
request,
154+
});
155+
Ok(None)
156+
}
157+
158+
fn transfer_out(
159+
&mut self,
160+
channel_id: u32,
161+
request_id: RequestId,
162+
request: TransferOutPacket,
163+
) -> PduResult<Option<TransferOutCompletionResult>> {
164+
self.send(ClientEvent::TransferOut {
165+
channel_id,
166+
request_id,
167+
request,
168+
});
169+
Ok(None)
170+
}
171+
172+
fn transfer_out_no_ack(
173+
&mut self,
174+
channel_id: u32,
175+
request_id: RequestId,
176+
request: TransferOutPacket,
177+
) -> PduResult<()> {
178+
self.send(ClientEvent::TransferOutNoAck {
179+
channel_id,
180+
request_id,
181+
request,
182+
});
183+
Ok(())
184+
}
185+
186+
fn retract(&mut self, _channel_id: u32) -> PduResult<()> {
187+
Ok(())
188+
}
189+
}
190+
191+
struct TestServerBackend {
192+
events: Sender<ServerEvent>,
193+
}
194+
195+
impl TestServerBackend {
196+
fn send(&self, event: ServerEvent) {
197+
self.events
198+
.send(event)
199+
.expect("server event receiver should remain connected");
200+
}
201+
}
202+
203+
impl UrbdrcDeviceServerBackend for TestServerBackend {
204+
fn add_device(&mut self, _device: DeviceAnnounce) -> PduResult<()> {
205+
Ok(())
206+
}
207+
208+
fn device_text(&mut self, device_text: DeviceText) {
209+
self.send(ServerEvent::DeviceText(device_text));
210+
}
211+
212+
fn io_control_completed(
213+
&mut self,
214+
channel_id: u32,
215+
request_id: RequestId,
216+
completion: IoControlCompletionResult,
217+
) -> PduResult<()> {
218+
self.send(ServerEvent::IoControlCompleted {
219+
channel_id,
220+
request_id,
221+
completion,
222+
});
223+
Ok(())
224+
}
225+
226+
fn internal_io_control_completed(
227+
&mut self,
228+
channel_id: u32,
229+
request_id: RequestId,
230+
completion: IoControlCompletionResult,
231+
) -> PduResult<()> {
232+
self.send(ServerEvent::InternalIoControlCompleted {
233+
channel_id,
234+
request_id,
235+
completion,
236+
});
237+
Ok(())
238+
}
239+
240+
fn transfer_in_completed(
241+
&mut self,
242+
channel_id: u32,
243+
request_id: RequestId,
244+
completion: TransferInCompletionResult,
245+
) -> PduResult<()> {
246+
self.send(ServerEvent::TransferInCompleted {
247+
channel_id,
248+
request_id,
249+
completion,
250+
});
251+
Ok(())
252+
}
253+
254+
fn transfer_out_completed(
255+
&mut self,
256+
channel_id: u32,
257+
request_id: RequestId,
258+
completion: TransferOutCompletionResult,
259+
) -> PduResult<()> {
260+
self.send(ServerEvent::TransferOutCompleted {
261+
channel_id,
262+
request_id,
263+
completion,
264+
});
265+
Ok(())
266+
}
267+
}
268+
269+
struct ConnectedDevice {
270+
client: UrbdrcDeviceClient,
271+
server: UrbdrcDeviceServer,
272+
client_events: Receiver<ClientEvent>,
273+
server_events: Receiver<ServerEvent>,
274+
}
275+
276+
impl ConnectedDevice {
277+
fn new() -> Self {
278+
let udev_iface = InterfaceId::try_from(4).expect("valid device interface id");
279+
let completion_iface = InterfaceId::try_from(5).expect("valid completion interface id");
280+
let (client_events_tx, client_events) = mpsc::channel();
281+
let (server_events_tx, server_events) = mpsc::channel();
282+
283+
let client_backend = Box::new(TestClientBackend {
284+
events: client_events_tx,
285+
});
286+
let server_backend = Box::new(TestServerBackend {
287+
events: server_events_tx,
288+
});
289+
let mut client = UrbdrcDeviceClient::new(udev_iface, client_backend).expect("device client should be created");
290+
let mut server =
291+
UrbdrcDeviceServer::new(server_backend, completion_iface).expect("device server should be created");
292+
293+
let server_messages = server.start(CHANNEL_ID).expect("server start should succeed");
294+
let client_messages = process_message(&mut client, only_message(server_messages));
295+
let server_messages = process_message(&mut server, only_message(client_messages));
296+
let client_messages = process_message(&mut client, only_message(server_messages));
297+
let server_messages = process_message(&mut server, only_message(client_messages));
298+
assert_eq!(server_messages.len(), 2);
299+
for message in server_messages {
300+
assert!(process_message(&mut client, message).is_empty());
301+
}
302+
assert!(client.ready_for_io());
303+
304+
Self {
305+
client,
306+
server,
307+
client_events,
308+
server_events,
309+
}
310+
}
311+
312+
fn send_to_client(&mut self, message: DvcMessage) -> Vec<DvcMessage> {
313+
process_message(&mut self.client, message)
314+
}
315+
316+
fn send_to_server(&mut self, message: DvcMessage) -> Vec<DvcMessage> {
317+
process_message(&mut self.server, message)
318+
}
319+
320+
fn next_client_event(&self) -> ClientEvent {
321+
self.client_events.try_recv().expect("client backend should be called")
322+
}
323+
324+
fn next_server_event(&self) -> ServerEvent {
325+
self.server_events.try_recv().expect("server backend should be called")
326+
}
327+
}
328+
329+
fn process_message(processor: &mut dyn ironrdp_dvc::DvcProcessor, message: DvcMessage) -> Vec<DvcMessage> {
330+
let payload = encode_vec(message.as_ref()).expect("DVC message should encode");
331+
processor
332+
.process(CHANNEL_ID, &payload)
333+
.expect("DVC message should process")
334+
}
335+
336+
fn only_message(mut messages: Vec<DvcMessage>) -> DvcMessage {
337+
assert_eq!(messages.len(), 1);
338+
messages.pop().expect("one message should be present")
339+
}
340+
341+
mod requests;
342+
mod transfers;

0 commit comments

Comments
 (0)