mirror of
https://github.com/imjasonh/testscript-rs
synced 2026-07-18 14:46:25 +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:
parent
e356ddf789
commit
a030b26bb9
6 changed files with 103 additions and 21 deletions
|
|
@ -87,6 +87,6 @@ testscript::run("testdata")
|
||||||
|
|
||||||
## Built-in Commands
|
## 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.
|
The command dispatch checks custom commands first, then falls back to built-ins, enabling easy extension.
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,7 @@ Test scripts use the [`txtar`](https://pkg.go.dev/github.com/rogpeppe/go-interna
|
||||||
- **stop** - Stop test early (pass)
|
- **stop** - Stop test early (pass)
|
||||||
- **unquote** - Remove leading `>` from file lines
|
- **unquote** - Remove leading `>` from file lines
|
||||||
- **grep** - Search files with regex
|
- **grep** - Search files with regex
|
||||||
|
- **symlink** - Create symbolic links
|
||||||
|
|
||||||
Commands can be prefixed with conditions (`[unix]`) or negated (`!`).
|
Commands can be prefixed with conditions (`[unix]`) or negated (`!`).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -271,12 +271,12 @@ impl TestEnvironment {
|
||||||
|
|
||||||
/// Create a symbolic link
|
/// Create a symbolic link
|
||||||
pub fn create_symlink(&self, target: &str, link_name: &str) -> Result<()> {
|
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);
|
let link_path = self.work_dir.join(link_name);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[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(
|
Error::command_error(
|
||||||
"symlink",
|
"symlink",
|
||||||
format!(
|
format!(
|
||||||
|
|
@ -292,6 +292,8 @@ impl TestEnvironment {
|
||||||
// On Windows, try to create a symlink but fall back gracefully
|
// On Windows, try to create a symlink but fall back gracefully
|
||||||
use std::os::windows::fs::symlink_file;
|
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() {
|
if target_path.is_file() {
|
||||||
symlink_file(&target_path, &link_path).map_err(|e| {
|
symlink_file(&target_path, &link_path).map_err(|e| {
|
||||||
Error::command_error(
|
Error::command_error(
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
use testscript_rs::testscript;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_symlink() {
|
|
||||||
testscript::run("/tmp")
|
|
||||||
.filter_file("test_symlink.txtar")
|
|
||||||
.execute()
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
8
testdata/test_symlink.txt
vendored
8
testdata/test_symlink.txt
vendored
|
|
@ -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
|
|
||||||
|
|
@ -181,3 +181,99 @@ hello from stdout"#;
|
||||||
let result = run_test(&script_path);
|
let result = run_test(&script_path);
|
||||||
assert!(result.is_ok(), "CP stdout test failed: {:?}", result);
|
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);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue