Skip to content

Refactor filesystem tests to gracefully handle missing block devices #162

@coderabbitai

Description

@coderabbitai

Problem

The current implementation of filesystem-related Cucumber tests in tests/steps/fs_steps.rs panics when it cannot find a block device on the host system. This makes the test suite brittle and unable to run in environments where /dev lacks such devices (e.g., certain containerised CI environments).

Currently, the code hardcodes /dev/loop0 as a fallback, which may not exist on minimal runners or containerised environments.

Proposed Solution

Refactor the test setup to gracefully handle the absence of block devices by leveraging the cucumber::Step::skip function. Instead of panicking, the setup will detect this condition and programmatically skip the relevant scenarios, ensuring the test suite can still run and report other results.

Implementation Details

1. Make find_block_device_fallback fallible

Change the function to return Option<Utf8PathBuf> instead of panicking:

fn find_block_device_fallback() -> Option<Utf8PathBuf> {
    let entries = std::fs::read_dir("/dev").ok()?;
    for entry in entries {
        let entry = entry.ok()?;
        let ft = entry.file_type().ok()?;
        if ft.is_block_device() {
            let path = entry.path();
            return Utf8PathBuf::from_path_buf(path).ok();
        }
    }
    None
}

2. Update create_device_fixtures to handle None

Propagate the Option by returning Option<(Utf8PathBuf, Utf8PathBuf)>:

fn create_device_fixtures() -> Option<(Utf8PathBuf, Utf8PathBuf)> {
    let block_path = find_block_device_fallback()?;
    let char_path = create_device_with_fallback(DeviceConfig {
        file_type: RxFileType::CharacterDevice,
        fallback_path: "/dev/null",
    });
    Some((block_path, char_path))
}

3. Update file_type_workspace to skip scenarios

Change the step function to return cucumber::Step::skip() when no block device is available:

use cucumber::{given, Step};
use tracing::warn;

#[given("a file-type test workspace")]
async fn file_type_workspace(world: &mut CliWorld) -> Step {
    let (temp, root, handle) = setup_workspace();
    create_basic_fixtures(&handle);

    if let Some(device_paths) = create_device_fixtures() {
        setup_environment_variables(world, &root, &device_paths);
        verify_missing_fixtures(&handle, &root);
        world.temp = Some(temp);
        Step::succeeded()
    } else {
        warn\!("No block device found in /dev; skipping file-type test scenario.");
        Step::skipped()
    }
}

4. Simplify tests/cucumber.rs

Remove the now-redundant block_device_exists check since skipping is handled at the step level.

Expected Outcome

When the test suite runs on a system without block devices:

  1. find_block_device_fallback returns None
  2. create_device_fixtures propagates this None
  3. The file_type_workspace step logs a warning and returns Step::skipped()
  4. The Cucumber test runner marks scenarios using this step as skipped
  5. The test suite completes successfully without panicking

This makes the test suite more robust and portable, correctly handling environmental differences without failing the entire run.

References

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions