Improve support for gpui tests that need multiple contexts

If a test function takes multiple contexts, pass it however many
distinct contexts are needed. Construct each one with a different
starting entity id so that they do not share any entity ids.
This commit is contained in:
Max Brunsfeld 2021-07-07 17:18:39 -07:00
parent 7335e70eb7
commit f46c0a790e
5 changed files with 26 additions and 24 deletions

1
Cargo.lock generated
View file

@ -1635,6 +1635,7 @@ dependencies = [
name = "gpui_macros" name = "gpui_macros"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"proc-macro2",
"quote", "quote",
"syn", "syn",
] ]

View file

@ -128,17 +128,6 @@ impl App {
f(&mut *cx) f(&mut *cx)
} }
pub fn test_async<T, F, Fn>(f: Fn) -> T
where
Fn: FnOnce(TestAppContext) -> F,
F: Future<Output = T>,
{
let foreground = Rc::new(executor::Foreground::test());
let cx = TestAppContext::new(foreground.clone());
let future = f(cx);
smol::block_on(foreground.run(future))
}
pub fn new(asset_source: impl AssetSource) -> Result<Self> { pub fn new(asset_source: impl AssetSource) -> Result<Self> {
let platform = platform::current::platform(); let platform = platform::current::platform();
let foreground_platform = platform::current::foreground_platform(); let foreground_platform = platform::current::foreground_platform();
@ -248,16 +237,18 @@ impl App {
} }
impl TestAppContext { impl TestAppContext {
pub fn new(foreground: Rc<executor::Foreground>) -> Self { pub fn new(foreground: Rc<executor::Foreground>, first_entity_id: usize) -> Self {
let platform = Arc::new(platform::test::platform()); let platform = Arc::new(platform::test::platform());
let foreground_platform = Rc::new(platform::test::foreground_platform()); let foreground_platform = Rc::new(platform::test::foreground_platform());
let cx = TestAppContext { let mut cx = MutableAppContext::new(
cx: Rc::new(RefCell::new(MutableAppContext::new(
foreground.clone(), foreground.clone(),
platform, platform,
foreground_platform.clone(), foreground_platform.clone(),
(), (),
))), );
cx.next_entity_id = first_entity_id;
let cx = TestAppContext {
cx: Rc::new(RefCell::new(cx)),
foreground_platform, foreground_platform,
}; };
cx.cx.borrow_mut().weak_self = Some(Rc::downgrade(&cx.cx)); cx.cx.borrow_mut().weak_self = Some(Rc::downgrade(&cx.cx));

View file

@ -31,3 +31,4 @@ pub use presenter::{
SizeConstraint, Vector2FExt, SizeConstraint, Vector2FExt,
}; };
pub use scoped_pool; pub use scoped_pool;
pub use smol::block_on;

View file

@ -9,3 +9,4 @@ proc-macro = true
[dependencies] [dependencies]
syn = "1.0" syn = "1.0"
quote = "1.0" quote = "1.0"
proc-macro2 = "1.0"

View file

@ -38,6 +38,16 @@ pub fn test(args: TokenStream, function: TokenStream) -> TokenStream {
let inner_fn_attributes = mem::take(&mut inner_fn.attrs); let inner_fn_attributes = mem::take(&mut inner_fn.attrs);
let inner_fn_name = format_ident!("_{}", inner_fn.sig.ident); let inner_fn_name = format_ident!("_{}", inner_fn.sig.ident);
let outer_fn_name = mem::replace(&mut inner_fn.sig.ident, inner_fn_name.clone()); let outer_fn_name = mem::replace(&mut inner_fn.sig.ident, inner_fn_name.clone());
// Pass to the test function the number of app contexts that it needs,
// based on its parameter list.
let inner_fn_args = (0..inner_fn.sig.inputs.len())
.map(|i| {
let first_entity_id = i * 100_000;
quote!(#namespace::TestAppContext::new(foreground.clone(), #first_entity_id),)
})
.collect::<proc_macro2::TokenStream>();
let mut outer_fn: ItemFn = if inner_fn.sig.asyncness.is_some() { let mut outer_fn: ItemFn = if inner_fn.sig.asyncness.is_some() {
parse_quote! { parse_quote! {
#[test] #[test]
@ -48,9 +58,8 @@ pub fn test(args: TokenStream, function: TokenStream) -> TokenStream {
let mut retries = 0; let mut retries = 0;
loop { loop {
let result = std::panic::catch_unwind(|| { let result = std::panic::catch_unwind(|| {
#namespace::App::test_async(move |cx| async { let foreground = ::std::rc::Rc::new(#namespace::executor::Foreground::test());
#inner_fn_name(cx).await; #namespace::block_on(foreground.run(#inner_fn_name(#inner_fn_args)));
});
}); });
match result { match result {
@ -66,9 +75,8 @@ pub fn test(args: TokenStream, function: TokenStream) -> TokenStream {
} }
} }
} else { } else {
#namespace::App::test_async(move |cx| async { let foreground = ::std::rc::Rc::new(#namespace::executor::Foreground::test());
#inner_fn_name(cx).await; #namespace::block_on(foreground.run(#inner_fn_name(#inner_fn_args)));
});
} }
} }
} }