Update tests (async and table)

This commit is contained in:
Alex Orlenko 2020-04-20 01:14:34 +01:00
parent c826798a6d
commit 4e19ae6ccf
2 changed files with 167 additions and 15 deletions

View File

@ -1,11 +1,13 @@
#![cfg(feature = "async")] #![cfg(feature = "async")]
use std::cell::Cell;
use std::rc::Rc; use std::rc::Rc;
use std::time::Duration; use std::time::Duration;
use futures_timer::Delay;
use futures_util::stream::TryStreamExt; use futures_util::stream::TryStreamExt;
use mlua::{Error, Function, Lua, Result}; use mlua::{Error, Function, Lua, Result, Table, TableExt, UserData, UserDataMethods};
#[tokio::test] #[tokio::test]
async fn test_async_function() -> Result<()> { async fn test_async_function() -> Result<()> {
@ -26,7 +28,7 @@ async fn test_async_sleep() -> Result<()> {
let lua = Lua::new(); let lua = Lua::new();
let sleep = lua.create_async_function(move |_lua, n: u64| async move { let sleep = lua.create_async_function(move |_lua, n: u64| async move {
futures_timer::Delay::new(Duration::from_millis(n)).await; Delay::new(Duration::from_millis(n)).await;
Ok(format!("elapsed:{}ms", n)) Ok(format!("elapsed:{}ms", n))
})?; })?;
lua.globals().set("sleep", sleep)?; lua.globals().set("sleep", sleep)?;
@ -41,19 +43,19 @@ async fn test_async_sleep() -> Result<()> {
async fn test_async_call() -> Result<()> { async fn test_async_call() -> Result<()> {
let lua = Lua::new(); let lua = Lua::new();
let sleep = lua.create_async_function(|_lua, name: String| async move { let hello = lua.create_async_function(|_lua, name: String| async move {
futures_timer::Delay::new(Duration::from_millis(10)).await; Delay::new(Duration::from_millis(10)).await;
Ok(format!("hello, {}!", name)) Ok(format!("hello, {}!", name))
})?; })?;
match sleep.call::<_, ()>("alex") { match hello.call::<_, ()>("alex") {
Err(Error::RuntimeError(_)) => {} Err(Error::RuntimeError(_)) => {}
_ => panic!( _ => panic!(
"non-async executing async function must fail on the yield stage with RuntimeError" "non-async executing async function must fail on the yield stage with RuntimeError"
), ),
}; };
assert_eq!(sleep.call_async::<_, String>("alex").await?, "hello, alex!"); assert_eq!(hello.call_async::<_, String>("alex").await?, "hello, alex!");
// Executing non-async functions using async call is allowed // Executing non-async functions using async call is allowed
let sum = lua.create_function(|_lua, (a, b): (i64, i64)| return Ok(a + b))?; let sum = lua.create_function(|_lua, (a, b): (i64, i64)| return Ok(a + b))?;
@ -66,13 +68,13 @@ async fn test_async_call() -> Result<()> {
async fn test_async_bind_call() -> Result<()> { async fn test_async_bind_call() -> Result<()> {
let lua = Lua::new(); let lua = Lua::new();
let less = lua.create_async_function(|_lua, (a, b): (i64, i64)| async move { Ok(a < b) })?; let sum = lua.create_async_function(|_lua, (a, b): (i64, i64)| async move { Ok(a + b) })?;
let less_bound = less.bind(0)?; let plus_10 = sum.bind(10)?;
lua.globals().set("f", less_bound)?; lua.globals().set("plus_10", plus_10)?;
assert_eq!(lua.load("f(-1)").eval_async::<bool>().await?, false); assert_eq!(lua.load("plus_10(-1)").eval_async::<i64>().await?, 9);
assert_eq!(lua.load("f(1)").eval_async::<bool>().await?, true); assert_eq!(lua.load("plus_10(1)").eval_async::<i64>().await?, 11);
Ok(()) Ok(())
} }
@ -82,7 +84,7 @@ async fn test_async_handle_yield() -> Result<()> {
let lua = Lua::new(); let lua = Lua::new();
let sum = lua.create_async_function(|_lua, (a, b): (i64, i64)| async move { let sum = lua.create_async_function(|_lua, (a, b): (i64, i64)| async move {
futures_timer::Delay::new(Duration::from_millis(100)).await; Delay::new(Duration::from_millis(10)).await;
Ok(a + b) Ok(a + b)
})?; })?;
@ -117,6 +119,33 @@ async fn test_async_handle_yield() -> Result<()> {
Ok(()) Ok(())
} }
#[tokio::test]
async fn test_async_return_async_closure() -> Result<()> {
let lua = Lua::new();
let f = lua.create_async_function(|lua, a: i64| async move {
Delay::new(Duration::from_millis(10)).await;
let g = lua.create_async_function(move |_, b: i64| async move {
Delay::new(Duration::from_millis(10)).await;
return Ok(a + b);
})?;
Ok(g)
})?;
lua.globals().set("f", f)?;
let res: i64 = lua
.load("local g = f(1); return g(2) + g(3)")
.call_async(())
.await?;
assert_eq!(res, 7);
Ok(())
}
#[tokio::test] #[tokio::test]
async fn test_async_thread_stream() -> Result<()> { async fn test_async_thread_stream() -> Result<()> {
let lua = Lua::new(); let lua = Lua::new();
@ -151,12 +180,12 @@ async fn test_async_thread_stream() -> Result<()> {
async fn test_async_thread() -> Result<()> { async fn test_async_thread() -> Result<()> {
let lua = Lua::new(); let lua = Lua::new();
let cnt = Rc::new(100); // sleep 100ms let cnt = Rc::new(10); // sleep 10ms
let cnt2 = cnt.clone(); let cnt2 = cnt.clone();
let f = lua.create_async_function(move |_lua, ()| { let f = lua.create_async_function(move |_lua, ()| {
let cnt3 = cnt2.clone(); let cnt3 = cnt2.clone();
async move { async move {
futures_timer::Delay::new(Duration::from_millis(*cnt3.as_ref())).await; Delay::new(Duration::from_millis(*cnt3.as_ref())).await;
Ok("done") Ok("done")
} }
})?; })?;
@ -171,3 +200,96 @@ async fn test_async_thread() -> Result<()> {
Ok(()) Ok(())
} }
#[tokio::test]
async fn test_async_table() -> Result<()> {
let lua = Lua::new();
let table = lua.create_table()?;
table.set("val", 10)?;
let get_value = lua.create_async_function(|_, table: Table| async move {
Delay::new(Duration::from_millis(10)).await;
table.get::<_, i64>("val")
})?;
table.set("get_value", get_value)?;
let set_value = lua.create_async_function(|_, (table, n): (Table, i64)| async move {
Delay::new(Duration::from_millis(10)).await;
table.set("val", n)
})?;
table.set("set_value", set_value)?;
let sleep = lua.create_async_function(|_, n| async move {
Delay::new(Duration::from_millis(n)).await;
Ok(format!("elapsed:{}ms", n))
})?;
table.set("sleep", sleep)?;
assert_eq!(
table
.call_async_method::<_, _, i64>("get_value", ())
.await?,
10
);
table.call_async_method("set_value", 15).await?;
assert_eq!(
table
.call_async_method::<_, _, i64>("get_value", ())
.await?,
15
);
assert_eq!(
table
.call_async_function::<_, _, String>("sleep", 7)
.await?,
"elapsed:7ms"
);
Ok(())
}
#[tokio::test]
async fn test_async_userdata() -> Result<()> {
#[derive(Clone)]
struct MyUserData(Rc<Cell<i64>>);
impl UserData for MyUserData {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_async_method("get_value", |_, data, ()| async move {
Delay::new(Duration::from_millis(10)).await;
Ok(data.0.get())
});
methods.add_async_method("set_value", |_, data, n| async move {
Delay::new(Duration::from_millis(10)).await;
data.0.set(n);
Ok(())
});
methods.add_async_function("sleep", |_, n| async move {
Delay::new(Duration::from_millis(n)).await;
Ok(format!("elapsed:{}ms", n))
});
}
}
let lua = Lua::new();
let globals = lua.globals();
let userdata = lua.create_userdata(MyUserData(Rc::new(Cell::new(11))))?;
globals.set("userdata", userdata.clone())?;
lua.load(
r#"
assert(userdata:get_value() == 11)
userdata:set_value(12)
assert(userdata:get_value() == 12)
assert(userdata.sleep(5) == "elapsed:5ms")
"#,
)
.exec_async()
.await?;
Ok(())
}

View File

@ -1,4 +1,4 @@
use mlua::{Lua, Nil, Result, Table, Value}; use mlua::{Lua, Nil, Result, Table, TableExt, Value};
#[test] #[test]
fn test_set_get() -> Result<()> { fn test_set_get() -> Result<()> {
@ -226,3 +226,33 @@ fn test_table_error() -> Result<()> {
Ok(()) Ok(())
} }
#[test]
fn test_table_call() -> Result<()> {
let lua = Lua::new();
lua.load(
r#"
table = {a = 1}
function table.func(key)
return "func_"..key
end
function table:method(key)
return "method_"..self[key]
end
"#,
)
.exec()?;
let table: Table = lua.globals().get("table")?;
assert_eq!(table.call_function::<_, _, String>("func", "a")?, "func_a");
assert_eq!(
table.call_method::<_, _, String>("method", "a")?,
"method_1"
);
Ok(())
}