Skip to content

feat(cheatcodes): Revert ffi on non-zero exit code #11101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 36 additions & 3 deletions crates/cheatcodes/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,12 +527,25 @@ impl Cheatcode for ffiCall {
let Self { commandInput: input } = self;

let output = ffi(state, input)?;
// TODO: check exit code?

// Check the exit code of the command.
if output.exitCode != 0 {
// If the command failed, return an error with the exit code and stderr.
return Err(fmt_err!(
"ffi command {:?} exited with code {}. stderr: {}",
input,
output.exitCode,
String::from_utf8_lossy(&output.stderr)
));
}

// If the command succeeded but still wrote to stderr, log it as a warning.
if !output.stderr.is_empty() {
let stderr = String::from_utf8_lossy(&output.stderr);
error!(target: "cheatcodes", ?input, ?stderr, "non-empty stderr");
warn!(target: "cheatcodes", ?input, ?stderr, "ffi command wrote to stderr");
}
// we already hex-decoded the stdout in `ffi`

// We already hex-decoded the stdout in the `ffi` helper function.
Ok(output.stdout.abi_encode())
}
}
Expand Down Expand Up @@ -884,6 +897,26 @@ mod tests {
assert_eq!(output.stdout, Bytes::from(msg.as_bytes()));
}

#[test]
fn test_ffi_fails_on_error_code() {
let mut cheats = cheats();

// Use a command that is guaranteed to fail with a non-zero exit code on any platform.
#[cfg(unix)]
let args = vec!["false".to_string()];
#[cfg(windows)]
let args = vec!["cmd".to_string(), "/c".to_string(), "exit 1".to_string()];

let result = ffiCall { commandInput: args }.apply(&mut cheats);

// Assert that the cheatcode returned an error.
assert!(result.is_err(), "Expected ffi cheatcode to fail, but it succeeded");

// Assert that the error message contains the expected information.
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains("exited with code 1"), "Error message did not contain exit code: {}", err_msg);
}

#[test]
fn test_artifact_parsing() {
let s = include_str!("../../evm/test-data/solc-obj.json");
Expand Down
Loading