This commit is contained in:
nora 2023-10-15 21:10:37 +02:00
parent 5ef748c2c5
commit b76d57ee9d
9 changed files with 226 additions and 36 deletions

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
/target /target
*a.out *a.out
_TEST*

66
Cargo.lock generated
View file

@ -71,6 +71,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
[[package]] [[package]]
name = "bstr" name = "bstr"
version = "1.7.0" version = "1.7.0"
@ -176,7 +182,7 @@ dependencies = [
name = "elven-parser" name = "elven-parser"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"bstr", "bstr",
"bytemuck", "bytemuck",
"memmap2", "memmap2",
@ -192,10 +198,27 @@ dependencies = [
"clap", "clap",
"elven-parser", "elven-parser",
"memmap2", "memmap2",
"tempfile",
"tracing", "tracing",
"tracing-subscriber", "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]] [[package]]
name = "fnv" name = "fnv"
version = "1.0.7" version = "1.0.7"
@ -220,6 +243,12 @@ version = "0.2.149"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
[[package]]
name = "linux-raw-sys"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f"
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.20" version = "0.4.20"
@ -331,6 +360,15 @@ dependencies = [
"proc-macro2", "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]] [[package]]
name = "regex" name = "regex"
version = "1.10.1" version = "1.10.1"
@ -381,6 +419,19 @@ version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" 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]] [[package]]
name = "serde" name = "serde"
version = "1.0.189" version = "1.0.189"
@ -468,6 +519,19 @@ dependencies = [
"syn 1.0.109", "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]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.49" version = "1.0.49"

View file

@ -13,3 +13,6 @@ elven-parser = { path = "../elven-parser" }
memmap2 = "0.5.8" memmap2 = "0.5.8"
tracing = "0.1.37" tracing = "0.1.37"
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
[dev-dependencies]
tempfile = "3.8.0"

View file

@ -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<File> for OsString {
fn from(value: File) -> Self {
value.0.into_os_string()
}
}
impl AsRef<OsStr> 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)
}
}

View file

@ -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));
}

View file

@ -0,0 +1,5 @@
mod integration;
mod prelude {
pub(crate) use crate::integration::{ctx, elven_wald};
}

View file

@ -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

View file

@ -1,7 +0,0 @@
global _start
section .text
_start:
mov rax, 60
mov rdi, 0
syscall

View file

@ -1,7 +0,0 @@
set -e
nasm -felf64 -o empty empty.asm
"$ELVEN_WALD" empty
./a.out