Skip to content

Commit 64610c6

Browse files
Add support for running the tests from uACPI. (#285)
1 parent 6e01602 commit 64610c6

11 files changed

Lines changed: 502 additions & 31 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[workspace]
2-
members = ["tools/aml_tester", "tools/acpi_dumper", "tools/aml_test_tools"]
2+
members = ["tools/aml_tester", "tools/acpi_dumper", "tools/aml_test_tools", "tools/uacpi_test_adapter"]
33
resolver = "2"
44

55
[package]

src/sdt/facs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub struct Facs {
1111
pub flags: u32,
1212
pub x_firmware_waking_vector: u64,
1313
pub version: u8,
14-
_reserved0: [u8; 3],
14+
pub _reserved0: [u8; 3],
1515
pub ospm_flags: u32,
16-
reserved1: [u8; 24],
16+
pub reserved1: [u8; 24],
1717
}

tests/README.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Tests in the ACPI crate.
2+
3+
There are 4 categories of tests:
4+
5+
1. Unit tests in the main crate source.
6+
2. Integration tests in the `tests` directory - these all have the extension `.rs`.
7+
3. Raw ASL files that can be checked using `aml_tester`
8+
4. Support for running tests from the `uacpi` project.
9+
10+
## Unit tests
11+
12+
These are standard Rust unit tests. Run them using `cargo test` (which will also run the integration tests). There are
13+
relatively few unit tests at present - feel free to send PRs with more!
14+
15+
## Integration tests
16+
17+
These are the `.rs` files in the `tests` directory. They largely consist of snippets of ASL code that are parsed and
18+
then executed using the `aml_test_tools` sub-crate. Most of the tests specify the expected output from the provided
19+
`Handler`, which provides reasonable confidence the parser is working correctly.
20+
21+
The `aml_test_tools` sub-crate provides various utilities for writing this style of test.
22+
23+
Like the unit tests, they can be run using `cargo test`.
24+
25+
## Raw ASL files
26+
27+
Various ASL files are provided in the `tests` directory. They can be parsed and executed by running
28+
`cargo run_tests -p tests` from the root of the repository. This cargo alias runs the `aml_tester` tool.
29+
30+
The `aml_tester` tool provides a command-line way to run ASL files - similar to `acpiexec`.
31+
32+
## Running tests from the `uacpi` project
33+
34+
> See the documentation for `uacpi_test_adapter` for more detailed information. Note that a large proportion of the
35+
> tests in the `uacpi` project do not yet pass in this crate.
36+
37+
The `uacpi` project has a fairly extensive test suite. It makes sense for us to be able to check against their test
38+
suite as well as our own. This can be done by:
39+
40+
1. Checking out the [`uacpi` repository.](https://github.com/uACPI/uACPI)
41+
2. Navigating to the root of that repo.
42+
3. Running something like:
43+
```shell
44+
python3 tests/run_tests.py --test-runner ../acpi/target/debug/uacpi_test_adapter
45+
```
46+
Adjusting the paths as necessary. See the `uacpi_test_adapter` documentation for details on how it finds
47+
`aml_tester`.
48+
49+
Note that, at present, several of the uACPI tests run indefinitely. You may want to skip these! The easiest way to do so
50+
is probably just to delete them... The relevant tests are:
51+
52+
* `global-lock.asl`
53+
* `hanging-while.asl`
54+
* `infinite-recursion.asl`
55+
* `mutex-1.asl`
56+
* `mutex-2.asl`
57+
* `mutex-3.asl`

tests/test_infra/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ pub fn run_aml_test(asl: &'static str, handler: impl Handler) {
1414
let logged_handler = LoggingHandler::new(handler);
1515
let interpreter = new_interpreter(logged_handler);
1616

17-
let result = run_test_for_string(asl, interpreter);
17+
let result = run_test_for_string(asl, interpreter, &None);
1818
assert!(matches!(result, RunTestResult::Pass(_)), "Test failed with: {:?}", TestResult::from(&result));
1919
}

tests/uacpi_examples.rs

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
//! These examples have been adapted from the Readme of the [uACPI](https://github.com/uACPI/uACPI)
2+
//! project at commit 1ca45f3.
3+
//!
4+
//! At present most of these tests probably won't work, but it'll help to guide us towards better
5+
//! compatibility.
6+
//!
7+
//! The comments demonstrate some of the differences between the NT "real world" interpreter and
8+
//! the ACPI reference standard.
9+
10+
mod test_infra;
11+
12+
use aml_test_tools::{handlers::null_handler::NullHandler};
13+
14+
#[test]
15+
#[ignore] // Fails with ObjectNotOfExpectedType { expected: Reference, got: Integer }
16+
fn expressions_with_package() {
17+
const ASL: &str = r#"
18+
DefinitionBlock("", "DSDT", 1, "RSACPI", "UACPI", 1) {
19+
Method (TEST) {
20+
Local0 = 10
21+
Local1 = Package { Local0 * 5 }
22+
Return (DerefOf(Local1[0]))
23+
}
24+
25+
// ACPICA: AE_SUPPORT, Expressions within package elements are not supported
26+
// Windows, uACPI: Local0 = 50
27+
Local0 = TEST()
28+
}
29+
"#;
30+
31+
let handler = NullHandler;
32+
test_infra::run_aml_test(ASL, handler);
33+
}
34+
35+
#[test]
36+
fn package_outside_of_control_method() {
37+
const ASL: &str = r#"
38+
DefinitionBlock("", "DSDT", 1, "RSACPI", "UACPI", 1) {
39+
// ACPICA: internal error
40+
// Windows, uACPI: ok
41+
Local0 = Package { 1 }
42+
43+
// I don't have a good way of testing this, but if it completes without errors it's probably OK.
44+
Debug = Local0[0]
45+
}"#;
46+
47+
let handler = NullHandler;
48+
test_infra::run_aml_test(ASL, handler);
49+
}
50+
51+
#[test]
52+
#[ignore] // Local0 is set to 123 - we follow the ACPICA way, not the Windows way.
53+
fn reference_rebind_semantics() {
54+
const ASL: &str = r#"
55+
DefinitionBlock("", "DSDT", 1, "RSACPI", "UACPI", 1) {
56+
Method (MAIN, 0, NotSerialized) {
57+
Local0 = 123
58+
Local1 = RefOf(Local0)
59+
60+
// ACPICA: Local1 = 321, Local0 = 123
61+
// Windows, uACPI: Local1 = reference->Local0, Local0 = 321
62+
Local1 = 321
63+
64+
Return (Local0 == 123)
65+
}
66+
}"#;
67+
68+
let handler = NullHandler;
69+
test_infra::run_aml_test(ASL, handler);
70+
}
71+
72+
#[test]
73+
#[ignore] // ParseFail(ObjectNotOfExpectedType { expected: Integer, got: Integer } (a referencing failure)
74+
fn increment_decrement() {
75+
const ASL: &str = r#"
76+
DefinitionBlock("", "DSDT", 1, "RSACPI", "UACPI", 1) {
77+
Local0 = 123
78+
Local1 = RefOf(Local0)
79+
80+
// ACPICA: error
81+
// Windows, uACPI: Local0 = 124
82+
Local1++
83+
}"#;
84+
85+
let handler = NullHandler;
86+
test_infra::run_aml_test(ASL, handler);
87+
}
88+
89+
#[test]
90+
#[ignore] // ParseFail(ObjectNotOfExpectedType { expected: Reference, got: Integer })
91+
fn multilevel_references() {
92+
const ASL: &str = r#"
93+
DefinitionBlock("", "DSDT", 1, "RSACPI", "UACPI", 1) {
94+
Local0 = 123
95+
Local1 = RefOf(Local0)
96+
Local2 = RefOf(Local1)
97+
98+
// ACPICA: Local3 = reference->Local0
99+
// Windows, uACPI: Local3 = 123
100+
Local3 = DerefOf(Local2)
101+
}"#;
102+
103+
let handler = NullHandler;
104+
test_infra::run_aml_test(ASL, handler);
105+
}
106+
107+
#[test]
108+
#[ignore] // "Stores to objects like WrappedObject(UnsafeCell { .. }) are not yet supported"
109+
fn implicit_case_semantics() {
110+
const ASL: &str = r#"
111+
DefinitionBlock("", "DSDT", 1, "RSACPI", "UACPI", 1) {
112+
Name (TEST, "BAR")
113+
114+
// ACPICA: TEST = "00000000004F4F46"
115+
// Windows, uACPI: TEST = "FOO"
116+
TEST = 0x4F4F46
117+
}"#;
118+
119+
let handler = NullHandler;
120+
test_infra::run_aml_test(ASL, handler);
121+
}
122+
123+
#[test]
124+
#[ignore] // "Stores to objects like WrappedObject(UnsafeCell { .. }) are not yet supported"
125+
fn buffer_size_mutability() {
126+
const ASL: &str = r#"
127+
DefinitionBlock("", "DSDT", 1, "RSACPI", "UACPI", 1) {
128+
Name (TEST, "XXXX")
129+
Name (VAL, "")
130+
131+
// ACPICA: TEST = "LONGSTRING"
132+
// Windows, UACPI: TEST = "LONG"
133+
TEST = "LONGSTRING"
134+
135+
// ACPICA: VAL = "FOO"
136+
// Windows, UACPI: VAL = ""
137+
VAL = "FOO"
138+
}"#;
139+
140+
let handler = NullHandler;
141+
test_infra::run_aml_test(ASL, handler);
142+
}
143+
144+
#[test]
145+
fn ref_to_local() {
146+
const ASL: &str = r#"
147+
DefinitionBlock("", "DSDT", 1, "RSACPI", "UACPI", 1) {
148+
Method (TEST) {
149+
Local0 = 123
150+
151+
// Use-after-free in ACPICA, perfectly fine in uACPI
152+
Return (RefOf(Local0))
153+
}
154+
155+
Method (FOO) {
156+
Name (TEST, 123)
157+
158+
// Use-after-free in ACPICA, object lifetime prolonged in uACPI (node is still removed from the namespace)
159+
Return (RefOf(TEST))
160+
}
161+
162+
Method (MAIN) {
163+
FOO ()
164+
Return (0)
165+
}
166+
}"#;
167+
168+
let handler = NullHandler;
169+
test_infra::run_aml_test(ASL, handler);
170+
}
171+
172+
#[test]
173+
#[ignore] // CopyObject not yet implemented
174+
fn copy_object_to_self() {
175+
const ASL: &str = r#"
176+
DefinitionBlock("", "DSDT", 1, "RSACPI", "UACPI", 1) {
177+
Method (TEST) {
178+
CopyObject(123, TEST)
179+
Return (1)
180+
}
181+
182+
// Segfault in ACPICA, prints 1 in uACPI
183+
Debug = TEST()
184+
185+
// Unreachable in ACPICA, prints 123 in uACPI
186+
Debug = TEST
187+
}"#;
188+
189+
let handler = NullHandler;
190+
test_infra::run_aml_test(ASL, handler);
191+
}

0 commit comments

Comments
 (0)