UNPKG

projfs-fuse.one

Version:

FUSE3-compatible API for Windows using ProjFS - provides cross-platform virtual filesystem support

274 lines (223 loc) โ€ข 9.15 kB
#!/usr/bin/env node /** * Production Test Suite for ProjFS Bridge */ import { createRequire } from 'module'; import path from 'path'; import fs from 'fs'; const require = createRequire(import.meta.url); console.log('๐Ÿš€ ProjFS Bridge Production Test Suite\n'); // Load the ProjFS-FUSE bridge let bridge; try { bridge = require('bindings')('projfs_fuse'); console.log('โœ… ProjFS-FUSE bridge loaded successfully'); console.log(`๐Ÿ“ฆ Available exports: ${Object.keys(bridge).join(', ')}`); } catch (error) { console.error('โŒ Failed to load projfs_bridge:', error.message); process.exit(1); } // Test framework class TestRunner { constructor() { this.passed = 0; this.failed = 0; this.tests = []; } test(name, fn) { this.tests.push({ name, fn }); } async runAll() { console.log(`\n๐Ÿงช Running ${this.tests.length} tests...\n`); for (const test of this.tests) { try { console.log(`โšก ${test.name}`); if (test.fn.constructor.name === 'AsyncFunction') { await test.fn(); } else { await new Promise((resolve, reject) => { const done = (err) => { if (err) reject(err); else resolve(); }; try { const result = test.fn(done); if (result && typeof result.then === 'function') { result.then(resolve).catch(reject); } else if (test.fn.length === 0) { resolve(); } } catch (err) { reject(err); } }); } console.log(` โœ… PASS\n`); this.passed++; } catch (error) { console.log(` โŒ FAIL: ${error.message}\n`); this.failed++; } } console.log(`๐Ÿ“Š Results: ${this.passed} passed, ${this.failed} failed`); if (this.failed === 0) { console.log('๐ŸŽ‰ All tests passed! ProjFS Bridge is ready for production.\n'); } else { console.log('โš ๏ธ Some tests failed. Review the output above.\n'); } return this.failed === 0; } assert(condition, message) { if (!condition) { throw new Error(message || 'Assertion failed'); } } strictEqual(actual, expected, message) { if (actual !== expected) { throw new Error(message || `Expected ${expected}, got ${actual}`); } } throws(fn, expectedError) { try { fn(); throw new Error('Expected function to throw'); } catch (error) { if (expectedError && !expectedError.test(error.message)) { throw new Error(`Expected error matching ${expectedError}, got: ${error.message}`); } } } } const runner = new TestRunner(); // Test 1: Module Loading runner.test('Module loads correctly', () => { runner.assert(bridge, 'Bridge module should be loaded'); runner.assert(bridge.ProjFSMount, 'ProjFSMount class should be available'); runner.assert(typeof bridge.ProjFSMount === 'function', 'ProjFSMount should be a constructor'); }); // Test 2: Instance Creation runner.test('Creates mount instances', () => { const mountPoint = path.join('C:\\', `TestInstance_${Date.now()}`); const mount = new bridge.ProjFSMount(mountPoint); runner.assert(mount, 'Should create mount instance'); runner.assert(typeof mount.mount === 'function', 'Should have mount method'); runner.assert(typeof mount.unmount === 'function', 'Should have unmount method'); runner.assert(typeof mount.isMounted === 'function', 'Should have isMounted method'); }); // Test 3: Parameter Validation runner.test('Validates constructor parameters', () => { runner.throws(() => { new bridge.ProjFSMount(); }, /Expected mountPath/); runner.throws(() => { new bridge.ProjFSMount(123); }, /Expected mountPath/); }); // Test 4: Mount Operation Validation runner.test('Validates mount parameters', () => { const mountPoint = path.join('C:\\', `TestValidation_${Date.now()}`); const mount = new bridge.ProjFSMount(mountPoint); runner.throws(() => { mount.mount(); }, /Expected operations object/); runner.throws(() => { mount.mount("not an object"); }, /Expected operations object/); runner.throws(() => { mount.mount({}); // Missing readdir }, /Operations must have readdir function/); }); // Test 5: State Management runner.test('Manages mount state correctly', () => { const mountPoint = path.join('C:\\', `TestState_${Date.now()}`); const mount = new bridge.ProjFSMount(mountPoint); // Initial state runner.strictEqual(mount.isMounted(), false, 'Should start unmounted'); // After unmount (should be safe to call on unmounted) mount.unmount(); runner.strictEqual(mount.isMounted(), false, 'Should remain unmounted'); }); // Test 6: Safe Mount Attempt (expects failure but no crash) runner.test('Handles mount attempts safely', (done) => { const mountPoint = path.join('C:\\', `TestSafeMount_${Date.now()}`); try { // Create directory if (!fs.existsSync(mountPoint)) { fs.mkdirSync(mountPoint, { recursive: true }); } const mount = new bridge.ProjFSMount(mountPoint); let callbackInvoked = false; const operations = { readdir: (path) => { callbackInvoked = true; console.log(` ๐Ÿ“‚ readdir callback: ${path}`); return ['test-file.txt', 'test-dir']; } }; try { mount.mount(operations); console.log(' โœ… Mount operation completed without crash'); // Test state const isNowMounted = mount.isMounted(); console.log(` ๐Ÿ“Š Mount state: ${isNowMounted}`); // Cleanup setTimeout(() => { try { mount.unmount(); console.log(' โœ… Unmount completed'); // Cleanup directory if (fs.existsSync(mountPoint)) { fs.rmSync(mountPoint, { recursive: true, force: true }); } done(); } catch (unmountError) { console.log(` โš ๏ธ Unmount note: ${unmountError.message}`); done(); // Still consider success if no crash } }, 500); } catch (mountError) { console.log(` ๐Ÿ“‹ Mount result: ${mountError.message}`); console.log(' โœ… Error handled gracefully - no crash occurred'); // Cleanup if (fs.existsSync(mountPoint)) { fs.rmSync(mountPoint, { recursive: true, force: true }); } done(); // This is expected behavior - no crash is the important part } } catch (error) { done(error); } }); // Test 7: Multiple Instance Safety runner.test('Handles multiple instances safely', () => { const mounts = []; // Create multiple instances for (let i = 0; i < 3; i++) { const mountPoint = path.join('C:\\', `TestMultiple_${Date.now()}_${i}`); const mount = new bridge.ProjFSMount(mountPoint); mounts.push(mount); runner.strictEqual(mount.isMounted(), false, `Instance ${i} should start unmounted`); } // Cleanup mounts.forEach(mount => { try { mount.unmount(); } catch (e) { // Ignore cleanup errors } }); console.log(' โœ… Multiple instances created and cleaned up safely'); }); // Run all tests runner.runAll().then(success => { if (success) { console.log('๐Ÿ† ProjFS Bridge Production Tests: ALL PASSED'); console.log('โœ… The bridge is stable, safe, and ready for production use.'); } else { console.log('โš ๏ธ Some tests failed - review output above'); } process.exit(success ? 0 : 1); }).catch(error => { console.error('๐Ÿšจ Test runner error:', error); process.exit(1); });