zeroclaw/src/skills/symlink_tests.rs
argenis de la rosa 04a35144e8 feat: integrate open-skills library and cleanup clippy warnings
- Add open-skills auto-clone/pull/sync support in skills loader
  - Clone https://github.com/besoeasy/open-skills to ~/open-skills
  - Weekly sync via .zeroclaw-open-skills-sync marker
  - Env controls: ZEROCLAW_OPEN_SKILLS_ENABLED, ZEROCLAW_OPEN_SKILLS_DIR
  - Load open-skills markdown files before workspace skills
  - Track Skill.location for accurate prompt rendering

- Update system prompt to render skill.location with fallback
  - Use actual file path when available
  - Maintain backward compatibility with workspace SKILL.md path

- Fix clippy warnings across tests and supporting files
  - Readable timestamp literals
  - Remove underscore bindings in tests
  - Use struct update syntax for Config::default() patterns
  - Fix module inception, duplicate attributes, manual strip
  - Clean raw string hashes and empty string construction

Resolves: #77
2026-02-14 20:25:07 -05:00

109 lines
4.2 KiB
Rust

#[cfg(test)]
mod tests {
use crate::skills::skills_dir;
use std::path::Path;
use tempfile::TempDir;
#[test]
fn test_skills_symlink_unix_edge_cases() {
let tmp = TempDir::new().unwrap();
let workspace_dir = tmp.path().join("workspace");
std::fs::create_dir_all(&workspace_dir).unwrap();
let skills_path = skills_dir(&workspace_dir);
std::fs::create_dir_all(&skills_path).unwrap();
// Test case 1: Valid symlink creation on Unix
#[cfg(unix)]
{
let source_dir = tmp.path().join("source_skill");
std::fs::create_dir_all(&source_dir).unwrap();
std::fs::write(source_dir.join("SKILL.md"), "# Test Skill\nContent").unwrap();
let dest_link = skills_path.join("linked_skill");
// Create symlink
let result = std::os::unix::fs::symlink(&source_dir, &dest_link);
assert!(result.is_ok(), "Symlink creation should succeed");
// Verify symlink works
assert!(dest_link.exists());
assert!(dest_link.is_symlink());
// Verify we can read through symlink
let content = std::fs::read_to_string(dest_link.join("SKILL.md"));
assert!(content.is_ok());
assert!(content.unwrap().contains("Test Skill"));
// Test case 2: Symlink to non-existent target should fail gracefully
let broken_link = skills_path.join("broken_skill");
let non_existent = tmp.path().join("non_existent");
let result = std::os::unix::fs::symlink(&non_existent, &broken_link);
assert!(
result.is_ok(),
"Symlink creation should succeed even if target doesn't exist"
);
// But reading through it should fail
let content = std::fs::read_to_string(broken_link.join("SKILL.md"));
assert!(content.is_err());
}
// Test case 3: Non-Unix platforms should handle symlink errors gracefully
#[cfg(not(unix))]
{
let source_dir = tmp.path().join("source_skill");
std::fs::create_dir_all(&source_dir).unwrap();
let dest_link = skills_path.join("linked_skill");
// Symlink should fail on non-Unix
let result = std::os::unix::fs::symlink(&source_dir, &dest_link);
assert!(result.is_err());
// Directory should not exist
assert!(!dest_link.exists());
}
// Test case 4: skills_dir function edge cases
let workspace_with_trailing_slash = format!("{}/", workspace_dir.display());
let path_from_str = skills_dir(Path::new(&workspace_with_trailing_slash));
assert_eq!(path_from_str, skills_path);
// Test case 5: Empty workspace directory
let empty_workspace = tmp.path().join("empty");
let empty_skills_path = skills_dir(&empty_workspace);
assert_eq!(empty_skills_path, empty_workspace.join("skills"));
assert!(!empty_skills_path.exists());
}
#[test]
fn test_skills_symlink_permissions_and_safety() {
let tmp = TempDir::new().unwrap();
let workspace_dir = tmp.path().join("workspace");
std::fs::create_dir_all(&workspace_dir).unwrap();
let skills_path = skills_dir(&workspace_dir);
std::fs::create_dir_all(&skills_path).unwrap();
#[cfg(unix)]
{
// Test case: Symlink outside workspace should be allowed (user responsibility)
let outside_dir = tmp.path().join("outside_skill");
std::fs::create_dir_all(&outside_dir).unwrap();
std::fs::write(outside_dir.join("SKILL.md"), "# Outside Skill\nContent").unwrap();
let dest_link = skills_path.join("outside_skill");
let result = std::os::unix::fs::symlink(&outside_dir, &dest_link);
assert!(
result.is_ok(),
"Should allow symlinking to directories outside workspace"
);
// Should still be readable
let content = std::fs::read_to_string(dest_link.join("SKILL.md"));
assert!(content.is_ok());
assert!(content.unwrap().contains("Outside Skill"));
}
}
}