Move all tests into a tests/ subfolder

This commit is contained in:
kyren 2018-02-09 23:52:05 -05:00
parent d331e4b97c
commit 60743d45cd
13 changed files with 632 additions and 662 deletions

View File

@ -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");
}
}

View File

@ -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(), &[]);
}
}

View File

@ -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);
}
}

68
src/tests/function.rs Normal file
View File

@ -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");
}

View File

@ -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;

60
src/tests/string.rs Normal file
View File

@ -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(), &[]);
}

177
src/tests/table.rs Normal file
View File

@ -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);
}

115
src/tests/thread.rs Normal file
View File

@ -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(_) => {}
}
}

23
src/tests/types.rs Normal file
View File

@ -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));
}

182
src/tests/userdata.rs Normal file
View File

@ -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");
}

View File

@ -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(_) => {}
}
}
}

View File

@ -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));
}
}

View File

@ -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");
}
}