Skip to content

Commit c77c77d

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

File tree

1 file changed

+168
-0
lines changed

1 file changed

+168
-0
lines changed

gio/tests/dbus_peer.rs

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

0 commit comments

Comments
 (0)