Skip to content

Commit e8e0c7b

Browse files
committed
add basic bidirectional flow test
1 parent 632bb36 commit e8e0c7b

1 file changed

Lines changed: 233 additions & 0 deletions

File tree

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
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 {
143+
serialize: true,
144+
def_site: 0,
145+
call_site: 0,
146+
mixed_site: 0,
147+
},
148+
span_data_table: vec![],
149+
},
150+
}));
151+
152+
let response = request(writer, reader, request1, Some(&reject_subrequests)).into();
153+
154+
match response {
155+
Response::ExpandMacro(Err(PanicMessage(msg))) => {
156+
assert!(msg.contains("fn_like_panic"), "panic message should mention macro name");
157+
}
158+
other => panic!("expected panic response, got: {other:?}"),
159+
}
160+
});
161+
}
162+
163+
#[test]
164+
fn test_bidi_basic_call_flow() {
165+
with_server(BidirectionalPostcardPrototype, |writer, reader| {
166+
let dylib_path = proc_macro_test_dylib_path();
167+
168+
let response1 =
169+
request(writer, reader, Request::ApiVersionCheck {}, Some(&reject_subrequests)).into();
170+
assert!(matches!(response1, Response::ApiVersionCheck(_)));
171+
172+
let response2 = request(
173+
writer,
174+
reader,
175+
Request::SetConfig(ServerConfig { span_mode: SpanMode::Id }),
176+
Some(&reject_subrequests),
177+
)
178+
.into();
179+
assert!(matches!(response2, Response::SetConfig(_)));
180+
181+
let response3 = request(
182+
writer,
183+
reader,
184+
Request::ListMacros { dylib_path: dylib_path.clone() },
185+
Some(&reject_subrequests),
186+
)
187+
.into();
188+
assert!(matches!(response3, Response::ListMacros(Ok(_))));
189+
});
190+
}
191+
192+
#[test]
193+
fn test_bidi_expand_nonexistent_macro() {
194+
with_server(BidirectionalPostcardPrototype, |writer, reader| {
195+
let dylib_path = proc_macro_test_dylib_path();
196+
197+
let version_response =
198+
request(writer, reader, Request::ApiVersionCheck {}, Some(&reject_subrequests)).into();
199+
let Response::ApiVersionCheck(version) = version_response else {
200+
panic!("expected version check response");
201+
};
202+
203+
let mut span_data_table = SpanDataIndexMap::default();
204+
let macro_body = create_empty_token_tree(version, &mut span_data_table);
205+
206+
let expand_request = Request::ExpandMacro(Box::new(ExpandMacro {
207+
lib: dylib_path,
208+
env: vec![],
209+
current_dir: None,
210+
data: ExpandMacroData {
211+
macro_body,
212+
macro_name: "NonexistentMacro".to_owned(),
213+
attributes: None,
214+
has_global_spans: ExpnGlobals {
215+
serialize: version >= 3,
216+
def_site: 0,
217+
call_site: 0,
218+
mixed_site: 0,
219+
},
220+
span_data_table: vec![],
221+
},
222+
}));
223+
224+
let response = request(writer, reader, expand_request, Some(&reject_subrequests)).into();
225+
226+
match response {
227+
Response::ExpandMacro(Err(PanicMessage(msg))) => {
228+
expect!["proc-macro `NonexistentMacro` is missing"].assert_eq(&msg)
229+
}
230+
other => panic!("expected error for nonexistent macro, got: {other:?}"),
231+
}
232+
});
233+
}

0 commit comments

Comments
 (0)