Skip to content
Merged
Show file tree
Hide file tree
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
14 changes: 14 additions & 0 deletions kernel/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,20 @@ fn kernel_main_continue() -> ! {
log::info!("=== FS TEST: block allocation regression test ===");
test_exec::test_fs_block_alloc();

// Coreutil tests - verify true, false, head, tail, wc work correctly
log::info!("=== COREUTIL TEST: true (exit code 0) ===");
test_exec::test_true_coreutil();
log::info!("=== COREUTIL TEST: false (exit code 1) ===");
test_exec::test_false_coreutil();
log::info!("=== COREUTIL TEST: head (first N lines) ===");
test_exec::test_head_coreutil();
log::info!("=== COREUTIL TEST: tail (last N lines) ===");
test_exec::test_tail_coreutil();
log::info!("=== COREUTIL TEST: wc (line/word/byte counts) ===");
test_exec::test_wc_coreutil();
log::info!("=== COREUTIL TEST: which (command location) ===");
test_exec::test_which_coreutil();

// Test Rust std library support
log::info!("=== STD TEST: Rust std library support ===");
test_exec::test_hello_std_real();
Expand Down
174 changes: 174 additions & 0 deletions kernel/src/test_exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2561,3 +2561,177 @@ pub fn test_shell_pipe() {
}
}
}

/// Test the `true` coreutil
///
/// Verifies that /bin/true correctly exits with code 0.
pub fn test_true_coreutil() {
log::info!("Testing true coreutil (exit code 0)");

#[cfg(feature = "testing")]
let true_test_elf_buf = crate::userspace_test::get_test_binary("true_test");
#[cfg(feature = "testing")]
let true_test_elf: &[u8] = &true_test_elf_buf;
#[cfg(not(feature = "testing"))]
let true_test_elf = &create_hello_world_elf();

match crate::process::creation::create_user_process(
String::from("true_test"),
true_test_elf,
) {
Ok(pid) => {
log::info!("Created true_test process with PID {:?}", pid);
log::info!("true_test: process scheduled for execution.");
log::info!(" -> Userspace will emit TRUE_TEST_PASSED marker if successful");
}
Err(e) => {
log::error!("Failed to create true_test process: {}", e);
log::error!("true_test cannot run without valid userspace process");
}
}
}

/// Test the `false` coreutil
///
/// Verifies that /bin/false correctly exits with code 1.
pub fn test_false_coreutil() {
log::info!("Testing false coreutil (exit code 1)");

#[cfg(feature = "testing")]
let false_test_elf_buf = crate::userspace_test::get_test_binary("false_test");
#[cfg(feature = "testing")]
let false_test_elf: &[u8] = &false_test_elf_buf;
#[cfg(not(feature = "testing"))]
let false_test_elf = &create_hello_world_elf();

match crate::process::creation::create_user_process(
String::from("false_test"),
false_test_elf,
) {
Ok(pid) => {
log::info!("Created false_test process with PID {:?}", pid);
log::info!("false_test: process scheduled for execution.");
log::info!(" -> Userspace will emit FALSE_TEST_PASSED marker if successful");
}
Err(e) => {
log::error!("Failed to create false_test process: {}", e);
log::error!("false_test cannot run without valid userspace process");
}
}
}

/// Test the `head` coreutil
///
/// Verifies that /bin/head correctly outputs the first N lines of files.
pub fn test_head_coreutil() {
log::info!("Testing head coreutil (first N lines)");

#[cfg(feature = "testing")]
let head_test_elf_buf = crate::userspace_test::get_test_binary("head_test");
#[cfg(feature = "testing")]
let head_test_elf: &[u8] = &head_test_elf_buf;
#[cfg(not(feature = "testing"))]
let head_test_elf = &create_hello_world_elf();

match crate::process::creation::create_user_process(
String::from("head_test"),
head_test_elf,
) {
Ok(pid) => {
log::info!("Created head_test process with PID {:?}", pid);
log::info!("head_test: process scheduled for execution.");
log::info!(" -> Userspace will emit HEAD_TEST_PASSED marker if successful");
}
Err(e) => {
log::error!("Failed to create head_test process: {}", e);
log::error!("head_test cannot run without valid userspace process");
}
}
}

/// Test the `tail` coreutil
///
/// Verifies that /bin/tail correctly outputs the last N lines of files.
pub fn test_tail_coreutil() {
log::info!("Testing tail coreutil (last N lines)");

#[cfg(feature = "testing")]
let tail_test_elf_buf = crate::userspace_test::get_test_binary("tail_test");
#[cfg(feature = "testing")]
let tail_test_elf: &[u8] = &tail_test_elf_buf;
#[cfg(not(feature = "testing"))]
let tail_test_elf = &create_hello_world_elf();

match crate::process::creation::create_user_process(
String::from("tail_test"),
tail_test_elf,
) {
Ok(pid) => {
log::info!("Created tail_test process with PID {:?}", pid);
log::info!("tail_test: process scheduled for execution.");
log::info!(" -> Userspace will emit TAIL_TEST_PASSED marker if successful");
}
Err(e) => {
log::error!("Failed to create tail_test process: {}", e);
log::error!("tail_test cannot run without valid userspace process");
}
}
}

