tests.rs: statically defined `CARGO_BIN_EXE_coreutils` causes all integration tests to fail on Yocto ptest-cargo

Open
#9,246 1 comment 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
48/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Stale
Tech stack
rust
Domain
cli, testing-qa

Research direction

Start in coreutils/tests/tests.rs at init() and inspect how CARGO_BIN_EXE_coreutils and UUTESTS_BINARY_PATH are used. Reproduce the integration-test setup with Cargo and the Yocto ptest-cargo flow described in the issue. Done means tests can use a runtime-provided binary path while the normal Cargo test behavior remains supported.

Written by the indexing model from the issue text.

Description

Hi,

I have been working on extending the uutils-coreutils recipe in Yocto to support the ptest-cargo utility which aims to execute the tests cargo produces, locally on the target machine.

ptest-cargo copies the test files produced by cargo and places them in the image, where they are executed using an auto-generated script. However, all integration tests fail with a failure message "No such file or directory" when executing the coreutils binary. Tracing the issue, I have discovered that this is caused by the way the location of the binary executable is baked into the integration tests binaries at the time of compilation. The core of the problem is in coreutils/tests/tests.rs:12:fn init():

Problem

pub const TESTS_BINARY: &str = env!("CARGO_BIN_EXE_coreutils");

// Use the ctor attribute to run this function before any tests
#[ctor::ctor]
fn init() {
    unsafe {
        // Necessary for uutests to be able to find the binary
        std::env::set_var("UUTESTS_BINARY_PATH", TESTS_BINARY);
    }
}

In detail, when setting up the execution environment of the integration tests, the environment variable CARGO_BIN_EXE_coreutils is used, which is provided by cargo during compile time (and not during run time) and is baked into the executable statically. However, for Yocto and any other project that aims to run the tests directly by bypassing cargo, this will always fail. Furthermore, this configuration also bakes into the executable information about the compilation environment and the absolute path of the executable, which may be undesirable.

Solution

My suggestion would be to modify this function so that the environment variable is read first during runtime and if the variable is not defined, it can default to the value specified by cargo during compile time. This way every framework that would like to perform the tests by bypassing cargo, such as Yocto, can simply provide the specified variable at run time and the cargo test framework will continue to work by providing the variable during compilation.

pub const TESTS_BINARY: &str = env!("CARGO_BIN_EXE_coreutils");

// Use the ctor attribute to run this function before any tests
#[ctor::ctor]
fn init() {

    let cargo_bin_exe_location = PathBuf::from(
        env::var("CARGO_BIN_EXE_coreutils").unwrap_or(TESTS_BINARY.to_string())
    );

    unsafe {
        // Necessary for uutests to be able to find the binary
        std::env::set_var("UUTESTS_BINARY_PATH", cargo_bin_exe_location);
    }
}

Environment

My platform is Ubuntu 24.04 on x86_64 and I am cross-compiling using Yocto for qemux86_64. I started my investigation with uutils-coreutils version 0.3.0 but the problems persists in main until the moment of writing this.

Reproduction

The following steps reproduce the issue:

  1. Add uutils-coreutils on your Yocto image
  2. This is the diff of the changes on the uutils-coreutils recipe:
diff --git a/meta-oe/recipes-core/uutils-coreutils/uutils-coreutils_0.3.0.bb b/meta-oe/recipes-core/uutils-coreutils/uutils-coreutils_0.3.0.bb
index 1e207f7fb4..b780f45a30 100644
--- a/meta-oe/recipes-core/uutils-coreutils/uutils-coreutils_0.3.0.bb
+++ b/meta-oe/recipes-core/uutils-coreutils/uutils-coreutils_0.3.0.bb
@@ -5,8 +5,7 @@ HOMEPAGE = "https://github.com/uutils/coreutils"
 LICENSE = "MIT"
 LIC_FILES_CHKSUM = "file://LICENSE;md5=e74349878141b240070458d414ab3b64"
 
-inherit cargo cargo-update-recipe-crates
-
+inherit cargo cargo-update-recipe-crates ptest-cargo
 SRC_URI = " \
     git://github.com/uutils/coreutils.git;protocol=https;branch=main;tag=${PV} \
 "
@@ -22,7 +21,8 @@ PACKAGECONFIG ?= "${@bb.utils.filter('DISTRO_FEATURES', 'selinux systemd', d)}"
 PACKAGECONFIG[selinux] = "--features feat_selinux,,clang-native libselinux-native libselinux"
 PACKAGECONFIG[systemd] = "--features feat_systemd_logind,,systemd"
 
-CARGO_BUILD_FLAGS += "--features unix --features feat_external_libstdbuf"
+CARGO_BUILD_FLAGS += "--features unix"
+do_package_qa[noexec] = "1"
 
 # The code which follows is strongly inspired from the GNU coreutils bitbake recipe:
  1. bitbake core-image-minimal
  2. Run generated image on QEMU
  3. ptest-runner uutils-coreutils

Related

Edit Nov. 12: Added cargo environment variables reference.

Dominant language
Rust
Stars
24.1k
Forks
2k
Avg merge
1d 5h
Merged PRs (30d)
365

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from uutils/coreutils

All issues in uutils/coreutils

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.