Skip to content

Commit

Permalink
Test CLI entrypoint with real filesystem
Browse files Browse the repository at this point in the history
  • Loading branch information
orecham committed Sep 10, 2024
1 parent f556bea commit d092ddc
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 22 deletions.
2 changes: 2 additions & 0 deletions iceoryx2-cli/iox2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ cargo_metadata = "0.18.1"
[dev-dependencies]
iceoryx2-bb-testing = { workspace = true }
tempfile = "3.12.0"
winapi = { version = "0.3", features = ["winnt"] }
pelite = "0.10"
99 changes: 77 additions & 22 deletions iceoryx2-cli/iox2/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ pub struct PathsList {
#[cfg(windows)]
const PATH_SEPARATOR: char = ';';
#[cfg(windows)]
const COMMAND_SUFFIX: &str = ".exe";
const COMMAND_EXT: &str = "exe";

#[cfg(not(windows))]
const PATH_SEPARATOR: char = ':';
#[cfg(not(windows))]
const COMMAND_SUFFIX: &str = "";
const COMMAND_EXT: &str = "";

pub trait Environment {
fn install_paths() -> Result<Vec<PathBuf>>;
Expand Down Expand Up @@ -97,23 +97,22 @@ where
E: Environment,
{
fn parse_command_name(path: &PathBuf) -> Result<String> {
path.file_name()
let file_stem = path
.file_stem()
.and_then(|os_str| os_str.to_str())
.ok_or_else(|| anyhow!("Invalid file name"))
.and_then(
|file_name| match path.extension().and_then(|ext| ext.to_str()) {
Some(ext) if ext != COMMAND_SUFFIX => {
Err(anyhow!("File has an invalid extension: {}", file_name))
}
_ => Ok(file_name),
},
)
.and_then(|file_name| {
file_name
.strip_prefix("iox2-")
.map(String::from)
.ok_or_else(|| anyhow!("Not an iox2 command: {}", file_name))
})
.ok_or_else(|| anyhow!("Invalid file name"))?;

let command_name = file_stem
.strip_prefix("iox2-")
.ok_or_else(|| anyhow!("Not an iox2 command: {}", file_stem))?;

let extension = path.extension().and_then(|ext| ext.to_str()).unwrap_or("");

if extension == COMMAND_EXT {
Ok(command_name.to_string())
} else {
Err(anyhow!("Invalid file extension: {}", extension))
}
}

fn list_commands_in_path(path: &Path, command_type: CommandType) -> Result<Vec<CommandInfo>> {
Expand Down Expand Up @@ -280,6 +279,48 @@ mod tests {
const BAR_COMMAND: &str = "m3Qf8RzN";
const BAZ_COMMAND: &str = "P5hJ2wAc";

#[cfg(windows)]
fn create_minimal_exe(path: &Path) -> Result<(), Box<dyn std::error::Error>> {
use std::io::Write;

let mut file = std::fs::File::create(path)?;

// Create a minimal PE file
let mut image = vec![0; 1024];
let mut pe = PeFile::from_bytes_mut(&mut image)?;

// Set up the DOS header
pe.dos_header_mut().e_magic = pelite::image::IMAGE_DOS_SIGNATURE;
pe.dos_header_mut().e_lfanew = 0x40;

// Set up the NT headers
let nt = pe.nt_headers_mut();
nt.Signature = pelite::image::IMAGE_NT_SIGNATURE;
nt.FileHeader.Machine = pelite::image::IMAGE_FILE_MACHINE_AMD64;
nt.FileHeader.NumberOfSections = 1;
nt.FileHeader.SizeOfOptionalHeader = 0xF0;
nt.FileHeader.Characteristics = FileCharacteristics::EXECUTABLE_IMAGE.bits();

// Set up the Optional header
let opt = &mut nt.OptionalHeader;
opt.Magic = pelite::image::IMAGE_NT_OPTIONAL_HDR64_MAGIC;
opt.SizeOfCode = 0x200;
opt.AddressOfEntryPoint = 0x1000;
opt.BaseOfCode = 0x1000;
opt.ImageBase = 0x140000000;
opt.SectionAlignment = 0x1000;
opt.FileAlignment = 0x200;
opt.MajorSubsystemVersion = 6;
opt.SizeOfImage = 0x2000;
opt.SizeOfHeaders = 0x200;
opt.Subsystem = pelite::image::IMAGE_SUBSYSTEM_WINDOWS_CUI;

// Write the PE file
file.write_all(&image)?;

Ok(())
}

macro_rules! create_file {
($path:expr, $file:expr) => {{
let file_path = $path.join($file);
Expand All @@ -293,6 +334,12 @@ mod tests {
perms.set_mode(0o755);
fs::set_permissions(&file_path, perms).expect("Failed to set permissions");
}
#[cfg(windows)]
{
if file_path.extension().and_then(|s| s.to_str()) == Some("exe") {
create_minimal_exe(&file_path).expect("Failed to create minimal executable");
}
}
}};
}

Expand Down Expand Up @@ -364,19 +411,27 @@ mod tests {
let commands = IceoryxCommandFinder::<HostEnvironment>::commands()
.expect("Failed to retrieve commands");

let [foo_command, bar_command, ..] = commands
let [foo_command, ..] = commands
.iter()
.filter(|cmd| [FOO_COMMAND, BAR_COMMAND].contains(&cmd.name.as_str()))
.filter(|cmd| cmd.name == FOO_COMMAND)
.collect::<Vec<_>>()[..]
else {
panic!("Failed to find FOO_COMMAND and BAR_COMMAND");
panic!("Failed to extract CommandInfo of test files");
};

let result = IceoryxCommandExecutor::execute(&foo_command, None);
match result {
Ok(_) => {
println!("Command executed successfully");
}
Err(ref e) => {
println!("Command execution failed with error: {:?}", e);
}
}
assert_that!(result, is_ok);

let args = vec!["arg1".to_string(), "arg2".to_string()];
let result = IceoryxCommandExecutor::execute(&bar_command, Some(&args));
let result = IceoryxCommandExecutor::execute(&foo_command, Some(&args));
assert_that!(result, is_ok);
}
}

0 comments on commit d092ddc

Please sign in to comment.