mlua/tests/userdata.rs

240 lines
6.4 KiB
Rust
Raw Normal View History

2018-02-09 23:52:05 -05:00
use std::sync::Arc;
2019-09-28 10:23:17 -04:00
use rlua::{
AnyUserData, ExternalError, Function, MetaMethod, Result, String, UserData, UserDataMethods,
};
include!("_lua.rs");
2018-02-09 23:52:05 -05:00
#[test]
2019-09-28 10:23:17 -04:00
fn test_user_data() -> Result<()> {
2018-02-09 23:52:05 -05:00
struct UserData1(i64);
struct UserData2(Box<i64>);
impl UserData for UserData1 {};
impl UserData for UserData2 {};
2019-09-28 10:23:17 -04:00
let lua = make_lua();
let userdata1 = lua.create_userdata(UserData1(1))?;
let userdata2 = lua.create_userdata(UserData2(Box::new(2)))?;
2018-02-09 23:52:05 -05:00
assert!(userdata1.is::<UserData1>());
assert!(!userdata1.is::<UserData2>());
assert!(userdata2.is::<UserData2>());
assert!(!userdata2.is::<UserData1>());
2018-02-09 23:52:05 -05:00
2019-09-28 10:23:17 -04:00
assert_eq!(userdata1.borrow::<UserData1>()?.0, 1);
assert_eq!(*userdata2.borrow::<UserData2>()?.0, 2);
Ok(())
2018-02-09 23:52:05 -05:00
}
#[test]
2019-09-28 10:23:17 -04:00
fn test_methods() -> Result<()> {
2018-02-09 23:52:05 -05:00
struct MyUserData(i64);
impl UserData for MyUserData {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
2018-02-09 23:52:05 -05:00
methods.add_method("get_value", |_, data, ()| Ok(data.0));
methods.add_method_mut("set_value", |_, data, args| {
data.0 = args;
Ok(())
});
}
}
2019-09-28 10:23:17 -04:00
let lua = make_lua();
2018-02-09 23:52:05 -05:00
let globals = lua.globals();
2019-09-28 10:23:17 -04:00
let userdata = lua.create_userdata(MyUserData(42))?;
globals.set("userdata", userdata.clone())?;
lua.load(
2018-02-09 23:52:05 -05:00
r#"
2019-09-28 10:23:17 -04:00
function get_it()
return userdata:get_value()
end
function set_it(i)
return userdata:set_value(i)
end
"#,
2019-09-27 12:38:24 -04:00
)
2019-09-28 10:23:17 -04:00
.exec()?;
let get = globals.get::<_, Function>("get_it")?;
let set = globals.get::<_, Function>("set_it")?;
assert_eq!(get.call::<_, i64>(())?, 42);
userdata.borrow_mut::<MyUserData>()?.0 = 64;
assert_eq!(get.call::<_, i64>(())?, 64);
set.call::<_, ()>(100)?;
assert_eq!(get.call::<_, i64>(())?, 100);
Ok(())
2018-02-09 23:52:05 -05:00
}
#[test]
2019-09-28 10:23:17 -04:00
fn test_metamethods() -> Result<()> {
2018-02-09 23:52:05 -05:00
#[derive(Copy, Clone)]
struct MyUserData(i64);
impl UserData for MyUserData {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
2018-02-09 23:52:05 -05:00
methods.add_method("get", |_, data, ()| Ok(data.0));
methods.add_meta_function(
MetaMethod::Add,
|_, (lhs, rhs): (MyUserData, MyUserData)| Ok(MyUserData(lhs.0 + rhs.0)),
);
methods.add_meta_function(
MetaMethod::Sub,
|_, (lhs, rhs): (MyUserData, MyUserData)| Ok(MyUserData(lhs.0 - rhs.0)),
);
methods.add_meta_method(MetaMethod::Index, |_, data, index: String| {
if index.to_str()? == "inner" {
Ok(data.0)
} else {
2019-09-28 10:23:17 -04:00
Err("no such custom index".to_lua_err())
2018-02-09 23:52:05 -05:00
}
});
}
}
2019-09-28 10:23:17 -04:00
let lua = make_lua();
2018-02-09 23:52:05 -05:00
let globals = lua.globals();
2019-09-28 10:23:17 -04:00
globals.set("userdata1", MyUserData(7))?;
globals.set("userdata2", MyUserData(3))?;
2018-02-09 23:52:05 -05:00
assert_eq!(
2019-09-28 10:23:17 -04:00
lua.load("userdata1 + userdata2").eval::<MyUserData>()?.0,
2018-02-09 23:52:05 -05:00
10
);
2019-09-28 10:23:17 -04:00
assert_eq!(lua.load("userdata1 - userdata2").eval::<MyUserData>()?.0, 4);
assert_eq!(lua.load("userdata1:get()").eval::<i64>()?, 7);
assert_eq!(lua.load("userdata2.inner").eval::<i64>()?, 3);
assert!(lua.load("userdata2.nonexist_field").eval::<()>().is_err());
Ok(())
2018-02-09 23:52:05 -05:00
}
#[test]
2019-09-28 10:23:17 -04:00
fn test_gc_userdata() -> Result<()> {
2018-02-09 23:52:05 -05:00
struct MyUserdata {
id: u8,
}
impl UserData for MyUserdata {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
2018-02-09 23:52:05 -05:00
methods.add_method("access", |_, this, ()| {
assert!(this.id == 123);
Ok(())
});
}
}
2019-09-28 10:23:17 -04:00
let lua = make_lua();
lua.globals().set("userdata", MyUserdata { id: 123 })?;
2018-02-09 23:52:05 -05:00
2019-09-27 12:38:24 -04:00
assert!(lua
2019-09-28 10:23:17 -04:00
.load(
2018-08-05 09:51:39 -04:00
r#"
2019-09-28 10:23:17 -04:00
local tbl = setmetatable({
userdata = userdata
}, { __gc = function(self)
-- resurrect userdata
hatch = self.userdata
end })
tbl = nil
userdata = nil -- make table and userdata collectable
collectgarbage("collect")
hatch:access()
"#
2019-09-27 12:38:24 -04:00
)
2019-09-28 10:23:17 -04:00
.exec()
2019-09-27 12:38:24 -04:00
.is_err());
2019-09-28 10:23:17 -04:00
Ok(())
2018-02-09 23:52:05 -05:00
}
#[test]
2019-09-28 10:23:17 -04:00
fn detroys_userdata() -> Result<()> {
2018-02-09 23:52:05 -05:00
struct MyUserdata(Arc<()>);
impl UserData for MyUserdata {}
let rc = Arc::new(());
2019-09-28 10:23:17 -04:00
let lua = make_lua();
lua.globals().set("userdata", MyUserdata(rc.clone()))?;
2018-02-09 23:52:05 -05:00
assert_eq!(Arc::strong_count(&rc), 2);
2019-09-28 10:23:17 -04:00
// should destroy all objects
let _ = lua.globals().raw_remove("userdata")?;
lua.gc_collect()?;
2018-02-09 23:52:05 -05:00
assert_eq!(Arc::strong_count(&rc), 1);
2019-09-28 10:23:17 -04:00
Ok(())
2018-02-09 23:52:05 -05:00
}
#[test]
2019-09-28 10:23:17 -04:00
fn user_value() -> Result<()> {
2018-02-09 23:52:05 -05:00
struct MyUserData;
impl UserData for MyUserData {}
2019-09-28 10:23:17 -04:00
let lua = make_lua();
let ud = lua.create_userdata(MyUserData)?;
ud.set_user_value("hello")?;
assert_eq!(ud.get_user_value::<String>()?, "hello");
assert!(ud.get_user_value::<u32>().is_err());
2019-09-28 10:23:17 -04:00
Ok(())
}
#[test]
fn test_functions() -> Result<()> {
struct MyUserData(i64);
impl UserData for MyUserData {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_function("get_value", |_, ud: AnyUserData| {
Ok(ud.borrow::<MyUserData>()?.0)
});
methods.add_function("set_value", |_, (ud, value): (AnyUserData, i64)| {
ud.borrow_mut::<MyUserData>()?.0 = value;
Ok(())
});
methods.add_function("get_constant", |_, ()| Ok(7));
}
}
let lua = make_lua();
let globals = lua.globals();
let userdata = lua.create_userdata(MyUserData(42))?;
globals.set("userdata", userdata.clone())?;
lua.load(
r#"
function get_it()
return userdata:get_value()
end
function set_it(i)
return userdata:set_value(i)
end
function get_constant()
return userdata.get_constant()
end
"#,
)
.exec()?;
let get = globals.get::<_, Function>("get_it")?;
let set = globals.get::<_, Function>("set_it")?;
let get_constant = globals.get::<_, Function>("get_constant")?;
assert_eq!(get.call::<_, i64>(())?, 42);
userdata.borrow_mut::<MyUserData>()?.0 = 64;
assert_eq!(get.call::<_, i64>(())?, 64);
set.call::<_, ()>(100)?;
assert_eq!(get.call::<_, i64>(())?, 100);
assert_eq!(get_constant.call::<_, i64>(())?, 7);
Ok(())
2018-02-09 23:52:05 -05:00
}