diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index 65a2504ab8..10df4cee9e 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -39,72 +39,11 @@ pub struct App(Arc>); impl App { pub fn production(asset_source: Arc) -> Self { - let http_client = http::client(); - Self::new(current_platform(), asset_source, http_client) - } - - #[cfg(any(test, feature = "test-support"))] - pub fn test(seed: u64) -> Self { - let platform = Arc::new(crate::TestPlatform::new(seed)); - let asset_source = Arc::new(()); - let http_client = util::http::FakeHttpClient::with_404_response(); - Self::new(platform, asset_source, http_client) - } - - fn new( - platform: Arc, - asset_source: Arc, - http_client: Arc, - ) -> Self { - let executor = platform.executor(); - assert!( - executor.is_main_thread(), - "must construct App on main thread" - ); - - let text_system = Arc::new(TextSystem::new(platform.text_system())); - let mut entities = EntityMap::new(); - let unit_entity = entities.insert(entities.reserve(), ()); - let app_metadata = AppMetadata { - os_name: platform.os_name(), - os_version: platform.os_version().ok(), - app_version: platform.app_version().ok(), - }; - - Self(Arc::new_cyclic(|this| { - Mutex::new(AppContext { - this: this.clone(), - text_system, - platform: MainThreadOnly::new(platform, executor.clone()), - app_metadata, - flushing_effects: false, - pending_updates: 0, - next_frame_callbacks: Default::default(), - executor, - svg_renderer: SvgRenderer::new(asset_source.clone()), - asset_source, - image_cache: ImageCache::new(http_client), - text_style_stack: Vec::new(), - globals_by_type: HashMap::default(), - unit_entity, - entities, - windows: SlotMap::with_key(), - keymap: Arc::new(RwLock::new(Keymap::default())), - global_action_listeners: HashMap::default(), - action_builders: HashMap::default(), - pending_effects: VecDeque::new(), - pending_notifications: HashSet::default(), - pending_global_notifications: HashSet::default(), - observers: SubscriberSet::new(), - event_listeners: SubscriberSet::new(), - release_listeners: SubscriberSet::new(), - global_observers: SubscriberSet::new(), - quit_observers: SubscriberSet::new(), - layout_id_buffer: Default::default(), - propagate_event: true, - active_drag: None, - }) - })) + Self(AppContext::new( + current_platform(), + asset_source, + http::client(), + )) } pub fn run(self, on_finish_launching: F) @@ -210,6 +149,62 @@ pub struct AppContext { } impl AppContext { + pub(crate) fn new( + platform: Arc, + asset_source: Arc, + http_client: Arc, + ) -> Arc> { + let executor = platform.executor(); + assert!( + executor.is_main_thread(), + "must construct App on main thread" + ); + + let text_system = Arc::new(TextSystem::new(platform.text_system())); + let mut entities = EntityMap::new(); + let unit_entity = entities.insert(entities.reserve(), ()); + let app_metadata = AppMetadata { + os_name: platform.os_name(), + os_version: platform.os_version().ok(), + app_version: platform.app_version().ok(), + }; + + Arc::new_cyclic(|this| { + Mutex::new(AppContext { + this: this.clone(), + text_system, + platform: MainThreadOnly::new(platform, executor.clone()), + app_metadata, + flushing_effects: false, + pending_updates: 0, + next_frame_callbacks: Default::default(), + executor, + svg_renderer: SvgRenderer::new(asset_source.clone()), + asset_source, + image_cache: ImageCache::new(http_client), + text_style_stack: Vec::new(), + globals_by_type: HashMap::default(), + unit_entity, + entities, + windows: SlotMap::with_key(), + keymap: Arc::new(RwLock::new(Keymap::default())), + global_action_listeners: HashMap::default(), + action_builders: HashMap::default(), + pending_effects: VecDeque::new(), + pending_notifications: HashSet::default(), + pending_global_notifications: HashSet::default(), + observers: SubscriberSet::new(), + event_listeners: SubscriberSet::new(), + release_listeners: SubscriberSet::new(), + global_observers: SubscriberSet::new(), + quit_observers: SubscriberSet::new(), + layout_id_buffer: Default::default(), + propagate_event: true, + active_drag: None, + }) + }) + } + pub fn quit(&mut self) { let mut futures = Vec::new(); diff --git a/crates/gpui2/src/app/test_context.rs b/crates/gpui2/src/app/test_context.rs index d31efca2c0..15e6dcb3a4 100644 --- a/crates/gpui2/src/app/test_context.rs +++ b/crates/gpui2/src/app/test_context.rs @@ -1,6 +1,6 @@ use crate::{ AnyWindowHandle, AppContext, AsyncAppContext, Context, Executor, Handle, MainThread, - ModelContext, Result, Task, WindowContext, + ModelContext, Result, Task, TestDispatcher, TestPlatform, WindowContext, }; use parking_lot::Mutex; use std::{any::Any, future::Future, sync::Arc}; @@ -37,6 +37,17 @@ impl Context for TestAppContext { } impl TestAppContext { + pub fn new(dispatcher: TestDispatcher) -> Self { + let executor = Executor::new(Arc::new(dispatcher)); + let platform = Arc::new(TestPlatform::new(executor.clone())); + let asset_source = Arc::new(()); + let http_client = util::http::FakeHttpClient::with_404_response(); + Self { + app: AppContext::new(platform, asset_source, http_client), + executor, + } + } + pub fn refresh(&mut self) -> Result<()> { let mut lock = self.app.lock(); lock.refresh(); @@ -47,27 +58,27 @@ impl TestAppContext { &self.executor } - pub fn update(&self, f: impl FnOnce(&mut AppContext) -> R) -> Result { + pub fn update(&self, f: impl FnOnce(&mut AppContext) -> R) -> R { let mut lock = self.app.lock(); - Ok(f(&mut *lock)) + f(&mut *lock) } pub fn read_window( &self, handle: AnyWindowHandle, - update: impl FnOnce(&WindowContext) -> R, - ) -> Result { + read: impl FnOnce(&WindowContext) -> R, + ) -> R { let mut app_context = self.app.lock(); - app_context.read_window(handle.id, update) + app_context.read_window(handle.id, read).unwrap() } pub fn update_window( &self, handle: AnyWindowHandle, update: impl FnOnce(&mut WindowContext) -> R, - ) -> Result { + ) -> R { let mut app = self.app.lock(); - app.update_window(handle.id, update) + app.update_window(handle.id, update).unwrap() } pub fn spawn(&self, f: impl FnOnce(AsyncAppContext) -> Fut + Send + 'static) -> Task @@ -94,22 +105,22 @@ impl TestAppContext { pub fn run_on_main( &self, f: impl FnOnce(&mut MainThread) -> R + Send + 'static, - ) -> Result> + ) -> Task where R: Send + 'static, { let mut app_context = self.app.lock(); - Ok(app_context.run_on_main(f)) + app_context.run_on_main(f) } - pub fn has_global(&self) -> Result { + pub fn has_global(&self) -> bool { let lock = self.app.lock(); - Ok(lock.has_global::()) + lock.has_global::() } - pub fn read_global(&self, read: impl FnOnce(&G, &AppContext) -> R) -> Result { + pub fn read_global(&self, read: impl FnOnce(&G, &AppContext) -> R) -> R { let lock = self.app.lock(); - Ok(read(lock.global(), &lock)) + read(lock.global(), &lock) } pub fn try_read_global( @@ -123,9 +134,9 @@ impl TestAppContext { pub fn update_global( &mut self, update: impl FnOnce(&mut G, &mut AppContext) -> R, - ) -> Result { + ) -> R { let mut lock = self.app.lock(); - Ok(lock.update_global(update)) + lock.update_global(update) } fn to_async(&self) -> AsyncAppContext { diff --git a/crates/gpui2/src/platform/test/platform.rs b/crates/gpui2/src/platform/test/platform.rs index f4e88756c0..01c56090f7 100644 --- a/crates/gpui2/src/platform/test/platform.rs +++ b/crates/gpui2/src/platform/test/platform.rs @@ -1,5 +1,4 @@ -use crate::{DisplayId, Executor, Platform, PlatformTextSystem, TestDispatcher}; -use rand::prelude::*; +use crate::{DisplayId, Executor, Platform, PlatformTextSystem}; use std::sync::Arc; pub struct TestPlatform { @@ -7,11 +6,8 @@ pub struct TestPlatform { } impl TestPlatform { - pub fn new(seed: u64) -> Self { - let rng = StdRng::seed_from_u64(seed); - TestPlatform { - executor: Executor::new(Arc::new(TestDispatcher::new(rng))), - } + pub fn new(executor: Executor) -> Self { + TestPlatform { executor } } } diff --git a/crates/gpui2/src/text_system/line_wrapper.rs b/crates/gpui2/src/text_system/line_wrapper.rs index 3420ed1be4..99950fbe10 100644 --- a/crates/gpui2/src/text_system/line_wrapper.rs +++ b/crates/gpui2/src/text_system/line_wrapper.rs @@ -139,11 +139,15 @@ impl Boundary { #[cfg(test)] mod tests { use super::*; - use crate::{font, App}; + use crate::{font, TestAppContext, TestDispatcher}; + use rand::prelude::*; #[test] fn test_wrap_line() { - App::test(0).run(|cx| { + let dispatcher = TestDispatcher::new(StdRng::seed_from_u64(0)); + let cx = TestAppContext::new(dispatcher); + + cx.update(|cx| { let text_system = cx.text_system().clone(); let mut wrapper = LineWrapper::new( text_system.font_id(&font("Courier")).unwrap(),