From 60743d45cd5c98f8235c1284f31a931b75cc0c43 Mon Sep 17 00:00:00 2001 From: kyren Date: Fri, 9 Feb 2018 23:52:05 -0500 Subject: [PATCH] Move all tests into a tests/ subfolder --- src/function.rs | 74 ------------- src/string.rs | 65 ------------ src/table.rs | 184 -------------------------------- src/tests/function.rs | 68 ++++++++++++ src/{tests.rs => tests/mod.rs} | 7 ++ src/tests/string.rs | 60 +++++++++++ src/tests/table.rs | 177 ++++++++++++++++++++++++++++++ src/tests/thread.rs | 115 ++++++++++++++++++++ src/tests/types.rs | 23 ++++ src/tests/userdata.rs | 182 +++++++++++++++++++++++++++++++ src/thread.rs | 121 --------------------- src/types.rs | 29 ----- src/userdata.rs | 189 --------------------------------- 13 files changed, 632 insertions(+), 662 deletions(-) create mode 100644 src/tests/function.rs rename src/{tests.rs => tests/mod.rs} (99%) create mode 100644 src/tests/string.rs create mode 100644 src/tests/table.rs create mode 100644 src/tests/thread.rs create mode 100644 src/tests/types.rs create mode 100644 src/tests/userdata.rs diff --git a/src/function.rs b/src/function.rs index 5537a45..c268de3 100644 --- a/src/function.rs +++ b/src/function.rs @@ -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"); - } -} diff --git a/src/string.rs b/src/string.rs index a205dde..5eda24a 100644 --- a/src/string.rs +++ b/src/string.rs @@ -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(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 - 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(), &[]); - } -} diff --git a/src/table.rs b/src/table.rs index cadb077..afac271 100644 --- a/src/table.rs +++ b/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::>>() - .unwrap(), - vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)] - ); - assert_eq!( - table1 - .clone() - .sequence_values() - .collect::>>() - .unwrap(), - vec![1, 2, 3, 4, 5] - ); - - assert_eq!(table2.len().unwrap(), 0); - assert_eq!( - table2 - .clone() - .pairs() - .collect::>>() - .unwrap(), - vec![] - ); - assert_eq!( - table2 - .sequence_values() - .collect::>>() - .unwrap(), - vec![] - ); - - // sequence_values should only iterate until the first border - assert_eq!( - table3 - .sequence_values() - .collect::>>() - .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::>>().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); - } -} diff --git a/src/tests/function.rs b/src/tests/function.rs new file mode 100644 index 0000000..2945a2e --- /dev/null +++ b/src/tests/function.rs @@ -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"); +} diff --git a/src/tests.rs b/src/tests/mod.rs similarity index 99% rename from src/tests.rs rename to src/tests/mod.rs index 1cd5970..aaaff94 100644 --- a/src/tests.rs +++ b/src/tests/mod.rs @@ -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; diff --git a/src/tests/string.rs b/src/tests/string.rs new file mode 100644 index 0000000..ccaeb8d --- /dev/null +++ b/src/tests/string.rs @@ -0,0 +1,60 @@ +use std::borrow::Cow; + +use {Lua, String}; + +fn with_str(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 + 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(), &[]); +} diff --git a/src/tests/table.rs b/src/tests/table.rs new file mode 100644 index 0000000..d48b7be --- /dev/null +++ b/src/tests/table.rs @@ -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::>>() + .unwrap(), + vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)] + ); + assert_eq!( + table1 + .clone() + .sequence_values() + .collect::>>() + .unwrap(), + vec![1, 2, 3, 4, 5] + ); + + assert_eq!(table2.len().unwrap(), 0); + assert_eq!( + table2 + .clone() + .pairs() + .collect::>>() + .unwrap(), + vec![] + ); + assert_eq!( + table2 + .sequence_values() + .collect::>>() + .unwrap(), + vec![] + ); + + // sequence_values should only iterate until the first border + assert_eq!( + table3 + .sequence_values() + .collect::>>() + .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::>>().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); +} diff --git a/src/tests/thread.rs b/src/tests/thread.rs new file mode 100644 index 0000000..2d483a0 --- /dev/null +++ b/src/tests/thread.rs @@ -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::( + 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::( + 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::( + 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(_) => {} + } +} diff --git a/src/tests/types.rs b/src/tests/types.rs new file mode 100644 index 0000000..2981701 --- /dev/null +++ b/src/tests/types.rs @@ -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)); +} diff --git a/src/tests/userdata.rs b/src/tests/userdata.rs new file mode 100644 index 0000000..4af0f6e --- /dev/null +++ b/src/tests/userdata.rs @@ -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); + + 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::().unwrap()); + assert!(!userdata1.is::().unwrap()); + assert!(userdata2.is::().unwrap()); + assert!(!userdata2.is::().unwrap()); + + assert_eq!(userdata1.borrow::().unwrap().0, 1); + assert_eq!(*userdata2.borrow::().unwrap().0, 2); +} + +#[test] +fn test_methods() { + struct MyUserData(i64); + + impl UserData for MyUserData { + fn add_methods(methods: &mut UserDataMethods) { + 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::().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) { + 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::("userdata1 + userdata2", None) + .unwrap() + .0, + 10 + ); + assert_eq!( + lua.eval::("userdata1 - userdata2", None) + .unwrap() + .0, + 4 + ); + assert_eq!(lua.eval::("userdata1:get()", None).unwrap(), 7); + assert_eq!(lua.eval::("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) { + 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::().unwrap(), "hello"); +} diff --git a/src/thread.rs b/src/thread.rs index 1ab62b2..d775827 100644 --- a/src/thread.rs +++ b/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::( - 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::( - 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::( - 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(_) => {} - } - } -} diff --git a/src/types.rs b/src/types.rs index 1fb9f30..da45b91 100644 --- a/src/types.rs +++ b/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)); - } -} diff --git a/src/userdata.rs b/src/userdata.rs index a870d71..c48a1b4 100644 --- a/src/userdata.rs +++ b/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); - - 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::().unwrap()); - assert!(!userdata1.is::().unwrap()); - assert!(userdata2.is::().unwrap()); - assert!(!userdata2.is::().unwrap()); - - assert_eq!(userdata1.borrow::().unwrap().0, 1); - assert_eq!(*userdata2.borrow::().unwrap().0, 2); - } - - #[test] - fn test_methods() { - struct MyUserData(i64); - - impl UserData for MyUserData { - fn add_methods(methods: &mut UserDataMethods) { - 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::().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) { - 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::("userdata1 + userdata2", None) - .unwrap() - .0, - 10 - ); - assert_eq!( - lua.eval::("userdata1 - userdata2", None) - .unwrap() - .0, - 4 - ); - assert_eq!(lua.eval::("userdata1:get()", None).unwrap(), 7); - assert_eq!(lua.eval::("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) { - 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::().unwrap(), "hello"); - } -}