mirror of
https://github.com/enso-org/enso.git
synced 2024-12-19 07:02:04 +03:00
Fix problems with tests run in parallel (https://github.com/enso-org/ide/pull/332)
Global spawner was made thread local.
Original commit: 8931df9b44
This commit is contained in:
parent
160811f506
commit
97c146fbdc
@ -26,11 +26,16 @@ use crate::prelude::*;
|
||||
use futures::task::LocalSpawnExt;
|
||||
use futures::task::LocalSpawn;
|
||||
|
||||
/// Global spawner handle.
|
||||
///
|
||||
/// It should be set up once, as part of the IDE initialization routine and
|
||||
/// remain accessible indefinitely.
|
||||
static mut SPAWNER: Option<Box<dyn LocalSpawn>> = None;
|
||||
thread_local! {
|
||||
/// Global spawner handle.
|
||||
///
|
||||
/// It should be set up once, as part of the IDE initialization routine and
|
||||
/// remain accessible indefinitely.
|
||||
///
|
||||
/// This is made thread local for tests which may be run in parallel; Each test should set
|
||||
/// executor independently.
|
||||
static SPAWNER: RefCell<Option<Box<dyn LocalSpawn>>> = default();
|
||||
}
|
||||
|
||||
/// Sets the global spawner. It will remain accessible until it is set again to
|
||||
/// something else.
|
||||
@ -40,29 +45,26 @@ static mut SPAWNER: Option<Box<dyn LocalSpawn>> = None;
|
||||
#[allow(unsafe_code)]
|
||||
pub fn set_spawner(spawner_to_set:impl LocalSpawn + 'static) {
|
||||
// Note [Global Executor Safety]
|
||||
unsafe {
|
||||
SPAWNER = Some(Box::new(spawner_to_set));
|
||||
}
|
||||
SPAWNER.with(|s| *s.borrow_mut() = Some(Box::new(spawner_to_set)));
|
||||
}
|
||||
|
||||
// Note [Global Executor Safety]
|
||||
// =============================
|
||||
// This is safe, because the global mutable state is only accessed through the
|
||||
// two functions provided in this module, the code will be used only in a web
|
||||
// single-threaded environment (so no race conditions are possible), and the
|
||||
// functions do not leak reference to the global spawner.
|
||||
|
||||
/// Spawns a task using the global spawner.
|
||||
/// Panics, if called when there is no global spawner set or if it fails to
|
||||
/// spawn task (e.g. because the connected executor was prematurely dropped).
|
||||
#[allow(unsafe_code)]
|
||||
pub fn spawn(f:impl Future<Output=()> + 'static) {
|
||||
// Note [Global Executor Safety]
|
||||
let spawner = unsafe {
|
||||
SPAWNER.with(|spawner| {
|
||||
let error_msg = "No global executor has been provided.";
|
||||
SPAWNER.as_mut().expect(error_msg)
|
||||
};
|
||||
|
||||
let error_msg = "Failed to spawn the task. Global executor might have been dropped.";
|
||||
spawner.spawn_local(f).expect(error_msg);
|
||||
// Note [Global Executor Safety]
|
||||
let mut borrowed = spawner.borrow_mut();
|
||||
let unwrapped = borrowed.as_mut().expect(error_msg);
|
||||
let error_msg = "Failed to spawn the task. Global executor might have been dropped.";
|
||||
unwrapped.spawn_local(f).expect(error_msg);
|
||||
});
|
||||
}
|
||||
|
||||
// Note [Global Executor Safety]
|
||||
// =============================
|
||||
// This borrowing is safe, because the global mutable state is only accessed through the
|
||||
// two functions provided in this module, and the functions do not leak reference to the global
|
||||
// spawner.
|
||||
|
@ -219,7 +219,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn notifying() {
|
||||
let mut test = TestWithLocalPoolExecutor::set_up();
|
||||
let mut test = TestWithLocalPoolExecutor::set_up();
|
||||
test.run_task(async {
|
||||
let module = Module::default();
|
||||
let mut text_subscription = module.subscribe_text_notifications();
|
||||
@ -259,21 +259,24 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn handling_metadata() {
|
||||
let module = Module::default();
|
||||
let mut test = TestWithLocalPoolExecutor::set_up();
|
||||
test.run_task(async {
|
||||
let module = Module::default();
|
||||
|
||||
let id = Uuid::new_v4();
|
||||
let initial_md = module.node_metadata(id.clone());
|
||||
assert!(initial_md.is_err());
|
||||
let id = Uuid::new_v4();
|
||||
let initial_md = module.node_metadata(id.clone());
|
||||
assert!(initial_md.is_err());
|
||||
|
||||
let md_to_set = NodeMetadata {position:Some(Position::new(1.0, 2.0))};
|
||||
module.set_node_metadata(id.clone(),md_to_set.clone());
|
||||
assert_eq!(md_to_set.position, module.node_metadata(id.clone()).unwrap().position);
|
||||
let md_to_set = NodeMetadata {position:Some(Position::new(1.0, 2.0))};
|
||||
module.set_node_metadata(id.clone(),md_to_set.clone());
|
||||
assert_eq!(md_to_set.position, module.node_metadata(id.clone()).unwrap().position);
|
||||
|
||||
let new_pos = Position::new(4.0, 5.0);
|
||||
module.with_node_metadata(id.clone(), |md| {
|
||||
assert_eq!(md_to_set.position, md.position);
|
||||
md.position = Some(new_pos);
|
||||
let new_pos = Position::new(4.0, 5.0);
|
||||
module.with_node_metadata(id.clone(), |md| {
|
||||
assert_eq!(md_to_set.position, md.position);
|
||||
md.position = Some(new_pos);
|
||||
});
|
||||
assert_eq!(Some(new_pos), module.node_metadata(id).unwrap().position);
|
||||
});
|
||||
assert_eq!(Some(new_pos), module.node_metadata(id).unwrap().position);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user