# MarkBase FUSE POC Test Plan ## Overview **Objective**: Verify FUSE-T installation, basic functionality, and backend selection before full implementation. **Scope**: Phase 1 POC verification (Day 1-2) **Environment**: M4 Mac mini, macOS 26.4.1, NVMe storage --- ## Test Environment Setup ### Hardware Configuration | Component | Specification | |-----------|--------------| | **CPU** | Apple M4, 10 physical cores | | **RAM** | 16 GB unified memory | | **Storage** | KIOXIA NVMe 2TB (PCIe) | | **OS** | macOS 26.4.1 (Sequoia) | | **Network** | Thunderbolt Ethernet | ### Software Dependencies ```bash # Required tools brew install fuse-t # FUSE-T installation brew install rustup # Rust toolchain (already installed) # Optional test tools brew install ajadatacalc # AJA Data Calculator (storage estimation) ``` ### AJA System Test Installation ```bash # Download AJA System Test curl -L -o ~/Downloads/AJA_System_Test.dmg \ "https://www.aja.com/en/products/aja-system-test" # Install hdiutil attach ~/Downloads/AJA_System_Test.dmg cp -R /Volumes/AJA\ System\ Test/*.app /Applications/ hdiutil detach /Volumes/AJA\ System\ Test # Verify installation ls -la /Applications/AJA\ System\ Test.app ``` --- ## Test 1: FUSE-T Installation Verification ### Objective Verify FUSE-T can be installed and basic mount/unmount operations work. ### Steps ```bash # Step 1: Install FUSE-T brew install macos-fuse-t/homebrew-cask/fuse-t # Step 2: Verify installation ls -la /usr/local/bin/fuse-t fuse-t --version # Step 3: Check NFS server ls -la /usr/local/bin/nfs-t nfs-t --version # Step 4: Verify mount capability mount | grep fuse # Should show no existing FUSE mounts ``` ### Expected Results | Check | Expected | Actual | Pass/Fail | |-------|----------|--------|-----------| | fuse-t binary exists | `/usr/local/bin/fuse-t` | TBD | TBD | | fuse-t version | >=1.2.6 | TBD | TBD | | nfs-t binary exists | `/usr/local/bin/nfs-t` | TBD | TBD | | No existing FUSE mounts | Empty output | TBD | TBD | ### Failure Handling **If installation fails:** 1. Check System Settings → Privacy & Security → Network Volumes permission 2. Manual download: https://github.com/macos-fuse-t/fuse-t/releases 3. Install from PKG: `sudo installer -pkg fuse-t-macos-installer-1.2.6.pkg -target /` --- ## Test 2: Hello FUSE POC ### Objective Create minimal FUSE filesystem to verify mount/unmount works. ### Implementation ```rust // src/fuse/poc_hello.rs use fuse::{Filesystem, FileAttr, FileType}; use time::Timespec; use std::path::Path; pub struct HelloFs; impl Filesystem for HelloFs { fn lookup(&mut self, _parent: u64, name: &str, reply: fuse::ReplyEntry) { if name == "hello.txt" { let attr = FileAttr { ino: 2, size: 13, blocks: 0, atime: Timespec::new(0, 0), mtime: Timespec::new(0, 0), ctime: Timespec::new(0, 0), crtime: Timespec::new(0, 0), kind: FileType::RegularFile, perm: 0o644, nlink: 1, uid: 0, gid: 0, rdev: 0, flags: 0, }; reply.entry(&Timespec::new(0, 0), &attr, 0); } else { reply.error(libc::ENOENT); } } fn getattr(&mut self, ino: u64, reply: fuse::ReplyAttr) { match ino { 1 => { // Root directory let attr = FileAttr { ino: 1, size: 0, blocks: 0, atime: Timespec::new(0, 0), mtime: Timespec::new(0, 0), ctime: Timespec::new(0, 0), crtime: Timespec::new(0, 0), kind: FileType::Directory, perm: 0o755, nlink: 2, uid: 0, gid: 0, rdev: 0, flags: 0, }; reply.attr(&Timespec::new(0, 0), &attr); } 2 => { // hello.txt let attr = FileAttr { ino: 2, size: 13, blocks: 0, atime: Timespec::new(0, 0), mtime: Timespec::new(0, 0), ctime: Timespec::new(0, 0), crtime: Timespec::new(0, 0), kind: FileType::RegularFile, perm: 0o644, nlink: 1, uid: 0, gid: 0, rdev: 0, flags: 0, }; reply.attr(&Timespec::new(0, 0), &attr); } _ => reply.error(libc::ENOENT), } } fn read(&mut self, ino: u64, _offset: u64, _size: u32, reply: fuse::ReplyData) { if ino == 2 { reply.data(&b"Hello from MarkBase FUSE!\n"[..]); } else { reply.error(libc::ENOENT); } } fn readdir(&mut self, ino: u64, _offset: u64, reply: fuse::ReplyDirectory) { if ino == 1 { reply.add(1, 0, FileType::Directory, "."); reply.add(1, 1, FileType::Directory, ".."); reply.add(2, 2, FileType::RegularFile, "hello.txt"); reply.ok(); } else { reply.error(libc::ENOENT); } } } pub fn mount_hello_fs(path: &Path) -> Result<(), Box> { let fs = HelloFs; fuse::mount(fs, path, &[])?; Ok(()) } ``` ### Test Commands ```bash # Create test directory mkdir -p /tmp/fuse_test # Mount Hello FUSE cargo run -- fuse --poc --mount --dir /tmp/fuse_test # Verify mount mount | grep fuse_test ls -la /tmp/fuse_test cat /tmp/fuse_test/hello.txt # Expected output: "Hello from MarkBase FUSE!\n" # Unmount cargo run -- fuse --poc --unmount --dir /tmp/fuse_test umount /tmp/fuse_test # Manual fallback ``` ### Expected Results | Check | Expected | Actual | Pass/Fail | |-------|----------|--------|-----------| | Mount succeeds | Exit code 0 | TBD | TBD | | Mount visible in `mount` | `fuse_test` entry | TBD | TBD | | Directory listing | `hello.txt` visible | TBD | TBD | | File read | "Hello from MarkBase FUSE!\n" | TBD | TBD | | Unmount succeeds | Exit code 0 | TBD | TBD | | Mount removed | No `fuse_test` in `mount` | TBD | TBD | --- ## Test 3: Backend Selection Verification ### Objective Test both NFSv4 and FSKit backends to verify performance difference. ### Backend Detection ```rust // src/fuse/backend.rs use std::env; pub fn detect_macos_version() -> String { env::var("MACOS_VERSION").unwrap_or_else(|_| { // Fallback: parse from system let output = Command::new("sw_vers") .arg("-productVersion") .output() .expect("Failed to get macOS version"); String::from_utf8_lossy(&output.stdout).trim().to_string() }) } pub fn select_backend() -> BackendType { let version = detect_macos_version(); if version.starts_with("26") { BackendType::Fskit // macOS 26+ supports FSKit } else { BackendType::Nfs4 // Older macOS uses NFSv4 } } ``` ### Test NFSv4 Backend ```bash # Force NFSv4 backend cargo run -- fuse --poc --mount --dir /tmp/fuse_nfs --backend nfs # Performance test time ls -la /tmp/fuse_nfs time cat /tmp/fuse_nfs/hello.txt # Unmount cargo run -- fuse --poc --unmount --dir /tmp/fuse_nfs ``` ### Test FSKit Backend ```bash # Force FSKit backend (macOS 26+) cargo run -- fuse --poc --mount --dir /tmp/fuse_fskit --backend fskit # Performance test time ls -la /tmp/fuse_fskit time cat /tmp/fuse_fskit/hello.txt # Unmount cargo run -- fuse --poc --unmount --dir /tmp/fuse_fskit ``` ### Performance Comparison | Backend | ls latency | cat latency | Notes | |---------|------------|--------------|-------| | NFSv4 | TBD | TBD | Baseline | | FSKit | TBD | TBD | Target: 40% faster | | Direct disk | TBD | TBD | Reference | --- ## Test 4: Basic Read/Write Operations ### Objective Verify basic file operations work through FUSE mount. ### Test Script ```bash #!/bin/bash # tests/fuse_basic_ops.sh MOUNT_DIR="/tmp/fuse_ops_test" # Setup mkdir -p "$MOUNT_DIR" cargo run -- fuse --poc --mount --dir "$MOUNT_DIR" # Test 1: Directory listing echo "=== Test 1: Directory Listing ===" ls -la "$MOUNT_DIR" # Test 2: File read echo "=== Test 2: File Read ===" cat "$MOUNT_DIR/hello.txt" # Test 3: File stat echo "=== Test 3: File Stat ===" stat "$MOUNT_DIR/hello.txt" # Cleanup cargo run -- fuse --poc --unmount --dir "$MOUNT_DIR" rm -rf "$MOUNT_DIR" echo "All tests completed" ``` ### Expected Results | Operation | Expected Output | Pass/Fail | |-----------|-----------------|-----------| | Directory listing | Shows `hello.txt` | TBD | | File read | "Hello from MarkBase FUSE!\n" | TBD | | File stat | ino=2, size=13, perm=644 | TBD | | Unmount | Exit code 0 | TBD | --- ## Test 5: AJA System Test Baseline ### Objective Measure raw disk performance before FUSE implementation. ### AJA Test Configuration | Setting | Value | |---------|-------| | **Target** | `/System/Volumes/Data` (NVMe) | | **Resolution** | 4K (3840×2160) | | **Codec** | ProRes 4444 | | **Frame Rate** | 60 fps | | **Duration** | 10 seconds | | **Mode** | Write test | ### Test Procedure ```bash # Open AJA System Test open -a "AJA System Test" # Manual steps: 1. Select target: /System/Volumes/Data 2. Configure: 4K ProRes 4444, 60fps 3. Run Write test (10 seconds) 4. Record results: - Write speed: ___ MB/s - Frame rate achieved: ___ fps - Disk usage: ___ % ``` ### dd Baseline Test ```bash # Write test (6GB) time dd if=/dev/zero of=/System/Volumes/Data/test_baseline.bin bs=1M count=6000 # Expected: ~1.5GB/s (NVMe raw speed) # Record: ___ MB/s # Cleanup rm /System/Volumes/Data/test_baseline.bin ``` ### Expected Results | Test | Expected Speed | Actual Speed | Pass/Fail | |------|----------------|--------------|-----------| | AJA 4K ProRes 4444 Write | >=1500 MB/s | TBD | TBD | | dd write (6GB) | >=1500 MB/s | TBD | TBD | | AJA frame rate | 60 fps sustained | TBD | TBD | --- ## Test 6: Rust FUSE Library Verification ### Objective Verify Rust FUSE library compatibility with FUSE-T. ### Dependency Check ```toml # Cargo.toml [dependencies] fuse = "0.3" # Or fuse-t specific binding time = "0.3" libc = "0.2" ``` ### Compilation Test ```bash # Add fuse dependency cargo add fuse # Compile check cargo check # Expected: No compilation errors ``` ### Mount Options Verification ```rust // src/fuse/options.rs use fuse::MountOption; pub fn get_mount_options(backend: BackendType) -> Vec { match backend { BackendType::Nfs4 => vec![ MountOption::FSName("markbase"), MountOption::Noatime, ], BackendType::Fskit => vec![ MountOption::FSName("markbase"), MountOption::Noatime, ], } } ``` ### Expected Results | Check | Expected | Actual | Pass/Fail | |-------|----------|--------|-----------| | Cargo build succeeds | Exit code 0 | TBD | TBD | | fuse library linked | Binary includes fuse symbols | TBD | TBD | | Mount options valid | No runtime errors | TBD | TBD | --- ## Test Execution Schedule ### Day 1: Environment Setup | Time | Task | Duration | |------|------|----------| | 09:00 | Install FUSE-T | 15 min | | 09:15 | Verify installation | 10 min | | 09:25 | Download AJA System Test | 20 min | | 09:45 | Install AJA System Test | 10 min | | 09:55 | Run AJA baseline test | 30 min | | 10:25 | Document results | 15 min | | **Total** | | **1.5 hours** | ### Day 1: Hello FUSE POC | Time | Task | Duration | |------|------|----------| | 10:40 | Create src/fuse/poc_hello.rs | 30 min | | 11:10 | Add fuse dependency | 10 min | | 11:20 | Compile and test | 20 min | | 11:40 | Document results | 15 min | | **Total** | | **1.25 hours** | ### Day 2: Backend Verification | Time | Task | Duration | |------|------|----------| | 09:00 | Test NFSv4 backend | 30 min | | 09:30 | Test FSKit backend | 30 min | | 10:00 | Compare performance | 20 min | | 10:20 | Document findings | 20 min | | **Total** | | **1.7 hours** | --- ## Test Reporting Template ### FUSE-T Installation Report ``` ## Test 1: FUSE-T Installation **Date**: 2026-05-17 **Environment**: M4 Mac mini, macOS 26.4.1 ### Results | Check | Expected | Actual | Pass/Fail | |-------|----------|--------|-----------| | fuse-t binary | Exists | [Record] | [Pass/Fail] | | fuse-t version | >=1.2.6 | [Record] | [Pass/Fail] | | nfs-t binary | Exists | [Record] | [Pass/Fail] | ### Issues Found - [Document any issues] ### Resolution - [Document solutions applied] ``` ### Hello FUSE POC Report ``` ## Test 2: Hello FUSE POC **Date**: 2026-05-17 **Mount Path**: /tmp/fuse_test ### Results | Check | Expected | Actual | Pass/Fail | |-------|----------|--------|-----------| | Mount succeeds | Exit 0 | [Record] | [Pass/Fail] | | Directory listing | hello.txt | [Record] | [Pass/Fail] | | File read | "Hello..." | [Record] | [Pass/Fail] | ### Latency Measurements - Mount time: [Record] ms - ls time: [Record] ms - cat time: [Record] ms ### Backend Used - Backend: [NFSv4/FSKit/Auto] - Reason: [Auto-detect/Manual] ``` ### Performance Baseline Report ``` ## Test 5: AJA System Test Baseline **Date**: 2026-05-17 **Target**: /System/Volumes/Data (NVMe) ### AJA Results | Codec | Resolution | Frame Rate | Write Speed | Pass/Fail | |-------|------------|------------|-------------|-----------| | ProRes 4444 | 4K | 60fps | [Record] MB/s | [Pass/Fail] | ### dd Results | Test | Block Size | Count | Speed | Pass/Fail | |------|------------|-------|-------|-----------| | Write | 1MB | 6000 | [Record] MB/s | [Pass/Fail] | ### Analysis - NVMe raw speed: [Record] MB/s - AJA speed: [Record] MB/s - Overhead: [Calculate] % ``` --- ## Failure Recovery Procedures ### FUSE-T Installation Failure **Symptoms:** - brew install fails - Permission denied - Network volumes not accessible **Recovery:** ```bash # Step 1: Check permissions System Settings → Privacy & Security → Files and Folders → Network Volumes → Enable # Step 2: Manual install curl -L -o ~/Downloads/fuse-t.pkg \ https://github.com/macos-fuse-t/fuse-t/releases/download/1.2.6/fuse-t-macos-installer-1.2.6.pkg sudo installer -pkg ~/Downloads/fuse-t.pkg -target / # Step 3: Restart terminal exec zsh ``` ### Mount Failure **Symptoms:** - mount command hangs - Operation not permitted - Device not found **Recovery:** ```bash # Check mount status mount | grep fuse # Force unmount umount -f /tmp/fuse_test # Check process ps aux | grep fuse # Kill if needed kill -9 [PID] ``` ### Compilation Failure **Symptoms:** - Cargo build fails - fuse library not found - Linking errors **Recovery:** ```bash # Check Rust version rustc --version # Need >=1.70 # Update toolchain rustup update stable # Rebuild dependencies cargo clean cargo build ``` --- ## Success Criteria ### Phase 1 POC Complete | Criterion | Threshold | Measurement | |-----------|-----------|-------------| | FUSE-T installed | Binary exists | `/usr/local/bin/fuse-t` present | | Hello FUSE works | Read/write succeeds | `cat /tmp/fuse_test/hello.txt` outputs correctly | | Backend detected | Auto-select works | macOS 26 → FSKit, older → NFSv4 | | AJA baseline | >=1500 MB/s | Raw disk write speed | | Compilation succeeds | Exit code 0 | `cargo build` completes | ### Proceed to Phase 2 **Decision Criteria:** - All Test 1-6 pass - No critical failures - Performance baseline documented - Backend selection confirmed --- ## Next Steps After POC ### Phase 2: SQLite-backed FUSE (Day 3-5) 1. Implement `MarkBaseFs` struct 2. Integrate file_nodes/file_locations queries 3. Test warren user (12,659 nodes) 4. Implement LRU caching 5. Performance measurement ### Phase 3: Multi-user Concurrent (Day 6-8) 1. Implement `MountManager` 2. Test 10 user parallel mount 3. AJA concurrent write test 4. Stability test (24h) ### Phase 4: Performance Optimization (Day 9-12) 1. Write buffering (64KB chunks) 2. FSKit backend optimization 3. AJA 600MB/s target validation 4. Final documentation --- **Last Updated**: 2026-05-17 **Version**: 1.0 **Status**: Ready for Execution