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()
|
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::{error, fmt};
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::rc::Rc;
|
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