1
0
Fork 0
mirror of https://github.com/imjasonh/testscript-rs synced 2026-07-08 17:16:38 +00:00

Fix symlink implementation and add comprehensive tests and documentation

Co-authored-by: imjasonh <210737+imjasonh@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2025-09-27 02:47:44 +00:00
parent e356ddf789
commit a030b26bb9
6 changed files with 103 additions and 21 deletions

View file

@ -87,6 +87,6 @@ testscript::run("testdata")
## Built-in Commands
Core: `exec`, `cmp`, `stdout`, `stderr`, `cd`, `wait`, `exists`, `mkdir`, `cp`, `mv`, `rm`, `chmod`, `env`, `cmpenv`, `stdin`, `skip`, `stop`, `kill`, `unquote`, `grep`
Core: `exec`, `cmp`, `stdout`, `stderr`, `cd`, `wait`, `exists`, `mkdir`, `cp`, `mv`, `rm`, `chmod`, `env`, `cmpenv`, `stdin`, `skip`, `stop`, `kill`, `unquote`, `grep`, `symlink`
The command dispatch checks custom commands first, then falls back to built-ins, enabling easy extension.

View file

@ -137,6 +137,7 @@ Test scripts use the [`txtar`](https://pkg.go.dev/github.com/rogpeppe/go-interna
- **stop** - Stop test early (pass)
- **unquote** - Remove leading `>` from file lines
- **grep** - Search files with regex
- **symlink** - Create symbolic links
Commands can be prefixed with conditions (`[unix]`) or negated (`!`).

View file

@ -271,12 +271,12 @@ impl TestEnvironment {
/// Create a symbolic link
pub fn create_symlink(&self, target: &str, link_name: &str) -> Result<()> {
let target_path = self.work_dir.join(target);
let link_path = self.work_dir.join(link_name);
#[cfg(unix)]
{
std::os::unix::fs::symlink(&target_path, &link_path).map_err(|e| {
// For Unix systems, preserve the target path as-is to support relative links
std::os::unix::fs::symlink(target, &link_path).map_err(|e| {
Error::command_error(
"symlink",
format!(
@ -292,6 +292,8 @@ impl TestEnvironment {
// On Windows, try to create a symlink but fall back gracefully
use std::os::windows::fs::symlink_file;
// For Windows, we need to resolve the path to check if it's a file
let target_path = self.work_dir.join(target);
if target_path.is_file() {
symlink_file(&target_path, &link_path).map_err(|e| {
Error::command_error(

View file

@ -1,9 +0,0 @@
use testscript_rs::testscript;
#[test]
fn test_symlink() {
testscript::run("/tmp")
.filter_file("test_symlink.txtar")
.execute()
.unwrap();
}

View file

@ -1,8 +0,0 @@
# Test symlink functionality
symlink original.txt link.txt
exists link.txt
exec cat link.txt
stdout "original content"
-- original.txt --
original content

View file

@ -181,3 +181,99 @@ hello from stdout"#;
let result = run_test(&script_path);
assert!(result.is_ok(), "CP stdout test failed: {:?}", result);
}
#[cfg(unix)]
#[test]
fn test_symlink_command() {
let temp_dir = TempDir::new().unwrap();
let script_path = temp_dir.path().join("symlink_test.txt");
let script_content = r#"# Test symlink command
symlink original.txt link.txt
exists link.txt
exec cat link.txt
stdout "original content"
-- original.txt --
original content"#;
fs::write(&script_path, script_content).unwrap();
let result = run_test(&script_path);
assert!(result.is_ok(), "Symlink test failed: {:?}", result);
}
#[cfg(unix)]
#[test]
fn test_symlink_directory() {
let temp_dir = TempDir::new().unwrap();
let script_path = temp_dir.path().join("symlink_dir_test.txt");
let script_content = r#"# Test symlink with directory
mkdir test_dir
symlink test_dir link_dir
exists link_dir
exec ls link_dir"#;
fs::write(&script_path, script_content).unwrap();
let result = run_test(&script_path);
assert!(result.is_ok(), "Directory symlink test failed: {:?}", result);
}
#[cfg(unix)]
#[test]
fn test_symlink_relative_path() {
let temp_dir = TempDir::new().unwrap();
let script_path = temp_dir.path().join("symlink_relative_test.txt");
let script_content = r#"# Test symlink with relative path
mkdir subdir
symlink ../original.txt subdir/link.txt
exists subdir/link.txt
exec cat subdir/link.txt
stdout "relative content"
-- original.txt --
relative content"#;
fs::write(&script_path, script_content).unwrap();
let result = run_test(&script_path);
assert!(result.is_ok(), "Relative path symlink test failed: {:?}", result);
}
#[test]
fn test_symlink_error_cases() {
let temp_dir = TempDir::new().unwrap();
let script_path = temp_dir.path().join("symlink_error_test.txt");
let script_content = r#"# Test symlink error cases
! symlink
! symlink only_one_arg"#;
fs::write(&script_path, script_content).unwrap();
let result = run_test(&script_path);
assert!(result.is_ok(), "Symlink error test failed: {:?}", result);
}
#[test]
fn test_issue_example() {
let temp_dir = TempDir::new().unwrap();
let script_path = temp_dir.path().join("issue_example.txt");
let script_content = r#"# Create a symlink
symlink original.txt link.txt
exists link.txt
exec cat link.txt
stdout "original content"
-- original.txt --
original content"#;
fs::write(&script_path, script_content).unwrap();
let result = run_test(&script_path);
assert!(result.is_ok(), "Issue example test failed: {:?}", result);
}