Move all tests into a tests/ subfolder
This commit is contained in:
parent
d331e4b97c
commit
60743d45cd
|
@ -170,77 +170,3 @@ impl<'lua> Function<'lua> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Function;
|
||||
use string::String;
|
||||
use lua::Lua;
|
||||
|
||||
#[test]
|
||||
fn test_function() {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
lua.exec::<()>(
|
||||
r#"
|
||||
function concat(arg1, arg2)
|
||||
return arg1 .. arg2
|
||||
end
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
|
||||
let concat = globals.get::<_, Function>("concat").unwrap();
|
||||
assert_eq!(concat.call::<_, String>(("foo", "bar")).unwrap(), "foobar");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bind() {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
lua.exec::<()>(
|
||||
r#"
|
||||
function concat(...)
|
||||
local res = ""
|
||||
for _, s in pairs({...}) do
|
||||
res = res..s
|
||||
end
|
||||
return res
|
||||
end
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
|
||||
let mut concat = globals.get::<_, Function>("concat").unwrap();
|
||||
concat = concat.bind("foo").unwrap();
|
||||
concat = concat.bind("bar").unwrap();
|
||||
concat = concat.bind(("baz", "baf")).unwrap();
|
||||
assert_eq!(
|
||||
concat.call::<_, String>(("hi", "wut")).unwrap(),
|
||||
"foobarbazbafhiwut"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rust_function() {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
lua.exec::<()>(
|
||||
r#"
|
||||
function lua_function()
|
||||
return rust_function()
|
||||
end
|
||||
|
||||
-- Test to make sure chunk return is ignored
|
||||
return 1
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
|
||||
let lua_function = globals.get::<_, Function>("lua_function").unwrap();
|
||||
let rust_function = lua.create_function(|_, ()| Ok("hello")).unwrap();
|
||||
|
||||
globals.set("rust_function", rust_function).unwrap();
|
||||
assert_eq!(lua_function.call::<_, String>(()).unwrap(), "hello");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,68 +108,3 @@ where
|
|||
self.as_bytes() == other.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use lua::Lua;
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
fn with_str<F>(s: &str, f: F)
|
||||
where
|
||||
F: FnOnce(String),
|
||||
{
|
||||
let lua = Lua::new();
|
||||
let string = lua.create_string(s).unwrap();
|
||||
f(string);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compare() {
|
||||
// Tests that all comparisons we want to have are usable
|
||||
with_str("teststring", |t| assert_eq!(t, "teststring")); // &str
|
||||
with_str("teststring", |t| assert_eq!(t, b"teststring")); // &[u8]
|
||||
with_str("teststring", |t| assert_eq!(t, b"teststring".to_vec())); // Vec<u8>
|
||||
with_str("teststring", |t| assert_eq!(t, "teststring".to_string())); // String
|
||||
with_str("teststring", |t| assert_eq!(t, t)); // rlua::String
|
||||
with_str("teststring", |t| {
|
||||
assert_eq!(t, Cow::from(b"teststring".as_ref()))
|
||||
}); // Cow (borrowed)
|
||||
with_str("bla", |t| assert_eq!(t, Cow::from(b"bla".to_vec()))); // Cow (owned)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_views() {
|
||||
let lua = Lua::new();
|
||||
lua.eval::<()>(
|
||||
r#"
|
||||
ok = "null bytes are valid utf-8, wh\0 knew?"
|
||||
err = "but \xff isn't :("
|
||||
empty = ""
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
|
||||
let globals = lua.globals();
|
||||
let ok: String = globals.get("ok").unwrap();
|
||||
let err: String = globals.get("err").unwrap();
|
||||
let empty: String = globals.get("empty").unwrap();
|
||||
|
||||
assert_eq!(
|
||||
ok.to_str().unwrap(),
|
||||
"null bytes are valid utf-8, wh\0 knew?"
|
||||
);
|
||||
assert_eq!(
|
||||
ok.as_bytes(),
|
||||
&b"null bytes are valid utf-8, wh\0 knew?"[..]
|
||||
);
|
||||
|
||||
assert!(err.to_str().is_err());
|
||||
assert_eq!(err.as_bytes(), &b"but \xff isn't :("[..]);
|
||||
|
||||
assert_eq!(empty.to_str().unwrap(), "");
|
||||
assert_eq!(empty.as_bytes_with_nul(), &[0]);
|
||||
assert_eq!(empty.as_bytes(), &[]);
|
||||
}
|
||||
}
|
||||
|
|
184
src/table.rs
184
src/table.rs
|
@ -432,187 +432,3 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Table;
|
||||
use error::Result;
|
||||
use value::{Nil, Value};
|
||||
use lua::Lua;
|
||||
|
||||
#[test]
|
||||
fn test_set_get() {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
globals.set("foo", "bar").unwrap();
|
||||
globals.set("baz", "baf").unwrap();
|
||||
assert_eq!(globals.get::<_, String>("foo").unwrap(), "bar");
|
||||
assert_eq!(globals.get::<_, String>("baz").unwrap(), "baf");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_table() {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
|
||||
globals.set("table", lua.create_table().unwrap()).unwrap();
|
||||
let table1: Table = globals.get("table").unwrap();
|
||||
let table2: Table = globals.get("table").unwrap();
|
||||
|
||||
table1.set("foo", "bar").unwrap();
|
||||
table2.set("baz", "baf").unwrap();
|
||||
|
||||
assert_eq!(table2.get::<_, String>("foo").unwrap(), "bar");
|
||||
assert_eq!(table1.get::<_, String>("baz").unwrap(), "baf");
|
||||
|
||||
lua.exec::<()>(
|
||||
r#"
|
||||
table1 = {1, 2, 3, 4, 5}
|
||||
table2 = {}
|
||||
table3 = {1, 2, nil, 4, 5}
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
|
||||
let table1 = globals.get::<_, Table>("table1").unwrap();
|
||||
let table2 = globals.get::<_, Table>("table2").unwrap();
|
||||
let table3 = globals.get::<_, Table>("table3").unwrap();
|
||||
|
||||
assert_eq!(table1.len().unwrap(), 5);
|
||||
assert_eq!(
|
||||
table1
|
||||
.clone()
|
||||
.pairs()
|
||||
.collect::<Result<Vec<(i64, i64)>>>()
|
||||
.unwrap(),
|
||||
vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
|
||||
);
|
||||
assert_eq!(
|
||||
table1
|
||||
.clone()
|
||||
.sequence_values()
|
||||
.collect::<Result<Vec<i64>>>()
|
||||
.unwrap(),
|
||||
vec![1, 2, 3, 4, 5]
|
||||
);
|
||||
|
||||
assert_eq!(table2.len().unwrap(), 0);
|
||||
assert_eq!(
|
||||
table2
|
||||
.clone()
|
||||
.pairs()
|
||||
.collect::<Result<Vec<(i64, i64)>>>()
|
||||
.unwrap(),
|
||||
vec![]
|
||||
);
|
||||
assert_eq!(
|
||||
table2
|
||||
.sequence_values()
|
||||
.collect::<Result<Vec<i64>>>()
|
||||
.unwrap(),
|
||||
vec![]
|
||||
);
|
||||
|
||||
// sequence_values should only iterate until the first border
|
||||
assert_eq!(
|
||||
table3
|
||||
.sequence_values()
|
||||
.collect::<Result<Vec<i64>>>()
|
||||
.unwrap(),
|
||||
vec![1, 2]
|
||||
);
|
||||
|
||||
globals
|
||||
.set(
|
||||
"table4",
|
||||
lua.create_sequence_from(vec![1, 2, 3, 4, 5]).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let table4 = globals.get::<_, Table>("table4").unwrap();
|
||||
assert_eq!(
|
||||
table4.pairs().collect::<Result<Vec<(i64, i64)>>>().unwrap(),
|
||||
vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_table_scope() {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
lua.exec::<()>(
|
||||
r#"
|
||||
touter = {
|
||||
tin = {1, 2, 3}
|
||||
}
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
|
||||
// Make sure that table gets do not borrow the table, but instead just borrow lua.
|
||||
let tin;
|
||||
{
|
||||
let touter = globals.get::<_, Table>("touter").unwrap();
|
||||
tin = touter.get::<_, Table>("tin").unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(tin.get::<_, i64>(1).unwrap(), 1);
|
||||
assert_eq!(tin.get::<_, i64>(2).unwrap(), 2);
|
||||
assert_eq!(tin.get::<_, i64>(3).unwrap(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_metatable() {
|
||||
let lua = Lua::new();
|
||||
|
||||
let table = lua.create_table().unwrap();
|
||||
let metatable = lua.create_table().unwrap();
|
||||
metatable
|
||||
.set(
|
||||
"__index",
|
||||
lua.create_function(|_, ()| Ok("index_value")).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
table.set_metatable(Some(metatable));
|
||||
assert_eq!(table.get::<_, String>("any_key").unwrap(), "index_value");
|
||||
match table.raw_get::<_, Value>("any_key").unwrap() {
|
||||
Nil => {}
|
||||
_ => panic!(),
|
||||
}
|
||||
table.set_metatable(None);
|
||||
match table.get::<_, Value>("any_key").unwrap() {
|
||||
Nil => {}
|
||||
_ => panic!(),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_table_error() {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
lua.exec::<()>(
|
||||
r#"
|
||||
table = {}
|
||||
setmetatable(table, {
|
||||
__index = function()
|
||||
error("lua error")
|
||||
end,
|
||||
__newindex = function()
|
||||
error("lua error")
|
||||
end,
|
||||
__len = function()
|
||||
error("lua error")
|
||||
end
|
||||
})
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
|
||||
let bad_table: Table = globals.get("table").unwrap();
|
||||
assert!(bad_table.set(1, 1).is_err());
|
||||
assert!(bad_table.get::<_, i32>(1).is_err());
|
||||
assert!(bad_table.len().is_err());
|
||||
assert!(bad_table.raw_set(1, 1).is_ok());
|
||||
assert!(bad_table.raw_get::<_, i32>(1).is_ok());
|
||||
assert_eq!(bad_table.raw_len(), 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
use {Function, Lua, String};
|
||||
|
||||
#[test]
|
||||
fn test_function() {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
lua.exec::<()>(
|
||||
r#"
|
||||
function concat(arg1, arg2)
|
||||
return arg1 .. arg2
|
||||
end
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
|
||||
let concat = globals.get::<_, Function>("concat").unwrap();
|
||||
assert_eq!(concat.call::<_, String>(("foo", "bar")).unwrap(), "foobar");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bind() {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
lua.exec::<()>(
|
||||
r#"
|
||||
function concat(...)
|
||||
local res = ""
|
||||
for _, s in pairs({...}) do
|
||||
res = res..s
|
||||
end
|
||||
return res
|
||||
end
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
|
||||
let mut concat = globals.get::<_, Function>("concat").unwrap();
|
||||
concat = concat.bind("foo").unwrap();
|
||||
concat = concat.bind("bar").unwrap();
|
||||
concat = concat.bind(("baz", "baf")).unwrap();
|
||||
assert_eq!(
|
||||
concat.call::<_, String>(("hi", "wut")).unwrap(),
|
||||
"foobarbazbafhiwut"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rust_function() {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
lua.exec::<()>(
|
||||
r#"
|
||||
function lua_function()
|
||||
return rust_function()
|
||||
end
|
||||
|
||||
-- Test to make sure chunk return is ignored
|
||||
return 1
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
|
||||
let lua_function = globals.get::<_, Function>("lua_function").unwrap();
|
||||
let rust_function = lua.create_function(|_, ()| Ok("hello")).unwrap();
|
||||
|
||||
globals.set("rust_function", rust_function).unwrap();
|
||||
assert_eq!(lua_function.call::<_, String>(()).unwrap(), "hello");
|
||||
}
|
|
@ -1,3 +1,10 @@
|
|||
mod function;
|
||||
mod string;
|
||||
mod table;
|
||||
mod thread;
|
||||
mod types;
|
||||
mod userdata;
|
||||
|
||||
use std::{error, fmt};
|
||||
use std::iter::FromIterator;
|
||||
use std::rc::Rc;
|
|
@ -0,0 +1,60 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use {Lua, String};
|
||||
|
||||
fn with_str<F>(s: &str, f: F)
|
||||
where
|
||||
F: FnOnce(String),
|
||||
{
|
||||
let lua = Lua::new();
|
||||
let string = lua.create_string(s).unwrap();
|
||||
f(string);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compare() {
|
||||
// Tests that all comparisons we want to have are usable
|
||||
with_str("teststring", |t| assert_eq!(t, "teststring")); // &str
|
||||
with_str("teststring", |t| assert_eq!(t, b"teststring")); // &[u8]
|
||||
with_str("teststring", |t| assert_eq!(t, b"teststring".to_vec())); // Vec<u8>
|
||||
with_str("teststring", |t| assert_eq!(t, "teststring".to_string())); // String
|
||||
with_str("teststring", |t| assert_eq!(t, t)); // rlua::String
|
||||
with_str("teststring", |t| {
|
||||
assert_eq!(t, Cow::from(b"teststring".as_ref()))
|
||||
}); // Cow (borrowed)
|
||||
with_str("bla", |t| assert_eq!(t, Cow::from(b"bla".to_vec()))); // Cow (owned)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_views() {
|
||||
let lua = Lua::new();
|
||||
lua.eval::<()>(
|
||||
r#"
|
||||
ok = "null bytes are valid utf-8, wh\0 knew?"
|
||||
err = "but \xff isn't :("
|
||||
empty = ""
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
|
||||
let globals = lua.globals();
|
||||
let ok: String = globals.get("ok").unwrap();
|
||||
let err: String = globals.get("err").unwrap();
|
||||
let empty: String = globals.get("empty").unwrap();
|
||||
|
||||
assert_eq!(
|
||||
ok.to_str().unwrap(),
|
||||
"null bytes are valid utf-8, wh\0 knew?"
|
||||
);
|
||||
assert_eq!(
|
||||
ok.as_bytes(),
|
||||
&b"null bytes are valid utf-8, wh\0 knew?"[..]
|
||||
);
|
||||
|
||||
assert!(err.to_str().is_err());
|
||||
assert_eq!(err.as_bytes(), &b"but \xff isn't :("[..]);
|
||||
|
||||
assert_eq!(empty.to_str().unwrap(), "");
|
||||
assert_eq!(empty.as_bytes_with_nul(), &[0]);
|
||||
assert_eq!(empty.as_bytes(), &[]);
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
use {Lua, Nil, Result, Table, Value};
|
||||
|
||||
#[test]
|
||||
fn test_set_get() {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
globals.set("foo", "bar").unwrap();
|
||||
globals.set("baz", "baf").unwrap();
|
||||
assert_eq!(globals.get::<_, String>("foo").unwrap(), "bar");
|
||||
assert_eq!(globals.get::<_, String>("baz").unwrap(), "baf");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_table() {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
|
||||
globals.set("table", lua.create_table().unwrap()).unwrap();
|
||||
let table1: Table = globals.get("table").unwrap();
|
||||
let table2: Table = globals.get("table").unwrap();
|
||||
|
||||
table1.set("foo", "bar").unwrap();
|
||||
table2.set("baz", "baf").unwrap();
|
||||
|
||||
assert_eq!(table2.get::<_, String>("foo").unwrap(), "bar");
|
||||
assert_eq!(table1.get::<_, String>("baz").unwrap(), "baf");
|
||||
|
||||
lua.exec::<()>(
|
||||
r#"
|
||||
table1 = {1, 2, 3, 4, 5}
|
||||
table2 = {}
|
||||
table3 = {1, 2, nil, 4, 5}
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
|
||||
let table1 = globals.get::<_, Table>("table1").unwrap();
|
||||
let table2 = globals.get::<_, Table>("table2").unwrap();
|
||||
let table3 = globals.get::<_, Table>("table3").unwrap();
|
||||
|
||||
assert_eq!(table1.len().unwrap(), 5);
|
||||
assert_eq!(
|
||||
table1
|
||||
.clone()
|
||||
.pairs()
|
||||
.collect::<Result<Vec<(i64, i64)>>>()
|
||||
.unwrap(),
|
||||
vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
|
||||
);
|
||||
assert_eq!(
|
||||
table1
|
||||
.clone()
|
||||
.sequence_values()
|
||||
.collect::<Result<Vec<i64>>>()
|
||||
.unwrap(),
|
||||
vec![1, 2, 3, 4, 5]
|
||||
);
|
||||
|
||||
assert_eq!(table2.len().unwrap(), 0);
|
||||
assert_eq!(
|
||||
table2
|
||||
.clone()
|
||||
.pairs()
|
||||
.collect::<Result<Vec<(i64, i64)>>>()
|
||||
.unwrap(),
|
||||
vec![]
|
||||
);
|
||||
assert_eq!(
|
||||
table2
|
||||
.sequence_values()
|
||||
.collect::<Result<Vec<i64>>>()
|
||||
.unwrap(),
|
||||
vec![]
|
||||
);
|
||||
|
||||
// sequence_values should only iterate until the first border
|
||||
assert_eq!(
|
||||
table3
|
||||
.sequence_values()
|
||||
.collect::<Result<Vec<i64>>>()
|
||||
.unwrap(),
|
||||
vec![1, 2]
|
||||
);
|
||||
|
||||
globals
|
||||
.set(
|
||||
"table4",
|
||||
lua.create_sequence_from(vec![1, 2, 3, 4, 5]).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let table4 = globals.get::<_, Table>("table4").unwrap();
|
||||
assert_eq!(
|
||||
table4.pairs().collect::<Result<Vec<(i64, i64)>>>().unwrap(),
|
||||
vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_table_scope() {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
lua.exec::<()>(
|
||||
r#"
|
||||
touter = {
|
||||
tin = {1, 2, 3}
|
||||
}
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
|
||||
// Make sure that table gets do not borrow the table, but instead just borrow lua.
|
||||
let tin;
|
||||
{
|
||||
let touter = globals.get::<_, Table>("touter").unwrap();
|
||||
tin = touter.get::<_, Table>("tin").unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(tin.get::<_, i64>(1).unwrap(), 1);
|
||||
assert_eq!(tin.get::<_, i64>(2).unwrap(), 2);
|
||||
assert_eq!(tin.get::<_, i64>(3).unwrap(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_metatable() {
|
||||
let lua = Lua::new();
|
||||
|
||||
let table = lua.create_table().unwrap();
|
||||
let metatable = lua.create_table().unwrap();
|
||||
metatable
|
||||
.set(
|
||||
"__index",
|
||||
lua.create_function(|_, ()| Ok("index_value")).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
table.set_metatable(Some(metatable));
|
||||
assert_eq!(table.get::<_, String>("any_key").unwrap(), "index_value");
|
||||
match table.raw_get::<_, Value>("any_key").unwrap() {
|
||||
Nil => {}
|
||||
_ => panic!(),
|
||||
}
|
||||
table.set_metatable(None);
|
||||
match table.get::<_, Value>("any_key").unwrap() {
|
||||
Nil => {}
|
||||
_ => panic!(),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_table_error() {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
lua.exec::<()>(
|
||||
r#"
|
||||
table = {}
|
||||
setmetatable(table, {
|
||||
__index = function()
|
||||
error("lua error")
|
||||
end,
|
||||
__newindex = function()
|
||||
error("lua error")
|
||||
end,
|
||||
__len = function()
|
||||
error("lua error")
|
||||
end
|
||||
})
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
|
||||
let bad_table: Table = globals.get("table").unwrap();
|
||||
assert!(bad_table.set(1, 1).is_err());
|
||||
assert!(bad_table.get::<_, i32>(1).is_err());
|
||||
assert!(bad_table.len().is_err());
|
||||
assert!(bad_table.raw_set(1, 1).is_ok());
|
||||
assert!(bad_table.raw_get::<_, i32>(1).is_ok());
|
||||
assert_eq!(bad_table.raw_len(), 1);
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
|
||||
use std::panic::catch_unwind;
|
||||
|
||||
use {Error, Function, Lua, Thread, ThreadStatus};
|
||||
|
||||
#[test]
|
||||
fn test_thread() {
|
||||
let lua = Lua::new();
|
||||
let thread = lua.create_thread(lua.eval::<Function>(
|
||||
r#"
|
||||
function (s)
|
||||
local sum = s
|
||||
for i = 1,4 do
|
||||
sum = sum + coroutine.yield(sum)
|
||||
end
|
||||
return sum
|
||||
end
|
||||
"#,
|
||||
None,
|
||||
).unwrap())
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(thread.status(), ThreadStatus::Resumable);
|
||||
assert_eq!(thread.resume::<_, i64>(0).unwrap(), 0);
|
||||
assert_eq!(thread.status(), ThreadStatus::Resumable);
|
||||
assert_eq!(thread.resume::<_, i64>(1).unwrap(), 1);
|
||||
assert_eq!(thread.status(), ThreadStatus::Resumable);
|
||||
assert_eq!(thread.resume::<_, i64>(2).unwrap(), 3);
|
||||
assert_eq!(thread.status(), ThreadStatus::Resumable);
|
||||
assert_eq!(thread.resume::<_, i64>(3).unwrap(), 6);
|
||||
assert_eq!(thread.status(), ThreadStatus::Resumable);
|
||||
assert_eq!(thread.resume::<_, i64>(4).unwrap(), 10);
|
||||
assert_eq!(thread.status(), ThreadStatus::Unresumable);
|
||||
|
||||
let accumulate = lua.create_thread(lua.eval::<Function>(
|
||||
r#"
|
||||
function (sum)
|
||||
while true do
|
||||
sum = sum + coroutine.yield(sum)
|
||||
end
|
||||
end
|
||||
"#,
|
||||
None,
|
||||
).unwrap())
|
||||
.unwrap();
|
||||
|
||||
for i in 0..4 {
|
||||
accumulate.resume::<_, ()>(i).unwrap();
|
||||
}
|
||||
assert_eq!(accumulate.resume::<_, i64>(4).unwrap(), 10);
|
||||
assert_eq!(accumulate.status(), ThreadStatus::Resumable);
|
||||
assert!(accumulate.resume::<_, ()>("error").is_err());
|
||||
assert_eq!(accumulate.status(), ThreadStatus::Error);
|
||||
|
||||
let thread = lua.eval::<Thread>(
|
||||
r#"
|
||||
coroutine.create(function ()
|
||||
while true do
|
||||
coroutine.yield(42)
|
||||
end
|
||||
end)
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
assert_eq!(thread.status(), ThreadStatus::Resumable);
|
||||
assert_eq!(thread.resume::<_, i64>(()).unwrap(), 42);
|
||||
|
||||
let thread: Thread = lua.eval(
|
||||
r#"
|
||||
coroutine.create(function(arg)
|
||||
assert(arg == 42)
|
||||
local yieldarg = coroutine.yield(123)
|
||||
assert(yieldarg == 43)
|
||||
return 987
|
||||
end)
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
|
||||
assert_eq!(thread.resume::<_, u32>(42).unwrap(), 123);
|
||||
assert_eq!(thread.resume::<_, u32>(43).unwrap(), 987);
|
||||
|
||||
match thread.resume::<_, u32>(()) {
|
||||
Err(Error::CoroutineInactive) => {}
|
||||
Err(_) => panic!("resuming dead coroutine error is not CoroutineInactive kind"),
|
||||
_ => panic!("resuming dead coroutine did not return error"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coroutine_from_closure() {
|
||||
let lua = Lua::new();
|
||||
let thrd_main = lua.create_function(|_, ()| Ok(())).unwrap();
|
||||
lua.globals().set("main", thrd_main).unwrap();
|
||||
let thrd: Thread = lua.eval("coroutine.create(main)", None).unwrap();
|
||||
thrd.resume::<_, ()>(()).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coroutine_panic() {
|
||||
// check that coroutines propagate panics correctly
|
||||
let lua = Lua::new();
|
||||
let thrd_main = lua.create_function(|lua, ()| {
|
||||
// whoops, 'main' has a wrong type
|
||||
let _coro: u32 = lua.globals().get("main").unwrap();
|
||||
Ok(())
|
||||
}).unwrap();
|
||||
lua.globals().set("main", thrd_main.clone()).unwrap();
|
||||
let thrd: Thread = lua.create_thread(thrd_main).unwrap();
|
||||
|
||||
match catch_unwind(|| thrd.resume::<_, ()>(())) {
|
||||
Ok(r) => panic!("coroutine panic not propagated, instead returned {:?}", r),
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
use std::os::raw::c_void;
|
||||
|
||||
use {Function, LightUserData, Lua};
|
||||
|
||||
#[test]
|
||||
fn test_lightuserdata() {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
lua.exec::<()>(
|
||||
r#"
|
||||
function id(a)
|
||||
return a
|
||||
end
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
let res = globals
|
||||
.get::<_, Function>("id")
|
||||
.unwrap()
|
||||
.call::<_, LightUserData>(LightUserData(42 as *mut c_void))
|
||||
.unwrap();
|
||||
assert_eq!(res, LightUserData(42 as *mut c_void));
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
|
||||
use std::sync::Arc;
|
||||
|
||||
use {ExternalError, Function, Lua, MetaMethod, String, UserData, UserDataMethods};
|
||||
|
||||
#[test]
|
||||
fn test_user_data() {
|
||||
struct UserData1(i64);
|
||||
struct UserData2(Box<i64>);
|
||||
|
||||
impl UserData for UserData1 {};
|
||||
impl UserData for UserData2 {};
|
||||
|
||||
let lua = Lua::new();
|
||||
|
||||
let userdata1 = lua.create_userdata(UserData1(1)).unwrap();
|
||||
let userdata2 = lua.create_userdata(UserData2(Box::new(2))).unwrap();
|
||||
|
||||
assert!(userdata1.is::<UserData1>().unwrap());
|
||||
assert!(!userdata1.is::<UserData2>().unwrap());
|
||||
assert!(userdata2.is::<UserData2>().unwrap());
|
||||
assert!(!userdata2.is::<UserData1>().unwrap());
|
||||
|
||||
assert_eq!(userdata1.borrow::<UserData1>().unwrap().0, 1);
|
||||
assert_eq!(*userdata2.borrow::<UserData2>().unwrap().0, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_methods() {
|
||||
struct MyUserData(i64);
|
||||
|
||||
impl UserData for MyUserData {
|
||||
fn add_methods(methods: &mut UserDataMethods<Self>) {
|
||||
methods.add_method("get_value", |_, data, ()| Ok(data.0));
|
||||
methods.add_method_mut("set_value", |_, data, args| {
|
||||
data.0 = args;
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
let userdata = lua.create_userdata(MyUserData(42)).unwrap();
|
||||
globals.set("userdata", userdata.clone()).unwrap();
|
||||
lua.exec::<()>(
|
||||
r#"
|
||||
function get_it()
|
||||
return userdata:get_value()
|
||||
end
|
||||
|
||||
function set_it(i)
|
||||
return userdata:set_value(i)
|
||||
end
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
let get = globals.get::<_, Function>("get_it").unwrap();
|
||||
let set = globals.get::<_, Function>("set_it").unwrap();
|
||||
assert_eq!(get.call::<_, i64>(()).unwrap(), 42);
|
||||
userdata.borrow_mut::<MyUserData>().unwrap().0 = 64;
|
||||
assert_eq!(get.call::<_, i64>(()).unwrap(), 64);
|
||||
set.call::<_, ()>(100).unwrap();
|
||||
assert_eq!(get.call::<_, i64>(()).unwrap(), 100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_metamethods() {
|
||||
#[derive(Copy, Clone)]
|
||||
struct MyUserData(i64);
|
||||
|
||||
impl UserData for MyUserData {
|
||||
fn add_methods(methods: &mut UserDataMethods<Self>) {
|
||||
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 {
|
||||
Err(format_err!("no such custom index").to_lua_err())
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
globals.set("userdata1", MyUserData(7)).unwrap();
|
||||
globals.set("userdata2", MyUserData(3)).unwrap();
|
||||
assert_eq!(
|
||||
lua.eval::<MyUserData>("userdata1 + userdata2", None)
|
||||
.unwrap()
|
||||
.0,
|
||||
10
|
||||
);
|
||||
assert_eq!(
|
||||
lua.eval::<MyUserData>("userdata1 - userdata2", None)
|
||||
.unwrap()
|
||||
.0,
|
||||
4
|
||||
);
|
||||
assert_eq!(lua.eval::<i64>("userdata1:get()", None).unwrap(), 7);
|
||||
assert_eq!(lua.eval::<i64>("userdata2.inner", None).unwrap(), 3);
|
||||
assert!(lua.eval::<()>("userdata2.nonexist_field", None).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gc_userdata() {
|
||||
struct MyUserdata {
|
||||
id: u8,
|
||||
}
|
||||
|
||||
impl UserData for MyUserdata {
|
||||
fn add_methods(methods: &mut UserDataMethods<Self>) {
|
||||
methods.add_method("access", |_, this, ()| {
|
||||
assert!(this.id == 123);
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let lua = Lua::new();
|
||||
{
|
||||
let globals = lua.globals();
|
||||
globals.set("userdata", MyUserdata { id: 123 }).unwrap();
|
||||
}
|
||||
|
||||
assert!(lua.eval::<()>(
|
||||
r#"
|
||||
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()
|
||||
"#,
|
||||
None
|
||||
).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detroys_userdata() {
|
||||
struct MyUserdata(Arc<()>);
|
||||
|
||||
impl UserData for MyUserdata {}
|
||||
|
||||
let rc = Arc::new(());
|
||||
|
||||
let lua = Lua::new();
|
||||
{
|
||||
let globals = lua.globals();
|
||||
globals.set("userdata", MyUserdata(rc.clone())).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(Arc::strong_count(&rc), 2);
|
||||
drop(lua); // should destroy all objects
|
||||
assert_eq!(Arc::strong_count(&rc), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn user_value() {
|
||||
let lua = Lua::new();
|
||||
|
||||
struct MyUserData;
|
||||
impl UserData for MyUserData {}
|
||||
|
||||
let ud = lua.create_userdata(MyUserData).unwrap();
|
||||
ud.set_user_value("hello").unwrap();
|
||||
assert_eq!(ud.get_user_value::<String>().unwrap(), "hello");
|
||||
}
|
121
src/thread.rs
121
src/thread.rs
|
@ -139,124 +139,3 @@ impl<'lua> Thread<'lua> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::panic::catch_unwind;
|
||||
|
||||
use super::{Thread, ThreadStatus};
|
||||
use error::Error;
|
||||
use function::Function;
|
||||
use lua::Lua;
|
||||
|
||||
#[test]
|
||||
fn test_thread() {
|
||||
let lua = Lua::new();
|
||||
let thread = lua.create_thread(lua.eval::<Function>(
|
||||
r#"
|
||||
function (s)
|
||||
local sum = s
|
||||
for i = 1,4 do
|
||||
sum = sum + coroutine.yield(sum)
|
||||
end
|
||||
return sum
|
||||
end
|
||||
"#,
|
||||
None,
|
||||
).unwrap())
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(thread.status(), ThreadStatus::Resumable);
|
||||
assert_eq!(thread.resume::<_, i64>(0).unwrap(), 0);
|
||||
assert_eq!(thread.status(), ThreadStatus::Resumable);
|
||||
assert_eq!(thread.resume::<_, i64>(1).unwrap(), 1);
|
||||
assert_eq!(thread.status(), ThreadStatus::Resumable);
|
||||
assert_eq!(thread.resume::<_, i64>(2).unwrap(), 3);
|
||||
assert_eq!(thread.status(), ThreadStatus::Resumable);
|
||||
assert_eq!(thread.resume::<_, i64>(3).unwrap(), 6);
|
||||
assert_eq!(thread.status(), ThreadStatus::Resumable);
|
||||
assert_eq!(thread.resume::<_, i64>(4).unwrap(), 10);
|
||||
assert_eq!(thread.status(), ThreadStatus::Unresumable);
|
||||
|
||||
let accumulate = lua.create_thread(lua.eval::<Function>(
|
||||
r#"
|
||||
function (sum)
|
||||
while true do
|
||||
sum = sum + coroutine.yield(sum)
|
||||
end
|
||||
end
|
||||
"#,
|
||||
None,
|
||||
).unwrap())
|
||||
.unwrap();
|
||||
|
||||
for i in 0..4 {
|
||||
accumulate.resume::<_, ()>(i).unwrap();
|
||||
}
|
||||
assert_eq!(accumulate.resume::<_, i64>(4).unwrap(), 10);
|
||||
assert_eq!(accumulate.status(), ThreadStatus::Resumable);
|
||||
assert!(accumulate.resume::<_, ()>("error").is_err());
|
||||
assert_eq!(accumulate.status(), ThreadStatus::Error);
|
||||
|
||||
let thread = lua.eval::<Thread>(
|
||||
r#"
|
||||
coroutine.create(function ()
|
||||
while true do
|
||||
coroutine.yield(42)
|
||||
end
|
||||
end)
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
assert_eq!(thread.status(), ThreadStatus::Resumable);
|
||||
assert_eq!(thread.resume::<_, i64>(()).unwrap(), 42);
|
||||
|
||||
let thread: Thread = lua.eval(
|
||||
r#"
|
||||
coroutine.create(function(arg)
|
||||
assert(arg == 42)
|
||||
local yieldarg = coroutine.yield(123)
|
||||
assert(yieldarg == 43)
|
||||
return 987
|
||||
end)
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
|
||||
assert_eq!(thread.resume::<_, u32>(42).unwrap(), 123);
|
||||
assert_eq!(thread.resume::<_, u32>(43).unwrap(), 987);
|
||||
|
||||
match thread.resume::<_, u32>(()) {
|
||||
Err(Error::CoroutineInactive) => {}
|
||||
Err(_) => panic!("resuming dead coroutine error is not CoroutineInactive kind"),
|
||||
_ => panic!("resuming dead coroutine did not return error"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coroutine_from_closure() {
|
||||
let lua = Lua::new();
|
||||
let thrd_main = lua.create_function(|_, ()| Ok(())).unwrap();
|
||||
lua.globals().set("main", thrd_main).unwrap();
|
||||
let thrd: Thread = lua.eval("coroutine.create(main)", None).unwrap();
|
||||
thrd.resume::<_, ()>(()).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn coroutine_panic() {
|
||||
// check that coroutines propagate panics correctly
|
||||
let lua = Lua::new();
|
||||
let thrd_main = lua.create_function(|lua, ()| {
|
||||
// whoops, 'main' has a wrong type
|
||||
let _coro: u32 = lua.globals().get("main").unwrap();
|
||||
Ok(())
|
||||
}).unwrap();
|
||||
lua.globals().set("main", thrd_main.clone()).unwrap();
|
||||
let thrd: Thread = lua.create_thread(thrd_main).unwrap();
|
||||
|
||||
match catch_unwind(|| thrd.resume::<_, ()>(())) {
|
||||
Ok(r) => panic!("coroutine panic not propagated, instead returned {:?}", r),
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
29
src/types.rs
29
src/types.rs
|
@ -79,32 +79,3 @@ impl<'lua> Drop for LuaRef<'lua> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::LightUserData;
|
||||
use function::Function;
|
||||
use lua::Lua;
|
||||
|
||||
use std::os::raw::c_void;
|
||||
|
||||
#[test]
|
||||
fn test_lightuserdata() {
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
lua.exec::<()>(
|
||||
r#"
|
||||
function id(a)
|
||||
return a
|
||||
end
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
let res = globals
|
||||
.get::<_, Function>("id")
|
||||
.unwrap()
|
||||
.call::<_, LightUserData>(LightUserData(42 as *mut c_void))
|
||||
.unwrap();
|
||||
assert_eq!(res, LightUserData(42 as *mut c_void));
|
||||
}
|
||||
}
|
||||
|
|
189
src/userdata.rs
189
src/userdata.rs
|
@ -434,192 +434,3 @@ impl<'lua> AnyUserData<'lua> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::{MetaMethod, UserData, UserDataMethods};
|
||||
use error::ExternalError;
|
||||
use string::String;
|
||||
use function::Function;
|
||||
use lua::Lua;
|
||||
|
||||
#[test]
|
||||
fn test_user_data() {
|
||||
struct UserData1(i64);
|
||||
struct UserData2(Box<i64>);
|
||||
|
||||
impl UserData for UserData1 {};
|
||||
impl UserData for UserData2 {};
|
||||
|
||||
let lua = Lua::new();
|
||||
|
||||
let userdata1 = lua.create_userdata(UserData1(1)).unwrap();
|
||||
let userdata2 = lua.create_userdata(UserData2(Box::new(2))).unwrap();
|
||||
|
||||
assert!(userdata1.is::<UserData1>().unwrap());
|
||||
assert!(!userdata1.is::<UserData2>().unwrap());
|
||||
assert!(userdata2.is::<UserData2>().unwrap());
|
||||
assert!(!userdata2.is::<UserData1>().unwrap());
|
||||
|
||||
assert_eq!(userdata1.borrow::<UserData1>().unwrap().0, 1);
|
||||
assert_eq!(*userdata2.borrow::<UserData2>().unwrap().0, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_methods() {
|
||||
struct MyUserData(i64);
|
||||
|
||||
impl UserData for MyUserData {
|
||||
fn add_methods(methods: &mut UserDataMethods<Self>) {
|
||||
methods.add_method("get_value", |_, data, ()| Ok(data.0));
|
||||
methods.add_method_mut("set_value", |_, data, args| {
|
||||
data.0 = args;
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
let userdata = lua.create_userdata(MyUserData(42)).unwrap();
|
||||
globals.set("userdata", userdata.clone()).unwrap();
|
||||
lua.exec::<()>(
|
||||
r#"
|
||||
function get_it()
|
||||
return userdata:get_value()
|
||||
end
|
||||
|
||||
function set_it(i)
|
||||
return userdata:set_value(i)
|
||||
end
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
let get = globals.get::<_, Function>("get_it").unwrap();
|
||||
let set = globals.get::<_, Function>("set_it").unwrap();
|
||||
assert_eq!(get.call::<_, i64>(()).unwrap(), 42);
|
||||
userdata.borrow_mut::<MyUserData>().unwrap().0 = 64;
|
||||
assert_eq!(get.call::<_, i64>(()).unwrap(), 64);
|
||||
set.call::<_, ()>(100).unwrap();
|
||||
assert_eq!(get.call::<_, i64>(()).unwrap(), 100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_metamethods() {
|
||||
#[derive(Copy, Clone)]
|
||||
struct MyUserData(i64);
|
||||
|
||||
impl UserData for MyUserData {
|
||||
fn add_methods(methods: &mut UserDataMethods<Self>) {
|
||||
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 {
|
||||
Err(format_err!("no such custom index").to_lua_err())
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
globals.set("userdata1", MyUserData(7)).unwrap();
|
||||
globals.set("userdata2", MyUserData(3)).unwrap();
|
||||
assert_eq!(
|
||||
lua.eval::<MyUserData>("userdata1 + userdata2", None)
|
||||
.unwrap()
|
||||
.0,
|
||||
10
|
||||
);
|
||||
assert_eq!(
|
||||
lua.eval::<MyUserData>("userdata1 - userdata2", None)
|
||||
.unwrap()
|
||||
.0,
|
||||
4
|
||||
);
|
||||
assert_eq!(lua.eval::<i64>("userdata1:get()", None).unwrap(), 7);
|
||||
assert_eq!(lua.eval::<i64>("userdata2.inner", None).unwrap(), 3);
|
||||
assert!(lua.eval::<()>("userdata2.nonexist_field", None).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gc_userdata() {
|
||||
struct MyUserdata {
|
||||
id: u8,
|
||||
}
|
||||
|
||||
impl UserData for MyUserdata {
|
||||
fn add_methods(methods: &mut UserDataMethods<Self>) {
|
||||
methods.add_method("access", |_, this, ()| {
|
||||
assert!(this.id == 123);
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let lua = Lua::new();
|
||||
{
|
||||
let globals = lua.globals();
|
||||
globals.set("userdata", MyUserdata { id: 123 }).unwrap();
|
||||
}
|
||||
|
||||
assert!(lua.eval::<()>(
|
||||
r#"
|
||||
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()
|
||||
"#,
|
||||
None
|
||||
).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detroys_userdata() {
|
||||
struct MyUserdata(Arc<()>);
|
||||
|
||||
impl UserData for MyUserdata {}
|
||||
|
||||
let rc = Arc::new(());
|
||||
|
||||
let lua = Lua::new();
|
||||
{
|
||||
let globals = lua.globals();
|
||||
globals.set("userdata", MyUserdata(rc.clone())).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(Arc::strong_count(&rc), 2);
|
||||
drop(lua); // should destroy all objects
|
||||
assert_eq!(Arc::strong_count(&rc), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn user_value() {
|
||||
let lua = Lua::new();
|
||||
|
||||
struct MyUserData;
|
||||
impl UserData for MyUserData {}
|
||||
|
||||
let ud = lua.create_userdata(MyUserData).unwrap();
|
||||
ud.set_user_value("hello").unwrap();
|
||||
assert_eq!(ud.get_user_value::<String>().unwrap(), "hello");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue