#![allow(clippy::redundant_clone)]
use crossbeam_utils::thread::scope;
use std::{thread, time::Duration};
use super::{build_recursive, Element, ResolvedNode, SyntaxNode};
use cstree::{interning::IntoResolver, GreenNodeBuilder};
fn build_tree<D>(root: &Element<'_>) -> ResolvedNode<D> {
let mut builder = GreenNodeBuilder::new();
build_recursive(root, &mut builder, 0);
let (node, cache) = builder.finish();
SyntaxNode::new_root_with_resolver(node, cache.unwrap().into_interner().unwrap().into_resolver())
}
fn two_level_tree() -> Element<'static> {
use Element::*;
Node(vec![
Node(vec![Token("0.0"), Token("0.1")]),
Node(vec![Token("1.0")]),
Node(vec![Token("2.0"), Token("2.1"), Token("2.2")]),
])
}
#[test]
#[cfg_attr(miri, ignore)]
fn send() {
let tree = two_level_tree();
let tree = build_tree::<()>(&tree);
let thread_tree = tree.clone();
let thread = thread::spawn(move || {
let leaf1_0 = thread_tree
.children()
.nth(1)
.unwrap()
.children_with_tokens()
.next()
.unwrap();
let leaf1_0 = leaf1_0.into_token().unwrap();
leaf1_0.text().to_string()
});
assert_eq!(thread.join().unwrap(), "1.0");
}
#[test]
#[cfg_attr(miri, ignore)]
fn send_data() {
let tree = two_level_tree();
let tree = build_tree::<String>(&tree);
let thread_tree = tree.clone();
{
let node2 = tree.children().nth(2).unwrap();
assert_eq!(*node2.try_set_data("data".into()).unwrap(), "data");
let data = node2.get_data().unwrap();
assert_eq!(data.as_str(), "data");
node2.set_data("payload".into());
let data = node2.get_data().unwrap();
assert_eq!(data.as_str(), "payload");
}
let t = thread::spawn(move || {
let node2 = thread_tree.children().nth(2).unwrap();
assert!(node2.try_set_data("already present".into()).is_err());
let data = node2.get_data().unwrap();
assert_eq!(data.as_str(), "payload");
node2.set_data("new data".into());
});
t.join().unwrap();
{
let node2 = tree.children().nth(2).unwrap();
let data = node2.get_data().unwrap();
assert_eq!(data.as_str(), "new data");
node2.clear_data();
assert_eq!(data.as_str(), "new data");
}
let thread_tree = tree.clone();
thread::spawn(move || {
let node2 = thread_tree.children().nth(2).unwrap();
assert_eq!(node2.get_data(), None);
})
.join()
.unwrap();
}
#[test]
#[cfg_attr(miri, ignore)]
fn sync() {
let tree = two_level_tree();
let tree = build_tree::<()>(&tree);
let thread_tree = &tree;
let result = scope(move |s| {
s.spawn(move |_| {
let leaf1_0 = thread_tree
.children()
.nth(1)
.unwrap()
.children_with_tokens()
.next()
.unwrap();
let leaf1_0 = leaf1_0.into_token().unwrap();
leaf1_0.resolve_text(thread_tree.resolver().as_ref()).to_string()
})
.join()
.unwrap()
});
assert_eq!(result.unwrap(), "1.0");
}
#[test]
#[cfg_attr(miri, ignore)]
fn drop_send() {
let tree = two_level_tree();
let tree = build_tree::<()>(&tree);
let thread_tree = tree.clone();
let thread = thread::spawn(move || {
drop(thread_tree);
});
thread.join().unwrap();
thread::sleep(Duration::from_millis(500));
drop(tree);
let tree = two_level_tree();
let tree = build_tree::<()>(&tree);
let thread_tree = tree.clone();
drop(tree);
let thread = thread::spawn(move || {
thread::sleep(Duration::from_millis(500));
drop(thread_tree);
});
thread.join().unwrap();
}
#[test]
#[cfg_attr(miri, ignore)]
#[allow(clippy::drop_ref)]
fn drop_sync() {
let tree = two_level_tree();
let tree = build_tree::<()>(&tree);
let thread_tree = &tree;
scope(move |s| {
s.spawn(move |_| {
drop(thread_tree);
});
})
.unwrap();
thread::sleep(Duration::from_millis(500));
drop(tree);
}