Skip to content

Commit 5db1e9d

Browse files
committed
add basic bidirectional flow test
1 parent 32821aa commit 5db1e9d

1 file changed

Lines changed: 223 additions & 0 deletions

File tree

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
#![cfg(feature = "sysroot-abi")]
2+
3+
mod common {
4+
pub(crate) mod utils;
5+
}
6+
7+
use common::utils::{create_empty_token_tree, proc_macro_test_dylib_path, request, with_server};
8+
use expect_test::expect;
9+
use proc_macro_api::{
10+
ProtocolFormat::BidirectionalPostcardPrototype,
11+
bidirectional_protocol::{
12+
msg::{ExpandMacro, ExpandMacroData, ExpnGlobals, Request, Response},
13+
reject_subrequests,
14+
},
15+
legacy_protocol::msg::{PanicMessage, ServerConfig, SpanDataIndexMap, SpanMode},
16+
version::CURRENT_API_VERSION,
17+
};
18+
19+
#[test]
20+
fn test_bidi_version_check_bidirectional() {
21+
with_server(BidirectionalPostcardPrototype, |writer, reader| {
22+
let response =
23+
request(writer, reader, Request::ApiVersionCheck {}, Some(&reject_subrequests)).into();
24+
25+
match response {
26+
Response::ApiVersionCheck(version) => {
27+
assert_eq!(version, CURRENT_API_VERSION);
28+
}
29+
other => panic!("unexpected response: {other:?}"),
30+
}
31+
});
32+
}
33+
34+
#[test]
35+
fn test_bidi_list_macros() {
36+
with_server(BidirectionalPostcardPrototype, |writer, reader| {
37+
let dylib_path = proc_macro_test_dylib_path();
38+
let response =
39+
request(writer, reader, Request::ListMacros { dylib_path }, Some(&reject_subrequests))
40+
.into();
41+
42+
let Response::ListMacros(Ok(macros)) = response else {
43+
panic!("expected successful ListMacros response");
44+
};
45+
46+
let mut macro_list: Vec<_> =
47+
macros.iter().map(|(name, kind)| format!("{name} [{kind:?}]")).collect();
48+
macro_list.sort();
49+
let macro_list_str = macro_list.join("\n");
50+
51+
expect![[r#"
52+
DeriveEmpty [CustomDerive]
53+
DeriveError [CustomDerive]
54+
DerivePanic [CustomDerive]
55+
DeriveReemit [CustomDerive]
56+
attr_error [Attr]
57+
attr_noop [Attr]
58+
attr_panic [Attr]
59+
fn_like_clone_tokens [Bang]
60+
fn_like_error [Bang]
61+
fn_like_mk_idents [Bang]
62+
fn_like_mk_literals [Bang]
63+
fn_like_noop [Bang]
64+
fn_like_panic [Bang]
65+
fn_like_span_join [Bang]
66+
fn_like_span_line_column [Bang]
67+
fn_like_span_ops [Bang]"#]]
68+
.assert_eq(&macro_list_str);
69+
});
70+
}
71+
72+
#[test]
73+
fn test_bidi_list_macros_invalid_path() {
74+
with_server(BidirectionalPostcardPrototype, |writer, reader| {
75+
let response = request(
76+
writer,
77+
reader,
78+
Request::ListMacros { dylib_path: "/nonexistent/path/to/dylib.so".into() },
79+
Some(&reject_subrequests),
80+
)
81+
.into();
82+
83+
match response {
84+
Response::ListMacros(Err(e)) => assert!(
85+
e.starts_with("Cannot create expander for /nonexistent/path/to/dylib.so"),
86+
"{e}"
87+
),
88+
other => panic!("expected error response, got: {other:?}"),
89+
}
90+
});
91+
}
92+
93+
#[test]
94+
fn test_bidi_set_config() {
95+
with_server(BidirectionalPostcardPrototype, |writer, reader| {
96+
let config = ServerConfig { span_mode: SpanMode::Id };
97+
let response =
98+
request(writer, reader, Request::SetConfig(config), Some(&reject_subrequests)).into();
99+
100+
match response {
101+
Response::SetConfig(returned_config) => {
102+
assert_eq!(returned_config.span_mode, SpanMode::Id);
103+
}
104+
other => panic!("unexpected response: {other:?}"),
105+
}
106+
});
107+
}
108+
109+
#[test]
110+
fn test_bidi_set_config_rust_analyzer_mode() {
111+
with_server(BidirectionalPostcardPrototype, |writer, reader| {
112+
let config = ServerConfig { span_mode: SpanMode::RustAnalyzer };
113+
let response =
114+
request(writer, reader, Request::SetConfig(config), Some(&reject_subrequests)).into();
115+
116+
match response {
117+
Response::SetConfig(returned_config) => {
118+
assert_eq!(returned_config.span_mode, SpanMode::RustAnalyzer);
119+
}
120+
other => panic!("unexpected response: {other:?}"),
121+
}
122+
});
123+
}
124+
125+
#[test]
126+
fn test_bidi_expand_macro_panic() {
127+
with_server(BidirectionalPostcardPrototype, |writer, reader| {
128+
let dylib_path = proc_macro_test_dylib_path();
129+
130+
let mut span_data_table = SpanDataIndexMap::default();
131+
let macro_body =
132+
common::utils::create_empty_token_tree(CURRENT_API_VERSION, &mut span_data_table);
133+
134+
let request1 = Request::ExpandMacro(Box::new(ExpandMacro {
135+
lib: dylib_path,
136+
env: vec![],
137+
current_dir: None,
138+
data: ExpandMacroData {
139+
macro_body,
140+
macro_name: "fn_like_panic".to_owned(),
141+
attributes: None,
142+
has_global_spans: ExpnGlobals { def_site: 0, call_site: 0, mixed_site: 0 },
143+
span_data_table: vec![],
144+
},
145+
}));
146+
147+
let response = request(writer, reader, request1, Some(&reject_subrequests)).into();
148+
149+
match response {
150+
Response::ExpandMacro(Err(PanicMessage(msg))) => {
151+
assert!(msg.contains("fn_like_panic"), "panic message should mention macro name");
152+
}
153+
other => panic!("expected panic response, got: {other:?}"),
154+
}
155+
});
156+
}
157+
158+
#[test]
159+
fn test_bidi_basic_call_flow() {
160+
with_server(BidirectionalPostcardPrototype, |writer, reader| {
161+
let dylib_path = proc_macro_test_dylib_path();
162+
163+
let response1 =
164+
request(writer, reader, Request::ApiVersionCheck {}, Some(&reject_subrequests)).into();
165+
assert!(matches!(response1, Response::ApiVersionCheck(_)));
166+
167+
let response2 = request(
168+
writer,
169+
reader,
170+
Request::SetConfig(ServerConfig { span_mode: SpanMode::Id }),
171+
Some(&reject_subrequests),
172+
)
173+
.into();
174+
assert!(matches!(response2, Response::SetConfig(_)));
175+
176+
let response3 = request(
177+
writer,
178+
reader,
179+
Request::ListMacros { dylib_path: dylib_path.clone() },
180+
Some(&reject_subrequests),
181+
)
182+
.into();
183+
assert!(matches!(response3, Response::ListMacros(Ok(_))));
184+
});
185+
}
186+
187+
#[test]
188+
fn test_bidi_expand_nonexistent_macro() {
189+
with_server(BidirectionalPostcardPrototype, |writer, reader| {
190+
let dylib_path = proc_macro_test_dylib_path();
191+
192+
let version_response =
193+
request(writer, reader, Request::ApiVersionCheck {}, Some(&reject_subrequests)).into();
194+
let Response::ApiVersionCheck(version) = version_response else {
195+
panic!("expected version check response");
196+
};
197+
198+
let mut span_data_table = SpanDataIndexMap::default();
199+
let macro_body = create_empty_token_tree(version, &mut span_data_table);
200+
201+
let expand_request = Request::ExpandMacro(Box::new(ExpandMacro {
202+
lib: dylib_path,
203+
env: vec![],
204+
current_dir: None,
205+
data: ExpandMacroData {
206+
macro_body,
207+
macro_name: "NonexistentMacro".to_owned(),
208+
attributes: None,
209+
has_global_spans: ExpnGlobals { def_site: 0, call_site: 0, mixed_site: 0 },
210+
span_data_table: vec![],
211+
},
212+
}));
213+
214+
let response = request(writer, reader, expand_request, Some(&reject_subrequests)).into();
215+
216+
match response {
217+
Response::ExpandMacro(Err(PanicMessage(msg))) => {
218+
expect!["proc-macro `NonexistentMacro` is missing"].assert_eq(&msg)
219+
}
220+
other => panic!("expected error for nonexistent macro, got: {other:?}"),
221+
}
222+
});
223+
}

0 commit comments

Comments
 (0)