crates/heimdall-container/tests/exec.rs
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Ignalina ApS and Vetra Automation AB
//! The job's execve retry on ETXTBSY. Heimdall is a defensive sandbox;
//! nothing is executed here.
use std::time::Duration;
use heimdall_container::exec::{retry_text_busy, PAUSE, TRIES};
#[test]
fn a_busy_program_is_tried_again_until_it_is_free() {
let mut calls = 0;
let errs = [libc::ETXTBSY, libc::ETXTBSY, libc::ENOENT];
let e = retry_text_busy(10, Duration::ZERO, || {
calls += 1;
errs[calls - 1]
});
assert_eq!(e, libc::ENOENT);
assert_eq!(calls, 3);
}
#[test]
fn any_other_error_is_returned_at_once() {
for err in [libc::ENOENT, libc::EACCES, libc::EPERM, libc::ENOEXEC] {
let mut calls = 0;
let e = retry_text_busy(10, Duration::ZERO, || {
calls += 1;
err
});
assert_eq!((e, calls), (err, 1));
}
}
#[test]
fn a_program_busy_for_good_is_given_up_after_the_tries() {
let mut calls = 0;
let e = retry_text_busy(7, Duration::ZERO, || {
calls += 1;
libc::ETXTBSY
});
assert_eq!((e, calls), (libc::ETXTBSY, 7));
// The default bound: about a second.
assert!(PAUSE * TRIES >= Duration::from_millis(500));
assert!(PAUSE * TRIES <= Duration::from_secs(2));
}