Skip to content

Commit b556a3c

Browse files
committed
gio: Add test for DBus method calls over a UNIX fd pair
1 parent d2958b5 commit b556a3c

File tree

1 file changed

+159
-0
lines changed

1 file changed

+159
-0
lines changed

gio/tests/dbus_peer.rs

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
// Take a look at the license at the top of the repository in the LICENSE file.
2+
3+
#[cfg(unix)]
4+
#[test]
5+
fn test_gdbus_peer_connection() {
6+
use gio::{
7+
glib::{self, VariantTy},
8+
prelude::SocketExt,
9+
DBusConnection, DBusConnectionFlags, DBusNodeInfo, Socket,
10+
};
11+
use std::os::{fd::IntoRawFd, unix::net::UnixStream};
12+
13+
use gio::prelude::*;
14+
15+
const EXAMPLE_XML: &str = r#"
16+
<node>
17+
<interface name='com.github.gtk_rs'>
18+
<method name='Hello'>
19+
<arg type='s' name='name' direction='in'/>
20+
<arg type='s' name='greet' direction='out'/>
21+
</method>
22+
</interface>
23+
</node>
24+
"#;
25+
26+
pub async fn spawn_server(fd: UnixStream) -> DBusConnection {
27+
let socket = unsafe { Socket::from_fd(fd.into_raw_fd()) }.unwrap();
28+
let socket_connection = socket.connection_factory_create_connection();
29+
30+
let guid = gio::dbus_generate_guid();
31+
32+
dbg!("server connecting");
33+
34+
let connection = DBusConnection::new_future(
35+
&socket_connection,
36+
Some(&guid),
37+
DBusConnectionFlags::AUTHENTICATION_SERVER
38+
.union(DBusConnectionFlags::DELAY_MESSAGE_PROCESSING),
39+
None,
40+
)
41+
.await
42+
.unwrap();
43+
44+
dbg!("server connected");
45+
46+
let interface_info = DBusNodeInfo::for_xml(EXAMPLE_XML)
47+
.unwrap()
48+
.lookup_interface("com.github.gtk_rs")
49+
.unwrap();
50+
51+
let _id = connection
52+
.register_object("/com/github/gtk_rs", &interface_info)
53+
.method_call(
54+
|_connection,
55+
_sender,
56+
_object_path,
57+
_interface_name,
58+
_method_name,
59+
parameters,
60+
invocation| {
61+
dbg!(
62+
_sender,
63+
_object_path,
64+
_interface_name,
65+
_method_name,
66+
&parameters,
67+
&invocation
68+
);
69+
70+
let name = parameters.child_get::<String>(0);
71+
invocation.return_value(Some(&(format!("Hello {name}!"),).to_variant()));
72+
},
73+
)
74+
.build()
75+
.unwrap();
76+
77+
dbg!("server starts message processing");
78+
79+
connection.start_message_processing();
80+
81+
dbg!("server awaiting calls");
82+
83+
connection
84+
}
85+
86+
pub async fn spawn_client(fd: UnixStream) -> DBusConnection {
87+
let socket_client = unsafe { Socket::from_fd(fd.into_raw_fd()) }.unwrap();
88+
let socket_connection_client = socket_client.connection_factory_create_connection();
89+
90+
dbg!("client connecting");
91+
92+
let connection = DBusConnection::new_future(
93+
&socket_connection_client,
94+
None,
95+
DBusConnectionFlags::AUTHENTICATION_CLIENT,
96+
None,
97+
)
98+
.await
99+
.unwrap();
100+
101+
dbg!("client connected");
102+
103+
connection
104+
}
105+
106+
let ctx = glib::MainContext::default();
107+
108+
let (x, y) = std::os::unix::net::UnixStream::pair().unwrap();
109+
110+
x.set_nonblocking(true).unwrap();
111+
y.set_nonblocking(true).unwrap();
112+
113+
ctx.block_on(async move {
114+
let ctx = glib::MainContext::default();
115+
116+
let server = ctx.spawn_local(spawn_server(x));
117+
let client = ctx.spawn_local(spawn_client(y));
118+
119+
let server = server.await.unwrap();
120+
let client = client.await.unwrap();
121+
122+
dbg!("calling method");
123+
124+
let result = client
125+
.call_future(
126+
None,
127+
"/com/github/gtk_rs",
128+
"com.github.gtk_rs",
129+
"Hello",
130+
Some(&("World",).into()),
131+
Some(VariantTy::new("(s)").unwrap()),
132+
gio::DBusCallFlags::NONE,
133+
10000,
134+
)
135+
.await
136+
.unwrap();
137+
138+
dbg!("method called");
139+
140+
dbg!(&result);
141+
142+
dbg!("closing client");
143+
client.close_future().await.unwrap();
144+
dbg!("closed client, closing server");
145+
server.close_future().await.unwrap();
146+
dbg!("closed server");
147+
148+
drop(client);
149+
drop(server);
150+
151+
assert_eq!(result.child_get::<String>(0), "Hello World!");
152+
153+
glib::timeout_future_with_priority(
154+
glib::Priority::LOW,
155+
std::time::Duration::from_millis(50),
156+
)
157+
.await;
158+
});
159+
}

0 commit comments

Comments
 (0)