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:
2530//! results.
2631use std:: {
2732 env,
33+ ffi:: OsString ,
34+ path:: PathBuf ,
2835 process:: { Command , ExitCode } ,
2936} ;
37+ use which:: which;
3038
3139fn 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