/// Test the `wc` coreutil
///
/// Verifies that /bin/wc correctly counts lines, words, and bytes.
pub fn test_wc_coreutil() {
log::info!("Testing wc coreutil (line/word/byte counts)");

#[cfg(feature = "testing")]
let wc_test_elf_buf = crate::userspace_test::get_test_binary("wc_test");
#[cfg(feature = "testing")]
let wc_test_elf: &[u8] = &wc_test_elf_buf;
#[cfg(not(feature = "testing"))]
let wc_test_elf = &create_hello_world_elf();

match crate::process::creation::create_user_process(
String::from("wc_test"),
wc_test_elf,
) {
Ok(pid) => {
log::info!("Created wc_test process with PID {:?}", pid);
log::info!("wc_test: process scheduled for execution.");
log::info!(" -> Userspace will emit WC_TEST_PASSED marker if successful");
}
Err(e) => {
log::error!("Failed to create wc_test process: {}", e);
log::error!("wc_test cannot run without valid userspace process");
}
}
}

/// Test the `which` coreutil
///
/// Verifies that /bin/which correctly locates commands in PATH.
pub fn test_which_coreutil() {
log::info!("Testing which coreutil (command location)");

#[cfg(feature = "testing")]
let which_test_elf_buf = crate::userspace_test::get_test_binary("which_test");
#[cfg(feature = "testing")]
let which_test_elf: &[u8] = &which_test_elf_buf;
#[cfg(not(feature = "testing"))]
let which_test_elf = &create_hello_world_elf();

match crate::process::creation::create_user_process(
String::from("which_test"),
which_test_elf,
) {
Ok(pid) => {
log::info!("Created which_test process with PID {:?}", pid);
log::info!("which_test: process scheduled for execution.");
log::info!(" -> Userspace will emit WHICH_TEST_PASSED marker if successful");
}
Err(e) => {
log::error!("Failed to create which_test process: {}", e);
log::error!("which_test cannot run without valid userspace process");
}
}
}
88 changes: 77 additions & 11 deletions scripts/create_ext2_disk.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
#
# This script creates a 4MB ext2 filesystem image with:
# - Test files for filesystem testing
# - Coreutils binaries in /bin/ (cat, ls, echo, mkdir, rmdir, rm, cp, mv, true, false, head, tail, wc)
# - Coreutils binaries in /bin/ (cat, ls, echo, mkdir, rmdir, rm, cp, mv, false, head, tail, wc, which)
# - /sbin/true for PATH order testing
# - hello_world binary for exec testing
#
# Requires Docker on macOS (or mke2fs on Linux).
Expand All @@ -25,7 +26,7 @@ TESTDATA_FILE="$PROJECT_ROOT/testdata/ext2.img"
SIZE_MB=4

# Coreutils to install in /bin
COREUTILS="cat ls echo mkdir rmdir rm cp mv true false head tail wc"
COREUTILS="cat ls echo mkdir rmdir rm cp mv true false head tail wc which"

echo "Creating ext2 disk image..."
echo " Output: $OUTPUT_FILE"
Expand Down Expand Up @@ -71,12 +72,13 @@ if [[ "$(uname)" == "Darwin" ]]; then
mkdir -p /mnt/ext2
mount /work/ext2.img /mnt/ext2

# Create /bin directory for coreutils
# Create /bin and /sbin directories for coreutils
mkdir -p /mnt/ext2/bin
mkdir -p /mnt/ext2/sbin

# Copy coreutils binaries
# Copy coreutils binaries to /bin (excluding true which goes to /sbin)
echo "Installing coreutils in /bin..."
for bin in cat ls echo mkdir rmdir rm cp mv true false head tail wc; do
for bin in cat ls echo mkdir rmdir rm cp mv false head tail wc which; do
if [ -f /binaries/${bin}.elf ]; then
cp /binaries/${bin}.elf /mnt/ext2/bin/${bin}
chmod 755 /mnt/ext2/bin/${bin}
Expand All @@ -86,6 +88,16 @@ if [[ "$(uname)" == "Darwin" ]]; then
fi
done

# Install true in /sbin to test PATH lookup order
echo "Installing binaries in /sbin..."
if [ -f /binaries/true.elf ]; then
cp /binaries/true.elf /mnt/ext2/sbin/true
chmod 755 /mnt/ext2/sbin/true
echo " /sbin/true installed"
else
echo " WARNING: true.elf not found in /binaries/"
fi

