diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 82260a4f7..0fdd30e4c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -53,6 +53,10 @@ jobs: key: ${{ runner.os }}-imix-cargo-${{ hashFiles('**/Cargo.lock') }} restore-keys: | ${{ runner.os }}-imix-cargo- + - if: matrix.os == 'windows-latest' + run: start-process -filepath powershell -ArgumentList '/c','Set-MpPreference -DisableRealtimeMonitoring $true' -verb RunAs + name: 👾 Disable defender + shell: powershell - name: 🔨 Build run: cd implants/imix && cargo build --verbose - name: 🔎 Run tests @@ -79,6 +83,10 @@ jobs: key: ${{ runner.os }}-eldritch-cargo-${{ hashFiles('**/Cargo.lock') }} restore-keys: | ${{ runner.os }}-eldritch-cargo- + - if: matrix.os == 'windows-latest' + run: start-process -filepath powershell -ArgumentList '/c','Set-MpPreference -DisableRealtimeMonitoring $true' -verb RunAs + name: 👾 Disable defender + shell: powershell - name: 🔨 Build run: cd implants/eldritch && cargo build --verbose - name: 🔎 Run tests diff --git a/implants/eldritch/src/lib.rs b/implants/eldritch/src/lib.rs index 739f435f9..d1c47c9c4 100644 --- a/implants/eldritch/src/lib.rs +++ b/implants/eldritch/src/lib.rs @@ -29,6 +29,7 @@ pub fn get_eldritch() -> anyhow::Result { } pub fn eldritch_run(tome_filename: String, tome_contents: String, tome_parameters: Option) -> anyhow::Result { + // Boilder plate let ast: AstModule; match AstModule::parse( &tome_filename, @@ -41,7 +42,7 @@ pub fn eldritch_run(tome_filename: String, tome_contents: String, tome_parameter let tome_params_str: String = match tome_parameters { Some(param_string) => param_string, - None => "".to_string(), + None => "{}".to_string(), }; let globals = get_eldritch()?; @@ -50,7 +51,7 @@ pub fn eldritch_run(tome_filename: String, tome_contents: String, tome_parameter let res: SmallMap = SmallMap::new(); let mut input_params: Dict = Dict::new(res); - + let parsed: serde_json::Value = serde_json::from_str(&tome_params_str)?; let param_map: serde_json::Map = match parsed.as_object() { Some(tmp_param_map) => tmp_param_map.clone(), @@ -110,10 +111,13 @@ pub fn eldritch_run(tome_filename: String, tome_contents: String, tome_parameter #[cfg(test)] mod tests { + use std::thread; + use super::*; use starlark::environment::{GlobalsBuilder}; use starlark::{starlark_module}; use starlark::assert::Assert; + use tempfile::NamedTempFile; use super::file::FileLibrary; use super::process::ProcessLibrary; @@ -191,4 +195,19 @@ input_params Ok(()) } + #[tokio::test] + async fn test_library_async() -> anyhow::Result<()> { + // just using a temp file for its path + let tmp_file = NamedTempFile::new()?; + let path = String::from(tmp_file.path().to_str().unwrap()).clone().replace("\\", "\\\\"); + let test_content = format!(r#" +file.download("https://www.google.com/", "{path}") +"#); + let test_res = thread::spawn(|| { eldritch_run("test.tome".to_string(), test_content, None) }); + let test_val = test_res.join(); + + assert!(tmp_file.as_file().metadata().unwrap().len() > 5); + + Ok(()) + } } \ No newline at end of file diff --git a/implants/golem/src/main.rs b/implants/golem/src/main.rs index 38db33c98..737f8f7bd 100644 --- a/implants/golem/src/main.rs +++ b/implants/golem/src/main.rs @@ -2,22 +2,14 @@ extern crate golem; extern crate eldritch; use clap::{Command, Arg}; -use tokio::task; use std::fs; use std::process; +use std::thread; use eldritch::{eldritch_run}; mod inter; - -async fn run(tome_path: String) -> anyhow::Result { - // Read a tome script - let tome_contents = fs::read_to_string(tome_path.clone())?; - // Execute a tome script - eldritch_run(tome_path, tome_contents, None) -} - #[tokio::main] async fn main() -> anyhow::Result<()> { let matches = Command::new("golem") @@ -37,31 +29,32 @@ async fn main() -> anyhow::Result<()> { // Queue async tasks let mut all_tome_futures: Vec<(String, _)> = vec![]; for tome in tome_files { - let tome_execution_task = run(tome.to_string()); - let tmp_row = (tome.to_string(), task::spawn(tome_execution_task)); + let tome_path = tome.to_string().clone(); + let tome_contents = fs::read_to_string(tome_path.clone())?; + let tmp_row = (tome.to_string(), thread::spawn(|| { eldritch_run(tome_path, tome_contents, None) })); all_tome_futures.push(tmp_row) } + let mut error_code = 0; - // Collect results and do error handling let mut result: Vec = Vec::new(); for tome_task in all_tome_futures { - // Get the name of the file from our tuple. let tome_name: String = tome_task.0; - match tome_task.1.await { - // Match on task results. - Ok(res) => match res { - Ok(task_res) => result.push(task_res), - Err(task_err) => { - eprintln!("[TASK ERROR] {tome_name}: {task_err}"); - error_code = 1; - } - }, - - Err(err) => { - eprintln!("[ERROR] {tome_name}: {err}"); + // Join our + let tome_result_thread_join = match tome_task.1.join() { + Ok(local_thread_join_res) => local_thread_join_res, + Err(_) => { error_code = 1; + Err(anyhow::anyhow!("An error occured waiting for the tome thread to complete while executing {tome_name}.")) }, + }; + + match tome_result_thread_join { + Ok(local_tome_result) => result.push(local_tome_result), + Err(task_error) => { + error_code = 1; + eprintln!("[TASK ERROR] {tome_name}: {task_error}"); + } } } if result.len() > 0 { @@ -73,5 +66,3 @@ async fn main() -> anyhow::Result<()> { } Ok(()) } - - diff --git a/implants/golem/tests/cli.rs b/implants/golem/tests/cli.rs index 2bfce4dc0..50267fa79 100644 --- a/implants/golem/tests/cli.rs +++ b/implants/golem/tests/cli.rs @@ -12,7 +12,7 @@ fn test_golem_main_file_not_found() -> anyhow::Result<()> { cmd.arg("nonexistentdir/run.tome"); cmd.assert() .failure() - .stderr(predicate::str::contains("[TASK ERROR] nonexistentdir/run.tome: No such file or directory (os error 2)")); + .stderr(predicate::str::contains("Error: No such file or directory")); Ok(()) } @@ -53,7 +53,21 @@ fn test_golem_main_basic_eldritch_non_interactive() -> anyhow::Result<()> { cmd.arg("working_dir/tomes/eldritch_test.tome"); cmd.assert() .success() - .stdout(predicate::str::contains("[\"[\\\"append\\\", \\\"copy\\\", \\\"download\\\", \\\"exists\\\", \\\"hash\\\", \\\"is_dir\\\", \\\"is_file\\\", \\\"mkdir\\\", \\\"read\\\", \\\"remove\\\", \\\"rename\\\", \\\"replace\\\", \\\"replace_all\\\", \\\"timestomp\\\", \\\"write\\\"]\"]")); + .stdout(predicate::str::contains(r#"[\"append\", \"compress\""#)); + + Ok(()) +} + + +// Test running `./golem ./working_dir/tomes/eldritch_test.tome` +#[test] +fn test_golem_main_basic_async() -> anyhow::Result<()> { + let mut cmd = Command::cargo_bin("golem")?; + + cmd.arg("working_dir/tomes/download_test.tome"); + cmd.assert() + .success() + .stderr(predicate::str::contains(r#"OKAY!"#)); Ok(()) } diff --git a/implants/golem/working_dir/tomes/download_test.tome b/implants/golem/working_dir/tomes/download_test.tome new file mode 100644 index 000000000..ee8d36f96 --- /dev/null +++ b/implants/golem/working_dir/tomes/download_test.tome @@ -0,0 +1,2 @@ +file.download("https://github.com/KCarretto/realm/releases/download/v0.0.1/imix-linux-x64","/tmp/abc") +print("OKAY!") \ No newline at end of file diff --git a/implants/imix/src/main.rs b/implants/imix/src/main.rs index c0e72d8e5..115697888 100644 --- a/implants/imix/src/main.rs +++ b/implants/imix/src/main.rs @@ -1,3 +1,4 @@ +use std::thread; use std::{collections::HashMap, fs}; use std::fs::File; use std::io::Write; @@ -40,7 +41,11 @@ async fn handle_exec_tome(task: GraphQLTask) -> Result<(String,String)> { let tome_contents = task_job.tome.eldritch; // Execute a tome script - let res = eldritch_run(tome_name, tome_contents, task_job.tome.parameters); + let res = match thread::spawn(|| { eldritch_run(tome_name, tome_contents, task_job.tome.parameters) }).join() { + Ok(local_thread_res) => local_thread_res, + Err(_) => todo!(), + }; + match res { Ok(tome_output) => Ok((tome_output, "".to_string())), Err(tome_error) => Ok(("".to_string(), tome_error.to_string())), diff --git a/tests/create_file_dll/src/lib.rs b/tests/create_file_dll/src/lib.rs index cfee5b560..bd87c479f 100644 --- a/tests/create_file_dll/src/lib.rs +++ b/tests/create_file_dll/src/lib.rs @@ -27,7 +27,7 @@ extern "system" fn DllMain( pub fn demo_init() { unsafe { consoleapi::AllocConsole() }; for (key, value) in env::vars_os() { - println!("{key:?}: {value:?}"); + // println!("{key:?}: {value:?}"); if key == "LIBTESTFILE" { let mut file = File::create(value).unwrap(); let _ = file.write_all(b"Hello, world!");