16 KiB
16 KiB
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
# 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
# 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
# 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:
- Check System Settings → Privacy & Security → Network Volumes permission
- Manual download: https://github.com/macos-fuse-t/fuse-t/releases
- 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
// 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<dyn std::error::Error>> {
let fs = HelloFs;
fuse::mount(fs, path, &[])?;
Ok(())
}
Test Commands
# 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
// 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
# 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
# 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
#!/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
# 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
# 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
# Cargo.toml
[dependencies]
fuse = "0.3" # Or fuse-t specific binding
time = "0.3"
libc = "0.2"
Compilation Test
# Add fuse dependency
cargo add fuse
# Compile check
cargo check
# Expected: No compilation errors
Mount Options Verification
// src/fuse/options.rs
use fuse::MountOption;
pub fn get_mount_options(backend: BackendType) -> Vec<MountOption> {
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:
# 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:
# 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:
# 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)
- Implement
MarkBaseFsstruct - Integrate file_nodes/file_locations queries
- Test warren user (12,659 nodes)
- Implement LRU caching
- Performance measurement
Phase 3: Multi-user Concurrent (Day 6-8)
- Implement
MountManager - Test 10 user parallel mount
- AJA concurrent write test
- Stability test (24h)
Phase 4: Performance Optimization (Day 9-12)
- Write buffering (64KB chunks)
- FSKit backend optimization
- AJA 600MB/s target validation
- Final documentation
Last Updated: 2026-05-17 Version: 1.0 Status: Ready for Execution