#![allow(clippy::unwrap_used, clippy::expect_used)]
#![cfg(feature = "localfs")]
mod common;
use std::fs;
use common::{kernel_at, run};
use tempfile::tempdir;
fn touch(dir: &std::path::Path, name: &str) {
fs::write(dir.join(name), b"").expect("write file");
}
#[tokio::test]
async fn ls_dash_one_is_a_flag_not_a_path() {
let dir = tempdir().unwrap();
touch(dir.path(), "alpha.txt");
touch(dir.path(), "beta.txt");
let kernel = kernel_at(dir.path());
let (out, code) = run(&kernel, "ls -1").await;
assert_eq!(code, 0, "ls -1 should succeed, not error with 'not found': {out:?}");
}
#[tokio::test]
async fn ls_dash_one_lists_one_per_line() {
let dir = tempdir().unwrap();
touch(dir.path(), "alpha.txt");
touch(dir.path(), "beta.txt");
let kernel = kernel_at(dir.path());
let (out, code) = run(&kernel, "ls -1").await;
assert_eq!(code, 0, "ls -1 should succeed: {out:?}");
assert!(out.contains("alpha.txt"), "alpha.txt missing from ls -1 output: {out:?}");
assert!(out.contains("beta.txt"), "beta.txt missing from ls -1 output: {out:?}");
let lines: Vec<&str> = out.lines().filter(|l| !l.is_empty()).collect();
assert!(lines.len() >= 2, "expected at least 2 lines from ls -1, got: {out:?}");
for line in &lines {
assert!(
!line.contains(" "),
"ls -1 output line contains multiple columns (spaces): {line:?}"
);
}
}
#[tokio::test]
async fn basename_double_slash_returns_single_slash() {
let dir = tempdir().unwrap();
let kernel = kernel_at(dir.path());
let (out, code) = run(&kernel, "basename //").await;
assert_eq!(code, 0, "basename // should succeed: {out:?}");
assert_eq!(
out.trim(),
"/",
"basename // must return '/' per POSIX, got {out:?}"
);
}
#[tokio::test]
async fn basename_single_slash_returns_slash() {
let dir = tempdir().unwrap();
let kernel = kernel_at(dir.path());
let (out, code) = run(&kernel, "basename /").await;
assert_eq!(code, 0, "basename / should succeed: {out:?}");
assert_eq!(out.trim(), "/", "basename / must return '/': {out:?}");
}
#[tokio::test]
async fn dirname_double_slash_returns_single_slash() {
let dir = tempdir().unwrap();
let kernel = kernel_at(dir.path());
let (out, code) = run(&kernel, "dirname //").await;
assert_eq!(code, 0, "dirname // should succeed: {out:?}");
assert_eq!(
out.trim(),
"/",
"dirname // must return '/' per POSIX, got {out:?}"
);
}
#[tokio::test]
async fn dirname_single_slash_returns_slash() {
let dir = tempdir().unwrap();
let kernel = kernel_at(dir.path());
let (out, code) = run(&kernel, "dirname /").await;
assert_eq!(code, 0, "dirname / should succeed: {out:?}");
assert_eq!(out.trim(), "/", "dirname / must return '/': {out:?}");
}
#[tokio::test]
async fn basename_empty_string_is_empty() {
let dir = tempdir().unwrap();
let kernel = kernel_at(dir.path());
let (out, code) = run(&kernel, r#"basename """#).await;
assert_eq!(code, 0, "{out:?}");
assert_eq!(out, "", "basename \"\" should be empty, not /: {out:?}");
}
#[tokio::test]
async fn dirname_empty_string_is_dot() {
let dir = tempdir().unwrap();
let kernel = kernel_at(dir.path());
let (out, code) = run(&kernel, r#"dirname """#).await;
assert_eq!(code, 0, "{out:?}");
assert_eq!(out, ".", "dirname \"\" should be ., not /: {out:?}");
}