2023-01-21 03:01:02 +00:00
|
|
|
use anyhow::Result;
|
|
|
|
use mlua::Lua;
|
|
|
|
|
|
|
|
pub mod globals;
|
|
|
|
pub mod utils;
|
|
|
|
|
|
|
|
use crate::{
|
2023-01-21 18:33:33 +00:00
|
|
|
globals::{ConsoleGlobal, FsGlobal, NetGlobal, ProcessGlobal, TaskGlobal},
|
2023-01-21 03:01:02 +00:00
|
|
|
utils::formatting::{pretty_print_luau_error, print_label},
|
|
|
|
};
|
|
|
|
|
|
|
|
pub struct Lune {
|
|
|
|
lua: Lua,
|
|
|
|
args: Vec<String>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Lune {
|
|
|
|
pub fn new() -> Result<Self> {
|
|
|
|
let lua = Lua::new();
|
|
|
|
lua.sandbox(true)?;
|
|
|
|
Ok(Self { lua, args: vec![] })
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_args(mut self, args: Vec<String>) -> Result<Self> {
|
|
|
|
self.args = args;
|
|
|
|
Ok(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_default_globals(self) -> Result<Self> {
|
|
|
|
{
|
|
|
|
let globals = self.lua.globals();
|
2023-01-21 18:33:33 +00:00
|
|
|
globals.raw_set("console", ConsoleGlobal::new())?;
|
|
|
|
globals.raw_set("fs", FsGlobal::new())?;
|
|
|
|
globals.raw_set("net", NetGlobal::new())?;
|
|
|
|
globals.raw_set("process", ProcessGlobal::new(self.args.clone()))?;
|
|
|
|
globals.raw_set("task", TaskGlobal::new())?;
|
|
|
|
globals.set_readonly(true);
|
2023-01-21 03:01:02 +00:00
|
|
|
}
|
|
|
|
Ok(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn run(&self, chunk: &str) -> Result<()> {
|
|
|
|
self.handle_result(self.lua.load(chunk).exec_async().await)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn run_with_name(&self, chunk: &str, name: &str) -> Result<()> {
|
|
|
|
self.handle_result(self.lua.load(chunk).set_name(name)?.exec_async().await)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn handle_result(&self, result: mlua::Result<()>) -> Result<()> {
|
|
|
|
match result {
|
|
|
|
Ok(_) => Ok(()),
|
|
|
|
Err(e) => {
|
|
|
|
eprintln!();
|
|
|
|
print_label("ERROR").unwrap();
|
|
|
|
eprintln!();
|
|
|
|
pretty_print_luau_error(&e);
|
2023-01-21 04:40:31 +00:00
|
|
|
Err(e.into())
|
2023-01-21 03:01:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-01-21 05:03:16 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
macro_rules! run_tests {
|
|
|
|
($($name:ident: $value:expr,)*) => {
|
|
|
|
$(
|
|
|
|
#[tokio::test]
|
|
|
|
async fn $name() {
|
|
|
|
let args = vec![
|
|
|
|
"Foo".to_owned(),
|
|
|
|
"Bar".to_owned()
|
|
|
|
];
|
|
|
|
let path = std::env::current_dir()
|
|
|
|
.unwrap()
|
|
|
|
.join(format!("src/tests/{}.luau", $value));
|
|
|
|
let lune = crate::Lune::new()
|
|
|
|
.unwrap()
|
|
|
|
.with_args(args)
|
|
|
|
.unwrap()
|
|
|
|
.with_default_globals()
|
|
|
|
.unwrap();
|
|
|
|
let script = tokio::fs::read_to_string(&path)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
if let Err(e) = lune.run_with_name(&script, $value).await {
|
2023-01-21 06:10:19 +00:00
|
|
|
panic!("Test '{}' failed!\n{}", $value, e.to_string())
|
2023-01-21 05:03:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
)*
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
run_tests! {
|
2023-01-21 06:37:31 +00:00
|
|
|
console_format: "console/format",
|
|
|
|
console_set_color: "console/set_color",
|
|
|
|
console_set_style: "console/set_style",
|
2023-01-21 07:01:46 +00:00
|
|
|
fs_files: "fs/files",
|
|
|
|
fs_dirs: "fs/dirs",
|
2023-01-21 05:03:16 +00:00
|
|
|
process_args: "process/args",
|
|
|
|
process_env: "process/env",
|
2023-01-21 07:07:17 +00:00
|
|
|
// NOTE: This test does not currently work, it will exit the entire
|
|
|
|
// process, meaning it will also exit our test runner and skip testing
|
|
|
|
// process_exit: "process/exit",
|
2023-01-21 05:03:16 +00:00
|
|
|
process_spawn: "process/spawn",
|
2023-01-21 06:10:19 +00:00
|
|
|
net_request_codes: "net/request/codes",
|
|
|
|
net_request_methods: "net/request/methods",
|
|
|
|
net_request_redirect: "net/request/redirect",
|
|
|
|
net_json_decode: "net/json/decode",
|
|
|
|
net_json_encode: "net/json/encode",
|
2023-01-21 20:07:18 +00:00
|
|
|
task_defer: "task/defer",
|
|
|
|
task_delay: "task/delay",
|
|
|
|
task_spawn: "task/spawn",
|
2023-01-21 18:33:33 +00:00
|
|
|
task_wait: "task/wait",
|
2023-01-21 05:03:16 +00:00
|
|
|
}
|
|
|
|
}
|