# Copy hello_world for exec testing
if [ -f /binaries/hello_world.elf ]; then
cp /binaries/hello_world.elf /mnt/ext2/bin/hello_world
Expand All @@ -97,13 +109,34 @@ if [[ "$(uname)" == "Darwin" ]]; then

# Create test files for filesystem testing
echo "Hello from ext2!" > /mnt/ext2/hello.txt
echo "Truncate test file" > /mnt/ext2/trunctest.txt
touch /mnt/ext2/empty.txt # Empty file for wc testing
mkdir -p /mnt/ext2/test
echo "Nested file content" > /mnt/ext2/test/nested.txt

# Create additional test content
mkdir -p /mnt/ext2/deep/path/to/file
echo "Deep nested content" > /mnt/ext2/deep/path/to/file/data.txt

# Create multi-line test file for head/tail/wc testing (15 lines)
cat > /mnt/ext2/lines.txt << EOF
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line 8
Line 9
Line 10
Line 11
Line 12
Line 13
Line 14
Line 15
EOF

# Show what was created
echo ""
echo "ext2 filesystem contents:"
Expand Down Expand Up @@ -143,12 +176,13 @@ else
MOUNT_DIR=$(mktemp -d)
mount "$OUTPUT_FILE" "$MOUNT_DIR"

# Create /bin directory
# Create /bin and /sbin directories
mkdir -p "$MOUNT_DIR/bin"
mkdir -p "$MOUNT_DIR/sbin"

# Copy coreutils binaries
# Copy coreutils binaries to /bin (excluding true which goes to /sbin)
echo "Installing coreutils in /bin..."
for bin in cat ls echo mkdir rmdir rm cp mv true false head tail wc; do
for bin in cat ls echo mkdir rmdir rm cp mv false head tail wc which; do
if [ -f "$USERSPACE_DIR/${bin}.elf" ]; then
cp "$USERSPACE_DIR/${bin}.elf" "$MOUNT_DIR/bin/${bin}"
chmod 755 "$MOUNT_DIR/bin/${bin}"
Expand All @@ -158,6 +192,16 @@ else
fi
done

# Install true in /sbin to test PATH lookup order
echo "Installing binaries in /sbin..."
if [ -f "$USERSPACE_DIR/true.elf" ]; then
cp "$USERSPACE_DIR/true.elf" "$MOUNT_DIR/sbin/true"
chmod 755 "$MOUNT_DIR/sbin/true"
echo " /sbin/true installed"
else
echo " WARNING: true.elf not found"
fi

# Copy hello_world for exec testing
if [ -f "$USERSPACE_DIR/hello_world.elf" ]; then
cp "$USERSPACE_DIR/hello_world.elf" "$MOUNT_DIR/bin/hello_world"
Expand All @@ -167,11 +211,32 @@ else

# Create test files
echo "Hello from ext2!" > "$MOUNT_DIR/hello.txt"
echo "Truncate test file" > "$MOUNT_DIR/trunctest.txt"
touch "$MOUNT_DIR/empty.txt" # Empty file for wc testing
mkdir -p "$MOUNT_DIR/test"
echo "Nested file content" > "$MOUNT_DIR/test/nested.txt"
mkdir -p "$MOUNT_DIR/deep/path/to/file"
echo "Deep nested content" > "$MOUNT_DIR/deep/path/to/file/data.txt"

# Create multi-line test file for head/tail/wc testing (15 lines)
cat > "$MOUNT_DIR/lines.txt" << EOF
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line 8
Line 9
Line 10
Line 11
Line 12
Line 13
Line 14
Line 15
EOF

# Show what was created
echo ""
echo "ext2 filesystem contents:"
Expand All @@ -197,10 +262,11 @@ if [[ -f "$OUTPUT_FILE" ]]; then
echo ""
echo "Contents:"
echo " /bin/cat, ls, echo, mkdir, rmdir, rm, cp, mv - file coreutils"
echo " /bin/true, false - exit status coreutils"
echo " /bin/head, tail, wc - text processing coreutils"
echo " /sbin/true, /bin/false - exit status coreutils"
echo " /bin/head, tail, wc, which - text processing coreutils"
echo " /bin/hello_world - exec test binary (exit code 42)"
echo " /hello.txt - test file"
echo " /hello.txt - test file (1 line)"
echo " /lines.txt - multi-line test file (15 lines) for head/tail/wc"
echo " /test/nested.txt - nested test file"
echo " /deep/path/to/file/data.txt - deep nested test file"
else
Expand Down
Binary file modified testdata/ext2.img
Binary file not shown.
Loading
Loading