> ## Documentation Index
> Fetch the complete documentation index at: https://nono.sh/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing

> nono integration test suites, running tests, and CI pipeline

nono includes comprehensive integration tests that verify the sandbox enforcement works correctly across different scenarios and platforms.

## Running Tests

### Full Test Suite

Run all integration tests with:

```bash theme={null}
./tests/run_integration_tests.sh
```

This script:

1. Builds nono in release mode
2. Runs all integration test suites
3. Reports results with pass/fail/skip counts
4. Exits with non-zero status if any tests fail

### Individual Test Suites

Run a specific test suite:

```bash theme={null}
# Build first
cargo build --release

# Export binary location
export NONO_BIN="$(pwd)/target/release/nono"

# Run a specific suite
./tests/integration/test_fs_access.sh
```

## Test Suites

The integration tests are organized into 7 focused suites:

### 1. Filesystem Access (`test_fs_access.sh`)

Tests that nono correctly enforces read/write permissions on directories and files.

| Test Category      | What It Verifies                                              |
| ------------------ | ------------------------------------------------------------- |
| Directory Read     | Files can be read in granted directories                      |
| Directory Write    | Files can be written in granted directories                   |
| Nested Access      | Permissions apply to subdirectories                           |
| Read-only Mode     | `--read` flag allows reads but not writes                     |
| Write-only Mode    | `--write` flag allows writes but not reads                    |
| Single File Access | `--read-file` and `--write-file` grant file-level permissions |
| Multiple Grants    | Multiple `--allow`, `--read`, `--write` flags work together   |

### 2. Sensitive Paths (`test_sensitive_paths.sh`)

Verifies that credential and configuration files are protected by default.

Protected paths include:

* `~/.ssh/` - SSH keys
* `~/.aws/` - AWS credentials
* `~/.gnupg/` - GPG keys
* `~/.kube/` - Kubernetes config
* `~/.docker/` - Docker credentials
* `~/.npmrc` - npm auth tokens
* `~/.netrc` - Network credentials
* `~/.bash_history`, `~/.zsh_history` - Command history
* `~/.bashrc`, `~/.zshrc` - Shell configs

These paths are blocked even if a parent directory is explicitly allowed.

### 3. System Paths (`test_system_paths.sh`)

Tests protection of system directories.

| Test Category   | What It Verifies                                          |
| --------------- | --------------------------------------------------------- |
| System Reads    | Can read from `/usr/bin`, `/etc` (needed for executables) |
| System Writes   | Cannot write to system directories                        |
| Root Protection | Cannot write to `/`, `/tmp/..` escapes                    |
| macOS Specifics | `/System/Library` is readable but not writable            |

### 4. Binary Execution (`test_binary_exec.sh`)

Verifies that various binaries execute correctly under the sandbox.

| Category            | Commands Tested                                                     |
| ------------------- | ------------------------------------------------------------------- |
| Basic               | `echo`, `true`, `false`, exit codes                                 |
| File Operations     | `ls`, `cat`, `head`, `tail`, `wc`, `grep`, `find`, `touch`, `mkdir` |
| Shells              | `sh`, `bash`, `zsh`, `env`, `printenv`                              |
| Text Processing     | `sort`, `uniq`, `cut`, `sed`, `awk`                                 |
| Language Runtimes   | `python3`, `node`, `ruby`, `perl`, `gofmt`                          |
| Output Verification | Correct output from commands                                        |

<Note>
  Language runtime tests (Python, Node, Ruby) may be skipped if the runtime is installed via Homebrew, as `/opt/homebrew` isn't in the sandbox allowlist by default.
</Note>

### 5. Network (`test_network.sh`)

Tests network blocking functionality.

| Test              | What It Verifies                                       |
| ----------------- | ------------------------------------------------------ |
| `--block-net`     | `curl`, `wget`, `nc`, `ping` are blocked               |
| Default (allowed) | Network access works without `--block-net`             |
| DNS Resolution    | `host`, `nslookup`, `dig` work when network is allowed |

### 6. Dangerous Commands (`test_commands.sh`)

Verifies the current startup-only command-blocking compatibility behavior.

