Browse Source

Start work on testing framework

This adds the start of a program to automatically compile and test a
bunch of ASL files against out parser. It relies on `iasl` being
installed to compile the files. It's still very basic and not polished
at all, but will work as a MVP until it's finished and I can be bothered
to polish it a bit.
Isaac Woods 5 years ago
parent
commit
9c424541c3
4 changed files with 85 additions and 1 deletions
  1. 1 1
      Cargo.toml
  2. 8 0
      aml_tester/Cargo.toml
  3. 65 0
      aml_tester/src/main.rs
  4. 11 0
      tests/scopes.asl

+ 1 - 1
Cargo.toml

@@ -1,2 +1,2 @@
 [workspace]
-members = ["acpi", "aml", "acpi-dumper"]
+members = ["acpi", "aml", "acpi-dumper", "aml_tester"]

+ 8 - 0
aml_tester/Cargo.toml

@@ -0,0 +1,8 @@
+[package]
+name = "aml_tester"
+version = "0.1.0"
+authors = ["Isaac Woods"]
+edition = "2018"
+
+[dependencies]
+clap = "2"

+ 65 - 0
aml_tester/src/main.rs

@@ -0,0 +1,65 @@
+/*
+ * This is a small program that is meant for testing the AML parser on artificial
+ * AML. We want to:
+ *      - scan a directory for ASL files
+ *      - compile them using `iasl` into AML files (these should be gitignored), but only if the ASL file
+ *        has a newer timestamp than the AML file (or just compile if there isn't a corresponding AML file)
+ *      - Run the AML parser on each AML file, printing test output like `cargo test` does in a nice table
+ *        for each AML file
+ *      - For failing tests, print out a nice summary of the errors for each file
+ */
+
+use clap::{App, Arg};
+use std::{ffi::OsStr, fs, path::Path, process::Command};
+
+fn main() {
+    let matches = App::new("aml_tester")
+        .version("v0.1.0")
+        .author("Isaac Woods")
+        .about("Compiles and tests ASL files")
+        .arg(Arg::with_name("path").short("p").long("path").required(true).takes_value(true))
+        .get_matches();
+
+    println!("Running tests in directory: {:?}", matches.value_of("path"));
+
+    compile_asl_files(Path::new(matches.value_of("path").unwrap())).unwrap();
+}
+
+fn compile_asl_files(dir_path: &Path) -> std::io::Result<()> {
+    let asl_files = fs::read_dir(dir_path)?
+        .filter(|entry| {
+            entry.is_ok() && entry.as_ref().unwrap().path().extension() == Some(OsStr::new("asl"))
+        })
+        .map(|file| file.unwrap());
+
+    for file in asl_files {
+        let aml_path = file.path().with_extension(OsStr::new("aml"));
+
+        /*
+         * Check if an AML path with a matching last-modified date exists. If it
+         * does, we don't need to compile the ASL file again.
+         */
+        if aml_path.is_file() {
+            let asl_last_modified = file.metadata()?.modified()?;
+            let aml_last_modified = aml_path.metadata()?.modified()?;
+
+            if asl_last_modified <= aml_last_modified {
+                continue;
+            }
+        }
+
+        // Compile the ASL file using `iasl`
+        println!("Compiling file: {}", file.path().to_str().unwrap());
+        let output = Command::new("iasl").arg(file.path()).output()?;
+
+        if !output.status.success() {
+            println!(
+                "Failed to compile ASL file: {}. Output from iasl: {}",
+                file.path().to_str().unwrap(),
+                String::from_utf8_lossy(&output.stderr)
+            );
+        }
+    }
+
+    Ok(())
+}

+ 11 - 0
tests/scopes.asl

@@ -0,0 +1,11 @@
+DefinitionBlock("scopes.aml", "DSDT", 1, "RSOSDEV", "SCOPES", 1) {
+	Scope(_SB) {
+		Name(X, 320)
+		Device(\PCI0) {
+			Name(Y, 15)
+			Scope(\) {
+				Name(Z, 413)
+			}
+		}
+	}
+}