summaryrefslogtreecommitdiff
path: root/tests/scope.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/scope.rs')
-rw-r--r--tests/scope.rs237
1 files changed, 237 insertions, 0 deletions
diff --git a/tests/scope.rs b/tests/scope.rs
new file mode 100644
index 0000000..103a9ea
--- /dev/null
+++ b/tests/scope.rs
@@ -0,0 +1,237 @@
+extern crate rlua;
+
+use std::cell::Cell;
+use std::rc::Rc;
+
+use rlua::{Error, Function, Lua, MetaMethod, String, UserData, UserDataMethods};
+
+#[test]
+fn scope_func() {
+ let lua = Lua::new();
+
+ let rc = Rc::new(Cell::new(0));
+ lua.scope(|scope| {
+ let r = rc.clone();
+ let f = scope
+ .create_function(move |_, ()| {
+ r.set(42);
+ Ok(())
+ })
+ .unwrap();
+ lua.globals().set("bad", f.clone()).unwrap();
+ f.call::<_, ()>(()).unwrap();
+ assert_eq!(Rc::strong_count(&rc), 2);
+ });
+ assert_eq!(rc.get(), 42);
+ assert_eq!(Rc::strong_count(&rc), 1);
+
+ match lua
+ .globals()
+ .get::<_, Function>("bad")
+ .unwrap()
+ .call::<_, ()>(())
+ {
+ Err(Error::CallbackError { .. }) => {}
+ r => panic!("improper return for destructed function: {:?}", r),
+ };
+}
+
+#[test]
+fn scope_drop() {
+ let lua = Lua::new();
+
+ struct MyUserdata(Rc<()>);
+ impl UserData for MyUserdata {
+ fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ methods.add_method("method", |_, _, ()| Ok(()));
+ }
+ }
+
+ let rc = Rc::new(());
+
+ lua.scope(|scope| {
+ lua.globals()
+ .set(
+ "test",
+ scope
+ .create_static_userdata(MyUserdata(rc.clone()))
+ .unwrap(),
+ )
+ .unwrap();
+ assert_eq!(Rc::strong_count(&rc), 2);
+ });
+ assert_eq!(Rc::strong_count(&rc), 1);
+
+ match lua.exec::<()>("test:method()", None) {
+ Err(Error::CallbackError { .. }) => {}
+ r => panic!("improper return for destructed userdata: {:?}", r),
+ };
+}
+
+#[test]
+fn scope_capture() {
+ let lua = Lua::new();
+
+ let mut i = 0;
+ lua.scope(|scope| {
+ scope
+ .create_function_mut(|_, ()| {
+ i = 42;
+ Ok(())
+ })
+ .unwrap()
+ .call::<_, ()>(())
+ .unwrap();
+ });
+ assert_eq!(i, 42);
+}
+
+#[test]
+fn outer_lua_access() {
+ let lua = Lua::new();
+ let table = lua.create_table().unwrap();
+ lua.scope(|scope| {
+ scope
+ .create_function_mut(|_, ()| {
+ table.set("a", "b").unwrap();
+ Ok(())
+ })
+ .unwrap()
+ .call::<_, ()>(())
+ .unwrap();
+ });
+ assert_eq!(table.get::<_, String>("a").unwrap(), "b");
+}
+
+#[test]
+fn scope_userdata_methods() {
+ struct MyUserData<'a>(&'a Cell<i64>);
+
+ impl<'a> UserData for MyUserData<'a> {
+ fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ methods.add_method("inc", |_, data, ()| {
+ data.0.set(data.0.get() + 1);
+ Ok(())
+ });
+
+ methods.add_method("dec", |_, data, ()| {
+ data.0.set(data.0.get() - 1);
+ Ok(())
+ });
+ }
+ }
+
+ let lua = Lua::new();
+
+ let i = Cell::new(42);
+ lua.scope(|scope| {
+ let f: Function =
+ lua.eval(
+ r#"
+ function(u)
+ u:inc()
+ u:inc()
+ u:inc()
+ u:dec()
+ end
+ "#,
+ None,
+ ).unwrap();
+
+ f.call::<_, ()>(scope.create_nonstatic_userdata(MyUserData(&i)).unwrap())
+ .unwrap();
+ });
+
+ assert_eq!(i.get(), 44);
+}
+
+#[test]
+fn scope_userdata_functions() {
+ struct MyUserData<'a>(&'a i64);
+
+ impl<'a> UserData for MyUserData<'a> {
+ fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ methods.add_meta_function(MetaMethod::Add, |lua, ()| {
+ let globals = lua.globals();
+ globals.set("i", globals.get::<_, i64>("i")? + 1)?;
+ Ok(())
+ });
+ methods.add_meta_function(MetaMethod::Sub, |lua, ()| {
+ let globals = lua.globals();
+ globals.set("i", globals.get::<_, i64>("i")? + 1)?;
+ Ok(())
+ });
+ }
+ }
+
+ let lua = Lua::new();
+ let f =
+ lua.exec::<Function>(
+ r#"
+ i = 0
+ return function(u)
+ _ = u + u
+ _ = u - 1
+ _ = 1 + u
+ end
+ "#,
+ None,
+ ).unwrap();
+
+ let dummy = 0;
+ lua.scope(|scope| {
+ f.call::<_, ()>(scope.create_nonstatic_userdata(MyUserData(&dummy)).unwrap())
+ .unwrap();
+ });
+
+ assert_eq!(lua.globals().get::<_, i64>("i").unwrap(), 3);
+}
+
+#[test]
+fn scope_userdata_mismatch() {
+ struct MyUserData<'a>(&'a Cell<i64>);
+
+ impl<'a> UserData for MyUserData<'a> {
+ fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
+ methods.add_method("inc", |_, data, ()| {
+ data.0.set(data.0.get() + 1);
+ Ok(())
+ });
+ }
+ }
+
+ let lua = Lua::new();
+ lua.exec::<()>(
+ r#"
+ function okay(a, b)
+ a.inc(a)
+ b.inc(b)
+ end
+
+ function bad(a, b)
+ a.inc(b)
+ end
+ "#,
+ None,
+ ).unwrap();
+
+ let a = Cell::new(1);
+ let b = Cell::new(1);
+
+ let okay: Function = lua.globals().get("okay").unwrap();
+ let bad: Function = lua.globals().get("bad").unwrap();
+
+ lua.scope(|scope| {
+ let au = scope.create_nonstatic_userdata(MyUserData(&a)).unwrap();
+ let bu = scope.create_nonstatic_userdata(MyUserData(&b)).unwrap();
+ assert!(okay.call::<_, ()>((au.clone(), bu.clone())).is_ok());
+ match bad.call::<_, ()>((au, bu)) {
+ Err(Error::CallbackError { ref cause, .. }) => match *cause.as_ref() {
+ Error::UserDataTypeMismatch => {}
+ ref other => panic!("wrong error type {:?}", other),
+ },
+ Err(other) => panic!("wrong error type {:?}", other),
+ Ok(_) => panic!("incorrectly returned Ok"),
+ }
+ });
+}