From b76d57ee9d140d947eab366faf39dd01de382a6b Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 15 Oct 2023 21:10:37 +0200 Subject: [PATCH] tests --- .gitignore | 1 + Cargo.lock | 66 ++++++++++++++- elven-wald/Cargo.toml | 3 + elven-wald/tests/integration/mod.rs | 96 ++++++++++++++++++++++ elven-wald/tests/integration/simple_asm.rs | 56 +++++++++++++ elven-wald/tests/runtest.rs | 5 ++ runtest.sh | 21 ----- tests/single_object_file/empty.asm | 7 -- tests/single_object_file/run.sh | 7 -- 9 files changed, 226 insertions(+), 36 deletions(-) create mode 100644 elven-wald/tests/integration/mod.rs create mode 100644 elven-wald/tests/integration/simple_asm.rs create mode 100644 elven-wald/tests/runtest.rs delete mode 100755 runtest.sh delete mode 100644 tests/single_object_file/empty.asm delete mode 100644 tests/single_object_file/run.sh diff --git a/.gitignore b/.gitignore index 899b82c..1e33d6e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target *a.out +_TEST* \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 0ee383e..c9fb3ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,6 +71,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + [[package]] name = "bstr" version = "1.7.0" @@ -176,7 +182,7 @@ dependencies = [ name = "elven-parser" version = "0.1.0" dependencies = [ - "bitflags", + "bitflags 1.3.2", "bstr", "bytemuck", "memmap2", @@ -192,10 +198,27 @@ dependencies = [ "clap", "elven-parser", "memmap2", + "tempfile", "tracing", "tracing-subscriber", ] +[[package]] +name = "errno" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + [[package]] name = "fnv" version = "1.0.7" @@ -220,6 +243,12 @@ version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +[[package]] +name = "linux-raw-sys" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" + [[package]] name = "log" version = "0.4.20" @@ -331,6 +360,15 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "regex" version = "1.10.1" @@ -381,6 +419,19 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustix" +version = "0.38.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed" +dependencies = [ + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "serde" version = "1.0.189" @@ -468,6 +519,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "tempfile" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys", +] + [[package]] name = "thiserror" version = "1.0.49" diff --git a/elven-wald/Cargo.toml b/elven-wald/Cargo.toml index b36e1cd..6e50140 100644 --- a/elven-wald/Cargo.toml +++ b/elven-wald/Cargo.toml @@ -13,3 +13,6 @@ elven-parser = { path = "../elven-parser" } memmap2 = "0.5.8" tracing = "0.1.37" tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } + +[dev-dependencies] +tempfile = "3.8.0" diff --git a/elven-wald/tests/integration/mod.rs b/elven-wald/tests/integration/mod.rs new file mode 100644 index 0000000..d321f84 --- /dev/null +++ b/elven-wald/tests/integration/mod.rs @@ -0,0 +1,96 @@ +mod simple_asm; + +use std::{ + ffi::{OsStr, OsString}, + fmt::Display, + path::PathBuf, + process::Command, +}; + +pub fn run(mut cmd: Command) { + let out = cmd.output().expect("failed to spawn command"); + if !out.status.success() { + panic!( + "FAILED to run {}: {}", + cmd.get_program().to_str().unwrap(), + String::from_utf8_lossy(&out.stderr) + ); + } +} + +macro_rules! elven_wald { + ($ctx:expr; $($args:expr),*) => {{ + let ctx = &$ctx; + let output = ctx.file_ref("elven-wald-output"); + let mut cmd = std::process::Command::new("../target/debug/elven-wald"); + cmd.arg("-o"); + cmd.arg(&output); + $( cmd.arg($args); )* + $crate::integration::run(cmd); + output + }}; +} +pub(crate) use elven_wald; + +pub struct Ctx { + _tempdir: tempfile::TempDir, + path: PathBuf, +} + +pub struct File(PathBuf); + +impl Display for File { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(self.0.to_str().unwrap()) + } +} + +impl From for OsString { + fn from(value: File) -> Self { + value.0.into_os_string() + } +} + +impl AsRef for File { + fn as_ref(&self) -> &OsStr { + self.0.as_os_str() + } +} + +pub fn ctx() -> Ctx { + let tempdir = tempfile::tempdir().expect("failed to create tempdir"); + let path = tempdir.path().to_owned(); + Ctx { + _tempdir: tempdir, + path, + } +} + +impl Ctx { + #[allow(dead_code)] + pub fn write_to_path(mut self, path: &str) -> Self { + self.path = path.into(); + self + } + + pub fn file_ref(&self, filename: &str) -> File { + File(self.path.join(filename)) + } + + pub fn file(&self, filename: &str, content: &str) -> File { + let out = self.path.join(filename); + std::fs::write(&out, content).expect("failed to write file"); + File(out) + } + + pub fn nasm(&self, filename: &str, content: &str) -> File { + let input = self.file(&format!("{filename}.asm"), content); + let out = self.path.join(filename); + let mut cmd = Command::new("nasm"); + cmd.args(["-felf64", "-o"]); + cmd.arg(&out); + cmd.arg(input); + run(cmd); + File(out) + } +} diff --git a/elven-wald/tests/integration/simple_asm.rs b/elven-wald/tests/integration/simple_asm.rs new file mode 100644 index 0000000..0f09dd7 --- /dev/null +++ b/elven-wald/tests/integration/simple_asm.rs @@ -0,0 +1,56 @@ +use std::process::Command; + +use crate::prelude::*; + +use super::run; + +#[test] +fn single_object_file() { + let ctx = ctx(); + + let empty = ctx.nasm( + "empty", + " + global _start + section .text + _start: + mov rax, 60 + mov rdi, 0 + syscall + ", + ); + + let out = elven_wald!(ctx; empty); + run(Command::new(out)); +} + +#[test] +fn two_object_files() { + let ctx = ctx(); + + let start = ctx.nasm( + "start", + " + global _start + extern exit + + section .text + _start: + call exit + ", + ); + let exit = ctx.nasm( + "exit", + " + global exit + section .text + exit: + mov rax, 60 + mov rdi, 0 + syscall + ", + ); + + let out = elven_wald!(ctx; start, exit); + run(Command::new(out)); +} diff --git a/elven-wald/tests/runtest.rs b/elven-wald/tests/runtest.rs new file mode 100644 index 0000000..2d1839d --- /dev/null +++ b/elven-wald/tests/runtest.rs @@ -0,0 +1,5 @@ +mod integration; + +mod prelude { + pub(crate) use crate::integration::{ctx, elven_wald}; +} diff --git a/runtest.sh b/runtest.sh deleted file mode 100755 index 1b79016..0000000 --- a/runtest.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR=$(dirname "$(readlink -f "$0")") - -cargo build -p elven-wald --manifest-path "$SCRIPT_DIR/Cargo.toml" - -export ELVEN_WALD="$SCRIPT_DIR/target/debug/elven-wald" - -for dir in "$SCRIPT_DIR"/tests/*; do - echo "Testing $(basename "$dir")" - tmpdir=$(mktemp -d) - cp -r "$dir" "$tmpdir" - cd "$tmpdir/$(basename "$dir")" || exit 1 - if ! bash "$dir/run.sh" >"$tmpdir/__stderr" 2>&1; then - cat "$tmpdir/__stderr" - echo "failed" - else - echo "passed" - fi -done diff --git a/tests/single_object_file/empty.asm b/tests/single_object_file/empty.asm deleted file mode 100644 index e20cc18..0000000 --- a/tests/single_object_file/empty.asm +++ /dev/null @@ -1,7 +0,0 @@ -global _start - - section .text -_start: - mov rax, 60 - mov rdi, 0 - syscall \ No newline at end of file diff --git a/tests/single_object_file/run.sh b/tests/single_object_file/run.sh deleted file mode 100644 index 09cd3d2..0000000 --- a/tests/single_object_file/run.sh +++ /dev/null @@ -1,7 +0,0 @@ -set -e - -nasm -felf64 -o empty empty.asm - -"$ELVEN_WALD" empty - -./a.out