Backport official GLib iterator safety fix for Linux desktop
This commit is contained in:
1 parent
43c43ebdc9
commit
8ef874c609
133 files changed
+55342
-2
No files matched your search
+635
@@ -0,0 +1,635 @@
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
panic,
|
||||
rc::Rc,
|
||||
sync::{Arc, Mutex},
|
||||
thread,
|
||||
};
|
||||
|
||||
use futures_executor::block_on;
|
||||
use glib::clone;
|
||||
|
||||
struct State {
|
||||
count: i32,
|
||||
started: bool,
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
count: 0,
|
||||
started: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clone_and_references() {
|
||||
let state = Rc::new(RefCell::new(State::new()));
|
||||
let ref_state = &state;
|
||||
assert!(!ref_state.borrow().started);
|
||||
|
||||
let closure = {
|
||||
clone!(@weak ref_state => move || {
|
||||
ref_state.borrow_mut().started = true;
|
||||
})
|
||||
};
|
||||
|
||||
closure();
|
||||
assert!(ref_state.borrow().started);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn subfields_renaming() {
|
||||
struct Foo {
|
||||
v: Rc<usize>,
|
||||
}
|
||||
|
||||
impl Foo {
|
||||
fn foo(&self) {
|
||||
let state = Rc::new(RefCell::new(State::new()));
|
||||
|
||||
let closure = clone!(@strong self.v as v, @weak state as hello => move |_| {
|
||||
println!("v: {v}");
|
||||
hello.borrow_mut().started = true;
|
||||
});
|
||||
closure(2);
|
||||
}
|
||||
}
|
||||
|
||||
Foo { v: Rc::new(0) }.foo();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn renaming() {
|
||||
let state = Rc::new(RefCell::new(State::new()));
|
||||
assert!(!state.borrow().started);
|
||||
|
||||
let closure = {
|
||||
clone!(@weak state as hello => move || {
|
||||
hello.borrow_mut().started = true;
|
||||
})
|
||||
};
|
||||
|
||||
closure();
|
||||
assert!(state.borrow().started);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clone_closure() {
|
||||
let state = Rc::new(RefCell::new(State::new()));
|
||||
assert!(!state.borrow().started);
|
||||
|
||||
let closure = {
|
||||
clone!(@weak state => move || {
|
||||
state.borrow_mut().started = true;
|
||||
})
|
||||
};
|
||||
|
||||
closure();
|
||||
|
||||
assert!(state.borrow().started);
|
||||
assert_eq!(state.borrow().count, 0);
|
||||
|
||||
let closure = {
|
||||
let state2 = Rc::new(RefCell::new(State::new()));
|
||||
assert!(state.borrow().started);
|
||||
|
||||
clone!(@weak state, @strong state2 => move || {
|
||||
state.borrow_mut().count += 1;
|
||||
state.borrow_mut().started = true;
|
||||
state2.borrow_mut().started = true;
|
||||
})
|
||||
};
|
||||
|
||||
closure();
|
||||
|
||||
assert_eq!(state.borrow().count, 1);
|
||||
assert!(state.borrow().started);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clone_default_value() {
|
||||
let closure = {
|
||||
let state = Rc::new(RefCell::new(State::new()));
|
||||
clone!(@weak state => @default-return 42, move |_| {
|
||||
state.borrow_mut().started = true;
|
||||
10
|
||||
})
|
||||
};
|
||||
|
||||
assert_eq!(42, closure(50));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clone_panic() {
|
||||
let state = Arc::new(Mutex::new(State::new()));
|
||||
state.lock().expect("Failed to lock state mutex").count = 20;
|
||||
|
||||
let closure = {
|
||||
let state2 = Arc::new(Mutex::new(State::new()));
|
||||
clone!(@weak state2, @strong state => @default-return panic!(), move |_| {
|
||||
state.lock().expect("Failed to lock state mutex").count = 21;
|
||||
state2.lock().expect("Failed to lock state2 mutex").started = true;
|
||||
10
|
||||
})
|
||||
};
|
||||
|
||||
let result = panic::catch_unwind(|| {
|
||||
closure(50);
|
||||
});
|
||||
|
||||
assert!(result.is_err());
|
||||
|
||||
assert_eq!(state.lock().expect("Failed to lock state mutex").count, 20);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clone_import_rename() {
|
||||
import_rename::test();
|
||||
}
|
||||
|
||||
mod import_rename {
|
||||
use glib::clone as clone_g;
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! clone {
|
||||
($($anything:tt)*) => {
|
||||
|_, _| panic!("The clone! macro doesn't support renaming")
|
||||
};
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
pub fn test() {
|
||||
let n = 2;
|
||||
|
||||
let closure: Box<dyn Fn(u32, u32)> = Box::new(clone_g!(
|
||||
@strong n
|
||||
=> move |_, _|
|
||||
println!("The clone! macro does support renaming")
|
||||
));
|
||||
|
||||
closure(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clone_macro_self_rename() {
|
||||
#[derive(Debug)]
|
||||
struct Foo {
|
||||
v: u8,
|
||||
}
|
||||
|
||||
impl Foo {
|
||||
#[allow(dead_code)]
|
||||
fn foo(&self) {
|
||||
let closure = clone!(@strong self as this => move |_x| {
|
||||
println!("v: {this:?}");
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@strong self as this => move || {
|
||||
println!("v: {this:?}");
|
||||
});
|
||||
let closure = clone!(@strong self as this => move |_x| println!("v: {this:?}"));
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@strong self as this => move || println!("v: {this:?}"));
|
||||
|
||||
// Fields now!
|
||||
let closure = clone!(@strong self.v as v => move |_x| {
|
||||
println!("v: {v:?}");
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@strong self.v as v => move || println!("v: {v:?}"));
|
||||
|
||||
// With @default-panic
|
||||
let closure = clone!(@strong self.v as v => @default-panic, move |_x| {
|
||||
println!("v: {v:?}");
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@strong self.v as v => @default-panic, move || println!("v: {v:?}"));
|
||||
|
||||
// With @default-return
|
||||
let closure = clone!(@strong self.v as _v => @default-return true, move |_x| {
|
||||
false
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@strong self.v as _v => @default-return true, move || false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clone_macro_rename() {
|
||||
let v = Rc::new(1);
|
||||
|
||||
let closure = clone!(@weak v as y => @default-panic, move |_x| {
|
||||
println!("v: {y}");
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@weak v as y => @default-panic, move || println!("v: {y}"));
|
||||
|
||||
let closure = clone!(@strong v as y => @default-panic, move |_x| {
|
||||
println!("v: {y}");
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@strong v as y => @default-panic, move || println!("v: {y}"));
|
||||
|
||||
let closure = clone!(@weak v as y => move |_x| {
|
||||
println!("v: {y}");
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@weak v as y => move || println!("v: {y}"));
|
||||
|
||||
let closure = clone!(@strong v as y => move |_x| {
|
||||
println!("v: {y}");
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@strong v as y => move || println!("v: {y}"));
|
||||
|
||||
let closure = clone!(@weak v as _y => @default-return true, move |_x| {
|
||||
false
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@weak v as _y => @default-return true, move || false);
|
||||
|
||||
let closure = clone!(@strong v as _y => @default-return true, move |_x| false);
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@strong v as _y => @default-return true, move || false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clone_macro_simple() {
|
||||
let v = Rc::new(1);
|
||||
|
||||
let closure = clone!(@weak v => @default-panic, move |_x| {
|
||||
println!("v: {v}");
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@weak v => @default-panic, move || println!("v: {v}"));
|
||||
|
||||
let closure = clone!(@strong v => @default-panic, move |_x| {
|
||||
println!("v: {v}");
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@strong v => @default-panic, move || println!("v: {v}"));
|
||||
|
||||
let closure = clone!(@weak v => move |_x| {
|
||||
println!("v: {v}");
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@weak v => move || println!("v: {v}"));
|
||||
|
||||
let closure = clone!(@strong v => move |_x| {
|
||||
println!("v: {v}");
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@strong v => move || println!("v: {v}"));
|
||||
|
||||
let closure = clone!(@weak v => @default-return true, move |_x| {
|
||||
false
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@weak v => @default-return true, move || false);
|
||||
|
||||
let closure = clone!(@strong v => @default-return true, move |_x| false);
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@strong v => @default-return true, move || false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clone_macro_double_simple() {
|
||||
let v = Rc::new(1);
|
||||
let w = Rc::new(2);
|
||||
|
||||
let closure = clone!(@weak v, @weak w => @default-panic, move |_x| {
|
||||
println!("v: {v}, w: {w}");
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@weak v, @weak w => @default-panic, move || println!("v: {v}, w: {w}"));
|
||||
|
||||
let closure = clone!(@strong v, @strong w => @default-panic, move |_x| {
|
||||
println!("v: {v}, w: {w}");
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@strong v, @strong w => @default-panic, move || println!("v: {v}, w: {w}"));
|
||||
|
||||
let closure = clone!(@weak v, @weak w => move |_x| {
|
||||
println!("v: {v}, w: {w}");
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@weak v, @weak w => move || println!("v: {v}, w: {w}"));
|
||||
|
||||
let closure = clone!(@strong v, @strong w => move |_x| {
|
||||
println!("v: {v}, w: {w}");
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@strong v, @strong w => move || println!("v: {v}, w: {w}"));
|
||||
|
||||
let closure = clone!(@weak v, @weak w => @default-return true, move |_x| {
|
||||
false
|
||||
});
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@weak v, @weak w => @default-return true, move || false);
|
||||
|
||||
let closure = clone!(@strong v, @strong w => @default-return true, move |_x| false);
|
||||
closure(0i8); // to prevent compiler error for unknown `x` type.
|
||||
let _ = clone!(@strong v, @strong w => @default-return true, move || false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clone_macro_double_rename() {
|
||||
let v = Rc::new(1);
|
||||
let w = Rc::new(2);
|
||||
let done = Rc::new(RefCell::new(0));
|
||||
|
||||
let closure = clone!(@weak v as x, @weak w => @default-panic, move |z| {
|
||||
z + *x + *w
|
||||
});
|
||||
assert_eq!(closure(1i8), 4i8);
|
||||
let closure = clone!(@weak v as x, @weak w => @default-panic, move || 1);
|
||||
assert_eq!(closure(), 1);
|
||||
|
||||
let closure = clone!(@weak v, @weak w as x => @default-panic, move |z| {
|
||||
z + *v + *x
|
||||
});
|
||||
assert_eq!(closure(10i8), 13i8);
|
||||
let closure = clone!(@weak v, @weak w as x => @default-panic, move || 2 + *x);
|
||||
assert_eq!(closure(), 4);
|
||||
|
||||
let closure = clone!(@strong v as x, @strong w => @default-panic, move |z| {
|
||||
z + *x + *w
|
||||
});
|
||||
assert_eq!(closure(3i8), 6i8);
|
||||
let closure = clone!(@strong v as x, @strong w => @default-panic, move || 4 + *w);
|
||||
assert_eq!(closure(), 6);
|
||||
|
||||
let closure = clone!(@strong v, @strong w as x => @default-panic, move |z| {
|
||||
z + *v + *x
|
||||
});
|
||||
assert_eq!(closure(0i8), 3i8);
|
||||
let closure = clone!(@strong v, @strong w as x => @default-panic, move || 5);
|
||||
assert_eq!(closure(), 5);
|
||||
|
||||
let t_done = done.clone();
|
||||
let closure = clone!(@weak v as x, @weak w => move |z| {
|
||||
*t_done.borrow_mut() = z + *x + *w;
|
||||
});
|
||||
closure(4i8);
|
||||
assert_eq!(*done.borrow(), 7);
|
||||
let t_done = done.clone();
|
||||
let closure = clone!(@weak v as x, @weak w => move || *t_done.borrow_mut() = *x + *w);
|
||||
closure();
|
||||
assert_eq!(*done.borrow(), 3);
|
||||
|
||||
let t_done = done.clone();
|
||||
let closure = clone!(@weak v, @weak w as x => move |z| {
|
||||
*t_done.borrow_mut() = z + *v + *x;
|
||||
});
|
||||
closure(8i8);
|
||||
assert_eq!(*done.borrow(), 11i8);
|
||||
let t_done = done.clone();
|
||||
let closure = clone!(@weak v, @weak w as x => move || *t_done.borrow_mut() = *v * *x);
|
||||
closure();
|
||||
assert_eq!(*done.borrow(), 2);
|
||||
|
||||
let t_done = done.clone();
|
||||
let closure = clone!(@strong v as x, @strong w => move |z| {
|
||||
*t_done.borrow_mut() = z + *x + *w;
|
||||
});
|
||||
closure(9i8);
|
||||
assert_eq!(*done.borrow(), 12i8);
|
||||
let t_done = done.clone();
|
||||
let closure = clone!(@strong v as x, @strong w => move || *t_done.borrow_mut() = *x - *w);
|
||||
closure();
|
||||
assert_eq!(*done.borrow(), -1);
|
||||
|
||||
let t_done = done.clone();
|
||||
let closure = clone!(@strong v, @strong w as x => move |z| {
|
||||
*t_done.borrow_mut() = *v + *x * z;
|
||||
});
|
||||
closure(2i8);
|
||||
assert_eq!(*done.borrow(), 5);
|
||||
let t_done = done.clone();
|
||||
let closure = clone!(@strong v, @strong w as x => move || *t_done.borrow_mut() = *x - *v);
|
||||
closure();
|
||||
assert_eq!(*done.borrow(), 1);
|
||||
|
||||
let closure = clone!(@weak v as _x, @weak w => @default-return true, move |_| {
|
||||
false
|
||||
});
|
||||
assert!(!closure(0u8));
|
||||
let closure = clone!(@weak v as _x, @weak w => @default-return true, move || false);
|
||||
assert!(!closure());
|
||||
|
||||
let closure = clone!(@weak v, @weak w as _x => @default-return true, move |_| {
|
||||
false
|
||||
});
|
||||
assert!(!closure("a"));
|
||||
let closure = clone!(@weak v, @weak w as _x => @default-return true, move || false);
|
||||
assert!(!closure());
|
||||
|
||||
let closure = clone!(@strong v as _x, @strong w => @default-return true, move |_| {
|
||||
false
|
||||
});
|
||||
assert!(!closure('a'));
|
||||
let closure = clone!(@strong v as _x, @strong w => @default-return true, move || false);
|
||||
assert!(!closure());
|
||||
|
||||
let closure = clone!(@strong v, @strong w as _x => @default-return true, move |_| {
|
||||
false
|
||||
});
|
||||
assert!(!closure(12.));
|
||||
let closure = clone!(@strong v, @strong w as _x => @default-return true, move || false);
|
||||
assert!(!closure());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clone_macro_typed_args() {
|
||||
macro_rules! test_closure {
|
||||
($kind:tt, panic) => {{
|
||||
// We need Arc and Mutex to use them below in the thread.
|
||||
let check = Arc::new(Mutex::new(0));
|
||||
let v = Arc::new(Mutex::new(1));
|
||||
let w = Arc::new(Mutex::new(1));
|
||||
|
||||
let closure = clone!(@$kind v as x, @$kind w, @weak check => @default-panic, move |arg: i8| {
|
||||
*x.lock().unwrap() += arg;
|
||||
*w.lock().unwrap() += arg;
|
||||
*check.lock().unwrap() += 1;
|
||||
});
|
||||
closure(1);
|
||||
assert_eq!(2, *v.lock().unwrap());
|
||||
assert_eq!(2, *w.lock().unwrap());
|
||||
assert_eq!(1, *check.lock().unwrap());
|
||||
|
||||
let closure2 = clone!(@$kind v, @$kind w as x, @weak check => @default-panic, move |arg: i8| {
|
||||
*v.lock().unwrap() += arg;
|
||||
*x.lock().unwrap() += arg;
|
||||
*check.lock().unwrap() += 1;
|
||||
});
|
||||
closure2(1);
|
||||
assert_eq!(3, *v.lock().unwrap());
|
||||
assert_eq!(3, *w.lock().unwrap());
|
||||
assert_eq!(2, *check.lock().unwrap());
|
||||
|
||||
#[allow(unused_macro_rules)]
|
||||
macro_rules! inner {
|
||||
(strong) => {{}};
|
||||
(weak) => {{
|
||||
std::mem::drop(v);
|
||||
std::mem::drop(w);
|
||||
|
||||
// We use the threads to ensure that the closure panics as expected.
|
||||
assert!(thread::spawn(move || {
|
||||
closure(1);
|
||||
}).join().is_err());
|
||||
assert_eq!(2, *check.lock().unwrap());
|
||||
assert!(thread::spawn(move || {
|
||||
closure2(1);
|
||||
}).join().is_err());
|
||||
assert_eq!(2, *check.lock().unwrap());
|
||||
}}
|
||||
}
|
||||
|
||||
inner!($kind);
|
||||
}};
|
||||
($kind:tt) => {{
|
||||
let check = Rc::new(RefCell::new(0));
|
||||
let v = Rc::new(RefCell::new(1));
|
||||
let w = Rc::new(RefCell::new(1));
|
||||
|
||||
let closure = clone!(@$kind v as x, @$kind w, @weak check => move |arg: i8| {
|
||||
*x.borrow_mut() += arg;
|
||||
*w.borrow_mut() += arg;
|
||||
*check.borrow_mut() += 1;
|
||||
});
|
||||
closure(1);
|
||||
assert_eq!(2, *v.borrow());
|
||||
assert_eq!(2, *w.borrow());
|
||||
assert_eq!(1, *check.borrow());
|
||||
|
||||
let closure2 = clone!(@$kind v, @$kind w as x, @weak check => move |arg: i8| {
|
||||
*v.borrow_mut() += arg;
|
||||
*x.borrow_mut() += arg;
|
||||
*check.borrow_mut() += 1;
|
||||
});
|
||||
closure2(1);
|
||||
assert_eq!(3, *v.borrow());
|
||||
assert_eq!(3, *w.borrow());
|
||||
assert_eq!(2, *check.borrow());
|
||||
|
||||
#[allow(unused_macro_rules)]
|
||||
macro_rules! inner {
|
||||
(strong) => {{}};
|
||||
(weak) => {{
|
||||
std::mem::drop(v);
|
||||
std::mem::drop(w);
|
||||
|
||||
closure(1);
|
||||
assert_eq!(2, *check.borrow());
|
||||
closure2(1);
|
||||
assert_eq!(2, *check.borrow());
|
||||
}}
|
||||
}
|
||||
|
||||
inner!($kind);
|
||||
}};
|
||||
}
|
||||
|
||||
test_closure!(weak, panic);
|
||||
test_closure!(strong, panic);
|
||||
test_closure!(weak);
|
||||
test_closure!(strong);
|
||||
|
||||
let check = Rc::new(RefCell::new(0));
|
||||
let v = Rc::new(RefCell::new(1));
|
||||
let w = Rc::new(RefCell::new(1));
|
||||
let closure = clone!(@weak v, @weak w as x, @weak check => move |arg: i8, arg2| {
|
||||
*v.borrow_mut() = arg;
|
||||
*x.borrow_mut() = arg2;
|
||||
*check.borrow_mut() += 1;
|
||||
});
|
||||
closure(0, 9);
|
||||
assert_eq!(0, *v.borrow());
|
||||
assert_eq!(9, *w.borrow());
|
||||
assert_eq!(1, *check.borrow());
|
||||
|
||||
std::mem::drop(v);
|
||||
std::mem::drop(w);
|
||||
assert_eq!(1, *check.borrow());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::bool_assert_comparison)]
|
||||
#[allow(clippy::nonminimal_bool)]
|
||||
fn test_clone_macro_default_return() {
|
||||
macro_rules! test_default {
|
||||
($ret:expr, $($closure_body:tt)*) => {{
|
||||
let v = Rc::new(1);
|
||||
let tmp = clone!(@weak v => @default-return $ret, move || $($closure_body)*);
|
||||
assert_eq!(tmp(), $($closure_body)*, "shouldn't use default-return value!");
|
||||
::std::mem::drop(v);
|
||||
assert_eq!(tmp(), $ret, "should use default-return value!");
|
||||
}}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct Foo(i32);
|
||||
|
||||
test_default!(Foo(0), Foo(1));
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct Bar {
|
||||
x: i32,
|
||||
}
|
||||
|
||||
test_default!(Bar { x: 0 }, Bar { x: 1 });
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
enum Enum {
|
||||
A,
|
||||
B(i32),
|
||||
C { x: i32 },
|
||||
}
|
||||
test_default!(Enum::A, Enum::B(0));
|
||||
test_default!(Enum::B(0), Enum::A);
|
||||
test_default!(Enum::C { x: 0 }, Enum::A);
|
||||
test_default!(
|
||||
{
|
||||
let x = 12;
|
||||
x + 2
|
||||
},
|
||||
19
|
||||
);
|
||||
// This one is simply to check that we wait for the comma for the default-return value.
|
||||
test_default!(Enum::A == Enum::B(0) || false, true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clone_macro_body() {
|
||||
let v = Arc::new(Mutex::new(0));
|
||||
|
||||
let closure = clone!(@weak v => move || {
|
||||
std::thread::spawn(move || {
|
||||
let mut lock = v.lock().expect("failed to lock");
|
||||
for _ in 1..=10 {
|
||||
*lock += 1;
|
||||
}
|
||||
}).join().expect("thread::spawn failed");
|
||||
});
|
||||
closure();
|
||||
assert_eq!(10, *v.lock().expect("failed to lock"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clone_macro_async_kinds() {
|
||||
let v = Rc::new(RefCell::new(1));
|
||||
|
||||
// This one is still a rust unstable feature.
|
||||
// let _closure = clone!(@weak v => async move || 0);
|
||||
let closure = clone!(@weak v => move || async move { *v.borrow_mut() += 1; });
|
||||
block_on(closure());
|
||||
assert_eq!(*v.borrow(), 2);
|
||||
block_on(clone!(@weak v => async move { *v.borrow_mut() += 1; }));
|
||||
assert_eq!(*v.borrow(), 3);
|
||||
}
|
||||
Reference in new issue
Block a user