Skip to content

Commit 7da2f37

Browse files
committed
Make it easier to find aml_tester
`uacpi_test_adapter` will now try three different ways to find `aml_tester`: 1. From the `AML_TESTER_PATH` environment variable, 2. From the system path, 3. As a sibling executable to the running one. Also, in `aml_test_tools`, remove the memory leak.
1 parent 3951974 commit 7da2f37

File tree

4 files changed

+80
-9
lines changed

4 files changed

+80
-9
lines changed

tests/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,10 @@ suite as well as our own. This can be done by:
4141
2. Navigating to the root of that repo.
4242
3. Running something like:
4343
```shell
44-
AML_TESTER_PATH=../acpi/target/debug/aml_tester python3 tests/run_tests.py --test-runner ../acpi/target/debug/uacpi_test_adapter`
44+
python3 tests/run_tests.py --test-runner ../acpi/target/debug/uacpi_test_adapter
4545
```
46-
Adjusting the paths as necessary. (And editing as needed for PowerShell)
46+
Adjusting the paths as necessary. See the `uacpi_test_adapter` documentation for details on how it finds
47+
`aml_tester`.
4748

4849
Note that, at present, several of the uACPI tests run indefinitely. You may want to skip these! The easiest way to do so
4950
is probably just to delete them... The relevant tests are:

tools/aml_test_tools/src/lib.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![feature(sync_unsafe_cell)]
12
//! A collection of helper utilities for testing AML using the [`acpi`] crate.
23
//!
34
//! These utilities are very heavily based on the way the [`acpi`] crate has used them historically.
@@ -20,6 +21,7 @@ use acpi::{
2021
};
2122
use log::{error, trace};
2223
use std::{
24+
cell::SyncUnsafeCell,
2325
ffi::OsStr,
2426
fmt::Debug,
2527
fs::File,
@@ -198,6 +200,11 @@ pub fn resolve_and_compile(path: &PathBuf, can_compile: bool) -> CompilationOutc
198200
///
199201
/// * `handler`: The Handler to be called by the interpreter when needed. This crate includes some
200202
/// example [handlers].
203+
///
204+
/// Thread safety:
205+
///
206+
/// This function uses a single, static, FACS for all tests. If tests are run in parallel, this
207+
/// means they will share a single global lock.
201208
pub fn new_interpreter<T>(handler: T) -> Interpreter<T>
202209
where
203210
T: Handler + Clone,
@@ -238,7 +245,7 @@ where
238245
},
239246
});
240247

241-
let fake_facs = Box::new(Facs {
248+
static FAKE_FACS: SyncUnsafeCell<Facs> = SyncUnsafeCell::new(Facs {
242249
signature: Signature::FACS,
243250
length: size_of::<Facs>() as u32,
244251
hardware_signature: 0,
@@ -258,7 +265,7 @@ where
258265
// It'd be possible to tidy this up creating a newtype containing both the Interpeter and FACS
259266
// which manually drops the FACS when appropriate, but since that makes the test interfaces
260267
// less ergonomic, this is left until the leak is an actual problem.
261-
let fake_facs_ptr = Box::leak(fake_facs) as *mut Facs;
268+
let fake_facs_ptr = FAKE_FACS.get();
262269

263270
// This PhysicalMapping is dropped when the interpreter is dropped, and if you use logging in
264271
// the handler object you'll see a call to Handler::unmap_physical_region without any

tools/uacpi_test_adapter/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ authors = ["Martin Hughes"]
66
repository = "https://github.com/rust-osdev/acpi"
77
description = "uACPI to aml_tester adapter"
88
categories = ["hardware-support"]
9-
readme = "../README.md"
9+
readme = "../../README.md"
1010
license = "MIT/Apache-2.0"
1111
edition = "2024"
12+
13+
[dependencies]
14+
which = "8.0.2"

tools/uacpi_test_adapter/src/main.rs

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@
99
//! complicate `aml_tester`.
1010
//!
1111
//! Usage:
12-
//! * Set the environment variable `AML_TESTER_PATH` to the path of the `aml_tester` binary.
12+
//! * Make sure `aml_tester` can be found. The following methods are tried, in this order of
13+
//! precedence:
14+
//! * Set the environment variable `AML_TESTER_PATH` to the path and filename of the `aml_tester`
15+
//! binary, or
16+
//! * Make sure `aml_tester` is in the system PATH, or
17+
//! * Ensure `aml_tester` is in the same folder as `uacpi_test_adapter`.
1318
//! * Run the uACPI test suite but setting `uacpi_test_adapter` to the test runner.
1419
//!
1520
//! e.g.: from the uACPI root directory:
@@ -25,8 +30,11 @@
2530
//! results.
2631
use std::{
2732
env,
33+
ffi::OsString,
34+
path::PathBuf,
2835
process::{Command, ExitCode},
2936
};
37+
use which::which;
3038

3139
fn main() -> ExitCode {
3240
// We don't support the resource tests, so just claim success to allow the main test suite to
@@ -35,15 +43,15 @@ fn main() -> ExitCode {
3543
return ExitCode::SUCCESS;
3644
}
3745

38-
let Some(tester_path) = env::var_os("AML_TESTER_PATH") else {
39-
eprintln!("AML_TESTER_PATH is not set");
46+
let Some(tester_path) = get_aml_tester_path() else {
47+
eprintln!("aml_tester not found. Try setting AML_TESTER_PATH to the path of the aml_tester binary.");
4048
return ExitCode::FAILURE;
4149
};
4250

4351
let status = match Command::new(tester_path).args(env::args_os().skip(1)).status() {
4452
Ok(status) => status,
4553
Err(err) => {
46-
eprintln!("Failed to execute AML_TESTER_PATH: {err}");
54+
eprintln!("Failed to execute aml_tester: {err}");
4755
return ExitCode::FAILURE;
4856
}
4957
};
@@ -53,3 +61,55 @@ fn main() -> ExitCode {
5361
None => ExitCode::FAILURE,
5462
}
5563
}
64+
65+
/// Find the path to the `aml_tester` binary.
66+
///
67+
/// Uses the search order given in this executable's main documentation.
68+
fn get_aml_tester_path() -> Option<OsString> {
69+
[get_aml_tester_from_env, get_aml_tester_from_path_env, get_aml_tester_from_binary_path]
70+
.iter()
71+
.find_map(|f| f())
72+
}
73+
74+
/// If the environment variable `AML_TESTER_PATH` is set, use that. Assume it is correct without
75+
/// checking.
76+
fn get_aml_tester_from_env() -> Option<OsString> {
77+
env::var_os("AML_TESTER_PATH")
78+
}
79+
80+
/// If `aml_tester` is in the system PATH, use that.
81+
fn get_aml_tester_from_path_env() -> Option<OsString> {
82+
which("aml_tester").ok().map(|path| path.into())
83+
}
84+
85+
/// If `aml_tester` exists alongside this executable, use that.
86+
fn get_aml_tester_from_binary_path() -> Option<OsString> {
87+
// This says: "change the name of the current executable to `aml_tester` and see if that exists."
88+
env::current_exe().ok().map(change_exec_name).and_then(|path| which(path).ok()).map(|path| path.into())
89+
}
90+
91+
/// Replace the filename of the given path with `aml_tester`. Preserve the extension so that
92+
/// Windows won't have problems.
93+
fn change_exec_name(mut path: PathBuf) -> PathBuf {
94+
// The final `unwrap` on the following line is reasonable because if the UTF-8 conversion fails,
95+
// the filename is probably invalid, so we don't really want to keep trying to use it!
96+
let extension = String::from(path.extension().unwrap_or_default().to_str().unwrap());
97+
path.set_file_name("aml_tester");
98+
path.set_extension(extension);
99+
path
100+
}
101+
102+
#[cfg(test)]
103+
mod tests {
104+
use super::*;
105+
106+
#[test]
107+
fn test_filename_replacement() {
108+
const PATH: &str = "/a/b/c/uacpi_test_adapter.ext";
109+
let original_path = PathBuf::from(PATH);
110+
let expected_path = PathBuf::from("/a/b/c/aml_tester.ext");
111+
let result_path = change_exec_name(original_path);
112+
113+
assert_eq!(result_path, expected_path);
114+
}
115+
}

0 commit comments

Comments
 (0)