program_tools 0.2.0

Rust script runner — compile and execute Rust files as scripts with output capture.
Documentation
# Manual Testing Plan: program_tools

### Scope

Manual testing plan for the `program_tools` data structure layer (Source, Program, Plan with Former builder pattern) and runner API (run_source, run_file, run_project, CapturedOutput). See `docs/feature/` and `docs/api/` for full specifications.

### Testing Objectives

Validate builder API construction for all three data structures across comprehensive corner cases including edge cases, empty inputs, large data, and special characters.

### Manual Test Cases

#### 1. Source Builder API

**Test Case 1.1: Empty file_path**
```rust
// Execute in Rust playground or test environment
use program_tools::program::*;

let source = Source::former()
  .file_path("")
  .data("fn main() {}")
  .form();

println!("Empty file_path: {:?}", source);
// Expected: Source { file_path: "", data: "fn main() {}" }
// Status: ✅ PASS if constructs without panic
```

**Test Case 1.2: Empty data**
```rust
let source = Source::former()
  .file_path("main.rs")
  .data("")
  .form();

println!("Empty data: {:?}", source);
// Expected: Source { file_path: "main.rs", data: "" }
// Status: ✅ PASS if constructs without panic
```

**Test Case 1.3: Both fields empty**
```rust
let source = Source::former()
  .file_path("")
  .data("")
  .form();

println!("Both empty: {:?}", source);
// Expected: Source { file_path: "", data: "" }
// Status: ✅ PASS if constructs without panic
```

**Test Case 1.4: Large data (1MB string)**
```rust
let large_data = "// comment\n".repeat(50_000); // ~500KB
let source = Source::former()
  .file_path("large.rs")
  .data(&large_data)
  .form();

println!("Large data size: {} bytes", source.data.len());
// Expected: Constructs without panic, len ~500,000
// Status: ✅ PASS if no memory issues
```

**Test Case 1.5: Special characters (Unicode, newlines, tabs)**
```rust
let source = Source::former()
  .file_path("src/模块.rs") // Unicode Chinese
  .data("fn main() {\n\tprintln!(\"🦀 Rust\");\n}")
  .form();

println!("Special chars: {:?}", source);
// Expected: Preserves exact Unicode and escape sequences
// Status: ✅ PASS if exact preservation
```

#### 2. Program Builder API

**Test Case 2.1: Zero sources (empty program)**
```rust
let program = Program::former().form();

println!("Empty program sources: {:?}", program.source);
// Expected: Program { source: [] }
// Status: ✅ PASS if empty Vec
```

**Test Case 2.2: Single source**
```rust
let program = Program::former()
  .source()
    .file_path("main.rs")
    .data("fn main() {}")
    .end()
  .form();

println!("Single source count: {}", program.source.len());
// Expected: 1 source in Vec
// Status: ✅ PASS if len == 1
```

**Test Case 2.3: Multiple sources**
```rust
let program = Program::former()
  .source()
    .file_path("main.rs")
    .data("fn main() {}")
    .end()
  .source()
    .file_path("lib.rs")
    .data("pub fn helper() {}")
    .end()
  .source()
    .file_path("utils.rs")
    .data("pub fn util() {}")
    .end()
  .form();

println!("Multiple sources count: {}", program.source.len());
// Expected: 3 sources in Vec
// Status: ✅ PASS if len == 3
```

**Test Case 2.4: Duplicate file paths**
```rust
let program = Program::former()
  .source()
    .file_path("main.rs")
    .data("// version 1")
    .end()
  .source()
    .file_path("main.rs") // Duplicate path
    .data("// version 2")
    .end()
  .form();

println!("Duplicate paths: {:?}", program.source);
// Expected: Both sources present (no validation)
// Status: ✅ PASS if both exist with same path
```

#### 3. Plan Builder API

**Test Case 3.1: Minimal plan (program with zero sources)**
```rust
let plan = Plan::former()
  .program()
    // No sources added
    .end()
  .form();

println!("Minimal plan: {:?}", plan);
// Expected: Plan with empty program
// Status: ✅ PASS if constructs
```

**Test Case 3.2: Complete nested builder chain**
```rust
let plan = Plan::former()
  .program()
    .source()
      .file_path("main.rs")
      .data("fn main() { println!(\"test\"); }")
      .end()
    .end()
  .form();

println!("Complete chain: {:?}", plan);
// Expected: Fully populated Plan → Program → Source
// Status: ✅ PASS if all fields populated
```