| Category         | Commands Blocked                        |
| ---------------- | --------------------------------------- |
| Destructive      | `rm`, `rmdir`, `mv`                     |
| Permissions      | `chmod`, `chown`, `chgrp`               |
| Privilege        | `sudo`, `su`, `doas`                    |
| Package Managers | `pip`, `npm`, `gem`, `cargo install`    |
| System           | `shutdown`, `reboot`, `kill`, `killall` |

Also tests:

* `--allow-command` flag to permit specific blocked commands
* `--block-command` flag to block additional commands
* documented child-process bypass behavior while the feature is deprecated in `v0.33.x`

### 7. Edge Cases (`test_edge_cases.sh`)

Tests unusual scenarios and boundary conditions.

| Test Category      | What It Verifies                                                     |
| ------------------ | -------------------------------------------------------------------- |
| Symlinks           | Symlink traversal within allowed paths                               |
| Symlink Escapes    | Symlinks to sensitive paths are blocked                              |
| Path Variations    | Relative paths, `..` references, spaces, special characters          |
| Capability Queries | `nono why --self` for sandbox introspection, `NONO_CAP_FILE` env var |
| Non-existent Paths | Proper error handling for missing paths                              |
| Dry Run Mode       | `--dry-run` shows sandbox info without executing                     |
| Mixed Permissions  | Combining `--read` and `--write` directories                         |

## Test Framework

Tests use a shared helper library (`tests/lib/test_helpers.sh`) providing:

```bash theme={null}
# Run a test expecting success (exit 0)
expect_success "test name" command args...

# Run a test expecting failure (non-zero exit)
expect_failure "test name" command args...

# Check command output contains a string
expect_output_contains "test name" "expected string" command args...

# Skip a test with a reason
skip_test "test name" "reason"

# Platform checks
is_macos    # Returns true on macOS
is_linux    # Returns true on Linux

# Check if a command is available
command_exists curl
```

## CI Pipeline

Integration tests run automatically in GitHub Actions on:

* Pull requests to `main`
* Pushes to `main`

The CI runs tests on both Ubuntu and macOS:

```yaml theme={null}
integration:
  name: Integration Tests
  runs-on: ${{ matrix.os }}
  strategy:
    matrix:
      os: [ubuntu-latest, macos-latest]
  steps:
    - uses: actions/checkout@v4
    - name: Install Rust toolchain
      uses: dtolnay/rust-toolchain@stable
    - name: Build release binary
      run: cargo build --release
    - name: Run integration tests
      run: ./tests/run_integration_tests.sh
```

## Platform-Specific Behavior

### macOS Notes

* **TMPDIR**: On macOS, `/var/folders` (where `TMPDIR` points) is a system-writable path. Tests that expect write denial within TMPDIR won't work. Write denial is instead verified via system paths (`/usr/bin`, `/etc`).

* **Homebrew runtimes**: Language runtimes installed via Homebrew at `/opt/homebrew/` aren't in the sandbox allowlist. Tests for Python, Node, Ruby gracefully skip if the runtime isn't accessible.

### Linux Notes

* **Landlock ABI**: Tests should work on any Landlock-enabled kernel (5.13+). Network filtering requires ABI v4+ (kernel 6.7+).

## Adding New Tests

1. Create a new test file in `tests/integration/`:
   ```bash theme={null}
   #!/bin/bash
   SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
   source "$SCRIPT_DIR/../lib/test_helpers.sh"

   echo ""
   echo -e "${BLUE}=== My New Tests ===${NC}"

   verify_nono_binary

   TMPDIR=$(setup_test_dir)
   trap 'cleanup_test_dir "$TMPDIR"' EXIT

   # Your tests here
   expect_success "my test" "$NONO_BIN" run --allow "$TMPDIR" -- echo "hello"

   print_summary
   ```

2. Add the suite to `tests/run_integration_tests.sh`:
   ```bash theme={null}
   run_suite "$SCRIPT_DIR/integration/test_my_new.sh" "My New Tests"
   ```

3. Make the script executable:
   ```bash theme={null}
   chmod +x tests/integration/test_my_new.sh
   ```
