rlua-searcher/tests/tests.rs

237 lines
6.4 KiB
Rust
Raw Normal View History

use rlua::{Context, Lua, Table, UserData, UserDataMethods, Value};
use rlua_searcher::{AddSearcher, Result};
use std::collections::HashMap;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
#[test]
fn add_searcher_works() {
let lume = read_lume_to_string();
let name = "lume".to_string();
let mut map = HashMap::new();
map.insert(name, lume);
let lua = Lua::new();
let hello = lua
.context::<_, Result<String>>(|lua_ctx| {
lua_ctx.add_searcher(map)?;
Ok(lua_ctx.load(r#"return require("lume")"#).eval()?)
})
.unwrap();
assert_eq!("hello lume", hello);
}
#[test]
fn add_static_searcher_works() {
let lume = read_lume_to_str();
let name = "lume";
let mut map = HashMap::new();
map.insert(name, lume);
let lua = Lua::new();
let hello = lua
.context::<_, Result<String>>(|lua_ctx| {
lua_ctx.add_static_searcher(map)?;
Ok(lua_ctx.load(r#"return require("lume")"#).eval()?)
})
.unwrap();
assert_eq!("hello lume", hello);
}
#[test]
fn add_path_searcher_works() {
let name = "lume".to_string();
let path = PathBuf::new()
.join(std::env::var("CARGO_MANIFEST_DIR").unwrap())
.join("tests")
.join("data")
.join("lume.lua");
let mut map = HashMap::new();
map.insert(name, path);
let lua = Lua::new();
let hello = lua
.context::<_, Result<String>>(|lua_ctx| {
lua_ctx.add_path_searcher(map)?;
Ok(lua_ctx.load(r#"return require("lume")"#).eval()?)
})
.unwrap();
assert_eq!("hello lume", hello);
}
#[test]
fn module_reloading_works() {
let name = "lume".to_string();
let path = PathBuf::new()
.join(std::env::var("CARGO_MANIFEST_DIR").unwrap())
.join("tests")
.join("data")
.join("lume.lua");
let mut map = HashMap::new();
map.insert(name.clone(), path.clone());
let lua = Lua::new();
// Add searcher for lume module on disk, and read from it.
let hello = lua
.context::<_, Result<String>>(|lua_ctx| {
lua_ctx.add_path_searcher(map)?;
Ok(lua_ctx.load(r#"return require("lume")"#).eval()?)
})
.unwrap();
assert_eq!("hello lume", hello);
// Twice.
let hello = lua
.context::<_, Result<String>>(|lua_ctx| {
Ok(lua_ctx.load(r#"return require("lume")"#).eval()?)
})
.unwrap();
assert_eq!("hello lume", hello);
// Modify lume module on disk.
let mut out = File::create(path.clone()).expect("Could not create Lume module on disk");
write!(out, "{}\n", r#"return "hello again lume""#)
.expect("Could not modify Lume module on disk");
// Thrice. Should still be unchanged due to caching.
let hello = lua
.context::<_, Result<String>>(|lua_ctx| {
Ok(lua_ctx.load(r#"return require("lume")"#).eval()?)
})
.unwrap();
assert_eq!("hello lume", hello);
// Remove lume module from Luas `package.loaded` cache to facilitate reload.
lua.context::<_, rlua::Result<()>>(|lua_ctx| {
let globals = lua_ctx.globals();
let loaded: Table = globals.get::<_, Table>("package")?.get("loaded")?;
loaded.set(name.clone(), Value::Nil)
})
.unwrap();
// Re-read from lume module on disk.
let hello = lua
.context::<_, Result<String>>(|lua_ctx| {
Ok(lua_ctx.load(r#"return require("lume")"#).eval()?)
})
.unwrap();
assert_eq!("hello again lume", hello);
// Twice.
let hello = lua
.context::<_, Result<String>>(|lua_ctx| {
Ok(lua_ctx.load(r#"return require("lume")"#).eval()?)
})
.unwrap();
assert_eq!("hello again lume", hello);
// Revert changes to lume module on disk.
let mut out = File::create(path).expect("Could not create Lume module on disk");
write!(out, "{}\n", r#"return "hello lume""#).expect("Could not modify Lume module on disk");
// Clear cache again.
lua.context::<_, rlua::Result<()>>(|lua_ctx| {
let globals = lua_ctx.globals();
let loaded: Table = globals.get::<_, Table>("package")?.get("loaded")?;
loaded.set(name, Value::Nil)
})
.unwrap();
// Ensure changes have been successfully reverted.
let hello = lua
.context::<_, Result<String>>(|lua_ctx| {
Ok(lua_ctx.load(r#"return require("lume")"#).eval()?)
})
.unwrap();
assert_eq!("hello lume", hello);
}
#[test]
fn add_closure_searcher_works() {
let lua = Lua::new();
let mut modules: HashMap<
&'static str,
Box<dyn Fn(Context) -> rlua::Result<&'static str> + Send>,
> = HashMap::new();
let instrument_loader = Box::new(|lua_ctx: Context| {
let globals = lua_ctx.globals();
let new = lua_ctx.create_function(|_, (name, sound): (String, String)| {
Ok(Instrument::new(name, sound))
})?;
let tbl = lua_ctx.create_table()?;
tbl.set("new", new)?;
globals.set("instrument", tbl)?;
Ok("return instrument")
});
modules.insert("instrument", instrument_loader);
let sound = lua
.context::<_, Result<String>>(|lua_ctx| {
lua_ctx.add_closure_searcher(modules)?;
// Ensure global variable `instrument` is unset.
let nil: String = lua_ctx.load("return type(instrument)").eval()?;
assert_eq!(nil, "nil");
Ok(lua_ctx
.load(
r#"local instrument = require("instrument")
local ukulele = instrument.new("ukulele", "twang")
return ukulele:play()"#,
)
.eval()?)
})
.unwrap();
assert_eq!(sound, "The ukulele goes twang");
}
struct Instrument {
name: String,
sound: String,
}
impl Instrument {
pub fn new(name: String, sound: String) -> Self {
Self { name, sound }
}
pub fn play(&self) -> String {
format!("The {} goes {}", self.name, self.sound)
}
}
impl UserData for Instrument {
fn add_methods<'lua, M>(methods: &mut M)
where
M: UserDataMethods<'lua, Self>,
{
methods.add_method("play", |_, instrument, ()| Ok(instrument.play()));
}
}
fn read_lume_to_string() -> String {
r#"return "hello lume""#.to_string()
}
fn read_lume_to_str() -> &'static str {
r#"return "hello lume""#
}