**Test Case 3.3: Verify .end() returns correct parent**
```rust
// This is tested by compilation success - type system enforces correctness
let plan = Plan::former()
  .program() // Returns ProgramFormer
    .source() // Returns SourceFormer
      .file_path("test.rs")
      .data("code")
      .end() // MUST return ProgramFormer, not PlanFormer
    .end() // MUST return PlanFormer
  .form();

// Expected: Compiles without type errors
// Status: ✅ PASS if compiles (Former guarantees)
```

#### 4. Debug Trait Validation

**Test Case 4.1: Debug formatting for all structs**
```rust
let source = Source::former()
  .file_path("test.rs")
  .data("code")
  .form();

let program = Program::former()
  .source()
    .file_path("main.rs")
    .data("fn main() {}")
    .end()
  .form();

let plan = Plan::former()
  .program()
    .source()
      .file_path("lib.rs")
      .data("pub fn test() {}")
      .end()
    .end()
  .form();

println!("Source: {:?}", source);
println!("Program: {:?}", program);
println!("Plan: {:?}", plan);

// Expected: All print without panic
// Status: ✅ PASS if no panics
```

#### 5. Namespace Validation

**Test Case 5.1: Exposed namespace**
```rust
use program_tools::*;

let _source: program::Source = program::Source::former().form();
let _program: program::Program = program::Program::former().form();
let _plan: program::Plan = program::Plan::former().form();

// Expected: All types accessible via program:: namespace
// Status: ✅ PASS if compiles
```

**Test Case 5.2: Prelude namespace**
```rust
use program_tools::prelude::*;

// Prelude imports should also work
// Check via documentation what prelude exports

// Expected: Types accessible via prelude
// Status: ℹ️ CHECK documentation for prelude contents
```

### Manual Execution Instructions

All cases are now covered by automated tests. For ad-hoc manual verification:

1. **Create temporary test binary:**
   ```bash
   cd /tmp
   cargo new program_tools_manual_test
   cd program_tools_manual_test
   ```

2. **Add program_tools dependency to Cargo.toml:**
   ```toml
   [dependencies]
   program_tools = { path = "/home/user1/pro/lib/wip_core/wtools/dev/module/experimental/program_tools" }
   ```

3. **Copy test case code to src/main.rs**

4. **Run:**
   ```bash
   cargo run
   ```

5. **Verify output matches expected behavior**

### Test Results Tracking

| Test ID | Description | Status | Notes |
|---------|-------------|--------|-------|
| 1.1 | Empty file_path | Covered | `corner_cases_test::source_empty_file_path` |
| 1.2 | Empty data | Covered | `corner_cases_test::source_empty_data` |
| 1.3 | Both empty | Covered | `corner_cases_test::source_both_fields_empty` |
| 1.4 | Large data | Covered | `corner_cases_test::source_large_data` |
| 1.5 | Special chars | Covered | `corner_cases_test::source_special_characters` |
| 2.1 | Zero sources | Covered | `corner_cases_test::program_zero_sources` |
| 2.2 | Single source | Covered | `corner_cases_test::program_single_source` |
| 2.3 | Multiple sources | Covered | `basic::basic` |
| 2.4 | Duplicate paths | Covered | `corner_cases_test::program_duplicate_file_paths` |
| 3.1 | Minimal plan | Covered | `corner_cases_test::plan_minimal_with_empty_program` |
| 3.2 | Complete chain | Covered | `basic::basic` |
| 3.3 | Nested end() | Covered | Verified by type system |
| 4.1 | Debug trait | Covered | `corner_cases_test::debug_trait_all_structs` |
| 5.1 | Exposed namespace | Covered | `basic::basic` |
| 5.2 | Prelude namespace | Covered | `corner_cases_test::namespace_prelude_imports` |

### Implemented Runner API

The following capabilities are now implemented and covered by automated tests in `tests/inc/runner_test.rs`:

- Script compilation and execution via `run_source`, `run_file`, `run_project` (`api/002`)
- Output capture into `CapturedOutput` with predicate and assertion methods (`feature/002`, `api/003`)
- Isolated temp workspaces with RAII cleanup (`feature/003`)
- Forwarding mode (`capture=false`) via `cmd.status()` / `try_wait()` — output streams to terminal
- Timeout enforcement via `timeout_ms` (`runner_test::run_timeout_fires`, `run_timeout_does_not_fire`)
  - Capture mode: channel + background thread; child not killed on timeout (v0.1.0 limitation)
  - Forwarding mode: polling `try_wait()` + `child.kill()` on expiry

Not yet implemented:

- CLI interface `program_tools run` (`api/004`)
- Async execution

### Conclusion

All data-structure corner cases are automated in `tests/inc/corner_cases_test.rs`. Runner and output API integration tests are in `tests/inc/runner_test.rs`. This plan serves as a reference for test design rationale.