Files
markbase/docs/FUSE_POC_TEST.md
2026-05-18 17:02:30 +08:00

16 KiB
Raw Permalink Blame History

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:

  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

// 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)

  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